A bf16 fp_extend is just a shift into the higher bits. This changes the lowering from using a relatively ugly tablegen pattern, to ISel generating the shift using an extended vector. This is cleaner and should optimize better. StrictFP goes through the same route as it cannot round or set flags.
415 lines
11 KiB
LLVM
415 lines
11 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
|
|
; RUN: llc -O0 -fast-isel -verify-machineinstrs -mtriple=arm64-eabi < %s | FileCheck --enable-var-scope %s
|
|
|
|
; Test fptosi
|
|
define i32 @fptosi_wh(half %a) nounwind ssp {
|
|
; CHECK-LABEL: fptosi_wh:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fcvt s0, h0
|
|
; CHECK-NEXT: fcvtzs w0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptosi half %a to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; Test fptoui
|
|
define i32 @fptoui_swh(half %a) nounwind ssp {
|
|
; CHECK-LABEL: fptoui_swh:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fcvt s0, h0
|
|
; CHECK-NEXT: fcvtzu w0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptoui half %a to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; Test sitofp
|
|
define half @sitofp_hw_i1(i1 %a) nounwind ssp {
|
|
; CHECK-LABEL: sitofp_hw_i1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: sbfx w8, w0, #0, #1
|
|
; CHECK-NEXT: scvtf s0, w8
|
|
; CHECK-NEXT: fcvt h0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = sitofp i1 %a to half
|
|
ret half %conv
|
|
}
|
|
|
|
; Test sitofp
|
|
define half @sitofp_hw_i8(i8 %a) nounwind ssp {
|
|
; CHECK-LABEL: sitofp_hw_i8:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: sxtb w8, w0
|
|
; CHECK-NEXT: scvtf s0, w8
|
|
; CHECK-NEXT: fcvt h0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = sitofp i8 %a to half
|
|
ret half %conv
|
|
}
|
|
|
|
; Test sitofp
|
|
define half @sitofp_hw_i16(i16 %a) nounwind ssp {
|
|
; CHECK-LABEL: sitofp_hw_i16:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: sxth w8, w0
|
|
; CHECK-NEXT: scvtf s0, w8
|
|
; CHECK-NEXT: fcvt h0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = sitofp i16 %a to half
|
|
ret half %conv
|
|
}
|
|
|
|
; Test sitofp
|
|
define half @sitofp_hw_i32(i32 %a) nounwind ssp {
|
|
; CHECK-LABEL: sitofp_hw_i32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: scvtf s0, w0
|
|
; CHECK-NEXT: fcvt h0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = sitofp i32 %a to half
|
|
ret half %conv
|
|
}
|
|
|
|
; Test sitofp
|
|
define half @sitofp_hx(i64 %a) nounwind ssp {
|
|
; CHECK-LABEL: sitofp_hx:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: scvtf s0, x0
|
|
; CHECK-NEXT: fcvt h0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = sitofp i64 %a to half
|
|
ret half %conv
|
|
}
|
|
|
|
; Test uitofp
|
|
define half @uitofp_hw_i1(i1 %a) nounwind ssp {
|
|
; CHECK-LABEL: uitofp_hw_i1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: and w8, w0, #0x1
|
|
; CHECK-NEXT: ucvtf s0, w8
|
|
; CHECK-NEXT: fcvt h0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = uitofp i1 %a to half
|
|
ret half %conv
|
|
}
|
|
|
|
; Test uitofp
|
|
define half @uitofp_hw_i8(i8 %a) nounwind ssp {
|
|
; CHECK-LABEL: uitofp_hw_i8:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: and w8, w0, #0xff
|
|
; CHECK-NEXT: ucvtf s0, w8
|
|
; CHECK-NEXT: fcvt h0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = uitofp i8 %a to half
|
|
ret half %conv
|
|
}
|
|
|
|
; Test uitofp
|
|
define half @uitofp_hw_i16(i16 %a) nounwind ssp {
|
|
; CHECK-LABEL: uitofp_hw_i16:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: and w8, w0, #0xffff
|
|
; CHECK-NEXT: ucvtf s0, w8
|
|
; CHECK-NEXT: fcvt h0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = uitofp i16 %a to half
|
|
ret half %conv
|
|
}
|
|
|
|
; Test uitofp
|
|
define half @uitofp_hw_i32(i32 %a) nounwind ssp {
|
|
; CHECK-LABEL: uitofp_hw_i32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: ucvtf s0, w0
|
|
; CHECK-NEXT: fcvt h0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = uitofp i32 %a to half
|
|
ret half %conv
|
|
}
|
|
|
|
; Test uitofp
|
|
define half @uitofp_hx(i64 %a) nounwind ssp {
|
|
; CHECK-LABEL: uitofp_hx:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: ucvtf s0, x0
|
|
; CHECK-NEXT: fcvt h0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = uitofp i64 %a to half
|
|
ret half %conv
|
|
}
|
|
|
|
; Test fptosi
|
|
define i32 @fptosi_bf(bfloat %a) nounwind ssp {
|
|
; CHECK-LABEL: fptosi_bf:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fmov s1, s0
|
|
; CHECK-NEXT: // implicit-def: $d0
|
|
; CHECK-NEXT: fmov s0, s1
|
|
; CHECK-NEXT: shll v0.4s, v0.4h, #16
|
|
; CHECK-NEXT: // kill: def $s0 killed $s0 killed $q0
|
|
; CHECK-NEXT: fcvtzs w0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptosi bfloat %a to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; Test fptoui
|
|
define i32 @fptoui_sbf(bfloat %a) nounwind ssp {
|
|
; CHECK-LABEL: fptoui_sbf:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fmov s1, s0
|
|
; CHECK-NEXT: // implicit-def: $d0
|
|
; CHECK-NEXT: fmov s0, s1
|
|
; CHECK-NEXT: shll v0.4s, v0.4h, #16
|
|
; CHECK-NEXT: // kill: def $s0 killed $s0 killed $q0
|
|
; CHECK-NEXT: fcvtzu w0, s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptoui bfloat %a to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; Test sitofp
|
|
define bfloat @sitofp_bf_i1(i1 %a) nounwind ssp {
|
|
; CHECK-LABEL: sitofp_bf_i1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: sbfx w8, w0, #0, #1
|
|
; CHECK-NEXT: scvtf s0, w8
|
|
; CHECK-NEXT: fmov w9, s0
|
|
; CHECK-NEXT: ubfx w8, w9, #16, #1
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: mov w9, #32767 // =0x7fff
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: lsr w8, w8, #16
|
|
; CHECK-NEXT: fmov s0, w8
|
|
; CHECK-NEXT: // kill: def $h0 killed $h0 killed $s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = sitofp i1 %a to bfloat
|
|
ret bfloat %conv
|
|
}
|
|
|
|
; Test sitofp
|
|
define bfloat @sitofp_bf_i8(i8 %a) nounwind ssp {
|
|
; CHECK-LABEL: sitofp_bf_i8:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: sxtb w8, w0
|
|
; CHECK-NEXT: scvtf s0, w8
|
|
; CHECK-NEXT: fmov w9, s0
|
|
; CHECK-NEXT: ubfx w8, w9, #16, #1
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: mov w9, #32767 // =0x7fff
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: lsr w8, w8, #16
|
|
; CHECK-NEXT: fmov s0, w8
|
|
; CHECK-NEXT: // kill: def $h0 killed $h0 killed $s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = sitofp i8 %a to bfloat
|
|
ret bfloat %conv
|
|
}
|
|
|
|
; Test sitofp
|
|
define bfloat @sitofp_bf_i16(i16 %a) nounwind ssp {
|
|
; CHECK-LABEL: sitofp_bf_i16:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: sxth w8, w0
|
|
; CHECK-NEXT: scvtf s0, w8
|
|
; CHECK-NEXT: fmov w9, s0
|
|
; CHECK-NEXT: ubfx w8, w9, #16, #1
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: mov w9, #32767 // =0x7fff
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: lsr w8, w8, #16
|
|
; CHECK-NEXT: fmov s0, w8
|
|
; CHECK-NEXT: // kill: def $h0 killed $h0 killed $s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = sitofp i16 %a to bfloat
|
|
ret bfloat %conv
|
|
}
|
|
|
|
; Test sitofp
|
|
define bfloat @sitofp_bf_i32(i32 %a) nounwind ssp {
|
|
; CHECK-LABEL: sitofp_bf_i32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: scvtf d0, w0
|
|
; CHECK-NEXT: fcvtxn s0, d0
|
|
; CHECK-NEXT: fmov w9, s0
|
|
; CHECK-NEXT: ubfx w8, w9, #16, #1
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: mov w9, #32767 // =0x7fff
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: lsr w8, w8, #16
|
|
; CHECK-NEXT: fmov s0, w8
|
|
; CHECK-NEXT: // kill: def $h0 killed $h0 killed $s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = sitofp i32 %a to bfloat
|
|
ret bfloat %conv
|
|
}
|
|
|
|
; Test sitofp
|
|
define bfloat @sitofp_bf_i164(i64 %a) nounwind ssp {
|
|
; CHECK-LABEL: sitofp_bf_i164:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: subs x8, x0, #0
|
|
; CHECK-NEXT: cneg x10, x0, mi
|
|
; CHECK-NEXT: and x8, x10, #0xfffffffffffff000
|
|
; CHECK-NEXT: lsr x9, x10, #53
|
|
; CHECK-NEXT: subs x9, x9, #0
|
|
; CHECK-NEXT: csel x8, x8, x10, ne
|
|
; CHECK-NEXT: scvtf d0, x8
|
|
; CHECK-NEXT: fmov x8, d0
|
|
; CHECK-NEXT: and x9, x0, #0x8000000000000000
|
|
; CHECK-NEXT: orr x8, x8, x9
|
|
; CHECK-NEXT: cset w9, ne
|
|
; CHECK-NEXT: ands x10, x10, #0xfff
|
|
; CHECK-NEXT: csel w9, wzr, w9, eq
|
|
; CHECK-NEXT: mov w9, w9
|
|
; CHECK-NEXT: // kill: def $x9 killed $w9
|
|
; CHECK-NEXT: orr x8, x8, x9
|
|
; CHECK-NEXT: fmov d0, x8
|
|
; CHECK-NEXT: fcvtxn s0, d0
|
|
; CHECK-NEXT: fmov w9, s0
|
|
; CHECK-NEXT: ubfx w8, w9, #16, #1
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: mov w9, #32767 // =0x7fff
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: lsr w8, w8, #16
|
|
; CHECK-NEXT: fmov s0, w8
|
|
; CHECK-NEXT: // kill: def $h0 killed $h0 killed $s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = sitofp i64 %a to bfloat
|
|
ret bfloat %conv
|
|
}
|
|
|
|
; Test uitofp
|
|
define bfloat @uitofp_bf_i1(i1 %a) nounwind ssp {
|
|
; CHECK-LABEL: uitofp_bf_i1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: and w8, w0, #0x1
|
|
; CHECK-NEXT: ucvtf s0, w8
|
|
; CHECK-NEXT: fmov w9, s0
|
|
; CHECK-NEXT: ubfx w8, w9, #16, #1
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: mov w9, #32767 // =0x7fff
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: lsr w8, w8, #16
|
|
; CHECK-NEXT: fmov s0, w8
|
|
; CHECK-NEXT: // kill: def $h0 killed $h0 killed $s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = uitofp i1 %a to bfloat
|
|
ret bfloat %conv
|
|
}
|
|
|
|
; Test uitofp
|
|
define bfloat @uitofp_bf_i8(i8 %a) nounwind ssp {
|
|
; CHECK-LABEL: uitofp_bf_i8:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: and w8, w0, #0xff
|
|
; CHECK-NEXT: ucvtf s0, w8
|
|
; CHECK-NEXT: fmov w9, s0
|
|
; CHECK-NEXT: ubfx w8, w9, #16, #1
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: mov w9, #32767 // =0x7fff
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: lsr w8, w8, #16
|
|
; CHECK-NEXT: fmov s0, w8
|
|
; CHECK-NEXT: // kill: def $h0 killed $h0 killed $s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = uitofp i8 %a to bfloat
|
|
ret bfloat %conv
|
|
}
|
|
|
|
; Test uitofp
|
|
define bfloat @uitofp_bf_i16(i16 %a) nounwind ssp {
|
|
; CHECK-LABEL: uitofp_bf_i16:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: and w8, w0, #0xffff
|
|
; CHECK-NEXT: ucvtf s0, w8
|
|
; CHECK-NEXT: fmov w9, s0
|
|
; CHECK-NEXT: ubfx w8, w9, #16, #1
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: mov w9, #32767 // =0x7fff
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: lsr w8, w8, #16
|
|
; CHECK-NEXT: fmov s0, w8
|
|
; CHECK-NEXT: // kill: def $h0 killed $h0 killed $s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = uitofp i16 %a to bfloat
|
|
ret bfloat %conv
|
|
}
|
|
|
|
; Test uitofp
|
|
define bfloat @uitofp_bf_i32(i32 %a) nounwind ssp {
|
|
; CHECK-LABEL: uitofp_bf_i32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: ucvtf d0, w0
|
|
; CHECK-NEXT: fcvtxn s0, d0
|
|
; CHECK-NEXT: fmov w9, s0
|
|
; CHECK-NEXT: ubfx w8, w9, #16, #1
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: mov w9, #32767 // =0x7fff
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: lsr w8, w8, #16
|
|
; CHECK-NEXT: fmov s0, w8
|
|
; CHECK-NEXT: // kill: def $h0 killed $h0 killed $s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = uitofp i32 %a to bfloat
|
|
ret bfloat %conv
|
|
}
|
|
|
|
; Test uitofp
|
|
define bfloat @uitofp_bf_i64(i64 %a) nounwind ssp {
|
|
; CHECK-LABEL: uitofp_bf_i64:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: and x8, x0, #0xfffffffffffff000
|
|
; CHECK-NEXT: lsr x9, x0, #53
|
|
; CHECK-NEXT: subs x9, x9, #0
|
|
; CHECK-NEXT: csel x8, x8, x0, ne
|
|
; CHECK-NEXT: ucvtf d0, x8
|
|
; CHECK-NEXT: fmov x8, d0
|
|
; CHECK-NEXT: cset w9, ne
|
|
; CHECK-NEXT: ands x10, x0, #0xfff
|
|
; CHECK-NEXT: csel w9, wzr, w9, eq
|
|
; CHECK-NEXT: mov w9, w9
|
|
; CHECK-NEXT: // kill: def $x9 killed $w9
|
|
; CHECK-NEXT: orr x8, x8, x9
|
|
; CHECK-NEXT: fmov d0, x8
|
|
; CHECK-NEXT: fcvtxn s0, d0
|
|
; CHECK-NEXT: fmov w9, s0
|
|
; CHECK-NEXT: ubfx w8, w9, #16, #1
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: mov w9, #32767 // =0x7fff
|
|
; CHECK-NEXT: add w8, w8, w9
|
|
; CHECK-NEXT: lsr w8, w8, #16
|
|
; CHECK-NEXT: fmov s0, w8
|
|
; CHECK-NEXT: // kill: def $h0 killed $h0 killed $s0
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = uitofp i64 %a to bfloat
|
|
ret bfloat %conv
|
|
}
|
|
|
|
|