@@ -65,6 +65,7 @@ class RISCVVectorPeephole : public MachineFunctionPass {
65
65
bool convertToWholeRegister (MachineInstr &MI) const ;
66
66
bool convertToUnmasked (MachineInstr &MI) const ;
67
67
bool convertVMergeToVMv (MachineInstr &MI) const ;
68
+ bool foldVMV_V_V (MachineInstr &MI);
68
69
69
70
bool isAllOnesMask (const MachineInstr *MaskDef) const ;
70
71
std::optional<unsigned > getConstant (const MachineOperand &VL) const ;
@@ -323,6 +324,143 @@ bool RISCVVectorPeephole::convertToUnmasked(MachineInstr &MI) const {
323
324
return true ;
324
325
}
325
326
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
+
326
464
bool RISCVVectorPeephole::runOnMachineFunction (MachineFunction &MF) {
327
465
if (skipFunction (MF.getFunction ()))
328
466
return false ;
@@ -357,11 +495,12 @@ bool RISCVVectorPeephole::runOnMachineFunction(MachineFunction &MF) {
357
495
}
358
496
359
497
for (MachineBasicBlock &MBB : MF) {
360
- for (MachineInstr &MI : MBB) {
498
+ for (MachineInstr &MI : make_early_inc_range ( MBB) ) {
361
499
Changed |= convertToVLMAX (MI);
362
500
Changed |= convertToUnmasked (MI);
363
501
Changed |= convertToWholeRegister (MI);
364
502
Changed |= convertVMergeToVMv (MI);
503
+ Changed |= foldVMV_V_V (MI);
365
504
}
366
505
}
367
506
0 commit comments