[clang] 9e06d18 - [LoongArch] Add intrinsics for CACOP instruction
Xiaodong Liu via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 5 19:44:46 PST 2023
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:
More information about the cfe-commits
mailing list