[llvm] r344198 - [LTO] Account for overriding lib calls via the alias attribute

Warren Ristow via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 10 15:54:31 PDT 2018


Author: wristow
Date: Wed Oct 10 15:54:31 2018
New Revision: 344198

URL: http://llvm.org/viewvc/llvm-project?rev=344198&view=rev
Log:
[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

Added:
    llvm/trunk/test/LTO/X86/libcall-overridden-via-alias.ll   (with props)
Modified:
    llvm/trunk/lib/LTO/UpdateCompilerUsed.cpp

Modified: llvm/trunk/lib/LTO/UpdateCompilerUsed.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/UpdateCompilerUsed.cpp?rev=344198&r1=344197&r2=344198&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/UpdateCompilerUsed.cpp (original)
+++ llvm/trunk/lib/LTO/UpdateCompilerUsed.cpp Wed Oct 10 15:54:31 2018
@@ -95,12 +95,18 @@ private:
     if (GV.hasPrivateLinkage())
       return;
 
-    // Conservatively append user-supplied runtime library functions to
-    // llvm.compiler.used.  These could be internalized and deleted by
-    // optimizations like -globalopt, causing problems when later optimizations
-    // add new library calls (e.g., llvm.memset => memset and printf => puts).
+    // Conservatively append user-supplied runtime library functions (supplied
+    // either directly, or via a function alias) to llvm.compiler.used.  These
+    // could be internalized and deleted by optimizations like -globalopt,
+    // causing problems when later optimizations add new library calls (e.g.,
+    // llvm.memset => memset and printf => puts).
     // Leave it to the linker to remove any dead code (e.g. with -dead_strip).
-    if (isa<Function>(GV) && Libcalls.count(GV.getName())) {
+    GlobalValue *FuncAliasee = nullptr;
+    if (isa<GlobalAlias>(GV)) {
+      auto *A = cast<GlobalAlias>(&GV);
+      FuncAliasee = dyn_cast<Function>(A->getAliasee());
+    }
+    if ((isa<Function>(GV) || FuncAliasee) && Libcalls.count(GV.getName())) {
       LLVMUsed.push_back(&GV);
       return;
     }

Added: llvm/trunk/test/LTO/X86/libcall-overridden-via-alias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/X86/libcall-overridden-via-alias.ll?rev=344198&view=auto
==============================================================================
--- llvm/trunk/test/LTO/X86/libcall-overridden-via-alias.ll (added)
+++ llvm/trunk/test/LTO/X86/libcall-overridden-via-alias.ll Wed Oct 10 15:54:31 2018
@@ -0,0 +1,69 @@
+; 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, verify that LTO
+; does not eliminate the definition.  This is a test for PR38547.
+;
+; RUN: llvm-as -o %t1 %s
+; RUN: llvm-lto -exported-symbol=main -save-merged-module -filetype=asm -o %t2 %t1
+; RUN: llvm-dis -o - %t2.merged.bc | FileCheck --check-prefix=CHECK_IR %s
+;
+; Check that the call is represented as an llvm intrinsic in the IR after LTO:
+; CHECK_IR-LABEL: main
+; CHECK_IR: call float @llvm.log.f32
+;
+; Check that the IR contains the overriding definition of the library routine
+; in the IR after LTO:
+; CHECK_IR: define internal float @logf(float [[X:%.*]])
+; CHECK_IR-NEXT:   [[TMP:%.*]] = fadd float [[X]], [[X]]
+; CHECK_IR-NEXT:   ret float [[TMP]]
+;
+; Check that the assembly code from LTO contains the call to the expected
+; library routine, and that the overriding definition of the library routine
+; is present:
+; RUN: FileCheck --check-prefix=CHECK_ASM %s < %t2
+; CHECK_ASM-LABEL: main:
+; CHECK_ASM: callq logf
+; CHECK_ASM-LABEL: logf:
+; CHECK_ASM-NEXT: add
+; CHECK_ASM-NEXT: ret
+
+; Produced from the following source-code:
+;
+;extern float logf(float);
+;// 'src' and 'dst' are 'volatile' to prohibit optimization.
+;volatile float src = 3.14f;
+;volatile float dst;
+;
+;int main() {
+;  dst = logf(src);
+;  return 0;
+;}
+;
+;extern float fname(float x);
+;float fname(float x) {
+;  return x + x;
+;}
+;
+;float logf(float x) __attribute__((alias("fname")));
+;
+target triple = "x86_64-unknown-linux-gnu"
+
+ at src = global float 0x40091EB860000000, align 4
+ at dst = common global float 0.000000e+00, align 4
+
+ at logf = alias float (float), float (float)* @fname
+
+define i32 @main() local_unnamed_addr {
+entry:
+  %0 = load volatile float, float* @src, align 4
+  %1 = tail call float @llvm.log.f32(float %0)
+  store volatile float %1, float* @dst, align 4
+  ret i32 0
+}
+
+declare float @llvm.log.f32(float)
+
+define float @fname(float %x) {
+  %add = fadd float %x, %x
+  ret float %add
+}

Propchange: llvm/trunk/test/LTO/X86/libcall-overridden-via-alias.ll
------------------------------------------------------------------------------
    svn:executable = *




More information about the llvm-commits mailing list