[llvm] [LoopVectorize] Add llvm.loop.vectorize.fp_reordering.{enable,disable} metadata (PR #219167)

Karthika Devi C via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 9 00:31:07 PDT 2026


https://github.com/kartcq updated https://github.com/llvm/llvm-project/pull/219167

>From 7dd426dd24b5496c1f59de9bf1eadcd16d1db74f Mon Sep 17 00:00:00 2001
From: Karthika Devi C <kartc at qti.qualcomm.com>
Date: Thu, 27 Aug 2026 02:40:40 -0700
Subject: [PATCH 1/4] [LoopVectorize] Add llvm.loop.vectorize.fp_reordering
 metadata

Add a new per-loop metadata key llvm.loop.vectorize.fp_reordering that
takes a boolean operand to explicitly control whether the Loop Vectorizer
may reorder floating-point operations:

  !{!"llvm.loop.vectorize.fp_reordering", i1 true}   ; reordering allowed
  !{!"llvm.loop.vectorize.fp_reordering", i1 false}  ; reordering suppressed

When absent, allowReordering() retains its existing behaviour: vectorize.enable
or an explicit vector width > 1 grants FP reordering. When present, the value
takes precedence over that default.

This is the infrastructure patch for a proper long-term fix for #205756.

Refer #198726
---
 llvm/docs/LangRef.md                             | 16 ++++++++++++++++
 .../Vectorize/LoopVectorizationLegality.h        | 12 ++++++++++++
 .../Vectorize/LoopVectorizationLegality.cpp      |  9 ++++++++-
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/llvm/docs/LangRef.md b/llvm/docs/LangRef.md
index 139c0501d410a..3dc2ba6a00a97 100644
--- a/llvm/docs/LangRef.md
+++ b/llvm/docs/LangRef.md
@@ -8101,6 +8101,22 @@ node has a single operand containing the name string:
 !1 = !{!"llvm.loop.vectorize.disable"}
 ```
 
+When `llvm.loop.vectorize.enable` is present, the Loop Vectorizer is also
+permitted to reorder floating-point operations by default (equivalent to the
+behaviour of `#pragma clang loop vectorize(enable)`). This default can be
+overridden per-loop using `llvm.loop.vectorize.fp_reordering` (see below).
+
+#### '`llvm.loop.vectorize.fp_reordering`' Metadata
+
+This metadata gives the Loop Vectorizer an explicit per-loop instruction about
+whether floating-point operation reordering (reassociation) is permitted. It
+takes a single boolean operand:
+
+```llvm
+!0 = !{!"llvm.loop.vectorize.fp_reordering", i1 true}   ; reordering allowed
+!1 = !{!"llvm.loop.vectorize.fp_reordering", i1 false}  ; reordering suppressed
+```
+
 #### '`llvm.loop.vectorize.predicate.enable`' and '`llvm.loop.vectorize.predicate.disable`' Metadata
 
 This metadata selectively enables or disables creating predicated instructions
diff --git a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
index 7b8b27c6541e1..7bfa8cd3626d2 100644
--- a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
+++ b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
@@ -92,6 +92,13 @@ class LoopVectorizeHints {
   /// a plain value because the enable/disable pair has no operand to validate.
   unsigned Scalable;
 
+  /// FP reordering hint from llvm.loop.vectorize.fp_reordering; one of
+  /// ForceKind, carried as a plain unsigned like Force and Predicate.
+  ///   FK_Undefined : not specified
+  ///   FK_Disabled  : reordering explicitly suppressed
+  ///   FK_Enabled   : reordering explicitly allowed
+  unsigned FPReordering;
+
   /// Return the loop metadata prefix.
   static StringRef Prefix() { return "llvm.loop."; }
 
@@ -175,6 +182,11 @@ class LoopVectorizeHints {
   /// error accumulates in the loop.
   LLVM_ABI bool allowReordering() const;
 
+  /// \return the per-loop FP reordering hint as a ForceKind:
+  enum ForceKind getFPReordering() const {
+    return (ForceKind)FPReordering;
+  }
+
   bool isPotentiallyUnsafe() const {
     // Avoid FP vectorization if the target is unsure about proper support.
     // This may be related to the SIMD unit in the target not handling
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index f1d785b571367..dbc53730998cd 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -104,7 +104,8 @@ LoopVectorizeHints::LoopVectorizeHints(const Loop *L,
             VectorizerParams::VectorizationFactor.getKnownMinValue(), HK_WIDTH),
       Interleave("interleave.count", InterleaveOnlyWhenForced, HK_INTERLEAVE),
       Force(FK_Undefined), IsVectorized("isvectorized", 0, HK_ISVECTORIZED),
-      Predicate(FK_Undefined), Scalable(SK_Unspecified), TheLoop(L), ORE(ORE) {
+      Predicate(FK_Undefined), Scalable(SK_Unspecified),
+      FPReordering(FK_Undefined), TheLoop(L), ORE(ORE) {
   // Populate values with existing loop metadata.
   getHintsFromMetadata();
 
@@ -243,6 +244,9 @@ void LoopVectorizeHints::emitRemarkWithHints() const {
 bool LoopVectorizeHints::allowReordering() const {
   // Allow the vectorizer to change the order of operations if enabling
   // loop hints are provided
+  if ((ForceKind)FPReordering != FK_Undefined)
+    return HintsAllowReordering && ((ForceKind)FPReordering == FK_Enabled);
+
   ElementCount EC = getWidth();
   return HintsAllowReordering &&
          (getForce() == LoopVectorizeHints::FK_Enabled ||
@@ -322,6 +326,9 @@ void LoopVectorizeHints::setHint(StringRef Name, Metadata *Arg) {
       break;
     }
   }
+
+  if (Name == "vectorize.fp_reordering")
+    FPReordering = (Val != 0) ? FK_Enabled : FK_Disabled;
 }
 
 // Return true if the inner loop \p Lp is uniform with regard to the outer loop

>From 4cd404f5c15156eecc5b2d109c6545e4d8f054d2 Mon Sep 17 00:00:00 2001
From: Karthika Devi C <kartc at qti.qualcomm.com>
Date: Thu, 27 Aug 2026 03:33:26 -0700
Subject: [PATCH 2/4] Fix Formatting

---
 .../llvm/Transforms/Vectorize/LoopVectorizationLegality.h     | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
index 7bfa8cd3626d2..7fcc55ce8348c 100644
--- a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
+++ b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
@@ -183,9 +183,7 @@ class LoopVectorizeHints {
   LLVM_ABI bool allowReordering() const;
 
   /// \return the per-loop FP reordering hint as a ForceKind:
-  enum ForceKind getFPReordering() const {
-    return (ForceKind)FPReordering;
-  }
+  enum ForceKind getFPReordering() const { return (ForceKind)FPReordering; }
 
   bool isPotentiallyUnsafe() const {
     // Avoid FP vectorization if the target is unsure about proper support.

>From a8ea34a314d9fa7b6c1438e15063c96ee036a0a1 Mon Sep 17 00:00:00 2001
From: Karthika Devi C <kartc at qti.qualcomm.com>
Date: Sun, 30 Aug 2026 07:16:11 -0700
Subject: [PATCH 3/4] Convert fp_reordering metadata to single-operand
 enable/disable form

---
 llvm/docs/LangRef.md                                | 13 +++++++------
 .../Vectorize/LoopVectorizationLegality.h           |  5 +++--
 .../Vectorize/LoopVectorizationLegality.cpp         | 12 +++++++-----
 3 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/llvm/docs/LangRef.md b/llvm/docs/LangRef.md
index 3dc2ba6a00a97..94e878f2ddc2f 100644
--- a/llvm/docs/LangRef.md
+++ b/llvm/docs/LangRef.md
@@ -8104,17 +8104,18 @@ node has a single operand containing the name string:
 When `llvm.loop.vectorize.enable` is present, the Loop Vectorizer is also
 permitted to reorder floating-point operations by default (equivalent to the
 behaviour of `#pragma clang loop vectorize(enable)`). This default can be
-overridden per-loop using `llvm.loop.vectorize.fp_reordering` (see below).
+overridden per-loop using `llvm.loop.vectorize.fp_reordering.enable` /
+`llvm.loop.vectorize.fp_reordering.disable` (see below).
 
-#### '`llvm.loop.vectorize.fp_reordering`' Metadata
+#### '`llvm.loop.vectorize.fp_reordering.enable`' and '`llvm.loop.vectorize.fp_reordering.disable`' Metadata
 
 This metadata gives the Loop Vectorizer an explicit per-loop instruction about
-whether floating-point operation reordering (reassociation) is permitted. It
-takes a single boolean operand:
+whether floating-point operation reordering (reassociation) is permitted. Each
+node has a single operand containing the name string:
 
 ```llvm
-!0 = !{!"llvm.loop.vectorize.fp_reordering", i1 true}   ; reordering allowed
-!1 = !{!"llvm.loop.vectorize.fp_reordering", i1 false}  ; reordering suppressed
+!0 = !{!"llvm.loop.vectorize.fp_reordering.enable"}   ; reordering allowed
+!1 = !{!"llvm.loop.vectorize.fp_reordering.disable"}  ; reordering suppressed
 ```
 
 #### '`llvm.loop.vectorize.predicate.enable`' and '`llvm.loop.vectorize.predicate.disable`' Metadata
diff --git a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
index 7fcc55ce8348c..19457a2fb853a 100644
--- a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
+++ b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
@@ -92,8 +92,9 @@ class LoopVectorizeHints {
   /// a plain value because the enable/disable pair has no operand to validate.
   unsigned Scalable;
 
-  /// FP reordering hint from llvm.loop.vectorize.fp_reordering; one of
-  /// ForceKind, carried as a plain unsigned like Force and Predicate.
+  /// FP reordering hint from
+  /// llvm.loop.vectorize.fp_reordering.{enable,disable}; one of ForceKind,
+  /// carried as a plain unsigned like Force and Predicate.
   ///   FK_Undefined : not specified
   ///   FK_Disabled  : reordering explicitly suppressed
   ///   FK_Enabled   : reordering explicitly allowed
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index dbc53730998cd..0dde28c478bb3 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -290,6 +290,10 @@ void LoopVectorizeHints::getHintsFromMetadata() {
         Force = FK_Enabled;
       else if (Name == "llvm.loop.vectorize.disable")
         Force = FK_Disabled;
+      else if (Name == "llvm.loop.vectorize.fp_reordering.enable")
+        FPReordering = FK_Enabled;
+      else if (Name == "llvm.loop.vectorize.fp_reordering.disable")
+        FPReordering = FK_Disabled;
       else if (Name == "llvm.loop.vectorize.predicate.enable")
         Predicate = FK_Enabled;
       else if (Name == "llvm.loop.vectorize.predicate.disable")
@@ -314,8 +318,9 @@ void LoopVectorizeHints::setHint(StringRef Name, Metadata *Arg) {
     return;
   unsigned Val = C->getZExtValue();
 
-  // Force, Predicate, and Scalable are omitted: they are only spelled as
-  // single-operand enable/disable nodes, which never reach setHint().
+  // Force, Predicate, Scalable and FPReordering are omitted: they are only
+  // spelled as single-operand enable/disable nodes, which never reach
+  // setHint().
   Hint *Hints[] = {&Width, &Interleave, &IsVectorized};
   for (auto *H : Hints) {
     if (Name == H->Name) {
@@ -326,9 +331,6 @@ void LoopVectorizeHints::setHint(StringRef Name, Metadata *Arg) {
       break;
     }
   }
-
-  if (Name == "vectorize.fp_reordering")
-    FPReordering = (Val != 0) ? FK_Enabled : FK_Disabled;
 }
 
 // Return true if the inner loop \p Lp is uniform with regard to the outer loop

>From 2bc11776b831b99f03f1419949f0fc977effde72 Mon Sep 17 00:00:00 2001
From: Karthika Devi C <kartc at qti.qualcomm.com>
Date: Wed, 9 Sep 2026 00:27:17 -0700
Subject: [PATCH 4/4] Address review comments: drop unused getter, fix
 HintsAllowReordering override, add tests

---
 .../Vectorize/LoopVectorizationLegality.h     |  3 -
 .../Vectorize/LoopVectorizationLegality.cpp   |  2 +-
 .../LoopVectorize/fp-reordering-metadata.ll   | 79 +++++++++++++++++++
 3 files changed, 80 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/Transforms/LoopVectorize/fp-reordering-metadata.ll

diff --git a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
index 19457a2fb853a..973903471792e 100644
--- a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
+++ b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
@@ -183,9 +183,6 @@ class LoopVectorizeHints {
   /// error accumulates in the loop.
   LLVM_ABI bool allowReordering() const;
 
-  /// \return the per-loop FP reordering hint as a ForceKind:
-  enum ForceKind getFPReordering() const { return (ForceKind)FPReordering; }
-
   bool isPotentiallyUnsafe() const {
     // Avoid FP vectorization if the target is unsure about proper support.
     // This may be related to the SIMD unit in the target not handling
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
index 0dde28c478bb3..5d011e19f736b 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
@@ -245,7 +245,7 @@ bool LoopVectorizeHints::allowReordering() const {
   // Allow the vectorizer to change the order of operations if enabling
   // loop hints are provided
   if ((ForceKind)FPReordering != FK_Undefined)
-    return HintsAllowReordering && ((ForceKind)FPReordering == FK_Enabled);
+    return (ForceKind)FPReordering == FK_Enabled;
 
   ElementCount EC = getWidth();
   return HintsAllowReordering &&
diff --git a/llvm/test/Transforms/LoopVectorize/fp-reordering-metadata.ll b/llvm/test/Transforms/LoopVectorize/fp-reordering-metadata.ll
new file mode 100644
index 0000000000000..3bb668630f734
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/fp-reordering-metadata.ll
@@ -0,0 +1,79 @@
+; RUN: opt -passes='loop-vectorize' -force-vector-width=4 -S < %s 2>&1 | FileCheck %s
+
+; Tests for llvm.loop.vectorize.fp_reordering metadata.
+
+; Test 1: vectorize.enable only — default, FP reordering allowed.
+; CHECK-LABEL: @fp_reduction_enable_only
+; CHECK: vector.body
+; CHECK: call float @llvm.vector.reduce.fadd.{{.*}}(float -0.000000e+00,
+define float @fp_reduction_enable_only(ptr %A, i64 %n) {
+entry:
+  br label %loop
+
+loop:
+  %i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
+  %sum = phi float [ 0.0, %entry ], [ %sum.next, %loop ]
+  %ptr = getelementptr inbounds float, ptr %A, i64 %i
+  %val = load float, ptr %ptr, align 4
+  %sum.next = fadd float %sum, %val
+  %i.next = add nuw nsw i64 %i, 1
+  %cond = icmp eq i64 %i.next, %n
+  br i1 %cond, label %exit, label %loop, !llvm.loop !0
+
+exit:
+  ret float %sum.next
+}
+
+; Test 2: vectorize.enable + fp_reordering.enable — FP reordering explicitly allowed.
+; CHECK-LABEL: @fp_reduction_enable_fp_reordering_true
+; CHECK: vector.body
+; CHECK: call float @llvm.vector.reduce.fadd.{{.*}}(float -0.000000e+00,
+define float @fp_reduction_enable_fp_reordering_true(ptr %A, i64 %n) {
+entry:
+  br label %loop
+
+loop:
+  %i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
+  %sum = phi float [ 0.0, %entry ], [ %sum.next, %loop ]
+  %ptr = getelementptr inbounds float, ptr %A, i64 %i
+  %val = load float, ptr %ptr, align 4
+  %sum.next = fadd float %sum, %val
+  %i.next = add nuw nsw i64 %i, 1
+  %cond = icmp eq i64 %i.next, %n
+  br i1 %cond, label %exit, label %loop, !llvm.loop !2
+
+exit:
+  ret float %sum.next
+}
+
+; Test 3: vectorize.enable + fp_reordering.disable — FP reordering suppressed, loop not vectorized.
+; CHECK-LABEL: @fp_reduction_enable_fp_reordering_false
+; CHECK-NOT: vector.body
+define float @fp_reduction_enable_fp_reordering_false(ptr %A, i64 %n) {
+entry:
+  br label %loop
+
+loop:
+  %i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
+  %sum = phi float [ 0.0, %entry ], [ %sum.next, %loop ]
+  %ptr = getelementptr inbounds float, ptr %A, i64 %i
+  %val = load float, ptr %ptr, align 4
+  %sum.next = fadd float %sum, %val
+  %i.next = add nuw nsw i64 %i, 1
+  %cond = icmp eq i64 %i.next, %n
+  br i1 %cond, label %exit, label %loop, !llvm.loop !4
+
+exit:
+  ret float %sum.next
+}
+
+!0 = distinct !{!0, !1}
+!1 = !{!"llvm.loop.vectorize.enable"}
+
+!2 = distinct !{!2, !3, !5}
+!3 = !{!"llvm.loop.vectorize.enable"}
+!5 = !{!"llvm.loop.vectorize.fp_reordering.enable"}
+
+!4 = distinct !{!4, !6, !7}
+!6 = !{!"llvm.loop.vectorize.enable"}
+!7 = !{!"llvm.loop.vectorize.fp_reordering.disable"}



More information about the llvm-commits mailing list