[flang-commits] [flang] 38bb79b - [Flang][OpenMP] Add support for OpenMP MIN reduction
Kavitha Natarajan via flang-commits
flang-commits at lists.llvm.org
Wed Apr 19 23:45:40 PDT 2023
Author: Kavitha Natarajan
Date: 2023-04-20T12:13:58+05:30
New Revision: 38bb79beac50ab4dda18b29d869c9000a7d916bc
URL: https://github.com/llvm/llvm-project/commit/38bb79beac50ab4dda18b29d869c9000a7d916bc
DIFF: https://github.com/llvm/llvm-project/commit/38bb79beac50ab4dda18b29d869c9000a7d916bc.diff
LOG: [Flang][OpenMP] Add support for OpenMP MIN reduction
This patch adds support for reduction of min-intrinsic for scalar
types. Min is lowered as a compare-select in the default lowering
flow for Flang. This pattern is matched and replaced with the
OpenMP dialect reduction operation.
Note: This is a temporary flow. The plan is to move to a flow
where the OpenMP reduction operation is inserted during lowering.
Added:
flang/test/Lower/OpenMP/wsloop-reduction-min.f90
Modified:
flang/lib/Lower/OpenMP.cpp
Removed:
flang/test/Lower/OpenMP/Todo/reduction-min.f90
################################################################################
diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp
index 21ad8630f062..8c201e0d30a2 100644
--- a/flang/lib/Lower/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP.cpp
@@ -1172,6 +1172,15 @@ static Value getReductionInitValue(mlir::Location loc, mlir::Type type,
unsigned bits = type.getIntOrFloatBitWidth();
int64_t minInt = llvm::APInt::getSignedMinValue(bits).getSExtValue();
return builder.createIntegerConstant(loc, type, minInt);
+ } else if (reductionOpName.contains("min")) {
+ if (auto ty = type.dyn_cast<mlir::FloatType>()) {
+ const llvm::fltSemantics &sem = ty.getFloatSemantics();
+ return builder.createRealConstant(
+ loc, type, llvm::APFloat::getSmallest(sem, /*Negative=*/true));
+ }
+ unsigned bits = type.getIntOrFloatBitWidth();
+ int64_t maxInt = llvm::APInt::getSignedMaxValue(bits).getSExtValue();
+ return builder.createIntegerConstant(loc, type, maxInt);
} else {
if (type.isa<FloatType>())
return builder.create<mlir::arith::ConstantOp>(
@@ -1255,6 +1264,10 @@ createReductionDecl(fir::FirOpBuilder &builder, llvm::StringRef reductionOpName,
reductionOp =
getReductionOperation<mlir::arith::MaxFOp, mlir::arith::MaxSIOp>(
builder, type, loc, op1, op2);
+ } else if (name->source == "min") {
+ reductionOp =
+ getReductionOperation<mlir::arith::MinFOp, mlir::arith::MinSIOp>(
+ builder, type, loc, op1, op2);
} else {
TODO(loc, "Reduction of some intrinsic operators is not supported");
}
@@ -1581,10 +1594,11 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
&redOperator.u)) {
if (const auto *name{Fortran::parser::Unwrap<Fortran::parser::Name>(
reductionIntrinsic)}) {
- if (name->source != "max") {
+ if ((name->source != "max") && (name->source != "min")) {
TODO(currentLocation,
"Reduction of intrinsic procedures is not supported");
}
+ std::string intrinsicOp = name->ToString();
for (const auto &ompObject : objectList.v) {
if (const auto *name{Fortran::parser::Unwrap<Fortran::parser::Name>(
ompObject)}) {
@@ -1596,7 +1610,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
assert(redType.isIntOrIndexOrFloat() &&
"Unsupported reduction type");
decl = createReductionDecl(
- firOpBuilder, getReductionName("max", redType),
+ firOpBuilder, getReductionName(intrinsicOp, redType),
*reductionIntrinsic, redType, currentLocation);
reductionDeclSymbols.push_back(SymbolRefAttr::get(
firOpBuilder.getContext(), decl.getSymName()));
@@ -2350,7 +2364,7 @@ void Fortran::lower::genOpenMPReduction(
&redOperator.u)) {
if (const auto *name{Fortran::parser::Unwrap<Fortran::parser::Name>(
reductionIntrinsic)}) {
- if (name->source != "max") {
+ if ((name->source != "max") && (name->source != "min")) {
continue;
}
for (const auto &ompObject : objectList.v) {
diff --git a/flang/test/Lower/OpenMP/Todo/reduction-min.f90 b/flang/test/Lower/OpenMP/Todo/reduction-min.f90
deleted file mode 100644
index 9880b6eb153b..000000000000
--- a/flang/test/Lower/OpenMP/Todo/reduction-min.f90
+++ /dev/null
@@ -1,16 +0,0 @@
-! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
-! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
-
-! CHECK: not yet implemented: Reduction of intrinsic procedures is not supported
-subroutine reduction_min(y)
- integer :: x, y(:)
- x = 0
- !$omp parallel
- !$omp do reduction(min:x)
- do i=1, 100
- x = min(x, y(i))
- end do
- !$omp end do
- !$omp end parallel
- print *, x
-end subroutine
diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min.f90
new file mode 100644
index 000000000000..de7107792756
--- /dev/null
+++ b/flang/test/Lower/OpenMP/wsloop-reduction-min.f90
@@ -0,0 +1,76 @@
+! RUN: bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
+! RUN: %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
+
+!CHECK: omp.reduction.declare @[[MIN_DECLARE_F:.*]] : f32 init {
+!CHECK: %[[MAXIMUM_VAL_F:.*]] = arith.constant -1.401300e-45 : f32
+!CHECK: omp.yield(%[[MAXIMUM_VAL_F]] : f32)
+!CHECK: combiner
+!CHECK: ^bb0(%[[ARG0_F:.*]]: f32, %[[ARG1_F:.*]]: f32):
+!CHECK: %[[COMB_VAL_F:.*]] = arith.minf %[[ARG0_F]], %[[ARG1_F]] {{.*}}: f32
+!CHECK: omp.yield(%[[COMB_VAL_F]] : f32)
+
+!CHECK: omp.reduction.declare @[[MIN_DECLARE_I:.*]] : i32 init {
+!CHECK: %[[MAXIMUM_VAL_I:.*]] = arith.constant 2147483647 : i32
+!CHECK: omp.yield(%[[MAXIMUM_VAL_I]] : i32)
+!CHECK: combiner
+!CHECK: ^bb0(%[[ARG0_I:.*]]: i32, %[[ARG1_I:.*]]: i32):
+!CHECK: %[[COMB_VAL_I:.*]] = arith.minsi %[[ARG0_I]], %[[ARG1_I]] : i32
+!CHECK: omp.yield(%[[COMB_VAL_I]] : i32)
+
+!CHECK-LABEL: @_QPreduction_min_int
+!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xi32>>
+!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_min_intEx"}
+!CHECK: omp.parallel
+!CHECK: omp.wsloop reduction(@[[MIN_DECLARE_I]] -> %[[X_REF]] : !fir.ref<i32>) for
+!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]]
+!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref<i32>
+!CHECK: omp.reduction %[[Y_I]], %[[X_REF]] : i32, !fir.ref<i32>
+!CHECK: omp.yield
+!CHECK: omp.terminator
+
+!CHECK-LABEL: @_QPreduction_min_real
+!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xf32>>
+!CHECK: %[[X_REF:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFreduction_min_realEx"}
+!CHECK: omp.parallel
+!CHECK: omp.wsloop reduction(@[[MIN_DECLARE_F]] -> %[[X_REF]] : !fir.ref<f32>) for
+!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]]
+!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref<f32>
+!CHECK: omp.reduction %[[Y_I]], %[[X_REF]] : f32, !fir.ref<f32>
+!CHECK: omp.yield
+!CHECK: omp.terminator
+
+subroutine reduction_min_int(y)
+ integer :: x, y(:)
+ x = 0
+ !$omp parallel
+ !$omp do reduction(min:x)
+ do i=1, 100
+ x = min(x, y(i))
+ end do
+ !$omp end do
+ !$omp end parallel
+ print *, x
+end subroutine
+
+subroutine reduction_min_real(y)
+ real :: x, y(:)
+ x = 0.0
+ !$omp parallel
+ !$omp do reduction(min:x)
+ do i=1, 100
+ x = min(y(i), x)
+ end do
+ !$omp end do
+ !$omp end parallel
+ print *, x
+
+ !$omp parallel
+ !$omp do reduction(min:x)
+ do i=1, 100
+ !CHECK-NOT: omp.reduction
+ if (y(i) .gt. x) x = y(i)
+ end do
+ !$omp end do
+ !$omp end parallel
+ print *, x
+end subroutine
More information about the flang-commits
mailing list