[llvm] 84870c4 - [GlobalOpt] Collect initializer when building GlobalPart.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 19 13:54:10 PDT 2023


Author: Florian Hahn
Date: 2023-03-19T20:47:59Z
New Revision: 84870c4abbacfb97ca025c9219b724f381611380

URL: https://github.com/llvm/llvm-project/commit/84870c4abbacfb97ca025c9219b724f381611380
DIFF: https://github.com/llvm/llvm-project/commit/84870c4abbacfb97ca025c9219b724f381611380.diff

LOG: [GlobalOpt] Collect initializer when building GlobalPart.

Update the code to collect the initializer when collecting the types for
a global, as suggested by @nikic in D144476.

This replaces code which bailed out if *any* part doesn't have an
initializer with a continue to just skip parts which don't have an
initializer.

Depends on D145489.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D145490

Added: 
    

Modified: 
    llvm/lib/Transforms/IPO/GlobalOpt.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
index 622733dad24bd..1d5661119df84 100644
--- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
@@ -342,6 +342,7 @@ static bool CleanupConstantGlobalUsers(GlobalVariable *GV,
 /// loads and stores with the given type.
 struct GlobalPart {
   Type *Ty;
+  Constant *Initializer = nullptr;
   bool IsLoaded = false;
   bool IsStored = false;
 };
@@ -384,15 +385,27 @@ static bool collectSRATypes(DenseMap<uint64_t, GlobalPart> &Parts,
       // TODO: We currently require that all accesses at a given offset must
       // use the same type. This could be relaxed.
       Type *Ty = getLoadStoreType(V);
-      auto It = Parts.try_emplace(Offset.getZExtValue(), GlobalPart{Ty}).first;
+      const auto &[It, Inserted] =
+          Parts.try_emplace(Offset.getZExtValue(), GlobalPart{Ty});
       if (Ty != It->second.Ty)
         return false;
 
+      if (Inserted) {
+        It->second.Initializer =
+            ConstantFoldLoadFromConst(GV->getInitializer(), Ty, Offset, DL);
+        if (!It->second.Initializer) {
+          LLVM_DEBUG(dbgs() << "Global SRA: Failed to evaluate initializer of "
+                            << *GV << " with type " << *Ty << " at offset "
+                            << Offset.getZExtValue());
+          return false;
+        }
+      }
+
       // Scalable types not currently supported.
       if (isa<ScalableVectorType>(Ty))
         return false;
 
-      auto IsStored = [GV, &DL, &Offset](Value *V) {
+      auto IsStored = [](Value *V, Constant *Initializer) {
         auto *SI = dyn_cast<StoreInst>(V);
         if (!SI)
           return false;
@@ -402,15 +415,11 @@ static bool collectSRATypes(DenseMap<uint64_t, GlobalPart> &Parts,
           return true;
 
         // Don't consider stores that only write the initializer value.
-        if (Constant *Result = ConstantFoldLoadFromConst(
-                GV->getInitializer(), StoredConst->getType(), Offset, DL))
-          return Result != StoredConst;
-
-        return true;
+        return Initializer != StoredConst;
       };
 
       It->second.IsLoaded |= isa<LoadInst>(V);
-      It->second.IsStored |= IsStored(V);
+      It->second.IsStored |= IsStored(V, It->second.Initializer);
       continue;
     }
 
@@ -531,14 +540,16 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const DataLayout &DL) {
     return nullptr;
 
   // Sort by offset.
-  SmallVector<std::pair<uint64_t, Type *>, 16> TypesVector;
-  for (const auto &Pair : Parts)
-    TypesVector.push_back({Pair.first, Pair.second.Ty});
+  SmallVector<std::tuple<uint64_t, Type *, Constant *>, 16> TypesVector;
+  for (const auto &Pair : Parts) {
+    TypesVector.push_back(
+        {Pair.first, Pair.second.Ty, Pair.second.Initializer});
+  }
   sort(TypesVector, llvm::less_first());
 
   // Check that the types are non-overlapping.
   uint64_t Offset = 0;
-  for (const auto &[OffsetForTy, Ty] : TypesVector) {
+  for (const auto &[OffsetForTy, Ty, _] : TypesVector) {
     // Overlaps with previous type.
     if (OffsetForTy < Offset)
       return nullptr;
@@ -550,21 +561,6 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const DataLayout &DL) {
   if (Offset > DL.getTypeAllocSize(GV->getValueType()))
     return nullptr;
 
-  // Collect initializers for new globals.
-  Constant *OrigInit = GV->getInitializer();
-  DenseMap<uint64_t, Constant *> Initializers;
-  for (const auto &[OffsetForTy, Ty] : TypesVector) {
-    Constant *NewInit =
-        ConstantFoldLoadFromConst(OrigInit, Ty, APInt(64, OffsetForTy), DL);
-    if (!NewInit) {
-      LLVM_DEBUG(dbgs() << "Global SRA: Failed to evaluate initializer of "
-                        << *GV << " with type " << *Ty << " at offset "
-                        << OffsetForTy << "\n");
-      return nullptr;
-    }
-    Initializers.insert({OffsetForTy, NewInit});
-  }
-
   LLVM_DEBUG(dbgs() << "PERFORMING GLOBAL SRA ON: " << *GV << "\n");
 
   // Get the alignment of the global, either explicit or target-specific.
@@ -575,11 +571,11 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const DataLayout &DL) {
   // Create replacement globals.
   DenseMap<uint64_t, GlobalVariable *> NewGlobals;
   unsigned NameSuffix = 0;
-  for (auto &[OffsetForTy, Ty] : TypesVector) {
+  for (auto &[OffsetForTy, Ty, Initializer] : TypesVector) {
     GlobalVariable *NGV = new GlobalVariable(
         *GV->getParent(), Ty, false, GlobalVariable::InternalLinkage,
-        Initializers[OffsetForTy], GV->getName() + "." + Twine(NameSuffix++),
-        GV, GV->getThreadLocalMode(), GV->getAddressSpace());
+        Initializer, GV->getName() + "." + Twine(NameSuffix++), GV,
+        GV->getThreadLocalMode(), GV->getAddressSpace());
     NGV->copyAttributesFrom(GV);
     NewGlobals.insert({OffsetForTy, NGV});
 


        


More information about the llvm-commits mailing list