#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Transforms/Utils/BuildLibCalls.h"
+#include "llvm/Transforms/Utils/Local.h"
using namespace llvm;
using namespace PatternMatch;
//===----------------------------------------------------------------------===//
static bool ignoreCallingConv(LibFunc::Func Func) {
- switch (Func) {
- case LibFunc::abs:
- case LibFunc::labs:
- case LibFunc::llabs:
- case LibFunc::strlen:
- return true;
- default:
- return false;
- }
- llvm_unreachable("All cases should be covered in the switch.");
+ return Func == LibFunc::abs || Func == LibFunc::labs ||
+ Func == LibFunc::llabs || Func == LibFunc::strlen;
}
/// isOnlyUsedInZeroEqualityComparison - Return true if it only matters that the
}
static bool callHasFloatingPointArgument(const CallInst *CI) {
- for (CallInst::const_op_iterator it = CI->op_begin(), e = CI->op_end();
- it != e; ++it) {
- if ((*it)->getType()->isFloatingPointTy())
- return true;
- }
- return false;
+ return std::any_of(CI->op_begin(), CI->op_end(), [](const Use &OI) {
+ return OI->getType()->isFloatingPointTy();
+ });
}
/// \brief Check whether the overloaded unary floating point function
}
}
+/// \brief Check whether we can use unsafe floating point math for
+/// the function passed as input.
+static bool canUseUnsafeFPMath(Function *F) {
+
+ // FIXME: For finer-grain optimization, we need intrinsics to have the same
+ // fast-math flag decorations that are applied to FP instructions. For now,
+ // we have to rely on the function-level unsafe-fp-math attribute to do this
+ // optimization because there's no other way to express that the call can be
+ // relaxed.
+ if (F->hasFnAttribute("unsafe-fp-math")) {
+ Attribute Attr = F->getFnAttribute("unsafe-fp-math");
+ if (Attr.getValueAsString() == "true")
+ return true;
+ }
+ return false;
+}
+
/// \brief Returns whether \p F matches the signature expected for the
/// string/memory copying library function \p Func.
/// Acceptable functions are st[rp][n]?cpy, memove, memcpy, and memset.
Value *LibCallSimplifier::optimizeStpCpy(CallInst *CI, IRBuilder<> &B) {
Function *Callee = CI->getCalledFunction();
- // Verify the "stpcpy" function prototype.
- FunctionType *FT = Callee->getFunctionType();
-
if (!checkStringCopyLibFuncSignature(Callee, LibFunc::stpcpy))
return nullptr;
if (Len == 0)
return nullptr;
- Type *PT = FT->getParamType(0);
+ Type *PT = Callee->getFunctionType()->getParamType(0);
Value *LenV = ConstantInt::get(DL.getIntPtrType(PT), Len);
Value *DstEnd =
B.CreateGEP(B.getInt8Ty(), Dst, ConstantInt::get(DL.getIntPtrType(PT), Len - 1));
Value *LibCallSimplifier::optimizeStrNCpy(CallInst *CI, IRBuilder<> &B) {
Function *Callee = CI->getCalledFunction();
- FunctionType *FT = Callee->getFunctionType();
-
if (!checkStringCopyLibFuncSignature(Callee, LibFunc::strncpy))
return nullptr;
if (Len > SrcLen + 1)
return nullptr;
- Type *PT = FT->getParamType(0);
+ Type *PT = Callee->getFunctionType()->getParamType(0);
// strncpy(x, s, c) -> memcpy(x, s, c, 1) [s and c are constant]
B.CreateMemCpy(Dst, Src, ConstantInt::get(DL.getIntPtrType(PT), Len), 1);
return B.CreateSub(LHSV, RHSV, "chardiff");
}
+ // memcmp(S1,S2,N/8)==0 -> (*(intN_t*)S1 != *(intN_t*)S2)==0
+ if (DL.isLegalInteger(Len * 8) && isOnlyUsedInZeroEqualityComparison(CI)) {
+
+ IntegerType *IntType = IntegerType::get(CI->getContext(), Len * 8);
+ unsigned PrefAlignment = DL.getPrefTypeAlignment(IntType);
+
+ if (getKnownAlignment(LHS, DL, CI) >= PrefAlignment &&
+ getKnownAlignment(RHS, DL, CI) >= PrefAlignment) {
+
+ Type *LHSPtrTy =
+ IntType->getPointerTo(LHS->getType()->getPointerAddressSpace());
+ Type *RHSPtrTy =
+ IntType->getPointerTo(RHS->getType()->getPointerAddressSpace());
+
+ Value *LHSV = B.CreateLoad(B.CreateBitCast(LHS, LHSPtrTy, "lhsc"), "lhsv");
+ Value *RHSV = B.CreateLoad(B.CreateBitCast(RHS, RHSPtrTy, "rhsc"), "rhsv");
+
+ return B.CreateZExt(B.CreateICmpNE(LHSV, RHSV), CI->getType(), "memcmp");
+ }
+ }
+
// Constant folding: memcmp(x, y, l) -> cnst (all arguments are constant)
StringRef LHSStr, RHSStr;
if (getConstantStringInfo(LHS, LHSStr) &&
Value *LibCallSimplifier::optimizeCos(CallInst *CI, IRBuilder<> &B) {
Function *Callee = CI->getCalledFunction();
Value *Ret = nullptr;
- if (UnsafeFPShrink && Callee->getName() == "cos" && TLI->has(LibFunc::cosf)) {
+ StringRef Name = Callee->getName();
+ if (UnsafeFPShrink && Name == "cos" && hasFloatVersion(Name))
Ret = optimizeUnaryDoubleFP(CI, B, true);
- }
FunctionType *FT = Callee->getFunctionType();
// Just make sure this has 1 argument of FP type, which matches the
Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) {
Function *Callee = CI->getCalledFunction();
-
Value *Ret = nullptr;
- if (UnsafeFPShrink && Callee->getName() == "pow" && TLI->has(LibFunc::powf)) {
+ StringRef Name = Callee->getName();
+ if (UnsafeFPShrink && Name == "pow" && hasFloatVersion(Name))
Ret = optimizeUnaryDoubleFP(CI, B, true);
- }
FunctionType *FT = Callee->getFunctionType();
// Just make sure this has 2 arguments of the same FP type, which match the
if (Op1C->isExactlyValue(2.0) &&
hasUnaryFloatFn(TLI, Op1->getType(), LibFunc::exp2, LibFunc::exp2f,
LibFunc::exp2l))
- return EmitUnaryFloatFnCall(Op2, "exp2", B, Callee->getAttributes());
+ return EmitUnaryFloatFnCall(Op2, TLI->getName(LibFunc::exp2), B,
+ Callee->getAttributes());
// pow(10.0, x) -> exp10(x)
if (Op1C->isExactlyValue(10.0) &&
hasUnaryFloatFn(TLI, Op1->getType(), LibFunc::exp10, LibFunc::exp10f,
Callee->getAttributes());
}
+ bool unsafeFPMath = canUseUnsafeFPMath(CI->getParent()->getParent());
+
+ // pow(exp(x), y) -> exp(x*y)
+ // pow(exp2(x), y) -> exp2(x * y)
+ // We enable these only under fast-math. Besides rounding
+ // differences the transformation changes overflow and
+ // underflow behavior quite dramatically.
+ // Example: x = 1000, y = 0.001.
+ // pow(exp(x), y) = pow(inf, 0.001) = inf, whereas exp(x*y) = exp(1).
+ if (unsafeFPMath) {
+ if (auto *OpC = dyn_cast<CallInst>(Op1)) {
+ IRBuilder<>::FastMathFlagGuard Guard(B);
+ FastMathFlags FMF;
+ FMF.setUnsafeAlgebra();
+ B.SetFastMathFlags(FMF);
+
+ LibFunc::Func Func;
+ Function *OpCCallee = OpC->getCalledFunction();
+ if (OpCCallee && TLI->getLibFunc(OpCCallee->getName(), Func) &&
+ TLI->has(Func) && (Func == LibFunc::exp || Func == LibFunc::exp2))
+ return EmitUnaryFloatFnCall(
+ B.CreateFMul(OpC->getArgOperand(0), Op2, "mul"),
+ OpCCallee->getName(), B, OpCCallee->getAttributes());
+ }
+ }
+
ConstantFP *Op2C = dyn_cast<ConstantFP>(Op2);
if (!Op2C)
return Ret;
LibFunc::sqrtl) &&
hasUnaryFloatFn(TLI, Op2->getType(), LibFunc::fabs, LibFunc::fabsf,
LibFunc::fabsl)) {
+
+ // In -ffast-math, pow(x, 0.5) -> sqrt(x).
+ if (unsafeFPMath)
+ return EmitUnaryFloatFnCall(Op1, TLI->getName(LibFunc::sqrt), B,
+ Callee->getAttributes());
+
// Expand pow(x, 0.5) to (x == -infinity ? +infinity : fabs(sqrt(x))).
// This is faster than calling pow, and still handles negative zero
// and negative infinity correctly.
- // TODO: In fast-math mode, this could be just sqrt(x).
// TODO: In finite-only mode, this could be just fabs(sqrt(x)).
Value *Inf = ConstantFP::getInfinity(CI->getType());
Value *NegInf = ConstantFP::getInfinity(CI->getType(), true);
Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilder<> &B) {
Function *Callee = CI->getCalledFunction();
Function *Caller = CI->getParent()->getParent();
-
Value *Ret = nullptr;
- if (UnsafeFPShrink && Callee->getName() == "exp2" &&
- TLI->has(LibFunc::exp2f)) {
+ StringRef Name = Callee->getName();
+ if (UnsafeFPShrink && Name == "exp2" && hasFloatVersion(Name))
Ret = optimizeUnaryDoubleFP(CI, B, true);
- }
FunctionType *FT = Callee->getFunctionType();
// Just make sure this has 1 argument of FP type, which matches the
Value *LibCallSimplifier::optimizeFabs(CallInst *CI, IRBuilder<> &B) {
Function *Callee = CI->getCalledFunction();
-
Value *Ret = nullptr;
- if (Callee->getName() == "fabs" && TLI->has(LibFunc::fabsf)) {
+ StringRef Name = Callee->getName();
+ if (Name == "fabs" && hasFloatVersion(Name))
Ret = optimizeUnaryDoubleFP(CI, B, false);
- }
FunctionType *FT = Callee->getFunctionType();
// Make sure this has 1 argument of FP type which matches the result type.
// If we can shrink the call to a float function rather than a double
// function, do that first.
Function *Callee = CI->getCalledFunction();
- if ((Callee->getName() == "fmin" && TLI->has(LibFunc::fminf)) ||
- (Callee->getName() == "fmax" && TLI->has(LibFunc::fmaxf))) {
+ StringRef Name = Callee->getName();
+ if ((Name == "fmin" && hasFloatVersion(Name)) ||
+ (Name == "fmax" && hasFloatVersion(Name))) {
Value *Ret = optimizeBinaryDoubleFP(CI, B);
if (Ret)
return Ret;
!FT->getParamType(0)->isFloatingPointTy())
return nullptr;
- // FIXME: For finer-grain optimization, we need intrinsics to have the same
- // fast-math flag decorations that are applied to FP instructions. For now,
- // we have to rely on the function-level attributes to do this optimization
- // because there's no other way to express that the calls can be relaxed.
- IRBuilder<true, ConstantFolder,
- IRBuilderDefaultInserter<true> >::FastMathFlagGuard Guard(B);
+ IRBuilder<>::FastMathFlagGuard Guard(B);
FastMathFlags FMF;
Function *F = CI->getParent()->getParent();
- Attribute Attr = F->getFnAttribute("unsafe-fp-math");
- if (Attr.getValueAsString() == "true") {
+ if (canUseUnsafeFPMath(F)) {
// Unsafe algebra sets all fast-math-flags to true.
FMF.setUnsafeAlgebra();
} else {
// At a minimum, no-nans-fp-math must be true.
- Attr = F->getFnAttribute("no-nans-fp-math");
+ Attribute Attr = F->getFnAttribute("no-nans-fp-math");
if (Attr.getValueAsString() != "true")
return nullptr;
// No-signed-zeros is implied by the definitions of fmax/fmin themselves:
// "Ideally, fmax would be sensitive to the sign of zero, for example
- // fmax(−0. 0, +0. 0) would return +0; however, implementation in software
+ // fmax(-0. 0, +0. 0) would return +0; however, implementation in software
// might be impractical."
FMF.setNoSignedZeros();
FMF.setNoNaNs();
return B.CreateSelect(Cmp, Op0, Op1);
}
+Value *LibCallSimplifier::optimizeLog(CallInst *CI, IRBuilder<> &B) {
+ Function *Callee = CI->getCalledFunction();
+ Value *Ret = nullptr;
+ StringRef Name = Callee->getName();
+ if (UnsafeFPShrink && hasFloatVersion(Name))
+ Ret = optimizeUnaryDoubleFP(CI, B, true);
+ FunctionType *FT = Callee->getFunctionType();
+
+ // Just make sure this has 1 argument of FP type, which matches the
+ // result type.
+ if (FT->getNumParams() != 1 || FT->getReturnType() != FT->getParamType(0) ||
+ !FT->getParamType(0)->isFloatingPointTy())
+ return Ret;
+
+ if (!canUseUnsafeFPMath(CI->getParent()->getParent()))
+ return Ret;
+ Value *Op1 = CI->getArgOperand(0);
+ auto *OpC = dyn_cast<CallInst>(Op1);
+ if (!OpC)
+ return Ret;
+
+ // log(pow(x,y)) -> y*log(x)
+ // This is only applicable to log, log2, log10.
+ if (Name != "log" && Name != "log2" && Name != "log10")
+ return Ret;
+
+ IRBuilder<>::FastMathFlagGuard Guard(B);
+ FastMathFlags FMF;
+ FMF.setUnsafeAlgebra();
+ B.SetFastMathFlags(FMF);
+
+ LibFunc::Func Func;
+ Function *F = OpC->getCalledFunction();
+ if (F && ((TLI->getLibFunc(F->getName(), Func) && TLI->has(Func) &&
+ Func == LibFunc::pow) || F->getIntrinsicID() == Intrinsic::pow))
+ return B.CreateFMul(OpC->getArgOperand(1),
+ EmitUnaryFloatFnCall(OpC->getOperand(0), Callee->getName(), B,
+ Callee->getAttributes()), "mul");
+
+ // log(exp2(y)) -> y*log(2)
+ if (F && Name == "log" && TLI->getLibFunc(F->getName(), Func) &&
+ TLI->has(Func) && Func == LibFunc::exp2)
+ return B.CreateFMul(
+ OpC->getArgOperand(0),
+ EmitUnaryFloatFnCall(ConstantFP::get(CI->getType(), 2.0),
+ Callee->getName(), B, Callee->getAttributes()),
+ "logmul");
+ return Ret;
+}
+
Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilder<> &B) {
Function *Callee = CI->getCalledFunction();
if (TLI->has(LibFunc::sqrtf) && (Callee->getName() == "sqrt" ||
Callee->getIntrinsicID() == Intrinsic::sqrt))
Ret = optimizeUnaryDoubleFP(CI, B, true);
+ if (!canUseUnsafeFPMath(CI->getParent()->getParent()))
+ return Ret;
- // FIXME: For finer-grain optimization, we need intrinsics to have the same
- // fast-math flag decorations that are applied to FP instructions. For now,
- // we have to rely on the function-level unsafe-fp-math attribute to do this
- // optimization because there's no other way to express that the sqrt can be
- // reassociated.
- Function *F = CI->getParent()->getParent();
- if (F->hasFnAttribute("unsafe-fp-math")) {
- // Check for unsafe-fp-math = true.
- Attribute Attr = F->getFnAttribute("unsafe-fp-math");
- if (Attr.getValueAsString() != "true")
- return Ret;
- }
Value *Op = CI->getArgOperand(0);
if (Instruction *I = dyn_cast<Instruction>(Op)) {
if (I->getOpcode() == Instruction::FMul && I->hasUnsafeAlgebra()) {
// and multiply.
// FIXME: We're not checking the sqrt because it doesn't have
// fast-math-flags (see earlier comment).
- IRBuilder<true, ConstantFolder,
- IRBuilderDefaultInserter<true> >::FastMathFlagGuard Guard(B);
+ IRBuilder<>::FastMathFlagGuard Guard(B);
B.SetFastMathFlags(I->getFastMathFlags());
// If we found a repeated factor, hoist it out of the square root and
// replace it with the fabs of that factor.
return Ret;
}
+Value *LibCallSimplifier::optimizeTan(CallInst *CI, IRBuilder<> &B) {
+ Function *Callee = CI->getCalledFunction();
+ Value *Ret = nullptr;
+ StringRef Name = Callee->getName();
+ if (UnsafeFPShrink && Name == "tan" && hasFloatVersion(Name))
+ Ret = optimizeUnaryDoubleFP(CI, B, true);
+ FunctionType *FT = Callee->getFunctionType();
+
+ // Just make sure this has 1 argument of FP type, which matches the
+ // result type.
+ if (FT->getNumParams() != 1 || FT->getReturnType() != FT->getParamType(0) ||
+ !FT->getParamType(0)->isFloatingPointTy())
+ return Ret;
+
+ if (!canUseUnsafeFPMath(CI->getParent()->getParent()))
+ return Ret;
+ Value *Op1 = CI->getArgOperand(0);
+ auto *OpC = dyn_cast<CallInst>(Op1);
+ if (!OpC)
+ return Ret;
+
+ // tan(atan(x)) -> x
+ // tanf(atanf(x)) -> x
+ // tanl(atanl(x)) -> x
+ LibFunc::Func Func;
+ Function *F = OpC->getCalledFunction();
+ if (F && TLI->getLibFunc(F->getName(), Func) && TLI->has(Func) &&
+ ((Func == LibFunc::atan && Callee->getName() == "tan") ||
+ (Func == LibFunc::atanf && Callee->getName() == "tanf") ||
+ (Func == LibFunc::atanl && Callee->getName() == "tanl")))
+ Ret = OpC->getArgOperand(0);
+ return Ret;
+}
+
static bool isTrigLibCall(CallInst *CI);
static void insertSinCosCall(IRBuilder<> &B, Function *OrigCallee, Value *Arg,
bool UseFloat, Value *&Sin, Value *&Cos,
return;
Function *Callee = CI->getCalledFunction();
- StringRef FuncName = Callee->getName();
LibFunc::Func Func;
- if (!TLI->getLibFunc(FuncName, Func) || !TLI->has(Func) || !isTrigLibCall(CI))
+ if (!Callee || !TLI->getLibFunc(Callee->getName(), Func) || !TLI->has(Func) ||
+ !isTrigLibCall(CI))
return;
if (IsFloat) {
void LibCallSimplifier::replaceTrigInsts(SmallVectorImpl<CallInst *> &Calls,
Value *Res) {
- for (SmallVectorImpl<CallInst *>::iterator I = Calls.begin(), E = Calls.end();
- I != E; ++I) {
- replaceAllUsesWith(*I, Res);
- }
+ for (CallInst *C : Calls)
+ replaceAllUsesWith(C, Res);
}
void insertSinCosCall(IRBuilder<> &B, Function *OrigCallee, Value *Arg,
if (Instruction *ArgInst = dyn_cast<Instruction>(Arg)) {
// If the argument is an instruction, it must dominate all uses so put our
// sincos call there.
- BasicBlock::iterator Loc = ArgInst;
- B.SetInsertPoint(ArgInst->getParent(), ++Loc);
+ B.SetInsertPoint(ArgInst->getParent(), ++ArgInst->getIterator());
} else {
// Otherwise (e.g. for a constant) the beginning of the function is as
// good a place as any.
// Integer Library Call Optimizations
//===----------------------------------------------------------------------===//
+static bool checkIntUnaryReturnAndParam(Function *Callee) {
+ FunctionType *FT = Callee->getFunctionType();
+ return FT->getNumParams() == 1 && FT->getReturnType()->isIntegerTy(32) &&
+ FT->getParamType(0)->isIntegerTy();
+}
+
Value *LibCallSimplifier::optimizeFFS(CallInst *CI, IRBuilder<> &B) {
Function *Callee = CI->getCalledFunction();
- FunctionType *FT = Callee->getFunctionType();
- // Just make sure this has 2 arguments of the same FP type, which match the
- // result type.
- if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy(32) ||
- !FT->getParamType(0)->isIntegerTy())
+ if (!checkIntUnaryReturnAndParam(Callee))
return nullptr;
-
Value *Op = CI->getArgOperand(0);
// Constant fold.
}
Value *LibCallSimplifier::optimizeIsDigit(CallInst *CI, IRBuilder<> &B) {
- Function *Callee = CI->getCalledFunction();
- FunctionType *FT = Callee->getFunctionType();
- // We require integer(i32)
- if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() ||
- !FT->getParamType(0)->isIntegerTy(32))
+ if (!checkIntUnaryReturnAndParam(CI->getCalledFunction()))
return nullptr;
// isdigit(c) -> (c-'0') <u 10
}
Value *LibCallSimplifier::optimizeIsAscii(CallInst *CI, IRBuilder<> &B) {
- Function *Callee = CI->getCalledFunction();
- FunctionType *FT = Callee->getFunctionType();
- // We require integer(i32)
- if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() ||
- !FT->getParamType(0)->isIntegerTy(32))
+ if (!checkIntUnaryReturnAndParam(CI->getCalledFunction()))
return nullptr;
// isascii(c) -> c <u 128
}
Value *LibCallSimplifier::optimizeToAscii(CallInst *CI, IRBuilder<> &B) {
- Function *Callee = CI->getCalledFunction();
- FunctionType *FT = Callee->getFunctionType();
- // We require i32(i32)
- if (FT->getNumParams() != 1 || FT->getReturnType() != FT->getParamType(0) ||
- !FT->getParamType(0)->isIntegerTy(32))
+ if (!checkIntUnaryReturnAndParam(CI->getCalledFunction()))
return nullptr;
// toascii(c) -> c & 0x7f
}
static bool isReportingError(Function *Callee, CallInst *CI, int StreamArg) {
- if (!ColdErrorCalls)
- return false;
-
- if (!Callee || !Callee->isDeclaration())
+ if (!ColdErrorCalls || !Callee || !Callee->isDeclaration())
return false;
if (StreamArg < 0)
// Command-line parameter overrides function attribute.
if (EnableUnsafeFPShrink.getNumOccurrences() > 0)
UnsafeFPShrink = EnableUnsafeFPShrink;
- else if (Callee->hasFnAttribute("unsafe-fp-math")) {
- // FIXME: This is the same problem as described in optimizeSqrt().
- // If calls gain access to IR-level FMF, then use that instead of a
- // function attribute.
-
- // Check for unsafe-fp-math = true.
- Attribute Attr = Callee->getFnAttribute("unsafe-fp-math");
- if (Attr.getValueAsString() == "true")
- UnsafeFPShrink = true;
- }
+ else if (canUseUnsafeFPMath(Callee))
+ UnsafeFPShrink = true;
// First, check for intrinsics.
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) {
return optimizeExp2(CI, Builder);
case Intrinsic::fabs:
return optimizeFabs(CI, Builder);
+ case Intrinsic::log:
+ return optimizeLog(CI, Builder);
case Intrinsic::sqrt:
return optimizeSqrt(CI, Builder);
default:
if (Value *SimplifiedFortifiedCI = FortifiedSimplifier.optimizeCall(CI)) {
// Try to further simplify the result.
CallInst *SimplifiedCI = dyn_cast<CallInst>(SimplifiedFortifiedCI);
- if (SimplifiedCI && SimplifiedCI->getCalledFunction())
- if (Value *V = optimizeStringMemoryLibCall(SimplifiedCI, Builder)) {
+ if (SimplifiedCI && SimplifiedCI->getCalledFunction()) {
+ // Use an IR Builder from SimplifiedCI if available instead of CI
+ // to guarantee we reach all uses we might replace later on.
+ IRBuilder<> TmpBuilder(SimplifiedCI);
+ if (Value *V = optimizeStringMemoryLibCall(SimplifiedCI, TmpBuilder)) {
// If we were able to further simplify, remove the now redundant call.
SimplifiedCI->replaceAllUsesWith(V);
SimplifiedCI->eraseFromParent();
return V;
}
+ }
return SimplifiedFortifiedCI;
}
return optimizeFWrite(CI, Builder);
case LibFunc::fputs:
return optimizeFPuts(CI, Builder);
+ case LibFunc::log:
+ case LibFunc::log10:
+ case LibFunc::log1p:
+ case LibFunc::log2:
+ case LibFunc::logb:
+ return optimizeLog(CI, Builder);
case LibFunc::puts:
return optimizePuts(CI, Builder);
+ case LibFunc::tan:
+ case LibFunc::tanf:
+ case LibFunc::tanl:
+ return optimizeTan(CI, Builder);
case LibFunc::perror:
return optimizeErrorReporting(CI, Builder);
case LibFunc::vfprintf:
case LibFunc::exp:
case LibFunc::exp10:
case LibFunc::expm1:
- case LibFunc::log:
- case LibFunc::log10:
- case LibFunc::log1p:
- case LibFunc::log2:
- case LibFunc::logb:
case LibFunc::sin:
case LibFunc::sinh:
- case LibFunc::tan:
case LibFunc::tanh:
if (UnsafeFPShrink && hasFloatVersion(FuncName))
return optimizeUnaryDoubleFP(CI, Builder, true);
Replacer(I, With);
}
-/*static*/ void LibCallSimplifier::replaceAllUsesWithDefault(Instruction *I,
- Value *With) {
- I->replaceAllUsesWith(With);
- I->eraseFromParent();
-}
-
// TODO:
// Additional cases that we need to add to this file:
//
// cbrt:
// * cbrt(expN(X)) -> expN(x/3)
// * cbrt(sqrt(x)) -> pow(x,1/6)
-// * cbrt(sqrt(x)) -> pow(x,1/9)
+// * cbrt(cbrt(x)) -> pow(x,1/9)
//
// exp, expf, expl:
// * exp(log(x)) -> x
//
// log, logf, logl:
// * log(exp(x)) -> x
-// * log(x**y) -> y*log(x)
// * log(exp(y)) -> y*log(e)
-// * log(exp2(y)) -> y*log(2)
// * log(exp10(y)) -> y*log(10)
// * log(sqrt(x)) -> 0.5*log(x)
-// * log(pow(x,y)) -> y*log(x)
//
// lround, lroundf, lroundl:
// * lround(cnst) -> cnst'
//
// pow, powf, powl:
-// * pow(exp(x),y) -> exp(x*y)
// * pow(sqrt(x),y) -> pow(x,y*0.5)
// * pow(pow(x,y),z)-> pow(x,y*z)
//
// * sqrt(Nroot(x)) -> pow(x,1/(2*N))
// * sqrt(pow(x,y)) -> pow(|x|,y*0.5)
//
-// tan, tanf, tanl:
-// * tan(atan(x)) -> x
-//
// trunc, truncf, truncl:
// * trunc(cnst) -> cnst'
//