| ; 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 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 @utest_f16i32(half %x) { | |
| ; CHECK-LABEL: utest_f16i32: | |
| ; CHECK: .functype utest_f16i32 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 @utest_f16i32_cse(half %x) { | |
| ; CHECK-LABEL: utest_f16i32_cse: | |
| ; CHECK: .functype utest_f16i32_cse (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: call __extendhfsf2 | |
| ; CHECK-NEXT: i32.trunc_sat_f32_s | |
| ; CHECK-NEXT: local.tee 0 | |
| ; CHECK-NEXT: i32.const 32767 | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: i32.const 32767 | |
| ; CHECK-NEXT: i32.lt_s | |
| ; CHECK-NEXT: i32.select | |
| ; CHECK-NEXT: local.tee 0 | |
| ; CHECK-NEXT: i32.const -32768 | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 @utest_f16i16(half %x) { | |
| ; CHECK-LABEL: utest_f16i16: | |
| ; CHECK: .functype utest_f16i16 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: call __extendhfsf2 | |
| ; CHECK-NEXT: i32.trunc_sat_f32_u | |
| ; CHECK-NEXT: local.tee 0 | |
| ; CHECK-NEXT: i32.const 65535 | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 @utest_f16i16_cse(half %x) { | |
| ; CHECK-LABEL: utest_f16i16_cse: | |
| ; CHECK: .functype utest_f16i16_cse (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: call __extendhfsf2 | |
| ; CHECK-NEXT: i32.trunc_sat_f32_s | |
| ; CHECK-NEXT: local.tee 0 | |
| ; CHECK-NEXT: i32.const 65535 | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: i32.const 65535 | |
| ; CHECK-NEXT: i32.lt_s | |
| ; CHECK-NEXT: i32.select | |
| ; CHECK-NEXT: local.tee 0 | |
| ; CHECK-NEXT: i32.const 0 | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 (i32) -> (i64) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 @utest_f16i64(half %x) { | |
| ; CHECK-LABEL: utest_f16i64: | |
| ; CHECK: .functype utest_f16i64 (i32) -> (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 __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 @utest_f16i64_cse(half %x) { | |
| ; CHECK-LABEL: utest_f16i64_cse: | |
| ; CHECK: .functype utest_f16i64_cse (i32) -> (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 __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 (i32) -> (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 __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 | |
| } | |
| ; A zero clamp is not saturation bound, so umin(fptoui(x), 0) should fold to 0. | |
| define i32 @utest_f32i32_zero(float %x) { | |
| ; CHECK-LABEL: utest_f32i32_zero: | |
| ; CHECK: .functype utest_f32i32_zero (f32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: i32.const 0 | |
| ; CHECK-NEXT: # fallthrough-return | |
| entry: | |
| %conv = fptoui float %x to i32 | |
| %spec.store.select = call i32 @llvm.umin.i32(i32 %conv, i32 0) | |
| ret i32 %spec.store.select | |
| } | |
| 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 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 @utest_f16i32_mm(half %x) { | |
| ; CHECK-LABEL: utest_f16i32_mm: | |
| ; CHECK: .functype utest_f16i32_mm (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: call __extendhfsf2 | |
| ; CHECK-NEXT: i32.trunc_sat_f32_s | |
| ; CHECK-NEXT: local.tee 0 | |
| ; CHECK-NEXT: i32.const 32767 | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: i32.const 32767 | |
| ; CHECK-NEXT: i32.lt_s | |
| ; CHECK-NEXT: i32.select | |
| ; CHECK-NEXT: local.tee 0 | |
| ; CHECK-NEXT: i32.const -32768 | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 @utest_f16i16_mm(half %x) { | |
| ; CHECK-LABEL: utest_f16i16_mm: | |
| ; CHECK: .functype utest_f16i16_mm (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: call __extendhfsf2 | |
| ; CHECK-NEXT: i32.trunc_sat_f32_u | |
| ; CHECK-NEXT: local.tee 0 | |
| ; CHECK-NEXT: i32.const 65535 | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: call __extendhfsf2 | |
| ; CHECK-NEXT: i32.trunc_sat_f32_s | |
| ; CHECK-NEXT: local.tee 0 | |
| ; CHECK-NEXT: i32.const 65535 | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: i32.const 65535 | |
| ; CHECK-NEXT: i32.lt_s | |
| ; CHECK-NEXT: i32.select | |
| ; CHECK-NEXT: local.tee 0 | |
| ; CHECK-NEXT: i32.const 0 | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 (i32) -> (i64) | |
| ; CHECK-NEXT: # %bb.0: # %entry | |
| ; CHECK-NEXT: local.get 0 | |
| ; 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 @utest_f16i64_mm(half %x) { | |
| ; CHECK-LABEL: utest_f16i64_mm: | |
| ; CHECK: .functype utest_f16i64_mm (i32) -> (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 __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 (i32) -> (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 __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 @utest_f16i64_mm_cse(half %x) { | |
| ; CHECK-LABEL: utest_f16i64_mm_cse: | |
| ; CHECK: .functype utest_f16i64_mm_cse (i32) -> (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 __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 | |
| } | |
| ; i32 non saturate | |
| define i32 @ustest_f16i32_nsat(half %x) { | |
| ; CHECK-LABEL: ustest_f16i32_nsat: | |
| ; CHECK: .functype ustest_f16i32_nsat (i32) -> (i32) | |
| ; CHECK-NEXT: # %bb.0: | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: call __extendhfsf2 | |
| ; CHECK-NEXT: i32.trunc_sat_f32_s | |
| ; CHECK-NEXT: local.tee 0 | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: i32.const 31 | |
| ; CHECK-NEXT: i32.shr_s | |
| ; CHECK-NEXT: i32.and | |
| ; CHECK-NEXT: local.tee 0 | |
| ; CHECK-NEXT: i32.const 0 | |
| ; CHECK-NEXT: local.get 0 | |
| ; CHECK-NEXT: i32.const 0 | |
| ; CHECK-NEXT: i32.gt_s | |
| ; CHECK-NEXT: i32.select | |
| ; CHECK-NEXT: # fallthrough-return | |
| %conv = fptosi half %x to i32 | |
| %spec.store.select = call i32 @llvm.smin.i32(i32 0, i32 %conv) | |
| %spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 0) | |
| ret i32 %spec.store.select7 | |
| } | |
| 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) |