3

Context :

Trying to understand how lto (link time compilation) works

Code:

I have those files :

julia.h:

#ifndef JULIA_H
#define JULIA_H
#include <stdio.h>
int julian();

#endif // JULIA_H

julia.c :

#include "julia.h"

int julian()
{
    printf("Hello Worldu!\n");
    return 0;
}

compiled as a shared library like so : gcc -O3 -fPIC -shared julia.c -o libjulia.so -L$PWD -I$PWD -flto

and my main program :

main.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "julia.h"

int main()
{

    julian();

    return 0;
}

compiled with : gcc -O3 main.c -I/path/to/inc -L/path/to/lib -Wl,-rpath=/path/to/lib -ljulia -flto

It compiles fines.

Question :

So, this is a hello world program but am I doing it right with LTO ? Is is all it takes to optimize the linkage ?

Thanks

Community
  • 1
  • 1
Larry
  • 1,735
  • 1
  • 18
  • 46

2 Answers2

14

As keltar saied, LTO doesn't affect shared libraries. But...

LTO works with static libraries

Just replace ar by gcc-ar and add the option --plugin gccpath/liblto_plugin.so. This LTO plugin will copy the declarations, types, callgraph and GIMPLE representation from LTO-compiled objects into the static lib. (same for ranlib to be replaced by gcc-ranlib)

In your example

# First retrieve the GCC path
gccpath=$(gcc -print-search-dirs | awk '/install/{print $2}')

# Compile the static library
gcc julia.c -o julia.o -flto -ffat-lto-objects
gcc-ar rcs libjulia.a julia.o --plugin $gccpath/liblto_plugin.so

# Compile & link the executable
gcc main.c libjulia.a -flto -Ofast -march=native

Note: -Ofast was introduced in GCC-4.6 [ref] and includes -ffast-math.
Use -O3 if you don't want that.

Update Makefile

GCCPATH = $(shell gcc -print-search-dirs | awk '/install/{print $$2}')
AR      = gcc-ar
RANLIB  = gcc-ranlib
ARFLAGS     += --plugin $(GCCPATH)/liblto_plugin.so
RANLIBFLAGS += --plugin $(GCCPATH)/liblto_plugin.so
CFLAGS      += -flto -ffat-lto-objects
CXXFLAGS    += -flto -ffat-lto-objects
LDFLAGS     += -flto=8    # 8 -> compiles using 8 threads

Do not forget, the real compilation will be done at link time. Therefore, move your optimization flags from CFLAGS (and CXXFLAGS) to LDFLAGS ;-) One more thing, debugging info and LTO is still experimental in GCC-4.9. GCC-5.0 should improve this point...

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
oHo
  • 51,447
  • 27
  • 165
  • 200
2

LTO doesn't affect shared libraries; they're being linked with by dynamic linker, which is not aware of LTO and can't modify code at runtime.

Moreover, LTO doesn't even work with static libraries, but some day it presumably will (it is TODO on gcc wiki).

But yes, what it takes to enable is using -flto on both compilation and linking phases.

keltar
  • 17,711
  • 2
  • 37
  • 42
  • So basically, for me it is useless, right ? What optimizations can be made for dynamic libraries ? – Larry Jul 14 '14 at 10:16
  • It will affect compilation of library itself, if it consists of multiple files, so it still may have some benefits. Compilation time will suffer severely, of course. – keltar Jul 14 '14 at 10:22
  • Ok, So I will use the usual pattern gcc -c foo.c -o foo.o -flto and link that to my main gcc -O3 main.c foo.o L/blah -Iblah -flto. And then I will benefit from all optimizations possible. I hope. – Larry Jul 14 '14 at 10:27
  • There are a lot more flags like `-fomit-frame-pointer`, `-ffast-math`, `-mtune`, `-msse` and many many more, but they are not generic or have other problems, - so disabled by default. – keltar Jul 14 '14 at 10:34
  • 1
    Note that when compiling and linking the dynamic library itself, you can use link time optimization.(Ofcourse, if your dynamic library consists of just 1 file, it's pretty much useless to use LTO). You can use LTO with static libraries, see http://stackoverflow.com/questions/25878407/how-can-i-use-lto-with-static-libraries – nos Feb 27 '15 at 08:25