Skip to content

Commit ddd95b1

Browse files
authored
[RemoveDIs] Handle DPValues in hoistCommonCodeFromSuccessors (#79476)
Hoist DPValues attached to each instruction being considered for hoisting if they are identical in lock-step. This includes the final instructions which are considered but not hoisted, because the corresponding dbg.values would appear before those instruction and thus hoisted if identical. Identical debug records hoisted: llvm/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll Non-identical debug records not hoisted: llvm/test/Transforms/SimplifyCFG/X86/pr39187-g.ll Debug records attached to first not-hoisted instructions are hoisted: llvm/test/Transforms/SimplifyCFG/hoist-dbgvalue-inlined.ll
1 parent 2d69827 commit ddd95b1

File tree

4 files changed

+87
-12
lines changed

4 files changed

+87
-12
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 84 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,6 +1526,62 @@ static bool shouldHoistCommonInstructions(Instruction *I1, Instruction *I2,
15261526
return true;
15271527
}
15281528

1529+
/// Hoists DPValues from \p I1 and \p OtherInstrs that are identical in
1530+
/// lock-step to \p TI. This matches how dbg.* intrinsics are hoisting in
1531+
/// hoistCommonCodeFromSuccessors. e.g. The input:
1532+
/// I1 DPVs: { x, z },
1533+
/// OtherInsts: { I2 DPVs: { x, y, z } }
1534+
/// would result in hoisting only DPValue x.
1535+
static void
1536+
hoistLockstepIdenticalDPValues(Instruction *TI, Instruction *I1,
1537+
SmallVectorImpl<Instruction *> &OtherInsts) {
1538+
if (!I1->hasDbgValues())
1539+
return;
1540+
using CurrentAndEndIt =
1541+
std::pair<DPValue::self_iterator, DPValue::self_iterator>;
1542+
// Vector of {Current, End} iterators.
1543+
SmallVector<CurrentAndEndIt> Itrs;
1544+
Itrs.reserve(OtherInsts.size() + 1);
1545+
// Helper lambdas for lock-step checks:
1546+
// Return true if this Current == End.
1547+
auto atEnd = [](const CurrentAndEndIt &Pair) {
1548+
return Pair.first == Pair.second;
1549+
};
1550+
// Return true if all Current are identical.
1551+
auto allIdentical = [](const SmallVector<CurrentAndEndIt> &Itrs) {
1552+
return all_of(make_first_range(ArrayRef(Itrs).drop_front()),
1553+
[&](DPValue::self_iterator I) {
1554+
return Itrs[0].first->isIdenticalToWhenDefined(*I);
1555+
});
1556+
};
1557+
1558+
// Collect the iterators.
1559+
Itrs.push_back(
1560+
{I1->getDbgValueRange().begin(), I1->getDbgValueRange().end()});
1561+
for (Instruction *Other : OtherInsts) {
1562+
if (!Other->hasDbgValues())
1563+
return;
1564+
Itrs.push_back(
1565+
{Other->getDbgValueRange().begin(), Other->getDbgValueRange().end()});
1566+
}
1567+
1568+
// Iterate in lock-step until any of the DPValue lists are exausted. If
1569+
// the lock-step DPValues are identical, hoist all of them to TI.
1570+
// This replicates the dbg.* intrinsic behaviour in
1571+
// hoistCommonCodeFromSuccessors.
1572+
while (none_of(Itrs, atEnd)) {
1573+
bool HoistDPVs = allIdentical(Itrs);
1574+
for (CurrentAndEndIt &Pair : Itrs) {
1575+
// Increment Current iterator now as we may be about to move the DPValue.
1576+
DPValue &DPV = *Pair.first++;
1577+
if (HoistDPVs) {
1578+
DPV.removeFromParent();
1579+
TI->getParent()->insertDPValueBefore(&DPV, TI->getIterator());
1580+
}
1581+
}
1582+
}
1583+
}
1584+
15291585
/// Hoist any common code in the successor blocks up into the block. This
15301586
/// function guarantees that BB dominates all successors. If EqTermsOnly is
15311587
/// given, only perform hoisting in case both blocks only contain a terminator.
@@ -1598,7 +1654,6 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
15981654
auto OtherSuccIterRange = make_first_range(OtherSuccIterPairRange);
15991655

16001656
Instruction *I1 = &*BB1ItrPair.first;
1601-
auto *BB1 = I1->getParent();
16021657

16031658
// Skip debug info if it is not identical.
16041659
bool AllDbgInstsAreIdentical = all_of(OtherSuccIterRange, [I1](auto &Iter) {
@@ -1624,18 +1679,23 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
16241679
AllInstsAreIdentical = false;
16251680
}
16261681

1682+
SmallVector<Instruction *, 8> OtherInsts;
1683+
for (auto &SuccIter : OtherSuccIterRange)
1684+
OtherInsts.push_back(&*SuccIter);
1685+
16271686
// If we are hoisting the terminator instruction, don't move one (making a
16281687
// broken BB), instead clone it, and remove BI.
16291688
if (HasTerminator) {
16301689
// Even if BB, which contains only one unreachable instruction, is ignored
16311690
// at the beginning of the loop, we can hoist the terminator instruction.
16321691
// If any instructions remain in the block, we cannot hoist terminators.
1633-
if (NumSkipped || !AllInstsAreIdentical)
1692+
if (NumSkipped || !AllInstsAreIdentical) {
1693+
hoistLockstepIdenticalDPValues(TI, I1, OtherInsts);
16341694
return Changed;
1635-
SmallVector<Instruction *, 8> Insts;
1636-
for (auto &SuccIter : OtherSuccIterRange)
1637-
Insts.push_back(&*SuccIter);
1638-
return hoistSuccIdenticalTerminatorToSwitchOrIf(TI, I1, Insts) || Changed;
1695+
}
1696+
1697+
return hoistSuccIdenticalTerminatorToSwitchOrIf(TI, I1, OtherInsts) ||
1698+
Changed;
16391699
}
16401700

16411701
if (AllInstsAreIdentical) {
@@ -1660,18 +1720,25 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
16601720
// The debug location is an integral part of a debug info intrinsic
16611721
// and can't be separated from it or replaced. Instead of attempting
16621722
// to merge locations, simply hoist both copies of the intrinsic.
1663-
I1->moveBeforePreserving(TI);
1723+
hoistLockstepIdenticalDPValues(TI, I1, OtherInsts);
1724+
// We've just hoisted DPValues; move I1 after them (before TI) and
1725+
// leave any that were not hoisted behind (by calling moveBefore
1726+
// rather than moveBeforePreserving).
1727+
I1->moveBefore(TI);
16641728
for (auto &SuccIter : OtherSuccIterRange) {
16651729
auto *I2 = &*SuccIter++;
16661730
assert(isa<DbgInfoIntrinsic>(I2));
1667-
I2->moveBeforePreserving(TI);
1731+
I2->moveBefore(TI);
16681732
}
16691733
} else {
16701734
// For a normal instruction, we just move one to right before the
16711735
// branch, then replace all uses of the other with the first. Finally,
16721736
// we remove the now redundant second instruction.
1673-
I1->moveBeforePreserving(TI);
1674-
BB->splice(TI->getIterator(), BB1, I1->getIterator());
1737+
hoistLockstepIdenticalDPValues(TI, I1, OtherInsts);
1738+
// We've just hoisted DPValues; move I1 after them (before TI) and
1739+
// leave any that were not hoisted behind (by calling moveBefore
1740+
// rather than moveBeforePreserving).
1741+
I1->moveBefore(TI);
16751742
for (auto &SuccIter : OtherSuccIterRange) {
16761743
Instruction *I2 = &*SuccIter++;
16771744
assert(I2 != I1);
@@ -1690,8 +1757,10 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
16901757
Changed = true;
16911758
NumHoistCommonInstrs += SuccIterPairs.size();
16921759
} else {
1693-
if (NumSkipped >= HoistCommonSkipLimit)
1760+
if (NumSkipped >= HoistCommonSkipLimit) {
1761+
hoistLockstepIdenticalDPValues(TI, I1, OtherInsts);
16941762
return Changed;
1763+
}
16951764
// We are about to skip over a pair of non-identical instructions. Record
16961765
// if any have characteristics that would prevent reordering instructions
16971766
// across them.
@@ -1752,7 +1821,10 @@ bool SimplifyCFGOpt::hoistSuccIdenticalTerminatorToSwitchOrIf(
17521821
}
17531822
}
17541823

1755-
// Okay, it is safe to hoist the terminator.
1824+
// Hoist DPValues attached to the terminator to match dbg.* intrinsic hoisting
1825+
// behaviour in hoistCommonCodeFromSuccessors.
1826+
hoistLockstepIdenticalDPValues(TI, I1, OtherSuccTIs);
1827+
// Clone the terminator and hoist it into the pred, without any debug info.
17561828
Instruction *NT = I1->clone();
17571829
NT->insertInto(TIParent, TI->getIterator());
17581830
if (!NT->getType()->isVoidTy()) {

llvm/test/Transforms/SimplifyCFG/X86/pr39187-g.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
; RUN: opt < %s -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -hoist-common-insts=true | FileCheck %s
2+
; RUN: opt --try-experimental-debuginfo-iterators < %s -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -hoist-common-insts=true | FileCheck %s
23

34
; SimplifyCFG can hoist any common code in the 'then' and 'else' blocks to
45
; the 'if' basic block.

llvm/test/Transforms/SimplifyCFG/hoist-dbgvalue-inlined.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
; RUN: opt -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -hoist-common-insts=true -S < %s | FileCheck %s
2+
; RUN: opt --try-experimental-debuginfo-iterators -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -hoist-common-insts=true -S < %s | FileCheck %s
23
; Verify that we don't crash due an invalid !dbg location on the hoisted llvm.dbg.value
34

45
define i64 @caller(ptr %ptr, i64 %flag) !dbg !10 {

llvm/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
22
; RUN: opt -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s
3+
; RUN: opt -try-experimental-debuginfo-iterators -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s
34

45
define i32 @foo(i32 %i) nounwind ssp !dbg !0 {
56
; CHECK-LABEL: @foo(

0 commit comments

Comments
 (0)