-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang][OpenMP] Add MLIR lowering for loop ... bind
#114219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-flang-parser @llvm/pr-subscribers-mlir Author: Kareem Ergawy (ergawy) ChangesExtends MLIR lowering support for the Patch is 32.53 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/114219.diff 24 Files Affected:
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 31ad1b7c6ce5b5..ef6a774ec2c3d2 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -551,6 +551,8 @@ class ParseTreeDumper {
NODE_ENUM(OmpGrainsizeClause, Prescriptiveness)
NODE(parser, OmpNumTasksClause)
NODE_ENUM(OmpNumTasksClause, Prescriptiveness)
+ NODE(parser, OmpBindClause)
+ NODE_ENUM(OmpBindClause, Type)
NODE(parser, OmpProcBindClause)
NODE_ENUM(OmpProcBindClause, Type)
NODE_ENUM(OmpReductionClause, ReductionModifier)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 174f4c631e9d4c..d7d996ddf4239d 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3716,6 +3716,13 @@ struct OmpNumTasksClause {
std::tuple<std::optional<Prescriptiveness>, ScalarIntExpr> t;
};
+// OMP 5.2 11.7.1 bind-clause ->
+// BIND( PARALLEL | TEAMS | THREAD )
+struct OmpBindClause {
+ ENUM_CLASS(Type, Parallel, Teams, Thread)
+ WRAPPER_CLASS_BOILERPLATE(OmpBindClause, Type);
+};
+
// OpenMP Clauses
struct OmpClause {
UNION_CLASS_BOILERPLATE(OmpClause);
diff --git a/flang/include/flang/Semantics/openmp-directive-sets.h b/flang/include/flang/Semantics/openmp-directive-sets.h
index 55ef1e0ca61b9f..5e51c5c7de0e82 100644
--- a/flang/include/flang/Semantics/openmp-directive-sets.h
+++ b/flang/include/flang/Semantics/openmp-directive-sets.h
@@ -169,6 +169,7 @@ static const OmpDirectiveSet topTeamsSet{
Directive::OMPD_teams_distribute_parallel_do,
Directive::OMPD_teams_distribute_parallel_do_simd,
Directive::OMPD_teams_distribute_simd,
+ Directive::OMPD_teams_loop,
};
static const OmpDirectiveSet allTeamsSet{
@@ -366,6 +367,7 @@ static const OmpDirectiveSet nestedTeamsAllowedSet{
Directive::OMPD_distribute_parallel_do,
Directive::OMPD_distribute_parallel_do_simd,
Directive::OMPD_distribute_simd,
+ Directive::OMPD_loop,
Directive::OMPD_parallel,
Directive::OMPD_parallel_do,
Directive::OMPD_parallel_do_simd,
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 7c254ce673855a..3e8d9c0ff161ee 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -98,6 +98,25 @@ genAllocateClause(lower::AbstractConverter &converter,
genObjectList(objects, converter, allocateOperands);
}
+static mlir::omp::ClauseBindKindAttr
+genBindKindAttr(fir::FirOpBuilder &firOpBuilder,
+ const omp::clause::Bind &clause) {
+ mlir::omp::ClauseBindKind bindKind;
+ switch (clause.v) {
+ case omp::clause::Bind::Binding::Teams:
+ bindKind = mlir::omp::ClauseBindKind::Teams;
+ break;
+ case omp::clause::Bind::Binding::Parallel:
+ bindKind = mlir::omp::ClauseBindKind::Parallel;
+ break;
+ case omp::clause::Bind::Binding::Thread:
+ bindKind = mlir::omp::ClauseBindKind::Thread;
+ break;
+ }
+ return mlir::omp::ClauseBindKindAttr::get(firOpBuilder.getContext(),
+ bindKind);
+}
+
static mlir::omp::ClauseProcBindKindAttr
genProcBindKindAttr(fir::FirOpBuilder &firOpBuilder,
const omp::clause::ProcBind &clause) {
@@ -197,6 +216,15 @@ static void convertLoopBounds(lower::AbstractConverter &converter,
// ClauseProcessor unique clauses
//===----------------------------------------------------------------------===//
+bool ClauseProcessor::processBind(mlir::omp::BindClauseOps &result) const {
+ if (auto *clause = findUniqueClause<omp::clause::Bind>()) {
+ fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
+ result.bindKind = genBindKindAttr(firOpBuilder, *clause);
+ return true;
+ }
+ return false;
+}
+
bool ClauseProcessor::processCollapse(
mlir::Location currentLocation, lower::pft::Evaluation &eval,
mlir::omp::LoopRelatedClauseOps &result,
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h
index f34121c70d0b44..772e5415d2da27 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.h
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h
@@ -53,6 +53,7 @@ class ClauseProcessor {
: converter(converter), semaCtx(semaCtx), clauses(clauses) {}
// 'Unique' clauses: They can appear at most once in the clause list.
+ bool processBind(mlir::omp::BindClauseOps &result) const;
bool
processCollapse(mlir::Location currentLocation, lower::pft::Evaluation &eval,
mlir::omp::LoopRelatedClauseOps &result,
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 9483f643acd55a..71e2bcce27e183 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -461,8 +461,19 @@ AtomicDefaultMemOrder make(const parser::OmpClause::AtomicDefaultMemOrder &inp,
Bind make(const parser::OmpClause::Bind &inp,
semantics::SemanticsContext &semaCtx) {
- // inp -> empty
- llvm_unreachable("Empty: bind");
+ // inp.v -> parser::OmpBindClause
+ using wrapped = parser::OmpBindClause;
+
+ CLAUSET_ENUM_CONVERT( //
+ convert, wrapped::Type, Bind::Binding,
+ // clang-format off
+ MS(Teams, Teams)
+ MS(Parallel, Parallel)
+ MS(Thread, Thread)
+ // clang-format on
+ );
+
+ return Bind{/*Binding=*/convert(inp.v.v)};
}
// CancellationConstructType: empty
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 01a40d6e2204ef..6b35ad81f2a0ca 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2023,6 +2023,52 @@ static void genStandaloneDo(lower::AbstractConverter &converter,
llvm::omp::Directive::OMPD_do, dsp);
}
+static void genLoopClauses(
+ lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
+ const List<Clause> &clauses, mlir::Location loc,
+ mlir::omp::LoopOperands &clauseOps,
+ llvm::SmallVectorImpl<const semantics::Symbol *> &reductionSyms) {
+ ClauseProcessor cp(converter, semaCtx, clauses);
+ cp.processBind(clauseOps);
+ cp.processOrder(clauseOps);
+ cp.processReduction(loc, clauseOps, reductionSyms);
+ cp.processTODO<clause::Lastprivate>(loc, llvm::omp::Directive::OMPD_loop);
+}
+
+static void genLoopOp(lower::AbstractConverter &converter,
+ lower::SymMap &symTable,
+ semantics::SemanticsContext &semaCtx,
+ lower::pft::Evaluation &eval, mlir::Location loc,
+ const ConstructQueue &queue,
+ ConstructQueue::const_iterator item) {
+ mlir::omp::LoopOperands loopClauseOps;
+ llvm::SmallVector<const semantics::Symbol *> loopReductionSyms;
+ genLoopClauses(converter, semaCtx, item->clauses, loc, loopClauseOps,
+ loopReductionSyms);
+
+ DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval,
+ /*shouldCollectPreDeterminedSymbols=*/true,
+ /*useDelayedPrivatization=*/true, &symTable);
+ dsp.processStep1(&loopClauseOps);
+
+ mlir::omp::LoopNestOperands loopNestClauseOps;
+ llvm::SmallVector<const semantics::Symbol *> iv;
+ genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc,
+ loopNestClauseOps, iv);
+
+ EntryBlockArgs loopArgs;
+ loopArgs.priv.syms = dsp.getDelayedPrivSymbols();
+ loopArgs.priv.vars = loopClauseOps.privateVars;
+ loopArgs.reduction.syms = loopReductionSyms;
+ loopArgs.reduction.vars = loopClauseOps.reductionVars;
+
+ auto loopOp =
+ genWrapperOp<mlir::omp::LoopOp>(converter, loc, loopClauseOps, loopArgs);
+ genLoopNestOp(converter, symTable, semaCtx, eval, loc, queue, item,
+ loopNestClauseOps, iv, {{loopOp, loopArgs}},
+ llvm::omp::Directive::OMPD_loop, dsp);
+}
+
static void genStandaloneParallel(lower::AbstractConverter &converter,
lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
@@ -2459,7 +2505,7 @@ static void genOMPDispatch(lower::AbstractConverter &converter,
genStandaloneDo(converter, symTable, semaCtx, eval, loc, queue, item);
break;
case llvm::omp::Directive::OMPD_loop:
- TODO(loc, "Unhandled directive " + llvm::omp::getOpenMPDirectiveName(dir));
+ genLoopOp(converter, symTable, semaCtx, eval, loc, queue, item);
break;
case llvm::omp::Directive::OMPD_masked:
genMaskedOp(converter, symTable, semaCtx, eval, loc, queue, item);
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 5276e1ec1dcadd..e4a0192f20a105 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -428,6 +428,12 @@ TYPE_PARSER(construct<OmpLastprivateClause>(
pure(OmpLastprivateClause::LastprivateModifier::Conditional) / ":"),
Parser<OmpObjectList>{}))
+// OMP 5.2 11.7.1 BIND ( PARALLEL | TEAMS | THREAD )
+TYPE_PARSER(construct<OmpBindClause>(
+ "PARALLEL" >> pure(OmpBindClause::Type::Parallel) ||
+ "TEAMS" >> pure(OmpBindClause::Type::Teams) ||
+ "THREAD" >> pure(OmpBindClause::Type::Thread)))
+
TYPE_PARSER(
"ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) ||
"ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) ||
@@ -442,6 +448,8 @@ TYPE_PARSER(
"ATOMIC_DEFAULT_MEM_ORDER" >>
construct<OmpClause>(construct<OmpClause::AtomicDefaultMemOrder>(
parenthesized(Parser<OmpAtomicDefaultMemOrderClause>{}))) ||
+ "BIND" >> construct<OmpClause>(construct<OmpClause::Bind>(
+ parenthesized(Parser<OmpBindClause>{}))) ||
"COLLAPSE" >> construct<OmpClause>(construct<OmpClause::Collapse>(
parenthesized(scalarIntConstantExpr))) ||
"COPYIN" >> construct<OmpClause>(construct<OmpClause::Copyin>(
@@ -623,6 +631,7 @@ TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
"TEAMS DISTRIBUTE SIMD" >>
pure(llvm::omp::Directive::OMPD_teams_distribute_simd),
"TEAMS DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_teams_distribute),
+ "TEAMS LOOP" >> pure(llvm::omp::Directive::OMPD_teams_loop),
"TILE" >> pure(llvm::omp::Directive::OMPD_tile),
"UNROLL" >> pure(llvm::omp::Directive::OMPD_unroll)))))
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 8f3eb9fefee678..f6ad1b996c9433 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -369,13 +369,47 @@ void OmpStructureChecker::HasInvalidDistributeNesting(
"region."_err_en_US);
}
}
+void OmpStructureChecker::HasInvalidLoopBinding(
+ const parser::OpenMPLoopConstruct &x) {
+ const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
+ const auto &beginDir{std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
+
+ auto teamsBindingChecker = [&](parser::MessageFixedText msg) {
+ const auto &clauseList{std::get<parser::OmpClauseList>(beginLoopDir.t)};
+ for (const auto &clause : clauseList.v) {
+ if (const auto *bindClause{
+ std::get_if<parser::OmpClause::Bind>(&clause.u)}) {
+ if (bindClause->v.v != parser::OmpBindClause::Type::Teams) {
+ context_.Say(beginDir.source, msg);
+ }
+ }
+ }
+ };
+
+ if (llvm::omp::Directive::OMPD_loop == beginDir.v &&
+ CurrentDirectiveIsNested() &&
+ OmpDirectiveSet{llvm::omp::OMPD_teams, llvm::omp::OMPD_target_teams}.test(
+ GetContextParent().directive)) {
+ teamsBindingChecker(
+ "`BIND(TEAMS)` must be specified since the `LOOP` region is "
+ "strictly nested inside a `TEAMS` region."_err_en_US);
+ }
+
+ if (OmpDirectiveSet{
+ llvm::omp::OMPD_teams_loop, llvm::omp::OMPD_target_teams_loop}
+ .test(beginDir.v)) {
+ teamsBindingChecker(
+ "`BIND(TEAMS)` must be specified since the `LOOP` directive is "
+ "combined with a `TEAMS` construct."_err_en_US);
+ }
+}
void OmpStructureChecker::HasInvalidTeamsNesting(
const llvm::omp::Directive &dir, const parser::CharBlock &source) {
if (!llvm::omp::nestedTeamsAllowedSet.test(dir)) {
context_.Say(source,
- "Only `DISTRIBUTE` or `PARALLEL` regions are allowed to be strictly "
- "nested inside `TEAMS` region."_err_en_US);
+ "Only `DISTRIBUTE`, `PARALLEL`, or `LOOP` regions are allowed to be "
+ "strictly nested inside `TEAMS` region."_err_en_US);
}
}
@@ -538,6 +572,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
CheckLoopItrVariableIsInt(x);
CheckAssociatedLoopConstraints(x);
HasInvalidDistributeNesting(x);
+ HasInvalidLoopBinding(x);
if (CurrentDirectiveIsNested() &&
llvm::omp::topTeamsSet.test(GetContextParent().directive)) {
HasInvalidTeamsNesting(beginDir.v, beginDir.source);
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 237569bc40c483..b1f19c19bd2375 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -148,6 +148,7 @@ class OmpStructureChecker
void HasInvalidTeamsNesting(
const llvm::omp::Directive &dir, const parser::CharBlock &source);
void HasInvalidDistributeNesting(const parser::OpenMPLoopConstruct &x);
+ void HasInvalidLoopBinding(const parser::OpenMPLoopConstruct &x);
// specific clause related
bool ScheduleModifierHasType(const parser::OmpScheduleClause &,
const parser::OmpScheduleModifierType::ModType &);
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 5e3ad5f3b4773d..20f050c71a426b 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1663,6 +1663,7 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
case llvm::omp::Directive::OMPD_teams_distribute_parallel_do:
case llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd:
case llvm::omp::Directive::OMPD_teams_distribute_simd:
+ case llvm::omp::Directive::OMPD_teams_loop:
case llvm::omp::Directive::OMPD_tile:
case llvm::omp::Directive::OMPD_unroll:
PushContext(beginDir.source, beginDir.v);
diff --git a/flang/test/Lower/OpenMP/Todo/loop-directive.f90 b/flang/test/Lower/OpenMP/Todo/loop-directive.f90
deleted file mode 100644
index f1aea70458aa6c..00000000000000
--- a/flang/test/Lower/OpenMP/Todo/loop-directive.f90
+++ /dev/null
@@ -1,15 +0,0 @@
-! This test checks lowering of OpenMP loop Directive.
-
-! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
-! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
-
-! CHECK: not yet implemented: Unhandled directive loop
-subroutine test_loop()
- integer :: i, j = 1
- !$omp loop
- do i=1,10
- j = j + 1
- end do
- !$omp end loop
-end subroutine
-
diff --git a/flang/test/Lower/OpenMP/loop-directive.f90 b/flang/test/Lower/OpenMP/loop-directive.f90
new file mode 100644
index 00000000000000..59bf20c060f4ee
--- /dev/null
+++ b/flang/test/Lower/OpenMP/loop-directive.f90
@@ -0,0 +1,94 @@
+! This test checks lowering of OpenMP loop Directive.
+
+! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
+
+! CHECK: omp.declare_reduction @[[RED:add_reduction_i32]] : i32
+! CHECK: omp.private {type = private} @[[DUMMY_PRIV:.*test_privateEdummy_private.*]] : !fir.ref<i32>
+! CHECK: omp.private {type = private} @[[I_PRIV:.*test_no_clausesEi.*]] : !fir.ref<i32>
+
+! CHECK-LABEL: func.func @_QPtest_no_clauses
+subroutine test_no_clauses()
+ integer :: i, j, dummy = 1
+
+ ! CHECK: omp.loop private(@[[I_PRIV]] %{{.*}}#0 -> %[[ARG:.*]] : !fir.ref<i32>) {
+ ! CHECK: omp.loop_nest (%[[IV:.*]]) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} {
+ ! CHECK: %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]]
+ ! CHECK: fir.store %[[IV]] to %[[ARG_DECL]]#1 : !fir.ref<i32>
+ ! CHECK: }
+ ! CHECK: }
+ !$omp loop
+ do i=1,10
+ dummy = dummy + 1
+ end do
+ !$omp end loop
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtest_collapse
+subroutine test_collapse()
+ integer :: i, j, dummy = 1
+ ! CHECK: omp.loop private(@{{.*}} %{{.*}}#0 -> %{{.*}}, @{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
+ ! CHECK: omp.loop_nest (%{{.*}}, %{{.*}}) : i32 {{.*}} {
+ ! CHECK: }
+ ! CHECK: }
+ !$omp loop collapse(2)
+ do i=1,10
+ do j=2,20
+ dummy = dummy + 1
+ end do
+ end do
+ !$omp end loop
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtest_private
+subroutine test_private()
+ integer :: i, dummy = 1
+ ! CHECK: omp.loop private(@[[DUMMY_PRIV]] %{{.*}}#0 -> %{{.*}}, @{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
+ ! CHECK: omp.loop_nest (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} {
+ ! CHECK: }
+ ! CHECK: }
+ !$omp loop private(dummy)
+ do i=1,10
+ dummy = dummy + 1
+ end do
+ !$omp end loop
+end subroutine
+
+
+! CHECK-LABEL: func.func @_QPtest_order
+subroutine test_order()
+ integer :: i, dummy = 1
+ ! CHECK: omp.loop order(reproducible:concurrent) private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
+ ! CHECK: }
+ !$omp loop order(concurrent)
+ do i=1,10
+ dummy = dummy + 1
+ end do
+ !$omp end loop
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtest_reduction
+subroutine test_reduction()
+ integer :: i, dummy = 1
+
+ ! CHECK: omp.loop private(@{{.*}} %{{.*}}#0 -> %{{.*}} : !{{.*}}) reduction
+ ! CHECK-SAME: (@[[RED]] %{{.*}}#0 -> %{{.*}} : !{{.*}}) {
+ ! CHECK: }
+ !$omp loop reduction(+:dummy)
+ do i=1,10
+ dummy = dummy + 1
+ end do
+ !$omp end loop
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtest_bind
+subroutine test_bind()
+ integer :: i, dummy = 1
+ ! CHECK: omp.loop bind(thread) private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
+ ! CHECK: }
+ !$omp loop bind(thread)
+ do i=1,10
+ dummy = dummy + 1
+ end do
+ !$omp end loop
+end subroutine
diff --git a/flang/test/Parser/OpenMP/target-loop-unparse.f90 b/flang/test/Parser/OpenMP/target-loop-unparse.f90
index 3ee2fcef075a37..b2047070496527 100644
--- a/flang/test/Parser/OpenMP/target-loop-unparse.f90
+++ b/flang/test/Parser/OpenMP/target-loop-unparse.f90
@@ -1,6 +1,8 @@
+! RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=50 %s | \
+! RUN: FileCheck --ignore-case %s
-! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s
-! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s
+! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=50 %s | \
+! RUN: FileCheck --check-prefix="PARSE-TREE" %s
! Check for parsing of loop directive
@@ -14,6 +16,16 @@ subroutine test_loop
j = j + 1
end do
!$omp end loop
+
+ !PARSE-TREE: OmpBeginLoopDirective
+ !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = loop
+ !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Bind -> OmpBindClause -> Type = Thread
+ !CHECK: !$omp loop
+ !$omp loop bind(thread)
+ do i=1,10
+ j = j + 1
+ end do
+ !$omp end loop
end subroutine
subroutine test_target_loop
diff --git a/flang/test/Semantics/OpenMP/loop-bind.f90 b/flang/test/Semantics/OpenMP/loop-bind.f90
new file mode 100644
index 00000000000000..f3aa9d19fe989e
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/loop-bind.f90
@@ -0,0 +1,33 @@
+! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50
+
+! OpenMP Version 5.0
+! Check OpenMP construct validity for the following directives:
+! 11.7 Loop directive
+
+program main
+ integer :: i, x
+
+ !$omp teams
+ !ERROR: `BIND(TEAMS)` must be specified since the `LOOP` region is strictly nested inside a `TEAMS` region.
+ !$omp loop bind(thread)
+ do i = 1, 10
+ x = x + 1
+ end do
+ !$omp end loop
+ !$omp end teams
+
+ !ERROR: `BIND(TEAMS)` must be specified since the `LOOP` directive is combined with a `TEAMS` construct.
+ !$omp target teams loop bind(thread)
+ do i = 1, 10
+ x = x + 1
+ end do
+ !$omp end target teams loop
+
+ !ERROR: `BIND(TEAMS)` must be specified since the `LOOP` directive is combined with a `TEAMS` construct.
+ !$omp teams loo...
[truncated]
|
ecbfdcd
to
8c7e397
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
d7a0e0a
to
7056680
Compare
7056680
to
d4f18a6
Compare
Extends MLIR lowering support for the `loop` directive by adding lowering support for the `bind` clause.
d4f18a6
to
9d7d0a5
Compare
Extends MLIR lowering support for the
loop
directive by addinglowering support for the
bind
clause.Parent PR: #114199, only the latest commit is relevant to this PR.