; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s ; Test llvm.convert.from.arbitrary intrinsic expansion. declare float @llvm.convert.from.arbitrary.fp.f32.i8(i8, metadata) declare float @llvm.convert.from.arbitrary.fp.f32.i6(i6, metadata) declare float @llvm.convert.from.arbitrary.fp.f32.i4(i4, metadata) declare <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i4(<4 x i4>, metadata) declare half @llvm.convert.from.arbitrary.fp.f16.i8(i8, metadata) declare double @llvm.convert.from.arbitrary.fp.f64.i8(i8, metadata) ; Float8E5M2 ; Layout: sign(1) exp(5) mant(2), bias=15 ; Supports: Inf, NaN, signed zero, denormals ; Float8E5M2 normal: 0_01111_00 = 1.0 define float @from_f8e5m2_normal() { ; CHECK-LABEL: from_f8e5m2_normal: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 60, metadata !"Float8E5M2") ret float %r } ; Float8E5M2 zero: 0_00000_00 = +0.0 define float @from_f8e5m2_zero() { ; CHECK-LABEL: from_f8e5m2_zero: ; CHECK: # %bb.0: ; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 0, metadata !"Float8E5M2") ret float %r } ; Float8E5M2 negative zero: 1_00000_00 = -0.0 define float @from_f8e5m2_neg_zero() { ; CHECK-LABEL: from_f8e5m2_neg_zero: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [-0.0E+0,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 -128, metadata !"Float8E5M2") ret float %r } ; Float8E5M2 denorm: 0_00000_01 = 2^(-16) define float @from_f8e5m2_denorm() { ; CHECK-LABEL: from_f8e5m2_denorm: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [1.52587891E-5,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 1, metadata !"Float8E5M2") ret float %r } ; Float8E5M2 +Inf: 0_11111_00 define float @from_f8e5m2_inf() { ; CHECK-LABEL: from_f8e5m2_inf: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [+Inf,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 124, metadata !"Float8E5M2") ret float %r } ; Float8E5M2 NaN: 0_11111_01 define float @from_f8e5m2_nan() { ; CHECK-LABEL: from_f8e5m2_nan: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [NaN,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 125, metadata !"Float8E5M2") ret float %r } ; Float8E5M2 max: 0_11110_11 = 57344 define float @from_f8e5m2_max() { ; CHECK-LABEL: from_f8e5m2_max: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [5.7344E+4,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 123, metadata !"Float8E5M2") ret float %r } ; Float8E5M2 negative: 1_01111_00 = -1.0 define float @from_f8e5m2_neg() { ; CHECK-LABEL: from_f8e5m2_neg: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [-1.0E+0,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 -68, metadata !"Float8E5M2") ret float %r } ; Float8E5M2 runtime arg test define float @from_f8e5m2_dynamic(i8 %x) { ; CHECK-LABEL: from_f8e5m2_dynamic: ; CHECK: # %bb.0: ; CHECK-NEXT: movl %edi, %edx ; CHECK-NEXT: andl $3, %edx ; CHECK-NEXT: movl %edx, %ecx ; CHECK-NEXT: shll $21, %ecx ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: andl $-128, %eax ; CHECK-NEXT: shll $24, %eax ; CHECK-NEXT: shrl $2, %edi ; CHECK-NEXT: andl $31, %edi ; CHECK-NEXT: movl %edi, %esi ; CHECK-NEXT: shll $23, %esi ; CHECK-NEXT: orl %eax, %esi ; CHECK-NEXT: leal 939524096(%rcx,%rsi), %esi ; CHECK-NEXT: bsrl %edx, %r8d ; CHECK-NEXT: movl %edx, %r9d ; CHECK-NEXT: btcl %r8d, %r9d ; CHECK-NEXT: xorl $31, %r8d ; CHECK-NEXT: leal -8(%r8), %ecx ; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx ; CHECK-NEXT: shll %cl, %r9d ; CHECK-NEXT: movl $142, %ecx ; CHECK-NEXT: subl %r8d, %ecx ; CHECK-NEXT: shll $23, %ecx ; CHECK-NEXT: orl %eax, %ecx ; CHECK-NEXT: orl %r9d, %ecx ; CHECK-NEXT: testl %edx, %edx ; CHECK-NEXT: sete %dl ; CHECK-NEXT: setne %r8b ; CHECK-NEXT: testl %edi, %edi ; CHECK-NEXT: sete %r9b ; CHECK-NEXT: testb %r8b, %r9b ; CHECK-NEXT: cmovel %esi, %ecx ; CHECK-NEXT: testb %dl, %r9b ; CHECK-NEXT: cmovnel %eax, %ecx ; CHECK-NEXT: orl $2139095040, %eax # imm = 0x7F800000 ; CHECK-NEXT: cmpl $31, %edi ; CHECK-NEXT: sete %sil ; CHECK-NEXT: testb %dl, %sil ; CHECK-NEXT: cmovel %ecx, %eax ; CHECK-NEXT: testb %r8b, %sil ; CHECK-NEXT: movl $2143289344, %ecx # imm = 0x7FC00000 ; CHECK-NEXT: cmovel %eax, %ecx ; CHECK-NEXT: movd %ecx, %xmm0 ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %x, metadata !"Float8E5M2") ret float %r } ; Float8E4M3FN (NanOnly, NanEncoding=AllOnes) ; Layout: sign(1) exp(4) mant(3), maxExp=8, minExp=-6, bias=7 ; Only 0_1111_111 and 1_1111_111 are NaN; all other exp=15 values are finite. ; Float8E4M3FN normal: 0_0111_000 = 1.0 define float @from_f8e4m3fn_normal() { ; CHECK-LABEL: from_f8e4m3fn_normal: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 56, metadata !"Float8E4M3FN") ret float %r } ; Float8E4M3FN NaN: 0_1111_111 define float @from_f8e4m3fn_nan() { ; CHECK-LABEL: from_f8e4m3fn_nan: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [NaN,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 127, metadata !"Float8E4M3FN") ret float %r } ; Float8E4M3FN not-NaN: 0_1111_110 = 448 ; Despite exp=all-ones, this is a valid finite number (max value) define float @from_f8e4m3fn_max() { ; CHECK-LABEL: from_f8e4m3fn_max: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [4.48E+2,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 126, metadata !"Float8E4M3FN") ret float %r } ; Float8E4M3FN not-NaN: 0_1111_101 = 416 ; exp=all-ones but mant!=all-ones so this is finite define float @from_f8e4m3fn_not_nan() { ; CHECK-LABEL: from_f8e4m3fn_not_nan: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [4.16E+2,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 125, metadata !"Float8E4M3FN") ret float %r } ; Float8E4M3FN zero: 0_0000_000 = +0.0 define float @from_f8e4m3fn_zero() { ; CHECK-LABEL: from_f8e4m3fn_zero: ; CHECK: # %bb.0: ; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 0, metadata !"Float8E4M3FN") ret float %r } ; Float8E4M3FN denorm: 0_0000_001 = 2^(-9) define float @from_f8e4m3fn_denorm() { ; CHECK-LABEL: from_f8e4m3fn_denorm: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [1.953125E-3,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 1, metadata !"Float8E4M3FN") ret float %r } ; Float8E4M3FN runtime arg test define float @from_f8e4m3fn_dynamic(i8 %x) { ; CHECK-LABEL: from_f8e4m3fn_dynamic: ; CHECK: # %bb.0: ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: andl $7, %eax ; CHECK-NEXT: movl %eax, %ecx ; CHECK-NEXT: shll $20, %ecx ; CHECK-NEXT: movl %edi, %edx ; CHECK-NEXT: andl $-128, %edx ; CHECK-NEXT: shll $24, %edx ; CHECK-NEXT: shrl $3, %edi ; CHECK-NEXT: andl $15, %edi ; CHECK-NEXT: movl %edi, %esi ; CHECK-NEXT: shll $23, %esi ; CHECK-NEXT: orl %edx, %esi ; CHECK-NEXT: leal 1006632960(%rcx,%rsi), %esi ; CHECK-NEXT: bsrl %eax, %r8d ; CHECK-NEXT: movl %eax, %r9d ; CHECK-NEXT: btcl %r8d, %r9d ; CHECK-NEXT: xorl $31, %r8d ; CHECK-NEXT: leal -8(%r8), %ecx ; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx ; CHECK-NEXT: shll %cl, %r9d ; CHECK-NEXT: movl $149, %ecx ; CHECK-NEXT: subl %r8d, %ecx ; CHECK-NEXT: shll $23, %ecx ; CHECK-NEXT: orl %edx, %ecx ; CHECK-NEXT: orl %r9d, %ecx ; CHECK-NEXT: testl %eax, %eax ; CHECK-NEXT: sete %r8b ; CHECK-NEXT: setne %r9b ; CHECK-NEXT: testl %edi, %edi ; CHECK-NEXT: sete %r10b ; CHECK-NEXT: testb %r9b, %r10b ; CHECK-NEXT: cmovel %esi, %ecx ; CHECK-NEXT: testb %r8b, %r10b ; CHECK-NEXT: cmovnel %edx, %ecx ; CHECK-NEXT: cmpl $7, %eax ; CHECK-NEXT: sete %al ; CHECK-NEXT: cmpl $15, %edi ; CHECK-NEXT: sete %dl ; CHECK-NEXT: testb %al, %dl ; CHECK-NEXT: movl $2143289344, %eax # imm = 0x7FC00000 ; CHECK-NEXT: cmovel %ecx, %eax ; CHECK-NEXT: movd %eax, %xmm0 ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i8(i8 %x, metadata !"Float8E4M3FN") ret float %r } ; Float6E3M2FN (FiniteOnly) ; Layout: sign(1) exp(3) mant(2), bias=3, maxExp=4 ; No Inf, no NaN. All bit patterns are finite. ; Float6E3M2FN normal: 0_011_00 = 1.0 define float @from_f6e3m2fn_normal() { ; CHECK-LABEL: from_f6e3m2fn_normal: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i6(i6 12, metadata !"Float6E3M2FN") ret float %r } ; Float6E3M2FN max: 0_111_11 = 28.0 define float @from_f6e3m2fn_max() { ; CHECK-LABEL: from_f6e3m2fn_max: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [2.8E+1,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i6(i6 31, metadata !"Float6E3M2FN") ret float %r } ; Float6E3M2FN denorm: 0_000_01 = 0.0625 define float @from_f6e3m2fn_denorm() { ; CHECK-LABEL: from_f6e3m2fn_denorm: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [6.25E-2,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i6(i6 1, metadata !"Float6E3M2FN") ret float %r } ; Float6E3M2FN zero: 0_000_00 = +0.0 define float @from_f6e3m2fn_zero() { ; CHECK-LABEL: from_f6e3m2fn_zero: ; CHECK: # %bb.0: ; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i6(i6 0, metadata !"Float6E3M2FN") ret float %r } ; Float6E3M2FN negative: 1_011_00 = -1.0 define float @from_f6e3m2fn_neg() { ; CHECK-LABEL: from_f6e3m2fn_neg: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [-1.0E+0,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i6(i6 -20, metadata !"Float6E3M2FN") ret float %r } ; Float6E3M2FN runtime arg test define float @from_f6e3m2fn_dynamic(i6 %x) { ; CHECK-LABEL: from_f6e3m2fn_dynamic: ; CHECK: # %bb.0: ; CHECK-NEXT: movl %edi, %edx ; CHECK-NEXT: andl $3, %edx ; CHECK-NEXT: movl %edx, %ecx ; CHECK-NEXT: shll $21, %ecx ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: andl $-32, %eax ; CHECK-NEXT: shll $26, %eax ; CHECK-NEXT: shrl $2, %edi ; CHECK-NEXT: andl $7, %edi ; CHECK-NEXT: movl %edi, %esi ; CHECK-NEXT: shll $23, %esi ; CHECK-NEXT: orl %eax, %esi ; CHECK-NEXT: leal 1040187392(%rcx,%rsi), %esi ; CHECK-NEXT: bsrl %edx, %r8d ; CHECK-NEXT: movl %edx, %r9d ; CHECK-NEXT: btcl %r8d, %r9d ; CHECK-NEXT: xorl $31, %r8d ; CHECK-NEXT: leal -8(%r8), %ecx ; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx ; CHECK-NEXT: shll %cl, %r9d ; CHECK-NEXT: movl $154, %ecx ; CHECK-NEXT: subl %r8d, %ecx ; CHECK-NEXT: shll $23, %ecx ; CHECK-NEXT: orl %eax, %ecx ; CHECK-NEXT: orl %r9d, %ecx ; CHECK-NEXT: testl %edx, %edx ; CHECK-NEXT: sete %dl ; CHECK-NEXT: setne %r8b ; CHECK-NEXT: testl %edi, %edi ; CHECK-NEXT: sete %dil ; CHECK-NEXT: testb %r8b, %dil ; CHECK-NEXT: cmovel %esi, %ecx ; CHECK-NEXT: testb %dl, %dil ; CHECK-NEXT: cmovnel %eax, %ecx ; CHECK-NEXT: movd %ecx, %xmm0 ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i6(i6 %x, metadata !"Float6E3M2FN") ret float %r } ; Float6E2M3FN (FiniteOnly) ; Layout: sign(1) exp(2) mant(3), bias=1, maxExp=2 ; No Inf, no NaN. All bit patterns are finite. ; Float6E2M3FN normal: 0_01_000 = 1.0 define float @from_f6e2m3fn_normal() { ; CHECK-LABEL: from_f6e2m3fn_normal: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i6(i6 8, metadata !"Float6E2M3FN") ret float %r } ; Float6E2M3FN max: 0_11_111 = 7.5 define float @from_f6e2m3fn_max() { ; CHECK-LABEL: from_f6e2m3fn_max: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [7.5E+0,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i6(i6 31, metadata !"Float6E2M3FN") ret float %r } ; Float6E2M3FN denorm: 0_00_001 = 0.125 define float @from_f6e2m3fn_denorm() { ; CHECK-LABEL: from_f6e2m3fn_denorm: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [1.25E-1,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i6(i6 1, metadata !"Float6E2M3FN") ret float %r } ; Float6E2M3FN zero: 0_00_000 = +0.0 define float @from_f6e2m3fn_zero() { ; CHECK-LABEL: from_f6e2m3fn_zero: ; CHECK: # %bb.0: ; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i6(i6 0, metadata !"Float6E2M3FN") ret float %r } ; Float6E2M3FN runtime arg test define float @from_f6e2m3fn_dynamic(i6 %x) { ; CHECK-LABEL: from_f6e2m3fn_dynamic: ; CHECK: # %bb.0: ; CHECK-NEXT: movl %edi, %edx ; CHECK-NEXT: andl $7, %edx ; CHECK-NEXT: movl %edx, %ecx ; CHECK-NEXT: shll $20, %ecx ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: andl $-32, %eax ; CHECK-NEXT: shll $26, %eax ; CHECK-NEXT: shrl $3, %edi ; CHECK-NEXT: andl $3, %edi ; CHECK-NEXT: movl %edi, %esi ; CHECK-NEXT: shll $23, %esi ; CHECK-NEXT: orl %eax, %esi ; CHECK-NEXT: leal 1056964608(%rcx,%rsi), %esi ; CHECK-NEXT: bsrl %edx, %r8d ; CHECK-NEXT: movl %edx, %r9d ; CHECK-NEXT: btcl %r8d, %r9d ; CHECK-NEXT: xorl $31, %r8d ; CHECK-NEXT: leal -8(%r8), %ecx ; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx ; CHECK-NEXT: shll %cl, %r9d ; CHECK-NEXT: movl $155, %ecx ; CHECK-NEXT: subl %r8d, %ecx ; CHECK-NEXT: shll $23, %ecx ; CHECK-NEXT: orl %eax, %ecx ; CHECK-NEXT: orl %r9d, %ecx ; CHECK-NEXT: testl %edx, %edx ; CHECK-NEXT: sete %dl ; CHECK-NEXT: setne %r8b ; CHECK-NEXT: testl %edi, %edi ; CHECK-NEXT: sete %dil ; CHECK-NEXT: testb %r8b, %dil ; CHECK-NEXT: cmovel %esi, %ecx ; CHECK-NEXT: testb %dl, %dil ; CHECK-NEXT: cmovnel %eax, %ecx ; CHECK-NEXT: movd %ecx, %xmm0 ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i6(i6 %x, metadata !"Float6E2M3FN") ret float %r } ; Float4E2M1FN (FiniteOnly) ; Layout: sign(1) exp(2) mant(1), bias=1, maxExp=2 ; No Inf, no NaN. ; Float4E2M1FN normal: 0_01_0 = 1.0 define float @from_f4e2m1fn_normal() { ; CHECK-LABEL: from_f4e2m1fn_normal: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i4(i4 2, metadata !"Float4E2M1FN") ret float %r } ; Float4E2M1FN denorm: 0_00_1 = 0.5 define float @from_f4e2m1fn_denorm() { ; CHECK-LABEL: from_f4e2m1fn_denorm: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [5.0E-1,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i4(i4 1, metadata !"Float4E2M1FN") ret float %r } ; Float4E2M1FN max: 0_11_1 = 6.0 define float @from_f4e2m1fn_max() { ; CHECK-LABEL: from_f4e2m1fn_max: ; CHECK: # %bb.0: ; CHECK-NEXT: movss {{.*#+}} xmm0 = [6.0E+0,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i4(i4 7, metadata !"Float4E2M1FN") ret float %r } ; Float4E2M1FN runtime arg test define float @from_f4e2m1fn_dynamic(i4 %x) { ; CHECK-LABEL: from_f4e2m1fn_dynamic: ; CHECK: # %bb.0: ; CHECK-NEXT: movl %edi, %edx ; CHECK-NEXT: andl $1, %edx ; CHECK-NEXT: movl %edx, %ecx ; CHECK-NEXT: shll $22, %ecx ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: andl $-8, %eax ; CHECK-NEXT: shll $28, %eax ; CHECK-NEXT: shrl %edi ; CHECK-NEXT: andl $3, %edi ; CHECK-NEXT: movl %edi, %esi ; CHECK-NEXT: shll $23, %esi ; CHECK-NEXT: orl %eax, %esi ; CHECK-NEXT: leal 1056964608(%rcx,%rsi), %esi ; CHECK-NEXT: bsrl %edx, %r8d ; CHECK-NEXT: movl %edx, %r9d ; CHECK-NEXT: btcl %r8d, %r9d ; CHECK-NEXT: xorl $31, %r8d ; CHECK-NEXT: leal -8(%r8), %ecx ; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx ; CHECK-NEXT: shll %cl, %r9d ; CHECK-NEXT: movl $157, %ecx ; CHECK-NEXT: subl %r8d, %ecx ; CHECK-NEXT: shll $23, %ecx ; CHECK-NEXT: orl %eax, %ecx ; CHECK-NEXT: orl %r9d, %ecx ; CHECK-NEXT: testl %edx, %edx ; CHECK-NEXT: sete %dl ; CHECK-NEXT: setne %r8b ; CHECK-NEXT: testl %edi, %edi ; CHECK-NEXT: sete %dil ; CHECK-NEXT: testb %r8b, %dil ; CHECK-NEXT: cmovel %esi, %ecx ; CHECK-NEXT: testb %dl, %dil ; CHECK-NEXT: cmovnel %eax, %ecx ; CHECK-NEXT: movd %ecx, %xmm0 ; CHECK-NEXT: retq %r = call float @llvm.convert.from.arbitrary.fp.f32.i4(i4 %x, metadata !"Float4E2M1FN") ret float %r } ; Float8E5M2 to f16: 1.0 define half @from_f8e5m2_to_f16() { ; CHECK-LABEL: from_f8e5m2_to_f16: ; CHECK: # %bb.0: ; CHECK-NEXT: pinsrw $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; CHECK-NEXT: retq %r = call half @llvm.convert.from.arbitrary.fp.f16.i8(i8 60, metadata !"Float8E5M2") ret half %r } ; Float8E5M2 to f64: 1.0 define double @from_f8e5m2_to_f64() { ; CHECK-LABEL: from_f8e5m2_to_f64: ; CHECK: # %bb.0: ; CHECK-NEXT: movsd {{.*#+}} xmm0 = [1.0E+0,0.0E+0] ; CHECK-NEXT: retq %r = call double @llvm.convert.from.arbitrary.fp.f64.i8(i8 60, metadata !"Float8E5M2") ret double %r } declare bfloat @llvm.convert.from.arbitrary.fp.bf16.i8(i8, metadata) declare <2 x bfloat> @llvm.convert.from.arbitrary.fp.v2bf16.v2i8(<2 x i8>, metadata) ; Float8E5M2 to bf16: 1.0 ; bf16 has: sign(1) exp(8) mant(7), bias=127 define bfloat @from_f8e5m2_to_bf16() { ; CHECK-LABEL: from_f8e5m2_to_bf16: ; CHECK: # %bb.0: ; CHECK-NEXT: pushq %rax ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: movss {{.*#+}} xmm0 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0] ; CHECK-NEXT: callq __truncsfbf2@PLT ; CHECK-NEXT: popq %rax ; CHECK-NEXT: .cfi_def_cfa_offset 8 ; CHECK-NEXT: retq %r = call bfloat @llvm.convert.from.arbitrary.fp.bf16.i8(i8 60, metadata !"Float8E5M2") ret bfloat %r } ; Vector test: Float4E2M1FN <4 x i4> -> <4 x float> define <4 x float> @fp4_to_f32_vec(<4 x i4> %x) { ; CHECK-LABEL: fp4_to_f32_vec: ; CHECK: # %bb.0: ; CHECK-NEXT: movdqa %xmm0, %xmm1 ; CHECK-NEXT: movdqa {{.*#+}} xmm2 = [1,1,1,1] ; CHECK-NEXT: pand %xmm2, %xmm0 ; CHECK-NEXT: pcmpeqd %xmm3, %xmm3 ; CHECK-NEXT: pxor %xmm0, %xmm3 ; CHECK-NEXT: psubb {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm3 ; CHECK-NEXT: movdqa {{.*#+}} xmm4 = [51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51] ; CHECK-NEXT: movdqa %xmm3, %xmm5 ; CHECK-NEXT: pand %xmm4, %xmm5 ; CHECK-NEXT: psrlw $2, %xmm3 ; CHECK-NEXT: pand %xmm4, %xmm3 ; CHECK-NEXT: paddb %xmm5, %xmm3 ; CHECK-NEXT: movdqa %xmm3, %xmm5 ; CHECK-NEXT: psrlw $4, %xmm5 ; CHECK-NEXT: paddb %xmm3, %xmm5 ; CHECK-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm5 ; CHECK-NEXT: pxor %xmm3, %xmm3 ; CHECK-NEXT: movdqa %xmm5, %xmm4 ; CHECK-NEXT: punpckhdq {{.*#+}} xmm4 = xmm4[2],xmm3[2],xmm4[3],xmm3[3] ; CHECK-NEXT: psadbw %xmm3, %xmm4 ; CHECK-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm3[0],xmm5[1],xmm3[1] ; CHECK-NEXT: psadbw %xmm3, %xmm5 ; CHECK-NEXT: packuswb %xmm4, %xmm5 ; CHECK-NEXT: movdqa {{.*#+}} xmm4 = [31,31,31,31] ; CHECK-NEXT: psubd %xmm5, %xmm4 ; CHECK-NEXT: pslld $23, %xmm4 ; CHECK-NEXT: movdqa {{.*#+}} xmm6 = [1065353216,1065353216,1065353216,1065353216] ; CHECK-NEXT: paddd %xmm6, %xmm4 ; CHECK-NEXT: cvttps2dq %xmm4, %xmm7 ; CHECK-NEXT: pxor %xmm0, %xmm7 ; CHECK-NEXT: movdqa {{.*#+}} xmm4 = [157,157,157,157] ; CHECK-NEXT: psubd %xmm5, %xmm4 ; CHECK-NEXT: psubd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm5 ; CHECK-NEXT: pslld $23, %xmm5 ; CHECK-NEXT: paddd %xmm6, %xmm5 ; CHECK-NEXT: cvttps2dq %xmm5, %xmm5 ; CHECK-NEXT: pshufd {{.*#+}} xmm6 = xmm7[1,1,3,3] ; CHECK-NEXT: pmuludq %xmm5, %xmm7 ; CHECK-NEXT: pshufd {{.*#+}} xmm7 = xmm7[0,2,2,3] ; CHECK-NEXT: pshufd {{.*#+}} xmm5 = xmm5[1,1,3,3] ; CHECK-NEXT: pmuludq %xmm6, %xmm5 ; CHECK-NEXT: pshufd {{.*#+}} xmm5 = xmm5[0,2,2,3] ; CHECK-NEXT: punpckldq {{.*#+}} xmm7 = xmm7[0],xmm5[0],xmm7[1],xmm5[1] ; CHECK-NEXT: pslld $23, %xmm4 ; CHECK-NEXT: movdqa %xmm1, %xmm5 ; CHECK-NEXT: psrld $3, %xmm5 ; CHECK-NEXT: pslld $31, %xmm5 ; CHECK-NEXT: por %xmm5, %xmm4 ; CHECK-NEXT: por %xmm7, %xmm4 ; CHECK-NEXT: pcmpeqd %xmm0, %xmm2 ; CHECK-NEXT: psrld $1, %xmm1 ; CHECK-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 ; CHECK-NEXT: movdqa %xmm1, %xmm6 ; CHECK-NEXT: pcmpeqd %xmm3, %xmm6 ; CHECK-NEXT: pand %xmm6, %xmm2 ; CHECK-NEXT: pand %xmm2, %xmm4 ; CHECK-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 # [126,126,126,126] ; CHECK-NEXT: pslld $23, %xmm1 ; CHECK-NEXT: movdqa %xmm0, %xmm7 ; CHECK-NEXT: pslld $22, %xmm7 ; CHECK-NEXT: por %xmm5, %xmm7 ; CHECK-NEXT: por %xmm1, %xmm7 ; CHECK-NEXT: pandn %xmm7, %xmm2 ; CHECK-NEXT: por %xmm4, %xmm2 ; CHECK-NEXT: pcmpeqd %xmm3, %xmm0 ; CHECK-NEXT: pand %xmm6, %xmm0 ; CHECK-NEXT: pand %xmm0, %xmm5 ; CHECK-NEXT: pandn %xmm2, %xmm0 ; CHECK-NEXT: por %xmm5, %xmm0 ; CHECK-NEXT: retq %r = call <4 x float> @llvm.convert.from.arbitrary.fp.v4f32.v4i4(<4 x i4> %x, metadata !"Float4E2M1FN") ret <4 x float> %r } define bfloat @from_f8e5m2_bf16(i8 %x) { ; CHECK-LABEL: from_f8e5m2_bf16: ; CHECK: # %bb.0: ; CHECK-NEXT: pushq %rax ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: movl %edi, %edx ; CHECK-NEXT: andl $3, %edx ; CHECK-NEXT: movl %edx, %ecx ; CHECK-NEXT: shll $21, %ecx ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: andl $-128, %eax ; CHECK-NEXT: shll $24, %eax ; CHECK-NEXT: shrl $2, %edi ; CHECK-NEXT: andl $31, %edi ; CHECK-NEXT: movl %edi, %esi ; CHECK-NEXT: shll $23, %esi ; CHECK-NEXT: orl %eax, %esi ; CHECK-NEXT: leal 939524096(%rcx,%rsi), %esi ; CHECK-NEXT: bsrl %edx, %r8d ; CHECK-NEXT: movl %edx, %r9d ; CHECK-NEXT: btcl %r8d, %r9d ; CHECK-NEXT: xorl $31, %r8d ; CHECK-NEXT: leal -8(%r8), %ecx ; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx ; CHECK-NEXT: shll %cl, %r9d ; CHECK-NEXT: movl $142, %ecx ; CHECK-NEXT: subl %r8d, %ecx ; CHECK-NEXT: shll $23, %ecx ; CHECK-NEXT: orl %eax, %ecx ; CHECK-NEXT: orl %r9d, %ecx ; CHECK-NEXT: testl %edx, %edx ; CHECK-NEXT: sete %dl ; CHECK-NEXT: setne %r8b ; CHECK-NEXT: testl %edi, %edi ; CHECK-NEXT: sete %r9b ; CHECK-NEXT: testb %r8b, %r9b ; CHECK-NEXT: cmovel %esi, %ecx ; CHECK-NEXT: testb %dl, %r9b ; CHECK-NEXT: cmovnel %eax, %ecx ; CHECK-NEXT: orl $2139095040, %eax # imm = 0x7F800000 ; CHECK-NEXT: cmpl $31, %edi ; CHECK-NEXT: sete %sil ; CHECK-NEXT: testb %dl, %sil ; CHECK-NEXT: cmovel %ecx, %eax ; CHECK-NEXT: testb %r8b, %sil ; CHECK-NEXT: movl $2143289344, %ecx # imm = 0x7FC00000 ; CHECK-NEXT: cmovel %eax, %ecx ; CHECK-NEXT: movd %ecx, %xmm0 ; CHECK-NEXT: callq __truncsfbf2@PLT ; CHECK-NEXT: popq %rax ; CHECK-NEXT: .cfi_def_cfa_offset 8 ; CHECK-NEXT: retq %r = call bfloat @llvm.convert.from.arbitrary.fp.bf16.i8(i8 %x, metadata !"Float8E5M2") ret bfloat %r } define bfloat @from_f8e4m3fn_bf16(i8 %x) { ; CHECK-LABEL: from_f8e4m3fn_bf16: ; CHECK: # %bb.0: ; CHECK-NEXT: pushq %rax ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: andl $7, %eax ; CHECK-NEXT: movl %eax, %ecx ; CHECK-NEXT: shll $20, %ecx ; CHECK-NEXT: movl %edi, %edx ; CHECK-NEXT: andl $-128, %edx ; CHECK-NEXT: shll $24, %edx ; CHECK-NEXT: shrl $3, %edi ; CHECK-NEXT: andl $15, %edi ; CHECK-NEXT: movl %edi, %esi ; CHECK-NEXT: shll $23, %esi ; CHECK-NEXT: orl %edx, %esi ; CHECK-NEXT: leal 1006632960(%rcx,%rsi), %esi ; CHECK-NEXT: bsrl %eax, %r8d ; CHECK-NEXT: movl %eax, %r9d ; CHECK-NEXT: btcl %r8d, %r9d ; CHECK-NEXT: xorl $31, %r8d ; CHECK-NEXT: leal -8(%r8), %ecx ; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx ; CHECK-NEXT: shll %cl, %r9d ; CHECK-NEXT: movl $149, %ecx ; CHECK-NEXT: subl %r8d, %ecx ; CHECK-NEXT: shll $23, %ecx ; CHECK-NEXT: orl %edx, %ecx ; CHECK-NEXT: orl %r9d, %ecx ; CHECK-NEXT: testl %eax, %eax ; CHECK-NEXT: sete %r8b ; CHECK-NEXT: setne %r9b ; CHECK-NEXT: testl %edi, %edi ; CHECK-NEXT: sete %r10b ; CHECK-NEXT: testb %r9b, %r10b ; CHECK-NEXT: cmovel %esi, %ecx ; CHECK-NEXT: testb %r8b, %r10b ; CHECK-NEXT: cmovnel %edx, %ecx ; CHECK-NEXT: cmpl $7, %eax ; CHECK-NEXT: sete %al ; CHECK-NEXT: cmpl $15, %edi ; CHECK-NEXT: sete %dl ; CHECK-NEXT: testb %al, %dl ; CHECK-NEXT: movl $2143289344, %eax # imm = 0x7FC00000 ; CHECK-NEXT: cmovel %ecx, %eax ; CHECK-NEXT: movd %eax, %xmm0 ; CHECK-NEXT: callq __truncsfbf2@PLT ; CHECK-NEXT: popq %rax ; CHECK-NEXT: .cfi_def_cfa_offset 8 ; CHECK-NEXT: retq %r = call bfloat @llvm.convert.from.arbitrary.fp.bf16.i8(i8 %x, metadata !"Float8E4M3FN") ret bfloat %r } define <2 x bfloat> @from_f8e5m2_v2bf16(<2 x i8> %x) { ; CHECK-LABEL: from_f8e5m2_v2bf16: ; CHECK: # %bb.0: ; CHECK-NEXT: pushq %rbp ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: pushq %r14 ; CHECK-NEXT: .cfi_def_cfa_offset 24 ; CHECK-NEXT: pushq %rbx ; CHECK-NEXT: .cfi_def_cfa_offset 32 ; CHECK-NEXT: subq $16, %rsp ; CHECK-NEXT: .cfi_def_cfa_offset 48 ; CHECK-NEXT: .cfi_offset %rbx, -32 ; CHECK-NEXT: .cfi_offset %r14, -24 ; CHECK-NEXT: .cfi_offset %rbp, -16 ; CHECK-NEXT: movd %xmm0, %ebx ; CHECK-NEXT: movl %ebx, %esi ; CHECK-NEXT: shrl $8, %esi ; CHECK-NEXT: andl $3, %esi ; CHECK-NEXT: movl %esi, %ecx ; CHECK-NEXT: shll $21, %ecx ; CHECK-NEXT: movl %ebx, %eax ; CHECK-NEXT: shll $16, %eax ; CHECK-NEXT: andl $-2147483648, %eax # imm = 0x80000000 ; CHECK-NEXT: movl %ebx, %edx ; CHECK-NEXT: shrl $10, %edx ; CHECK-NEXT: andl $31, %edx ; CHECK-NEXT: movl %edx, %edi ; CHECK-NEXT: shll $23, %edi ; CHECK-NEXT: orl %eax, %edi ; CHECK-NEXT: leal 939524096(%rcx,%rdi), %edi ; CHECK-NEXT: bsrl %esi, %r8d ; CHECK-NEXT: movl %esi, %r9d ; CHECK-NEXT: btcl %r8d, %r9d ; CHECK-NEXT: xorl $31, %r8d ; CHECK-NEXT: leal -8(%r8), %ecx ; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx ; CHECK-NEXT: shll %cl, %r9d ; CHECK-NEXT: movl $142, %ebp ; CHECK-NEXT: movl $142, %ecx ; CHECK-NEXT: subl %r8d, %ecx ; CHECK-NEXT: shll $23, %ecx ; CHECK-NEXT: orl %eax, %ecx ; CHECK-NEXT: orl %r9d, %ecx ; CHECK-NEXT: testl %esi, %esi ; CHECK-NEXT: sete %sil ; CHECK-NEXT: setne %r8b ; CHECK-NEXT: testl %edx, %edx ; CHECK-NEXT: sete %r9b ; CHECK-NEXT: testb %r8b, %r9b ; CHECK-NEXT: cmovel %edi, %ecx ; CHECK-NEXT: testb %sil, %r9b ; CHECK-NEXT: cmovnel %eax, %ecx ; CHECK-NEXT: orl $2139095040, %eax # imm = 0x7F800000 ; CHECK-NEXT: cmpl $31, %edx ; CHECK-NEXT: sete %dl ; CHECK-NEXT: testb %sil, %dl ; CHECK-NEXT: cmovel %ecx, %eax ; CHECK-NEXT: testb %r8b, %dl ; CHECK-NEXT: movl $2143289344, %r14d # imm = 0x7FC00000 ; CHECK-NEXT: cmovnel %r14d, %eax ; CHECK-NEXT: movd %eax, %xmm0 ; CHECK-NEXT: callq __truncsfbf2@PLT ; CHECK-NEXT: movdqa %xmm0, (%rsp) # 16-byte Spill ; CHECK-NEXT: movl %ebx, %edx ; CHECK-NEXT: andl $3, %edx ; CHECK-NEXT: movl %edx, %ecx ; CHECK-NEXT: shll $21, %ecx ; CHECK-NEXT: movl %ebx, %eax ; CHECK-NEXT: andl $-128, %eax ; CHECK-NEXT: shll $24, %eax ; CHECK-NEXT: shrl $2, %ebx ; CHECK-NEXT: andl $31, %ebx ; CHECK-NEXT: movl %ebx, %esi ; CHECK-NEXT: shll $23, %esi ; CHECK-NEXT: orl %eax, %esi ; CHECK-NEXT: leal 939524096(%rcx,%rsi), %esi ; CHECK-NEXT: bsrl %edx, %edi ; CHECK-NEXT: movl %edx, %r8d ; CHECK-NEXT: btcl %edi, %r8d ; CHECK-NEXT: xorl $31, %edi ; CHECK-NEXT: leal -8(%rdi), %ecx ; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx ; CHECK-NEXT: shll %cl, %r8d ; CHECK-NEXT: subl %edi, %ebp ; CHECK-NEXT: shll $23, %ebp ; CHECK-NEXT: orl %eax, %ebp ; CHECK-NEXT: orl %r8d, %ebp ; CHECK-NEXT: testl %edx, %edx ; CHECK-NEXT: sete %cl ; CHECK-NEXT: setne %dl ; CHECK-NEXT: testl %ebx, %ebx ; CHECK-NEXT: sete %dil ; CHECK-NEXT: testb %dl, %dil ; CHECK-NEXT: cmovel %esi, %ebp ; CHECK-NEXT: testb %cl, %dil ; CHECK-NEXT: cmovnel %eax, %ebp ; CHECK-NEXT: orl $2139095040, %eax # imm = 0x7F800000 ; CHECK-NEXT: cmpl $31, %ebx ; CHECK-NEXT: sete %sil ; CHECK-NEXT: testb %cl, %sil ; CHECK-NEXT: cmovel %ebp, %eax ; CHECK-NEXT: testb %dl, %sil ; CHECK-NEXT: cmovnel %r14d, %eax ; CHECK-NEXT: movd %eax, %xmm0 ; CHECK-NEXT: callq __truncsfbf2@PLT ; CHECK-NEXT: punpcklwd (%rsp), %xmm0 # 16-byte Folded Reload ; CHECK-NEXT: # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1],xmm0[2],mem[2],xmm0[3],mem[3] ; CHECK-NEXT: addq $16, %rsp ; CHECK-NEXT: .cfi_def_cfa_offset 32 ; CHECK-NEXT: popq %rbx ; CHECK-NEXT: .cfi_def_cfa_offset 24 ; CHECK-NEXT: popq %r14 ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: popq %rbp ; CHECK-NEXT: .cfi_def_cfa_offset 8 ; CHECK-NEXT: retq %r = call <2 x bfloat> @llvm.convert.from.arbitrary.fp.v2bf16.v2i8(<2 x i8> %x, metadata !"Float8E5M2") ret <2 x bfloat> %r }