Announcement

Collapse
No announcement yet.

LLVM Clang 3.9 Mostly Trails GCC In Compiler Performance

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #21
    Originally posted by Ansla View Post

    I don't see the problem with reordering in the above scenario as long as there is no code that reads errno between those calls and as long as the last executed call is sin(x).
    Well, the as long is the problem. gcc just handles the math functions as side-effect free. See below for the output (Arm is alot better readable).
    I`d really like the accesses to errno go away, it doesnt make sense since the C Standard doesnt guarantee the functions will set errno (and noone sane will write portable code depending on this behaviour). On Linux however they usually do (glibc) and optimizing this can have sideeffects.

    My point wasnt to slam GCC, but to note that the math flags can have really big influence on benchmarks. Whetstone was 2x-3x times faster with -ffastm-math on my tests as I recall. To make benchmarks more even. this should be taken into account.

    Code:
    test.o:     file format elf32-littlearm
    
    
    Disassembly of section .text:
    
    00000000 <test>:
       0:    b508          push    {r3, lr}
       2:    ed2d 8b04     vpush    {d8-d9}
       6:    eeb0 9b41     vmov.f64    d9, d1
       a:    f7ff fffe     bl    0 <sin>
       e:    eeb0 8b40     vmov.f64    d8, d0
      12:    eeb0 0b49     vmov.f64    d0, d9
      16:    f7ff fffe     bl    0 <log>
      1a:    ee38 7b08     vadd.f64    d7, d8, d8
      1e:    ee28 0b00     vmul.f64    d0, d8, d0
      22:    ecbd 8b04     vpop    {d8-d9}
      26:    ee20 0b07     vmul.f64    d0, d0, d7
      2a:    bd08          pop    {r3, pc}

    Comment


    • #22
      Originally posted by discordian View Post
      It would be interesting to run these tests on clang with the -fno-math-errno flag.
      clang prohibits several optimization by default (which could result in visible differences), whereas gcc doesnt.

      Code:
      double a = sin(x); /* this could set errno */
      double b = log(y); /* this could set errno */
      double c = sin(x) + a; /* this could set errno */
      gcc will only call sin(x) once and double the value, clang will not change the order since the functions could modify global state (errno) and reordering them could break programs that depend on this behavior.

      Whetstone for example is notoriously affected by such flags.
      More generally, I don;t understand the flags situation. Every benchmark shows a long collection of (presumably carefully chosen) gcc flags, and never shows the LLVM flags. What's going on here? Are the gcc tests iterated multiple times to get the best flags, but the LLVM tests are not? Is there a bug that doesn't display the LLVM flags? It's all very weird.

      Comment


      • #23
        Originally posted by Ansla View Post

        I don't see the problem with reordering in the above scenario as long as there is no code that reads errno between those calls and as long as the last executed call is sin(x).
        This is language lawyer stuff.
        errno is volatile, and so IN PRINCIPLE other threads are supposedly allowed to read it at any time. You could argue that by spec you have to set it at the point where it happens.

        Yeah, these things are dumb. That's why C is such a crappy language, because it's full of this dumb shit that maybe (if you had no taste...) made sense in 1980, and that we're still stuck with today.

        Comment


        • #24
          errno is per-thread as of POSIX-1c (http://www.unix.org/whitepapers/reentrant.html):
          In POSIX.1, errno is defined as an external global variable. But this definition is unacceptable in a multithreaded environment, because its use can result in nondeterministic results. The problem is that two or more threads can encounter errors, all causing the same errno to be set. Under these circumstances, a thread might end up checking errno after it has already been updated by another thread.

          To circumvent the resulting nondeterminism, POSIX.1c redefines errno as a service that can access the per-thread error number as follows (ISO/IEC 9945:1-1996, ยง2.4): Some functions may provide the error number in a variable accessed through the symbol errno. The symbol errno is defined by including the header <errno.h>, as specified by the C Standard ... For each thread of a process, the value of errno shall not be affected by function calls or assignments to errno by other threads.

          Comment


          • #25
            Originally posted by Ansla View Post
            errno is per-thread as of POSIX-1c (http://www.unix.org/whitepapers/reentrant.html):
            Of course POSIX is not dispositive over the C Language. And I gave the example with threads just to be clear; the point holds in principle for signal handlers or anything else that can run at interrupt time.
            The basic issue is --- by default (ie with default flag settings) do you follow the spec 100%, even where that is stupid? As opposed to allowing flags to switch off stupid behavior?

            Which gets back to my question above? Why are the flags for always gcc given in detail, but never the flags for LLVM? And is there an attempt made, for LLVM, to ensure that the optimal flags are used?

            Comment


            • #26
              Originally posted by name99 View Post
              Of course POSIX is not dispositive over the C Language. And I gave the example with threads just to be clear; the point holds in principle for signal handlers or anything else that can run at interrupt time.
              Do you mean that a signal handler might execute between 2 sin calls and it will not be able to read the errno? That's not a problem as the signal handler would not know what function was executed last anyway.

              Originally posted by name99 View Post
              The basic issue is --- by default (ie with default flag settings) do you follow the spec 100%, even where that is stupid? As opposed to allowing flags to switch off stupid behavior?
              Can you point to what exact part of the C spec you think is stupid? Or are you just talking in general? Generally speaking, a compiler should respect the spec 100% when it comes to "defined behavior" and do whatever it wants for the "undefined behavior" cases.

              Originally posted by name99 View Post
              Which gets back to my question above? Why are the flags for always gcc given in detail, but never the flags for LLVM? And is there an attempt made, for LLVM, to ensure that the optimal flags are used?
              Probably a bug in PTS

              Comment


              • #27
                "With the LAMMPS test GCC 6/7 no longer cleanly built this version of the molecular dynamics simulator..."

                I see no issues whatsoever building LAMMPS git HEAD (e2c7acabac53e3034c9e5914b4e4c62bbd30ac3c) with GCC 6.2.0. Please cite the details of supposed compiler failures in detail so as to avoid creating FUD.

                $ g++-6 -v

                Using built-in specs.

                COLLECT_GCC=g++-6

                COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc/6.2.0/libexec/gcc/x86_64-apple-darwin15.6.0/6.2.0/lto-wrapper

                Target: x86_64-apple-darwin15.6.0

                Configured with: ../configure --build=x86_64-apple-darwin15.6.0 --prefix=/usr/local/Cellar/gcc/6.2.0 --libdir=/usr/local/Cellar/gcc/6.2.0/lib/gcc/6 --enable-languages=c,c++,objc,obj-c++,fortran --program-suffix=-6 --with-gmp=/usr/local/opt/gmp --with-mpfr=/usr/local/opt/mpfr --with-mpc=/usr/local/opt/libmpc --with-isl=/usr/local/opt/isl --with-system-zlib --enable-libstdcxx-time=yes --enable-stage1-checking --enable-checking=release --enable-lto --with-build-config=bootstrap-debug --disable-werror --with-pkgversion='Homebrew gcc 6.2.0 --without-multilib' --with-bugurl=https://github.com/Homebrew/homebrew/issues --enable-plugin --disable-nls --disable-multilib

                Thread model: posix

                gcc version 6.2.0 (Homebrew gcc 6.2.0 --without-multilib)

                Comment

                Working...
                X