@@ -3458,19 +3458,27 @@ static unsigned GetVMSetForLMul(RISCVII::VLMUL LMUL) {
3458
3458
llvm_unreachable (" Unknown VLMUL enum" );
3459
3459
}
3460
3460
3461
- // Try to fold away VMERGE_VVM instructions. We handle these cases:
3462
- // -Masked TU VMERGE_VVM combined with an unmasked TA instruction instruction
3463
- // folds to a masked TU instruction. VMERGE_VVM must have have merge operand
3464
- // same as false operand.
3465
- // -Masked TA VMERGE_VVM combined with an unmasked TA instruction fold to a
3466
- // masked TA instruction.
3467
- // -Unmasked TU VMERGE_VVM combined with a masked MU TA instruction folds to
3468
- // masked TU instruction. Both instructions must have the same merge operand.
3469
- // VMERGE_VVM must have have merge operand same as false operand.
3470
- // Note: The VMERGE_VVM forms above (TA, and TU) refer to the policy implied,
3471
- // not the pseudo name. That is, a TA VMERGE_VVM can be either the _TU pseudo
3472
- // form with an IMPLICIT_DEF passthrough operand or the unsuffixed (TA) pseudo
3473
- // form.
3461
+ // Try to fold away VMERGE_VVM instructions into their true operands:
3462
+ //
3463
+ // %true = PseudoVADD_VV ...
3464
+ // %x = PseudoVMERGE_VVM %false, %false, %true, %mask
3465
+ // ->
3466
+ // %x = PseudoVADD_VV_MASK %false, ..., %mask
3467
+ //
3468
+ // We can only fold if vmerge's merge operand, vmerge's false operand and
3469
+ // %true's merge operand (if it has one) are the same. This is because we have
3470
+ // to consolidate them into one merge operand in the result.
3471
+ //
3472
+ // If %true is masked, then we can use its mask instead of vmerge's if vmerge's
3473
+ // mask is all ones.
3474
+ //
3475
+ // We can also fold a VMV_V_V into its true operand, since it is equivalent to a
3476
+ // VMERGE_VVM with an all ones mask.
3477
+ //
3478
+ // The resulting VL is the minimum of the two VLs.
3479
+ //
3480
+ // The resulting policy is the effective policy the vmerge would have had,
3481
+ // i.e. whether or not it's merge operand was implicit-def.
3474
3482
bool RISCVDAGToDAGISel::performCombineVMergeAndVOps (SDNode *N) {
3475
3483
SDValue Merge, False, True, VL, Mask, Glue;
3476
3484
// A vmv.v.v is equivalent to a vmerge with an all-ones mask.
@@ -3530,26 +3538,26 @@ bool RISCVDAGToDAGISel::performCombineVMergeAndVOps(SDNode *N) {
3530
3538
if (Info->MaskAffectsResult && Mask && !usesAllOnesMask (Mask, Glue))
3531
3539
return false ;
3532
3540
3541
+ // If True has a merge operand then it needs to be the same as vmerge's False,
3542
+ // since False will be used for the result's merge operand.
3533
3543
if (HasTiedDest && !isImplicitDef (True->getOperand (0 ))) {
3534
3544
// The vmerge instruction must be TU.
3535
3545
// FIXME: This could be relaxed, but we need to handle the policy for the
3536
3546
// resulting op correctly.
3537
3547
if (isImplicitDef (Merge))
3538
3548
return false ;
3539
3549
SDValue MergeOpTrue = True->getOperand (0 );
3540
- // Both the vmerge instruction and the True instruction must have the same
3541
- // merge operand.
3542
3550
if (False != MergeOpTrue)
3543
3551
return false ;
3544
3552
}
3545
3553
3554
+ // If True is masked then the vmerge must have an all 1s mask, since we're
3555
+ // going to keep the mask from True.
3546
3556
if (IsMasked) {
3547
3557
assert (HasTiedDest && " Expected tied dest" );
3548
3558
// The vmerge instruction must be TU.
3549
3559
if (isImplicitDef (Merge))
3550
3560
return false ;
3551
- // The vmerge instruction must have an all 1s mask since we're going to keep
3552
- // the mask from the True instruction.
3553
3561
// FIXME: Support mask agnostic True instruction which would have an
3554
3562
// undef merge operand.
3555
3563
if (Mask && !usesAllOnesMask (Mask, Glue))
0 commit comments