[llvm] r266877 - [ThinLTO] Prevent importing of "llvm.used" values

Teresa Johnson via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 20 07:39:46 PDT 2016


Author: tejohnson
Date: Wed Apr 20 09:39:45 2016
New Revision: 266877

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

Added:
    llvm/trunk/test/Transforms/FunctionImport/Inputs/inlineasm.ll
    llvm/trunk/test/Transforms/FunctionImport/inlineasm.ll
Modified:
    llvm/trunk/include/llvm/IR/Module.h
    llvm/trunk/include/llvm/Transforms/Utils/ModuleUtils.h
    llvm/trunk/lib/Analysis/ModuleSummaryAnalysis.cpp
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/trunk/lib/IR/Module.cpp
    llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
    llvm/trunk/lib/Transforms/IPO/Internalize.cpp
    llvm/trunk/lib/Transforms/Utils/FunctionImportUtils.cpp
    llvm/trunk/lib/Transforms/Utils/ModuleUtils.cpp
    llvm/trunk/tools/gold/gold-plugin.cpp

Modified: llvm/trunk/include/llvm/IR/Module.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Module.h?rev=266877&r1=266876&r2=266877&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Module.h (original)
+++ llvm/trunk/include/llvm/IR/Module.h Wed Apr 20 09:39:45 2016
@@ -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);

Modified: llvm/trunk/include/llvm/Transforms/Utils/ModuleUtils.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/ModuleUtils.h?rev=266877&r1=266876&r2=266877&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/ModuleUtils.h (original)
+++ llvm/trunk/include/llvm/Transforms/Utils/ModuleUtils.h Wed Apr 20 09:39:45 2016
@@ -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, Func
 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

Modified: llvm/trunk/lib/Analysis/ModuleSummaryAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ModuleSummaryAnalysis.cpp?rev=266877&r1=266876&r2=266877&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ModuleSummaryAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/ModuleSummaryAnalysis.cpp Wed Apr 20 09:39:45 2016
@@ -120,6 +120,31 @@ ModuleSummaryIndexBuilder::ModuleSummary
     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) {

Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=266877&r1=266876&r2=266877&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Wed Apr 20 09:39:45 2016
@@ -2889,6 +2889,9 @@ static void WritePerModuleGlobalValueSum
   if (M->empty())
     return;
 
+  if (Index.begin() == Index.end())
+    return;
+
   Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3);
 
   // Abbrev for FS_PERMODULE.

Modified: llvm/trunk/lib/IR/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Module.cpp?rev=266877&r1=266876&r2=266877&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Module.cpp (original)
+++ llvm/trunk/lib/IR/Module.cpp Wed Apr 20 09:39:45 2016
@@ -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
 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;
+}

Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=266877&r1=266876&r2=266877&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Wed Apr 20 09:39:45 2016
@@ -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;
 

Modified: llvm/trunk/lib/Transforms/IPO/Internalize.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Internalize.cpp?rev=266877&r1=266876&r2=266877&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/Internalize.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/Internalize.cpp Wed Apr 20 09:39:45 2016
@@ -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;

Modified: llvm/trunk/lib/Transforms/Utils/FunctionImportUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/FunctionImportUtils.cpp?rev=266877&r1=266876&r2=266877&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/FunctionImportUtils.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/FunctionImportUtils.cpp Wed Apr 20 09:39:45 2016
@@ -206,6 +206,26 @@ void FunctionImportGlobalProcessing::pro
 }
 
 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)

Modified: llvm/trunk/lib/Transforms/Utils/ModuleUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/ModuleUtils.cpp?rev=266877&r1=266876&r2=266877&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/ModuleUtils.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/ModuleUtils.cpp Wed Apr 20 09:39:45 2016
@@ -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
   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);

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/inlineasm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/inlineasm.ll?rev=266877&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/inlineasm.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/inlineasm.ll Wed Apr 20 09:39:45 2016
@@ -0,0 +1,11 @@
+ at myvar = internal constant i8 1, align 1
+ at 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
+}

Added: llvm/trunk/test/Transforms/FunctionImport/inlineasm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/inlineasm.ll?rev=266877&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/inlineasm.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/inlineasm.ll Wed Apr 20 09:39:45 2016
@@ -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

Modified: llvm/trunk/tools/gold/gold-plugin.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/gold/gold-plugin.cpp?rev=266877&r1=266876&r2=266877&view=diff
==============================================================================
--- llvm/trunk/tools/gold/gold-plugin.cpp (original)
+++ llvm/trunk/tools/gold/gold-plugin.cpp Wed Apr 20 09:39:45 2016
@@ -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>




More information about the llvm-commits mailing list