[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