[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
This commit is contained in:
Evandro Menezes 2018-08-03 17:50:16 +00:00
parent c7d3d34b98
commit 5aa217ac68
1 changed files with 55 additions and 72 deletions

View File

@ -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.
// same name as the float version of this call, otherwise the result is an
// infinite loop. For example, from MinGW-w64:
//
// e.g. inline float expf(float val) { return (float) exp((double) val); }
//
// 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)))