Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can GCC optimize things better when I compile everything in one step?

gcc optimizes code when I pass it the -O2 flag, but I'm wondering how well it can actually do that if I compile all source files to object files and then link them afterwards.

Here's an example:

// in a.h
int foo(int n);

// in foo.cpp
int foo(int n) {
  return n;
}

// in main.cpp
#include "a.h"
int main(void) {
  return foo(5);
}

// code used to compile it all
gcc -c -O2 foo.cpp -o foo.o
gcc -c -O2 main.cpp -o main.o
gcc -O2 foo.o main.o -o executable

Normally, gcc should inline foo because it's a small function and -O2 enables -finline-small-functions, right? But here, gcc only sees the code of foo and main independently before it creates the object files, so there won't be any optimizations like that, right? So, does compiling like this really make code slower?

However, I could also compile it like this:

gcc -O2 foo.cpp main.cpp -o executable

Would that be faster? If not, would it be faster this way?

// in foo.cpp
int foo(int n) {
  return n;
}

// in main.cpp
#include "foo.cpp"
int main(void) {
  return foo(5);
}

Edit: I looked at objdump, and its disassembled code showed that only the #include "foo.cpp" thing worked.

like image 647
thejh Avatar asked Apr 21 '12 14:04

thejh


People also ask

Is GCC an optimizing compiler?

By default, GCC compiles code that is optimized for the most processors. However, you can use the -mtune and -march options with gcc to optimize instruction scheduling and instruction set selection respectively.

What optimization does GCC do?

GCC performs nearly all supported optimizations that do not involve a space-speed tradeoff. As compared to -O , this option increases both compilation time and the performance of the generated code. Please note the warning under -fgcse about invoking -O2 on programs that use computed gotos.

How many optimization levels are there in GCC?

Seven distinct levels: -O0 (default): No optimization. -O or -O1 (same thing): Optimize, but do not spend too much time. -O2 : Optimize more aggressively.

Is GCC slow?

It's all automatic. GCC is slower to compile than clang, so I spend a lot of time compiling, but my final system is (usually) faster with GCC, so I have set GCC as my system compiler.


1 Answers

It seems that you have rediscovered on your own the issue about the separate compilation model that C and C++ use. While it certainly eases memory requirements (which was important at the time of its creation), it does so by exposing only minimal information to the compiler, meaning that some optimizations (like this one) cannot be performed.

Newer languages, with their module systems can expose as much information as necessary, and we can hope to rip those benefits if modules get into the next version of C++...

In the mean time, the simplest thing to go for is called Link-Time Optimization. The idea is that you will perform as much optimization as possible on each TU (Translation Unit) to obtain an object file, but you will also enrich the traditional object file (which contain assembly) with IR (Intermediate Representation, used by compilers to optimize) for part of or all functions.

When the linker will be invoked to merge those object files together, instead of just merging the files together, it will merge the IR representations, rexeecute a number of optimization passes (constant propagation, inlining, ...) and then create assembly on its own. It means that instead of being just a linker, it is in fact a backend optimizer.

Of course, like all optimization passes this has a cost, so makes for longer compilation. Also, it means that both the compiler and the linker should be passed a special option to trigger this behavior, in the case of gcc, it would be -lto or -O4.

like image 95
Matthieu M. Avatar answered Oct 20 '22 00:10

Matthieu M.