https://github.com/madhur13490 updated 
https://github.com/llvm/llvm-project/pull/201077

>From f4a850b7455781116f95bcb5421fc0ed81ea725d Mon Sep 17 00:00:00 2001
From: Madhur Amilkanthwar <[email protected]>
Date: Wed, 15 Apr 2026 01:00:40 -0700
Subject: [PATCH 1/3] Enforce single-operand form for llvm.loop.distribute
 metadata

This patch implements Phase 1 of the RFC "Enforce Single-Operand Format for All
.enable Metadata Nodes". The two-operand boolean form
!{!"llvm.loop.distribute.enable", i1 0/1} is replaced by a
single-operand enable/disable pair:

  !{!"llvm.loop.distribute.enable"}    ; force distribution
  !{!"llvm.loop.distribute.disable"}   ; suppress distribution
---
 clang/lib/CodeGen/CGLoopInfo.cpp              | 22 ++++-----
 .../test/CodeGenCXX/pragma-followup_inner.cpp |  2 +-
 .../test/CodeGenCXX/pragma-followup_outer.cpp |  2 +-
 .../CodeGenCXX/pragma-loop-distribute.cpp     |  2 +-
 clang/test/CodeGenCXX/pragma-loop.cpp         |  2 +-
 llvm/docs/LangRef.rst                         | 15 +++---
 llvm/lib/Analysis/LoopAccessAnalysis.cpp      | 11 ++---
 llvm/lib/IR/Verifier.cpp                      |  8 +++
 llvm/lib/Transforms/Scalar/LoopDistribute.cpp | 13 ++---
 llvm/lib/Transforms/Utils/LoopConstrainer.cpp |  3 +-
 llvm/lib/Transforms/Utils/LoopUtils.cpp       |  3 ++
 .../Analysis/LoopAccessAnalysis/pr64637.ll    |  2 +-
 .../Other/optimization-remarks-lazy-bfi.ll    |  2 +-
 .../IRCE/add-metadata-pre-post-loops.ll       |  2 +-
 .../test/Transforms/IRCE/correct-loop-info.ll |  2 +-
 .../Transforms/IRCE/loop-guarded-bounds.ll    |  2 +-
 llvm/test/Transforms/IRCE/pre_post_loops.ll   |  2 +-
 .../IRCE/range_intersect_miscompile.ll        |  2 +-
 .../IRCE/unsigned_comparisons_ugt.ll          |  2 +-
 .../IRCE/unsigned_comparisons_ult.ll          |  2 +-
 .../Inline/dilocation-loop-metadata-update.ll |  4 +-
 .../LoopDistribute/basic-with-memchecks.ll    |  2 +-
 .../diagnostics-with-hotness.ll               |  2 +-
 .../Transforms/LoopDistribute/diagnostics.ll  |  2 +-
 .../disable_nonforced_enable.ll               |  2 +-
 .../Transforms/LoopDistribute/early-exit.ll   |  2 +-
 .../Transforms/LoopDistribute/followup.ll     |  2 +-
 .../Transforms/LoopDistribute/metadata.ll     |  4 +-
 .../preserve-llvm-loop-metadata.ll            |  4 +-
 .../preserve-llvm-loop-metadata.ll            |  4 +-
 llvm/test/Verifier/llvm.loop.distribute.ll    | 49 +++++++++++++++++++
 llvm/unittests/Analysis/LoopInfoTest.cpp      |  8 +--
 .../Target/LLVMIR/LoopAnnotationImporter.cpp  |  6 ++-
 .../LLVMIR/LoopAnnotationTranslation.cpp      |  7 ++-
 .../Target/LLVMIR/Import/metadata-loop.ll     |  2 +-
 mlir/test/Target/LLVMIR/loop-metadata.mlir    |  2 +-
 36 files changed, 131 insertions(+), 72 deletions(-)
 create mode 100644 llvm/test/Verifier/llvm.loop.distribute.ll

diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp
index 6b0b1b55213e1..1ae6bbe0ff595 100644
--- a/clang/lib/CodeGen/CGLoopInfo.cpp
+++ b/clang/lib/CodeGen/CGLoopInfo.cpp
@@ -331,11 +331,12 @@ clang::CodeGen::LoopInfo::createLoopDistributeMetadata(
   if (Enabled != true) {
     SmallVector<Metadata *, 4> NewLoopProperties;
     if (Enabled == false) {
-      NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
-      NewLoopProperties.push_back(
-          MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"),
-                            ConstantAsMetadata::get(ConstantInt::get(
-                                llvm::Type::getInt1Ty(Ctx), 0))}));
+      NewLoopProperties.append(
+          LoopProperties.begin(), LoopProperties.end());
+      NewLoopProperties.push_back(MDNode::get(
+          Ctx,
+          {MDString::get(
+              Ctx, "llvm.loop.distribute.disable")}));
       LoopProperties = NewLoopProperties;
     }
     return createLoopVectorizeMetadata(Attrs, LoopProperties,
@@ -344,16 +345,15 @@ clang::CodeGen::LoopInfo::createLoopDistributeMetadata(
 
   bool FollowupHasTransforms = false;
   SmallVector<Metadata *, 4> Followup =
-      createLoopVectorizeMetadata(Attrs, LoopProperties, 
FollowupHasTransforms);
+      createLoopVectorizeMetadata(
+          Attrs, LoopProperties, FollowupHasTransforms);
 
   SmallVector<Metadata *, 4> Args;
   Args.append(LoopProperties.begin(), LoopProperties.end());
 
-  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
-                      ConstantAsMetadata::get(ConstantInt::get(
-                          llvm::Type::getInt1Ty(Ctx),
-                          (Attrs.DistributeEnable == 
LoopAttributes::Enable)))};
-  Args.push_back(MDNode::get(Ctx, Vals));
+  Args.push_back(MDNode::get(
+      Ctx,
+      {MDString::get(Ctx, "llvm.loop.distribute.enable")}));
 
   if (FollowupHasTransforms)
     Args.push_back(
diff --git a/clang/test/CodeGenCXX/pragma-followup_inner.cpp 
b/clang/test/CodeGenCXX/pragma-followup_inner.cpp
index 04f5656dcd638..2cf2dba5b913d 100644
--- a/clang/test/CodeGenCXX/pragma-followup_inner.cpp
+++ b/clang/test/CodeGenCXX/pragma-followup_inner.cpp
@@ -22,7 +22,7 @@ extern "C" void followup_inner(int n, int *x) {
 
 // CHECK-DAG: ![[INNERLOOP_3]] = distinct !{![[INNERLOOP_3]], 
![[PARALLEL_ACCESSES_4:[0-9]+]], ![[DISTRIBUTE_5:[0-9]+]], 
![[DISTRIBUTE_FOLLOWUP_6:[0-9]+]]}
 // CHECK-DAG: ![[PARALLEL_ACCESSES_4]] = !{!"llvm.loop.parallel_accesses", 
![[ACCESSGROUP_2]]}
-// CHECK-DAG: ![[DISTRIBUTE_5]] = !{!"llvm.loop.distribute.enable", i1 true}
+// CHECK-DAG: ![[DISTRIBUTE_5]] = !{!"llvm.loop.distribute.enable"}
 
 // CHECK-DAG: ![[DISTRIBUTE_FOLLOWUP_6]] = 
!{!"llvm.loop.distribute.followup_all", ![[PARALLEL_ACCESSES_4]], 
![[VECTORIZE_8:[0-9]+]]}
 // CHECK-DAG: ![[VECTORIZE_8]] = !{!"llvm.loop.vectorize.enable", i1 true}
diff --git a/clang/test/CodeGenCXX/pragma-followup_outer.cpp 
b/clang/test/CodeGenCXX/pragma-followup_outer.cpp
index fdd5a07d00857..2e907fb814b3d 100644
--- a/clang/test/CodeGenCXX/pragma-followup_outer.cpp
+++ b/clang/test/CodeGenCXX/pragma-followup_outer.cpp
@@ -19,7 +19,7 @@ extern "C" void followup_outer(int n, int *x) {
 
 // CHECK-DAG: ![[LOOP_3:[0-9]+]] = distinct !{![[LOOP_3:[0-9]+]], 
[[MP:![0-9]+]], ![[PARALLEL_ACCESSES_4:[0-9]+]], ![[DISTRIBUTE_5:[0-9]+]], 
![[DISTRIBUTE_FOLLOWUP_6:[0-9]+]]}
 // CHECK-DAG: ![[PARALLEL_ACCESSES_4:[0-9]+]] = 
!{!"llvm.loop.parallel_accesses", ![[ACCESSGROUP_2]]}
-// CHECK-DAG: ![[DISTRIBUTE_5:[0-9]+]] = !{!"llvm.loop.distribute.enable", i1 
true}
+// CHECK-DAG: ![[DISTRIBUTE_5:[0-9]+]] = !{!"llvm.loop.distribute.enable"}
 
 // CHECK-DAG: ![[DISTRIBUTE_FOLLOWUP_6:[0-9]+]] = 
