[llvm] r223215 - Ask the module for its the identified types.

Rafael Espindola rafael.espindola at gmail.com
Tue Dec 2 23:18:24 PST 2014


Author: rafael
Date: Wed Dec  3 01:18:23 2014
New Revision: 223215

URL: http://llvm.org/viewvc/llvm-project?rev=223215&view=rev
Log:
Ask the module for its the identified types.

When lazy reading a module, the types used in a function will not be visible to
a TypeFinder until the body is read.

This patch fixes that by asking the module for its identified struct types.
If a materializer is present, the module asks it. If not, it uses a TypeFinder.

This fixes pr21374.

I will be the first to say that this is ugly, but it was the best I could find.

Some of the options I looked at:

* Asking the LLVMContext. This could be made to work for gold, but not currently
  for ld64. ld64 will load multiple modules into a single context before merging
  them. This causes us to see types from future merges. Unfortunately,
  MappedTypes is not just a cache when it comes to opaque types. Once the
  mapping has been made, we have to remember it for as long as the key may
  be used. This would mean moving MappedTypes to the Linker class and having
  to drop the Linker::LinkModules static methods, which are visible from C.

* Adding an option to ignore function bodies in the TypeFinder. This would
  fix the PR by picking the worst result. It would work, but unfortunately
  we are currently quite dependent on the upfront type merging. I will
  try to reduce our dependency, but it is not clear that we will be able
  to get rid of it for now.

The only clean solution I could think of is making the Module own the types.
This would have other advantages, but it is a much bigger change. I will
propose it, but it is nice to have this fixed while that is discussed.

With the gold plugin, this patch takes the number of types in the LTO clang
binary from 52817 to 49669.

Added:
    llvm/trunk/test/Linker/Inputs/pr21374.ll
    llvm/trunk/test/Linker/pr21374.ll
Modified:
    llvm/trunk/include/llvm/IR/GVMaterializer.h
    llvm/trunk/include/llvm/IR/Module.h
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h
    llvm/trunk/lib/IR/Module.cpp
    llvm/trunk/lib/Linker/LinkModules.cpp

Modified: llvm/trunk/include/llvm/IR/GVMaterializer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/GVMaterializer.h?rev=223215&r1=223214&r2=223215&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/GVMaterializer.h (original)
+++ llvm/trunk/include/llvm/IR/GVMaterializer.h Wed Dec  3 01:18:23 2014
@@ -19,11 +19,13 @@
 #define LLVM_IR_GVMATERIALIZER_H
 
 #include <system_error>
+#include <vector>
 
 namespace llvm {
 class Function;
 class GlobalValue;
 class Module;
+class StructType;
 
 class GVMaterializer {
 protected:
@@ -50,6 +52,8 @@ public:
   /// Make sure the entire Module has been completely read.
   ///
   virtual std::error_code MaterializeModule(Module *M) = 0;
+
+  virtual std::vector<StructType *> getIdentifiedStructTypes() const = 0;
 };
 
 } // End llvm namespace

Modified: llvm/trunk/include/llvm/IR/Module.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Module.h?rev=223215&r1=223214&r2=223215&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Module.h (original)
+++ llvm/trunk/include/llvm/IR/Module.h Wed Dec  3 01:18:23 2014
@@ -327,6 +327,8 @@ public:
   /// name.
   StructType *getTypeByName(StringRef Name) const;
 
+  std::vector<StructType *> getIdentifiedStructTypes() const;
+
 /// @}
 /// @name Function Accessors
 /// @{

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=223215&r1=223214&r2=223215&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Wed Dec  3 01:18:23 2014
@@ -487,7 +487,20 @@ Type *BitcodeReader::getTypeByID(unsigne
 
   // If we have a forward reference, the only possible case is when it is to a
   // named struct.  Just create a placeholder for now.
-  return TypeList[ID] = StructType::create(Context);
+  return TypeList[ID] = createIdentifiedStructType(Context);
+}
+
+StructType *BitcodeReader::createIdentifiedStructType(LLVMContext &Context,
+                                                      StringRef Name) {
+  auto *Ret = StructType::create(Context, Name);
+  IdentifiedStructTypes.push_back(Ret);
+  return Ret;
+}
+
+StructType *BitcodeReader::createIdentifiedStructType(LLVMContext &Context) {
+  auto *Ret = StructType::create(Context);
+  IdentifiedStructTypes.push_back(Ret);
+  return Ret;
 }
 
 
@@ -922,7 +935,7 @@ std::error_code BitcodeReader::ParseType
         Res->setName(TypeName);
         TypeList[NumRecords] = nullptr;
       } else  // Otherwise, create a new struct.
-        Res = StructType::create(Context, TypeName);
+        Res = createIdentifiedStructType(Context, TypeName);
       TypeName.clear();
 
       SmallVector<Type*, 8> EltTys;
@@ -951,7 +964,7 @@ std::error_code BitcodeReader::ParseType
         Res->setName(TypeName);
         TypeList[NumRecords] = nullptr;
       } else  // Otherwise, create a new struct with no body.
-        Res = StructType::create(Context, TypeName);
+        Res = createIdentifiedStructType(Context, TypeName);
       TypeName.clear();
       ResultTy = Res;
       break;
@@ -3416,6 +3429,10 @@ std::error_code BitcodeReader::Materiali
   return std::error_code();
 }
 
