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