| ; 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) |
| |
| ; 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 |
| } |
| |
| ; 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 |
| } |