[llvm] 0486120 - [Clang][LoongArch] Add intrinsic for iocsrrd and iocsrwr

via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 9 22:10:45 PST 2022


Author: gonglingqin
Date: 2022-12-10T14:05:19+08:00
New Revision: 048612050a2fc0a89b84632a48da0d86f0d13646

URL: https://github.com/llvm/llvm-project/commit/048612050a2fc0a89b84632a48da0d86f0d13646
DIFF: https://github.com/llvm/llvm-project/commit/048612050a2fc0a89b84632a48da0d86f0d13646.diff

LOG: [Clang][LoongArch] Add intrinsic for iocsrrd and iocsrwr

These intrinsics are required by Linux [1].

[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/include/asm/loongarch.h#n240

Differential Revision: https://reviews.llvm.org/D139612

Added: 
    

Modified: 
    clang/include/clang/Basic/BuiltinsLoongArch.def
    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
    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.ll
    llvm/test/CodeGen/LoongArch/intrinsic.ll

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/BuiltinsLoongArch.def b/clang/include/clang/Basic/BuiltinsLoongArch.def
index fa4aaffa5ff71..5b0dd799a4bcd 100644
--- a/clang/include/clang/Basic/BuiltinsLoongArch.def
+++ b/clang/include/clang/Basic/BuiltinsLoongArch.def
@@ -38,5 +38,14 @@ TARGET_BUILTIN(__builtin_loongarch_csrwr_d, "ULiULiIUi", "nc", "64bit")
 TARGET_BUILTIN(__builtin_loongarch_csrxchg_w, "UiUiUiIUi", "nc", "")
 TARGET_BUILTIN(__builtin_loongarch_csrxchg_d, "ULiULiULiIUi", "nc", "64bit")
 
+TARGET_BUILTIN(__builtin_loongarch_iocsrrd_b, "UiUi", "nc", "")
+TARGET_BUILTIN(__builtin_loongarch_iocsrrd_h, "UiUi", "nc", "")
+TARGET_BUILTIN(__builtin_loongarch_iocsrrd_w, "UiUi", "nc", "")
+TARGET_BUILTIN(__builtin_loongarch_iocsrrd_d, "ULiUi", "nc", "64bit")
+TARGET_BUILTIN(__builtin_loongarch_iocsrwr_b, "vUiUi", "nc", "")
+TARGET_BUILTIN(__builtin_loongarch_iocsrwr_h, "vUiUi", "nc", "")
+TARGET_BUILTIN(__builtin_loongarch_iocsrwr_w, "vUiUi", "nc", "")
+TARGET_BUILTIN(__builtin_loongarch_iocsrwr_d, "vULiUi", "nc", "64bit")
+
 #undef BUILTIN
 #undef TARGET_BUILTIN

diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 9650b9ce978f7..be1ce2796c8aa 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19718,6 +19718,30 @@ Value *CodeGenFunction::EmitLoongArchBuiltinExpr(unsigned BuiltinID,
   case LoongArch::BI__builtin_loongarch_csrxchg_d:
     ID = Intrinsic::loongarch_csrxchg_d;
     break;
+  case LoongArch::BI__builtin_loongarch_iocsrrd_b:
+    ID = Intrinsic::loongarch_iocsrrd_b;
+    break;
+  case LoongArch::BI__builtin_loongarch_iocsrrd_h:
+    ID = Intrinsic::loongarch_iocsrrd_h;
+    break;
+  case LoongArch::BI__builtin_loongarch_iocsrrd_w:
+    ID = Intrinsic::loongarch_iocsrrd_w;
+    break;
+  case LoongArch::BI__builtin_loongarch_iocsrrd_d:
+    ID = Intrinsic::loongarch_iocsrrd_d;
+    break;
+  case LoongArch::BI__builtin_loongarch_iocsrwr_b:
+    ID = Intrinsic::loongarch_iocsrwr_b;
+    break;
+  case LoongArch::BI__builtin_loongarch_iocsrwr_h:
+    ID = Intrinsic::loongarch_iocsrwr_h;
+    break;
+  case LoongArch::BI__builtin_loongarch_iocsrwr_w:
+    ID = Intrinsic::loongarch_iocsrwr_w;
+    break;
+  case LoongArch::BI__builtin_loongarch_iocsrwr_d:
+    ID = Intrinsic::loongarch_iocsrwr_d;
+    break;
     // TODO: Support more Intrinsics.
   }
 

diff  --git a/clang/lib/Headers/larchintrin.h b/clang/lib/Headers/larchintrin.h
index 02c31657a2bc9..787b7b8deda2d 100644
--- a/clang/lib/Headers/larchintrin.h
+++ b/clang/lib/Headers/larchintrin.h
@@ -95,6 +95,58 @@ extern __inline int
       (unsigned long int)(_1), (unsigned long int)(_2), (_3)))
 #endif
 
