8

According to this article/video:

GCC recognizes several architecture-dependent optimizations for increasing the speed of C executables. Passing an executable through GCC a second time can often provide a dramatic performance improvement.

If you watched the video on the link, you can see this methods doubles the speed of an executable. I am not sure if this is general.

My question is: Why does this happen?

Bonus: What happen when we recompile a compiled program exactly?

AK_
  • 1,879
  • 4
  • 21
  • 30
  • 13
    That got to be a hoax. See how the code contains a `sleep(10)`? That's a system call that puts the process to sleep for ten seconds. Why would "double compiling" cause the sleep to halve its time? Note how the poster doesn't list the files after running the first program. – Some programmer dude Jul 25 '14 at 22:10
  • @JoachimPileborg that's why I Am asking here lol :) this is the first time I see such thing – AK_ Jul 25 '14 at 22:11
  • 3
    The ten seconds running the first program is ample time to edit the source and rename it to `compiled` in a terminal not being recorded. Remember that filename suffixes (like `.c`) are optional in POSIX systems (like Linux). :) – Some programmer dude Jul 25 '14 at 22:12
  • 5
    All those conspiracy theories... now invading compiler optimization. – Deduplicator Jul 25 '14 at 22:15
  • 1
    Clearly a hoax. The idea of double compilation does not even make sense, the quote from the article is rubbish, the `X64_...` macro does not exist in any compilator I have heard of (not in GCC for sure). – Stefano Sanfilippo Jul 25 '14 at 22:31
  • "Peter Swire [ machine learning & data mining specialist ]" He's got an MS in CS, and was pursuing a Ph.D. Even CS is starting to become a "no hope for society" situation. lol – Ricky Mutschlechner Jul 25 '14 at 22:35
  • this is clearly nonsense, the only "double compile" that could make sense is profile guided optimization, but that requires running your program in between compiles (-fprofile-generate, -fprofile-use with gcc) – jtaylor Jul 25 '14 at 23:10
  • 3
    There is a concept of "double compilation" that has been used in the past for optimization, but it really just amounted to compiling once to find out how big methods were, etc, to inform the optimizer on the next iteration. Only in very rare cases would this result in double speed, and I doubt that the scheme has been used at all in 20 years. – Hot Licks Jul 26 '14 at 00:45
  • https://twitter.com/rninty_/status/492905268032708609 – Ry- Jul 26 '14 at 15:47
  • @minitech I see now...... – AK_ Jul 26 '14 at 16:10
  • 6
    Thanks to @minitech, I tracked down the [Reddit post where the author reveals the trick behind the joke](http://www.reddit.com/r/programming/comments/2bjlvk/doublecompilation_of_c_code_dramatically/cj62tev). He simply swapped the compiled file with another source file behind the curtains and aliased `gcc` to `gcc -x c` so that it would not complain about being unable to guess the source language. – Stefano Sanfilippo Jul 26 '14 at 19:39

1 Answers1

47

This is a hoax.

Neither gcc nor any other compiler is capable of reading object code, “compiling” it, and producing object code that is faster.

The closest thing is feedback-directed compilation, where you first compile a program with instrumentation (e.g. gcc --fprofile-generate), run that program, generating a data file about the run (e.g. foo.gcda), and then compile the program again using the same source code and the data file as input to the compiler (e.g. gcc --fprofile-use). This can result in fairly modest speed-ups, typically between 5% and 10% in my experience.

Suppose that you have a long chain of 50 if … else if constructs (that isn't amenable to being restructured as a switch). This often occurs in Monte Carlo simulations, for example. If you're a reasonably experienced programmer, you'll probably order these so that the branch that's taken most often appears first. The idea is that, at runtime, you don't waste time considering 30 less likely branches before considering the most likely. Moreover, you will attempt to order these branches from most likely to least likely, so that, on average, the fewest number of branch tests is executed before the right one is found.

Note that the compiler has no basis for ordering these branches because the information that one is more likely than another simply isn't in the source code, so the best that can be done is to output the branches in source order.

With classical feedback-directed compilation, you first create an instrumented version of the executable that (when you run it) records how many times each branch is taken (or not) to a data file. The second time you compile, the compiler has empirical data from runtime (that it doesn't normally have) that can be used to reorder tests and insert branch hints that will make the code run faster… at least with workloads similar to the profiled test program.

I'm sure that modern feedback-directed compilation is considerably more sophisticated, but this is the general idea.

Emmet
  • 6,192
  • 26
  • 39