!{!"llvm.loop.distribute.followup_all", [[MP]], 
![[PARALLEL_ACCESSES_4:[0-9]+]], ![[VECTORIZE_8:[0-9]+]], 
![[VECTORIZE_FOLLOWUP_9:[0-9]+]]}
 // CHECK-DAG: ![[VECTORIZE_8:[0-9]+]] = !{!"llvm.loop.vectorize.enable", i1 
true}
diff --git a/clang/test/CodeGenCXX/pragma-loop-distribute.cpp 
b/clang/test/CodeGenCXX/pragma-loop-distribute.cpp
index 98aef21da2acd..66f0fb07b51fb 100644
--- a/clang/test/CodeGenCXX/pragma-loop-distribute.cpp
+++ b/clang/test/CodeGenCXX/pragma-loop-distribute.cpp
@@ -20,5 +20,5 @@ void while_test(int *List, int Length, int *List2, int 
Length2) {
 }
 
 // CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], [[MP:![0-9]+]], 
![[DISTRIBUTE_ENABLE:.*]]}
-// CHECK: ![[DISTRIBUTE_ENABLE]] = !{!"llvm.loop.distribute.enable", i1 true}
+// CHECK: ![[DISTRIBUTE_ENABLE]] = !{!"llvm.loop.distribute.enable"}
 // CHECK: [[LOOP_2]] = distinct !{[[LOOP_2]], [[MP]]}
diff --git a/clang/test/CodeGenCXX/pragma-loop.cpp 
b/clang/test/CodeGenCXX/pragma-loop.cpp
index 8cb3346247daf..f9106725ad99d 100644
--- a/clang/test/CodeGenCXX/pragma-loop.cpp
+++ b/clang/test/CodeGenCXX/pragma-loop.cpp
@@ -248,7 +248,7 @@ void for_test_interleave_vectorize_disable_unroll(int 
*List, int Length) {
 // CHECK-DAG: ![[UNROLL_32:[0-9]+]] = !{!"llvm.loop.unroll.count", i32 32}
 // CHECK-DAG: ![[UNROLL_FULL:[0-9]+]] = !{!"llvm.loop.unroll.full"}
 
-// CHECK-DAG: ![[DISTRIBUTE_DISABLE:[0-9]+]] = 
!{!"llvm.loop.distribute.enable", i1 false}
+// CHECK-DAG: ![[DISTRIBUTE_DISABLE:[0-9]+]] = 
!{!"llvm.loop.distribute.disable"}
 
 // CHECK-DAG: ![[INTERLEAVE_2:[0-9]+]] = !{!"llvm.loop.interleave.count", i32 
2}
 // CHECK-DAG: ![[INTERLEAVE_4:[0-9]+]] = !{!"llvm.loop.interleave.count", i32 
4}
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 6e7f63ed7fb69..9d37207753686 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -8385,18 +8385,17 @@ this is only performed if the entire loop cannot be 
vectorized due to unsafe
 memory dependencies.  The transformation will attempt to isolate the unsafe
 dependencies into their own loop.
 
-This metadata can be used to selectively enable or disable distribution of the
-loop.  The first operand is the string ``llvm.loop.distribute.enable`` and the
-second operand is a bit. If the bit operand value is 1 distribution is
-enabled. A value of 0 disables distribution:
+This metadata can be used to selectively enable or disable
+distribution of the loop.  Each node has a single operand
+containing the name string:
 
 .. code-block:: llvm
 
-   !0 = !{!"llvm.loop.distribute.enable", i1 0}
-   !1 = !{!"llvm.loop.distribute.enable", i1 1}
+   !0 = !{!"llvm.loop.distribute.enable"}
+   !1 = !{!"llvm.loop.distribute.disable"}
 
-This metadata should be used in conjunction with ``llvm.loop`` loop
-identification metadata.
+This metadata should be used in conjunction with ``llvm.loop``
+loop identification metadata.
 
 '``llvm.loop.distribute.followup_coincident``' Metadata
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp 
b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index f28b570d6191b..d63208e2fe5d3 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -2929,14 +2929,9 @@ void LoopAccessInfo::emitUnsafeDependenceRemark() {
   LLVM_DEBUG(dbgs() << "LAA: unsafe dependent memory operations in loop\n");
 
   // Emit remark for first unsafe dependence
-  bool HasForcedDistribution = false;
-  std::optional<const MDOperand *> Value =
-      findStringMetadataForLoop(TheLoop, "llvm.loop.distribute.enable");
-  if (Value) {
-    const MDOperand *Op = *Value;
-    assert(Op && mdconst::hasa<ConstantInt>(*Op) && "invalid metadata");
-    HasForcedDistribution = mdconst::extract<ConstantInt>(*Op)->getZExtValue();
-  }
+  bool HasForcedDistribution =
+      getBooleanLoopAttribute(
+          TheLoop, "llvm.loop.distribute.enable");
 
   const std::string Info =
       HasForcedDistribution
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 198ff055f9721..857fa1200c590 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -995,6 +995,14 @@ void Verifier::visitMDNode(const MDNode &BaseMD,
             CurrentMD);
     }
 
