diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -306,7 +306,7 @@ inline bool operator!=(const RangeTy &A, const RangeTy &B) { return !(A == B); } /// Return the initial value of \p Obj with type \p Ty if that is a constant. -Constant *getInitialValueForObj(Value &Obj, Type &Ty, +Constant *getInitialValueForObj(Attributor &A, Value &Obj, Type &Ty, const TargetLibraryInfo *TLI, const DataLayout &DL, RangeTy *RangePtr = nullptr); @@ -1895,6 +1895,35 @@ return SimplificationCallbacks.count(IRP); } + /// Register \p CB as a simplification callback. + /// Similar to \p registerSimplificationCallback, the call back will be called + /// first when we simplify a global variable \p GV. + using GlobalVariableSimplifictionCallbackTy = + std::function( + const GlobalVariable &, const AbstractAttribute *, bool &)>; + void registerGlobalVariableSimplificationCallback( + const GlobalVariable &GV, + const GlobalVariableSimplifictionCallbackTy &CB) { + GlobalVariableSimplificationCallbacks[&GV].emplace_back(CB); + } + + /// Return \p std::nullopt if there is no call back registered for \p GV or + /// the call back is still not sure if \p GV can be simplified. Return \p + /// nullptr if \p GV can't be simplified. + std::optional + getAssumedSimplifiedGlobalVariableFromCallBack(const GlobalVariable &GV, + const AbstractAttribute *AA, + bool &UsedAssumedInformation) { + if (!GlobalVariableSimplificationCallbacks.count(&GV)) + return std::nullopt; + for (auto &CB : GlobalVariableSimplificationCallbacks.lookup(&GV)) { + auto SimplifiedGV = CB(GV, AA, UsedAssumedInformation); + if (SimplifiedGV.has_value()) + return *SimplifiedGV; + } + return std::nullopt; + } + using VirtualUseCallbackTy = std::function; void registerVirtualUseCallback(const Value &V, @@ -1907,6 +1936,12 @@ DenseMap> SimplificationCallbacks; + /// The vector with all simplification callbacks for global variables + /// registered by outside AAs. + DenseMap> + GlobalVariableSimplificationCallbacks; + DenseMap> VirtualUseCallbacks; diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -222,7 +222,7 @@ return InstanceInfoAA.isAssumedUniqueForAnalysis(); } -Constant *AA::getInitialValueForObj(Value &Obj, Type &Ty, +Constant *AA::getInitialValueForObj(Attributor &A, Value &Obj, Type &Ty, const TargetLibraryInfo *TLI, const DataLayout &DL, AA::RangeTy *RangePtr) { @@ -233,17 +233,31 @@ auto *GV = dyn_cast(&Obj); if (!GV) return nullptr; + + bool UsedAssumedInformation = false; + Constant *Initializer = nullptr; + auto AssumedGV = A.getAssumedSimplifiedGlobalVariableFromCallBack( + *GV, /* const AbstractAttribute *AA */ nullptr, UsedAssumedInformation); + if (AssumedGV.has_value()) { + Initializer = *AssumedGV; + if (!Initializer) + return nullptr; + } + if (!GV->hasLocalLinkage() && !(GV->isConstant() && GV->hasInitializer())) return nullptr; if (!GV->hasInitializer()) return UndefValue::get(&Ty); + if (!Initializer) + Initializer = GV->getInitializer(); + if (RangePtr && !RangePtr->offsetOrSizeAreUnknown()) { APInt Offset = APInt(64, RangePtr->Offset); - return ConstantFoldLoadFromConst(GV->getInitializer(), &Ty, Offset, DL); + return ConstantFoldLoadFromConst(Initializer, &Ty, Offset, DL); } - return ConstantFoldLoadFromUniformValue(GV->getInitializer(), &Ty); + return ConstantFoldLoadFromUniformValue(Initializer, &Ty); } bool AA::isValidInScope(const Value &V, const Function *Scope) { @@ -482,7 +496,7 @@ if (IsLoad && !HasBeenWrittenTo && !Range.isUnassigned()) { const DataLayout &DL = A.getDataLayout(); Value *InitialValue = - AA::getInitialValueForObj(Obj, *I.getType(), TLI, DL, &Range); + AA::getInitialValueForObj(A, Obj, *I.getType(), TLI, DL, &Range); if (!InitialValue) { LLVM_DEBUG(dbgs() << "Could not determine required initial value of " "underlying object, abort!\n");