Can LTO for gcc or clang optimize across C and C++ methods
Asked Answered
M

1

10

If link-time optimization (LTO) is being used with gcc or clang, is it possible that code can be optimized across the C and C++ language boundary?

For example, can a C function be inlined into a C++ caller?

Misappropriate answered 30/12, 2017 at 3:37 Comment(0)
C
12

Yes!

Link-time optimization typically works on intermediate representation (IR) present in "fat" object files, which can contain both machine code for traditional linking, and IR for LTO linking.

At this stage, there are no more high-level language constructs, so link-time-optimization is language-agnostic.


GCC

GCC's link-time optimization (LTO) works on GIMPLE, one of GCC's intermediate representations. The IR is always language-agnostic, so any link-time optimizations will work across code generated from any language.

From the GCC Optimization Options documentation:

Another feature of LTO is that it is possible to apply interprocedural optimizations on files written in different languages:

gcc -c -flto foo.c
g++ -c -flto bar.cc
gfortran -c -flto baz.f90
g++ -o myprog -flto -O3 foo.o bar.o baz.o -lgfortran

Notice that the final link is done with g++ to get the C++ runtime libraries and -lgfortran is added to get the Fortran runtime libraries. In general, when mixing languages in LTO mode, you should use the same link command options as when mixing languages in a regular (non-LTO) compilation.


Here's an example to show you just how powerful this technology is. We'll define a C function and call it from a C++ program:

func.h

#ifndef FUNC_DOT_H
#define FUNC_DOT_H

#ifdef __cplusplus
extern "C" {
#endif

int func(int a, int b, int c);

#ifdef __cplusplus
}
#endif

#endif /* FUNC_DOT_H */

func.c

#include "func.h"

int func(int a, int b, int c)
{
    return 3*a + 2*b + c;
}

main.cpp

#include "func.h"

int main()
{
    int a = 1;
    int b = 2;
    int c = 3;

    return func(a, b, c);
}

Compile

gcc -o func.o -c -Wall -Werror -flto -O2 func.c
g++ -o main.o -c -Wall -Werror -flto -O2 main.cpp
g++ -o testlto -flto -O2 main.o func.o

Disassemble (objdump -Mintel -d -R -C testlto)

Disassembly of section .text:

00000000004003d0 <main>:
  4003d0:   b8 0a 00 00 00          mov    eax,0xa   ; 1*3 + 2*2 + 3 = 10
  4003d5:   c3                      ret

You can see that it not only inlined my C func() into my C++ main(), but it turned the whole thing into a constant expression!


Clang / LLVM

Using the same syntax, Clang is capable of emitting "fat" object files with LLVM IR, which can be optimized during link time. See LLVM Link Time Optimization.

Using the same test code as above, clang produces the exact same result:

00000000004004b0 <main>:
  4004b0:   b8 0a 00 00 00          mov    eax,0xa
  4004b5:   c3                      ret
Chapel answered 30/12, 2017 at 3:43 Comment(4)
I suppose the usual caveats about LTO still apply: AFAIK different versions of gcc might produce different GIMPLE versions which may not work if the linker invokes a version of the compiler that doesn't use the version embedded in the .o file? In the really weird case that your gcc and g++ were somehow different versions I guess it could matter.Misappropriate
Right -- my answer is assuming a sane, correctly-working compiler / linker installation.Chapel
Right - a more realistic way a version mismatch might occur would be with say static linking where the .a file was compiler "fat" and contains IR but was generated in a different way, on a different machine or at a different time than the final executable. In this case the GIMPLE in the '.a' might be ignored if it is not compatible with the local compiler. Of course, this is just a general "gotcha" for LTO versus traditional linking and doesn't apply specifically to cross-language optimization.Misappropriate
Clang doesn't seem to have a way to produce "fat" object files (at least according to gcc's terminology). func.o is just LLVM IR bitcode, so it can't be compiled with anything other than clang (supposedly the reverse should be possible, though I'm struggling at the moment): #51259840Rationalize

© 2022 - 2024 — McMap. All rights reserved.