diff options
author | Evandro Menezes <e.menezes@samsung.com> | 2018-08-03 17:50:16 +0000 |
---|---|---|
committer | Evandro Menezes <e.menezes@samsung.com> | 2018-08-03 17:50:16 +0000 |
commit | 5aa217ac68cd9e4d21642dcbefb68b4a1301971d (patch) | |
tree | 79fa5e504905a401b0d23f72725a837358f62728 /llvm/lib/Transforms/Utils | |
parent | c7d3d34b98e9397fd24eb4b148987aad3311a880 (diff) | |
download | bcm5719-llvm-5aa217ac68cd9e4d21642dcbefb68b4a1301971d.tar.gz bcm5719-llvm-5aa217ac68cd9e4d21642dcbefb68b4a1301971d.zip |
[SLC] Refactor shrinking of functions (NFC)
Merge the helper functions for shrinking unary and binary functions into a
single one, while keeping all their functionality. Otherwise, NFC.
llvm-svn: 338905
Diffstat (limited to 'llvm/lib/Transforms/Utils')
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 127 |
1 files changed, 55 insertions, 72 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index bf92399dcf2..f378b0d4b1a 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -927,6 +927,20 @@ Value *LibCallSimplifier::optimizeRealloc(CallInst *CI, IRBuilder<> &B) { // Math Library Optimizations //===----------------------------------------------------------------------===// +// Replace a libcall \p CI with a call to intrinsic \p IID +static Value *replaceUnaryCall(CallInst *CI, IRBuilder<> &B, Intrinsic::ID IID) { + // Propagate fast-math flags from the existing call to the new call. + IRBuilder<>::FastMathFlagGuard Guard(B); + B.setFastMathFlags(CI->getFastMathFlags()); + + Module *M = CI->getModule(); + Value *V = CI->getArgOperand(0); + Function *F = Intrinsic::getDeclaration(M, IID, CI->getType()); + CallInst *NewCall = B.CreateCall(F, V); + NewCall->takeName(CI); + return NewCall; +} + /// Return a variant of Val with float type. /// Currently this works in two cases: If Val is an FPExtension of a float /// value to something bigger, simply return the operand. @@ -949,104 +963,73 @@ static Value *valueHasFloatPrecision(Value *Val) { return nullptr; } -/// Shrink double -> float for unary functions like 'floor'. -static Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilder<> &B, - bool CheckRetType) { - Function *Callee = CI->getCalledFunction(); - // We know this libcall has a valid prototype, but we don't know which. +/// Shrink double -> float functions. +static Value *optimizeDoubleFP(CallInst *CI, IRBuilder<> &B, + bool isBinary, bool doResultCheck = false) { if (!CI->getType()->isDoubleTy()) return nullptr; - if (CheckRetType) { - // Check if all the uses for function like 'sin' are converted to float. + // Check if all the uses of the function are converted to float. + if (doResultCheck) for (User *U : CI->users()) { FPTruncInst *Cast = dyn_cast<FPTruncInst>(U); if (!Cast || !Cast->getType()->isFloatTy()) return nullptr; } - } - // If this is something like 'floor((double)floatval)', convert to floorf. - Value *V = valueHasFloatPrecision(CI->getArgOperand(0)); - if (V == nullptr) + // If this is something like 'g((double) float)', convert to 'gf(float)'. + Value *V[2]; + V[0] = valueHasFloatPrecision(CI->getArgOperand(0)); + V[1] = isBinary ? valueHasFloatPrecision(CI->getArgOperand(1)) : nullptr; + if (!V[0] || (isBinary && !V[1])) return nullptr; // If call isn't an intrinsic, check that it isn't within a function with the - // same name as the float version of this call. - // - // e.g. inline float expf(float val) { return (float) exp((double) val); } + // same name as the float version of this call, otherwise the result is an + // infinite loop. For example, from MinGW-w64: // - // A similar such definition exists in the MinGW-w64 math.h header file which - // when compiled with -O2 -ffast-math causes the generation of infinite loops - // where expf is called. - if (!Callee->isIntrinsic()) { - const Function *F = CI->getFunction(); - StringRef FName = F->getName(); - StringRef CalleeName = Callee->getName(); - if ((FName.size() == (CalleeName.size() + 1)) && - (FName.back() == 'f') && - FName.startswith(CalleeName)) + // float expf(float val) { return (float) exp((double) val); } + Function *CalleeFn = CI->getCalledFunction(); + StringRef CalleeNm = CalleeFn->getName(); + AttributeList CalleeAt = CalleeFn->getAttributes(); + if (CalleeFn && !CalleeFn->isIntrinsic()) { + const Function *Fn = CI->getFunction(); + StringRef FnName = Fn->getName(); + if (FnName.back() == 'f' && + FnName.size() == (CalleeNm.size() + 1) && + FnName.startswith(CalleeNm)) return nullptr; } - // Propagate fast-math flags from the existing call to the new call. + // Propagate the math semantics from the current function to the new function. IRBuilder<>::FastMathFlagGuard Guard(B); B.setFastMathFlags(CI->getFastMathFlags()); - // floor((double)floatval) -> (double)floorf(floatval) - if (Callee->isIntrinsic()) { + // g((double) float) -> (double) gf(float) + Value *R; + if (CalleeFn->isIntrinsic()) { Module *M = CI->getModule(); - Intrinsic::ID IID = Callee->getIntrinsicID(); - Function *F = Intrinsic::getDeclaration(M, IID, B.getFloatTy()); - V = B.CreateCall(F, V); - } else { - // The call is a library call rather than an intrinsic. - V = emitUnaryFloatFnCall(V, Callee->getName(), B, Callee->getAttributes()); + Intrinsic::ID IID = CalleeFn->getIntrinsicID(); + Function *Fn = Intrinsic::getDeclaration(M, IID, B.getFloatTy()); + R = isBinary ? B.CreateCall(Fn, V) : B.CreateCall(Fn, V[0]); } + else + R = isBinary ? emitBinaryFloatFnCall(V[0], V[1], CalleeNm, B, CalleeAt) + : emitUnaryFloatFnCall(V[0], CalleeNm, B, CalleeAt); - return B.CreateFPExt(V, B.getDoubleTy()); + return B.CreateFPExt(R, B.getDoubleTy()); } -// Replace a libcall \p CI with a call to intrinsic \p IID -static Value *replaceUnaryCall(CallInst *CI, IRBuilder<> &B, Intrinsic::ID IID) { - // Propagate fast-math flags from the existing call to the new call. - IRBuilder<>::FastMathFlagGuard Guard(B); - B.setFastMathFlags(CI->getFastMathFlags()); - - Module *M = CI->getModule(); - Value *V = CI->getArgOperand(0); - Function *F = Intrinsic::getDeclaration(M, IID, CI->getType()); - CallInst *NewCall = B.CreateCall(F, V); - NewCall->takeName(CI); - return NewCall; +/// Shrink double -> float for unary functions. +static Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilder<> &B, + bool doResultCheck = false) { + return optimizeDoubleFP(CI, B, false, doResultCheck); } -/// Shrink double -> float for binary functions like 'fmin/fmax'. -static Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilder<> &B) { - Function *Callee = CI->getCalledFunction(); - // We know this libcall has a valid prototype, but we don't know which. - if (!CI->getType()->isDoubleTy()) - return nullptr; - - // If this is something like 'fmin((double)floatval1, (double)floatval2)', - // or fmin(1.0, (double)floatval), then we convert it to fminf. - Value *V1 = valueHasFloatPrecision(CI->getArgOperand(0)); - if (V1 == nullptr) - return nullptr; - Value *V2 = valueHasFloatPrecision(CI->getArgOperand(1)); - if (V2 == nullptr) - return nullptr; - - // Propagate fast-math flags from the existing call to the new call. - IRBuilder<>::FastMathFlagGuard Guard(B); - B.setFastMathFlags(CI->getFastMathFlags()); - - // fmin((double)floatval1, (double)floatval2) - // -> (double)fminf(floatval1, floatval2) - // TODO: Handle intrinsics in the same way as in optimizeUnaryDoubleFP(). - Value *V = emitBinaryFloatFnCall(V1, V2, Callee->getName(), B, - Callee->getAttributes()); - return B.CreateFPExt(V, B.getDoubleTy()); +/// Shrink double -> float for binary functions. +static Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilder<> &B, + bool doResultCheck = false) { + return optimizeDoubleFP(CI, B, true, doResultCheck); } // cabs(z) -> sqrt((creal(z)*creal(z)) + (cimag(z)*cimag(z))) |