+extern __inline unsigned char
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+    __iocsrrd_b(unsigned int _1) {
+  return (unsigned char)__builtin_loongarch_iocsrrd_b((unsigned int)_1);
+}
+
+extern __inline unsigned char
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+    __iocsrrd_h(unsigned int _1) {
+  return (unsigned short)__builtin_loongarch_iocsrrd_h((unsigned int)_1);
+}
+
+extern __inline unsigned int
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+    __iocsrrd_w(unsigned int _1) {
+  return (unsigned int)__builtin_loongarch_iocsrrd_w((unsigned int)_1);
+}
+
+#if __loongarch_grlen == 64
+extern __inline unsigned long int
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+    __iocsrrd_d(unsigned int _1) {
+  return (unsigned long int)__builtin_loongarch_iocsrrd_d((unsigned int)_1);
+}
+#endif
+
+extern __inline void
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+    __iocsrwr_b(unsigned char _1, unsigned int _2) {
+  __builtin_loongarch_iocsrwr_b((unsigned char)_1, (unsigned int)_2);
+}
+
+extern __inline void
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+    __iocsrwr_h(unsigned short _1, unsigned int _2) {
+  __builtin_loongarch_iocsrwr_h((unsigned short)_1, (unsigned int)_2);
+}
+
+extern __inline void
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+    __iocsrwr_w(unsigned int _1, unsigned int _2) {
+  __builtin_loongarch_iocsrwr_w((unsigned int)_1, (unsigned int)_2);
+}
+
+#if __loongarch_grlen == 64
+extern __inline void
+    __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+    __iocsrwr_d(unsigned long int _1, unsigned int _2) {
+  __builtin_loongarch_iocsrwr_d((unsigned long int)_1, (unsigned int)_2);
+}
+#endif
+
 #ifdef __cplusplus
 }
 #endif

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 4b3b52db52956..48a11b853ec20 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3712,6 +3712,8 @@ bool Sema::CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI,
   case LoongArch::BI__builtin_loongarch_crcc_w_h_w:
   case LoongArch::BI__builtin_loongarch_crcc_w_w_w:
   case LoongArch::BI__builtin_loongarch_crcc_w_d_w:
+  case LoongArch::BI__builtin_loongarch_iocsrrd_d:
+  case LoongArch::BI__builtin_loongarch_iocsrwr_d:
     if (!TI.hasFeature("64bit"))
       return Diag(TheCall->getBeginLoc(),
                   diag::err_loongarch_builtin_requires_la64)

diff  --git a/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c b/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c
index 633a32fc919da..be4f319e884df 100644
--- a/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c
+++ b/clang/test/CodeGen/LoongArch/intrinsic-la32-error.c
@@ -87,3 +87,11 @@ void csrxchg_w(unsigned int a, unsigned int b) {
     __builtin_loongarch_csrxchg_w(a, b, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 16383]}}
     __builtin_loongarch_csrxchg_w(a, b, b); // expected-error {{argument to '__builtin_loongarch_csrxchg_w' must be a constant integer}}
 }
+
+unsigned long int iocsrrd_d(unsigned int a) {
+  return __builtin_loongarch_iocsrrd_d(a); // expected-error {{this builtin requires target: loongarch64}}
+}
+
+void iocsrwr_d(unsigned long int a, unsigned int b) {
+  __builtin_loongarch_iocsrwr_d(a, b); // expected-error {{this builtin requires target: loongarch64}}
+}

diff  --git a/clang/test/CodeGen/LoongArch/intrinsic-la32.c b/clang/test/CodeGen/LoongArch/intrinsic-la32.c
index 4d973d4a65691..d9c201f05141c 100644
--- a/clang/test/CodeGen/LoongArch/intrinsic-la32.c
+++ b/clang/test/CodeGen/LoongArch/intrinsic-la32.c
@@ -107,3 +107,157 @@ unsigned int csrxchg_w(unsigned int a, unsigned int b) {
   unsigned int d = __builtin_loongarch_csrxchg_w(a, b, 1);
   return 0;
 }
