[llvm] [Analysis] Adding convert_from_arbitrary_fp support in computeKnownFPClass. (PR #208585)

Chirag Patel via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 15 18:50:41 PDT 2026


https://github.com/ChiragPatel8 updated https://github.com/llvm/llvm-project/pull/208585

>From ad7a5b62e2f0aad161be5a54e4f0b1a3dcf590c1 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Fri, 10 Jul 2026 01:36:24 +0530
Subject: [PATCH 01/19] [Analysis] Initial implementation of
 convert_from_arbitrary_fp computeKnownFPClass.

---
 llvm/lib/Analysis/ValueTracking.cpp | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 59631873305d4..239c3c81723c2 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5709,6 +5709,34 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       Known.knownNot(fcNan | fcInf | fcNegative);
       break;
     }
+    case Intrinsic::convert_from_arbitrary_fp: {
+      auto *MD = cast<MetadataAsValue>(II->getArgOperand(1))->getMetadata();
+      StringRef FormatStr = cast<MDString>(MD)->getString();
+      const fltSemantics *SrcSemanticsPtr = APFloat::getArbitraryFPSemantics(FormatStr);
+      if (!SrcSemanticsPtr)
+          break;
+
+      const fltSemantics SrcSemantics = *SrcSemanticsPtr;
+      const fltSemantics DestSemantics = II->getType()->getFltSemantics();
+
+      int SrcMaxExp = APFloat::semanticsMaxExponent(SrcSemantics);
+      int DestMaxExp = APFloat::semanticsMaxExponent(DestSemantics);
+
+      if (!APFloat::semanticsHasInf(SrcSemantics) &&
+          (SrcMaxExp <= DestMaxExp))
+        Known.KnownFPClasses &= ~fcInf;
+
+      const bool SrcSupportsNaN = APFloat::semanticsHasNaN(SrcSemantics);
+      // If the source format doesn't have NaN, the output cannot be NaN
+      if (!SrcSupportsNaN)
+        Known.KnownFPClasses &= ~fcNan;
+
+      // override compile-time flag
+      if (II->hasNoNaNs())
+        Known.KnownFPClasses &= ~fcNan;
+
+      break;
+    }
     default:
       break;
     }

>From 8074c15904cf63b0c98bd92c3568539795ffddba Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Fri, 10 Jul 2026 04:59:36 +0530
Subject: [PATCH 02/19] minor format cleanup

