Compiler projects using 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 @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 @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
}

; 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 @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
}

; 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:    i32.const 8
; CHECK-NEXT:    i32.add
; CHECK-NEXT:    i64.load 0
; 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 @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:    i32.const 8
; CHECK-NEXT:    i32.add
; CHECK-NEXT:    i64.load 0
; 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 @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:    i32.const 8
; CHECK-NEXT:    i32.add
; CHECK-NEXT:    i64.load 0
; 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 @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:    i32.const 8
; CHECK-NEXT:    i32.add
; CHECK-NEXT:    i64.load 0
; 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 @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:    i32.const 8
; CHECK-NEXT:    i32.add
; CHECK-NEXT:    i64.load 0
; 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 @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:    i32.const 8
; CHECK-NEXT:    i32.add
; CHECK-NEXT:    i64.load 0
; 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
}

; 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
}

; 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:    i32.const 8
; CHECK-NEXT:    i32.add
; CHECK-NEXT:    i64.load 0
; 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.eqz
; CHECK-NEXT:    i64.select
; CHECK-NEXT:    local.get 2
; CHECK-NEXT:    i64.const 1
; CHECK-NEXT:    i64.eq
; 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:    i32.const 8
; CHECK-NEXT:    i32.add
; CHECK-NEXT:    i64.load 0
; 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:    i64.eq
; CHECK-NEXT:    i64.select
; CHECK-NEXT:    local.tee 3
; CHECK-NEXT:    local.get 3
; CHECK-NEXT:    i64.const 0
; 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:    i64.select
; CHECK-NEXT:    local.get 2
; CHECK-NEXT:    i64.eqz
; 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:    i32.const 8
; CHECK-NEXT:    i32.add
; CHECK-NEXT:    i64.load 0
; 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.eqz
; CHECK-NEXT:    i64.select
; CHECK-NEXT:    local.get 2
; CHECK-NEXT:    i64.const 1
; CHECK-NEXT:    i64.eq
; 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:    i32.const 8
; CHECK-NEXT:    i32.add
; CHECK-NEXT:    i64.load 0
; 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:    i64.eq
; CHECK-NEXT:    i64.select
; CHECK-NEXT:    local.tee 3
; CHECK-NEXT:    local.get 3
; CHECK-NEXT:    i64.const 0
; 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:    i64.select
; CHECK-NEXT:    local.get 2
; CHECK-NEXT:    i64.eqz
; 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:    i32.const 8
; CHECK-NEXT:    i32.add
; CHECK-NEXT:    i64.load 0
; 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.eqz
; CHECK-NEXT:    i64.select
; CHECK-NEXT:    local.get 2
; CHECK-NEXT:    i64.const 1
; CHECK-NEXT:    i64.eq
; 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:    i32.const 8
; CHECK-NEXT:    i32.add
; CHECK-NEXT:    i64.load 0
; 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:    i64.eq
; CHECK-NEXT:    i64.select
; CHECK-NEXT:    local.tee 3
; CHECK-NEXT:    local.get 3
; CHECK-NEXT:    i64.const 0
; 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:    i64.select
; CHECK-NEXT:    local.get 2
; CHECK-NEXT:    i64.eqz
; 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
}

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)