[clang] [llvm] [RISCV][P-ext] Support Packed Narrowing Clip Pair (PR #215779)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 14 00:38:52 PDT 2026


================
@@ -12302,6 +12283,72 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
     return DAG.getNode(Opc, DL, Op.getValueType(), Op.getOperand(1),
                        Op.getOperand(2));
   }
+  case Intrinsic::riscv_pnclipp:
+  case Intrinsic::riscv_pnclipup: {
+    bool IsSigned = IntNo == Intrinsic::riscv_pnclipp;
+    EVT VT = Op.getValueType();
+    SDValue Rs1 = Op.getOperand(1);
+    SDValue Rs2 = Op.getOperand(2);
+    unsigned Opc = IsSigned ? RISCVISD::PNCLIPP : RISCVISD::PNCLIPUP;
+
+    if (Subtarget.is64Bit()) {
+      if (VT == MVT::v2i32 && !Rs1.getValueType().isVector()) {
+        unsigned WOpc = IsSigned ? RISCVISD::PNCLIPP_W : RISCVISD::PNCLIPUP_W;
+        return DAG.getNode(WOpc, DL, VT, Rs1, Rs2);
+      }
+      return DAG.getNode(Opc, DL, VT, Rs1, Rs2);
+    }
+
+    MVT XLenVT = Subtarget.getXLenVT();
+    auto ToXLen = [&](SDValue V) {
+      return DAG.getBitcast(XLenVT, V);
+    };
+    if (VT == MVT::v4i8) {
+      unsigned ClipOpc = IsSigned ? RISCVISD::PNCLIPP_I : RISCVISD::PNCLIPUP_I;
+      // BuildPairGPRVec requires i32 operands; the v2i16 sources are
+      // bitcast to the XLen type before pairing.
+      SDValue Pair = DAG.getNode(RISCVISD::BuildPairGPRVec, DL, MVT::v4i16,
+                                 ToXLen(Rs1), ToXLen(Rs2));
+      return DAG.getNode(ClipOpc, DL, MVT::v4i8, Pair,
+                         DAG.getConstant(0, DL, XLenVT));
+    }
+    if (VT == MVT::v2i16) {
+      unsigned HOpc = IsSigned ? RISCVISD::PNCLIPP_I : RISCVISD::PNCLIPUP_I;
+      SDValue Pair = DAG.getNode(RISCVISD::BuildPairGPRVec, DL, MVT::v2i32,
+                                 ToXLen(Rs1), ToXLen(Rs2));
+      return DAG.getNode(HOpc, DL, MVT::v2i16, Pair,
+                         DAG.getConstant(0, DL, XLenVT));
+    }
+    if (VT == MVT::v2i32) {
+      unsigned NOpc = IsSigned ? RISCVISD::NCLIPP_I : RISCVISD::NCLIPUP_I;
+      SDValue Zero = DAG.getConstant(0, DL, XLenVT);
+      auto BuildPairFromI64 = [&](SDValue I64) {
+        SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, XLenVT, I64,
+                                 DAG.getConstant(0, DL, MVT::i32));
+        SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, XLenVT, I64,
+                                 DAG.getConstant(1, DL, MVT::i32));
+        return DAG.getNode(RISCVISD::BuildGPRPair, DL, MVT::Untyped, Lo, Hi);
+      };
+      SDValue Pair1 = BuildPairFromI64(Rs1);
+      SDValue Pair2 = BuildPairFromI64(Rs2);
+      SDValue Lo = DAG.getNode(NOpc, DL, XLenVT, Pair1, Zero);
+      SDValue Hi = DAG.getNode(NOpc, DL, XLenVT, Pair2, Zero);
+      return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi);
+    }
+    if (VT == MVT::v8i8 || VT == MVT::v4i16) {
+      unsigned HOpc = IsSigned ? RISCVISD::PNCLIPP_I : RISCVISD::PNCLIPUP_I;
+      MVT HalfVT = VT == MVT::v8i8 ? MVT::v4i8 : MVT::v2i16;
+      SDValue Zero = DAG.getConstant(0, DL, XLenVT);
+      SDValue Lo = DAG.getNode(HOpc, DL, HalfVT, Rs1, Zero);
+      SDValue Hi = DAG.getNode(HOpc, DL, HalfVT, Rs2, Zero);
+      // BuildPairGPRVec requires i32 operands; the v4i8/v2i16 clip results
+      // are bitcast to the XLen type before pairing.
+      return DAG.getNode(RISCVISD::BuildPairGPRVec, DL, VT, ToXLen(Lo),
----------------
TelGome wrote:

I tested using `ISD::CONCAT_VECTORS` for the v2i16 cases and the intrinsics work correctly.

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


More information about the llvm-commits mailing list