diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 5ee7ecc61a4e2..e70f5aeae117e 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3462,8 +3462,8 @@ struct OmpDeviceTypeClause { // 2.12 if-clause -> IF ([ directive-name-modifier :] scalar-logical-expr) struct OmpIfClause { TUPLE_CLASS_BOILERPLATE(OmpIfClause); - ENUM_CLASS(DirectiveNameModifier, Parallel, Target, TargetEnterData, - TargetExitData, TargetData, TargetUpdate, Taskloop, Task) + ENUM_CLASS(DirectiveNameModifier, Parallel, Simd, Target, TargetData, + TargetEnterData, TargetExitData, TargetUpdate, Task, Taskloop, Teams) std::tuple, ScalarLogicalExpr> t; }; diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp index 8dba0dbba10ca..2a04f3bb5be56 100644 --- a/flang/lib/Lower/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP.cpp @@ -518,8 +518,10 @@ class ClauseProcessor { bool processCopyin() const; bool processDepend(llvm::SmallVectorImpl &dependTypeOperands, llvm::SmallVectorImpl &dependOperands) const; - bool processIf(Fortran::lower::StatementContext &stmtCtx, - mlir::Value &result) const; + bool + processIf(Fortran::lower::StatementContext &stmtCtx, + Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName, + mlir::Value &result) const; bool processLink(llvm::SmallVectorImpl &result) const; bool processMap(llvm::SmallVectorImpl &mapOperands, @@ -1049,11 +1051,19 @@ genDependKindAttr(fir::FirOpBuilder &firOpBuilder, pbKind); } -static mlir::Value -getIfClauseOperand(Fortran::lower::AbstractConverter &converter, - Fortran::lower::StatementContext &stmtCtx, - const Fortran::parser::OmpClause::If *ifClause, - mlir::Location clauseLocation) { +static mlir::Value getIfClauseOperand( + Fortran::lower::AbstractConverter &converter, + Fortran::lower::StatementContext &stmtCtx, + const Fortran::parser::OmpClause::If *ifClause, + Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName, + mlir::Location clauseLocation) { + // Only consider the clause if it's intended for the given directive. + auto &directive = std::get< + std::optional>( + ifClause->v.t); + if (directive && directive.value() != directiveName) + return nullptr; + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); auto &expr = std::get(ifClause->v.t); mlir::Value ifVal = fir::getBase( @@ -1572,17 +1582,25 @@ bool ClauseProcessor::processDepend( }); } -bool ClauseProcessor::processIf(Fortran::lower::StatementContext &stmtCtx, - mlir::Value &result) const { - return findRepeatableClause( +bool ClauseProcessor::processIf( + Fortran::lower::StatementContext &stmtCtx, + Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName, + mlir::Value &result) const { + bool found = false; + findRepeatableClause( [&](const ClauseTy::If *ifClause, const Fortran::parser::CharBlock &source) { mlir::Location clauseLocation = converter.genLocation(source); - // TODO Consider DirectiveNameModifier of the `ifClause` to only search - // for an applicable 'if' clause. - result = - getIfClauseOperand(converter, stmtCtx, ifClause, clauseLocation); + mlir::Value operand = getIfClauseOperand(converter, stmtCtx, ifClause, + directiveName, clauseLocation); + // Assume that, at most, a single 'if' clause will be applicable to the + // given directive. + if (operand) { + result = operand; + found = true; + } }); + return found; } bool ClauseProcessor::processLink( @@ -2109,8 +2127,30 @@ static void createTargetOp(Fortran::lower::AbstractConverter &converter, llvm::SmallVector useDeviceLocs; llvm::SmallVector useDeviceSymbols; + Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName; + switch (directive) { + case llvm::omp::Directive::OMPD_target: + directiveName = Fortran::parser::OmpIfClause::DirectiveNameModifier::Target; + break; + case llvm::omp::Directive::OMPD_target_data: + directiveName = + Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetData; + break; + case llvm::omp::Directive::OMPD_target_enter_data: + directiveName = + Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetEnterData; + break; + case llvm::omp::Directive::OMPD_target_exit_data: + directiveName = + Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetExitData; + break; + default: + TODO(currentLocation, "OMPD_target directive unknown"); + break; + } + ClauseProcessor cp(converter, opClauseList); - cp.processIf(stmtCtx, ifClauseOperand); + cp.processIf(stmtCtx, directiveName, ifClauseOperand); cp.processDevice(stmtCtx, deviceOperand); cp.processThreadLimit(stmtCtx, threadLmtOperand); cp.processNowait(nowaitAttr); @@ -2157,8 +2197,6 @@ static void createTargetOp(Fortran::lower::AbstractConverter &converter, firOpBuilder.create(currentLocation, ifClauseOperand, deviceOperand, nowaitAttr, mapOperands, mapTypesArrayAttr); - } else { - TODO(currentLocation, "OMPD_target directive unknown"); } } @@ -2256,7 +2294,9 @@ createCombinedParallelOp(Fortran::lower::AbstractConverter &converter, // 1. default // Note: rest of the clauses are handled when the inner operation is created ClauseProcessor cp(converter, opClauseList); - cp.processIf(stmtCtx, ifClauseOperand); + cp.processIf(stmtCtx, + Fortran::parser::OmpIfClause::DirectiveNameModifier::Parallel, + ifClauseOperand); cp.processNumThreads(stmtCtx, numThreadsClauseOperand); cp.processProcBind(procBindKindAttr); @@ -2315,7 +2355,9 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, cp.processCollapse(currentLocation, eval, lowerBound, upperBound, step, iv, loopVarTypeSize); cp.processScheduleChunk(stmtCtx, scheduleChunkClauseOperand); - cp.processIf(stmtCtx, ifClauseOperand); + cp.processIf(stmtCtx, + Fortran::parser::OmpIfClause::DirectiveNameModifier::Simd, + ifClauseOperand); cp.processReduction(currentLocation, reductionVars, reductionDeclSymbols); cp.processSimdlen(simdlenClauseOperand); cp.processSafelen(safelenClauseOperand); @@ -2416,10 +2458,38 @@ genOMP(Fortran::lower::AbstractConverter &converter, llvm::SmallVector dependTypeOperands, reductionDeclSymbols; mlir::UnitAttr nowaitAttr, untiedAttr, mergeableAttr; + // Use placeholder value to avoid uninitialized `directiveName` compiler + // errors. The 'if clause' obtained won't be used for these directives. + Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName = + Fortran::parser::OmpIfClause::DirectiveNameModifier::Parallel; + switch (blockDirective.v) { + case llvm::omp::OMPD_parallel: + directiveName = + Fortran::parser::OmpIfClause::DirectiveNameModifier::Parallel; + break; + case llvm::omp::OMPD_task: + directiveName = Fortran::parser::OmpIfClause::DirectiveNameModifier::Task; + break; + // Target-related 'if' clauses handled by createTargetOp(). + case llvm::omp::OMPD_target: + case llvm::omp::OMPD_target_data: + // These block directives do not accept an 'if' clause. + case llvm::omp::OMPD_master: + case llvm::omp::OMPD_single: + case llvm::omp::OMPD_ordered: + case llvm::omp::OMPD_taskgroup: + break; + default: + TODO(currentLocation, + "Unhandled block directive (" + + llvm::omp::getOpenMPDirectiveName(blockDirective.v) + ")"); + break; + } + const auto &opClauseList = std::get(beginBlockDirective.t); ClauseProcessor cp(converter, opClauseList); - cp.processIf(stmtCtx, ifClauseOperand); + cp.processIf(stmtCtx, directiveName, ifClauseOperand); cp.processNumThreads(stmtCtx, numThreadsClauseOperand); cp.processProcBind(procBindKindAttr); cp.processAllocate(allocatorOperands, allocateOperands); @@ -2524,8 +2594,6 @@ genOMP(Fortran::lower::AbstractConverter &converter, } else if (blockDirective.v == llvm::omp::OMPD_target_data) { createTargetOp(converter, opClauseList, blockDirective.v, currentLocation, &eval); - } else { - TODO(currentLocation, "Unhandled block directive"); } } diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 7baf96c1658c8..6d1a3a04b481e 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -115,6 +115,7 @@ TYPE_PARSER(construct( TYPE_PARSER(construct( maybe( ("PARALLEL" >> pure(OmpIfClause::DirectiveNameModifier::Parallel) || + "SIMD" >> pure(OmpIfClause::DirectiveNameModifier::Simd) || "TARGET ENTER DATA" >> pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) || "TARGET EXIT DATA" >> @@ -125,7 +126,8 @@ TYPE_PARSER(construct( pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) || "TARGET" >> pure(OmpIfClause::DirectiveNameModifier::Target) || "TASK"_id >> pure(OmpIfClause::DirectiveNameModifier::Task) || - "TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop)) / + "TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) || + "TEAMS" >> pure(OmpIfClause::DirectiveNameModifier::Teams)) / ":"), scalarLogicalExpr)) diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index fb67cb41953c7..0c838a968812f 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -2395,19 +2395,35 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) { void OmpStructureChecker::Enter(const parser::OmpClause::If &x) { CheckAllowed(llvm::omp::Clause::OMPC_if); using dirNameModifier = parser::OmpIfClause::DirectiveNameModifier; + // TODO Check that, when multiple 'if' clauses are applied to a combined + // construct, at most one of them applies to each directive. + // Need to define set here because llvm::omp::teamSet does not include target + // teams combined constructs. + OmpDirectiveSet teamSet{llvm::omp::Directive::OMPD_target_teams, + llvm::omp::Directive::OMPD_target_teams_distribute, + llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do, + llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd, + llvm::omp::Directive::OMPD_target_teams_distribute_simd, + llvm::omp::Directive::OMPD_teams, + llvm::omp::Directive::OMPD_teams_distribute, + llvm::omp::Directive::OMPD_teams_distribute_parallel_do, + llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd, + llvm::omp::Directive::OMPD_teams_distribute_simd}; static std::unordered_map dirNameModifierMap{{dirNameModifier::Parallel, llvm::omp::parallelSet}, + {dirNameModifier::Simd, llvm::omp::simdSet}, {dirNameModifier::Target, llvm::omp::targetSet}, + {dirNameModifier::TargetData, + {llvm::omp::Directive::OMPD_target_data}}, {dirNameModifier::TargetEnterData, {llvm::omp::Directive::OMPD_target_enter_data}}, {dirNameModifier::TargetExitData, {llvm::omp::Directive::OMPD_target_exit_data}}, - {dirNameModifier::TargetData, - {llvm::omp::Directive::OMPD_target_data}}, {dirNameModifier::TargetUpdate, {llvm::omp::Directive::OMPD_target_update}}, {dirNameModifier::Task, {llvm::omp::Directive::OMPD_task}}, - {dirNameModifier::Taskloop, llvm::omp::taskloopSet}}; + {dirNameModifier::Taskloop, llvm::omp::taskloopSet}, + {dirNameModifier::Teams, teamSet}}; if (const auto &directiveName{ std::get>(x.v.t)}) { auto search{dirNameModifierMap.find(*directiveName)}; diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index d41d60755edbc..3b5de101fe079 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -66,22 +66,21 @@ static OmpDirectiveSet targetSet{Directive::OMPD_target, Directive::OMPD_target_parallel, Directive::OMPD_target_parallel_do, Directive::OMPD_target_parallel_do_simd, Directive::OMPD_target_simd, Directive::OMPD_target_teams, Directive::OMPD_target_teams_distribute, + Directive::OMPD_target_teams_distribute_parallel_do, + Directive::OMPD_target_teams_distribute_parallel_do_simd, Directive::OMPD_target_teams_distribute_simd}; static OmpDirectiveSet simdSet{Directive::OMPD_distribute_parallel_do_simd, - Directive::OMPD_distribute_simd, Directive::OMPD_parallel_do_simd, - Directive::OMPD_do_simd, Directive::OMPD_simd, - Directive::OMPD_target_parallel_do_simd, + Directive::OMPD_distribute_simd, Directive::OMPD_do_simd, + Directive::OMPD_parallel_do_simd, Directive::OMPD_simd, + Directive::OMPD_target_parallel_do_simd, Directive::OMPD_target_simd, Directive::OMPD_target_teams_distribute_parallel_do_simd, - Directive::OMPD_target_teams_distribute_simd, Directive::OMPD_target_simd, - Directive::OMPD_taskloop_simd, + Directive::OMPD_target_teams_distribute_simd, Directive::OMPD_taskloop_simd, Directive::OMPD_teams_distribute_parallel_do_simd, Directive::OMPD_teams_distribute_simd}; static OmpDirectiveSet teamSet{Directive::OMPD_teams, Directive::OMPD_teams_distribute, Directive::OMPD_teams_distribute_parallel_do, Directive::OMPD_teams_distribute_parallel_do_simd, - Directive::OMPD_teams_distribute_parallel_for, - Directive::OMPD_teams_distribute_parallel_for_simd, Directive::OMPD_teams_distribute_simd}; static OmpDirectiveSet taskGeneratingSet{ OmpDirectiveSet{Directive::OMPD_task} | taskloopSet}; diff --git a/flang/test/Parser/OpenMP/if-clause-unparse.f90 b/flang/test/Parser/OpenMP/if-clause-unparse.f90 new file mode 100644 index 0000000000000..20f7b36e743e1 --- /dev/null +++ b/flang/test/Parser/OpenMP/if-clause-unparse.f90 @@ -0,0 +1,61 @@ +! RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp %s | FileCheck %s +! Check Unparsing of OpenMP IF clause + +program if_unparse + logical :: cond + integer :: i + + ! CHECK: !$OMP TARGET UPDATE + ! CHECK-SAME: IF(cond) + !$omp target update if(cond) + + ! CHECK: !$OMP TARGET UPDATE + ! CHECK-SAME: IF(TARGETUPDATE:cond) + !$omp target update if(target update: cond) + + ! CHECK: !$OMP TARGET UPDATE + ! CHECK-SAME: IF(TARGETUPDATE:cond) + !$omp target update if(targetupdate: cond) + + ! CHECK: !$OMP TARGET ENTER DATA + ! CHECK-SAME: IF(TARGETENTERDATA:cond) + !$omp target enter data map(to: i) if(target enter data: cond) + + ! CHECK: !$OMP TARGET EXIT DATA + ! CHECK-SAME: IF(TARGETEXITDATA:cond) + !$omp target exit data map(from: i) if(target exit data: cond) + + ! CHECK: !$OMP TARGET DATA + ! CHECK-SAME: IF(TARGETDATA:cond) + !$omp target data map(tofrom: i) if(target data: cond) + !$omp end target data + + ! CHECK: !$OMP TARGET + ! CHECK-SAME: IF(TARGET:cond) + !$omp target if(target: cond) + !$omp end target + + ! CHECK: !$OMP TEAMS + ! CHECK-SAME: IF(TEAMS:cond) + !$omp teams if(teams: cond) + !$omp end teams + + ! CHECK: !$OMP PARALLEL DO SIMD + ! CHECK-SAME: IF(PARALLEL:i<10) IF(SIMD:.FALSE.) + !$omp parallel do simd if(parallel: i < 10) if(simd: .false.) + do i = 1, 10 + end do + !$omp end parallel do simd + + ! CHECK: !$OMP TASK + ! CHECK-SAME: IF(TASK:cond) + !$omp task if(task: cond) + !$omp end task + + ! CHECK: !$OMP TASKLOOP + ! CHECK-SAME: IF(TASKLOOP:cond) + !$omp taskloop if(taskloop: cond) + do i = 1, 10 + end do + !$omp end taskloop +end program if_unparse diff --git a/flang/test/Parser/OpenMP/if-clause.f90 b/flang/test/Parser/OpenMP/if-clause.f90 new file mode 100644 index 0000000000000..ca62f6969eee1 --- /dev/null +++ b/flang/test/Parser/OpenMP/if-clause.f90 @@ -0,0 +1,61 @@ +! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck %s + +program openmp_parse_if + logical :: cond + integer :: i + + ! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update + ! CHECK-NEXT: OmpClause -> If -> OmpIfClause + ! CHECK-NOT: DirectiveNameModifier + !$omp target update if(cond) + + ! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update + ! CHECK-NEXT: OmpClause -> If -> OmpIfClause + ! CHECK-NEXT: DirectiveNameModifier = TargetUpdate + !$omp target update if(target update: cond) + + ! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target enter data + ! CHECK: OmpClause -> If -> OmpIfClause + ! CHECK-NEXT: DirectiveNameModifier = TargetEnterData + !$omp target enter data map(to: i) if(target enter data: cond) + + ! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target exit data + ! CHECK: OmpClause -> If -> OmpIfClause + ! CHECK-NEXT: DirectiveNameModifier = TargetExitData + !$omp target exit data map(from: i) if(target exit data: cond) + + ! CHECK: OmpBlockDirective -> llvm::omp::Directive = target data + ! CHECK: OmpClause -> If -> OmpIfClause + ! CHECK-NEXT: DirectiveNameModifier = TargetData + !$omp target data map(tofrom: i) if(target data: cond) + !$omp end target data + + ! CHECK: OmpLoopDirective -> llvm::omp::Directive = target teams distribute parallel do simd + ! CHECK: OmpClause -> If -> OmpIfClause + ! CHECK-NEXT: DirectiveNameModifier = Target + ! CHECK: OmpClause -> If -> OmpIfClause + ! CHECK-NEXT: DirectiveNameModifier = Teams + ! CHECK: OmpClause -> If -> OmpIfClause + ! CHECK-NEXT: DirectiveNameModifier = Parallel + ! CHECK: OmpClause -> If -> OmpIfClause + ! CHECK-NEXT: DirectiveNameModifier = Simd + !$omp target teams distribute parallel do simd if(target: cond) & + !$omp& if(teams: cond) if(parallel: cond) if(simd: cond) + do i = 1, 10 + end do + !$omp end target teams distribute parallel do simd + + ! CHECK: OmpBlockDirective -> llvm::omp::Directive = task + ! CHECK-NEXT: OmpClause -> If -> OmpIfClause + ! CHECK-NEXT: DirectiveNameModifier = Task + !$omp task if(task: cond) + !$omp end task + + ! CHECK: OmpLoopDirective -> llvm::omp::Directive = taskloop + ! CHECK-NEXT: OmpClause -> If -> OmpIfClause + ! CHECK-NEXT: DirectiveNameModifier = Taskloop + !$omp taskloop if(taskloop: cond) + do i = 1, 10 + end do + !$omp end taskloop +end program openmp_parse_if diff --git a/flang/test/Semantics/OpenMP/if-clause.f90 b/flang/test/Semantics/OpenMP/if-clause.f90 new file mode 100644 index 0000000000000..dc9aa5ef7f1d1 --- /dev/null +++ b/flang/test/Semantics/OpenMP/if-clause.f90 @@ -0,0 +1,624 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! Check OpenMP 'if' clause validity for all directives that can have it + +program main + integer :: i + + ! ---------------------------------------------------------------------------- + ! DISTRIBUTE PARALLEL DO + ! ---------------------------------------------------------------------------- + !$omp teams + !$omp distribute parallel do if(.true.) + do i = 1, 10 + end do + !$omp end distribute parallel do + + !$omp distribute parallel do if(parallel: .true.) + do i = 1, 10 + end do + !$omp end distribute parallel do + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp distribute parallel do if(target: .true.) + do i = 1, 10 + end do + !$omp end distribute parallel do + + !ERROR: At most one IF clause can appear on the DISTRIBUTE PARALLEL DO directive + !$omp distribute parallel do if(.true.) if(parallel: .false.) + do i = 1, 10 + end do + !$omp end distribute parallel do + !$omp end teams + + ! ---------------------------------------------------------------------------- + ! DISTRIBUTE PARALLEL DO SIMD + ! ---------------------------------------------------------------------------- + !$omp teams + !$omp distribute parallel do simd if(.true.) + do i = 1, 10 + end do + !$omp end distribute parallel do simd + + !$omp distribute parallel do simd if(parallel: .true.) if(simd: .false.) + do i = 1, 10 + end do + !$omp end distribute parallel do simd + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp distribute parallel do simd if(target: .true.) + do i = 1, 10 + end do + !$omp end distribute parallel do simd + !$omp end teams + + ! ---------------------------------------------------------------------------- + ! DISTRIBUTE SIMD + ! ---------------------------------------------------------------------------- + !$omp teams + !$omp distribute simd if(.true.) + do i = 1, 10 + end do + !$omp end distribute simd + + !$omp distribute simd if(simd: .true.) + do i = 1, 10 + end do + !$omp end distribute simd + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp distribute simd if(target: .true.) + do i = 1, 10 + end do + !$omp end distribute simd + + !ERROR: At most one IF clause can appear on the DISTRIBUTE SIMD directive + !$omp distribute simd if(.true.) if(simd: .false.) + do i = 1, 10 + end do + !$omp end distribute simd + !$omp end teams + + ! ---------------------------------------------------------------------------- + ! DO SIMD + ! ---------------------------------------------------------------------------- + !$omp do simd if(.true.) + do i = 1, 10 + end do + !$omp end do simd + + !$omp do simd if(simd: .true.) + do i = 1, 10 + end do + !$omp end do simd + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp do simd if(target: .true.) + do i = 1, 10 + end do + !$omp end do simd + + !ERROR: At most one IF clause can appear on the DO SIMD directive + !$omp do simd if(.true.) if(simd: .false.) + do i = 1, 10 + end do + !$omp end do simd + + ! ---------------------------------------------------------------------------- + ! PARALLEL + ! ---------------------------------------------------------------------------- + !$omp parallel if(.true.) + !$omp end parallel + + !$omp parallel if(parallel: .true.) + !$omp end parallel + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp parallel if(target: .true.) + !$omp end parallel + + !ERROR: At most one IF clause can appear on the PARALLEL directive + !$omp parallel if(.true.) if(parallel: .false.) + !$omp end parallel + + ! ---------------------------------------------------------------------------- + ! PARALLEL DO + ! ---------------------------------------------------------------------------- + !$omp parallel do if(.true.) + do i = 1, 10 + end do + !$omp end parallel do + + !$omp parallel do if(parallel: .true.) + do i = 1, 10 + end do + !$omp end parallel do + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp parallel do if(target: .true.) + do i = 1, 10 + end do + !$omp end parallel do + + !ERROR: At most one IF clause can appear on the PARALLEL DO directive + !$omp parallel do if(.true.) if(parallel: .false.) + do i = 1, 10 + end do + !$omp end parallel do + + ! ---------------------------------------------------------------------------- + ! PARALLEL DO SIMD + ! ---------------------------------------------------------------------------- + !$omp parallel do simd if(.true.) + do i = 1, 10 + end do + !$omp end parallel do simd + + !$omp parallel do simd if(parallel: .true.) if(simd: .false.) + do i = 1, 10 + end do + !$omp end parallel do simd + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp parallel do simd if(target: .true.) + do i = 1, 10 + end do + !$omp end parallel do simd + + ! ---------------------------------------------------------------------------- + ! PARALLEL SECTIONS + ! ---------------------------------------------------------------------------- + !$omp parallel sections if(.true.) + !$omp end parallel sections + + !$omp parallel sections if(parallel: .true.) + !$omp end parallel sections + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp parallel sections if(target: .true.) + !$omp end parallel sections + + !ERROR: At most one IF clause can appear on the PARALLEL SECTIONS directive + !$omp parallel sections if(.true.) if(parallel: .false.) + !$omp end parallel sections + + ! ---------------------------------------------------------------------------- + ! PARALLEL WORKSHARE + ! ---------------------------------------------------------------------------- + !$omp parallel workshare if(.true.) + !$omp end parallel workshare + + !$omp parallel workshare if(parallel: .true.) + !$omp end parallel workshare + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp parallel workshare if(target: .true.) + !$omp end parallel workshare + + !ERROR: At most one IF clause can appear on the PARALLEL WORKSHARE directive + !$omp parallel workshare if(.true.) if(parallel: .false.) + !$omp end parallel workshare + + ! ---------------------------------------------------------------------------- + ! SIMD + ! ---------------------------------------------------------------------------- + !$omp simd if(.true.) + do i = 1, 10 + end do + !$omp end simd + + !$omp simd if(simd: .true.) + do i = 1, 10 + end do + !$omp end simd + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp simd if(target: .true.) + do i = 1, 10 + end do + !$omp end simd + + !ERROR: At most one IF clause can appear on the SIMD directive + !$omp simd if(.true.) if(simd: .false.) + do i = 1, 10 + end do + !$omp end simd + + ! ---------------------------------------------------------------------------- + ! TARGET + ! ---------------------------------------------------------------------------- + !$omp target if(.true.) + !$omp end target + + !$omp target if(target: .true.) + !$omp end target + + !ERROR: Unmatched directive name modifier PARALLEL on the IF clause + !$omp target if(parallel: .true.) + !$omp end target + + !ERROR: At most one IF clause can appear on the TARGET directive + !$omp target if(.true.) if(target: .false.) + !$omp end target + + ! ---------------------------------------------------------------------------- + ! TARGET DATA + ! ---------------------------------------------------------------------------- + !$omp target data map(tofrom: i) if(.true.) + !$omp end target data + + !$omp target data map(tofrom: i) if(target data: .true.) + !$omp end target data + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp target data map(tofrom: i) if(target: .true.) + !$omp end target data + + !ERROR: At most one IF clause can appear on the TARGET DATA directive + !$omp target data map(tofrom: i) if(.true.) if(target data: .false.) + !$omp end target data + + ! ---------------------------------------------------------------------------- + ! TARGET ENTER DATA + ! ---------------------------------------------------------------------------- + !$omp target enter data map(to: i) if(.true.) + + !$omp target enter data map(to: i) if(target enter data: .true.) + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp target enter data map(to: i) if(target: .true.) + + !ERROR: At most one IF clause can appear on the TARGET ENTER DATA directive + !$omp target enter data map(to: i) if(.true.) if(target enter data: .false.) + + ! ---------------------------------------------------------------------------- + ! TARGET EXIT DATA + ! ---------------------------------------------------------------------------- + !$omp target exit data map(from: i) if(.true.) + + !$omp target exit data map(from: i) if(target exit data: .true.) + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp target exit data map(from: i) if(target: .true.) + + !ERROR: At most one IF clause can appear on the TARGET EXIT DATA directive + !$omp target exit data map(from: i) if(.true.) if(target exit data: .false.) + + ! ---------------------------------------------------------------------------- + ! TARGET PARALLEL + ! ---------------------------------------------------------------------------- + !$omp target parallel if(.true.) + !$omp end target parallel + + !$omp target parallel if(target: .true.) if(parallel: .false.) + !$omp end target parallel + + !ERROR: Unmatched directive name modifier SIMD on the IF clause + !$omp target parallel if(simd: .true.) + !$omp end target parallel + + ! ---------------------------------------------------------------------------- + ! TARGET PARALLEL DO + ! ---------------------------------------------------------------------------- + !$omp target parallel do if(.true.) + do i = 1, 10 + end do + !$omp end target parallel do + + !$omp target parallel do if(target: .true.) if(parallel: .false.) + do i = 1, 10 + end do + !$omp end target parallel do + + !ERROR: Unmatched directive name modifier SIMD on the IF clause + !$omp target parallel do if(simd: .true.) + do i = 1, 10 + end do + !$omp end target parallel do + + ! ---------------------------------------------------------------------------- + ! TARGET PARALLEL DO SIMD + ! ---------------------------------------------------------------------------- + !$omp target parallel do simd if(.true.) + do i = 1, 10 + end do + !$omp end target parallel do simd + + !$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 + + !ERROR: Unmatched directive name modifier TEAMS on the IF clause + !$omp target parallel do simd if(teams: .true.) + do i = 1, 10 + end do + !$omp end target parallel do simd + + ! ---------------------------------------------------------------------------- + ! TARGET SIMD + ! ---------------------------------------------------------------------------- + !$omp target simd if(.true.) + do i = 1, 10 + end do + !$omp end target simd + + !$omp target simd if(target: .true.) if(simd: .false.) + do i = 1, 10 + end do + !$omp end target simd + + !ERROR: Unmatched directive name modifier PARALLEL on the IF clause + !$omp target simd if(parallel: .true.) + do i = 1, 10 + end do + !$omp end target simd + + ! ---------------------------------------------------------------------------- + ! TARGET TEAMS + ! ---------------------------------------------------------------------------- + !$omp target teams if(.true.) + !$omp end target teams + + !$omp target teams if(target: .true.) if(teams: .false.) + !$omp end target teams + + !ERROR: Unmatched directive name modifier PARALLEL on the IF clause + !$omp target teams if(parallel: .true.) + !$omp end target teams + + ! ---------------------------------------------------------------------------- + ! TARGET TEAMS DISTRIBUTE + ! ---------------------------------------------------------------------------- + !$omp target teams distribute if(.true.) + do i = 1, 10 + end do + !$omp end target teams distribute + + !$omp target teams distribute if(target: .true.) if(teams: .false.) + do i = 1, 10 + end do + !$omp end target teams distribute + + !ERROR: Unmatched directive name modifier PARALLEL on the IF clause + !$omp target teams distribute if(parallel: .true.) + do i = 1, 10 + end do + !$omp end target teams distribute + + ! ---------------------------------------------------------------------------- + ! TARGET TEAMS DISTRIBUTE PARALLEL DO + ! ---------------------------------------------------------------------------- + !$omp target teams distribute parallel do if(.true.) + do i = 1, 10 + end do + !$omp end target teams distribute parallel do + + !$omp target teams distribute parallel do & + !$omp& if(target: .true.) if(teams: .false.) if(parallel: .true.) + do i = 1, 10 + end do + !$omp end target teams distribute parallel do + + !ERROR: Unmatched directive name modifier SIMD on the IF clause + !$omp target teams distribute parallel do if(simd: .true.) + do i = 1, 10 + end do + !$omp end target teams distribute parallel do + + ! ---------------------------------------------------------------------------- + ! TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD + ! ---------------------------------------------------------------------------- + !$omp target teams distribute parallel do simd if(.true.) + do i = 1, 10 + end do + !$omp end target teams distribute parallel do simd + + !$omp target teams distribute parallel do simd & + !$omp& if(target: .true.) if(teams: .false.) if(parallel: .true.) & + !$omp& if(simd: .false.) + do i = 1, 10 + end do + !$omp end target teams distribute parallel do simd + + !ERROR: Unmatched directive name modifier TASK on the IF clause + !$omp target teams distribute parallel do simd if(task: .true.) + do i = 1, 10 + end do + !$omp end target teams distribute parallel do simd + + ! ---------------------------------------------------------------------------- + ! TARGET TEAMS DISTRIBUTE SIMD + ! ---------------------------------------------------------------------------- + !$omp target teams distribute simd if(.true.) + do i = 1, 10 + end do + !$omp end target teams distribute simd + + !$omp target teams distribute simd & + !$omp& if(target: .true.) if(teams: .false.) if(simd: .true.) + do i = 1, 10 + end do + !$omp end target teams distribute simd + + !ERROR: Unmatched directive name modifier PARALLEL on the IF clause + !$omp target teams distribute simd if(parallel: .true.) + do i = 1, 10 + end do + !$omp end target teams distribute simd + + ! ---------------------------------------------------------------------------- + ! TARGET UPDATE + ! ---------------------------------------------------------------------------- + !$omp target update if(.true.) + + !$omp target update if(target update: .true.) + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp target update if(target: .true.) + + !ERROR: At most one IF clause can appear on the TARGET UPDATE directive + !$omp target update if(.true.) if(target update: .false.) + + ! ---------------------------------------------------------------------------- + ! TASK + ! ---------------------------------------------------------------------------- + !$omp task if(.true.) + !$omp end task + + !$omp task if(task: .true.) + !$omp end task + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp task if(target: .true.) + !$omp end task + + !ERROR: At most one IF clause can appear on the TASK directive + !$omp task if(.true.) if(task: .false.) + !$omp end task + + ! ---------------------------------------------------------------------------- + ! TASKLOOP + ! ---------------------------------------------------------------------------- + !$omp taskloop if(.true.) + do i = 1, 10 + end do + !$omp end taskloop + + !$omp taskloop if(taskloop: .true.) + do i = 1, 10 + end do + !$omp end taskloop + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp taskloop if(target: .true.) + do i = 1, 10 + end do + !$omp end taskloop + + !ERROR: At most one IF clause can appear on the TASKLOOP directive + !$omp taskloop if(.true.) if(taskloop: .false.) + do i = 1, 10 + end do + !$omp end taskloop + + ! ---------------------------------------------------------------------------- + ! TASKLOOP SIMD + ! ---------------------------------------------------------------------------- + !$omp taskloop simd if(.true.) + do i = 1, 10 + end do + !$omp end taskloop simd + + !$omp taskloop simd if(taskloop: .true.) if(simd: .false.) + do i = 1, 10 + end do + !$omp end taskloop simd + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp taskloop simd if(target: .true.) + do i = 1, 10 + end do + !$omp end taskloop simd + + ! ---------------------------------------------------------------------------- + ! TEAMS + ! ---------------------------------------------------------------------------- + !$omp teams if(.true.) + !$omp end teams + + !$omp teams if(teams: .true.) + !$omp end teams + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp teams if(target: .true.) + !$omp end teams + + !ERROR: At most one IF clause can appear on the TEAMS directive + !$omp teams if(.true.) if(teams: .false.) + !$omp end teams + + ! ---------------------------------------------------------------------------- + ! TEAMS DISTRIBUTE + ! ---------------------------------------------------------------------------- + !$omp teams distribute if(.true.) + do i = 1, 10 + end do + !$omp end teams distribute + + !$omp teams distribute if(teams: .true.) + do i = 1, 10 + end do + !$omp end teams distribute + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp teams distribute if(target: .true.) + do i = 1, 10 + end do + !$omp end teams distribute + + !ERROR: At most one IF clause can appear on the TEAMS DISTRIBUTE directive + !$omp teams distribute if(.true.) if(teams: .true.) + do i = 1, 10 + end do + !$omp end teams distribute + + ! ---------------------------------------------------------------------------- + ! TEAMS DISTRIBUTE PARALLEL DO + ! ---------------------------------------------------------------------------- + !$omp teams distribute parallel do if(.true.) + do i = 1, 10 + end do + !$omp end teams distribute parallel do + + !$omp teams distribute parallel do if(teams: .true.) if(parallel: .false.) + do i = 1, 10 + end do + !$omp end teams distribute parallel do + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp teams distribute parallel do if(target: .true.) + do i = 1, 10 + end do + !$omp end teams distribute parallel do + + ! ---------------------------------------------------------------------------- + ! TEAMS DISTRIBUTE PARALLEL DO SIMD + ! ---------------------------------------------------------------------------- + !$omp teams distribute parallel do simd if(.true.) + do i = 1, 10 + end do + !$omp end teams distribute parallel do simd + + !$omp teams distribute parallel do simd & + !$omp& if(teams: .true.) if(parallel: .true.) if(simd: .true.) + do i = 1, 10 + end do + !$omp end teams distribute parallel do simd + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp teams distribute parallel do simd if(target: .true.) + do i = 1, 10 + end do + !$omp end teams distribute parallel do simd + + ! ---------------------------------------------------------------------------- + ! TEAMS DISTRIBUTE SIMD + ! ---------------------------------------------------------------------------- + !$omp teams distribute simd if(.true.) + do i = 1, 10 + end do + !$omp end teams distribute simd + + !$omp teams distribute simd if(teams: .true.) if(simd: .true.) + do i = 1, 10 + end do + !$omp end teams distribute simd + + !ERROR: Unmatched directive name modifier TARGET on the IF clause + !$omp teams distribute simd if(target: .true.) + do i = 1, 10 + end do + !$omp end teams distribute simd +end program main diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index f7a980476bac0..6c9f6a5edb01c 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -640,7 +640,6 @@ def OMP_Atomic : Directive<"atomic"> { } def OMP_Target : Directive<"target"> { let allowedClauses = [ - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -654,6 +653,7 @@ def OMP_Target : Directive<"target"> { VersionedClause, ]; let allowedOnceClauses = [ + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -672,12 +672,13 @@ def OMP_Teams : Directive<"teams"> { ]; let allowedOnceClauses = [ VersionedClause, + VersionedClause, VersionedClause, VersionedClause ]; } def OMP_Cancel : Directive<"cancel"> { - let allowedClauses = [ + let allowedOnceClauses = [ VersionedClause ]; } @@ -740,6 +741,7 @@ def OMP_TargetExitData : Directive<"target exit data"> { } def OMP_TargetParallel : Directive<"target parallel"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -757,7 +759,6 @@ def OMP_TargetParallel : Directive<"target parallel"> { let allowedOnceClauses = [ VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -796,6 +797,7 @@ def OMP_TargetParallelFor : Directive<"target parallel for"> { } def OMP_TargetParallelDo : Directive<"target parallel do"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -812,7 +814,6 @@ def OMP_TargetParallelDo : Directive<"target parallel do"> { VersionedClause ]; let allowedOnceClauses = [ - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -905,6 +906,7 @@ def OMP_ParallelForSimd : Directive<"parallel for simd"> { } def OMP_ParallelDoSimd : Directive<"parallel do simd"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -918,7 +920,6 @@ def OMP_ParallelDoSimd : Directive<"parallel do simd"> { VersionedClause, ]; let allowedOnceClauses = [ - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -962,7 +963,6 @@ def OMP_ParallelMasked : Directive<"parallel masked"> { } def OMP_ParallelSections : Directive<"parallel sections"> { let allowedClauses = [ - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -975,6 +975,7 @@ def OMP_ParallelSections : Directive<"parallel sections"> { VersionedClause, ]; let allowedOnceClauses = [ + VersionedClause, VersionedClause ]; } @@ -1008,6 +1009,7 @@ def OMP_DoSimd : Directive<"do simd"> { VersionedClause ]; let allowedOnceClauses = [ + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1065,6 +1067,7 @@ def OMP_TaskLoop : Directive<"taskloop"> { } def OMP_TaskLoopSimd : Directive<"taskloop simd"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1081,7 +1084,6 @@ def OMP_TaskLoopSimd : Directive<"taskloop simd"> { VersionedClause ]; let allowedOnceClauses = [ - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1312,6 +1314,7 @@ def OMP_TargetParallelDoSimd : Directive<"target parallel do simd"> { } def OMP_TargetSimd : Directive<"target simd"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1333,7 +1336,6 @@ def OMP_TargetSimd : Directive<"target simd"> { VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1358,9 +1360,13 @@ def OMP_TeamsDistribute : Directive<"teams distribute"> { VersionedClause, VersionedClause, ]; + let allowedOnceClauses = [ + VersionedClause + ]; } def OMP_TeamsDistributeSimd : Directive<"teams distribute simd"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1376,7 +1382,6 @@ def OMP_TeamsDistributeSimd : Directive<"teams distribute simd"> { VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1415,6 +1420,7 @@ def OMP_TeamsDistributeParallelForSimd : def OMP_TeamsDistributeParallelDoSimd : Directive<"teams distribute parallel do simd"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1436,7 +1442,6 @@ def OMP_TeamsDistributeParallelDoSimd : VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause ]; } @@ -1466,6 +1471,7 @@ def OMP_TeamsDistributeParallelFor : def OMP_TeamsDistributeParallelDo : Directive<"teams distribute parallel do"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1482,7 +1488,6 @@ let allowedOnceClauses = [ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1652,6 +1657,7 @@ def OMP_TargetTeamsDistributeParallelForSimd : def OMP_TargetTeamsDistributeParallelDoSimd : Directive<"target teams distribute parallel do simd"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1670,7 +1676,6 @@ def OMP_TargetTeamsDistributeParallelDoSimd : VersionedClause ]; let allowedOnceClauses = [ - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -2070,6 +2075,7 @@ def OMP_teams_loop : Directive<"teams loop"> { } def OMP_target_teams_loop : Directive<"target teams loop"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -2089,7 +2095,6 @@ def OMP_target_teams_loop : Directive<"target teams loop"> { VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -2120,6 +2125,7 @@ def OMP_parallel_loop : Directive<"parallel loop"> { } def OMP_target_parallel_loop : Directive<"target parallel loop"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -2140,7 +2146,6 @@ def OMP_target_parallel_loop : Directive<"target parallel loop"> { VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause,