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 4declare double @sin(double %f) 5 6; When the subs are strict, they can't be removed because of signed zero. 7 8define 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@PLT 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 28define double @fast(double %e) nounwind { 29; CHECK-LABEL: fast: 30; CHECK: # %bb.0: 31; CHECK-NEXT: jmp sin@PLT # 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 40define double @nsz(double %e) nounwind { 41; CHECK-LABEL: nsz: 42; CHECK: # %bb.0: 43; CHECK-NEXT: jmp sin@PLT # 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 52define 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@PLT 59; CHECK-NEXT: vxorpd {{\.?LCPI[0-9]+_[0-9]+}}(%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 70define 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@PLT 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 88define double @fn_attr(double %e) nounwind #0 { 89; CHECK-LABEL: fn_attr: 90; CHECK: # %bb.0: 91; CHECK-NEXT: jmp sin@PLT # 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 98attributes #0 = { "unsafe-fp-math"="true" "no-signed-zeros-fp-math"="true" } 99 100