43 votes

L'éditeur de liens peut-il fonctionner?

Dans le fichier file1.c , il existe un appel à une fonction implémentée dans le fichier file2.c . Lorsque je lie file1.o et file2.o à un exécutable, si la fonction dans file2 est très petite, l'éditeur de liens détectera-t-il automatiquement que la fonction est petite et en ligne appel?

68voto

Michael Burr Points 181287

En plus du soutien pour le Lien, le Temps de Génération de Code (LTCG) que Jame McNellis mentionné, la chaîne de compilation GCC supporte également le lien de l'optimisation du temps. A partir de la version 4.5, GCC prend en charge l' -flto interrupteur qui permet à Link Time Optimization (LTO), une forme d'ensemble du programme d'optimisation qui permet de l'fonctions inline de séparer les fichiers objets (et toutes les autres optimisations du compilateur pourrait être en mesure de faire si elle était la compilation de tous les fichiers de l'objet, comme si elles l'ont été à partir d'un seul fichier source C).

Voici un exemple simple:

// file test.c
void print_int(int x);

int main(){
    print_int(1);
    print_int(42);
    print_int(-1);

    return 0;
}


// file print_int.c
#include <stdio.h>

void print_int( int x)
{
    printf( "the int is %d\n", x);
}

D'abord compiler à l'aide de GCC4.5.x - exemples de GCC docs utiliser -O2, mais pour obtenir des résultats visibles dans mon test simple, j'ai dû utiliser -O3:

C:\temp>gcc --version
gcc (GCC) 4.5.2

# compile with preparation for LTO
C:\temp>gcc -c -O3 -flto test.c
C:\temp>gcc -c -O3 -flto print_int.c

# link without LTO
C:\temp>gcc -o test-nolto.exe  print_int.o test.o

Pour obtenir l'effet de LTO, vous êtes censé utiliser les options d'optimisation, même au niveau de la liaison stade de l'éditeur de liens appelle en fait le compilateur pour compiler des morceaux de code intermédiaire que le compilateur de la mettre dans le fichier de l'objet dans les premières étapes ci-dessus. Si vous ne passez pas l'option d'optimisation, à ce stade, ainsi, le compilateur n'effectue pas de l'inlining que vous seriez à la recherche pour.

# link using LTO
C:\temp>gcc -o test-lto.exe -flto -O3 print_int.o test.o

Le démontage de la version sans lien à l'optimisation du temps. Notez que les appels sont effectués à l' print_int() fonction de:

C:\temp>gdb test-nolto.exe
GNU gdb (GDB) 7.2
(gdb) start
Temporary breakpoint 1 at 0x401373
Starting program: C:\temp/test-nolto.exe
[New Thread 3324.0xdc0]

Temporary breakpoint 1, 0x00401373 in main ()
(gdb) disassem
Dump of assembler code for function main:
   0x00401370 <+0>:     push   %ebp
   0x00401371 <+1>:     mov    %esp,%ebp
=> 0x00401373 <+3>:     and    $0xfffffff0,%esp
   0x00401376 <+6>:     sub    $0x10,%esp
   0x00401379 <+9>:     call   0x4018ca <__main>
   0x0040137e <+14>:    movl   $0x1,(%esp)
   0x00401385 <+21>:    call   0x401350 <print_int>
   0x0040138a <+26>:    movl   $0x2a,(%esp)
   0x00401391 <+33>:    call   0x401350 <print_int>
   0x00401396 <+38>:    movl   $0xffffffff,(%esp)
   0x0040139d <+45>:    call   0x401350 <print_int>
   0x004013a2 <+50>:    xor    %eax,%eax
   0x004013a4 <+52>:    leave
   0x004013a5 <+53>:    ret

Le démontage de la version avec lien à l'optimisation du temps. Notez que les appels à l' printf() sont effectués directement:

C:\temp>gdb test-lto.exe

GNU gdb (GDB) 7.2
(gdb) start
Temporary breakpoint 1 at 0x401373
Starting program: C:\temp/test-lto.exe
[New Thread 1768.0x126c]

Temporary breakpoint 1, 0x00401373 in main ()
(gdb) disassem
Dump of assembler code for function main:
   0x00401370 <+0>:     push   %ebp
   0x00401371 <+1>:     mov    %esp,%ebp
