mirror-llvm-project/llvm/test/Transforms/Attributor/nofpclass-arbitrary-fp.ll
Chirag Patel dc5f2aae75
[Analysis] Adding convert_from_arbitrary_fp support in computeKnownFPClass. (#208585)
fixes #208437 

From LangRef for intrinsic convert_from_arbitrary_fp ,
"Normal finite values are converted exactly. NaN values follow LLVM’s
standard NaN rules; the NaN representation is preserved... and the NaN
payload may be truncated or extended..."
-> if src has Nan -> preserve nan

"If a value exceeds the representable range of the target type (for
example, converting Float8E8M0FNU with large exponents to half), the
result is converted to infinity with the appropriate sign."
2026-07-29 15:35:52 +02:00

192 lines
9.3 KiB
LLVM

; 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
}
define double @test_convert_float4e2m1fn_to_f64(i4 %bits) {
; CHECK-LABEL: define nofpclass(nan inf sub) double @test_convert_float4e2m1fn_to_f64(
; CHECK-SAME: i4 [[BITS:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FP:%.*]] = call nofpclass(nan inf sub) double @llvm.convert.from.arbitrary.fp.f64.i4(i4 [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2]]
; CHECK-NEXT: ret double [[FP]]
;
%fp = call double @llvm.convert.from.arbitrary.fp.f64.i4(i4 %bits, metadata !"Float4E2M1FN")
ret double %fp
}
define half @test_convert_float8e4m3fn_to_f16(i8 %bits) {
; CHECK-LABEL: define nofpclass(inf sub) half @test_convert_float8e4m3fn_to_f16(
; CHECK-SAME: i8 [[BITS:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FP:%.*]] = call nofpclass(inf sub) half @llvm.convert.from.arbitrary.fp.f16.i8(i8 [[BITS]], metadata !"Float8E4M3FN") #[[ATTR2]]
; CHECK-NEXT: ret half [[FP]]
;
%fp = call half @llvm.convert.from.arbitrary.fp.f16.i8(i8 %bits, metadata !"Float8E4M3FN")
ret half %fp
}
define half @test_convert_float6e2m3fn_to_f16(i6 %bits) {
; CHECK-LABEL: define nofpclass(nan inf sub) half @test_convert_float6e2m3fn_to_f16(
; CHECK-SAME: i6 [[BITS:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FP:%.*]] = call nofpclass(nan inf sub) half @llvm.convert.from.arbitrary.fp.f16.i6(i6 [[BITS]], metadata !"Float6E2M3FN") #[[ATTR2]]
; CHECK-NEXT: ret half [[FP]]
;
%fp = call half @llvm.convert.from.arbitrary.fp.f16.i6(i6 %bits, metadata !"Float6E2M3FN")
ret half %fp
}
define <4 x half> @test_convert_float8e5m2_to_v4f16(<4 x i8> %bits) {
; CHECK-LABEL: define <4 x half> @test_convert_float8e5m2_to_v4f16(
; CHECK-SAME: <4 x i8> [[BITS:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FP:%.*]] = call <4 x half> @llvm.convert.from.arbitrary.fp.v4f16.v4i8(<4 x i8> [[BITS]], metadata !"Float8E5M2") #[[ATTR2]]
; CHECK-NEXT: ret <4 x half> [[FP]]
;
%fp = call <4 x half> @llvm.convert.from.arbitrary.fp.v4f16.v4i8(<4 x i8> %bits, metadata !"Float8E5M2")
ret <4 x half> %fp
}
define <4 x double> @test_convert_float4e2m1fn_to_v4f64(<4 x i4> %bits) {
; CHECK-LABEL: define nofpclass(nan inf sub) <4 x double> @test_convert_float4e2m1fn_to_v4f64(
; CHECK-SAME: <4 x i4> [[BITS:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FP:%.*]] = call nofpclass(nan inf sub) <4 x double> @llvm.convert.from.arbitrary.fp.v4f64.v4i4(<4 x i4> [[BITS]], metadata !"Float4E2M1FN") #[[ATTR2]]
; CHECK-NEXT: ret <4 x double> [[FP]]
;
%fp = call <4 x double> @llvm.convert.from.arbitrary.fp.v4f64.v4i4(<4 x i4> %bits, metadata !"Float4E2M1FN")
ret <4 x double> %fp
}
define <4 x double> @test_convert_float6e3m2fn_to_v4f64(<4 x i6> %bits) {
; CHECK-LABEL: define nofpclass(nan inf sub) <4 x double> @test_convert_float6e3m2fn_to_v4f64(
; CHECK-SAME: <4 x i6> [[BITS:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FP:%.*]] = call nofpclass(nan inf sub) <4 x double> @llvm.convert.from.arbitrary.fp.v4f64.v4i6(<4 x i6> [[BITS]], metadata !"Float6E3M2FN") #[[ATTR2]]
; CHECK-NEXT: ret <4 x double> [[FP]]
;
%fp = call <4 x double> @llvm.convert.from.arbitrary.fp.v4f64.v4i6(<4 x i6> %bits, metadata !"Float6E3M2FN")
ret <4 x double> %fp
}
define half @test_convert_float8e8m0fnu_to_f16(i8 %bits) {
; CHECK-LABEL: define half @test_convert_float8e8m0fnu_to_f16(
; CHECK-SAME: i8 [[BITS:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FP:%.*]] = call half @llvm.convert.from.arbitrary.fp.f16.i8(i8 [[BITS]], metadata !"Float8E8M0FNU") #[[ATTR2]]
; CHECK-NEXT: ret half [[FP]]
;
%fp = call half @llvm.convert.from.arbitrary.fp.f16.i8(i8 %bits, metadata !"Float8E8M0FNU")
ret half %fp
}
declare float @llvm.convert.from.arbitrary.fp.f32.i4(i4, metadata)
declare float @llvm.convert.from.arbitrary.fp.f32.i6(i6, metadata)
declare float @llvm.convert.from.arbitrary.fp.f32.i8(i8, metadata)
declare double @llvm.convert.from.arbitrary.fp.f64.i4(i4, metadata)
declare half @llvm.convert.from.arbitrary.fp.f16.i8(i8, metadata)
declare half @llvm.convert.from.arbitrary.fp.f16.i6(i6, metadata)
declare <4 x double> @llvm.convert.from.arbitrary.fp.v4f64.v4i4(<4 x i4>, metadata)
declare <4 x half> @llvm.convert.from.arbitrary.fp.v4f16.v4i8(<4 x i8>, metadata)
declare <4 x double> @llvm.convert.from.arbitrary.fp.v4f64.v4i6(<4 x i6>, metadata)