Skip to content

Commit 740c0b3

Browse files
committed
{Flang][OpenMP] Add support for ior, ieor, and iand reduction in worksharing-loop
Adds support for .ior., .ieor., and .iand. reductions. Reviewed By: kiranchandramohan Differential Revision: https://reviews.llvm.org/D148994
1 parent 5202aa1 commit 740c0b3

File tree

7 files changed

+145
-56
lines changed

7 files changed

+145
-56
lines changed

flang/lib/Lower/OpenMP.cpp

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,18 @@ static Value getReductionInitValue(mlir::Location loc, mlir::Type type,
11811181
unsigned bits = type.getIntOrFloatBitWidth();
11821182
int64_t maxInt = llvm::APInt::getSignedMaxValue(bits).getSExtValue();
11831183
return builder.createIntegerConstant(loc, type, maxInt);
1184+
} else if (reductionOpName.contains("ior")) {
1185+
unsigned bits = type.getIntOrFloatBitWidth();
1186+
int64_t zeroInt = llvm::APInt::getZero(bits).getSExtValue();
1187+
return builder.createIntegerConstant(loc, type, zeroInt);
1188+
} else if (reductionOpName.contains("ieor")) {
1189+
unsigned bits = type.getIntOrFloatBitWidth();
1190+
int64_t zeroInt = llvm::APInt::getZero(bits).getSExtValue();
1191+
return builder.createIntegerConstant(loc, type, zeroInt);
1192+
} else if (reductionOpName.contains("iand")) {
1193+
unsigned bits = type.getIntOrFloatBitWidth();
1194+
int64_t allOnInt = llvm::APInt::getAllOnes(bits).getSExtValue();
1195+
return builder.createIntegerConstant(loc, type, allOnInt);
11841196
} else {
11851197
if (type.isa<FloatType>())
11861198
return builder.create<mlir::arith::ConstantOp>(
@@ -1268,6 +1280,15 @@ createReductionDecl(fir::FirOpBuilder &builder, llvm::StringRef reductionOpName,
12681280
reductionOp =
12691281
getReductionOperation<mlir::arith::MinFOp, mlir::arith::MinSIOp>(
12701282
builder, type, loc, op1, op2);
1283+
} else if (name->source == "ior") {
1284+
assert((type.isIntOrIndex()) && "only integer is expected");
1285+
reductionOp = builder.create<mlir::arith::OrIOp>(loc, op1, op2);
1286+
} else if (name->source == "ieor") {
1287+
assert((type.isIntOrIndex()) && "only integer is expected");
1288+
reductionOp = builder.create<mlir::arith::XOrIOp>(loc, op1, op2);
1289+
} else if (name->source == "iand") {
1290+
assert((type.isIntOrIndex()) && "only integer is expected");
1291+
reductionOp = builder.create<mlir::arith::AndIOp>(loc, op1, op2);
12711292
} else {
12721293
TODO(loc, "Reduction of some intrinsic operators is not supported");
12731294
}
@@ -1594,7 +1615,9 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
15941615
&redOperator.u)) {
15951616
if (const auto *name{Fortran::parser::Unwrap<Fortran::parser::Name>(
15961617
reductionIntrinsic)}) {
1597-
if ((name->source != "max") && (name->source != "min")) {
1618+
if ((name->source != "max") && (name->source != "min") &&
1619+
(name->source != "ior") && (name->source != "ieor") &&
1620+
(name->source != "iand")) {
15981621
TODO(currentLocation,
15991622
"Reduction of intrinsic procedures is not supported");
16001623
}
@@ -2364,7 +2387,10 @@ void Fortran::lower::genOpenMPReduction(
23642387
&redOperator.u)) {
23652388
if (const auto *name{Fortran::parser::Unwrap<Fortran::parser::Name>(
23662389
reductionIntrinsic)}) {
2367-
if ((name->source != "max") && (name->source != "min")) {
2390+
std::string redName = name->ToString();
2391+
if ((name->source != "max") && (name->source != "min") &&
2392+
(name->source != "ior") && (name->source != "ieor") &&
2393+
(name->source != "iand")) {
23682394
continue;
23692395
}
23702396
for (const auto &ompObject : objectList.v) {
@@ -2383,12 +2409,21 @@ void Fortran::lower::genOpenMPReduction(
23832409
findReductionChain(loadVal, &reductionVal);
23842410
if (reductionOp == nullptr)
23852411
continue;
2386-
assert(mlir::isa<mlir::arith::SelectOp>(reductionOp) &&
2387-
"Selection Op not found in reduction intrinsic");
2388-
mlir::Operation *compareOp =
2389-
getCompareFromReductionOp(reductionOp, loadVal);
2390-
updateReduction(compareOp, firOpBuilder, loadVal,
2391-
reductionVal);
2412+
2413+
if (redName == "max" || redName == "min") {
2414+
assert(mlir::isa<mlir::arith::SelectOp>(reductionOp) &&
2415+
"Selection Op not found in reduction intrinsic");
2416+
mlir::Operation *compareOp =
2417+
getCompareFromReductionOp(reductionOp, loadVal);
2418+
updateReduction(compareOp, firOpBuilder, loadVal,
2419+
reductionVal);
2420+
}
2421+
if (redName == "ior" || redName == "ieor" ||
2422+
redName == "iand") {
2423+
2424+
updateReduction(reductionOp, firOpBuilder, loadVal,
2425+
reductionVal);
2426+
}
23922427
}
23932428
}
23942429
}

flang/test/Lower/OpenMP/Todo/reduction-iand.f90

Lines changed: 0 additions & 16 deletions
This file was deleted.

flang/test/Lower/OpenMP/Todo/reduction-ieor.f90

Lines changed: 0 additions & 16 deletions
This file was deleted.

flang/test/Lower/OpenMP/Todo/reduction-ior.f90

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
! RUN: bbc -emit-fir -fopenmp %s -o - | FileCheck %s
2+
! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s
3+
4+
!CHECK: omp.reduction.declare @[[IAND_DECLARE_I:.*]] : i32 init {
5+
!CHECK: %[[ZERO_VAL_I:.*]] = arith.constant -1 : i32
6+
!CHECK: omp.yield(%[[ZERO_VAL_I]] : i32)
7+
!CHECK: combiner
8+
!CHECK: ^bb0(%[[ARG0_I:.*]]: i32, %[[ARG1_I:.*]]: i32):
9+
!CHECK: %[[IAND_VAL_I:.*]] = arith.andi %[[ARG0_I]], %[[ARG1_I]] : i32
10+
!CHECK: omp.yield(%[[IAND_VAL_I]] : i32)
11+
12+
!CHECK-LABEL: @_QPreduction_iand
13+
!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xi32>>
14+
!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iandEx"}
15+
!CHECK: omp.parallel
16+
!CHECK: omp.wsloop reduction(@[[IAND_DECLARE_I]] -> %[[X_REF]] : !fir.ref<i32>) for
17+
!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]]
18+
!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref<i32>
19+
!CHECK: omp.reduction %[[Y_I]], %[[X_REF]] : i32, !fir.ref<i32>
20+
!CHECK: omp.yield
21+
!CHECK: omp.terminator
22+
23+
subroutine reduction_iand(y)
24+
integer :: x, y(:)
25+
x = 0
26+
!$omp parallel
27+
!$omp do reduction(iand:x)
28+
do i=1, 100
29+
x = iand(x, y(i))
30+
end do
31+
!$omp end do
32+
!$omp end parallel
33+
print *, x
34+
end subroutine
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
! RUN: bbc -emit-fir -fopenmp %s -o - | FileCheck %s
2+
! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s
3+
4+
!CHECK: omp.reduction.declare @[[IEOR_DECLARE_I:.*]] : i32 init {
5+
!CHECK: %[[ZERO_VAL_I:.*]] = arith.constant 0 : i32
6+
!CHECK: omp.yield(%[[ZERO_VAL_I]] : i32)
7+
!CHECK: combiner
8+
!CHECK: ^bb0(%[[ARG0_I:.*]]: i32, %[[ARG1_I:.*]]: i32):
9+
!CHECK: %[[IEOR_VAL_I:.*]] = arith.xori %[[ARG0_I]], %[[ARG1_I]] : i32
10+
!CHECK: omp.yield(%[[IEOR_VAL_I]] : i32)
11+
12+
!CHECK-LABEL: @_QPreduction_ieor
13+
!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xi32>>
14+
!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_ieorEx"}
15+
!CHECK: omp.parallel
16+
!CHECK: omp.wsloop reduction(@[[IEOR_DECLARE_I]] -> %[[X_REF]] : !fir.ref<i32>) for
17+
!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]]
18+
!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref<i32>
19+
!CHECK: omp.reduction %[[Y_I]], %[[X_REF]] : i32, !fir.ref<i32>
20+
!CHECK: omp.yield
21+
!CHECK: omp.terminator
22+
23+
subroutine reduction_ieor(y)
24+
integer :: x, y(:)
25+
x = 0
26+
!$omp parallel
27+
!$omp do reduction(ieor:x)
28+
do i=1, 100
29+
x = ieor(x, y(i))
30+
end do
31+
!$omp end do
32+
!$omp end parallel
33+
print *, x
34+
end subroutine
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
! RUN: bbc -emit-fir -fopenmp %s -o - | FileCheck %s
2+
! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s
3+
4+
!CHECK: omp.reduction.declare @[[IOR_DECLARE_I:.*]] : i32 init {
5+
!CHECK: %[[ZERO_VAL_I:.*]] = arith.constant 0 : i32
6+
!CHECK: omp.yield(%[[ZERO_VAL_I]] : i32)
7+
!CHECK: combiner
8+
!CHECK: ^bb0(%[[ARG0_I:.*]]: i32, %[[ARG1_I:.*]]: i32):
9+
!CHECK: %[[IOR_VAL_I:.*]] = arith.ori %[[ARG0_I]], %[[ARG1_I]] : i32
10+
!CHECK: omp.yield(%[[IOR_VAL_I]] : i32)
11+
12+
!CHECK-LABEL: @_QPreduction_ior
13+
!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xi32>>
14+
!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iorEx"}
15+
!CHECK: omp.parallel
16+
!CHECK: omp.wsloop reduction(@[[IOR_DECLARE_I]] -> %[[X_REF]] : !fir.ref<i32>) for
17+
!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]]
18+
!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref<i32>
19+
!CHECK: omp.reduction %[[Y_I]], %[[X_REF]] : i32, !fir.ref<i32>
20+
!CHECK: omp.yield
21+
!CHECK: omp.terminator
22+
23+
subroutine reduction_ior(y)
24+
integer :: x, y(:)
25+
x = 0
26+
!$omp parallel
27+
!$omp do reduction(ior:x)
28+
do i=1, 100
29+
x = ior(x, y(i))
30+
end do
31+
!$omp end do
32+
!$omp end parallel
33+
print *, x
34+
end subroutine

0 commit comments

Comments
 (0)