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 ;
@@ -778,18 +785,51 @@ class RISCVInsertVSETVLI : public MachineFunctionPass {
778
785
VSETVLIInfo &Info) const ;
779
786
void computeIncomingVLVTYPE (const MachineBasicBlock &MBB);
780
787
void emitVSETVLIs (MachineBasicBlock &MBB);
781
- void doLocalPostpass (MachineBasicBlock &MBB);
782
788
void doPRE (MachineBasicBlock &MBB);
783
789
void insertReadVL (MachineBasicBlock &MBB);
784
790
};
785
791
792
+ class RISCVCoalesceVSETVLI : public MachineFunctionPass {
793
+ public:
794
+ static char ID;
795
+ const RISCVSubtarget *ST;
796
+ const TargetInstrInfo *TII;
797
+ MachineRegisterInfo *MRI;
798
+ LiveIntervals *LIS;
799
+
800
+ RISCVCoalesceVSETVLI () : MachineFunctionPass(ID) {}
801
+ bool runOnMachineFunction (MachineFunction &MF) override ;
802
+
803
+ void getAnalysisUsage (AnalysisUsage &AU) const override {
804
+ AU.setPreservesCFG ();
805
+
806
+ AU.addRequired <LiveIntervals>();
807
+ AU.addPreserved <LiveIntervals>();
808
+ AU.addRequired <SlotIndexes>();
809
+ AU.addPreserved <SlotIndexes>();
810
+ AU.addPreserved <LiveStacks>();
811
+
812
+ MachineFunctionPass::getAnalysisUsage (AU);
813
+ }
814
+
815
+ StringRef getPassName () const override { return RISCV_COALESCE_VSETVLI_NAME; }
816
+
817
+ private:
818
+ bool runOnBasicBlock (MachineBasicBlock &MF);
819
+ };
820
+
786
821
} // end anonymous namespace
787
822
788
823
char RISCVInsertVSETVLI::ID = 0 ;
789
824
790
825
INITIALIZE_PASS (RISCVInsertVSETVLI, DEBUG_TYPE, RISCV_INSERT_VSETVLI_NAME,
791
826
false , false )
792
827
828
+ char RISCVCoalesceVSETVLI::ID = 0;
829
+
830
+ INITIALIZE_PASS (RISCVCoalesceVSETVLI, " riscv-coalesce-vsetvli" ,
831
+ RISCV_COALESCE_VSETVLI_NAME, false , false )
832
+
793
833
// Return a VSETVLIInfo representing the changes made by this VSETVLI or
794
834
// VSETIVLI instruction.
795
835
static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) {
@@ -1511,7 +1551,10 @@ static bool canMutatePriorConfig(const MachineInstr &PrevMI,
1511
1551
1512
1552
auto &AVL = MI.getOperand (1 );
1513
1553
auto &PrevAVL = PrevMI.getOperand (1 );
1514
- assert (MRI.isSSA ());
1554
+ assert (!AVL.isReg () || !AVL.getReg ().isVirtual () ||
1555
+ MRI.hasOneDef (AVL.getReg ()));
1556
+ assert (!PrevAVL.isReg () || !PrevAVL.getReg ().isVirtual () ||
1557
+ MRI.hasOneDef (PrevAVL.getReg ()));
1515
1558
1516
1559
// If the AVL is a register, we need to make sure MI's AVL dominates PrevMI.
1517
1560
// For now just check that PrevMI uses the same virtual register.
@@ -1526,7 +1569,7 @@ static bool canMutatePriorConfig(const MachineInstr &PrevMI,
1526
1569
return areCompatibleVTYPEs (PriorVType, VType, Used);
1527
1570
}
1528
1571
1529
- void RISCVInsertVSETVLI::doLocalPostpass (MachineBasicBlock &MBB) {
1572
+ bool RISCVCoalesceVSETVLI::runOnBasicBlock (MachineBasicBlock &MBB) {
1530
1573
MachineInstr *NextMI = nullptr ;
1531
1574
// We can have arbitrary code in successors, so VL and VTYPE
1532
1575
// must be considered demanded.
@@ -1558,20 +1601,47 @@ void RISCVInsertVSETVLI::doLocalPostpass(MachineBasicBlock &MBB) {
1558
1601
1559
1602
if (canMutatePriorConfig (MI, *NextMI, Used, *MRI)) {
1560
1603
if (!isVLPreservingConfig (*NextMI)) {
1561
- MI.getOperand (0 ).setReg (NextMI->getOperand (0 ).getReg ());
1604
+ Register DefReg = NextMI->getOperand (0 ).getReg ();
1605
+
1606
+ MI.getOperand (0 ).setReg (DefReg);
1562
1607
MI.getOperand (0 ).setIsDead (false );
1608
+
1609
+ // The def of DefReg moved to MI, so extend the LiveInterval up to
1610
+ // it.
1611
+ if (DefReg.isVirtual ()) {
1612
+ LiveInterval &DefLI = LIS->getInterval (DefReg);
1613
+ SlotIndex MISlot = LIS->getInstructionIndex (MI).getRegSlot ();
1614
+ VNInfo *DefVNI = DefLI.getVNInfoAt (DefLI.beginIndex ());
1615
+ LiveInterval::Segment S (MISlot, DefLI.beginIndex (), DefVNI);
1616
+ DefLI.addSegment (S);
1617
+ DefVNI->def = MISlot;
1618
+
1619
+ // DefReg may have had no uses, in which case we need to shrink
1620
+ // the LiveInterval up to MI.
1621
+ LIS->shrinkToUses (&DefLI);
1622
+ }
1623
+
1563
1624
Register OldVLReg;
1564
1625
if (MI.getOperand (1 ).isReg ())
1565
1626
OldVLReg = MI.getOperand (1 ).getReg ();
1566
1627
if (NextMI->getOperand (1 ).isImm ())
1567
1628
MI.getOperand (1 ).ChangeToImmediate (NextMI->getOperand (1 ).getImm ());
1568
1629
else
1569
1630
MI.getOperand (1 ).ChangeToRegister (NextMI->getOperand (1 ).getReg (), false );
1631
+
1632
+ // Clear NextMI's AVL early so we're not counting it as a use.
1633
+ if (NextMI->getOperand (1 ).isReg ())
1634
+ NextMI->getOperand (1 ).setReg (RISCV::NoRegister);
1635
+
1570
1636
if (OldVLReg) {
1571
1637
MachineInstr *VLOpDef = MRI->getUniqueVRegDef (OldVLReg);
1572
1638
if (VLOpDef && TII->isAddImmediate (*VLOpDef, OldVLReg) &&
1573
1639
MRI->use_nodbg_empty (OldVLReg))
1574
1640
VLOpDef->eraseFromParent ();
1641
+
1642
+ // NextMI no longer uses OldVLReg so shrink its LiveInterval.
1643
+ if (OldVLReg.isVirtual ())
1644
+ LIS->shrinkToUses (&LIS->getInterval (OldVLReg));
1575
1645
}
1576
1646
MI.setDesc (NextMI->getDesc ());
1577
1647
}
@@ -1584,9 +1654,13 @@ void RISCVInsertVSETVLI::doLocalPostpass(MachineBasicBlock &MBB) {
1584
1654
Used = getDemanded (MI, MRI, ST);
1585
1655
}
1586
1656
1587
- NumRemovedVSETVL += ToDelete.size ();
1588
- for (auto *MI : ToDelete)
1657
+ NumCoalescedVSETVL += ToDelete.size ();
1658
+ for (auto *MI : ToDelete) {
1659
+ LIS->RemoveMachineInstrFromMaps (*MI);
1589
1660
MI->eraseFromParent ();
1661
+ }
1662
+
1663
+ return !ToDelete.empty ();
1590
1664
}
1591
1665
1592
1666
void RISCVInsertVSETVLI::insertReadVL (MachineBasicBlock &MBB) {
@@ -1661,15 +1735,6 @@ bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) {
1661
1735
for (MachineBasicBlock &MBB : MF)
1662
1736
emitVSETVLIs (MBB);
1663
1737
1664
- // Now that all vsetvlis are explicit, go through and do block local
1665
- // DSE and peephole based demanded fields based transforms. Note that
1666
- // this *must* be done outside the main dataflow so long as we allow
1667
- // any cross block analysis within the dataflow. We can't have both
1668
- // demanded fields based mutation and non-local analysis in the
1669
- // dataflow at the same time without introducing inconsistencies.
1670
- for (MachineBasicBlock &MBB : MF)
1671
- doLocalPostpass (MBB);
1672
-
1673
1738
// Insert PseudoReadVL after VLEFF/VLSEGFF and replace it with the vl output
1674
1739
// of VLEFF/VLSEGFF.
1675
1740
for (MachineBasicBlock &MBB : MF)
@@ -1683,3 +1748,29 @@ bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) {
1683
1748
FunctionPass *llvm::createRISCVInsertVSETVLIPass () {
1684
1749
return new RISCVInsertVSETVLI ();
1685
1750
}
1751
+
1752
+ // Now that all vsetvlis are explicit, go through and do block local
1753
+ // DSE and peephole based demanded fields based transforms. Note that
1754
+ // this *must* be done outside the main dataflow so long as we allow
1755
+ // any cross block analysis within the dataflow. We can't have both
1756
+ // demanded fields based mutation and non-local analysis in the
1757
+ // dataflow at the same time without introducing inconsistencies.
1758
+ bool RISCVCoalesceVSETVLI::runOnMachineFunction (MachineFunction &MF) {
1759
+ // Skip if the vector extension is not enabled.
1760
+ ST = &MF.getSubtarget <RISCVSubtarget>();
1761
+ if (!ST->hasVInstructions ())
1762
+ return false ;
1763
+ TII = ST->getInstrInfo ();
1764
+ MRI = &MF.getRegInfo ();
1765
+ LIS = &getAnalysis<LiveIntervals>();
1766
+
1767
+ bool Changed = false ;
1768
+ for (MachineBasicBlock &MBB : MF)
1769
+ Changed |= runOnBasicBlock (MBB);
1770
+
1771
+ return Changed;
1772
+ }
1773
+
1774
+ FunctionPass *llvm::createRISCVCoalesceVSETVLIPass () {
1775
+ return new RISCVCoalesceVSETVLI ();
1776
+ }
0 commit comments