summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/IR/Module.h7
-rw-r--r--llvm/include/llvm/Transforms/Utils/ModuleUtils.h7
-rw-r--r--llvm/lib/Analysis/ModuleSummaryAnalysis.cpp25
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp3
-rw-r--r--llvm/lib/IR/Module.cpp16
-rw-r--r--llvm/lib/Transforms/IPO/GlobalOpt.cpp1
-rw-r--r--llvm/lib/Transforms/IPO/Internalize.cpp1
-rw-r--r--llvm/lib/Transforms/Utils/FunctionImportUtils.cpp20
-rw-r--r--llvm/lib/Transforms/Utils/ModuleUtils.cpp17
-rw-r--r--llvm/test/Transforms/FunctionImport/Inputs/inlineasm.ll11
-rw-r--r--llvm/test/Transforms/FunctionImport/inlineasm.ll19
-rw-r--r--llvm/tools/gold/gold-plugin.cpp1
12 files changed, 101 insertions, 27 deletions
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index 05e704978ae..0a6a127bb0d 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -35,6 +35,7 @@ class GVMaterializer;
class LLVMContext;
class RandomNumberGenerator;
class StructType;
+template <class PtrType> class SmallPtrSetImpl;
template<> struct ilist_traits<NamedMDNode>
: public ilist_default_traits<NamedMDNode> {
@@ -748,6 +749,12 @@ public:
/// @}
};
+/// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect
+/// the initializer elements of that global in Set and return the global itself.
+GlobalVariable *collectUsedGlobalVariables(const Module &M,
+ SmallPtrSetImpl<GlobalValue *> &Set,
+ bool CompilerUsed);
+
/// An raw_ostream inserter for modules.
inline raw_ostream &operator<<(raw_ostream &O, const Module &M) {
M.print(O, nullptr);
diff --git a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
index 4781bd623b7..2eb2b1363b0 100644
--- a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
@@ -28,7 +28,6 @@ class Constant;
class StringRef;
class Value;
class Type;
-template <class PtrType> class SmallPtrSetImpl;
/// Append F to the list of global ctors of module M with the given Priority.
/// This wraps the function in the appropriate structure and stores it along
@@ -41,12 +40,6 @@ void appendToGlobalCtors(Module &M, Function *F, int Priority,
void appendToGlobalDtors(Module &M, Function *F, int Priority,
Constant *Data = nullptr);
-/// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect
-/// the initializer elements of that global in Set and return the global itself.
-GlobalVariable *collectUsedGlobalVariables(Module &M,
- SmallPtrSetImpl<GlobalValue *> &Set,
- bool CompilerUsed);
-
// Validate the result of Module::getOrInsertFunction called for an interface
// function of given sanitizer. If the instrumented module defines a function
// with the same name, their prototypes must match, otherwise
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);
diff --git a/llvm/test/Transforms/FunctionImport/Inputs/inlineasm.ll b/llvm/test/Transforms/FunctionImport/Inputs/inlineasm.ll
new file mode 100644
index 00000000000..1ffc5db5f8b
--- /dev/null
+++ b/llvm/test/Transforms/FunctionImport/Inputs/inlineasm.ll
@@ -0,0 +1,11 @@
+@myvar = internal constant i8 1, align 1
+@llvm.used = appending global [1 x i8*] [i8* @myvar], section "llvm.metadata"
+
+define void @foo(i64* %v) #0 {
+entry:
+ %v.addr = alloca i64*, align 8
+ store i64* %v, i64** %v.addr, align 8
+ %0 = load i64*, i64** %v.addr, align 8
+ call void asm sideeffect "movzbl myvar(%rip), %eax\0A\09movq %rax, $0\0A\09", "=*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i64* %0) #1
+ ret void
+}
diff --git a/llvm/test/Transforms/FunctionImport/inlineasm.ll b/llvm/test/Transforms/FunctionImport/inlineasm.ll
new file mode 100644
index 00000000000..d0516f14653
--- /dev/null
+++ b/llvm/test/Transforms/FunctionImport/inlineasm.ll
@@ -0,0 +1,19 @@
+; Do setup work for all below tests: generate bitcode and combined index
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/inlineasm.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+
+; Attempt the import now, ensure below that file containing inline assembly
+; is not imported from. Otherwise we would need to promote its local variable
+; used in the inline assembly, which would not see the rename.
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=CHECK
+
+define i32 @main() #0 {
+entry:
+ %f = alloca i64, align 8
+ call void @foo(i64* %f)
+ ret i32 0
+}
+
+; CHECK: declare void @foo(i64*)
+declare void @foo(i64*) #1
diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp
index 1c78d2fc745..42e93b1c58f 100644
--- a/llvm/tools/gold/gold-plugin.cpp
+++ b/llvm/tools/gold/gold-plugin.cpp
@@ -44,7 +44,6 @@
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
#include "llvm/Transforms/Utils/GlobalStatus.h"
-#include "llvm/Transforms/Utils/ModuleUtils.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <list>
#include <plugin-api.h>
OpenPOWER on IntegriCloud