+
+// LA32-LABEL: @iocsrrd_b(
+// LA32-NEXT:  entry:
+// LA32-NEXT:    [[_1_ADDR_I:%.*]] = alloca i32, align 4
+// LA32-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// LA32-NEXT:    [[B:%.*]] = alloca i8, align 1
+// LA32-NEXT:    [[C:%.*]] = alloca i8, align 1
+// LA32-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// LA32-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// LA32-NEXT:    store i32 [[TMP0]], ptr [[_1_ADDR_I]], align 4
+// LA32-NEXT:    [[TMP1:%.*]] = load i32, ptr [[_1_ADDR_I]], align 4
+// LA32-NEXT:    [[TMP2:%.*]] = call i32 @llvm.loongarch.iocsrrd.b(i32 [[TMP1]])
+// LA32-NEXT:    [[CONV_I:%.*]] = trunc i32 [[TMP2]] to i8
+// LA32-NEXT:    store i8 [[CONV_I]], ptr [[B]], align 1
+// LA32-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// LA32-NEXT:    [[TMP4:%.*]] = call i32 @llvm.loongarch.iocsrrd.b(i32 [[TMP3]])
+// LA32-NEXT:    [[CONV:%.*]] = trunc i32 [[TMP4]] to i8
+// LA32-NEXT:    store i8 [[CONV]], ptr [[C]], align 1
+// LA32-NEXT:    ret i8 0
+//
+unsigned char iocsrrd_b(unsigned int a) {
+  unsigned char b = __iocsrrd_b(a);
+  unsigned char c = __builtin_loongarch_iocsrrd_b(a);
+  return 0;
+}
+
+// LA32-LABEL: @iocsrrd_h(
+// LA32-NEXT:  entry:
+// LA32-NEXT:    [[_1_ADDR_I:%.*]] = alloca i32, align 4
+// LA32-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// LA32-NEXT:    [[B:%.*]] = alloca i16, align 2
+// LA32-NEXT:    [[C:%.*]] = alloca i16, align 2
+// LA32-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// LA32-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// LA32-NEXT:    store i32 [[TMP0]], ptr [[_1_ADDR_I]], align 4
+// LA32-NEXT:    [[TMP1:%.*]] = load i32, ptr [[_1_ADDR_I]], align 4
+// LA32-NEXT:    [[TMP2:%.*]] = call i32 @llvm.loongarch.iocsrrd.h(i32 [[TMP1]])
+// LA32-NEXT:    [[CONV_I:%.*]] = trunc i32 [[TMP2]] to i16
+// LA32-NEXT:    [[CONV1_I:%.*]] = trunc i16 [[CONV_I]] to i8
+// LA32-NEXT:    [[CONV:%.*]] = zext i8 [[CONV1_I]] to i16
+// LA32-NEXT:    store i16 [[CONV]], ptr [[B]], align 2
+// LA32-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// LA32-NEXT:    [[TMP4:%.*]] = call i32 @llvm.loongarch.iocsrrd.h(i32 [[TMP3]])
+// LA32-NEXT:    [[CONV1:%.*]] = trunc i32 [[TMP4]] to i16
+// LA32-NEXT:    store i16 [[CONV1]], ptr [[C]], align 2
+// LA32-NEXT:    ret i16 0
+//
+unsigned short iocsrrd_h(unsigned int a) {
+  unsigned short b = __iocsrrd_h(a);
+  unsigned short c = __builtin_loongarch_iocsrrd_h(a);
+  return 0;
+}
+
+// LA32-LABEL: @iocsrrd_w(
+// LA32-NEXT:  entry:
+// LA32-NEXT:    [[_1_ADDR_I:%.*]] = alloca i32, align 4
+// LA32-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// LA32-NEXT:    [[B:%.*]] = alloca i32, align 4
+// LA32-NEXT:    [[C:%.*]] = alloca i32, align 4
+// LA32-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// LA32-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// LA32-NEXT:    store i32 [[TMP0]], ptr [[_1_ADDR_I]], align 4
+// LA32-NEXT:    [[TMP1:%.*]] = load i32, ptr [[_1_ADDR_I]], align 4
+// LA32-NEXT:    [[TMP2:%.*]] = call i32 @llvm.loongarch.iocsrrd.w(i32 [[TMP1]])
+// LA32-NEXT:    store i32 [[TMP2]], ptr [[B]], align 4
+// LA32-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// LA32-NEXT:    [[TMP4:%.*]] = call i32 @llvm.loongarch.iocsrrd.w(i32 [[TMP3]])
+// LA32-NEXT:    store i32 [[TMP4]], ptr [[C]], align 4
+// LA32-NEXT:    ret i32 0
+//
+unsigned int iocsrrd_w(unsigned int a) {
+  unsigned int b = __iocsrrd_w(a);
+  unsigned int c = __builtin_loongarch_iocsrrd_w(a);
+  return 0;
+}
+
+// LA32-LABEL: @iocsrwr_b(
+// LA32-NEXT:  entry:
+// LA32-NEXT:    [[_1_ADDR_I:%.*]] = alloca i8, align 1
+// LA32-NEXT:    [[_2_ADDR_I:%.*]] = alloca i32, align 4
+// LA32-NEXT:    [[A_ADDR:%.*]] = alloca i8, align 1
+// LA32-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// LA32-NEXT:    store i8 [[A:%.*]], ptr [[A_ADDR]], align 1
+// LA32-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// LA32-NEXT:    [[TMP0:%.*]] = load i8, ptr [[A_ADDR]], align 1
+// LA32-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// LA32-NEXT:    store i8 [[TMP0]], ptr [[_1_ADDR_I]], align 1
+// LA32-NEXT:    store i32 [[TMP1]], ptr [[_2_ADDR_I]], align 4
+// LA32-NEXT:    [[TMP2:%.*]] = load i8, ptr [[_1_ADDR_I]], align 1
+// LA32-NEXT:    [[CONV_I:%.*]] = zext i8 [[TMP2]] to i32
+// LA32-NEXT:    [[TMP3:%.*]] = load i32, ptr [[_2_ADDR_I]], align 4
+// LA32-NEXT:    call void @llvm.loongarch.iocsrwr.b(i32 [[CONV_I]], i32 [[TMP3]])
+// LA32-NEXT:    [[TMP4:%.*]] = load i8, ptr [[A_ADDR]], align 1
+// LA32-NEXT:    [[CONV:%.*]] = zext i8 [[TMP4]] to i32
+// LA32-NEXT:    [[TMP5:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// LA32-NEXT:    call void @llvm.loongarch.iocsrwr.b(i32 [[CONV]], i32 [[TMP5]])
+// LA32-NEXT:    ret void
+//
+void iocsrwr_b(unsigned char a, unsigned int b) {
+  __iocsrwr_b(a, b);
+  __builtin_loongarch_iocsrwr_b(a, b);
+}
+
+// LA32-LABEL: @iocsrwr_h(
+// LA32-NEXT:  entry:
+// LA32-NEXT:    [[_1_ADDR_I:%.*]] = alloca i16, align 2
+// LA32-NEXT:    [[_2_ADDR_I:%.*]] = alloca i32, align 4
+// LA32-NEXT:    [[A_ADDR:%.*]] = alloca i16, align 2
+// LA32-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// LA32-NEXT:    store i16 [[A:%.*]], ptr [[A_ADDR]], align 2
+// LA32-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// LA32-NEXT:    [[TMP0:%.*]] = load i16, ptr [[A_ADDR]], align 2
+// LA32-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// LA32-NEXT:    store i16 [[TMP0]], ptr [[_1_ADDR_I]], align 2
+// LA32-NEXT:    store i32 [[TMP1]], ptr [[_2_ADDR_I]], align 4
+// LA32-NEXT:    [[TMP2:%.*]] = load i16, ptr [[_1_ADDR_I]], align 2
+// LA32-NEXT:    [[CONV_I:%.*]] = zext i16 [[TMP2]] to i32
+// LA32-NEXT:    [[TMP3:%.*]] = load i32, ptr [[_2_ADDR_I]], align 4
+// LA32-NEXT:    call void @llvm.loongarch.iocsrwr.h(i32 [[CONV_I]], i32 [[TMP3]])
+// LA32-NEXT:    [[TMP4:%.*]] = load i16, ptr [[A_ADDR]], align 2
+// LA32-NEXT:    [[CONV:%.*]] = zext i16 [[TMP4]] to i32
+// LA32-NEXT:    [[TMP5:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// LA32-NEXT:    call void @llvm.loongarch.iocsrwr.h(i32 [[CONV]], i32 [[TMP5]])
+// LA32-NEXT:    ret void
+//
+void iocsrwr_h(unsigned short a, unsigned int b) {
+  __iocsrwr_h(a, b);
+  __builtin_loongarch_iocsrwr_h(a, b);
+}
+
+// LA32-LABEL: @iocsrwr_w(
+// LA32-NEXT:  entry:
+// LA32-NEXT:    [[_1_ADDR_I:%.*]] = alloca i32, align 4
+// LA32-NEXT:    [[_2_ADDR_I:%.*]] = alloca i32, align 4
+// LA32-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// LA32-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// LA32-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// LA32-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// LA32-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// LA32-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// LA32-NEXT:    store i32 [[TMP0]], ptr [[_1_ADDR_I]], align 4
+// LA32-NEXT:    store i32 [[TMP1]], ptr [[_2_ADDR_I]], align 4
+// LA32-NEXT:    [[TMP2:%.*]] = load i32, ptr [[_1_ADDR_I]], align 4
+// LA32-NEXT:    [[TMP3:%.*]] = load i32, ptr [[_2_ADDR_I]], align 4
+// LA32-NEXT:    call void @llvm.loongarch.iocsrwr.w(i32 [[TMP2]], i32 [[TMP3]])
+// LA32-NEXT:    [[TMP4:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// LA32-NEXT:    [[TMP5:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// LA32-NEXT:    call void @llvm.loongarch.iocsrwr.w(i32 [[TMP4]], i32 [[TMP5]])
+// LA32-NEXT:    ret void
+//
+void iocsrwr_w(unsigned int a, unsigned int b) {
+  __iocsrwr_w(a, b);
+  __builtin_loongarch_iocsrwr_w(a, b);
+}

