llvm.org GIT mirror llvm / 7f7ab9f
[LTO] Account for overriding lib calls via the alias attribute Given a library call that is represented as an llvm intrinsic call, but later transformed to an actual call, if an overriding definition of that library routine is provided indirectly via an alias, prevent LTO from eliminating the definition. This is a fix for PR38547. Differential Revision: https://reviews.llvm.org/D52836 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@344198 91177308-0d34-0410-b5e6-96231b3b80d8 Warren Ristow 11 months ago
2 changed file(s) with 80 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
9494 if (GV.hasPrivateLinkage())
9595 return;
9696
97 // Conservatively append user-supplied runtime library functions to
98 // llvm.compiler.used. These could be internalized and deleted by
99 // optimizations like -globalopt, causing problems when later optimizations
100 // add new library calls (e.g., llvm.memset => memset and printf => puts).
97 // Conservatively append user-supplied runtime library functions (supplied
98 // either directly, or via a function alias) to llvm.compiler.used. These
99 // could be internalized and deleted by optimizations like -globalopt,
100 // causing problems when later optimizations add new library calls (e.g.,
101 // llvm.memset => memset and printf => puts).
101102 // Leave it to the linker to remove any dead code (e.g. with -dead_strip).
102 if (isa(GV) && Libcalls.count(GV.getName())) {
103 GlobalValue *FuncAliasee = nullptr;
104 if (isa(GV)) {
105 auto *A = cast(&GV);
106 FuncAliasee = dyn_cast(A->getAliasee());
107 }
108 if ((isa(GV) || FuncAliasee) && Libcalls.count(GV.getName())) {
103109 LLVMUsed.push_back(&GV);
104110 return;
105111 }
0 ; Given a library call that is represented as an llvm intrinsic call, but
1 ; later transformed to an actual call, if an overriding definition of that
2 ; library routine is provided indirectly via an alias, verify that LTO
3 ; does not eliminate the definition. This is a test for PR38547.
4 ;
5 ; RUN: llvm-as -o %t1 %s
6 ; RUN: llvm-lto -exported-symbol=main -save-merged-module -filetype=asm -o %t2 %t1
7 ; RUN: llvm-dis -o - %t2.merged.bc | FileCheck --check-prefix=CHECK_IR %s
8 ;
9 ; Check that the call is represented as an llvm intrinsic in the IR after LTO:
10 ; CHECK_IR-LABEL: main
11 ; CHECK_IR: call float @llvm.log.f32
12 ;
13 ; Check that the IR contains the overriding definition of the library routine
14 ; in the IR after LTO:
15 ; CHECK_IR: define internal float @logf(float [[X:%.*]])
16 ; CHECK_IR-NEXT: [[TMP:%.*]] = fadd float [[X]], [[X]]
17 ; CHECK_IR-NEXT: ret float [[TMP]]
18 ;
19 ; Check that the assembly code from LTO contains the call to the expected
20 ; library routine, and that the overriding definition of the library routine
21 ; is present:
22 ; RUN: FileCheck --check-prefix=CHECK_ASM %s < %t2
23 ; CHECK_ASM-LABEL: main:
24 ; CHECK_ASM: callq logf
25 ; CHECK_ASM-LABEL: logf:
26 ; CHECK_ASM-NEXT: add
27 ; CHECK_ASM-NEXT: ret
28
29 ; Produced from the following source-code:
30 ;
31 ;extern float logf(float);
32 ;// 'src' and 'dst' are 'volatile' to prohibit optimization.
33 ;volatile float src = 3.14f;
34 ;volatile float dst;
35 ;
36 ;int main() {
37 ; dst = logf(src);
38 ; return 0;
39 ;}
40 ;
41 ;extern float fname(float x);
42 ;float fname(float x) {
43 ; return x + x;
44 ;}
45 ;
46 ;float logf(float x) __attribute__((alias("fname")));
47 ;
48 target triple = "x86_64-unknown-linux-gnu"
49
50 @src = global float 0x40091EB860000000, align 4
51 @dst = common global float 0.000000e+00, align 4
52
53 @logf = alias float (float), float (float)* @fname
54
55 define i32 @main() local_unnamed_addr {
56 entry:
57 %0 = load volatile float, float* @src, align 4
58 %1 = tail call float @llvm.log.f32(float %0)
59 store volatile float %1, float* @dst, align 4
60 ret i32 0
61 }
62
63 declare float @llvm.log.f32(float)
64
65 define float @fname(float %x) {
66 %add = fadd float %x, %x
67 ret float %add
68 }