summaryrefslogtreecommitdiff
path: root/clang/test/CIR/CodeGen/volatile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CIR/CodeGen/volatile.cpp')
-rw-r--r--clang/test/CIR/CodeGen/volatile.cpp184
1 files changed, 184 insertions, 0 deletions
diff --git a/clang/test/CIR/CodeGen/volatile.cpp b/clang/test/CIR/CodeGen/volatile.cpp
new file mode 100644
index 000000000000..df1d3a66733e
--- /dev/null
+++ b/clang/test/CIR/CodeGen/volatile.cpp
@@ -0,0 +1,184 @@
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR %s < %t.cir
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM %s < %t-cir.ll
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG %s < %t.ll
+
+int test_load(volatile int *ptr) {
+ return *ptr;
+}
+
+// CIR: cir.func dso_local @_Z9test_loadPVi
+// CIR: cir.load volatile
+
+// LLVM: define {{.*}} i32 @_Z9test_loadPVi
+// LLVM: load volatile i32, ptr %{{.*}}
+
+// OGCG: define {{.*}} i32 @_Z9test_loadPVi
+// OGCG: load volatile i32, ptr %{{.*}}
+
+void test_store(volatile int *ptr) {
+ *ptr = 42;
+}
+
+// CIR: cir.func dso_local @_Z10test_storePVi
+// CIR: cir.store volatile
+
+// LLVM: define {{.*}} void @_Z10test_storePVi
+// LLVM: store volatile i32 42, ptr %{{.*}}
+
+// OGCG: define {{.*}} void @_Z10test_storePVi
+// OGCG: store volatile i32 42, ptr %{{.*}}
+
+struct Foo {
+ int x;
+ volatile int y;
+ volatile int z: 4;
+};
+
+int test_load_field1(volatile Foo *ptr) {
+ return ptr->x;
+}
+
+// CIR: cir.func dso_local @_Z16test_load_field1PV3Foo
+// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member
+// CIR: %{{.+}} = cir.load volatile{{.*}} %[[MEMBER_ADDR]]
+
+// LLVM: define {{.*}} i32 @_Z16test_load_field1PV3Foo
+// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.Foo, ptr %{{.*}}, i32 0, i32 0
+// LLVM: %{{.*}} = load volatile i32, ptr %[[MEMBER_ADDR]]
+
+// OGCG: define {{.*}} i32 @_Z16test_load_field1PV3Foo
+// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.Foo, ptr %{{.*}}, i32 0, i32 0
+// OGCG: %{{.*}} = load volatile i32, ptr %[[MEMBER_ADDR]]
+
+int test_load_field2(Foo *ptr) {
+ return ptr->y;
+}
+
+// CIR: cir.func dso_local @_Z16test_load_field2P3Foo
+// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member
+// CIR: %{{.+}} = cir.load volatile{{.*}} %[[MEMBER_ADDR]]
+
+// LLVM: define {{.*}} i32 @_Z16test_load_field2P3Foo
+// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.Foo, ptr %{{.*}}, i32 0, i32 1
+// LLVM: %{{.*}} = load volatile i32, ptr %[[MEMBER_ADDR]]
+
+// OGCG: define {{.*}} i32 @_Z16test_load_field2P3Foo
+// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.Foo, ptr %{{.*}}, i32 0, i32 1
+// OGCG: %{{.*}} = load volatile i32, ptr %[[MEMBER_ADDR]]
+
+int test_load_field3(Foo *ptr) {
+ return ptr->z;
+}
+
+// CIR: cir.func dso_local @_Z16test_load_field3P3Foo
+// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member
+// CIR: %{{.*}} = cir.get_bitfield align(4) (#bfi_z, %[[MEMBER_ADDR:.+]] {is_volatile} : !cir.ptr<!u8i>) -> !s32i
+
+// LLVM: define {{.*}} i32 @_Z16test_load_field3P3Foo
+// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.Foo, ptr %{{.*}}, i32 0, i32 2
+// LLVM: %[[TMP1:.*]] = load volatile i8, ptr %[[MEMBER_ADDR]]
+// LLVM: %[[TMP2:.*]] = shl i8 %[[TMP1]], 4
+// LLVM: %[[TMP3:.*]] = ashr i8 %[[TMP2]], 4
+// LLVM: %{{.*}} = sext i8 %[[TMP3]] to i32
+
+// OGCG: define {{.*}} i32 @_Z16test_load_field3P3Foo
+// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.Foo, ptr %{{.*}}, i32 0, i32 2
+// OGCG: %[[TMP1:.*]] = load volatile i8, ptr %[[MEMBER_ADDR]]
+// OGCG: %[[TMP2:.*]] = shl i8 %[[TMP1]], 4
+// OGCG: %[[TMP3:.*]] = ashr i8 %[[TMP2]], 4
+// OGCG: %{{.*}} = sext i8 %[[TMP3]] to i32
+
+void test_store_field1(volatile Foo *ptr) {
+ ptr->x = 42;
+}
+
+// CIR: cir.func dso_local @_Z17test_store_field1PV3Foo
+// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member
+// CIR: cir.store volatile{{.*}} %{{.+}}, %[[MEMBER_ADDR]]
+
+// LLVM: define {{.*}} void @_Z17test_store_field1PV3Foo
+// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.Foo, ptr %{{.*}}, i32 0, i32 0
+// LLVM: store volatile i32 42, ptr %[[MEMBER_ADDR]]
+
+// OGCG: define {{.*}} void @_Z17test_store_field1PV3Foo
+// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.Foo, ptr %{{.*}}, i32 0, i32 0
+// OGCG: store volatile i32 42, ptr %[[MEMBER_ADDR]]
+
+void test_store_field2(Foo *ptr) {
+ ptr->y = 42;
+}
+
+// CIR: cir.func dso_local @_Z17test_store_field2P3Foo
+// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member
+// CIR: cir.store volatile{{.*}} %{{.+}}, %[[MEMBER_ADDR]]
+
+// LLVM: define {{.*}} void @_Z17test_store_field2P3Foo
+// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.Foo, ptr %{{.*}}, i32 0, i32 1
+// LLVM: store volatile i32 42, ptr %[[MEMBER_ADDR]]
+
+// OGCG: define {{.*}} void @_Z17test_store_field2P3Foo
+// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.Foo, ptr %{{.*}}, i32 0, i32 1
+// OGCG: store volatile i32 42, ptr %[[MEMBER_ADDR]]
+
+void test_store_field3(Foo *ptr) {
+ ptr->z = 4;
+}
+
+// CIR: cir.func dso_local @_Z17test_store_field3P3Foo
+// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member
+// CIR: cir.set_bitfield align(4) (#bfi_z, %[[MEMBER_ADDR:.+]] : !cir.ptr<!u8i>, %1 : !s32i) {is_volatile}
+
+// LLVM: define {{.*}} void @_Z17test_store_field3P3Foo
+// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.Foo, ptr %{{.*}}, i32 0, i32 2
+// LLVM: %[[TMP1:.*]] = load volatile i8, ptr %[[MEMBER_ADDR]]
+// LLVM: %[[TMP2:.*]] = and i8 %[[TMP1]], -16
+// LLVM: %[[TMP3:.*]] = or i8 %[[TMP2]], 4
+// LLVM: store volatile i8 %[[TMP3]], ptr %[[MEMBER_ADDR]]
+
+// OGCG: define {{.*}} void @_Z17test_store_field3P3Foo
+// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.Foo, ptr %{{.*}}, i32 0, i32 2
+// OGCG: %[[TMP1:.*]] = load volatile i8, ptr %[[MEMBER_ADDR]]
+// OGCG: %[[TMP2:.*]] = and i8 %[[TMP1]], -16
+// OGCG: %[[TMP3:.*]] = or i8 %[[TMP2]], 4
+// OGCG: store volatile i8 %[[TMP3]], ptr %[[MEMBER_ADDR]]
+
+struct A {
+ int x;
+ void set_x(int val) volatile;
+ int get_x() volatile;
+};
+
+void A::set_x(int val) volatile {
+ x = val;
+}
+
+// CIR: cir.func dso_local @_ZNV1A5set_xEi
+// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member %{{.*}}[0] {name = "x"}
+// CIR: cir.store volatile {{.*}} %{{.*}}, %[[MEMBER_ADDR]]
+
+// LLVM: define {{.*}} void @_ZNV1A5set_xEi
+// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.A, ptr %{{.*}}, i32 0, i32 0
+// LLVM: store volatile i32 %{{.*}}, ptr %[[MEMBER_ADDR]]
+
+// OGCG: define {{.*}} void @_ZNV1A5set_xEi
+// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.A, ptr %{{.*}}, i32 0, i32 0
+// OGCG: store volatile i32 %{{.*}}, ptr %[[MEMBER_ADDR]]
+
+int A::get_x() volatile {
+ return x;
+}
+
+// CIR: cir.func dso_local @_ZNV1A5get_xEv
+// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member %{{.*}}[0] {name = "x"}
+// CIR: cir.load volatile {{.*}} %[[MEMBER_ADDR]]
+
+// LLVM: define {{.*}} i32 @_ZNV1A5get_xEv
+// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.A, ptr %{{.*}}, i32 0, i32 0
+// LLVM: %{{.*}} = load volatile i32, ptr %[[MEMBER_ADDR]]
+
+// OGCG: define {{.*}} i32 @_ZNV1A5get_xEv
+// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.A, ptr %{{.*}}, i32 0, i32 0
+// OGCG: %{{.*}} = load volatile i32, ptr %[[MEMBER_ADDR]]