llvm.org GIT mirror llvm / 89c5c63
[ThinLTO] Prevent importing of "llvm.used" values Summary: This patch prevents importing from (and therefore exporting from) any module with a "llvm.used" local value. Local values need to be promoted and renamed when importing, and their presense on the llvm.used variable indicates that there are opaque uses that won't see the rename. One such example is a use in inline assembly. See also the discussion at: http://lists.llvm.org/pipermail/llvm-dev/2016-April/098047.html As part of this, move collectUsedGlobalVariables out of Transforms/Utils and into IR/Module so that it can be used more widely. There are several other places in LLVM that used copies of this code that can be cleaned up as a follow on NFC patch. Reviewers: joker.eph Subscribers: pcc, llvm-commits, joker.eph Differential Revision: http://reviews.llvm.org/D18986 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266877 91177308-0d34-0410-b5e6-96231b3b80d8 Teresa Johnson 3 years ago
12 changed file(s) with 101 addition(s) and 27 deletion(s). Raw diff Collapse all Expand all
3434 class LLVMContext;
3535 class RandomNumberGenerator;
3636 class StructType;
37 template class SmallPtrSetImpl;
3738
3839 template<> struct ilist_traits
3940 : public ilist_default_traits {
747748 /// @}
748749 };
749750
751 /// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect
752 /// the initializer elements of that global in Set and return the global itself.
753 GlobalVariable *collectUsedGlobalVariables(const Module &M,
754 SmallPtrSetImpl &Set,
755 bool CompilerUsed);
756
750757 /// An raw_ostream inserter for modules.
751758 inline raw_ostream &operator<<(raw_ostream &O, const Module &M) {
752759 M.print(O, nullptr);
2727 class StringRef;
2828 class Value;
2929 class Type;
30 template class SmallPtrSetImpl;
3130
3231 /// Append F to the list of global ctors of module M with the given Priority.
3332 /// This wraps the function in the appropriate structure and stores it along
3938 /// Same as appendToGlobalCtors(), but for global dtors.
4039 void appendToGlobalDtors(Module &M, Function *F, int Priority,
4140 Constant *Data = nullptr);
42
43 /// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect
44 /// the initializer elements of that global in Set and return the global itself.
45 GlobalVariable *collectUsedGlobalVariables(Module &M,
46 SmallPtrSetImpl &Set,
47 bool CompilerUsed);
4841
4942 // Validate the result of Module::getOrInsertFunction called for an interface
5043 // function of given sanitizer. If the instrumented module defines a function
119119 const Module *M,
120120 std::function Ftor)
121121 : Index(llvm::make_unique()), M(M) {
122 // We cannot currently promote or rename anything that is in llvm.used,
123 // since any such value may have a use that won't see the new name.
124 // Specifically, any uses within inline assembly are not visible to the
125 // compiler. Prevent importing of any modules containing these uses by
126 // suppressing generation of the index. This also prevents importing
127 // into this module, which is also necessary to avoid needing to rename
128 // in case of a name clash between a local in this module and an imported
129 // global.
130 // FIXME: If we find we need a finer-grained approach of preventing promotion
131 // and renaming of just the functions using inline assembly we will need to:
132 // - Add flag in the function summaries to identify those with inline asm.
133 // - Prevent importing of any functions with flag set.
134 // - Prevent importing of any global function with the same name as a
135 // function in current module that has the flag set.
136 // - For any llvm.used value that is exported and promoted, add a private
137 // alias to the original name in the current module (even if we don't
138 // export the function using those values in inline asm, another function
139 // with a reference could be exported).
140 SmallPtrSet Used;
141 collectUsedGlobalVariables(*M, Used, /*CompilerUsed*/ false);
142 for (GlobalValue *V : Used) {
143 if (V->hasLocalLinkage())
144 return;
145 }
146
122147 // Compute summaries for all functions defined in module, and save in the
123148 // index.
124149 for (auto &F : *M) {
28882888 if (M->empty())
28892889 return;
28902890
2891 if (Index.begin() == Index.end())
2892 return;
2893
28912894 Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3);
28922895
28932896 // Abbrev for FS_PERMODULE.
1313 #include "llvm/IR/Module.h"
1414 #include "SymbolTableListTraitsImpl.h"
1515 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/SmallPtrSet.h"
1617 #include "llvm/ADT/SmallString.h"
1718 #include "llvm/ADT/StringExtras.h"
1819 #include "llvm/IR/Constants.h"
514515 Metadata *Module::getProfileSummary() {
515516 return getModuleFlag("ProfileSummary");
516517 }
518
519 GlobalVariable *llvm::collectUsedGlobalVariables(
520 const Module &M, SmallPtrSetImpl &Set, bool CompilerUsed) {
521 const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used";
522 GlobalVariable *GV = M.getGlobalVariable(Name);
523 if (!GV || !GV->hasInitializer())
524 return GV;
525
526 const ConstantArray *Init = cast(GV->getInitializer());
527 for (Value *Op : Init->operands()) {
528 GlobalValue *G = cast(Op->stripPointerCastsNoFollowAliases());
529 Set.insert(G);
530 }
531 return GV;
532 }
4242 #include "llvm/Transforms/Utils/CtorUtils.h"
4343 #include "llvm/Transforms/Utils/Evaluator.h"
4444 #include "llvm/Transforms/Utils/GlobalStatus.h"
45 #include "llvm/Transforms/Utils/ModuleUtils.h"
4645 #include
4746 using namespace llvm;
4847
3030 #include "llvm/Support/Debug.h"
3131 #include "llvm/Support/raw_ostream.h"
3232 #include "llvm/Transforms/Utils/GlobalStatus.h"
33 #include "llvm/Transforms/Utils/ModuleUtils.h"
3433 #include
3534 #include
3635 using namespace llvm;
205205 }
206206
207207 void FunctionImportGlobalProcessing::processGlobalsForThinLTO() {
208 // We cannot currently promote or rename anything that is in llvm.used,
209 // since any such value may have a use that won't see the new name.
210 // Specifically, any uses within inline assembly are not visible to the
211 // compiler. Prevent changing any such values on the exporting side,
212 // since we would already have guarded against an import from this module by
213 // suppressing its index generation. See comments on what is required
214 // in order to implement a finer grained solution in
215 // ModuleSummaryIndexBuilder::ModuleSummaryIndexBuilder().
216 SmallPtrSet Used;
217 collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
218 for (GlobalValue *V : Used) {
219 if (!V->hasLocalLinkage())
220 continue;
221 // We would have blocked importing from this module by suppressing index
222 // generation.
223 assert(!isPerformingImport() &&
224 "Should have blocked importing from module with local used");
225 return;
226 }
227
208228 for (GlobalVariable &GV : M.globals())
209229 processGlobalForThinLTO(GV);
210230 for (Function &SF : M)
1111 //===----------------------------------------------------------------------===//
1212
1313 #include "llvm/Transforms/Utils/ModuleUtils.h"
14 #include "llvm/ADT/SmallPtrSet.h"
1514 #include "llvm/IR/DerivedTypes.h"
1615 #include "llvm/IR/Function.h"
1716 #include "llvm/IR/IRBuilder.h"
8988 appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data);
9089 }
9190
92 GlobalVariable *
93 llvm::collectUsedGlobalVariables(Module &M, SmallPtrSetImpl &Set,
94 bool CompilerUsed) {
95 const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used";
96 GlobalVariable *GV = M.getGlobalVariable(Name);
97 if (!GV || !GV->hasInitializer())
98 return GV;
99
100 const ConstantArray *Init = cast(GV->getInitializer());
101 for (Value *Op : Init->operands()) {
102 GlobalValue *G = cast(Op->stripPointerCastsNoFollowAliases());
103 Set.insert(G);
104 }
105 return GV;
106 }
107
10891 Function *llvm::checkSanitizerInterfaceFunction(Constant *FuncOrBitcast) {
10992 if (isa(FuncOrBitcast))
11093 return cast(FuncOrBitcast);
0 @myvar = internal constant i8 1, align 1
1 @llvm.used = appending global [1 x i8*] [i8* @myvar], section "llvm.metadata"
2
3 define void @foo(i64* %v) #0 {
4 entry:
5 %v.addr = alloca i64*, align 8
6 store i64* %v, i64** %v.addr, align 8
7 %0 = load i64*, i64** %v.addr, align 8
8 call void asm sideeffect "movzbl myvar(%rip), %eax\0A\09movq %rax, $0\0A\09", "=*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i64* %0) #1
9 ret void
10 }
0 ; Do setup work for all below tests: generate bitcode and combined index
1 ; RUN: opt -module-summary %s -o %t.bc
2 ; RUN: opt -module-summary %p/Inputs/inlineasm.ll -o %t2.bc
3 ; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
4
5 ; Attempt the import now, ensure below that file containing inline assembly
6 ; is not imported from. Otherwise we would need to promote its local variable
7 ; used in the inline assembly, which would not see the rename.
8 ; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=CHECK
9
10 define i32 @main() #0 {
11 entry:
12 %f = alloca i64, align 8
13 call void @foo(i64* %f)
14 ret i32 0
15 }
16
17 ; CHECK: declare void @foo(i64*)
18 declare void @foo(i64*) #1
4343 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
4444 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
4545 #include "llvm/Transforms/Utils/GlobalStatus.h"
46 #include "llvm/Transforms/Utils/ModuleUtils.h"
4746 #include "llvm/Transforms/Utils/ValueMapper.h"
4847 #include
4948 #include