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 ;
@@ -778,18 +786,52 @@ class RISCVInsertVSETVLI : public MachineFunctionPass {
778786 VSETVLIInfo &Info) const ;
779787 void computeIncomingVLVTYPE (const MachineBasicBlock &MBB);
780788 void emitVSETVLIs (MachineBasicBlock &MBB);
781- void doLocalPostpass (MachineBasicBlock &MBB);
782789 void doPRE (MachineBasicBlock &MBB);
783790 void insertReadVL (MachineBasicBlock &MBB);
784791};
785792
793+ class RISCVCoalesceVSETVLI : public MachineFunctionPass {
794+ public:
795+ static char ID;
796+ const RISCVSubtarget *ST;
797+ const TargetInstrInfo *TII;
798+ MachineRegisterInfo *MRI;
799+ LiveIntervals *LIS;
800+
801+ RISCVCoalesceVSETVLI () : MachineFunctionPass(ID) {}
802+ bool runOnMachineFunction (MachineFunction &MF) override ;
803+
804+ void getAnalysisUsage (AnalysisUsage &AU) const override {
805+ AU.setPreservesCFG ();
806+
807+ AU.addRequired <LiveIntervals>();
808+ AU.addPreserved <LiveIntervals>();
809+ AU.addRequired <SlotIndexes>();
810+ AU.addPreserved <SlotIndexes>();
811+ AU.addPreserved <LiveDebugVariables>();
812+ AU.addPreserved <LiveStacks>();
813+
814+ MachineFunctionPass::getAnalysisUsage (AU);
815+ }
816+
817+ StringRef getPassName () const override { return RISCV_COALESCE_VSETVLI_NAME; }
818+
819+ private:
820+ bool coalesceVSETVLIs (MachineBasicBlock &MBB);
821+ };
822+
786823} // end anonymous namespace
787824
788825char RISCVInsertVSETVLI::ID = 0 ;
789826
790827INITIALIZE_PASS (RISCVInsertVSETVLI, DEBUG_TYPE, RISCV_INSERT_VSETVLI_NAME,
791828 false , false )
792829
830+ char RISCVCoalesceVSETVLI::ID = 0;
831+
832+ INITIALIZE_PASS (RISCVCoalesceVSETVLI, " riscv-coalesce-vsetvli" ,
833+ RISCV_COALESCE_VSETVLI_NAME, false , false )
834+
793835// Return a VSETVLIInfo representing the changes made by this VSETVLI or
794836// VSETIVLI instruction.
795837static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) {
@@ -1511,12 +1553,12 @@ static bool canMutatePriorConfig(const MachineInstr &PrevMI,
15111553
15121554 auto &AVL = MI.getOperand (1 );
15131555 auto &PrevAVL = PrevMI.getOperand (1 );
1514- assert (MRI.isSSA ());
15151556
15161557 // If the AVL is a register, we need to make sure MI's AVL dominates PrevMI.
15171558 // For now just check that PrevMI uses the same virtual register.
15181559 if (AVL.isReg () && AVL.getReg () != RISCV::X0 &&
1519- (!PrevAVL.isReg () || PrevAVL.getReg () != AVL.getReg ()))
1560+ (!MRI.hasOneDef (AVL.getReg ()) || !PrevAVL.isReg () ||
1561+ PrevAVL.getReg () != AVL.getReg ()))
15201562 return false ;
15211563 }
15221564
@@ -1526,7 +1568,7 @@ static bool canMutatePriorConfig(const MachineInstr &PrevMI,
15261568 return areCompatibleVTYPEs (PriorVType, VType, Used);
15271569}
15281570
1529- void RISCVInsertVSETVLI::doLocalPostpass (MachineBasicBlock &MBB) {
1571+ bool RISCVCoalesceVSETVLI::coalesceVSETVLIs (MachineBasicBlock &MBB) {
15301572 MachineInstr *NextMI = nullptr ;
15311573 // We can have arbitrary code in successors, so VL and VTYPE
15321574 // must be considered demanded.
@@ -1558,20 +1600,49 @@ void RISCVInsertVSETVLI::doLocalPostpass(MachineBasicBlock &MBB) {
15581600
15591601 if (canMutatePriorConfig (MI, *NextMI, Used, *MRI)) {
15601602 if (!isVLPreservingConfig (*NextMI)) {
1561- MI.getOperand (0 ).setReg (NextMI->getOperand (0 ).getReg ());
1603+ Register DefReg = NextMI->getOperand (0 ).getReg ();
1604+
1605+ MI.getOperand (0 ).setReg (DefReg);
15621606 MI.getOperand (0 ).setIsDead (false );
1607+
1608+ // The def of DefReg moved to MI, so extend the LiveInterval up to
1609+ // it.
1610+ if (DefReg.isVirtual ()) {
1611+ LiveInterval &DefLI = LIS->getInterval (DefReg);
1612+ SlotIndex MISlot = LIS->getInstructionIndex (MI).getRegSlot ();
1613+ VNInfo *DefVNI = DefLI.getVNInfoAt (DefLI.beginIndex ());
1614+ LiveInterval::Segment S (MISlot, DefLI.beginIndex (), DefVNI);
1615+ DefLI.addSegment (S);
1616+ DefVNI->def = MISlot;
1617+ // Mark DefLI as spillable if it was previously unspillable
1618+ DefLI.setWeight (0 );
1619+
1620+ // DefReg may have had no uses, in which case we need to shrink
1621+ // the LiveInterval up to MI.
1622+ LIS->shrinkToUses (&DefLI);
1623+ }
1624+
15631625 Register OldVLReg;
15641626 if (MI.getOperand (1 ).isReg ())
15651627 OldVLReg = MI.getOperand (1 ).getReg ();
15661628 if (NextMI->getOperand (1 ).isImm ())
15671629 MI.getOperand (1 ).ChangeToImmediate (NextMI->getOperand (1 ).getImm ());
15681630 else
15691631 MI.getOperand (1 ).ChangeToRegister (NextMI->getOperand (1 ).getReg (), false );
1632+
1633+ // Clear NextMI's AVL early so we're not counting it as a use.
1634+ if (NextMI->getOperand (1 ).isReg ())
1635+ NextMI->getOperand (1 ).setReg (RISCV::NoRegister);
1636+
15701637 if (OldVLReg) {
15711638 MachineInstr *VLOpDef = MRI->getUniqueVRegDef (OldVLReg);
15721639 if (VLOpDef && TII->isAddImmediate (*VLOpDef, OldVLReg) &&
15731640 MRI->use_nodbg_empty (OldVLReg))
15741641 VLOpDef->eraseFromParent ();
1642+
1643+ // NextMI no longer uses OldVLReg so shrink its LiveInterval.
1644+ if (OldVLReg.isVirtual ())
1645+ LIS->shrinkToUses (&LIS->getInterval (OldVLReg));
15751646 }
15761647 MI.setDesc (NextMI->getDesc ());
15771648 }
@@ -1584,9 +1655,13 @@ void RISCVInsertVSETVLI::doLocalPostpass(MachineBasicBlock &MBB) {
15841655 Used = getDemanded (MI, MRI, ST);
15851656 }
15861657
1587- NumRemovedVSETVL += ToDelete.size ();
1588- for (auto *MI : ToDelete)
1658+ NumCoalescedVSETVL += ToDelete.size ();
1659+ for (auto *MI : ToDelete) {
1660+ LIS->RemoveMachineInstrFromMaps (*MI);
15891661 MI->eraseFromParent ();
1662+ }
1663+
1664+ return !ToDelete.empty ();
15901665}
15911666
15921667void RISCVInsertVSETVLI::insertReadVL (MachineBasicBlock &MBB) {
@@ -1661,15 +1736,6 @@ bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) {
16611736 for (MachineBasicBlock &MBB : MF)
16621737 emitVSETVLIs (MBB);
16631738
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-
16731739 // Insert PseudoReadVL after VLEFF/VLSEGFF and replace it with the vl output
16741740 // of VLEFF/VLSEGFF.
16751741 for (MachineBasicBlock &MBB : MF)
@@ -1683,3 +1749,29 @@ bool RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction &MF) {
16831749FunctionPass *llvm::createRISCVInsertVSETVLIPass () {
16841750 return new RISCVInsertVSETVLI ();
16851751}
1752+
1753+ // Now that all vsetvlis are explicit, go through and do block local
1754+ // DSE and peephole based demanded fields based transforms. Note that
1755+ // this *must* be done outside the main dataflow so long as we allow
1756+ // any cross block analysis within the dataflow. We can't have both
1757+ // demanded fields based mutation and non-local analysis in the
1758+ // dataflow at the same time without introducing inconsistencies.
1759+ bool RISCVCoalesceVSETVLI::runOnMachineFunction (MachineFunction &MF) {
1760+ // Skip if the vector extension is not enabled.
1761+ ST = &MF.getSubtarget <RISCVSubtarget>();
1762+ if (!ST->hasVInstructions ())
1763+ return false ;
1764+ TII = ST->getInstrInfo ();
1765+ MRI = &MF.getRegInfo ();
1766+ LIS = &getAnalysis<LiveIntervals>();
1767+
1768+ bool Changed = false ;
1769+ for (MachineBasicBlock &MBB : MF)
1770+ Changed |= coalesceVSETVLIs (MBB);
1771+
1772+ return Changed;
1773+ }
1774+
1775+ FunctionPass *llvm::createRISCVCoalesceVSETVLIPass () {
1776+ return new RISCVCoalesceVSETVLI ();
1777+ }
0 commit comments