// RUN: mlir-opt %s -acc-implicit-data=enable-implicit-reduction-copy=true -split-input-file | FileCheck %s --check-prefix=COPY // RUN: mlir-opt %s -acc-implicit-data=enable-implicit-reduction-copy=false -split-input-file | FileCheck %s --check-prefix=FIRSTPRIVATE // Test case: scalar reduction variable in parallel loop // When enable-implicit-reduction-copy=true: expect copyin/copyout for reduction variable // When enable-implicit-reduction-copy=false: expect firstprivate for reduction variable acc.reduction.recipe @reduction_add_memref_i32 : memref reduction_operator init { ^bb0(%arg0: memref): %c0_i32 = arith.constant 0 : i32 %alloc = memref.alloca() : memref memref.store %c0_i32, %alloc[] : memref acc.yield %alloc : memref } combiner { ^bb0(%arg0: memref, %arg1: memref): %0 = memref.load %arg0[] : memref %1 = memref.load %arg1[] : memref %2 = arith.addi %0, %1 : i32 memref.store %2, %arg0[] : memref acc.yield %arg0 : memref } func.func @test_reduction_implicit_copy() { %c1_i32 = arith.constant 1 : i32 %c100_i32 = arith.constant 100 : i32 %c0_i32 = arith.constant 0 : i32 %r = memref.alloca() : memref memref.store %c0_i32, %r[] : memref acc.parallel { %red_var = acc.reduction varPtr(%r : memref) recipe(@reduction_add_memref_i32) -> memref {name = "r"} acc.loop reduction(%red_var : memref) control(%iv : i32) = (%c1_i32 : i32) to (%c100_i32 : i32) step (%c1_i32 : i32) { %load = memref.load %red_var[] : memref %add = arith.addi %load, %c1_i32 : i32 memref.store %add, %red_var[] : memref acc.yield } attributes {independent = [#acc.device_type]} acc.yield } return } // When enable-implicit-reduction-copy=true: expect copyin/copyout for reduction variable // COPY-LABEL: func.func @test_reduction_implicit_copy // COPY: %[[COPYIN:.*]] = acc.copyin varPtr({{.*}} : memref) -> memref {dataClause = #acc, implicit = true, name = ""} // COPY: acc.copyout accPtr(%[[COPYIN]] : memref) to varPtr({{.*}} : memref) {dataClause = #acc, implicit = true, name = ""} // When enable-implicit-reduction-copy=false: expect firstprivate for reduction variable // FIRSTPRIVATE-LABEL: func.func @test_reduction_implicit_copy // FIRSTPRIVATE: acc.firstprivate varPtr({{.*}} : memref) recipe({{.*}}) -> memref {implicit = true, name = ""} // FIRSTPRIVATE-NOT: acc.copyin // FIRSTPRIVATE-NOT: acc.copyout // ----- // Test case: reduction variable used both in loop and outside // Should be firstprivate regardless of the flag setting acc.reduction.recipe @reduction_add_memref_i32_2 : memref reduction_operator init { ^bb0(%arg0: memref): %c0_i32 = arith.constant 0 : i32 %alloc = memref.alloca() : memref memref.store %c0_i32, %alloc[] : memref acc.yield %alloc : memref } combiner { ^bb0(%arg0: memref, %arg1: memref): %0 = memref.load %arg0[] : memref %1 = memref.load %arg1[] : memref %2 = arith.addi %0, %1 : i32 memref.store %2, %arg0[] : memref acc.yield %arg0 : memref } func.func @test_reduction_with_usage_outside_loop() { %c1_i32 = arith.constant 1 : i32 %c100_i32 = arith.constant 100 : i32 %c0_i32 = arith.constant 0 : i32 %r = memref.alloca() : memref %out = memref.alloca() : memref memref.store %c0_i32, %r[] : memref %out_create = acc.create varPtr(%out : memref) -> memref {dataClause = #acc, name = "out"} acc.parallel dataOperands(%out_create : memref) { %red_var = acc.reduction varPtr(%r : memref) recipe(@reduction_add_memref_i32_2) -> memref {name = "r"} acc.loop reduction(%red_var : memref) control(%iv : i32) = (%c1_i32 : i32) to (%c100_i32 : i32) step (%c1_i32 : i32) { %load = memref.load %red_var[] : memref %add = arith.addi %load, %c1_i32 : i32 memref.store %add, %red_var[] : memref acc.yield } attributes {independent = [#acc.device_type]} // out = r (usage of r outside the loop) %final_r = memref.load %r[] : memref memref.store %final_r, %out_create[] : memref acc.yield } acc.copyout accPtr(%out_create : memref) to varPtr(%out : memref) {dataClause = #acc, name = "out"} return } // In this case, r should be firstprivate regardless of the flag setting // because it's used outside the reduction context // COPY-LABEL: func.func @test_reduction_with_usage_outside_loop // COPY: acc.firstprivate varPtr({{.*}} : memref) recipe({{.*}}) -> memref {implicit = true, name = ""} // COPY-NOT: acc.copyin varPtr({{.*}} : memref) -> memref {{.*}} name = "" // FIRSTPRIVATE-LABEL: func.func @test_reduction_with_usage_outside_loop // FIRSTPRIVATE: acc.firstprivate varPtr({{.*}} : memref) recipe({{.*}}) -> memref {implicit = true, name = ""} // FIRSTPRIVATE-NOT: acc.copyin varPtr({{.*}} : memref) -> memref {{.*}} name = ""