2727#include " RISCV.h"
2828#include " RISCVSubtarget.h"
2929#include " llvm/ADT/Statistic.h"
30+ #include " llvm/CodeGen/LiveDebugVariables.h"
3031#include " llvm/CodeGen/LiveIntervals.h"
32+ #include " llvm/CodeGen/LiveStacks.h"
3133#include " llvm/CodeGen/MachineFunctionPass.h"
3234#include < queue>
3335using namespace llvm ;
3436
3537#define DEBUG_TYPE " riscv-insert-vsetvli"
3638#define RISCV_INSERT_VSETVLI_NAME " RISC-V Insert VSETVLI pass"
39+ #define RISCV_COALESCE_VSETVLI_NAME " RISC-V Coalesce VSETVLI pass"
3740
3841STATISTIC (NumInsertedVSETVL, " Number of VSETVL inst inserted" );
39- STATISTIC (NumRemovedVSETVL , " Number of VSETVL inst removed " );
42+ STATISTIC (NumCoalescedVSETVL , " Number of VSETVL inst coalesced " );
4043
4144static cl::opt<bool > DisableInsertVSETVLPHIOpt (
4245 " riscv-disable-insert-vsetvl-phi-opt" , cl::init(false ), cl::Hidden,
@@ -190,6 +193,11 @@ static bool hasUndefinedMergeOp(const MachineInstr &MI,
190193 if (UseMO.getReg () == RISCV::NoRegister)
191194 return true ;
192195
196+ if (UseMO.isUndef ())
197+ return true ;
198+ if (UseMO.getReg ().isPhysical ())
199+ return false ;
200+
193201 if (MachineInstr *UseMI = MRI.getVRegDef (UseMO.getReg ())) {
194202 if (UseMI->isImplicitDef ())
195203 return true ;
@@ -780,18 +788,52 @@ class RISCVInsertVSETVLI : public MachineFunctionPass {
780788 VSETVLIInfo &Info) const ;
781789 void computeIncomingVLVTYPE (const MachineBasicBlock &MBB);
782790 void emitVSETVLIs (MachineBasicBlock &MBB);
783- void doLocalPostpass (MachineBasicBlock &MBB);
784791 void doPRE (MachineBasicBlock &MBB);
785792 void insertReadVL (MachineBasicBlock &MBB);
786793};
787794
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+
788825} // end anonymous namespace
789826
790827char RISCVInsertVSETVLI::ID = 0 ;
791828
792829INITIALIZE_PASS (RISCVInsertVSETVLI, DEBUG_TYPE, RISCV_INSERT_VSETVLI_NAME,
793830 false , false )
794831
832+ char RISCVCoalesceVSETVLI::ID = 0;
833+
834+ INITIALIZE_PASS (RISCVCoalesceVSETVLI, " riscv-coalesce-vsetvli" ,
835+ RISCV_COALESCE_VSETVLI_NAME, false , false )
836+
795837// Return a VSETVLIInfo representing the changes made by this VSETVLI or
796838// VSETIVLI instruction.
797839static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) {
@@ -1515,12 +1557,12 @@ static bool canMutatePriorConfig(const MachineInstr &PrevMI,
15151557
15161558 auto &AVL = MI.getOperand (1 );
15171559 auto &PrevAVL = PrevMI.getOperand (1 );
1518- assert (MRI.isSSA ());
15191560
15201561 // If the AVL is a register, we need to make sure MI's AVL dominates PrevMI.
15211562 // For now just check that PrevMI uses the same virtual register.
15221563 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 ()))
15241566 return false ;
15251567 }
15261568
@@ -1530,7 +1572,7 @@ static bool canMutatePriorConfig(const MachineInstr &PrevMI,
15301572 return areCompatibleVTYPEs (PriorVType, VType, Used);
15311573}
15321574
1533- void RISCVInsertVSETVLI::doLocalPostpass (MachineBasicBlock &MBB) {
1575+ bool RISCVCoalesceVSETVLI::coalesceVSETVLIs (MachineBasicBlock &MBB) {
15341576 MachineInstr *NextMI = nullptr ;
15351577 // We can have arbitrary code in successors, so VL and VTYPE
15361578 // must be considered demanded.
@@ -1563,20 +1605,50 @@ void RISCVInsertVSETVLI::doLocalPostpass(MachineBasicBlock &MBB) {
15631605
15641606 if (canMutatePriorConfig (MI, *NextMI, Used, *MRI)) {
15651607 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);
15671611 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+
15681630 Register OldVLReg;
15691631 if (MI.getOperand (1 ).isReg ())
15701632 OldVLReg = MI.getOperand (1 ).getReg ();
15711633 if (NextMI->getOperand (1 ).isImm ())
15721634 MI.getOperand (1 ).ChangeToImmediate (NextMI->getOperand (1 ).getImm ());
15731635 else
15741636 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+
15761646 MachineInstr *VLOpDef = MRI->getUniqueVRegDef (OldVLReg);
15771647 if (VLOpDef && TII->isAddImmediate (*VLOpDef, OldVLReg) &&
1578- MRI->use_nodbg_empty (OldVLReg))
1648+ MRI->use_nodbg_empty (OldVLReg)) {
15791649 VLOpDef->eraseFromParent ();
1650+ LIS->removeInterval (OldVLReg);
1651+ }
15801652 }
15811653 MI.setDesc (NextMI->getDesc ());
15821654 }
@@ -1589,9 +1661,13 @@ void RISCVInsertVSETVLI::doLocalPostpass(MachineBasicBlock &MBB) {
15891661 Used = getDemanded (MI, MRI, ST);
15901662 }
15911663
1592- NumRemovedVSETVL += ToDelete.size ();
1593- for (auto *MI : ToDelete)
1664+ NumCoalescedVSETVL += ToDelete.size ();
1665+ for (auto *MI : ToDelete) {
1666+ LIS->RemoveMachineInstrFromMaps (*MI);
15941667 MI->eraseFromParent ();
1668+ }
1669+
1670+ return !ToDelete.empty ();
15951671}
15961672
15971673void RISCVInsertVSETVLI::insertReadVL (MachineBasicBlock &MBB) {
@@ -1666,15 +1742,6 @@ bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) {
16661742 for (MachineBasicBlock &MBB : MF)
16671743 emitVSETVLIs (MBB);
16681744
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-
16781745 // Insert PseudoReadVL after VLEFF/VLSEGFF and replace it with the vl output
16791746 // of VLEFF/VLSEGFF.
16801747 for (MachineBasicBlock &MBB : MF)
@@ -1688,3 +1755,29 @@ bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) {
16881755FunctionPass *llvm::createRISCVInsertVSETVLIPass () {
16891756 return new RISCVInsertVSETVLI ();
16901757}
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