[clang] [llvm] [Clang][RISCV][P-ext] Add Packed Widening Multiply Accumulate intrinsics (PR #226505)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 25 09:49:06 PDT 2026


================
@@ -13386,6 +13399,51 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
 
     return DAG.getNode(Opc, DL, VT, Rs1, Rs2);
   }
+  case Intrinsic::riscv_pwmacc_i32x2:
+  case Intrinsic::riscv_pwmaccu_u32x2:
+  case Intrinsic::riscv_pwmaccsu_i32x2: {
+    EVT VT = Op.getValueType();
+    SDValue Acc = Op.getOperand(1);
+    SDValue Rs1 = Op.getOperand(2);
+    SDValue Rs2 = Op.getOperand(3);
+    MVT XLenVT = Subtarget.getXLenVT();
+
+    if (Subtarget.is64Bit()) {
+      // Per the spec decomposition table: zip16p duplicates each halfword
+      // into both positions of its 32-bit lane (the su form uses the
+      // pwcvtu.wh spelling, zip16p with x0), then pmacc.w.h01 or
+      // pmaccsu.w.h00 multiplies the lane-local halfwords into rd. The
+      // upper halfwords of the operands are not read. RV32 selects the
+      // pwmacc.h family on the register pair instead.
+      Rs1 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16, Rs1,
+                        DAG.getUNDEF(MVT::v2i16));
+      Rs2 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16, Rs2,
+                        DAG.getUNDEF(MVT::v2i16));
+      if (IntNo == Intrinsic::riscv_pwmaccsu_i32x2) {
+        SDValue Zero = DAG.getNode(ISD::SPLAT_VECTOR, DL, MVT::v4i16,
+                                   DAG.getConstant(0, DL, XLenVT));
+        Rs1 = DAG.getNode(RISCVISD::ZIP16P, DL, MVT::v4i16, Rs1, Zero);
+        Rs2 = DAG.getNode(RISCVISD::ZIP16P, DL, MVT::v4i16, Rs2, Zero);
+        return DAG.getNode(RISCVISD::PMACCSU_HALVES_00, DL, VT, Acc, Rs1, Rs2);
+      }
+      Rs1 = DAG.getNode(RISCVISD::ZIP16P, DL, MVT::v4i16, Rs1, Rs1);
+      Rs2 = DAG.getNode(RISCVISD::ZIP16P, DL, MVT::v4i16, Rs2, Rs2);
+      unsigned Opc = IntNo == Intrinsic::riscv_pwmaccu_u32x2
+                         ? RISCVISD::PMACCU_HALVES_01
+                         : RISCVISD::PMACC_HALVES_01;
+      return DAG.getNode(Opc, DL, VT, Acc, Rs1, Rs2);
+    }
+
+    // RV32 uses pwmacc.h/pwmaccsu.h on the 64-bit accumulator register
+    // pair, exposed as a two-result node over the accumulator words.
+    SDValue RdLo = DAG.getExtractVectorElt(DL, XLenVT, Acc, 0);
+    SDValue RdHi = DAG.getExtractVectorElt(DL, XLenVT, Acc, 1);
+    SDVTList VTs = DAG.getVTList(XLenVT, XLenVT);
+    SDValue Res = DAG.getNode(getRVPWideningMulAccPairOpcode(IntNo), DL, VTs,
----------------
topperc wrote:

This should produce a v2i32 result. No need for a build_vector.

https://github.com/llvm/llvm-project/pull/226505


More information about the llvm-commits mailing list