diff --git a/flang/docs/Directives.md b/flang/docs/Directives.md index 5e76d4331f6de..91c27cb510ea0 100644 --- a/flang/docs/Directives.md +++ b/flang/docs/Directives.md @@ -50,6 +50,9 @@ A list of non-standard directives supported by Flang integer that specifying the unrolling factor. When `N` is `0` or `1`, the loop should not be unrolled at all. If `N` is omitted the optimizer will selects the number of times to unroll the loop. +* `!dir$ novector` disabling vectorization on the following loop. +* `!dir$ nounroll` disabling unrolling on the following loop. +* `!dir$ nounroll_and_jam` disabling unrolling and jamming on the following loop. # Directive Details diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 9bff2dab974ec..b49fc2f0729e4 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -210,6 +210,9 @@ class ParseTreeDumper { NODE(CompilerDirective, VectorAlways) NODE(CompilerDirective, Unroll) NODE(CompilerDirective, UnrollAndJam) + NODE(CompilerDirective, NoVector) + NODE(CompilerDirective, NoUnroll) + NODE(CompilerDirective, NoUnrollAndJam) NODE(parser, ComplexLiteralConstant) NODE(parser, ComplexPart) NODE(parser, ComponentArraySpec) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 029c3de354b66..551ccc4938311 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3351,6 +3351,9 @@ struct StmtFunctionStmt { // !DIR$ name[=value] [, name[=value]]... = can be : // !DIR$ UNROLL [N] // !DIR$ UNROLL_AND_JAM [N] +// !DIR$ NOVECTOR +// !DIR$ NOUNROLL +// !DIR$ NOUNROLL_AND_JAM // !DIR$ struct CompilerDirective { UNION_CLASS_BOILERPLATE(CompilerDirective); @@ -3376,10 +3379,14 @@ struct CompilerDirective { struct UnrollAndJam { WRAPPER_CLASS_BOILERPLATE(UnrollAndJam, std::optional); }; + EMPTY_CLASS(NoVector); + EMPTY_CLASS(NoUnroll); + EMPTY_CLASS(NoUnrollAndJam); EMPTY_CLASS(Unrecognized); CharBlock source; std::variant, LoopCount, std::list, - VectorAlways, std::list, Unroll, UnrollAndJam, Unrecognized> + VectorAlways, std::list, Unroll, UnrollAndJam, Unrecognized, + NoVector, NoUnroll, NoUnrollAndJam> u; }; diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 6e6e88a32517c..7b286612a98c5 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -2261,6 +2261,23 @@ class FirConverter : public Fortran::lower::AbstractConverter { uja = genLoopUnrollAndJamAttr(u.v); has_attrs = true; }, + [&](const Fortran::parser::CompilerDirective::NoVector &u) { + mlir::BoolAttr trueAttr = + mlir::BoolAttr::get(builder->getContext(), true); + va = mlir::LLVM::LoopVectorizeAttr::get(builder->getContext(), + /*disable=*/trueAttr, + {}, {}, {}, {}, {}, {}); + has_attrs = true; + }, + [&](const Fortran::parser::CompilerDirective::NoUnroll &u) { + ua = genLoopUnrollAttr(/*unrollingFactor=*/0); + has_attrs = true; + }, + [&](const Fortran::parser::CompilerDirective::NoUnrollAndJam &u) { + uja = genLoopUnrollAndJamAttr(/*unrollingFactor=*/0); + has_attrs = true; + }, + [&](const auto &) {}}, dir->u); } @@ -2925,6 +2942,15 @@ class FirConverter : public Fortran::lower::AbstractConverter { [&](const Fortran::parser::CompilerDirective::UnrollAndJam &) { attachDirectiveToLoop(dir, &eval); }, + [&](const Fortran::parser::CompilerDirective::NoVector &) { + attachDirectiveToLoop(dir, &eval); + }, + [&](const Fortran::parser::CompilerDirective::NoUnroll &) { + attachDirectiveToLoop(dir, &eval); + }, + [&](const Fortran::parser::CompilerDirective::NoUnrollAndJam &) { + attachDirectiveToLoop(dir, &eval); + }, [&](const auto &) {}}, dir.u); } diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp index cfe9ecb29b0b7..fbe629ab52935 100644 --- a/flang/lib/Parser/Fortran-parsers.cpp +++ b/flang/lib/Parser/Fortran-parsers.cpp @@ -1310,6 +1310,10 @@ constexpr auto unroll{ "UNROLL" >> construct(maybe(digitString64))}; constexpr auto unrollAndJam{"UNROLL_AND_JAM" >> construct(maybe(digitString64))}; +constexpr auto novector{"NOVECTOR" >> construct()}; +constexpr auto nounroll{"NOUNROLL" >> construct()}; +constexpr auto nounrollAndJam{ + "NOUNROLL_AND_JAM" >> construct()}; TYPE_PARSER(beginDirective >> "DIR$ "_tok >> sourced((construct(ignore_tkr) || construct(loopCount) || @@ -1317,6 +1321,9 @@ TYPE_PARSER(beginDirective >> "DIR$ "_tok >> construct(vectorAlways) || construct(unrollAndJam) || construct(unroll) || + construct(novector) || + construct(nounrollAndJam) || + construct(nounroll) || construct( many(construct( name, maybe(("="_tok || ":"_tok) >> digitString64))))) / diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 8cdbf8ed2a672..85ecf79147376 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -1855,6 +1855,15 @@ class UnparseVisitor { Word("!DIR$ UNROLL_AND_JAM"); Walk(" ", unrollAndJam.v); }, + [&](const CompilerDirective::NoVector &) { + Word("!DIR$ NOVECTOR"); + }, + [&](const CompilerDirective::NoUnroll &) { + Word("!DIR$ NOUNROLL"); + }, + [&](const CompilerDirective::NoUnrollAndJam &) { + Word("!DIR$ NOUNROLL_AND_JAM"); + }, [&](const CompilerDirective::Unrecognized &) { Word("!DIR$ "); Word(x.source.ToString()); diff --git a/flang/lib/Semantics/canonicalize-directives.cpp b/flang/lib/Semantics/canonicalize-directives.cpp index 1a0a0d145b3e2..104df253ab642 100644 --- a/flang/lib/Semantics/canonicalize-directives.cpp +++ b/flang/lib/Semantics/canonicalize-directives.cpp @@ -57,7 +57,10 @@ static bool IsExecutionDirective(const parser::CompilerDirective &dir) { return std::holds_alternative( dir.u) || std::holds_alternative(dir.u) || - std::holds_alternative(dir.u); + std::holds_alternative(dir.u) || + std::holds_alternative(dir.u) || + std::holds_alternative(dir.u) || + std::holds_alternative(dir.u); } void CanonicalizationOfDirectives::Post(parser::SpecificationPart &spec) { @@ -119,6 +122,15 @@ void CanonicalizationOfDirectives::Post(parser::Block &block) { [&](parser::CompilerDirective::UnrollAndJam &) { CheckLoopDirective(*dir, block, it); }, + [&](parser::CompilerDirective::NoVector &) { + CheckLoopDirective(*dir, block, it); + }, + [&](parser::CompilerDirective::NoUnroll &) { + CheckLoopDirective(*dir, block, it); + }, + [&](parser::CompilerDirective::NoUnrollAndJam &) { + CheckLoopDirective(*dir, block, it); + }, [&](auto &) {}}, dir->u); } diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 8ba476ec547fc..11c0ecc9e8410 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -9573,7 +9573,10 @@ void ResolveNamesVisitor::Post(const parser::AssignedGotoStmt &x) { void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) { if (std::holds_alternative(x.u) || std::holds_alternative(x.u) || - std::holds_alternative(x.u)) { + std::holds_alternative(x.u) || + std::holds_alternative(x.u) || + std::holds_alternative(x.u) || + std::holds_alternative(x.u)) { return; } if (const auto *tkr{ diff --git a/flang/test/Integration/unroll_and_jam.f90 b/flang/test/Integration/unroll_and_jam.f90 index 771b7fb411855..b9c16d34ac90a 100644 --- a/flang/test/Integration/unroll_and_jam.f90 +++ b/flang/test/Integration/unroll_and_jam.f90 @@ -30,6 +30,16 @@ subroutine unroll_and_jam_dir_1 end do end subroutine unroll_and_jam_dir_1 +! CHECK-LABEL: nounroll_and_jam_dir +subroutine nounroll_and_jam_dir + integer :: a(10) + !dir$ nounroll_and_jam + ! CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[ANNOTATION_DISABLE]] + do i=1,10 + a(i)=i + end do +end subroutine nounroll_and_jam_dir + ! CHECK-LABEL: unroll_and_jam_dir_no_factor subroutine unroll_and_jam_dir_no_factor integer :: a(10) diff --git a/flang/test/Integration/vector-always.f90 b/flang/test/Integration/vector-always.f90 index 7216698f901c1..ee2aa8ab485e0 100644 --- a/flang/test/Integration/vector-always.f90 +++ b/flang/test/Integration/vector-always.f90 @@ -10,5 +10,17 @@ subroutine vector_always end do end subroutine vector_always +! CHECK-LABEL: no_vector +subroutine no_vector + integer :: a(10) + !dir$ novector + ! CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[ANNOTATION2:.*]] + do i=1,10 + a(i)=i + end do +end subroutine no_vector + ! CHECK: ![[ANNOTATION]] = distinct !{![[ANNOTATION]], ![[VECTORIZE:.*]]} ! CHECK: ![[VECTORIZE]] = !{!"llvm.loop.vectorize.enable", i1 true} +! CHECK: ![[ANNOTATION2]] = distinct !{![[ANNOTATION2]], ![[VECTORIZE2:.*]]} +! CHECK: ![[VECTORIZE2]] = !{!"llvm.loop.vectorize.enable", i1 false} diff --git a/flang/test/Lower/unroll_and_jam.f90 b/flang/test/Lower/unroll_and_jam.f90 index afc5a7b6b271e..a9f6e1dcd22aa 100644 --- a/flang/test/Lower/unroll_and_jam.f90 +++ b/flang/test/Lower/unroll_and_jam.f90 @@ -2,8 +2,10 @@ ! CHECK: #loop_unroll_and_jam = #llvm.loop_unroll_and_jam ! CHECK: #loop_unroll_and_jam1 = #llvm.loop_unroll_and_jam +! CHECK: #loop_unroll_and_jam2 = #llvm.loop_unroll_and_jam ! CHECK: #loop_annotation = #llvm.loop_annotation ! CHECK: #loop_annotation1 = #llvm.loop_annotation +! CHECK: #loop_annotation2 = #llvm.loop_annotation ! CHECK-LABEL: unroll_and_jam_dir subroutine unroll_and_jam_dir @@ -32,3 +34,14 @@ subroutine intermediate_directive a(i)=i end do end subroutine intermediate_directive + + +! CHECK-LABEL: nounroll_and_jam_dir +subroutine nounroll_and_jam_dir + integer :: a(10) + !dir$ nounroll_and_jam + !CHECK: fir.do_loop {{.*}} attributes {loopAnnotation = #loop_annotation2} + do i=1,10 + a(i)=i + end do +end subroutine nounroll_and_jam_dir diff --git a/flang/test/Lower/vector-always.f90 b/flang/test/Lower/vector-always.f90 index 1822fc33dfdb8..75753de4d686f 100644 --- a/flang/test/Lower/vector-always.f90 +++ b/flang/test/Lower/vector-always.f90 @@ -1,7 +1,9 @@ ! RUN: %flang_fc1 -emit-hlfir -o - %s | FileCheck %s ! CHECK: #loop_vectorize = #llvm.loop_vectorize +! CHECK: #loop_vectorize1 = #llvm.loop_vectorize ! CHECK: #loop_annotation = #llvm.loop_annotation +! CHECK: #loop_annotation1 = #llvm.loop_annotation ! CHECK-LABEL: vector_always subroutine vector_always @@ -24,3 +26,14 @@ subroutine intermediate_directive a(i)=i end do end subroutine intermediate_directive + + +! CHECK-LABEL: no_vector +subroutine no_vector + integer :: a(10) + !dir$ novector + !CHECK: fir.do_loop {{.*}} attributes {loopAnnotation = #loop_annotation1} + do i=1,10 + a(i)=i + end do +end subroutine no_vector diff --git a/flang/test/Parser/compiler-directives.f90 b/flang/test/Parser/compiler-directives.f90 index d1e386a01dd4d..04d22ff0fd8ee 100644 --- a/flang/test/Parser/compiler-directives.f90 +++ b/flang/test/Parser/compiler-directives.f90 @@ -45,6 +45,10 @@ subroutine unroll ! CHECK: !DIR$ UNROLL 2 do i=1,10 enddo + !dir$ nounroll + ! CHECK: !DIR$ NOUNROLL + do i=1,10 + enddo end subroutine subroutine unroll_and_jam @@ -56,4 +60,15 @@ subroutine unroll_and_jam ! CHECK: !DIR$ UNROLL_AND_JAM 2 do i=1,10 enddo + !dir$ nounroll_and_jam + ! CHECK: !DIR$ NOUNROLL_AND_JAM + do i=1,10 + enddo +end subroutine + +subroutine no_vector + !dir$ novector + ! CHECK: !DIR$ NOVECTOR + do i=1,10 + enddo end subroutine