@@ -1526,19 +1526,29 @@ static bool shouldHoistCommonInstructions(Instruction *I1, Instruction *I2,
1526
1526
return true ;
1527
1527
}
1528
1528
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
+
1529
1540
// / Hoist any common code in the successor blocks up into the block. This
1530
1541
// / function guarantees that BB dominates all successors. If EqTermsOnly is
1531
1542
// / given, only perform hoisting in case both blocks only contain a terminator.
1532
1543
// / In that case, only the original BI will be replaced and selects for PHIs are
1533
1544
// / added.
1534
1545
bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors (BasicBlock *BB,
1535
1546
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.
1542
1552
unsigned int SuccSize = succ_size (BB);
1543
1553
if (SuccSize < 2 )
1544
1554
return false ;
@@ -1552,10 +1562,21 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
1552
1562
1553
1563
auto *TI = BB->getTerminator ();
1554
1564
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
+
1555
1576
// The second of pair is a SkipFlags bitmask.
1556
1577
using SuccIterPair = std::pair<BasicBlock::iterator, unsigned >;
1557
1578
SmallVector<SuccIterPair, 8 > SuccIterPairs;
1558
- for (auto *Succ : successors (BB) ) {
1579
+ for (auto *Succ : SuccessorBlocks ) {
1559
1580
BasicBlock::iterator SuccItr = Succ->begin ();
1560
1581
if (isa<PHINode>(*SuccItr))
1561
1582
return false ;
@@ -1589,80 +1610,121 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
1589
1610
}
1590
1611
1591
1612
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
+ }
1592
1634
1635
+ // Keep track of instructions skipped in the first successor
1636
+ unsigned SkipFlagsBB1 = 0 ;
1637
+ bool SameLevelHoist = true ;
1593
1638
for (;;) {
1594
1639
auto *SuccIterPairBegin = SuccIterPairs.begin ();
1595
1640
auto &BB1ItrPair = *SuccIterPairBegin++;
1596
1641
auto OtherSuccIterPairRange =
1597
1642
iterator_range (SuccIterPairBegin, SuccIterPairs.end ());
1598
- auto OtherSuccIterRange = make_first_range (OtherSuccIterPairRange);
1599
-
1600
1643
Instruction *I1 = &*BB1ItrPair.first ;
1601
1644
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 ;
1615
1655
}
1616
1656
}
1617
1657
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 ;
1625
1673
}
1626
1674
1627
1675
// If we are hoisting the terminator instruction, don't move one (making a
1628
1676
// broken BB), instead clone it, and remove BI.
1629
- if (HasTerminator ) {
1677
+ if (I1-> isTerminator () ) {
1630
1678
// Even if BB, which contains only one unreachable instruction, is ignored
1631
1679
// at the beginning of the loop, we can hoist the terminator instruction.
1632
1680
// If any instructions remain in the block, we cannot hoist terminators.
1633
- if (NumSkipped || !AllInstsAreIdentical )
1681
+ if (NumSkipped)
1634
1682
return Changed;
1635
1683
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
+ }
1638
1692
return hoistSuccIdenticalTerminatorToSwitchOrIf (TI, I1, Insts) || Changed;
1639
1693
}
1640
1694
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++;
1655
1713
}
1656
1714
1657
- if (AllInstsAreIdentical ) {
1715
+ if (SafeToHoist ) {
1658
1716
BB1ItrPair.first ++;
1717
+ if (SameLevelHoist) {
1718
+ for (auto &SuccIterPair : OtherSuccIterPairRange)
1719
+ SuccIterPair.first ++;
1720
+ }
1659
1721
if (isa<DbgInfoIntrinsic>(I1)) {
1660
1722
// The debug location is an integral part of a debug info intrinsic
1661
1723
// and can't be separated from it or replaced. Instead of attempting
1662
1724
// to merge locations, simply hoist both copies of the intrinsic.
1663
1725
I1->moveBeforePreserving (TI);
1664
- for (auto &SuccIter : OtherSuccIterRange ) {
1665
- auto *I2 = &*SuccIter++ ;
1726
+ for (auto &map : OtherSuccessorsHash ) {
1727
+ Instruction *I2 = map[ getHash (I1)]. first ;
1666
1728
assert (isa<DbgInfoIntrinsic>(I2));
1667
1729
I2->moveBeforePreserving (TI);
1668
1730
}
@@ -1672,8 +1734,8 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
1672
1734
// we remove the now redundant second instruction.
1673
1735
I1->moveBeforePreserving (TI);
1674
1736
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 ;
1677
1739
assert (I2 != I1);
1678
1740
if (!I2->use_empty ())
1679
1741
I2->replaceAllUsesWith (I1);
@@ -1695,9 +1757,12 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
1695
1757
// We are about to skip over a pair of non-identical instructions. Record
1696
1758
// if any have characteristics that would prevent reordering instructions
1697
1759
// 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
+ }
1701
1766
}
1702
1767
++NumSkipped;
1703
1768
}
@@ -1741,7 +1806,6 @@ bool SimplifyCFGOpt::hoistSuccIdenticalTerminatorToSwitchOrIf(
1741
1806
Value *BB2V = PN.getIncomingValueForBlock (OtherSuccTI->getParent ());
1742
1807
if (BB1V == BB2V)
1743
1808
continue ;
1744
-
1745
1809
// In the case of an if statement, check for
1746
1810
// passingValueIsAlwaysUndefined here because we would rather eliminate
1747
1811
// undefined control flow then converting it to a select.
@@ -1810,20 +1874,16 @@ bool SimplifyCFGOpt::hoistSuccIdenticalTerminatorToSwitchOrIf(
1810
1874
}
1811
1875
}
1812
1876
}
1813
-
1814
1877
SmallVector<DominatorTree::UpdateType, 4 > Updates;
1815
-
1816
1878
// Update any PHI nodes in our new successors.
1817
1879
for (BasicBlock *Succ : successors (BB1)) {
1818
1880
AddPredecessorToBlock (Succ, TIParent, BB1);
1819
1881
if (DTU)
1820
1882
Updates.push_back ({DominatorTree::Insert, TIParent, Succ});
1821
1883
}
1822
-
1823
1884
if (DTU)
1824
1885
for (BasicBlock *Succ : successors (TI))
1825
1886
Updates.push_back ({DominatorTree::Delete, TIParent, Succ});
1826
-
1827
1887
EraseTerminatorAndDCECond (TI);
1828
1888
if (DTU)
1829
1889
DTU->applyUpdates (Updates);
0 commit comments