| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt < %s -passes=instcombine -S | FileCheck %s |
| |
| declare double @cosh(double) |
| declare float @coshf(float) |
| declare fp128 @coshl(fp128) |
| |
| declare double @sinh(double) |
| declare float @sinhf(float) |
| declare fp128 @sinhl(fp128) |
| |
| declare double @tanh(double) |
| declare float @tanhf(float) |
| declare fp128 @tanhl(fp128) |
| |
| declare void @use(double) |
| |
| ; cosh(-x) -> cosh(x) |
| |
| define double @cosh_negated_arg(double %x) { |
| ; CHECK-LABEL: @cosh_negated_arg( |
| ; CHECK-NEXT: [[COSH:%.*]] = call double @cosh(double [[X:%.*]]) |
| ; CHECK-NEXT: ret double [[COSH]] |
| ; |
| %neg = fneg double %x |
| %r = call double @cosh(double %neg) |
| ret double %r |
| } |
| |
| define double @cosh_fsub_negated_arg(double %x) { |
| ; CHECK-LABEL: @cosh_fsub_negated_arg( |
| ; CHECK-NEXT: [[COSH:%.*]] = call double @cosh(double [[X:%.*]]) |
| ; CHECK-NEXT: ret double [[COSH]] |
| ; |
| %neg = fsub double -0.0, %x |
| %r = call double @cosh(double %neg) |
| ret double %r |
| } |
| |
| define float @coshf_negated_arg(float %x) { |
| ; CHECK-LABEL: @coshf_negated_arg( |
| ; CHECK-NEXT: [[COSH:%.*]] = call float @coshf(float [[X:%.*]]) |
| ; CHECK-NEXT: ret float [[COSH]] |
| ; |
| %neg = fneg float %x |
| %r = call float @coshf(float %neg) |
| ret float %r |
| } |
| |
| define fp128 @coshl_negated_arg(fp128 %x) { |
| ; CHECK-LABEL: @coshl_negated_arg( |
| ; CHECK-NEXT: [[COSH:%.*]] = call fp128 @coshl(fp128 [[X:%.*]]) |
| ; CHECK-NEXT: ret fp128 [[COSH]] |
| ; |
| %neg = fneg fp128 %x |
| %r = call fp128 @coshl(fp128 %neg) |
| ret fp128 %r |
| } |
| |
| ; cosh(fabs(x)) -> cosh(x) |
| |
| define double @cosh_fabs_arg(double %x) { |
| ; CHECK-LABEL: @cosh_fabs_arg( |
| ; CHECK-NEXT: [[COSH:%.*]] = call double @cosh(double [[X:%.*]]) |
| ; CHECK-NEXT: ret double [[COSH]] |
| ; |
| %fabs = call double @llvm.fabs.f64(double %x) |
| %r = call double @cosh(double %fabs) |
| ret double %r |
| } |
| |
| declare double @llvm.fabs.f64(double) |
| |
| ; sinh(-x) -> -sinh(x) |
| |
| define double @sinh_negated_arg(double %x) { |
| ; CHECK-LABEL: @sinh_negated_arg( |
| ; CHECK-NEXT: [[R:%.*]] = call double @sinh(double [[R2:%.*]]) |
| ; CHECK-NEXT: [[R1:%.*]] = fneg double [[R]] |
| ; CHECK-NEXT: ret double [[R1]] |
| ; |
| %neg = fneg double %x |
| %r = call double @sinh(double %neg) |
| ret double %r |
| } |
| |
| define double @sinh_fsub_negated_arg(double %x) { |
| ; CHECK-LABEL: @sinh_fsub_negated_arg( |
| ; CHECK-NEXT: [[R:%.*]] = call double @sinh(double [[R2:%.*]]) |
| ; CHECK-NEXT: [[R1:%.*]] = fneg double [[R]] |
| ; CHECK-NEXT: ret double [[R1]] |
| ; |
| %neg = fsub double -0.0, %x |
| %r = call double @sinh(double %neg) |
| ret double %r |
| } |
| |
| define float @sinhf_negated_arg(float %x) { |
| ; CHECK-LABEL: @sinhf_negated_arg( |
| ; CHECK-NEXT: [[R:%.*]] = call float @sinhf(float [[R2:%.*]]) |
| ; CHECK-NEXT: [[R1:%.*]] = fneg float [[R]] |
| ; CHECK-NEXT: ret float [[R1]] |
| ; |
| %neg = fneg float %x |
| %r = call float @sinhf(float %neg) |
| ret float %r |
| } |
| |
| define fp128 @sinhl_negated_arg(fp128 %x) { |
| ; CHECK-LABEL: @sinhl_negated_arg( |
| ; CHECK-NEXT: [[R:%.*]] = call fp128 @sinhl(fp128 [[R2:%.*]]) |
| ; CHECK-NEXT: [[R1:%.*]] = fneg fp128 [[R]] |
| ; CHECK-NEXT: ret fp128 [[R1]] |
| ; |
| %neg = fneg fp128 %x |
| %r = call fp128 @sinhl(fp128 %neg) |
| ret fp128 %r |
| } |
| |
| ; -sinh(-x) -> sinh(x) |
| |
| define double @neg_sinh_negated_arg(double %x) { |
| ; CHECK-LABEL: @neg_sinh_negated_arg( |
| ; CHECK-NEXT: [[TMP1:%.*]] = call double @sinh(double [[X:%.*]]) |
| ; CHECK-NEXT: ret double [[TMP1]] |
| ; |
| %neg = fneg double %x |
| %r = call double @sinh(double %neg) |
| %rn = fneg double %r |
| ret double %rn |
| } |
| |
| ; sinh(-x) not folded when fneg has multiple uses |
| |
| define double @sinh_negated_arg_extra_use(double %x) { |
| ; CHECK-LABEL: @sinh_negated_arg_extra_use( |
| ; CHECK-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]] |
| ; CHECK-NEXT: [[R:%.*]] = call double @sinh(double [[NEG]]) |
| ; CHECK-NEXT: call void @use(double [[NEG]]) |
| ; CHECK-NEXT: ret double [[R]] |
| ; |
| %neg = fneg double %x |
| %r = call double @sinh(double %neg) |
| call void @use(double %neg) |
| ret double %r |
| } |
| |
| ; tanh(-x) -> -tanh(x) |
| |
| define double @tanh_negated_arg(double %x) { |
| ; CHECK-LABEL: @tanh_negated_arg( |
| ; CHECK-NEXT: [[R:%.*]] = call double @tanh(double [[R2:%.*]]) |
| ; CHECK-NEXT: [[R1:%.*]] = fneg double [[R]] |
| ; CHECK-NEXT: ret double [[R1]] |
| ; |
| %neg = fneg double %x |
| %r = call double @tanh(double %neg) |
| ret double %r |
| } |
| |
| define double @tanh_fsub_negated_arg(double %x) { |
| ; CHECK-LABEL: @tanh_fsub_negated_arg( |
| ; CHECK-NEXT: [[R:%.*]] = call double @tanh(double [[R2:%.*]]) |
| ; CHECK-NEXT: [[R1:%.*]] = fneg double [[R]] |
| ; CHECK-NEXT: ret double [[R1]] |
| ; |
| %neg = fsub double -0.0, %x |
| %r = call double @tanh(double %neg) |
| ret double %r |
| } |
| |
| define float @tanhf_negated_arg(float %x) { |
| ; CHECK-LABEL: @tanhf_negated_arg( |
| ; CHECK-NEXT: [[R:%.*]] = call float @tanhf(float [[R2:%.*]]) |
| ; CHECK-NEXT: [[R1:%.*]] = fneg float [[R]] |
| ; CHECK-NEXT: ret float [[R1]] |
| ; |
| %neg = fneg float %x |
| %r = call float @tanhf(float %neg) |
| ret float %r |
| } |
| |
| define fp128 @tanhl_negated_arg(fp128 %x) { |
| ; CHECK-LABEL: @tanhl_negated_arg( |
| ; CHECK-NEXT: [[R:%.*]] = call fp128 @tanhl(fp128 [[R2:%.*]]) |
| ; CHECK-NEXT: [[R1:%.*]] = fneg fp128 [[R]] |
| ; CHECK-NEXT: ret fp128 [[R1]] |
| ; |
| %neg = fneg fp128 %x |
| %r = call fp128 @tanhl(fp128 %neg) |
| ret fp128 %r |
| } |
| |
| ; -tanh(-x) -> tanh(x) |
| |
| define double @neg_tanh_negated_arg(double %x) { |
| ; CHECK-LABEL: @neg_tanh_negated_arg( |
| ; CHECK-NEXT: [[TMP1:%.*]] = call double @tanh(double [[X:%.*]]) |
| ; CHECK-NEXT: ret double [[TMP1]] |
| ; |
| %neg = fneg double %x |
| %r = call double @tanh(double %neg) |
| %rn = fneg double %r |
| ret double %rn |
| } |