Skip to content

Commit 6e36f63

Browse files
[SimplifyCFG] Fix hoisting problem in SimplifyCFG
1 parent 895ee26 commit 6e36f63

File tree

1 file changed

+129
-63
lines changed

1 file changed

+129
-63
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 129 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,19 +1582,29 @@ hoistLockstepIdenticalDPValues(Instruction *TI, Instruction *I1,
15821582
}
15831583
}
15841584

1585+
// Hash instructions based on following factors:
1586+
// 1- Instruction Opcode
1587+
// 2- Instruction type
1588+
// 3- Instruction operands
1589+
llvm::hash_code getHash(Instruction *Instr) {
1590+
std::vector<Value *> operands(Instr->op_begin(), Instr->op_end());
1591+
return llvm::hash_combine(
1592+
Instr->getOpcode(), Instr->getType(),
1593+
hash_combine_range(operands.begin(), operands.end()));
1594+
}
1595+
15851596
/// Hoist any common code in the successor blocks up into the block. This
15861597
/// function guarantees that BB dominates all successors. If EqTermsOnly is
15871598
/// given, only perform hoisting in case both blocks only contain a terminator.
15881599
/// In that case, only the original BI will be replaced and selects for PHIs are
15891600
/// added.
15901601
bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
15911602
bool EqTermsOnly) {
1592-
// This does very trivial matching, with limited scanning, to find identical
1593-
// instructions in the two blocks. In particular, we don't want to get into
1594-
// O(N1*N2*...) situations here where Ni are the sizes of these successors. As
1595-
// such, we currently just scan for obviously identical instructions in an
1596-
// identical order, possibly separated by the same number of non-identical
1597-
// instructions.
1603+
// We first sort successors based on the number of instructions each block
1604+
// holds. Then for each successor we make a hashmap from its instructions,
1605+
// except for the first successor. After that, we iterate over the
1606+
// instructions of the first successor. If we find identical instructions from
1607+
// every other successor, we hoist all of them into the predeccessor.
15981608
unsigned int SuccSize = succ_size(BB);
15991609
if (SuccSize < 2)
16001610
return false;
@@ -1608,10 +1618,21 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
16081618

16091619
auto *TI = BB->getTerminator();
16101620

1621+
SmallVector<BasicBlock *> SuccessorBlocks;
1622+
for (auto *Succ : successors(BB))
1623+
SuccessorBlocks.push_back(Succ);
1624+
1625+
// Sort successor blocks based on the number of instructions.
1626+
// This is because we always want to iterate over instructions
1627+
// of the smallest block.
1628+
llvm::stable_sort(SuccessorBlocks, [](BasicBlock *BB1, BasicBlock *BB2) {
1629+
return BB1->sizeWithoutDebug() < BB2->sizeWithoutDebug();
1630+
});
1631+
16111632
// The second of pair is a SkipFlags bitmask.
16121633
using SuccIterPair = std::pair<BasicBlock::iterator, unsigned>;
16131634
SmallVector<SuccIterPair, 8> SuccIterPairs;
1614-
for (auto *Succ : successors(BB)) {
1635+
for (auto *Succ : SuccessorBlocks) {
16151636
BasicBlock::iterator SuccItr = Succ->begin();
16161637
if (isa<PHINode>(*SuccItr))
16171638
return false;
@@ -1645,77 +1666,124 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
16451666
}
16461667

16471668
bool Changed = false;
1669+
auto *SuccIterPairBegin = SuccIterPairs.begin();
1670+
SuccIterPairBegin++;
1671+
auto OtherSuccIterPairRange =
1672+
iterator_range(SuccIterPairBegin, SuccIterPairs.end());
1673+
auto OtherSuccIterRange = make_first_range(OtherSuccIterPairRange);
1674+
using InstrFlagPair = std::pair<Instruction *, unsigned>;
1675+
SmallVector<DenseMap<llvm::hash_code, InstrFlagPair>, 2> OtherSuccessorsHash;
1676+
1677+
for (auto BBItrPair : OtherSuccIterRange) {
1678+
// Fill the hashmap for every other successor
1679+
DenseMap<llvm::hash_code, InstrFlagPair> hashMap;
1680+
unsigned skipFlag = 0;
1681+
Instruction *I = nullptr;
1682+
do {
1683+
I = &*BBItrPair;
1684+
skipFlag |= skippedInstrFlags(I);
1685+
hashMap[getHash(I)] = InstrFlagPair(I, skipFlag);
1686+
BBItrPair++;
1687+
} while (!I->isTerminator());
1688+
OtherSuccessorsHash.push_back(hashMap);
1689+
}
16481690

1691+
// Keep track of instructions skipped in the first successor
1692+
unsigned SkipFlagsBB1 = 0;
1693+
bool SameLevelHoist = true;
16491694
for (;;) {
16501695
auto *SuccIterPairBegin = SuccIterPairs.begin();
16511696
auto &BB1ItrPair = *SuccIterPairBegin++;
16521697
auto OtherSuccIterPairRange =
16531698
iterator_range(SuccIterPairBegin, SuccIterPairs.end());
1654-
auto OtherSuccIterRange = make_first_range(OtherSuccIterPairRange);
1655-
16561699
Instruction *I1 = &*BB1ItrPair.first;
1657-
1658-
// Skip debug info if it is not identical.
1659-
bool AllDbgInstsAreIdentical = all_of(OtherSuccIterRange, [I1](auto &Iter) {
1660-
Instruction *I2 = &*Iter;
1661-
return I1->isIdenticalToWhenDefined(I2);
1662-
});
1663-
if (!AllDbgInstsAreIdentical) {
1664-
while (isa<DbgInfoIntrinsic>(I1))
1665-
I1 = &*++BB1ItrPair.first;
1666-
for (auto &SuccIter : OtherSuccIterRange) {
1667-
Instruction *I2 = &*SuccIter;
1668-
while (isa<DbgInfoIntrinsic>(I2))
1669-
I2 = &*++SuccIter;
1700+
bool HasIdenticalInst = true;
1701+
1702+
// Check if there are identical instructions in all other successors
1703+
for (auto &map : OtherSuccessorsHash) {
1704+
Instruction *I2 = map[getHash(I1)].first;
1705+
// We might face with same hash values for different instructions.
1706+
// If that happens, ignore the instruction.
1707+
if (!I2 || !I1->isIdenticalTo(I2)) {
1708+
HasIdenticalInst = false;
1709+
break;
16701710
}
16711711
}
16721712

1673-
bool AllInstsAreIdentical = true;
1674-
bool HasTerminator = I1->isTerminator();
1675-
for (auto &SuccIter : OtherSuccIterRange) {
1676-
Instruction *I2 = &*SuccIter;
1677-
HasTerminator |= I2->isTerminator();
1678-
if (AllInstsAreIdentical && !I1->isIdenticalToWhenDefined(I2))
1679-
AllInstsAreIdentical = false;
1713+
if (!HasIdenticalInst) {
1714+
if (NumSkipped >= HoistCommonSkipLimit)
1715+
return Changed;
1716+
SkipFlagsBB1 |= skippedInstrFlags(I1);
1717+
if (SameLevelHoist) {
1718+
for (auto &SuccIterPair : OtherSuccIterPairRange) {
1719+
Instruction *I = &*SuccIterPair.first++;
1720+
SuccIterPair.second |= skippedInstrFlags(I);
1721+
}
1722+
}
1723+
NumSkipped++;
1724+
if (I1->isTerminator())
1725+
return Changed;
1726+
++BB1ItrPair.first;
1727+
continue;
16801728
}
16811729

16821730
SmallVector<Instruction *, 8> OtherInsts;
1683-
for (auto &SuccIter : OtherSuccIterRange)
1684-
OtherInsts.push_back(&*SuccIter);
1731+
if (SameLevelHoist) {
1732+
for (auto &SuccIterPair : OtherSuccIterPairRange)
1733+
OtherInsts.push_back(&*(SuccIterPair.first));
1734+
} else {
1735+
for (auto &map : OtherSuccessorsHash)
1736+
OtherInstrs.push_back(map[getHash(I1)].first);
1737+
}
16851738

16861739
// If we are hoisting the terminator instruction, don't move one (making a
16871740
// broken BB), instead clone it, and remove BI.
1688-
if (HasTerminator) {
1741+
if (I1->isTerminator()) {
16891742
// Even if BB, which contains only one unreachable instruction, is ignored
16901743
// at the beginning of the loop, we can hoist the terminator instruction.
16911744
// If any instructions remain in the block, we cannot hoist terminators.
1692-
if (NumSkipped || !AllInstsAreIdentical) {
1745+
if (NumSkipped) {
16931746
hoistLockstepIdenticalDPValues(TI, I1, OtherInsts);
16941747
return Changed;
16951748
}
1696-
1697-
return hoistSuccIdenticalTerminatorToSwitchOrIf(TI, I1, OtherInsts) ||
1698-
Changed;
1749+
SmallVector<Instruction *, 8> Insts;
1750+
for (auto &map : OtherSuccessorsHash) {
1751+
Instruction *I2 = map[getHash(I1)].first;
1752+
// BB holding I2 should only contain the branch instruction
1753+
auto itr = I2->getParent()->instructionsWithoutDebug();
1754+
if (&*itr.begin() != I2)
1755+
return Changed;
1756+
Insts.push_back(I2);
1757+
}
1758+
return hoistSuccIdenticalTerminatorToSwitchOrIf(TI, I1, Insts) || Changed;
16991759
}
17001760

1701-
if (AllInstsAreIdentical) {
1702-
unsigned SkipFlagsBB1 = BB1ItrPair.second;
1703-
AllInstsAreIdentical =
1704-
isSafeToHoistInstr(I1, SkipFlagsBB1) &&
1705-
all_of(OtherSuccIterPairRange, [=](const auto &Pair) {
1706-
Instruction *I2 = &*Pair.first;
1707-
unsigned SkipFlagsBB2 = Pair.second;
1708-
// Even if the instructions are identical, it may not
1709-
// be safe to hoist them if we have skipped over
1710-
// instructions with side effects or their operands
1711-
// weren't hoisted.
1712-
return isSafeToHoistInstr(I2, SkipFlagsBB2) &&
1713-
shouldHoistCommonInstructions(I1, I2, TTI);
1714-
});
1761+
bool SafeToHoist = isSafeToHoistInstr(I1, SkipFlagsBB1);
1762+
unsigned index = 0;
1763+
for (auto &SuccIterPair : OtherSuccIterPairRange) {
1764+
Instruction *I2 = OtherSuccessorsHash[index][getHash(I1)].first;
1765+
// If instructions of all successors are at the same level, use the
1766+
// skipFlag of its BB, i.e., SameLevelHoist. Otherwise, use the skipFlag
1767+
// that was calculated initially for this instruction in the hashmap
1768+
if (SameLevelHoist && I2 == (&*(SuccIterPair.first))) {
1769+
SafeToHoist = SafeToHoist &&
1770+
isSafeToHoistInstr(I2, SuccIterPair.second) &&
1771+
shouldHoistCommonInstructions(I1, I2, TTI);
1772+
} else {
1773+
unsigned skipFlag = OtherSuccessorsHash[index][getHash(I1)].second;
1774+
SafeToHoist = SafeToHoist && isSafeToHoistInstr(I2, skipFlag) &&
1775+
shouldHoistCommonInstructions(I1, I2, TTI);
1776+
SameLevelHoist = false;
1777+
}
1778+
index++;
17151779
}
17161780

1717-
if (AllInstsAreIdentical) {
1781+
if (SafeToHoist) {
17181782
BB1ItrPair.first++;
1783+
if (SameLevelHoist) {
1784+
for (auto &SuccIterPair : OtherSuccIterPairRange)
1785+
SuccIterPair.first++;
1786+
}
17191787
if (isa<DbgInfoIntrinsic>(I1)) {
17201788
// The debug location is an integral part of a debug info intrinsic
17211789
// and can't be separated from it or replaced. Instead of attempting
@@ -1725,8 +1793,8 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
17251793
// leave any that were not hoisted behind (by calling moveBefore
17261794
// rather than moveBeforePreserving).
17271795
I1->moveBefore(TI);
1728-
for (auto &SuccIter : OtherSuccIterRange) {
1729-
auto *I2 = &*SuccIter++;
1796+
for (auto &map : OtherSuccessorsHash) {
1797+
Instruction *I2 = map[getHash(I1)].first;
17301798
assert(isa<DbgInfoIntrinsic>(I2));
17311799
I2->moveBefore(TI);
17321800
}
@@ -1739,8 +1807,8 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
17391807
// leave any that were not hoisted behind (by calling moveBefore
17401808
// rather than moveBeforePreserving).
17411809
I1->moveBefore(TI);
1742-
for (auto &SuccIter : OtherSuccIterRange) {
1743-
Instruction *I2 = &*SuccIter++;
1810+
for (auto &map : OtherSuccessorsHash) {
1811+
Instruction *I2 = map[getHash(I1)].first;
17441812
assert(I2 != I1);
17451813
if (!I2->use_empty())
17461814
I2->replaceAllUsesWith(I1);
@@ -1764,9 +1832,12 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
17641832
// We are about to skip over a pair of non-identical instructions. Record
17651833
// if any have characteristics that would prevent reordering instructions
17661834
// across them.
1767-
for (auto &SuccIterPair : SuccIterPairs) {
1768-
Instruction *I = &*SuccIterPair.first++;
1769-
SuccIterPair.second |= skippedInstrFlags(I);
1835+
SkipFlagsBB1 |= skippedInstrFlags(I1);
1836+
if (SameLevelHoist) {
1837+
for (auto &SuccIterPair : OtherSuccIterPairRange) { // update flags
1838+
Instruction *I = &*SuccIterPair.first;
1839+
SuccIterPair.second |= skippedInstrFlags(I);
1840+
}
17701841
}
17711842
++NumSkipped;
17721843
}
@@ -1810,7 +1881,6 @@ bool SimplifyCFGOpt::hoistSuccIdenticalTerminatorToSwitchOrIf(
18101881
Value *BB2V = PN.getIncomingValueForBlock(OtherSuccTI->getParent());
18111882
if (BB1V == BB2V)
18121883
continue;
1813-
18141884
// In the case of an if statement, check for
18151885
// passingValueIsAlwaysUndefined here because we would rather eliminate
18161886
// undefined control flow then converting it to a select.
@@ -1882,20 +1952,16 @@ bool SimplifyCFGOpt::hoistSuccIdenticalTerminatorToSwitchOrIf(
18821952
}
18831953
}
18841954
}
1885-
18861955
SmallVector<DominatorTree::UpdateType, 4> Updates;
1887-
18881956
// Update any PHI nodes in our new successors.
18891957
for (BasicBlock *Succ : successors(BB1)) {
18901958
AddPredecessorToBlock(Succ, TIParent, BB1);
18911959
if (DTU)
18921960
Updates.push_back({DominatorTree::Insert, TIParent, Succ});
18931961
}
1894-
18951962
if (DTU)
18961963
for (BasicBlock *Succ : successors(TI))
18971964
Updates.push_back({DominatorTree::Delete, TIParent, Succ});
1898-
18991965
EraseTerminatorAndDCECond(TI);
19001966
if (DTU)
19011967
DTU->applyUpdates(Updates);

0 commit comments

Comments
 (0)