[llvm] [X86] Fix i64-to-bf16 conversion crash on 32-bit targets (PR #222934)
Tim Besard via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 11 04:59:05 PDT 2026
https://github.com/maleadt created https://github.com/llvm/llvm-project/pull/222934
Converting a loaded `i64` to `bfloat` can crash instruction selection on i686:
```llvm
define bfloat @convert(ptr %p) {
%value = load i64, ptr %p
%result = sitofp i64 %value to bfloat
ret bfloat %result
}
```
With `llc -mtriple=i686-linux-gnu`, this hits:
```text
Do not know how to custom type legalize this operation!
```
The X86 DAG combine folds the load and conversion into an x87 `FILD` node
before type legalization. It already excludes `f16` and `f128`, but was missing
`bf16`, leaving the legalizer with an unsupported result type.
Add `bf16` to that exclusion. This lets the existing legalization promote the
conversion through `f32` and then round to bf16. The change also covers the
constrained signed conversion, which uses the same combine.
Assisted by: Fable 5.1, Astra 6
>From 71c556b0fcdcde5eb93eee614f50a7588eb21084 Mon Sep 17 00:00:00 2001
From: Tim Besard <tim.besard at gmail.com>
Date: Fri, 11 Sep 2026 13:11:00 +0200
Subject: [PATCH] [X86] Fix i64-to-bf16 conversion crash on 32-bit targets
combineSIntToFP can fold a loaded i64 into an x87 FILD before type
legalization. The result-type exclusions covered f16 and f128, but not
bf16, so the type legalizer could encounter a FILD with an unsupported
bf16 result and abort:
Do not know how to custom type legalize this operation!
Exclude bf16 as well, leaving the conversion to the existing legalization
through f32. This also fixes constrained signed conversions, which use
the same combine.
Test signed and unsigned conversions, including explicit loads and
constrained conversions, on baseline i686, SSE2, AVX512DQ/VL, and x86-64.
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 4 +-
.../test/CodeGen/X86/bfloat-int64-cvt-i686.ll | 455 ++++++++++++++++++
2 files changed, 457 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/bfloat-int64-cvt-i686.ll
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index a41cb2914660c..11dbec24adb33 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -59522,8 +59522,8 @@ static SDValue combineSIntToFP(SDNode *N, SelectionDAG &DAG,
Op0.getOpcode() == ISD::LOAD) {
LoadSDNode *Ld = cast<LoadSDNode>(Op0.getNode());
- // This transformation is not supported if the result type is f16 or f128.
- if (VT == MVT::f16 || VT == MVT::f128)
+ // FILD does not support f16, bf16, or f128 results.
+ if (VT == MVT::f16 || VT == MVT::bf16 || VT == MVT::f128)
return SDValue();
// If we have AVX512DQ we can use packed conversion instructions unless
diff --git a/llvm/test/CodeGen/X86/bfloat-int64-cvt-i686.ll b/llvm/test/CodeGen/X86/bfloat-int64-cvt-i686.ll
new file mode 100644
index 0000000000000..254224c2ad190
--- /dev/null
+++ b/llvm/test/CodeGen/X86/bfloat-int64-cvt-i686.ll
@@ -0,0 +1,455 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i686-linux-gnu | FileCheck %s --check-prefix=X87
+; RUN: llc < %s -mtriple=i686-linux-gnu -mattr=+sse2 | FileCheck %s --check-prefix=SSE2
+; RUN: llc < %s -mtriple=i686-linux-gnu -mattr=+avx512dq,+avx512vl | FileCheck %s --check-prefix=DQ
+; RUN: llc < %s -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefix=X64
+
+; Do not fold an i64 load into a FILD with a bf16 result on 32-bit targets.
+; Leave the conversion to be promoted through f32.
+
+define bfloat @sitofp_i64_to_bf16(i64 %a) {
+; X87-LABEL: sitofp_i64_to_bf16:
+; X87: # %bb.0:
+; X87-NEXT: subl $28, %esp
+; X87-NEXT: .cfi_def_cfa_offset 32
+; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X87-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X87-NEXT: movl %ecx, {{[0-9]+}}(%esp)
+; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; X87-NEXT: fildll {{[0-9]+}}(%esp)
+; X87-NEXT: fstps (%esp)
+; X87-NEXT: calll __truncsfbf2
+; X87-NEXT: # kill: def $ax killed $ax def $eax
+; X87-NEXT: shll $16, %eax
+; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; X87-NEXT: flds {{[0-9]+}}(%esp)
+; X87-NEXT: addl $28, %esp
+; X87-NEXT: .cfi_def_cfa_offset 4
+; X87-NEXT: retl
+;
+; SSE2-LABEL: sitofp_i64_to_bf16:
+; SSE2: # %bb.0:
+; SSE2-NEXT: subl $28, %esp
+; SSE2-NEXT: .cfi_def_cfa_offset 32
+; SSE2-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
+; SSE2-NEXT: movlps %xmm0, {{[0-9]+}}(%esp)
+; SSE2-NEXT: fildll {{[0-9]+}}(%esp)
+; SSE2-NEXT: fstps {{[0-9]+}}(%esp)
+; SSE2-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; SSE2-NEXT: movss %xmm0, (%esp)
+; SSE2-NEXT: calll __truncsfbf2
+; SSE2-NEXT: addl $28, %esp
+; SSE2-NEXT: .cfi_def_cfa_offset 4
+; SSE2-NEXT: retl
+;
+; DQ-LABEL: sitofp_i64_to_bf16:
+; DQ: # %bb.0:
+; DQ-NEXT: subl $12, %esp
+; DQ-NEXT: .cfi_def_cfa_offset 16
+; DQ-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; DQ-NEXT: vcvtqq2ps %ymm0, %xmm0
+; DQ-NEXT: vmovss %xmm0, (%esp)
+; DQ-NEXT: vzeroupper
+; DQ-NEXT: calll __truncsfbf2
+; DQ-NEXT: addl $12, %esp
+; DQ-NEXT: .cfi_def_cfa_offset 4
+; DQ-NEXT: retl
+;
+; X64-LABEL: sitofp_i64_to_bf16:
+; X64: # %bb.0:
+; X64-NEXT: pushq %rax
+; X64-NEXT: .cfi_def_cfa_offset 16
+; X64-NEXT: cvtsi2ss %rdi, %xmm0
+; X64-NEXT: callq __truncsfbf2 at PLT
+; X64-NEXT: popq %rax
+; X64-NEXT: .cfi_def_cfa_offset 8
+; X64-NEXT: retq
+ %cvt = sitofp i64 %a to bfloat
+ ret bfloat %cvt
+}
+
+define bfloat @sitofp_load_i64_to_bf16(ptr %p) {
+; X87-LABEL: sitofp_load_i64_to_bf16:
+; X87: # %bb.0:
+; X87-NEXT: subl $28, %esp
+; X87-NEXT: .cfi_def_cfa_offset 32
+; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X87-NEXT: movl (%eax), %ecx
+; X87-NEXT: movl 4(%eax), %eax
+; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; X87-NEXT: movl %ecx, {{[0-9]+}}(%esp)
+; X87-NEXT: fildll {{[0-9]+}}(%esp)
+; X87-NEXT: fstps (%esp)
+; X87-NEXT: calll __truncsfbf2
+; X87-NEXT: # kill: def $ax killed $ax def $eax
+; X87-NEXT: shll $16, %eax
+; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; X87-NEXT: flds {{[0-9]+}}(%esp)
+; X87-NEXT: addl $28, %esp
+; X87-NEXT: .cfi_def_cfa_offset 4
+; X87-NEXT: retl
+;
+; SSE2-LABEL: sitofp_load_i64_to_bf16:
+; SSE2: # %bb.0:
+; SSE2-NEXT: subl $28, %esp
+; SSE2-NEXT: .cfi_def_cfa_offset 32
+; SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax
+; SSE2-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
+; SSE2-NEXT: movlps %xmm0, {{[0-9]+}}(%esp)
+; SSE2-NEXT: fildll {{[0-9]+}}(%esp)
+; SSE2-NEXT: fstps {{[0-9]+}}(%esp)
+; SSE2-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; SSE2-NEXT: movss %xmm0, (%esp)
+; SSE2-NEXT: calll __truncsfbf2
+; SSE2-NEXT: addl $28, %esp
+; SSE2-NEXT: .cfi_def_cfa_offset 4
+; SSE2-NEXT: retl
+;
+; DQ-LABEL: sitofp_load_i64_to_bf16:
+; DQ: # %bb.0:
+; DQ-NEXT: subl $12, %esp
+; DQ-NEXT: .cfi_def_cfa_offset 16
+; DQ-NEXT: movl {{[0-9]+}}(%esp), %eax
+; DQ-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; DQ-NEXT: vcvtqq2ps %ymm0, %xmm0
+; DQ-NEXT: vmovss %xmm0, (%esp)
+; DQ-NEXT: vzeroupper
+; DQ-NEXT: calll __truncsfbf2
+; DQ-NEXT: addl $12, %esp
+; DQ-NEXT: .cfi_def_cfa_offset 4
+; DQ-NEXT: retl
+;
+; X64-LABEL: sitofp_load_i64_to_bf16:
+; X64: # %bb.0:
+; X64-NEXT: pushq %rax
+; X64-NEXT: .cfi_def_cfa_offset 16
+; X64-NEXT: cvtsi2ssq (%rdi), %xmm0
+; X64-NEXT: callq __truncsfbf2 at PLT
+; X64-NEXT: popq %rax
+; X64-NEXT: .cfi_def_cfa_offset 8
+; X64-NEXT: retq
+ %a = load i64, ptr %p
+ %cvt = sitofp i64 %a to bfloat
+ ret bfloat %cvt
+}
+
+define bfloat @uitofp_i64_to_bf16(i64 %a) {
+; X87-LABEL: uitofp_i64_to_bf16:
+; X87: # %bb.0:
+; X87-NEXT: subl $28, %esp
+; X87-NEXT: .cfi_def_cfa_offset 32
+; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X87-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X87-NEXT: movl %ecx, {{[0-9]+}}(%esp)
+; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; X87-NEXT: shrl $31, %ecx
+; X87-NEXT: fildll {{[0-9]+}}(%esp)
+; X87-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%ecx,4)
+; X87-NEXT: fstps (%esp)
+; X87-NEXT: calll __truncsfbf2
+; X87-NEXT: # kill: def $ax killed $ax def $eax
+; X87-NEXT: shll $16, %eax
+; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; X87-NEXT: flds {{[0-9]+}}(%esp)
+; X87-NEXT: addl $28, %esp
+; X87-NEXT: .cfi_def_cfa_offset 4
+; X87-NEXT: retl
+;
+; SSE2-LABEL: uitofp_i64_to_bf16:
+; SSE2: # %bb.0:
+; SSE2-NEXT: subl $28, %esp
+; SSE2-NEXT: .cfi_def_cfa_offset 32
+; SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax
+; SSE2-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
+; SSE2-NEXT: movlps %xmm0, {{[0-9]+}}(%esp)
+; SSE2-NEXT: shrl $31, %eax
+; SSE2-NEXT: fildll {{[0-9]+}}(%esp)
+; SSE2-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%eax,4)
+; SSE2-NEXT: fstps (%esp)
+; SSE2-NEXT: calll __truncsfbf2
+; SSE2-NEXT: addl $28, %esp
+; SSE2-NEXT: .cfi_def_cfa_offset 4
+; SSE2-NEXT: retl
+;
+; DQ-LABEL: uitofp_i64_to_bf16:
+; DQ: # %bb.0:
+; DQ-NEXT: subl $12, %esp
+; DQ-NEXT: .cfi_def_cfa_offset 16
+; DQ-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; DQ-NEXT: vcvtuqq2ps %ymm0, %xmm0
+; DQ-NEXT: vmovss %xmm0, (%esp)
+; DQ-NEXT: vzeroupper
+; DQ-NEXT: calll __truncsfbf2
+; DQ-NEXT: addl $12, %esp
+; DQ-NEXT: .cfi_def_cfa_offset 4
+; DQ-NEXT: retl
+;
+; X64-LABEL: uitofp_i64_to_bf16:
+; X64: # %bb.0:
+; X64-NEXT: testq %rdi, %rdi
+; X64-NEXT: js .LBB2_1
+; X64-NEXT: # %bb.2:
+; X64-NEXT: cvtsi2ss %rdi, %xmm0
+; X64-NEXT: jmp .LBB2_3
+; X64-NEXT: .LBB2_1:
+; X64-NEXT: movq %rdi, %rax
+; X64-NEXT: shrq %rax
+; X64-NEXT: andl $1, %edi
+; X64-NEXT: orq %rax, %rdi
+; X64-NEXT: cvtsi2ss %rdi, %xmm0
+; X64-NEXT: addss %xmm0, %xmm0
+; X64-NEXT: .LBB2_3:
+; X64-NEXT: pushq %rax
+; X64-NEXT: .cfi_def_cfa_offset 16
+; X64-NEXT: callq __truncsfbf2 at PLT
+; X64-NEXT: popq %rax
+; X64-NEXT: .cfi_def_cfa_offset 8
+; X64-NEXT: retq
+ %cvt = uitofp i64 %a to bfloat
+ ret bfloat %cvt
+}
+
+define bfloat @uitofp_load_i64_to_bf16(ptr %p) {
+; X87-LABEL: uitofp_load_i64_to_bf16:
+; X87: # %bb.0:
+; X87-NEXT: subl $28, %esp
+; X87-NEXT: .cfi_def_cfa_offset 32
+; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X87-NEXT: movl (%eax), %ecx
+; X87-NEXT: movl 4(%eax), %eax
+; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; X87-NEXT: movl %ecx, {{[0-9]+}}(%esp)
+; X87-NEXT: shrl $31, %eax
+; X87-NEXT: fildll {{[0-9]+}}(%esp)
+; X87-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%eax,4)
+; X87-NEXT: fstps (%esp)
+; X87-NEXT: calll __truncsfbf2
+; X87-NEXT: # kill: def $ax killed $ax def $eax
+; X87-NEXT: shll $16, %eax
+; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; X87-NEXT: flds {{[0-9]+}}(%esp)
+; X87-NEXT: addl $28, %esp
+; X87-NEXT: .cfi_def_cfa_offset 4
+; X87-NEXT: retl
+;
+; SSE2-LABEL: uitofp_load_i64_to_bf16:
+; SSE2: # %bb.0:
+; SSE2-NEXT: subl $28, %esp
+; SSE2-NEXT: .cfi_def_cfa_offset 32
+; SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax
+; SSE2-NEXT: movl 4(%eax), %ecx
+; SSE2-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
+; SSE2-NEXT: movlps %xmm0, {{[0-9]+}}(%esp)
+; SSE2-NEXT: shrl $31, %ecx
+; SSE2-NEXT: fildll {{[0-9]+}}(%esp)
+; SSE2-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%ecx,4)
+; SSE2-NEXT: fstps (%esp)
+; SSE2-NEXT: calll __truncsfbf2
+; SSE2-NEXT: addl $28, %esp
+; SSE2-NEXT: .cfi_def_cfa_offset 4
+; SSE2-NEXT: retl
+;
+; DQ-LABEL: uitofp_load_i64_to_bf16:
+; DQ: # %bb.0:
+; DQ-NEXT: subl $12, %esp
+; DQ-NEXT: .cfi_def_cfa_offset 16
+; DQ-NEXT: movl {{[0-9]+}}(%esp), %eax
+; DQ-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; DQ-NEXT: vcvtuqq2ps %ymm0, %xmm0
+; DQ-NEXT: vmovss %xmm0, (%esp)
+; DQ-NEXT: vzeroupper
+; DQ-NEXT: calll __truncsfbf2
+; DQ-NEXT: addl $12, %esp
+; DQ-NEXT: .cfi_def_cfa_offset 4
+; DQ-NEXT: retl
+;
+; X64-LABEL: uitofp_load_i64_to_bf16:
+; X64: # %bb.0:
+; X64-NEXT: movq (%rdi), %rax
+; X64-NEXT: testq %rax, %rax
+; X64-NEXT: js .LBB3_1
+; X64-NEXT: # %bb.2:
+; X64-NEXT: cvtsi2ss %rax, %xmm0
+; X64-NEXT: jmp .LBB3_3
+; X64-NEXT: .LBB3_1:
+; X64-NEXT: movq %rax, %rcx
+; X64-NEXT: shrq %rcx
+; X64-NEXT: andl $1, %eax
+; X64-NEXT: orq %rcx, %rax
+; X64-NEXT: cvtsi2ss %rax, %xmm0
+; X64-NEXT: addss %xmm0, %xmm0
+; X64-NEXT: .LBB3_3:
+; X64-NEXT: pushq %rax
+; X64-NEXT: .cfi_def_cfa_offset 16
+; X64-NEXT: callq __truncsfbf2 at PLT
+; X64-NEXT: popq %rax
+; X64-NEXT: .cfi_def_cfa_offset 8
+; X64-NEXT: retq
+ %a = load i64, ptr %p
+ %cvt = uitofp i64 %a to bfloat
+ ret bfloat %cvt
+}
+
+define bfloat @strict_sitofp_load_i64_to_bf16(ptr %p) strictfp {
+; X87-LABEL: strict_sitofp_load_i64_to_bf16:
+; X87: # %bb.0:
+; X87-NEXT: subl $28, %esp
+; X87-NEXT: .cfi_def_cfa_offset 32
+; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X87-NEXT: movl (%eax), %ecx
+; X87-NEXT: movl 4(%eax), %eax
+; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; X87-NEXT: movl %ecx, {{[0-9]+}}(%esp)
+; X87-NEXT: fildll {{[0-9]+}}(%esp)
+; X87-NEXT: fstps (%esp)
+; X87-NEXT: wait
+; X87-NEXT: calll __truncsfbf2
+; X87-NEXT: # kill: def $ax killed $ax def $eax
+; X87-NEXT: shll $16, %eax
+; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; X87-NEXT: flds {{[0-9]+}}(%esp)
+; X87-NEXT: wait
+; X87-NEXT: addl $28, %esp
+; X87-NEXT: .cfi_def_cfa_offset 4
+; X87-NEXT: retl
+;
+; SSE2-LABEL: strict_sitofp_load_i64_to_bf16:
+; SSE2: # %bb.0:
+; SSE2-NEXT: subl $28, %esp
+; SSE2-NEXT: .cfi_def_cfa_offset 32
+; SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax
+; SSE2-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
+; SSE2-NEXT: movlps %xmm0, {{[0-9]+}}(%esp)
+; SSE2-NEXT: fildll {{[0-9]+}}(%esp)
+; SSE2-NEXT: fstps {{[0-9]+}}(%esp)
+; SSE2-NEXT: wait
+; SSE2-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; SSE2-NEXT: movd %xmm0, (%esp)
+; SSE2-NEXT: calll __truncsfbf2
+; SSE2-NEXT: # kill: def $ax killed $ax def $eax
+; SSE2-NEXT: pinsrw $0, %eax, %xmm0
+; SSE2-NEXT: addl $28, %esp
+; SSE2-NEXT: .cfi_def_cfa_offset 4
+; SSE2-NEXT: retl
+;
+; DQ-LABEL: strict_sitofp_load_i64_to_bf16:
+; DQ: # %bb.0:
+; DQ-NEXT: subl $12, %esp
+; DQ-NEXT: .cfi_def_cfa_offset 16
+; DQ-NEXT: movl {{[0-9]+}}(%esp), %eax
+; DQ-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; DQ-NEXT: vcvtqq2ps %ymm0, %xmm0
+; DQ-NEXT: vmovd %xmm0, (%esp)
+; DQ-NEXT: vzeroupper
+; DQ-NEXT: calll __truncsfbf2
+; DQ-NEXT: # kill: def $ax killed $ax def $eax
+; DQ-NEXT: vpinsrw $0, %eax, %xmm0, %xmm0
+; DQ-NEXT: addl $12, %esp
+; DQ-NEXT: .cfi_def_cfa_offset 4
+; DQ-NEXT: retl
+;
+; X64-LABEL: strict_sitofp_load_i64_to_bf16:
+; X64: # %bb.0:
+; X64-NEXT: pushq %rax
+; X64-NEXT: .cfi_def_cfa_offset 16
+; X64-NEXT: cvtsi2ssq (%rdi), %xmm0
+; X64-NEXT: callq __truncsfbf2 at PLT
+; X64-NEXT: # kill: def $ax killed $ax def $eax
+; X64-NEXT: pinsrw $0, %eax, %xmm0
+; X64-NEXT: popq %rax
+; X64-NEXT: .cfi_def_cfa_offset 8
+; X64-NEXT: retq
+ %a = load i64, ptr %p
+ %cvt = call bfloat @llvm.experimental.constrained.sitofp.bf16.i64(i64 %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret bfloat %cvt
+}
+
+define bfloat @strict_uitofp_i64_to_bf16(i64 %a) strictfp {
+; X87-LABEL: strict_uitofp_i64_to_bf16:
+; X87: # %bb.0:
+; X87-NEXT: subl $28, %esp
+; X87-NEXT: .cfi_def_cfa_offset 32
+; X87-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X87-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X87-NEXT: movl %ecx, {{[0-9]+}}(%esp)
+; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; X87-NEXT: shrl $31, %ecx
+; X87-NEXT: fildll {{[0-9]+}}(%esp)
+; X87-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%ecx,4)
+; X87-NEXT: fstps {{[0-9]+}}(%esp)
+; X87-NEXT: flds {{[0-9]+}}(%esp)
+; X87-NEXT: fstps (%esp)
+; X87-NEXT: wait
+; X87-NEXT: calll __truncsfbf2
+; X87-NEXT: # kill: def $ax killed $ax def $eax
+; X87-NEXT: shll $16, %eax
+; X87-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; X87-NEXT: flds {{[0-9]+}}(%esp)
+; X87-NEXT: wait
+; X87-NEXT: addl $28, %esp
+; X87-NEXT: .cfi_def_cfa_offset 4
+; X87-NEXT: retl
+;
+; SSE2-LABEL: strict_uitofp_i64_to_bf16:
+; SSE2: # %bb.0:
+; SSE2-NEXT: subl $28, %esp
+; SSE2-NEXT: .cfi_def_cfa_offset 32
+; SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax
+; SSE2-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
+; SSE2-NEXT: movlps %xmm0, {{[0-9]+}}(%esp)
+; SSE2-NEXT: shrl $31, %eax
+; SSE2-NEXT: fildll {{[0-9]+}}(%esp)
+; SSE2-NEXT: fadds {{\.?LCPI[0-9]+_[0-9]+}}(,%eax,4)
+; SSE2-NEXT: fstps {{[0-9]+}}(%esp)
+; SSE2-NEXT: wait
+; SSE2-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; SSE2-NEXT: movd %xmm0, (%esp)
+; SSE2-NEXT: calll __truncsfbf2
+; SSE2-NEXT: # kill: def $ax killed $ax def $eax
+; SSE2-NEXT: pinsrw $0, %eax, %xmm0
+; SSE2-NEXT: addl $28, %esp
+; SSE2-NEXT: .cfi_def_cfa_offset 4
+; SSE2-NEXT: retl
+;
+; DQ-LABEL: strict_uitofp_i64_to_bf16:
+; DQ: # %bb.0:
+; DQ-NEXT: subl $12, %esp
+; DQ-NEXT: .cfi_def_cfa_offset 16
+; DQ-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; DQ-NEXT: vcvtuqq2ps %ymm0, %xmm0
+; DQ-NEXT: vmovd %xmm0, (%esp)
+; DQ-NEXT: vzeroupper
+; DQ-NEXT: calll __truncsfbf2
+; DQ-NEXT: # kill: def $ax killed $ax def $eax
+; DQ-NEXT: vpinsrw $0, %eax, %xmm0, %xmm0
+; DQ-NEXT: addl $12, %esp
+; DQ-NEXT: .cfi_def_cfa_offset 4
+; DQ-NEXT: retl
+;
+; X64-LABEL: strict_uitofp_i64_to_bf16:
+; X64: # %bb.0:
+; X64-NEXT: movq %rdi, %rax
+; X64-NEXT: shrq %rax
+; X64-NEXT: movl %edi, %ecx
+; X64-NEXT: andl $1, %ecx
+; X64-NEXT: orq %rax, %rcx
+; X64-NEXT: testq %rdi, %rdi
+; X64-NEXT: cmovnsq %rdi, %rcx
+; X64-NEXT: cvtsi2ss %rcx, %xmm1
+; X64-NEXT: movaps %xmm1, %xmm0
+; X64-NEXT: addss %xmm1, %xmm0
+; X64-NEXT: js .LBB5_2
+; X64-NEXT: # %bb.1:
+; X64-NEXT: movaps %xmm1, %xmm0
+; X64-NEXT: .LBB5_2:
+; X64-NEXT: pushq %rax
+; X64-NEXT: .cfi_def_cfa_offset 16
+; X64-NEXT: callq __truncsfbf2 at PLT
+; X64-NEXT: # kill: def $ax killed $ax def $eax
+; X64-NEXT: pinsrw $0, %eax, %xmm0
+; X64-NEXT: popq %rax
+; X64-NEXT: .cfi_def_cfa_offset 8
+; X64-NEXT: retq
+ %cvt = call bfloat @llvm.experimental.constrained.uitofp.bf16.i64(i64 %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret bfloat %cvt
+}
More information about the llvm-commits
mailing list