Author: Xiaodong Liu Date: 2023-01-06T11:41:35+08:00 New Revision: 9e06d18c80e77383f0ecdda428e74fbc1df3dd99
URL: https://github.com/llvm/llvm-project/commit/9e06d18c80e77383f0ecdda428e74fbc1df3dd99 DIFF: https://github.com/llvm/llvm-project/commit/9e06d18c80e77383f0ecdda428e74fbc1df3dd99.diff LOG: [LoongArch] Add intrinsics for CACOP instruction The CACOP instruction is mainly used for cache initialization and cache-consistency maintenance. Depends on D140872 Reviewed By: SixWeining Differential Revision: https://reviews.llvm.org/D140527 Added: llvm/test/CodeGen/LoongArch/intrinsic-la32.ll Modified: clang/include/clang/Basic/BuiltinsLoongArch.def clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Basic/Targets/LoongArch.cpp clang/lib/CodeGen/CGBuiltin.cpp clang/lib/Headers/larchintrin.h clang/lib/Sema/SemaChecking.cpp clang/test/CodeGen/LoongArch/intrinsic-la32-error.c clang/test/CodeGen/LoongArch/intrinsic-la32.c clang/test/CodeGen/LoongArch/intrinsic-la64.c clang/test/Driver/loongarch-default-features.c llvm/include/llvm/IR/IntrinsicsLoongArch.td llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp llvm/lib/Target/LoongArch/LoongArchISelLowering.h llvm/lib/Target/LoongArch/LoongArchInstrInfo.td llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll llvm/test/CodeGen/LoongArch/intrinsic-la64-error.ll llvm/test/CodeGen/LoongArch/intrinsic-la64.ll Removed: ################################################################################ diff --git a/clang/include/clang/Basic/BuiltinsLoongArch.def b/clang/include/clang/Basic/BuiltinsLoongArch.def index cc466cf2703ca..7f2c8403410dd 100644 --- a/clang/include/clang/Basic/BuiltinsLoongArch.def +++ b/clang/include/clang/Basic/BuiltinsLoongArch.def @@ -17,6 +17,8 @@ // TODO: Support more builtins. // TODO: Added feature constraints. +TARGET_BUILTIN(__builtin_loongarch_cacop_d, "vLiULiLi", "nc", "64bit") +TARGET_BUILTIN(__builtin_loongarch_cacop_w, "viUii", "nc", "32bit") TARGET_BUILTIN(__builtin_loongarch_dbar, "vIUi", "nc", "") TARGET_BUILTIN(__builtin_loongarch_ibar, "vIUi", "nc", "") TARGET_BUILTIN(__builtin_loongarch_movfcsr2gr, "UiIUi", "nc", "f") diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 16ab35fcb7a67..c684d3b4a7810 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11764,4 +11764,6 @@ def warn_unsafe_buffer_expression : Warning< def warn_unsafe_buffer_variable : Warning< "variable %0 participates in unchecked buffer operations">, InGroup<UnsafeBufferUsage>, DefaultIgnore; +def err_loongarch_builtin_requires_la32 : Error< + "this builtin requires target: loongarch32">; } // end of sema component. diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp index 5ac94864cebb2..4ce2be8c80742 100644 --- a/clang/lib/Basic/Targets/LoongArch.cpp +++ b/clang/lib/Basic/Targets/LoongArch.cpp @@ -179,6 +179,8 @@ bool LoongArchTargetInfo::initFeatureMap( const std::vector<std::string> &FeaturesVec) const { if (getTriple().getArch() == llvm::Triple::loongarch64) Features["64bit"] = true; + if (getTriple().getArch() == llvm::Triple::loongarch32) + Features["32bit"] = true; return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 0afa25da7aee3..fa6128b2a6441 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19694,6 +19694,12 @@ Value *CodeGenFunction::EmitLoongArchBuiltinExpr(unsigned BuiltinID, switch (BuiltinID) { default: llvm_unreachable("unexpected builtin ID."); + case LoongArch::BI__builtin_loongarch_cacop_d: + ID = Intrinsic::loongarch_cacop_d; + break; + case LoongArch::BI__builtin_loongarch_cacop_w: + ID = Intrinsic::loongarch_cacop_w; + break; case LoongArch::BI__builtin_loongarch_dbar: ID = Intrinsic::loongarch_dbar; break; diff --git a/clang/lib/Headers/larchintrin.h b/clang/lib/Headers/larchintrin.h index 5edcf4c02a441..c5c533ee0b8c1 100644 --- a/clang/lib/Headers/larchintrin.h +++ b/clang/lib/Headers/larchintrin.h @@ -106,6 +106,16 @@ extern __inline int #define __break(/*ui15*/ _1) __builtin_loongarch_break((_1)) +#if __loongarch_grlen == 32 +#define __cacop_w(/*uimm5*/ _1, /*unsigned int*/ _2, /*simm12*/ _3) \ + ((void)__builtin_loongarch_cacop_w((_1), (unsigned int)(_2), (_3))) +#endif + +#if __loongarch_grlen == 64 +#define __cacop_d(/*uimm5*/ _1, /*unsigned long int*/ _2, /*simm12*/ _3) \ + ((void)__builtin_loongarch_cacop_d((_1), (unsigned long int)(_2), (_3))) +#endif + #define __dbar(/*ui15*/ _1) __builtin_loongarch_dbar((_1)) #define __ibar(/*ui15*/ _1) __builtin_loongarch_ibar((_1)) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 05bf498737ec4..f787d6c2255f5 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3705,6 +3705,23 @@ bool Sema::CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI, switch (BuiltinID) { default: break; + case LoongArch::BI__builtin_loongarch_cacop_d: + if (!TI.hasFeature("64bit")) + return Diag(TheCall->getBeginLoc(), + diag::err_loongarch_builtin_requires_la64) + << TheCall->getSourceRange(); + LLVM_FALLTHROUGH; + case LoongArch::BI__builtin_loongarch_cacop_w: { + if (BuiltinID == LoongArch::BI__builtin_loongarch_cacop_w && + !TI.hasFeature("32bit")) + return Diag(TheCall->getBeginLoc(), + diag::err_loongarch_builtin_requires_la32) + << TheCall->getSourceRange(); + SemaBuiltinConstantArgRange(TheCall, 0, 0, llvm::maxUIntN(5)); + SemaBuiltinConstantArgRange(TheCall, 2, llvm::minIntN(12), + llvm::maxIntN(12)); + break; + } case LoongArch::BI__builtin_loongarch_crc_w_b_w: case LoongArch::BI__builtin_loongarch_crc_w_h_w: case LoongArch::BI__builtin_loongarch_crc_w_w_w: diff --git a/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c b/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c index 9941a6f874cba..2c3c249c54b13 100644 --- a/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c +++ b/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c @@ -3,6 +3,14 @@ #include <larchintrin.h> +void cacop_d(unsigned long int a) { + __builtin_loongarch_cacop_d(1, a, 1024); // expected-error {{this builtin requires target: loongarch64}} + __builtin_loongarch_cacop_w(-1, a, 1024); // expected-error {{argument value -1 is outside the valid range [0, 31]}} + __builtin_loongarch_cacop_w(32, a, 1024); // expected-error {{argument value 32 is outside the valid range [0, 31]}} + __builtin_loongarch_cacop_w(1, a, -4096); // expected-error {{argument value -4096 is outside the valid range [-2048, 2047]}} + __builtin_loongarch_cacop_w(1, a, 4096); // expected-error {{argument value 4096 is outside the valid range [-2048, 2047]}} +} + void dbar(int a) { __builtin_loongarch_dbar(32768); // expected-error {{argument value 32768 is outside the valid range [0, 32767]}} __builtin_loongarch_dbar(-1); // expected-error {{argument value 4294967295 is outside the valid range [0, 32767]}} diff --git a/clang/test/CodeGen/LoongArch/intrinsic-la32.c b/clang/test/CodeGen/LoongArch/intrinsic-la32.c index 060692a79ef4b..93d54f511a9cd 100644 --- a/clang/test/CodeGen/LoongArch/intrinsic-la32.c +++ b/clang/test/CodeGen/LoongArch/intrinsic-la32.c @@ -200,3 +200,14 @@ void loongarch_movgr2fcsr(int a) { __movgr2fcsr(1, a); __builtin_loongarch_movgr2fcsr(1, a); } + +// CHECK-LABEL: @cacop_w( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.loongarch.cacop.w(i32 1, i32 [[A:%.*]], i32 1024) +// CHECK-NEXT: tail call void @llvm.loongarch.cacop.w(i32 1, i32 [[A]], i32 1024) +// CHECK-NEXT: ret void +// +void cacop_w(unsigned long int a) { + __cacop_w(1, a, 1024); + __builtin_loongarch_cacop_w(1, a, 1024); +} diff --git a/clang/test/CodeGen/LoongArch/intrinsic-la64.c b/clang/test/CodeGen/LoongArch/intrinsic-la64.c index a8e8f7dddade0..a740882eef541 100644 --- a/clang/test/CodeGen/LoongArch/intrinsic-la64.c +++ b/clang/test/CodeGen/LoongArch/intrinsic-la64.c @@ -123,6 +123,17 @@ int crc_w_w_w(int a, int b) { return 0; } +// CHECK-LABEL: @cacop_d( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.loongarch.cacop.d(i64 1, i64 [[A:%.*]], i64 1024) +// CHECK-NEXT: tail call void @llvm.loongarch.cacop.d(i64 1, i64 [[A]], i64 1024) +// CHECK-NEXT: ret void +// +void cacop_d(unsigned long int a) { + __cacop_d(1, a, 1024); + __builtin_loongarch_cacop_d(1, a, 1024); +} + // CHECK-LABEL: @crc_w_d_w( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.loongarch.crc.w.d.w(i64 [[A:%.*]], i32 [[B:%.*]]) diff --git a/clang/test/Driver/loongarch-default-features.c b/clang/test/Driver/loongarch-default-features.c index 8abc68b9ee744..027d8cdb70cf4 100644 --- a/clang/test/Driver/loongarch-default-features.c +++ b/clang/test/Driver/loongarch-default-features.c @@ -1,7 +1,7 @@ // RUN: %clang --target=loongarch32 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=LA32 // RUN: %clang --target=loongarch64 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=LA64 -// LA32-NOT: "target-features"= +// LA32: "target-features"="+32bit" // LA64: "target-features"="+64bit,+d,+f" int foo(void) { diff --git a/llvm/include/llvm/IR/IntrinsicsLoongArch.td b/llvm/include/llvm/IR/IntrinsicsLoongArch.td index 995e357d3186f..5edce3c529e12 100644 --- a/llvm/include/llvm/IR/IntrinsicsLoongArch.td +++ b/llvm/include/llvm/IR/IntrinsicsLoongArch.td @@ -52,6 +52,10 @@ defm int_loongarch_masked_cmpxchg : MaskedAtomicRMWFiveOpIntrinsics; // LoongArch BASE def int_loongarch_break : Intrinsic<[], [llvm_i32_ty], [ImmArg<ArgIndex<0>>]>; +def int_loongarch_cacop_d : Intrinsic<[], [llvm_i64_ty, llvm_i64_ty, llvm_i64_ty], + [ImmArg<ArgIndex<0>>, ImmArg<ArgIndex<2>>]>; +def int_loongarch_cacop_w : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [ImmArg<ArgIndex<0>>, ImmArg<ArgIndex<2>>]>; def int_loongarch_dbar : Intrinsic<[], [llvm_i32_ty], [ImmArg<ArgIndex<0>>]>; def int_loongarch_ibar : Intrinsic<[], [llvm_i32_ty], [ImmArg<ArgIndex<0>>]>; def int_loongarch_movfcsr2gr : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 55d5af82587c1..b5e5374a5e76b 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -746,13 +746,38 @@ SDValue LoongArchTargetLowering::lowerINTRINSIC_VOID(SDValue Op, SDLoc DL(Op); MVT GRLenVT = Subtarget.getGRLenVT(); SDValue Op0 = Op.getOperand(0); + uint64_t IntrinsicEnum = Op.getConstantOperandVal(1); SDValue Op2 = Op.getOperand(2); const StringRef ErrorMsgOOR = "out of range"; - switch (Op.getConstantOperandVal(1)) { + switch (IntrinsicEnum) { default: // TODO: Add more Intrinsics. return SDValue(); + case Intrinsic::loongarch_cacop_d: + case Intrinsic::loongarch_cacop_w: { + if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit()) { + DAG.getContext()->emitError( + "llvm.loongarch.cacop.d requires target: loongarch64"); + return Op.getOperand(0); + } + if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit()) { + DAG.getContext()->emitError( + "llvm.loongarch.cacop.w requires target: loongarch32"); + return Op.getOperand(0); + } + // call void @llvm.loongarch.cacop.[d/w](uimm5, rj, simm12) + unsigned Imm1 = cast<ConstantSDNode>(Op2)->getZExtValue(); + if (!isUInt<5>(Imm1)) + return emitIntrinsicErrorMessage(Op, ErrorMsgOOR, DAG); + SDValue Op4 = Op.getOperand(4); + int Imm2 = cast<ConstantSDNode>(Op4)->getSExtValue(); + if (!isInt<12>(Imm2)) + return emitIntrinsicErrorMessage(Op, ErrorMsgOOR, DAG); + + return Op; + } + case Intrinsic::loongarch_dbar: { unsigned Imm = cast<ConstantSDNode>(Op2)->getZExtValue(); if (!isUInt<15>(Imm)) @@ -1778,6 +1803,8 @@ const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const { NODE_NAME_CASE(CPUCFG) NODE_NAME_CASE(MOVGR2FCSR) NODE_NAME_CASE(MOVFCSR2GR) + NODE_NAME_CASE(CACOP_D) + NODE_NAME_CASE(CACOP_W) } #undef NODE_NAME_CASE return nullptr; diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h index 9227131461d39..976aae3bb6cee 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h @@ -61,8 +61,10 @@ enum NodeType : unsigned { BITREV_4B, BITREV_W, - // Intrinsic operations + // Intrinsic operations start ============================================ BREAK, + CACOP_D, + CACOP_W, DBAR, IBAR, SYSCALL, @@ -93,6 +95,7 @@ enum NodeType : unsigned { // Read CPU configuration information operation CPUCFG, + // Intrinsic operations end ============================================= }; } // end namespace LoongArchISD diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td index b4a8ad8991757..8e552b23b65d7 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -589,6 +589,10 @@ def RDTIMEL_W : RDTIME_2R<0b0000000000000000011000, "rdtimel.w">; def RDTIMEH_W : RDTIME_2R<0b0000000000000000011001, "rdtimeh.w">; def CPUCFG : ALU_2R<0b0000000000000000011011, "cpucfg">; +// Cache Maintenance Instructions +def CACOP : FmtCACOP<(outs), (ins uimm5:$op, GPR:$rj, simm12:$imm12), "cacop", + "$op, $rj, $imm12">; + /// LA64 instructions let Predicates = [IsLA64] in { @@ -1563,6 +1567,10 @@ defm : PseudoBinPat<"atomic_load_xor_32", PseudoAtomicLoadXor32>; /// Intrinsics +def : Pat<(int_loongarch_cacop_d timm:$op, i64:$rj, timm:$imm12), + (CACOP uimm5:$op, GPR:$rj, simm12:$imm12)>; +def : Pat<(int_loongarch_cacop_w i32:$op, i32:$rj, i32:$imm12), + (CACOP uimm5:$op, GPR:$rj, simm12:$imm12)>; def : Pat<(loongarch_dbar uimm15:$imm15), (DBAR uimm15:$imm15)>; def : Pat<(loongarch_ibar uimm15:$imm15), (IBAR uimm15:$imm15)>; def : Pat<(loongarch_break uimm15:$imm15), (BREAK uimm15:$imm15)>; @@ -1673,10 +1681,6 @@ def IOCSRRD_D : IOCSRRD<0b0000011001001000000011, "iocsrrd.d">; def IOCSRWR_D : IOCSRWR<0b0000011001001000000111, "iocsrwr.d">; } // Predicates = [IsLA64] -// Cache Maintenance Instructions -def CACOP : FmtCACOP<(outs), (ins uimm5:$op, GPR:$rj, simm12:$imm12), "cacop", - "$op, $rj, $imm12">; - // TLB Maintenance Instructions def TLBSRCH : FmtI32<0b00000110010010000010100000000000, "tlbsrch">; def TLBRD : FmtI32<0b00000110010010000010110000000000, "tlbrd">; diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll b/llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll index c4910ccad4d56..4b38e6ca10906 100644 --- a/llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll @@ -1,5 +1,6 @@ ; RUN: not llc --mtriple=loongarch32 --disable-verify < %s 2>&1 | FileCheck %s +declare void @llvm.loongarch.cacop.w(i32, i32, i32) declare i32 @llvm.loongarch.crc.w.b.w(i32, i32) declare i32 @llvm.loongarch.crc.w.h.w(i32, i32) declare i32 @llvm.loongarch.crc.w.w.w(i32, i32) @@ -18,6 +19,34 @@ declare void @llvm.loongarch.asrtgt.d(i64, i64) declare i64 @llvm.loongarch.lddir.d(i64, i32) declare void @llvm.loongarch.ldpte.d(i64, i32) +define void @cacop_arg0_out_of_hi_range(i32 %a) nounwind { +; CHECK: argument to 'llvm.loongarch.cacop.w' out of range +entry: + call void @llvm.loongarch.cacop.w(i32 32, i32 %a, i32 1024) + ret void +} + +define void @cacop_arg0_out_of_lo_range(i32 %a) nounwind { +; CHECK: argument to 'llvm.loongarch.cacop.w' out of range +entry: + call void @llvm.loongarch.cacop.w(i32 -1, i32 %a, i32 1024) + ret void +} + +define void @cacop_arg2_out_of_hi_range(i32 %a) nounwind { +; CHECK: argument to 'llvm.loongarch.cacop.w' out of range +entry: + call void @llvm.loongarch.cacop.w(i32 1, i32 %a, i32 4096) + ret void +} + +define void @cacop_arg2_out_of_lo_range(i32 %a) nounwind { +; CHECK: argument to 'llvm.loongarch.cacop.w' out of range +entry: + call void @llvm.loongarch.cacop.w(i32 1, i32 %a, i32 -4096) + ret void +} + define i32 @crc_w_b_w(i32 %a, i32 %b) nounwind { ; CHECK: llvm.loongarch.crc.w.b.w requires target: loongarch64 entry: diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-la32.ll b/llvm/test/CodeGen/LoongArch/intrinsic-la32.ll new file mode 100644 index 0000000000000..37e0902625a2c --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/intrinsic-la32.ll @@ -0,0 +1,13 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s + +declare void @llvm.loongarch.cacop.w(i32, i32, i32) + +define void @cacop_w(i32 %a) nounwind { +; CHECK-LABEL: cacop_w: +; CHECK: # %bb.0: +; CHECK-NEXT: cacop 1, $a0, 4 +; CHECK-NEXT: ret + call void @llvm.loongarch.cacop.w(i32 1, i32 %a, i32 4) + ret void +} diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-la64-error.ll b/llvm/test/CodeGen/LoongArch/intrinsic-la64-error.ll index 05eb9f313e24f..51f6c445309ab 100644 --- a/llvm/test/CodeGen/LoongArch/intrinsic-la64-error.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic-la64-error.ll @@ -1,6 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: not llc --mtriple=loongarch64 < %s 2>&1 | FileCheck %s +declare void @llvm.loongarch.cacop.w(i32, i32, i32) +declare void @llvm.loongarch.cacop.d(i64, i64, i64) declare i64 @llvm.loongarch.csrrd.d(i32 immarg) declare i64 @llvm.loongarch.csrwr.d(i64, i32 immarg) declare i64 @llvm.loongarch.csrxchg.d(i64, i64, i32 immarg) @@ -46,3 +48,37 @@ entry: %0 = call i64 @llvm.loongarch.csrxchg.d(i64 %a, i64 %b, i32 -1) ret i64 %0 } + +define void @cacop_w(i32 %a) nounwind { +; CHECK: llvm.loongarch.cacop.w requires target: loongarch32 + call void @llvm.loongarch.cacop.w(i32 1, i32 %a, i32 4) + ret void +} + +define void @cacop_arg0_out_of_hi_range(i64 %a) nounwind { +; CHECK: argument to 'llvm.loongarch.cacop.d' out of range +entry: + call void @llvm.loongarch.cacop.d(i64 32, i64 %a, i64 1024) + ret void +} + +define void @cacop_arg0_out_of_lo_range(i64 %a) nounwind { +; CHECK: argument to 'llvm.loongarch.cacop.d' out of range +entry: + call void @llvm.loongarch.cacop.d(i64 -1, i64 %a, i64 1024) + ret void +} + +define void @cacop_arg2_out_of_hi_range(i64 %a) nounwind { +; CHECK: argument to 'llvm.loongarch.cacop.d' out of range +entry: + call void @llvm.loongarch.cacop.d(i64 1, i64 %a, i64 4096) + ret void +} + +define void @cacop_arg2_out_of_lo_range(i64 %a) nounwind { +; CHECK: argument to 'llvm.loongarch.cacop.d' out of range +entry: + call void @llvm.loongarch.cacop.d(i64 1, i64 %a, i64 -4096) + ret void +} diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll b/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll index 1ec55f341629b..7b28682b5aa97 100644 --- a/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll @@ -1,6 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s +declare void @llvm.loongarch.cacop.d(i64, i64, i64) declare i32 @llvm.loongarch.crc.w.b.w(i32, i32) declare i32 @llvm.loongarch.crc.w.h.w(i32, i32) declare i32 @llvm.loongarch.crc.w.w.w(i32, i32) @@ -46,6 +47,15 @@ define i32 @crc_w_w_w(i32 %a, i32 %b) nounwind { ret i32 %res } +define void @cacop_d(i64 %a) nounwind { +; CHECK-LABEL: cacop_d: +; CHECK: # %bb.0: +; CHECK-NEXT: cacop 1, $a0, 4 +; CHECK-NEXT: ret + call void @llvm.loongarch.cacop.d(i64 1, i64 %a, i64 4) + ret void +} + define i32 @crc_w_d_w(i64 %a, i32 %b) nounwind { ; CHECK-LABEL: crc_w_d_w: ; CHECK: # %bb.0: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits