[llvm] [Analysis] Adding convert_from_arbitrary_fp support in computeKnownFPClass. (PR #208585)
Chirag Patel via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 21 04:43:13 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/24] [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/24] 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/24] [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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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/24] 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
>From f0342d9690cb55727915da748996dd1b305dd382 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Thu, 16 Jul 2026 08:24:55 +0530
Subject: [PATCH 20/24] Adding todo for failing testcase
---
llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
index 7f9f6976fb8d9..e6cea6bbad940 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
@@ -32,10 +32,10 @@ define <4 x float> @ret_arbitrary_fp_vector_nan_inf_sub(<4 x i4> %bits) {
}
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
+; TODO-CHECK-LABEL: define nofpclass(inf nzero sub) float @ret_arbitrary_fp_inf_nzero_sub
+; TODO-CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
+; TODO-CHECK-NEXT: %fp = call nofpclass(inf nzero sub) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E4M3FNUZ") #[[ATTR2:[0-9]+]]
+; TODO-CHECK-NEXT: ret float %fp
;
%fp = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %bits, metadata !"Float8E4M3FNUZ")
ret float %fp
>From 6c444aceb19adf7b5ff305966d4837df107d34fd Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Sat, 18 Jul 2026 04:57:28 +0530
Subject: [PATCH 21/24] Adding comments. Removing unused path.
---
CppProperties.json | 21 +++++++++++++++++++++
llvm/lib/Analysis/ValueTracking.cpp | 14 +++++++-------
2 files changed, 28 insertions(+), 7 deletions(-)
create mode 100644 CppProperties.json
diff --git a/CppProperties.json b/CppProperties.json
new file mode 100644
index 0000000000000..6017def899500
--- /dev/null
+++ b/CppProperties.json
@@ -0,0 +1,21 @@
+{
+ "configurations": [
+ {
+ "inheritEnvironments": [
+ "msvc_x64"
+ ],
+ "name": "x64-Release",
+ "includePath": [
+ "${env.INCLUDE}",
+ "${workspaceRoot}\\**"
+ ],
+ "defines": [
+ "WIN32",
+ "NDEBUG",
+ "UNICODE",
+ "_UNICODE"
+ ],
+ "intelliSenseMode": "windows-msvc-x64"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 187f56aa741cd..1d1e91acffce8 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5742,21 +5742,21 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
if (!APFloat::semanticsHasNaN(SrcSemantics))
Known.knownNot(fcNan);
+
+ // fcInf can only be cleared if the source format has no Inf encoding
+ // (IEEE754) AND every finite src value fits correctly in the dest
+ // finite range, so inf is not possible
if (!APFloat::semanticsHasInf(SrcSemantics) &&
APFloat::isRepresentableBy(SrcSemantics, DstSemantics))
Known.knownNot(fcInf);
+ // Check and clear for FNUZ formats which lacks negative zero
if (SrcSemantics.nanEncoding == fltNanEncoding::NegativeZero)
Known.knownNot(fcNegZero);
- if (!APFloat::semanticsHasZero(SrcSemantics)) {
+ // Check if format has no zero at all, Float8E8M0FNU
+ if (!APFloat::semanticsHasZero(SrcSemantics))
Known.knownNot(fcZero);
- } else {
- KnownBits IntKnown =
- computeKnownBits(Op->getOperand(0), DemandedElts, Q, Depth + 1);
- if (IntKnown.isNonZero())
- Known.knownNot(fcPosZero);
- }
// If src lands normaly in dest, result can never be subnormal.
if (APFloat::isRepresentableAsNormalIn(SrcSemantics, DstSemantics))
>From 39a392b09e7c90e2b8380bfa0e041c9e879611d1 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Sat, 18 Jul 2026 05:02:32 +0530
Subject: [PATCH 22/24] cleanup
---
CppProperties.json | 21 ---------------------
1 file changed, 21 deletions(-)
delete mode 100644 CppProperties.json
diff --git a/CppProperties.json b/CppProperties.json
deleted file mode 100644
index 6017def899500..0000000000000
--- a/CppProperties.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "configurations": [
- {
- "inheritEnvironments": [
- "msvc_x64"
- ],
- "name": "x64-Release",
- "includePath": [
- "${env.INCLUDE}",
- "${workspaceRoot}\\**"
- ],
- "defines": [
- "WIN32",
- "NDEBUG",
- "UNICODE",
- "_UNICODE"
- ],
- "intelliSenseMode": "windows-msvc-x64"
- }
- ]
-}
\ No newline at end of file
>From 1a8afc5e49a8a02eeefb11bd6e6b3e12a4ceb332 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Tue, 21 Jul 2026 09:23:18 +0530
Subject: [PATCH 23/24] fixing inf related bug. Adding testcase for
Float8E8M0FNU
---
llvm/lib/Analysis/ValueTracking.cpp | 6 +++---
.../Transforms/Attributor/nofpclass-arbitrary-fp.ll | 10 ++++++++++
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 1d1e91acffce8..3c9ecc14134d7 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5744,10 +5744,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
Known.knownNot(fcNan);
// fcInf can only be cleared if the source format has no Inf encoding
- // (IEEE754) AND every finite src value fits correctly in the dest
- // finite range, so inf is not possible
+ // (IEEE754) AND the dst max exp can accomodate src max exp.
if (!APFloat::semanticsHasInf(SrcSemantics) &&
- APFloat::isRepresentableBy(SrcSemantics, DstSemantics))
+ APFloat::semanticsMaxExponent(SrcSemantics) <=
+ APFloat::semanticsMaxExponent(DstSemantics))
Known.knownNot(fcInf);
// Check and clear for FNUZ formats which lacks negative zero
diff --git a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
index e6cea6bbad940..6d7eb54899419 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
@@ -51,6 +51,16 @@ define <2 x float> @ret_arbitrary_fp_vector_sub(<2 x i8> %bits) {
ret <2 x float> %fp
}
+define float @ret_arbitrary_fp_inf_zero(i8 %bits) {
+; TODO-CHECK-LABEL: define nofpclass(inf zero) float @ret_arbitrary_fp_inf_zero
+; TODO-CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
+; TODO-CHECK-NEXT: %fp = call nofpclass(inf zero) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E8M0FNU") #[[ATTR2:[0-9]+]]
+; TODO-CHECK-NEXT: ret float %fp
+;
+ %fp = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %bits, metadata !"Float8E8M0FNU")
+ 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 79780753357329da86475e2f4e3072f7e96a4d19 Mon Sep 17 00:00:00 2001
From: chirag <chirag198838 at gmail.com>
Date: Tue, 21 Jul 2026 17:12:43 +0530
Subject: [PATCH 24/24] Adding neg flags check Fixing comment grammer mistakes
---
llvm/lib/Analysis/ValueTracking.cpp | 9 +++++++--
.../test/Transforms/Attributor/nofpclass-arbitrary-fp.ll | 6 +++---
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 3c9ecc14134d7..c5eb0f0dd3b83 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5744,7 +5744,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
Known.knownNot(fcNan);
// fcInf can only be cleared if the source format has no Inf encoding
- // (IEEE754) AND the dst max exp can accomodate src max exp.
+ // (IEEE-754) AND the dst max exp can accommodate src max exp.
if (!APFloat::semanticsHasInf(SrcSemantics) &&
APFloat::semanticsMaxExponent(SrcSemantics) <=
APFloat::semanticsMaxExponent(DstSemantics))
@@ -5754,11 +5754,16 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
if (SrcSemantics.nanEncoding == fltNanEncoding::NegativeZero)
Known.knownNot(fcNegZero);
+ // Check and clear all neg flags for formats that do not have signed
+ // representation.
+ if (!APFloat::semanticsHasSignedRepr(SrcSemantics))
+ Known.knownNot(fcNegative);
+
// Check if format has no zero at all, Float8E8M0FNU
if (!APFloat::semanticsHasZero(SrcSemantics))
Known.knownNot(fcZero);
- // If src lands normaly in dest, result can never be subnormal.
+ // If src lands normally in dest, the 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 6d7eb54899419..cdde26dfbc158 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
@@ -51,10 +51,10 @@ define <2 x float> @ret_arbitrary_fp_vector_sub(<2 x i8> %bits) {
ret <2 x float> %fp
}
-define float @ret_arbitrary_fp_inf_zero(i8 %bits) {
-; TODO-CHECK-LABEL: define nofpclass(inf zero) float @ret_arbitrary_fp_inf_zero
+define float @ret_arbitrary_fp_inf_zero_nsub_nnorm(i8 %bits) {
+; TODO-CHECK-LABEL: define nofpclass(inf zero nsub nnorm) float @ret_arbitrary_fp_inf_zero_nsub_nnorm
; TODO-CHECK-SAME: (i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
-; TODO-CHECK-NEXT: %fp = call nofpclass(inf zero) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E8M0FNU") #[[ATTR2:[0-9]+]]
+; TODO-CHECK-NEXT: %fp = call nofpclass(inf zero nsub nnorm) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E8M0FNU") #[[ATTR2:[0-9]+]]
; TODO-CHECK-NEXT: ret float %fp
;
%fp = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %bits, metadata !"Float8E8M0FNU")
More information about the llvm-commits
mailing list