llvm.org GIT mirror llvm / 071eccb
SimplifyLibCalls: Remove incorrect optimization of fabs fabs(x * x) is not generally safe to assume x is positive if x is a NaN. This is also less general than it could be, so this will be replaced with a transformation on the intrinsic. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@291359 91177308-0d34-0410-b5e6-96231b3b80d8 Matt Arsenault 2 years ago
3 changed file(s) with 40 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
11881188
11891189 Value *LibCallSimplifier::optimizeFabs(CallInst *CI, IRBuilder<> &B) {
11901190 Function *Callee = CI->getCalledFunction();
1191 Value *Ret = nullptr;
11921191 StringRef Name = Callee->getName();
11931192 if (Name == "fabs" && hasFloatVersion(Name))
1194 Ret = optimizeUnaryDoubleFP(CI, B, false);
1195
1196 Value *Op = CI->getArgOperand(0);
1197 if (Instruction *I = dyn_cast(Op)) {
1198 // Fold fabs(x * x) -> x * x; any squared FP value must already be positive.
1199 if (I->getOpcode() == Instruction::FMul)
1200 if (I->getOperand(0) == I->getOperand(1))
1201 return Op;
1202 }
1203 return Ret;
1193 return optimizeUnaryDoubleFP(CI, B, false);
1194
1195 return nullptr;
12041196 }
12051197
12061198 Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilder<> &B) {
1212
1313 ; CHECK-LABEL: square_fabs_call_f32(
1414 ; CHECK-NEXT: %mul = fmul float %x, %x
15 ; CHECK-NEXT: ret float %mul
15 ; CHECK-NEXT: %fabsf = tail call float @fabsf(float %mul)
16 ; CHECK-NEXT: ret float %fabsf
1617 }
1718
1819 define double @square_fabs_call_f64(double %x) {
2223
2324 ; CHECK-LABEL: square_fabs_call_f64(
2425 ; CHECK-NEXT: %mul = fmul double %x, %x
25 ; CHECK-NEXT: ret double %mul
26 ; CHECK-NEXT: %fabs = tail call double @fabs(double %mul)
27 ; CHECK-NEXT: ret double %fabs
2628 }
2729
2830 define fp128 @square_fabs_call_f128(fp128 %x) {
3234
3335 ; CHECK-LABEL: square_fabs_call_f128(
3436 ; CHECK-NEXT: %mul = fmul fp128 %x, %x
35 ; CHECK-NEXT: ret fp128 %mul
37 ; CHECK-NEXT: %fabsl = tail call fp128 @fabsl(fp128 %mul)
38 ; CHECK-NEXT: ret fp128 %fabsl
3639 }
3740
38 ; Make sure all intrinsic calls are eliminated when the input is known positive.
41 ; Make sure all intrinsic calls are eliminated when the input is known
42 ; positive.
3943
4044 declare float @llvm.fabs.f32(float)
4145 declare double @llvm.fabs.f64(double)
4246 declare fp128 @llvm.fabs.f128(fp128)
4347
48 ; The fabs cannot be eliminated because %x may be a NaN
4449 define float @square_fabs_intrinsic_f32(float %x) {
4550 %mul = fmul float %x, %x
4651 %fabsf = tail call float @llvm.fabs.f32(float %mul)
4853
4954 ; CHECK-LABEL: square_fabs_intrinsic_f32(
5055 ; CHECK-NEXT: %mul = fmul float %x, %x
51 ; CHECK-NEXT: ret float %mul
56 ; CHECK-NEXT: %fabsf = tail call float @llvm.fabs.f32(float %mul)
57 ; CHECK-NEXT: ret float %fabsf
5258 }
5359
5460 define double @square_fabs_intrinsic_f64(double %x) {
5864
5965 ; CHECK-LABEL: square_fabs_intrinsic_f64(
6066 ; CHECK-NEXT: %mul = fmul double %x, %x
61 ; CHECK-NEXT: ret double %mul
67 ; CHECK-NEXT: %fabs = tail call double @llvm.fabs.f64(double %mul)
68 ; CHECK-NEXT: ret double %fabs
6269 }
6370
6471 define fp128 @square_fabs_intrinsic_f128(fp128 %x) {
6875
6976 ; CHECK-LABEL: square_fabs_intrinsic_f128(
7077 ; CHECK-NEXT: %mul = fmul fp128 %x, %x
71 ; CHECK-NEXT: ret fp128 %mul
78 ; CHECK-NEXT: %fabsl = tail call fp128 @llvm.fabs.f128(fp128 %mul)
79 ; CHECK-NEXT: ret fp128 %fabsl
80 }
81
82 ; TODO: This should be able to elimnated the fabs
83 define float @square_nnan_fabs_intrinsic_f32(float %x) {
84 %mul = fmul nnan float %x, %x
85 %fabsf = call float @llvm.fabs.f32(float %mul)
86 ret float %fabsf
87
88 ; CHECK-LABEL: square_nnan_fabs_intrinsic_f32(
89 ; CHECK-NEXT: %mul = fmul nnan float %x, %x
90 ; CHECK-NEXT: %fabsf = call float @llvm.fabs.f32(float %mul)
91 ; CHECK-NEXT: ret float %fabsf
7292 }
7393
7494 ; Shrinking a library call to a smaller type should not be inhibited by nor inhibit the square optimization.
81101 ret float %trunc
82102
83103 ; CHECK-LABEL: square_fabs_shrink_call1(
84 ; CHECK-NEXT: %trunc = fmul float %x, %x
104 ; CHECK-NEXT: %ext = fpext float %x to double
105 ; CHECK-NEXT: %sq = fmul double %ext, %ext
106 ; CHECK-NEXT: call double @fabs(double %sq)
107 ; CHECK-NEXT: %trunc = fptrunc double %fabs to float
85108 ; CHECK-NEXT: ret float %trunc
86109 }
87110
94117
95118 ; CHECK-LABEL: square_fabs_shrink_call2(
96119 ; CHECK-NEXT: %sq = fmul float %x, %x
97 ; CHECK-NEXT: ret float %sq
120 ; CHECK-NEXT: %fabsf = call float @fabsf(float %sq)
121 ; CHECK-NEXT: ret float %fabsf
98122 }
99123
100124 ; CHECK-LABEL: @fabs_select_constant_negative_positive(
671671
672672 ; CHECK-LABEL: sqrt_intrinsic_arg_4th(
673673 ; CHECK-NEXT: %mul = fmul fast double %x, %x
674 ; CHECK-NEXT: ret double %mul
674 ; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %mul)
675 ; CHECK-NEXT: ret double %fabs
675676 }
676677
677678 define double @sqrt_intrinsic_arg_5th(double %x) {
683684
684685 ; CHECK-LABEL: sqrt_intrinsic_arg_5th(
685686 ; CHECK-NEXT: %mul = fmul fast double %x, %x
687 ; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %mul)
686688 ; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %x)
687 ; CHECK-NEXT: %1 = fmul fast double %mul, %sqrt1
689 ; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1
688690 ; CHECK-NEXT: ret double %1
689691 }
690692