! This test checks lowering of atomic and atomic update constructs ! RUN: bbc -fopenmp -emit-fir %s -o - | FileCheck %s ! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s program OmpAtomicUpdate use omp_lib integer :: x, y, z integer, pointer :: a, b integer, target :: c, d a=>c b=>d !CHECK: func.func @_QQmain() { !CHECK: %[[A:.*]] = fir.alloca !fir.box> {bindc_name = "a", uniq_name = "_QFEa"} !CHECK: %[[A_ADDR:.*]] = fir.alloca !fir.ptr {uniq_name = "_QFEa.addr"} !CHECK: %{{.*}} = fir.zero_bits !fir.ptr !CHECK: fir.store %{{.*}} to %[[A_ADDR]] : !fir.ref> !CHECK: %[[B:.*]] = fir.alloca !fir.box> {bindc_name = "b", uniq_name = "_QFEb"} !CHECK: %[[B_ADDR:.*]] = fir.alloca !fir.ptr {uniq_name = "_QFEb.addr"} !CHECK: %{{.*}} = fir.zero_bits !fir.ptr !CHECK: fir.store %{{.*}} to %[[B_ADDR]] : !fir.ref> !CHECK: %[[C_ADDR:.*]] = fir.address_of(@_QFEc) : !fir.ref !CHECK: %[[D_ADDR:.*]] = fir.address_of(@_QFEd) : !fir.ref !CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} !CHECK: %[[Y:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFEy"} !CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFEz"} !CHECK: %{{.*}} = fir.convert %[[C_ADDR]] : (!fir.ref) -> !fir.ptr !CHECK: fir.store %{{.*}} to %[[A_ADDR]] : !fir.ref> !CHECK: %{{.*}} = fir.convert %[[D_ADDR]] : (!fir.ref) -> !fir.ptr !CHECK: fir.store {{.*}} to %[[B_ADDR]] : !fir.ref> !CHECK: %[[LOADED_A:.*]] = fir.load %[[A_ADDR]] : !fir.ref> !CHECK: omp.atomic.update %[[LOADED_A]] : !fir.ptr { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %[[LOADED_B:.*]] = fir.load %[[B_ADDR]] : !fir.ref> !CHECK: %{{.*}} = fir.load %[[LOADED_B]] : !fir.ptr !CHECK: %[[RESULT:.*]] = arith.addi %[[ARG]], %{{.*}} : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !$omp atomic update a = a + b !CHECK: omp.atomic.update %[[Y]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: {{.*}} = arith.constant 1 : i32 !CHECK: %[[RESULT:.*]] = arith.addi %[[ARG]], {{.*}} : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !CHECK: omp.atomic.update %[[Z]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %[[LOADED_X:.*]] = fir.load %[[X]] : !fir.ref !CHECK: %[[RESULT:.*]] = arith.muli %[[LOADED_X]], %[[ARG]] : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !$omp atomic y = y + 1 !$omp atomic update z = x * z !CHECK: omp.atomic.update memory_order(relaxed) hint(uncontended) %[[X]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %{{.*}} = arith.constant 1 : i32 !CHECK: %[[RESULT:.*]] = arith.subi %[[ARG]], {{.*}} : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !CHECK: omp.atomic.update memory_order(relaxed) %[[Y]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %[[LOADED_X:.*]] = fir.load %[[X]] : !fir.ref !CHECK: %[[LOADED_Z:.*]] = fir.load %[[Z]] : !fir.ref !CHECK: %{{.*}} = arith.cmpi sgt, %[[LOADED_X]], %[[ARG]] : i32 !CHECK: %{{.*}} = arith.select %{{.*}}, %[[LOADED_X]], %[[ARG]] : i32 !CHECK: %{{.*}} = arith.cmpi sgt, %{{.*}}, %[[LOADED_Z]] : i32 !CHECK: %[[RESULT:.*]] = arith.select %{{.*}}, %{{.*}}, %[[LOADED_Z]] : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !CHECK: omp.atomic.update memory_order(relaxed) hint(contended) %[[Z]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %[[LOADED_X:.*]] = fir.load %[[X]] : !fir.ref !CHECK: %[[RESULT:.*]] = arith.addi %[[ARG]], %[[LOADED_X]] : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !$omp atomic relaxed update hint(omp_sync_hint_uncontended) x = x - 1 !$omp atomic update relaxed y = max(x, y, z) !$omp atomic relaxed hint(omp_sync_hint_contended) z = z + x !CHECK: omp.atomic.update memory_order(release) hint(contended) %[[Z]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %{{.*}} = arith.constant 10 : i32 !CHECK: %[[RESULT:.*]] = arith.muli {{.*}}, %[[ARG]] : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !CHECK: omp.atomic.update memory_order(release) hint(speculative) %[[X]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %[[LOADED_Z:.*]] = fir.load %[[Z]] : !fir.ref !CHECK: %[[RESULT:.*]] = arith.divsi %[[ARG]], %[[LOADED_Z]] : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !$omp atomic release update hint(omp_lock_hint_contended) z = z * 10 !$omp atomic hint(omp_lock_hint_speculative) update release x = x / z !CHECK: omp.atomic.update memory_order(seq_cst) hint(nonspeculative) %[[Y]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %{{.*}} = arith.constant 10 : i32 !CHECK: %[[RESULT:.*]] = arith.addi %{{.*}}, %[[ARG]] : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !CHECK: omp.atomic.update memory_order(seq_cst) %[[Z]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %[[LOADED_Y:.*]] = fir.load %[[Y]] : !fir.ref !CHECK: %[[RESULT:.*]] = arith.addi %[[LOADED_Y]], %[[ARG]] : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !CHECK: return !CHECK: } !$omp atomic hint(omp_sync_hint_nonspeculative) seq_cst y = 10 + y !$omp atomic seq_cst update z = y + z end program OmpAtomicUpdate