[flang-commits] [flang] 3f4a63e - [Flang][OpenMP] Implementation of lowering of SIMD construct.
Arnamoy Bhattacharyya via flang-commits
flang-commits at lists.llvm.org
Mon Jun 13 06:42:37 PDT 2022
Author: Arnamoy Bhattacharyya
Date: 2022-06-13T09:46:20-04:00
New Revision: 3f4a63e5f882eb062da33a5643499597efefe1ba
URL: https://github.com/llvm/llvm-project/commit/3f4a63e5f882eb062da33a5643499597efefe1ba
DIFF: https://github.com/llvm/llvm-project/commit/3f4a63e5f882eb062da33a5643499597efefe1ba.diff
LOG: [Flang][OpenMP] Implementation of lowering of SIMD construct.
This patch adds code so that using bbc we are able to see an end-to-end lowering of simd construct in action.
Reviewed By: kiranchandramohan, peixin, shraiysh
Differential Revision: https://reviews.llvm.org/D125282
Added:
flang/test/Lower/OpenMP/simd.f90
Modified:
flang/lib/Lower/OpenMP.cpp
flang/test/Fir/convert-to-llvm-openmp-and-fir.fir
Removed:
################################################################################
diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp
index bc624dc47388e..b2dbe2f0d5fb3 100644
--- a/flang/lib/Lower/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP.cpp
@@ -319,7 +319,8 @@ createBodyOfOp(Op &op, Fortran::lower::AbstractConverter &converter,
createEmptyRegionBlocks(firOpBuilder, eval.getNestedEvaluations());
// Insert the terminator.
- if constexpr (std::is_same_v<Op, omp::WsLoopOp>) {
+ if constexpr (std::is_same_v<Op, omp::WsLoopOp> ||
+ std::is_same_v<Op, omp::SimdLoopOp>) {
mlir::ValueRange results;
firOpBuilder.create<mlir::omp::YieldOp>(loc, results);
} else {
@@ -703,7 +704,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
mlir::Value scheduleChunkClauseOperand;
mlir::Attribute scheduleClauseOperand, collapseClauseOperand,
noWaitClauseOperand, orderedClauseOperand, orderClauseOperand;
- const auto &wsLoopOpClauseList = std::get<Fortran::parser::OmpClauseList>(
+ const auto &loopOpClauseList = std::get<Fortran::parser::OmpClauseList>(
std::get<Fortran::parser::OmpBeginLoopDirective>(loopConstruct.t).t);
const auto ompDirective =
@@ -714,7 +715,8 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
createCombinedParallelOp<Fortran::parser::OmpBeginLoopDirective>(
converter, eval,
std::get<Fortran::parser::OmpBeginLoopDirective>(loopConstruct.t));
- } else if (llvm::omp::OMPD_do != ompDirective) {
+ } else if (llvm::omp::OMPD_do != ompDirective &&
+ llvm::omp::OMPD_simd != ompDirective) {
TODO(converter.getCurrentLocation(), "Construct enclosing do loop");
}
@@ -722,7 +724,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
auto *doConstructEval = &eval.getFirstNestedEvaluation();
std::int64_t collapseValue =
- Fortran::lower::getCollapseValue(wsLoopOpClauseList);
+ Fortran::lower::getCollapseValue(loopOpClauseList);
std::size_t loopVarTypeSize = 0;
SmallVector<const Fortran::semantics::Symbol *> iv;
do {
@@ -755,7 +757,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
&*std::next(doConstructEval->getNestedEvaluations().begin());
} while (collapseValue > 0);
- for (const auto &clause : wsLoopOpClauseList.v) {
+ for (const auto &clause : loopOpClauseList.v) {
if (const auto &scheduleClause =
std::get_if<Fortran::parser::OmpClause::Schedule>(&clause.u)) {
if (const auto &chunkExpr =
@@ -782,6 +784,17 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
firOpBuilder.createConvert(currentLocation, loopVarType, step[it]);
}
+ // 2.9.3.1 SIMD construct
+ // TODO: Support all the clauses
+ if (llvm::omp::OMPD_simd == ompDirective) {
+ TypeRange resultType;
+ auto SimdLoopOp = firOpBuilder.create<mlir::omp::SimdLoopOp>(
+ currentLocation, resultType, lowerBound, upperBound, step);
+ createBodyOfOp<omp::SimdLoopOp>(SimdLoopOp, converter, currentLocation,
+ eval, &loopOpClauseList, iv);
+ return;
+ }
+
// FIXME: Add support for following clauses:
// 1. linear
// 2. order
@@ -798,7 +811,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
/*inclusive=*/firOpBuilder.getUnitAttr());
// Handle attribute based clauses.
- for (const Fortran::parser::OmpClause &clause : wsLoopOpClauseList.v) {
+ for (const Fortran::parser::OmpClause &clause : loopOpClauseList.v) {
if (const auto &orderedClause =
std::get_if<Fortran::parser::OmpClause::Ordered>(&clause.u)) {
if (orderedClause->v.has_value()) {
@@ -873,7 +886,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
}
createBodyOfOp<omp::WsLoopOp>(wsLoopOp, converter, currentLocation, eval,
- &wsLoopOpClauseList, iv);
+ &loopOpClauseList, iv);
}
static void
diff --git a/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir b/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir
index b6da69a20a5e5..32e7bfceab959 100644
--- a/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir
+++ b/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir
@@ -171,3 +171,49 @@ func.func @sections_data_without_clauses(%arg0: !fir.ref<i32> {fir.bindc_name =
// CHECK: }
// CHECK: omp.terminator
// CHECK: }
+
+// -----
+
+func.func @_QPsimd1(%arg0: !fir.ref<i32> {fir.bindc_name = "n"}, %arg1: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "arr"}) {
+ %c1_i64 = arith.constant 1 : i64
+ %c1_i32 = arith.constant 1 : i32
+ %0 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsbEi"}
+ omp.parallel {
+ %1 = fir.alloca i32 {adapt.valuebyref, pinned}
+ %2 = fir.load %arg0 : !fir.ref<i32>
+ omp.simdloop (%arg2) : i32 = (%c1_i32) to (%2) step (%c1_i32) {
+ fir.store %arg2 to %1 : !fir.ref<i32>
+ %3 = fir.load %1 : !fir.ref<i32>
+ %4 = fir.convert %3 : (i32) -> i64
+ %5 = arith.subi %4, %c1_i64 : i64
+ %6 = fir.coordinate_of %arg1, %5 : (!fir.ref<!fir.array<?xi32>>, i64) -> !fir.ref<i32>
+ fir.store %3 to %6 : !fir.ref<i32>
+ omp.yield
+ }
+ omp.terminator
+ }
+ return
+}
+
+// CHECK-LABEL: _QPsimd1
+// CHECK-SAME: %[[N_REF:.*]]: !llvm.ptr<i32> {fir.bindc_name = "n"}, %[[ARR_REF:.*]]: !llvm.ptr<i32> {fir.bindc_name = "arr"}) {
+// CHECK: %[[ONE_1:.*]] = llvm.mlir.constant(1 : i64) : i64
+// CHECK: %[[ONE_2:.*]] = llvm.mlir.constant(1 : i32) : i32
+// CHECK: omp.parallel {
+// CHECK: %[[ONE_3:.*]] = llvm.mlir.constant(1 : i64) : i64
+// CHECK: %[[I_VAR:.*]] = llvm.alloca %[[ONE_3]] x i32 {adapt.valuebyref, in_type = i32, operand_segment_sizes = dense<0> : vector<2xi32>, pinned} : (i64) -> !llvm.ptr<i32>
+// CHECK: %[[N:.*]] = llvm.load %[[N_REF]] : !llvm.ptr<i32>
+// CHECK: omp.simdloop
+// CHECK-SAME: (%[[I:.*]]) : i32 = (%[[ONE_2]]) to (%[[N]]) step (%[[ONE_2]]) {
+// CHECK: llvm.store %[[I]], %[[I_VAR]] : !llvm.ptr<i32>
+// CHECK: %[[I1:.*]] = llvm.load %[[I_VAR]] : !llvm.ptr<i32>
+// CHECK: %[[I1_EXT:.*]] = llvm.sext %[[I1]] : i32 to i64
+// CHECK: %[[I_CSTYLE:.*]] = llvm.sub %[[I1_EXT]], %[[ONE_1]] : i64
+// CHECK: %[[ARR_I_REF:.*]] = llvm.getelementptr %[[ARR_REF]][%[[I_CSTYLE]]] : (!llvm.ptr<i32>, i64) -> !llvm.ptr<i32>
+// CHECK: llvm.store %[[I1]], %[[ARR_I_REF]] : !llvm.ptr<i32>
+// CHECK: omp.yield
+// CHECK: }
+// CHECK: omp.terminator
+// CHECK: }
+// CHECK: llvm.return
+// CHECK: }
diff --git a/flang/test/Lower/OpenMP/simd.f90 b/flang/test/Lower/OpenMP/simd.f90
new file mode 100644
index 0000000000000..1d08fb7069c90
--- /dev/null
+++ b/flang/test/Lower/OpenMP/simd.f90
@@ -0,0 +1,20 @@
+! Tests for 2.9.3.1 Simd
+
+! RUN: bbc -fopenmp -emit-fir %s -o - | FileCheck %s
+
+!CHECK-LABEL: func @_QPsimdloop()
+subroutine simdloop
+integer :: i
+ !$OMP SIMD
+ ! CHECK: %[[LB:.*]] = arith.constant 1 : i32
+ ! CHECK-NEXT: %[[UB:.*]] = arith.constant 9 : i32
+ ! CHECK-NEXT: %[[STEP:.*]] = arith.constant 1 : i32
+ ! CHECK-NEXT: omp.simdloop (%[[I:.*]]) : i32 = (%[[LB]]) to (%[[UB]]) step (%[[STEP]]) {
+ do i=1, 9
+ ! CHECK: fir.store %[[I]] to %[[LOCAL:.*]] : !fir.ref<i32>
+ ! CHECK: %[[LD:.*]] = fir.load %[[LOCAL]] : !fir.ref<i32>
+ ! CHECK: fir.call @_FortranAioOutputInteger32({{.*}}, %[[LD]]) : (!fir.ref<i8>, i32) -> i1
+ print*, i
+ end do
+ !$OMP END SIMD
+end subroutine
More information about the flang-commits
mailing list