diff options
Diffstat (limited to 'clang/test/CIR/CodeGen/volatile.cpp')
| -rw-r--r-- | clang/test/CIR/CodeGen/volatile.cpp | 184 |
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]] |
