
When expanding a load into two loads, use nuw for the add that computes the offset from the base of the second load, because the original load doesn't straddle the address space. It turns out there's already a dedicated helper function for doing this, `getObjectPtrOffset`. This is in target-independent code, however in practice it only seems to affact WebAssembly code, because WebAssembly load and store instructions' constant offsets don't perform wrapping, so constant folding often depends on the nuw flag being present. This was noticed in the development of #119204.
1766 lines
56 KiB
LLVM
1766 lines
56 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc < %s -mtriple=wasm32-unknown-unknown -mattr=+simd128,+nontrapping-fptoint | FileCheck %s
|
|
|
|
; i32 saturate
|
|
|
|
define i32 @stest_f64i32(double %x) {
|
|
; CHECK-LABEL: stest_f64i32:
|
|
; CHECK: .functype stest_f64i32 (f64) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f64_s
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi double %x to i64
|
|
%0 = icmp slt i64 %conv, 2147483647
|
|
%spec.store.select = select i1 %0, i64 %conv, i64 2147483647
|
|
%1 = icmp sgt i64 %spec.store.select, -2147483648
|
|
%spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 -2147483648
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @utest_f64i32(double %x) {
|
|
; CHECK-LABEL: utest_f64i32:
|
|
; CHECK: .functype utest_f64i32 (f64) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f64_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui double %x to i64
|
|
%0 = icmp ult i64 %conv, 4294967295
|
|
%spec.store.select = select i1 %0, i64 %conv, i64 4294967295
|
|
%conv6 = trunc i64 %spec.store.select to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @ustest_f64i32(double %x) {
|
|
; CHECK-LABEL: ustest_f64i32:
|
|
; CHECK: .functype ustest_f64i32 (f64) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f64_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi double %x to i64
|
|
%0 = icmp slt i64 %conv, 4294967295
|
|
%spec.store.select = select i1 %0, i64 %conv, i64 4294967295
|
|
%1 = icmp sgt i64 %spec.store.select, 0
|
|
%spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 0
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @stest_f32i32(float %x) {
|
|
; CHECK-LABEL: stest_f32i32:
|
|
; CHECK: .functype stest_f32i32 (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f32_s
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i64
|
|
%0 = icmp slt i64 %conv, 2147483647
|
|
%spec.store.select = select i1 %0, i64 %conv, i64 2147483647
|
|
%1 = icmp sgt i64 %spec.store.select, -2147483648
|
|
%spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 -2147483648
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @utest_f32i32(float %x) {
|
|
; CHECK-LABEL: utest_f32i32:
|
|
; CHECK: .functype utest_f32i32 (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui float %x to i64
|
|
%0 = icmp ult i64 %conv, 4294967295
|
|
%spec.store.select = select i1 %0, i64 %conv, i64 4294967295
|
|
%conv6 = trunc i64 %spec.store.select to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @ustest_f32i32(float %x) {
|
|
; CHECK-LABEL: ustest_f32i32:
|
|
; CHECK: .functype ustest_f32i32 (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i64
|
|
%0 = icmp slt i64 %conv, 4294967295
|
|
%spec.store.select = select i1 %0, i64 %conv, i64 4294967295
|
|
%1 = icmp sgt i64 %spec.store.select, 0
|
|
%spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 0
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @stest_f16i32(half %x) {
|
|
; CHECK-LABEL: stest_f16i32:
|
|
; CHECK: .functype stest_f16i32 (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_s
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i64
|
|
%0 = icmp slt i64 %conv, 2147483647
|
|
%spec.store.select = select i1 %0, i64 %conv, i64 2147483647
|
|
%1 = icmp sgt i64 %spec.store.select, -2147483648
|
|
%spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 -2147483648
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @stest_f16i32_cse(half %x) {
|
|
; CHECK-LABEL: stest_f16i32_cse:
|
|
; CHECK: .functype stest_f16i32_cse (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i64.trunc_sat_f32_s
|
|
; CHECK-NEXT: i32.wrap_i64
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i64
|
|
%conv6 = trunc i64 %conv to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @utesth_f16i32(half %x) {
|
|
; CHECK-LABEL: utesth_f16i32:
|
|
; CHECK: .functype utesth_f16i32 (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui half %x to i64
|
|
%0 = icmp ult i64 %conv, 4294967295
|
|
%spec.store.select = select i1 %0, i64 %conv, i64 4294967295
|
|
%conv6 = trunc i64 %spec.store.select to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @utesth_f16i32_cse(half %x) {
|
|
; CHECK-LABEL: utesth_f16i32_cse:
|
|
; CHECK: .functype utesth_f16i32_cse (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i64.trunc_sat_f32_u
|
|
; CHECK-NEXT: i32.wrap_i64
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui half %x to i64
|
|
%conv6 = trunc i64 %conv to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @ustest_f16i32(half %x) {
|
|
; CHECK-LABEL: ustest_f16i32:
|
|
; CHECK: .functype ustest_f16i32 (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i64
|
|
%0 = icmp slt i64 %conv, 4294967295
|
|
%spec.store.select = select i1 %0, i64 %conv, i64 4294967295
|
|
%1 = icmp sgt i64 %spec.store.select, 0
|
|
%spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 0
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @ustest_f16i32_cse(half %x) {
|
|
; CHECK-LABEL: ustest_f16i32_cse:
|
|
; CHECK: .functype ustest_f16i32_cse (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i64
|
|
%0 = icmp sgt i64 %conv, 0
|
|
%spec.store.select7 = select i1 %0, i64 %conv, i64 0
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
; i16 saturate
|
|
|
|
define i16 @stest_f64i16(double %x) {
|
|
; CHECK-LABEL: stest_f64i16:
|
|
; CHECK: .functype stest_f64i16 (f64) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f64_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 32767
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 32767
|
|
; CHECK-NEXT: i32.lt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const -32768
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const -32768
|
|
; CHECK-NEXT: i32.gt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi double %x to i32
|
|
%0 = icmp slt i32 %conv, 32767
|
|
%spec.store.select = select i1 %0, i32 %conv, i32 32767
|
|
%1 = icmp sgt i32 %spec.store.select, -32768
|
|
%spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 -32768
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @utest_f64i16(double %x) {
|
|
; CHECK-LABEL: utest_f64i16:
|
|
; CHECK: .functype utest_f64i16 (f64) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f64_u
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: i32.lt_u
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui double %x to i32
|
|
%0 = icmp ult i32 %conv, 65535
|
|
%spec.store.select = select i1 %0, i32 %conv, i32 65535
|
|
%conv6 = trunc i32 %spec.store.select to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @ustest_f64i16(double %x) {
|
|
; CHECK-LABEL: ustest_f64i16:
|
|
; CHECK: .functype ustest_f64i16 (f64) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f64_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: i32.lt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 0
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 0
|
|
; CHECK-NEXT: i32.gt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi double %x to i32
|
|
%0 = icmp slt i32 %conv, 65535
|
|
%spec.store.select = select i1 %0, i32 %conv, i32 65535
|
|
%1 = icmp sgt i32 %spec.store.select, 0
|
|
%spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 0
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @stest_f32i16(float %x) {
|
|
; CHECK-LABEL: stest_f32i16:
|
|
; CHECK: .functype stest_f32i16 (f32) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f32_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 32767
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 32767
|
|
; CHECK-NEXT: i32.lt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const -32768
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const -32768
|
|
; CHECK-NEXT: i32.gt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i32
|
|
%0 = icmp slt i32 %conv, 32767
|
|
%spec.store.select = select i1 %0, i32 %conv, i32 32767
|
|
%1 = icmp sgt i32 %spec.store.select, -32768
|
|
%spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 -32768
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @utest_f32i16(float %x) {
|
|
; CHECK-LABEL: utest_f32i16:
|
|
; CHECK: .functype utest_f32i16 (f32) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: i32.lt_u
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui float %x to i32
|
|
%0 = icmp ult i32 %conv, 65535
|
|
%spec.store.select = select i1 %0, i32 %conv, i32 65535
|
|
%conv6 = trunc i32 %spec.store.select to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @ustest_f32i16(float %x) {
|
|
; CHECK-LABEL: ustest_f32i16:
|
|
; CHECK: .functype ustest_f32i16 (f32) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f32_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: i32.lt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 0
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 0
|
|
; CHECK-NEXT: i32.gt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i32
|
|
%0 = icmp slt i32 %conv, 65535
|
|
%spec.store.select = select i1 %0, i32 %conv, i32 65535
|
|
%1 = icmp sgt i32 %spec.store.select, 0
|
|
%spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 0
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @stest_f16i16(half %x) {
|
|
; CHECK-LABEL: stest_f16i16:
|
|
; CHECK: .functype stest_f16i16 (f32) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 32767
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 32767
|
|
; CHECK-NEXT: i32.lt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const -32768
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const -32768
|
|
; CHECK-NEXT: i32.gt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i32
|
|
%0 = icmp slt i32 %conv, 32767
|
|
%spec.store.select = select i1 %0, i32 %conv, i32 32767
|
|
%1 = icmp sgt i32 %spec.store.select, -32768
|
|
%spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 -32768
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @utesth_f16i16(half %x) {
|
|
; CHECK-LABEL: utesth_f16i16:
|
|
; CHECK: .functype utesth_f16i16 (f32) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: i32.lt_u
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui half %x to i32
|
|
%0 = icmp ult i32 %conv, 65535
|
|
%spec.store.select = select i1 %0, i32 %conv, i32 65535
|
|
%conv6 = trunc i32 %spec.store.select to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @utesth_f16i16_cse(half %x) {
|
|
; CHECK-LABEL: utesth_f16i16_cse:
|
|
; CHECK: .functype utesth_f16i16_cse (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui half %x to i32
|
|
%conv6 = trunc i32 %conv to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @ustest_f16i16(half %x) {
|
|
; CHECK-LABEL: ustest_f16i16:
|
|
; CHECK: .functype ustest_f16i16 (f32) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: i32.lt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 0
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 0
|
|
; CHECK-NEXT: i32.gt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i32
|
|
%0 = icmp slt i32 %conv, 65535
|
|
%spec.store.select = select i1 %0, i32 %conv, i32 65535
|
|
%1 = icmp sgt i32 %spec.store.select, 0
|
|
%spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 0
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @ustest_f16i16_cse(half %x) {
|
|
; CHECK-LABEL: ustest_f16i16_cse:
|
|
; CHECK: .functype ustest_f16i16_cse (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i32
|
|
%0 = icmp sgt i32 %conv, 0
|
|
%spec.store.select7 = select i1 %0, i32 %conv, i32 0
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
; i64 saturate
|
|
|
|
define i64 @stest_f64i64(double %x) {
|
|
; CHECK-LABEL: stest_f64i64:
|
|
; CHECK: .functype stest_f64i64 (f64) -> (i64)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i64.trunc_sat_f64_s
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi double %x to i128
|
|
%0 = icmp slt i128 %conv, 9223372036854775807
|
|
%spec.store.select = select i1 %0, i128 %conv, i128 9223372036854775807
|
|
%1 = icmp sgt i128 %spec.store.select, -9223372036854775808
|
|
%spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 -9223372036854775808
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @utest_f64i64(double %x) {
|
|
; CHECK-LABEL: utest_f64i64:
|
|
; CHECK: .functype utest_f64i64 (f64) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __fixunsdfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.eqz
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui double %x to i128
|
|
%0 = icmp ult i128 %conv, 18446744073709551616
|
|
%spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
|
|
%conv6 = trunc i128 %spec.store.select to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @utest_f64i64_cse_combine(double %x) #0 {
|
|
; CHECK-LABEL: utest_f64i64_cse_combine:
|
|
; CHECK: .functype utest_f64i64_cse_combine (f64) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __fixunsdfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.eqz
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui double %x to i128
|
|
%spec.store.select = call i128 @llvm.umin.i128(i128 %conv, i128 18446744073709551616)
|
|
%conv6 = trunc i128 %spec.store.select to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
|
|
define i64 @ustest_f64i64(double %x) {
|
|
; CHECK-LABEL: ustest_f64i64:
|
|
; CHECK: .functype ustest_f64i64 (f64) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __fixdfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: i64.lt_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: local.tee 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: i64.ne
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: local.tee 2
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: i64.gt_s
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.eqz
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi double %x to i128
|
|
%0 = icmp slt i128 %conv, 18446744073709551616
|
|
%spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
|
|
%1 = icmp sgt i128 %spec.store.select, 0
|
|
%spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 0
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @ustest_f64i64_cse_combine(double %x) #0 {
|
|
; CHECK-LABEL: ustest_f64i64_cse_combine:
|
|
; CHECK: .functype ustest_f64i64_cse_combine (f64) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __fixdfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: i64.lt_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: i64.lt_s
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi double %x to i128
|
|
%spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 18446744073709551616)
|
|
%spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 0)
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @stest_f32i64(float %x) {
|
|
; CHECK-LABEL: stest_f32i64:
|
|
; CHECK: .functype stest_f32i64 (f32) -> (i64)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i64.trunc_sat_f32_s
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i128
|
|
%0 = icmp slt i128 %conv, 9223372036854775807
|
|
%spec.store.select = select i1 %0, i128 %conv, i128 9223372036854775807
|
|
%1 = icmp sgt i128 %spec.store.select, -9223372036854775808
|
|
%spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 -9223372036854775808
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @utest_f32i64(float %x) {
|
|
; CHECK-LABEL: utest_f32i64:
|
|
; CHECK: .functype utest_f32i64 (f32) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __fixunssfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.eqz
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui float %x to i128
|
|
%0 = icmp ult i128 %conv, 18446744073709551616
|
|
%spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
|
|
%conv6 = trunc i128 %spec.store.select to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @stest_f32i64_cse_combine(float %x) #0 {
|
|
; CHECK-LABEL: stest_f32i64_cse_combine:
|
|
; CHECK: .functype stest_f32i64_cse_combine (f32) -> (i64)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i64.trunc_sat_f32_s
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i128
|
|
%spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 9223372036854775807)
|
|
%spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 -9223372036854775808)
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @ustest_f32i64(float %x) {
|
|
; CHECK-LABEL: ustest_f32i64:
|
|
; CHECK: .functype ustest_f32i64 (f32) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __fixsfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: i64.lt_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: local.tee 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: i64.ne
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: local.tee 2
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: i64.gt_s
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.eqz
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i128
|
|
%0 = icmp slt i128 %conv, 18446744073709551616
|
|
%spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
|
|
%1 = icmp sgt i128 %spec.store.select, 0
|
|
%spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 0
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @ustest_f32i64_cse_combine(float %x) #0 {
|
|
; CHECK-LABEL: ustest_f32i64_cse_combine:
|
|
; CHECK: .functype ustest_f32i64_cse_combine (f32) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __fixsfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: i64.lt_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: i64.lt_s
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i128
|
|
%spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 18446744073709551616)
|
|
%spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 0)
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @stest_f16i64(half %x) {
|
|
; CHECK-LABEL: stest_f16i64:
|
|
; CHECK: .functype stest_f16i64 (f32) -> (i64)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i64.trunc_sat_f32_s
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i128
|
|
%0 = icmp slt i128 %conv, 9223372036854775807
|
|
%spec.store.select = select i1 %0, i128 %conv, i128 9223372036854775807
|
|
%1 = icmp sgt i128 %spec.store.select, -9223372036854775808
|
|
%spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 -9223372036854775808
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @utesth_f16i64(half %x) {
|
|
; CHECK-LABEL: utesth_f16i64:
|
|
; CHECK: .functype utesth_f16i64 (f32) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: call __fixunssfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.eqz
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui half %x to i128
|
|
%0 = icmp ult i128 %conv, 18446744073709551616
|
|
%spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
|
|
%conv6 = trunc i128 %spec.store.select to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @utesth_f16i64_cse(half %x) {
|
|
; CHECK-LABEL: utesth_f16i64_cse:
|
|
; CHECK: .functype utesth_f16i64_cse (f32) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: call __fixunssfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui half %x to i128
|
|
%conv6 = trunc i128 %conv to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @ustest_f16i64(half %x) {
|
|
; CHECK-LABEL: ustest_f16i64:
|
|
; CHECK: .functype ustest_f16i64 (f32) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: call __fixsfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: i64.lt_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: local.tee 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: i64.ne
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: local.tee 2
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: i64.gt_s
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.eqz
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i128
|
|
%0 = icmp slt i128 %conv, 18446744073709551616
|
|
%spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
|
|
%1 = icmp sgt i128 %spec.store.select, 0
|
|
%spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 0
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
|
|
|
|
|
|
; i32 saturate
|
|
|
|
define i32 @stest_f64i32_mm(double %x) {
|
|
; CHECK-LABEL: stest_f64i32_mm:
|
|
; CHECK: .functype stest_f64i32_mm (f64) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f64_s
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi double %x to i64
|
|
%spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
|
|
%spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @utest_f64i32_mm(double %x) {
|
|
; CHECK-LABEL: utest_f64i32_mm:
|
|
; CHECK: .functype utest_f64i32_mm (f64) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f64_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui double %x to i64
|
|
%spec.store.select = call i64 @llvm.umin.i64(i64 %conv, i64 4294967295)
|
|
%conv6 = trunc i64 %spec.store.select to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @ustest_f64i32_mm(double %x) {
|
|
; CHECK-LABEL: ustest_f64i32_mm:
|
|
; CHECK: .functype ustest_f64i32_mm (f64) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f64_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi double %x to i64
|
|
%spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 4294967295)
|
|
%spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 0)
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @stest_f32i32_mm(float %x) {
|
|
; CHECK-LABEL: stest_f32i32_mm:
|
|
; CHECK: .functype stest_f32i32_mm (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f32_s
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i64
|
|
%spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
|
|
%spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @utest_f32i32_mm(float %x) {
|
|
; CHECK-LABEL: utest_f32i32_mm:
|
|
; CHECK: .functype utest_f32i32_mm (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui float %x to i64
|
|
%spec.store.select = call i64 @llvm.umin.i64(i64 %conv, i64 4294967295)
|
|
%conv6 = trunc i64 %spec.store.select to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @ustest_f32i32_mm(float %x) {
|
|
; CHECK-LABEL: ustest_f32i32_mm:
|
|
; CHECK: .functype ustest_f32i32_mm (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i64
|
|
%spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 4294967295)
|
|
%spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 0)
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @stest_f16i32_mm(half %x) {
|
|
; CHECK-LABEL: stest_f16i32_mm:
|
|
; CHECK: .functype stest_f16i32_mm (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_s
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i64
|
|
%spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
|
|
%spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @utesth_f16i32_mm(half %x) {
|
|
; CHECK-LABEL: utesth_f16i32_mm:
|
|
; CHECK: .functype utesth_f16i32_mm (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui half %x to i64
|
|
%spec.store.select = call i64 @llvm.umin.i64(i64 %conv, i64 4294967295)
|
|
%conv6 = trunc i64 %spec.store.select to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @ustest_f16i32_mm(half %x) {
|
|
; CHECK-LABEL: ustest_f16i32_mm:
|
|
; CHECK: .functype ustest_f16i32_mm (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i64
|
|
%spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 4294967295)
|
|
%spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 0)
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
define i32 @ustest_f16i32_mm_cse(half %x) {
|
|
; CHECK-LABEL: ustest_f16i32_mm_cse:
|
|
; CHECK: .functype ustest_f16i32_mm_cse (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i64
|
|
%spec.store.select7 = call i64 @llvm.smax.i64(i64 %conv, i64 0)
|
|
%conv6 = trunc i64 %spec.store.select7 to i32
|
|
ret i32 %conv6
|
|
}
|
|
|
|
; i16 saturate
|
|
|
|
define i16 @stest_f64i16_mm(double %x) {
|
|
; CHECK-LABEL: stest_f64i16_mm:
|
|
; CHECK: .functype stest_f64i16_mm (f64) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f64_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 32767
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 32767
|
|
; CHECK-NEXT: i32.lt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const -32768
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const -32768
|
|
; CHECK-NEXT: i32.gt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi double %x to i32
|
|
%spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
|
|
%spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 -32768)
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @utest_f64i16_mm(double %x) {
|
|
; CHECK-LABEL: utest_f64i16_mm:
|
|
; CHECK: .functype utest_f64i16_mm (f64) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f64_u
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: i32.lt_u
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui double %x to i32
|
|
%spec.store.select = call i32 @llvm.umin.i32(i32 %conv, i32 65535)
|
|
%conv6 = trunc i32 %spec.store.select to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @ustest_f64i16_mm(double %x) {
|
|
; CHECK-LABEL: ustest_f64i16_mm:
|
|
; CHECK: .functype ustest_f64i16_mm (f64) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f64_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: i32.lt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 0
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 0
|
|
; CHECK-NEXT: i32.gt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi double %x to i32
|
|
%spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 65535)
|
|
%spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 0)
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @stest_f32i16_mm(float %x) {
|
|
; CHECK-LABEL: stest_f32i16_mm:
|
|
; CHECK: .functype stest_f32i16_mm (f32) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f32_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 32767
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 32767
|
|
; CHECK-NEXT: i32.lt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const -32768
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const -32768
|
|
; CHECK-NEXT: i32.gt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i32
|
|
%spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
|
|
%spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 -32768)
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @utest_f32i16_mm(float %x) {
|
|
; CHECK-LABEL: utest_f32i16_mm:
|
|
; CHECK: .functype utest_f32i16_mm (f32) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: i32.lt_u
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui float %x to i32
|
|
%spec.store.select = call i32 @llvm.umin.i32(i32 %conv, i32 65535)
|
|
%conv6 = trunc i32 %spec.store.select to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @ustest_f32i16_mm(float %x) {
|
|
; CHECK-LABEL: ustest_f32i16_mm:
|
|
; CHECK: .functype ustest_f32i16_mm (f32) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i32.trunc_sat_f32_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: i32.lt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 0
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 0
|
|
; CHECK-NEXT: i32.gt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i32
|
|
%spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 65535)
|
|
%spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 0)
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @stest_f16i16_mm(half %x) {
|
|
; CHECK-LABEL: stest_f16i16_mm:
|
|
; CHECK: .functype stest_f16i16_mm (f32) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 32767
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 32767
|
|
; CHECK-NEXT: i32.lt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const -32768
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const -32768
|
|
; CHECK-NEXT: i32.gt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i32
|
|
%spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
|
|
%spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 -32768)
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @utesth_f16i16_mm(half %x) {
|
|
; CHECK-LABEL: utesth_f16i16_mm:
|
|
; CHECK: .functype utesth_f16i16_mm (f32) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: i32.lt_u
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui half %x to i32
|
|
%spec.store.select = call i32 @llvm.umin.i32(i32 %conv, i32 65535)
|
|
%conv6 = trunc i32 %spec.store.select to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @ustest_f16i16_mm(half %x) {
|
|
; CHECK-LABEL: ustest_f16i16_mm:
|
|
; CHECK: .functype ustest_f16i16_mm (f32) -> (i32)
|
|
; CHECK-NEXT: .local i32
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 65535
|
|
; CHECK-NEXT: i32.lt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i32.const 0
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 0
|
|
; CHECK-NEXT: i32.gt_s
|
|
; CHECK-NEXT: i32.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i32
|
|
%spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 65535)
|
|
%spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 0)
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
define i16 @ustest_f16i16_mm_cse(half %x) {
|
|
; CHECK-LABEL: ustest_f16i16_mm_cse:
|
|
; CHECK: .functype ustest_f16i16_mm_cse (f32) -> (i32)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i32.trunc_sat_f32_u
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i32
|
|
%spec.store.select7 = call i32 @llvm.smax.i32(i32 %conv, i32 0)
|
|
%conv6 = trunc i32 %spec.store.select7 to i16
|
|
ret i16 %conv6
|
|
}
|
|
|
|
; i64 saturate
|
|
|
|
define i64 @stest_f64i64_mm(double %x) {
|
|
; CHECK-LABEL: stest_f64i64_mm:
|
|
; CHECK: .functype stest_f64i64_mm (f64) -> (i64)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i64.trunc_sat_f64_s
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi double %x to i128
|
|
%spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 9223372036854775807)
|
|
%spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 -9223372036854775808)
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @utest_f64i64_mm(double %x) {
|
|
; CHECK-LABEL: utest_f64i64_mm:
|
|
; CHECK: .functype utest_f64i64_mm (f64) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __fixunsdfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.eqz
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui double %x to i128
|
|
%spec.store.select = call i128 @llvm.umin.i128(i128 %conv, i128 18446744073709551616)
|
|
%conv6 = trunc i128 %spec.store.select to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @ustest_f64i64_mm(double %x) {
|
|
; CHECK-LABEL: ustest_f64i64_mm:
|
|
; CHECK: .functype ustest_f64i64_mm (f64) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __fixdfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: i64.lt_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: i64.lt_s
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi double %x to i128
|
|
%spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 18446744073709551616)
|
|
%spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 0)
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @stest_f32i64_mm(float %x) {
|
|
; CHECK-LABEL: stest_f32i64_mm:
|
|
; CHECK: .functype stest_f32i64_mm (f32) -> (i64)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: i64.trunc_sat_f32_s
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i128
|
|
%spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 9223372036854775807)
|
|
%spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 -9223372036854775808)
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @utest_f32i64_mm(float %x) {
|
|
; CHECK-LABEL: utest_f32i64_mm:
|
|
; CHECK: .functype utest_f32i64_mm (f32) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __fixunssfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.eqz
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui float %x to i128
|
|
%spec.store.select = call i128 @llvm.umin.i128(i128 %conv, i128 18446744073709551616)
|
|
%conv6 = trunc i128 %spec.store.select to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @ustest_f32i64_mm(float %x) {
|
|
; CHECK-LABEL: ustest_f32i64_mm:
|
|
; CHECK: .functype ustest_f32i64_mm (f32) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __fixsfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: i64.lt_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: i64.lt_s
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi float %x to i128
|
|
%spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 18446744073709551616)
|
|
%spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 0)
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @stest_f16i64_mm(half %x) {
|
|
; CHECK-LABEL: stest_f16i64_mm:
|
|
; CHECK: .functype stest_f16i64_mm (f32) -> (i64)
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: i64.trunc_sat_f32_s
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i128
|
|
%spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 9223372036854775807)
|
|
%spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 -9223372036854775808)
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @utesth_f16i64_mm(half %x) {
|
|
; CHECK-LABEL: utesth_f16i64_mm:
|
|
; CHECK: .functype utesth_f16i64_mm (f32) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: call __fixunssfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.eqz
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui half %x to i128
|
|
%spec.store.select = call i128 @llvm.umin.i128(i128 %conv, i128 18446744073709551616)
|
|
%conv6 = trunc i128 %spec.store.select to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @ustest_f16i64_mm(half %x) {
|
|
; CHECK-LABEL: ustest_f16i64_mm:
|
|
; CHECK: .functype ustest_f16i64_mm (f32) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: call __fixsfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 8
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 3
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 3
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: i64.lt_s
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: i64.const 1
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: i64.const 0
|
|
; CHECK-NEXT: i64.lt_s
|
|
; CHECK-NEXT: i64.select
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptosi half %x to i128
|
|
%spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 18446744073709551616)
|
|
%spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 0)
|
|
%conv6 = trunc i128 %spec.store.select7 to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
define i64 @utesth_f16i64_mm_cse(half %x) {
|
|
; CHECK-LABEL: utesth_f16i64_mm_cse:
|
|
; CHECK: .functype utesth_f16i64_mm_cse (f32) -> (i64)
|
|
; CHECK-NEXT: .local i32, i64
|
|
; CHECK-NEXT: # %bb.0: # %entry
|
|
; CHECK-NEXT: global.get __stack_pointer
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.sub
|
|
; CHECK-NEXT: local.tee 1
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: local.get 0
|
|
; CHECK-NEXT: call __truncsfhf2
|
|
; CHECK-NEXT: call __extendhfsf2
|
|
; CHECK-NEXT: call __fixunssfti
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i64.load 0
|
|
; CHECK-NEXT: local.set 2
|
|
; CHECK-NEXT: local.get 1
|
|
; CHECK-NEXT: i32.const 16
|
|
; CHECK-NEXT: i32.add
|
|
; CHECK-NEXT: global.set __stack_pointer
|
|
; CHECK-NEXT: local.get 2
|
|
; CHECK-NEXT: # fallthrough-return
|
|
entry:
|
|
%conv = fptoui half %x to i128
|
|
%conv6 = trunc i128 %conv to i64
|
|
ret i64 %conv6
|
|
}
|
|
|
|
declare i32 @llvm.smin.i32(i32, i32)
|
|
declare i32 @llvm.smax.i32(i32, i32)
|
|
declare i32 @llvm.umin.i32(i32, i32)
|
|
declare i64 @llvm.smin.i64(i64, i64)
|
|
declare i64 @llvm.smax.i64(i64, i64)
|
|
declare i64 @llvm.umin.i64(i64, i64)
|
|
declare i128 @llvm.smin.i128(i128, i128)
|
|
declare i128 @llvm.smax.i128(i128, i128)
|
|
declare i128 @llvm.umin.i128(i128, i128)
|