[Mlir-commits] [mlir] [mlir][LLVMIR] Fix loop follow-up metadata import and export (PR #223376)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Sep 14 04:42:20 PDT 2026


https://github.com/ardenyang0125 created https://github.com/llvm/llvm-project/pull/223376

## Problem

MLIR currently exports loop follow-up metadata by wrapping its properties in an additional self-referencing loop ID:

```llvm
!1 = !{!"llvm.loop.unroll.followup_unrolled", !2}
!2 = distinct !{!2, !3}
!3 = !{!"llvm.loop.mustprogress"}
```

LLVM expects the properties directly after the follow-up name:

```llvm
!1 = !{!"llvm.loop.unroll.followup_unrolled", !3}
!3 = !{!"llvm.loop.mustprogress"}
```

`makeFollowupLoopID` copies the follow-up operands without unwrapping a nested loop ID. Consequently, properties such as `llvm.loop.mustprogress` inside the extra wrapper are not recognized as properties of the resulting loop.

## Changes

- Export follow-up properties directly, excluding the temporary loop ID's self-reference.
- Update import to read direct property lists.
- Preserve explicitly empty follow-ups, multiple properties, nested follow-ups, and debug locations.
- Diagnose malformed follow-up metadata and detect cycles to prevent infinite recursion.

An explicitly empty follow-up is different from an absent follow-up: it specifies an empty configuration instead of leaving the transformation to use its default follow-up attributes. Import therefore preserves it as a non-null, empty `LoopAnnotationAttr`.

This patch corrects MLIR's representation of existing LLVM follow-up metadata. It does not change LLVM's transformation policies or introduce automatic attribute inheritance.

## Testing

Built `mlir-translate`, `FileCheck`, `count`, and `not` on Linux using a Release build with assertions enabled.

All three targeted regression tests passed:

- `mlir/test/Target/LLVMIR/loop-metadata.mlir`
- `mlir/test/Target/LLVMIR/Import/metadata-loop.ll`
- `mlir/test/Target/LLVMIR/Import/import-failure.ll`

`git diff --check` also passed. The full MLIR test suite was not run.

Assisted-by: OpenAI Codex

>From ac5d586080fd1d35984632b178fbf8f6489480f8 Mon Sep 17 00:00:00 2001
From: yangzihan <yangzihan at sunmmio.com>
Date: Mon, 14 Sep 2026 18:59:52 +0800
Subject: [PATCH] [mlir][LLVMIR] Fix loop follow-up metadata import and export

Emit follow-up properties directly instead of wrapping them in a loop ID. Update import to handle direct property lists, preserve empty and nested follow-ups, and detect cycles.

Assisted-by: OpenAI Codex
---
 .../Target/LLVMIR/LoopAnnotationImporter.cpp  | 79 +++++++++-------
 .../LLVMIR/LoopAnnotationTranslation.cpp      | 10 +-
 .../Target/LLVMIR/Import/import-failure.ll    | 38 +++++++-
 .../Target/LLVMIR/Import/metadata-loop.ll     | 92 +++++++++++++++++--
 mlir/test/Target/LLVMIR/loop-metadata.mlir    | 34 +++----
 5 files changed, 187 insertions(+), 66 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp b/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp
index 6658b4a920e373..672c8df1c9465f 100644
--- a/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp
@@ -7,6 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "LoopAnnotationImporter.h"
+#include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/IR/Constants.h"
 
 using namespace mlir;
@@ -16,10 +18,16 @@ using namespace mlir::LLVM::detail;
 namespace {
 /// Helper class that keeps the state of one metadata to attribute conversion.
 struct LoopMetadataConversion {
-  LoopMetadataConversion(const llvm::MDNode *node, Location loc,
-                         LoopAnnotationImporter &loopAnnotationImporter)
+  enum class InputKind { LoopID, Followup };
+
+  LoopMetadataConversion(
+      const llvm::MDNode *node, Location loc,
+      LoopAnnotationImporter &loopAnnotationImporter,
+      llvm::SmallPtrSetImpl<const llvm::MDNode *> &activeNodes,
+      InputKind inputKind = InputKind::LoopID)
       : node(node), loc(loc), loopAnnotationImporter(loopAnnotationImporter),
-        ctx(loc->getContext()){};
+        ctx(loc->getContext()), activeNodes(activeNodes), inputKind(inputKind) {
+  }
   /// Converts this structs loop metadata node into a LoopAnnotationAttr.
   LoopAnnotationAttr convert();
 
@@ -36,7 +44,6 @@ struct LoopMetadataConversion {
   FailureOr<BoolAttr> lookupBoolNode(StringRef name, bool negated = false);
   FailureOr<BoolAttr> lookupIntNodeAsBoolAttr(StringRef name);
   FailureOr<IntegerAttr> lookupIntNode(StringRef name);
-  FailureOr<llvm::MDNode *> lookupMDNode(StringRef name);
   FailureOr<SmallVector<llvm::MDNode *>> lookupMDNodes(StringRef name);
   FailureOr<LoopAnnotationAttr> lookupFollowupNode(StringRef name);
   FailureOr<BoolAttr> lookupBooleanUnitNode(StringRef enableName,
@@ -63,14 +70,21 @@ struct LoopMetadataConversion {
   Location loc;
   LoopAnnotationImporter &loopAnnotationImporter;
   MLIRContext *ctx;
+  llvm::SmallPtrSetImpl<const llvm::MDNode *> &activeNodes;
+  InputKind inputKind;
 };
 } // namespace
 
 LogicalResult LoopMetadataConversion::initConversionState() {
-  // Check if it's a valid node.
-  if (node->getNumOperands() == 0 ||
-      dyn_cast<llvm::MDNode>(node->getOperand(0)) != node)
-    return emitWarning(loc) << "invalid loop node";
+  // LoopIDs begin with a self-reference; follow-ups begin with their name.
+  if (inputKind == InputKind::LoopID) {
+    if (node->getNumOperands() == 0 ||
+        dyn_cast<llvm::MDNode>(node->getOperand(0)) != node)
+      return emitWarning(loc) << "invalid loop node";
+  } else if (node->getNumOperands() == 0 ||
+             !isa<llvm::MDString>(node->getOperand(0))) {
+    return emitWarning(loc) << "invalid loop followup node";
+  }
 
   for (const llvm::MDOperand &operand : llvm::drop_begin(node->operands())) {
     if (auto *diLoc = dyn_cast<llvm::DILocation>(operand)) {
@@ -206,26 +220,6 @@ FailureOr<IntegerAttr> LoopMetadataConversion::lookupIntNode(StringRef name) {
                           val->getValue().getLimitedValue());
 }
 
-FailureOr<llvm::MDNode *> LoopMetadataConversion::lookupMDNode(StringRef name) {
-  const llvm::MDNode *property = lookupAndEraseProperty(name);
-  if (!property)
-    return nullptr;
-
-  auto emitNodeWarning = [&]() {
-    return emitWarning(loc)
-           << "expected metadata node " << name << " to hold an MDNode";
-  };
-
-  if (property->getNumOperands() != 2)
-    return emitNodeWarning();
-
-  auto *node = dyn_cast<llvm::MDNode>(property->getOperand(1));
-  if (!node)
-    return emitNodeWarning();
-
-  return node;
-}
-
 FailureOr<SmallVector<llvm::MDNode *>>
 LoopMetadataConversion::lookupMDNodes(StringRef name) {
   const llvm::MDNode *property = lookupAndEraseProperty(name);
@@ -253,13 +247,17 @@ LoopMetadataConversion::lookupMDNodes(StringRef name) {
 
 FailureOr<LoopAnnotationAttr>
 LoopMetadataConversion::lookupFollowupNode(StringRef name) {
-  auto node = lookupMDNode(name);
-  if (failed(node))
-    return failure();
-  if (*node == nullptr)
+  const llvm::MDNode *followup = lookupAndEraseProperty(name);
+  if (!followup)
     return LoopAnnotationAttr(nullptr);
 
-  return loopAnnotationImporter.translateLoopAnnotation(*node, loc);
+  LoopAnnotationAttr attr =
+      LoopMetadataConversion(followup, loc, loopAnnotationImporter, activeNodes,
+                             InputKind::Followup)
+          .convert();
+  if (!attr)
+    return failure();
+  return attr;
 }
 
 static bool isEmptyOrNull(const Attribute attr) { return !attr; }
@@ -432,9 +430,20 @@ FailureOr<FusedLoc> LoopMetadataConversion::convertEndLoc() {
 }
 
 LoopAnnotationAttr LoopMetadataConversion::convert() {
+  if (!activeNodes.insert(node).second) {
+    emitWarning(loc) << "cannot import cyclic loop annotation";
+    return {};
+  }
+  llvm::scope_exit guard([&] { activeNodes.erase(node); });
+
   if (failed(initConversionState()))
     return {};
 
+  // An explicit empty follow-up is different from an absent follow-up.
+  if (inputKind == InputKind::Followup && node->getNumOperands() == 1)
+    return LoopAnnotationAttr::get(ctx, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
+                                   {}, {}, {}, {}, {});
+
   FailureOr<BoolAttr> disableNonForced =
       lookupUnitNode("llvm.loop.disable_nonforced");
   FailureOr<LoopVectorizeAttr> vecAttr = convertVectorizeAttr();
@@ -481,7 +490,9 @@ LoopAnnotationImporter::translateLoopAnnotation(const llvm::MDNode *node,
   if (it != loopMetadataMapping.end())
     return it->getSecond();
 
-  LoopAnnotationAttr attr = LoopMetadataConversion(node, loc, *this).convert();
+  llvm::SmallPtrSet<const llvm::MDNode *, 4> activeNodes;
+  LoopAnnotationAttr attr =
+      LoopMetadataConversion(node, loc, *this, activeNodes).convert();
 
   mapLoopMetadata(node, attr);
   return attr;
diff --git a/mlir/lib/Target/LLVMIR/LoopAnnotationTranslation.cpp b/mlir/lib/Target/LLVMIR/LoopAnnotationTranslation.cpp
index 475799e7fdbfde..37866718de9e78 100644
--- a/mlir/lib/Target/LLVMIR/LoopAnnotationTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/LoopAnnotationTranslation.cpp
@@ -110,11 +110,15 @@ void LoopAnnotationConversion::convertFollowupNode(StringRef name,
   if (!attr)
     return;
 
-  llvm::MDNode *node =
+  llvm::MDNode *loopID =
       loopAnnotationTranslation.translateLoopAnnotation(attr, op);
 
-  metadataNodes.push_back(
-      llvm::MDNode::get(ctx, {llvm::MDString::get(ctx, name), node}));
+  // Follow-ups contain properties directly, without the LoopID self-reference.
+  SmallVector<llvm::Metadata *, 4> operands;
+  operands.push_back(llvm::MDString::get(ctx, name));
+  for (const llvm::MDOperand &operand : llvm::drop_begin(loopID->operands()))
+    operands.push_back(operand.get());
+  metadataNodes.push_back(llvm::MDNode::get(ctx, operands));
 }
 
 void LoopAnnotationConversion::convertLoopOptions(LoopVectorizeAttr options) {
diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll
index 9015eff87a8c76..552841ebda9eb6 100644
--- a/mlir/test/Target/LLVMIR/Import/import-failure.ll
+++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll
@@ -175,7 +175,7 @@ end:
 ; // -----
 
 ; CHECK:      <unknown>
-; CHECK-SAME: warning: expected metadata node llvm.loop.vectorize.followup_all to hold an MDNode
+; CHECK-SAME: warning: expected all loop properties to be either debug locations or metadata nodes
 ; CHECK:      <unknown>
 ; CHECK-SAME: warning: unhandled metadata: ![[FOLLOWUP_LOOP:[0-9]+]] = distinct !{![[FOLLOWUP_LOOP]], ![[FOLLOWUP_PROP:[0-9]+]]}
 define void @unsupported_loop_annotation(i64 %n, ptr %A) {
@@ -190,6 +190,42 @@ end:
 
 ; // -----
 
+; A whole LoopID is not a named property in a followup's direct attribute list.
+; CHECK:      <unknown>
+; CHECK-SAME: warning: cannot import loop property without a name
+; CHECK:      <unknown>
+; CHECK-SAME: warning: unhandled metadata: ![[WRAPPED_LOOP:[0-9]+]] = distinct !{![[WRAPPED_LOOP]], ![[WRAPPED_PROP:[0-9]+]]}
+define void @followup_with_loop_id() {
+entry:
+  br label %end, !llvm.loop !0
+end:
+  ret void
+}
+
+!0 = distinct !{!0, !1}
+!1 = !{!"llvm.loop.unroll.followup_unrolled", !2}
+!2 = distinct !{!2, !3}
+!3 = !{!"llvm.loop.mustprogress"}
+
+; // -----
+
+; Reject recursive followup metadata instead of recursing indefinitely.
+; CHECK:      <unknown>
+; CHECK-SAME: warning: cannot import cyclic loop annotation
+; CHECK:      <unknown>
+; CHECK-SAME: warning: unhandled metadata: ![[CYCLIC_LOOP:[0-9]+]] = distinct !{![[CYCLIC_LOOP]], ![[CYCLIC_PROP:[0-9]+]]}
+define void @cyclic_followup() {
+entry:
+  br label %end, !llvm.loop !0
+end:
+  ret void
+}
+
+!0 = distinct !{!0, !1}
+!1 = distinct !{!"llvm.loop.unroll.followup_unrolled", !1}
+
+; // -----
+
 ; CHECK:      <unknown>
 ; CHECK-SAME: warning: expected metadata node llvm.loop.parallel_accesses to hold one or multiple MDNodes
 ; CHECK:      <unknown>
diff --git a/mlir/test/Target/LLVMIR/Import/metadata-loop.ll b/mlir/test/Target/LLVMIR/Import/metadata-loop.ll
index 89357186409e33..ba601fedecb291 100644
--- a/mlir/test/Target/LLVMIR/Import/metadata-loop.ll
+++ b/mlir/test/Target/LLVMIR/Import/metadata-loop.ll
@@ -1,4 +1,5 @@
 ; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s
+; RUN: mlir-translate -import-llvm -mlir-to-llvmir -split-input-file %s | FileCheck %s --check-prefix=ROUNDTRIP
 
 ; CHECK-DAG: #[[$GROUP0:.*]] = #llvm.access_group<id = {{.*}}>
 ; CHECK-DAG: #[[$GROUP1:.*]] = #llvm.access_group<id = {{.*}}>
@@ -94,8 +95,7 @@ end:
 !7 = !{!"llvm.loop.vectorize.followup_epilogue", !9}
 !8 = !{!"llvm.loop.vectorize.followup_all", !9}
 
-!9 = distinct !{!9, !10}
-!10 = !{!"llvm.loop.disable_nonforced"}
+!9 = !{!"llvm.loop.disable_nonforced"}
 
 ; // -----
 
@@ -138,8 +138,7 @@ end:
 !7 = !{!"llvm.loop.unroll.followup_remainder", !9}
 !8 = !{!"llvm.loop.unroll.followup_all", !9}
 
-!9 = distinct !{!9, !10}
-!10 = !{!"llvm.loop.disable_nonforced"}
+!9 = !{!"llvm.loop.disable_nonforced"}
 
 ; // -----
 
@@ -160,6 +159,69 @@ end:
 
 ; // -----
 
+; An explicitly empty followup must survive import and export, rather than
+; disappear or acquire a self-referential LoopID wrapper.
+; CHECK-DAG: #[[EMPTY:.*]] = #llvm.loop_annotation<>
+; CHECK-DAG: #[[UNROLL_ATTR:.*]] = #llvm.loop_unroll<count = 8 : i32, followupUnrolled = #[[EMPTY]]>
+; CHECK-DAG: #[[$ANNOT_ATTR:.*]] = #llvm.loop_annotation<unroll = #[[UNROLL_ATTR]]>
+; CHECK-LABEL: @unroll_empty_followup
+; ROUNDTRIP-LABEL: @unroll_empty_followup(
+define void @unroll_empty_followup() {
+entry:
+; CHECK: llvm.br ^{{.*}} loop_annotation = #[[$ANNOT_ATTR]]
+; ROUNDTRIP: br label {{.*}}, !llvm.loop ![[EMPTY_LOOP:[0-9]+]]
+  br label %end, !llvm.loop !0
+end:
+  ret void
+}
+
+!0 = distinct !{!0, !1, !2}
+!1 = !{!"llvm.loop.unroll.count", i32 8}
+!2 = !{!"llvm.loop.unroll.followup_unrolled"}
+
+; ROUNDTRIP: ![[EMPTY_LOOP]] = distinct !{![[EMPTY_LOOP]], ![[COUNT:[0-9]+]], ![[EMPTY_FOLLOWUP:[0-9]+]]}
+; ROUNDTRIP-DAG: ![[COUNT]] = !{!"llvm.loop.unroll.count", i32 8}
+; ROUNDTRIP-DAG: ![[EMPTY_FOLLOWUP]] = !{!"llvm.loop.unroll.followup_unrolled"}
+
+; // -----
+
+; Keep multiple direct properties and a later followup as separate properties.
+; In particular, do not recursively flatten the nested empty followup.
+; CHECK-DAG: #[[EMPTY:.*]] = #llvm.loop_annotation<>
+; CHECK-DAG: #[[VECTORIZE_ATTR:.*]] = #llvm.loop_vectorize<disable = true>
+; CHECK-DAG: #[[INNER_UNROLL:.*]] = #llvm.loop_unroll<count = 2 : i32, followupUnrolled = #[[EMPTY]]>
+; CHECK-DAG: #[[FOLLOWUP:.*]] = #llvm.loop_annotation<vectorize = #[[VECTORIZE_ATTR]], unroll = #[[INNER_UNROLL]], mustProgress = true>
+; CHECK-DAG: #[[UNROLL_ATTR:.*]] = #llvm.loop_unroll<count = 8 : i32, followupUnrolled = #[[FOLLOWUP]]>
+; CHECK-DAG: #[[$ANNOT_ATTR:.*]] = #llvm.loop_annotation<unroll = #[[UNROLL_ATTR]]>
+; CHECK-LABEL: @unroll_nested_followup
+; ROUNDTRIP-LABEL: @unroll_nested_followup(
+define void @unroll_nested_followup() {
+entry:
+; CHECK: llvm.br ^{{.*}} loop_annotation = #[[$ANNOT_ATTR]]
+; ROUNDTRIP: br label {{.*}}, !llvm.loop ![[NESTED_LOOP:[0-9]+]]
+  br label %end, !llvm.loop !0
+end:
+  ret void
+}
+
+!0 = distinct !{!0, !1, !2}
+!1 = !{!"llvm.loop.unroll.count", i32 8}
+!2 = !{!"llvm.loop.unroll.followup_unrolled", !3, !4, !5, !6}
+!3 = !{!"llvm.loop.mustprogress"}
+!4 = !{!"llvm.loop.vectorize.disable"}
+!5 = !{!"llvm.loop.unroll.count", i32 2}
+!6 = !{!"llvm.loop.unroll.followup_unrolled"}
+
+; ROUNDTRIP: ![[NESTED_LOOP]] = distinct !{![[NESTED_LOOP]], ![[COUNT:[0-9]+]], ![[FOLLOWUP:[0-9]+]]}
+; ROUNDTRIP: ![[COUNT]] = !{!"llvm.loop.unroll.count", i32 8}
+; ROUNDTRIP: ![[FOLLOWUP]] = !{!"llvm.loop.unroll.followup_unrolled", ![[PROGRESS:[0-9]+]], ![[VECTORIZE:[0-9]+]], ![[INNER_COUNT:[0-9]+]], ![[INNER_FOLLOWUP:[0-9]+]]}
+; ROUNDTRIP-DAG: ![[PROGRESS]] = !{!"llvm.loop.mustprogress"}
+; ROUNDTRIP-DAG: ![[VECTORIZE]] = !{!"llvm.loop.vectorize.disable"}
+; ROUNDTRIP-DAG: ![[INNER_COUNT]] = !{!"llvm.loop.unroll.count", i32 2}
+; ROUNDTRIP-DAG: ![[INNER_FOLLOWUP]] = !{!"llvm.loop.unroll.followup_unrolled"}
+
+; // -----
+
 ; CHECK-DAG: #[[FOLLOWUP:.*]] = #llvm.loop_annotation<disableNonforced = true>
 ; CHECK-DAG: #[[UNROLL_AND_JAM_ATTR:.*]] = #llvm.loop_unroll_and_jam<disable = false, count = 32 : i32, followupOuter = #[[FOLLOWUP]], followupInner = #[[FOLLOWUP]], followupRemainderOuter = #[[FOLLOWUP]], followupRemainderInner = #[[FOLLOWUP]], followupAll = #[[FOLLOWUP]]>
 ; CHECK-DAG: #[[$ANNOT_ATTR:.*]] = #llvm.loop_annotation<unrollAndJam = #[[UNROLL_AND_JAM_ATTR]]>
@@ -182,8 +244,7 @@ end:
 !7 = !{!"llvm.loop.unroll_and_jam.followup_remainder_inner", !9}
 !8 = !{!"llvm.loop.unroll_and_jam.followup_all", !9}
 
-!9 = distinct !{!9, !10}
-!10 = !{!"llvm.loop.disable_nonforced"}
+!9 = !{!"llvm.loop.disable_nonforced"}
 
 ; // -----
 
@@ -225,8 +286,7 @@ end:
 !5 = !{!"llvm.loop.distribute.followup_fallback", !9}
 !6 = !{!"llvm.loop.distribute.followup_all", !9}
 
-!9 = distinct !{!9, !10}
-!10 = !{!"llvm.loop.disable_nonforced"}
+!9 = !{!"llvm.loop.disable_nonforced"}
 
 ; // -----
 
@@ -347,15 +407,20 @@ end:
 ; CHECK: #[[SUBPROGRAM:.*]] = #llvm.di_subprogram<
 ; CHECK: #[[start_loc_fused:.*]] = loc(fused<#[[SUBPROGRAM]]>[#[[start_loc]]])
 ; CHECK: #[[end_loc_fused:.*]] = loc(fused<#[[SUBPROGRAM]]>[#[[end_loc]]])
+; CHECK: #[[FOLLOWUP:.*]] = #llvm.loop_annotation<mustProgress = true, startLoc = #[[start_loc_fused]], endLoc = #[[end_loc_fused]]>
+; CHECK: #[[UNROLL_ATTR:.*]] = #llvm.loop_unroll<followupUnrolled = #[[FOLLOWUP]]>
 ; CHECK: #[[$ANNOT_ATTR:.*]] = #llvm.loop_annotation<
+; CHECK-SAME: unroll = #[[UNROLL_ATTR]]
 ; CHECK-SAME: mustProgress = true
 ; CHECK-SAME: startLoc = #[[start_loc_fused]]
 ; CHECK-SAME: endLoc = #[[end_loc_fused]]
 
 ; CHECK-LABEL: @loop_locs
+; ROUNDTRIP-LABEL: @loop_locs(
 define void @loop_locs(i64 %n, ptr %A) {
 entry:
 ; CHECK: llvm.br ^{{.*}} loop_annotation = #[[$ANNOT_ATTR]]
+; ROUNDTRIP: br label {{.*}}, !llvm.loop ![[LOC_LOOP:[0-9]+]]
   br label %end, !llvm.loop !6
 end:
   ret void
@@ -370,7 +435,16 @@ end:
 !4 = !DILocation(line: 1, column: 2, scope: !3)
 !5 = !DILocation(line: 2, column: 2, scope: !3)
 
-!6 = distinct !{!6, !4, !5, !7}
+!6 = distinct !{!6, !4, !5, !7, !8}
 !7 = !{!"llvm.loop.mustprogress"}
+!8 = !{!"llvm.loop.unroll.followup_unrolled", !4, !5, !7}
 !999 = !DISubroutineType(types: !1000)
 !1000 = !{null}
+
+; Debug locations are direct followup operands too, not named properties to
+; filter out when removing a LoopID wrapper.
+; ROUNDTRIP: ![[LOC_LOOP]] = distinct !{![[LOC_LOOP]], ![[START:[0-9]+]], ![[END:[0-9]+]], ![[PROGRESS:[0-9]+]], ![[FOLLOWUP:[0-9]+]]}
+; ROUNDTRIP-DAG: ![[START]] = !DILocation(line: 1, column: 2, scope:
+; ROUNDTRIP-DAG: ![[END]] = !DILocation(line: 2, column: 2, scope:
+; ROUNDTRIP-DAG: ![[PROGRESS]] = !{!"llvm.loop.mustprogress"}
+; ROUNDTRIP-DAG: ![[FOLLOWUP]] = !{!"llvm.loop.unroll.followup_unrolled", ![[START]], ![[END]], ![[PROGRESS]]}
diff --git a/mlir/test/Target/LLVMIR/loop-metadata.mlir b/mlir/test/Target/LLVMIR/loop-metadata.mlir
index 12daaf6d5d2821..bb8a87ac330822 100644
--- a/mlir/test/Target/LLVMIR/loop-metadata.mlir
+++ b/mlir/test/Target/LLVMIR/loop-metadata.mlir
@@ -53,15 +53,14 @@ 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: !{{[0-9]+}} = !{!"llvm.loop.vectorize.enable"}
 // CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.vectorize.predicate.enable"}
 // CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.vectorize.scalable.disable"}
 // 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]]}
-// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.vectorize.followup_all", ![[FOLLOWUP]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.vectorize.followup_vectorized", ![[NON_FORCED]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.vectorize.followup_epilogue", ![[NON_FORCED]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.vectorize.followup_all", ![[NON_FORCED]]}
 
 // -----
 
@@ -92,14 +91,13 @@ llvm.func @unrollOptions() {
 }
 
 // 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]+}}}
 // CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll.disable"}
 // CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll.count", i32 64}
 // CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll.runtime.disable", i1 false}
-// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll.followup_unrolled", ![[FOLLOWUP]]}
-// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll.followup_remainder", ![[FOLLOWUP]]}
-// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll.followup_all", ![[FOLLOWUP]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll.followup_unrolled", ![[NON_FORCED]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll.followup_remainder", ![[NON_FORCED]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll.followup_all", ![[NON_FORCED]]}
 
 // -----
 
@@ -131,15 +129,14 @@ llvm.func @unrollAndJamOptions() {
 }
 
 // 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: !{{[0-9]+}} = !{!"llvm.loop.unroll_and_jam.enable"}
 // CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll_and_jam.count", i32 8}
-// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll_and_jam.followup_outer", ![[FOLLOWUP]]}
-// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll_and_jam.followup_inner", ![[FOLLOWUP]]}
-// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll_and_jam.followup_remainder_outer", ![[FOLLOWUP]]}
-// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll_and_jam.followup_remainder_inner", ![[FOLLOWUP]]}
-// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll_and_jam.followup_all", ![[FOLLOWUP]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll_and_jam.followup_outer", ![[NON_FORCED]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll_and_jam.followup_inner", ![[NON_FORCED]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll_and_jam.followup_remainder_outer", ![[NON_FORCED]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll_and_jam.followup_remainder_inner", ![[NON_FORCED]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.unroll_and_jam.followup_all", ![[NON_FORCED]]}
 
 // -----
 
@@ -183,13 +180,12 @@ llvm.func @distributeOptions() {
 }
 
 // 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]+}}}
 // CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.distribute.disable"}
-// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.distribute.followup_coincident", ![[FOLLOWUP]]}
-// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.distribute.followup_sequential", ![[FOLLOWUP]]}
-// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.distribute.followup_fallback", ![[FOLLOWUP]]}
-// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.distribute.followup_all", ![[FOLLOWUP]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.distribute.followup_coincident", ![[NON_FORCED]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.distribute.followup_sequential", ![[NON_FORCED]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.distribute.followup_fallback", ![[NON_FORCED]]}
+// CHECK-DAG: !{{[0-9]+}} = !{!"llvm.loop.distribute.followup_all", ![[NON_FORCED]]}
 
 // -----
 



More information about the Mlir-commits mailing list