[llvm] [Analysis] Adding convert_from_arbitrary_fp support in computeKnownFPClass. (PR #208585)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 28 04:55:50 PDT 2026
================
@@ -0,0 +1,116 @@
+; 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 @test_convert_float8e5m2_to_f32(i8 %bits) {
+; CHECK-LABEL: define nofpclass(sub) float @test_convert_float8e5m2_to_f32(
+; CHECK-SAME: i8 [[BITS:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[FP:%.*]] = call nofpclass(sub) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E5M2") #[[ATTR2:[0-9]+]]
+; CHECK-NEXT: ret float [[FP]]
+;
+ %fp = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %bits, metadata !"Float8E5M2")
+ ret float %fp
+}
+
+define float @test_convert_float8e5m2fnuz_to_f32(i8 %bits) {
+; CHECK-LABEL: define float @test_convert_float8e5m2fnuz_to_f32(
+; CHECK-SAME: i8 [[BITS:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[FP:%.*]] = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E5M2FNUZ") #[[ATTR2]]
+; CHECK-NEXT: ret float [[FP]]
+;
+ %fp = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %bits, metadata !"Float8E5M2FNUZ")
+ ret float %fp
+}
+
+define float @test_convert_float8e4m3_to_f32(i8 %bits) {
+; CHECK-LABEL: define float @test_convert_float8e4m3_to_f32(
+; CHECK-SAME: i8 [[BITS:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[FP:%.*]] = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E4M3") #[[ATTR2]]
+; CHECK-NEXT: ret float [[FP]]
+;
+ %fp = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %bits, metadata !"Float8E4M3")
+ ret float %fp
+}
+
+define float @test_convert_float8e4m3fn_to_f32(i8 %bits) {
+; CHECK-LABEL: define nofpclass(inf sub) float @test_convert_float8e4m3fn_to_f32(
+; CHECK-SAME: i8 [[BITS:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[FP:%.*]] = call nofpclass(inf sub) float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E4M3FN") #[[ATTR2]]
+; CHECK-NEXT: ret float [[FP]]
+;
+ %fp = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %bits, metadata !"Float8E4M3FN")
+ ret float %fp
+}
+
+define float @test_convert_float8e4m3fnuz_to_f32(i8 %bits) {
+; CHECK-LABEL: define float @test_convert_float8e4m3fnuz_to_f32(
+; CHECK-SAME: i8 [[BITS:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[FP:%.*]] = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E4M3FNUZ") #[[ATTR2]]
+; CHECK-NEXT: ret float [[FP]]
+;
+ %fp = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %bits, metadata !"Float8E4M3FNUZ")
+ ret float %fp
+}
+
+define float @test_convert_float8e4m3b11fnuz_to_f32(i8 %bits) {
+; CHECK-LABEL: define float @test_convert_float8e4m3b11fnuz_to_f32(
+; CHECK-SAME: i8 [[BITS:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[FP:%.*]] = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E4M3B11FNUZ") #[[ATTR2]]
+; CHECK-NEXT: ret float [[FP]]
+;
+ %fp = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %bits, metadata !"Float8E4M3B11FNUZ")
+ ret float %fp
+}
+
+define float @test_convert_float8e3m4_to_f32(i8 %bits) {
+; CHECK-LABEL: define float @test_convert_float8e3m4_to_f32(
+; CHECK-SAME: i8 [[BITS:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[FP:%.*]] = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E3M4") #[[ATTR2]]
+; CHECK-NEXT: ret float [[FP]]
+;
+ %fp = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %bits, metadata !"Float8E3M4")
+ ret float %fp
+}
+
+define float @test_convert_float8e8m0fnu_to_f32(i8 %bits) {
+; CHECK-LABEL: define float @test_convert_float8e8m0fnu_to_f32(
+; CHECK-SAME: i8 [[BITS:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[FP:%.*]] = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 [[BITS]], metadata !"Float8E8M0FNU") #[[ATTR2]]
+; CHECK-NEXT: ret float [[FP]]
+;
+ %fp = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %bits, metadata !"Float8E8M0FNU")
+ ret float %fp
+}
+
+define float @test_convert_float6e3m2fn_to_f32(i6 %bits) {
+; CHECK-LABEL: define nofpclass(nan inf sub) float @test_convert_float6e3m2fn_to_f32(
+; CHECK-SAME: i6 [[BITS:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[FP:%.*]] = call nofpclass(nan inf sub) float @llvm.convert.from.arbitrary.fp.f32.i6(i6 [[BITS]], metadata !"Float6E3M2FN") #[[ATTR2]]
+; CHECK-NEXT: ret float [[FP]]
+;
+ %fp = call float @llvm.convert.from.arbitrary.fp.f32.i6(i6 %bits, metadata !"Float6E3M2FN")
+ ret float %fp
+}
+
+define float @test_convert_float6e2m3fn_to_f32(i6 %bits) {
+; CHECK-LABEL: define nofpclass(nan inf sub) float @test_convert_float6e2m3fn_to_f32(
+; CHECK-SAME: i6 [[BITS:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[FP:%.*]] = call nofpclass(nan inf sub) float @llvm.convert.from.arbitrary.fp.f32.i6(i6 [[BITS]], metadata !"Float6E2M3FN") #[[ATTR2]]
+; CHECK-NEXT: ret float [[FP]]
+;
+ %fp = call float @llvm.convert.from.arbitrary.fp.f32.i6(i6 %bits, metadata !"Float6E2M3FN")
+ ret float %fp
+}
+
+define float @test_convert_float4e2m1fn_to_f32(i4 %bits) {
+; CHECK-LABEL: define nofpclass(nan inf sub) float @test_convert_float4e2m1fn_to_f32(
+; CHECK-SAME: i4 [[BITS:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[FP:%.*]] = call nofpclass(nan inf sub) float @llvm.convert.from.arbitrary.fp.f32.i4(i4 [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2]]
+; CHECK-NEXT: ret float [[FP]]
+;
+ %fp = call float @llvm.convert.from.arbitrary.fp.f32.i4(i4 %bits, metadata !"Float4E2M1FN")
+ ret float %fp
+}
+
----------------
arsenm wrote:
> Here, we clear ninf flag but inf is possible. But as format is unsigned anyways, can we keep the ninf cleared in nofpclass ?
Yes, if it's unsigned only then `nofpclass(ninf)` should be fine; this comment has `nofpclass(inf)` on that example, which is a problem since pinf is not known
https://github.com/llvm/llvm-project/pull/208585
More information about the llvm-commits
mailing list