llvm.org GIT mirror llvm / 1d4f2b0
[SimplifyLibCalls] Inline calls to cabs when it's safe to do so When unsafe algerbra is allowed calls to cabs(r) can be replaced by: sqrt(creal(r)*creal(r) + cimag(r)*cimag(r)) Patch by Paul Walker, thanks! Differential Revision: https://reviews.llvm.org/D40069 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@320901 91177308-0d34-0410-b5e6-96231b3b80d8 Hal Finkel 2 years ago
7 changed file(s) with 192 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
456456 /// void bzero(void *s, size_t n);
457457 TLI_DEFINE_ENUM_INTERNAL(bzero)
458458 TLI_DEFINE_STRING_INTERNAL("bzero")
459 /// double cabs(double complex z)
460 TLI_DEFINE_ENUM_INTERNAL(cabs)
461 TLI_DEFINE_STRING_INTERNAL("cabs")
462 /// float cabs(float complex z)
463 TLI_DEFINE_ENUM_INTERNAL(cabsf)
464 TLI_DEFINE_STRING_INTERNAL("cabsf")
465 /// long double cabs(long double complex z)
466 TLI_DEFINE_ENUM_INTERNAL(cabsl)
467 TLI_DEFINE_STRING_INTERNAL("cabsl")
459468 /// void *calloc(size_t count, size_t size);
460469 TLI_DEFINE_ENUM_INTERNAL(calloc)
461470 TLI_DEFINE_STRING_INTERNAL("calloc")
128128 Value *optimizeStringMemoryLibCall(CallInst *CI, IRBuilder<> &B);
129129
130130 // Math Library Optimizations
131 Value *optimizeCAbs(CallInst *CI, IRBuilder<> &B);
131132 Value *optimizeCos(CallInst *CI, IRBuilder<> &B);
132133 Value *optimizePow(CallInst *CI, IRBuilder<> &B);
133134 Value *replacePowWithSqrt(CallInst *Pow, IRBuilder<> &B);
181181 TLI.setUnavailable(LibFunc_atanh);
182182 TLI.setUnavailable(LibFunc_atanhf);
183183 TLI.setUnavailable(LibFunc_atanhl);
184 TLI.setUnavailable(LibFunc_cabs);
185 TLI.setUnavailable(LibFunc_cabsf);
186 TLI.setUnavailable(LibFunc_cabsl);
184187 TLI.setUnavailable(LibFunc_cbrt);
185188 TLI.setUnavailable(LibFunc_cbrtf);
186189 TLI.setUnavailable(LibFunc_cbrtl);
12661269 return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() &&
12671270 FTy.getReturnType()->isIntegerTy());
12681271
1272 case LibFunc_cabs:
1273 case LibFunc_cabsf:
1274 case LibFunc_cabsl: {
1275 Type* RetTy = FTy.getReturnType();
1276 if (!RetTy->isFloatingPointTy())
1277 return false;
1278
1279 // NOTE: These prototypes are target specific and currently support
1280 // "complex" passed as an array or discrete real & imaginary parameters.
1281 // Add other calling conventions to enable libcall optimizations.
1282 if (NumParams == 1)
1283 return (FTy.getParamType(0)->isArrayTy() &&
1284 FTy.getParamType(0)->getArrayNumElements() == 2 &&
1285 FTy.getParamType(0)->getArrayElementType() == RetTy);
1286 else if (NumParams == 2)
1287 return (FTy.getParamType(0) == RetTy && FTy.getParamType(1) == RetTy);
1288 else
1289 return false;
1290 }
12691291 case LibFunc::NumLibFuncs:
12701292 break;
12711293 }
10301030 Value *V = emitBinaryFloatFnCall(V1, V2, Callee->getName(), B,
10311031 Callee->getAttributes());
10321032 return B.CreateFPExt(V, B.getDoubleTy());
1033 }
1034
1035 // cabs(z) -> sqrt((creal(z)*creal(z)) + (cimag(z)*cimag(z)))
1036 Value *LibCallSimplifier::optimizeCAbs(CallInst *CI, IRBuilder<> &B) {
1037 if (!CI->isFast())
1038 return nullptr;
1039
1040 // Propagate fast-math flags from the existing call to new instructions.
1041 IRBuilder<>::FastMathFlagGuard Guard(B);
1042 B.setFastMathFlags(CI->getFastMathFlags());
1043
1044 Value *Real, *Imag;
1045 if (CI->getNumArgOperands() == 1) {
1046 Value *Op = CI->getArgOperand(0);
1047 assert(Op->getType()->isArrayTy() && "Unexpected signature for cabs!");
1048 Real = B.CreateExtractValue(Op, 0, "real");
1049 Imag = B.CreateExtractValue(Op, 1, "imag");
1050 } else {
1051 assert(CI->getNumArgOperands() == 2 && "Unexpected signature for cabs!");
1052 Real = CI->getArgOperand(0);
1053 Imag = CI->getArgOperand(1);
1054 }
1055
1056 Value *RealReal = B.CreateFMul(Real, Real);
1057 Value *ImagImag = B.CreateFMul(Imag, Imag);
1058
1059 Function *FSqrt = Intrinsic::getDeclaration(CI->getModule(), Intrinsic::sqrt,
1060 CI->getType());
1061 return B.CreateCall(FSqrt, B.CreateFAdd(RealReal, ImagImag), "cabs");
10331062 }
10341063
10351064 Value *LibCallSimplifier::optimizeCos(CallInst *CI, IRBuilder<> &B) {
21612190 case LibFunc_fmax:
21622191 case LibFunc_fmaxl:
21632192 return optimizeFMinFMax(CI, Builder);
2193 case LibFunc_cabs:
2194 case LibFunc_cabsf:
2195 case LibFunc_cabsl:
2196 return optimizeCAbs(CI, Builder);
21642197 default:
21652198 return nullptr;
21662199 }
0 ; RUN: opt < %s -instcombine -S | FileCheck %s
1
2 define double @std_cabs([2 x double] %z) {
3 ; CHECK-LABEL: define double @std_cabs(
4 ; CHECK: tail call double @cabs(
5 %call = tail call double @cabs([2 x double] %z)
6 ret double %call
7 }
8
9 define float @std_cabsf([2 x float] %z) {
10 ; CHECK-LABEL: define float @std_cabsf(
11 ; CHECK: tail call float @cabsf(
12 %call = tail call float @cabsf([2 x float] %z)
13 ret float %call
14 }
15
16 define fp128 @std_cabsl([2 x fp128] %z) {
17 ; CHECK-LABEL: define fp128 @std_cabsl(
18 ; CHECK: tail call fp128 @cabsl(
19 %call = tail call fp128 @cabsl([2 x fp128] %z)
20 ret fp128 %call
21 }
22
23 define double @fast_cabs([2 x double] %z) {
24 ; CHECK-LABEL: define double @fast_cabs(
25 ; CHECK: %real = extractvalue [2 x double] %z, 0
26 ; CHECK: %imag = extractvalue [2 x double] %z, 1
27 ; CHECK: %1 = fmul fast double %real, %real
28 ; CHECK: %2 = fmul fast double %imag, %imag
29 ; CHECK: %3 = fadd fast double %1, %2
30 ; CHECK: %cabs = call fast double @llvm.sqrt.f64(double %3)
31 ; CHECK: ret double %cabs
32 %call = tail call fast double @cabs([2 x double] %z)
33 ret double %call
34 }
35
36 define float @fast_cabsf([2 x float] %z) {
37 ; CHECK-LABEL: define float @fast_cabsf(
38 ; CHECK: %real = extractvalue [2 x float] %z, 0
39 ; CHECK: %imag = extractvalue [2 x float] %z, 1
40 ; CHECK: %1 = fmul fast float %real, %real
41 ; CHECK: %2 = fmul fast float %imag, %imag
42 ; CHECK: %3 = fadd fast float %1, %2
43 ; CHECK: %cabs = call fast float @llvm.sqrt.f32(float %3)
44 ; CHECK: ret float %cabs
45 %call = tail call fast float @cabsf([2 x float] %z)
46 ret float %call
47 }
48
49 define fp128 @fast_cabsl([2 x fp128] %z) {
50 ; CHECK-LABEL: define fp128 @fast_cabsl(
51 ; CHECK: %real = extractvalue [2 x fp128] %z, 0
52 ; CHECK: %imag = extractvalue [2 x fp128] %z, 1
53 ; CHECK: %1 = fmul fast fp128 %real, %real
54 ; CHECK: %2 = fmul fast fp128 %imag, %imag
55 ; CHECK: %3 = fadd fast fp128 %1, %2
56 ; CHECK: %cabs = call fast fp128 @llvm.sqrt.f128(fp128 %3)
57 ; CHECK: ret fp128 %cabs
58 %call = tail call fast fp128 @cabsl([2 x fp128] %z)
59 ret fp128 %call
60 }
61
62 declare double @cabs([2 x double])
63 declare float @cabsf([2 x float])
64 declare fp128 @cabsl([2 x fp128])
0 ; RUN: opt < %s -instcombine -S | FileCheck %s
1
2 define double @std_cabs(double %real, double %imag) {
3 ; CHECK-LABEL: define double @std_cabs(
4 ; CHECK: tail call double @cabs(
5 %call = tail call double @cabs(double %real, double %imag)
6 ret double %call
7 }
8
9 define float @std_cabsf(float %real, float %imag) {
10 ; CHECK-LABEL: define float @std_cabsf(
11 ; CHECK: tail call float @cabsf(
12 %call = tail call float @cabsf(float %real, float %imag)
13 ret float %call
14 }
15
16 define fp128 @std_cabsl(fp128 %real, fp128 %imag) {
17 ; CHECK-LABEL: define fp128 @std_cabsl(
18 ; CHECK: tail call fp128 @cabsl(
19 %call = tail call fp128 @cabsl(fp128 %real, fp128 %imag)
20 ret fp128 %call
21 }
22
23 define double @fast_cabs(double %real, double %imag) {
24 ; CHECK-LABEL: define double @fast_cabs(
25 ; CHECK: %1 = fmul fast double %real, %real
26 ; CHECK: %2 = fmul fast double %imag, %imag
27 ; CHECK: %3 = fadd fast double %1, %2
28 ; CHECK: %cabs = call fast double @llvm.sqrt.f64(double %3)
29 ; CHECK: ret double %cabs
30 %call = tail call fast double @cabs(double %real, double %imag)
31 ret double %call
32 }
33
34 define float @fast_cabsf(float %real, float %imag) {
35 ; CHECK-LABEL: define float @fast_cabsf(
36 ; CHECK: %1 = fmul fast float %real, %real
37 ; CHECK: %2 = fmul fast float %imag, %imag
38 ; CHECK: %3 = fadd fast float %1, %2
39 ; CHECK: %cabs = call fast float @llvm.sqrt.f32(float %3)
40 ; CHECK: ret float %cabs
41 %call = tail call fast float @cabsf(float %real, float %imag)
42 ret float %call
43 }
44
45 define fp128 @fast_cabsl(fp128 %real, fp128 %imag) {
46 ; CHECK-LABEL: define fp128 @fast_cabsl(
47 ; CHECK: %1 = fmul fast fp128 %real, %real
48 ; CHECK: %2 = fmul fast fp128 %imag, %imag
49 ; CHECK: %3 = fadd fast fp128 %1, %2
50 ; CHECK: %cabs = call fast fp128 @llvm.sqrt.f128(fp128 %3)
51 ; CHECK: ret fp128 %cabs
52 %call = tail call fast fp128 @cabsl(fp128 %real, fp128 %imag)
53 ret fp128 %call
54 }
55
56 declare double @cabs(double %real, double %imag)
57 declare float @cabsf(float %real, float %imag)
58 declare fp128 @cabsl(fp128 %real, fp128 %imag)
130130 "declare double @copysign(double, double)\n"
131131 "declare float @copysignf(float, float)\n"
132132 "declare x86_fp80 @copysignl(x86_fp80, x86_fp80)\n"
133 "declare double @cabs([2 x double])\n"
134 "declare float @cabsf([2 x float])\n"
135 "declare x86_fp80 @cabsl([2 x x86_fp80])\n"
133136 "declare double @cos(double)\n"
134137 "declare float @cosf(float)\n"
135138 "declare double @cosh(double)\n"