+    // Enforce the single-operand form of llvm.loop.distribute metadata.
+    if (CurrentMD->getNumOperands() > 0 &&
+        (CurrentMD->getOperand(0).equalsStr("llvm.loop.distribute.enable") ||
+         CurrentMD->getOperand(0).equalsStr("llvm.loop.distribute.disable")))
+      Check(CurrentMD->getNumOperands() == 1,
+            "Expected one operand for llvm.loop.distribute metadata",
+            CurrentMD);
+
     // Check these last, so we diagnose problems in operands first.
     Check(!CurrentMD->isTemporary(), "Expected no forward declarations!",
           CurrentMD);
diff --git a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp 
b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp
index 2d0b08fed859b..07cfd8628a4f6 100644
--- a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp
@@ -941,14 +941,11 @@ class LoopDistributeForLoop {
   /// Check whether the loop metadata is forcing distribution to be
   /// enabled/disabled.
   void setForced() {
-    std::optional<const MDOperand *> Value =
-        findStringMetadataForLoop(L, "llvm.loop.distribute.enable");
-    if (!Value)
-      return;
-
-    const MDOperand *Op = *Value;
-    assert(Op && mdconst::hasa<ConstantInt>(*Op) && "invalid metadata");
-    IsForced = mdconst::extract<ConstantInt>(*Op)->getZExtValue();
+    if (getBooleanLoopAttribute(L, "llvm.loop.distribute.enable"))
+      IsForced = true;
+    else if (getBooleanLoopAttribute(
+                 L, "llvm.loop.distribute.disable"))
+      IsForced = false;
   }
 
   Loop *L;
diff --git a/llvm/lib/Transforms/Utils/LoopConstrainer.cpp 
b/llvm/lib/Transforms/Utils/LoopConstrainer.cpp
index 72fae62e56e88..74cd2a729d285 100644
--- a/llvm/lib/Transforms/Utils/LoopConstrainer.cpp
+++ b/llvm/lib/Transforms/Utils/LoopConstrainer.cpp
@@ -453,7 +453,8 @@ static void DisableAllLoopOptsOnLoop(Loop &L) {
       Context, {MDString::get(Context, "llvm.loop.licm_versioning.disable")});
   MDNode *DisableDistribution = MDNode::get(
       Context,
-      {MDString::get(Context, "llvm.loop.distribute.enable"), FalseVal});
+      {MDString::get(
+          Context, "llvm.loop.distribute.disable")});
   MDNode *NewLoopID =
       MDNode::get(Context, {Dummy, DisableUnroll, DisableVectorize,
                             DisableLICMVersioning, DisableDistribution});
diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp 
b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index a2630c481a72e..3133bf2804034 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -441,6 +441,9 @@ TransformationMode llvm::hasVectorizeTransformation(const 
Loop *L) {
 }
 
 TransformationMode llvm::hasDistributeTransformation(const Loop *L) {
+  if (getBooleanLoopAttribute(L, "llvm.loop.distribute.disable"))
+    return TM_SuppressedByUser;
+
   if (getBooleanLoopAttribute(L, "llvm.loop.distribute.enable"))
     return TM_ForcedByUser;
 
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/pr64637.ll 
b/llvm/test/Analysis/LoopAccessAnalysis/pr64637.ll
index d3e589cf99cf3..7b25d1fffcbba 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/pr64637.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/pr64637.ll
@@ -76,4 +76,4 @@ for.body:                                         ; preds = 
%for.body, %for.body
 }
 
 !0 = distinct !{!0, !1}
-!1 = !{!"llvm.loop.distribute.enable", i1 true}
+!1 = !{!"llvm.loop.distribute.enable"}
diff --git a/llvm/test/Other/optimization-remarks-lazy-bfi.ll 
b/llvm/test/Other/optimization-remarks-lazy-bfi.ll
index c5099bb2179e4..5fc34cc14bdc8 100644
--- a/llvm/test/Other/optimization-remarks-lazy-bfi.ll
+++ b/llvm/test/Other/optimization-remarks-lazy-bfi.ll
@@ -75,7 +75,7 @@ for.cond.cleanup:
 !18 = !DILocation(line: 4, column: 5, scope: !7)
 !19 = !DILocation(line: 4, column: 10, scope: !7)
 !20 = distinct !{!20, !21}
-!21 = !{!"llvm.loop.distribute.enable", i1 true}
+!21 = !{!"llvm.loop.distribute.enable"}
 !22 = !{!"function_entry_count", i64 3}
 !23 = !{!"branch_weights", i32 99, i32 1}
 !24 = !{!"branch_weights", i32 1, i32 99}
diff --git a/llvm/test/Transforms/IRCE/add-metadata-pre-post-loops.ll 
b/llvm/test/Transforms/IRCE/add-metadata-pre-post-loops.ll
index eb72907730c6d..3a360814e361e 100644
--- a/llvm/test/Transforms/IRCE/add-metadata-pre-post-loops.ll
+++ b/llvm/test/Transforms/IRCE/add-metadata-pre-post-loops.ll
@@ -76,7 +76,7 @@ attributes #0 = { alwaysinline }
 !3 = !{!"llvm.loop.unroll.disable"}
 !4 = !{!"llvm.loop.vectorize.enable", i1 false}
 !5 = !{!"llvm.loop.licm_versioning.disable"}
-!6 = !{!"llvm.loop.distribute.enable", i1 false}
+!6 = !{!"llvm.loop.distribute.disable"}
 !7 = !{}
 !8 = distinct !{!8, !3, !4, !5}
 !9 = distinct !{!9, !3, !4, !5}
diff --git a/llvm/test/Transforms/IRCE/correct-loop-info.ll 
b/llvm/test/Transforms/IRCE/correct-loop-info.ll
index 7ea445718289a..bc5987ebba2e4 100644
--- a/llvm/test/Transforms/IRCE/correct-loop-info.ll
+++ b/llvm/test/Transforms/IRCE/correct-loop-info.ll
@@ -178,6 +178,6 @@ declare void @pluto()
 !1 = !{!"llvm.loop.unroll.disable"}
 !2 = !{!"llvm.loop.vectorize.enable", i1 false}
 !3 = !{!"llvm.loop.licm_versioning.disable"}
-!4 = !{!"llvm.loop.distribute.enable", i1 false}
+!4 = !{!"llvm.loop.distribute.disable"}
 !5 = !{}
 !6 = distinct !{!6, !1, !2, !3, !4}
diff --git a/llvm/test/Transforms/IRCE/loop-guarded-bounds.ll 
b/llvm/test/Transforms/IRCE/loop-guarded-bounds.ll
index ea169987cf2fc..61cfef6f1492a 100644
--- a/llvm/test/Transforms/IRCE/loop-guarded-bounds.ll
+++ b/llvm/test/Transforms/IRCE/loop-guarded-bounds.ll
@@ -130,7 +130,7 @@ exit:                                       ; preds = 
%guarded, %loop_, %prehead
 ; CHECK: [[META1]] = !{!"llvm.loop.unroll.disable"}
 ; CHECK: [[META2]] = !{!"llvm.loop.vectorize.enable", i1 false}
 ; CHECK: [[META3]] = !{!"llvm.loop.licm_versioning.disable"}
-; CHECK: [[META4]] = !{!"llvm.loop.distribute.enable", i1 false}
+; CHECK: [[META4]] = !{!"llvm.loop.distribute.disable"}
 ; CHECK: [[META5]] = !{}
 ; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]], [[META2]], [[META3]], 
