From e0409098aee1270164a7e453e450264f8e62cbfd Mon Sep 17 00:00:00 2001 From: Shuxin Yang Date: Wed, 9 Oct 2013 17:21:44 +0000 Subject: Fix a bug in Dead Argument Elimination. If a function seen at compile time is not necessarily the one linked to the binary being built, it is illegal to change the actual arguments passing to it. e.g. -------------------------- void foo(int lol) { // foo() has linkage satisifying isWeakForLinker() // "lol" is not used at all. } void bar(int lo2) { // xform to foo(undef) is illegal, as compiler dose not know which // instance of foo() will be linked to the the binary being built. foo(lol2); } ----------------------------- Such functions can be captured by isWeakForLinker(). NOTE that mayBeOverridden() is insufficient for this purpose as it dosen't include linkage types like AvailableExternallyLinkage and LinkOnceODRLinkage. Take link_odr* as an example, it indicates a set of *EQUIVALENT* globals that can be merged at link-time. However, the semantic of *EQUIVALENT*-functions includes parameters. Changing parameters breaks the assumption. Thank John McCall for help, especially for the explanation of subtle difference between linkage types. rdar://11546243 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@192302 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/DeadArgumentElimination.cpp | 13 +++++++++++++ test/Transforms/DeadArgElim/linkage.ll | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 test/Transforms/DeadArgElim/linkage.ll diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index 6ee6162..8621f1a 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -357,6 +357,19 @@ bool DAE::RemoveDeadArgumentsFromCallers(Function &Fn) if (Fn.hasLocalLinkage() && !Fn.getFunctionType()->isVarArg()) return false; + // If a function seen at compile time is not necessarily the one linked to + // the binary being built, it is illegal to change the actual arguments + // passing to it. These functions can be captured by isWeakForLinker(). + // *NOTE* that mayBeOverridden() is insufficient for this purpose as it + // dosen't include linkage types like AvailableExternallyLinkage and + // LinkOnceODRLinkage. Take link_odr* as an example, it indicates a set of + // *EQUIVALENT* globals that can be merged at link-time. However, the + // semantic of *EQUIVALENT*-functions includes parameters. Changing + // parameters breaks the assumption. + // + if (Fn.isWeakForLinker()) + return false; + if (Fn.use_empty()) return false; diff --git a/test/Transforms/DeadArgElim/linkage.ll b/test/Transforms/DeadArgElim/linkage.ll new file mode 100644 index 0000000..f475484 --- /dev/null +++ b/test/Transforms/DeadArgElim/linkage.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -deadargelim -S | FileCheck %s + +; rdar://11546243 +%struct.A = type { i8 } + +define available_externally void @_Z17externallyDefinedP1A(%struct.A* %a) { +entry: + call void @_Z3foov() + ret void +} + +declare void @_Z3foov() + +define void @_Z4testP1A(%struct.A* %a) { +; CHECK: @_Z4testP1A +; CHECK: @_Z17externallyDefinedP1A(%struct.A* %a) + +entry: + call void @_Z17externallyDefinedP1A(%struct.A* %a) + ret void +} -- cgit v1.1