
Currently bf16 fpextend is lowered to a vector shift. Instead leave it as fpextend and have an instruction selection pattern which selects to a shift later. Doing this means that DAGCombiner patterns for fpextend will be applied, leading to better codegen. It also means that in some situations we use a mov instruction where we previously have a dup instruction, but I don't think this makes any difference.
411 lines
11 KiB
LLVM
411 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: // kill: def $d0 killed $h0
|
|
; 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: // kill: def $d0 killed $h0
|
|
; 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
|
|
}
|
|
|
|
|