[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
This commit is contained in:
Florian Hahn 2023-03-19 20:47:59 +00:00
parent ef860cf150
commit 84870c4abb
No known key found for this signature in database
GPG Key ID: EEF712BB5E80EBBA

View File

@ -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});