diff  --git a/clang/test/CodeGen/LoongArch/intrinsic-la64.c b/clang/test/CodeGen/LoongArch/intrinsic-la64.c
index 97b93a6077c0b..4497fae66a75a 100644
--- a/clang/test/CodeGen/LoongArch/intrinsic-la64.c
+++ b/clang/test/CodeGen/LoongArch/intrinsic-la64.c
@@ -222,3 +222,97 @@ unsigned long int csrxchg_d(unsigned long int a, unsigned long int b) {
   unsigned long int d = __builtin_loongarch_csrxchg_d(a, b, 1);
   return 0;
 }
+
+// CHECK-LABEL: @iocsrrd_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call i32 @llvm.loongarch.iocsrrd.b(i32 [[A:%.*]])
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call i32 @llvm.loongarch.iocsrrd.b(i32 [[A]])
+// CHECK-NEXT:    ret i8 0
+//
+unsigned char iocsrrd_b(unsigned int a) {
+  unsigned char b = __iocsrrd_b(a);
+  unsigned char c = __builtin_loongarch_iocsrrd_b(a);
+  return 0;
+}
+
+// CHECK-LABEL: @iocsrrd_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call i32 @llvm.loongarch.iocsrrd.h(i32 [[A:%.*]])
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call i32 @llvm.loongarch.iocsrrd.h(i32 [[A]])
+// CHECK-NEXT:    ret i16 0
+//
+unsigned short iocsrrd_h(unsigned int a) {
+  unsigned short b = __iocsrrd_h(a);
+  unsigned short c = __builtin_loongarch_iocsrrd_h(a);
+  return 0;
+}
+
+// CHECK-LABEL: @iocsrrd_w(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call i32 @llvm.loongarch.iocsrrd.w(i32 [[A:%.*]])
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call i32 @llvm.loongarch.iocsrrd.w(i32 [[A]])
+// CHECK-NEXT:    ret i32 0
+//
+unsigned int iocsrrd_w(unsigned int a) {
+  unsigned int b = __iocsrrd_w(a);
+  unsigned int c = __builtin_loongarch_iocsrrd_w(a);
+  return 0;
+}
+
+// CHECK-LABEL: @iocsrwr_b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[CONV_I:%.*]] = zext i8 [[A:%.*]] to i32
+// CHECK-NEXT:    tail call void @llvm.loongarch.iocsrwr.b(i32 [[CONV_I]], i32 [[B:%.*]])
+// CHECK-NEXT:    tail call void @llvm.loongarch.iocsrwr.b(i32 [[CONV_I]], i32 [[B]])
+// CHECK-NEXT:    ret void
+//
+void iocsrwr_b(unsigned char a, unsigned int b) {
+  __iocsrwr_b(a, b);
+  __builtin_loongarch_iocsrwr_b(a, b);
+}
+
+// CHECK-LABEL: @iocsrwr_h(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[CONV_I:%.*]] = zext i16 [[A:%.*]] to i32
+// CHECK-NEXT:    tail call void @llvm.loongarch.iocsrwr.h(i32 [[CONV_I]], i32 [[B:%.*]])
+// CHECK-NEXT:    tail call void @llvm.loongarch.iocsrwr.h(i32 [[CONV_I]], i32 [[B]])
+// CHECK-NEXT:    ret void
+//
+void iocsrwr_h(unsigned short a, unsigned int b) {
+  __iocsrwr_h(a, b);
+  __builtin_loongarch_iocsrwr_h(a, b);
+}
+
+// CHECK-LABEL: @iocsrwr_w(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    tail call void @llvm.loongarch.iocsrwr.w(i32 [[A:%.*]], i32 [[B:%.*]])
+// CHECK-NEXT:    tail call void @llvm.loongarch.iocsrwr.w(i32 [[A]], i32 [[B]])
+// CHECK-NEXT:    ret void
+//
+void iocsrwr_w(unsigned int a, unsigned int b) {
+  __iocsrwr_w(a, b);
+  __builtin_loongarch_iocsrwr_w(a, b);
+}
+
+// CHECK-LABEL: @iocsrrd_d(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call i64 @llvm.loongarch.iocsrrd.d(i32 [[A:%.*]])
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call i64 @llvm.loongarch.iocsrrd.d(i32 [[A]])
+// CHECK-NEXT:    ret i64 0
+//
+unsigned long int iocsrrd_d(unsigned int a) {
+  unsigned long int b = __iocsrrd_d(a);
+  unsigned long int c = __builtin_loongarch_iocsrrd_d(a);
+  return 0;
+}
+
+// CHECK-LABEL: @iocsrwr_d(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    tail call void @llvm.loongarch.iocsrwr.d(i64 [[A:%.*]], i32 [[B:%.*]])
+// CHECK-NEXT:    tail call void @llvm.loongarch.iocsrwr.d(i64 [[A]], i32 [[B]])
+// CHECK-NEXT:    ret void
+//
+void iocsrwr_d(unsigned long int a, unsigned int b) {
+  __iocsrwr_d(a, b);
+  __builtin_loongarch_iocsrwr_d(a, b);
+}

