| // RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-cir %s -o %t.cir |
| // RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s |
| // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll |
| // RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s |
| // RUN: %clang_cc1 -triple aarch64-none-linux-android21 -emit-llvm %s -o %t.ll |
| // RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s |
| |
| struct Data { |
| int value; |
| void *ptr; |
| }; |
| |
| typedef struct Data *DataPtr; |
| |
| void applyThreadFence() { |
| __atomic_thread_fence(__ATOMIC_SEQ_CST); |
| // CIR-LABEL: @applyThreadFence |
| // CIR: cir.atomic.fence syncscope(system) seq_cst |
| // CIR: cir.return |
| |
| // LLVM-LABEL: @applyThreadFence |
| // LLVM: fence seq_cst |
| // LLVM: ret void |
| |
| // OGCG-LABEL: @applyThreadFence |
| // OGCG: fence seq_cst |
| // OGCG: ret void |
| } |
| |
| void applySignalFence() { |
| __atomic_signal_fence(__ATOMIC_SEQ_CST); |
| // CIR-LABEL: @applySignalFence |
| // CIR: cir.atomic.fence syncscope(single_thread) seq_cst |
| // CIR: cir.return |
| |
| // LLVM-LABEL: @applySignalFence |
| // LLVM: fence syncscope("singlethread") seq_cst |
| // LLVM: ret void |
| |
| // OGCG-LABEL: @applySignalFence |
| // OGCG: fence syncscope("singlethread") seq_cst |
| // OGCG: ret void |
| } |
| |
| void modifyWithThreadFence(DataPtr d) { |
| __atomic_thread_fence(__ATOMIC_SEQ_CST); |
| d->value = 42; |
| // CIR-LABEL: @modifyWithThreadFence |
| // CIR: %[[DATA:.*]] = cir.alloca "d" align(8) init : !cir.ptr<!cir.ptr<!rec_Data>> |
| // CIR: cir.atomic.fence syncscope(system) seq_cst |
| // CIR: %[[VAL_42:.*]] = cir.const #cir.int<42> : !s32i |
| // CIR: %[[LOAD_DATA:.*]] = cir.load{{.*}} %[[DATA]] : !cir.ptr<!cir.ptr<!rec_Data>>, !cir.ptr<!rec_Data> |
| // CIR: %[[DATA_VALUE:.*]] = cir.get_member %[[LOAD_DATA]][0] {name = "value"} : !cir.ptr<!rec_Data> -> !cir.ptr<!s32i> |
| // CIR: cir.store{{.*}} %[[VAL_42]], %[[DATA_VALUE]] : !s32i, !cir.ptr<!s32i> |
| // CIR: cir.return |
| |
| // LLVM-LABEL: @modifyWithThreadFence |
| // LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8 |
| // LLVM: fence seq_cst |
| // LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8 |
| // LLVM: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0 |
| // LLVM: store i32 42, ptr %[[DATA_VALUE]], align 8 |
| // LLVM: ret void |
| |
| // OGCG-LABEL: @modifyWithThreadFence |
| // OGCG: %[[DATA:.*]] = alloca ptr, align 8 |
| // OGCG: fence seq_cst |
| // OGCG: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8 |
| // OGCG: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0 |
| // OGCG: store i32 42, ptr %[[DATA_VALUE]], align 8 |
| // OGCG: ret void |
| } |
| |
| void modifyWithSignalFence(DataPtr d) { |
| __atomic_signal_fence(__ATOMIC_SEQ_CST); |
| d->value = 24; |
| // CIR-LABEL: @modifyWithSignalFence |
| // CIR: %[[DATA:.*]] = cir.alloca "d" align(8) init : !cir.ptr<!cir.ptr<!rec_Data>> |
| // CIR: cir.atomic.fence syncscope(single_thread) seq_cst |
| // CIR: %[[VAL_42:.*]] = cir.const #cir.int<24> : !s32i |
| // CIR: %[[LOAD_DATA:.*]] = cir.load{{.*}} %[[DATA]] : !cir.ptr<!cir.ptr<!rec_Data>>, !cir.ptr<!rec_Data> |
| // CIR: %[[DATA_VALUE:.*]] = cir.get_member %[[LOAD_DATA]][0] {name = "value"} : !cir.ptr<!rec_Data> -> !cir.ptr<!s32i> |
| // CIR: cir.store{{.*}} %[[VAL_42]], %[[DATA_VALUE]] : !s32i, !cir.ptr<!s32i> |
| // CIR: cir.return |
| |
| // LLVM-LABEL: @modifyWithSignalFence |
| // LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8 |
| // LLVM: fence syncscope("singlethread") seq_cst |
| // LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8 |
| // LLVM: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0 |
| // LLVM: store i32 24, ptr %[[DATA_VALUE]], align 8 |
| // LLVM: ret void |
| |
| // OGCG-LABEL: @modifyWithSignalFence |
| // OGCG: %[[DATA:.*]] = alloca ptr, align 8 |
| // OGCG: fence syncscope("singlethread") seq_cst |
| // OGCG: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8 |
| // OGCG: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0 |
| // OGCG: store i32 24, ptr %[[DATA_VALUE]], align 8 |
| // OGCG: ret void |
| } |
| |
| void loadWithThreadFence(DataPtr d) { |
| __atomic_thread_fence(__ATOMIC_SEQ_CST); |
| __atomic_load_n(&d->ptr, __ATOMIC_SEQ_CST); |
| // CIR-LABEL: @loadWithThreadFence |
| // CIR: %[[DATA:.*]] = cir.alloca "d" align(8) init : !cir.ptr<!cir.ptr<!rec_Data>> |
| // CIR: %[[ATOMIC_TEMP:.*]] = cir.alloca "atomic-temp" align(8) : !cir.ptr<!cir.ptr<!void>> |
| // CIR: cir.atomic.fence syncscope(system) seq_cst |
| // CIR: %[[LOAD_DATA:.*]] = cir.load{{.*}} %[[DATA]] : !cir.ptr<!cir.ptr<!rec_Data>>, !cir.ptr<!rec_Data> |
| // CIR: %[[DATA_VALUE:.*]] = cir.get_member %[[LOAD_DATA]][1] {name = "ptr"} : !cir.ptr<!rec_Data> -> !cir.ptr<!cir.ptr<!void>> |
| // CIR: %[[ATOMIC_LOAD:.*]] = cir.load{{.*}} atomic(seq_cst) %[[DATA_VALUE]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> |
| // CIR: cir.store{{.*}} %[[ATOMIC_LOAD]], %[[ATOMIC_TEMP]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> |
| // CIR: %[[ATOMIC_LOAD_PTR:.*]] = cir.load{{.*}} %[[ATOMIC_TEMP]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> |
| // CIR: cir.return |
| |
| // LLVM-LABEL: @loadWithThreadFence |
| // LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8 |
| // LLVM: %[[DATA_TEMP:.*]] = alloca ptr, i64 1, align 8 |
| // LLVM: fence seq_cst |
| // LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8 |
| // LLVM: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1 |
| // LLVM: %[[ATOMIC_LOAD:.*]] = load atomic ptr, ptr %[[DATA_VALUE]] seq_cst, align 8 |
| // LLVM: store ptr %[[ATOMIC_LOAD]], ptr %[[DATA_TEMP]], align 8 |
| // LLVM: %[[DATA_TEMP_LOAD:.*]] = load ptr, ptr %[[DATA_TEMP]], align 8 |
| // LLVM: ret void |
| |
| // OGCG-LABEL: @loadWithThreadFence |
| // OGCG: %[[DATA:.*]] = alloca ptr, align 8 |
| // OGCG: %[[DATA_TEMP:.*]] = alloca ptr, align 8 |
| // OGCG: fence seq_cst |
| // OGCG: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8 |
| // OGCG: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1 |
| // OGCG: %[[ATOMIC_LOAD:.*]] = load atomic ptr, ptr %[[DATA_VALUE]] seq_cst, align 8 |
| // OGCG: store ptr %[[ATOMIC_LOAD]], ptr %[[DATA_TEMP]], align 8 |
| // OGCG: %[[DATA_TEMP_LOAD:.*]] = load ptr, ptr %[[DATA_TEMP]], align 8 |
| // OGCG: ret void |
| } |
| |
| void loadWithSignalFence(DataPtr d) { |
| __atomic_signal_fence(__ATOMIC_SEQ_CST); |
| __atomic_load_n(&d->ptr, __ATOMIC_SEQ_CST); |
| // CIR-LABEL: @loadWithSignalFence |
| // CIR: %[[DATA:.*]] = cir.alloca "d" align(8) init : !cir.ptr<!cir.ptr<!rec_Data>> |
| // CIR: %[[ATOMIC_TEMP:.*]] = cir.alloca "atomic-temp" align(8) : !cir.ptr<!cir.ptr<!void>> |
| // CIR: cir.atomic.fence syncscope(single_thread) seq_cst |
| // CIR: %[[LOAD_DATA:.*]] = cir.load{{.*}} %[[DATA]] : !cir.ptr<!cir.ptr<!rec_Data>>, !cir.ptr<!rec_Data> |
| // CIR: %[[DATA_PTR:.*]] = cir.get_member %[[LOAD_DATA]][1] {name = "ptr"} : !cir.ptr<!rec_Data> -> !cir.ptr<!cir.ptr<!void>> |
| // CIR: %[[ATOMIC_LOAD:.*]] = cir.load{{.*}} atomic(seq_cst) %[[DATA_PTR]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> |
| // CIR: cir.store{{.*}} %[[ATOMIC_LOAD]], %[[ATOMIC_TEMP]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>> |
| // CIR: %[[LOAD_ATOMIC_TEMP:.*]] = cir.load{{.*}} %[[ATOMIC_TEMP]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> |
| // CIR: cir.return |
| |
| // LLVM-LABEL: @loadWithSignalFence |
| // LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8 |
| // LLVM: %[[DATA_TEMP:.*]] = alloca ptr, i64 1, align 8 |
| // LLVM: fence syncscope("singlethread") seq_cst |
| // LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8 |
| // LLVM: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1 |
| // LLVM: %[[ATOMIC_LOAD:.*]] = load atomic ptr, ptr %[[DATA_VALUE]] seq_cst, align 8 |
| // LLVM: store ptr %[[ATOMIC_LOAD]], ptr %[[DATA_TEMP]], align 8 |
| // LLVM: %[[DATA_TEMP_LOAD]] = load ptr, ptr %[[DATA_TEMP]], align 8 |
| // LLVM: ret void |
| |
| // OGCG-LABEL: @loadWithSignalFence |
| // OGCG: %[[DATA:.*]] = alloca ptr, align 8 |
| // OGCG: %[[DATA_TEMP:.*]] = alloca ptr, align 8 |
| // OGCG: fence syncscope("singlethread") seq_cst |
| // OGCG: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8 |
| // OGCG: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1 |
| // OGCG: %[[ATOMIC_LOAD:.*]] = load atomic ptr, ptr %[[DATA_VALUE]] seq_cst, align 8 |
| // OGCG: store ptr %[[ATOMIC_LOAD]], ptr %[[DATA_TEMP]], align 8 |
| // OGCG: %[[DATA_TEMP_LOAD]] = load ptr, ptr %[[DATA_TEMP]], align 8 |
| // OGCG: ret void |
| } |
| |
| void const_atomic_thread_fence() { |
| __atomic_thread_fence(__ATOMIC_RELAXED); |
| __atomic_thread_fence(__ATOMIC_CONSUME); |
| __atomic_thread_fence(__ATOMIC_ACQUIRE); |
| __atomic_thread_fence(__ATOMIC_RELEASE); |
| __atomic_thread_fence(__ATOMIC_ACQ_REL); |
| __atomic_thread_fence(__ATOMIC_SEQ_CST); |
| // CIR-LABEL: const_atomic_thread_fence |
| // CIR-NOT: cir.atomic.fence syncscope(system) relaxed |
| // CIR: cir.atomic.fence syncscope(system) acquire |
| // CIR: cir.atomic.fence syncscope(system) acquire |
| // CIR: cir.atomic.fence syncscope(system) release |
| // CIR: cir.atomic.fence syncscope(system) acq_rel |
| // CIR: cir.atomic.fence syncscope(system) seq_cst |
| |
| // LLVM-LABEL: const_atomic_thread_fence |
| // LLVM-NOT: fence relaxed |
| // LLVM: fence acquire |
| // LLVM: fence acquire |
| // LLVM: fence release |
| // LLVM: fence acq_rel |
| // LLVM: fence seq_cst |
| |
| // OGCG-LABEL: const_atomic_thread_fence |
| // OGCG-NOT: fence relaxed |
| // OGCG: fence acquire |
| // OGCG: fence acquire |
| // OGCG: fence release |
| // OGCG: fence acq_rel |
| // OGCG: fence seq_cst |
| } |
| |
| void const_c11_atomic_thread_fence() { |
| __c11_atomic_thread_fence(__ATOMIC_RELAXED); |
| __c11_atomic_thread_fence(__ATOMIC_CONSUME); |
| __c11_atomic_thread_fence(__ATOMIC_ACQUIRE); |
| __c11_atomic_thread_fence(__ATOMIC_RELEASE); |
| __c11_atomic_thread_fence(__ATOMIC_ACQ_REL); |
| __c11_atomic_thread_fence(__ATOMIC_SEQ_CST); |
| // CIR-LABEL: const_c11_atomic_thread_fence |
| // CIR-NOT: cir.atomic.fence syncscope(system) relaxed |
| // CIR: cir.atomic.fence syncscope(system) acquire |
| // CIR: cir.atomic.fence syncscope(system) acquire |
| // CIR: cir.atomic.fence syncscope(system) release |
| // CIR: cir.atomic.fence syncscope(system) acq_rel |
| // CIR: cir.atomic.fence syncscope(system) seq_cst |
| |
| // LLVM-LABEL: const_c11_atomic_thread_fence |
| // LLVM-NOT: fence relaxed |
| // LLVM: fence acquire |
| // LLVM: fence acquire |
| // LLVM: fence release |
| // LLVM: fence acq_rel |
| // LLVM: fence seq_cst |
| |
| // OGCG-LABEL: const_c11_atomic_thread_fence |
| // OGCG-NOT: fence relaxed |
| // OGCG: fence acquire |
| // OGCG: fence acquire |
| // OGCG: fence release |
| // OGCG: fence acq_rel |
| // OGCG: fence seq_cst |
| } |
| |
| void const_atomic_signal_fence() { |
| __atomic_signal_fence(__ATOMIC_RELAXED); |
| __atomic_signal_fence(__ATOMIC_CONSUME); |
| __atomic_signal_fence(__ATOMIC_ACQUIRE); |
| __atomic_signal_fence(__ATOMIC_RELEASE); |
| __atomic_signal_fence(__ATOMIC_ACQ_REL); |
| __atomic_signal_fence(__ATOMIC_SEQ_CST); |
| // CIR-LABEL: const_atomic_signal_fence |
| // CIR-NOT: cir.atomic.fence syncscope(single_thread) relaxed |
| // CIR: cir.atomic.fence syncscope(single_thread) acquire |
| // CIR: cir.atomic.fence syncscope(single_thread) acquire |
| // CIR: cir.atomic.fence syncscope(single_thread) release |
| // CIR: cir.atomic.fence syncscope(single_thread) acq_rel |
| // CIR: cir.atomic.fence syncscope(single_thread) seq_cst |
| |
| // LLVM-LABEL: const_atomic_signal_fence |
| // LLVM-NOT: fence syncscope("singlethread") relaxed |
| // LLVM: fence syncscope("singlethread") acquire |
| // LLVM: fence syncscope("singlethread") acquire |
| // LLVM: fence syncscope("singlethread") release |
| // LLVM: fence syncscope("singlethread") acq_rel |
| // LLVM: fence syncscope("singlethread") seq_cst |
| |
| // OGCG--LABEL: const_atomic_signal_fence |
| // OGCG-NOT: fence syncscope("singlethread") relaxed |
| // OGCG: fence syncscope("singlethread") acquire |
| // OGCG: fence syncscope("singlethread") acquire |
| // OGCG: fence syncscope("singlethread") release |
| // OGCG: fence syncscope("singlethread") acq_rel |
| // OGCG: fence syncscope("singlethread") seq_cst |
| } |
| |
| void const_c11_atomic_signal_fence() { |
| __c11_atomic_signal_fence(__ATOMIC_RELAXED); |
| __c11_atomic_signal_fence(__ATOMIC_CONSUME); |
| __c11_atomic_signal_fence(__ATOMIC_ACQUIRE); |
| __c11_atomic_signal_fence(__ATOMIC_RELEASE); |
| __c11_atomic_signal_fence(__ATOMIC_ACQ_REL); |
| __c11_atomic_signal_fence(__ATOMIC_SEQ_CST); |
| // CIR-LABEL: const_c11_atomic_signal_fence |
| // CIR-NOT: cir.atomic.fence syncscope(single_thread) relaxed |
| // CIR: cir.atomic.fence syncscope(single_thread) acquire |
| // CIR: cir.atomic.fence syncscope(single_thread) acquire |
| // CIR: cir.atomic.fence syncscope(single_thread) release |
| // CIR: cir.atomic.fence syncscope(single_thread) acq_rel |
| // CIR: cir.atomic.fence syncscope(single_thread) seq_cst |
| |
| // LLVM-LABEL: const_c11_atomic_signal_fence |
| // LLVM-NOT: fence syncscope("singlethread") relaxed |
| // LLVM: fence syncscope("singlethread") acquire |
| // LLVM: fence syncscope("singlethread") acquire |
| // LLVM: fence syncscope("singlethread") release |
| // LLVM: fence syncscope("singlethread") acq_rel |
| // LLVM: fence syncscope("singlethread") seq_cst |
| |
| // OGCG-LABEL: const_c11_atomic_signal_fence |
| // OGCG-NOT: fence syncscope("singlethread") relaxed |
| // OGCG: fence syncscope("singlethread") acquire |
| // OGCG: fence syncscope("singlethread") acquire |
| // OGCG: fence syncscope("singlethread") release |
| // OGCG: fence syncscope("singlethread") acq_rel |
| // OGCG: fence syncscope("singlethread") seq_cst |
| } |
| |
| void variable_atomic_thread_fences(int memorder) { |
| __atomic_thread_fence(memorder); |
| // CIR-LABEL: variable_atomic_thread_fences |
| // CIR: cir.switch |
| // CIR: cir.case(default, []) { |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(system) acquire |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<3> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(system) release |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<4> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(system) acq_rel |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<5> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(system) |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.yield |
| // CIR: } |
| |
| // LLVM-LABEL: variable_atomic_thread_fences |
| // LLVM: %[[ORDER:.+]] = load i32, ptr %[[PTR:.+]], align 4 |
| // LLVM: br label %[[SWITCH_BLK:.+]] |
| // LLVM: [[SWITCH_BLK]]: |
| // LLVM: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [ |
| // LLVM: i32 1, label %[[ACQUIRE_BLK:.+]] |
| // LLVM: i32 2, label %[[ACQUIRE_BLK]] |
| // LLVM: i32 3, label %[[RELEASE_BLK:.+]] |
| // LLVM: i32 4, label %[[ACQ_REL_BLK:.+]] |
| // LLVM: i32 5, label %[[SEQ_CST_BLK:.+]] |
| // LLVM: ] |
| // LLVM: [[DEFAULT_BLK]]: |
| // LLVM: br label %{{.+}} |
| // LLVM: [[ACQUIRE_BLK]]: |
| // LLVM: fence acquire |
| // LLVM: br label %{{.+}} |
| // LLVM: [[RELEASE_BLK]]: |
| // LLVM: fence release |
| // LLVM: br label %{{.+}} |
| // LLVM: [[ACQ_REL_BLK]]: |
| // LLVM: fence acq_rel |
| // LLVM: br label %{{.+}} |
| // LLVM: [[SEQ_CST_BLK]]: |
| // LLVM: fence seq_cst |
| // LLVM: br label %{{.+}} |
| |
| // OGCG-LABEL: variable_atomic_thread_fences |
| // OGCG: %[[ORDER:.+]] = load i32, ptr %[[PTR:.+]], align 4 |
| // OGCG: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [ |
| // OGCG: i32 1, label %[[ACQUIRE_BLK:.+]] |
| // OGCG: i32 2, label %[[ACQUIRE_BLK]] |
| // OGCG: i32 3, label %[[RELEASE_BLK:.+]] |
| // OGCG: i32 4, label %[[ACQ_REL_BLK:.+]] |
| // OGCG: i32 5, label %[[SEQ_CST_BLK:.+]] |
| // OGCG: ] |
| // OGCG: [[ACQUIRE_BLK]]: |
| // OGCG: fence acquire |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[RELEASE_BLK]]: |
| // OGCG: fence release |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[ACQ_REL_BLK]]: |
| // OGCG: fence acq_rel |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[SEQ_CST_BLK]]: |
| // OGCG: fence seq_cst |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[DEFAULT_BLK]]: |
| // OGCG: ret void |
| } |
| |
| void variable_c11_atomic_thread_fences(int memorder) { |
| __c11_atomic_thread_fence(memorder); |
| // CIR-LABEL: variable_c11_atomic_thread_fences |
| // CIR: cir.switch |
| // CIR: cir.case(default, []) { |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(system) acquire |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<3> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(system) release |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<4> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(system) acq_rel |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<5> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(system) |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.yield |
| // CIR: } |
| |
| // LLVM-LABEL: variable_c11_atomic_thread_fences |
| // LLVM: %[[ORDER:.+]] = load i32, ptr %[[PTR:.+]], align 4 |
| // LLVM: br label %[[SWITCH_BLK:.+]] |
| // LLVM: [[SWITCH_BLK]]: |
| // LLVM: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [ |
| // LLVM: i32 1, label %[[ACQUIRE_BLK:.+]] |
| // LLVM: i32 2, label %[[ACQUIRE_BLK]] |
| // LLVM: i32 3, label %[[RELEASE_BLK:.+]] |
| // LLVM: i32 4, label %[[ACQ_REL_BLK:.+]] |
| // LLVM: i32 5, label %[[SEQ_CST_BLK:.+]] |
| // LLVM: ] |
| // LLVM: [[DEFAULT_BLK]]: |
| // LLVM: br label %{{.+}} |
| // LLVM: [[ACQUIRE_BLK]]: |
| // LLVM: fence acquire |
| // LLVM: br label %{{.+}} |
| // LLVM: [[RELEASE_BLK]]: |
| // LLVM: fence release |
| // LLVM: br label %{{.+}} |
| // LLVM: [[ACQ_REL_BLK]]: |
| // LLVM: fence acq_rel |
| // LLVM: br label %{{.+}} |
| // LLVM: [[SEQ_CST_BLK]]: |
| // LLVM: fence seq_cst |
| // LLVM: br label %{{.+}} |
| |
| // OGCG-LABEL: variable_c11_atomic_thread_fences |
| // OGCG: %[[ORDER:.+]] = load i32, ptr %[[PTR:.+]], align 4 |
| // OGCG: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [ |
| // OGCG: i32 1, label %[[ACQUIRE_BLK:.+]] |
| // OGCG: i32 2, label %[[ACQUIRE_BLK]] |
| // OGCG: i32 3, label %[[RELEASE_BLK:.+]] |
| // OGCG: i32 4, label %[[ACQ_REL_BLK:.+]] |
| // OGCG: i32 5, label %[[SEQ_CST_BLK:.+]] |
| // OGCG: ] |
| // OGCG: [[ACQUIRE_BLK]]: |
| // OGCG: fence acquire |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[RELEASE_BLK]]: |
| // OGCG: fence release |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[ACQ_REL_BLK]]: |
| // OGCG: fence acq_rel |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[SEQ_CST_BLK]]: |
| // OGCG: fence seq_cst |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[DEFAULT_BLK]]: |
| // OGCG: ret void |
| } |
| |
| void variable_atomic_signal_fences(int memorder) { |
| __atomic_signal_fence(memorder); |
| // CIR-LABEL: variable_atomic_signal_fences |
| // CIR: cir.switch |
| // CIR: cir.case(default, []) { |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(single_thread) acquire |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<3> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(single_thread) release |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<4> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(single_thread) acq_rel |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<5> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(single_thread) |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.yield |
| // CIR: } |
| |
| // LLVM-LABEL: variable_atomic_signal_fences |
| // LLVM: %[[ORDER:.+]] = load i32, ptr %[[PTR:.+]], align 4 |
| // LLVM: br label %[[SWITCH_BLK:.+]] |
| // LLVM: [[SWITCH_BLK]]: |
| // LLVM: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [ |
| // LLVM: i32 1, label %[[ACQUIRE_BLK:.+]] |
| // LLVM: i32 2, label %[[ACQUIRE_BLK]] |
| // LLVM: i32 3, label %[[RELEASE_BLK:.+]] |
| // LLVM: i32 4, label %[[ACQ_REL_BLK:.+]] |
| // LLVM: i32 5, label %[[SEQ_CST_BLK:.+]] |
| // LLVM: ] |
| // LLVM: [[DEFAULT_BLK]]: |
| // LLVM: br label %{{.+}} |
| // LLVM: [[ACQUIRE_BLK]]: |
| // LLVM: fence syncscope("singlethread") acquire |
| // LLVM: br label %{{.+}} |
| // LLVM: [[RELEASE_BLK]]: |
| // LLVM: fence syncscope("singlethread") release |
| // LLVM: br label %{{.+}} |
| // LLVM: [[ACQ_REL_BLK]]: |
| // LLVM: fence syncscope("singlethread") acq_rel |
| // LLVM: br label %{{.+}} |
| // LLVM: [[SEQ_CST_BLK]]: |
| // LLVM: fence syncscope("singlethread") seq_cst |
| // LLVM: br label %{{.+}} |
| |
| // OGCG-LABEL: variable_atomic_signal_fences |
| // OGCG: %[[ORDER:.+]] = load i32, ptr %[[PTR:.+]], align 4 |
| // OGCG: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [ |
| // OGCG: i32 1, label %[[ACQUIRE_BLK:.+]] |
| // OGCG: i32 2, label %[[ACQUIRE_BLK]] |
| // OGCG: i32 3, label %[[RELEASE_BLK:.+]] |
| // OGCG: i32 4, label %[[ACQ_REL_BLK:.+]] |
| // OGCG: i32 5, label %[[SEQ_CST_BLK:.+]] |
| // OGCG: ] |
| // OGCG: [[ACQUIRE_BLK]]: |
| // OGCG: fence syncscope("singlethread") acquire |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[RELEASE_BLK]]: |
| // OGCG: fence syncscope("singlethread") release |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[ACQ_REL_BLK]]: |
| // OGCG: fence syncscope("singlethread") acq_rel |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[SEQ_CST_BLK]]: |
| // OGCG: fence syncscope("singlethread") seq_cst |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[DEFAULT_BLK]]: |
| // OGCG: ret void |
| } |
| |
| void variable_c11_atomic_signal_fences(int memorder) { |
| __c11_atomic_signal_fence(memorder); |
| // CIR-LABEL: variable_c11_atomic_signal_fences |
| // CIR: cir.switch |
| // CIR: cir.case(default, []) { |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(single_thread) acquire |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<3> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(single_thread) release |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<4> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(single_thread) acq_rel |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.case(anyof, [#cir.int<5> : !s32i]) { |
| // CIR: cir.atomic.fence syncscope(single_thread) |
| // CIR: cir.break |
| // CIR: } |
| // CIR: cir.yield |
| // CIR: } |
| |
| // LLVM-LABEL: variable_c11_atomic_signal_fences |
| // LLVM: %[[ORDER:.+]] = load i32, ptr %[[PTR:.+]], align 4 |
| // LLVM: br label %[[SWITCH_BLK:.+]] |
| // LLVM: [[SWITCH_BLK]]: |
| // LLVM: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [ |
| // LLVM: i32 1, label %[[ACQUIRE_BLK:.+]] |
| // LLVM: i32 2, label %[[ACQUIRE_BLK]] |
| // LLVM: i32 3, label %[[RELEASE_BLK:.+]] |
| // LLVM: i32 4, label %[[ACQ_REL_BLK:.+]] |
| // LLVM: i32 5, label %[[SEQ_CST_BLK:.+]] |
| // LLVM: ] |
| // LLVM: [[DEFAULT_BLK]]: |
| // LLVM: br label %{{.+}} |
| // LLVM: [[ACQUIRE_BLK]]: |
| // LLVM: fence syncscope("singlethread") acquire |
| // LLVM: br label %{{.+}} |
| // LLVM: [[RELEASE_BLK]]: |
| // LLVM: fence syncscope("singlethread") release |
| // LLVM: br label %{{.+}} |
| // LLVM: [[ACQ_REL_BLK]]: |
| // LLVM: fence syncscope("singlethread") acq_rel |
| // LLVM: br label %{{.+}} |
| // LLVM: [[SEQ_CST_BLK]]: |
| // LLVM: fence syncscope("singlethread") seq_cst |
| // LLVM: br label %{{.+}} |
| |
| // OGCG-LABEL: variable_c11_atomic_signal_fences |
| // OGCG: %[[ORDER:.+]] = load i32, ptr %[[PTR:.+]], align 4 |
| // OGCG: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [ |
| // OGCG: i32 1, label %[[ACQUIRE_BLK:.+]] |
| // OGCG: i32 2, label %[[ACQUIRE_BLK]] |
| // OGCG: i32 3, label %[[RELEASE_BLK:.+]] |
| // OGCG: i32 4, label %[[ACQ_REL_BLK:.+]] |
| // OGCG: i32 5, label %[[SEQ_CST_BLK:.+]] |
| // OGCG: ] |
| // OGCG: [[ACQUIRE_BLK]]: |
| // OGCG: fence syncscope("singlethread") acquire |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[RELEASE_BLK]]: |
| // OGCG: fence syncscope("singlethread") release |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[ACQ_REL_BLK]]: |
| // OGCG: fence syncscope("singlethread") acq_rel |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[SEQ_CST_BLK]]: |
| // OGCG: fence syncscope("singlethread") seq_cst |
| // OGCG: br label %[[DEFAULT_BLK]] |
| // OGCG: [[DEFAULT_BLK]]: |
| // OGCG: ret void |
| } |