[llvm] [RISCV][XCV] Add LLVM intrinsics for non-representable XCVsimd ops (PR #204880)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 1 23:05:08 PDT 2026
================
@@ -857,3 +857,246 @@ let Predicates = [HasVendorXCVmac, IsRV32] in {
def : PatCoreVMacGprGprGprUimm5<"macsRN", "MACSRN">;
def : PatCoreVMacGprGprGprUimm5<"machhsRN", "MACHHSRN">;
}
+
+//===----------------------------------------------------------------------===//
+// cv.shuffle.sci.b 8-bit immediate split
+//===----------------------------------------------------------------------===//
+// The hardware encodes the 8-bit shuffle immediate across four opcodes:
+// cv.shufflei{0,1,2,3}.sci.b, where bits [7:6] select the opcode and bits
+// [5:0] are the 6-bit payload. Match the high bits with a predicate and
+// extract the payload with an SDNodeXForm, so each immediate selects the
+// right real instruction directly in TableGen.
+
+def ShuffleSciBPayload : SDNodeXForm<timm, [{
+ return CurDAG->getTargetConstant(N->getZExtValue() & 0x3f, SDLoc(N),
+ MVT::i32);
+}]>;
+def imm_shuffle_sci_b0 : TImmLeaf<i32, [{ return (Imm & 0xc0) == 0x00; }]>;
+def imm_shuffle_sci_b1 : TImmLeaf<i32, [{ return (Imm & 0xc0) == 0x40; }]>;
+def imm_shuffle_sci_b2 : TImmLeaf<i32, [{ return (Imm & 0xc0) == 0x80; }]>;
+def imm_shuffle_sci_b3 : TImmLeaf<i32, [{ return (Imm & 0xc0) == 0xc0; }]>;
+
+//===----------------------------------------------------------------------===//
+// Pattern helper multiclasses for XCVsimd
+//===----------------------------------------------------------------------===//
+
+// Binary signed: RR variants + SCI with simm6
+multiclass PatCoreVSimdSigned<string iname> {
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h"),
+ !cast<RVInst>("CV_" # NAME # "_H")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b"),
+ !cast<RVInst>("CV_" # NAME # "_B")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h"),
+ !cast<RVInst>("CV_" # NAME # "_SC_H")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b"),
+ !cast<RVInst>("CV_" # NAME # "_SC_B")>;
+ // SCI: when the scalar fits in simm6, prefer the immediate instruction
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, simm6:$imm),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rs1, simm6:$imm)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, simm6:$imm),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rs1, simm6:$imm)>;
+}
+
+// Binary unsigned: RR variants + SCI with uimm6
+multiclass PatCoreVSimdUnsigned<string iname> {
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h"),
+ !cast<RVInst>("CV_" # NAME # "_H")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b"),
+ !cast<RVInst>("CV_" # NAME # "_B")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h"),
+ !cast<RVInst>("CV_" # NAME # "_SC_H")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b"),
+ !cast<RVInst>("CV_" # NAME # "_SC_B")>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, uimm6:$imm),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rs1, uimm6:$imm)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, uimm6:$imm),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rs1, uimm6:$imm)>;
+}
+
+// Shift: RR variants + SCI with uimm4 for .h, uimm3 for .b
+multiclass PatCoreVSimdShift<string iname> {
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h"),
+ !cast<RVInst>("CV_" # NAME # "_H")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b"),
+ !cast<RVInst>("CV_" # NAME # "_B")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h"),
+ !cast<RVInst>("CV_" # NAME # "_SC_H")>;
+ def : PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b"),
+ !cast<RVInst>("CV_" # NAME # "_SC_B")>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, uimm4:$imm),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rs1, uimm4:$imm)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, uimm3:$imm),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rs1, uimm3:$imm)>;
+}
+
+// Accumulating signed (Wb): intrinsic(rs1, rs2, acc) → instr(acc, rs1, rs2)
+// + SCI variant where rs2 (arg1) is simm6
+multiclass PatCoreVSimdSignedWb<string iname> {
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_H") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_B") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SC_H") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SC_B") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, simm6:$imm, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rd, GPR:$rs1, simm6:$imm)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, simm6:$imm, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rd, GPR:$rs1, simm6:$imm)>;
+}
+
+// Accumulating unsigned (Wb): same but SCI uses uimm6
+multiclass PatCoreVSimdUnsignedWb<string iname> {
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_h")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_H") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_b")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_B") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SC_H") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, GPR:$rs2, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SC_B") GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_h")
+ GPR:$rs1, uimm6:$imm, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_H") GPR:$rd, GPR:$rs1, uimm6:$imm)>;
+ def : Pat<(!cast<Intrinsic>("int_riscv_cv_simd_" # iname # "_sc_b")
+ GPR:$rs1, uimm6:$imm, GPR:$rd),
+ (!cast<RVInst>("CV_" # NAME # "_SCI_B") GPR:$rd, GPR:$rs1, uimm6:$imm)>;
+}
+
+//===----------------------------------------------------------------------===//
+// XCVsimd intrinsic-to-instruction patterns
+//===----------------------------------------------------------------------===//
+
+let Predicates = [HasVendorXCVsimd, IsRV32] in {
+
+ // ---- ADD / SUB ----
----------------
topperc wrote:
Remove the empty sections?
https://github.com/llvm/llvm-project/pull/204880
More information about the llvm-commits
mailing list