diff  --git a/llvm/include/llvm/IR/IntrinsicsLoongArch.td b/llvm/include/llvm/IR/IntrinsicsLoongArch.td
index 599ed83609212..8fc20d98d484f 100644
--- a/llvm/include/llvm/IR/IntrinsicsLoongArch.td
+++ b/llvm/include/llvm/IR/IntrinsicsLoongArch.td
@@ -92,4 +92,14 @@ def int_loongarch_csrxchg_d : Intrinsic<[llvm_i64_ty],
                                         [llvm_i64_ty, llvm_i64_ty,
                                          llvm_i32_ty],
                                         [ImmArg<ArgIndex<2>>]>;
+
+def int_loongarch_iocsrrd_b : Intrinsic<[llvm_i32_ty], [llvm_i32_ty]>;
+def int_loongarch_iocsrrd_h : Intrinsic<[llvm_i32_ty], [llvm_i32_ty]>;
+def int_loongarch_iocsrrd_w : Intrinsic<[llvm_i32_ty], [llvm_i32_ty]>;
+def int_loongarch_iocsrrd_d : Intrinsic<[llvm_i64_ty], [llvm_i32_ty]>;
+
+def int_loongarch_iocsrwr_b : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty]>;
+def int_loongarch_iocsrwr_h : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty]>;
+def int_loongarch_iocsrwr_w : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty]>;
+def int_loongarch_iocsrwr_d : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty]>;
 } // TargetPrefix = "loongarch"

diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index fd23aadcdb755..bc7ef23b88533 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -124,6 +124,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::READ_REGISTER, MVT::i64, Custom);
     setOperationAction(ISD::WRITE_REGISTER, MVT::i64, Custom);
     setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);
+    setOperationAction(ISD::INTRINSIC_VOID, MVT::i64, Custom);
   }
 
   static const ISD::CondCode FPCCToExpand[] = {
@@ -660,6 +661,30 @@ LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,
          Op0},
         DL);
   }
