27
27
#include " RISCV.h"
28
28
#include " RISCVSubtarget.h"
29
29
#include " llvm/ADT/Statistic.h"
30
+ #include " llvm/CodeGen/LiveDebugVariables.h"
30
31
#include " llvm/CodeGen/LiveIntervals.h"
32
+ #include " llvm/CodeGen/LiveStacks.h"
31
33
#include " llvm/CodeGen/MachineFunctionPass.h"
32
34
#include < queue>
33
35
using namespace llvm ;
34
36
35
37
#define DEBUG_TYPE " riscv-insert-vsetvli"
36
38
#define RISCV_INSERT_VSETVLI_NAME " RISC-V Insert VSETVLI pass"
39
+ #define RISCV_COALESCE_VSETVLI_NAME " RISC-V Coalesce VSETVLI pass"
37
40
38
41
STATISTIC (NumInsertedVSETVL, " Number of VSETVL inst inserted" );
39
- STATISTIC (NumRemovedVSETVL , " Number of VSETVL inst removed " );
42
+ STATISTIC (NumCoalescedVSETVL , " Number of VSETVL inst coalesced " );
40
43
41
44
static cl::opt<bool > DisableInsertVSETVLPHIOpt (
42
45
" riscv-disable-insert-vsetvl-phi-opt" , cl::init(false ), cl::Hidden,
@@ -190,6 +193,11 @@ static bool hasUndefinedMergeOp(const MachineInstr &MI,
190
193
if (UseMO.getReg () == RISCV::NoRegister)
191
194
return true ;
192
195
196
+ if (UseMO.isUndef ())
197
+ return true ;
198
+ if (UseMO.getReg ().isPhysical ())
199
+ return false ;
200
+
193
201
if (MachineInstr *UseMI = MRI.getVRegDef (UseMO.getReg ())) {
194
202
if (UseMI->isImplicitDef ())
195
203
return true ;
@@ -780,18 +788,52 @@ class RISCVInsertVSETVLI : public MachineFunctionPass {
780
788
VSETVLIInfo &Info) const ;
781
789
void computeIncomingVLVTYPE (const MachineBasicBlock &MBB);
782
790
void emitVSETVLIs (MachineBasicBlock &MBB);
783
- void doLocalPostpass (MachineBasicBlock &MBB);
784
791
void doPRE (MachineBasicBlock &MBB);
785
792
void insertReadVL (MachineBasicBlock &MBB);
786
793
};
787
794
795
+ class RISCVCoalesceVSETVLI : public MachineFunctionPass {
796
+ public:
797
+ static char ID;
798
+ const RISCVSubtarget *ST;
799
+ const TargetInstrInfo *TII;
800
+ MachineRegisterInfo *MRI;
801
+ LiveIntervals *LIS;
802
+
803
+ RISCVCoalesceVSETVLI () : MachineFunctionPass(ID) {}
804
+ bool runOnMachineFunction (MachineFunction &MF) override ;
805
+
806
+ void getAnalysisUsage (AnalysisUsage &AU) const override {
807
+ AU.setPreservesCFG ();
808
+
809
+ AU.addRequired <LiveIntervals>();
810
+ AU.addPreserved <LiveIntervals>();
811
+ AU.addRequired <SlotIndexes>();
812
+ AU.addPreserved <SlotIndexes>();
813
+ AU.addPreserved <LiveDebugVariables>();
814
+ AU.addPreserved <LiveStacks>();
815
+
816
+ MachineFunctionPass::getAnalysisUsage (AU);
817
+ }
818
+
819
+ StringRef getPassName () const override { return RISCV_COALESCE_VSETVLI_NAME; }
820
+
821
+ private:
822
+ bool coalesceVSETVLIs (MachineBasicBlock &MBB);
823
+ };
824
+
788
825
} // end anonymous namespace
789
826
790
827
char RISCVInsertVSETVLI::ID = 0 ;
791
828
792
829
INITIALIZE_PASS (RISCVInsertVSETVLI, DEBUG_TYPE, RISCV_INSERT_VSETVLI_NAME,
793
830
false , false )
794
831
832
+ char RISCVCoalesceVSETVLI::ID = 0;
833
+
834
+ INITIALIZE_PASS (RISCVCoalesceVSETVLI, " riscv-coalesce-vsetvli" ,
835
+ RISCV_COALESCE_VSETVLI_NAME, false , false )
836
+
795
837
// Return a VSETVLIInfo representing the changes made by this VSETVLI or
796
838
// VSETIVLI instruction.
797
839
static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) {
@@ -1515,12 +1557,12 @@ static bool canMutatePriorConfig(const MachineInstr &PrevMI,
1515
1557
1516
1558
auto &AVL = MI.getOperand (1 );
1517
1559
auto &PrevAVL = PrevMI.getOperand (1 );
1518
- assert (MRI.isSSA ());
1519
1560
1520
1561
// If the AVL is a register, we need to make sure MI's AVL dominates PrevMI.
1521
1562
// For now just check that PrevMI uses the same virtual register.
1522
1563
if (AVL.isReg () && AVL.getReg () != RISCV::X0 &&
1523
- (!PrevAVL.isReg () || PrevAVL.getReg () != AVL.getReg ()))
1564
+ (!MRI.hasOneDef (AVL.getReg ()) || !PrevAVL.isReg () ||
1565
+ PrevAVL.getReg () != AVL.getReg ()))
1524
1566
return false ;
1525
1567
}
1526
1568
@@ -1530,7 +1572,7 @@ static bool canMutatePriorConfig(const MachineInstr &PrevMI,
1530
1572
return areCompatibleVTYPEs (PriorVType, VType, Used);
1531
1573
}
1532
1574
1533
- void RISCVInsertVSETVLI::doLocalPostpass (MachineBasicBlock &MBB) {
1575
+ bool RISCVCoalesceVSETVLI::coalesceVSETVLIs (MachineBasicBlock &MBB) {
1534
1576
MachineInstr *NextMI = nullptr ;
1535
1577
// We can have arbitrary code in successors, so VL and VTYPE
1536
1578
// must be considered demanded.
@@ -1563,20 +1605,50 @@ void RISCVInsertVSETVLI::doLocalPostpass(MachineBasicBlock &MBB) {
1563
1605
1564
1606
if (canMutatePriorConfig (MI, *NextMI, Used, *MRI)) {
1565
1607
if (!isVLPreservingConfig (*NextMI)) {
1566
- MI.getOperand (0 ).setReg (NextMI->getOperand (0 ).getReg ());
1608
+ Register DefReg = NextMI->getOperand (0 ).getReg ();
1609
+
1610
+ MI.getOperand (0 ).setReg (DefReg);
1567
1611
MI.getOperand (0 ).setIsDead (false );
1612
+
1613
+ // The def of DefReg moved to MI, so extend the LiveInterval up to
1614
+ // it.
1615
+ if (DefReg.isVirtual ()) {
1616
+ LiveInterval &DefLI = LIS->getInterval (DefReg);
1617
+ SlotIndex MISlot = LIS->getInstructionIndex (MI).getRegSlot ();
1618
+ VNInfo *DefVNI = DefLI.getVNInfoAt (DefLI.beginIndex ());
1619
+ LiveInterval::Segment S (MISlot, DefLI.beginIndex (), DefVNI);
1620
+ DefLI.addSegment (S);
1621
+ DefVNI->def = MISlot;
1622
+ // Mark DefLI as spillable if it was previously unspillable
1623
+ DefLI.setWeight (0 );
1624
+
1625
+ // DefReg may have had no uses, in which case we need to shrink
1626
+ // the LiveInterval up to MI.
1627
+ LIS->shrinkToUses (&DefLI);
1628
+ }
1629
+
1568
1630
Register OldVLReg;
1569
1631
if (MI.getOperand (1 ).isReg ())
1570
1632
OldVLReg = MI.getOperand (1 ).getReg ();
1571
1633
if (NextMI->getOperand (1 ).isImm ())
1572
1634
MI.getOperand (1 ).ChangeToImmediate (NextMI->getOperand (1 ).getImm ());
1573
1635
else
1574
1636
MI.getOperand (1 ).ChangeToRegister (NextMI->getOperand (1 ).getReg (), false );
1575
- if (OldVLReg) {
1637
+
1638
+ // Clear NextMI's AVL early so we're not counting it as a use.
1639
+ if (NextMI->getOperand (1 ).isReg ())
1640
+ NextMI->getOperand (1 ).setReg (RISCV::NoRegister);
1641
+
1642
+ if (OldVLReg && OldVLReg.isVirtual ()) {
1643
+ // NextMI no longer uses OldVLReg so shrink its LiveInterval.
1644
+ LIS->shrinkToUses (&LIS->getInterval (OldVLReg));
1645
+
1576
1646
MachineInstr *VLOpDef = MRI->getUniqueVRegDef (OldVLReg);
1577
1647
if (VLOpDef && TII->isAddImmediate (*VLOpDef, OldVLReg) &&
1578
- MRI->use_nodbg_empty (OldVLReg))
1648
+ MRI->use_nodbg_empty (OldVLReg)) {
1579
1649
VLOpDef->eraseFromParent ();
1650
+ LIS->removeInterval (OldVLReg);
1651
+ }
1580
1652
}
1581
1653
MI.setDesc (NextMI->getDesc ());
1582
1654
}
@@ -1589,9 +1661,13 @@ void RISCVInsertVSETVLI::doLocalPostpass(MachineBasicBlock &MBB) {
1589
1661
Used = getDemanded (MI, MRI, ST);
1590
1662
}
1591
1663
1592
- NumRemovedVSETVL += ToDelete.size ();
1593
- for (auto *MI : ToDelete)
1664
+ NumCoalescedVSETVL += ToDelete.size ();
1665
+ for (auto *MI : ToDelete) {
1666
+ LIS->RemoveMachineInstrFromMaps (*MI);
1594
1667
MI->eraseFromParent ();
1668
+ }
1669
+
1670
+ return !ToDelete.empty ();
1595
1671
}
1596
1672
1597
1673
void RISCVInsertVSETVLI::insertReadVL (MachineBasicBlock &MBB) {
@@ -1666,15 +1742,6 @@ bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) {
1666
1742
for (MachineBasicBlock &MBB : MF)
1667
1743
emitVSETVLIs (MBB);
1668
1744
1669
- // Now that all vsetvlis are explicit, go through and do block local
1670
- // DSE and peephole based demanded fields based transforms. Note that
1671
- // this *must* be done outside the main dataflow so long as we allow
1672
- // any cross block analysis within the dataflow. We can't have both
1673
- // demanded fields based mutation and non-local analysis in the
1674
- // dataflow at the same time without introducing inconsistencies.
1675
- for (MachineBasicBlock &MBB : MF)
1676
- doLocalPostpass (MBB);
1677
-
1678
1745
// Insert PseudoReadVL after VLEFF/VLSEGFF and replace it with the vl output
1679
1746
// of VLEFF/VLSEGFF.
1680
1747
for (MachineBasicBlock &MBB : MF)
@@ -1688,3 +1755,29 @@ bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) {
1688
1755
FunctionPass *llvm::createRISCVInsertVSETVLIPass () {
1689
1756
return new RISCVInsertVSETVLI ();
1690
1757
}
1758
+
1759
+ // Now that all vsetvlis are explicit, go through and do block local
1760
+ // DSE and peephole based demanded fields based transforms. Note that
1761
+ // this *must* be done outside the main dataflow so long as we allow
1762
+ // any cross block analysis within the dataflow. We can't have both
1763
+ // demanded fields based mutation and non-local analysis in the
1764
+ // dataflow at the same time without introducing inconsistencies.
1765
+ bool RISCVCoalesceVSETVLI::runOnMachineFunction (MachineFunction &MF) {
1766
+ // Skip if the vector extension is not enabled.
1767
+ ST = &MF.getSubtarget <RISCVSubtarget>();
1768
+ if (!ST->hasVInstructions ())
1769
+ return false ;
1770
+ TII = ST->getInstrInfo ();
1771
+ MRI = &MF.getRegInfo ();
1772
+ LIS = &getAnalysis<LiveIntervals>();
1773
+
1774
+ bool Changed = false ;
1775
+ for (MachineBasicBlock &MBB : MF)
1776
+ Changed |= coalesceVSETVLIs (MBB);
1777
+
1778
+ return Changed;
1779
+ }
1780
+
1781
+ FunctionPass *llvm::createRISCVCoalesceVSETVLIPass () {
1782
+ return new RISCVCoalesceVSETVLI ();
1783
+ }
0 commit comments