28
28
#include " RISCVSubtarget.h"
29
29
#include " llvm/ADT/Statistic.h"
30
30
#include " llvm/CodeGen/LiveIntervals.h"
31
+ #include " llvm/CodeGen/LiveStacks.h"
31
32
#include " llvm/CodeGen/MachineFunctionPass.h"
32
33
#include < queue>
33
34
using namespace llvm ;
34
35
35
36
#define DEBUG_TYPE " riscv-insert-vsetvli"
36
37
#define RISCV_INSERT_VSETVLI_NAME " RISC-V Insert VSETVLI pass"
38
+ #define RISCV_COALESCE_VSETVLI_NAME " RISC-V Coalesce VSETVLI pass"
37
39
38
40
STATISTIC (NumInsertedVSETVL, " Number of VSETVL inst inserted" );
39
- STATISTIC (NumRemovedVSETVL , " Number of VSETVL inst removed " );
41
+ STATISTIC (NumCoalescedVSETVL , " Number of VSETVL inst coalesced " );
40
42
41
43
static cl::opt<bool > DisableInsertVSETVLPHIOpt (
42
44
" riscv-disable-insert-vsetvl-phi-opt" , cl::init(false ), cl::Hidden,
@@ -190,6 +192,11 @@ static bool hasUndefinedMergeOp(const MachineInstr &MI,
190
192
if (UseMO.getReg () == RISCV::NoRegister)
191
193
return true ;
192
194
195
+ if (UseMO.isUndef ())
196
+ return true ;
197
+ if (UseMO.getReg ().isPhysical ())
198
+ return false ;
199
+
193
200
if (MachineInstr *UseMI = MRI.getVRegDef (UseMO.getReg ())) {
194
201
if (UseMI->isImplicitDef ())
195
202
return true ;
@@ -777,18 +784,44 @@ class RISCVInsertVSETVLI : public MachineFunctionPass {
777
784
VSETVLIInfo &Info) const ;
778
785
void computeIncomingVLVTYPE (const MachineBasicBlock &MBB);
779
786
void emitVSETVLIs (MachineBasicBlock &MBB);
780
- void doLocalPostpass (MachineBasicBlock &MBB);
781
787
void doPRE (MachineBasicBlock &MBB);
782
788
void insertReadVL (MachineBasicBlock &MBB);
783
789
};
784
790
791
+ class RISCVCoalesceVSETVLI : public MachineFunctionPass {
792
+ public:
793
+ static char ID;
794
+
795
+ RISCVCoalesceVSETVLI () : MachineFunctionPass(ID) {}
796
+ bool runOnMachineFunction (MachineFunction &MF) override ;
797
+
798
+ void getAnalysisUsage (AnalysisUsage &AU) const override {
799
+ AU.setPreservesCFG ();
800
+
801
+ AU.addRequired <LiveIntervals>();
802
+ AU.addPreserved <LiveIntervals>();
803
+ AU.addRequired <SlotIndexes>();
804
+ AU.addPreserved <SlotIndexes>();
805
+ AU.addPreserved <LiveStacks>();
806
+
807
+ MachineFunctionPass::getAnalysisUsage (AU);
808
+ }
809
+
810
+ StringRef getPassName () const override { return RISCV_COALESCE_VSETVLI_NAME; }
811
+ };
812
+
785
813
} // end anonymous namespace
786
814
787
815
char RISCVInsertVSETVLI::ID = 0 ;
788
816
789
817
INITIALIZE_PASS (RISCVInsertVSETVLI, DEBUG_TYPE, RISCV_INSERT_VSETVLI_NAME,
790
818
false , false )
791
819
820
+ char RISCVCoalesceVSETVLI::ID = 0;
821
+
822
+ INITIALIZE_PASS (RISCVCoalesceVSETVLI, " riscv-coalesce-vsetvli" ,
823
+ RISCV_COALESCE_VSETVLI_NAME, false , false )
824
+
792
825
// Return a VSETVLIInfo representing the changes made by this VSETVLI or
793
826
// VSETIVLI instruction.
794
827
static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) {
@@ -1510,7 +1543,10 @@ static bool canMutatePriorConfig(const MachineInstr &PrevMI,
1510
1543
1511
1544
auto &AVL = MI.getOperand (1 );
1512
1545
auto &PrevAVL = PrevMI.getOperand (1 );
1513
- assert (MRI.isSSA ());
1546
+ assert (!AVL.isReg () || !AVL.getReg ().isVirtual () ||
1547
+ MRI.hasOneDef (AVL.getReg ()));
1548
+ assert (!PrevAVL.isReg () || !PrevAVL.getReg ().isVirtual () ||
1549
+ MRI.hasOneDef (PrevAVL.getReg ()));
1514
1550
1515
1551
// If the AVL is a register, we need to make sure MI's AVL dominates PrevMI.
1516
1552
// For now just check that PrevMI uses the same virtual register.
@@ -1530,64 +1566,6 @@ static bool canMutatePriorConfig(const MachineInstr &PrevMI,
1530
1566
return areCompatibleVTYPEs (PriorVType, VType, Used);
1531
1567
}
1532
1568
1533
- void RISCVInsertVSETVLI::doLocalPostpass (MachineBasicBlock &MBB) {
1534
- MachineInstr *NextMI = nullptr ;
1535
- // We can have arbitrary code in successors, so VL and VTYPE
1536
- // must be considered demanded.
1537
- DemandedFields Used;
1538
- Used.demandVL ();
1539
- Used.demandVTYPE ();
1540
- SmallVector<MachineInstr*> ToDelete;
1541
- for (MachineInstr &MI : make_range (MBB.rbegin (), MBB.rend ())) {
1542
-
1543
- if (!isVectorConfigInstr (MI)) {
1544
- doUnion (Used, getDemanded (MI, MRI, ST));
1545
- continue ;
1546
- }
1547
-
1548
- Register VRegDef = MI.getOperand (0 ).getReg ();
1549
- if (VRegDef != RISCV::X0 &&
1550
- !(VRegDef.isVirtual () && MRI->use_nodbg_empty (VRegDef)))
1551
- Used.demandVL ();
1552
-
1553
- if (NextMI) {
1554
- if (!Used.usedVL () && !Used.usedVTYPE ()) {
1555
- ToDelete.push_back (&MI);
1556
- // Leave NextMI unchanged
1557
- continue ;
1558
- } else if (canMutatePriorConfig (MI, *NextMI, Used, *MRI)) {
1559
- if (!isVLPreservingConfig (*NextMI)) {
1560
- MI.getOperand (0 ).setReg (NextMI->getOperand (0 ).getReg ());
1561
- MI.getOperand (0 ).setIsDead (false );
1562
- Register OldVLReg;
1563
- if (MI.getOperand (1 ).isReg ())
1564
- OldVLReg = MI.getOperand (1 ).getReg ();
1565
- if (NextMI->getOperand (1 ).isImm ())
1566
- MI.getOperand (1 ).ChangeToImmediate (NextMI->getOperand (1 ).getImm ());
1567
- else
1568
- MI.getOperand (1 ).ChangeToRegister (NextMI->getOperand (1 ).getReg (), false );
1569
- if (OldVLReg) {
1570
- MachineInstr *VLOpDef = MRI->getUniqueVRegDef (OldVLReg);
1571
- if (VLOpDef && TII->isAddImmediate (*VLOpDef, OldVLReg) &&
1572
- MRI->use_nodbg_empty (OldVLReg))
1573
- VLOpDef->eraseFromParent ();
1574
- }
1575
- MI.setDesc (NextMI->getDesc ());
1576
- }
1577
- MI.getOperand (2 ).setImm (NextMI->getOperand (2 ).getImm ());
1578
- ToDelete.push_back (NextMI);
1579
- // fallthrough
1580
- }
1581
- }
1582
- NextMI = &MI;
1583
- Used = getDemanded (MI, MRI, ST);
1584
- }
1585
-
1586
- NumRemovedVSETVL += ToDelete.size ();
1587
- for (auto *MI : ToDelete)
1588
- MI->eraseFromParent ();
1589
- }
1590
-
1591
1569
void RISCVInsertVSETVLI::insertReadVL (MachineBasicBlock &MBB) {
1592
1570
for (auto I = MBB.begin (), E = MBB.end (); I != E;) {
1593
1571
MachineInstr &MI = *I++;
@@ -1660,15 +1638,6 @@ bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) {
1660
1638
for (MachineBasicBlock &MBB : MF)
1661
1639
emitVSETVLIs (MBB);
1662
1640
1663
- // Now that all vsetvlis are explicit, go through and do block local
1664
- // DSE and peephole based demanded fields based transforms. Note that
1665
- // this *must* be done outside the main dataflow so long as we allow
1666
- // any cross block analysis within the dataflow. We can't have both
1667
- // demanded fields based mutation and non-local analysis in the
1668
- // dataflow at the same time without introducing inconsistencies.
1669
- for (MachineBasicBlock &MBB : MF)
1670
- doLocalPostpass (MBB);
1671
-
1672
1641
// Insert PseudoReadVL after VLEFF/VLSEGFF and replace it with the vl output
1673
1642
// of VLEFF/VLSEGFF.
1674
1643
for (MachineBasicBlock &MBB : MF)
@@ -1682,3 +1651,121 @@ bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) {
1682
1651
FunctionPass *llvm::createRISCVInsertVSETVLIPass () {
1683
1652
return new RISCVInsertVSETVLI ();
1684
1653
}
1654
+
1655
+ // Now that all vsetvlis are explicit, go through and do block local
1656
+ // DSE and peephole based demanded fields based transforms. Note that
1657
+ // this *must* be done outside the main dataflow so long as we allow
1658
+ // any cross block analysis within the dataflow. We can't have both
1659
+ // demanded fields based mutation and non-local analysis in the
1660
+ // dataflow at the same time without introducing inconsistencies.
1661
+ bool RISCVCoalesceVSETVLI::runOnMachineFunction (MachineFunction &MF) {
1662
+ // Skip if the vector extension is not enabled.
1663
+ auto *ST = &MF.getSubtarget <RISCVSubtarget>();
1664
+ if (!ST->hasVInstructions ())
1665
+ return false ;
1666
+
1667
+ LiveIntervals &LIS = getAnalysis<LiveIntervals>();
1668
+
1669
+ bool Changed = false ;
1670
+
1671
+ const auto *TII = ST->getInstrInfo ();
1672
+ auto *MRI = &MF.getRegInfo ();
1673
+ for (MachineBasicBlock &MBB : MF) {
1674
+ MachineInstr *NextMI = nullptr ;
1675
+ // We can have arbitrary code in successors, so VL and VTYPE
1676
+ // must be considered demanded.
1677
+ DemandedFields Used;
1678
+ Used.demandVL ();
1679
+ Used.demandVTYPE ();
1680
+ SmallVector<MachineInstr *> ToDelete;
1681
+ for (MachineInstr &MI : make_range (MBB.rbegin (), MBB.rend ())) {
1682
+
1683
+ if (!isVectorConfigInstr (MI)) {
1684
+ doUnion (Used, getDemanded (MI, MRI, ST));
1685
+ continue ;
1686
+ }
1687
+
1688
+ Register VRegDef = MI.getOperand (0 ).getReg ();
1689
+ if (VRegDef != RISCV::X0 &&
1690
+ !(VRegDef.isVirtual () && MRI->use_nodbg_empty (VRegDef)))
1691
+ Used.demandVL ();
1692
+
1693
+ if (NextMI) {
1694
+ if (!Used.usedVL () && !Used.usedVTYPE ()) {
1695
+ ToDelete.push_back (&MI);
1696
+ // Leave NextMI unchanged
1697
+ continue ;
1698
+ } else if (canMutatePriorConfig (MI, *NextMI, Used, *MRI)) {
1699
+ if (!isVLPreservingConfig (*NextMI)) {
1700
+
1701
+ Register DefReg = NextMI->getOperand (0 ).getReg ();
1702
+
1703
+ MI.getOperand (0 ).setReg (DefReg);
1704
+ MI.getOperand (0 ).setIsDead (false );
1705
+
1706
+ // The def of DefReg moved to MI, so extend the LiveInterval up to
1707
+ // it.
1708
+ if (DefReg.isVirtual ()) {
1709
+ LiveInterval &DefLI = LIS.getInterval (DefReg);
1710
+ SlotIndex MISlot = LIS.getInstructionIndex (MI).getRegSlot ();
1711
+ VNInfo *DefVNI = DefLI.getVNInfoAt (DefLI.beginIndex ());
1712
+ LiveInterval::Segment S (MISlot, DefLI.beginIndex (), DefVNI);
1713
+ DefLI.addSegment (S);
1714
+ DefVNI->def = MISlot;
1715
+
1716
+ // DefReg may have had no uses, in which case we need to shrink
1717
+ // the LiveInterval up to MI.
1718
+ LIS.shrinkToUses (&DefLI);
1719
+ }
1720
+
1721
+ Register OldVLReg;
1722
+ if (MI.getOperand (1 ).isReg ())
1723
+ OldVLReg = MI.getOperand (1 ).getReg ();
1724
+ if (NextMI->getOperand (1 ).isImm ())
1725
+ MI.getOperand (1 ).ChangeToImmediate (
1726
+ NextMI->getOperand (1 ).getImm ());
1727
+ else
1728
+ MI.getOperand (1 ).ChangeToRegister (NextMI->getOperand (1 ).getReg (),
1729
+ false );
1730
+
1731
+ // Clear NextMI's AVL early so we're not counting it as a use.
1732
+ if (NextMI->getOperand (1 ).isReg ())
1733
+ NextMI->getOperand (1 ).setReg (RISCV::NoRegister);
1734
+
1735
+ if (OldVLReg) {
1736
+ MachineInstr *VLOpDef = MRI->getUniqueVRegDef (OldVLReg);
1737
+ if (VLOpDef && TII->isAddImmediate (*VLOpDef, OldVLReg) &&
1738
+ MRI->use_nodbg_empty (OldVLReg)) {
1739
+ VLOpDef->eraseFromParent ();
1740
+ }
1741
+
1742
+ // NextMI no longer uses OldVLReg so shrink its LiveInterval.
1743
+ if (OldVLReg.isVirtual ())
1744
+ LIS.shrinkToUses (&LIS.getInterval (OldVLReg));
1745
+ }
1746
+
1747
+ MI.setDesc (NextMI->getDesc ());
1748
+ }
1749
+ MI.getOperand (2 ).setImm (NextMI->getOperand (2 ).getImm ());
1750
+ ToDelete.push_back (NextMI);
1751
+ // fallthrough
1752
+ }
1753
+ }
1754
+ NextMI = &MI;
1755
+ Used = getDemanded (MI, MRI, ST);
1756
+ }
1757
+
1758
+ Changed |= !ToDelete.empty ();
1759
+ NumCoalescedVSETVL += ToDelete.size ();
1760
+ for (auto *MI : ToDelete) {
1761
+ LIS.RemoveMachineInstrFromMaps (*MI);
1762
+ MI->eraseFromParent ();
1763
+ }
1764
+ }
1765
+
1766
+ return Changed;
1767
+ }
1768
+
1769
+ FunctionPass *llvm::createRISCVCoalesceVSETVLIPass () {
1770
+ return new RISCVCoalesceVSETVLI ();
1771
+ }
0 commit comments