Unverified Commit a5c1ecad authored by Yeting Kuo's avatar Yeting Kuo Committed by GitHub
Browse files

[RISCV] Disable performCombineVMergeAndVOps for PseduoVIOTA_M. (#71483)

This transformation might be illegal for `PseduoVIOTA_M`. The value of
`viota.m vd, vs2` is the prefix sum of vd2 and adding mask for it may
cause wrong prefix sum.
Take an example, the result of following expression is `{5, 5, 5, 3}`,
```
; v4 = {1, 1, 1, 1}
viota.m v1, v4
; v0 = {0, 0, 0, 1}, v1 = {0, 1, 2, 3}, v8 = {5, 5, 5, 5}
vmerge.vvm v8, v8, v1, v0.t
; v8 = {5, 5, 5, 3}
```
but if we merge them to `viota.m v8, v4, v0.t`, then the result of is
`{5, 5, 5, 0}`.
Also, we still does `performCombineVMergeAndVOps` for `voita.m` when
mask of `vmerge.vvm` is a true mask.
parent 0b3d5497
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -3517,6 +3517,11 @@ bool RISCVDAGToDAGISel::performCombineVMergeAndVOps(SDNode *N) {
  if (!Info)
    return false;

  // When Mask is not a true mask, this transformation is illegal for some
  // operations whose results are affected by mask, like viota.m.
  if (Info->MaskAffectsResult && Mask && !usesAllOnesMask(Mask, Glue))
    return false;

  if (HasTiedDest && !isImplicitDef(True->getOperand(0))) {
    // The vmerge instruction must be TU.
    // FIXME: This could be relaxed, but we need to handle the policy for the
+1 −0
Original line number Diff line number Diff line
@@ -263,6 +263,7 @@ struct RISCVMaskedPseudoInfo {
  uint16_t MaskedPseudo;
  uint16_t UnmaskedPseudo;
  uint8_t MaskOpIdx;
  uint8_t MaskAffectsResult : 1;
};

#define GET_RISCVVSSEGTable_DECL
+4 −3
Original line number Diff line number Diff line
@@ -570,16 +570,17 @@ def RISCVVIntrinsicsTable : GenericTable {
//    unmasked variant.  For all but compares, both the masked and
//    unmasked variant have a passthru and policy operand.  For compares,
//    neither has a policy op, and only the masked version has a passthru.
class RISCVMaskedPseudo<bits<4> MaskIdx> {
class RISCVMaskedPseudo<bits<4> MaskIdx, bit MaskAffectsRes=false> {
  Pseudo MaskedPseudo = !cast<Pseudo>(NAME);
  Pseudo UnmaskedPseudo = !cast<Pseudo>(!subst("_MASK", "", NAME));
  bits<4> MaskOpIdx = MaskIdx;
  bit MaskAffectsResult = MaskAffectsRes;
}

def RISCVMaskedPseudosTable : GenericTable {
  let FilterClass = "RISCVMaskedPseudo";
  let CppTypeName = "RISCVMaskedPseudoInfo";
  let Fields = ["MaskedPseudo", "UnmaskedPseudo", "MaskOpIdx"];
  let Fields = ["MaskedPseudo", "UnmaskedPseudo", "MaskOpIdx", "MaskAffectsResult"];
  let PrimaryKey = ["MaskedPseudo"];
  let PrimaryKeyName = "getMaskedPseudoInfo";
}
@@ -2092,7 +2093,7 @@ multiclass VPseudoVIOT_M {
                       SchedUnary<"WriteVMIotV", "ReadVMIotV", mx,
                                  forceMergeOpRead=true>;
      def "_" # mx # "_MASK" : VPseudoUnaryMask<m.vrclass, VR, constraint>,
                                 RISCVMaskedPseudo<MaskIdx=2>,
                                 RISCVMaskedPseudo<MaskIdx=2, MaskAffectsRes=true>,
                                 SchedUnary<"WriteVMIotV", "ReadVMIotV", mx,
                                            forceMergeOpRead=true>;
    }
+16 −0
Original line number Diff line number Diff line
@@ -258,3 +258,19 @@ entry:
  %res = call <vscale x 2 x i32> @llvm.vp.merge.nxv2i32(<vscale x 2 x i1> %m, <vscale x 2 x i32> %i, <vscale x 2 x i32> %passthru, i32 %evl)
  ret <vscale x 2 x i32> %res
}

; Test VIOTA_M
declare <vscale x 2 x i32> @llvm.riscv.viota.mask.nxv2i32(<vscale x 2 x i32>, <vscale x 2 x i1>,  <vscale x 2 x i1>, i64, i64)
define <vscale x 2 x i32> @vpmerge_viota(<vscale x 2 x i32> %passthru, <vscale x 2 x i1> %m, <vscale x 2 x i1> %vm, i32 zeroext %vl) {
; CHECK-LABEL: vpmerge_viota:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetvli zero, a0, e32, m1, tu, mu
; CHECK-NEXT:    viota.m v8, v9, v0.t
; CHECK-NEXT:    ret
  %1 = zext i32 %vl to i64
  %a = call <vscale x 2 x i32> @llvm.riscv.viota.mask.nxv2i32(<vscale x 2 x i32> undef, <vscale x 2 x i1> %vm, <vscale x 2 x i1> %m, i64 %1, i64 0)
  %splat = insertelement <vscale x 2 x i1> poison, i1 -1, i32 0
  %mask = shufflevector <vscale x 2 x i1> %splat, <vscale x 2 x i1> poison, <vscale x 2 x i32> zeroinitializer
  %b = call <vscale x 2 x i32> @llvm.riscv.vmerge.nxv2i32.nxv2i32(<vscale x 2 x i32> %passthru, <vscale x 2 x i32> %passthru, <vscale x 2 x i32> %a, <vscale x 2 x i1> %mask, i64 %1)
  ret <vscale x 2 x i32> %b
}
+23 −5
Original line number Diff line number Diff line
@@ -279,13 +279,15 @@ define <vscale x 2 x i32> @vpmerge_vid(<vscale x 2 x i32> %passthru, <vscale x 2
  ret <vscale x 2 x i32> %b
}

; Test riscv.viota
; Test not combine VIOTA_M and VMERGE_VVM without true mask.
declare <vscale x 2 x i32> @llvm.riscv.viota.nxv2i32(<vscale x 2 x i32>, <vscale x 2 x i1>, i64)
define <vscale x 2 x i32> @vpmerge_viota(<vscale x 2 x i32> %passthru, <vscale x 2 x i1> %m, <vscale x 2 x i1> %vm, i32 zeroext %vl) {
; CHECK-LABEL: vpmerge_viota:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetvli zero, a0, e32, m1, tu, mu
; CHECK-NEXT:    viota.m v8, v9, v0.t
; CHECK-NEXT:    vsetvli zero, a0, e32, m1, ta, ma
; CHECK-NEXT:    viota.m v10, v9
; CHECK-NEXT:    vsetvli zero, zero, e32, m1, tu, ma
; CHECK-NEXT:    vmerge.vvm v8, v8, v10, v0
; CHECK-NEXT:    ret
  %1 = zext i32 %vl to i64
  %a = call <vscale x 2 x i32> @llvm.riscv.viota.nxv2i32(<vscale x 2 x i32> undef, <vscale x 2 x i1> %vm, i64 %1)
@@ -293,6 +295,21 @@ define <vscale x 2 x i32> @vpmerge_viota(<vscale x 2 x i32> %passthru, <vscale x
  ret <vscale x 2 x i32> %b
}

; Test combine VIOTA_M and VMERGE_VVM with true mask.
define <vscale x 2 x i32> @vpmerge_viota2(<vscale x 2 x i32> %passthru, <vscale x 2 x i1> %vm, i32 zeroext %vl) {
; CHECK-LABEL: vpmerge_viota2:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetvli zero, a0, e32, m1, tu, ma
; CHECK-NEXT:    viota.m v8, v0
; CHECK-NEXT:    ret
  %1 = zext i32 %vl to i64
  %a = call <vscale x 2 x i32> @llvm.riscv.viota.nxv2i32(<vscale x 2 x i32> undef, <vscale x 2 x i1> %vm, i64 %1)
  %splat = insertelement <vscale x 2 x i1> poison, i1 -1, i32 0
  %true = shufflevector <vscale x 2 x i1> %splat, <vscale x 2 x i1> poison, <vscale x 2 x i32> zeroinitializer
  %b = call <vscale x 2 x i32> @llvm.vp.merge.nxv2i32(<vscale x 2 x i1> %true, <vscale x 2 x i32> %a, <vscale x 2 x i32> %passthru, i32 %vl)
  ret <vscale x 2 x i32> %b
}

; Test riscv.vfclass
declare <vscale x 2 x i32> @llvm.riscv.vfclass.nxv2i32(<vscale x 2 x i32>, <vscale x 2 x float>, i64)
define <vscale x 2 x i32> @vpmerge_vflcass(<vscale x 2 x i32> %passthru, <vscale x 2 x float> %vf, <vscale x 2 x i1> %m, i32 zeroext %vl) {
@@ -730,8 +747,9 @@ define <vscale x 2 x i32> @vpselect_vid(<vscale x 2 x i32> %passthru, <vscale x
define <vscale x 2 x i32> @vpselect_viota(<vscale x 2 x i32> %passthru, <vscale x 2 x i1> %m, <vscale x 2 x i1> %vm, i32 zeroext %vl) {
; CHECK-LABEL: vpselect_viota:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsetvli zero, a0, e32, m1, ta, mu
; CHECK-NEXT:    viota.m v8, v9, v0.t
; CHECK-NEXT:    vsetvli zero, a0, e32, m1, ta, ma
; CHECK-NEXT:    viota.m v10, v9
; CHECK-NEXT:    vmerge.vvm v8, v8, v10, v0
; CHECK-NEXT:    ret
  %1 = zext i32 %vl to i64
  %a = call <vscale x 2 x i32> @llvm.riscv.viota.nxv2i32(<vscale x 2 x i32> undef, <vscale x 2 x i1> %vm, i64 %1)