#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"
//===----------------------------------------------------------------------===//
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
// 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.
+ // 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")
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);
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;
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();
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) {
static bool checkIntUnaryReturnAndParam(Function *Callee) {
FunctionType *FT = Callee->getFunctionType();
- return !(FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy(32) ||
- !FT->getParamType(0)->isIntegerTy());
+ return FT->getNumParams() == 1 && FT->getReturnType()->isIntegerTy(32) &&
+ FT->getParamType(0)->isIntegerTy();
}
Value *LibCallSimplifier::optimizeFFS(CallInst *CI, IRBuilder<> &B) {
}
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)
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:
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);
//
// 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'
//