| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc < %s -mtriple=arm64-eabi -enable-no-nans-fp-math | FileCheck %s |
| |
| define double @test_direct(float %in) { |
| ; CHECK-LABEL: test_direct: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: movi d1, #0000000000000000 |
| ; CHECK-NEXT: fmaxnm s0, s0, s1 |
| ; CHECK-NEXT: fcvt d0, s0 |
| ; CHECK-NEXT: ret |
| %cmp = fcmp nnan olt float %in, 0.000000e+00 |
| %val = select i1 %cmp, float 0.000000e+00, float %in |
| %longer = fpext float %val to double |
| ret double %longer |
| } |
| |
| define double @test_cross(float %in) { |
| ; CHECK-LABEL: test_cross: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: movi d1, #0000000000000000 |
| ; CHECK-NEXT: fminnm s0, s0, s1 |
| ; CHECK-NEXT: fcvt d0, s0 |
| ; CHECK-NEXT: ret |
| %cmp = fcmp nnan ult float %in, 0.000000e+00 |
| %val = select i1 %cmp, float %in, float 0.000000e+00 |
| %longer = fpext float %val to double |
| ret double %longer |
| } |
| |
| ; Same as previous, but with ordered comparison; |
| ; can't be converted in safe-math mode. |
| define double @test_cross_fail_nan(float %in) { |
| ; CHECK-LABEL: test_cross_fail_nan: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: movi d1, #0000000000000000 |
| ; CHECK-NEXT: fminnm s0, s0, s1 |
| ; CHECK-NEXT: fcvt d0, s0 |
| ; CHECK-NEXT: ret |
| %cmp = fcmp nnan olt float %in, 0.000000e+00 |
| %val = select i1 %cmp, float %in, float 0.000000e+00 |
| %longer = fpext float %val to double |
| ret double %longer |
| } |
| |
| ; This isn't a min or a max, but passes the first condition for swapping the |
| ; results. Make sure they're put back before we resort to the normal fcsel. |
| define float @test_cross_fail(float %lhs, float %rhs) { |
| ; CHECK-LABEL: test_cross_fail: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fcmp s0, s1 |
| ; CHECK-NEXT: fcsel s0, s1, s0, ne |
| ; CHECK-NEXT: ret |
| %tst = fcmp nnan une float %lhs, %rhs |
| %res = select i1 %tst, float %rhs, float %lhs |
| ret float %res |
| } |
| |
| ; Make sure the transformation isn't triggered for integers |
| define i64 @test_integer(i64 %in) { |
| ; CHECK-LABEL: test_integer: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: cmp x0, #0 |
| ; CHECK-NEXT: csel x0, xzr, x0, lt |
| ; CHECK-NEXT: ret |
| %cmp = icmp slt i64 %in, 0 |
| %val = select i1 %cmp, i64 0, i64 %in |
| ret i64 %val |
| } |
| |
| ; FIXME: It'd be nice for this to create an fmin instruction! |
| define float @test_f16(half %in) { |
| ; CHECK-LABEL: test_f16: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: // kill: def $h0 killed $h0 def $s0 |
| ; CHECK-NEXT: fcvt s1, h0 |
| ; CHECK-NEXT: adrp x8, .LCPI5_0 |
| ; CHECK-NEXT: ldr h2, [x8, :lo12:.LCPI5_0] |
| ; CHECK-NEXT: fcmp s1, #0.0 |
| ; CHECK-NEXT: fcsel s0, s0, s2, lt |
| ; CHECK-NEXT: fcvt s0, h0 |
| ; CHECK-NEXT: ret |
| %cmp = fcmp nnan ult half %in, 0.000000e+00 |
| %val = select i1 %cmp, half %in, half 0.000000e+00 |
| %longer = fpext half %val to float |
| ret float %longer |
| } |