[llvm-branch-commits] [llvm] ValueTracking: Handle constant structs in computeKnownFPClass (PR #184192)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Mar 2 10:46:21 PST 2026
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/184192
>From e2dd6572c3b6a0c87b157513bb92403c4719d25c Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 2 Mar 2026 18:44:36 +0100
Subject: [PATCH] ValueTracking: Handle constant structs in computeKnownFPClass
Also fix attributor not bothering to deal with structs.
---
llvm/include/llvm/Transforms/IPO/Attributor.h | 10 +--------
llvm/lib/Analysis/ValueTracking.cpp | 15 +++++++++++++
llvm/test/Transforms/Attributor/nofpclass.ll | 21 +++++++++++++++++--
.../simplify-demanded-fpclass-aggregates.ll | 6 ++----
4 files changed, 37 insertions(+), 15 deletions(-)
diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h
index f2657a338ba76..cee9cb8e7322b 100644
--- a/llvm/include/llvm/Transforms/IPO/Attributor.h
+++ b/llvm/include/llvm/Transforms/IPO/Attributor.h
@@ -5469,15 +5469,7 @@ struct AANoFPClass
/// See AbstractAttribute::isValidIRPositionForInit
static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
- Type *Ty = IRP.getAssociatedType();
- do {
- if (Ty->isFPOrFPVectorTy())
- return IRAttribute::isValidIRPositionForInit(A, IRP);
- if (!Ty->isArrayTy())
- break;
- Ty = Ty->getArrayElementType();
- } while (true);
- return false;
+ return AttributeFuncs::isNoFPClassCompatibleType(IRP.getAssociatedType());
}
/// Return the underlying assumed nofpclass.
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index f0a11f7d9df3f..a6fb6b1a4b90c 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5058,6 +5058,21 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
return;
}
+ if (const auto *CDS = dyn_cast<ConstantAggregate>(V)) {
+ Known.KnownFPClasses = fcNone;
+ for (const Use &Op : CDS->operands()) {
+ auto *CFP = dyn_cast<ConstantFP>(Op.get());
+ if (!CFP) {
+ Known = KnownFPClass();
+ return;
+ }
+
+ Known |= CFP->getValueAPF().classify();
+ }
+
+ return;
+ }
+
FPClassTest KnownNotFromFlags = fcNone;
if (const auto *CB = dyn_cast<CallBase>(V))
KnownNotFromFlags |= CB->getRetNoFPClass();
diff --git a/llvm/test/Transforms/Attributor/nofpclass.ll b/llvm/test/Transforms/Attributor/nofpclass.ll
index 7ed5e78539a90..d950d196d9f7c 100644
--- a/llvm/test/Transforms/Attributor/nofpclass.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass.ll
@@ -3824,10 +3824,9 @@ define <2 x float> @infer_return_from_load_nofpclass_md_v2f32(ptr %ptr) {
ret <2 x float> %load
}
-; TODO: Misses this case
define { float, float } @infer_return_from_load_nofpclass_md_struct(ptr %ptr) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
-; CHECK-LABEL: define { float, float } @infer_return_from_load_nofpclass_md_struct
+; CHECK-LABEL: define nofpclass(nan) { float, float } @infer_return_from_load_nofpclass_md_struct
; CHECK-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(8) [[PTR:%.*]]) #[[ATTR5]] {
; CHECK-NEXT: [[LOAD:%.*]] = load { float, float }, ptr [[PTR]], align 4, !nofpclass [[META1]]
; CHECK-NEXT: ret { float, float } [[LOAD]]
@@ -3865,6 +3864,24 @@ define [2 x float] @constant_data_array_1() {
ret [2 x float] [float 0x7FF8000000000000, float 0x7FF8000000000000]
}
+define { float, float } @constant_data_struct_0() {
+; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define nofpclass(nan inf nzero sub nnorm) { float, float } @constant_data_struct_0
+; CHECK-SAME: () #[[ATTR3]] {
+; CHECK-NEXT: ret { float, float } { float 0.000000e+00, float 1.000000e+00 }
+;
+ ret { float, float } { float 0.0, float 1.0 }
+}
+
+define { float, float } @constant_data_struct_1() {
+; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) { float, float } @constant_data_struct_1
+; CHECK-SAME: () #[[ATTR3]] {
+; CHECK-NEXT: ret { float, float } { float 0x7FF8000000000000, float 0x7FF8000000000000 }
+;
+ ret { float, float } { float 0x7FF8000000000000, float 0x7FF8000000000000 }
+}
+
declare i64 @_Z13get_global_idj(i32 noundef)
attributes #0 = { denormal_fpenv(preservesign) }
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-aggregates.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-aggregates.ll
index 68df1fd212d2e..7c4fcd8674c1e 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-aggregates.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-aggregates.ll
@@ -106,17 +106,15 @@ entry:
ret { float, float } { float 0x7FF0000000000000, float 0x7FF0000000000000 }
}
-; FIXME (should be poison): Support computeKnownFPClass() for non-zero aggregates.
define nofpclass(inf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_inf__npinf() {
; CHECK-LABEL: define nofpclass(inf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_inf__npinf() {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: ret { float, float } { float 0x7FF0000000000000, float 0x7FF0000000000000 }
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: ret { float, float } poison
;
entry:
ret { float, float } { float 0x7FF0000000000000, float 0x7FF0000000000000 }
}
-; FIXME (should be poison): Support computeKnownFPClass() for non-zero aggregates.
define nofpclass(nzero) [ 1 x float ] @ret_nofpclass_multiple_elems_struct_ty_nzero_nzero() {
; CHECK-LABEL: define nofpclass(nzero) [1 x float] @ret_nofpclass_multiple_elems_struct_ty_nzero_nzero() {
; CHECK-NEXT: [[ENTRY:.*:]]
More information about the llvm-branch-commits
mailing list