[Mlir-commits] [flang] [mlir] [flang] Implement !DIR$ IVDEP directive (PR #133728)
Jean-Didier PAILLEUX
llvmlistbot at llvm.org
Fri Sep 26 02:12:15 PDT 2025
https://github.com/JDPailleux updated https://github.com/llvm/llvm-project/pull/133728
>From f9cdd2208e15e9c349b5de5173426731d3abf071 Mon Sep 17 00:00:00 2001
From: Jean-Didier Pailleux <jean-didier.pailleux at sipearl.com>
Date: Fri, 26 Sep 2025 10:05:53 +0200
Subject: [PATCH 1/2] [mlir][LLVMIR] Adding `ivdepEnable` parameter in
LoopVectorizeAttr
`loop.vectorize.ivdep.enable` metadata has been added to LLVM to
ignoring vector dependencies. Adding this parameter to LoopVectorizeAttr
will allow Flang to use this metadata with the `!DIR$ IVDEP` directive.
---
.../mlir/Dialect/LLVMIR/LLVMAttrDefs.td | 17 ++++++++---------
.../Target/LLVMIR/LoopAnnotationImporter.cpp | 8 +++++---
.../LLVMIR/LoopAnnotationTranslation.cpp | 1 +
.../Target/LLVMIR/Import/metadata-loop.ll | 19 ++++++++++---------
mlir/test/Target/LLVMIR/loop-metadata.mlir | 5 +++--
5 files changed, 27 insertions(+), 23 deletions(-)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 75bce6b0a0e54..965f273ab53d4 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -106,15 +106,14 @@ def LoopVectorizeAttr : LLVM_Attr<"LoopVectorize", "loop_vectorize"> {
the "!llvm.loop.vectorize" metadata.
}];
- let parameters = (ins
- OptionalParameter<"BoolAttr">:$disable,
- OptionalParameter<"BoolAttr">:$predicateEnable,
- OptionalParameter<"BoolAttr">:$scalableEnable,
- OptionalParameter<"IntegerAttr">:$width,
- OptionalParameter<"LoopAnnotationAttr">:$followupVectorized,
- OptionalParameter<"LoopAnnotationAttr">:$followupEpilogue,
- OptionalParameter<"LoopAnnotationAttr">:$followupAll
- );
+ let parameters = (ins OptionalParameter<"BoolAttr">:$disable,
+ OptionalParameter<"BoolAttr">:$predicateEnable,
+ OptionalParameter<"BoolAttr">:$scalableEnable,
+ OptionalParameter<"BoolAttr">:$ivdepEnable,
+ OptionalParameter<"IntegerAttr">:$width,
+ OptionalParameter<"LoopAnnotationAttr">:$followupVectorized,
+ OptionalParameter<"LoopAnnotationAttr">:$followupEpilogue,
+ OptionalParameter<"LoopAnnotationAttr">:$followupAll);
let assemblyFormat = "`<` struct(params) `>`";
diff --git a/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp b/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp
index e4905423347a2..9354d2112db72 100644
--- a/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp
@@ -291,6 +291,8 @@ FailureOr<LoopVectorizeAttr> LoopMetadataConversion::convertVectorizeAttr() {
lookupBoolNode("llvm.loop.vectorize.predicate.enable");
FailureOr<BoolAttr> scalableEnable =
lookupBoolNode("llvm.loop.vectorize.scalable.enable");
+ FailureOr<BoolAttr> ivdepEnable =
+ lookupBoolNode("llvm.loop.vectorize.ivdep.enable");
FailureOr<IntegerAttr> width = lookupIntNode("llvm.loop.vectorize.width");
FailureOr<LoopAnnotationAttr> followupVec =
lookupFollowupNode("llvm.loop.vectorize.followup_vectorized");
@@ -299,9 +301,9 @@ FailureOr<LoopVectorizeAttr> LoopMetadataConversion::convertVectorizeAttr() {
FailureOr<LoopAnnotationAttr> followupAll =
lookupFollowupNode("llvm.loop.vectorize.followup_all");
- return createIfNonNull<LoopVectorizeAttr>(ctx, enable, predicateEnable,
- scalableEnable, width, followupVec,
- followupEpi, followupAll);
+ return createIfNonNull<LoopVectorizeAttr>(
+ ctx, enable, predicateEnable, scalableEnable, ivdepEnable, width,
+ followupVec, followupEpi, followupAll);
}
FailureOr<LoopInterleaveAttr> LoopMetadataConversion::convertInterleaveAttr() {
diff --git a/mlir/lib/Target/LLVMIR/LoopAnnotationTranslation.cpp b/mlir/lib/Target/LLVMIR/LoopAnnotationTranslation.cpp
index f3ec18c9074e4..cd892404f113e 100644
--- a/mlir/lib/Target/LLVMIR/LoopAnnotationTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/LoopAnnotationTranslation.cpp
@@ -108,6 +108,7 @@ void LoopAnnotationConversion::convertLoopOptions(LoopVectorizeAttr options) {
options.getPredicateEnable());
convertBoolNode("llvm.loop.vectorize.scalable.enable",
options.getScalableEnable());
+ convertBoolNode("llvm.loop.vectorize.ivdep.enable", options.getIvdepEnable());
convertI32Node("llvm.loop.vectorize.width", options.getWidth());
convertFollowupNode("llvm.loop.vectorize.followup_vectorized",
options.getFollowupVectorized());
diff --git a/mlir/test/Target/LLVMIR/Import/metadata-loop.ll b/mlir/test/Target/LLVMIR/Import/metadata-loop.ll
index 20431a7412bd1..b4fc36727bc84 100644
--- a/mlir/test/Target/LLVMIR/Import/metadata-loop.ll
+++ b/mlir/test/Target/LLVMIR/Import/metadata-loop.ll
@@ -73,7 +73,7 @@ end:
; // -----
; CHECK-DAG: #[[FOLLOWUP:.*]] = #llvm.loop_annotation<disableNonforced = true>
-; CHECK-DAG: #[[VECTORIZE_ATTR:.*]] = #llvm.loop_vectorize<disable = false, predicateEnable = true, scalableEnable = false, width = 16 : i32, followupVectorized = #[[FOLLOWUP]], followupEpilogue = #[[FOLLOWUP]], followupAll = #[[FOLLOWUP]]>
+; CHECK-DAG: #[[VECTORIZE_ATTR:.*]] = #llvm.loop_vectorize<disable = false, predicateEnable = true, scalableEnable = false, ivdepEnable = false, width = 16 : i32, followupVectorized = #[[FOLLOWUP]], followupEpilogue = #[[FOLLOWUP]], followupAll = #[[FOLLOWUP]]>
; CHECK-DAG: #[[$ANNOT_ATTR:.*]] = #llvm.loop_annotation<vectorize = #[[VECTORIZE_ATTR]]>
; CHECK-LABEL: @vectorize
@@ -85,17 +85,18 @@ end:
ret void
}
-!1 = distinct !{!1, !2, !3, !4, !5, !6, !7, !8}
+!1 = distinct !{!1, !2, !3, !4, !5, !6, !7, !8, !9}
!2 = !{!"llvm.loop.vectorize.enable", i1 1}
!3 = !{!"llvm.loop.vectorize.predicate.enable", i1 1}
!4 = !{!"llvm.loop.vectorize.scalable.enable", i1 0}
-!5 = !{!"llvm.loop.vectorize.width", i32 16}
-!6 = !{!"llvm.loop.vectorize.followup_vectorized", !9}
-!7 = !{!"llvm.loop.vectorize.followup_epilogue", !9}
-!8 = !{!"llvm.loop.vectorize.followup_all", !9}
-
-!9 = distinct !{!9, !10}
-!10 = !{!"llvm.loop.disable_nonforced"}
+!5 = !{!"llvm.loop.vectorize.ivdep.enable", i1 0}
+!6 = !{!"llvm.loop.vectorize.width", i32 16}
+!7 = !{!"llvm.loop.vectorize.followup_vectorized", !10}
+!8 = !{!"llvm.loop.vectorize.followup_epilogue", !10}
+!9 = !{!"llvm.loop.vectorize.followup_all", !10}
+
+!10 = distinct !{!10, !11}
+!11 = !{!"llvm.loop.disable_nonforced"}
; // -----
diff --git a/mlir/test/Target/LLVMIR/loop-metadata.mlir b/mlir/test/Target/LLVMIR/loop-metadata.mlir
index 2fe4a994aeb66..fa8d522b742dc 100644
--- a/mlir/test/Target/LLVMIR/loop-metadata.mlir
+++ b/mlir/test/Target/LLVMIR/loop-metadata.mlir
@@ -45,7 +45,7 @@ llvm.func @isvectorized() {
llvm.func @vectorizeOptions() {
// CHECK: br {{.*}} !llvm.loop ![[LOOP_NODE:[0-9]+]]
llvm.br ^bb1 {loop_annotation = #llvm.loop_annotation<vectorize = <
- disable = false, predicateEnable = true, scalableEnable = false, width = 16 : i32,
+ disable = false, predicateEnable = true, scalableEnable = false, ivdepEnable = false, width = 16 : i32,
followupVectorized = #followup, followupEpilogue = #followup, followupAll = #followup>
>}
^bb1:
@@ -54,10 +54,11 @@ llvm.func @vectorizeOptions() {
// CHECK-DAG: ![[NON_FORCED:[0-9]+]] = !{!"llvm.loop.disable_nonforced"}
// CHECK-DAG: ![[FOLLOWUP:[0-9]+]] = distinct !{![[FOLLOWUP]], ![[NON_FORCED]]}
-// CHECK-DAG: ![[LOOP_NODE]] = distinct !{![[LOOP_NODE]], !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
+// CHECK-DAG: ![[LOOP_NODE]] = distinct !{![[LOOP_NODE]], !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.vectorize.enable", i1 true}
// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.vectorize.predicate.enable", i1 true}
// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.vectorize.scalable.enable", i1 false}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.vectorize.ivdep.enable", i1 false}
// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.vectorize.width", i32 16}
// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.vectorize.followup_vectorized", ![[FOLLOWUP]]}
// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.vectorize.followup_epilogue", ![[FOLLOWUP]]}
>From 002922906284fa624f35a9f080ab54f01539c46c Mon Sep 17 00:00:00 2001
From: Jean-Didier Pailleux <jean-didier.pailleux at sipearl.com>
Date: Fri, 26 Sep 2025 10:37:43 +0200
Subject: [PATCH 2/2] [flang] Implement !DIR$ IVDEP directive
---
flang/include/flang/Parser/dump-parse-tree.h | 1 +
flang/include/flang/Parser/parse-tree.h | 4 +-
flang/lib/Lower/Bridge.cpp | 37 ++++++++++++++-----
flang/lib/Optimizer/Builder/HLFIRTools.cpp | 2 +-
flang/lib/Parser/Fortran-parsers.cpp | 3 ++
flang/lib/Parser/unparse.cpp | 1 +
.../lib/Semantics/canonicalize-directives.cpp | 7 +++-
flang/lib/Semantics/resolve-names.cpp | 3 +-
flang/test/Integration/ivdep.f90 | 16 ++++++++
flang/test/Lower/ivdep.f90 | 26 +++++++++++++
flang/test/Parser/compiler-directives.f90 | 7 ++++
11 files changed, 93 insertions(+), 14 deletions(-)
create mode 100644 flang/test/Integration/ivdep.f90
create mode 100644 flang/test/Lower/ivdep.f90
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index b2341226c7688..47f62c6129662 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -206,6 +206,7 @@ class ParseTreeDumper {
NODE(parser, CompilerDirective)
NODE(CompilerDirective, AssumeAligned)
NODE(CompilerDirective, IgnoreTKR)
+ NODE(CompilerDirective, IVDep)
NODE(CompilerDirective, LoopCount)
NODE(CompilerDirective, NameValue)
NODE(CompilerDirective, Unrecognized)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 39dbeb5e7cfbe..4e136a29efee9 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3354,6 +3354,7 @@ struct StmtFunctionStmt {
// !DIR$ NOVECTOR
// !DIR$ NOUNROLL
// !DIR$ NOUNROLL_AND_JAM
+// !DIR$ IVDEP
// !DIR$ <anything else>
struct CompilerDirective {
UNION_CLASS_BOILERPLATE(CompilerDirective);
@@ -3382,11 +3383,12 @@ struct CompilerDirective {
EMPTY_CLASS(NoVector);
EMPTY_CLASS(NoUnroll);
EMPTY_CLASS(NoUnrollAndJam);
+ EMPTY_CLASS(IVDep);
EMPTY_CLASS(Unrecognized);
CharBlock source;
std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>,
VectorAlways, std::list<NameValue>, Unroll, UnrollAndJam, Unrecognized,
- NoVector, NoUnroll, NoUnrollAndJam>
+ NoVector, NoUnroll, NoUnrollAndJam, IVDep>
u;
};
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 4a5b9885bb7c4..70c56758e025d 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -2428,22 +2428,33 @@ class FirConverter : public Fortran::lower::AbstractConverter {
{}, {}, {}, {});
}
+ // Enabling loop vectorization attribute.
+ mlir::LLVM::LoopVectorizeAttr
+ genLoopVectorizeAttr(mlir::BoolAttr disableAttr,
+ mlir::BoolAttr ivdepEnableAttr) {
+ mlir::LLVM::LoopVectorizeAttr va;
+ if (disableAttr || ivdepEnableAttr)
+ va = mlir::LLVM::LoopVectorizeAttr::get(builder->getContext(),
+ /*disable=*/disableAttr, {}, {},
+ /*ivdepEnable*/ ivdepEnableAttr,
+ {}, {}, {}, {});
+ return va;
+ }
+
void addLoopAnnotationAttr(
IncrementLoopInfo &info,
llvm::SmallVectorImpl<const Fortran::parser::CompilerDirective *> &dirs) {
- mlir::LLVM::LoopVectorizeAttr va;
+ mlir::BoolAttr disableVecAttr, ivdepEnableAttr;
mlir::LLVM::LoopUnrollAttr ua;
mlir::LLVM::LoopUnrollAndJamAttr uja;
+ llvm::SmallVector<mlir::LLVM::AccessGroupAttr> aga;
bool has_attrs = false;
for (const auto *dir : dirs) {
Fortran::common::visit(
Fortran::common::visitors{
[&](const Fortran::parser::CompilerDirective::VectorAlways &) {
- mlir::BoolAttr falseAttr =
+ disableVecAttr =
mlir::BoolAttr::get(builder->getContext(), false);
- va = mlir::LLVM::LoopVectorizeAttr::get(builder->getContext(),
- /*disable=*/falseAttr,
- {}, {}, {}, {}, {}, {});
has_attrs = true;
},
[&](const Fortran::parser::CompilerDirective::Unroll &u) {
@@ -2455,11 +2466,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
has_attrs = true;
},
[&](const Fortran::parser::CompilerDirective::NoVector &u) {
- mlir::BoolAttr trueAttr =
+ disableVecAttr =
mlir::BoolAttr::get(builder->getContext(), true);
- va = mlir::LLVM::LoopVectorizeAttr::get(builder->getContext(),
- /*disable=*/trueAttr,
- {}, {}, {}, {}, {}, {});
has_attrs = true;
},
[&](const Fortran::parser::CompilerDirective::NoUnroll &u) {
@@ -2470,10 +2478,16 @@ class FirConverter : public Fortran::lower::AbstractConverter {
uja = genLoopUnrollAndJamAttr(/*unrollingFactor=*/0);
has_attrs = true;
},
-
+ [&](const Fortran::parser::CompilerDirective::IVDep &iv) {
+ ivdepEnableAttr =
+ mlir::BoolAttr::get(builder->getContext(), true);
+ has_attrs = true;
+ },
[&](const auto &) {}},
dir->u);
}
+ mlir::LLVM::LoopVectorizeAttr va =
+ genLoopVectorizeAttr(disableVecAttr, ivdepEnableAttr);
mlir::LLVM::LoopAnnotationAttr la = mlir::LLVM::LoopAnnotationAttr::get(
builder->getContext(), {}, /*vectorize=*/va, {}, /*unroll*/ ua,
/*unroll_and_jam*/ uja, {}, {}, {}, {}, {}, {}, {}, {}, {}, {});
@@ -3178,6 +3192,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
[&](const Fortran::parser::CompilerDirective::NoUnrollAndJam &) {
attachDirectiveToLoop(dir, &eval);
},
+ [&](const Fortran::parser::CompilerDirective::IVDep &) {
+ attachDirectiveToLoop(dir, &eval);
+ },
[&](const auto &) {}},
dir.u);
}
diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index f93eaf7ba90b4..4c6aa37f11ade 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -983,7 +983,7 @@ hlfir::LoopNest hlfir::genLoopNest(mlir::Location loc,
if (!couldVectorize) {
mlir::LLVM::LoopVectorizeAttr va{mlir::LLVM::LoopVectorizeAttr::get(
builder.getContext(),
- /*disable=*/builder.getBoolAttr(true), {}, {}, {}, {}, {}, {})};
+ /*disable=*/builder.getBoolAttr(true), {}, {}, {}, {}, {}, {}, {})};
mlir::LLVM::LoopAnnotationAttr la = mlir::LLVM::LoopAnnotationAttr::get(
builder.getContext(), {}, /*vectorize=*/va, {}, /*unroll*/ {},
/*unroll_and_jam*/ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {});
diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp
index fbe629ab52935..bd90d2db6f50f 100644
--- a/flang/lib/Parser/Fortran-parsers.cpp
+++ b/flang/lib/Parser/Fortran-parsers.cpp
@@ -1294,6 +1294,7 @@ TYPE_PARSER(construct<StatOrErrmsg>("STAT =" >> statVariable) ||
// !DIR$ LOOP COUNT (n1[, n2]...)
// !DIR$ name[=value] [, name[=value]]...
// !DIR$ UNROLL [n]
+// !DIR$ IVDEP
// !DIR$ <anything else>
constexpr auto ignore_tkr{
"IGNORE_TKR" >> optionalList(construct<CompilerDirective::IgnoreTKR>(
@@ -1314,6 +1315,7 @@ constexpr auto novector{"NOVECTOR" >> construct<CompilerDirective::NoVector>()};
constexpr auto nounroll{"NOUNROLL" >> construct<CompilerDirective::NoUnroll>()};
constexpr auto nounrollAndJam{
"NOUNROLL_AND_JAM" >> construct<CompilerDirective::NoUnrollAndJam>()};
+constexpr auto ivdep{"IVDEP" >> construct<CompilerDirective::IVDep>()};
TYPE_PARSER(beginDirective >> "DIR$ "_tok >>
sourced((construct<CompilerDirective>(ignore_tkr) ||
construct<CompilerDirective>(loopCount) ||
@@ -1324,6 +1326,7 @@ TYPE_PARSER(beginDirective >> "DIR$ "_tok >>
construct<CompilerDirective>(novector) ||
construct<CompilerDirective>(nounrollAndJam) ||
construct<CompilerDirective>(nounroll) ||
+ construct<CompilerDirective>(ivdep) ||
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 3455b535ccb51..55bb40c2bdea4 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -1867,6 +1867,7 @@ class UnparseVisitor {
[&](const CompilerDirective::NoUnrollAndJam &) {
Word("!DIR$ NOUNROLL_AND_JAM");
},
+ [&](const CompilerDirective::IVDep &) { Word("!DIR$ IVDEP"); },
[&](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 104df253ab642..7fb6f0424db49 100644
--- a/flang/lib/Semantics/canonicalize-directives.cpp
+++ b/flang/lib/Semantics/canonicalize-directives.cpp
@@ -60,7 +60,9 @@ static bool IsExecutionDirective(const parser::CompilerDirective &dir) {
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);
+ std::holds_alternative<parser::CompilerDirective::NoUnrollAndJam>(
+ dir.u) ||
+ std::holds_alternative<parser::CompilerDirective::IVDep>(dir.u);
}
void CanonicalizationOfDirectives::Post(parser::SpecificationPart &spec) {
@@ -131,6 +133,9 @@ void CanonicalizationOfDirectives::Post(parser::Block &block) {
[&](parser::CompilerDirective::NoUnrollAndJam &) {
CheckLoopDirective(*dir, block, it);
},
+ [&](parser::CompilerDirective::IVDep &) {
+ CheckLoopDirective(*dir, block, it);
+ },
[&](auto &) {}},
dir->u);
}
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index d4e3b9cd4e00f..a1dd1fffb533e 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -9957,7 +9957,8 @@ void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) {
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)) {
+ std::holds_alternative<parser::CompilerDirective::NoUnrollAndJam>(x.u) ||
+ std::holds_alternative<parser::CompilerDirective::IVDep>(x.u)) {
return;
}
if (const auto *tkr{
diff --git a/flang/test/Integration/ivdep.f90 b/flang/test/Integration/ivdep.f90
new file mode 100644
index 0000000000000..c1ba963f4583e
--- /dev/null
+++ b/flang/test/Integration/ivdep.f90
@@ -0,0 +1,16 @@
+! RUN: %flang_fc1 -emit-llvm -o - %s | FileCheck %s
+
+! CHECK-LABEL: ivdep
+subroutine ivdep
+ integer :: a(10)
+ !dir$ ivdep
+ ! CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}
+ ! CHECK-NOT: !llvm.loop
+ ! CHECK: br label {{.*}}, !llvm.loop ![[ANNOTATION:.*]]
+ do i=1,10
+ a(i)=i
+ end do
+end subroutine ivdep
+
+! CHECK: ![[ANNOTATION]] = distinct !{![[ANNOTATION]], ![[IVDEP:.*]]}
+! CHECK: ![[IVDEP]] = !{!"llvm.loop.vectorize.ivdep.enable", i1 true}
diff --git a/flang/test/Lower/ivdep.f90 b/flang/test/Lower/ivdep.f90
new file mode 100644
index 0000000000000..7070ed7703e74
--- /dev/null
+++ b/flang/test/Lower/ivdep.f90
@@ -0,0 +1,26 @@
+! RUN: %flang_fc1 -emit-hlfir -o - %s | FileCheck %s
+
+! CHECK: #loop_vectorize = #llvm.loop_vectorize<ivdepEnable = true>
+! CHECK: #loop_annotation = #llvm.loop_annotation<vectorize = #loop_vectorize>
+
+! CHECK-LABEL: @_QPivdep
+subroutine ivdep
+ integer :: a(10)
+ !dir$ ivdep
+ !CHECK: fir.do_loop {{.*}} attributes {loopAnnotation = #loop_annotation}
+ do i=1,10
+ a(i)=i
+ end do
+end subroutine ivdep
+
+
+! CHECK-LABEL: @_QPintermediate_directive
+subroutine intermediate_directive
+ integer :: a(10)
+ !dir$ ivdep
+ !dir$ unknown
+ !CHECK: fir.do_loop {{.*}} attributes {loopAnnotation = #loop_annotation}
+ do i=1,10
+ a(i)=i
+ end do
+end subroutine intermediate_directive
diff --git a/flang/test/Parser/compiler-directives.f90 b/flang/test/Parser/compiler-directives.f90
index 04d22ff0fd8ee..e904319c472a2 100644
--- a/flang/test/Parser/compiler-directives.f90
+++ b/flang/test/Parser/compiler-directives.f90
@@ -72,3 +72,10 @@ subroutine no_vector
do i=1,10
enddo
end subroutine
+
+subroutine ivdep
+ !dir$ ivdep
+ ! CHECK: !DIR$ IVDEP
+ do i=1,10
+ enddo
+end subroutine
More information about the Mlir-commits
mailing list