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 @@ -584,24 +584,52 @@ mlir::acc::ReductionOperator op) { if (op != mlir::acc::ReductionOperator::AccAdd && op != mlir::acc::ReductionOperator::AccMul && - op != mlir::acc::ReductionOperator::AccMin) + op != mlir::acc::ReductionOperator::AccMin && + op != mlir::acc::ReductionOperator::AccMax) TODO(loc, "reduction operator"); - // 0 for +, ior, ieor - // 1 for * - int64_t initValue = op == mlir::acc::ReductionOperator::AccMul ? 1 : 0; - + // min -> largest if (op == mlir::acc::ReductionOperator::AccMin) { - unsigned bits = ty.getIntOrFloatBitWidth(); - initValue = llvm::APInt::getSignedMinValue(bits).getSExtValue(); + 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))); + } + // max -> least + } else if (op == mlir::acc::ReductionOperator::AccMax) { + if (ty.isIntOrIndex()) + return builder.create( + loc, ty, + builder.getIntegerAttr( + ty, llvm::APInt::getSignedMinValue(ty.getIntOrFloatBitWidth()) + .getSExtValue())); + if (auto floatTy = mlir::dyn_cast_or_null(ty)) + return builder.create( + loc, ty, + builder.getFloatAttr( + ty, llvm::APFloat::getSmallest(floatTy.getFloatSemantics(), + /*negative=*/true))); + } 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)); } - 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"); } @@ -624,16 +652,27 @@ TODO(loc, "reduction mul type"); } - if (op == mlir::acc::ReductionOperator::AccMin) { + if (op == mlir::acc::ReductionOperator::AccMin || + op == mlir::acc::ReductionOperator::AccMax) { 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 (ty.isIntOrIndex()) { + mlir::arith::CmpIPredicate predicate = + op == mlir::acc::ReductionOperator::AccMin + ? mlir::arith::CmpIPredicate::slt + : mlir::arith::CmpIPredicate::sgt; + cmp = builder.create(loc, predicate, value1, value2); + } + if (mlir::isa(ty)) { + mlir::arith::CmpFPredicate predicate = + op == mlir::acc::ReductionOperator::AccMin + ? mlir::arith::CmpFPredicate::OLT + : mlir::arith::CmpFPredicate::OGT; + cmp = builder.create(loc, predicate, value1, value2); + } if (cmp) return builder.create(loc, cmp, value1, value2); - - TODO(loc, "reduction mul type"); + + TODO(loc, "reduction min/max 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,9 +2,31 @@ ! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s +! CHECK-LABEL: acc.reduction.recipe @reduction_max_f32 : f32 reduction_operator init { +! CHECK: ^bb0(%{{.*}}: f32): +! CHECK: %[[INIT:.*]] = arith.constant -1.401300e-45 : f32 +! CHECK: acc.yield %[[INIT]] : f32 +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: f32, %[[ARG1:.*]]: f32): +! CHECK: %[[CMP:.*]] = arith.cmpf ogt, %[[ARG0]], %[[ARG1]] : f32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[ARG0]], %[[ARG1]] : f32 +! CHECK: acc.yield %[[SELECT]] : f32 +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_i32 : i32 reduction_operator init { +! CHECK: ^bb0(%arg0: i32): +! CHECK: %[[INIT:.*]] = arith.constant -2147483648 : i32 +! CHECK: acc.yield %[[INIT]] : i32 +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32): +! CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[ARG0]], %[[ARG1]] : i32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[ARG0]], %[[ARG1]] : i32 +! CHECK: acc.yield %[[SELECT]] : i32 +! CHECK: } + ! CHECK-LABEL: acc.reduction.recipe @reduction_min_f32 : f32 reduction_operator init { ! CHECK: ^bb0(%{{.*}}: f32): -! CHECK: %[[INIT:.*]] = arith.constant -2.14748365E+9 : f32 +! CHECK: %[[INIT:.*]] = arith.constant 3.40282347E+38 : f32 ! CHECK: acc.yield %[[INIT]] : f32 ! CHECK: } combiner { ! CHECK: ^bb0(%[[ARG0:.*]]: f32, %[[ARG1:.*]]: f32): @@ -15,7 +37,7 @@ ! CHECK-LABEL: acc.reduction.recipe @reduction_min_i32 : i32 reduction_operator init { ! CHECK: ^bb0(%arg0: i32): -! CHECK: %[[INIT:.*]] = arith.constant -2147483648 : i32 +! CHECK: %[[INIT:.*]] = arith.constant 2147483647 : i32 ! CHECK: acc.yield %[[INIT]] : i32 ! CHECK: } combiner { ! CHECK: ^bb0(%[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32): @@ -148,3 +170,31 @@ ! 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) + +subroutine acc_reduction_max_int(a, b) + integer :: a(100) + integer :: i, b + + !$acc loop reduction(max:b) + do i = 1, 100 + b = max(b, a(i)) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_max_int( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref {fir.bindc_name = "b"}) +! CHECK: acc.loop reduction(@reduction_max_i32 -> %[[B]] : !fir.ref) + +subroutine acc_reduction_max_float(a, b) + real :: a(100), b + integer :: i + + !$acc loop reduction(max:b) + do i = 1, 100 + b = max(b, a(i)) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_max_float( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref {fir.bindc_name = "b"}) +! CHECK: acc.loop reduction(@reduction_max_f32 -> %[[B]] : !fir.ref)