[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:05 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);
----------------
topperc wrote:

This doesn't match the decomposition table which only has a single zip16p.

It should be
```
  SDValue Zip = DAG.getNode(RISCVISD::PZIP, DL, MVT::v4i16, Rs1, Rs2);
  unsigned Opc = IntNo == Intrinsic::riscv_pwmaccu_u32x2
                         ? RISCVISD::PMACCU_HALVES_01
                         : RISCVISD::PMACC_HALVES_01;
  return DAG.getNode(Opc, DL, VT, Acc, Zip, Zip);
```

This puts the elements from the low half of Rs1 in to the even elements of Zip. and the elements from the low half of Rs2 in to the odd elements of Zip. The PMACCU_HALVES_01/PMACC_HALVES_01 will multiply the even elements of the first source(which came from Rs1) and odd elements of the second source(which came from Rs2).

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


More information about the llvm-commits mailing list