[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