1818
1919#include " RISCV.h"
2020#include " RISCVSubtarget.h"
21- #include " llvm/ADT/SetVector .h"
21+ #include " llvm/ADT/PostOrderIterator .h"
2222#include " llvm/CodeGen/MachineDominators.h"
2323#include " llvm/CodeGen/MachineFunctionPass.h"
2424#include " llvm/InitializePasses.h"
@@ -56,6 +56,10 @@ class RISCVVLOptimizer : public MachineFunctionPass {
5656 std::optional<MachineOperand> checkUsers (MachineInstr &MI);
5757 bool tryReduceVL (MachineInstr &MI);
5858 bool isCandidate (const MachineInstr &MI) const ;
59+
60+ // / For a given instruction, records what elements of it are demanded by
61+ // / downstream users.
62+ DenseMap<const MachineInstr *, std::optional<MachineOperand>> DemandedVLs;
5963};
6064
6165} // end anonymous namespace
@@ -1201,14 +1205,19 @@ RISCVVLOptimizer::getMinimumVLForUser(MachineOperand &UserOp) {
12011205 // Looking for an immediate or a register VL that isn't X0.
12021206 assert ((!VLOp.isReg () || VLOp.getReg () != RISCV::X0) &&
12031207 " Did not expect X0 VL" );
1208+
1209+ // If we know the demanded VL of UserMI, then we can reduce the VL it
1210+ // requires.
1211+ if (auto DemandedVL = DemandedVLs[&UserMI]) {
1212+ assert (isCandidate (UserMI));
1213+ if (RISCV::isVLKnownLE (*DemandedVL, VLOp))
1214+ return DemandedVL;
1215+ }
1216+
12041217 return VLOp;
12051218}
12061219
12071220std::optional<MachineOperand> RISCVVLOptimizer::checkUsers (MachineInstr &MI) {
1208- // FIXME: Avoid visiting each user for each time we visit something on the
1209- // worklist, combined with an extra visit from the outer loop. Restructure
1210- // along lines of an instcombine style worklist which integrates the outer
1211- // pass.
12121221 std::optional<MachineOperand> CommonVL;
12131222 for (auto &UserOp : MRI->use_operands (MI.getOperand (0 ).getReg ())) {
12141223 const MachineInstr &UserMI = *UserOp.getParent ();
@@ -1285,7 +1294,7 @@ bool RISCVVLOptimizer::tryReduceVL(MachineInstr &MI) {
12851294 return false ;
12861295 }
12871296
1288- auto CommonVL = checkUsers (MI) ;
1297+ auto CommonVL = DemandedVLs[&MI] ;
12891298 if (!CommonVL)
12901299 return false ;
12911300
@@ -1333,29 +1342,19 @@ bool RISCVVLOptimizer::runOnMachineFunction(MachineFunction &MF) {
13331342 if (!ST.hasVInstructions ())
13341343 return false ;
13351344
1336- SetVector<MachineInstr *> Worklist;
1337- auto PushOperands = [this , &Worklist](MachineInstr &MI,
1338- bool IgnoreSameBlock) {
1339- for (auto &Op : MI.operands ()) {
1340- if (!Op.isReg () || !Op.isUse () || !Op.getReg ().isVirtual () ||
1341- !isVectorRegClass (Op.getReg (), MRI))
1342- continue ;
1343-
1344- MachineInstr *DefMI = MRI->getVRegDef (Op.getReg ());
1345- if (!isCandidate (*DefMI))
1346- continue ;
1347-
1348- if (IgnoreSameBlock && DefMI->getParent () == MI.getParent ())
1345+ // For each instruction that defines a vector, compute what VL its
1346+ // downstream users demand.
1347+ for (MachineBasicBlock *MBB : post_order (&MF)) {
1348+ assert (MDT->isReachableFromEntry (MBB));
1349+ for (MachineInstr &MI : reverse (*MBB)) {
1350+ if (!isCandidate (MI))
13491351 continue ;
1350-
1351- Worklist.insert (DefMI);
1352+ DemandedVLs.insert ({&MI, checkUsers (MI)});
13521353 }
1353- };
1354+ }
13541355
1355- // Do a first pass eagerly rewriting in roughly reverse instruction
1356- // order, populate the worklist with any instructions we might need to
1357- // revisit. We avoid adding definitions to the worklist if they're
1358- // in the same block - we're about to visit them anyways.
1356+ // Then go through and see if we can reduce the VL of any instructions to
1357+ // only what's demanded.
13591358 bool MadeChange = false ;
13601359 for (MachineBasicBlock &MBB : MF) {
13611360 // Avoid unreachable blocks as they have degenerate dominance
@@ -1368,18 +1367,8 @@ bool RISCVVLOptimizer::runOnMachineFunction(MachineFunction &MF) {
13681367 if (!tryReduceVL (MI))
13691368 continue ;
13701369 MadeChange = true ;
1371- PushOperands (MI, /* IgnoreSameBlock*/ true );
13721370 }
13731371 }
13741372
1375- while (!Worklist.empty ()) {
1376- assert (MadeChange);
1377- MachineInstr &MI = *Worklist.pop_back_val ();
1378- assert (isCandidate (MI));
1379- if (!tryReduceVL (MI))
1380- continue ;
1381- PushOperands (MI, /* IgnoreSameBlock*/ false );
1382- }
1383-
13841373 return MadeChange;
13851374}
0 commit comments