+std::vector<StructType *> BitcodeReader::getIdentifiedStructTypes() const {
+  return IdentifiedStructTypes;
+}
+
 std::error_code BitcodeReader::InitStream() {
   if (LazyStreamer)
     return InitLazyStream();

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h?rev=223215&r1=223214&r2=223215&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h Wed Dec  3 01:18:23 2014
@@ -227,6 +227,7 @@ public:
   bool isDematerializable(const GlobalValue *GV) const override;
   std::error_code materialize(GlobalValue *GV) override;
   std::error_code MaterializeModule(Module *M) override;
+  std::vector<StructType *> getIdentifiedStructTypes() const override;
   void Dematerialize(GlobalValue *GV) override;
 
   /// @brief Main interface to parsing a bitcode buffer.
@@ -240,6 +241,10 @@ public:
   static uint64_t decodeSignRotatedValue(uint64_t V);
 
 private:
+  std::vector<StructType *> IdentifiedStructTypes;
+  StructType *createIdentifiedStructType(LLVMContext &Context, StringRef Name);
+  StructType *createIdentifiedStructType(LLVMContext &Context);
+
   Type *getTypeByID(unsigned ID);
   Value *getFnValueByID(unsigned ID, Type *Ty) {
     if (Ty && Ty->isMetadataTy())

Modified: llvm/trunk/lib/IR/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Module.cpp?rev=223215&r1=223214&r2=223215&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Module.cpp (original)
+++ llvm/trunk/lib/IR/Module.cpp Wed Dec  3 01:18:23 2014
@@ -23,6 +23,7 @@
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/LeakDetector.h"
+#include "llvm/IR/TypeFinder.h"
 #include "llvm/Support/Dwarf.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/RandomNumberGenerator.h"
@@ -425,6 +426,19 @@ std::error_code Module::materializeAllPe
 // Other module related stuff.
 //
 
+std::vector<StructType *> Module::getIdentifiedStructTypes() const {
+  // If we have a materializer, it is possible that some unread function
+  // uses a type that is currently not visible to a TypeFinder, so ask
+  // the materializer which types it created.
+  if (Materializer)
+    return Materializer->getIdentifiedStructTypes();
+
+  std::vector<StructType *> Ret;
+  TypeFinder SrcStructTypes;
+  SrcStructTypes.run(*this, true);
+  Ret.assign(SrcStructTypes.begin(), SrcStructTypes.end());
+  return Ret;
+}
 
 // dropAllReferences() - This function causes all the subelements to "let go"
 // of all references that they are maintaining.  This allows one to 'delete' a

Modified: llvm/trunk/lib/Linker/LinkModules.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=223215&r1=223214&r2=223215&view=diff
==============================================================================
--- llvm/trunk/lib/Linker/LinkModules.cpp (original)
+++ llvm/trunk/lib/Linker/LinkModules.cpp Wed Dec  3 01:18:23 2014
@@ -791,10 +791,8 @@ void ModuleLinker::computeTypeMapping()
   // At this point, the destination module may have a type "%foo = { i32 }" for
   // example.  When the source module got loaded into the same LLVMContext, if
   // it had the same type, it would have been renamed to "%foo.42 = { i32 }".
-  TypeFinder SrcStructTypes;
-  SrcStructTypes.run(*SrcM, true);
-
-  for (StructType *ST : SrcStructTypes) {
+  std::vector<StructType *> Types = SrcM->getIdentifiedStructTypes();
+  for (StructType *ST : Types) {
     if (!ST->hasName())
       continue;
 

Added: llvm/trunk/test/Linker/Inputs/pr21374.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/Inputs/pr21374.ll?rev=223215&view=auto
==============================================================================
--- llvm/trunk/test/Linker/Inputs/pr21374.ll (added)
+++ llvm/trunk/test/Linker/Inputs/pr21374.ll Wed Dec  3 01:18:23 2014
@@ -0,0 +1,4 @@
+%foo = type { i8* }
+define void @g(%foo* %x) {
+  ret void
+}

Added: llvm/trunk/test/Linker/pr21374.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/pr21374.ll?rev=223215&view=auto
==============================================================================
--- llvm/trunk/test/Linker/pr21374.ll (added)
+++ llvm/trunk/test/Linker/pr21374.ll Wed Dec  3 01:18:23 2014
@@ -0,0 +1,20 @@
+; RUN: llvm-link -S -o - %p/pr21374.ll %p/Inputs/pr21374.ll | FileCheck %s
+; RUN: llvm-link -S -o - %p/Inputs/pr21374.ll %p/pr21374.ll | FileCheck %s
+
+; RUN: llvm-as -o %t1.bc %p/pr21374.ll
+; RUN: llvm-as -o %t2.bc %p/Inputs/pr21374.ll
+
+; RUN: llvm-link -S -o - %t1.bc %t2.bc | FileCheck %s
+; RUN: llvm-link -S -o - %t2.bc %t1.bc | FileCheck %s
+
+; Test that we get the same result with or without lazy loading.
+
+; CHECK: %foo = type { i8* }
+; CHECK-DAG: bitcast i32* null to %foo*
+; CHECK-DAG: define void @g(%foo* %x)
+
+%foo = type { i8* }
+define void @f() {
+  bitcast i32* null to %foo*
+  ret void
+}





More information about the llvm-commits mailing list