; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instcombine -S | FileCheck %s --check-prefixes=ANY,NO-FLOAT-SHRINK
; RUN: opt < %s -passes=instcombine -enable-double-float-shrink -S | FileCheck %s --check-prefixes=ANY,DO-FLOAT-SHRINK
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
declare double @cos(double)
declare double @llvm.cos.f64(double)
declare float @cosf(float)
declare float @llvm.cos.f32(float)
declare double @sin(double)
declare double @llvm.sin.f64(double)
declare float @sinf(float)
declare float @llvm.sin.f32(float)
declare double @tan(double)
declare fp128 @tanl(fp128)
declare double @fabs(double)
declare double @llvm.fabs.f64(double)
declare float @fabsf(float)
declare float @llvm.fabs.f32(float)
declare double @llvm.copysign(double, double)
declare float @llvm.copysign.f32(float, float)
; cos(-x) -> cos(x);
define double @cos_negated_arg(double %x) {
; ANY-LABEL: @cos_negated_arg(
; ANY-NEXT: [[COS:%.*]] = call double @cos(double [[X:%.*]])
; ANY-NEXT: ret double [[COS]]
;
%neg = fsub double -0.0, %x
%r = call double @cos(double %neg)
ret double %r
}
define double @cos_negated_arg_tail(double %x) {
; ANY-LABEL: @cos_negated_arg_tail(
; ANY-NEXT: [[COS:%.*]] = tail call double @cos(double [[X:%.*]])
; ANY-NEXT: ret double [[COS]]
;
%neg = fsub double -0.0, %x
%r = tail call double @cos(double %neg)
ret double %r
}
define double @cos_negated_arg_musttail(double %x) {
; ANY-LABEL: @cos_negated_arg_musttail(
; ANY-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]]
; ANY-NEXT: [[R:%.*]] = musttail call double @cos(double [[NEG]])
; ANY-NEXT: ret double [[R]]
;
%neg = fsub double -0.0, %x
%r = musttail call double @cos(double %neg)
ret double %r
}
define double @cos_unary_negated_arg(double %x) {
; ANY-LABEL: @cos_unary_negated_arg(
; ANY-NEXT: [[COS:%.*]] = call double @cos(double [[X:%.*]])
; ANY-NEXT: ret double [[COS]]
;
%neg = fneg double %x
%r = call double @cos(double %neg)
ret double %r
}
define float @cosf_negated_arg(float %x) {
; ANY-LABEL: @cosf_negated_arg(
; ANY-NEXT: [[COS:%.*]] = call float @cosf(float [[X:%.*]])
; ANY-NEXT: ret float [[COS]]
;
%neg = fsub float -0.0, %x
%r = call float @cosf(float %neg)
ret float %r
}
define float @cosf_unary_negated_arg(float %x) {
; ANY-LABEL: @cosf_unary_negated_arg(
; ANY-NEXT: [[COS:%.*]] = call float @cosf(float [[X:%.*]])
; ANY-NEXT: ret float [[COS]]
;
%neg = fneg float %x
%r = call float @cosf(float %neg)
ret float %r
}
define float @cosf_negated_arg_FMF(float %x) {
; ANY-LABEL: @cosf_negated_arg_FMF(
; ANY-NEXT: [[COS:%.*]] = call reassoc nnan float @cosf(float [[X:%.*]])
; ANY-NEXT: ret float [[COS]]
;
%neg = fsub float -0.0, %x
%r = call nnan reassoc float @cosf(float %neg)
ret float %r
}
define float @cosf_unary_negated_arg_FMF(float %x) {
; ANY-LABEL: @cosf_unary_negated_arg_FMF(
; ANY-NEXT: [[COS:%.*]] = call reassoc nnan float @cosf(float [[X:%.*]])
; ANY-NEXT: ret float [[COS]]
;
%neg = fneg float %x
%r = call nnan reassoc float @cosf(float %neg)
ret float %r
}
; cos(fabs(x)) -> cos(x)
define double @cos_unary_fabs_arg(double %x) {
; ANY-LABEL: @cos_unary_fabs_arg(
; ANY-NEXT: [[COS:%.*]] = call double @cos(double [[X:%.*]])
; ANY-NEXT: ret double [[COS]]
;
%fabs = tail call double @llvm.fabs.f64(double %x)
%r = call double @cos(double %fabs)
ret double %r
}
define float @cosf_unary_fabs_arg(float %x) {
; ANY-LABEL: @cosf_unary_fabs_arg(
; ANY-NEXT: [[COS:%.*]] = call float @cosf(float [[X:%.*]])
; ANY-NEXT: ret float [[COS]]
;
%fabs = tail call float @llvm.fabs.f32(float %x)
%r = call float @cosf(float %fabs)
ret float %r
}
define float @cosf_unary_fabs_arg_FMF(float %x) {
; ANY-LABEL: @cosf_unary_fabs_arg_FMF(
; ANY-NEXT: [[COS:%.*]] = call reassoc nnan float @cosf(float [[X:%.*]])
; ANY-NEXT: ret float [[COS]]
;
%fabs = tail call float @llvm.fabs.f32(float %x)
%r = call nnan reassoc float @cosf(float %fabs)
ret float %r
}
; cos(copysign(x, y)) -> cos(x)
define double @cos_copysign_arg(double %x, double %y) {
; ANY-LABEL: @cos_copysign_arg(
; ANY-NEXT: [[COS:%.*]] = call double @cos(double [[X:%.*]])
; ANY-NEXT: ret double [[COS]]
;
%copysign = tail call double @llvm.copysign(double %x, double %y)
%r = call double @cos(double %copysign)
ret double %r
}
define float @cosf_unary_copysign_arg(float %x) {
; ANY-LABEL: @cosf_unary_copysign_arg(
; ANY-NEXT: [[COS:%.*]] = call float @cosf(float [[X:%.*]])
; ANY-NEXT: ret float [[COS]]
;
%copysign = tail call float @llvm.copysign.f32(float %x, float 1.0)
%r = call float @cosf(float %copysign)
ret float %r
}
define float @cosf_copysign_arg_FMF(float %x, float %y) {
; ANY-LABEL: @cosf_copysign_arg_FMF(
; ANY-NEXT: [[COS:%.*]] = call reassoc nnan float @cosf(float [[X:%.*]])
; ANY-NEXT: ret float [[COS]]
;
%copysign = tail call float @llvm.copysign.f32(float %x, float %y)
%r = call nnan reassoc float @cosf(float %copysign)
ret float %r
}
; sin(-x) -> -sin(x);
define double @sin_negated_arg(double %x) {
; ANY-LABEL: @sin_negated_arg(
; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]])
; ANY-NEXT: [[R:%.*]] = fneg double [[TMP1]]
; ANY-NEXT: ret double [[R]]
;
%neg = fsub double -0.0, %x
%r = call double @sin(double %neg)
ret double %r
}
define double @sin_unary_negated_arg(double %x) {
; ANY-LABEL: @sin_unary_negated_arg(
; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]])
; ANY-NEXT: [[R:%.*]] = fneg double [[TMP1]]
; ANY-NEXT: ret double [[R]]
;
%neg = fneg double %x
%r = call double @sin(double %neg)
ret double %r
}
define double @sin_unary_negated_arg_musttail(double %x) {
; ANY-LABEL: @sin_unary_negated_arg_musttail(
; ANY-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]]
; ANY-NEXT: [[R:%.*]] = musttail call double @sin(double [[NEG]])
; ANY-NEXT: ret double [[R]]
;
%neg = fneg double %x
%r = musttail call double @sin(double %neg)
ret double %r
}
define float @sinf_negated_arg(float %x) {
; ANY-LABEL: @sinf_negated_arg(
; ANY-NEXT: [[TMP1:%.*]] = call float @sinf(float [[X:%.*]])
; ANY-NEXT: [[R:%.*]] = fneg float [[TMP1]]
; ANY-NEXT: ret float [[R]]
;
%neg = fsub float -0.0, %x
%r = call float @sinf(float %neg)
ret float %r
}
define float @sinf_unary_negated_arg(float %x) {
; ANY-LABEL: @sinf_unary_negated_arg(
; ANY-NEXT: [[TMP1:%.*]] = call float @sinf(float [[X:%.*]])
; ANY-NEXT: [[R:%.*]] = fneg float [[TMP1]]
; ANY-NEXT: ret float [[R]]
;
%neg = fneg float %x
%r = call float @sinf(float %neg)
ret float %r
}
define float @sinf_negated_arg_FMF(float %x) {
; ANY-LABEL: @sinf_negated_arg_FMF(
; ANY-NEXT: [[TMP1:%.*]] = call nnan afn float @sinf(float [[X:%.*]])
; ANY-NEXT: [[R:%.*]] = fneg nnan afn float [[TMP1]]
; ANY-NEXT: ret float [[R]]
;
%neg = fsub ninf float -0.0, %x
%r = call afn nnan float @sinf(float %neg)
ret float %r
}
define float @sinf_unary_negated_arg_FMF(float %x) {
; ANY-LABEL: @sinf_unary_negated_arg_FMF(
; ANY-NEXT: [[TMP1:%.*]] = call nnan afn float @sinf(float [[X:%.*]])
; ANY-NEXT: [[R:%.*]] = fneg nnan afn float [[TMP1]]
; ANY-NEXT: ret float [[R]]
;
%neg = fneg ninf float %x
%r = call afn nnan float @sinf(float %neg)
ret float %r
}
declare void @use(double)
define double @sin_negated_arg_extra_use(double %x) {
; ANY-LABEL: @sin_negated_arg_extra_use(
; ANY-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]]
; ANY-NEXT: [[R:%.*]] = call double @sin(double [[NEG]])
; ANY-NEXT: call void @use(double [[NEG]])
; ANY-NEXT: ret double [[R]]
;
%neg = fsub double -0.0, %x
%r = call double @sin(double %neg)
call void @use(double %neg)
ret double %r
}
define double @sin_unary_negated_arg_extra_use(double %x) {
; ANY-LABEL: @sin_unary_negated_arg_extra_use(
; ANY-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]]
; ANY-NEXT: [[R:%.*]] = call double @sin(double [[NEG]])
; ANY-NEXT: call void @use(double [[NEG]])
; ANY-NEXT: ret double [[R]]
;
%neg = fneg double %x
%r = call double @sin(double %neg)
call void @use(double %neg)
ret double %r
}
; -sin(-x) --> sin(x)
; PR38458: https://bugs.llvm.org/show_bug.cgi?id=38458
define double @neg_sin_negated_arg(double %x) {
; ANY-LABEL: @neg_sin_negated_arg(
; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]])
; ANY-NEXT: ret double [[TMP1]]
;
%neg = fsub double -0.0, %x
%r = call double @sin(double %neg)
%rn = fsub double -0.0, %r
ret double %rn
}
define double @unary_neg_sin_unary_negated_arg(double %x) {
; ANY-LABEL: @unary_neg_sin_unary_negated_arg(
; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]])
; ANY-NEXT: ret double [[TMP1]]
;
%neg = fneg double %x
%r = call double @sin(double %neg)
%rn = fneg double %r
ret double %rn
}
define double @neg_sin_unary_negated_arg(double %x) {
; ANY-LABEL: @neg_sin_unary_negated_arg(
; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]])
; ANY-NEXT: ret double [[TMP1]]
;
%neg = fsub double -0.0, %x
%r = call double @sin(double %neg)
%rn = fneg double %r
ret double %rn
}
define double @unary_neg_sin_negated_arg(double %x) {
; ANY-LABEL: @unary_neg_sin_negated_arg(
; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]])
; ANY-NEXT: ret double [[TMP1]]
;
%neg = fneg double %x
%r = call double @sin(double %neg)
%rn = fsub double -0.0, %r
ret double %rn
}
; tan(-x) -> -tan(x);
define double @tan_negated_arg(double %x) {
; ANY-LABEL: @tan_negated_arg(
; ANY-NEXT: [[TMP1:%.*]] = call double @tan(double [[X:%.*]])
; ANY-NEXT: [[R:%.*]] = fneg double [[TMP1]]
; ANY-NEXT: ret double [[R]]
;
%neg = fsub double -0.0, %x
%r = call double @tan(double %neg)
ret double %r
}
define double @tan_negated_arg_tail(double %x) {
; ANY-LABEL: @tan_negated_arg_tail(
; ANY-NEXT: [[TMP1:%.*]] = tail call double @tan(double [[X:%.*]])
; ANY-NEXT: [[R:%.*]] = fneg double [[TMP1]]
; ANY-NEXT: ret double [[R]]
;
%neg = fsub double -0.0, %x
%r = tail call double @tan(double %neg)
ret double %r
}
define double @tan_negated_arg_musttail(double %x) {
; ANY-LABEL: @tan_negated_arg_musttail(
; ANY-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]]
; ANY-NEXT: [[R:%.*]] = musttail call double @tan(double [[NEG]])
; ANY-NEXT: ret double [[R]]
;
%neg = fsub double -0.0, %x
%r = musttail call double @tan(double %neg)
ret double %r
}
define double @tan_unary_negated_arg(double %x) {
; ANY-LABEL: @tan_unary_negated_arg(
; ANY-NEXT: [[TMP1:%.*]] = call double @tan(double [[X:%.*]])
; ANY-NEXT: [[R:%.*]] = fneg double [[TMP1]]
; ANY-NEXT: ret double [[R]]
;
%neg = fneg double %x
%r = call double @tan(double %neg)
ret double %r
}
; tanl(-x) -> -tanl(x);
define fp128 @tanl_negated_arg(fp128 %x) {
; ANY-LABEL: @tanl_negated_arg(
; ANY-NEXT: [[TMP1:%.*]] = call fp128 @tanl(fp128 [[X:%.*]])
; ANY-NEXT: [[R:%.*]] = fneg fp128 [[TMP1]]
; ANY-NEXT: ret fp128 [[R]]
;
%neg = fsub fp128 0xL00000000000000008000000000000000, %x
%r = call fp128 @tanl(fp128 %neg)
ret fp128 %r
}
define fp128 @tanl_unary_negated_arg(fp128 %x) {
; ANY-LABEL: @tanl_unary_negated_arg(
; ANY-NEXT: [[TMP1:%.*]] = call fp128 @tanl(fp128 [[X:%.*]])
; ANY-NEXT: [[R:%.*]] = fneg fp128 [[TMP1]]
; ANY-NEXT: ret fp128 [[R]]
;
%neg = fneg fp128 %x
%r = call fp128 @tanl(fp128 %neg)
ret fp128 %r
}
define float @negated_and_shrinkable_libcall(float %f) {
; NO-FLOAT-SHRINK-LABEL: @negated_and_shrinkable_libcall(
; NO-FLOAT-SHRINK-NEXT: [[CONV1:%.*]] = fpext float [[F:%.*]] to double
; NO-FLOAT-SHRINK-NEXT: [[COS1:%.*]] = call double @cos(double [[CONV1]])
; NO-FLOAT-SHRINK-NEXT: [[CONV2:%.*]] = fptrunc double [[COS1]] to float
; NO-FLOAT-SHRINK-NEXT: ret float [[CONV2]]
;
; DO-FLOAT-SHRINK-LABEL: @negated_and_shrinkable_libcall(
; DO-FLOAT-SHRINK-NEXT: [[COSF:%.*]] = call float @cosf(float [[F:%.*]])
; DO-FLOAT-SHRINK-NEXT: ret float [[COSF]]
;
%conv1 = fpext float %f to double
%neg = fsub double -0.0, %conv1
%cos = call double @cos(double %neg)
%conv2 = fptrunc double %cos to float
ret float %conv2
}
define float @unary_negated_and_shrinkable_libcall(float %f) {
; NO-FLOAT-SHRINK-LABEL: @unary_negated_and_shrinkable_libcall(
; NO-FLOAT-SHRINK-NEXT: [[CONV1:%.*]] = fpext float [[F:%.*]] to double
; NO-FLOAT-SHRINK-NEXT: [[COS1:%.*]] = call double @cos(double [[CONV1]])
; NO-FLOAT-SHRINK-NEXT: [[CONV2:%.*]] = fptrunc double [[COS1]] to float
; NO-FLOAT-SHRINK-NEXT: ret float [[CONV2]]
;
; DO-FLOAT-SHRINK-LABEL: @unary_negated_and_shrinkable_libcall(
; DO-FLOAT-SHRINK-NEXT: [[COSF:%.*]] = call float @cosf(float [[F:%.*]])
; DO-FLOAT-SHRINK-NEXT: ret float [[COSF]]
;
%conv1 = fpext float %f to double
%neg = fneg double %conv1
%cos = call double @cos(double %neg)
%conv2 = fptrunc double %cos to float
ret float %conv2
}
; TODO: It was ok to shrink the libcall, so the intrinsic should shrink too?
define float @negated_and_shrinkable_intrinsic(float %f) {
; ANY-LABEL: @negated_and_shrinkable_intrinsic(
; ANY-NEXT: [[CONV1:%.*]] = fpext float [[F:%.*]] to double
; ANY-NEXT: [[COS:%.*]] = call double @llvm.cos.f64(double [[CONV1]])
; ANY-NEXT: [[CONV2:%.*]] = fptrunc double [[COS]] to float
; ANY-NEXT: ret float [[CONV2]]
;
%conv1 = fpext float %f to double
%neg = fsub double -0.0, %conv1
%cos = call double @llvm.cos.f64(double %neg)
%conv2 = fptrunc double %cos to float
ret float %conv2
}
define float @unary_negated_and_shrinkable_intrinsic(float %f) {
; ANY-LABEL: @unary_negated_and_shrinkable_intrinsic(
; ANY-NEXT: [[CONV1:%.*]] = fpext float [[F:%.*]] to double
; ANY-NEXT: [[COS:%.*]] = call double @llvm.cos.f64(double [[CONV1]])
; ANY-NEXT: [[CONV2:%.*]] = fptrunc double [[COS]] to float
; ANY-NEXT: ret float [[CONV2]]
;
%conv1 = fpext float %f to double
%neg = fneg double %conv1
%cos = call double @llvm.cos.f64(double %neg)
%conv2 = fptrunc double %cos to float
ret float %conv2
}