// 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 !cir.ptr, !cir.ptr>, ["d", init] {alignment = 8 : i64} // 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 // CIR: %[[DATA_VALUE:.*]] = cir.get_member %[[LOAD_DATA]][0] {name = "value"} : !cir.ptr -> !cir.ptr // CIR: cir.store{{.*}} %[[VAL_42]], %[[DATA_VALUE]] : !s32i, !cir.ptr // 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 !cir.ptr, !cir.ptr>, ["d", init] {alignment = 8 : i64} // 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 // CIR: %[[DATA_VALUE:.*]] = cir.get_member %[[LOAD_DATA]][0] {name = "value"} : !cir.ptr -> !cir.ptr // CIR: cir.store{{.*}} %[[VAL_42]], %[[DATA_VALUE]] : !s32i, !cir.ptr // 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 !cir.ptr, !cir.ptr>, ["d", init] {alignment = 8 : i64} // CIR: %[[ATOMIC_TEMP:.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["atomic-temp"] {alignment = 8 : i64} // CIR: cir.atomic.fence syncscope(system) seq_cst // CIR: %[[LOAD_DATA:.*]] = cir.load{{.*}} %[[DATA]] : !cir.ptr>, !cir.ptr // CIR: %[[DATA_VALUE:.*]] = cir.get_member %[[LOAD_DATA]][1] {name = "ptr"} : !cir.ptr -> !cir.ptr> // CIR: %[[ATOMIC_LOAD:.*]] = cir.load{{.*}} atomic(seq_cst) %[[DATA_VALUE]] : !cir.ptr>, !cir.ptr // CIR: cir.store{{.*}} %[[ATOMIC_LOAD]], %[[ATOMIC_TEMP]] : !cir.ptr, !cir.ptr> // CIR: %[[ATOMIC_LOAD_PTR:.*]] = cir.load{{.*}} %[[ATOMIC_TEMP]] : !cir.ptr>, !cir.ptr // 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 !cir.ptr, !cir.ptr>, ["d", init] {alignment = 8 : i64} // CIR: %[[ATOMIC_TEMP:.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["atomic-temp"] {alignment = 8 : i64} // CIR: cir.atomic.fence syncscope(single_thread) seq_cst // CIR: %[[LOAD_DATA:.*]] = cir.load{{.*}} %[[DATA]] : !cir.ptr>, !cir.ptr // CIR: %[[DATA_PTR:.*]] = cir.get_member %[[LOAD_DATA]][1] {name = "ptr"} : !cir.ptr -> !cir.ptr> // CIR: %[[ATOMIC_LOAD:.*]] = cir.load{{.*}} atomic(seq_cst) %[[DATA_PTR]] : !cir.ptr>, !cir.ptr // CIR: cir.store{{.*}} %[[ATOMIC_LOAD]], %[[ATOMIC_TEMP]] : !cir.ptr, !cir.ptr> // CIR: %[[LOAD_ATOMIC_TEMP:.*]] = cir.load{{.*}} %[[ATOMIC_TEMP]] : !cir.ptr>, !cir.ptr // 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 }