diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -583,19 +583,37 @@ mlir::Location loc, mlir::Type ty, mlir::acc::ReductionOperator op) { if (op != mlir::acc::ReductionOperator::AccAdd && - op != mlir::acc::ReductionOperator::AccMul) + op != mlir::acc::ReductionOperator::AccMul && + op != mlir::acc::ReductionOperator::AccMin) TODO(loc, "reduction operator"); - // 0 for +, ior, ieor - // 1 for * - unsigned initValue = op == mlir::acc::ReductionOperator::AccMul ? 1 : 0; - - if (ty.isIntOrIndex()) - return builder.create( - loc, ty, builder.getIntegerAttr(ty, initValue)); - if (mlir::isa(ty)) - return builder.create( - loc, ty, builder.getFloatAttr(ty, initValue)); + // min -> largest + if (op == mlir::acc::ReductionOperator::AccMin) { + if (ty.isIntOrIndex()) { + unsigned bits = ty.getIntOrFloatBitWidth(); + return builder.create( + loc, ty, + builder.getIntegerAttr( + ty, llvm::APInt::getSignedMaxValue(bits).getSExtValue())); + } + if (auto floatTy = mlir::dyn_cast_or_null(ty)) { + const llvm::fltSemantics &sem = floatTy.getFloatSemantics(); + return builder.create( + loc, ty, + builder.getFloatAttr( + ty, llvm::APFloat::getLargest(sem, /*negative=*/false))); + } + } else { + // 0 for +, ior, ieor + // 1 for * + int64_t initValue = op == mlir::acc::ReductionOperator::AccMul ? 1 : 0; + if (ty.isIntOrIndex()) + return builder.create( + loc, ty, builder.getIntegerAttr(ty, initValue)); + if (mlir::isa(ty)) + return builder.create( + loc, ty, builder.getFloatAttr(ty, initValue)); + } TODO(loc, "reduction type"); } @@ -617,6 +635,21 @@ return builder.create(loc, value1, value2); TODO(loc, "reduction mul type"); } + + if (op == mlir::acc::ReductionOperator::AccMin) { + mlir::Value cmp; + if (ty.isIntOrIndex()) + cmp = builder.create( + loc, mlir::arith::CmpIPredicate::slt, value1, value2); + if (mlir::isa(ty)) + cmp = builder.create( + loc, mlir::arith::CmpFPredicate::OLT, value1, value2); + if (cmp) + return builder.create(loc, cmp, value1, value2); + + TODO(loc, "reduction mul type"); + } + TODO(loc, "reduction operator"); } diff --git a/flang/test/Lower/OpenACC/acc-reduction.f90 b/flang/test/Lower/OpenACC/acc-reduction.f90 --- a/flang/test/Lower/OpenACC/acc-reduction.f90 +++ b/flang/test/Lower/OpenACC/acc-reduction.f90 @@ -2,6 +2,28 @@ ! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s +! CHECK-LABEL: acc.reduction.recipe @reduction_min_f32 : f32 reduction_operator init { +! CHECK: ^bb0(%{{.*}}: f32): +! CHECK: %[[INIT:.*]] = arith.constant 3.40282347E+38 : f32 +! CHECK: acc.yield %[[INIT]] : f32 +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: f32, %[[ARG1:.*]]: f32): +! CHECK: %[[CMP:.*]] = arith.cmpf olt, %[[ARG0]], %[[ARG1]] : f32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[ARG0]], %[[ARG1]] : f32 +! CHECK: acc.yield %[[SELECT]] : f32 +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_min_i32 : i32 reduction_operator init { +! CHECK: ^bb0(%arg0: i32): +! CHECK: %[[INIT:.*]] = arith.constant 2147483647 : i32 +! CHECK: acc.yield %[[INIT]] : i32 +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32): +! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[ARG0]], %[[ARG1]] : i32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[ARG0]], %[[ARG1]] : i32 +! CHECK: acc.yield %[[SELECT]] : i32 +! CHECK: } + ! CHECK-LABEL: acc.reduction.recipe @reduction_mul_f32 : f32 reduction_operator init { ! CHECK: ^bb0(%{{.*}}: f32): ! CHECK: %[[INIT:.*]] = arith.constant 1.000000e+00 : f32 @@ -97,3 +119,32 @@ ! CHECK-LABEL: func.func @_QPacc_reduction_mul_float( ! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref {fir.bindc_name = "b"}) ! CHECK: acc.loop reduction(@reduction_mul_f32 -> %[[B]] : !fir.ref) + + +subroutine acc_reduction_min_int(a, b) + integer :: a(100) + integer :: i, b + + !$acc loop reduction(min:b) + do i = 1, 100 + b = min(b, a(i)) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_min_int( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref {fir.bindc_name = "b"}) +! CHECK: acc.loop reduction(@reduction_min_i32 -> %[[B]] : !fir.ref) + +subroutine acc_reduction_min_float(a, b) + real :: a(100), b + integer :: i + + !$acc loop reduction(min:b) + do i = 1, 100 + b = min(b, a(i)) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_min_float( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref {fir.bindc_name = "b"}) +! CHECK: acc.loop reduction(@reduction_min_f32 -> %[[B]] : !fir.ref)