This revision was automatically updated to reflect the committed changes.
Closed by commit rG9e06d18c80e7: [LoongArch] Add intrinsics for CACOP 
instruction (authored by XiaodongLoong).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D140527/new/

https://reviews.llvm.org/D140527

Files:
  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-la32.ll
  llvm/test/CodeGen/LoongArch/intrinsic-la64-error.ll
  llvm/test/CodeGen/LoongArch/intrinsic-la64.ll

Index: llvm/test/CodeGen/LoongArch/intrinsic-la64.ll
===================================================================
--- llvm/test/CodeGen/LoongArch/intrinsic-la64.ll
+++ 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 @@
   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:
Index: llvm/test/CodeGen/LoongArch/intrinsic-la64-error.ll
===================================================================
--- llvm/test/CodeGen/LoongArch/intrinsic-la64-error.ll
+++ 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 @@
   %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
+}
Index: llvm/test/CodeGen/LoongArch/intrinsic-la32.ll
===================================================================
--- /dev/null
+++ 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
+}
Index: llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll
===================================================================
--- llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll
+++ 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 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:
Index: llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
===================================================================
--- llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -589,6 +589,10 @@
 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 @@
 
 /// 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 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">;
Index: llvm/lib/Target/LoongArch/LoongArchISelLowering.h
===================================================================
--- llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -61,8 +61,10 @@
   BITREV_4B,
   BITREV_W,
 
-  // Intrinsic operations
+  // Intrinsic operations start ============================================
   BREAK,
+  CACOP_D,
+  CACOP_W,
   DBAR,
   IBAR,
   SYSCALL,
@@ -93,6 +95,7 @@
 
   // Read CPU configuration information operation
   CPUCFG,
+  // Intrinsic operations end =============================================
 };
 } // end namespace LoongArchISD
 
Index: llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
===================================================================
--- llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -746,13 +746,38 @@
   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 @@
     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;
Index: llvm/include/llvm/IR/IntrinsicsLoongArch.td
===================================================================
--- llvm/include/llvm/IR/IntrinsicsLoongArch.td
+++ llvm/include/llvm/IR/IntrinsicsLoongArch.td
@@ -52,6 +52,10 @@
 // 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],
Index: clang/test/Driver/loongarch-default-features.c
===================================================================
--- clang/test/Driver/loongarch-default-features.c
+++ 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) {
Index: clang/test/CodeGen/LoongArch/intrinsic-la64.c
===================================================================
--- clang/test/CodeGen/LoongArch/intrinsic-la64.c
+++ clang/test/CodeGen/LoongArch/intrinsic-la64.c
@@ -123,6 +123,17 @@
   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:%.*]])
Index: clang/test/CodeGen/LoongArch/intrinsic-la32.c
===================================================================
--- clang/test/CodeGen/LoongArch/intrinsic-la32.c
+++ clang/test/CodeGen/LoongArch/intrinsic-la32.c
@@ -200,3 +200,14 @@
   __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);
+}
Index: clang/test/CodeGen/LoongArch/intrinsic-la32-error.c
===================================================================
--- clang/test/CodeGen/LoongArch/intrinsic-la32-error.c
+++ 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]}}
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -3705,6 +3705,23 @@
   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:
Index: clang/lib/Headers/larchintrin.h
===================================================================
--- clang/lib/Headers/larchintrin.h
+++ clang/lib/Headers/larchintrin.h
@@ -106,6 +106,16 @@
 
 #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))
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -19694,6 +19694,12 @@
   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;
Index: clang/lib/Basic/Targets/LoongArch.cpp
===================================================================
--- clang/lib/Basic/Targets/LoongArch.cpp
+++ clang/lib/Basic/Targets/LoongArch.cpp
@@ -179,6 +179,8 @@
     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);
 }
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11764,4 +11764,6 @@
 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.
Index: clang/include/clang/Basic/BuiltinsLoongArch.def
===================================================================
--- clang/include/clang/Basic/BuiltinsLoongArch.def
+++ 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")
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to