mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
24a623a765
Summary: Rewrite the fsub-0.0 idiom to fneg and always emit fneg for fp negation. This also extends the scalarization cost in instcombine for unary operators to result in the same IR rewrites for fneg as for the idiom. Reviewed By: cameron.mcinally Differential Revision: https://reviews.llvm.org/D75467
338 lines
10 KiB
LLVM
338 lines
10 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -instcombine -S | FileCheck %s --check-prefixes=ANY,NO-FLOAT-SHRINK
|
|
; RUN: opt < %s -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_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: [[TMP2:%.*]] = fneg double [[TMP1]]
|
|
; ANY-NEXT: ret double [[TMP2]]
|
|
;
|
|
%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: [[TMP2:%.*]] = fneg double [[TMP1]]
|
|
; ANY-NEXT: ret double [[TMP2]]
|
|
;
|
|
%neg = fneg double %x
|
|
%r = 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: [[TMP2:%.*]] = fneg float [[TMP1]]
|
|
; ANY-NEXT: ret float [[TMP2]]
|
|
;
|
|
%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: [[TMP2:%.*]] = fneg float [[TMP1]]
|
|
; ANY-NEXT: ret float [[TMP2]]
|
|
;
|
|
%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: [[TMP2:%.*]] = fneg nnan afn float [[TMP1]]
|
|
; ANY-NEXT: ret float [[TMP2]]
|
|
;
|
|
%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: [[TMP2:%.*]] = fneg nnan afn float [[TMP1]]
|
|
; ANY-NEXT: ret float [[TMP2]]
|
|
;
|
|
%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: [[TMP2:%.*]] = fneg double [[TMP1]]
|
|
; ANY-NEXT: ret double [[TMP2]]
|
|
;
|
|
%neg = fsub double -0.0, %x
|
|
%r = 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: [[TMP2:%.*]] = fneg double [[TMP1]]
|
|
; ANY-NEXT: ret double [[TMP2]]
|
|
;
|
|
%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: [[TMP2:%.*]] = fneg fp128 [[TMP1]]
|
|
; ANY-NEXT: ret fp128 [[TMP2]]
|
|
;
|
|
%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: [[TMP2:%.*]] = fneg fp128 [[TMP1]]
|
|
; ANY-NEXT: ret fp128 [[TMP2]]
|
|
;
|
|
%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
|
|
}
|