[[META4]]}
 ;.
diff --git a/llvm/test/Transforms/IRCE/pre_post_loops.ll 
b/llvm/test/Transforms/IRCE/pre_post_loops.ll
index da2faa34719af..2807adba35940 100644
--- a/llvm/test/Transforms/IRCE/pre_post_loops.ll
+++ b/llvm/test/Transforms/IRCE/pre_post_loops.ll
@@ -163,7 +163,7 @@ exit:
 ; CHECK: [[META2]] = !{!"llvm.loop.unroll.disable"}
 ; CHECK: [[META3]] = !{!"llvm.loop.vectorize.enable", i1 false}
 ; CHECK: [[META4]] = !{!"llvm.loop.licm_versioning.disable"}
-; CHECK: [[META5]] = !{!"llvm.loop.distribute.enable", i1 false}
+; CHECK: [[META5]] = !{!"llvm.loop.distribute.disable"}
 ; CHECK: [[META6]] = !{}
 ; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META3]], [[META4]], 
[[META5]]}
 ;.
diff --git a/llvm/test/Transforms/IRCE/range_intersect_miscompile.ll 
b/llvm/test/Transforms/IRCE/range_intersect_miscompile.ll
index 68613feacba32..2e21bb5ad0bd0 100644
--- a/llvm/test/Transforms/IRCE/range_intersect_miscompile.ll
+++ b/llvm/test/Transforms/IRCE/range_intersect_miscompile.ll
@@ -490,7 +490,7 @@ deopt:                                          ; preds = 
%range_check_block
 ; CHECK: [[META1]] = !{!"llvm.loop.unroll.disable"}
 ; CHECK: [[META2]] = !{!"llvm.loop.vectorize.enable", i1 false}
 ; CHECK: [[META3]] = !{!"llvm.loop.licm_versioning.disable"}
-; CHECK: [[META4]] = !{!"llvm.loop.distribute.enable", i1 false}
+; CHECK: [[META4]] = !{!"llvm.loop.distribute.disable"}
 ; CHECK: [[META5]] = !{}
 ; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]], [[META2]], [[META3]], 
[[META4]]}
 ; CHECK: [[RNG7]] = !{i32 0, i32 50}
diff --git a/llvm/test/Transforms/IRCE/unsigned_comparisons_ugt.ll 
b/llvm/test/Transforms/IRCE/unsigned_comparisons_ugt.ll
index 7236cf4817ade..cdd7235ac45b4 100644
--- a/llvm/test/Transforms/IRCE/unsigned_comparisons_ugt.ll
+++ b/llvm/test/Transforms/IRCE/unsigned_comparisons_ugt.ll
@@ -447,7 +447,7 @@ exit:
 ; CHECK: [[META2]] = !{!"llvm.loop.unroll.disable"}
 ; CHECK: [[META3]] = !{!"llvm.loop.vectorize.enable", i1 false}
 ; CHECK: [[META4]] = !{!"llvm.loop.licm_versioning.disable"}
-; CHECK: [[META5]] = !{!"llvm.loop.distribute.enable", i1 false}
+; CHECK: [[META5]] = !{!"llvm.loop.distribute.disable"}
 ; CHECK: [[META6]] = !{}
 ; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META3]], [[META4]], 
[[META5]]}
 ; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META2]], [[META3]], [[META4]], 
[[META5]]}
diff --git a/llvm/test/Transforms/IRCE/unsigned_comparisons_ult.ll 
b/llvm/test/Transforms/IRCE/unsigned_comparisons_ult.ll
index 546e1b0faa1c3..107a3554282ad 100644
--- a/llvm/test/Transforms/IRCE/unsigned_comparisons_ult.ll
+++ b/llvm/test/Transforms/IRCE/unsigned_comparisons_ult.ll
@@ -654,7 +654,7 @@ exit:
 ; CHECK: [[META2]] = !{!"llvm.loop.unroll.disable"}
 ; CHECK: [[META3]] = !{!"llvm.loop.vectorize.enable", i1 false}
 ; CHECK: [[META4]] = !{!"llvm.loop.licm_versioning.disable"}
-; CHECK: [[META5]] = !{!"llvm.loop.distribute.enable", i1 false}
+; CHECK: [[META5]] = !{!"llvm.loop.distribute.disable"}
 ; CHECK: [[META6]] = !{}
 ; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META3]], [[META4]], 
[[META5]]}
 ; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META2]], [[META3]], [[META4]], 
[[META5]]}
diff --git a/llvm/test/Transforms/Inline/dilocation-loop-metadata-update.ll 
b/llvm/test/Transforms/Inline/dilocation-loop-metadata-update.ll
index 1bc132663331b..0d8dcfbcf2a8b 100644
--- a/llvm/test/Transforms/Inline/dilocation-loop-metadata-update.ll
+++ b/llvm/test/Transforms/Inline/dilocation-loop-metadata-update.ll
@@ -47,7 +47,7 @@ entry:
 !7 = !DILocation(line: 6, column: 3, scope: !3)
 !8 = !DILocation(line: 7, column: 22, scope: !3)
 !9 = !{!"llvm.loop.mustprogress"}
-!10 = !{!"llvm.loop.distribute.enable", i1 true}
+!10 = !{!"llvm.loop.distribute.enable"}
 !11 = !{!"llvm.loop.distribute.followup_all", !7, !8, !9, !12, !13, !14}
 !12 = !{!"llvm.loop.vectorize.width", i32 8}
 !13 = !{!"llvm.loop.vectorize.enable", i1 true}
@@ -66,7 +66,7 @@ entry:
 ; CHECK: [[META7]] = !DILocation(line: 6, column: 3, scope: [[DBG3]])
 ; CHECK: [[META8]] = !DILocation(line: 7, column: 22, scope: [[DBG3]])
 ; CHECK: [[META9]] = !{!"llvm.loop.mustprogress"}
-; CHECK: [[META10]] = !{!"llvm.loop.distribute.enable", i1 true}
+; CHECK: [[META10]] = !{!"llvm.loop.distribute.enable"}
 ; CHECK: [[META11]] = !{!"llvm.loop.distribute.followup_all", [[META7]], 
[[META8]], [[META9]], [[META12:![0-9]+]], [[META13:![0-9]+]], 
[[META14:![0-9]+]]}
 ; CHECK: [[META12]] = !{!"llvm.loop.vectorize.width", i32 8}
 ; CHECK: [[META13]] = !{!"llvm.loop.vectorize.enable", i1 true}
diff --git a/llvm/test/Transforms/LoopDistribute/basic-with-memchecks.ll 
b/llvm/test/Transforms/LoopDistribute/basic-with-memchecks.ll
index 2828882afe779..dcd231a900ee2 100644
--- a/llvm/test/Transforms/LoopDistribute/basic-with-memchecks.ll
+++ b/llvm/test/Transforms/LoopDistribute/basic-with-memchecks.ll
@@ -288,5 +288,5 @@ attributes #0 = { nounwind readnone convergent }
 attributes #1 = { nounwind convergent }
 
 !0 = distinct !{!0, !1}
-!1 = !{!"llvm.loop.distribute.enable", i1 true}
+!1 = !{!"llvm.loop.distribute.enable"}
 ; CHECK: ![[PROF1]] = !{!"unknown", !"loop-versioning"}
