1! This test checks lowering of atomic and atomic update constructs 2! RUN: bbc -fopenmp -emit-fir %s -o - | FileCheck %s 3! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s 4 5program OmpAtomicUpdate 6 use omp_lib 7 integer :: x, y, z 8 integer, pointer :: a, b 9 integer, target :: c, d 10 a=>c 11 b=>d 12 13!CHECK: func.func @_QQmain() { 14!CHECK: %[[A:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "a", uniq_name = "_QFEa"} 15!CHECK: %[[A_ADDR:.*]] = fir.alloca !fir.ptr<i32> {uniq_name = "_QFEa.addr"} 16!CHECK: %{{.*}} = fir.zero_bits !fir.ptr<i32> 17!CHECK: fir.store %{{.*}} to %[[A_ADDR]] : !fir.ref<!fir.ptr<i32>> 18!CHECK: %[[B:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "b", uniq_name = "_QFEb"} 19!CHECK: %[[B_ADDR:.*]] = fir.alloca !fir.ptr<i32> {uniq_name = "_QFEb.addr"} 20!CHECK: %{{.*}} = fir.zero_bits !fir.ptr<i32> 21!CHECK: fir.store %{{.*}} to %[[B_ADDR]] : !fir.ref<!fir.ptr<i32>> 22!CHECK: %[[C_ADDR:.*]] = fir.address_of(@_QFEc) : !fir.ref<i32> 23!CHECK: %[[D_ADDR:.*]] = fir.address_of(@_QFEd) : !fir.ref<i32> 24!CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} 25!CHECK: %[[Y:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFEy"} 26!CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFEz"} 27!CHECK: %{{.*}} = fir.convert %[[C_ADDR]] : (!fir.ref<i32>) -> !fir.ptr<i32> 28!CHECK: fir.store %{{.*}} to %[[A_ADDR]] : !fir.ref<!fir.ptr<i32>> 29!CHECK: %{{.*}} = fir.convert %[[D_ADDR]] : (!fir.ref<i32>) -> !fir.ptr<i32> 30!CHECK: fir.store {{.*}} to %[[B_ADDR]] : !fir.ref<!fir.ptr<i32>> 31!CHECK: %[[LOADED_A:.*]] = fir.load %[[A_ADDR]] : !fir.ref<!fir.ptr<i32>> 32!CHECK: omp.atomic.update %[[LOADED_A]] : !fir.ptr<i32> { 33!CHECK: ^bb0(%[[ARG:.*]]: i32): 34!CHECK: %[[LOADED_B:.*]] = fir.load %[[B_ADDR]] : !fir.ref<!fir.ptr<i32>> 35!CHECK: %{{.*}} = fir.load %[[LOADED_B]] : !fir.ptr<i32> 36!CHECK: %[[RESULT:.*]] = arith.addi %[[ARG]], %{{.*}} : i32 37!CHECK: omp.yield(%[[RESULT]] : i32) 38!CHECK: } 39 !$omp atomic update 40 a = a + b 41 42!CHECK: omp.atomic.update %[[Y]] : !fir.ref<i32> { 43!CHECK: ^bb0(%[[ARG:.*]]: i32): 44!CHECK: {{.*}} = arith.constant 1 : i32 45!CHECK: %[[RESULT:.*]] = arith.addi %[[ARG]], {{.*}} : i32 46!CHECK: omp.yield(%[[RESULT]] : i32) 47!CHECK: } 48!CHECK: omp.atomic.update %[[Z]] : !fir.ref<i32> { 49!CHECK: ^bb0(%[[ARG:.*]]: i32): 50!CHECK: %[[LOADED_X:.*]] = fir.load %[[X]] : !fir.ref<i32> 51!CHECK: %[[RESULT:.*]] = arith.muli %[[LOADED_X]], %[[ARG]] : i32 52!CHECK: omp.yield(%[[RESULT]] : i32) 53!CHECK: } 54 !$omp atomic 55 y = y + 1 56 !$omp atomic update 57 z = x * z 58 59!CHECK: omp.atomic.update memory_order(relaxed) hint(uncontended) %[[X]] : !fir.ref<i32> { 60!CHECK: ^bb0(%[[ARG:.*]]: i32): 61!CHECK: %{{.*}} = arith.constant 1 : i32 62!CHECK: %[[RESULT:.*]] = arith.subi %[[ARG]], {{.*}} : i32 63!CHECK: omp.yield(%[[RESULT]] : i32) 64!CHECK: } 65!CHECK: omp.atomic.update memory_order(relaxed) %[[Y]] : !fir.ref<i32> { 66!CHECK: ^bb0(%[[ARG:.*]]: i32): 67!CHECK: %[[LOADED_X:.*]] = fir.load %[[X]] : !fir.ref<i32> 68!CHECK: %[[LOADED_Z:.*]] = fir.load %[[Z]] : !fir.ref<i32> 69!CHECK: %{{.*}} = arith.cmpi sgt, %[[LOADED_X]], %[[ARG]] : i32 70!CHECK: %{{.*}} = arith.select %{{.*}}, %[[LOADED_X]], %[[ARG]] : i32 71!CHECK: %{{.*}} = arith.cmpi sgt, %{{.*}}, %[[LOADED_Z]] : i32 72!CHECK: %[[RESULT:.*]] = arith.select %{{.*}}, %{{.*}}, %[[LOADED_Z]] : i32 73!CHECK: omp.yield(%[[RESULT]] : i32) 74!CHECK: } 75!CHECK: omp.atomic.update memory_order(relaxed) hint(contended) %[[Z]] : !fir.ref<i32> { 76!CHECK: ^bb0(%[[ARG:.*]]: i32): 77!CHECK: %[[LOADED_X:.*]] = fir.load %[[X]] : !fir.ref<i32> 78!CHECK: %[[RESULT:.*]] = arith.addi %[[ARG]], %[[LOADED_X]] : i32 79!CHECK: omp.yield(%[[RESULT]] : i32) 80!CHECK: } 81 !$omp atomic relaxed update hint(omp_sync_hint_uncontended) 82 x = x - 1 83 !$omp atomic update relaxed 84 y = max(x, y, z) 85 !$omp atomic relaxed hint(omp_sync_hint_contended) 86 z = z + x 87 88!CHECK: omp.atomic.update memory_order(release) hint(contended) %[[Z]] : !fir.ref<i32> { 89!CHECK: ^bb0(%[[ARG:.*]]: i32): 90!CHECK: %{{.*}} = arith.constant 10 : i32 91!CHECK: %[[RESULT:.*]] = arith.muli {{.*}}, %[[ARG]] : i32 92!CHECK: omp.yield(%[[RESULT]] : i32) 93!CHECK: } 94!CHECK: omp.atomic.update memory_order(release) hint(speculative) %[[X]] : !fir.ref<i32> { 95!CHECK: ^bb0(%[[ARG:.*]]: i32): 96!CHECK: %[[LOADED_Z:.*]] = fir.load %[[Z]] : !fir.ref<i32> 97!CHECK: %[[RESULT:.*]] = arith.divsi %[[ARG]], %[[LOADED_Z]] : i32 98!CHECK: omp.yield(%[[RESULT]] : i32) 99!CHECK: } 100 101 !$omp atomic release update hint(omp_lock_hint_contended) 102 z = z * 10 103 !$omp atomic hint(omp_lock_hint_speculative) update release 104 x = x / z 105 106!CHECK: omp.atomic.update memory_order(seq_cst) hint(nonspeculative) %[[Y]] : !fir.ref<i32> { 107!CHECK: ^bb0(%[[ARG:.*]]: i32): 108!CHECK: %{{.*}} = arith.constant 10 : i32 109!CHECK: %[[RESULT:.*]] = arith.addi %{{.*}}, %[[ARG]] : i32 110!CHECK: omp.yield(%[[RESULT]] : i32) 111!CHECK: } 112!CHECK: omp.atomic.update memory_order(seq_cst) %[[Z]] : !fir.ref<i32> { 113!CHECK: ^bb0(%[[ARG:.*]]: i32): 114!CHECK: %[[LOADED_Y:.*]] = fir.load %[[Y]] : !fir.ref<i32> 115!CHECK: %[[RESULT:.*]] = arith.addi %[[LOADED_Y]], %[[ARG]] : i32 116!CHECK: omp.yield(%[[RESULT]] : i32) 117!CHECK: } 118!CHECK: return 119!CHECK: } 120 !$omp atomic hint(omp_sync_hint_nonspeculative) seq_cst 121 y = 10 + y 122 !$omp atomic seq_cst update 123 z = y + z 124end program OmpAtomicUpdate 125