Может ли LTO для gcc или clang оптимизироваться в методах C и C++

Если для gcc или clang используется оптимизация во время компоновки (LTO), возможно ли оптимизировать код за пределами границ языка C и C++?

Например, может ли функция C быть встроена в C++?

1 ответ

Решение

Да!

Оптимизация времени соединения обычно работает с промежуточным представлением (IR), присутствующим в "толстых" объектных файлах, которые могут содержать как машинный код для традиционного связывания, так и IR для связывания LTO.

На данном этапе больше нет языковых конструкций высокого уровня, поэтому оптимизация времени соединения не зависит от языка.


НКУ

Оптимизация времени соединения (LTO) GCC работает на GIMPLE, одном из промежуточных представлений GCC. IR всегда не зависит от языка, поэтому любая оптимизация во время компоновки будет работать с кодом, сгенерированным из любого языка.

Из документации по параметрам оптимизации GCC:

Другой особенностью LTO является то, что можно применять межпроцедурную оптимизацию к файлам, написанным на разных языках:

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

Обратите внимание, что последняя ссылка выполняется с помощью g ++, чтобы получить библиотеки времени выполнения C++ и -lgfortran добавлен для получения библиотек времени исполнения Fortran. В общем случае при смешивании языков в режиме LTO следует использовать те же параметры команды ссылки, что и при смешивании языков в обычной (не LTO) компиляции.


Вот пример, чтобы показать вам, насколько мощна эта технология. Мы определим функцию C и вызовем ее из программы C++:

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);
}

компилировать

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

Разбирать (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

Вы можете видеть, что это не только встроенный мой C func() в мой C++ main(), но это превратило все это в постоянное выражение!


Clang / LLVM

Используя тот же синтаксис, Clang может генерировать "толстые" объектные файлы с LLVM IR, которые можно оптимизировать во время соединения. См. Оптимизация времени соединения LLVM.

Используя тот же тестовый код, что и выше, clang дает точно такой же результат:

00000000004004b0 <main>:
  4004b0:   b8 0a 00 00 00          mov    eax,0xa
  4004b5:   c3                      ret
Другие вопросы по тегам