! This test checks lowering of atomic and atomic update constructs ! RUN: bbc --use-desc-for-alloc=false -fopenmp -emit-fir -hlfir=false %s -o - | FileCheck %s ! RUN: %flang_fc1 -mllvm --use-desc-for-alloc=false -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s program OmpAtomicUpdate use omp_lib integer :: x, y, z integer, pointer :: a, b integer, target :: c, d integer(1) :: i1 a=>c b=>d !CHECK: func.func @_QQmain() attributes {fir.bindc_name = "ompatomicupdate"} { !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: %[[I1:.*]] = fir.alloca i8 {bindc_name = "i1", uniq_name = "_QFEi1"} !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: %[[LOADED_B:.*]] = fir.load %[[B_ADDR]] : !fir.ref> !CHECK: %{{.*}} = fir.load %[[LOADED_B]] : !fir.ptr !CHECK: omp.atomic.update %[[LOADED_A]] : !fir.ptr { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %[[RESULT:.*]] = arith.addi %[[ARG]], %{{.*}} : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !$omp atomic update a = a + b !CHECK: {{.*}} = arith.constant 1 : i32 !CHECK: omp.atomic.update %[[Y]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %[[RESULT:.*]] = arith.addi %[[ARG]], {{.*}} : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !CHECK: %[[LOADED_X:.*]] = fir.load %[[X]] : !fir.ref !CHECK: omp.atomic.update %[[Z]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !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: %{{.*}} = arith.constant 1 : i32 !CHECK: omp.atomic.update memory_order(relaxed) hint(uncontended) %[[X]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %[[RESULT:.*]] = arith.subi %[[ARG]], {{.*}} : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !CHECK: %[[LOADED_X:.*]] = fir.load %[[X]] : !fir.ref !CHECK: %[[LOADED_Z:.*]] = fir.load %[[Z]] : !fir.ref !CHECK: omp.atomic.update memory_order(relaxed) %[[Y]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %{{.*}} = arith.cmpi sgt, %[[ARG]], %[[LOADED_X]] : i32 !CHECK: %{{.*}} = arith.select %{{.*}}, %[[ARG]], %[[LOADED_X]] : i32 !CHECK: %{{.*}} = arith.cmpi sgt, %{{.*}}, %[[LOADED_Z]] : i32 !CHECK: %[[RESULT:.*]] = arith.select %{{.*}}, %{{.*}}, %[[LOADED_Z]] : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !CHECK: %[[LOADED_X:.*]] = fir.load %[[X]] : !fir.ref !CHECK: omp.atomic.update memory_order(relaxed) hint(contended) %[[Z]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !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(y, x, z) !$omp atomic relaxed hint(omp_sync_hint_contended) z = z + x !CHECK: %{{.*}} = arith.constant 10 : i32 !CHECK: omp.atomic.update memory_order(release) hint(contended) %[[Z]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %[[RESULT:.*]] = arith.muli {{.*}}, %[[ARG]] : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !CHECK: %[[LOADED_Z:.*]] = fir.load %[[Z]] : !fir.ref !CHECK: omp.atomic.update memory_order(release) hint(speculative) %[[X]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !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: %{{.*}} = arith.constant 10 : i32 !CHECK: omp.atomic.update memory_order(seq_cst) hint(nonspeculative) %[[Y]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %[[RESULT:.*]] = arith.addi %{{.*}}, %[[ARG]] : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !CHECK: %[[LOADED_Y:.*]] = fir.load %[[Y]] : !fir.ref !CHECK: omp.atomic.update memory_order(seq_cst) %[[Z]] : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %[[RESULT:.*]] = arith.addi %[[LOADED_Y]], %[[ARG]] : i32 !CHECK: omp.yield(%[[RESULT]] : i32) !CHECK: } !$omp atomic hint(omp_sync_hint_nonspeculative) seq_cst y = 10 + y !$omp atomic seq_cst update z = y + z !CHECK: %[[C1_VAL:.*]] = arith.constant 1 : i32 !CHECK: omp.atomic.update %[[I1]] : !fir.ref { !CHECK: ^bb0(%[[VAL:.*]]: i8): !CHECK: %[[CVT_VAL:.*]] = fir.convert %[[VAL]] : (i8) -> i32 !CHECK: %[[ADD_VAL:.*]] = arith.addi %[[CVT_VAL]], %[[C1_VAL]] : i32 !CHECK: %[[UPDATED_VAL:.*]] = fir.convert %[[ADD_VAL]] : (i32) -> i8 !CHECK: omp.yield(%[[UPDATED_VAL]] : i8) !CHECK: } !$omp atomic i1 = i1 + 1 !$omp end atomic !CHECK: return !CHECK: } end program OmpAtomicUpdate