=> 0x00401373 <+3>:     and    $0xfffffff0,%esp
   0x00401376 <+6>:     sub    $0x10,%esp
   0x00401379 <+9>:     call   0x4018da <__main>
   0x0040137e <+14>:    movl   $0x1,0x4(%esp)
   0x00401386 <+22>:    movl   $0x403064,(%esp)
   0x0040138d <+29>:    call   0x401acc <printf>
   0x00401392 <+34>:    movl   $0x2a,0x4(%esp)
   0x0040139a <+42>:    movl   $0x403064,(%esp)
   0x004013a1 <+49>:    call   0x401acc <printf>
   0x004013a6 <+54>:    movl   $0xffffffff,0x4(%esp)
   0x004013ae <+62>:    movl   $0x403064,(%esp)
   0x004013b5 <+69>:    call   0x401acc <printf>
   0x004013ba <+74>:    xor    %eax,%eax
   0x004013bc <+76>:    leave
   0x004013bd <+77>:    ret
End of assembler dump.

Et voici la même expérience avec MSVC (d'abord avec LTCG):

C:\temp>cl -c /GL /Zi /Ox test.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c

C:\temp>cl -c /GL /Zi /Ox print_int.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

print_int.c

C:\temp>link /LTCG test.obj print_int.obj /out:test-ltcg.exe /debug
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

Generating code
Finished generating code

C:\temp>"\Program Files (x86)\Debugging Tools for Windows (x86)"\cdb test-ltcg.exe

Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: test-ltcg.exe
    // ...
0:000> u main
*** WARNING: Unable to verify checksum for test-ltcg.exe
test_ltcg!main:
00cd1c20 6a01            push    1
00cd1c22 68d05dcd00      push    offset test_ltcg!__decimal_point_length+0x10 (00cd5dd0)
00cd1c27 e8e3f3feff      call    test_ltcg!printf (00cc100f)
00cd1c2c 6a2a            push    2Ah
00cd1c2e 68d05dcd00      push    offset test_ltcg!__decimal_point_length+0x10 (00cd5dd0)
00cd1c33 e8d7f3feff      call    test_ltcg!printf (00cc100f)
00cd1c38 6aff            push    0FFFFFFFFh
00cd1c3a 68d05dcd00      push    offset test_ltcg!__decimal_point_length+0x10 (00cd5dd0)
00cd1c3f e8cbf3feff      call    test_ltcg!printf (00cc100f)
00cd1c44 83c418          add     esp,18h
00cd1c47 33c0            xor     eax,eax
00cd1c49 c3              ret
0:000>

Maintenant sans LTCG. Notez qu'avec MSVC vous devez compiler le .c fichier sans l' /GL pour prévenir l'éditeur de liens à partir de l'exécution de la LTCG - sinon, l'éditeur de liens détecte qu' /GL a été spécifié, et il va forcer l' /LTCG option (hey, qu'est ce que tu voulais que la première fois /GL):

C:\temp>cl -c /Zi /Ox test.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c

C:\temp>cl -c /Zi /Ox print_int.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

print_int.c

C:\temp>link test.obj print_int.obj /out:test-noltcg.exe /debug
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

C:\temp>"\Program Files (x86)\Debugging Tools for Windows (x86)"\cdb test-noltcg.exe

Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: test-noltcg.exe
// ...
0:000> u main
test_noltcg!main:
00c41020 6a01            push    1
00c41022 e8e3ffffff      call    test_noltcg!ILT+5(_print_int) (00c4100a)
00c41027 6a2a            push    2Ah
00c41029 e8dcffffff      call    test_noltcg!ILT+5(_print_int) (00c4100a)
00c4102e 6aff            push    0FFFFFFFFh
00c41030 e8d5ffffff      call    test_noltcg!ILT+5(_print_int) (00c4100a)
00c41035 83c40c          add     esp,0Ch
00c41038 33c0            xor     eax,eax
00c4103a c3              ret
0:000>

Une chose que Microsoft est l'éditeur de liens prend en charge dans la LTCG qui n'est pas pris en charge par GCC (autant que je sache) est le Profil de l'Optimisation orientée (PGO). Cette technologie permet à Microsoft de l'éditeur de liens pour optimiser basé sur un profilage de données recueillies auprès de courses précédentes du programme. Cela permet à l'éditeur de liens pour faire des choses telles que de recueillir "à chaud" des fonctions dans les mêmes pages de mémoire et rarement utilisé séquences de code sur d'autres pages de mémoire afin de réduire le jeu de travail d'un programme.

 


Edit (28 Août 2011): GCC profil de support guidée d'optimisation à l'aide des options telles que -fprofile-generate et -fprofile-use, mais je suis complètement ignorant sur eux.

Grâce à Konrad Rudolph pour le rappeler à moi.

0voto

Steve Wellens Points 14348

Pouvez-vous DASM le code (le démonter)? S'il s'agit d'un appel de fonction (et non en ligne), il apparaîtra comme tel dans le code d'assemblage.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X