diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp --- a/flang/lib/Lower/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP.cpp @@ -319,7 +319,8 @@ createEmptyRegionBlocks(firOpBuilder, eval.getNestedEvaluations()); // Insert the terminator. - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || + std::is_same_v) { mlir::ValueRange results; firOpBuilder.create(loc, results); } else { @@ -703,7 +704,7 @@ mlir::Value scheduleChunkClauseOperand; mlir::Attribute scheduleClauseOperand, collapseClauseOperand, noWaitClauseOperand, orderedClauseOperand, orderClauseOperand; - const auto &wsLoopOpClauseList = std::get( + const auto &loopOpClauseList = std::get( std::get(loopConstruct.t).t); const auto ompDirective = @@ -714,7 +715,8 @@ createCombinedParallelOp( converter, eval, std::get(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 @@ auto *doConstructEval = &eval.getFirstNestedEvaluation(); std::int64_t collapseValue = - Fortran::lower::getCollapseValue(wsLoopOpClauseList); + Fortran::lower::getCollapseValue(loopOpClauseList); std::size_t loopVarTypeSize = 0; SmallVector iv; do { @@ -755,7 +757,7 @@ &*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(&clause.u)) { if (const auto &chunkExpr = @@ -782,6 +784,17 @@ 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( + currentLocation, resultType, lowerBound, upperBound, step); + createBodyOfOp(SimdLoopOp, converter, currentLocation, + eval, &loopOpClauseList, iv); + return; + } + // FIXME: Add support for following clauses: // 1. linear // 2. order @@ -798,7 +811,7 @@ /*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(&clause.u)) { if (orderedClause->v.has_value()) { @@ -873,7 +886,7 @@ } createBodyOfOp(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 --- 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 @@ // CHECK: } // CHECK: omp.terminator // CHECK: } + +// ----- + +func.func @_QPsimd1(%arg0: !fir.ref {fir.bindc_name = "n"}, %arg1: !fir.ref> {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 + omp.simdloop (%arg2) : i32 = (%c1_i32) to (%2) step (%c1_i32) { + fir.store %arg2 to %1 : !fir.ref + %3 = fir.load %1 : !fir.ref + %4 = fir.convert %3 : (i32) -> i64 + %5 = arith.subi %4, %c1_i64 : i64 + %6 = fir.coordinate_of %arg1, %5 : (!fir.ref>, i64) -> !fir.ref + fir.store %3 to %6 : !fir.ref + omp.yield + } + omp.terminator + } + return +} + +// CHECK-LABEL: _QPsimd1 +// CHECK-SAME: %[[N_REF:.*]]: !llvm.ptr {fir.bindc_name = "n"}, %[[ARR_REF:.*]]: !llvm.ptr {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 +// CHECK: %[[N:.*]] = llvm.load %[[N_REF]] : !llvm.ptr +// CHECK: omp.simdloop +// CHECK-SAME: (%[[I:.*]]) : i32 = (%[[ONE_2]]) to (%[[N]]) step (%[[ONE_2]]) { +// CHECK: llvm.store %[[I]], %[[I_VAR]] : !llvm.ptr +// CHECK: %[[I1:.*]] = llvm.load %[[I_VAR]] : !llvm.ptr +// 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, i64) -> !llvm.ptr +// CHECK: llvm.store %[[I1]], %[[ARR_I_REF]] : !llvm.ptr +// 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 --- /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 + ! CHECK: %[[LD:.*]] = fir.load %[[LOCAL]] : !fir.ref + ! CHECK: fir.call @_FortranAioOutputInteger32({{.*}}, %[[LD]]) : (!fir.ref, i32) -> i1 + print*, i + end do + !$OMP END SIMD +end subroutine