diff --git a/llvm/test/Transforms/LoopDistribute/diagnostics-with-hotness.ll 
b/llvm/test/Transforms/LoopDistribute/diagnostics-with-hotness.ll
index b5ef3578eadd9..4f2f76191e615 100644
--- a/llvm/test/Transforms/LoopDistribute/diagnostics-with-hotness.ll
+++ b/llvm/test/Transforms/LoopDistribute/diagnostics-with-hotness.ll
@@ -74,7 +74,7 @@ for.cond.cleanup:
 !18 = !DILocation(line: 4, column: 5, scope: !7)
 !19 = !DILocation(line: 4, column: 10, scope: !7)
 !20 = distinct !{!20, !21}
-!21 = !{!"llvm.loop.distribute.enable", i1 true}
+!21 = !{!"llvm.loop.distribute.enable"}
 !22 = !{!"function_entry_count", i64 3}
 !23 = !{!"branch_weights", i32 2000, i32 1}
 !24 = !{!"branch_weights", i32 1, i32 99}
diff --git a/llvm/test/Transforms/LoopDistribute/diagnostics.ll 
b/llvm/test/Transforms/LoopDistribute/diagnostics.ll
index e6a0d83bd63d2..80b217d0abb2b 100644
--- a/llvm/test/Transforms/LoopDistribute/diagnostics.ll
+++ b/llvm/test/Transforms/LoopDistribute/diagnostics.ll
@@ -194,7 +194,7 @@ attributes #1 = { nounwind convergent }
 !18 = !DILocation(line: 4, column: 5, scope: !7)
 !19 = !DILocation(line: 4, column: 10, scope: !7)
 !20 = distinct !{!20, !21}
-!21 = !{!"llvm.loop.distribute.enable", i1 true}
+!21 = !{!"llvm.loop.distribute.enable"}
 !22 = distinct !DISubprogram(name: "not_forced", scope: !1, file: !1, line: 8, 
type: !8, isLocal: false, isDefinition: true, scopeLine: 8, flags: 
DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
 !23 = !DILocation(line: 9, column: 20, scope: !22)
 !24 = !DILocation(line: 9, column: 3, scope: !22)
diff --git a/llvm/test/Transforms/LoopDistribute/disable_nonforced_enable.ll 
b/llvm/test/Transforms/LoopDistribute/disable_nonforced_enable.ll
index 45a2d31256a27..eff1621cd7ada 100644
--- a/llvm/test/Transforms/LoopDistribute/disable_nonforced_enable.ll
+++ b/llvm/test/Transforms/LoopDistribute/disable_nonforced_enable.ll
@@ -43,4 +43,4 @@ for.end:
   ret void
 }
 
-!0 = distinct !{!0, !{!"llvm.loop.disable_nonforced"}, 
!{!"llvm.loop.distribute.enable", i32 1}}
+!0 = distinct !{!0, !{!"llvm.loop.disable_nonforced"}, 
!{!"llvm.loop.distribute.enable"}}
diff --git a/llvm/test/Transforms/LoopDistribute/early-exit.ll 
b/llvm/test/Transforms/LoopDistribute/early-exit.ll
index 9353d842523f4..d2ad9b1bcd6c5 100644
--- a/llvm/test/Transforms/LoopDistribute/early-exit.ll
+++ b/llvm/test/Transforms/LoopDistribute/early-exit.ll
@@ -89,4 +89,4 @@ attributes #0 = { nounwind readnone convergent }
 attributes #1 = { nounwind convergent }
 
 !0 = distinct !{!0, !1}
-!1 = !{!"llvm.loop.distribute.enable", i1 true}
+!1 = !{!"llvm.loop.distribute.enable"}
diff --git a/llvm/test/Transforms/LoopDistribute/followup.ll 
b/llvm/test/Transforms/LoopDistribute/followup.ll
index ae418ad9e6b42..2753bad5e1c1e 100644
--- a/llvm/test/Transforms/LoopDistribute/followup.ll
+++ b/llvm/test/Transforms/LoopDistribute/followup.ll
@@ -125,7 +125,7 @@ for.end:
 }
 
 !0 = distinct !{!0, !1, !2, !3, !4, !5}
-!1 = !{!"llvm.loop.distribute.enable", i1 true}
+!1 = !{!"llvm.loop.distribute.enable"}
 !2 = !{!"llvm.loop.distribute.followup_all", !{!"FollowupAll"}}
 !3 = !{!"llvm.loop.distribute.followup_coincident", !{!"FollowupCoincident", 
i1 false}}
 !4 = !{!"llvm.loop.distribute.followup_sequential", !{!"FollowupSequential", 
i32 8}}
diff --git a/llvm/test/Transforms/LoopDistribute/metadata.ll 
b/llvm/test/Transforms/LoopDistribute/metadata.ll
index b0e461fe0ea75..8b74ac4249550 100644
--- a/llvm/test/Transforms/LoopDistribute/metadata.ll
+++ b/llvm/test/Transforms/LoopDistribute/metadata.ll
@@ -131,6 +131,6 @@ for.end:                                          ; preds = 
%for.body
 }
 
 !0 = distinct !{!0, !1}
-!1 = !{!"llvm.loop.distribute.enable", i1 true}
+!1 = !{!"llvm.loop.distribute.enable"}
 !2 = distinct !{!2, !3}
-!3 = !{!"llvm.loop.distribute.enable", i1 false}
+!3 = !{!"llvm.loop.distribute.disable"}
diff --git a/llvm/test/Transforms/LoopSimplify/preserve-llvm-loop-metadata.ll 
b/llvm/test/Transforms/LoopSimplify/preserve-llvm-loop-metadata.ll
index 2c1dff7ee5a5f..049880a97a211 100644
--- a/llvm/test/Transforms/LoopSimplify/preserve-llvm-loop-metadata.ll
+++ b/llvm/test/Transforms/LoopSimplify/preserve-llvm-loop-metadata.ll
@@ -65,6 +65,6 @@ cleanup:                                          ; preds = 
%cleanup.loopexit, %
 }
 
 !0 = distinct !{!0, !1}
-!1 = !{!"llvm.loop.distribute.enable", i1 true}
+!1 = !{!"llvm.loop.distribute.enable"}
 ; CHECK: !0 = distinct !{!0, !1}
-; CHECK: !1 = !{!"llvm.loop.distribute.enable", i1 true}
+; CHECK: !1 = !{!"llvm.loop.distribute.enable"}
diff --git a/llvm/test/Transforms/SimplifyCFG/preserve-llvm-loop-metadata.ll 
b/llvm/test/Transforms/SimplifyCFG/preserve-llvm-loop-metadata.ll
index 8b3bdbee2249c..d565b860a9ef6 100644
--- a/llvm/test/Transforms/SimplifyCFG/preserve-llvm-loop-metadata.ll
+++ b/llvm/test/Transforms/SimplifyCFG/preserve-llvm-loop-metadata.ll
@@ -147,7 +147,7 @@ while.end:                                        ; preds = 
%while.cond
 
 !0 = !{i32 2, !"Debug Info Version", i32 3}
 !1 = distinct !{!1, !2}
