aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/CodeGenPrepare.cpp
diff options
context:
space:
mode:
authorJeremy Morse <jeremy.morse@sony.com>2023-07-03 18:08:48 +0100
committerJeremy Morse <jeremy.morse@sony.com>2023-11-30 15:29:05 +0000
commit3ef98bcd46f22d1d25f9f83f5742209f87d399d0 (patch)
tree9c6e3983d0c9defb872aaca7f5188037fa9f885b /llvm/lib/CodeGen/CodeGenPrepare.cpp
parent73d9f5fda6648a9c75a265524da29bac061fb155 (diff)
downloadllvm-3ef98bcd46f22d1d25f9f83f5742209f87d399d0.zip
llvm-3ef98bcd46f22d1d25f9f83f5742209f87d399d0.tar.gz
llvm-3ef98bcd46f22d1d25f9f83f5742209f87d399d0.tar.bz2
[DebugInfo][RemoveDIs] Support maintaining DPValues in CodeGenPrepare (#73660)
CodeGenPrepare needs to support the maintenence of DPValues, the non-instruction replacement for dbg.value intrinsics. This means there are a few functions we need to duplicate or replicate the functionality of: * fixupDbgValue for setting users of sunk addr GEPs, * The remains of placeDbgValues needs a DPValue implementation for sinking * Rollback of RAUWs needs to update DPValues * Rollback of instruction removal needs supporting (see github #73350) * A few places where we have to use iterators rather than instructions. There are three places where we have to use the setHeadBit call on iterators to indicate which portion of debug-info records we're about to splice around. This is because CodeGenPrepare, unlike other optimisation passes, is very much concerned with which block an operation occurs in and where in the block instructions are because it's preparing things to be in a format that's good for SelectionDAG. There isn't a large amount of test coverage for debuginfo behaviours in this pass, hence I've added some more.
Diffstat (limited to 'llvm/lib/CodeGen/CodeGenPrepare.cpp')
-rw-r--r--llvm/lib/CodeGen/CodeGenPrepare.cpp221
1 files changed, 151 insertions, 70 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 07dc718..885d2d3 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -459,6 +459,7 @@ private:
bool optimizeExtractElementInst(Instruction *Inst);
bool dupRetToEnableTailCallOpts(BasicBlock *BB, ModifyDT &ModifiedDT);
bool fixupDbgValue(Instruction *I);
+ bool fixupDPValue(DPValue &I);
bool placeDbgValues(Function &F);
bool placePseudoProbes(Function &F);
bool canFormExtLd(const SmallVectorImpl<Instruction *> &MovedExts,
@@ -1753,8 +1754,8 @@ static bool sinkCmpExpression(CmpInst *Cmp, const TargetLowering &TLI) {
BasicBlock::iterator InsertPt = UserBB->getFirstInsertionPt();
assert(InsertPt != UserBB->end());
InsertedCmp = CmpInst::Create(Cmp->getOpcode(), Cmp->getPredicate(),
- Cmp->getOperand(0), Cmp->getOperand(1), "",
- &*InsertPt);
+ Cmp->getOperand(0), Cmp->getOperand(1), "");
+ InsertedCmp->insertBefore(*UserBB, InsertPt);
// Propagate the debug info.
InsertedCmp->setDebugLoc(Cmp->getDebugLoc());
}
@@ -2066,10 +2067,13 @@ SinkShiftAndTruncate(BinaryOperator *ShiftI, Instruction *User, ConstantInt *CI,
// Sink the trunc
BasicBlock::iterator TruncInsertPt = TruncUserBB->getFirstInsertionPt();
TruncInsertPt++;
+ // It will go ahead of any debug-info.
+ TruncInsertPt.setHeadBit(true);
assert(TruncInsertPt != TruncUserBB->end());
InsertedTrunc = CastInst::Create(TruncI->getOpcode(), InsertedShift,
- TruncI->getType(), "", &*TruncInsertPt);
+ TruncI->getType(), "");
+ InsertedTrunc->insertBefore(*TruncUserBB, TruncInsertPt);
InsertedTrunc->setDebugLoc(TruncI->getDebugLoc());
MadeChange = true;
@@ -2234,7 +2238,9 @@ static bool despeculateCountZeros(IntrinsicInst *CountZeros,
// Create another block after the count zero intrinsic. A PHI will be added
// in this block to select the result of the intrinsic or the bit-width
// constant if the input to the intrinsic is zero.
- BasicBlock::iterator SplitPt = ++(BasicBlock::iterator(CountZeros));
+ BasicBlock::iterator SplitPt = std::next(BasicBlock::iterator(CountZeros));
+ // Any debug-info after CountZeros should not be included.
+ SplitPt.setHeadBit(true);
BasicBlock *EndBlock = CallBlock->splitBasicBlock(SplitPt, "cond.end");
if (IsHugeFunc)
FreshBBs.insert(EndBlock);
@@ -2829,6 +2835,7 @@ class TypePromotionTransaction {
Instruction *PrevInst;
BasicBlock *BB;
} Point;
+ std::optional<DPValue::self_iterator> BeforeDPValue = std::nullopt;
/// Remember whether or not the instruction had a previous instruction.
bool HasPrevInstruction;
@@ -2836,12 +2843,19 @@ class TypePromotionTransaction {
public:
/// Record the position of \p Inst.
InsertionHandler(Instruction *Inst) {
- BasicBlock::iterator It = Inst->getIterator();
- HasPrevInstruction = (It != (Inst->getParent()->begin()));
- if (HasPrevInstruction)
- Point.PrevInst = &*--It;
- else
- Point.BB = Inst->getParent();
+ HasPrevInstruction = (Inst != &*(Inst->getParent()->begin()));
+ BasicBlock *BB = Inst->getParent();
+
+ // Record where we would have to re-insert the instruction in the sequence
+ // of DPValues, if we ended up reinserting.
+ if (BB->IsNewDbgInfoFormat)
+ BeforeDPValue = Inst->getDbgReinsertionPosition();
+
+ if (HasPrevInstruction) {
+ Point.PrevInst = &*std::prev(Inst->getIterator());
+ } else {
+ Point.BB = BB;
+ }
}
/// Insert \p Inst at the recorded position.
@@ -2849,14 +2863,16 @@ class TypePromotionTransaction {
if (HasPrevInstruction) {
if (Inst->getParent())
Inst->removeFromParent();
- Inst->insertAfter(Point.PrevInst);
+ Inst->insertAfter(&*Point.PrevInst);
} else {
- Instruction *Position = &*Point.BB->getFirstInsertionPt();
+ BasicBlock::iterator Position = Point.BB->getFirstInsertionPt();
if (Inst->getParent())
- Inst->moveBefore(Position);
+ Inst->moveBefore(*Point.BB, Position);
else
- Inst->insertBefore(Position);
+ Inst->insertBefore(*Point.BB, Position);
}
+
+ Inst->getParent()->reinsertInstInDPValues(Inst, BeforeDPValue);
}
};
@@ -3059,6 +3075,8 @@ class TypePromotionTransaction {
SmallVector<InstructionAndIdx, 4> OriginalUses;
/// Keep track of the debug users.
SmallVector<DbgValueInst *, 1> DbgValues;
+ /// And non-instruction debug-users too.
+ SmallVector<DPValue *, 1> DPValues;
/// Keep track of the new value so that we can undo it by replacing
/// instances of the new value with the original value.
@@ -3079,7 +3097,7 @@ class TypePromotionTransaction {
}
// Record the debug uses separately. They are not in the instruction's
// use list, but they are replaced by RAUW.
- findDbgValues(DbgValues, Inst);
+ findDbgValues(DbgValues, Inst, &DPValues);
// Now, we can replace the uses.
Inst->replaceAllUsesWith(New);
@@ -3096,6 +3114,10 @@ class TypePromotionTransaction {
// correctness and utility of debug value instructions.
for (auto *DVI : DbgValues)
DVI->replaceVariableLocationOp(New, Inst);
+ // Similar story with DPValues, the non-instruction representation of
+ // dbg.values.
+ for (DPValue *DPV : DPValues) // tested by transaction-test I'm adding
+ DPV->replaceVariableLocationOp(New, Inst);
}
};
@@ -6749,7 +6771,7 @@ bool CodeGenPrepare::optimizeLoadExt(LoadInst *Load) {
!TLI->isLoadExtLegal(ISD::ZEXTLOAD, LoadResultVT, TruncVT))
return false;
- IRBuilder<> Builder(Load->getNextNode());
+ IRBuilder<> Builder(Load->getNextNonDebugInstruction());
auto *NewAnd = cast<Instruction>(
Builder.CreateAnd(Load, ConstantInt::get(Ctx, DemandBits)));
// Mark this instruction as "inserted by CGP", so that other
@@ -7005,7 +7027,9 @@ bool CodeGenPrepare::optimizeSelectInst(SelectInst *SI) {
// Split the select block, according to how many (if any) values go on each
// side.
BasicBlock *StartBlock = SI->getParent();
- BasicBlock::iterator SplitPt = ++(BasicBlock::iterator(LastSI));
+ BasicBlock::iterator SplitPt = std::next(BasicBlock::iterator(LastSI));
+ // We should split before any debug-info.
+ SplitPt.setHeadBit(true);
IRBuilder<> IB(SI);
auto *CondFr = IB.CreateFreeze(SI->getCondition(), SI->getName() + ".frozen");
@@ -7017,18 +7041,18 @@ bool CodeGenPrepare::optimizeSelectInst(SelectInst *SI) {
BranchInst *FalseBranch = nullptr;
if (TrueInstrs.size() == 0) {
FalseBranch = cast<BranchInst>(SplitBlockAndInsertIfElse(
- CondFr, &*SplitPt, false, nullptr, nullptr, LI));
+ CondFr, SplitPt, false, nullptr, nullptr, LI));
FalseBlock = FalseBranch->getParent();
EndBlock = cast<BasicBlock>(FalseBranch->getOperand(0));
} else if (FalseInstrs.size() == 0) {
TrueBranch = cast<BranchInst>(SplitBlockAndInsertIfThen(
- CondFr, &*SplitPt, false, nullptr, nullptr, LI));
+ CondFr, SplitPt, false, nullptr, nullptr, LI));
TrueBlock = TrueBranch->getParent();
EndBlock = cast<BasicBlock>(TrueBranch->getOperand(0));
} else {
Instruction *ThenTerm = nullptr;
Instruction *ElseTerm = nullptr;
- SplitBlockAndInsertIfThenElse(CondFr, &*SplitPt, &ThenTerm, &ElseTerm,
+ SplitBlockAndInsertIfThenElse(CondFr, SplitPt, &ThenTerm, &ElseTerm,
nullptr, nullptr, LI);
TrueBranch = cast<BranchInst>(ThenTerm);
FalseBranch = cast<BranchInst>(ElseTerm);
@@ -8095,10 +8119,14 @@ static bool optimizeBranch(BranchInst *Branch, const TargetLowering &TLI,
}
bool CodeGenPrepare::optimizeInst(Instruction *I, ModifyDT &ModifiedDT) {
+ bool AnyChange = false;
+ for (DPValue &DPV : I->getDbgValueRange())
+ AnyChange |= fixupDPValue(DPV);
+
// Bail out if we inserted the instruction to prevent optimizations from
// stepping on each other's toes.
if (InsertedInsts.count(I))
- return false;
+ return AnyChange;
// TODO: Move into the switch on opcode below here.
if (PHINode *P = dyn_cast<PHINode>(I)) {
@@ -8112,7 +8140,7 @@ bool CodeGenPrepare::optimizeInst(Instruction *I, ModifyDT &ModifiedDT) {
++NumPHIsElim;
return true;
}
- return false;
+ return AnyChange;
}
if (CastInst *CI = dyn_cast<CastInst>(I)) {
@@ -8123,7 +8151,7 @@ bool CodeGenPrepare::optimizeInst(Instruction *I, ModifyDT &ModifiedDT) {
// the address of globals out of a loop). If this is the case, we don't
// want to forward-subst the cast.
if (isa<Constant>(CI->getOperand(0)))
- return false;
+ return AnyChange;
if (OptimizeNoopCopyExpression(CI, *TLI, *DL))
return true;
@@ -8149,7 +8177,7 @@ bool CodeGenPrepare::optimizeInst(Instruction *I, ModifyDT &ModifiedDT) {
return MadeChange | optimizeExtUses(I);
}
}
- return false;
+ return AnyChange;
}
if (auto *Cmp = dyn_cast<CmpInst>(I))
@@ -8244,7 +8272,7 @@ bool CodeGenPrepare::optimizeInst(Instruction *I, ModifyDT &ModifiedDT) {
return true;
}
}
- return false;
+ return AnyChange;
}
if (tryToSinkFreeOperands(I))
@@ -8269,7 +8297,7 @@ bool CodeGenPrepare::optimizeInst(Instruction *I, ModifyDT &ModifiedDT) {
return optimizeBranch(cast<BranchInst>(I), *TLI, FreshBBs, IsHugeFunc);
}
- return false;
+ return AnyChange;
}
/// Given an OR instruction, check to see if this is a bitreverse
@@ -8359,6 +8387,49 @@ bool CodeGenPrepare::fixupDbgValue(Instruction *I) {
return AnyChange;
}
+// FIXME: should updating debug-info really cause the "changed" flag to fire,
+// which can cause a function to be reprocessed?
+bool CodeGenPrepare::fixupDPValue(DPValue &DPV) {
+ if (DPV.Type != DPValue::LocationType::Value)
+ return false;
+
+ // Does this DPValue refer to a sunk address calculation?
+ bool AnyChange = false;
+ SmallDenseSet<Value *> LocationOps(DPV.location_ops().begin(),
+ DPV.location_ops().end());
+ for (Value *Location : LocationOps) {
+ WeakTrackingVH SunkAddrVH = SunkAddrs[Location];
+ Value *SunkAddr = SunkAddrVH.pointsToAliveValue() ? SunkAddrVH : nullptr;
+ if (SunkAddr) {
+ // Point dbg.value at locally computed address, which should give the best
+ // opportunity to be accurately lowered. This update may change the type
+ // of pointer being referred to; however this makes no difference to
+ // debugging information, and we can't generate bitcasts that may affect
+ // codegen.
+ DPV.replaceVariableLocationOp(Location, SunkAddr);
+ AnyChange = true;
+ }
+ }
+ return AnyChange;
+}
+
+static void DbgInserterHelper(DbgValueInst *DVI, Instruction *VI) {
+ DVI->removeFromParent();
+ if (isa<PHINode>(VI))
+ DVI->insertBefore(&*VI->getParent()->getFirstInsertionPt());
+ else
+ DVI->insertAfter(VI);
+}
+
+static void DbgInserterHelper(DPValue *DPV, Instruction *VI) {
+ DPV->removeFromParent();
+ BasicBlock *VIBB = VI->getParent();
+ if (isa<PHINode>(VI))
+ VIBB->insertDPValueBefore(DPV, VIBB->getFirstInsertionPt());
+ else
+ VIBB->insertDPValueAfter(DPV, VI);
+}
+
// A llvm.dbg.value may be using a value before its definition, due to
// optimizations in this pass and others. Scan for such dbg.values, and rescue
// them by moving the dbg.value to immediately after the value definition.
@@ -8368,59 +8439,69 @@ bool CodeGenPrepare::placeDbgValues(Function &F) {
bool MadeChange = false;
DominatorTree DT(F);
- for (BasicBlock &BB : F) {
- for (Instruction &Insn : llvm::make_early_inc_range(BB)) {
- DbgValueInst *DVI = dyn_cast<DbgValueInst>(&Insn);
- if (!DVI)
+ auto DbgProcessor = [&](auto *DbgItem, Instruction *Position) {
+ SmallVector<Instruction *, 4> VIs;
+ for (Value *V : DbgItem->location_ops())
+ if (Instruction *VI = dyn_cast_or_null<Instruction>(V))
+ VIs.push_back(VI);
+
+ // This item may depend on multiple instructions, complicating any
+ // potential sink. This block takes the defensive approach, opting to
+ // "undef" the item if it has more than one instruction and any of them do
+ // not dominate iem.
+ for (Instruction *VI : VIs) {
+ if (VI->isTerminator())
continue;
- SmallVector<Instruction *, 4> VIs;
- for (Value *V : DVI->getValues())
- if (Instruction *VI = dyn_cast_or_null<Instruction>(V))
- VIs.push_back(VI);
-
- // This DVI may depend on multiple instructions, complicating any
- // potential sink. This block takes the defensive approach, opting to
- // "undef" the DVI if it has more than one instruction and any of them do
- // not dominate DVI.
- for (Instruction *VI : VIs) {
- if (VI->isTerminator())
- continue;
+ // If VI is a phi in a block with an EHPad terminator, we can't insert
+ // after it.
+ if (isa<PHINode>(VI) && VI->getParent()->getTerminator()->isEHPad())
+ continue;
- // If VI is a phi in a block with an EHPad terminator, we can't insert
- // after it.
- if (isa<PHINode>(VI) && VI->getParent()->getTerminator()->isEHPad())
- continue;
+ // If the defining instruction dominates the dbg.value, we do not need
+ // to move the dbg.value.
+ if (DT.dominates(VI, Position))
+ continue;
- // If the defining instruction dominates the dbg.value, we do not need
- // to move the dbg.value.
- if (DT.dominates(VI, DVI))
- continue;
+ // If we depend on multiple instructions and any of them doesn't
+ // dominate this DVI, we probably can't salvage it: moving it to
+ // after any of the instructions could cause us to lose the others.
+ if (VIs.size() > 1) {
+ LLVM_DEBUG(
+ dbgs()
+ << "Unable to find valid location for Debug Value, undefing:\n"
+ << *DbgItem);
+ DbgItem->setKillLocation();
+ break;
+ }
- // If we depend on multiple instructions and any of them doesn't
- // dominate this DVI, we probably can't salvage it: moving it to
- // after any of the instructions could cause us to lose the others.
- if (VIs.size() > 1) {
- LLVM_DEBUG(
- dbgs()
- << "Unable to find valid location for Debug Value, undefing:\n"
- << *DVI);
- DVI->setKillLocation();
- break;
- }
+ LLVM_DEBUG(dbgs() << "Moving Debug Value before :\n"
+ << *DbgItem << ' ' << *VI);
+ DbgInserterHelper(DbgItem, VI);
+ MadeChange = true;
+ ++NumDbgValueMoved;
+ }
+ };
- LLVM_DEBUG(dbgs() << "Moving Debug Value before :\n"
- << *DVI << ' ' << *VI);
- DVI->removeFromParent();
- if (isa<PHINode>(VI))
- DVI->insertBefore(&*VI->getParent()->getFirstInsertionPt());
- else
- DVI->insertAfter(VI);
- MadeChange = true;
- ++NumDbgValueMoved;
+ for (BasicBlock &BB : F) {
+ for (Instruction &Insn : llvm::make_early_inc_range(BB)) {
+ // Process dbg.value intrinsics.
+ DbgValueInst *DVI = dyn_cast<DbgValueInst>(&Insn);
+ if (DVI) {
+ DbgProcessor(DVI, DVI);
+ continue;
+ }
+
+ // If this isn't a dbg.value, process any attached DPValue records
+ // attached to this instruction.
+ for (DPValue &DPV : llvm::make_early_inc_range(Insn.getDbgValueRange())) {
+ if (DPV.Type != DPValue::LocationType::Value)
+ continue;
+ DbgProcessor(&DPV, &Insn);
}
}
}
+
return MadeChange;
}