[clang] [llvm] [RISCV] Add riscv_atomics.h and Zawrs/Zalrsc builtins (PR #94578)

via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 5 22:49:14 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-risc-v

Author: Pengcheng Wang (wangpc-pp)

<details>
<summary>Changes</summary>

`riscv_atomics.h` contains all builtins for atomics.


---

Patch is 26.60 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/94578.diff


14 Files Affected:

- (modified) clang/include/clang/Basic/BuiltinsRISCV.td (+18) 
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+22) 
- (modified) clang/lib/Headers/CMakeLists.txt (+1) 
- (added) clang/lib/Headers/riscv_atomics.h (+36) 
- (modified) clang/lib/Sema/SemaRISCV.cpp (+9-1) 
- (added) clang/test/CodeGen/RISCV/atomics-intrinsics/zalrsc-error.c (+13) 
- (added) clang/test/CodeGen/RISCV/atomics-intrinsics/zalrsc.c (+222) 
- (added) clang/test/CodeGen/RISCV/atomics-intrinsics/zawrs.c (+42) 
- (modified) llvm/include/llvm/IR/IntrinsicsRISCV.td (+32) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoA.td (+25) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZa.td (+4-1) 
- (added) llvm/test/CodeGen/RISCV/zalrsc-rv32.ll (+74) 
- (added) llvm/test/CodeGen/RISCV/zalrsc-rv64.ll (+74) 
- (added) llvm/test/CodeGen/RISCV/zawrs.ll (+33) 


``````````diff
diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td b/clang/include/clang/Basic/BuiltinsRISCV.td
index 4cc89a8a9d8af..458c755179417 100644
--- a/clang/include/clang/Basic/BuiltinsRISCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCV.td
@@ -146,3 +146,21 @@ let Features = "zihintntl", Attributes = [CustomTypeChecking] in {
 def ntl_load : RISCVBuiltin<"void(...)">;
 def ntl_store : RISCVBuiltin<"void(...)">;
 } // Features = "zihintntl", Attributes = [CustomTypeChecking]
+
+//===----------------------------------------------------------------------===//
+// Zawrs extension.
+//===----------------------------------------------------------------------===//
+let Features = "zawrs" in {
+def wrs_nto : RISCVBuiltin<"void()">;
+def wrs_sto : RISCVBuiltin<"void()">;
+} // Features = "zawrs"
+
+//===----------------------------------------------------------------------===//
+// Zalrsc extension.
+//===----------------------------------------------------------------------===//
+let Features = "zalrsc" in {
+def lr_w : RISCVBuiltin<"int(int *, _Constant unsigned int)">;
+def lr_d : RISCVBuiltin<"int64_t(int64_t *, _Constant unsigned int)">;
+def sc_w : RISCVBuiltin<"int(int, int *, _Constant unsigned int)">;
+def sc_d : RISCVBuiltin<"int64_t(int64_t, int64_t *, _Constant unsigned int)">;
+} // Features = "zalrsc"
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 37d0c478e0330..db48c69e10c86 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -21769,6 +21769,28 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     ID = Intrinsic::riscv_sm3p1;
     break;
 
