@@ -65,6 +65,7 @@ class RISCVVectorPeephole : public MachineFunctionPass {
6565 bool convertToWholeRegister (MachineInstr &MI) const ;
6666 bool convertToUnmasked (MachineInstr &MI) const ;
6767 bool convertVMergeToVMv (MachineInstr &MI) const ;
68+ bool foldVMV_V_V (MachineInstr &MI);
6869
6970 bool isAllOnesMask (const MachineInstr *MaskDef) const ;
7071 std::optional<unsigned > getConstant (const MachineOperand &VL) const ;
@@ -323,6 +324,143 @@ bool RISCVVectorPeephole::convertToUnmasked(MachineInstr &MI) const {
323324 return true ;
324325}
325326
327+ // / Given two VL operands, returns the one known to be the smallest or nullptr
328+ // / if unknown.
329+ static const MachineOperand *getKnownMinVL (const MachineOperand *LHS,
330+ const MachineOperand *RHS) {
331+ if (LHS->isReg () && RHS->isReg () && LHS->getReg ().isVirtual () &&
332+ LHS->getReg () == RHS->getReg ())
333+ return LHS;
334+ if (LHS->isImm () && LHS->getImm () == RISCV::VLMaxSentinel)
335+ return RHS;
336+ if (RHS->isImm () && RHS->getImm () == RISCV::VLMaxSentinel)
337+ return LHS;
338+ if (!LHS->isImm () || !RHS->isImm ())
339+ return nullptr ;
340+ return LHS->getImm () <= RHS->getImm () ? LHS : RHS;
341+ }
342+
343+ // / Check if it's safe to move From down to To, checking that no physical
344+ // / registers are clobbered.
345+ static bool isSafeToMove (const MachineInstr &From, const MachineInstr &To) {
346+ assert (From.getParent () == To.getParent () && !From.hasImplicitDef ());
347+ SmallVector<Register> PhysUses;
348+ for (const MachineOperand &MO : From.all_uses ())
349+ if (MO.getReg ().isPhysical ())
350+ PhysUses.push_back (MO.getReg ());
351+ bool SawStore = false ;
352+ for (auto II = From.getIterator (); II != To.getIterator (); II++) {
353+ for (Register PhysReg : PhysUses)
354+ if (II->definesRegister (PhysReg, nullptr ))
355+ return false ;
356+ if (II->mayStore ()) {
357+ SawStore = true ;
358+ break ;
359+ }
360+ }
361+ return From.isSafeToMove (nullptr , SawStore);
362+ }
363+
364+ static const RISCV::RISCVMaskedPseudoInfo *
365+ lookupMaskedPseudoInfo (const MachineInstr &MI) {
366+ const RISCV::RISCVMaskedPseudoInfo *Info =
367+ RISCV::lookupMaskedIntrinsicByUnmasked (MI.getOpcode ());
368+ if (!Info)
369+ Info = RISCV::getMaskedPseudoInfo (MI.getOpcode ());
370+ return Info;
371+ }
372+
373+ // / If a PseudoVMV_V_V is the only user of it's input, fold its passthru and VL
374+ // / into it.
375+ // /
376+ // / %x = PseudoVADD_V_V_M1 %passthru, %a, %b, %vl, sew, policy
377+ // / %y = PseudoVMV_V_V_M1 %passthru, %x, %vl, sew, policy
378+ // /
379+ // / ->
380+ // /
381+ // / %y = PseudoVADD_V_V_M1 %passthru, %a, %b, %vl, sew, policy
382+ bool RISCVVectorPeephole::foldVMV_V_V (MachineInstr &MI) {
383+ if (RISCV::getRVVMCOpcode (MI.getOpcode ()) != RISCV::VMV_V_V)
384+ return false ;
385+
386+ MachineOperand &Passthru = MI.getOperand (1 );
387+ MachineInstr *Src = MRI->getVRegDef (MI.getOperand (2 ).getReg ());
388+
389+ if (!MRI->hasOneUse (MI.getOperand (2 ).getReg ()))
390+ return false ;
391+
392+ if (!Src || Src->hasUnmodeledSideEffects () ||
393+ Src->getParent () != MI.getParent ())
394+ return false ;
395+
396+ // Src needs to be a pseudo that's opted into this transform.
397+ const RISCV::RISCVMaskedPseudoInfo *Info = lookupMaskedPseudoInfo (*Src);
398+ if (!Info)
399+ return false ;
400+
401+ assert (Src->getNumDefs () == 1 &&
402+ RISCVII::isFirstDefTiedToFirstUse (Src->getDesc ()) &&
403+ RISCVII::hasVLOp (Src->getDesc ().TSFlags ) &&
404+ RISCVII::hasVecPolicyOp (Src->getDesc ().TSFlags ));
405+
406+ // Src needs to have the same passthru as VMV_V_V
407+ if (Src->getOperand (1 ).getReg () != RISCV::NoRegister &&
408+ Src->getOperand (1 ).getReg () != Passthru.getReg ())
409+ return false ;
410+
411+ // Because Src and MI have the same passthru, we can use either AVL as long as
412+ // it's the smaller of the two.
413+ //
414+ // (src pt, ..., vl=5) x x x x x|. . .
415+ // (vmv.v.v pt, src, vl=3) x x x|. . . . .
416+ // ->
417+ // (src pt, ..., vl=3) x x x|. . . . .
418+ //
419+ // (src pt, ..., vl=3) x x x|. . . . .
420+ // (vmv.v.v pt, src, vl=6) x x x . . .|. .
421+ // ->
422+ // (src pt, ..., vl=3) x x x|. . . . .
423+ MachineOperand &SrcVL = Src->getOperand (RISCVII::getVLOpNum (Src->getDesc ()));
424+ const MachineOperand *MinVL = getKnownMinVL (&MI.getOperand (3 ), &SrcVL);
425+ if (!MinVL)
426+ return false ;
427+
428+ bool VLChanged = !MinVL->isIdenticalTo (SrcVL);
429+ bool RaisesFPExceptions = MI.getDesc ().mayRaiseFPException () &&
430+ !MI.getFlag (MachineInstr::MIFlag::NoFPExcept);
431+ if (VLChanged && (Info->ActiveElementsAffectResult || RaisesFPExceptions))
432+ return false ;
433+
434+ if (!isSafeToMove (*Src, MI))
435+ return false ;
436+
437+ // Move Src down to MI, then replace all uses of MI with it.
438+ Src->moveBefore (&MI);
439+
440+ Src->getOperand (1 ).setReg (Passthru.getReg ());
441+ // If Src is masked then its passthru needs to be in VRNoV0.
442+ if (Passthru.getReg () != RISCV::NoRegister)
443+ MRI->constrainRegClass (Passthru.getReg (),
444+ TII->getRegClass (Src->getDesc (), 1 , TRI,
445+ *Src->getParent ()->getParent ()));
446+
447+ if (MinVL->isImm ())
448+ SrcVL.ChangeToImmediate (MinVL->getImm ());
449+ else if (MinVL->isReg ())
450+ SrcVL.ChangeToRegister (MinVL->getReg (), false );
451+
452+ // Use a conservative tu,mu policy, RISCVInsertVSETVLI will relax it if
453+ // passthru is undef.
454+ Src->getOperand (RISCVII::getVecPolicyOpNum (Src->getDesc ()))
455+ .setImm (RISCVII::TAIL_UNDISTURBED_MASK_UNDISTURBED);
456+
457+ MRI->replaceRegWith (MI.getOperand (0 ).getReg (), Src->getOperand (0 ).getReg ());
458+ MI.eraseFromParent ();
459+ V0Defs.erase (&MI);
460+
461+ return true ;
462+ }
463+
326464bool RISCVVectorPeephole::runOnMachineFunction (MachineFunction &MF) {
327465 if (skipFunction (MF.getFunction ()))
328466 return false ;
@@ -357,11 +495,12 @@ bool RISCVVectorPeephole::runOnMachineFunction(MachineFunction &MF) {
357495 }
358496
359497 for (MachineBasicBlock &MBB : MF) {
360- for (MachineInstr &MI : MBB) {
498+ for (MachineInstr &MI : make_early_inc_range ( MBB) ) {
361499 Changed |= convertToVLMAX (MI);
362500 Changed |= convertToUnmasked (MI);
363501 Changed |= convertToWholeRegister (MI);
364502 Changed |= convertVMergeToVMv (MI);
503+ Changed |= foldVMV_V_V (MI);
365504 }
366505 }
367506
0 commit comments