diff options
author | Teresa Johnson <tejohnson@google.com> | 2016-04-20 14:39:45 +0000 |
---|---|---|
committer | Teresa Johnson <tejohnson@google.com> | 2016-04-20 14:39:45 +0000 |
commit | b35cc691ea93d9408f76736170359fd7ce604b53 (patch) | |
tree | 61d2c9ebba7b2a675bdc47ff212be9e44ef4df89 /llvm/lib | |
parent | 6eda85ac1fd9aed299eceed5a014c38a8d89da07 (diff) | |
download | bcm5719-llvm-b35cc691ea93d9408f76736170359fd7ce604b53.tar.gz bcm5719-llvm-b35cc691ea93d9408f76736170359fd7ce604b53.zip |
[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
llvm-svn: 266877
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/ModuleSummaryAnalysis.cpp | 25 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/IR/Module.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/GlobalOpt.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/Internalize.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/FunctionImportUtils.cpp | 20 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/ModuleUtils.cpp | 17 |
7 files changed, 64 insertions, 19 deletions
diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp index 5c8b0aab193..ebc17214e2a 100644 --- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -120,6 +120,31 @@ ModuleSummaryIndexBuilder::ModuleSummaryIndexBuilder( const Module *M, std::function<BlockFrequencyInfo *(const Function &F)> Ftor) : Index(llvm::make_unique<ModuleSummaryIndex>()), M(M) { + // We cannot currently promote or rename anything that is in llvm.used, + // since any such value may have a use that won't see the new name. + // Specifically, any uses within inline assembly are not visible to the + // compiler. Prevent importing of any modules containing these uses by + // suppressing generation of the index. This also prevents importing + // into this module, which is also necessary to avoid needing to rename + // in case of a name clash between a local in this module and an imported + // global. + // FIXME: If we find we need a finer-grained approach of preventing promotion + // and renaming of just the functions using inline assembly we will need to: + // - Add flag in the function summaries to identify those with inline asm. + // - Prevent importing of any functions with flag set. + // - Prevent importing of any global function with the same name as a + // function in current module that has the flag set. + // - For any llvm.used value that is exported and promoted, add a private + // alias to the original name in the current module (even if we don't + // export the function using those values in inline asm, another function + // with a reference could be exported). + SmallPtrSet<GlobalValue *, 8> Used; + collectUsedGlobalVariables(*M, Used, /*CompilerUsed*/ false); + for (GlobalValue *V : Used) { + if (V->hasLocalLinkage()) + return; + } + // Compute summaries for all functions defined in module, and save in the // index. for (auto &F : *M) { diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index d7eda00f579..6e8d6e80bd7 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2889,6 +2889,9 @@ static void WritePerModuleGlobalValueSummary(const Module *M, if (M->empty()) return; + if (Index.begin() == Index.end()) + return; + Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3); // Abbrev for FS_PERMODULE. diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp index 64528d2815a..10110367841 100644 --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -14,6 +14,7 @@ #include "llvm/IR/Module.h" #include "SymbolTableListTraitsImpl.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Constants.h" @@ -515,3 +516,18 @@ void Module::setProfileSummary(Metadata *M) { Metadata *Module::getProfileSummary() { return getModuleFlag("ProfileSummary"); } + +GlobalVariable *llvm::collectUsedGlobalVariables( + const Module &M, SmallPtrSetImpl<GlobalValue *> &Set, bool CompilerUsed) { + const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used"; + GlobalVariable *GV = M.getGlobalVariable(Name); + if (!GV || !GV->hasInitializer()) + return GV; + + const ConstantArray *Init = cast<ConstantArray>(GV->getInitializer()); + for (Value *Op : Init->operands()) { + GlobalValue *G = cast<GlobalValue>(Op->stripPointerCastsNoFollowAliases()); + Set.insert(G); + } + return GV; +} diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 7c400d62307..60d1e7ccbe6 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -43,7 +43,6 @@ #include "llvm/Transforms/Utils/CtorUtils.h" #include "llvm/Transforms/Utils/Evaluator.h" #include "llvm/Transforms/Utils/GlobalStatus.h" -#include "llvm/Transforms/Utils/ModuleUtils.h" #include <algorithm> using namespace llvm; diff --git a/llvm/lib/Transforms/IPO/Internalize.cpp b/llvm/lib/Transforms/IPO/Internalize.cpp index c01a5e1c8ab..ca868e9d224 100644 --- a/llvm/lib/Transforms/IPO/Internalize.cpp +++ b/llvm/lib/Transforms/IPO/Internalize.cpp @@ -31,7 +31,6 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/GlobalStatus.h" -#include "llvm/Transforms/Utils/ModuleUtils.h" #include <fstream> #include <set> using namespace llvm; diff --git a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp index c0628b3bd49..f1d12bce06c 100644 --- a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp +++ b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp @@ -206,6 +206,26 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) { } void FunctionImportGlobalProcessing::processGlobalsForThinLTO() { + // We cannot currently promote or rename anything that is in llvm.used, + // since any such value may have a use that won't see the new name. + // Specifically, any uses within inline assembly are not visible to the + // compiler. Prevent changing any such values on the exporting side, + // since we would already have guarded against an import from this module by + // suppressing its index generation. See comments on what is required + // in order to implement a finer grained solution in + // ModuleSummaryIndexBuilder::ModuleSummaryIndexBuilder(). + SmallPtrSet<GlobalValue *, 8> Used; + collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false); + for (GlobalValue *V : Used) { + if (!V->hasLocalLinkage()) + continue; + // We would have blocked importing from this module by suppressing index + // generation. + assert(!isPerformingImport() && + "Should have blocked importing from module with local used"); + return; + } + for (GlobalVariable &GV : M.globals()) processGlobalForThinLTO(GV); for (Function &SF : M) diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp index 4d73a6bf037..eb918851862 100644 --- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp +++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/ModuleUtils.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" @@ -90,22 +89,6 @@ void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *D appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data); } -GlobalVariable * -llvm::collectUsedGlobalVariables(Module &M, SmallPtrSetImpl<GlobalValue *> &Set, - bool CompilerUsed) { - const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used"; - GlobalVariable *GV = M.getGlobalVariable(Name); - if (!GV || !GV->hasInitializer()) - return GV; - - const ConstantArray *Init = cast<ConstantArray>(GV->getInitializer()); - for (Value *Op : Init->operands()) { - GlobalValue *G = cast<GlobalValue>(Op->stripPointerCastsNoFollowAliases()); - Set.insert(G); - } - return GV; -} - Function *llvm::checkSanitizerInterfaceFunction(Constant *FuncOrBitcast) { if (isa<Function>(FuncOrBitcast)) return cast<Function>(FuncOrBitcast); |