+  // Zawrs
+  case RISCV::BI__builtin_riscv_wrs_nto:
+    ID = Intrinsic::riscv_wrs_nto;
+    break;
+  case RISCV::BI__builtin_riscv_wrs_sto:
+    ID = Intrinsic::riscv_wrs_sto;
+    break;
+
+  // Zalrsc
+  case RISCV::BI__builtin_riscv_lr_w:
+    ID = Intrinsic::riscv_lr_w;
+    break;
+  case RISCV::BI__builtin_riscv_lr_d:
+    ID = Intrinsic::riscv_lr_d;
+    break;
+  case RISCV::BI__builtin_riscv_sc_w:
+    ID = Intrinsic::riscv_sc_w;
+    break;
+  case RISCV::BI__builtin_riscv_sc_d:
+    ID = Intrinsic::riscv_sc_d;
+    break;
+
   // Zihintntl
   case RISCV::BI__builtin_riscv_ntl_load: {
     llvm::Type *ResTy = ConvertType(E->getType());
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index d3090e488306f..cf2fbf1893772 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -118,6 +118,7 @@ set(ppc_htm_files
   )
 
 set(riscv_files
+  riscv_atomics.h
   riscv_bitmanip.h
   riscv_crypto.h
   riscv_ntlh.h
diff --git a/clang/lib/Headers/riscv_atomics.h b/clang/lib/Headers/riscv_atomics.h
new file mode 100644
index 0000000000000..35db57fe36131
--- /dev/null
+++ b/clang/lib/Headers/riscv_atomics.h
@@ -0,0 +1,36 @@
+/*===---- riscv_atomics.h - RISC-V atomics intrinsics ----------------------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_ATOMICS_H
+#define __RISCV_ATOMICS_H
+
+#ifdef __riscv_zalrsc
+enum {
+  __RISCV_ORDER_NONE = 0,
+  __RISCV_ORDER_AQ = 1,
+  __RISCV_ORDER_RL = 2,
+  __RISCV_ORDER_AQ_RL = 3
+};
+
+#define __riscv_lr_w __builtin_riscv_lr_w
+#define __riscv_sc_w __builtin_riscv_sc_w
+
+#if __riscv_xlen == 64
+#define __riscv_lr_d __builtin_riscv_lr_d
+#define __riscv_sc_d __builtin_riscv_sc_d
+#endif
+
+#endif
+
+#ifdef __riscv_zawrs
+#define __riscv_wrs_nto __builtin_riscv_wrs_nto
+#define __riscv_wrs_sto __builtin_riscv_wrs_sto
+#endif
+
+#endif
diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp
index fd4fc15c1fd79..0b69b72cea8bb 100644
--- a/clang/lib/Sema/SemaRISCV.cpp
+++ b/clang/lib/Sema/SemaRISCV.cpp
@@ -1303,7 +1303,7 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI,
   case RISCVVector::BI__builtin_rvv_vfwnmsac_vf_rm_mu:
     return SemaRef.BuiltinConstantArgRange(TheCall, 4, 0, 4);
   case RISCV::BI__builtin_riscv_ntl_load:
-  case RISCV::BI__builtin_riscv_ntl_store:
+  case RISCV::BI__builtin_riscv_ntl_store: {
     DeclRefExpr *DRE =
         cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
     assert((BuiltinID == RISCV::BI__builtin_riscv_ntl_store ||
@@ -1368,6 +1368,14 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI,
     return false;
   }
 
+  case RISCV::BI__builtin_riscv_lr_w:
+  case RISCV::BI__builtin_riscv_lr_d:
+    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3);
+  case RISCV::BI__builtin_riscv_sc_w:
+  case RISCV::BI__builtin_riscv_sc_d:
+    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3);
+  }
+
   return false;
 }
 
diff --git a/clang/test/CodeGen/RISCV/atomics-intrinsics/zalrsc-error.c b/clang/test/CodeGen/RISCV/atomics-intrinsics/zalrsc-error.c
new file mode 100644
index 0000000000000..d274077c9acfd
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/atomics-intrinsics/zalrsc-error.c
@@ -0,0 +1,13 @@
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zalrsc -S -verify %s -o -
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zalrsc -S -verify %s -o -
+
+#include <riscv_atomics.h>
+
+int zalrsc_lr_w(int* ptr) {
+  return __riscv_lr_w(ptr, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+}
+
+int zalrsc_sc_w(int v, int* ptr) {
+  return __riscv_sc_w(v, ptr, 4); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+}
diff --git a/clang/test/CodeGen/RISCV/atomics-intrinsics/zalrsc.c b/clang/test/CodeGen/RISCV/atomics-intrinsics/zalrsc.c
new file mode 100644
index 0000000000000..662ac53ee1e57
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/atomics-intrinsics/zalrsc.c
@@ -0,0 +1,222 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv32 -target-feature +zalrsc -disable-O0-optnone \
+// RUN:   -emit-llvm %s -o - | opt -S -passes=mem2reg | \
+// RUN:   FileCheck --check-prefixes=CHECK-RV32 %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zalrsc -disable-O0-optnone \
+// RUN:   -emit-llvm %s -o - | opt -S -passes=mem2reg | \
+// RUN:   FileCheck --check-prefix=CHECK-RV64 %s
+
+#include <stdint.h>
+#include <riscv_atomics.h>
+
+// CHECK-RV32-LABEL: define dso_local i32 @zalrsc_lr_w_none
+// CHECK-RV32-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV32-NEXT:  entry:
+// CHECK-RV32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.lr.w(ptr [[PTR]], i32 0)
+// CHECK-RV32-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-RV64-LABEL: define dso_local signext i32 @zalrsc_lr_w_none
+// CHECK-RV64-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.lr.w(ptr [[PTR]], i32 0)
+// CHECK-RV64-NEXT:    ret i32 [[TMP0]]
+//
+int zalrsc_lr_w_none(int* ptr) {
+  return __riscv_lr_w(ptr, __RISCV_ORDER_NONE);
+}
+
+// CHECK-RV32-LABEL: define dso_local i32 @zalrsc_lr_w_aq
+// CHECK-RV32-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV32-NEXT:  entry:
+// CHECK-RV32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.lr.w(ptr [[PTR]], i32 1)
+// CHECK-RV32-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-RV64-LABEL: define dso_local signext i32 @zalrsc_lr_w_aq
+// CHECK-RV64-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.lr.w(ptr [[PTR]], i32 1)
+// CHECK-RV64-NEXT:    ret i32 [[TMP0]]
+//
+int zalrsc_lr_w_aq(int* ptr) {
+  return __riscv_lr_w(ptr, __RISCV_ORDER_AQ);
+}
+
+// CHECK-RV32-LABEL: define dso_local i32 @zalrsc_lr_w_rl
+// CHECK-RV32-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV32-NEXT:  entry:
+// CHECK-RV32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.lr.w(ptr [[PTR]], i32 2)
+// CHECK-RV32-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-RV64-LABEL: define dso_local signext i32 @zalrsc_lr_w_rl
+// CHECK-RV64-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.lr.w(ptr [[PTR]], i32 2)
+// CHECK-RV64-NEXT:    ret i32 [[TMP0]]
+//
+int zalrsc_lr_w_rl(int* ptr) {
+  return __riscv_lr_w(ptr, __RISCV_ORDER_RL);
+}
+
+// CHECK-RV32-LABEL: define dso_local i32 @zalrsc_lr_w_aqrl
+// CHECK-RV32-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV32-NEXT:  entry:
+// CHECK-RV32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.lr.w(ptr [[PTR]], i32 3)
+// CHECK-RV32-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-RV64-LABEL: define dso_local signext i32 @zalrsc_lr_w_aqrl
+// CHECK-RV64-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.lr.w(ptr [[PTR]], i32 3)
+// CHECK-RV64-NEXT:    ret i32 [[TMP0]]
+//
+int zalrsc_lr_w_aqrl(int* ptr) {
+  return __riscv_lr_w(ptr, __RISCV_ORDER_AQ_RL);
+}
+
+// CHECK-RV32-LABEL: define dso_local i32 @zalrsc_sc_w_none
+// CHECK-RV32-SAME: (i32 noundef [[V:%.*]], ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV32-NEXT:  entry:
+// CHECK-RV32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.sc.w(i32 [[V]], ptr [[PTR]], i32 0)
+// CHECK-RV32-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-RV64-LABEL: define dso_local signext i32 @zalrsc_sc_w_none
+// CHECK-RV64-SAME: (i32 noundef signext [[V:%.*]], ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.sc.w(i32 [[V]], ptr [[PTR]], i32 0)
+// CHECK-RV64-NEXT:    ret i32 [[TMP0]]
+//
+int zalrsc_sc_w_none(int v, int* ptr) {
+  return __riscv_sc_w(v, ptr, __RISCV_ORDER_NONE);
+}
+
+// CHECK-RV32-LABEL: define dso_local i32 @zalrsc_sc_w_aq
+// CHECK-RV32-SAME: (i32 noundef [[V:%.*]], ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV32-NEXT:  entry:
+// CHECK-RV32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.sc.w(i32 [[V]], ptr [[PTR]], i32 1)
+// CHECK-RV32-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-RV64-LABEL: define dso_local signext i32 @zalrsc_sc_w_aq
+// CHECK-RV64-SAME: (i32 noundef signext [[V:%.*]], ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.sc.w(i32 [[V]], ptr [[PTR]], i32 1)
+// CHECK-RV64-NEXT:    ret i32 [[TMP0]]
+//
+int zalrsc_sc_w_aq(int v, int* ptr) {
+  return __riscv_sc_w(v, ptr, __RISCV_ORDER_AQ);
+}
+
+// CHECK-RV32-LABEL: define dso_local i32 @zalrsc_sc_w_rl
+// CHECK-RV32-SAME: (i32 noundef [[V:%.*]], ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV32-NEXT:  entry:
+// CHECK-RV32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.sc.w(i32 [[V]], ptr [[PTR]], i32 2)
+// CHECK-RV32-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-RV64-LABEL: define dso_local signext i32 @zalrsc_sc_w_rl
+// CHECK-RV64-SAME: (i32 noundef signext [[V:%.*]], ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.sc.w(i32 [[V]], ptr [[PTR]], i32 2)
+// CHECK-RV64-NEXT:    ret i32 [[TMP0]]
+//
+int zalrsc_sc_w_rl(int v, int* ptr) {
+  return __riscv_sc_w(v, ptr, __RISCV_ORDER_RL);
+}
+
+// CHECK-RV32-LABEL: define dso_local i32 @zalrsc_sc_w_aqrl
+// CHECK-RV32-SAME: (i32 noundef [[V:%.*]], ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV32-NEXT:  entry:
+// CHECK-RV32-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.sc.w(i32 [[V]], ptr [[PTR]], i32 3)
+// CHECK-RV32-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-RV64-LABEL: define dso_local signext i32 @zalrsc_sc_w_aqrl
+// CHECK-RV64-SAME: (i32 noundef signext [[V:%.*]], ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.sc.w(i32 [[V]], ptr [[PTR]], i32 3)
+// CHECK-RV64-NEXT:    ret i32 [[TMP0]]
+//
+int zalrsc_sc_w_aqrl(int v, int* ptr) {
+  return __riscv_sc_w(v, ptr, __RISCV_ORDER_AQ_RL);
+}
+
+#if __riscv_xlen == 64
+// CHECK-RV64-LABEL: define dso_local i64 @zalrsc_lr_d_none
+// CHECK-RV64-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.riscv.lr.d(ptr [[PTR]], i32 0)
+// CHECK-RV64-NEXT:    ret i64 [[TMP0]]
+//
+int64_t zalrsc_lr_d_none(int64_t* ptr) {
+  return __riscv_lr_d(ptr, __RISCV_ORDER_NONE);
+}
+
+// CHECK-RV64-LABEL: define dso_local i64 @zalrsc_lr_d_aq
+// CHECK-RV64-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.riscv.lr.d(ptr [[PTR]], i32 1)
+// CHECK-RV64-NEXT:    ret i64 [[TMP0]]
+//
+int64_t zalrsc_lr_d_aq(int64_t* ptr) {
+  return __riscv_lr_d(ptr, __RISCV_ORDER_AQ);
+}
+
+// CHECK-RV64-LABEL: define dso_local i64 @zalrsc_lr_d_rl
+// CHECK-RV64-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.riscv.lr.d(ptr [[PTR]], i32 2)
+// CHECK-RV64-NEXT:    ret i64 [[TMP0]]
+//
+int64_t zalrsc_lr_d_rl(int64_t* ptr) {
+  return __riscv_lr_d(ptr, __RISCV_ORDER_RL);
+}
+
+// CHECK-RV64-LABEL: define dso_local i64 @zalrsc_lr_d_aqrl
+// CHECK-RV64-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.riscv.lr.d(ptr [[PTR]], i32 3)
+// CHECK-RV64-NEXT:    ret i64 [[TMP0]]
+//
+int64_t zalrsc_lr_d_aqrl(int64_t* ptr) {
+  return __riscv_lr_d(ptr, __RISCV_ORDER_AQ_RL);
+}
+
+// CHECK-RV64-LABEL: define dso_local i64 @zalrsc_sc_d_none
+// CHECK-RV64-SAME: (i64 noundef [[V:%.*]], ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.riscv.sc.d(i64 [[V]], ptr [[PTR]], i32 0)
+// CHECK-RV64-NEXT:    ret i64 [[TMP0]]
+//
+int64_t zalrsc_sc_d_none(int64_t v, int64_t* ptr) {
+  return __riscv_sc_d(v, ptr, __RISCV_ORDER_NONE);
+}
+
+// CHECK-RV64-LABEL: define dso_local i64 @zalrsc_sc_d_aq
+// CHECK-RV64-SAME: (i64 noundef [[V:%.*]], ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.riscv.sc.d(i64 [[V]], ptr [[PTR]], i32 1)
+// CHECK-RV64-NEXT:    ret i64 [[TMP0]]
+//
+int64_t zalrsc_sc_d_aq(int64_t v, int64_t* ptr) {
+  return __riscv_sc_d(v, ptr, __RISCV_ORDER_AQ);
+}
+
+// CHECK-RV64-LABEL: define dso_local i64 @zalrsc_sc_d_rl
+// CHECK-RV64-SAME: (i64 noundef [[V:%.*]], ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.riscv.sc.d(i64 [[V]], ptr [[PTR]], i32 2)
+// CHECK-RV64-NEXT:    ret i64 [[TMP0]]
+//
+int64_t zalrsc_sc_d_rl(int64_t v, int64_t* ptr) {
+  return __riscv_sc_d(v, ptr, __RISCV_ORDER_RL);
+}
+
+// CHECK-RV64-LABEL: define dso_local i64 @zalrsc_sc_d_aqrl
+// CHECK-RV64-SAME: (i64 noundef [[V:%.*]], ptr noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    [[TMP0:%.*]] = call i64 @llvm.riscv.sc.d(i64 [[V]], ptr [[PTR]], i32 3)
+// CHECK-RV64-NEXT:    ret i64 [[TMP0]]
+//
+int64_t zalrsc_sc_d_aqrl(int64_t v, int64_t* ptr) {
+  return __riscv_sc_d(v, ptr, __RISCV_ORDER_AQ_RL);
+}
+
+#endif
diff --git a/clang/test/CodeGen/RISCV/atomics-intrinsics/zawrs.c b/clang/test/CodeGen/RISCV/atomics-intrinsics/zawrs.c
new file mode 100644
index 0000000000000..998655e67a160
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/atomics-intrinsics/zawrs.c
@@ -0,0 +1,42 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv32 -target-feature +zawrs -disable-O0-optnone \
+// RUN:   -emit-llvm %s -o - | opt -S -passes=mem2reg | \
+// RUN:   FileCheck --check-prefixes=CHECK-RV32 %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zawrs -disable-O0-optnone \
+// RUN:   -emit-llvm %s -o - | opt -S -passes=mem2reg | \
+// RUN:   FileCheck --check-prefix=CHECK-RV64 %s
+
+#include <riscv_atomics.h>
+
+// CHECK-RV32-LABEL: define dso_local void @zawrs_nto
+// CHECK-RV32-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK-RV32-NEXT:  entry:
+// CHECK-RV32-NEXT:    call void @llvm.riscv.wrs.nto()
+// CHECK-RV32-NEXT:    ret void
+//
+// CHECK-RV64-LABEL: define dso_local void @zawrs_nto
+// CHECK-RV64-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    call void @llvm.riscv.wrs.nto()
+// CHECK-RV64-NEXT:    ret void
+//
+void zawrs_nto(){
+  __riscv_wrs_nto();
+}
+
+// CHECK-RV32-LABEL: define dso_local void @zawrs_sto
+// CHECK-RV32-SAME: () #[[ATTR0]] {
+// CHECK-RV32-NEXT:  entry:
+// CHECK-RV32-NEXT:    call void @llvm.riscv.wrs.sto()
+// CHECK-RV32-NEXT:    ret void
+//
+// CHECK-RV64-LABEL: define dso_local void @zawrs_sto
+// CHECK-RV64-SAME: () #[[ATTR0]] {
+// CHECK-RV64-NEXT:  entry:
+// CHECK-RV64-NEXT:    call void @llvm.riscv.wrs.sto()
+// CHECK-RV64-NEXT:    ret void
+//
+void zawrs_sto(){
+  __riscv_wrs_sto();
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td
index 4c4e7351212f8..c9a0e75645694 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td
@@ -124,6 +124,38 @@ let TargetPrefix = "riscv" in {
                               [IntrNoMem, IntrSpeculatable, ImmArg<ArgIndex<2>>]>;
 } // TargetPrefix = "riscv"
 
+//===----------------------------------------------------------------------===//
+// 'Zawrs' (Wait on Reservation Set)
+
+let TargetPrefix = "riscv" in {
+  def int_riscv_wrs_nto
+      : DefaultAttrsIntrinsic<[], [], [IntrHasSideEffects]>;
+  def int_riscv_wrs_sto
+      : DefaultAttrsIntrinsic<[], [], [IntrHasSideEffects]>;
+} // TargetPrefix = "riscv"
+
+//===----------------------------------------------------------------------===//
+// 'Zalrsc' (Load-Reserved/Store-Conditional)
+
+let TargetPrefix = "riscv" in {
+  def int_riscv_lr_w
+      : DefaultAttrsIntrinsic<[llvm_i32_ty],
+                              [llvm_ptr_ty, llvm_i32_ty],
+                              [IntrReadMem, ImmArg<ArgIndex<1>>]>;
+  def int_riscv_lr_d
+      : DefaultAttrsIntrinsic<[llvm_i64_ty],
+                              [llvm_ptr_ty, llvm_i32_ty],
+                              [IntrReadMem, ImmArg<ArgIndex<1>>]>;
+  def int_riscv_sc_w
+      : DefaultAttrsIntrinsic<[llvm_i32_ty],
+                              [llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty],
+                              [IntrWriteMem, ImmArg<ArgIndex<2>>]>;
+  def int_riscv_sc_d
+      : DefaultAttrsIntrinsic<[llvm_i64_ty],
+                              [llvm_i64_ty, llvm_ptr_ty, llvm_i32_ty],
+                              [IntrWriteMem, ImmArg<ArgIndex<2>>]>;
+} // TargetPrefix = "riscv"
+
 //===----------------------------------------------------------------------===//
 // Vectors
 
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
index 814e0ddf111e6..5dbf954995bed 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
@@ -136,6 +136,31 @@ let Predicates = [HasAtomicLdSt, IsRV64] in {
   def : StPat<atomic_store_64, SD, GPR, i64>;
 }
 
+/// LR/SC intrinsics patterns
+multiclass LRPat<Intrinsic intrinsic, string inst> {
+  def : Pat<(intrinsic GPR:$src, 0), (!cast<Instruction>(inst) GPR:$src)>;
+  def : Pat<(intrinsic GPR:$src, 1), (!cast<Instruction>(inst # "_AQ") GPR:$src)>;
+  def : Pat<(intrinsic GPR:$src, 2), (!cast<Instruction>(inst # "_RL") GPR:$src)>;
+  def : Pat<(intrinsic GPR:$src, 3), (!cast<Instruction>(inst # "_AQ_RL") GPR:$src)>;
+}
+
+multiclass SCPat<Intrinsic intrinsic, string inst> {
+  def : Pat<(intrinsic GPR:$src, GPR:$dst, 0), (!cast<Instruction>(inst) GPR:$src, GPR:$dst)>;
+  def : Pat<(intrinsic GPR:$src, GPR:$dst, 1), (!cast<Instruction>(inst # "_AQ") GPR:$src, GPR:$dst)>;
+  def : Pat<(intrinsic GPR:$src, GPR:$dst, 2), (!cast<Instruction>(inst # "_RL") GPR:$src, GPR:$dst)>;
+  def : Pat<(intrinsic GPR:$src, GPR:$dst, 3), (!cast<Instruction>(inst # "_AQ_RL") GPR:$src, GPR:$dst)>;
+}
+
+let Predicates = [HasStdExtAOrZalrsc] in {
+  defm : LRPat<int_riscv_lr_w, "LR_W">;
+  defm : SCPat<int_riscv_sc_w, "SC_W">;
+} // Predicates = [HasStdExtAOrZalrsc]
+
+let Predicates = [HasStdExtAOrZalrsc, IsRV64] in {
+  defm : LRPat<int_riscv_lr_d, "LR_D">;
+  defm :...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/94578


More information about the cfe-commits mailing list