N->getOperand(2), Mask, VL);
}
+static SDValue performVFMUL_VLCombine(SDNode *N, SelectionDAG &DAG) {
+ // FIXME: Ignore strict opcodes for now.
+ assert(!N->isTargetStrictFPOpcode() && "Unexpected opcode");
+
+ // Try to form widening multiply.
+ SDValue Op0 = N->getOperand(0);
+ SDValue Op1 = N->getOperand(1);
+ SDValue Merge = N->getOperand(2);
+ SDValue Mask = N->getOperand(3);
+ SDValue VL = N->getOperand(4);
+
+ if (Op0.getOpcode() != RISCVISD::FP_EXTEND_VL ||
+ Op1.getOpcode() != RISCVISD::FP_EXTEND_VL)
+ return SDValue();
+
+ // TODO: Refactor to handle more complex cases similar to
+ // combineBinOp_VLToVWBinOp_VL.
+ if (!Op0.hasOneUse() || !Op1.hasOneUse())
+ return SDValue();
+
+ // Check the mask and VL are the same.
+ if (Op0.getOperand(1) != Mask || Op0.getOperand(2) != VL ||
+ Op1.getOperand(1) != Mask || Op1.getOperand(2) != VL)
+ return SDValue();
+
+ Op0 = Op0.getOperand(0);
+ Op1 = Op1.getOperand(0);
+
+ return DAG.getNode(RISCVISD::VFWMUL_VL, SDLoc(N), N->getValueType(0), Op0,
+ Op1, Merge, Mask, VL);
+}
+
static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG,
const RISCVSubtarget &Subtarget) {
assert(N->getOpcode() == ISD::SRA && "Unexpected opcode");
case RISCVISD::STRICT_VFMSUB_VL:
case RISCVISD::STRICT_VFNMSUB_VL:
return performVFMADD_VLCombine(N, DAG);
+ case RISCVISD::FMUL_VL:
+ return performVFMUL_VLCombine(N, DAG);
case ISD::LOAD:
case ISD::STORE: {
if (DCI.isAfterLegalizeDAG())
NODE_NAME_CASE(VWADDU_W_VL)
NODE_NAME_CASE(VWSUB_W_VL)
NODE_NAME_CASE(VWSUBU_W_VL)
+ NODE_NAME_CASE(VFWMUL_VL)
NODE_NAME_CASE(VNSRL_VL)
NODE_NAME_CASE(SETCC_VL)
NODE_NAME_CASE(VSELECT_VL)
def riscv_vwsub_vl : SDNode<"RISCVISD::VWSUB_VL", SDT_RISCVVWBinOp_VL, []>;
def riscv_vwsubu_vl : SDNode<"RISCVISD::VWSUBU_VL", SDT_RISCVVWBinOp_VL, []>;
+def riscv_vfwmul_vl : SDNode<"RISCVISD::VFWMUL_VL", SDT_RISCVVWBinOp_VL, [SDNPCommutative]>;
+
def SDT_RISCVVNBinOp_VL : SDTypeProfile<1, 5, [SDTCisVec<0>,
SDTCisSameNumEltsAs<0, 1>,
SDTCisOpSmallerThanOp<0, 1>,
}
}
}
+
multiclass VPatBinaryWVL_VV_VX_WV_WX<SDPatternOperator vop, SDNode vop_w,
string instruction_name>
: VPatBinaryWVL_VV_VX<vop, instruction_name> {
}
}
+multiclass VPatBinaryFPWVL_VV_VF<SDNode vop, string instruction_name> {
+ foreach fvtiToFWti = AllWidenableFloatVectors in {
+ defvar vti = fvtiToFWti.Vti;
+ defvar wti = fvtiToFWti.Wti;
+ let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
+ GetVTypePredicates<wti>.Predicates) in {
+ defm : VPatBinaryVL_V<vop, instruction_name, "VV",
+ wti.Vector, vti.Vector, vti.Vector, vti.Mask,
+ vti.Log2SEW, vti.LMul, wti.RegClass, vti.RegClass,
+ vti.RegClass>;
+ defm : VPatBinaryVL_VF<vop, instruction_name#"_V"#vti.ScalarSuffix,
+ wti.Vector, vti.Vector, vti.Mask, vti.Log2SEW,
+ vti.LMul, wti.RegClass, vti.RegClass,
+ vti.ScalarRegClass>;
+ }
+ }
+}
+
multiclass VPatWidenBinaryFPVL_VV_VF<SDNode op, PatFrags extop, string instruction_name> {
foreach fvtiToFWti = AllWidenableFloatVectors in {
defvar fvti = fvtiToFWti.Vti;
defm : VPatBinaryFPVL_R_VF_E<any_riscv_fdiv_vl, "PseudoVFRDIV">;
// 13.5. Vector Widening Floating-Point Multiply Instructions
-defm : VPatWidenBinaryFPVL_VV_VF<riscv_fmul_vl, riscv_fpextend_vl_oneuse, "PseudoVFWMUL">;
+defm : VPatBinaryFPWVL_VV_VF<riscv_vfwmul_vl, "PseudoVFWMUL">;
// 13.6 Vector Single-Width Floating-Point Fused Multiply-Add Instructions.
defm : VPatFPMulAddVL_VV_VF<any_riscv_vfmadd_vl, "PseudoVFMADD">;