[flang-commits] [flang] c309abd - [flang] Implement !DIR$ NOVECTOR and !DIR$ NOUNROLL[_AND_JAM] (#133885)

via flang-commits flang-commits at lists.llvm.org
Wed Apr 2 05:30:05 PDT 2025


Author: Jean-Didier PAILLEUX
Date: 2025-04-02T14:30:01+02:00
New Revision: c309abd92553191c404f2dc13f637bcfd53033f9

URL: https://github.com/llvm/llvm-project/commit/c309abd92553191c404f2dc13f637bcfd53033f9
DIFF: https://github.com/llvm/llvm-project/commit/c309abd92553191c404f2dc13f637bcfd53033f9.diff

LOG: [flang] Implement !DIR$ NOVECTOR and !DIR$ NOUNROLL[_AND_JAM] (#133885)

Hi,
This patch implements support for the following directives :
- `!DIR$ NOUNROLL_AND_JAM` to disable unrolling and jamming on a DO
LOOP.
- `!DIR$ NOUNROLL` to disable unrolling on a DO LOOP.
- `!DIR$ NOVECTOR` to disable vectorization on a DO LOOP.

Added: 
    

Modified: 
    flang/docs/Directives.md
    flang/include/flang/Parser/dump-parse-tree.h
    flang/include/flang/Parser/parse-tree.h
    flang/lib/Lower/Bridge.cpp
    flang/lib/Parser/Fortran-parsers.cpp
    flang/lib/Parser/unparse.cpp
    flang/lib/Semantics/canonicalize-directives.cpp
    flang/lib/Semantics/resolve-names.cpp
    flang/test/Integration/unroll_and_jam.f90
    flang/test/Integration/vector-always.f90
    flang/test/Lower/unroll_and_jam.f90
    flang/test/Lower/vector-always.f90
    flang/test/Parser/compiler-directives.f90

Removed: 
    


################################################################################
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 41ad15794ad15..c66f0735f33f0 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 b026c26dc08cd..eeb438991feee 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$ <anything else>
 struct CompilerDirective {
   UNION_CLASS_BOILERPLATE(CompilerDirective);
@@ -3376,10 +3379,14 @@ struct CompilerDirective {
   struct UnrollAndJam {
     WRAPPER_CLASS_BOILERPLATE(UnrollAndJam, std::optional<std::uint64_t>);
   };
+  EMPTY_CLASS(NoVector);
+  EMPTY_CLASS(NoUnroll);
+  EMPTY_CLASS(NoUnrollAndJam);
   EMPTY_CLASS(Unrecognized);
   CharBlock source;
   std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>,
-      VectorAlways, std::list<NameValue>, Unroll, UnrollAndJam, Unrecognized>
+      VectorAlways, std::list<NameValue>, Unroll, UnrollAndJam, Unrecognized,
+      NoVector, NoUnroll, NoUnrollAndJam>
       u;
 };
 

diff  --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 178f3e066fb2b..65edf1cea8761 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -2268,6 +2268,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);
     }
@@ -2932,6 +2949,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<CompilerDirective::Unroll>(maybe(digitString64))};
 constexpr auto unrollAndJam{"UNROLL_AND_JAM" >>
     construct<CompilerDirective::UnrollAndJam>(maybe(digitString64))};
+constexpr auto novector{"NOVECTOR" >> construct<CompilerDirective::NoVector>()};
+constexpr auto nounroll{"NOUNROLL" >> construct<CompilerDirective::NoUnroll>()};
+constexpr auto nounrollAndJam{
+    "NOUNROLL_AND_JAM" >> construct<CompilerDirective::NoUnrollAndJam>()};
 TYPE_PARSER(beginDirective >> "DIR$ "_tok >>
     sourced((construct<CompilerDirective>(ignore_tkr) ||
                 construct<CompilerDirective>(loopCount) ||
@@ -1317,6 +1321,9 @@ TYPE_PARSER(beginDirective >> "DIR$ "_tok >>
                 construct<CompilerDirective>(vectorAlways) ||
                 construct<CompilerDirective>(unrollAndJam) ||
                 construct<CompilerDirective>(unroll) ||
+                construct<CompilerDirective>(novector) ||
+                construct<CompilerDirective>(nounrollAndJam) ||
+                construct<CompilerDirective>(nounroll) ||
                 construct<CompilerDirective>(
                     many(construct<CompilerDirective::NameValue>(
                         name, maybe(("="_tok || ":"_tok) >> digitString64))))) /

diff  --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 85c633802e412..47dae0ae753d2 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<parser::CompilerDirective::VectorAlways>(
              dir.u) ||
       std::holds_alternative<parser::CompilerDirective::Unroll>(dir.u) ||
-      std::holds_alternative<parser::CompilerDirective::UnrollAndJam>(dir.u);
+      std::holds_alternative<parser::CompilerDirective::UnrollAndJam>(dir.u) ||
+      std::holds_alternative<parser::CompilerDirective::NoVector>(dir.u) ||
+      std::holds_alternative<parser::CompilerDirective::NoUnroll>(dir.u) ||
+      std::holds_alternative<parser::CompilerDirective::NoUnrollAndJam>(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<parser::CompilerDirective::VectorAlways>(x.u) ||
       std::holds_alternative<parser::CompilerDirective::Unroll>(x.u) ||
-      std::holds_alternative<parser::CompilerDirective::UnrollAndJam>(x.u)) {
+      std::holds_alternative<parser::CompilerDirective::UnrollAndJam>(x.u) ||
+      std::holds_alternative<parser::CompilerDirective::NoVector>(x.u) ||
+      std::holds_alternative<parser::CompilerDirective::NoUnroll>(x.u) ||
+      std::holds_alternative<parser::CompilerDirective::NoUnrollAndJam>(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<disable = false>
 ! CHECK: #loop_unroll_and_jam1 = #llvm.loop_unroll_and_jam<disable = false, count = 2 : i64>
+! CHECK: #loop_unroll_and_jam2 = #llvm.loop_unroll_and_jam<disable = true>
 ! CHECK: #loop_annotation = #llvm.loop_annotation<unrollAndJam = #loop_unroll_and_jam>
 ! CHECK: #loop_annotation1 = #llvm.loop_annotation<unrollAndJam = #loop_unroll_and_jam1>
+! CHECK: #loop_annotation2 = #llvm.loop_annotation<unrollAndJam = #loop_unroll_and_jam2>
 
 ! 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<disable = false>
+! CHECK: #loop_vectorize1 = #llvm.loop_vectorize<disable = true>
 ! CHECK: #loop_annotation = #llvm.loop_annotation<vectorize = #loop_vectorize>
+! CHECK: #loop_annotation1 = #llvm.loop_annotation<vectorize = #loop_vectorize1>
 
 ! 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


        


More information about the flang-commits mailing list