@@ -62,6 +62,7 @@ class RISCVVectorPeephole : public MachineFunctionPass {
6262 bool convertToWholeRegister (MachineInstr &MI) const ;
6363 bool convertToUnmasked (MachineInstr &MI) const ;
6464 bool convertVMergeToVMv (MachineInstr &MI) const ;
65+ bool foldVMV_V_V (MachineInstr &MI);
6566
6667 bool isAllOnesMask (const MachineInstr *MaskDef) const ;
6768
@@ -297,6 +298,143 @@ bool RISCVVectorPeephole::convertToUnmasked(MachineInstr &MI) const {
297298 return true ;
298299}
299300
301+ // / Given two VL operands, returns the one known to be the smallest or nullptr
302+ // / if unknown.
303+ static const MachineOperand *getKnownMinVL (const MachineOperand *LHS,
304+ const MachineOperand *RHS) {
305+ if (LHS->isReg () && RHS->isReg () && LHS->getReg ().isVirtual () &&
306+ LHS->getReg () == RHS->getReg ())
307+ return LHS;
308+ if (LHS->isImm () && LHS->getImm () == RISCV::VLMaxSentinel)
309+ return RHS;
310+ if (RHS->isImm () && RHS->getImm () == RISCV::VLMaxSentinel)
311+ return LHS;
312+ if (!LHS->isImm () || !RHS->isImm ())
313+ return nullptr ;
314+ return LHS->getImm () <= RHS->getImm () ? LHS : RHS;
315+ }
316+
317+ // / Check if it's safe to move From down to To, checking that no physical
318+ // / registers are clobbered.
319+ static bool isSafeToMove (const MachineInstr &From, const MachineInstr &To) {
320+ assert (From.getParent () == To.getParent () && !From.hasImplicitDef ());
321+ SmallVector<Register> PhysUses;
322+ for (const MachineOperand &MO : From.all_uses ())
323+ if (MO.getReg ().isPhysical ())
324+ PhysUses.push_back (MO.getReg ());
325+ bool SawStore = false ;
326+ for (auto II = From.getIterator (); II != To.getIterator (); II++) {
327+ for (Register PhysReg : PhysUses)
328+ if (II->definesRegister (PhysReg, nullptr ))
329+ return false ;
330+ if (II->mayStore ()) {
331+ SawStore = true ;
332+ break ;
333+ }
334+ }
335+ return From.isSafeToMove (nullptr , SawStore);
336+ }
337+
338+ static const RISCV::RISCVMaskedPseudoInfo *
339+ lookupMaskedPseudoInfo (const MachineInstr &MI) {
340+ const RISCV::RISCVMaskedPseudoInfo *Info =
341+ RISCV::lookupMaskedIntrinsicByUnmasked (MI.getOpcode ());
342+ if (!Info)
343+ Info = RISCV::getMaskedPseudoInfo (MI.getOpcode ());
344+ return Info;
345+ }
346+
347+ // / If a PseudoVMV_V_V is the only user of it's input, fold its passthru and VL
348+ // / into it.
349+ // /
350+ // / %x = PseudoVADD_V_V_M1 %passthru, %a, %b, %vl, sew, policy
351+ // / %y = PseudoVMV_V_V_M1 %passthru, %x, %vl, sew, policy
352+ // /
353+ // / ->
354+ // /
355+ // / %y = PseudoVADD_V_V_M1 %passthru, %a, %b, %vl, sew, policy
356+ bool RISCVVectorPeephole::foldVMV_V_V (MachineInstr &MI) {
357+ if (RISCV::getRVVMCOpcode (MI.getOpcode ()) != RISCV::VMV_V_V)
358+ return false ;
359+
360+ MachineOperand &Passthru = MI.getOperand (1 );
361+ MachineInstr *Src = MRI->getVRegDef (MI.getOperand (2 ).getReg ());
362+
363+ if (!MRI->hasOneUse (MI.getOperand (2 ).getReg ()))
364+ return false ;
365+
366+ if (!Src || Src->hasUnmodeledSideEffects () ||
367+ Src->getParent () != MI.getParent ())
368+ return false ;
369+
370+ // Src needs to be a pseudo that's opted into this transform.
371+ const RISCV::RISCVMaskedPseudoInfo *Info = lookupMaskedPseudoInfo (*Src);
372+ if (!Info)
373+ return false ;
374+
375+ assert (Src->getNumDefs () == 1 &&
376+ RISCVII::isFirstDefTiedToFirstUse (Src->getDesc ()) &&
377+ RISCVII::hasVLOp (Src->getDesc ().TSFlags ) &&
378+ RISCVII::hasVecPolicyOp (Src->getDesc ().TSFlags ));
379+
380+ // Src needs to have the same passthru as VMV_V_V
381+ if (Src->getOperand (1 ).getReg () != RISCV::NoRegister &&
382+ Src->getOperand (1 ).getReg () != Passthru.getReg ())
383+ return false ;
384+
385+ // Because Src and MI have the same passthru, we can use either AVL as long as
386+ // it's the smaller of the two.
387+ //
388+ // (src pt, ..., vl=5) x x x x x|. . .
389+ // (vmv.v.v pt, src, vl=3) x x x|. . . . .
390+ // ->
391+ // (src pt, ..., vl=3) x x x|. . . . .
392+ //
393+ // (src pt, ..., vl=3) x x x|. . . . .
394+ // (vmv.v.v pt, src, vl=6) x x x . . .|. .
395+ // ->
396+ // (src pt, ..., vl=3) x x x|. . . . .
397+ MachineOperand &SrcVL = Src->getOperand (RISCVII::getVLOpNum (Src->getDesc ()));
398+ const MachineOperand *MinVL = getKnownMinVL (&MI.getOperand (3 ), &SrcVL);
399+ if (!MinVL)
400+ return false ;
401+
402+ bool VLChanged = !MinVL->isIdenticalTo (SrcVL);
403+ bool RaisesFPExceptions = MI.getDesc ().mayRaiseFPException () &&
404+ !MI.getFlag (MachineInstr::MIFlag::NoFPExcept);
405+ if (VLChanged && (Info->ActiveElementsAffectResult || RaisesFPExceptions))
406+ return false ;
407+
408+ if (!isSafeToMove (*Src, MI))
409+ return false ;
410+
411+ // Move Src down to MI, then replace all uses of MI with it.
412+ Src->moveBefore (&MI);
413+
414+ Src->getOperand (1 ).setReg (Passthru.getReg ());
415+ // If Src is masked then its passthru needs to be in VRNoV0.
416+ if (Passthru.getReg () != RISCV::NoRegister)
417+ MRI->constrainRegClass (Passthru.getReg (),
418+ TII->getRegClass (Src->getDesc (), 1 , TRI,
419+ *Src->getParent ()->getParent ()));
420+
421+ if (MinVL->isImm ())
422+ SrcVL.ChangeToImmediate (MinVL->getImm ());
423+ else if (MinVL->isReg ())
424+ SrcVL.ChangeToRegister (MinVL->getReg (), false );
425+
426+ // Use a conservative tu,mu policy, RISCVInsertVSETVLI will relax it if
427+ // passthru is undef.
428+ Src->getOperand (RISCVII::getVecPolicyOpNum (Src->getDesc ()))
429+ .setImm (RISCVII::TAIL_UNDISTURBED_MASK_UNDISTURBED);
430+
431+ MRI->replaceRegWith (MI.getOperand (0 ).getReg (), Src->getOperand (0 ).getReg ());
432+ MI.eraseFromParent ();
433+ V0Defs.erase (&MI);
434+
435+ return true ;
436+ }
437+
300438bool RISCVVectorPeephole::runOnMachineFunction (MachineFunction &MF) {
301439 if (skipFunction (MF.getFunction ()))
302440 return false ;
@@ -331,11 +469,12 @@ bool RISCVVectorPeephole::runOnMachineFunction(MachineFunction &MF) {
331469 }
332470
333471 for (MachineBasicBlock &MBB : MF) {
334- for (MachineInstr &MI : MBB) {
472+ for (MachineInstr &MI : make_early_inc_range ( MBB) ) {
335473 Changed |= convertToVLMAX (MI);
336474 Changed |= convertToUnmasked (MI);
337475 Changed |= convertToWholeRegister (MI);
338476 Changed |= convertVMergeToVMv (MI);
477+ Changed |= foldVMV_V_V (MI);
339478 }
340479 }
341480
0 commit comments