Skip to content

Commit f0b5527

Browse files
authored
[DebugInfo][RemoveDIs] Instrument loop-rotate for DPValues (#72997)
Loop-rotate manually maintains dbg.value intrinsics -- it also needs to manually maintain the replacement for dbg.value intrinsics, DPValue objects. For the most part this patch adds parallel implementations using the new type Some extra juggling is needed when loop-rotate hoists loop-invariant instructions out of the loop: the DPValues attached to such an instruction need to get rotated but not hoisted. Exercised by the new test function invariant_hoist in dbgvalue.ll. There's also a "don't insert duplicate debug intrinsics" facility in LoopRotate. The value and correctness of this isn't clear, but to continue preserving behaviour that's now tested in the "tak_dup" function in dbgvalue.ll. Other things in this patch include a helper DebugVariable constructor for DPValues, a insertDebugValuesForPHIs handler for RemoveDIs (exercised by the new tests), and beefing up the dbg.value checking in dbgvalue.ll to ensure that each record is tested (and that there's an implicit check-not).
1 parent 1a08887 commit f0b5527

File tree

5 files changed

+329
-8
lines changed

5 files changed

+329
-8
lines changed

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ enum Tag : uint16_t;
6565
}
6666

6767
class DbgVariableIntrinsic;
68+
class DPValue;
6869

6970
extern cl::opt<bool> EnableFSDiscriminator;
7071

