[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