// RUN: fir-opt %s --fir-acc-recipe-bufferization -split-input-file | FileCheck %s // ----- acc.private.recipe @priv_ref_box : !fir.box init { ^bb0(%arg0: !fir.box): %1 = fir.allocmem i32 %2 = fir.embox %1 : (!fir.heap) -> !fir.box acc.yield %2 : !fir.box } destroy { ^bb0(%arg0: !fir.box, %arg1: !fir.box): %0 = fir.box_addr %arg1 : (!fir.box) -> !fir.ref %1 = fir.convert %0 : (!fir.ref) -> !fir.heap fir.freemem %1 : !fir.heap acc.yield } // CHECK-LABEL: acc.private.recipe @priv_ref_box : !fir.ref> init // CHECK: ^bb0(%[[ARG:.*]]: !fir.ref>) // CHECK: %[[EMBOX:.*]] = fir.embox // CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.box // CHECK: fir.store %[[EMBOX]] to %[[ALLOCA]] : !fir.ref> // CHECK: acc.yield %[[ALLOCA]] : !fir.ref> // CHECK: } destroy { // CHECK: ^bb0(%[[DARG0:.*]]: !fir.ref>, %[[DARG1:.*]]: !fir.ref>) // CHECK: %[[LD1:.*]] = fir.load %[[DARG1]] : !fir.ref> // CHECK: %[[ADDR:.*]] = fir.box_addr %[[LD1]] : (!fir.box) -> !fir.ref // CHECK: %[[CVT:.*]] = fir.convert %[[ADDR]] : (!fir.ref) -> !fir.heap // ----- // Test private recipe without destroy region. acc.private.recipe @priv_ref_box_no_destroy : !fir.box init { ^bb0(%arg0: !fir.box): %1 = fir.alloca i32 %2 = fir.embox %1 : (!fir.ref) -> !fir.box acc.yield %2 : !fir.box } // CHECK-LABEL: acc.private.recipe @priv_ref_box_no_destroy : !fir.ref> init // CHECK: ^bb0(%[[ARG:.*]]: !fir.ref>) // CHECK: %[[EMBOX:.*]] = fir.embox // CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.box // CHECK: fir.store %[[EMBOX]] to %[[ALLOCA]] : !fir.ref> // CHECK: acc.yield %[[ALLOCA]] : !fir.ref> // CHECK: } // ----- // Firstprivate recipe with destroy region. acc.firstprivate.recipe @fp_ref_box : !fir.box init { ^bb0(%arg0: !fir.box): %0 = fir.allocmem i32 %1 = fir.embox %0 : (!fir.heap) -> !fir.box acc.yield %1 : !fir.box } copy { ^bb0(%src: !fir.box, %dst: !fir.box): %s_addr = fir.box_addr %src : (!fir.box) -> !fir.ref %val = fir.load %s_addr : !fir.ref %d_addr = fir.box_addr %dst : (!fir.box) -> !fir.ref fir.store %val to %d_addr : !fir.ref acc.yield } destroy { ^bb0(%arg0: !fir.box, %arg1: !fir.box): acc.yield } // CHECK-LABEL: acc.firstprivate.recipe @fp_ref_box : !fir.ref> init // CHECK: ^bb0(%[[IARG:.*]]: !fir.ref>) // CHECK: %[[EMBOX_FP:.*]] = fir.embox // CHECK: %[[ALLOCA_FP:.*]] = fir.alloca !fir.box // CHECK: fir.store %[[EMBOX_FP]] to %[[ALLOCA_FP]] : !fir.ref> // CHECK: acc.yield %[[ALLOCA_FP]] : !fir.ref> // CHECK: } copy { // CHECK: ^bb0(%[[SRC:.*]]: !fir.ref>, %[[DST:.*]]: !fir.ref>) // CHECK: %[[LSRC:.*]] = fir.load %[[SRC]] : !fir.ref> // CHECK: %[[LDST:.*]] = fir.load %[[DST]] : !fir.ref> // CHECK: %[[SADDR:.*]] = fir.box_addr %[[LSRC]] : (!fir.box) -> !fir.ref // CHECK: %[[VAL:.*]] = fir.load %[[SADDR]] : !fir.ref // CHECK: %[[DADDR:.*]] = fir.box_addr %[[LDST]] : (!fir.box) -> !fir.ref // CHECK: fir.store %[[VAL]] to %[[DADDR]] : !fir.ref // CHECK: } destroy { // CHECK: ^bb0(%[[FDARG0:.*]]: !fir.ref>, %[[FDARG1:.*]]: !fir.ref>) // ----- // Firstprivate recipe without destroy region. acc.firstprivate.recipe @fp_ref_box_no_destroy : !fir.box init { ^bb0(%arg0: !fir.box): %0 = fir.alloca i32 %1 = fir.embox %0 : (!fir.ref) -> !fir.box acc.yield %1 : !fir.box } copy { ^bb0(%src: !fir.box, %dst: !fir.box): %s_addr = fir.box_addr %src : (!fir.box) -> !fir.ref %val = fir.load %s_addr : !fir.ref %d_addr = fir.box_addr %dst : (!fir.box) -> !fir.ref fir.store %val to %d_addr : !fir.ref acc.yield } // CHECK-LABEL: acc.firstprivate.recipe @fp_ref_box_no_destroy : !fir.ref> init // CHECK: ^bb0(%[[IARG2:.*]]: !fir.ref>) // CHECK: %[[EMBOX_FP2:.*]] = fir.embox // CHECK: %[[ALLOCA_FP2:.*]] = fir.alloca !fir.box // CHECK: fir.store %[[EMBOX_FP2]] to %[[ALLOCA_FP2]] : !fir.ref> // CHECK: acc.yield %[[ALLOCA_FP2]] : !fir.ref> // CHECK: } copy { // CHECK: ^bb0(%[[SRC2:.*]]: !fir.ref>, %[[DST2:.*]]: !fir.ref>) // CHECK: %[[LSRC2:.*]] = fir.load %[[SRC2]] : !fir.ref> // CHECK: %[[LDST2:.*]] = fir.load %[[DST2]] : !fir.ref> // CHECK: %[[SADDR2:.*]] = fir.box_addr %[[LSRC2]] : (!fir.box) -> !fir.ref // CHECK: %[[VAL2:.*]] = fir.load %[[SADDR2]] : !fir.ref // CHECK: %[[DADDR2:.*]] = fir.box_addr %[[LDST2]] : (!fir.box) -> !fir.ref // CHECK: fir.store %[[VAL2]] to %[[DADDR2]] : !fir.ref // ----- // Reduction recipe with destroy region. acc.reduction.recipe @red_ref_box : !fir.box reduction_operator init { ^bb0(%arg0: !fir.box): %0 = fir.allocmem i32 %1 = fir.embox %0 : (!fir.heap) -> !fir.box acc.yield %1 : !fir.box } combiner { ^bb0(%lhs: !fir.box, %rhs: !fir.box): %l_addr = fir.box_addr %lhs : (!fir.box) -> !fir.ref %l_val = fir.load %l_addr : !fir.ref %r_addr = fir.box_addr %rhs : (!fir.box) -> !fir.ref %r_val = fir.load %r_addr : !fir.ref %sum = arith.addi %l_val, %r_val : i32 %tmp = fir.alloca i32 fir.store %sum to %tmp : !fir.ref %new = fir.embox %tmp : (!fir.ref) -> !fir.box acc.yield %new : !fir.box } destroy { ^bb0(%arg0: !fir.box, %arg1: !fir.box): acc.yield } // CHECK-LABEL: acc.reduction.recipe @red_ref_box : !fir.ref> reduction_operator init // CHECK: ^bb0(%[[IARGR:.*]]: !fir.ref>) // CHECK: %[[EMBOXR:.*]] = fir.embox // CHECK: %[[ALLOCAR:.*]] = fir.alloca !fir.box // CHECK: fir.store %[[EMBOXR]] to %[[ALLOCAR]] : !fir.ref> // CHECK: acc.yield %[[ALLOCAR]] : !fir.ref> // CHECK: } combiner { // CHECK: ^bb0(%[[LHS:.*]]: !fir.ref>, %[[RHS:.*]]: !fir.ref>) // CHECK: %[[LLHS:.*]] = fir.load %[[LHS]] : !fir.ref> // CHECK: %[[LRHS:.*]] = fir.load %[[RHS]] : !fir.ref> // CHECK: %[[LADDR:.*]] = fir.box_addr %[[LLHS]] : (!fir.box) -> !fir.ref // CHECK: %[[LVAL:.*]] = fir.load %[[LADDR]] : !fir.ref // CHECK: %[[RADDR:.*]] = fir.box_addr %[[LRHS]] : (!fir.box) -> !fir.ref // CHECK: %[[RVAL:.*]] = fir.load %[[RADDR]] : !fir.ref // CHECK: %[[SUM:.*]] = arith.addi %[[LVAL]], %[[RVAL]] : i32 // CHECK: %[[I32ALLOCA:.*]] = fir.alloca i32 // CHECK: fir.store %[[SUM]] to %[[I32ALLOCA]] : !fir.ref // CHECK: %[[NEWBOX:.*]] = fir.embox %[[I32ALLOCA]] : (!fir.ref) -> !fir.box // CHECK: %[[BOXALLOCA:.*]] = fir.alloca !fir.box // CHECK: fir.store %[[NEWBOX]] to %[[BOXALLOCA]] : !fir.ref> // CHECK: acc.yield %[[BOXALLOCA]] : !fir.ref> // CHECK: } destroy { // CHECK: ^bb0(%[[RD0:.*]]: !fir.ref>, %[[RD1:.*]]: !fir.ref>) // ----- // Reduction recipe without destroy region. acc.reduction.recipe @red_ref_box_no_destroy : !fir.box reduction_operator init { ^bb0(%arg0: !fir.box): %0 = fir.alloca i32 %1 = fir.embox %0 : (!fir.ref) -> !fir.box acc.yield %1 : !fir.box } combiner { ^bb0(%lhs: !fir.box, %rhs: !fir.box): %l_addr = fir.box_addr %lhs : (!fir.box) -> !fir.ref %l_val = fir.load %l_addr : !fir.ref %r_addr = fir.box_addr %rhs : (!fir.box) -> !fir.ref %r_val = fir.load %r_addr : !fir.ref %sum = arith.addi %l_val, %r_val : i32 %tmp = fir.alloca i32 fir.store %sum to %tmp : !fir.ref %new = fir.embox %tmp : (!fir.ref) -> !fir.box acc.yield %new : !fir.box } // CHECK-LABEL: acc.reduction.recipe @red_ref_box_no_destroy : !fir.ref> reduction_operator init // CHECK: ^bb0(%[[IARGR2:.*]]: !fir.ref>) // CHECK: %[[EMBOXR2:.*]] = fir.embox // CHECK: %[[ALLOCAR2:.*]] = fir.alloca !fir.box // CHECK: fir.store %[[EMBOXR2]] to %[[ALLOCAR2]] : !fir.ref> // CHECK: acc.yield %[[ALLOCAR2]] : !fir.ref> // CHECK: } combiner { // CHECK: ^bb0(%[[LHS2:.*]]: !fir.ref>, %[[RHS2:.*]]: !fir.ref>) // CHECK: %[[LLHS2:.*]] = fir.load %[[LHS2]] : !fir.ref> // CHECK: %[[LRHS2:.*]] = fir.load %[[RHS2]] : !fir.ref> // CHECK: %[[LADDR2:.*]] = fir.box_addr %[[LLHS2]] : (!fir.box) -> !fir.ref // CHECK: %[[LVAL2:.*]] = fir.load %[[LADDR2]] : !fir.ref // CHECK: %[[RADDR2:.*]] = fir.box_addr %[[LRHS2]] : (!fir.box) -> !fir.ref // CHECK: %[[RVAL2:.*]] = fir.load %[[RADDR2]] : !fir.ref // CHECK: %[[SUM2:.*]] = arith.addi %[[LVAL2]], %[[RVAL2]] : i32 // CHECK: %[[I32ALLOCA2:.*]] = fir.alloca i32 // CHECK: fir.store %[[SUM2]] to %[[I32ALLOCA2]] : !fir.ref // CHECK: %[[NEWBOX2:.*]] = fir.embox %[[I32ALLOCA2]] : (!fir.ref) -> !fir.box // CHECK: %[[BOXALLOCA2:.*]] = fir.alloca !fir.box // CHECK: fir.store %[[NEWBOX2]] to %[[BOXALLOCA2]] : !fir.ref> // CHECK: acc.yield %[[BOXALLOCA2]] : !fir.ref> // ----- // Comprehensive tests that also test recipe usages updates. acc.private.recipe @privatization_ref_i32 : !fir.ref init { ^bb0(%arg0: !fir.ref): %0 = fir.alloca i32 %1 = fir.declare %0 {uniq_name = "acc.private.init"} : (!fir.ref) -> !fir.ref acc.yield %1 : !fir.ref } acc.private.recipe @privatization_box_Uxf32 : !fir.box> init { ^bb0(%arg0: !fir.box>): %c0 = arith.constant 0 : index %0:3 = fir.box_dims %arg0, %c0 : (!fir.box>, index) -> (index, index, index) %1 = fir.shape %0#1 : (index) -> !fir.shape<1> %2 = fir.allocmem !fir.array, %0#1 {bindc_name = ".tmp", uniq_name = ""} %3 = fir.declare %2(%1) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> !fir.heap> %4 = fir.embox %3(%1) : (!fir.heap>, !fir.shape<1>) -> !fir.box> acc.yield %4 : !fir.box> } destroy { ^bb0(%arg0: !fir.box>, %arg1: !fir.box>): %0 = fir.box_addr %arg1 : (!fir.box>) -> !fir.ref> %1 = fir.convert %0 : (!fir.ref>) -> !fir.heap> fir.freemem %1 : !fir.heap> acc.terminator } func.func @_QPfoo(%arg0: !fir.box> {fir.bindc_name = "x"}) { %c200_i32 = arith.constant 200 : i32 %c1_i32 = arith.constant 1 : i32 %0 = fir.dummy_scope : !fir.dscope %1 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFfooEi"} %2 = fir.declare %1 {uniq_name = "_QFfooEi"} : (!fir.ref) -> !fir.ref %3 = fir.declare %arg0 dummy_scope %0 {uniq_name = "_QFfooEx"} : (!fir.box>, !fir.dscope) -> !fir.box> acc.parallel combined(loop) { %4 = acc.private var(%3 : !fir.box>) recipe(@privatization_box_Uxf32) -> !fir.box> {name = "x"} %5 = acc.private varPtr(%2 : !fir.ref) recipe(@privatization_ref_i32) -> !fir.ref {implicit = true, name = "i"} acc.loop combined(parallel) private(%4, %5 : !fir.box>, !fir.ref) control(%arg1 : i32) = (%c1_i32 : i32) to (%c200_i32 : i32) step (%c1_i32 : i32) { %6 = fir.dummy_scope : !fir.dscope %7 = fir.declare %4 dummy_scope %6 {uniq_name = "_QFfooEx"} : (!fir.box>, !fir.dscope) -> !fir.box> %8 = fir.declare %5 {uniq_name = "_QFfooEi"} : (!fir.ref) -> !fir.ref %9 = fir.convert %arg1 : (i32) -> f32 %10 = fir.convert %arg1 : (i32) -> i64 %11 = fir.array_coor %7 %10 : (!fir.box>, i64) -> !fir.ref fir.store %9 to %11 : !fir.ref acc.yield } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} acc.yield } return } // CHECK-LABEL: acc.private.recipe @privatization_ref_i32 : !fir.ref init { // CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): // CHECK: %[[VAL_1:.*]] = fir.alloca i32 // CHECK: %[[VAL_2:.*]] = fir.declare %[[VAL_1]] {uniq_name = "acc.private.init"} : (!fir.ref) -> !fir.ref // CHECK: acc.yield %[[VAL_2]] : !fir.ref // CHECK: } // CHECK-LABEL: acc.private.recipe @privatization_box_Uxf32 : !fir.ref>> init { // CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>): // CHECK: %[[VAL_1:.*]] = fir.load %[[VAL_0]] : !fir.ref>> // CHECK: %[[VAL_2:.*]] = arith.constant 0 : index // CHECK: %[[VAL_3:.*]]:3 = fir.box_dims %[[VAL_1]], %[[VAL_2]] : (!fir.box>, index) -> (index, index, index) // CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]]#1 : (index) -> !fir.shape<1> // CHECK: %[[VAL_5:.*]] = fir.allocmem !fir.array, %[[VAL_3]]#1 {bindc_name = ".tmp", uniq_name = ""} // CHECK: %[[VAL_6:.*]] = fir.declare %[[VAL_5]](%[[VAL_4]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> !fir.heap> // CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]](%[[VAL_4]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box> // CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box> // CHECK: fir.store %[[VAL_7]] to %[[VAL_8]] : !fir.ref>> // CHECK: acc.yield %[[VAL_8]] : !fir.ref>> // CHECK-LABEL: } destroy { // CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>>, %[[VAL_1:.*]]: !fir.ref>>): // CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]] : !fir.ref>> // CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_2]] : (!fir.box>) -> !fir.ref> // CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref>) -> !fir.heap> // CHECK: fir.freemem %[[VAL_4]] : !fir.heap> // CHECK: acc.terminator // CHECK: } // CHECK-LABEL: func.func @_QPfoo( // CHECK-SAME: %[[ARG0:.*]]: !fir.box> {fir.bindc_name = "x"}) { // CHECK: %[[VAL_0:.*]] = arith.constant 200 : i32 // CHECK: %[[VAL_1:.*]] = arith.constant 1 : i32 // CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope // CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFfooEi"} // CHECK: %[[VAL_4:.*]] = fir.declare %[[VAL_3]] {uniq_name = "_QFfooEi"} : (!fir.ref) -> !fir.ref // CHECK: %[[VAL_5:.*]] = fir.declare %[[ARG0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFfooEx"} : (!fir.box>, !fir.dscope) -> !fir.box> // CHECK: %[[VAL_6:.*]] = fir.alloca !fir.box> // CHECK: fir.store %[[VAL_5]] to %[[VAL_6]] : !fir.ref>> // CHECK: acc.parallel combined(loop) { // CHECK: %[[VAL_7:.*]] = acc.private varPtr(%[[VAL_6]] : !fir.ref>>) recipe(@privatization_box_Uxf32) -> !fir.ref>> {name = "x"} // CHECK: %[[VAL_8:.*]] = acc.private varPtr(%[[VAL_4]] : !fir.ref) recipe(@privatization_ref_i32) -> !fir.ref {implicit = true, name = "i"} // CHECK: acc.loop combined(parallel) private(%[[VAL_7]], %[[VAL_8]] : !fir.ref>>, !fir.ref) control(%[[VAL_9:.*]] : i32) = (%[[VAL_1]] : i32) to (%[[VAL_0]] : i32) step (%[[VAL_1]] : i32) { // CHECK: %[[VAL_10:.*]] = fir.dummy_scope : !fir.dscope // CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_7]] : !fir.ref>> // CHECK: %[[VAL_12:.*]] = fir.declare %[[VAL_11]] dummy_scope %[[VAL_10]] {uniq_name = "_QFfooEx"} : (!fir.box>, !fir.dscope) -> !fir.box> // CHECK: %[[VAL_13:.*]] = fir.declare %[[VAL_8]] {uniq_name = "_QFfooEi"} : (!fir.ref) -> !fir.ref // CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_9]] : (i32) -> f32 // CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_9]] : (i32) -> i64 // CHECK: %[[VAL_16:.*]] = fir.array_coor %[[VAL_12]] %[[VAL_15]] : (!fir.box>, i64) -> !fir.ref // CHECK: fir.store %[[VAL_14]] to %[[VAL_16]] : !fir.ref // CHECK: acc.yield // CHECK: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} // CHECK: acc.yield // CHECK: } // CHECK: return // CHECK: }