-!2 = !{!"llvm.loop.distribute.enable", i1 true}
+!2 = !{!"llvm.loop.distribute.enable"}
 !3 = distinct !{!3, !4}
 !4 = !{!"llvm.loop.mustprogress"}
 !5 = distinct !{!5, !4, !6}
@@ -161,7 +161,7 @@ while.end:                                        ; preds = 
%while.cond
 !13 = !DILocation(line: 9, column: 23, scope: !12)
 
 ; CHECK: !1 = distinct !{!1, !2}
-; CHECK: !2 = !{!"llvm.loop.distribute.enable", i1 true}
+; CHECK: !2 = !{!"llvm.loop.distribute.enable"}
 ; CHECK: !3 = distinct !{!3, !4}
 ; CHECK: !4 = !{!"llvm.loop.mustprogress"}
 ; CHECK: !5 = distinct !{!5, !4, !6}
diff --git a/llvm/test/Verifier/llvm.loop.distribute.ll 
b/llvm/test/Verifier/llvm.loop.distribute.ll
new file mode 100644
index 0000000000000..9e1e8138e93dc
--- /dev/null
+++ b/llvm/test/Verifier/llvm.loop.distribute.ll
@@ -0,0 +1,49 @@
+; Test "llvm.loop.distribute.enable" / "llvm.loop.distribute.disable"
+; single-operand validation.
+
+; DEFINE: %{RUN} = opt -passes=verify %t -disable-output 2>&1 | \
+; DEFINE:   FileCheck %s -allow-empty -check-prefix
+
+define void @test() {
+entry:
+  br label %body
+body:
+  br i1 0, label %body, label %exit, !llvm.loop !0
+exit:
+  ret void
+}
+!0 = distinct !{!0, !1}
+
+; GOOD-NOT: {{.}}
+
+;      BAD: Expected one operand for llvm.loop.distribute metadata
+
+; Single-operand enable.
+; RUN: cp %s %t
+; RUN: chmod u+w %t
+; RUN: echo '!1 = !{!"llvm.loop.distribute.enable"}' >> %t
+; RUN: %{RUN} GOOD
+
+; Single-operand disable.
+; RUN: cp %s %t
+; RUN: chmod u+w %t
+; RUN: echo '!1 = !{!"llvm.loop.distribute.disable"}' >> %t
+; RUN: %{RUN} GOOD
+
+; Two-operand enable with boolean false (legacy form, now rejected).
+; RUN: cp %s %t
+; RUN: chmod u+w %t
+; RUN: echo '!1 = !{!"llvm.loop.distribute.enable", i1 0}' >> %t
+; RUN: not %{RUN} BAD
+
+; Two-operand enable with boolean true (legacy form, now rejected).
+; RUN: cp %s %t
+; RUN: chmod u+w %t
+; RUN: echo '!1 = !{!"llvm.loop.distribute.enable", i1 1}' >> %t
+; RUN: not %{RUN} BAD
+
+; Two-operand disable (rejected).
+; RUN: cp %s %t
+; RUN: chmod u+w %t
+; RUN: echo '!1 = !{!"llvm.loop.distribute.disable", i1 0}' >> %t
+; RUN: not %{RUN} BAD
diff --git a/llvm/unittests/Analysis/LoopInfoTest.cpp 
b/llvm/unittests/Analysis/LoopInfoTest.cpp
index 4828573c32c10..5321f72aa1784 100644
--- a/llvm/unittests/Analysis/LoopInfoTest.cpp
+++ b/llvm/unittests/Analysis/LoopInfoTest.cpp
@@ -72,7 +72,7 @@ TEST(LoopInfoTest, LoopWithSingleLatch) {
       "  ret void\n"
       "}\n"
       "!0 = distinct !{!0, !1}\n"
-      "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n";
+      "!1 = !{!\"llvm.loop.distribute.enable\"}\n";
 
   // Parse the module.
   LLVMContext Context;
@@ -122,7 +122,7 @@ TEST(LoopInfoTest, LoopWithMultipleLatches) {
       "  ret void\n"
       "}\n"
       "!0 = distinct !{!0, !1}\n"
-      "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n";
+      "!1 = !{!\"llvm.loop.distribute.enable\"}\n";
 
   // Parse the module.
   LLVMContext Context;
@@ -1397,7 +1397,7 @@ TEST(LoopInfoTest, LoopUniqueExitBlocks) {
       "  ret void\n"
       "}\n"
       "!0 = distinct !{!0, !1}\n"
-      "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n";
+      "!1 = !{!\"llvm.loop.distribute.enable\"}\n";
 
   // Parse the module.
   LLVMContext Context;
@@ -1440,7 +1440,7 @@ TEST(LoopInfoTest, LoopNonLatchUniqueExitBlocks) {
       "  ret void\n"
       "}\n"
       "!0 = distinct !{!0, !1}\n"
-      "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n";
+      "!1 = !{!\"llvm.loop.distribute.enable\"}\n";
 
   // Parse the module.
   LLVMContext Context;
diff --git a/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp 
b/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp
index e4905423347a2..4022afc433a61 100644
--- a/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp
@@ -358,8 +358,10 @@ FailureOr<LoopLICMAttr> 
LoopMetadataConversion::convertLICMAttr() {
 }
 
 FailureOr<LoopDistributeAttr> LoopMetadataConversion::convertDistributeAttr() {
-  FailureOr<BoolAttr> disable =
-      lookupBoolNode("llvm.loop.distribute.enable", true);
+  FailureOr<BoolAttr> disable = lookupBooleanUnitNode(
+      "llvm.loop.distribute.enable",
+      "llvm.loop.distribute.disable",
+      /*negated=*/true);
   FailureOr<LoopAnnotationAttr> followupCoincident =
       lookupFollowupNode("llvm.loop.distribute.followup_coincident");
   FailureOr<LoopAnnotationAttr> followupSequential =
diff --git a/mlir/lib/Target/LLVMIR/LoopAnnotationTranslation.cpp 
b/mlir/lib/Target/LLVMIR/LoopAnnotationTranslation.cpp
index f3ec18c9074e4..41ba31106f788 100644
--- a/mlir/lib/Target/LLVMIR/LoopAnnotationTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/LoopAnnotationTranslation.cpp
@@ -162,7 +162,12 @@ void 
LoopAnnotationConversion::convertLoopOptions(LoopLICMAttr options) {
 }
 
 void LoopAnnotationConversion::convertLoopOptions(LoopDistributeAttr options) {
-  convertBoolNode("llvm.loop.distribute.enable", options.getDisable(), true);
+  if (auto disable = options.getDisable()) {
+    if (disable.getValue())
+      addUnitNode("llvm.loop.distribute.disable");
+    else
+      addUnitNode("llvm.loop.distribute.enable");
+  }
   convertFollowupNode("llvm.loop.distribute.followup_coincident",
                       options.getFollowupCoincident());
   convertFollowupNode("llvm.loop.distribute.followup_sequential",
diff --git a/mlir/test/Target/LLVMIR/Import/metadata-loop.ll 
b/mlir/test/Target/LLVMIR/Import/metadata-loop.ll
index c09fe92dc9cdc..021818ded3d3c 100644
--- a/mlir/test/Target/LLVMIR/Import/metadata-loop.ll
+++ b/mlir/test/Target/LLVMIR/Import/metadata-loop.ll
@@ -219,7 +219,7 @@ end:
 }
 
 !1 = distinct !{!1, !2, !3, !4, !5, !6}
-!2 = !{!"llvm.loop.distribute.enable", i1 0}
+!2 = !{!"llvm.loop.distribute.disable"}
 !3 = !{!"llvm.loop.distribute.followup_coincident", !9}
 !4 = !{!"llvm.loop.distribute.followup_sequential", !9}
 !5 = !{!"llvm.loop.distribute.followup_fallback", !9}
diff --git a/mlir/test/Target/LLVMIR/loop-metadata.mlir 
b/mlir/test/Target/LLVMIR/loop-metadata.mlir
index 72f0cf06ed0fe..299bcb481f67f 100644
--- a/mlir/test/Target/LLVMIR/loop-metadata.mlir
+++ b/mlir/test/Target/LLVMIR/loop-metadata.mlir
@@ -185,7 +185,7 @@ 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.enable", i1 false}
+// 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]]}

>From beb17d017d5a38a3226afd1a8997880d3b374093 Mon Sep 17 00:00:00 2001
From: Madhur Amilkanthwar <[email protected]>
Date: Tue, 7 Jul 2026 00:52:57 -0700
Subject: [PATCH 2/3] fixup! Enforce single-operand form for
 llvm.loop.distribute metadata

auto-upgrade old two-operand llvm.loop.distribute.enable metadata
---
 llvm/include/llvm/IR/AutoUpgrade.h            |   7 ++-
 llvm/lib/Bitcode/Reader/MetadataLoader.cpp    |   3 ++
 llvm/lib/IR/AutoUpgrade.cpp                   |  47 ++++++++++++++++--
 .../Bitcode/upgrade-loop-distribute-enable.ll |  37 ++++++++++++++
 .../upgrade-loop-distribute-enable.ll.bc      | Bin 0 -> 2080 bytes
 llvm/test/Verifier/llvm.loop.distribute.ll    |  30 ++++-------
 6 files changed, 101 insertions(+), 23 deletions(-)
 create mode 100644 llvm/test/Bitcode/upgrade-loop-distribute-enable.ll
 create mode 100644 llvm/test/Bitcode/upgrade-loop-distribute-enable.ll.bc

diff --git a/llvm/include/llvm/IR/AutoUpgrade.h 
b/llvm/include/llvm/IR/AutoUpgrade.h
index feb19e69389a9..423fea4205a80 100644
--- a/llvm/include/llvm/IR/AutoUpgrade.h
+++ b/llvm/include/llvm/IR/AutoUpgrade.h
@@ -112,7 +112,12 @@ namespace llvm {
 
   /// Check whether a string looks like an old loop attachment tag.
   inline bool mayBeOldLoopAttachmentTag(StringRef Name) {
-    return Name.starts_with("llvm.vectorizer.");
+    // "llvm.loop.distribute.enable" is intentionally included: the current
+    // single-operand form shares the tag with the removed two-operand form
+    // (!{!"llvm.loop.distribute.enable", i1 X}), so we can only decide by
+    // inspecting the operands, which happens in upgradeLoopArgument().
+    return Name.starts_with("llvm.vectorizer.") ||
+           Name == "llvm.loop.distribute.enable";
   }
 
   /// Upgrade the loop attachment metadata node.
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp 
b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 33062a0256bb8..5c4f8cb9fbeb1 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -2455,6 +2455,9 @@ Error 
MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
   }
   case bitc::METADATA_STRINGS: {
     auto CreateNextMDString = [&](StringRef Str) {
+      // Modern bitcode encodes MDStrings via this bulk record, so mirror the
+      // METADATA_STRING check above to arm the loop-attachment upgrader.
+      HasSeenOldLoopTags |= mayBeOldLoopAttachmentTag(Str);
       ++NumMDStringLoaded;
       MetadataList.assignValue(MDString::get(Context, Str), NextMetadataNo);
       NextMetadataNo++;
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 229c7757db3dc..2cd42c0822b6c 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -6847,6 +6847,18 @@ void llvm::copyModuleAttrToFunctions(Module &M) {
   }
 }
 
+// Old two-operand form: !{!"llvm.loop.distribute.enable", i1 X}. The new
+// single-operand form uses "llvm.loop.distribute.enable" for X = true and
+// "llvm.loop.distribute.disable" for X = false.
+static bool isOldDistributeEnable(const MDTuple *T) {
+  if (T->getNumOperands() != 2)
+    return false;
+  auto *Tag = dyn_cast_or_null<MDString>(T->getOperand(0));
+  if (!Tag || Tag->getString() != "llvm.loop.distribute.enable")
+    return false;
+  return mdconst::hasa<ConstantInt>(T->getOperand(1));
+}
+
 static bool isOldLoopArgument(Metadata *MD) {
   auto *T = dyn_cast_or_null<MDTuple>(MD);
   if (!T)
@@ -6856,7 +6868,9 @@ static bool isOldLoopArgument(Metadata *MD) {
   auto *S = dyn_cast_or_null<MDString>(T->getOperand(0));
   if (!S)
     return false;
-  return S->getString().starts_with("llvm.vectorizer.");
+  if (S->getString().starts_with("llvm.vectorizer."))
+    return true;
+  return isOldDistributeEnable(T);
 }
 
 static MDString *upgradeLoopTag(LLVMContext &C, StringRef OldTag) {
@@ -6880,17 +6894,28 @@ static Metadata *upgradeLoopArgument(Metadata *MD) {
   auto *OldTag = dyn_cast_or_null<MDString>(T->getOperand(0));
   if (!OldTag)
     return MD;
+
+  LLVMContext &C = T->getContext();
+
+  // Rewrite the old two-operand distribute form to the single-operand pair.
+  if (isOldDistributeEnable(T)) {
+    bool Enable = !mdconst::extract<ConstantInt>(T->getOperand(1))->isZero();
+    return MDTuple::get(
+        C, {MDString::get(C, Enable ? "llvm.loop.distribute.enable"
+                                    : "llvm.loop.distribute.disable")});
+  }
+
   if (!OldTag->getString().starts_with("llvm.vectorizer."))
     return MD;
 
   // This has an old tag.  Upgrade it.
   SmallVector<Metadata *, 8> Ops;
   Ops.reserve(T->getNumOperands());
-  Ops.push_back(upgradeLoopTag(T->getContext(), OldTag->getString()));
+  Ops.push_back(upgradeLoopTag(C, OldTag->getString()));
   for (unsigned I = 1, E = T->getNumOperands(); I != E; ++I)
     Ops.push_back(T->getOperand(I));
 
-  return MDTuple::get(T->getContext(), Ops);
+  return MDTuple::get(C, Ops);
 }
 
 MDNode *llvm::upgradeInstructionLoopAttachment(MDNode &N) {
@@ -6901,6 +6926,22 @@ MDNode *llvm::upgradeInstructionLoopAttachment(MDNode 
&N) {
   if (none_of(T->operands(), isOldLoopArgument))
     return &N;
 
+  // Fix the old two-operand llvm.loop.distribute.enable nodes in place: the
+  // Verifier rejects any MDNode carrying the distribute tag with more than one
+  // operand, so a leftover reference (from the distinct loop-ID) would still
+  // trigger a diagnostic. In-place mutation is safe on distinct MDNodes.
+  if (T->isDistinct()) {
+    for (unsigned I = 0, E = T->getNumOperands(); I < E; ++I) {
+      auto *OpT = dyn_cast_or_null<MDTuple>(T->getOperand(I));
+      if (OpT && isOldDistributeEnable(OpT))
+        T->replaceOperandWith(I, upgradeLoopArgument(OpT));
+    }
+    if (none_of(T->operands(), isOldLoopArgument))
+      return &N;
+  }
+
+  // Remaining old arguments (e.g. llvm.vectorizer.*) are handled via a wrapper
+  // attachment; the original distinct loop-ID is kept as the first operand.
   SmallVector<Metadata *, 8> Ops;
   Ops.reserve(T->getNumOperands());
   for (Metadata *MD : T->operands())
diff --git a/llvm/test/Bitcode/upgrade-loop-distribute-enable.ll 
b/llvm/test/Bitcode/upgrade-loop-distribute-enable.ll
new file mode 100644
index 0000000000000..8f1b5aec2d140
--- /dev/null
+++ b/llvm/test/Bitcode/upgrade-loop-distribute-enable.ll
@@ -0,0 +1,37 @@
+; Test that older bitcode carrying the two-operand form of
+; "llvm.loop.distribute.enable" is auto-upgraded to the single-operand
+; enable/disable pair on load.
+;
+; RUN: llvm-dis < %s.bc | FileCheck %s
+; RUN: verify-uselistorder < %s.bc
+
+define void @enable_true() {
+entry:
+  br label %body
+body:
+  br i1 0, label %body, label %exit, !llvm.loop !0
+exit:
+  ret void
+}
+
+define void @enable_false() {
+entry:
+  br label %body
+body:
+  br i1 0, label %body, label %exit, !llvm.loop !2
+exit:
+  ret void
+}
+
+; i1 true  -> single-operand enable.
+; i1 false -> disable.
+; CHECK: !{!"llvm.loop.distribute.enable"}
+; CHECK: !{!"llvm.loop.distribute.disable"}
+; The old two-operand nodes must be gone from the module.
+; CHECK-NOT: llvm.loop.distribute.enable", i1
+; CHECK-NOT: llvm.loop.distribute.disable", i1
+
+!0 = distinct !{!0, !1}
+!1 = !{!"llvm.loop.distribute.enable", i1 true}
+!2 = distinct !{!2, !3}
+!3 = !{!"llvm.loop.distribute.enable", i1 false}
diff --git a/llvm/test/Bitcode/upgrade-loop-distribute-enable.ll.bc 
b/llvm/test/Bitcode/upgrade-loop-distribute-enable.ll.bc
new file mode 100644
index 
0000000000000000000000000000000000000000..fdcbda4584522c06b5f5668e53c6c24fede99c65
GIT binary patch
literal 2080
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

literal 0
HcmV?d00001

diff --git a/llvm/test/Verifier/llvm.loop.distribute.ll 
b/llvm/test/Verifier/llvm.loop.distribute.ll
index 9e1e8138e93dc..65ca27720542b 100644
--- a/llvm/test/Verifier/llvm.loop.distribute.ll
+++ b/llvm/test/Verifier/llvm.loop.distribute.ll
@@ -1,8 +1,7 @@
 ; Test "llvm.loop.distribute.enable" / "llvm.loop.distribute.disable"
 ; single-operand validation.
 
-; DEFINE: %{RUN} = opt -passes=verify %t -disable-output 2>&1 | \
-; DEFINE:   FileCheck %s -allow-empty -check-prefix
+; DEFINE: %{VERIFY} = llvm-as -disable-output %t 2>&1
 
 define void @test() {
 entry:
@@ -14,36 +13,29 @@ exit:
 }
 !0 = distinct !{!0, !1}
 
-; GOOD-NOT: {{.}}
-
 ;      BAD: Expected one operand for llvm.loop.distribute metadata
 
 ; Single-operand enable.
-; RUN: cp %s %t
-; RUN: chmod u+w %t
+; RUN: cat %s > %t
 ; RUN: echo '!1 = !{!"llvm.loop.distribute.enable"}' >> %t
-; RUN: %{RUN} GOOD
+; RUN: %{VERIFY}
 
 ; Single-operand disable.
-; RUN: cp %s %t
-; RUN: chmod u+w %t
+; RUN: cat %s > %t
 ; RUN: echo '!1 = !{!"llvm.loop.distribute.disable"}' >> %t
-; RUN: %{RUN} GOOD
+; RUN: %{VERIFY}
 
 ; Two-operand enable with boolean false (legacy form, now rejected).
-; RUN: cp %s %t
-; RUN: chmod u+w %t
+; RUN: cat %s > %t
 ; RUN: echo '!1 = !{!"llvm.loop.distribute.enable", i1 0}' >> %t
-; RUN: not %{RUN} BAD
+; RUN: not %{VERIFY} | FileCheck %s -check-prefix=BAD
 
 ; Two-operand enable with boolean true (legacy form, now rejected).
-; RUN: cp %s %t
-; RUN: chmod u+w %t
+; RUN: cat %s > %t
 ; RUN: echo '!1 = !{!"llvm.loop.distribute.enable", i1 1}' >> %t
-; RUN: not %{RUN} BAD
+; RUN: not %{VERIFY} | FileCheck %s -check-prefix=BAD
 
 ; Two-operand disable (rejected).
-; RUN: cp %s %t
-; RUN: chmod u+w %t
+; RUN: cat %s > %t
 ; RUN: echo '!1 = !{!"llvm.loop.distribute.disable", i1 0}' >> %t
-; RUN: not %{RUN} BAD
+; RUN: not %{VERIFY} | FileCheck %s -check-prefix=BAD

>From e4f257b97ca79e0df10d1623f9462e7b390f369d Mon Sep 17 00:00:00 2001
From: Madhur Amilkanthwar <[email protected]>
Date: Tue, 7 Jul 2026 09:47:40 -0700
Subject: [PATCH 3/3] fixup! LangRef changes

---
 llvm/docs/LangRef.rst | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 9d37207753686..9e31caa1aa8b2 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -8385,17 +8385,16 @@ this is only performed if the entire loop cannot be 
vectorized due to unsafe
 memory dependencies.  The transformation will attempt to isolate the unsafe
 dependencies into their own loop.
 
-This metadata can be used to selectively enable or disable
-distribution of the loop.  Each node has a single operand
-containing the name string:
+This metadata can be used to selectively enable or disable distribution of the
+loop.  Each node has a single operand containing the name string:
 
 .. code-block:: llvm
 
    !0 = !{!"llvm.loop.distribute.enable"}
    !1 = !{!"llvm.loop.distribute.disable"}
 
-This metadata should be used in conjunction with ``llvm.loop``
-loop identification metadata.
+This metadata should be used in conjunction with ``llvm.loop`` loop
+identification metadata.
 
 '``llvm.loop.distribute.followup_coincident``' Metadata
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to