+  case Intrinsic::loongarch_iocsrrd_d: {
+    if (Subtarget.is64Bit())
+      return DAG.getMergeValues(
+          {DAG.getNode(
+               LoongArchISD::IOCSRRD_D, DL, GRLenVT, Op0,
+               DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op.getOperand(2))),
+           Op0},
+          DL);
+    else {
+      DAG.getContext()->emitError(
+          "llvm.loongarch.crc.w.d.w requires target: loongarch64");
+      return DAG.getMergeValues({DAG.getUNDEF(Op.getValueType()), Op0}, DL);
+    }
+  }
+#define IOCSRRD_CASE(NAME, NODE)                                               \
+  case Intrinsic::loongarch_##NAME: {                                          \
+    return DAG.getMergeValues(                                                 \
+        {DAG.getNode(LoongArchISD::NODE, DL, GRLenVT, Op0, Op.getOperand(2)),  \
+         Op0},                                                                 \
+        DL);                                                                   \
+  }
+    IOCSRRD_CASE(iocsrrd_b, IOCSRRD_B);
+    IOCSRRD_CASE(iocsrrd_h, IOCSRRD_H);
+    IOCSRRD_CASE(iocsrrd_w, IOCSRRD_W);
   }
 }
 
@@ -717,6 +742,30 @@ SDValue LoongArchTargetLowering::lowerINTRINSIC_VOID(SDValue Op,
     return DAG.getNode(LoongArchISD::SYSCALL, DL, MVT::Other, Op0,
                        DAG.getConstant(Imm, DL, GRLenVT));
   }
+#define IOCSRWR_CASE(NAME, NODE)                                               \
+  case Intrinsic::loongarch_##NAME: {                                          \
+    SDValue Op3 = Op.getOperand(3);                                            \
+    if (Subtarget.is64Bit())                                                   \
+      return DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Op0,              \
+                         DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2),      \
+                         DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3));     \
+    else                                                                       \
+      return DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Op0, Op2, Op3);   \
+  }
+    IOCSRWR_CASE(iocsrwr_b, IOCSRWR_B);
+    IOCSRWR_CASE(iocsrwr_h, IOCSRWR_H);
+    IOCSRWR_CASE(iocsrwr_w, IOCSRWR_W);
+  case Intrinsic::loongarch_iocsrwr_d: {
+    if (Subtarget.is64Bit())
+      return DAG.getNode(
+          LoongArchISD::IOCSRWR_D, DL, MVT::Other, Op0, Op2,
+          DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op.getOperand(3)));
+    else {
+      DAG.getContext()->emitError(
+          "llvm.loongarch.iocsrwr.d requires target: loongarch64");
+      return Op.getOperand(0);
+    }
+  }
   }
 }
 
@@ -1038,6 +1087,7 @@ void LoongArchTargetLowering::ReplaceNodeResults(
       CSR_CASE(csrrd_d);
       CSR_CASE(csrwr_d);
       CSR_CASE(csrxchg_d);
+      CSR_CASE(iocsrrd_d);
     case Intrinsic::loongarch_csrrd_w: {
       unsigned Imm = cast<ConstantSDNode>(Op2)->getZExtValue();
       if (!isUInt<14>(Imm)) {
@@ -1090,6 +1140,18 @@ void LoongArchTargetLowering::ReplaceNodeResults(
       Results.push_back(N->getOperand(0));
       break;
     }
+#define IOCSRRD_CASE(NAME, NODE)                                               \
+  case Intrinsic::loongarch_##NAME: {                                          \
+    Results.push_back(DAG.getNode(                                             \
+        ISD::TRUNCATE, DL, N->getValueType(0),                                 \
+        DAG.getNode(LoongArchISD::NODE, DL, MVT::i64, Op0,                     \
+                    DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2))));        \
+    Results.push_back(N->getOperand(0));                                       \
+    break;                                                                     \
+  }
+      IOCSRRD_CASE(iocsrrd_b, IOCSRRD_B);
+      IOCSRRD_CASE(iocsrrd_h, IOCSRRD_H);
+      IOCSRRD_CASE(iocsrrd_w, IOCSRRD_W);
     }
     break;
   }
@@ -1574,6 +1636,14 @@ const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const {
     NODE_NAME_CASE(CSRRD)
     NODE_NAME_CASE(CSRWR)
     NODE_NAME_CASE(CSRXCHG)
+    NODE_NAME_CASE(IOCSRRD_B)
+    NODE_NAME_CASE(IOCSRRD_H)
+    NODE_NAME_CASE(IOCSRRD_W)
+    NODE_NAME_CASE(IOCSRRD_D)
+    NODE_NAME_CASE(IOCSRWR_B)
+    NODE_NAME_CASE(IOCSRWR_H)
+    NODE_NAME_CASE(IOCSRWR_W)
+    NODE_NAME_CASE(IOCSRWR_D)
   }
 #undef NODE_NAME_CASE
   return nullptr;

diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 9dcc5bce0fa57..36d36682d2d60 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -78,6 +78,16 @@ enum NodeType : unsigned {
   CSRRD,
   CSRWR,
   CSRXCHG,
+
+  // IOCSR access operations
+  IOCSRRD_B,
+  IOCSRRD_W,
+  IOCSRRD_H,
+  IOCSRRD_D,
+  IOCSRWR_B,
+  IOCSRWR_H,
+  IOCSRWR_W,
+  IOCSRWR_D,
 };
 } // end namespace LoongArchISD
 