@@ -3814,6 +3815,7 @@ class DebugVariable {
38143815

38153816
public:
38163817
DebugVariable(const DbgVariableIntrinsic *DII);
3818+
DebugVariable(const DPValue *DPV);
38173819

38183820
DebugVariable(const DILocalVariable *Var,
38193821
std::optional<FragmentInfo> FragmentInfo,

llvm/lib/IR/DebugInfoMetadata.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "llvm/ADT/SmallPtrSet.h"
1717
#include "llvm/ADT/StringSwitch.h"
1818
#include "llvm/BinaryFormat/Dwarf.h"
19+
#include "llvm/IR/DebugProgramInstruction.h"
1920
#include "llvm/IR/Function.h"
2021
#include "llvm/IR/IntrinsicInst.h"
2122
#include "llvm/IR/Type.h"
@@ -41,6 +42,11 @@ DebugVariable::DebugVariable(const DbgVariableIntrinsic *DII)
4142
Fragment(DII->getExpression()->getFragmentInfo()),
4243
InlinedAt(DII->getDebugLoc().getInlinedAt()) {}
4344

45+
DebugVariable::DebugVariable(const DPValue *DPV)
46+
: Variable(DPV->getVariable()),
47+
Fragment(DPV->getExpression()->getFragmentInfo()),
48+
InlinedAt(DPV->getDebugLoc().getInlinedAt()) {}
49+
4450
DebugVariableAggregate::DebugVariableAggregate(const DbgVariableIntrinsic *DVI)
4551
: DebugVariable(DVI->getVariable(), std::nullopt,
4652
DVI->getDebugLoc()->getInlinedAt()) {}

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,13 +1972,78 @@ bool llvm::LowerDbgDeclare(Function &F) {
19721972
return Changed;
19731973
}
19741974

1975+
// RemoveDIs: re-implementation of insertDebugValuesForPHIs, but which pulls the
1976+
// debug-info out of the block's DPValues rather than dbg.value intrinsics.
1977+
static void insertDPValuesForPHIs(BasicBlock *BB,
1978+
SmallVectorImpl<PHINode *> &InsertedPHIs) {
1979+
assert(BB && "No BasicBlock to clone DPValue(s) from.");
1980+
if (InsertedPHIs.size() == 0)
1981+
return;
1982+
1983+
// Map existing PHI nodes to their DPValues.
1984+
DenseMap<Value *, DPValue *> DbgValueMap;
1985+
for (auto &I : *BB) {
1986+
for (auto &DPV : I.getDbgValueRange()) {
1987+
for (Value *V : DPV.location_ops())
1988+
if (auto *Loc = dyn_cast_or_null<PHINode>(V))
1989+
DbgValueMap.insert({Loc, &DPV});
1990+
}
1991+
}
1992+
if (DbgValueMap.size() == 0)
1993+
return;
1994+
1995+
// Map a pair of the destination BB and old DPValue to the new DPValue,
1996+
// so that if a DPValue is being rewritten to use more than one of the
1997+
// inserted PHIs in the same destination BB, we can update the same DPValue
1998+
// with all the new PHIs instead of creating one copy for each.
1999+
MapVector<std::pair<BasicBlock *, DPValue *>, DPValue *> NewDbgValueMap;
2000+
// Then iterate through the new PHIs and look to see if they use one of the
2001+
// previously mapped PHIs. If so, create a new DPValue that will propagate
2002+
// the info through the new PHI. If we use more than one new PHI in a single
2003+
// destination BB with the same old dbg.value, merge the updates so that we
2004+
// get a single new DPValue with all the new PHIs.
2005+
for (auto PHI : InsertedPHIs) {
2006+
BasicBlock *Parent = PHI->getParent();
2007+
// Avoid inserting a debug-info record into an EH block.
2008+
if (Parent->getFirstNonPHI()->isEHPad())
2009+
continue;
2010+
for (auto VI : PHI->operand_values()) {
2011+
auto V = DbgValueMap.find(VI);
2012+
if (V != DbgValueMap.end()) {
2013+
DPValue *DbgII = cast<DPValue>(V->second);
2014+
auto NewDI = NewDbgValueMap.find({Parent, DbgII});
2015+
if (NewDI == NewDbgValueMap.end()) {
2016+
DPValue *NewDbgII = DbgII->clone();
2017+
NewDI = NewDbgValueMap.insert({{Parent, DbgII}, NewDbgII}).first;
2018+
}
2019+
DPValue *NewDbgII = NewDI->second;
2020+
// If PHI contains VI as an operand more than once, we may
2021+
// replaced it in NewDbgII; confirm that it is present.
2022+
if (is_contained(NewDbgII->location_ops(), VI))
2023+
NewDbgII->replaceVariableLocationOp(VI, PHI);
2024+
}
2025+
}
2026+
}
2027+
// Insert the new DPValues into their destination blocks.
2028+
for (auto DI : NewDbgValueMap) {
2029+
BasicBlock *Parent = DI.first.first;
2030+
DPValue *NewDbgII = DI.second;
2031+
auto InsertionPt = Parent->getFirstInsertionPt();
2032+
assert(InsertionPt != Parent->end() && "Ill-formed basic block");
2033+
2034+
InsertionPt->DbgMarker->insertDPValue(NewDbgII, true);
2035+
}
2036+
}
2037+
19752038
/// Propagate dbg.value intrinsics through the newly inserted PHIs.
19762039
void llvm::insertDebugValuesForPHIs(BasicBlock *BB,
19772040
SmallVectorImpl<PHINode *> &InsertedPHIs) {
19782041
assert(BB && "No BasicBlock to clone dbg.value(s) from.");
19792042
if (InsertedPHIs.size() == 0)
19802043
return;
19812044

2045+
insertDPValuesForPHIs(BB, InsertedPHIs);
2046+
19822047
// Map existing PHI nodes to their dbg.values.
19832048
ValueToValueMapTy DbgValueMap;
19842049
for (auto &I : *BB) {

llvm/lib/Transforms/Utils/LoopRotationUtils.cpp

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ static void RewriteUsesOfClonedInstructions(BasicBlock *OrigHeader,
159159
// Replace MetadataAsValue(ValueAsMetadata(OrigHeaderVal)) uses in debug
160160
// intrinsics.
161161
SmallVector<DbgValueInst *, 1> DbgValues;
162-
llvm::findDbgValues(DbgValues, OrigHeaderVal);
162+
SmallVector<DPValue *, 1> DPValues;
163+
llvm::findDbgValues(DbgValues, OrigHeaderVal, &DPValues);
163164
for (auto &DbgValue : DbgValues) {
164165
// The original users in the OrigHeader are already using the original
165166
// definitions.
@@ -180,6 +181,29 @@ static void RewriteUsesOfClonedInstructions(BasicBlock *OrigHeader,
180181
NewVal = UndefValue::get(OrigHeaderVal->getType());
181182
DbgValue->replaceVariableLocationOp(OrigHeaderVal, NewVal);
182183
}
184+
185+
// RemoveDIs: duplicate implementation for non-instruction debug-info
186+
// storage in DPValues.
187+
for (DPValue *DPV : DPValues) {
188+
// The original users in the OrigHeader are already using the original
189+
// definitions.
190+
BasicBlock *UserBB = DPV->getMarker()->getParent();
191+
if (UserBB == OrigHeader)
192+
continue;
193+
194+
// Users in the OrigPreHeader need to use the value to which the
195+
// original definitions are mapped and anything else can be handled by
196+
// the SSAUpdater. To avoid adding PHINodes, check if the value is
197+
// available in UserBB, if not substitute undef.
198+
Value *NewVal;
199+
if (UserBB == OrigPreheader)
200+
NewVal = OrigPreHeaderVal;
201+
else if (SSA.HasValueForBlock(UserBB))
202+
NewVal = SSA.GetValueInMiddleOfBlock(UserBB);
203+
else
204+
NewVal = UndefValue::get(OrigHeaderVal->getType());
205+
DPV->replaceVariableLocationOp(OrigHeaderVal, NewVal);
206+
}
183207
}
184208
}
185209

@@ -531,6 +555,18 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
531555
break;
532556
}
533557

558+
// Duplicate implementation for DPValues, the non-instruction format of
559+
// debug-info records in RemoveDIs.
560+
auto makeHashDPV = [](const DPValue &D) -> DbgIntrinsicHash {
561+
auto VarLocOps = D.location_ops();
562+
return {{hash_combine_range(VarLocOps.begin(), VarLocOps.end()),
563+
D.getVariable()},
564+
D.getExpression()};
565+
};
566+
for (Instruction &I : llvm::drop_begin(llvm::reverse(*OrigPreheader)))
567+
for (const DPValue &DPV : I.getDbgValueRange())
568+
DbgIntrinsics.insert(makeHashDPV(DPV));
569+
534570
// Remember the local noalias scope declarations in the header. After the
535571
// rotation, they must be duplicated and the scope must be cloned. This
536572
// avoids unwanted interaction across iterations.
@@ -539,6 +575,29 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
539575
if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I))
540576
NoAliasDeclInstructions.push_back(Decl);
541577

578+
Module *M = OrigHeader->getModule();
579+
580+
// Track the next DPValue to clone. If we have a sequence where an
581+
// instruction is hoisted instead of being cloned:
582+
// DPValue blah
583+
// %foo = add i32 0, 0
584+
// DPValue xyzzy
585+
// %bar = call i32 @foobar()
586+
// where %foo is hoisted, then the DPValue "blah" will be seen twice, once
587+
// attached to %foo, then when %foo his hoisted it will "fall down" onto the
588+
// function call:
589+
// DPValue blah
590+
// DPValue xyzzy
591+
// %bar = call i32 @foobar()
592+
// causing it to appear attached to the call too.
593+
//
594+
// To avoid this, cloneDebugInfoFrom takes an optional "start cloning from
595+
// here" position to account for this behaviour. We point it at any DPValues
596+
// on the next instruction, here labelled xyzzy, before we hoist %foo.
597+
// Later, we only only clone DPValues from that position (xyzzy) onwards,
598+
// which avoids cloning DPValue "blah" multiple times.
599+
std::optional<DPValue::self_iterator> NextDbgInst = std::nullopt;
600+
542601
while (I != E) {
543602
Instruction *Inst = &*I++;
544603

@@ -551,7 +610,17 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
551610
if (L->hasLoopInvariantOperands(Inst) && !Inst->mayReadFromMemory() &&
552611
!Inst->mayWriteToMemory() && !Inst->isTerminator() &&
553612
!isa<DbgInfoIntrinsic>(Inst) && !isa<AllocaInst>(Inst)) {
613+
614+
if (LoopEntryBranch->getParent()->IsNewDbgInfoFormat) {
615+
auto DbgValueRange =
616+
LoopEntryBranch->cloneDebugInfoFrom(Inst, NextDbgInst);
617+
RemapDPValueRange(M, DbgValueRange, ValueMap,
618+
RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
619+
}
620+
621+
NextDbgInst = I->getDbgValueRange().begin();
554622
Inst->moveBefore(LoopEntryBranch);
623+
555624
++NumInstrsHoisted;
556625
continue;
557626
}
@@ -562,6 +631,17 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
562631

563632
++NumInstrsDuplicated;
564633

634+
if (LoopEntryBranch->getParent()->IsNewDbgInfoFormat) {
635+
auto Range = C->cloneDebugInfoFrom(Inst, NextDbgInst);
636+
// Erase anything we've seen before.
637+
for (DPValue &DPV : make_early_inc_range(Range))
638+
if (DbgIntrinsics.count(makeHashDPV(DPV)))
639+
DPV.eraseFromParent();
640+
RemapDPValueRange(M, Range, ValueMap,
641+
RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
642+
NextDbgInst = std::nullopt;
643+
}
644+
565645
// Eagerly remap the operands of the instruction.
566646
RemapInstruction(C, ValueMap,
567647
RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
@@ -676,6 +756,7 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
676756
// OrigPreHeader's old terminator (the original branch into the loop), and
677757
// remove the corresponding incoming values from the PHI nodes in OrigHeader.
678758
LoopEntryBranch->eraseFromParent();
759+
OrigPreheader->flushTerminatorDbgValues();
679760

680761
// Update MemorySSA before the rewrite call below changes the 1:1
681762
// instruction:cloned_instruction_or_value mapping.

0 commit comments

Comments
 (0)