diff --git a/flang/include/flang/Semantics/openmp-directive-sets.h b/flang/include/flang/Semantics/openmp-directive-sets.h --- a/flang/include/flang/Semantics/openmp-directive-sets.h +++ b/flang/include/flang/Semantics/openmp-directive-sets.h @@ -181,6 +181,49 @@ Directive::OMPD_declare_target, }; +static const OmpDirectiveSet loopConstructSet{ + Directive::OMPD_distribute_parallel_do_simd, + Directive::OMPD_distribute_parallel_do, + Directive::OMPD_distribute_simd, + Directive::OMPD_distribute, + Directive::OMPD_do_simd, + Directive::OMPD_do, + Directive::OMPD_parallel_do_simd, + Directive::OMPD_parallel_do, + Directive::OMPD_simd, + Directive::OMPD_target_parallel_do_simd, + Directive::OMPD_target_parallel_do, + Directive::OMPD_target_simd, + Directive::OMPD_target_teams_distribute_parallel_do_simd, + Directive::OMPD_target_teams_distribute_parallel_do, + Directive::OMPD_target_teams_distribute_simd, + Directive::OMPD_target_teams_distribute, + Directive::OMPD_taskloop_simd, + Directive::OMPD_taskloop, + Directive::OMPD_teams_distribute_parallel_do_simd, + Directive::OMPD_teams_distribute_parallel_do, + Directive::OMPD_teams_distribute_simd, + Directive::OMPD_teams_distribute, + Directive::OMPD_tile, + Directive::OMPD_unroll, +}; + +static const OmpDirectiveSet blockConstructSet{ + Directive::OMPD_master, + Directive::OMPD_ordered, + Directive::OMPD_parallel_workshare, + Directive::OMPD_parallel, + Directive::OMPD_single, + Directive::OMPD_target_data, + Directive::OMPD_target_parallel, + Directive::OMPD_target_teams, + Directive::OMPD_target, + Directive::OMPD_task, + Directive::OMPD_taskgroup, + Directive::OMPD_teams, + Directive::OMPD_workshare, +}; + //===----------------------------------------------------------------------===// // Directive sets for allowed/not allowed nested directives //===----------------------------------------------------------------------===// 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 @@ -22,6 +22,7 @@ #include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" #include "flang/Parser/parse-tree.h" +#include "flang/Semantics/openmp-directive-sets.h" #include "flang/Semantics/tools.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" @@ -2315,6 +2316,49 @@ /*isCombined=*/true); } +/* When target is used in a combined construct, then use this function to + * create the target operation. It handles the target specific clauses + * and leaves the rest for handling at the inner operations. + */ +template +static void createCombinedTargetOp(Fortran::lower::AbstractConverter &converter, + Fortran::lower::pft::Evaluation &eval, + const Directive &directive) { + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); + mlir::Location currentLocation = converter.getCurrentLocation(); + Fortran::lower::StatementContext stmtCtx; + mlir::Value ifClauseOperand, deviceOperand, threadLimitOperand; + llvm::SmallVector mapOperands; + llvm::SmallVector mapTypes; + mlir::UnitAttr nowaitAttr; + const auto &opClauseList = + std::get(directive.t); + + // Note: rest of the clauses are handled when the inner operation is created + ClauseProcessor cp(converter, opClauseList); + cp.processIf(stmtCtx, + Fortran::parser::OmpIfClause::DirectiveNameModifier::Target, + ifClauseOperand); + cp.processDevice(stmtCtx, deviceOperand); + cp.processThreadLimit(stmtCtx, threadLimitOperand); + cp.processNowait(nowaitAttr); + cp.processMap(mapOperands, mapTypes); + + llvm::SmallVector mapTypesAttr(mapTypes.begin(), + mapTypes.end()); + mlir::ArrayAttr mapTypesArrayAttr = + mlir::ArrayAttr::get(firOpBuilder.getContext(), mapTypesAttr); + + // Create and insert the operation. + auto targetOp = firOpBuilder.create( + currentLocation, ifClauseOperand, deviceOperand, threadLimitOperand, + nowaitAttr, mapOperands, mapTypesArrayAttr); + + createBodyOfOp(targetOp, converter, currentLocation, + eval, &opClauseList, + /*iv=*/{}, /*isCombined=*/true); +} + static void genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { @@ -2342,13 +2386,41 @@ const auto ompDirective = std::get(beginLoopDirective.t).v; - if (llvm::omp::OMPD_parallel_do == ompDirective) { - createCombinedParallelOp( - converter, eval, - std::get(loopConstruct.t)); - } else if (llvm::omp::OMPD_do != ompDirective && - llvm::omp::OMPD_simd != ompDirective) { - TODO(currentLocation, "Construct enclosing do loop"); + bool validDirective = false; + if (llvm::omp::topTaskloopSet.test(ompDirective)) { + validDirective = true; + TODO(currentLocation, "Taskloop construct"); + } else { + // Create omp.{target, teams, distribute, parallel} nested operations + if ((llvm::omp::allTargetSet & llvm::omp::loopConstructSet) + .test(ompDirective)) { + validDirective = true; + createCombinedTargetOp( + converter, eval, beginLoopDirective); + } + if ((llvm::omp::allTeamsSet & llvm::omp::loopConstructSet) + .test(ompDirective)) { + validDirective = true; + TODO(currentLocation, "Teams construct"); + } + if (llvm::omp::allDistributeSet.test(ompDirective)) { + validDirective = true; + TODO(currentLocation, "Distribute construct"); + } + if ((llvm::omp::allParallelSet & llvm::omp::loopConstructSet) + .test(ompDirective)) { + validDirective = true; + createCombinedParallelOp( + converter, eval, beginLoopDirective); + } + } + if ((llvm::omp::allDoSet | llvm::omp::allSimdSet).test(ompDirective)) + validDirective = true; + + if (!validDirective) { + TODO(currentLocation, "Unhandled loop directive (" + + llvm::omp::getOpenMPDirectiveName(ompDirective) + + ")"); } DataSharingProcessor dsp(converter, loopOpClauseList, eval); @@ -2379,7 +2451,7 @@ // 2.9.3.1 SIMD construct // TODO: Support all the clauses - if (llvm::omp::OMPD_simd == ompDirective) { + if (llvm::omp::allSimdSet.test(ompDirective)) { mlir::TypeRange resultType; auto simdLoopOp = firOpBuilder.create( currentLocation, resultType, lowerBound, upperBound, step, alignedVars, diff --git a/flang/test/Lower/OpenMP/if-clause.f90 b/flang/test/Lower/OpenMP/if-clause.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/OpenMP/if-clause.f90 @@ -0,0 +1,437 @@ +! This test checks lowering of OpenMP IF clauses. + +! RUN: bbc -fopenmp -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -fopenmp -emit-fir %s -o - | FileCheck %s + +program main + integer :: i + + ! TODO When they are supported, add tests for: + ! - DISTRIBUTE PARALLEL DO + ! - DISTRIBUTE PARALLEL DO SIMD + ! - DISTRIBUTE SIMD + ! - PARALLEL SECTIONS + ! - PARALLEL WORKSHARE + ! - TARGET PARALLEL + ! - TARGET TEAMS + ! - TARGET TEAMS DISTRIBUTE + ! - TARGET TEAMS DISTRIBUTE PARALLEL DO + ! - TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD + ! - TARGET TEAMS DISTRIBUTE SIMD + ! - TARGET UPDATE + ! - TASKLOOP + ! - TASKLOOP SIMD + ! - TEAMS + ! - TEAMS DISTRIBUTE + ! - TEAMS DISTRIBUTE PARALLEL DO + ! - TEAMS DISTRIBUTE PARALLEL DO SIMD + ! - TEAMS DISTRIBUTE SIMD + + ! ---------------------------------------------------------------------------- + ! DO SIMD + ! ---------------------------------------------------------------------------- + ! CHECK: omp.simdloop + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp do simd + do i = 1, 10 + end do + !$omp end do simd + + ! CHECK: omp.simdloop + ! CHECK-SAME: if({{.*}}) + !$omp do simd if(.true.) + do i = 1, 10 + end do + !$omp end do simd + + ! CHECK: omp.simdloop + ! CHECK-SAME: if({{.*}}) + !$omp do simd if(simd: .true.) + do i = 1, 10 + end do + !$omp end do simd + + ! ---------------------------------------------------------------------------- + ! PARALLEL + ! ---------------------------------------------------------------------------- + ! CHECK: omp.parallel + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp parallel + i = 10 + !$omp end parallel + + ! CHECK: omp.parallel + ! CHECK-SAME: if({{.*}}) + !$omp parallel if(.true.) + i = 10 + !$omp end parallel + + ! CHECK: omp.parallel + ! CHECK-SAME: if({{.*}}) + !$omp parallel if(parallel: .true.) + i = 10 + !$omp end parallel + + ! ---------------------------------------------------------------------------- + ! PARALLEL DO + ! ---------------------------------------------------------------------------- + ! CHECK: omp.parallel + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp parallel do + do i = 1, 10 + end do + !$omp end parallel do + + ! CHECK: omp.parallel + ! CHECK-SAME: if({{.*}}) + !$omp parallel do if(.true.) + do i = 1, 10 + end do + !$omp end parallel do + + ! CHECK: omp.parallel + ! CHECK-SAME: if({{.*}}) + !$omp parallel do if(parallel: .true.) + do i = 1, 10 + end do + !$omp end parallel do + + ! ---------------------------------------------------------------------------- + ! PARALLEL DO SIMD + ! ---------------------------------------------------------------------------- + ! CHECK: omp.parallel + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + ! CHECK: omp.simdloop + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp parallel do simd + do i = 1, 10 + end do + !$omp end parallel do simd + + ! CHECK: omp.parallel + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.simdloop + ! CHECK-SAME: if({{.*}}) + !$omp parallel do simd if(.true.) + do i = 1, 10 + end do + !$omp end parallel do simd + + ! CHECK: omp.parallel + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.simdloop + ! CHECK-SAME: if({{.*}}) + !$omp parallel do simd if(parallel: .true.) if(simd: .false.) + do i = 1, 10 + end do + !$omp end parallel do simd + + ! CHECK: omp.parallel + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.simdloop + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp parallel do simd if(parallel: .true.) + do i = 1, 10 + end do + !$omp end parallel do simd + + ! CHECK: omp.parallel + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + ! CHECK: omp.simdloop + ! CHECK-SAME: if({{.*}}) + !$omp parallel do simd if(simd: .true.) + do i = 1, 10 + end do + !$omp end parallel do simd + + ! ---------------------------------------------------------------------------- + ! SIMD + ! ---------------------------------------------------------------------------- + ! CHECK: omp.simdloop + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp simd + do i = 1, 10 + end do + !$omp end simd + + ! CHECK: omp.simdloop + ! CHECK-SAME: if({{.*}}) + !$omp simd if(.true.) + do i = 1, 10 + end do + !$omp end simd + + ! CHECK: omp.simdloop + ! CHECK-SAME: if({{.*}}) + !$omp simd if(simd: .true.) + do i = 1, 10 + end do + !$omp end simd + + ! ---------------------------------------------------------------------------- + ! TARGET + ! ---------------------------------------------------------------------------- + ! CHECK: omp.target + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp target + !$omp end target + + ! CHECK: omp.target + ! CHECK-SAME: if({{.*}}) + !$omp target if(.true.) + !$omp end target + + ! CHECK: omp.target + ! CHECK-SAME: if({{.*}}) + !$omp target if(target: .true.) + !$omp end target + + ! ---------------------------------------------------------------------------- + ! TARGET DATA + ! ---------------------------------------------------------------------------- + ! CHECK: omp.target_data + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp target data map(tofrom: i) + !$omp end target data + + ! CHECK: omp.target_data + ! CHECK-SAME: if({{.*}}) + !$omp target data map(tofrom: i) if(.true.) + !$omp end target data + + ! CHECK: omp.target_data + ! CHECK-SAME: if({{.*}}) + !$omp target data map(tofrom: i) if(target data: .true.) + !$omp end target data + + ! ---------------------------------------------------------------------------- + ! TARGET ENTER DATA + ! ---------------------------------------------------------------------------- + ! CHECK: omp.target_enter_data + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: map + !$omp target enter data map(to: i) + + ! CHECK: omp.target_enter_data + ! CHECK-SAME: if({{.*}}) + !$omp target enter data map(to: i) if(.true.) + + ! CHECK: omp.target_enter_data + ! CHECK-SAME: if({{.*}}) + !$omp target enter data map(to: i) if(target enter data: .true.) + + ! ---------------------------------------------------------------------------- + ! TARGET EXIT DATA + ! ---------------------------------------------------------------------------- + ! CHECK: omp.target_exit_data + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: map + !$omp target exit data map(from: i) + + ! CHECK: omp.target_exit_data + ! CHECK-SAME: if({{.*}}) + !$omp target exit data map(from: i) if(.true.) + + ! CHECK: omp.target_exit_data + ! CHECK-SAME: if({{.*}}) + !$omp target exit data map(from: i) if(target exit data: .true.) + + ! ---------------------------------------------------------------------------- + ! TARGET PARALLEL DO + ! ---------------------------------------------------------------------------- + ! CHECK: omp.target + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + ! CHECK: omp.parallel + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp target parallel do + do i = 1, 10 + end do + !$omp end target parallel do + + ! CHECK: omp.target + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.parallel + ! CHECK-SAME: if({{.*}}) + !$omp target parallel do if(.true.) + do i = 1, 10 + end do + !$omp end target parallel do + + ! CHECK: omp.target + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.parallel + ! CHECK-SAME: if({{.*}}) + !$omp target parallel do if(target: .true.) if(parallel: .false.) + do i = 1, 10 + end do + !$omp end target parallel do + + ! CHECK: omp.target + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.parallel + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp target parallel do if(target: .true.) + do i = 1, 10 + end do + !$omp end target parallel do + + + ! CHECK: omp.target + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + ! CHECK: omp.parallel + ! CHECK-SAME: if({{.*}}) + !$omp target parallel do if(parallel: .true.) + do i = 1, 10 + end do + !$omp end target parallel do + + ! ---------------------------------------------------------------------------- + ! TARGET PARALLEL DO SIMD + ! ---------------------------------------------------------------------------- + ! CHECK: omp.target + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + ! CHECK: omp.parallel + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + ! CHECK: omp.simdloop + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp target parallel do simd + do i = 1, 10 + end do + !$omp end target parallel do simd + + ! CHECK: omp.target + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.parallel + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.simdloop + ! CHECK-SAME: if({{.*}}) + !$omp target parallel do simd if(.true.) + do i = 1, 10 + end do + !$omp end target parallel do simd + + ! CHECK: omp.target + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.parallel + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.simdloop + ! CHECK-SAME: if({{.*}}) + !$omp target parallel do simd if(target: .true.) if(parallel: .false.) & + !$omp& if(simd: .true.) + do i = 1, 10 + end do + !$omp end target parallel do simd + + ! CHECK: omp.target + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.parallel + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + ! CHECK: omp.simdloop + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp target parallel do simd if(target: .true.) + do i = 1, 10 + end do + !$omp end target parallel do simd + + ! CHECK: omp.target + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + ! CHECK: omp.parallel + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.simdloop + ! CHECK-SAME: if({{.*}}) + !$omp target parallel do simd if(parallel: .true.) if(simd: .false.) + do i = 1, 10 + end do + !$omp end target parallel do simd + + ! ---------------------------------------------------------------------------- + ! TARGET SIMD + ! ---------------------------------------------------------------------------- + ! CHECK: omp.target + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + ! CHECK: omp.simdloop + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp target simd + do i = 1, 10 + end do + !$omp end target simd + + ! CHECK: omp.target + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.simdloop + ! CHECK-SAME: if({{.*}}) + !$omp target simd if(.true.) + do i = 1, 10 + end do + !$omp end target simd + + ! CHECK: omp.target + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.simdloop + ! CHECK-SAME: if({{.*}}) + !$omp target simd if(target: .true.) if(simd: .false.) + do i = 1, 10 + end do + !$omp end target simd + + ! CHECK: omp.target + ! CHECK-SAME: if({{.*}}) + ! CHECK: omp.simdloop + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp target simd if(target: .true.) + do i = 1, 10 + end do + !$omp end target simd + + ! CHECK: omp.target + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + ! CHECK: omp.simdloop + ! CHECK-SAME: if({{.*}}) + !$omp target simd if(simd: .true.) + do i = 1, 10 + end do + !$omp end target simd + + ! ---------------------------------------------------------------------------- + ! TASK + ! ---------------------------------------------------------------------------- + ! CHECK: omp.task + ! CHECK-NOT: if({{.*}}) + ! CHECK-SAME: { + !$omp task + !$omp end task + + ! CHECK: omp.task + ! CHECK-SAME: if({{.*}}) + !$omp task if(.true.) + !$omp end task + + ! CHECK: omp.task + ! CHECK-SAME: if({{.*}}) + !$omp task if(task: .true.) + !$omp end task +end program main diff --git a/flang/test/Lower/OpenMP/loop-combined.f90 b/flang/test/Lower/OpenMP/loop-combined.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/OpenMP/loop-combined.f90 @@ -0,0 +1,83 @@ +! This test checks lowering of OpenMP combined loop constructs. + +! RUN: bbc -fopenmp -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -fopenmp -emit-fir %s -o - | FileCheck %s + +program main + integer :: i + + ! TODO When DISTRIBUTE, TASKLOOP and TEAMS are supported add: + ! - DISTRIBUTE PARALLEL DO SIMD + ! - DISTRIBUTE PARALLEL DO + ! - DISTRIBUTE SIMD + ! - TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD + ! - TARGET TEAMS DISTRIBUTE PARALLEL DO + ! - TARGET TEAMS DISTRIBUTE SIMD + ! - TARGET TEAMS DISTRIBUTE + ! - TASKLOOP SIMD + ! - TEAMS DISTRIBUTE PARALLEL DO SIMD + ! - TEAMS DISTRIBUTE PARALLEL DO + ! - TEAMS DISTRIBUTE SIMD + ! - TEAMS DISTRIBUTE + + ! ---------------------------------------------------------------------------- + ! DO SIMD + ! ---------------------------------------------------------------------------- + ! CHECK: omp.simdloop + !$omp do simd + do i = 1, 10 + end do + !$omp end do simd + + ! ---------------------------------------------------------------------------- + ! PARALLEL DO SIMD + ! ---------------------------------------------------------------------------- + ! CHECK: omp.parallel + ! CHECK: omp.simdloop + !$omp parallel do simd + do i = 1, 10 + end do + !$omp end parallel do simd + + ! ---------------------------------------------------------------------------- + ! PARALLEL DO + ! ---------------------------------------------------------------------------- + ! CHECK: omp.parallel + ! CHECK: omp.wsloop + !$omp parallel do + do i = 1, 10 + end do + !$omp end parallel do + + ! ---------------------------------------------------------------------------- + ! TARGET PARALLEL DO SIMD + ! ---------------------------------------------------------------------------- + ! CHECK: omp.target + ! CHECK: omp.parallel + ! CHECK: omp.simdloop + !$omp target parallel do simd + do i = 1, 10 + end do + !$omp end target parallel do simd + + ! ---------------------------------------------------------------------------- + ! TARGET PARALLEL DO + ! ---------------------------------------------------------------------------- + ! CHECK: omp.target + ! CHECK: omp.parallel + ! CHECK: omp.wsloop + !$omp target parallel do + do i = 1, 10 + end do + !$omp end target parallel do + + ! ---------------------------------------------------------------------------- + ! TARGET SIMD + ! ---------------------------------------------------------------------------- + ! CHECK: omp.target + ! CHECK: omp.simdloop + !$omp target simd + do i = 1, 10 + end do + !$omp end target simd +end program main diff --git a/flang/test/Lower/OpenMP/target.f90 b/flang/test/Lower/OpenMP/target.f90 --- a/flang/test/Lower/OpenMP/target.f90 +++ b/flang/test/Lower/OpenMP/target.f90 @@ -216,3 +216,41 @@ !$omp end target data !CHECK: } end subroutine omp_target_device_addr + +!=============================================================================== +! Target with parallel loop +!=============================================================================== + +!CHECK-LABEL: func.func @_QPomp_target_parallel_do() { +subroutine omp_target_parallel_do + !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_parallel_doEa"} + integer :: a(1024) + !CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_target_parallel_doEi"} + integer :: i + !CHECK: omp.target map((tofrom -> %[[VAL_0]] : !fir.ref>)) { + !CHECK-NEXT: omp.parallel + !$omp target parallel do map(tofrom: a) + !CHECK: %[[VAL_2:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} + !CHECK: %[[VAL_3:.*]] = arith.constant 1 : i32 + !CHECK: %[[VAL_4:.*]] = arith.constant 1024 : i32 + !CHECK: %[[VAL_5:.*]] = arith.constant 1 : i32 + !CHECK: omp.wsloop for (%[[VAL_6:.*]]) : i32 = (%[[VAL_3]]) to (%[[VAL_4]]) inclusive step (%[[VAL_5]]) { + !CHECK: fir.store %[[VAL_6]] to %[[VAL_2]] : !fir.ref + !CHECK: %[[VAL_7:.*]] = arith.constant 10 : i32 + !CHECK: %[[VAL_8:.*]] = fir.load %2 : !fir.ref + !CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i32) -> i64 + !CHECK: %[[VAL_10:.*]] = arith.constant 1 : i64 + !CHECK: %[[VAL_11:.*]] = arith.subi %[[VAL_9]], %[[VAL_10]] : i64 + !CHECK: %[[VAL_12:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_11]] : (!fir.ref>, i64) -> !fir.ref + !CHECK: fir.store %[[VAL_7]] to %[[VAL_12]] : !fir.ref + do i = 1, 1024 + a(i) = 10 + end do + !CHECK: omp.yield + !CHECK: } + !CHECK: omp.terminator + !CHECK: } + !CHECK: omp.terminator + !CHECK: } + !$omp end target parallel do +end subroutine omp_target_parallel_do