-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RISCV] Implement Intrinsics Support for XCValu Extension in CV32E40P #85603
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-backend-risc-v @llvm/pr-subscribers-llvm-ir Author: None (realqhc) ChangesImplement XCValu intrinsics for CV32E40P according to the specification. This commit is part of a patch-set to upstream the vendor specific extensions of CV32E40P that need LLVM intrinsics to implement Clang builtins. Contributors: @CharKeaney, @ChunyuLiao, @jeremybennett, @lewis-revill, @NandniJamnadas, @PaoloS02, @serkm, @simonpcook, @xingmingjie. Full diff: https://github.com/llvm/llvm-project/pull/85603.diff 4 Files Affected:
diff --git a/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td b/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
index f1590ad66e362b..f0c6faadf6aabf 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td
@@ -18,6 +18,18 @@ class ScalarCoreVBitManipGprIntrinsic
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty],
[IntrNoMem, IntrSpeculatable]>;
+class ScalarCoreVAluGprIntrinsic
+ : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty],
+ [IntrNoMem, IntrSpeculatable]>;
+
+class ScalarCoreVAluGprGprIntrinsic
+ : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrSpeculatable]>;
+
+class ScalarCoreVAluGprGprGprIntrinsic
+ : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+ [IntrNoMem, IntrSpeculatable]>;
+
let TargetPrefix = "riscv" in {
def int_riscv_cv_bitmanip_extract : ScalarCoreVBitManipGprGprIntrinsic;
def int_riscv_cv_bitmanip_extractu : ScalarCoreVBitManipGprGprIntrinsic;
@@ -34,4 +46,20 @@ let TargetPrefix = "riscv" in {
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrWillReturn, IntrSpeculatable,
ImmArg<ArgIndex<1>>, ImmArg<ArgIndex<2>>]>;
+
+ def int_riscv_cv_alu_exths : ScalarCoreVAluGprIntrinsic;
+ def int_riscv_cv_alu_exthz : ScalarCoreVAluGprIntrinsic;
+ def int_riscv_cv_alu_extbs : ScalarCoreVAluGprIntrinsic;
+ def int_riscv_cv_alu_extbz : ScalarCoreVAluGprIntrinsic;
+
+ def int_riscv_cv_alu_clip : ScalarCoreVAluGprGprIntrinsic;
+ def int_riscv_cv_alu_clipu : ScalarCoreVAluGprGprIntrinsic;
+ def int_riscv_cv_alu_addn : ScalarCoreVAluGprGprGprIntrinsic;
+ def int_riscv_cv_alu_addun : ScalarCoreVAluGprGprGprIntrinsic;
+ def int_riscv_cv_alu_addrn : ScalarCoreVAluGprGprGprIntrinsic;
+ def int_riscv_cv_alu_addurn : ScalarCoreVAluGprGprGprIntrinsic;
+ def int_riscv_cv_alu_subn : ScalarCoreVAluGprGprGprIntrinsic;
+ def int_riscv_cv_alu_subun : ScalarCoreVAluGprGprGprIntrinsic;
+ def int_riscv_cv_alu_subrn : ScalarCoreVAluGprGprGprIntrinsic;
+ def int_riscv_cv_alu_suburn : ScalarCoreVAluGprGprGprIntrinsic;
} // TargetPrefix = "riscv"
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index f7275eb7c77bb3..144d320bde5768 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -249,10 +249,12 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
if (RV64LegalI32 && Subtarget.is64Bit())
setOperationAction(ISD::SELECT_CC, MVT::i32, Expand);
- setCondCodeAction(ISD::SETLE, XLenVT, Expand);
+ if (!Subtarget.hasVendorXCValu())
+ setCondCodeAction(ISD::SETLE, XLenVT, Expand);
setCondCodeAction(ISD::SETGT, XLenVT, Custom);
setCondCodeAction(ISD::SETGE, XLenVT, Expand);
- setCondCodeAction(ISD::SETULE, XLenVT, Expand);
+ if (!Subtarget.hasVendorXCValu())
+ setCondCodeAction(ISD::SETULE, XLenVT, Expand);
setCondCodeAction(ISD::SETUGT, XLenVT, Custom);
setCondCodeAction(ISD::SETUGE, XLenVT, Expand);
@@ -1384,6 +1386,16 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
}
}
+ if (Subtarget.hasVendorXCValu()) {
+ setOperationAction(ISD::ABS, XLenVT, Legal);
+ setOperationAction(ISD::SMIN, XLenVT, Legal);
+ setOperationAction(ISD::UMIN, XLenVT, Legal);
+ setOperationAction(ISD::SMAX, XLenVT, Legal);
+ setOperationAction(ISD::UMAX, XLenVT, Legal);
+ setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Legal);
+ setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Legal);
+ }
+
// Function alignments.
const Align FunctionAlignment(Subtarget.hasStdExtCOrZca() ? 2 : 4);
setMinFunctionAlignment(FunctionAlignment);
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
index 924e91e15c348f..f300aedad5b3d9 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
@@ -198,7 +198,7 @@ let DecoderNamespace = "XCValu" in {
} // DecoderNamespace = "XCValu"
-let Predicates = [HasVendorXCValu],
+let Predicates = [HasVendorXCValu, IsRV32],
hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
// General ALU Operations
def CV_ABS : CVInstAluR<0b0101000, 0b011, "cv.abs">,
@@ -249,10 +249,10 @@ let Predicates = [HasVendorXCValu],
Sched<[]>;
def CV_SUBURN : CVInstAluRRI<0b11, 0b011, "cv.suburn">,
Sched<[]>;
-} // Predicates = [HasVendorXCValu],
+} // Predicates = [HasVendorXCValu, IsRV32],
// hasSideEffects = 0, mayLoad = 0, mayStore = 0
-let Predicates = [HasVendorXCValu],
+let Predicates = [HasVendorXCValu, IsRV32],
hasSideEffects = 0, mayLoad = 0, mayStore = 0,
Constraints = "$rd = $rd_wb" in {
def CV_ADDNR : CVInstAluRRNR<0b1000000, 0b011, "cv.addnr">,
@@ -272,7 +272,7 @@ let Predicates = [HasVendorXCValu],
def CV_SUBURNR : CVInstAluRRNR<0b1000111, 0b011, "cv.suburnr">,
Sched<[]>;
-} // Predicates = [HasVendorXCValu],
+} // Predicates = [HasVendorXCValu, IsRV32],
// hasSideEffects = 0, mayLoad = 0, mayStore = 0,
// Constraints = "$rd = $rd_wb"
@@ -662,6 +662,8 @@ let Predicates = [HasVendorXCVelw, IsRV32], hasSideEffects = 0,
def cv_tuimm2 : TImmLeaf<XLenVT, [{return isUInt<2>(Imm);}]>;
def cv_tuimm5 : TImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]>;
def cv_uimm10 : ImmLeaf<XLenVT, [{return isUInt<10>(Imm);}]>;
+def cv_uimm_pow2: Operand<XLenVT>,
+ ImmLeaf<XLenVT, [{return isPowerOf2_32(Imm + 1);}]>;
def CV_LO5: SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(N->getZExtValue() & 0x1f, SDLoc(N),
@@ -673,6 +675,49 @@ def CV_HI5: SDNodeXForm<imm, [{
N->getValueType(0));
}]>;
+def between : PatFrags<(ops node:$lowerBound, node:$upperBound, node:$value),
+ [(smin (smax node:$value, node:$lowerBound), node:$upperBound),
+ (smax (smin node:$value, node:$upperBound), node:$lowerBound)]>;
+
+def betweenu : PatFrags<(ops node:$upperBound, node:$value),
+ [(smin (smax node:$value, 0), node:$upperBound),
+ (smax (smin node:$value, node:$upperBound), 0)]>;
+def powerOf2 : ImmLeaf<XLenVT, [{ return isPowerOf2_32(Imm); }]>;
+def powerOf2Minus1 : ImmLeaf<XLenVT, [{ return isPowerOf2_32(Imm+1); }]>;
+def negativePowerOf2 : ImmLeaf<XLenVT, [{ return isPowerOf2_32(-Imm); }]>;
+def roundBit : PatFrag<(ops node:$shiftAmount),
+ (srl (shl 1, node:$shiftAmount), (XLenVT 1))>;
+def trailing1sPlus1 : SDNodeXForm<imm, [{
+ return CurDAG->getTargetConstant(
+ llvm::countr_one(N->getZExtValue()) + 1,
+ SDLoc(N), N->getValueType(0));
+}]>;
+
+def shiftRound : PatFrag<(ops node:$value, node:$shiftAmount),
+ (sra (add node:$value, powerOf2), node:$shiftAmount), [{
+ if (auto powerOf2 = dyn_cast<ConstantSDNode>(N->getOperand(0)->getOperand(1)))
+ return (powerOf2->getZExtValue() << 1) == (1U << N->getConstantOperandVal(1));
+ return false;
+}]>;
+
+def ushiftRound : PatFrag<(ops node:$value, node:$shiftAmount),
+ (srl (add node:$value, powerOf2), node:$shiftAmount), [{
+ if (auto powerOf2 = dyn_cast<ConstantSDNode>(N->getOperand(0)->getOperand(1)))
+ return (powerOf2->getZExtValue() << 1) == (1U << N->getConstantOperandVal(1));
+ return false;
+}]>;
+
+def clip : PatFrag<(ops node:$upperBound, node:$value),
+ (between negativePowerOf2, node:$upperBound, node:$value), [{
+ // Checking lower & upper bound for the clip instruction
+ if (auto bound1 = dyn_cast<ConstantSDNode>(N->getOperand(0)->getOperand(1))) {
+ if (auto bound2 = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
+ return (bound1->getSExtValue() == ~bound2->getSExtValue());
+ }
+ }
+ return false;
+}]>;
+
multiclass PatCoreVBitManip<Intrinsic intr> {
def : PatGprGpr<intr, !cast<RVInst>("CV_" # NAME # "R")>;
def : Pat<(intr GPR:$rs1, cv_uimm10:$imm),
@@ -704,3 +749,51 @@ let Predicates = [HasVendorXCVbitmanip, IsRV32] in {
(CV_BITREV GPR:$rs1, cv_tuimm2:$radix, cv_tuimm5:$pts)>;
def : Pat<(bitreverse (XLenVT GPR:$rs)), (CV_BITREV GPR:$rs, 0, 0)>;
}
+
+class PatCoreVAluGpr <string intr, string asm> :
+ PatGpr<!cast<Intrinsic>("int_riscv_cv_alu_" # intr),
+ !cast<RVInst>("CV_" # asm)>;
+class PatCoreVAluGprGpr <string intr, string asm> :
+ PatGprGpr<!cast<Intrinsic>("int_riscv_cv_alu_" # intr),
+ !cast<RVInst>("CV_" # asm)>;
+
+multiclass PatCoreVAluGprImm <Intrinsic intr> {
+ def : PatGprGpr<intr, !cast<RVInst>("CV_" # NAME # "R")>;
+ def : Pat<(intr (XLenVT GPR:$rs1), powerOf2Minus1:$upperBound),
+ (!cast<RVInst>("CV_" # NAME) GPR:$rs1,
+ (trailing1sPlus1 imm:$upperBound))>;
+}
+
+multiclass PatCoreVAluGprGprImm <Intrinsic intr> {
+ def : Pat<(intr GPR:$rs1, GPR:$rs2, GPR:$rs3),
+ (!cast<RVInst>("CV_" # NAME # "R") GPR:$rs1, GPR:$rs2, GPR:$rs3)>;
+ def : Pat<(intr GPR:$rs1, GPR:$rs2, uimm5:$imm),
+ (!cast<RVInst>("CV_" # NAME) GPR:$rs1, GPR:$rs2, uimm5:$imm)>;
+}
+
+let Predicates = [HasVendorXCValu, IsRV32], AddedComplexity = 1 in {
+ def : PatGpr<abs, CV_ABS>;
+ def : PatGprGpr<setle, CV_SLET>;
+ def : PatGprGpr<setule, CV_SLETU>;
+ def : PatGprGpr<smin, CV_MIN>;
+ def : PatGprGpr<umin, CV_MINU>;
+ def : PatGprGpr<smax, CV_MAX>;
+ def : PatGprGpr<umax, CV_MAXU>;
+
+ def : Pat<(sext_inreg (XLenVT GPR:$rs1), i16), (CV_EXTHS GPR:$rs1)>;
+ def : Pat<(sext_inreg (XLenVT GPR:$rs1), i8), (CV_EXTBS GPR:$rs1)>;
+
+ def : Pat<(and (XLenVT GPR:$rs1), 0xffff), (CV_EXTHZ GPR:$rs1)>;
+ def : Pat<(and (XLenVT GPR:$rs1), 0xff), (CV_EXTBZ GPR:$rs1)>;
+
+ defm CLIP : PatCoreVAluGprImm<int_riscv_cv_alu_clip>;
+ defm CLIPU : PatCoreVAluGprImm<int_riscv_cv_alu_clipu>;
+ defm ADDN : PatCoreVAluGprGprImm<int_riscv_cv_alu_addn>;
+ defm ADDUN : PatCoreVAluGprGprImm<int_riscv_cv_alu_addun>;
+ defm ADDRN : PatCoreVAluGprGprImm<int_riscv_cv_alu_addrn>;
+ defm ADDURN : PatCoreVAluGprGprImm<int_riscv_cv_alu_addurn>;
+ defm SUBN : PatCoreVAluGprGprImm<int_riscv_cv_alu_subn>;
+ defm SUBUN : PatCoreVAluGprGprImm<int_riscv_cv_alu_subun>;
+ defm SUBRN : PatCoreVAluGprGprImm<int_riscv_cv_alu_subrn>;
+ defm SUBURN : PatCoreVAluGprGprImm<int_riscv_cv_alu_suburn>;
+} // Predicates = [HasVendorXCValu, IsRV32]
diff --git a/llvm/test/CodeGen/RISCV/xcvalu.ll b/llvm/test/CodeGen/RISCV/xcvalu.ll
new file mode 100644
index 00000000000000..2bcdc1b4cfeddd
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/xcvalu.ll
@@ -0,0 +1,322 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -O0 -mtriple=riscv32 -mattr=+m -mattr=+xcvalu -verify-machineinstrs < %s \
+; RUN: | FileCheck %s
+
+declare i32 @llvm.abs.i32(i32, i1)
+declare i32 @llvm.smin.i32(i32, i32)
+declare i32 @llvm.smax.i32(i32, i32)
+declare i32 @llvm.umin.i32(i32, i32)
+declare i32 @llvm.umax.i32(i32, i32)
+
+define i32 @abs(i32 %a) {
+; CHECK-LABEL: abs:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.abs a0, a0
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.abs.i32(i32 %a, i1 false)
+ ret i32 %1
+}
+
+define i1 @slet(i32 %a, i32 %b) {
+; CHECK-LABEL: slet:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.slet a0, a0, a1
+; CHECK-NEXT: ret
+ %1 = icmp sle i32 %a, %b
+ ret i1 %1
+}
+
+define i1 @sletu(i32 %a, i32 %b) {
+; CHECK-LABEL: sletu:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.sletu a0, a0, a1
+; CHECK-NEXT: ret
+ %1 = icmp ule i32 %a, %b
+ ret i1 %1
+}
+
+define i32 @smin(i32 %a, i32 %b) {
+; CHECK-LABEL: smin:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.min a0, a0, a1
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.smin.i32(i32 %a, i32 %b)
+ ret i32 %1
+}
+
+define i32 @umin(i32 %a, i32 %b) {
+; CHECK-LABEL: umin:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.minu a0, a0, a1
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.umin.i32(i32 %a, i32 %b)
+ ret i32 %1
+}
+
+define i32 @smax(i32 %a, i32 %b) {
+; CHECK-LABEL: smax:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.max a0, a0, a1
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.smax.i32(i32 %a, i32 %b)
+ ret i32 %1
+}
+
+define i32 @umax(i32 %a, i32 %b) {
+; CHECK-LABEL: umax:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.maxu a0, a0, a1
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.umax.i32(i32 %a, i32 %b)
+ ret i32 %1
+}
+
+define i32 @exths(i16 %a) {
+; CHECK-LABEL: exths:
+; CHECK: # %bb.0:
+; CHECK-NEXT: # kill: def $x11 killed $x10
+; CHECK-NEXT: cv.exths a0, a0
+; CHECK-NEXT: ret
+ %1 = sext i16 %a to i32
+ ret i32 %1
+}
+
+define i32 @exthz(i16 %a) {
+; CHECK-LABEL: exthz:
+; CHECK: # %bb.0:
+; CHECK-NEXT: # kill: def $x11 killed $x10
+; CHECK-NEXT: cv.exthz a0, a0
+; CHECK-NEXT: ret
+ %1 = zext i16 %a to i32
+ ret i32 %1
+}
+
+define i32 @extbs(i8 %a) {
+; CHECK-LABEL: extbs:
+; CHECK: # %bb.0:
+; CHECK-NEXT: # kill: def $x11 killed $x10
+; CHECK-NEXT: cv.extbs a0, a0
+; CHECK-NEXT: ret
+ %1 = sext i8 %a to i32
+ ret i32 %1
+}
+
+define i32 @extbz(i8 %a) {
+; CHECK-LABEL: extbz:
+; CHECK: # %bb.0:
+; CHECK-NEXT: # kill: def $x11 killed $x10
+; CHECK-NEXT: cv.extbz a0, a0
+; CHECK-NEXT: ret
+ %1 = zext i8 %a to i32
+ ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.alu.clip(i32, i32)
+
+define i32 @test.cv.alu.clip.case.a(i32 %a) {
+; CHECK-LABEL: test.cv.alu.clip.case.a:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.clip a0, a0, 5
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.clip(i32 %a, i32 15)
+ ret i32 %1
+}
+
+define i32 @test.cv.alu.clip.case.b(i32 %a) {
+; CHECK-LABEL: test.cv.alu.clip.case.b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a1, 10
+; CHECK-NEXT: cv.clipr a0, a0, a1
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.clip(i32 %a, i32 10)
+ ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.alu.clipu(i32, i32)
+
+define i32 @test.cv.alu.clipu.case.a(i32 %a) {
+; CHECK-LABEL: test.cv.alu.clipu.case.a:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.clipu a0, a0, 9
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.clipu(i32 %a, i32 255)
+ ret i32 %1
+}
+
+define i32 @test.cv.alu.clipu.case.b(i32 %a) {
+; CHECK-LABEL: test.cv.alu.clipu.case.b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a1, 200
+; CHECK-NEXT: cv.clipur a0, a0, a1
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.clipu(i32 %a, i32 200)
+ ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.alu.addn(i32, i32, i32)
+
+define i32 @test.cv.alu.addn.case.a(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.addn.case.a:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.addn a0, a0, a1, 15
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.addn(i32 %a, i32 %b, i32 15)
+ ret i32 %1
+}
+
+define i32 @test.cv.alu.addn.case.b(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.addn.case.b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a2, 32
+; CHECK-NEXT: cv.addnr a0, a1, a2
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.addn(i32 %a, i32 %b, i32 32)
+ ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.alu.addun(i32, i32, i32)
+
+define i32 @test.cv.alu.addun.case.a(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.addun.case.a:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.addun a0, a0, a1, 15
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.addun(i32 %a, i32 %b, i32 15)
+ ret i32 %1
+}
+
+define i32 @test.cv.alu.addun.case.b(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.addun.case.b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a2, 32
+; CHECK-NEXT: cv.addunr a0, a1, a2
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.addun(i32 %a, i32 %b, i32 32)
+ ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.alu.addrn(i32, i32, i32)
+
+define i32 @test.cv.alu.addrn.case.a(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.addrn.case.a:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.addrn a0, a0, a1, 15
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.addrn(i32 %a, i32 %b, i32 15)
+ ret i32 %1
+}
+
+define i32 @test.cv.alu.addrn.case.b(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.addrn.case.b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a2, 32
+; CHECK-NEXT: cv.addrnr a0, a1, a2
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.addrn(i32 %a, i32 %b, i32 32)
+ ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.alu.addurn(i32, i32, i32)
+
+define i32 @test.cv.alu.addurn.case.a(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.addurn.case.a:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.addurn a0, a0, a1, 15
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.addurn(i32 %a, i32 %b, i32 15)
+ ret i32 %1
+}
+
+define i32 @test.cv.alu.addurn.case.b(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.addurn.case.b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a2, 32
+; CHECK-NEXT: cv.addurnr a0, a1, a2
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.addurn(i32 %a, i32 %b, i32 32)
+ ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.alu.subn(i32, i32, i32)
+
+define i32 @test.cv.alu.subn.case.a(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.subn.case.a:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.subn a0, a0, a1, 15
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.subn(i32 %a, i32 %b, i32 15)
+ ret i32 %1
+}
+
+define i32 @test.cv.alu.subn.case.b(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.subn.case.b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a2, 32
+; CHECK-NEXT: cv.subnr a0, a1, a2
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.subn(i32 %a, i32 %b, i32 32)
+ ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.alu.subun(i32, i32, i32)
+
+define i32 @test.cv.alu.subun.case.a(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.subun.case.a:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.subun a0, a0, a1, 15
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.subun(i32 %a, i32 %b, i32 15)
+ ret i32 %1
+}
+
+define i32 @test.cv.alu.subun.case.b(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.subun.case.b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a2, 32
+; CHECK-NEXT: cv.subunr a0, a1, a2
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.subun(i32 %a, i32 %b, i32 32)
+ ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.alu.subrn(i32, i32, i32)
+
+define i32 @test.cv.alu.subrn.case.a(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.subrn.case.a:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.subrn a0, a0, a1, 15
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.subrn(i32 %a, i32 %b, i32 15)
+ ret i32 %1
+}
+
+define i32 @test.cv.alu.subrn.case.b(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.subrn.case.b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a2, 32
+; CHECK-NEXT: cv.subrnr a0, a1, a2
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.subrn(i32 %a, i32 %b, i32 32)
+ ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.alu.suburn(i32, i32, i32)
+
+define i32 @test.cv.alu.suburn.case.a(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.suburn.case.a:
+; CHECK: # %bb.0:
+; CHECK-NEXT: cv.suburn a0, a0, a1, 15
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.suburn(i32 %a, i32 %b, i32 15)
+ ret i32 %1
+}
+
+define i32 @test.cv.alu.suburn.case.b(i32 %a, i32 %b) {
+; CHECK-LABEL: test.cv.alu.suburn.case.b:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a2, 32
+; CHECK-NEXT: cv.suburnr a0, a1, a2
+; CHECK-NEXT: ret
+ %1 = call i32 @llvm.riscv.cv.alu.suburn(i32 %a, i32 %b, i32 32)
+ ret i32 %1
+}
|
033051e
to
c98a470
Compare
f86b6d0
to
37f9c41
Compare
332a616
to
b8c8dfb
Compare
b8c8dfb
to
6ff9c35
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
6ff9c35
to
45c09a1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Implement XCValu intrinsics for CV32E40P according to the specification. This commit is part of a patch-set to upstream the vendor specific extensions of CV32E40P that need LLVM intrinsics to implement Clang builtins. Contributors: @CharKeaney, @ChunyuLiao, @jeremybennett, @lewis-revill, @NandniJamnadas, @PaoloS02, @serkm, @simonpcook, @xingmingjie.
45c09a1
to
2d5119d
Compare
removed unused patterns, will merge it after all checks passed. |
…llvm#85603) Implement XCValu intrinsics for CV32E40P according to the specification. This commit is part of a patch-set to upstream the vendor specific extensions of CV32E40P that need LLVM intrinsics to implement Clang builtins. Contributors: @CharKeaney, @ChunyuLiao, @jeremybennett, @lewis-revill, @NandniJamnadas, @PaoloS02, @serkm, @simonpcook, @xingmingjie.
Implement XCValu intrinsics for CV32E40P according to the specification.
This commit is part of a patch-set to upstream the vendor specific extensions of CV32E40P that need LLVM intrinsics to implement Clang builtins.
Contributors: @CharKeaney, @ChunyuLiao, @jeremybennett, @lewis-revill, @NandniJamnadas, @PaoloS02, @serkm, @simonpcook, @xingmingjie.