These are long overdue for removal. These were originally a hack
to support loading half values before there was any / decent support
for the half type through the backend. There's no reason to continue
supporting these, they're equivalent to fpext/fptrunc with a bitcast.
SelectionDAG stopped translating these directly, and used the
bitcast + fp cast since f7a02c1762, so there's been no reason
to use these since 2014.
554 lines
19 KiB
LLVM
554 lines
19 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
|
|
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefixes=ALL,DEFISEL
|
|
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel | FileCheck %s --check-prefixes=ALL,FASTISEL
|
|
|
|
; Tests for various operations on half precison float. Much of the test is
|
|
; copied from test/CodeGen/X86/half.ll.
|
|
|
|
target triple = "wasm32-unknown-unknown"
|
|
|
|
define void @store(half %x, ptr %p) nounwind {
|
|
; ALL-LABEL: store:
|
|
; ALL: .functype store (i32, i32) -> ()
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push1=, 1
|
|
; ALL-NEXT: local.get $push0=, 0
|
|
; ALL-NEXT: i32.store16 0($pop1), $pop0
|
|
; ALL-NEXT: return
|
|
store half %x, ptr %p
|
|
ret void
|
|
}
|
|
|
|
define half @return(ptr %p) nounwind {
|
|
; ALL-LABEL: return:
|
|
; ALL: .functype return (i32) -> (i32)
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push1=, 0
|
|
; ALL-NEXT: i32.load16_u $push0=, 0($pop1)
|
|
; ALL-NEXT: return $pop0
|
|
%r = load half, ptr %p
|
|
ret half %r
|
|
}
|
|
|
|
define void @test_load_store(ptr %in, ptr %out) nounwind {
|
|
; ALL-LABEL: test_load_store:
|
|
; ALL: .functype test_load_store (i32, i32) -> ()
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push2=, 1
|
|
; ALL-NEXT: local.get $push1=, 0
|
|
; ALL-NEXT: i32.load16_u $push0=, 0($pop1)
|
|
; ALL-NEXT: i32.store16 0($pop2), $pop0
|
|
; ALL-NEXT: return
|
|
%val = load half, ptr %in
|
|
store half %val, ptr %out
|
|
ret void
|
|
}
|
|
|
|
define i16 @test_bitcast_from_half(ptr %addr) nounwind {
|
|
; ALL-LABEL: test_bitcast_from_half:
|
|
; ALL: .functype test_bitcast_from_half (i32) -> (i32)
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push1=, 0
|
|
; ALL-NEXT: i32.load16_u $push0=, 0($pop1)
|
|
; ALL-NEXT: return $pop0
|
|
%val = load half, ptr %addr
|
|
%val_int = bitcast half %val to i16
|
|
ret i16 %val_int
|
|
}
|
|
|
|
define void @test_bitcast_to_half(ptr %addr, i16 %in) nounwind {
|
|
; ALL-LABEL: test_bitcast_to_half:
|
|
; ALL: .functype test_bitcast_to_half (i32, i32) -> ()
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push1=, 0
|
|
; ALL-NEXT: local.get $push0=, 1
|
|
; ALL-NEXT: i32.store16 0($pop1), $pop0
|
|
; ALL-NEXT: return
|
|
%val_fp = bitcast i16 %in to half
|
|
store half %val_fp, ptr %addr
|
|
ret void
|
|
}
|
|
|
|
define half @from_bits(i16 %x) nounwind {
|
|
; ALL-LABEL: from_bits:
|
|
; ALL: .functype from_bits (i32) -> (i32)
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push0=, 0
|
|
; ALL-NEXT: return $pop0
|
|
%res = bitcast i16 %x to half
|
|
ret half %res
|
|
}
|
|
|
|
define i16 @to_bits(half %x) nounwind {
|
|
; ALL-LABEL: to_bits:
|
|
; ALL: .functype to_bits (i32) -> (i32)
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push0=, 0
|
|
; ALL-NEXT: return $pop0
|
|
%res = bitcast half %x to i16
|
|
ret i16 %res
|
|
}
|
|
|
|
define float @test_extend32(ptr %addr) nounwind {
|
|
; DEFISEL-LABEL: test_extend32:
|
|
; DEFISEL: .functype test_extend32 (i32) -> (f32)
|
|
; DEFISEL-NEXT: # %bb.0:
|
|
; DEFISEL-NEXT: local.get $push2=, 0
|
|
; DEFISEL-NEXT: i32.load16_u $push0=, 0($pop2)
|
|
; DEFISEL-NEXT: call $push1=, __extendhfsf2, $pop0
|
|
; DEFISEL-NEXT: return $pop1
|
|
;
|
|
; FASTISEL-LABEL: test_extend32:
|
|
; FASTISEL: .functype test_extend32 (i32) -> (f32)
|
|
; FASTISEL-NEXT: # %bb.0:
|
|
; FASTISEL-NEXT: local.get $push2=, 0
|
|
; FASTISEL-NEXT: i32.load16_u $push1=, 0($pop2)
|
|
; FASTISEL-NEXT: call $push0=, __extendhfsf2, $pop1
|
|
; FASTISEL-NEXT: return $pop0
|
|
%val16 = load half, ptr %addr
|
|
%val32 = fpext half %val16 to float
|
|
ret float %val32
|
|
}
|
|
|
|
define double @test_extend64(ptr %addr) nounwind {
|
|
; DEFISEL-LABEL: test_extend64:
|
|
; DEFISEL: .functype test_extend64 (i32) -> (f64)
|
|
; DEFISEL-NEXT: # %bb.0:
|
|
; DEFISEL-NEXT: local.get $push3=, 0
|
|
; DEFISEL-NEXT: i32.load16_u $push0=, 0($pop3)
|
|
; DEFISEL-NEXT: call $push1=, __extendhfsf2, $pop0
|
|
; DEFISEL-NEXT: f64.promote_f32 $push2=, $pop1
|
|
; DEFISEL-NEXT: return $pop2
|
|
;
|
|
; FASTISEL-LABEL: test_extend64:
|
|
; FASTISEL: .functype test_extend64 (i32) -> (f64)
|
|
; FASTISEL-NEXT: # %bb.0:
|
|
; FASTISEL-NEXT: local.get $push3=, 0
|
|
; FASTISEL-NEXT: i32.load16_u $push1=, 0($pop3)
|
|
; FASTISEL-NEXT: call $push2=, __extendhfsf2, $pop1
|
|
; FASTISEL-NEXT: f64.promote_f32 $push0=, $pop2
|
|
; FASTISEL-NEXT: return $pop0
|
|
%val16 = load half, ptr %addr
|
|
%val32 = fpext half %val16 to double
|
|
ret double %val32
|
|
}
|
|
|
|
define fp128 @test_extend128(ptr %addr) nounwind {
|
|
; ALL-LABEL: test_extend128:
|
|
; ALL: .functype test_extend128 (i32, i32) -> ()
|
|
; ALL-NEXT: .local i32
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: global.get $push4=, __stack_pointer
|
|
; ALL-NEXT: i32.const $push5=, 16
|
|
; ALL-NEXT: i32.sub $push9=, $pop4, $pop5
|
|
; ALL-NEXT: local.tee $push8=, 2, $pop9
|
|
; ALL-NEXT: global.set __stack_pointer, $pop8
|
|
; ALL-NEXT: local.get $push11=, 2
|
|
; ALL-NEXT: local.get $push10=, 1
|
|
; ALL-NEXT: i32.load16_u $push0=, 0($pop10)
|
|
; ALL-NEXT: call $push1=, __extendhfsf2, $pop0
|
|
; ALL-NEXT: call __extendsftf2, $pop11, $pop1
|
|
; ALL-NEXT: local.get $push13=, 0
|
|
; ALL-NEXT: local.get $push12=, 2
|
|
; ALL-NEXT: i64.load $push2=, 8($pop12)
|
|
; ALL-NEXT: i64.store 8($pop13), $pop2
|
|
; ALL-NEXT: local.get $push15=, 0
|
|
; ALL-NEXT: local.get $push14=, 2
|
|
; ALL-NEXT: i64.load $push3=, 0($pop14)
|
|
; ALL-NEXT: i64.store 0($pop15), $pop3
|
|
; ALL-NEXT: local.get $push16=, 2
|
|
; ALL-NEXT: i32.const $push6=, 16
|
|
; ALL-NEXT: i32.add $push7=, $pop16, $pop6
|
|
; ALL-NEXT: global.set __stack_pointer, $pop7
|
|
; ALL-NEXT: return
|
|
%val16 = load half, ptr %addr
|
|
%val32 = fpext half %val16 to fp128
|
|
ret fp128 %val32
|
|
}
|
|
|
|
define void @test_trunc32(float %in, ptr %addr) nounwind {
|
|
; ALL-LABEL: test_trunc32:
|
|
; ALL: .functype test_trunc32 (f32, i32) -> ()
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push2=, 1
|
|
; ALL-NEXT: local.get $push1=, 0
|
|
; ALL-NEXT: call $push0=, __truncsfhf2, $pop1
|
|
; ALL-NEXT: i32.store16 0($pop2), $pop0
|
|
; ALL-NEXT: return
|
|
%val16 = fptrunc float %in to half
|
|
store half %val16, ptr %addr
|
|
ret void
|
|
}
|
|
|
|
define void @test_trunc64(double %in, ptr %addr) nounwind {
|
|
; ALL-LABEL: test_trunc64:
|
|
; ALL: .functype test_trunc64 (f64, i32) -> ()
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push2=, 1
|
|
; ALL-NEXT: local.get $push1=, 0
|
|
; ALL-NEXT: call $push0=, __truncdfhf2, $pop1
|
|
; ALL-NEXT: i32.store16 0($pop2), $pop0
|
|
; ALL-NEXT: return
|
|
%val16 = fptrunc double %in to half
|
|
store half %val16, ptr %addr
|
|
ret void
|
|
}
|
|
|
|
define void @test_trunc128(fp128 %in, ptr %addr) nounwind {
|
|
; ALL-LABEL: test_trunc128:
|
|
; ALL: .functype test_trunc128 (i64, i64, i32) -> ()
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push3=, 2
|
|
; ALL-NEXT: local.get $push2=, 0
|
|
; ALL-NEXT: local.get $push1=, 1
|
|
; ALL-NEXT: call $push0=, __trunctfhf2, $pop2, $pop1
|
|
; ALL-NEXT: i32.store16 0($pop3), $pop0
|
|
; ALL-NEXT: return
|
|
%val16 = fptrunc fp128 %in to half
|
|
store half %val16, ptr %addr
|
|
ret void
|
|
}
|
|
|
|
define i64 @test_fptosi_i64(ptr %p) nounwind {
|
|
; DEFISEL-LABEL: test_fptosi_i64:
|
|
; DEFISEL: .functype test_fptosi_i64 (i32) -> (i64)
|
|
; DEFISEL-NEXT: # %bb.0:
|
|
; DEFISEL-NEXT: local.get $push3=, 0
|
|
; DEFISEL-NEXT: i32.load16_u $push0=, 0($pop3)
|
|
; DEFISEL-NEXT: call $push1=, __extendhfsf2, $pop0
|
|
; DEFISEL-NEXT: i64.trunc_sat_f32_s $push2=, $pop1
|
|
; DEFISEL-NEXT: return $pop2
|
|
;
|
|
; FASTISEL-LABEL: test_fptosi_i64:
|
|
; FASTISEL: .functype test_fptosi_i64 (i32) -> (i64)
|
|
; FASTISEL-NEXT: # %bb.0:
|
|
; FASTISEL-NEXT: local.get $push3=, 0
|
|
; FASTISEL-NEXT: i32.load16_u $push1=, 0($pop3)
|
|
; FASTISEL-NEXT: call $push2=, __extendhfsf2, $pop1
|
|
; FASTISEL-NEXT: i64.trunc_sat_f32_s $push0=, $pop2
|
|
; FASTISEL-NEXT: return $pop0
|
|
%a = load half, ptr %p, align 2
|
|
%r = fptosi half %a to i64
|
|
ret i64 %r
|
|
}
|
|
|
|
define void @test_sitofp_i64(i64 %a, ptr %p) nounwind {
|
|
; ALL-LABEL: test_sitofp_i64:
|
|
; ALL: .functype test_sitofp_i64 (i64, i32) -> ()
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push3=, 1
|
|
; ALL-NEXT: local.get $push2=, 0
|
|
; ALL-NEXT: f32.convert_i64_s $push0=, $pop2
|
|
; ALL-NEXT: call $push1=, __truncsfhf2, $pop0
|
|
; ALL-NEXT: i32.store16 0($pop3), $pop1
|
|
; ALL-NEXT: return
|
|
%r = sitofp i64 %a to half
|
|
store half %r, ptr %p
|
|
ret void
|
|
}
|
|
|
|
define i64 @test_fptoui_i64(ptr %p) nounwind {
|
|
; DEFISEL-LABEL: test_fptoui_i64:
|
|
; DEFISEL: .functype test_fptoui_i64 (i32) -> (i64)
|
|
; DEFISEL-NEXT: # %bb.0:
|
|
; DEFISEL-NEXT: local.get $push3=, 0
|
|
; DEFISEL-NEXT: i32.load16_u $push0=, 0($pop3)
|
|
; DEFISEL-NEXT: call $push1=, __extendhfsf2, $pop0
|
|
; DEFISEL-NEXT: i64.trunc_sat_f32_u $push2=, $pop1
|
|
; DEFISEL-NEXT: return $pop2
|
|
;
|
|
; FASTISEL-LABEL: test_fptoui_i64:
|
|
; FASTISEL: .functype test_fptoui_i64 (i32) -> (i64)
|
|
; FASTISEL-NEXT: # %bb.0:
|
|
; FASTISEL-NEXT: local.get $push3=, 0
|
|
; FASTISEL-NEXT: i32.load16_u $push1=, 0($pop3)
|
|
; FASTISEL-NEXT: call $push2=, __extendhfsf2, $pop1
|
|
; FASTISEL-NEXT: i64.trunc_sat_f32_u $push0=, $pop2
|
|
; FASTISEL-NEXT: return $pop0
|
|
%a = load half, ptr %p, align 2
|
|
%r = fptoui half %a to i64
|
|
ret i64 %r
|
|
}
|
|
|
|
define void @test_uitofp_i64(i64 %a, ptr %p) nounwind {
|
|
; ALL-LABEL: test_uitofp_i64:
|
|
; ALL: .functype test_uitofp_i64 (i64, i32) -> ()
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push3=, 1
|
|
; ALL-NEXT: local.get $push2=, 0
|
|
; ALL-NEXT: f32.convert_i64_u $push0=, $pop2
|
|
; ALL-NEXT: call $push1=, __truncsfhf2, $pop0
|
|
; ALL-NEXT: i32.store16 0($pop3), $pop1
|
|
; ALL-NEXT: return
|
|
%r = uitofp i64 %a to half
|
|
store half %r, ptr %p
|
|
ret void
|
|
}
|
|
|
|
define <4 x float> @test_extend32_vec4(ptr %p) nounwind {
|
|
; ALL-LABEL: test_extend32_vec4:
|
|
; ALL: .functype test_extend32_vec4 (i32, i32) -> ()
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push9=, 0
|
|
; ALL-NEXT: local.get $push8=, 1
|
|
; ALL-NEXT: i32.load16_u $push0=, 6($pop8)
|
|
; ALL-NEXT: call $push1=, __extendhfsf2, $pop0
|
|
; ALL-NEXT: f32.store 12($pop9), $pop1
|
|
; ALL-NEXT: local.get $push11=, 0
|
|
; ALL-NEXT: local.get $push10=, 1
|
|
; ALL-NEXT: i32.load16_u $push2=, 4($pop10)
|
|
; ALL-NEXT: call $push3=, __extendhfsf2, $pop2
|
|
; ALL-NEXT: f32.store 8($pop11), $pop3
|
|
; ALL-NEXT: local.get $push13=, 0
|
|
; ALL-NEXT: local.get $push12=, 1
|
|
; ALL-NEXT: i32.load16_u $push4=, 2($pop12)
|
|
; ALL-NEXT: call $push5=, __extendhfsf2, $pop4
|
|
; ALL-NEXT: f32.store 4($pop13), $pop5
|
|
; ALL-NEXT: local.get $push15=, 0
|
|
; ALL-NEXT: local.get $push14=, 1
|
|
; ALL-NEXT: i32.load16_u $push6=, 0($pop14)
|
|
; ALL-NEXT: call $push7=, __extendhfsf2, $pop6
|
|
; ALL-NEXT: f32.store 0($pop15), $pop7
|
|
; ALL-NEXT: return
|
|
%a = load <4 x half>, ptr %p, align 8
|
|
%b = fpext <4 x half> %a to <4 x float>
|
|
ret <4 x float> %b
|
|
}
|
|
|
|
define <4 x double> @test_extend64_vec4(ptr %p) nounwind {
|
|
; ALL-LABEL: test_extend64_vec4:
|
|
; ALL: .functype test_extend64_vec4 (i32, i32) -> ()
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push13=, 0
|
|
; ALL-NEXT: local.get $push12=, 1
|
|
; ALL-NEXT: i64.load16_u $push0=, 6($pop12)
|
|
; ALL-NEXT: call $push1=, __extendhfsf2, $pop0
|
|
; ALL-NEXT: f64.promote_f32 $push2=, $pop1
|
|
; ALL-NEXT: f64.store 24($pop13), $pop2
|
|
; ALL-NEXT: local.get $push15=, 0
|
|
; ALL-NEXT: local.get $push14=, 1
|
|
; ALL-NEXT: i64.load16_u $push3=, 4($pop14)
|
|
; ALL-NEXT: call $push4=, __extendhfsf2, $pop3
|
|
; ALL-NEXT: f64.promote_f32 $push5=, $pop4
|
|
; ALL-NEXT: f64.store 16($pop15), $pop5
|
|
; ALL-NEXT: local.get $push17=, 0
|
|
; ALL-NEXT: local.get $push16=, 1
|
|
; ALL-NEXT: i64.load16_u $push6=, 2($pop16)
|
|
; ALL-NEXT: call $push7=, __extendhfsf2, $pop6
|
|
; ALL-NEXT: f64.promote_f32 $push8=, $pop7
|
|
; ALL-NEXT: f64.store 8($pop17), $pop8
|
|
; ALL-NEXT: local.get $push19=, 0
|
|
; ALL-NEXT: local.get $push18=, 1
|
|
; ALL-NEXT: i64.load16_u $push9=, 0($pop18)
|
|
; ALL-NEXT: call $push10=, __extendhfsf2, $pop9
|
|
; ALL-NEXT: f64.promote_f32 $push11=, $pop10
|
|
; ALL-NEXT: f64.store 0($pop19), $pop11
|
|
; ALL-NEXT: return
|
|
%a = load <4 x half>, ptr %p, align 8
|
|
%b = fpext <4 x half> %a to <4 x double>
|
|
ret <4 x double> %b
|
|
}
|
|
|
|
define void @test_trunc32_vec4(<4 x float> %a, ptr %p) nounwind {
|
|
; DEFISEL-LABEL: test_trunc32_vec4:
|
|
; DEFISEL: .functype test_trunc32_vec4 (f32, f32, f32, f32, i32) -> ()
|
|
; DEFISEL-NEXT: # %bb.0:
|
|
; DEFISEL-NEXT: local.get $push5=, 4
|
|
; DEFISEL-NEXT: local.get $push4=, 3
|
|
; DEFISEL-NEXT: call $push0=, __truncsfhf2, $pop4
|
|
; DEFISEL-NEXT: i32.store16 6($pop5), $pop0
|
|
; DEFISEL-NEXT: local.get $push7=, 4
|
|
; DEFISEL-NEXT: local.get $push6=, 2
|
|
; DEFISEL-NEXT: call $push1=, __truncsfhf2, $pop6
|
|
; DEFISEL-NEXT: i32.store16 4($pop7), $pop1
|
|
; DEFISEL-NEXT: local.get $push9=, 4
|
|
; DEFISEL-NEXT: local.get $push8=, 1
|
|
; DEFISEL-NEXT: call $push2=, __truncsfhf2, $pop8
|
|
; DEFISEL-NEXT: i32.store16 2($pop9), $pop2
|
|
; DEFISEL-NEXT: local.get $push11=, 4
|
|
; DEFISEL-NEXT: local.get $push10=, 0
|
|
; DEFISEL-NEXT: call $push3=, __truncsfhf2, $pop10
|
|
; DEFISEL-NEXT: i32.store16 0($pop11), $pop3
|
|
; DEFISEL-NEXT: return
|
|
;
|
|
; FASTISEL-LABEL: test_trunc32_vec4:
|
|
; FASTISEL: .functype test_trunc32_vec4 (f32, f32, f32, f32, i32) -> ()
|
|
; FASTISEL-NEXT: # %bb.0:
|
|
; FASTISEL-NEXT: local.get $push5=, 4
|
|
; FASTISEL-NEXT: local.get $push4=, 0
|
|
; FASTISEL-NEXT: call $push0=, __truncsfhf2, $pop4
|
|
; FASTISEL-NEXT: i32.store16 0($pop5), $pop0
|
|
; FASTISEL-NEXT: local.get $push7=, 4
|
|
; FASTISEL-NEXT: local.get $push6=, 1
|
|
; FASTISEL-NEXT: call $push1=, __truncsfhf2, $pop6
|
|
; FASTISEL-NEXT: i32.store16 2($pop7), $pop1
|
|
; FASTISEL-NEXT: local.get $push9=, 4
|
|
; FASTISEL-NEXT: local.get $push8=, 2
|
|
; FASTISEL-NEXT: call $push2=, __truncsfhf2, $pop8
|
|
; FASTISEL-NEXT: i32.store16 4($pop9), $pop2
|
|
; FASTISEL-NEXT: local.get $push11=, 4
|
|
; FASTISEL-NEXT: local.get $push10=, 3
|
|
; FASTISEL-NEXT: call $push3=, __truncsfhf2, $pop10
|
|
; FASTISEL-NEXT: i32.store16 6($pop11), $pop3
|
|
; FASTISEL-NEXT: return
|
|
%v = fptrunc <4 x float> %a to <4 x half>
|
|
store <4 x half> %v, ptr %p
|
|
ret void
|
|
}
|
|
|
|
define void @test_trunc64_vec4(<4 x double> %a, ptr %p) nounwind {
|
|
; DEFISEL-LABEL: test_trunc64_vec4:
|
|
; DEFISEL: .functype test_trunc64_vec4 (f64, f64, f64, f64, i32) -> ()
|
|
; DEFISEL-NEXT: # %bb.0:
|
|
; DEFISEL-NEXT: local.get $push5=, 4
|
|
; DEFISEL-NEXT: local.get $push4=, 3
|
|
; DEFISEL-NEXT: call $push0=, __truncdfhf2, $pop4
|
|
; DEFISEL-NEXT: i32.store16 6($pop5), $pop0
|
|
; DEFISEL-NEXT: local.get $push7=, 4
|
|
; DEFISEL-NEXT: local.get $push6=, 2
|
|
; DEFISEL-NEXT: call $push1=, __truncdfhf2, $pop6
|
|
; DEFISEL-NEXT: i32.store16 4($pop7), $pop1
|
|
; DEFISEL-NEXT: local.get $push9=, 4
|
|
; DEFISEL-NEXT: local.get $push8=, 1
|
|
; DEFISEL-NEXT: call $push2=, __truncdfhf2, $pop8
|
|
; DEFISEL-NEXT: i32.store16 2($pop9), $pop2
|
|
; DEFISEL-NEXT: local.get $push11=, 4
|
|
; DEFISEL-NEXT: local.get $push10=, 0
|
|
; DEFISEL-NEXT: call $push3=, __truncdfhf2, $pop10
|
|
; DEFISEL-NEXT: i32.store16 0($pop11), $pop3
|
|
; DEFISEL-NEXT: return
|
|
;
|
|
; FASTISEL-LABEL: test_trunc64_vec4:
|
|
; FASTISEL: .functype test_trunc64_vec4 (f64, f64, f64, f64, i32) -> ()
|
|
; FASTISEL-NEXT: # %bb.0:
|
|
; FASTISEL-NEXT: local.get $push5=, 4
|
|
; FASTISEL-NEXT: local.get $push4=, 0
|
|
; FASTISEL-NEXT: call $push0=, __truncdfhf2, $pop4
|
|
; FASTISEL-NEXT: i32.store16 0($pop5), $pop0
|
|
; FASTISEL-NEXT: local.get $push7=, 4
|
|
; FASTISEL-NEXT: local.get $push6=, 1
|
|
; FASTISEL-NEXT: call $push1=, __truncdfhf2, $pop6
|
|
; FASTISEL-NEXT: i32.store16 2($pop7), $pop1
|
|
; FASTISEL-NEXT: local.get $push9=, 4
|
|
; FASTISEL-NEXT: local.get $push8=, 2
|
|
; FASTISEL-NEXT: call $push2=, __truncdfhf2, $pop8
|
|
; FASTISEL-NEXT: i32.store16 4($pop9), $pop2
|
|
; FASTISEL-NEXT: local.get $push11=, 4
|
|
; FASTISEL-NEXT: local.get $push10=, 3
|
|
; FASTISEL-NEXT: call $push3=, __truncdfhf2, $pop10
|
|
; FASTISEL-NEXT: i32.store16 6($pop11), $pop3
|
|
; FASTISEL-NEXT: return
|
|
%v = fptrunc <4 x double> %a to <4 x half>
|
|
store <4 x half> %v, ptr %p
|
|
ret void
|
|
}
|
|
|
|
define float @test_sitofp_fadd_i32(i32 %a, ptr %b) nounwind {
|
|
; DEFISEL-LABEL: test_sitofp_fadd_i32:
|
|
; DEFISEL: .functype test_sitofp_fadd_i32 (i32, i32) -> (f32)
|
|
; DEFISEL-NEXT: # %bb.0:
|
|
; DEFISEL-NEXT: local.get $push8=, 1
|
|
; DEFISEL-NEXT: i32.load16_u $push7=, 0($pop8)
|
|
; DEFISEL-NEXT: local.set 1, $pop7
|
|
; DEFISEL-NEXT: local.get $push9=, 0
|
|
; DEFISEL-NEXT: f32.convert_i32_s $push0=, $pop9
|
|
; DEFISEL-NEXT: call $push1=, __truncsfhf2, $pop0
|
|
; DEFISEL-NEXT: call $push2=, __extendhfsf2, $pop1
|
|
; DEFISEL-NEXT: local.get $push10=, 1
|
|
; DEFISEL-NEXT: call $push3=, __extendhfsf2, $pop10
|
|
; DEFISEL-NEXT: f32.add $push4=, $pop2, $pop3
|
|
; DEFISEL-NEXT: call $push5=, __truncsfhf2, $pop4
|
|
; DEFISEL-NEXT: call $push6=, __extendhfsf2, $pop5
|
|
; DEFISEL-NEXT: return $pop6
|
|
;
|
|
; FASTISEL-LABEL: test_sitofp_fadd_i32:
|
|
; FASTISEL: .functype test_sitofp_fadd_i32 (i32, i32) -> (f32)
|
|
; FASTISEL-NEXT: # %bb.0:
|
|
; FASTISEL-NEXT: local.get $push8=, 1
|
|
; FASTISEL-NEXT: i32.load16_u $push7=, 0($pop8)
|
|
; FASTISEL-NEXT: local.set 1, $pop7
|
|
; FASTISEL-NEXT: local.get $push9=, 0
|
|
; FASTISEL-NEXT: f32.convert_i32_s $push1=, $pop9
|
|
; FASTISEL-NEXT: call $push2=, __truncsfhf2, $pop1
|
|
; FASTISEL-NEXT: call $push3=, __extendhfsf2, $pop2
|
|
; FASTISEL-NEXT: local.get $push10=, 1
|
|
; FASTISEL-NEXT: call $push4=, __extendhfsf2, $pop10
|
|
; FASTISEL-NEXT: f32.add $push5=, $pop3, $pop4
|
|
; FASTISEL-NEXT: call $push6=, __truncsfhf2, $pop5
|
|
; FASTISEL-NEXT: call $push0=, __extendhfsf2, $pop6
|
|
; FASTISEL-NEXT: return $pop0
|
|
%tmp0 = load half, ptr %b
|
|
%tmp1 = sitofp i32 %a to half
|
|
%tmp2 = fadd half %tmp0, %tmp1
|
|
%tmp3 = fpext half %tmp2 to float
|
|
ret float %tmp3
|
|
}
|
|
|
|
define half @chained_fp_ops(half %x) {
|
|
; ALL-LABEL: chained_fp_ops:
|
|
; ALL: .functype chained_fp_ops (i32) -> (i32)
|
|
; ALL-NEXT: .local f32
|
|
; ALL-NEXT: # %bb.0: # %start
|
|
; ALL-NEXT: local.get $push8=, 0
|
|
; ALL-NEXT: call $push7=, __extendhfsf2, $pop8
|
|
; ALL-NEXT: local.tee $push6=, 1, $pop7
|
|
; ALL-NEXT: local.get $push9=, 1
|
|
; ALL-NEXT: f32.add $push0=, $pop6, $pop9
|
|
; ALL-NEXT: call $push2=, __truncsfhf2, $pop0
|
|
; ALL-NEXT: call $push3=, __extendhfsf2, $pop2
|
|
; ALL-NEXT: f32.const $push1=, 0x1p-1
|
|
; ALL-NEXT: f32.mul $push4=, $pop3, $pop1
|
|
; ALL-NEXT: call $push5=, __truncsfhf2, $pop4
|
|
; ALL-NEXT: return $pop5
|
|
start:
|
|
%y = fmul half %x, 0xH4000
|
|
%z = fdiv half %y, 0xH4000
|
|
ret half %z
|
|
}
|
|
|
|
define half @test_select_cc(half) nounwind {
|
|
; ALL-LABEL: test_select_cc:
|
|
; ALL: .functype test_select_cc (i32) -> (i32)
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: i32.const $push4=, 15360
|
|
; ALL-NEXT: i32.const $push3=, 0
|
|
; ALL-NEXT: local.get $push6=, 0
|
|
; ALL-NEXT: call $push1=, __extendhfsf2, $pop6
|
|
; ALL-NEXT: f32.const $push0=, 0x0p0
|
|
; ALL-NEXT: f32.ne $push2=, $pop1, $pop0
|
|
; ALL-NEXT: i32.select $push5=, $pop4, $pop3, $pop2
|
|
; ALL-NEXT: return $pop5
|
|
%2 = fcmp une half %0, 0xH0000
|
|
%3 = uitofp i1 %2 to half
|
|
ret half %3
|
|
}
|
|
|
|
define half @fabs(half %x) nounwind {
|
|
; ALL-LABEL: fabs:
|
|
; ALL: .functype fabs (i32) -> (i32)
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push2=, 0
|
|
; ALL-NEXT: i32.const $push0=, 32767
|
|
; ALL-NEXT: i32.and $push1=, $pop2, $pop0
|
|
; ALL-NEXT: return $pop1
|
|
%a = call half @llvm.fabs.f16(half %x)
|
|
ret half %a
|
|
}
|
|
|
|
define half @fcopysign(half %x, half %y) nounwind {
|
|
; ALL-LABEL: fcopysign:
|
|
; ALL: .functype fcopysign (i32, i32) -> (i32)
|
|
; ALL-NEXT: # %bb.0:
|
|
; ALL-NEXT: local.get $push5=, 0
|
|
; ALL-NEXT: i32.const $push2=, 32767
|
|
; ALL-NEXT: i32.and $push3=, $pop5, $pop2
|
|
; ALL-NEXT: local.get $push6=, 1
|
|
; ALL-NEXT: i32.const $push0=, -32768
|
|
; ALL-NEXT: i32.and $push1=, $pop6, $pop0
|
|
; ALL-NEXT: i32.or $push4=, $pop3, $pop1
|
|
; ALL-NEXT: return $pop4
|
|
%a = call half @llvm.copysign.f16(half %x, half %y)
|
|
ret half %a
|
|
}
|