diff  --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 83ca6a395b8e6..43cab04dd2120 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -46,6 +46,8 @@ def SDT_LoongArchCsrxchg : SDTypeProfile<1, 3, [SDTCisInt<0>,
                                                 SDTCisSameAs<0, 1>,
                                                 SDTCisSameAs<0, 2>,
                                                 SDTCisVT<3, GRLenVT>]>;
+def SDT_LoongArchIocsrwr : SDTypeProfile<0, 2, [SDTCisInt<0>,
+                                                SDTCisSameAs<0, 1>]>;
 
 // TODO: Add LoongArch specific DAG Nodes
 // Target-independent nodes, but with target-specific formats.
@@ -109,6 +111,26 @@ def loongarch_csrwr : SDNode<"LoongArchISD::CSRWR", SDT_LoongArchCsrwr,
 def loongarch_csrxchg : SDNode<"LoongArchISD::CSRXCHG",
                                 SDT_LoongArchCsrxchg,
                                 [SDNPHasChain, SDNPSideEffect]>;
+def loongarch_iocsrrd_b : SDNode<"LoongArchISD::IOCSRRD_B", SDTUnaryOp,
+                                  [SDNPHasChain, SDNPSideEffect]>;
+def loongarch_iocsrrd_h : SDNode<"LoongArchISD::IOCSRRD_H", SDTUnaryOp,
+                                  [SDNPHasChain, SDNPSideEffect]>;
+def loongarch_iocsrrd_w : SDNode<"LoongArchISD::IOCSRRD_W", SDTUnaryOp,
+                                  [SDNPHasChain, SDNPSideEffect]>;
+def loongarch_iocsrrd_d : SDNode<"LoongArchISD::IOCSRRD_D", SDTUnaryOp,
+                                  [SDNPHasChain, SDNPSideEffect]>;
+def loongarch_iocsrwr_b : SDNode<"LoongArchISD::IOCSRWR_B",
+                                  SDT_LoongArchIocsrwr,
+                                  [SDNPHasChain, SDNPSideEffect]>;
+def loongarch_iocsrwr_h : SDNode<"LoongArchISD::IOCSRWR_H",
+                                  SDT_LoongArchIocsrwr,
+                                  [SDNPHasChain, SDNPSideEffect]>;
+def loongarch_iocsrwr_w : SDNode<"LoongArchISD::IOCSRWR_W",
+                                  SDT_LoongArchIocsrwr,
+                                  [SDNPHasChain, SDNPSideEffect]>;
+def loongarch_iocsrwr_d : SDNode<"LoongArchISD::IOCSRWR_D",
+                                  SDT_LoongArchIocsrwr,
+                                  [SDNPHasChain, SDNPSideEffect]>;
 
 //===----------------------------------------------------------------------===//
 // Operand and SDNode transformation definitions.
@@ -1654,3 +1676,16 @@ def : Pat<(loongarch_csrwr GPR:$rd, uimm14:$imm14),
           (CSRWR GPR:$rd, uimm14:$imm14)>;
 def : Pat<(loongarch_csrxchg GPR:$rd, GPR:$rj, uimm14:$imm14),
           (CSRXCHG GPR:$rd, GPR:$rj, uimm14:$imm14)>;
+
+def : Pat<(loongarch_iocsrrd_b GPR:$rj), (IOCSRRD_B GPR:$rj)>;
+def : Pat<(loongarch_iocsrrd_h GPR:$rj), (IOCSRRD_H GPR:$rj)>;
+def : Pat<(loongarch_iocsrrd_w GPR:$rj), (IOCSRRD_W GPR:$rj)>;
+
+def : Pat<(loongarch_iocsrwr_b GPR:$rd, GPR:$rj), (IOCSRWR_B GPR:$rd, GPR:$rj)>;
+def : Pat<(loongarch_iocsrwr_h GPR:$rd, GPR:$rj), (IOCSRWR_H GPR:$rd, GPR:$rj)>;
+def : Pat<(loongarch_iocsrwr_w GPR:$rd, GPR:$rj), (IOCSRWR_W GPR:$rd, GPR:$rj)>;
+
+let Predicates = [IsLA64] in {
+def : Pat<(loongarch_iocsrrd_d GPR:$rj), (IOCSRRD_D GPR:$rj)>;
+def : Pat<(loongarch_iocsrwr_d GPR:$rd, GPR:$rj), (IOCSRWR_D GPR:$rd, GPR:$rj)>;
+} // Predicates = [IsLA64]

diff  --git a/llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll b/llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll
index 19930886a79f9..3bbeb13df034e 100644
--- a/llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll
+++ b/llvm/test/CodeGen/LoongArch/intrinsic-la32-error.ll
@@ -11,6 +11,8 @@ declare i32 @llvm.loongarch.crcc.w.d.w(i64, i32)
 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)
+declare i64 @llvm.loongarch.iocsrrd.d(i32)
+declare void @llvm.loongarch.iocsrwr.d(i64, i32)
 
 define i32 @crc_w_b_w(i32 %a, i32 %b) nounwind {
 ; CHECK: llvm.loongarch.crc.w.b.w requires target: loongarch64
@@ -88,3 +90,17 @@ entry:
   %0 = tail call i64 @llvm.loongarch.csrxchg.d(i64 %a, i64 %b, i32 1)
   ret i64 %0
 }