---
 llvm/lib/Analysis/ValueTracking.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 239c3c81723c2..144408b52bad1 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5712,9 +5712,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
     case Intrinsic::convert_from_arbitrary_fp: {
       auto *MD = cast<MetadataAsValue>(II->getArgOperand(1))->getMetadata();
       StringRef FormatStr = cast<MDString>(MD)->getString();
-      const fltSemantics *SrcSemanticsPtr = APFloat::getArbitraryFPSemantics(FormatStr);
+      const fltSemantics *SrcSemanticsPtr =
+          APFloat::getArbitraryFPSemantics(FormatStr);
       if (!SrcSemanticsPtr)
-          break;
+        break;
 
       const fltSemantics SrcSemantics = *SrcSemanticsPtr;
       const fltSemantics DestSemantics = II->getType()->getFltSemantics();
@@ -5722,8 +5723,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       int SrcMaxExp = APFloat::semanticsMaxExponent(SrcSemantics);
       int DestMaxExp = APFloat::semanticsMaxExponent(DestSemantics);
 
-      if (!APFloat::semanticsHasInf(SrcSemantics) &&
-          (SrcMaxExp <= DestMaxExp))
+      if (!APFloat::semanticsHasInf(SrcSemantics) && (SrcMaxExp <= DestMaxExp))
         Known.KnownFPClasses &= ~fcInf;
 
       const bool SrcSupportsNaN = APFloat::semanticsHasNaN(SrcSemantics);

>From fb3802e3046f658915fcf07f7bc58ad96ad68f12 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Fri, 10 Jul 2026 21:00:32 +0530
Subject: [PATCH 03/19] [test] Adding testcase for llvm.convert.from.arbitrary.

---
 .../known-fp-class-convert-arbitrary.ll       | 32 +++++++++++++++++++
 1 file changed, 32 insertions(+)
 create mode 100644 llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll

diff --git a/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll b/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll
new file mode 100644
index 0000000000000..6a43bb77b3f5a
--- /dev/null
+++ b/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll
@@ -0,0 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+; Test 1: Source format "Float8E4M3FN" structurally does not support NaN or Infinity.
+; InstCombine should completely optimize away the is.fpclass checks to 'false'.
+define i1 @test_no_nan_no_inf(i8 %bits) {
+; CHECK-LABEL: @test_no_nan_no_inf(
+; CHECK-NEXT:    ret i1 false
+;
+  ; Convert from a format that has no NaN and no Infinity
+  %fp = call float @llvm.convert.from.arbitrary.fp(i8 %bits, metadata !"Float8E4M3FN")
+  
+  ; Query if the result is either a NaN or an Infinity (fcNaN | fcInf = 3 | 512 = 515)
+  %is.nan.or.inf = call i1 @llvm.is.fpclass.f32(float %fp, i32 515)
+  ret i1 %is.nan.or.inf
+}
+
+; Test 2: Fast Math Flags (nnan) should also be respected and clear fcNaN.
+define i1 @test_fmf_nnan(i8 %bits) {
+; CHECK-LABEL: @test_fmf_nnan(
+; CHECK-NEXT:    ret i1 false
+;
+  ; Even if the format supported NaN, the 'nnan' flag forces fcNaN to clear
+  %fp = call nnan float @llvm.convert.from.arbitrary.fp(i8 %bits, metadata !"Float8E5M2")
+  
+  ; Query if the result is a NaN (fcNaN = 3)
+  %is.nan = call i1 @llvm.is.fpclass.f32(float %fp, i32 3)
+  ret i1 %is.nan
+}
+
+declare float @llvm.convert.from.arbitrary.fp(i8, metadata)
+declare i1 @llvm.is.fpclass.f32(float, i32)
\ No newline at end of file

>From 57db066973fee631fde0c69838f8e1bc8f89464f Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Fri, 10 Jul 2026 21:17:14 +0530
Subject: [PATCH 04/19] Adding compile-time override flag for 
 convert_from_arbitrary_fp

---
 llvm/lib/Analysis/ValueTracking.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 144408b52bad1..1fd038a4b8eb4 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5734,6 +5734,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       // override compile-time flag
       if (II->hasNoNaNs())
         Known.KnownFPClasses &= ~fcNan;
+      if (II->hasNoInfs())
+        Known.KnownFPClasses &= ~fcInf;
 
       break;
     }

>From 15d889380255210826091685f32aed70119e0927 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Fri, 10 Jul 2026 21:29:32 +0530
Subject: [PATCH 05/19] Fixing testcase, selected proper format with no nan and
 no inf.

---
 .../ValueTracking/known-fp-class-convert-arbitrary.ll         | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll b/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll
index 6a43bb77b3f5a..843058fd82a7b 100644
--- a/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll
+++ b/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll
@@ -1,14 +1,14 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s
 
-; Test 1: Source format "Float8E4M3FN" structurally does not support NaN or Infinity.
+; Test 1: Source format "Float4E2M1FN" structurally does not support NaN or Infinity.
 ; InstCombine should completely optimize away the is.fpclass checks to 'false'.
 define i1 @test_no_nan_no_inf(i8 %bits) {
 ; CHECK-LABEL: @test_no_nan_no_inf(
 ; CHECK-NEXT:    ret i1 false
 ;
   ; Convert from a format that has no NaN and no Infinity
-  %fp = call float @llvm.convert.from.arbitrary.fp(i8 %bits, metadata !"Float8E4M3FN")
+  %fp = call float @llvm.convert.from.arbitrary.fp(i8 %bits, metadata !"Float4E2M1FN")
   
   ; Query if the result is either a NaN or an Infinity (fcNaN | fcInf = 3 | 512 = 515)
   %is.nan.or.inf = call i1 @llvm.is.fpclass.f32(float %fp, i32 515)

>From 168b01fbff17bc10f2272b31a2b003d3c9218b93 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Fri, 10 Jul 2026 23:14:09 +0530
Subject: [PATCH 06/19] 1. Fixed vector support segfault in
 @llvm.convert.from.arbitrary.fp 2. Added vector testcase in ll file 3. format
 cleanup, removed useless code.

---
 llvm/lib/Analysis/ValueTracking.cpp           | 25 ++++++-------------
 .../known-fp-class-convert-arbitrary.ll       | 18 ++++++++++++-
 2 files changed, 24 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 1fd038a4b8eb4..1c4aa96351148 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5712,30 +5712,19 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
     case Intrinsic::convert_from_arbitrary_fp: {
       auto *MD = cast<MetadataAsValue>(II->getArgOperand(1))->getMetadata();
       StringRef FormatStr = cast<MDString>(MD)->getString();
-      const fltSemantics *SrcSemanticsPtr =
-          APFloat::getArbitraryFPSemantics(FormatStr);
-      if (!SrcSemanticsPtr)
-        break;
-
-      const fltSemantics SrcSemantics = *SrcSemanticsPtr;
-      const fltSemantics DestSemantics = II->getType()->getFltSemantics();
+      const fltSemantics SrcSemantics =
+          *(APFloat::getArbitraryFPSemantics(FormatStr));
 
-      int SrcMaxExp = APFloat::semanticsMaxExponent(SrcSemantics);
-      int DestMaxExp = APFloat::semanticsMaxExponent(DestSemantics);
+      Type *DestTy = II->getType()->getScalarType();
+      const fltSemantics DestSemantics = DestTy->getFltSemantics();
 
-      if (!APFloat::semanticsHasInf(SrcSemantics) && (SrcMaxExp <= DestMaxExp))
-        Known.KnownFPClasses &= ~fcInf;
+      if (!APFloat::semanticsHasInf(SrcSemantics))
+        Known.knownNot(fcInf);
 
       const bool SrcSupportsNaN = APFloat::semanticsHasNaN(SrcSemantics);
       // If the source format doesn't have NaN, the output cannot be NaN
       if (!SrcSupportsNaN)
-        Known.KnownFPClasses &= ~fcNan;
-
-      // override compile-time flag
-      if (II->hasNoNaNs())
-        Known.KnownFPClasses &= ~fcNan;
-      if (II->hasNoInfs())
-        Known.KnownFPClasses &= ~fcInf;
+        Known.knownNot(fcNan);
 
       break;
     }
diff --git a/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll b/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll
index 843058fd82a7b..a84caf0d72104 100644
--- a/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll
+++ b/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll
@@ -28,5 +28,21 @@ define i1 @test_fmf_nnan(i8 %bits) {
   ret i1 %is.nan
 }
 
+; Test 3: Vector support. The underlying scalar format "Float4E2M1FN" lacks NaN/Inf.
+; The vector check should optimize completely down to a zeroinitializer (all false).
+define <4 x i1> @test_vector_no_nan_no_inf(<4 x i8> %bits) {
+; CHECK-LABEL: @test_vector_no_nan_no_inf(
+; CHECK-NEXT:    ret <4 x i1> zeroinitializer
+;
+  ; Convert a vector of bits into a vector of floats
+  %fp = call <4 x float> @llvm.convert.from.arbitrary.fp.v4f32(<4 x i8> %bits, metadata !"Float4E2M1FN")
+  
+  ; Query if any lane is NaN or Infinity (3 | 512 = 515)
+  %is.nan.or.inf = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %fp, i32 515)
+  ret <4 x i1> %is.nan.or.inf
+}
+
 declare float @llvm.convert.from.arbitrary.fp(i8, metadata)
-declare i1 @llvm.is.fpclass.f32(float, i32)
\ No newline at end of file
+declare i1 @llvm.is.fpclass.f32(float, i32)
+declare <4 x float> @llvm.convert.from.arbitrary.fp.v4f32(<4 x i8>, metadata)
+declare <4 x i1> @llvm.is.fpclass.v4f32(<4 x float>, i32)

>From fad92c560ac82b442a4ee3ca500a13717c73c8f0 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Fri, 10 Jul 2026 23:22:37 +0530
Subject: [PATCH 07/19] simplfy changes

---
 llvm/lib/Analysis/ValueTracking.cpp | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 1c4aa96351148..838a2c7033ec8 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5715,17 +5715,11 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       const fltSemantics SrcSemantics =
           *(APFloat::getArbitraryFPSemantics(FormatStr));
 
-      Type *DestTy = II->getType()->getScalarType();
-      const fltSemantics DestSemantics = DestTy->getFltSemantics();
-
+      if (!APFloat::semanticsHasNaN(SrcSemantics))
+        Known.knownNot(fcNan);
       if (!APFloat::semanticsHasInf(SrcSemantics))
         Known.knownNot(fcInf);
 
-      const bool SrcSupportsNaN = APFloat::semanticsHasNaN(SrcSemantics);
-      // If the source format doesn't have NaN, the output cannot be NaN
-      if (!SrcSupportsNaN)
-        Known.knownNot(fcNan);
-
       break;
     }
     default:

>From f003c6fbe538032c5254e6751db88dfb2e994f15 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Sat, 11 Jul 2026 00:03:00 +0530
Subject: [PATCH 08/19] moving testfile to proper location.

---
 .../known-fp-class-convert-arbitrary.ll       | 48 -------------------
 .../Attributor/nofpclass-arbitrary-fp.ll      | 41 ++++++++++++++++
 2 files changed, 41 insertions(+), 48 deletions(-)
 delete mode 100644 llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll
 create mode 100644 llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll

diff --git a/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll b/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll
deleted file mode 100644
index a84caf0d72104..0000000000000
--- a/llvm/test/Analysis/ValueTracking/known-fp-class-convert-arbitrary.ll
+++ /dev/null
@@ -1,48 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=instcombine < %s | FileCheck %s
-
-; Test 1: Source format "Float4E2M1FN" structurally does not support NaN or Infinity.
-; InstCombine should completely optimize away the is.fpclass checks to 'false'.
-define i1 @test_no_nan_no_inf(i8 %bits) {
-; CHECK-LABEL: @test_no_nan_no_inf(
-; CHECK-NEXT:    ret i1 false
-;
-  ; Convert from a format that has no NaN and no Infinity
-  %fp = call float @llvm.convert.from.arbitrary.fp(i8 %bits, metadata !"Float4E2M1FN")
-  
-  ; Query if the result is either a NaN or an Infinity (fcNaN | fcInf = 3 | 512 = 515)
-  %is.nan.or.inf = call i1 @llvm.is.fpclass.f32(float %fp, i32 515)
-  ret i1 %is.nan.or.inf
-}
-
-; Test 2: Fast Math Flags (nnan) should also be respected and clear fcNaN.
-define i1 @test_fmf_nnan(i8 %bits) {
-; CHECK-LABEL: @test_fmf_nnan(
-; CHECK-NEXT:    ret i1 false
-;
-  ; Even if the format supported NaN, the 'nnan' flag forces fcNaN to clear
-  %fp = call nnan float @llvm.convert.from.arbitrary.fp(i8 %bits, metadata !"Float8E5M2")
-  
-  ; Query if the result is a NaN (fcNaN = 3)
-  %is.nan = call i1 @llvm.is.fpclass.f32(float %fp, i32 3)
-  ret i1 %is.nan
-}
-
-; Test 3: Vector support. The underlying scalar format "Float4E2M1FN" lacks NaN/Inf.
-; The vector check should optimize completely down to a zeroinitializer (all false).
-define <4 x i1> @test_vector_no_nan_no_inf(<4 x i8> %bits) {
-; CHECK-LABEL: @test_vector_no_nan_no_inf(
-; CHECK-NEXT:    ret <4 x i1> zeroinitializer
-;
-  ; Convert a vector of bits into a vector of floats
-  %fp = call <4 x float> @llvm.convert.from.arbitrary.fp.v4f32(<4 x i8> %bits, metadata !"Float4E2M1FN")
-  
-  ; Query if any lane is NaN or Infinity (3 | 512 = 515)
-  %is.nan.or.inf = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %fp, i32 515)
-  ret <4 x i1> %is.nan.or.inf
-}
-
-declare float @llvm.convert.from.arbitrary.fp(i8, metadata)
-declare i1 @llvm.is.fpclass.f32(float, i32)
-declare <4 x float> @llvm.convert.from.arbitrary.fp.v4f32(<4 x i8>, metadata)
-declare <4 x i1> @llvm.is.fpclass.v4f32(<4 x float>, i32)
diff --git a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
new file mode 100644
index 0000000000000..4de5d74b03a54
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
@@ -0,0 +1,41 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
+; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
+
+; Test 1: Float4E2M1FN has absolutely no NaN or Inf support. 
+; The Attributor should deduce and attach nofpclass(nan inf) to the function return.
+define float @ret_arbitrary_fp_no_nan_no_inf(i8 %bits) {
+; CHECK-LABEL: define nofpclass(nan inf) float @ret_arbitrary_fp_no_nan_no_inf
+; CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    %fp = call nofpclass(nan inf) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    ret float %fp
+;
+  %fp = call float @llvm.convert.from.arbitrary.fp(i8 %bits, metadata !"Float4E2M1FN")
+  ret float %fp
+}
+
+; Test 2: Float8E4M3FN supports NaNs but lacks Infinities (NaNOnly).
+; The Attributor should safely deduce and attach nofpclass(inf) to the function return.
+define float @ret_arbitrary_fp_nan_only(i8 %bits) {
+; CHECK-LABEL: define nofpclass(inf) float @ret_arbitrary_fp_nan_only
+; CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    %fp = call nofpclass(inf) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E4M3FN") #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    ret float %fp
+;
+  %fp = call float @llvm.convert.from.arbitrary.fp(i8 %bits, metadata !"Float8E4M3FN")
+  ret float %fp
+}
+
+; Test 3: Vector variation checking that your getScalarType() unpacks cleanly.
+; The Attributor should successfully attach nofpclass(nan inf) to the returning vector topology.
+define <4 x float> @ret_arbitrary_fp_vector(<4 x i8> %bits) {
+; CHECK-LABEL: define nofpclass(nan inf) <4 x float> @ret_arbitrary_fp_vector
+; CHECK-SAME: (<4 x i8> [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    %fp = call nofpclass(nan inf) <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i8(<4 x i8> [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    ret <4 x float> %fp
+;
+  %fp = call <4 x float> @llvm.convert.from.arbitrary.fp.v4f32(<4 x i8> %bits, metadata !"Float4E2M1FN")
+  ret <4 x float> %fp
+}
+
+declare float @llvm.convert.from.arbitrary.fp(i8, metadata)
+declare <4 x float> @llvm.convert.from.arbitrary.fp.v4f32(<4 x i8>, metadata)

>From bf67fba4e31462b5c623785744edc4009966e556 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Sat, 11 Jul 2026 00:07:08 +0530
Subject: [PATCH 09/19] Removing unnecessary tag

---
 llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
index 4de5d74b03a54..175bba96a5086 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
-; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
+; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -S < %s | FileCheck %s --check-prefixes=CHECK
 
 ; Test 1: Float4E2M1FN has absolutely no NaN or Inf support. 
 ; The Attributor should deduce and attach nofpclass(nan inf) to the function return.

>From 13fde9fae1f9dee64e1b6fb08b689a87b114fa02 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Sat, 11 Jul 2026 00:13:01 +0530
Subject: [PATCH 10/19] removing unnecessary LLM generated comment

---
 llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
index 175bba96a5086..a2074b527e403 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
@@ -25,7 +25,7 @@ define float @ret_arbitrary_fp_nan_only(i8 %bits) {
   ret float %fp
 }
 
-; Test 3: Vector variation checking that your getScalarType() unpacks cleanly.
+; Test 3: Vector variation.
 ; The Attributor should successfully attach nofpclass(nan inf) to the returning vector topology.
 define <4 x float> @ret_arbitrary_fp_vector(<4 x i8> %bits) {
 ; CHECK-LABEL: define nofpclass(nan inf) <4 x float> @ret_arbitrary_fp_vector

>From a1854f7664e296e14416c269127d72f6df841a42 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Sat, 11 Jul 2026 07:23:51 +0530
Subject: [PATCH 11/19] Testcases refactoring

---
 .../Attributor/nofpclass-arbitrary-fp.ll      | 20 +++++++------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
index a2074b527e403..6bca7d2656c4e 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
@@ -1,10 +1,8 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -S < %s | FileCheck %s --check-prefixes=CHECK
 
-; Test 1: Float4E2M1FN has absolutely no NaN or Inf support. 
-; The Attributor should deduce and attach nofpclass(nan inf) to the function return.
-define float @ret_arbitrary_fp_no_nan_no_inf(i8 %bits) {
-; CHECK-LABEL: define nofpclass(nan inf) float @ret_arbitrary_fp_no_nan_no_inf
+define float @ret_arbitrary_fp_nan_inf(i8 %bits) {
+; CHECK-LABEL: define nofpclass(nan inf) float @ret_arbitrary_fp_nan_inf
 ; CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:    %fp = call nofpclass(nan inf) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret float %fp
@@ -13,10 +11,8 @@ define float @ret_arbitrary_fp_no_nan_no_inf(i8 %bits) {
   ret float %fp
 }
 
-; Test 2: Float8E4M3FN supports NaNs but lacks Infinities (NaNOnly).
-; The Attributor should safely deduce and attach nofpclass(inf) to the function return.
-define float @ret_arbitrary_fp_nan_only(i8 %bits) {
-; CHECK-LABEL: define nofpclass(inf) float @ret_arbitrary_fp_nan_only
+define float @ret_arbitrary_fp_inf_only(i8 %bits) {
+; CHECK-LABEL: define nofpclass(inf) float @ret_arbitrary_fp_inf_only
 ; CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:    %fp = call nofpclass(inf) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E4M3FN") #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret float %fp
@@ -25,10 +21,8 @@ define float @ret_arbitrary_fp_nan_only(i8 %bits) {
   ret float %fp
 }
 
-; Test 3: Vector variation.
-; The Attributor should successfully attach nofpclass(nan inf) to the returning vector topology.
-define <4 x float> @ret_arbitrary_fp_vector(<4 x i8> %bits) {
-; CHECK-LABEL: define nofpclass(nan inf) <4 x float> @ret_arbitrary_fp_vector
+define <4 x float> @ret_arbitrary_fp_vector_nan_inf(<4 x i8> %bits) {
+; CHECK-LABEL: define nofpclass(nan inf) <4 x float> @ret_arbitrary_fp_vector_nan_inf
 ; CHECK-SAME: (<4 x i8> [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:    %fp = call nofpclass(nan inf) <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i8(<4 x i8> [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret <4 x float> %fp

>From d9211b0ca660dc3ef9127e6689410b0c29447de7 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Sat, 11 Jul 2026 07:49:29 +0530
Subject: [PATCH 12/19] adding fcPosZero and improving fcInf check for

---
 llvm/lib/Analysis/ValueTracking.cpp | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 838a2c7033ec8..e9133de7f4632 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5712,14 +5712,27 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
     case Intrinsic::convert_from_arbitrary_fp: {
       auto *MD = cast<MetadataAsValue>(II->getArgOperand(1))->getMetadata();
       StringRef FormatStr = cast<MDString>(MD)->getString();
+
       const fltSemantics SrcSemantics =
-          *(APFloat::getArbitraryFPSemantics(FormatStr));
+          *APFloat::getArbitraryFPSemantics(FormatStr);
+      const fltSemantics DstSemantics =
+          II->getType()->getScalarType()->getFltSemantics();
 
       if (!APFloat::semanticsHasNaN(SrcSemantics))
         Known.knownNot(fcNan);
-      if (!APFloat::semanticsHasInf(SrcSemantics))
+      if (!APFloat::semanticsHasInf(SrcSemantics) &&
+          APFloat::isRepresentableBy(SrcSemantics, DstSemantics))
         Known.knownNot(fcInf);
 
+      if (!APFloat::semanticsHasZero(SrcSemantics)) {
+        Known.knownNot(fcZero);
+      } else {
+        KnownBits IntKnown =
+            computeKnownBits(Op->getOperand(0), DemandedElts, Q, Depth + 1);
+        if (IntKnown.isNonZero())
+          Known.knownNot(fcPosZero);
+      }
+
       break;
     }
     default:

>From c73cbd6be3d92524d856211b03cd03f8bbd14d9a Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Sat, 11 Jul 2026 10:17:30 +0530
Subject: [PATCH 13/19] Adding subnormal test for convert_from_arbitrary_fp.

---
 llvm/lib/Analysis/ValueTracking.cpp                  |  3 +++
 .../Transforms/Attributor/nofpclass-arbitrary-fp.ll  | 12 ++++++------
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index e9133de7f4632..6891bc5464683 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5733,6 +5733,9 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
           Known.knownNot(fcPosZero);
       }
 
+      // if src lands normaly in dest, result can never be sub-normal.
+      if (APFloat::isRepresentableAsNormalIn(SrcSemantics, DstSemantics))
+        Known.knownNot(fcSubnormal);
       break;
     }
     default:
diff --git a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
index 6bca7d2656c4e..df2c74591beaa 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
@@ -2,9 +2,9 @@
 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -S < %s | FileCheck %s --check-prefixes=CHECK
 
 define float @ret_arbitrary_fp_nan_inf(i8 %bits) {
-; CHECK-LABEL: define nofpclass(nan inf) float @ret_arbitrary_fp_nan_inf
+; CHECK-LABEL: define nofpclass(nan inf sub) float @ret_arbitrary_fp_nan_inf
 ; CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT:    %fp = call nofpclass(nan inf) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    %fp = call nofpclass(nan inf sub) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret float %fp
 ;
   %fp = call float @llvm.convert.from.arbitrary.fp(i8 %bits, metadata !"Float4E2M1FN")
@@ -12,9 +12,9 @@ define float @ret_arbitrary_fp_nan_inf(i8 %bits) {
 }
 
 define float @ret_arbitrary_fp_inf_only(i8 %bits) {
-; CHECK-LABEL: define nofpclass(inf) float @ret_arbitrary_fp_inf_only
+; CHECK-LABEL: define nofpclass(inf sub) float @ret_arbitrary_fp_inf_only
 ; CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT:    %fp = call nofpclass(inf) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E4M3FN") #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    %fp = call nofpclass(inf sub) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E4M3FN") #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret float %fp
 ;
   %fp = call float @llvm.convert.from.arbitrary.fp(i8 %bits, metadata !"Float8E4M3FN")
@@ -22,9 +22,9 @@ define float @ret_arbitrary_fp_inf_only(i8 %bits) {
 }
 
 define <4 x float> @ret_arbitrary_fp_vector_nan_inf(<4 x i8> %bits) {
-; CHECK-LABEL: define nofpclass(nan inf) <4 x float> @ret_arbitrary_fp_vector_nan_inf
+; CHECK-LABEL: define nofpclass(nan inf sub) <4 x float> @ret_arbitrary_fp_vector_nan_inf
 ; CHECK-SAME: (<4 x i8> [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT:    %fp = call nofpclass(nan inf) <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i8(<4 x i8> [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    %fp = call nofpclass(nan inf sub) <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i8(<4 x i8> [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret <4 x float> %fp
 ;
   %fp = call <4 x float> @llvm.convert.from.arbitrary.fp.v4f32(<4 x i8> %bits, metadata !"Float4E2M1FN")

>From de4b1b5c956860125beb1864198132f2ab312346 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Mon, 13 Jul 2026 01:39:33 +0530
Subject: [PATCH 14/19] Adding nullpte check.

---
 llvm/lib/Analysis/ValueTracking.cpp | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 6891bc5464683..b23089a9a1b5f 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5713,8 +5713,14 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       auto *MD = cast<MetadataAsValue>(II->getArgOperand(1))->getMetadata();
       StringRef FormatStr = cast<MDString>(MD)->getString();
 
-      const fltSemantics SrcSemantics =
-          *APFloat::getArbitraryFPSemantics(FormatStr);
+      const fltSemantics *SrcSemanticsPtr =
+          APFloat::getArbitraryFPSemantics(FormatStr);
+      // TODO: the unsupported formats should be handle way before this
+      // remove once the verifier is updated.
+      if (!SrcSemanticsPtr)
+        break;
+
+      const fltSemantics SrcSemantics = *SrcSemanticsPtr;
       const fltSemantics DstSemantics =
           II->getType()->getScalarType()->getFltSemantics();
 

>From b46f90f6babde3b95d4d8fdce356e2d4cb373730 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Mon, 13 Jul 2026 05:53:33 +0530
Subject: [PATCH 15/19] Fixing test case.

---
 .../Attributor/nofpclass-arbitrary-fp.ll      | 25 ++++++++++---------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
index df2c74591beaa..204d506246be3 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
@@ -1,13 +1,13 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -S < %s | FileCheck %s --check-prefixes=CHECK
+; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -S < %s | FileCheck %s
 
-define float @ret_arbitrary_fp_nan_inf(i8 %bits) {
+define float @ret_arbitrary_fp_nan_inf(i4 %bits) {
 ; CHECK-LABEL: define nofpclass(nan inf sub) float @ret_arbitrary_fp_nan_inf
-; CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT:    %fp = call nofpclass(nan inf sub) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
+; CHECK-SAME: (i4 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    %fp = call nofpclass(nan inf sub) float @llvm.convert.from.arbitrary.fp.f32.i4(i4 [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret float %fp
 ;
-  %fp = call float @llvm.convert.from.arbitrary.fp(i8 %bits, metadata !"Float4E2M1FN")
+  %fp = call float @llvm.convert.from.arbitrary.fp.f32.i4(i4 %bits, metadata !"Float4E2M1FN")
   ret float %fp
 }
 
@@ -17,19 +17,20 @@ define float @ret_arbitrary_fp_inf_only(i8 %bits) {
 ; CHECK-NEXT:    %fp = call nofpclass(inf sub) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E4M3FN") #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret float %fp
 ;
-  %fp = call float @llvm.convert.from.arbitrary.fp(i8 %bits, metadata !"Float8E4M3FN")
+  %fp = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %bits, metadata !"Float8E4M3FN")
   ret float %fp
 }
 
-define <4 x float> @ret_arbitrary_fp_vector_nan_inf(<4 x i8> %bits) {
+define <4 x float> @ret_arbitrary_fp_vector_nan_inf(<4 x i4> %bits) {
 ; CHECK-LABEL: define nofpclass(nan inf sub) <4 x float> @ret_arbitrary_fp_vector_nan_inf
-; CHECK-SAME: (<4 x i8> [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT:    %fp = call nofpclass(nan inf sub) <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i8(<4 x i8> [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
+; CHECK-SAME: (<4 x i4> [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    %fp = call nofpclass(nan inf sub) <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i4(<4 x i4> [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret <4 x float> %fp
 ;
-  %fp = call <4 x float> @llvm.convert.from.arbitrary.fp.v4f32(<4 x i8> %bits, metadata !"Float4E2M1FN")
+  %fp = call <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i4(<4 x i4> %bits, metadata !"Float4E2M1FN")
   ret <4 x float> %fp
 }
 
-declare float @llvm.convert.from.arbitrary.fp(i8, metadata)
-declare <4 x float> @llvm.convert.from.arbitrary.fp.v4f32(<4 x i8>, metadata)
+declare float @llvm.convert.from.arbitrary.fp.f32.i4(i4, metadata)
+declare float @llvm.convert.from.arbitrary.fp.f32.i8(i8, metadata)
+declare <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i4(<4 x i4>, metadata)

>From 0ac310b04dd6d8fa236116b897765538dab04de6 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Wed, 15 Jul 2026 11:46:05 +0530
Subject: [PATCH 16/19] correcting comment format

---
 llvm/lib/Analysis/ValueTracking.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index f0ba175d888e9..6599a031a9825 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5757,7 +5757,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
           Known.knownNot(fcPosZero);
       }
 
-      // if src lands normaly in dest, result can never be sub-normal.
+      // If src lands normaly in dest, result can never be sub-normal.
       if (APFloat::isRepresentableAsNormalIn(SrcSemantics, DstSemantics))
         Known.knownNot(fcSubnormal);
       break;

>From 4ba83427c10c571858e862e7ab8853ec6dcb8b86 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Wed, 15 Jul 2026 13:12:19 +0530
Subject: [PATCH 17/19] Adding no-signed-zero testcase.

---
 llvm/lib/Analysis/ValueTracking.cpp                    |  3 +++
 .../Transforms/Attributor/nofpclass-arbitrary-fp.ll    | 10 ++++++++++
 2 files changed, 13 insertions(+)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 6599a031a9825..010702615c85e 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5748,6 +5748,9 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
           APFloat::isRepresentableBy(SrcSemantics, DstSemantics))
         Known.knownNot(fcInf);
 
+      if (SrcSemantics.nanEncoding == fltNanEncoding::NegativeZero)
+        Known.knownNot(fcNegZero);
+
       if (!APFloat::semanticsHasZero(SrcSemantics)) {
         Known.knownNot(fcZero);
       } else {
diff --git a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
index 204d506246be3..fd044b2b4aa87 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
@@ -31,6 +31,16 @@ define <4 x float> @ret_arbitrary_fp_vector_nan_inf(<4 x i4> %bits) {
   ret <4 x float> %fp
 }
 
+define float @ret_arbitrary_fp_inf_nzero_sub(i8 %bits) {
+; CHECK-LABEL: define nofpclass(inf nzero sub) float @ret_arbitrary_fp_inf_nzero_sub
+; CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    %fp = call nofpclass(inf nzero sub) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E4M3FNUZ") #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    ret float %fp
+;
+  %fp = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %bits, metadata !"Float8E4M3FNUZ")
+  ret float %fp
+}
+
 declare float @llvm.convert.from.arbitrary.fp.f32.i4(i4, metadata)
 declare float @llvm.convert.from.arbitrary.fp.f32.i8(i8, metadata)
 declare <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i4(<4 x i4>, metadata)

>From aa4729d6bb2775bfedd2a863a1951169cd389a57 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Wed, 15 Jul 2026 13:56:54 +0530
Subject: [PATCH 18/19] Adding not representable inf case.

---
 .../Transforms/Attributor/nofpclass-arbitrary-fp.ll  | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
index fd044b2b4aa87..3062f3c3e97d3 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
@@ -31,6 +31,7 @@ define <4 x float> @ret_arbitrary_fp_vector_nan_inf(<4 x i4> %bits) {
   ret <4 x float> %fp
 }
 
+;TODO: this format is not fully supported at the moment in LLVM and may cause crash.
 define float @ret_arbitrary_fp_inf_nzero_sub(i8 %bits) {
 ; CHECK-LABEL: define nofpclass(inf nzero sub) float @ret_arbitrary_fp_inf_nzero_sub
 ; CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
@@ -41,6 +42,17 @@ define float @ret_arbitrary_fp_inf_nzero_sub(i8 %bits) {
   ret float %fp
 }
 
+define <2 x float> @ret_arbitrary_fp_vector_no_inf(<2 x i8> %bits) {
+; CHECK-LABEL: define nofpclass(sub) <2 x float> @ret_arbitrary_fp_vector_no_inf
+; CHECK-SAME: (<2 x i8> [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    %fp = call nofpclass(sub) <2 x float> @llvm.convert.from.arbitrary.fp.v2f32.v2i8(<2 x i8> [[BITS]], metadata !"Float8E5M2") #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    ret <2 x float> %fp
+;
+  %fp = call <2 x float> @llvm.convert.from.arbitrary.fp.v2f32.v2i8(<2 x i8> %bits, metadata !"Float8E5M2")
+  ret <2 x float> %fp
+}
+
 declare float @llvm.convert.from.arbitrary.fp.f32.i4(i4, metadata)
 declare float @llvm.convert.from.arbitrary.fp.f32.i8(i8, metadata)
 declare <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i4(<4 x i4>, metadata)
+declare <2 x float> @llvm.convert.from.arbitrary.fp.v2f32.v2i8(<2 x i8>, metadata)

>From f331ece248cfe5d4eb4197040d38c1528db3fb3d Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Thu, 16 Jul 2026 07:20:10 +0530
Subject: [PATCH 19/19] Comment cleanup. Cleaning up name conventions of some
 testcase.

---
 llvm/lib/Analysis/ValueTracking.cpp             |  4 +---
 .../Attributor/nofpclass-arbitrary-fp.ll        | 17 ++++++++---------
 2 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 010702615c85e..187f56aa741cd 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5733,8 +5733,6 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
 
       const fltSemantics *SrcSemanticsPtr =
           APFloat::getArbitraryFPSemantics(FormatStr);
-      // TODO: the unsupported formats should be handle way before this
-      // remove once the verifier is updated.
       if (!SrcSemanticsPtr)
         break;
 
@@ -5760,7 +5758,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
           Known.knownNot(fcPosZero);
       }
 
-      // If src lands normaly in dest, result can never be sub-normal.
+      // If src lands normaly in dest, result can never be subnormal.
       if (APFloat::isRepresentableAsNormalIn(SrcSemantics, DstSemantics))
         Known.knownNot(fcSubnormal);
       break;
diff --git a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
index 3062f3c3e97d3..7f9f6976fb8d9 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
@@ -1,8 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -S < %s | FileCheck %s
 
-define float @ret_arbitrary_fp_nan_inf(i4 %bits) {
-; CHECK-LABEL: define nofpclass(nan inf sub) float @ret_arbitrary_fp_nan_inf
+define float @ret_arbitrary_fp_nan_inf_sub(i4 %bits) {
+; CHECK-LABEL: define nofpclass(nan inf sub) float @ret_arbitrary_fp_nan_inf_sub
 ; CHECK-SAME: (i4 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:    %fp = call nofpclass(nan inf sub) float @llvm.convert.from.arbitrary.fp.f32.i4(i4 [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret float %fp
@@ -11,8 +11,8 @@ define float @ret_arbitrary_fp_nan_inf(i4 %bits) {
   ret float %fp
 }
 
-define float @ret_arbitrary_fp_inf_only(i8 %bits) {
-; CHECK-LABEL: define nofpclass(inf sub) float @ret_arbitrary_fp_inf_only
+define float @ret_arbitrary_fp_inf_sub(i8 %bits) {
+; CHECK-LABEL: define nofpclass(inf sub) float @ret_arbitrary_fp_inf_sub
 ; CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:    %fp = call nofpclass(inf sub) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E4M3FN") #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret float %fp
@@ -21,8 +21,8 @@ define float @ret_arbitrary_fp_inf_only(i8 %bits) {
   ret float %fp
 }
 
-define <4 x float> @ret_arbitrary_fp_vector_nan_inf(<4 x i4> %bits) {
-; CHECK-LABEL: define nofpclass(nan inf sub) <4 x float> @ret_arbitrary_fp_vector_nan_inf
+define <4 x float> @ret_arbitrary_fp_vector_nan_inf_sub(<4 x i4> %bits) {
+; CHECK-LABEL: define nofpclass(nan inf sub) <4 x float> @ret_arbitrary_fp_vector_nan_inf_sub
 ; CHECK-SAME: (<4 x i4> [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:    %fp = call nofpclass(nan inf sub) <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i4(<4 x i4> [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret <4 x float> %fp
@@ -31,7 +31,6 @@ define <4 x float> @ret_arbitrary_fp_vector_nan_inf(<4 x i4> %bits) {
   ret <4 x float> %fp
 }
 
-;TODO: this format is not fully supported at the moment in LLVM and may cause crash.
 define float @ret_arbitrary_fp_inf_nzero_sub(i8 %bits) {
 ; CHECK-LABEL: define nofpclass(inf nzero sub) float @ret_arbitrary_fp_inf_nzero_sub
 ; CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
@@ -42,8 +41,8 @@ define float @ret_arbitrary_fp_inf_nzero_sub(i8 %bits) {
   ret float %fp
 }
 
-define <2 x float> @ret_arbitrary_fp_vector_no_inf(<2 x i8> %bits) {
-; CHECK-LABEL: define nofpclass(sub) <2 x float> @ret_arbitrary_fp_vector_no_inf
+define <2 x float> @ret_arbitrary_fp_vector_sub(<2 x i8> %bits) {
+; CHECK-LABEL: define nofpclass(sub) <2 x float> @ret_arbitrary_fp_vector_sub
 ; CHECK-SAME: (<2 x i8> [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:    %fp = call nofpclass(sub) <2 x float> @llvm.convert.from.arbitrary.fp.v2f32.v2i8(<2 x i8> [[BITS]], metadata !"Float8E5M2") #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret <2 x float> %fp



More information about the llvm-commits mailing list