[RISCV] Match widening fp instructions with same fpext used in multiple operands (#125803)

Because the fpext has a single use constraint on it we can't match cases
where it's used for both operands.

Introduce a new PatFrag that allows multiple uses on a single user and
use it for the binary patterns, and some ternary patterns.

(For some of the ternary patterns there is a fneg that counts as a
separate user, we still need to handle these)
This commit is contained in:
Luke Lau 2025-02-11 01:11:44 +08:00 committed by GitHub
parent 55015e150b
commit e42fdcb41f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 79 additions and 13 deletions

View File

@ -536,19 +536,19 @@ multiclass VPatWidenBinaryFPSDNode_VV_VF<SDNode op, string instruction_name> {
defvar wti = vtiToWti.Wti;
let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
GetVTypePredicates<wti>.Predicates) in {
def : Pat<(op (wti.Vector (riscv_fpextend_vl_oneuse
def : Pat<(op (wti.Vector (riscv_fpextend_vl_sameuser
(vti.Vector vti.RegClass:$rs2),
(vti.Mask true_mask), (XLenVT srcvalue))),
(wti.Vector (riscv_fpextend_vl_oneuse
(wti.Vector (riscv_fpextend_vl_sameuser
(vti.Vector vti.RegClass:$rs1),
(vti.Mask true_mask), (XLenVT srcvalue)))),
(!cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX)
(wti.Vector (IMPLICIT_DEF)), vti.RegClass:$rs2,
vti.RegClass:$rs1, vti.AVL, vti.Log2SEW, TA_MA)>;
def : Pat<(op (wti.Vector (riscv_fpextend_vl_oneuse
def : Pat<(op (wti.Vector (riscv_fpextend_vl_sameuser
(vti.Vector vti.RegClass:$rs2),
(vti.Mask true_mask), (XLenVT srcvalue))),
(wti.Vector (riscv_fpextend_vl_oneuse
(wti.Vector (riscv_fpextend_vl_sameuser
(vti.Vector (SplatFPOp vti.ScalarRegClass:$rs1)),
(vti.Mask true_mask), (XLenVT srcvalue)))),
(!cast<Instruction>(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX)
@ -571,10 +571,10 @@ multiclass VPatWidenBinaryFPSDNode_VV_VF_RM<SDNode op, string instruction_name>
defvar wti = vtiToWti.Wti;
let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
GetVTypePredicates<wti>.Predicates) in {
def : Pat<(op (wti.Vector (riscv_fpextend_vl_oneuse
def : Pat<(op (wti.Vector (riscv_fpextend_vl_sameuser
(vti.Vector vti.RegClass:$rs2),
(vti.Mask true_mask), (XLenVT srcvalue))),
(wti.Vector (riscv_fpextend_vl_oneuse
(wti.Vector (riscv_fpextend_vl_sameuser
(vti.Vector vti.RegClass:$rs1),
(vti.Mask true_mask), (XLenVT srcvalue)))),
(!cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX#"_E"#vti.SEW)
@ -584,10 +584,10 @@ multiclass VPatWidenBinaryFPSDNode_VV_VF_RM<SDNode op, string instruction_name>
// RISCVInsertReadWriteCSR
FRM_DYN,
vti.AVL, vti.Log2SEW, TA_MA)>;
def : Pat<(op (wti.Vector (riscv_fpextend_vl_oneuse
def : Pat<(op (wti.Vector (riscv_fpextend_vl_sameuser
(vti.Vector vti.RegClass:$rs2),
(vti.Mask true_mask), (XLenVT srcvalue))),
(wti.Vector (riscv_fpextend_vl_oneuse
(wti.Vector (riscv_fpextend_vl_sameuser
(vti.Vector (SplatFPOp (vti.Scalar vti.ScalarRegClass:$rs1))),
(vti.Mask true_mask), (XLenVT srcvalue)))),
(!cast<Instruction>(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX#"_E"#vti.SEW)
@ -669,10 +669,10 @@ multiclass VPatWidenFPMulAccSDNode_VV_VF_RM<string instruction_name,
!if(!eq(vti.Scalar, bf16),
[HasStdExtZvfbfwma],
[])) in {
def : Pat<(fma (wti.Vector (riscv_fpextend_vl_oneuse
def : Pat<(fma (wti.Vector (riscv_fpextend_vl_sameuser
(vti.Vector vti.RegClass:$rs1),
(vti.Mask true_mask), (XLenVT srcvalue))),
(wti.Vector (riscv_fpextend_vl_oneuse
(wti.Vector (riscv_fpextend_vl_sameuser
(vti.Vector vti.RegClass:$rs2),
(vti.Mask true_mask), (XLenVT srcvalue))),
(wti.Vector wti.RegClass:$rd)),
@ -749,11 +749,11 @@ multiclass VPatWidenFPMulSacSDNode_VV_VF_RM<string instruction_name> {
defvar suffix = vti.LMul.MX # "_E" # vti.SEW;
let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
GetVTypePredicates<wti>.Predicates) in {
def : Pat<(fma (wti.Vector (riscv_fpextend_vl_oneuse
def : Pat<(fma (wti.Vector (riscv_fpextend_vl_sameuser
(vti.Vector vti.RegClass:$rs1),
(vti.Mask true_mask), (XLenVT srcvalue))),
(riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs2),
(vti.Mask true_mask), (XLenVT srcvalue)),
(riscv_fpextend_vl_sameuser (vti.Vector vti.RegClass:$rs2),
(vti.Mask true_mask), (XLenVT srcvalue)),
(fneg wti.RegClass:$rd)),
(!cast<Instruction>(instruction_name#"_VV_"#suffix)
wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,

View File

@ -554,6 +554,11 @@ def riscv_fpextend_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C),
return N->hasOneUse();
}]>;
def riscv_fpextend_vl_sameuser : PatFrag<(ops node:$A, node:$B, node:$C),
(riscv_fpextend_vl node:$A, node:$B, node:$C), [{
return !N->use_empty() && all_equal(N->users());
}]>;
def riscv_vfmadd_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C, node:$D,
node:$E),
(riscv_vfmadd_vl node:$A, node:$B,

View File

@ -323,3 +323,15 @@ define <vscale x 8 x double> @vfwadd_wf_nxv8f64_2(<vscale x 8 x double> %va, flo
%vd = fadd <vscale x 8 x double> %va, %splat
ret <vscale x 8 x double> %vd
}
define <vscale x 1 x double> @vfwadd_vv_nxv1f64_same_op(<vscale x 1 x float> %va) {
; CHECK-LABEL: vfwadd_vv_nxv1f64_same_op:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma
; CHECK-NEXT: vfwadd.vv v9, v8, v8
; CHECK-NEXT: vmv1r.v v8, v9
; CHECK-NEXT: ret
%vb = fpext <vscale x 1 x float> %va to <vscale x 1 x double>
%vc = fadd <vscale x 1 x double> %vb, %vb
ret <vscale x 1 x double> %vc
}

View File

@ -1764,3 +1764,28 @@ define <vscale x 8 x double> @vfwnmsac_fv_nxv8f64(<vscale x 8 x double> %va, <vs
%vg = call <vscale x 8 x double> @llvm.fma.v8f64(<vscale x 8 x double> %vd, <vscale x 8 x double> %vf, <vscale x 8 x double> %va)
ret <vscale x 8 x double> %vg
}
define <vscale x 1 x double> @vfwma_vv_nxv1f64_same_op(<vscale x 1 x float> %va, <vscale x 1 x double> %vb) {
; CHECK-LABEL: vfwma_vv_nxv1f64_same_op:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma
; CHECK-NEXT: vfwmacc.vv v9, v8, v8
; CHECK-NEXT: vmv1r.v v8, v9
; CHECK-NEXT: ret
%vc = fpext <vscale x 1 x float> %va to <vscale x 1 x double>
%vd = call <vscale x 1 x double> @llvm.fma(<vscale x 1 x double> %vc, <vscale x 1 x double> %vc, <vscale x 1 x double> %vb)
ret <vscale x 1 x double> %vd
}
define <vscale x 1 x double> @vfwmsac_vv_nxv1f64_same_op(<vscale x 1 x float> %va, <vscale x 1 x double> %vb) {
; CHECK-LABEL: vfwmsac_vv_nxv1f64_same_op:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma
; CHECK-NEXT: vfwmsac.vv v9, v8, v8
; CHECK-NEXT: vmv1r.v v8, v9
; CHECK-NEXT: ret
%vc = fpext <vscale x 1 x float> %va to <vscale x 1 x double>
%vd = fneg <vscale x 1 x double> %vb
%ve = call <vscale x 1 x double> @llvm.fma(<vscale x 1 x double> %vc, <vscale x 1 x double> %vc, <vscale x 1 x double> %vd)
ret <vscale x 1 x double> %ve
}

View File

@ -175,3 +175,15 @@ define <vscale x 8 x double> @vfwmul_vf_nxv8f64_2(<vscale x 8 x float> %va, floa
%ve = fmul <vscale x 8 x double> %vc, %splat
ret <vscale x 8 x double> %ve
}
define <vscale x 1 x double> @vfwmul_vv_nxv1f64_same_op(<vscale x 1 x float> %va) {
; CHECK-LABEL: vfwmul_vv_nxv1f64_same_op:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma
; CHECK-NEXT: vfwmul.vv v9, v8, v8
; CHECK-NEXT: vmv1r.v v8, v9
; CHECK-NEXT: ret
%vb = fpext <vscale x 1 x float> %va to <vscale x 1 x double>
%vc = fmul <vscale x 1 x double> %vb, %vb
ret <vscale x 1 x double> %vc
}

View File

@ -323,3 +323,15 @@ define <vscale x 8 x double> @vfwsub_wf_nxv8f64_2(<vscale x 8 x double> %va, flo
%vd = fsub <vscale x 8 x double> %va, %splat
ret <vscale x 8 x double> %vd
}
define <vscale x 1 x double> @vfwsub_vv_nxv1f64_same_op(<vscale x 1 x float> %va) {
; CHECK-LABEL: vfwsub_vv_nxv1f64_same_op:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma
; CHECK-NEXT: vfwsub.vv v9, v8, v8
; CHECK-NEXT: vmv1r.v v8, v9
; CHECK-NEXT: ret
%vb = fpext <vscale x 1 x float> %va to <vscale x 1 x double>
%vc = fsub <vscale x 1 x double> %vb, %vb
ret <vscale x 1 x double> %vc
}