[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