Skip to content

Commit d29e5b0

Browse files
[SimplifyCFG] Fix hoisting problem in SimplifyCFG
1 parent b28897c commit d29e5b0

File tree

1 file changed

+120
-60
lines changed

1 file changed

+120
-60
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 120 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,19 +1526,29 @@ static bool shouldHoistCommonInstructions(Instruction *I1, Instruction *I2,
15261526
return true;
15271527
}
15281528

1529+
// Hash instructions based on following factors:
1530+
// 1- Instruction Opcode
1531+
// 2- Instruction type
1532+
// 3- Instruction operands
1533+
llvm::hash_code getHash(Instruction *Instr) {
1534+
std::vector<Value *> operands(Instr->op_begin(), Instr->op_end());
1535+
return llvm::hash_combine(
1536+
Instr->getOpcode(), Instr->getType(),
1537+
hash_combine_range(operands.begin(), operands.end()));
1538+
}
1539+
15291540
/// Hoist any common code in the successor blocks up into the block. This
15301541
/// function guarantees that BB dominates all successors. If EqTermsOnly is
15311542
/// given, only perform hoisting in case both blocks only contain a terminator.
15321543
/// In that case, only the original BI will be replaced and selects for PHIs are
15331544
/// added.
15341545
bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
15351546
bool EqTermsOnly) {
1536-
// This does very trivial matching, with limited scanning, to find identical
1537-
// instructions in the two blocks. In particular, we don't want to get into
1538-
// O(N1*N2*...) situations here where Ni are the sizes of these successors. As
1539-
// such, we currently just scan for obviously identical instructions in an
1540-
// identical order, possibly separated by the same number of non-identical
1541-
// instructions.
1547+
// We first sort successors based on the number of instructions each block
1548+
// holds. Then for each successor we make a hashmap from its instructions,
1549+
// except for the first successor. After that, we iterate over the
1550+
// instructions of the first successor. If we find identical instructions from
1551+
// every other successor, we hoist all of them into the predeccessor.
15421552
unsigned int SuccSize = succ_size(BB);
15431553
if (SuccSize < 2)
15441554
return false;
@@ -1552,10 +1562,21 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
15521562

15531563
auto *TI = BB->getTerminator();
15541564

1565+
SmallVector<BasicBlock *> SuccessorBlocks;
1566+
for (auto *Succ : successors(BB))
1567+
SuccessorBlocks.push_back(Succ);
1568+
1569+
// Sort successor blocks based on the number of instructions.
1570+
// This is because we always want to iterate over instructions
1571+
// of the smallest block.
1572+
llvm::stable_sort(SuccessorBlocks, [](BasicBlock *BB1, BasicBlock *BB2) {
1573+
return BB1->sizeWithoutDebug() < BB2->sizeWithoutDebug();
1574+
});
1575+
15551576
// The second of pair is a SkipFlags bitmask.
15561577
using SuccIterPair = std::pair<BasicBlock::iterator, unsigned>;
15571578
SmallVector<SuccIterPair, 8> SuccIterPairs;
1558-
for (auto *Succ : successors(BB)) {
1579+
for (auto *Succ : SuccessorBlocks) {
15591580
BasicBlock::iterator SuccItr = Succ->begin();
15601581
if (isa<PHINode>(*SuccItr))
15611582
return false;
@@ -1589,80 +1610,121 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
15891610
}
15901611

15911612
bool Changed = false;
1613+
auto *SuccIterPairBegin = SuccIterPairs.begin();
1614+
SuccIterPairBegin++;
1615+
auto OtherSuccIterPairRange =
1616+
iterator_range(SuccIterPairBegin, SuccIterPairs.end());
1617+
auto OtherSuccIterRange = make_first_range(OtherSuccIterPairRange);
1618+
using InstrFlagPair = std::pair<Instruction *, unsigned>;
1619+
SmallVector<DenseMap<llvm::hash_code, InstrFlagPair>, 2> OtherSuccessorsHash;
1620+
1621+
for (auto BBItrPair : OtherSuccIterRange) {
1622+
// Fill the hashmap for every other successor
1623+
DenseMap<llvm::hash_code, InstrFlagPair> hashMap;
1624+
unsigned skipFlag = 0;
1625+
Instruction *I = nullptr;
1626+
do {
1627+
I = &*BBItrPair;
1628+
skipFlag |= skippedInstrFlags(I);
1629+
hashMap[getHash(I)] = InstrFlagPair(I, skipFlag);
1630+
BBItrPair++;
1631+
} while (!I->isTerminator());
1632+
OtherSuccessorsHash.push_back(hashMap);
1633+
}
15921634

1635+
// Keep track of instructions skipped in the first successor
1636+
unsigned SkipFlagsBB1 = 0;
1637+
bool SameLevelHoist = true;
15931638
for (;;) {
15941639
auto *SuccIterPairBegin = SuccIterPairs.begin();
15951640
auto &BB1ItrPair = *SuccIterPairBegin++;
15961641
auto OtherSuccIterPairRange =
15971642
iterator_range(SuccIterPairBegin, SuccIterPairs.end());
1598-
auto OtherSuccIterRange = make_first_range(OtherSuccIterPairRange);
1599-
16001643
Instruction *I1 = &*BB1ItrPair.first;
16011644
auto *BB1 = I1->getParent();
1602-
1603-
// Skip debug info if it is not identical.
1604-
bool AllDbgInstsAreIdentical = all_of(OtherSuccIterRange, [I1](auto &Iter) {
1605-
Instruction *I2 = &*Iter;
1606-
return I1->isIdenticalToWhenDefined(I2);
1607-
});
1608-
if (!AllDbgInstsAreIdentical) {
1609-
while (isa<DbgInfoIntrinsic>(I1))
1610-
I1 = &*++BB1ItrPair.first;
1611-
for (auto &SuccIter : OtherSuccIterRange) {
1612-
Instruction *I2 = &*SuccIter;
1613-
while (isa<DbgInfoIntrinsic>(I2))
1614-
I2 = &*++SuccIter;
1645+
bool HasIdenticalInst = true;
1646+
1647+
// Check if there are identical instructions in all other successors
1648+
for (auto &map : OtherSuccessorsHash) {
1649+
Instruction *I2 = map[getHash(I1)].first;
1650+
// We might face with same hash values for different instructions.
1651+
// If that happens, ignore the instruction.
1652+
if (!I2 || !I1->isIdenticalTo(I2)) {
1653+
HasIdenticalInst = false;
1654+
break;
16151655
}
16161656
}
16171657

1618-
bool AllInstsAreIdentical = true;
1619-
bool HasTerminator = I1->isTerminator();
1620-
for (auto &SuccIter : OtherSuccIterRange) {
1621-
Instruction *I2 = &*SuccIter;
1622-
HasTerminator |= I2->isTerminator();
1623-
if (AllInstsAreIdentical && !I1->isIdenticalToWhenDefined(I2))
1624-
AllInstsAreIdentical = false;
1658+
if (!HasIdenticalInst) {
1659+
if (NumSkipped >= HoistCommonSkipLimit)
1660+
return Changed;
1661+
SkipFlagsBB1 |= skippedInstrFlags(I1);
1662+
if (SameLevelHoist) {
1663+
for (auto &SuccIterPair : OtherSuccIterPairRange) {
1664+
Instruction *I = &*SuccIterPair.first++;
1665+
SuccIterPair.second |= skippedInstrFlags(I);
1666+
}
1667+
}
1668+
NumSkipped++;
1669+
if (I1->isTerminator())
1670+
return Changed;
1671+
++BB1ItrPair.first;
1672+
continue;
16251673
}
16261674

16271675
// If we are hoisting the terminator instruction, don't move one (making a
16281676
// broken BB), instead clone it, and remove BI.
1629-
if (HasTerminator) {
1677+
if (I1->isTerminator()) {
16301678
// Even if BB, which contains only one unreachable instruction, is ignored
16311679
// at the beginning of the loop, we can hoist the terminator instruction.
16321680
// If any instructions remain in the block, we cannot hoist terminators.
1633-
if (NumSkipped || !AllInstsAreIdentical)
1681+
if (NumSkipped)
16341682
return Changed;
16351683
SmallVector<Instruction *, 8> Insts;
1636-
for (auto &SuccIter : OtherSuccIterRange)
1637-
Insts.push_back(&*SuccIter);
1684+
for (auto &map : OtherSuccessorsHash) {
1685+
Instruction *I2 = map[getHash(I1)].first;
1686+
// BB holding I2 should only contain the branch instruction
1687+
auto itr = I2->getParent()->instructionsWithoutDebug();
1688+
if (&*itr.begin() != I2)
1689+
return Changed;
1690+
Insts.push_back(I2);
1691+
}
16381692
return hoistSuccIdenticalTerminatorToSwitchOrIf(TI, I1, Insts) || Changed;
16391693
}
16401694

1641-
if (AllInstsAreIdentical) {
1642-
unsigned SkipFlagsBB1 = BB1ItrPair.second;
1643-
AllInstsAreIdentical =
1644-
isSafeToHoistInstr(I1, SkipFlagsBB1) &&
1645-
all_of(OtherSuccIterPairRange, [=](const auto &Pair) {
1646-
Instruction *I2 = &*Pair.first;
1647-
unsigned SkipFlagsBB2 = Pair.second;
1648-
// Even if the instructions are identical, it may not
1649-
// be safe to hoist them if we have skipped over
1650-
// instructions with side effects or their operands
1651-
// weren't hoisted.
1652-
return isSafeToHoistInstr(I2, SkipFlagsBB2) &&
1653-
shouldHoistCommonInstructions(I1, I2, TTI);
1654-
});
1695+
bool SafeToHoist = isSafeToHoistInstr(I1, SkipFlagsBB1);
1696+
unsigned index = 0;
1697+
for (auto &SuccIterPair : OtherSuccIterPairRange) {
1698+
Instruction *I2 = OtherSuccessorsHash[index][getHash(I1)].first;
1699+
// If instructions of all successors are at the same level, use the
1700+
// skipFlag of its BB, i.e., SameLevelHoist. Otherwise, use the skipFlag
1701+
// that was calculated initially for this instruction in the hashmap
1702+
if (SameLevelHoist && I2 == (&*(SuccIterPair.first))) {
1703+
SafeToHoist = SafeToHoist &&
1704+
isSafeToHoistInstr(I2, SuccIterPair.second) &&
1705+
shouldHoistCommonInstructions(I1, I2, TTI);
1706+
} else {
1707+
unsigned skipFlag = OtherSuccessorsHash[index][getHash(I1)].second;
1708+
SafeToHoist = SafeToHoist && isSafeToHoistInstr(I2, skipFlag) &&
1709+
shouldHoistCommonInstructions(I1, I2, TTI);
1710+
SameLevelHoist = false;
1711+
}
1712+
index++;
16551713
}
16561714

1657-
if (AllInstsAreIdentical) {
1715+
if (SafeToHoist) {
16581716
BB1ItrPair.first++;
1717+
if (SameLevelHoist) {
1718+
for (auto &SuccIterPair : OtherSuccIterPairRange)
1719+
SuccIterPair.first++;
1720+
}
16591721
if (isa<DbgInfoIntrinsic>(I1)) {
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.
16631725
I1->moveBeforePreserving(TI);
1664-
for (auto &SuccIter : OtherSuccIterRange) {
1665-
auto *I2 = &*SuccIter++;
1726+
for (auto &map : OtherSuccessorsHash) {
1727+
Instruction *I2 = map[getHash(I1)].first;
16661728
assert(isa<DbgInfoIntrinsic>(I2));
16671729
I2->moveBeforePreserving(TI);
16681730
}
@@ -1672,8 +1734,8 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
16721734
// we remove the now redundant second instruction.
16731735
I1->moveBeforePreserving(TI);
16741736
BB->splice(TI->getIterator(), BB1, I1->getIterator());
1675-
for (auto &SuccIter : OtherSuccIterRange) {
1676-
Instruction *I2 = &*SuccIter++;
1737+
for (auto &map : OtherSuccessorsHash) {
1738+
Instruction *I2 = map[getHash(I1)].first;
16771739
assert(I2 != I1);
16781740
if (!I2->use_empty())
16791741
I2->replaceAllUsesWith(I1);
@@ -1695,9 +1757,12 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
16951757
// We are about to skip over a pair of non-identical instructions. Record
16961758
// if any have characteristics that would prevent reordering instructions
16971759
// across them.
1698-
for (auto &SuccIterPair : SuccIterPairs) {
1699-
Instruction *I = &*SuccIterPair.first++;
1700-
SuccIterPair.second |= skippedInstrFlags(I);
1760+
SkipFlagsBB1 |= skippedInstrFlags(I1);
1761+
if (SameLevelHoist) {
1762+
for (auto &SuccIterPair : OtherSuccIterPairRange) { // update flags
1763+
Instruction *I = &*SuccIterPair.first;
1764+
SuccIterPair.second |= skippedInstrFlags(I);
1765+
}
17011766
}
17021767
++NumSkipped;
17031768
}
@@ -1741,7 +1806,6 @@ bool SimplifyCFGOpt::hoistSuccIdenticalTerminatorToSwitchOrIf(
17411806
Value *BB2V = PN.getIncomingValueForBlock(OtherSuccTI->getParent());
17421807
if (BB1V == BB2V)
17431808
continue;
1744-
17451809
// In the case of an if statement, check for
17461810
// passingValueIsAlwaysUndefined here because we would rather eliminate
17471811
// undefined control flow then converting it to a select.
@@ -1810,20 +1874,16 @@ bool SimplifyCFGOpt::hoistSuccIdenticalTerminatorToSwitchOrIf(
18101874
}
18111875
}
18121876
}
1813-
18141877
SmallVector<DominatorTree::UpdateType, 4> Updates;
1815-
18161878
// Update any PHI nodes in our new successors.
18171879
for (BasicBlock *Succ : successors(BB1)) {
18181880
AddPredecessorToBlock(Succ, TIParent, BB1);
18191881
if (DTU)
18201882
Updates.push_back({DominatorTree::Insert, TIParent, Succ});
18211883
}
1822-
18231884
if (DTU)
18241885
for (BasicBlock *Succ : successors(TI))
18251886
Updates.push_back({DominatorTree::Delete, TIParent, Succ});
1826-
18271887
EraseTerminatorAndDCECond(TI);
18281888
if (DTU)
18291889
DTU->applyUpdates(Updates);

0 commit comments

Comments
 (0)