================
@@ -13626,6 +13647,68 @@ SDValue
RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
return DAG.getNode(Opc, DL, VT, Rs1, Rs2);
}
+ case Intrinsic::riscv_pm2wadd:
+ case Intrinsic::riscv_pm2wadd_x:
+ case Intrinsic::riscv_pm2waddu:
+ case Intrinsic::riscv_pm2wsub:
+ case Intrinsic::riscv_pm2wsub_x:
+ case Intrinsic::riscv_pm2waddsu: {
+ // These intrinsics only have a dedicated widening instruction on RV32
+ // (handled in ReplaceNodeResults). On RV64 the i64 result type is legal,
+ // so synthesize the equivalent value directly at i64 width: the add forms
+ // zero-extend their operands to v4i16 and reuse pm4add(u/su).h, relying on
+ // zero lanes contributing zero products (the "_x" exchanged form
+ // additionally swaps rs2's halfwords via ppairoe.h first); the sub forms
+ // extract and sign-extend each halfword lane and compute the product
+ // difference with plain i64 arithmetic. A custom RISCVISD opcode must
+ // never be the direct result of an i32-producing DAG.getNode here: i32 is
+ // not a legal type on RV64 (only i64 has a register class), and the
+ // generic legalizer's post-hoc promotion of such a "naked" custom-opcode
+ // node mis-widens its vector operands instead of leaving the node alone.
+ assert(Subtarget.is64Bit() && Op.getValueType() == MVT::i64 &&
+ "Unexpected widening horizontal multiply-add legalization");
+ SDValue Rs1 = Op.getOperand(1);
+ SDValue Rs2 = Op.getOperand(2);
+
+ if (IntNo == Intrinsic::riscv_pm2wsub ||
+ IntNo == Intrinsic::riscv_pm2wsub_x) {
+ // Route through the existing riscv_pm2sub(_x) intrinsic (a plain
+ // ISD::INTRINSIC_WO_CHAIN, which is registered Custom for i32 on RV64)
+ // rather than calling RISCVISD::PM2SUB(_X) directly: a "naked" custom
+ // opcode freshly materialized here with an i32 result hits the same
+ // legalizer trap described above, but INTRINSIC_WO_CHAIN's i32 action
+ // is a recognized Custom target that correctly re-enters LowerOperation.
+ unsigned SubIntNo = IntNo == Intrinsic::riscv_pm2wsub
+ ? Intrinsic::riscv_pm2sub
+ : Intrinsic::riscv_pm2sub_x;
+ SDValue IntrId = DAG.getTargetConstant(SubIntNo, DL, MVT::i64);
+ SDValue Res =
+ DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32, IntrId, Rs1, Rs2);
+ return DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, Res);
+ }
+
+ auto WidenAny = [&](SDValue V) {
+ return DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16, V,
+ DAG.getUNDEF(MVT::v2i16));
+ };
+
+ SDValue A = WidenAny(Rs1);
+ SDValue B;
+ if (IntNo == Intrinsic::riscv_pm2wadd_x) {
+ SDValue Rs2Dup = WidenAny(Rs2);
+ SDValue Swapped =
----------------
topperc wrote:
According to the intrinsic document, shouldn't this be
`widenPackedVectorWithZeros` followed by PPAIROE? `zext.w+ppairoe.h+pm4add.h`
I will update the intrinsic spec to allow `pack` in place of `zext.w`
https://github.com/llvm/llvm-project/pull/232612
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits