1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s 3 4 declare double @sin(double %f) 5 6 ; When the subs are strict, they can't be removed because of signed zero. 7 8 define double @strict(double %e) nounwind { 9 ; CHECK-LABEL: strict: 10 ; CHECK: # %bb.0: 11 ; CHECK-NEXT: pushq %rax 12 ; CHECK-NEXT: vxorpd %xmm1, %xmm1, %xmm1 13 ; CHECK-NEXT: vsubsd %xmm0, %xmm1, %xmm0 14 ; CHECK-NEXT: callq sin 15 ; CHECK-NEXT: vxorpd %xmm1, %xmm1, %xmm1 16 ; CHECK-NEXT: vsubsd %xmm0, %xmm1, %xmm0 17 ; CHECK-NEXT: popq %rax 18 ; CHECK-NEXT: retq 19 %f = fsub double 0.0, %e 20 %g = call double @sin(double %f) readonly 21 %h = fsub double 0.0, %g 22 ret double %h 23 } 24 25 ; 'fast' implies no-signed-zeros, so the negates fold away. 26 ; The 'sin' does not need any fast-math-flags for this transform. 27 28 define double @fast(double %e) nounwind { 29 ; CHECK-LABEL: fast: 30 ; CHECK: # %bb.0: 31 ; CHECK-NEXT: jmp sin # TAILCALL 32 %f = fsub fast double 0.0, %e 33 %g = call double @sin(double %f) readonly 34 %h = fsub fast double 0.0, %g 35 ret double %h 36 } 37 38 ; No-signed-zeros is all that we need for this transform. 39 40 define double @nsz(double %e) nounwind { 41 ; CHECK-LABEL: nsz: 42 ; CHECK: # %bb.0: 43 ; CHECK-NEXT: jmp sin # TAILCALL 44 %f = fsub nsz double 0.0, %e 45 %g = call double @sin(double %f) readonly 46 %h = fsub nsz double 0.0, %g 47 ret double %h 48 } 49 50 ; The 1st negate is strict, so we can't kill that sub, but the 2nd disappears. 51 52 define double @semi_strict1(double %e) nounwind { 53 ; CHECK-LABEL: semi_strict1: 54 ; CHECK: # %bb.0: 55 ; CHECK-NEXT: pushq %rax 56 ; CHECK-NEXT: vxorpd %xmm1, %xmm1, %xmm1 57 ; CHECK-NEXT: vsubsd %xmm0, %xmm1, %xmm0 58 ; CHECK-NEXT: callq sin 59 ; CHECK-NEXT: vxorpd {{.*}}(%rip), %xmm0, %xmm0 60 ; CHECK-NEXT: popq %rax 61 ; CHECK-NEXT: retq 62 %f = fsub double 0.0, %e 63 %g = call double @sin(double %f) readonly 64 %h = fsub nsz double 0.0, %g 65 ret double %h 66 } 67 68 ; The 2nd negate is strict, so we can't kill it. It becomes an add of zero instead. 69 70 define double @semi_strict2(double %e) nounwind { 71 ; CHECK-LABEL: semi_strict2: 72 ; CHECK: # %bb.0: 73 ; CHECK-NEXT: pushq %rax 74 ; CHECK-NEXT: callq sin 75 ; CHECK-NEXT: vxorpd %xmm1, %xmm1, %xmm1 76 ; CHECK-NEXT: vaddsd %xmm1, %xmm0, %xmm0 77 ; CHECK-NEXT: popq %rax 78 ; CHECK-NEXT: retq 79 %f = fsub nsz double 0.0, %e 80 %g = call double @sin(double %f) readonly 81 %h = fsub double 0.0, %g 82 ret double %h 83 } 84 85 ; FIXME: 86 ; Auto-upgrade function attribute to IR-level fast-math-flags. 87 88 define double @fn_attr(double %e) nounwind #0 { 89 ; CHECK-LABEL: fn_attr: 90 ; CHECK: # %bb.0: 91 ; CHECK-NEXT: jmp sin # TAILCALL 92 %f = fsub double 0.0, %e 93 %g = call double @sin(double %f) readonly 94 %h = fsub double 0.0, %g 95 ret double %h 96 } 97 98 attributes #0 = { "unsafe-fp-math"="true" "no-signed-zeros-fp-math"="true" } 99 100