diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp index 8c201e0d30a2b..9ba610347c091 100644 --- a/flang/lib/Lower/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP.cpp @@ -1181,6 +1181,18 @@ static Value getReductionInitValue(mlir::Location loc, mlir::Type type, unsigned bits = type.getIntOrFloatBitWidth(); int64_t maxInt = llvm::APInt::getSignedMaxValue(bits).getSExtValue(); return builder.createIntegerConstant(loc, type, maxInt); + } else if (reductionOpName.contains("ior")) { + unsigned bits = type.getIntOrFloatBitWidth(); + int64_t zeroInt = llvm::APInt::getZero(bits).getSExtValue(); + return builder.createIntegerConstant(loc, type, zeroInt); + } else if (reductionOpName.contains("ieor")) { + unsigned bits = type.getIntOrFloatBitWidth(); + int64_t zeroInt = llvm::APInt::getZero(bits).getSExtValue(); + return builder.createIntegerConstant(loc, type, zeroInt); + } else if (reductionOpName.contains("iand")) { + unsigned bits = type.getIntOrFloatBitWidth(); + int64_t allOnInt = llvm::APInt::getAllOnes(bits).getSExtValue(); + return builder.createIntegerConstant(loc, type, allOnInt); } else { if (type.isa()) return builder.create( @@ -1268,6 +1280,15 @@ createReductionDecl(fir::FirOpBuilder &builder, llvm::StringRef reductionOpName, reductionOp = getReductionOperation( builder, type, loc, op1, op2); + } else if (name->source == "ior") { + assert((type.isIntOrIndex()) && "only integer is expected"); + reductionOp = builder.create(loc, op1, op2); + } else if (name->source == "ieor") { + assert((type.isIntOrIndex()) && "only integer is expected"); + reductionOp = builder.create(loc, op1, op2); + } else if (name->source == "iand") { + assert((type.isIntOrIndex()) && "only integer is expected"); + reductionOp = builder.create(loc, op1, op2); } else { TODO(loc, "Reduction of some intrinsic operators is not supported"); } @@ -1594,7 +1615,9 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, &redOperator.u)) { if (const auto *name{Fortran::parser::Unwrap( reductionIntrinsic)}) { - if ((name->source != "max") && (name->source != "min")) { + if ((name->source != "max") && (name->source != "min") && + (name->source != "ior") && (name->source != "ieor") && + (name->source != "iand")) { TODO(currentLocation, "Reduction of intrinsic procedures is not supported"); } @@ -2364,7 +2387,10 @@ void Fortran::lower::genOpenMPReduction( &redOperator.u)) { if (const auto *name{Fortran::parser::Unwrap( reductionIntrinsic)}) { - if ((name->source != "max") && (name->source != "min")) { + std::string redName = name->ToString(); + if ((name->source != "max") && (name->source != "min") && + (name->source != "ior") && (name->source != "ieor") && + (name->source != "iand")) { continue; } for (const auto &ompObject : objectList.v) { @@ -2383,12 +2409,21 @@ void Fortran::lower::genOpenMPReduction( findReductionChain(loadVal, &reductionVal); if (reductionOp == nullptr) continue; - assert(mlir::isa(reductionOp) && - "Selection Op not found in reduction intrinsic"); - mlir::Operation *compareOp = - getCompareFromReductionOp(reductionOp, loadVal); - updateReduction(compareOp, firOpBuilder, loadVal, - reductionVal); + + if (redName == "max" || redName == "min") { + assert(mlir::isa(reductionOp) && + "Selection Op not found in reduction intrinsic"); + mlir::Operation *compareOp = + getCompareFromReductionOp(reductionOp, loadVal); + updateReduction(compareOp, firOpBuilder, loadVal, + reductionVal); + } + if (redName == "ior" || redName == "ieor" || + redName == "iand") { + + updateReduction(reductionOp, firOpBuilder, loadVal, + reductionVal); + } } } } diff --git a/flang/test/Lower/OpenMP/Todo/reduction-iand.f90 b/flang/test/Lower/OpenMP/Todo/reduction-iand.f90 deleted file mode 100644 index f1b9b025d2a16..0000000000000 --- a/flang/test/Lower/OpenMP/Todo/reduction-iand.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_iand(y) - integer :: x, y(:) - x = 0 - !$omp parallel - !$omp do reduction(iand:x) - do i=1, 100 - x = iand(x, y(i)) - end do - !$omp end do - !$omp end parallel - print *, x -end subroutine diff --git a/flang/test/Lower/OpenMP/Todo/reduction-ieor.f90 b/flang/test/Lower/OpenMP/Todo/reduction-ieor.f90 deleted file mode 100644 index 2303a8edfaa94..0000000000000 --- a/flang/test/Lower/OpenMP/Todo/reduction-ieor.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_ieor(y) - integer :: x, y(:) - x = 0 - !$omp parallel - !$omp do reduction(ieor:x) - do i=1, 100 - x = ieor(x, y(i)) - end do - !$omp end do - !$omp end parallel - print *, x -end subroutine diff --git a/flang/test/Lower/OpenMP/Todo/reduction-ior.f90 b/flang/test/Lower/OpenMP/Todo/reduction-ior.f90 deleted file mode 100644 index 3460df2b9d6d2..0000000000000 --- a/flang/test/Lower/OpenMP/Todo/reduction-ior.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_ior(y) - integer :: x, y(:) - x = 0 - !$omp parallel - !$omp do reduction(ior:x) - do i=1, 100 - x = ior(x, y(i)) - end do - !$omp end do - !$omp end parallel - print *, x -end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-iand.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-iand.f90 new file mode 100644 index 0000000000000..c18971e14ff38 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-iand.f90 @@ -0,0 +1,34 @@ +! RUN: bbc -emit-fir -fopenmp %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s + +!CHECK: omp.reduction.declare @[[IAND_DECLARE_I:.*]] : i32 init { +!CHECK: %[[ZERO_VAL_I:.*]] = arith.constant -1 : i32 +!CHECK: omp.yield(%[[ZERO_VAL_I]] : i32) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0_I:.*]]: i32, %[[ARG1_I:.*]]: i32): +!CHECK: %[[IAND_VAL_I:.*]] = arith.andi %[[ARG0_I]], %[[ARG1_I]] : i32 +!CHECK: omp.yield(%[[IAND_VAL_I]] : i32) + +!CHECK-LABEL: @_QPreduction_iand +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iandEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop reduction(@[[IAND_DECLARE_I]] -> %[[X_REF]] : !fir.ref) for +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref +!CHECK: omp.reduction %[[Y_I]], %[[X_REF]] : i32, !fir.ref +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_iand(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(iand:x) + do i=1, 100 + x = iand(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ieor.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ieor.f90 new file mode 100644 index 0000000000000..93d1539bc63a9 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ieor.f90 @@ -0,0 +1,34 @@ +! RUN: bbc -emit-fir -fopenmp %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s + +!CHECK: omp.reduction.declare @[[IEOR_DECLARE_I:.*]] : i32 init { +!CHECK: %[[ZERO_VAL_I:.*]] = arith.constant 0 : i32 +!CHECK: omp.yield(%[[ZERO_VAL_I]] : i32) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0_I:.*]]: i32, %[[ARG1_I:.*]]: i32): +!CHECK: %[[IEOR_VAL_I:.*]] = arith.xori %[[ARG0_I]], %[[ARG1_I]] : i32 +!CHECK: omp.yield(%[[IEOR_VAL_I]] : i32) + +!CHECK-LABEL: @_QPreduction_ieor +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_ieorEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop reduction(@[[IEOR_DECLARE_I]] -> %[[X_REF]] : !fir.ref) for +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref +!CHECK: omp.reduction %[[Y_I]], %[[X_REF]] : i32, !fir.ref +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_ieor(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(ieor:x) + do i=1, 100 + x = ieor(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ior.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ior.f90 new file mode 100644 index 0000000000000..87e77c265fe1a --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ior.f90 @@ -0,0 +1,34 @@ +! RUN: bbc -emit-fir -fopenmp %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s + +!CHECK: omp.reduction.declare @[[IOR_DECLARE_I:.*]] : i32 init { +!CHECK: %[[ZERO_VAL_I:.*]] = arith.constant 0 : i32 +!CHECK: omp.yield(%[[ZERO_VAL_I]] : i32) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0_I:.*]]: i32, %[[ARG1_I:.*]]: i32): +!CHECK: %[[IOR_VAL_I:.*]] = arith.ori %[[ARG0_I]], %[[ARG1_I]] : i32 +!CHECK: omp.yield(%[[IOR_VAL_I]] : i32) + +!CHECK-LABEL: @_QPreduction_ior +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iorEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop reduction(@[[IOR_DECLARE_I]] -> %[[X_REF]] : !fir.ref) for +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref +!CHECK: omp.reduction %[[Y_I]], %[[X_REF]] : i32, !fir.ref +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_ior(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(ior:x) + do i=1, 100 + x = ior(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine