@@ -30,6 +30,27 @@ using namespace llvm;
3030
3131namespace {
3232
33+ // / Wrapper around MachineOperand that defaults to immediate 0.
34+ struct DemandedVL {
35+ MachineOperand VL;
36+ DemandedVL () : VL(MachineOperand::CreateImm(0 )) {}
37+ DemandedVL (MachineOperand VL) : VL(VL) {}
38+ static DemandedVL vlmax () {
39+ return DemandedVL (MachineOperand::CreateImm (RISCV::VLMaxSentinel));
40+ }
41+ bool operator !=(const DemandedVL &Other) const {
42+ return !VL.isIdenticalTo (Other.VL );
43+ }
44+ };
45+
46+ static DemandedVL max (const DemandedVL &LHS, const DemandedVL &RHS) {
47+ if (RISCV::isVLKnownLE (LHS.VL , RHS.VL ))
48+ return RHS;
49+ if (RISCV::isVLKnownLE (RHS.VL , LHS.VL ))
50+ return LHS;
51+ return DemandedVL::vlmax ();
52+ }
53+
3354class RISCVVLOptimizer : public MachineFunctionPass {
3455 const MachineRegisterInfo *MRI;
3556 const MachineDominatorTree *MDT;
@@ -51,17 +72,26 @@ class RISCVVLOptimizer : public MachineFunctionPass {
5172 StringRef getPassName () const override { return PASS_NAME; }
5273
5374private:
54- std::optional<MachineOperand>
55- getMinimumVLForUser (const MachineOperand &UserOp) const ;
56- // / Returns the largest common VL MachineOperand that may be used to optimize
57- // / MI. Returns std::nullopt if it failed to find a suitable VL.
58- std::optional<MachineOperand> checkUsers (const MachineInstr &MI) const ;
75+ DemandedVL getMinimumVLForUser (const MachineOperand &UserOp) const ;
76+ // / Returns true if the users of \p MI have compatible EEWs and SEWs.
77+ bool checkUsers (const MachineInstr &MI) const ;
5978 bool tryReduceVL (MachineInstr &MI) const ;
6079 bool isCandidate (const MachineInstr &MI) const ;
80+ void transfer (const MachineInstr &MI);
81+
82+ // / Returns all uses of vector virtual registers.
83+ auto vector_uses (const MachineInstr &MI) const {
84+ auto Pred = [this ](const MachineOperand &MO) -> bool {
85+ return MO.isReg () && MO.getReg ().isVirtual () &&
86+ RISCVRegisterInfo::isRVVRegClass (MRI->getRegClass (MO.getReg ()));
87+ };
88+ return make_filter_range (MI.uses (), Pred);
89+ }
6190
6291 // / For a given instruction, records what elements of it are demanded by
6392 // / downstream users.
64- DenseMap<const MachineInstr *, std::optional<MachineOperand>> DemandedVLs;
93+ DenseMap<const MachineInstr *, DemandedVL> DemandedVLs;
94+ SetVector<const MachineInstr *> Worklist;
6595};
6696
6797// / Represents the EMUL and EEW of a MachineOperand.
@@ -821,6 +851,9 @@ getOperandInfo(const MachineOperand &MO, const MachineRegisterInfo *MRI) {
821851// / white-list approach simplifies this optimization for instructions that may
822852// / have more complex semantics with relation to how it uses VL.
823853static bool isSupportedInstr (const MachineInstr &MI) {
854+ if (MI.isPHI () || MI.isFullCopy ())
855+ return true ;
856+
824857 const RISCVVPseudosTable::PseudoInfo *RVV =
825858 RISCVVPseudosTable::getPseudoInfo (MI.getOpcode ());
826859
@@ -1321,21 +1354,24 @@ bool RISCVVLOptimizer::isCandidate(const MachineInstr &MI) const {
13211354 return true ;
13221355}
13231356
1324- std::optional<MachineOperand>
1357+ DemandedVL
13251358RISCVVLOptimizer::getMinimumVLForUser (const MachineOperand &UserOp) const {
13261359 const MachineInstr &UserMI = *UserOp.getParent ();
13271360 const MCInstrDesc &Desc = UserMI.getDesc ();
13281361
1362+ if (UserMI.isPHI () || UserMI.isFullCopy ())
1363+ return DemandedVLs.lookup (&UserMI);
1364+
13291365 if (!RISCVII::hasVLOp (Desc.TSFlags ) || !RISCVII::hasSEWOp (Desc.TSFlags )) {
13301366 LLVM_DEBUG (dbgs () << " Abort due to lack of VL, assume that"
13311367 " use VLMAX\n " );
1332- return std:: nullopt ;
1368+ return DemandedVL::vlmax () ;
13331369 }
13341370
13351371 if (RISCVII::readsPastVL (
13361372 TII->get (RISCV::getRVVMCOpcode (UserMI.getOpcode ())).TSFlags )) {
13371373 LLVM_DEBUG (dbgs () << " Abort because used by unsafe instruction\n " );
1338- return std:: nullopt ;
1374+ return DemandedVL::vlmax () ;
13391375 }
13401376
13411377 unsigned VLOpNum = RISCVII::getVLOpNum (Desc);
@@ -1349,11 +1385,10 @@ RISCVVLOptimizer::getMinimumVLForUser(const MachineOperand &UserOp) const {
13491385 if (UserOp.isTied ()) {
13501386 assert (UserOp.getOperandNo () == UserMI.getNumExplicitDefs () &&
13511387 RISCVII::isFirstDefTiedToFirstUse (UserMI.getDesc ()));
1352- auto DemandedVL = DemandedVLs.lookup (&UserMI);
1353- if (!DemandedVL || !RISCV::isVLKnownLE (*DemandedVL, VLOp)) {
1388+ if (!RISCV::isVLKnownLE (DemandedVLs.lookup (&UserMI).VL , VLOp)) {
13541389 LLVM_DEBUG (dbgs () << " Abort because user is passthru in "
13551390 " instruction with demanded tail\n " );
1356- return std:: nullopt ;
1391+ return DemandedVL::vlmax () ;
13571392 }
13581393 }
13591394
@@ -1366,18 +1401,16 @@ RISCVVLOptimizer::getMinimumVLForUser(const MachineOperand &UserOp) const {
13661401
13671402 // If we know the demanded VL of UserMI, then we can reduce the VL it
13681403 // requires.
1369- if (auto DemandedVL = DemandedVLs.lookup (&UserMI)) {
1370- assert (isCandidate (UserMI));
1371- if (RISCV::isVLKnownLE (*DemandedVL, VLOp))
1372- return DemandedVL;
1373- }
1404+ if (RISCV::isVLKnownLE (DemandedVLs.lookup (&UserMI).VL , VLOp))
1405+ return DemandedVLs.lookup (&UserMI);
13741406
13751407 return VLOp;
13761408}
13771409
1378- std::optional<MachineOperand>
1379- RISCVVLOptimizer::checkUsers (const MachineInstr &MI) const {
1380- std::optional<MachineOperand> CommonVL;
1410+ bool RISCVVLOptimizer::checkUsers (const MachineInstr &MI) const {
1411+ if (MI.isPHI () || MI.isFullCopy ())
1412+ return true ;
1413+
13811414 SmallSetVector<MachineOperand *, 8 > Worklist;
13821415 SmallPtrSet<const MachineInstr *, 4 > PHISeen;
13831416 for (auto &UserOp : MRI->use_operands (MI.getOperand (0 ).getReg ()))
@@ -1405,23 +1438,9 @@ RISCVVLOptimizer::checkUsers(const MachineInstr &MI) const {
14051438 continue ;
14061439 }
14071440
1408- auto VLOp = getMinimumVLForUser (UserOp);
1409- if (!VLOp)
1410- return std::nullopt ;
1411-
1412- // Use the largest VL among all the users. If we cannot determine this
1413- // statically, then we cannot optimize the VL.
1414- if (!CommonVL || RISCV::isVLKnownLE (*CommonVL, *VLOp)) {
1415- CommonVL = *VLOp;
1416- LLVM_DEBUG (dbgs () << " User VL is: " << VLOp << " \n " );
1417- } else if (!RISCV::isVLKnownLE (*VLOp, *CommonVL)) {
1418- LLVM_DEBUG (dbgs () << " Abort because cannot determine a common VL\n " );
1419- return std::nullopt ;
1420- }
1421-
14221441 if (!RISCVII::hasSEWOp (UserMI.getDesc ().TSFlags )) {
14231442 LLVM_DEBUG (dbgs () << " Abort due to lack of SEW operand\n " );
1424- return std:: nullopt ;
1443+ return false ;
14251444 }
14261445
14271446 std::optional<OperandInfo> ConsumerInfo = getOperandInfo (UserOp, MRI);
@@ -1431,7 +1450,7 @@ RISCVVLOptimizer::checkUsers(const MachineInstr &MI) const {
14311450 LLVM_DEBUG (dbgs () << " Abort due to unknown operand information.\n " );
14321451 LLVM_DEBUG (dbgs () << " ConsumerInfo is: " << ConsumerInfo << " \n " );
14331452 LLVM_DEBUG (dbgs () << " ProducerInfo is: " << ProducerInfo << " \n " );
1434- return std:: nullopt ;
1453+ return false ;
14351454 }
14361455
14371456 if (!OperandInfo::areCompatible (*ProducerInfo, *ConsumerInfo)) {
@@ -1440,11 +1459,11 @@ RISCVVLOptimizer::checkUsers(const MachineInstr &MI) const {
14401459 << " Abort due to incompatible information for EMUL or EEW.\n " );
14411460 LLVM_DEBUG (dbgs () << " ConsumerInfo is: " << ConsumerInfo << " \n " );
14421461 LLVM_DEBUG (dbgs () << " ProducerInfo is: " << ProducerInfo << " \n " );
1443- return std:: nullopt ;
1462+ return false ;
14441463 }
14451464 }
14461465
1447- return CommonVL ;
1466+ return true ;
14481467}
14491468
14501469bool RISCVVLOptimizer::tryReduceVL (MachineInstr &MI) const {
@@ -1460,9 +1479,7 @@ bool RISCVVLOptimizer::tryReduceVL(MachineInstr &MI) const {
14601479 return false ;
14611480 }
14621481
1463- auto CommonVL = DemandedVLs.lookup (&MI);
1464- if (!CommonVL)
1465- return false ;
1482+ auto *CommonVL = &DemandedVLs.at (&MI).VL ;
14661483
14671484 assert ((CommonVL->isImm () || CommonVL->getReg ().isVirtual ()) &&
14681485 " Expected VL to be an Imm or virtual Reg" );
@@ -1497,6 +1514,24 @@ bool RISCVVLOptimizer::tryReduceVL(MachineInstr &MI) const {
14971514 return true ;
14981515}
14991516
1517+ static bool isPhysical (const MachineOperand &MO) {
1518+ return MO.isReg () && MO.getReg ().isPhysical ();
1519+ }
1520+
1521+ // / Look through \p MI's operands and propagate what it demands to its uses.
1522+ void RISCVVLOptimizer::transfer (const MachineInstr &MI) {
1523+ if (!isSupportedInstr (MI) || !checkUsers (MI) || any_of (MI.defs (), isPhysical))
1524+ DemandedVLs[&MI] = DemandedVL::vlmax ();
1525+
1526+ for (const MachineOperand &MO : vector_uses (MI)) {
1527+ const MachineInstr *Def = MRI->getVRegDef (MO.getReg ());
1528+ DemandedVL Prev = DemandedVLs[Def];
1529+ DemandedVLs[Def] = max (DemandedVLs[Def], getMinimumVLForUser (MO));
1530+ if (DemandedVLs[Def] != Prev)
1531+ Worklist.insert (Def);
1532+ }
1533+ }
1534+
15001535bool RISCVVLOptimizer::runOnMachineFunction (MachineFunction &MF) {
15011536 if (skipFunction (MF.getFunction ()))
15021537 return false ;
@@ -1513,14 +1548,17 @@ bool RISCVVLOptimizer::runOnMachineFunction(MachineFunction &MF) {
15131548 assert (DemandedVLs.empty ());
15141549
15151550 // For each instruction that defines a vector, compute what VL its
1516- // downstream users demand.
1551+ // upstream uses demand.
15171552 for (MachineBasicBlock *MBB : post_order (&MF)) {
15181553 assert (MDT->isReachableFromEntry (MBB));
1519- for (MachineInstr &MI : reverse (*MBB)) {
1520- if (!isCandidate (MI))
1521- continue ;
1522- DemandedVLs.insert ({&MI, checkUsers (MI)});
1523- }
1554+ for (MachineInstr &MI : reverse (*MBB))
1555+ Worklist.insert (&MI);
1556+ }
1557+
1558+ while (!Worklist.empty ()) {
1559+ const MachineInstr *MI = Worklist.front ();
1560+ Worklist.remove (MI);
1561+ transfer (*MI);
15241562 }
15251563
15261564 // Then go through and see if we can reduce the VL of any instructions to
0 commit comments