Skip to content

Commit 58dab7d

Browse files
committed
[RemoveDIs] Handle DPValues in hoistCommonCodeFromSuccessors
This involves hoisting DPValues that are identical in lock-step attached to each instruction being considered for hoisting (i.e., we also need to do it for the final instructions which are not hoisted, because dbg.values after the last "real" instruction would be hoisted). 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 d91bb2f commit 58dab7d

File tree

4 files changed

+90
-12
lines changed

4 files changed

+90
-12
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 87 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,6 +1526,63 @@ 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 any Current == End.
1547+
auto atEnd = [&]() {
1548+
return any_of(Itrs,
1549+
[](const CurrentAndEndIt &P) { return P.first == P.second; });
1550+
};
1551+
// Return true if all Current are identical.
1552+
auto allIdentical = [&]() {
1553+
return all_of(make_first_range(ArrayRef(Itrs).drop_front()),
1554+
[&](DPValue::self_iterator I) {
1555+
return Itrs[0].first->isIdenticalToWhenDefined(*I);
1556+
});
1557+
};
1558+
1559+
// Collect the iterators.
1560+
Itrs.push_back(
1561+
{I1->getDbgValueRange().begin(), I1->getDbgValueRange().end()});
1562+
for (Instruction *Other : OtherInsts) {
1563+
if (!Other->hasDbgValues())
1564+
return;
1565+
Itrs.push_back(
1566+
{Other->getDbgValueRange().begin(), Other->getDbgValueRange().end()});
1567+
}
1568+
1569+
// Iterate in lock-step until any of the DPValue lists are exausted. If
1570+
// the lock-step DPValues are identical, hoist all of them to TI.
1571+
// This replicates the dbg.* intrinsic behaviour in
1572+
// hoistCommonCodeFromSuccessors.
1573+
while (!atEnd()) {
1574+
bool HoistDPVs = allIdentical();
1575+
for (CurrentAndEndIt &Pair : Itrs) {
1576+
// Increment Current iterator now as we may be about to move the DPValue.
1577+
DPValue &DPV = *Pair.first++;
1578+
if (HoistDPVs) {
1579+
DPV.removeFromParent();
1580+
TI->getParent()->insertDPValueBefore(&DPV, TI->getIterator());
1581+
}
1582+
}
1583+
}
1584+
}
1585+
15291586
/// Hoist any common code in the successor blocks up into the block. This
15301587
/// function guarantees that BB dominates all successors. If EqTermsOnly is
15311588
/// given, only perform hoisting in case both blocks only contain a terminator.
@@ -1624,18 +1681,23 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
16241681
AllInstsAreIdentical = false;
16251682
}
16261683

1684+
SmallVector<Instruction *, 8> OtherInsts;
1685+
for (auto &SuccIter : OtherSuccIterRange)
1686+
OtherInsts.push_back(&*SuccIter);
1687+
16271688
// If we are hoisting the terminator instruction, don't move one (making a
16281689
// broken BB), instead clone it, and remove BI.
16291690
if (HasTerminator) {
16301691
// Even if BB, which contains only one unreachable instruction, is ignored
16311692
// at the beginning of the loop, we can hoist the terminator instruction.
16321693
// If any instructions remain in the block, we cannot hoist terminators.
1633-
if (NumSkipped || !AllInstsAreIdentical)
1694+
if (NumSkipped || !AllInstsAreIdentical) {
1695+
hoistLockstepIdenticalDPValues(TI, I1, OtherInsts);
16341696
return Changed;
1635-
SmallVector<Instruction *, 8> Insts;
1636-
for (auto &SuccIter : OtherSuccIterRange)
1637-
Insts.push_back(&*SuccIter);
1638-
return hoistSuccIdenticalTerminatorToSwitchOrIf(TI, I1, Insts) || Changed;
1697+
}
1698+
1699+
return hoistSuccIdenticalTerminatorToSwitchOrIf(TI, I1, OtherInsts) ||
1700+
Changed;
16391701
}
16401702

16411703
if (AllInstsAreIdentical) {
@@ -1660,18 +1722,25 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
16601722
// The debug location is an integral part of a debug info intrinsic
16611723
// and can't be separated from it or replaced. Instead of attempting
16621724
// to merge locations, simply hoist both copies of the intrinsic.
1663-
I1->moveBeforePreserving(TI);
1725+
hoistLockstepIdenticalDPValues(TI, I1, OtherInsts);
1726+
// We've just hoisted DPValues; move I1 after them (before TI) and
1727+
// leave any that were not hoisted behind (by calling moveBefore
1728+
// rather than moveBeforePreserving).
1729+
I1->moveBefore(TI);
16641730
for (auto &SuccIter : OtherSuccIterRange) {
16651731
auto *I2 = &*SuccIter++;
16661732
assert(isa<DbgInfoIntrinsic>(I2));
1667-
I2->moveBeforePreserving(TI);
1733+
I2->moveBefore(TI);
16681734
}
16691735
} else {
16701736
// For a normal instruction, we just move one to right before the
16711737
// branch, then replace all uses of the other with the first. Finally,
1672-
// we remove the now redundant second instruction.
1673-
I1->moveBeforePreserving(TI);
1674-
BB->splice(TI->getIterator(), BB1, I1->getIterator());
1738+
// we remove the now redundant second instruction.s
1739+
hoistLockstepIdenticalDPValues(TI, I1, OtherInsts);
1740+
// We've just hoisted DPValues; move I1 after them (before TI) and
1741+
// leave any that were not hoisted behind (by calling moveBefore
1742+
// rather than moveBeforePreserving).
1743+
I1->moveBefore(TI);
16751744
for (auto &SuccIter : OtherSuccIterRange) {
16761745
Instruction *I2 = &*SuccIter++;
16771746
assert(I2 != I1);
@@ -1690,8 +1759,10 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
16901759
Changed = true;
16911760
NumHoistCommonInstrs += SuccIterPairs.size();
16921761
} else {
1693-
if (NumSkipped >= HoistCommonSkipLimit)
1762+
if (NumSkipped >= HoistCommonSkipLimit) {
1763+
hoistLockstepIdenticalDPValues(TI, I1, OtherInsts);
16941764
return Changed;
1765+
}
16951766
// We are about to skip over a pair of non-identical instructions. Record
16961767
// if any have characteristics that would prevent reordering instructions
16971768
// across them.
@@ -1752,9 +1823,13 @@ bool SimplifyCFGOpt::hoistSuccIdenticalTerminatorToSwitchOrIf(
17521823
}
17531824
}
17541825

1755-
// Okay, it is safe to hoist the terminator.
1826+
// Hoist DPValues attached to the terminator to match dbg.* intrinsic hoisting
1827+
// behaviour in hoistCommonCodeFromSuccessors.
1828+
hoistLockstepIdenticalDPValues(TI, I1, OtherSuccTIs);
1829+
// Clone the terminator and hoist it into the pred, without any debug info.
17561830
Instruction *NT = I1->clone();
17571831
NT->insertInto(TIParent, TI->getIterator());
1832+
17581833
if (!NT->getType()->isVoidTy()) {
17591834
I1->replaceAllUsesWith(NT);
17601835
for (Instruction *OtherSuccTI : OtherSuccTIs)

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)