+
+define i64 @iocsrrd_d(i32 %a) {
+; CHECK: llvm.loongarch.iocsrrd.d requires target: loongarch64
+entry:
+  %0 = tail call i64 @llvm.loongarch.iocsrrd.d(i32 %a)
+  ret i64 %0
+}
+
+define void @iocsrwr_d(i64 %a, i32 signext %b) {
+; CHECK: llvm.loongarch.iocsrwr.d requires target: loongarch64
+entry:
+  tail call void @llvm.loongarch.iocsrwr.d(i64 %a, i32 %b)
+  ret void
+}

diff  --git a/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll b/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll
index 8b439b8b6cfe8..b2ad3776fdc46 100644
--- a/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll
+++ b/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll
@@ -12,6 +12,8 @@ declare i32 @llvm.loongarch.crcc.w.d.w(i64, i32)
 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)
+declare i64 @llvm.loongarch.iocsrrd.d(i32)
+declare void @llvm.loongarch.iocsrwr.d(i64, i32)
 
 define i32 @crc_w_b_w(i32 %a, i32 %b) nounwind {
 ; CHECK-LABEL: crc_w_b_w:
@@ -114,3 +116,23 @@ entry:
   %0 = tail call i64 @llvm.loongarch.csrxchg.d(i64 %a, i64 %b, i32 1)
   ret i64 %0
 }
+
+define i64 @iocsrrd_d(i32 %a) {
+; CHECK-LABEL: iocsrrd_d:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    iocsrrd.d $a0, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i64 @llvm.loongarch.iocsrrd.d(i32 %a)
+  ret i64 %0
+}
+
+define void @iocsrwr_d(i64 %a, i32 signext %b) {
+; CHECK-LABEL: iocsrwr_d:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    iocsrwr.d $a0, $a1
+; CHECK-NEXT:    ret
+entry:
+  tail call void @llvm.loongarch.iocsrwr.d(i64 %a, i32 %b)
+  ret void
+}

diff  --git a/llvm/test/CodeGen/LoongArch/intrinsic.ll b/llvm/test/CodeGen/LoongArch/intrinsic.ll
index 297e4d34cfee6..b3bf8159ce0ad 100644
--- a/llvm/test/CodeGen/LoongArch/intrinsic.ll
+++ b/llvm/test/CodeGen/LoongArch/intrinsic.ll
@@ -9,6 +9,12 @@ declare void @llvm.loongarch.syscall(i32)
 declare i32 @llvm.loongarch.csrrd.w(i32 immarg)
 declare i32 @llvm.loongarch.csrwr.w(i32, i32 immarg)
 declare i32 @llvm.loongarch.csrxchg.w(i32, i32, i32 immarg)
+declare i32 @llvm.loongarch.iocsrrd.b(i32)
+declare i32 @llvm.loongarch.iocsrrd.h(i32)
+declare i32 @llvm.loongarch.iocsrrd.w(i32)
+declare void @llvm.loongarch.iocsrwr.b(i32, i32)
+declare void @llvm.loongarch.iocsrwr.h(i32, i32)
+declare void @llvm.loongarch.iocsrwr.w(i32, i32)
 
 define void @foo() nounwind {
 ; CHECK-LABEL: foo:
@@ -79,3 +85,63 @@ entry:
   %0 = tail call i32 @llvm.loongarch.csrxchg.w(i32 %a, i32 %b, i32 1)
   ret i32 %0
 }
+
+define i32 @iocsrrd_b(i32 %a) {
+; CHECK-LABEL: iocsrrd_b:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    iocsrrd.b $a0, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i32 @llvm.loongarch.iocsrrd.b(i32 %a)
+  ret i32 %0
+}
+
+define i32 @iocsrrd_h(i32 %a) {
+; CHECK-LABEL: iocsrrd_h:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    iocsrrd.h $a0, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i32 @llvm.loongarch.iocsrrd.h(i32 %a)
+  ret i32 %0
+}
+
+define i32 @iocsrrd_w(i32 %a) {
+; CHECK-LABEL: iocsrrd_w:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    iocsrrd.w $a0, $a0
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call i32 @llvm.loongarch.iocsrrd.w(i32 %a)
+  ret i32 %0
+}
+
+define void @iocsrwr_b(i32 %a, i32 %b) {
+; CHECK-LABEL: iocsrwr_b:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    iocsrwr.b $a0, $a1
+; CHECK-NEXT:    ret
+entry:
+  tail call void @llvm.loongarch.iocsrwr.b(i32 %a, i32 %b)
+  ret void
+}
+
+define void @iocsrwr_h(i32 %a, i32 %b) {
+; CHECK-LABEL: iocsrwr_h:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    iocsrwr.h $a0, $a1
+; CHECK-NEXT:    ret
+entry:
+  tail call void @llvm.loongarch.iocsrwr.h(i32 %a, i32 %b)
+  ret void
+}
+
+define void @iocsrwr_w(i32 %a, i32 %b) {
+; CHECK-LABEL: iocsrwr_w:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    iocsrwr.w $a0, $a1
+; CHECK-NEXT:    ret
+entry:
+  tail call void @llvm.loongarch.iocsrwr.w(i32 %a, i32 %b)
+  ret void
+}


        


More information about the llvm-commits mailing list