mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[NFC] Disambiguate LI in GVN
Name GVN uses name 'LI' for two different unrelated things: LoadInst and LoopInfo. This patch relates the variables with former meaning into 'Load' to disambiguate the code.
This commit is contained in:
parent
1c951bda95
commit
467293274d
@ -314,17 +314,17 @@ private:
|
||||
/// Given a local dependency (Def or Clobber) determine if a value is
|
||||
/// available for the load. Returns true if an value is known to be
|
||||
/// available and populates Res. Returns false otherwise.
|
||||
bool AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo,
|
||||
bool AnalyzeLoadAvailability(LoadInst *Load, MemDepResult DepInfo,
|
||||
Value *Address, gvn::AvailableValue &Res);
|
||||
|
||||
/// Given a list of non-local dependencies, determine if a value is
|
||||
/// available for the load in each specified block. If it is, add it to
|
||||
/// ValuesPerBlock. If not, add it to UnavailableBlocks.
|
||||
void AnalyzeLoadAvailability(LoadInst *LI, LoadDepVect &Deps,
|
||||
void AnalyzeLoadAvailability(LoadInst *Load, LoadDepVect &Deps,
|
||||
AvailValInBlkVect &ValuesPerBlock,
|
||||
UnavailBlkVect &UnavailableBlocks);
|
||||
|
||||
bool PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
bool PerformLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
|
||||
UnavailBlkVect &UnavailableBlocks);
|
||||
|
||||
// Other helper routines
|
||||
|
@ -208,9 +208,9 @@ struct llvm::gvn::AvailableValue {
|
||||
return Res;
|
||||
}
|
||||
|
||||
static AvailableValue getLoad(LoadInst *LI, unsigned Offset = 0) {
|
||||
static AvailableValue getLoad(LoadInst *Load, unsigned Offset = 0) {
|
||||
AvailableValue Res;
|
||||
Res.Val.setPointer(LI);
|
||||
Res.Val.setPointer(Load);
|
||||
Res.Val.setInt(LoadVal);
|
||||
Res.Offset = Offset;
|
||||
return Res;
|
||||
@ -246,7 +246,7 @@ struct llvm::gvn::AvailableValue {
|
||||
|
||||
/// Emit code at the specified insertion point to adjust the value defined
|
||||
/// here to the specified type. This handles various coercion cases.
|
||||
Value *MaterializeAdjustedValue(LoadInst *LI, Instruction *InsertPt,
|
||||
Value *MaterializeAdjustedValue(LoadInst *Load, Instruction *InsertPt,
|
||||
GVN &gvn) const;
|
||||
};
|
||||
|
||||
@ -277,8 +277,8 @@ struct llvm::gvn::AvailableValueInBlock {
|
||||
|
||||
/// Emit code at the end of this block to adjust the value defined here to
|
||||
/// the specified type. This handles various coercion cases.
|
||||
Value *MaterializeAdjustedValue(LoadInst *LI, GVN &gvn) const {
|
||||
return AV.MaterializeAdjustedValue(LI, BB->getTerminator(), gvn);
|
||||
Value *MaterializeAdjustedValue(LoadInst *Load, GVN &gvn) const {
|
||||
return AV.MaterializeAdjustedValue(Load, BB->getTerminator(), gvn);
|
||||
}
|
||||
};
|
||||
|
||||
@ -670,10 +670,10 @@ PreservedAnalyses GVN::run(Function &F, FunctionAnalysisManager &AM) {
|
||||
auto &AA = AM.getResult<AAManager>(F);
|
||||
auto *MemDep =
|
||||
isMemDepEnabled() ? &AM.getResult<MemoryDependenceAnalysis>(F) : nullptr;
|
||||
auto *LI = AM.getCachedResult<LoopAnalysis>(F);
|
||||
auto *Load = AM.getCachedResult<LoopAnalysis>(F);
|
||||
auto *MSSA = AM.getCachedResult<MemorySSAAnalysis>(F);
|
||||
auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F);
|
||||
bool Changed = runImpl(F, AC, DT, TLI, AA, MemDep, LI, &ORE,
|
||||
bool Changed = runImpl(F, AC, DT, TLI, AA, MemDep, Load, &ORE,
|
||||
MSSA ? &MSSA->getMSSA() : nullptr);
|
||||
if (!Changed)
|
||||
return PreservedAnalyses::all();
|
||||
@ -683,7 +683,7 @@ PreservedAnalyses GVN::run(Function &F, FunctionAnalysisManager &AM) {
|
||||
PA.preserve<TargetLibraryAnalysis>();
|
||||
if (MSSA)
|
||||
PA.preserve<MemorySSAAnalysis>();
|
||||
if (LI)
|
||||
if (Load)
|
||||
PA.preserve<LoopAnalysis>();
|
||||
return PA;
|
||||
}
|
||||
@ -736,7 +736,7 @@ static bool IsValueFullyAvailableInBlock(
|
||||
|
||||
Worklist.emplace_back(BB);
|
||||
while (!Worklist.empty()) {
|
||||
BasicBlock *CurrBB = Worklist.pop_back_val(); // LIFO - depth-first!
|
||||
BasicBlock *CurrBB = Worklist.pop_back_val(); // LoadFO - depth-first!
|
||||
// Optimistically assume that the block is Speculatively Available and check
|
||||
// to see if we already know about this block in one lookup.
|
||||
std::pair<DenseMap<BasicBlock *, AvailabilityState>::iterator, bool> IV =
|
||||
@ -834,25 +834,26 @@ static bool IsValueFullyAvailableInBlock(
|
||||
}
|
||||
|
||||
/// Given a set of loads specified by ValuesPerBlock,
|
||||
/// construct SSA form, allowing us to eliminate LI. This returns the value
|
||||
/// that should be used at LI's definition site.
|
||||
static Value *ConstructSSAForLoadSet(LoadInst *LI,
|
||||
SmallVectorImpl<AvailableValueInBlock> &ValuesPerBlock,
|
||||
GVN &gvn) {
|
||||
/// construct SSA form, allowing us to eliminate Load. This returns the value
|
||||
/// that should be used at Load's definition site.
|
||||
static Value *
|
||||
ConstructSSAForLoadSet(LoadInst *Load,
|
||||
SmallVectorImpl<AvailableValueInBlock> &ValuesPerBlock,
|
||||
GVN &gvn) {
|
||||
// Check for the fully redundant, dominating load case. In this case, we can
|
||||
// just use the dominating value directly.
|
||||
if (ValuesPerBlock.size() == 1 &&
|
||||
gvn.getDominatorTree().properlyDominates(ValuesPerBlock[0].BB,
|
||||
LI->getParent())) {
|
||||
Load->getParent())) {
|
||||
assert(!ValuesPerBlock[0].AV.isUndefValue() &&
|
||||
"Dead BB dominate this block");
|
||||
return ValuesPerBlock[0].MaterializeAdjustedValue(LI, gvn);
|
||||
return ValuesPerBlock[0].MaterializeAdjustedValue(Load, gvn);
|
||||
}
|
||||
|
||||
// Otherwise, we have to construct SSA form.
|
||||
SmallVector<PHINode*, 8> NewPHIs;
|
||||
SSAUpdater SSAUpdate(&NewPHIs);
|
||||
SSAUpdate.Initialize(LI->getType(), LI->getName());
|
||||
SSAUpdate.Initialize(Load->getType(), Load->getName());
|
||||
|
||||
for (const AvailableValueInBlock &AV : ValuesPerBlock) {
|
||||
BasicBlock *BB = AV.BB;
|
||||
@ -867,24 +868,24 @@ static Value *ConstructSSAForLoadSet(LoadInst *LI,
|
||||
// available in is the block that the load is in, then don't add it as
|
||||
// SSAUpdater will resolve the value to the relevant phi which may let it
|
||||
// avoid phi construction entirely if there's actually only one value.
|
||||
if (BB == LI->getParent() &&
|
||||
((AV.AV.isSimpleValue() && AV.AV.getSimpleValue() == LI) ||
|
||||
(AV.AV.isCoercedLoadValue() && AV.AV.getCoercedLoadValue() == LI)))
|
||||
if (BB == Load->getParent() &&
|
||||
((AV.AV.isSimpleValue() && AV.AV.getSimpleValue() == Load) ||
|
||||
(AV.AV.isCoercedLoadValue() && AV.AV.getCoercedLoadValue() == Load)))
|
||||
continue;
|
||||
|
||||
SSAUpdate.AddAvailableValue(BB, AV.MaterializeAdjustedValue(LI, gvn));
|
||||
SSAUpdate.AddAvailableValue(BB, AV.MaterializeAdjustedValue(Load, gvn));
|
||||
}
|
||||
|
||||
// Perform PHI construction.
|
||||
return SSAUpdate.GetValueInMiddleOfBlock(LI->getParent());
|
||||
return SSAUpdate.GetValueInMiddleOfBlock(Load->getParent());
|
||||
}
|
||||
|
||||
Value *AvailableValue::MaterializeAdjustedValue(LoadInst *LI,
|
||||
Value *AvailableValue::MaterializeAdjustedValue(LoadInst *Load,
|
||||
Instruction *InsertPt,
|
||||
GVN &gvn) const {
|
||||
Value *Res;
|
||||
Type *LoadTy = LI->getType();
|
||||
const DataLayout &DL = LI->getModule()->getDataLayout();
|
||||
Type *LoadTy = Load->getType();
|
||||
const DataLayout &DL = Load->getModule()->getDataLayout();
|
||||
if (isSimpleValue()) {
|
||||
Res = getSimpleValue();
|
||||
if (Res->getType() != LoadTy) {
|
||||
@ -934,20 +935,20 @@ static bool isLifetimeStart(const Instruction *Inst) {
|
||||
|
||||
/// Try to locate the three instruction involved in a missed
|
||||
/// load-elimination case that is due to an intervening store.
|
||||
static void reportMayClobberedLoad(LoadInst *LI, MemDepResult DepInfo,
|
||||
static void reportMayClobberedLoad(LoadInst *Load, MemDepResult DepInfo,
|
||||
DominatorTree *DT,
|
||||
OptimizationRemarkEmitter *ORE) {
|
||||
using namespace ore;
|
||||
|
||||
User *OtherAccess = nullptr;
|
||||
|
||||
OptimizationRemarkMissed R(DEBUG_TYPE, "LoadClobbered", LI);
|
||||
R << "load of type " << NV("Type", LI->getType()) << " not eliminated"
|
||||
OptimizationRemarkMissed R(DEBUG_TYPE, "LoadClobbered", Load);
|
||||
R << "load of type " << NV("Type", Load->getType()) << " not eliminated"
|
||||
<< setExtraArgs();
|
||||
|
||||
for (auto *U : LI->getPointerOperand()->users())
|
||||
if (U != LI && (isa<LoadInst>(U) || isa<StoreInst>(U)) &&
|
||||
DT->dominates(cast<Instruction>(U), LI)) {
|
||||
for (auto *U : Load->getPointerOperand()->users())
|
||||
if (U != Load && (isa<LoadInst>(U) || isa<StoreInst>(U)) &&
|
||||
DT->dominates(cast<Instruction>(U), Load)) {
|
||||
// FIXME: for now give up if there are multiple memory accesses that
|
||||
// dominate the load. We need further analysis to decide which one is
|
||||
// that we're forwarding from.
|
||||
@ -965,13 +966,13 @@ static void reportMayClobberedLoad(LoadInst *LI, MemDepResult DepInfo,
|
||||
ORE->emit(R);
|
||||
}
|
||||
|
||||
bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo,
|
||||
bool GVN::AnalyzeLoadAvailability(LoadInst *Load, MemDepResult DepInfo,
|
||||
Value *Address, AvailableValue &Res) {
|
||||
assert((DepInfo.isDef() || DepInfo.isClobber()) &&
|
||||
"expected a local dependence");
|
||||
assert(LI->isUnordered() && "rules below are incorrect for ordered access");
|
||||
assert(Load->isUnordered() && "rules below are incorrect for ordered access");
|
||||
|
||||
const DataLayout &DL = LI->getModule()->getDataLayout();
|
||||
const DataLayout &DL = Load->getModule()->getDataLayout();
|
||||
|
||||
Instruction *DepInst = DepInfo.getInst();
|
||||
if (DepInfo.isClobber()) {
|
||||
@ -980,9 +981,9 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo,
|
||||
// stored value.
|
||||
if (StoreInst *DepSI = dyn_cast<StoreInst>(DepInst)) {
|
||||
// Can't forward from non-atomic to atomic without violating memory model.
|
||||
if (Address && LI->isAtomic() <= DepSI->isAtomic()) {
|
||||
if (Address && Load->isAtomic() <= DepSI->isAtomic()) {
|
||||
int Offset =
|
||||
analyzeLoadFromClobberingStore(LI->getType(), Address, DepSI, DL);
|
||||
analyzeLoadFromClobberingStore(Load->getType(), Address, DepSI, DL);
|
||||
if (Offset != -1) {
|
||||
Res = AvailableValue::get(DepSI->getValueOperand(), Offset);
|
||||
return true;
|
||||
@ -994,16 +995,17 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo,
|
||||
// load i32* P
|
||||
// load i8* (P+1)
|
||||
// if we have this, replace the later with an extraction from the former.
|
||||
if (LoadInst *DepLI = dyn_cast<LoadInst>(DepInst)) {
|
||||
if (LoadInst *DepLoad = dyn_cast<LoadInst>(DepInst)) {
|
||||
// If this is a clobber and L is the first instruction in its block, then
|
||||
// we have the first instruction in the entry block.
|
||||
// Can't forward from non-atomic to atomic without violating memory model.
|
||||
if (DepLI != LI && Address && LI->isAtomic() <= DepLI->isAtomic()) {
|
||||
int Offset =
|
||||
analyzeLoadFromClobberingLoad(LI->getType(), Address, DepLI, DL);
|
||||
if (DepLoad != Load && Address &&
|
||||
Load->isAtomic() <= DepLoad->isAtomic()) {
|
||||
int Offset = analyzeLoadFromClobberingLoad(Load->getType(), Address,
|
||||
DepLoad, DL);
|
||||
|
||||
if (Offset != -1) {
|
||||
Res = AvailableValue::getLoad(DepLI, Offset);
|
||||
Res = AvailableValue::getLoad(DepLoad, Offset);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1012,8 +1014,8 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo,
|
||||
// If the clobbering value is a memset/memcpy/memmove, see if we can
|
||||
// forward a value on from it.
|
||||
if (MemIntrinsic *DepMI = dyn_cast<MemIntrinsic>(DepInst)) {
|
||||
if (Address && !LI->isAtomic()) {
|
||||
int Offset = analyzeLoadFromClobberingMemInst(LI->getType(), Address,
|
||||
if (Address && !Load->isAtomic()) {
|
||||
int Offset = analyzeLoadFromClobberingMemInst(Load->getType(), Address,
|
||||
DepMI, DL);
|
||||
if (Offset != -1) {
|
||||
Res = AvailableValue::getMI(DepMI, Offset);
|
||||
@ -1024,10 +1026,10 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo,
|
||||
// Nothing known about this clobber, have to be conservative
|
||||
LLVM_DEBUG(
|
||||
// fast print dep, using operator<< on instruction is too slow.
|
||||
dbgs() << "GVN: load "; LI->printAsOperand(dbgs());
|
||||
dbgs() << "GVN: load "; Load->printAsOperand(dbgs());
|
||||
dbgs() << " is clobbered by " << *DepInst << '\n';);
|
||||
if (ORE->allowExtraAnalysis(DEBUG_TYPE))
|
||||
reportMayClobberedLoad(LI, DepInfo, DT, ORE);
|
||||
reportMayClobberedLoad(Load, DepInfo, DT, ORE);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -1038,13 +1040,13 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo,
|
||||
isAlignedAllocLikeFn(DepInst, TLI) ||
|
||||
// Loading immediately after lifetime begin -> undef.
|
||||
isLifetimeStart(DepInst)) {
|
||||
Res = AvailableValue::get(UndefValue::get(LI->getType()));
|
||||
Res = AvailableValue::get(UndefValue::get(Load->getType()));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Loading from calloc (which zero initializes memory) -> zero
|
||||
if (isCallocLikeFn(DepInst, TLI)) {
|
||||
Res = AvailableValue::get(Constant::getNullValue(LI->getType()));
|
||||
Res = AvailableValue::get(Constant::getNullValue(Load->getType()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1052,12 +1054,12 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo,
|
||||
// Reject loads and stores that are to the same address but are of
|
||||
// different types if we have to. If the stored value is convertable to
|
||||
// the loaded value, we can reuse it.
|
||||
if (!canCoerceMustAliasedValueToLoad(S->getValueOperand(), LI->getType(),
|
||||
if (!canCoerceMustAliasedValueToLoad(S->getValueOperand(), Load->getType(),
|
||||
DL))
|
||||
return false;
|
||||
|
||||
// Can't forward from non-atomic to atomic without violating memory model.
|
||||
if (S->isAtomic() < LI->isAtomic())
|
||||
if (S->isAtomic() < Load->isAtomic())
|
||||
return false;
|
||||
|
||||
Res = AvailableValue::get(S->getValueOperand());
|
||||
@ -1068,11 +1070,11 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo,
|
||||
// If the types mismatch and we can't handle it, reject reuse of the load.
|
||||
// If the stored value is larger or equal to the loaded value, we can reuse
|
||||
// it.
|
||||
if (!canCoerceMustAliasedValueToLoad(LD, LI->getType(), DL))
|
||||
if (!canCoerceMustAliasedValueToLoad(LD, Load->getType(), DL))
|
||||
return false;
|
||||
|
||||
// Can't forward from non-atomic to atomic without violating memory model.
|
||||
if (LD->isAtomic() < LI->isAtomic())
|
||||
if (LD->isAtomic() < Load->isAtomic())
|
||||
return false;
|
||||
|
||||
Res = AvailableValue::getLoad(LD);
|
||||
@ -1082,12 +1084,12 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo,
|
||||
// Unknown def - must be conservative
|
||||
LLVM_DEBUG(
|
||||
// fast print dep, using operator<< on instruction is too slow.
|
||||
dbgs() << "GVN: load "; LI->printAsOperand(dbgs());
|
||||
dbgs() << "GVN: load "; Load->printAsOperand(dbgs());
|
||||
dbgs() << " has unknown def " << *DepInst << '\n';);
|
||||
return false;
|
||||
}
|
||||
|
||||
void GVN::AnalyzeLoadAvailability(LoadInst *LI, LoadDepVect &Deps,
|
||||
void GVN::AnalyzeLoadAvailability(LoadInst *Load, LoadDepVect &Deps,
|
||||
AvailValInBlkVect &ValuesPerBlock,
|
||||
UnavailBlkVect &UnavailableBlocks) {
|
||||
// Filter out useless results (non-locals, etc). Keep track of the blocks
|
||||
@ -1117,7 +1119,7 @@ void GVN::AnalyzeLoadAvailability(LoadInst *LI, LoadDepVect &Deps,
|
||||
Value *Address = Deps[i].getAddress();
|
||||
|
||||
AvailableValue AV;
|
||||
if (AnalyzeLoadAvailability(LI, DepInfo, Address, AV)) {
|
||||
if (AnalyzeLoadAvailability(Load, DepInfo, Address, AV)) {
|
||||
// subtlety: because we know this was a non-local dependency, we know
|
||||
// it's safe to materialize anywhere between the instruction within
|
||||
// DepInfo and the end of it's block.
|
||||
@ -1132,7 +1134,7 @@ void GVN::AnalyzeLoadAvailability(LoadInst *LI, LoadDepVect &Deps,
|
||||
"post condition violation");
|
||||
}
|
||||
|
||||
bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
bool GVN::PerformLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
|
||||
UnavailBlkVect &UnavailableBlocks) {
|
||||
// Okay, we have *some* definitions of the value. This means that the value
|
||||
// is available in some of our (transitive) predecessors. Lets think about
|
||||
@ -1147,7 +1149,7 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
|
||||
// Let's find the first basic block with more than one predecessor. Walk
|
||||
// backwards through predecessors if needed.
|
||||
BasicBlock *LoadBB = LI->getParent();
|
||||
BasicBlock *LoadBB = Load->getParent();
|
||||
BasicBlock *TmpBB = LoadBB;
|
||||
|
||||
// Check that there is no implicit control flow instructions above our load in
|
||||
@ -1166,7 +1168,7 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
// access the array.
|
||||
// Check that there is no guard in this block above our instruction.
|
||||
bool MustEnsureSafetyOfSpeculativeExecution =
|
||||
ICF->isDominatedByICFIFromSameBlock(LI);
|
||||
ICF->isDominatedByICFIFromSameBlock(Load);
|
||||
|
||||
while (TmpBB->getSinglePredecessor()) {
|
||||
TmpBB = TmpBB->getSinglePredecessor();
|
||||
@ -1207,7 +1209,7 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
if (Pred->getTerminator()->isEHPad()) {
|
||||
LLVM_DEBUG(
|
||||
dbgs() << "COULD NOT PRE LOAD BECAUSE OF AN EH PAD PREDECESSOR '"
|
||||
<< Pred->getName() << "': " << *LI << '\n');
|
||||
<< Pred->getName() << "': " << *Load << '\n');
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1219,7 +1221,7 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
if (isa<IndirectBrInst>(Pred->getTerminator())) {
|
||||
LLVM_DEBUG(
|
||||
dbgs() << "COULD NOT PRE LOAD BECAUSE OF INDBR CRITICAL EDGE '"
|
||||
<< Pred->getName() << "': " << *LI << '\n');
|
||||
<< Pred->getName() << "': " << *Load << '\n');
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1227,14 +1229,14 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
if (isa<CallBrInst>(Pred->getTerminator())) {
|
||||
LLVM_DEBUG(
|
||||
dbgs() << "COULD NOT PRE LOAD BECAUSE OF CALLBR CRITICAL EDGE '"
|
||||
<< Pred->getName() << "': " << *LI << '\n');
|
||||
<< Pred->getName() << "': " << *Load << '\n');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LoadBB->isEHPad()) {
|
||||
LLVM_DEBUG(
|
||||
dbgs() << "COULD NOT PRE LOAD BECAUSE OF AN EH PAD CRITICAL EDGE '"
|
||||
<< Pred->getName() << "': " << *LI << '\n');
|
||||
<< Pred->getName() << "': " << *Load << '\n');
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1244,7 +1246,7 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
LLVM_DEBUG(
|
||||
dbgs()
|
||||
<< "COULD NOT PRE LOAD BECAUSE OF A BACKEDGE CRITICAL EDGE '"
|
||||
<< Pred->getName() << "': " << *LI << '\n');
|
||||
<< Pred->getName() << "': " << *Load << '\n');
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1262,7 +1264,7 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
|
||||
// If this load is unavailable in multiple predecessors, reject it.
|
||||
// FIXME: If we could restructure the CFG, we could make a common pred with
|
||||
// all the preds that don't have an available LI and insert a new load into
|
||||
// all the preds that don't have an available Load and insert a new load into
|
||||
// that one block.
|
||||
if (NumUnavailablePreds != 1)
|
||||
return false;
|
||||
@ -1271,10 +1273,10 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
// to speculatively execute the load at that points.
|
||||
if (MustEnsureSafetyOfSpeculativeExecution) {
|
||||
if (CriticalEdgePred.size())
|
||||
if (!isSafeToSpeculativelyExecute(LI, LoadBB->getFirstNonPHI(), DT))
|
||||
if (!isSafeToSpeculativelyExecute(Load, LoadBB->getFirstNonPHI(), DT))
|
||||
return false;
|
||||
for (auto &PL : PredLoads)
|
||||
if (!isSafeToSpeculativelyExecute(LI, PL.first->getTerminator(), DT))
|
||||
if (!isSafeToSpeculativelyExecute(Load, PL.first->getTerminator(), DT))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1289,21 +1291,21 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
|
||||
// Check if the load can safely be moved to all the unavailable predecessors.
|
||||
bool CanDoPRE = true;
|
||||
const DataLayout &DL = LI->getModule()->getDataLayout();
|
||||
const DataLayout &DL = Load->getModule()->getDataLayout();
|
||||
SmallVector<Instruction*, 8> NewInsts;
|
||||
for (auto &PredLoad : PredLoads) {
|
||||
BasicBlock *UnavailablePred = PredLoad.first;
|
||||
|
||||
// Do PHI translation to get its value in the predecessor if necessary. The
|
||||
// returned pointer (if non-null) is guaranteed to dominate UnavailablePred.
|
||||
// We do the translation for each edge we skipped by going from LI's block
|
||||
// We do the translation for each edge we skipped by going from Load's block
|
||||
// to LoadBB, otherwise we might miss pieces needing translation.
|
||||
|
||||
// If all preds have a single successor, then we know it is safe to insert
|
||||
// the load on the pred (?!?), so we can insert code to materialize the
|
||||
// pointer if it is not available.
|
||||
Value *LoadPtr = LI->getPointerOperand();
|
||||
BasicBlock *Cur = LI->getParent();
|
||||
Value *LoadPtr = Load->getPointerOperand();
|
||||
BasicBlock *Cur = Load->getParent();
|
||||
while (Cur != LoadBB) {
|
||||
PHITransAddr Address(LoadPtr, DL, AC);
|
||||
LoadPtr = Address.PHITranslateWithInsertion(
|
||||
@ -1324,7 +1326,7 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
// we fail PRE.
|
||||
if (!LoadPtr) {
|
||||
LLVM_DEBUG(dbgs() << "COULDN'T INSERT PHI TRANSLATED VALUE OF: "
|
||||
<< *LI->getPointerOperand() << "\n");
|
||||
<< *Load->getPointerOperand() << "\n");
|
||||
CanDoPRE = false;
|
||||
break;
|
||||
}
|
||||
@ -1349,7 +1351,7 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
// Okay, we can eliminate this load by inserting a reload in the predecessor
|
||||
// and using PHI construction to get the value in the other predecessors, do
|
||||
// it.
|
||||
LLVM_DEBUG(dbgs() << "GVN REMOVING PRE LOAD: " << *LI << '\n');
|
||||
LLVM_DEBUG(dbgs() << "GVN REMOVING PRE LOAD: " << *Load << '\n');
|
||||
LLVM_DEBUG(if (!NewInsts.empty()) dbgs()
|
||||
<< "INSERTED " << NewInsts.size() << " INSTS: " << *NewInsts.back()
|
||||
<< '\n');
|
||||
@ -1372,19 +1374,19 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
BasicBlock *UnavailablePred = PredLoad.first;
|
||||
Value *LoadPtr = PredLoad.second;
|
||||
|
||||
auto *NewLoad = new LoadInst(
|
||||
LI->getType(), LoadPtr, LI->getName() + ".pre", LI->isVolatile(),
|
||||
LI->getAlign(), LI->getOrdering(), LI->getSyncScopeID(),
|
||||
UnavailablePred->getTerminator());
|
||||
NewLoad->setDebugLoc(LI->getDebugLoc());
|
||||
auto *NewLoad =
|
||||
new LoadInst(Load->getType(), LoadPtr, Load->getName() + ".pre",
|
||||
Load->isVolatile(), Load->getAlign(), Load->getOrdering(),
|
||||
Load->getSyncScopeID(), UnavailablePred->getTerminator());
|
||||
NewLoad->setDebugLoc(Load->getDebugLoc());
|
||||
if (MSSAU) {
|
||||
auto *MSSA = MSSAU->getMemorySSA();
|
||||
// Get the defining access of the original load or use the load if it is a
|
||||
// MemoryDef (e.g. because it is volatile). The inserted loads are
|
||||
// guaranteed to load from the same definition.
|
||||
auto *LIAcc = MSSA->getMemoryAccess(LI);
|
||||
auto *LoadAcc = MSSA->getMemoryAccess(Load);
|
||||
auto *DefiningAcc =
|
||||
isa<MemoryDef>(LIAcc) ? LIAcc : LIAcc->getDefiningAccess();
|
||||
isa<MemoryDef>(LoadAcc) ? LoadAcc : LoadAcc->getDefiningAccess();
|
||||
auto *NewAccess = MSSAU->createMemoryAccessInBB(
|
||||
NewLoad, DefiningAcc, NewLoad->getParent(),
|
||||
MemorySSA::BeforeTerminator);
|
||||
@ -1396,19 +1398,19 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
|
||||
// Transfer the old load's AA tags to the new load.
|
||||
AAMDNodes Tags;
|
||||
LI->getAAMetadata(Tags);
|
||||
Load->getAAMetadata(Tags);
|
||||
if (Tags)
|
||||
NewLoad->setAAMetadata(Tags);
|
||||
|
||||
if (auto *MD = LI->getMetadata(LLVMContext::MD_invariant_load))
|
||||
if (auto *MD = Load->getMetadata(LLVMContext::MD_invariant_load))
|
||||
NewLoad->setMetadata(LLVMContext::MD_invariant_load, MD);
|
||||
if (auto *InvGroupMD = LI->getMetadata(LLVMContext::MD_invariant_group))
|
||||
if (auto *InvGroupMD = Load->getMetadata(LLVMContext::MD_invariant_group))
|
||||
NewLoad->setMetadata(LLVMContext::MD_invariant_group, InvGroupMD);
|
||||
if (auto *RangeMD = LI->getMetadata(LLVMContext::MD_range))
|
||||
if (auto *RangeMD = Load->getMetadata(LLVMContext::MD_range))
|
||||
NewLoad->setMetadata(LLVMContext::MD_range, RangeMD);
|
||||
if (auto *AccessMD = LI->getMetadata(LLVMContext::MD_access_group))
|
||||
if (this->LI && this->LI->getLoopFor(LI->getParent()) ==
|
||||
this->LI->getLoopFor(UnavailablePred))
|
||||
if (auto *AccessMD = Load->getMetadata(LLVMContext::MD_access_group))
|
||||
if (LI &&
|
||||
LI->getLoopFor(Load->getParent()) == LI->getLoopFor(UnavailablePred))
|
||||
NewLoad->setMetadata(LLVMContext::MD_access_group, AccessMD);
|
||||
|
||||
// We do not propagate the old load's debug location, because the new
|
||||
@ -1425,30 +1427,30 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
||||
}
|
||||
|
||||
// Perform PHI construction.
|
||||
Value *V = ConstructSSAForLoadSet(LI, ValuesPerBlock, *this);
|
||||
LI->replaceAllUsesWith(V);
|
||||
Value *V = ConstructSSAForLoadSet(Load, ValuesPerBlock, *this);
|
||||
Load->replaceAllUsesWith(V);
|
||||
if (isa<PHINode>(V))
|
||||
V->takeName(LI);
|
||||
V->takeName(Load);
|
||||
if (Instruction *I = dyn_cast<Instruction>(V))
|
||||
I->setDebugLoc(LI->getDebugLoc());
|
||||
I->setDebugLoc(Load->getDebugLoc());
|
||||
if (V->getType()->isPtrOrPtrVectorTy())
|
||||
MD->invalidateCachedPointerInfo(V);
|
||||
markInstructionForDeletion(LI);
|
||||
markInstructionForDeletion(Load);
|
||||
ORE->emit([&]() {
|
||||
return OptimizationRemark(DEBUG_TYPE, "LoadPRE", LI)
|
||||
return OptimizationRemark(DEBUG_TYPE, "LoadPRE", Load)
|
||||
<< "load eliminated by PRE";
|
||||
});
|
||||
++NumPRELoad;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void reportLoadElim(LoadInst *LI, Value *AvailableValue,
|
||||
static void reportLoadElim(LoadInst *Load, Value *AvailableValue,
|
||||
OptimizationRemarkEmitter *ORE) {
|
||||
using namespace ore;
|
||||
|
||||
ORE->emit([&]() {
|
||||
return OptimizationRemark(DEBUG_TYPE, "LoadElim", LI)
|
||||
<< "load of type " << NV("Type", LI->getType()) << " eliminated"
|
||||
return OptimizationRemark(DEBUG_TYPE, "LoadElim", Load)
|
||||
<< "load of type " << NV("Type", Load->getType()) << " eliminated"
|
||||
<< setExtraArgs() << " in favor of "
|
||||
<< NV("InfavorOfValue", AvailableValue);
|
||||
});
|
||||
@ -1456,17 +1458,17 @@ static void reportLoadElim(LoadInst *LI, Value *AvailableValue,
|
||||
|
||||
/// Attempt to eliminate a load whose dependencies are
|
||||
/// non-local by performing PHI construction.
|
||||
bool GVN::processNonLocalLoad(LoadInst *LI) {
|
||||
bool GVN::processNonLocalLoad(LoadInst *Load) {
|
||||
// non-local speculations are not allowed under asan.
|
||||
if (LI->getParent()->getParent()->hasFnAttribute(
|
||||
if (Load->getParent()->getParent()->hasFnAttribute(
|
||||
Attribute::SanitizeAddress) ||
|
||||
LI->getParent()->getParent()->hasFnAttribute(
|
||||
Load->getParent()->getParent()->hasFnAttribute(
|
||||
Attribute::SanitizeHWAddress))
|
||||
return false;
|
||||
|
||||
// Step 1: Find the non-local dependencies of the load.
|
||||
LoadDepVect Deps;
|
||||
MD->getNonLocalPointerDependency(LI, Deps);
|
||||
MD->getNonLocalPointerDependency(Load, Deps);
|
||||
|
||||
// If we had to process more than one hundred blocks to find the
|
||||
// dependencies, this load isn't worth worrying about. Optimizing
|
||||
@ -1479,14 +1481,15 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
|
||||
// clobber in the current block. Reject this early.
|
||||
if (NumDeps == 1 &&
|
||||
!Deps[0].getResult().isDef() && !Deps[0].getResult().isClobber()) {
|
||||
LLVM_DEBUG(dbgs() << "GVN: non-local load "; LI->printAsOperand(dbgs());
|
||||
LLVM_DEBUG(dbgs() << "GVN: non-local load "; Load->printAsOperand(dbgs());
|
||||
dbgs() << " has unknown dependencies\n";);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Changed = false;
|
||||
// If this load follows a GEP, see if we can PRE the indices before analyzing.
|
||||
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(LI->getOperand(0))) {
|
||||
if (GetElementPtrInst *GEP =
|
||||
dyn_cast<GetElementPtrInst>(Load->getOperand(0))) {
|
||||
for (GetElementPtrInst::op_iterator OI = GEP->idx_begin(),
|
||||
OE = GEP->idx_end();
|
||||
OI != OE; ++OI)
|
||||
@ -1497,7 +1500,7 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
|
||||
// Step 2: Analyze the availability of the load
|
||||
AvailValInBlkVect ValuesPerBlock;
|
||||
UnavailBlkVect UnavailableBlocks;
|
||||
AnalyzeLoadAvailability(LI, Deps, ValuesPerBlock, UnavailableBlocks);
|
||||
AnalyzeLoadAvailability(Load, Deps, ValuesPerBlock, UnavailableBlocks);
|
||||
|
||||
// If we have no predecessors that produce a known value for this load, exit
|
||||
// early.
|
||||
@ -1510,36 +1513,35 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
|
||||
// load, then it is fully redundant and we can use PHI insertion to compute
|
||||
// its value. Insert PHIs and remove the fully redundant value now.
|
||||
if (UnavailableBlocks.empty()) {
|
||||
LLVM_DEBUG(dbgs() << "GVN REMOVING NONLOCAL LOAD: " << *LI << '\n');
|
||||
LLVM_DEBUG(dbgs() << "GVN REMOVING NONLOCAL LOAD: " << *Load << '\n');
|
||||
|
||||
// Perform PHI construction.
|
||||
Value *V = ConstructSSAForLoadSet(LI, ValuesPerBlock, *this);
|
||||
LI->replaceAllUsesWith(V);
|
||||
Value *V = ConstructSSAForLoadSet(Load, ValuesPerBlock, *this);
|
||||
Load->replaceAllUsesWith(V);
|
||||
|
||||
if (isa<PHINode>(V))
|
||||
V->takeName(LI);
|
||||
V->takeName(Load);
|
||||
if (Instruction *I = dyn_cast<Instruction>(V))
|
||||
// If instruction I has debug info, then we should not update it.
|
||||
// Also, if I has a null DebugLoc, then it is still potentially incorrect
|
||||
// to propagate LI's DebugLoc because LI may not post-dominate I.
|
||||
if (LI->getDebugLoc() && LI->getParent() == I->getParent())
|
||||
I->setDebugLoc(LI->getDebugLoc());
|
||||
// to propagate Load's DebugLoc because Load may not post-dominate I.
|
||||
if (Load->getDebugLoc() && Load->getParent() == I->getParent())
|
||||
I->setDebugLoc(Load->getDebugLoc());
|
||||
if (V->getType()->isPtrOrPtrVectorTy())
|
||||
MD->invalidateCachedPointerInfo(V);
|
||||
markInstructionForDeletion(LI);
|
||||
markInstructionForDeletion(Load);
|
||||
++NumGVNLoad;
|
||||
reportLoadElim(LI, V, ORE);
|
||||
reportLoadElim(Load, V, ORE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step 4: Eliminate partial redundancy.
|
||||
if (!isPREEnabled() || !isLoadPREEnabled())
|
||||
return Changed;
|
||||
if (!isLoadInLoopPREEnabled() && this->LI &&
|
||||
this->LI->getLoopFor(LI->getParent()))
|
||||
if (!isLoadInLoopPREEnabled() && LI && LI->getLoopFor(Load->getParent()))
|
||||
return Changed;
|
||||
|
||||
return Changed || PerformLoadPRE(LI, ValuesPerBlock, UnavailableBlocks);
|
||||
return Changed || PerformLoadPRE(Load, ValuesPerBlock, UnavailableBlocks);
|
||||
}
|
||||
|
||||
static bool impliesEquivalanceIfTrue(CmpInst* Cmp) {
|
||||
@ -2190,12 +2192,12 @@ bool GVN::processInstruction(Instruction *I) {
|
||||
if (IntrinsicI->getIntrinsicID() == Intrinsic::assume)
|
||||
return processAssumeIntrinsic(IntrinsicI);
|
||||
|
||||
if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
|
||||
if (processLoad(LI))
|
||||
if (LoadInst *Load = dyn_cast<LoadInst>(I)) {
|
||||
if (processLoad(Load))
|
||||
return true;
|
||||
|
||||
unsigned Num = VN.lookupOrAdd(LI);
|
||||
addToLeaderTable(Num, LI, LI->getParent());
|
||||
unsigned Num = VN.lookupOrAdd(Load);
|
||||
addToLeaderTable(Num, Load, Load->getParent());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2299,7 +2301,7 @@ bool GVN::processInstruction(Instruction *I) {
|
||||
/// runOnFunction - This is the main transformation entry point for a function.
|
||||
bool GVN::runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
|
||||
const TargetLibraryInfo &RunTLI, AAResults &RunAA,
|
||||
MemoryDependenceResults *RunMD, LoopInfo *LI,
|
||||
MemoryDependenceResults *RunMD, LoopInfo *Load,
|
||||
OptimizationRemarkEmitter *RunORE, MemorySSA *MSSA) {
|
||||
AC = &RunAC;
|
||||
DT = &RunDT;
|
||||
@ -2309,7 +2311,7 @@ bool GVN::runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
|
||||
MD = RunMD;
|
||||
ImplicitControlFlowTracking ImplicitCFT;
|
||||
ICF = &ImplicitCFT;
|
||||
this->LI = LI;
|
||||
this->LI = Load;
|
||||
VN.setMemDep(MD);
|
||||
ORE = RunORE;
|
||||
InvalidBlockRPONumbers = true;
|
||||
@ -2325,7 +2327,7 @@ bool GVN::runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
|
||||
for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ) {
|
||||
BasicBlock *BB = &*FI++;
|
||||
|
||||
bool removedBlock = MergeBlockIntoPredecessor(BB, &DTU, LI, MSSAU, MD);
|
||||
bool removedBlock = MergeBlockIntoPredecessor(BB, &DTU, Load, MSSAU, MD);
|
||||
if (removedBlock)
|
||||
++NumGVNBlocks;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user