13861d79fSDimitry Andric //===------ SimplifyLibCalls.cpp - Library calls simplifier ---------------===//
23861d79fSDimitry Andric //
33861d79fSDimitry Andric // The LLVM Compiler Infrastructure
43861d79fSDimitry Andric //
53861d79fSDimitry Andric // This file is distributed under the University of Illinois Open Source
63861d79fSDimitry Andric // License. See LICENSE.TXT for details.
73861d79fSDimitry Andric //
83861d79fSDimitry Andric //===----------------------------------------------------------------------===//
93861d79fSDimitry Andric //
104ba319b5SDimitry Andric // This file implements the library calls simplifier. It does not implement
114ba319b5SDimitry Andric // any pass, but can't be used by other passes to do simplifications.
123861d79fSDimitry Andric //
133861d79fSDimitry Andric //===----------------------------------------------------------------------===//
143861d79fSDimitry Andric
153861d79fSDimitry Andric #include "llvm/Transforms/Utils/SimplifyLibCalls.h"
16*b5893f02SDimitry Andric #include "llvm/ADT/APSInt.h"
17139f7f9bSDimitry Andric #include "llvm/ADT/SmallString.h"
183861d79fSDimitry Andric #include "llvm/ADT/StringMap.h"
19f785676fSDimitry Andric #include "llvm/ADT/Triple.h"
202cab237bSDimitry Andric #include "llvm/Analysis/ConstantFolding.h"
212cab237bSDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h"
227d523365SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
234ba319b5SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
243861d79fSDimitry Andric #include "llvm/Analysis/ValueTracking.h"
254ba319b5SDimitry Andric #include "llvm/Analysis/CaptureTracking.h"
26*b5893f02SDimitry Andric #include "llvm/Analysis/Loads.h"
27139f7f9bSDimitry Andric #include "llvm/IR/DataLayout.h"
28139f7f9bSDimitry Andric #include "llvm/IR/Function.h"
29139f7f9bSDimitry Andric #include "llvm/IR/IRBuilder.h"
30139f7f9bSDimitry Andric #include "llvm/IR/IntrinsicInst.h"
31139f7f9bSDimitry Andric #include "llvm/IR/Intrinsics.h"
32139f7f9bSDimitry Andric #include "llvm/IR/LLVMContext.h"
33139f7f9bSDimitry Andric #include "llvm/IR/Module.h"
3439d628a0SDimitry Andric #include "llvm/IR/PatternMatch.h"
35f785676fSDimitry Andric #include "llvm/Support/CommandLine.h"
3651690af2SDimitry Andric #include "llvm/Support/KnownBits.h"
373861d79fSDimitry Andric #include "llvm/Transforms/Utils/BuildLibCalls.h"
383861d79fSDimitry Andric
393861d79fSDimitry Andric using namespace llvm;
4039d628a0SDimitry Andric using namespace PatternMatch;
413861d79fSDimitry Andric
42f785676fSDimitry Andric static cl::opt<bool>
4339d628a0SDimitry Andric EnableUnsafeFPShrink("enable-double-float-shrink", cl::Hidden,
4439d628a0SDimitry Andric cl::init(false),
4539d628a0SDimitry Andric cl::desc("Enable unsafe double to float "
4639d628a0SDimitry Andric "shrinking for math lib calls"));
473861d79fSDimitry Andric
483861d79fSDimitry Andric
493861d79fSDimitry Andric //===----------------------------------------------------------------------===//
503861d79fSDimitry Andric // Helper Functions
513861d79fSDimitry Andric //===----------------------------------------------------------------------===//
523861d79fSDimitry Andric
ignoreCallingConv(LibFunc Func)537a7e6055SDimitry Andric static bool ignoreCallingConv(LibFunc Func) {
547a7e6055SDimitry Andric return Func == LibFunc_abs || Func == LibFunc_labs ||
557a7e6055SDimitry Andric Func == LibFunc_llabs || Func == LibFunc_strlen;
5639d628a0SDimitry Andric }
5739d628a0SDimitry Andric
isCallingConvCCompatible(CallInst * CI)58d88c1a5aSDimitry Andric static bool isCallingConvCCompatible(CallInst *CI) {
59d88c1a5aSDimitry Andric switch(CI->getCallingConv()) {
60d88c1a5aSDimitry Andric default:
61d88c1a5aSDimitry Andric return false;
62d88c1a5aSDimitry Andric case llvm::CallingConv::C:
63d88c1a5aSDimitry Andric return true;
64d88c1a5aSDimitry Andric case llvm::CallingConv::ARM_APCS:
65d88c1a5aSDimitry Andric case llvm::CallingConv::ARM_AAPCS:
66d88c1a5aSDimitry Andric case llvm::CallingConv::ARM_AAPCS_VFP: {
67d88c1a5aSDimitry Andric
68d88c1a5aSDimitry Andric // The iOS ABI diverges from the standard in some cases, so for now don't
69d88c1a5aSDimitry Andric // try to simplify those calls.
70d88c1a5aSDimitry Andric if (Triple(CI->getModule()->getTargetTriple()).isiOS())
71d88c1a5aSDimitry Andric return false;
72d88c1a5aSDimitry Andric
73d88c1a5aSDimitry Andric auto *FuncTy = CI->getFunctionType();
74d88c1a5aSDimitry Andric
75d88c1a5aSDimitry Andric if (!FuncTy->getReturnType()->isPointerTy() &&
76d88c1a5aSDimitry Andric !FuncTy->getReturnType()->isIntegerTy() &&
77d88c1a5aSDimitry Andric !FuncTy->getReturnType()->isVoidTy())
78d88c1a5aSDimitry Andric return false;
79d88c1a5aSDimitry Andric
80d88c1a5aSDimitry Andric for (auto Param : FuncTy->params()) {
81d88c1a5aSDimitry Andric if (!Param->isPointerTy() && !Param->isIntegerTy())
82d88c1a5aSDimitry Andric return false;
83d88c1a5aSDimitry Andric }
84d88c1a5aSDimitry Andric return true;
85d88c1a5aSDimitry Andric }
86d88c1a5aSDimitry Andric }
87d88c1a5aSDimitry Andric return false;
88d88c1a5aSDimitry Andric }
89d88c1a5aSDimitry Andric
904d0b32cdSDimitry Andric /// Return true if it is only used in equality comparisons with With.
isOnlyUsedInEqualityComparison(Value * V,Value * With)913861d79fSDimitry Andric static bool isOnlyUsedInEqualityComparison(Value *V, Value *With) {
9291bc56edSDimitry Andric for (User *U : V->users()) {
9391bc56edSDimitry Andric if (ICmpInst *IC = dyn_cast<ICmpInst>(U))
943861d79fSDimitry Andric if (IC->isEquality() && IC->getOperand(1) == With)
953861d79fSDimitry Andric continue;
963861d79fSDimitry Andric // Unknown instruction.
973861d79fSDimitry Andric return false;
983861d79fSDimitry Andric }
993861d79fSDimitry Andric return true;
1003861d79fSDimitry Andric }
1013861d79fSDimitry Andric
callHasFloatingPointArgument(const CallInst * CI)102139f7f9bSDimitry Andric static bool callHasFloatingPointArgument(const CallInst *CI) {
103d88c1a5aSDimitry Andric return any_of(CI->operands(), [](const Use &OI) {
1047d523365SDimitry Andric return OI->getType()->isFloatingPointTy();
1057d523365SDimitry Andric });
106139f7f9bSDimitry Andric }
107139f7f9bSDimitry Andric
convertStrToNumber(CallInst * CI,StringRef & Str,int64_t Base)1084ba319b5SDimitry Andric static Value *convertStrToNumber(CallInst *CI, StringRef &Str, int64_t Base) {
1094ba319b5SDimitry Andric if (Base < 2 || Base > 36)
1104ba319b5SDimitry Andric // handle special zero base
1114ba319b5SDimitry Andric if (Base != 0)
1124ba319b5SDimitry Andric return nullptr;
1134ba319b5SDimitry Andric
1144ba319b5SDimitry Andric char *End;
1154ba319b5SDimitry Andric std::string nptr = Str.str();
1164ba319b5SDimitry Andric errno = 0;
1174ba319b5SDimitry Andric long long int Result = strtoll(nptr.c_str(), &End, Base);
1184ba319b5SDimitry Andric if (errno)
1194ba319b5SDimitry Andric return nullptr;
1204ba319b5SDimitry Andric
1214ba319b5SDimitry Andric // if we assume all possible target locales are ASCII supersets,
1224ba319b5SDimitry Andric // then if strtoll successfully parses a number on the host,
1234ba319b5SDimitry Andric // it will also successfully parse the same way on the target
1244ba319b5SDimitry Andric if (*End != '\0')
1254ba319b5SDimitry Andric return nullptr;
1264ba319b5SDimitry Andric
1274ba319b5SDimitry Andric if (!isIntN(CI->getType()->getPrimitiveSizeInBits(), Result))
1284ba319b5SDimitry Andric return nullptr;
1294ba319b5SDimitry Andric
1304ba319b5SDimitry Andric return ConstantInt::get(CI->getType(), Result);
131f785676fSDimitry Andric }
1324ba319b5SDimitry Andric
isLocallyOpenedFile(Value * File,CallInst * CI,IRBuilder<> & B,const TargetLibraryInfo * TLI)1334ba319b5SDimitry Andric static bool isLocallyOpenedFile(Value *File, CallInst *CI, IRBuilder<> &B,
1344ba319b5SDimitry Andric const TargetLibraryInfo *TLI) {
1354ba319b5SDimitry Andric CallInst *FOpen = dyn_cast<CallInst>(File);
1364ba319b5SDimitry Andric if (!FOpen)
1374ba319b5SDimitry Andric return false;
1384ba319b5SDimitry Andric
1394ba319b5SDimitry Andric Function *InnerCallee = FOpen->getCalledFunction();
1404ba319b5SDimitry Andric if (!InnerCallee)
1414ba319b5SDimitry Andric return false;
1424ba319b5SDimitry Andric
1434ba319b5SDimitry Andric LibFunc Func;
1444ba319b5SDimitry Andric if (!TLI->getLibFunc(*InnerCallee, Func) || !TLI->has(Func) ||
1454ba319b5SDimitry Andric Func != LibFunc_fopen)
1464ba319b5SDimitry Andric return false;
1474ba319b5SDimitry Andric
1484ba319b5SDimitry Andric inferLibFuncAttributes(*CI->getCalledFunction(), *TLI);
1494ba319b5SDimitry Andric if (PointerMayBeCaptured(File, true, true))
1504ba319b5SDimitry Andric return false;
1514ba319b5SDimitry Andric
1524ba319b5SDimitry Andric return true;
153f785676fSDimitry Andric }
154f785676fSDimitry Andric
isOnlyUsedInComparisonWithZero(Value * V)155*b5893f02SDimitry Andric static bool isOnlyUsedInComparisonWithZero(Value *V) {
156*b5893f02SDimitry Andric for (User *U : V->users()) {
157*b5893f02SDimitry Andric if (ICmpInst *IC = dyn_cast<ICmpInst>(U))
158*b5893f02SDimitry Andric if (Constant *C = dyn_cast<Constant>(IC->getOperand(1)))
159*b5893f02SDimitry Andric if (C->isNullValue())
160*b5893f02SDimitry Andric continue;
161*b5893f02SDimitry Andric // Unknown instruction.
162*b5893f02SDimitry Andric return false;
163*b5893f02SDimitry Andric }
164*b5893f02SDimitry Andric return true;
165*b5893f02SDimitry Andric }
166*b5893f02SDimitry Andric
canTransformToMemCmp(CallInst * CI,Value * Str,uint64_t Len,const DataLayout & DL)167*b5893f02SDimitry Andric static bool canTransformToMemCmp(CallInst *CI, Value *Str, uint64_t Len,
168*b5893f02SDimitry Andric const DataLayout &DL) {
169*b5893f02SDimitry Andric if (!isOnlyUsedInComparisonWithZero(CI))
170*b5893f02SDimitry Andric return false;
171*b5893f02SDimitry Andric
172*b5893f02SDimitry Andric if (!isDereferenceableAndAlignedPointer(Str, 1, APInt(64, Len), DL))
173*b5893f02SDimitry Andric return false;
174*b5893f02SDimitry Andric
175*b5893f02SDimitry Andric if (CI->getFunction()->hasFnAttribute(Attribute::SanitizeMemory))
176*b5893f02SDimitry Andric return false;
177*b5893f02SDimitry Andric
178*b5893f02SDimitry Andric return true;
179*b5893f02SDimitry Andric }
180*b5893f02SDimitry Andric
1813861d79fSDimitry Andric //===----------------------------------------------------------------------===//
1823861d79fSDimitry Andric // String and Memory Library Call Optimizations
1833861d79fSDimitry Andric //===----------------------------------------------------------------------===//
1843861d79fSDimitry Andric
optimizeStrCat(CallInst * CI,IRBuilder<> & B)18539d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStrCat(CallInst *CI, IRBuilder<> &B) {
1863861d79fSDimitry Andric // Extract some information from the instruction
1873861d79fSDimitry Andric Value *Dst = CI->getArgOperand(0);
1883861d79fSDimitry Andric Value *Src = CI->getArgOperand(1);
1893861d79fSDimitry Andric
1903861d79fSDimitry Andric // See if we can get the length of the input string.
1913861d79fSDimitry Andric uint64_t Len = GetStringLength(Src);
19239d628a0SDimitry Andric if (Len == 0)
19339d628a0SDimitry Andric return nullptr;
1943861d79fSDimitry Andric --Len; // Unbias length.
1953861d79fSDimitry Andric
1963861d79fSDimitry Andric // Handle the simple, do-nothing case: strcat(x, "") -> x
1973861d79fSDimitry Andric if (Len == 0)
1983861d79fSDimitry Andric return Dst;
1993861d79fSDimitry Andric
2003861d79fSDimitry Andric return emitStrLenMemCpy(Src, Dst, Len, B);
2013861d79fSDimitry Andric }
2023861d79fSDimitry Andric
emitStrLenMemCpy(Value * Src,Value * Dst,uint64_t Len,IRBuilder<> & B)20339d628a0SDimitry Andric Value *LibCallSimplifier::emitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len,
2043861d79fSDimitry Andric IRBuilder<> &B) {
2053861d79fSDimitry Andric // We need to find the end of the destination string. That's where the
2063861d79fSDimitry Andric // memory is to be moved to. We just generate a call to strlen.
2073ca95b02SDimitry Andric Value *DstLen = emitStrLen(Dst, B, DL, TLI);
2083861d79fSDimitry Andric if (!DstLen)
20991bc56edSDimitry Andric return nullptr;
2103861d79fSDimitry Andric
2113861d79fSDimitry Andric // Now that we have the destination's length, we must index into the
2123861d79fSDimitry Andric // destination's pointer to get the actual memcpy destination (end of
2133861d79fSDimitry Andric // the string .. we're concatenating).
214ff0cc061SDimitry Andric Value *CpyDst = B.CreateGEP(B.getInt8Ty(), Dst, DstLen, "endptr");
2153861d79fSDimitry Andric
2163861d79fSDimitry Andric // We have enough information to now generate the memcpy call to do the
2173861d79fSDimitry Andric // concatenation for us. Make a memcpy to copy the nul byte with align = 1.
2184ba319b5SDimitry Andric B.CreateMemCpy(CpyDst, 1, Src, 1,
2194ba319b5SDimitry Andric ConstantInt::get(DL.getIntPtrType(Src->getContext()), Len + 1));
2203861d79fSDimitry Andric return Dst;
2213861d79fSDimitry Andric }
2223861d79fSDimitry Andric
optimizeStrNCat(CallInst * CI,IRBuilder<> & B)22339d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStrNCat(CallInst *CI, IRBuilder<> &B) {
2244d0b32cdSDimitry Andric // Extract some information from the instruction.
2253861d79fSDimitry Andric Value *Dst = CI->getArgOperand(0);
2263861d79fSDimitry Andric Value *Src = CI->getArgOperand(1);
2273861d79fSDimitry Andric uint64_t Len;
2283861d79fSDimitry Andric
2294d0b32cdSDimitry Andric // We don't do anything if length is not constant.
2303861d79fSDimitry Andric if (ConstantInt *LengthArg = dyn_cast<ConstantInt>(CI->getArgOperand(2)))
2313861d79fSDimitry Andric Len = LengthArg->getZExtValue();
2323861d79fSDimitry Andric else
23391bc56edSDimitry Andric return nullptr;
2343861d79fSDimitry Andric
2353861d79fSDimitry Andric // See if we can get the length of the input string.
2363861d79fSDimitry Andric uint64_t SrcLen = GetStringLength(Src);
23739d628a0SDimitry Andric if (SrcLen == 0)
23839d628a0SDimitry Andric return nullptr;
2393861d79fSDimitry Andric --SrcLen; // Unbias length.
2403861d79fSDimitry Andric
2413861d79fSDimitry Andric // Handle the simple, do-nothing cases:
2423861d79fSDimitry Andric // strncat(x, "", c) -> x
2433861d79fSDimitry Andric // strncat(x, c, 0) -> x
24439d628a0SDimitry Andric if (SrcLen == 0 || Len == 0)
24539d628a0SDimitry Andric return Dst;
2463861d79fSDimitry Andric
2474d0b32cdSDimitry Andric // We don't optimize this case.
24839d628a0SDimitry Andric if (Len < SrcLen)
24939d628a0SDimitry Andric return nullptr;
2503861d79fSDimitry Andric
2513861d79fSDimitry Andric // strncat(x, s, c) -> strcat(x, s)
2524d0b32cdSDimitry Andric // s is constant so the strcat can be optimized further.
2533861d79fSDimitry Andric return emitStrLenMemCpy(Src, Dst, SrcLen, B);
2543861d79fSDimitry Andric }
2553861d79fSDimitry Andric
optimizeStrChr(CallInst * CI,IRBuilder<> & B)25639d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStrChr(CallInst *CI, IRBuilder<> &B) {
25739d628a0SDimitry Andric Function *Callee = CI->getCalledFunction();
2583861d79fSDimitry Andric FunctionType *FT = Callee->getFunctionType();
2593861d79fSDimitry Andric Value *SrcStr = CI->getArgOperand(0);
2603861d79fSDimitry Andric
2613861d79fSDimitry Andric // If the second operand is non-constant, see if we can compute the length
2623861d79fSDimitry Andric // of the input string and turn this into memchr.
2633861d79fSDimitry Andric ConstantInt *CharC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
26491bc56edSDimitry Andric if (!CharC) {
2653861d79fSDimitry Andric uint64_t Len = GetStringLength(SrcStr);
2663861d79fSDimitry Andric if (Len == 0 || !FT->getParamType(1)->isIntegerTy(32)) // memchr needs i32.
26791bc56edSDimitry Andric return nullptr;
2683861d79fSDimitry Andric
2693ca95b02SDimitry Andric return emitMemChr(SrcStr, CI->getArgOperand(1), // include nul.
270ff0cc061SDimitry Andric ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len),
271ff0cc061SDimitry Andric B, DL, TLI);
2723861d79fSDimitry Andric }
2733861d79fSDimitry Andric
2743861d79fSDimitry Andric // Otherwise, the character is a constant, see if the first argument is
2753861d79fSDimitry Andric // a string literal. If so, we can constant fold.
2763861d79fSDimitry Andric StringRef Str;
27791bc56edSDimitry Andric if (!getConstantStringInfo(SrcStr, Str)) {
278ff0cc061SDimitry Andric if (CharC->isZero()) // strchr(p, 0) -> p + strlen(p)
2793ca95b02SDimitry Andric return B.CreateGEP(B.getInt8Ty(), SrcStr, emitStrLen(SrcStr, B, DL, TLI),
2804d0b32cdSDimitry Andric "strchr");
28191bc56edSDimitry Andric return nullptr;
28291bc56edSDimitry Andric }
2833861d79fSDimitry Andric
2843861d79fSDimitry Andric // Compute the offset, make sure to handle the case when we're searching for
2853861d79fSDimitry Andric // zero (a weird way to spell strlen).
28639d628a0SDimitry Andric size_t I = (0xFF & CharC->getSExtValue()) == 0
28739d628a0SDimitry Andric ? Str.size()
28839d628a0SDimitry Andric : Str.find(CharC->getSExtValue());
2893861d79fSDimitry Andric if (I == StringRef::npos) // Didn't find the char. strchr returns null.
2903861d79fSDimitry Andric return Constant::getNullValue(CI->getType());
2913861d79fSDimitry Andric
2923861d79fSDimitry Andric // strchr(s+n,c) -> gep(s+n+i,c)
293ff0cc061SDimitry Andric return B.CreateGEP(B.getInt8Ty(), SrcStr, B.getInt64(I), "strchr");
2943861d79fSDimitry Andric }
2953861d79fSDimitry Andric
optimizeStrRChr(CallInst * CI,IRBuilder<> & B)29639d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStrRChr(CallInst *CI, IRBuilder<> &B) {
2973861d79fSDimitry Andric Value *SrcStr = CI->getArgOperand(0);
2983861d79fSDimitry Andric ConstantInt *CharC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
2993861d79fSDimitry Andric
3003861d79fSDimitry Andric // Cannot fold anything if we're not looking for a constant.
3013861d79fSDimitry Andric if (!CharC)
30291bc56edSDimitry Andric return nullptr;
3033861d79fSDimitry Andric
3043861d79fSDimitry Andric StringRef Str;
3053861d79fSDimitry Andric if (!getConstantStringInfo(SrcStr, Str)) {
3063861d79fSDimitry Andric // strrchr(s, 0) -> strchr(s, 0)
307ff0cc061SDimitry Andric if (CharC->isZero())
3083ca95b02SDimitry Andric return emitStrChr(SrcStr, '\0', B, TLI);
30991bc56edSDimitry Andric return nullptr;
3103861d79fSDimitry Andric }
3113861d79fSDimitry Andric
3123861d79fSDimitry Andric // Compute the offset.
31339d628a0SDimitry Andric size_t I = (0xFF & CharC->getSExtValue()) == 0
31439d628a0SDimitry Andric ? Str.size()
31539d628a0SDimitry Andric : Str.rfind(CharC->getSExtValue());
3163861d79fSDimitry Andric if (I == StringRef::npos) // Didn't find the char. Return null.
3173861d79fSDimitry Andric return Constant::getNullValue(CI->getType());
3183861d79fSDimitry Andric
3193861d79fSDimitry Andric // strrchr(s+n,c) -> gep(s+n+i,c)
320ff0cc061SDimitry Andric return B.CreateGEP(B.getInt8Ty(), SrcStr, B.getInt64(I), "strrchr");
3213861d79fSDimitry Andric }
3223861d79fSDimitry Andric
optimizeStrCmp(CallInst * CI,IRBuilder<> & B)32339d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStrCmp(CallInst *CI, IRBuilder<> &B) {
3243861d79fSDimitry Andric Value *Str1P = CI->getArgOperand(0), *Str2P = CI->getArgOperand(1);
3253861d79fSDimitry Andric if (Str1P == Str2P) // strcmp(x,x) -> 0
3263861d79fSDimitry Andric return ConstantInt::get(CI->getType(), 0);
3273861d79fSDimitry Andric
3283861d79fSDimitry Andric StringRef Str1, Str2;
3293861d79fSDimitry Andric bool HasStr1 = getConstantStringInfo(Str1P, Str1);
3303861d79fSDimitry Andric bool HasStr2 = getConstantStringInfo(Str2P, Str2);
3313861d79fSDimitry Andric
3323861d79fSDimitry Andric // strcmp(x, y) -> cnst (if both x and y are constant strings)
3333861d79fSDimitry Andric if (HasStr1 && HasStr2)
3343861d79fSDimitry Andric return ConstantInt::get(CI->getType(), Str1.compare(Str2));
3353861d79fSDimitry Andric
3363861d79fSDimitry Andric if (HasStr1 && Str1.empty()) // strcmp("", x) -> -*x
33739d628a0SDimitry Andric return B.CreateNeg(
33839d628a0SDimitry Andric B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"), CI->getType()));
3393861d79fSDimitry Andric
3403861d79fSDimitry Andric if (HasStr2 && Str2.empty()) // strcmp(x,"") -> *x
3413861d79fSDimitry Andric return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"), CI->getType());
3423861d79fSDimitry Andric
3433861d79fSDimitry Andric // strcmp(P, "x") -> memcmp(P, "x", 2)
3443861d79fSDimitry Andric uint64_t Len1 = GetStringLength(Str1P);
3453861d79fSDimitry Andric uint64_t Len2 = GetStringLength(Str2P);
3463861d79fSDimitry Andric if (Len1 && Len2) {
3473ca95b02SDimitry Andric return emitMemCmp(Str1P, Str2P,
348ff0cc061SDimitry Andric ConstantInt::get(DL.getIntPtrType(CI->getContext()),
34939d628a0SDimitry Andric std::min(Len1, Len2)),
35039d628a0SDimitry Andric B, DL, TLI);
3513861d79fSDimitry Andric }
3523861d79fSDimitry Andric
353*b5893f02SDimitry Andric // strcmp to memcmp
354*b5893f02SDimitry Andric if (!HasStr1 && HasStr2) {
355*b5893f02SDimitry Andric if (canTransformToMemCmp(CI, Str1P, Len2, DL))
356*b5893f02SDimitry Andric return emitMemCmp(
357*b5893f02SDimitry Andric Str1P, Str2P,
358*b5893f02SDimitry Andric ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len2), B, DL,
359*b5893f02SDimitry Andric TLI);
360*b5893f02SDimitry Andric } else if (HasStr1 && !HasStr2) {
361*b5893f02SDimitry Andric if (canTransformToMemCmp(CI, Str2P, Len1, DL))
362*b5893f02SDimitry Andric return emitMemCmp(
363*b5893f02SDimitry Andric Str1P, Str2P,
364*b5893f02SDimitry Andric ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len1), B, DL,
365*b5893f02SDimitry Andric TLI);
366*b5893f02SDimitry Andric }
367*b5893f02SDimitry Andric
36891bc56edSDimitry Andric return nullptr;
3693861d79fSDimitry Andric }
3703861d79fSDimitry Andric
optimizeStrNCmp(CallInst * CI,IRBuilder<> & B)37139d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStrNCmp(CallInst *CI, IRBuilder<> &B) {
3723861d79fSDimitry Andric Value *Str1P = CI->getArgOperand(0), *Str2P = CI->getArgOperand(1);
3733861d79fSDimitry Andric if (Str1P == Str2P) // strncmp(x,x,n) -> 0
3743861d79fSDimitry Andric return ConstantInt::get(CI->getType(), 0);
3753861d79fSDimitry Andric
3763861d79fSDimitry Andric // Get the length argument if it is constant.
3773861d79fSDimitry Andric uint64_t Length;
3783861d79fSDimitry Andric if (ConstantInt *LengthArg = dyn_cast<ConstantInt>(CI->getArgOperand(2)))
3793861d79fSDimitry Andric Length = LengthArg->getZExtValue();
3803861d79fSDimitry Andric else
38191bc56edSDimitry Andric return nullptr;
3823861d79fSDimitry Andric
3833861d79fSDimitry Andric if (Length == 0) // strncmp(x,y,0) -> 0
3843861d79fSDimitry Andric return ConstantInt::get(CI->getType(), 0);
3853861d79fSDimitry Andric
386ff0cc061SDimitry Andric if (Length == 1) // strncmp(x,y,1) -> memcmp(x,y,1)
3873ca95b02SDimitry Andric return emitMemCmp(Str1P, Str2P, CI->getArgOperand(2), B, DL, TLI);
3883861d79fSDimitry Andric
3893861d79fSDimitry Andric StringRef Str1, Str2;
3903861d79fSDimitry Andric bool HasStr1 = getConstantStringInfo(Str1P, Str1);
3913861d79fSDimitry Andric bool HasStr2 = getConstantStringInfo(Str2P, Str2);
3923861d79fSDimitry Andric
3933861d79fSDimitry Andric // strncmp(x, y) -> cnst (if both x and y are constant strings)
3943861d79fSDimitry Andric if (HasStr1 && HasStr2) {
3953861d79fSDimitry Andric StringRef SubStr1 = Str1.substr(0, Length);
3963861d79fSDimitry Andric StringRef SubStr2 = Str2.substr(0, Length);
3973861d79fSDimitry Andric return ConstantInt::get(CI->getType(), SubStr1.compare(SubStr2));
3983861d79fSDimitry Andric }
3993861d79fSDimitry Andric
4003861d79fSDimitry Andric if (HasStr1 && Str1.empty()) // strncmp("", x, n) -> -*x
40139d628a0SDimitry Andric return B.CreateNeg(
40239d628a0SDimitry Andric B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"), CI->getType()));
4033861d79fSDimitry Andric
4043861d79fSDimitry Andric if (HasStr2 && Str2.empty()) // strncmp(x, "", n) -> *x
4053861d79fSDimitry Andric return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"), CI->getType());
4063861d79fSDimitry Andric
407*b5893f02SDimitry Andric uint64_t Len1 = GetStringLength(Str1P);
408*b5893f02SDimitry Andric uint64_t Len2 = GetStringLength(Str2P);
409*b5893f02SDimitry Andric
410*b5893f02SDimitry Andric // strncmp to memcmp
411*b5893f02SDimitry Andric if (!HasStr1 && HasStr2) {
412*b5893f02SDimitry Andric Len2 = std::min(Len2, Length);
413*b5893f02SDimitry Andric if (canTransformToMemCmp(CI, Str1P, Len2, DL))
414*b5893f02SDimitry Andric return emitMemCmp(
415*b5893f02SDimitry Andric Str1P, Str2P,
416*b5893f02SDimitry Andric ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len2), B, DL,
417*b5893f02SDimitry Andric TLI);
418*b5893f02SDimitry Andric } else if (HasStr1 && !HasStr2) {
419*b5893f02SDimitry Andric Len1 = std::min(Len1, Length);
420*b5893f02SDimitry Andric if (canTransformToMemCmp(CI, Str2P, Len1, DL))
421*b5893f02SDimitry Andric return emitMemCmp(
422*b5893f02SDimitry Andric Str1P, Str2P,
423*b5893f02SDimitry Andric ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len1), B, DL,
424*b5893f02SDimitry Andric TLI);
425*b5893f02SDimitry Andric }
426*b5893f02SDimitry Andric
42791bc56edSDimitry Andric return nullptr;
4283861d79fSDimitry Andric }
4293861d79fSDimitry Andric
optimizeStrCpy(CallInst * CI,IRBuilder<> & B)43039d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStrCpy(CallInst *CI, IRBuilder<> &B) {
4313861d79fSDimitry Andric Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
4323861d79fSDimitry Andric if (Dst == Src) // strcpy(x,x) -> x
4333861d79fSDimitry Andric return Src;
4343861d79fSDimitry Andric
4353861d79fSDimitry Andric // See if we can get the length of the input string.
4363861d79fSDimitry Andric uint64_t Len = GetStringLength(Src);
43739d628a0SDimitry Andric if (Len == 0)
43839d628a0SDimitry Andric return nullptr;
4393861d79fSDimitry Andric
4403861d79fSDimitry Andric // We have enough information to now generate the memcpy call to do the
4413861d79fSDimitry Andric // copy for us. Make a memcpy to copy the nul byte with align = 1.
4424ba319b5SDimitry Andric B.CreateMemCpy(Dst, 1, Src, 1,
4434ba319b5SDimitry Andric ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len));
4443861d79fSDimitry Andric return Dst;
4453861d79fSDimitry Andric }
4463861d79fSDimitry Andric
optimizeStpCpy(CallInst * CI,IRBuilder<> & B)44739d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStpCpy(CallInst *CI, IRBuilder<> &B) {
44839d628a0SDimitry Andric Function *Callee = CI->getCalledFunction();
4493861d79fSDimitry Andric Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
4503861d79fSDimitry Andric if (Dst == Src) { // stpcpy(x,x) -> x+strlen(x)
4513ca95b02SDimitry Andric Value *StrLen = emitStrLen(Src, B, DL, TLI);
452ff0cc061SDimitry Andric return StrLen ? B.CreateInBoundsGEP(B.getInt8Ty(), Dst, StrLen) : nullptr;
4533861d79fSDimitry Andric }
4543861d79fSDimitry Andric
4553861d79fSDimitry Andric // See if we can get the length of the input string.
4563861d79fSDimitry Andric uint64_t Len = GetStringLength(Src);
45739d628a0SDimitry Andric if (Len == 0)
45839d628a0SDimitry Andric return nullptr;
4593861d79fSDimitry Andric
4607d523365SDimitry Andric Type *PT = Callee->getFunctionType()->getParamType(0);
461ff0cc061SDimitry Andric Value *LenV = ConstantInt::get(DL.getIntPtrType(PT), Len);
4624d0b32cdSDimitry Andric Value *DstEnd = B.CreateGEP(B.getInt8Ty(), Dst,
4634d0b32cdSDimitry Andric ConstantInt::get(DL.getIntPtrType(PT), Len - 1));
4643861d79fSDimitry Andric
4653861d79fSDimitry Andric // We have enough information to now generate the memcpy call to do the
4663861d79fSDimitry Andric // copy for us. Make a memcpy to copy the nul byte with align = 1.
4674ba319b5SDimitry Andric B.CreateMemCpy(Dst, 1, Src, 1, LenV);
4683861d79fSDimitry Andric return DstEnd;
4693861d79fSDimitry Andric }
4703861d79fSDimitry Andric
optimizeStrNCpy(CallInst * CI,IRBuilder<> & B)47139d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStrNCpy(CallInst *CI, IRBuilder<> &B) {
47239d628a0SDimitry Andric Function *Callee = CI->getCalledFunction();
4733861d79fSDimitry Andric Value *Dst = CI->getArgOperand(0);
4743861d79fSDimitry Andric Value *Src = CI->getArgOperand(1);
4753861d79fSDimitry Andric Value *LenOp = CI->getArgOperand(2);
4763861d79fSDimitry Andric
4773861d79fSDimitry Andric // See if we can get the length of the input string.
4783861d79fSDimitry Andric uint64_t SrcLen = GetStringLength(Src);
47939d628a0SDimitry Andric if (SrcLen == 0)
48039d628a0SDimitry Andric return nullptr;
4813861d79fSDimitry Andric --SrcLen;
4823861d79fSDimitry Andric
4833861d79fSDimitry Andric if (SrcLen == 0) {
4844ba319b5SDimitry Andric // strncpy(x, "", y) -> memset(align 1 x, '\0', y)
4853861d79fSDimitry Andric B.CreateMemSet(Dst, B.getInt8('\0'), LenOp, 1);
4863861d79fSDimitry Andric return Dst;
4873861d79fSDimitry Andric }
4883861d79fSDimitry Andric
4893861d79fSDimitry Andric uint64_t Len;
4903861d79fSDimitry Andric if (ConstantInt *LengthArg = dyn_cast<ConstantInt>(LenOp))
4913861d79fSDimitry Andric Len = LengthArg->getZExtValue();
4923861d79fSDimitry Andric else
49391bc56edSDimitry Andric return nullptr;
4943861d79fSDimitry Andric
49539d628a0SDimitry Andric if (Len == 0)
49639d628a0SDimitry Andric return Dst; // strncpy(x, y, 0) -> x
4973861d79fSDimitry Andric
4983861d79fSDimitry Andric // Let strncpy handle the zero padding
49939d628a0SDimitry Andric if (Len > SrcLen + 1)
50039d628a0SDimitry Andric return nullptr;
5013861d79fSDimitry Andric
5027d523365SDimitry Andric Type *PT = Callee->getFunctionType()->getParamType(0);
5034ba319b5SDimitry Andric // strncpy(x, s, c) -> memcpy(align 1 x, align 1 s, c) [s and c are constant]
5044ba319b5SDimitry Andric B.CreateMemCpy(Dst, 1, Src, 1, ConstantInt::get(DL.getIntPtrType(PT), Len));
5053861d79fSDimitry Andric
5063861d79fSDimitry Andric return Dst;
5073861d79fSDimitry Andric }
5083861d79fSDimitry Andric
optimizeStringLength(CallInst * CI,IRBuilder<> & B,unsigned CharSize)509d8866befSDimitry Andric Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilder<> &B,
510d8866befSDimitry Andric unsigned CharSize) {
5113861d79fSDimitry Andric Value *Src = CI->getArgOperand(0);
5123861d79fSDimitry Andric
5133861d79fSDimitry Andric // Constant folding: strlen("xyz") -> 3
514d8866befSDimitry Andric if (uint64_t Len = GetStringLength(Src, CharSize))
5153861d79fSDimitry Andric return ConstantInt::get(CI->getType(), Len - 1);
5163861d79fSDimitry Andric
5173ca95b02SDimitry Andric // If s is a constant pointer pointing to a string literal, we can fold
5183ca95b02SDimitry Andric // strlen(s + x) to strlen(s) - x, when x is known to be in the range
5193ca95b02SDimitry Andric // [0, strlen(s)] or the string has a single null terminator '\0' at the end.
5203ca95b02SDimitry Andric // We only try to simplify strlen when the pointer s points to an array
5213ca95b02SDimitry Andric // of i8. Otherwise, we would need to scale the offset x before doing the
5223ca95b02SDimitry Andric // subtraction. This will make the optimization more complex, and it's not
5233ca95b02SDimitry Andric // very useful because calling strlen for a pointer of other types is
5243ca95b02SDimitry Andric // very uncommon.
5253ca95b02SDimitry Andric if (GEPOperator *GEP = dyn_cast<GEPOperator>(Src)) {
526d8866befSDimitry Andric if (!isGEPBasedOnPointerToString(GEP, CharSize))
5273ca95b02SDimitry Andric return nullptr;
5283ca95b02SDimitry Andric
529d8866befSDimitry Andric ConstantDataArraySlice Slice;
530d8866befSDimitry Andric if (getConstantDataArrayInfo(GEP->getOperand(0), Slice, CharSize)) {
531d8866befSDimitry Andric uint64_t NullTermIdx;
532d8866befSDimitry Andric if (Slice.Array == nullptr) {
533d8866befSDimitry Andric NullTermIdx = 0;
534d8866befSDimitry Andric } else {
535d8866befSDimitry Andric NullTermIdx = ~((uint64_t)0);
536d8866befSDimitry Andric for (uint64_t I = 0, E = Slice.Length; I < E; ++I) {
537d8866befSDimitry Andric if (Slice.Array->getElementAsInteger(I + Slice.Offset) == 0) {
538d8866befSDimitry Andric NullTermIdx = I;
539d8866befSDimitry Andric break;
540d8866befSDimitry Andric }
541d8866befSDimitry Andric }
5423ca95b02SDimitry Andric // If the string does not have '\0', leave it to strlen to compute
5433ca95b02SDimitry Andric // its length.
544d8866befSDimitry Andric if (NullTermIdx == ~((uint64_t)0))
5453ca95b02SDimitry Andric return nullptr;
546d8866befSDimitry Andric }
5473ca95b02SDimitry Andric
5483ca95b02SDimitry Andric Value *Offset = GEP->getOperand(2);
549302affcbSDimitry Andric KnownBits Known = computeKnownBits(Offset, DL, 0, nullptr, CI, nullptr);
55051690af2SDimitry Andric Known.Zero.flipAllBits();
551d8866befSDimitry Andric uint64_t ArrSize =
5523ca95b02SDimitry Andric cast<ArrayType>(GEP->getSourceElementType())->getNumElements();
5533ca95b02SDimitry Andric
5543ca95b02SDimitry Andric // KnownZero's bits are flipped, so zeros in KnownZero now represent
5553ca95b02SDimitry Andric // bits known to be zeros in Offset, and ones in KnowZero represent
5563ca95b02SDimitry Andric // bits unknown in Offset. Therefore, Offset is known to be in range
5573ca95b02SDimitry Andric // [0, NullTermIdx] when the flipped KnownZero is non-negative and
5583ca95b02SDimitry Andric // unsigned-less-than NullTermIdx.
5593ca95b02SDimitry Andric //
5603ca95b02SDimitry Andric // If Offset is not provably in the range [0, NullTermIdx], we can still
5613ca95b02SDimitry Andric // optimize if we can prove that the program has undefined behavior when
5623ca95b02SDimitry Andric // Offset is outside that range. That is the case when GEP->getOperand(0)
5633ca95b02SDimitry Andric // is a pointer to an object whose memory extent is NullTermIdx+1.
56451690af2SDimitry Andric if ((Known.Zero.isNonNegative() && Known.Zero.ule(NullTermIdx)) ||
5653ca95b02SDimitry Andric (GEP->isInBounds() && isa<GlobalVariable>(GEP->getOperand(0)) &&
566d8866befSDimitry Andric NullTermIdx == ArrSize - 1)) {
567d8866befSDimitry Andric Offset = B.CreateSExtOrTrunc(Offset, CI->getType());
5683ca95b02SDimitry Andric return B.CreateSub(ConstantInt::get(CI->getType(), NullTermIdx),
5693ca95b02SDimitry Andric Offset);
5703ca95b02SDimitry Andric }
571d8866befSDimitry Andric }
5723ca95b02SDimitry Andric
5733ca95b02SDimitry Andric return nullptr;
5743ca95b02SDimitry Andric }
5753ca95b02SDimitry Andric
57691bc56edSDimitry Andric // strlen(x?"foo":"bars") --> x ? 3 : 4
57791bc56edSDimitry Andric if (SelectInst *SI = dyn_cast<SelectInst>(Src)) {
578d8866befSDimitry Andric uint64_t LenTrue = GetStringLength(SI->getTrueValue(), CharSize);
579d8866befSDimitry Andric uint64_t LenFalse = GetStringLength(SI->getFalseValue(), CharSize);
58091bc56edSDimitry Andric if (LenTrue && LenFalse) {
5812cab237bSDimitry Andric ORE.emit([&]() {
5822cab237bSDimitry Andric return OptimizationRemark("instcombine", "simplify-libcalls", CI)
5832cab237bSDimitry Andric << "folded strlen(select) to select of constants";
5842cab237bSDimitry Andric });
58591bc56edSDimitry Andric return B.CreateSelect(SI->getCondition(),
58691bc56edSDimitry Andric ConstantInt::get(CI->getType(), LenTrue - 1),
58791bc56edSDimitry Andric ConstantInt::get(CI->getType(), LenFalse - 1));
58891bc56edSDimitry Andric }
58991bc56edSDimitry Andric }
59091bc56edSDimitry Andric
5913861d79fSDimitry Andric // strlen(x) != 0 --> *x != 0
5923861d79fSDimitry Andric // strlen(x) == 0 --> *x == 0
5933861d79fSDimitry Andric if (isOnlyUsedInZeroEqualityComparison(CI))
5943861d79fSDimitry Andric return B.CreateZExt(B.CreateLoad(Src, "strlenfirst"), CI->getType());
59591bc56edSDimitry Andric
59691bc56edSDimitry Andric return nullptr;
5973861d79fSDimitry Andric }
5983861d79fSDimitry Andric
optimizeStrLen(CallInst * CI,IRBuilder<> & B)599d8866befSDimitry Andric Value *LibCallSimplifier::optimizeStrLen(CallInst *CI, IRBuilder<> &B) {
600d8866befSDimitry Andric return optimizeStringLength(CI, B, 8);
601d8866befSDimitry Andric }
602d8866befSDimitry Andric
optimizeWcslen(CallInst * CI,IRBuilder<> & B)603d8866befSDimitry Andric Value *LibCallSimplifier::optimizeWcslen(CallInst *CI, IRBuilder<> &B) {
6044ba319b5SDimitry Andric Module &M = *CI->getModule();
605d8866befSDimitry Andric unsigned WCharSize = TLI->getWCharSize(M) * 8;
6062cab237bSDimitry Andric // We cannot perform this optimization without wchar_size metadata.
6072cab237bSDimitry Andric if (WCharSize == 0)
6082cab237bSDimitry Andric return nullptr;
609d8866befSDimitry Andric
610d8866befSDimitry Andric return optimizeStringLength(CI, B, WCharSize);
611d8866befSDimitry Andric }
612d8866befSDimitry Andric
optimizeStrPBrk(CallInst * CI,IRBuilder<> & B)61339d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStrPBrk(CallInst *CI, IRBuilder<> &B) {
6143861d79fSDimitry Andric StringRef S1, S2;
6153861d79fSDimitry Andric bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
6163861d79fSDimitry Andric bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
6173861d79fSDimitry Andric
61839d628a0SDimitry Andric // strpbrk(s, "") -> nullptr
61939d628a0SDimitry Andric // strpbrk("", s) -> nullptr
6203861d79fSDimitry Andric if ((HasS1 && S1.empty()) || (HasS2 && S2.empty()))
6213861d79fSDimitry Andric return Constant::getNullValue(CI->getType());
6223861d79fSDimitry Andric
6233861d79fSDimitry Andric // Constant folding.
6243861d79fSDimitry Andric if (HasS1 && HasS2) {
6253861d79fSDimitry Andric size_t I = S1.find_first_of(S2);
626f785676fSDimitry Andric if (I == StringRef::npos) // No match.
6273861d79fSDimitry Andric return Constant::getNullValue(CI->getType());
6283861d79fSDimitry Andric
6294d0b32cdSDimitry Andric return B.CreateGEP(B.getInt8Ty(), CI->getArgOperand(0), B.getInt64(I),
6304d0b32cdSDimitry Andric "strpbrk");
6313861d79fSDimitry Andric }
6323861d79fSDimitry Andric
6333861d79fSDimitry Andric // strpbrk(s, "a") -> strchr(s, 'a')
634ff0cc061SDimitry Andric if (HasS2 && S2.size() == 1)
6353ca95b02SDimitry Andric return emitStrChr(CI->getArgOperand(0), S2[0], B, TLI);
6363861d79fSDimitry Andric
63791bc56edSDimitry Andric return nullptr;
6383861d79fSDimitry Andric }
6393861d79fSDimitry Andric
optimizeStrTo(CallInst * CI,IRBuilder<> & B)64039d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStrTo(CallInst *CI, IRBuilder<> &B) {
6413861d79fSDimitry Andric Value *EndPtr = CI->getArgOperand(1);
6423861d79fSDimitry Andric if (isa<ConstantPointerNull>(EndPtr)) {
6433861d79fSDimitry Andric // With a null EndPtr, this function won't capture the main argument.
6443861d79fSDimitry Andric // It would be readonly too, except that it still may write to errno.
645f37b6182SDimitry Andric CI->addParamAttr(0, Attribute::NoCapture);
6463861d79fSDimitry Andric }
6473861d79fSDimitry Andric
64891bc56edSDimitry Andric return nullptr;
6493861d79fSDimitry Andric }
6503861d79fSDimitry Andric
optimizeStrSpn(CallInst * CI,IRBuilder<> & B)65139d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStrSpn(CallInst *CI, IRBuilder<> &B) {
6523861d79fSDimitry Andric StringRef S1, S2;
6533861d79fSDimitry Andric bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
6543861d79fSDimitry Andric bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
6553861d79fSDimitry Andric
6563861d79fSDimitry Andric // strspn(s, "") -> 0
6573861d79fSDimitry Andric // strspn("", s) -> 0
6583861d79fSDimitry Andric if ((HasS1 && S1.empty()) || (HasS2 && S2.empty()))
6593861d79fSDimitry Andric return Constant::getNullValue(CI->getType());
6603861d79fSDimitry Andric
6613861d79fSDimitry Andric // Constant folding.
6623861d79fSDimitry Andric if (HasS1 && HasS2) {
6633861d79fSDimitry Andric size_t Pos = S1.find_first_not_of(S2);
66439d628a0SDimitry Andric if (Pos == StringRef::npos)
66539d628a0SDimitry Andric Pos = S1.size();
6663861d79fSDimitry Andric return ConstantInt::get(CI->getType(), Pos);
6673861d79fSDimitry Andric }
6683861d79fSDimitry Andric
66991bc56edSDimitry Andric return nullptr;
6703861d79fSDimitry Andric }
6713861d79fSDimitry Andric
optimizeStrCSpn(CallInst * CI,IRBuilder<> & B)67239d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStrCSpn(CallInst *CI, IRBuilder<> &B) {
6733861d79fSDimitry Andric StringRef S1, S2;
6743861d79fSDimitry Andric bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
6753861d79fSDimitry Andric bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
6763861d79fSDimitry Andric
6773861d79fSDimitry Andric // strcspn("", s) -> 0
6783861d79fSDimitry Andric if (HasS1 && S1.empty())
6793861d79fSDimitry Andric return Constant::getNullValue(CI->getType());
6803861d79fSDimitry Andric
6813861d79fSDimitry Andric // Constant folding.
6823861d79fSDimitry Andric if (HasS1 && HasS2) {
6833861d79fSDimitry Andric size_t Pos = S1.find_first_of(S2);
68439d628a0SDimitry Andric if (Pos == StringRef::npos)
68539d628a0SDimitry Andric Pos = S1.size();
6863861d79fSDimitry Andric return ConstantInt::get(CI->getType(), Pos);
6873861d79fSDimitry Andric }
6883861d79fSDimitry Andric
6893861d79fSDimitry Andric // strcspn(s, "") -> strlen(s)
690ff0cc061SDimitry Andric if (HasS2 && S2.empty())
6913ca95b02SDimitry Andric return emitStrLen(CI->getArgOperand(0), B, DL, TLI);
6923861d79fSDimitry Andric
69391bc56edSDimitry Andric return nullptr;
6943861d79fSDimitry Andric }
6953861d79fSDimitry Andric
optimizeStrStr(CallInst * CI,IRBuilder<> & B)69639d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStrStr(CallInst *CI, IRBuilder<> &B) {
6973861d79fSDimitry Andric // fold strstr(x, x) -> x.
6983861d79fSDimitry Andric if (CI->getArgOperand(0) == CI->getArgOperand(1))
6993861d79fSDimitry Andric return B.CreateBitCast(CI->getArgOperand(0), CI->getType());
7003861d79fSDimitry Andric
7013861d79fSDimitry Andric // fold strstr(a, b) == a -> strncmp(a, b, strlen(b)) == 0
702ff0cc061SDimitry Andric if (isOnlyUsedInEqualityComparison(CI, CI->getArgOperand(0))) {
7033ca95b02SDimitry Andric Value *StrLen = emitStrLen(CI->getArgOperand(1), B, DL, TLI);
7043861d79fSDimitry Andric if (!StrLen)
70591bc56edSDimitry Andric return nullptr;
7063ca95b02SDimitry Andric Value *StrNCmp = emitStrNCmp(CI->getArgOperand(0), CI->getArgOperand(1),
70791bc56edSDimitry Andric StrLen, B, DL, TLI);
7083861d79fSDimitry Andric if (!StrNCmp)
70991bc56edSDimitry Andric return nullptr;
71091bc56edSDimitry Andric for (auto UI = CI->user_begin(), UE = CI->user_end(); UI != UE;) {
7113861d79fSDimitry Andric ICmpInst *Old = cast<ICmpInst>(*UI++);
71239d628a0SDimitry Andric Value *Cmp =
71339d628a0SDimitry Andric B.CreateICmp(Old->getPredicate(), StrNCmp,
71439d628a0SDimitry Andric ConstantInt::getNullValue(StrNCmp->getType()), "cmp");
71539d628a0SDimitry Andric replaceAllUsesWith(Old, Cmp);
7163861d79fSDimitry Andric }
7173861d79fSDimitry Andric return CI;
7183861d79fSDimitry Andric }
7193861d79fSDimitry Andric
7203861d79fSDimitry Andric // See if either input string is a constant string.
7213861d79fSDimitry Andric StringRef SearchStr, ToFindStr;
7223861d79fSDimitry Andric bool HasStr1 = getConstantStringInfo(CI->getArgOperand(0), SearchStr);
7233861d79fSDimitry Andric bool HasStr2 = getConstantStringInfo(CI->getArgOperand(1), ToFindStr);
7243861d79fSDimitry Andric
7253861d79fSDimitry Andric // fold strstr(x, "") -> x.
7263861d79fSDimitry Andric if (HasStr2 && ToFindStr.empty())
7273861d79fSDimitry Andric return B.CreateBitCast(CI->getArgOperand(0), CI->getType());
7283861d79fSDimitry Andric
7293861d79fSDimitry Andric // If both strings are known, constant fold it.
7303861d79fSDimitry Andric if (HasStr1 && HasStr2) {
731f785676fSDimitry Andric size_t Offset = SearchStr.find(ToFindStr);
7323861d79fSDimitry Andric
7333861d79fSDimitry Andric if (Offset == StringRef::npos) // strstr("foo", "bar") -> null
7343861d79fSDimitry Andric return Constant::getNullValue(CI->getType());
7353861d79fSDimitry Andric
7363861d79fSDimitry Andric // strstr("abcd", "bc") -> gep((char*)"abcd", 1)
7373ca95b02SDimitry Andric Value *Result = castToCStr(CI->getArgOperand(0), B);
7383861d79fSDimitry Andric Result = B.CreateConstInBoundsGEP1_64(Result, Offset, "strstr");
7393861d79fSDimitry Andric return B.CreateBitCast(Result, CI->getType());
7403861d79fSDimitry Andric }
7413861d79fSDimitry Andric
7423861d79fSDimitry Andric // fold strstr(x, "y") -> strchr(x, 'y').
7433861d79fSDimitry Andric if (HasStr2 && ToFindStr.size() == 1) {
7443ca95b02SDimitry Andric Value *StrChr = emitStrChr(CI->getArgOperand(0), ToFindStr[0], B, TLI);
74591bc56edSDimitry Andric return StrChr ? B.CreateBitCast(StrChr, CI->getType()) : nullptr;
7463861d79fSDimitry Andric }
74791bc56edSDimitry Andric return nullptr;
7483861d79fSDimitry Andric }
7493861d79fSDimitry Andric
optimizeMemChr(CallInst * CI,IRBuilder<> & B)750ff0cc061SDimitry Andric Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilder<> &B) {
751ff0cc061SDimitry Andric Value *SrcStr = CI->getArgOperand(0);
752ff0cc061SDimitry Andric ConstantInt *CharC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
753ff0cc061SDimitry Andric ConstantInt *LenC = dyn_cast<ConstantInt>(CI->getArgOperand(2));
754ff0cc061SDimitry Andric
755ff0cc061SDimitry Andric // memchr(x, y, 0) -> null
756c4394386SDimitry Andric if (LenC && LenC->isZero())
757ff0cc061SDimitry Andric return Constant::getNullValue(CI->getType());
758ff0cc061SDimitry Andric
759ff0cc061SDimitry Andric // From now on we need at least constant length and string.
760ff0cc061SDimitry Andric StringRef Str;
761ff0cc061SDimitry Andric if (!LenC || !getConstantStringInfo(SrcStr, Str, 0, /*TrimAtNul=*/false))
762ff0cc061SDimitry Andric return nullptr;
763ff0cc061SDimitry Andric
764ff0cc061SDimitry Andric // Truncate the string to LenC. If Str is smaller than LenC we will still only
765ff0cc061SDimitry Andric // scan the string, as reading past the end of it is undefined and we can just
766ff0cc061SDimitry Andric // return null if we don't find the char.
767ff0cc061SDimitry Andric Str = Str.substr(0, LenC->getZExtValue());
768ff0cc061SDimitry Andric
769ff0cc061SDimitry Andric // If the char is variable but the input str and length are not we can turn
770ff0cc061SDimitry Andric // this memchr call into a simple bit field test. Of course this only works
771ff0cc061SDimitry Andric // when the return value is only checked against null.
772ff0cc061SDimitry Andric //
773ff0cc061SDimitry Andric // It would be really nice to reuse switch lowering here but we can't change
774ff0cc061SDimitry Andric // the CFG at this point.
775ff0cc061SDimitry Andric //
776ff0cc061SDimitry Andric // memchr("\r\n", C, 2) != nullptr -> (C & ((1 << '\r') | (1 << '\n'))) != 0
777ff0cc061SDimitry Andric // after bounds check.
778ff0cc061SDimitry Andric if (!CharC && !Str.empty() && isOnlyUsedInZeroEqualityComparison(CI)) {
779ff0cc061SDimitry Andric unsigned char Max =
780ff0cc061SDimitry Andric *std::max_element(reinterpret_cast<const unsigned char *>(Str.begin()),
781ff0cc061SDimitry Andric reinterpret_cast<const unsigned char *>(Str.end()));
782ff0cc061SDimitry Andric
783ff0cc061SDimitry Andric // Make sure the bit field we're about to create fits in a register on the
784ff0cc061SDimitry Andric // target.
785ff0cc061SDimitry Andric // FIXME: On a 64 bit architecture this prevents us from using the
786ff0cc061SDimitry Andric // interesting range of alpha ascii chars. We could do better by emitting
787ff0cc061SDimitry Andric // two bitfields or shifting the range by 64 if no lower chars are used.
788ff0cc061SDimitry Andric if (!DL.fitsInLegalInteger(Max + 1))
789ff0cc061SDimitry Andric return nullptr;
790ff0cc061SDimitry Andric
791ff0cc061SDimitry Andric // For the bit field use a power-of-2 type with at least 8 bits to avoid
792ff0cc061SDimitry Andric // creating unnecessary illegal types.
793ff0cc061SDimitry Andric unsigned char Width = NextPowerOf2(std::max((unsigned char)7, Max));
794ff0cc061SDimitry Andric
795ff0cc061SDimitry Andric // Now build the bit field.
796ff0cc061SDimitry Andric APInt Bitfield(Width, 0);
797ff0cc061SDimitry Andric for (char C : Str)
798ff0cc061SDimitry Andric Bitfield.setBit((unsigned char)C);
799ff0cc061SDimitry Andric Value *BitfieldC = B.getInt(Bitfield);
800ff0cc061SDimitry Andric
801*b5893f02SDimitry Andric // Adjust width of "C" to the bitfield width, then mask off the high bits.
802ff0cc061SDimitry Andric Value *C = B.CreateZExtOrTrunc(CI->getArgOperand(1), BitfieldC->getType());
803*b5893f02SDimitry Andric C = B.CreateAnd(C, B.getIntN(Width, 0xFF));
804*b5893f02SDimitry Andric
805*b5893f02SDimitry Andric // First check that the bit field access is within bounds.
806ff0cc061SDimitry Andric Value *Bounds = B.CreateICmp(ICmpInst::ICMP_ULT, C, B.getIntN(Width, Width),
807ff0cc061SDimitry Andric "memchr.bounds");
808ff0cc061SDimitry Andric
809ff0cc061SDimitry Andric // Create code that checks if the given bit is set in the field.
810ff0cc061SDimitry Andric Value *Shl = B.CreateShl(B.getIntN(Width, 1ULL), C);
811ff0cc061SDimitry Andric Value *Bits = B.CreateIsNotNull(B.CreateAnd(Shl, BitfieldC), "memchr.bits");
812ff0cc061SDimitry Andric
813ff0cc061SDimitry Andric // Finally merge both checks and cast to pointer type. The inttoptr
814ff0cc061SDimitry Andric // implicitly zexts the i1 to intptr type.
815ff0cc061SDimitry Andric return B.CreateIntToPtr(B.CreateAnd(Bounds, Bits, "memchr"), CI->getType());
816ff0cc061SDimitry Andric }
817ff0cc061SDimitry Andric
818ff0cc061SDimitry Andric // Check if all arguments are constants. If so, we can constant fold.
819ff0cc061SDimitry Andric if (!CharC)
820ff0cc061SDimitry Andric return nullptr;
821ff0cc061SDimitry Andric
822ff0cc061SDimitry Andric // Compute the offset.
823ff0cc061SDimitry Andric size_t I = Str.find(CharC->getSExtValue() & 0xFF);
824ff0cc061SDimitry Andric if (I == StringRef::npos) // Didn't find the char. memchr returns null.
825ff0cc061SDimitry Andric return Constant::getNullValue(CI->getType());
826ff0cc061SDimitry Andric
827ff0cc061SDimitry Andric // memchr(s+n,c,l) -> gep(s+n+i,c)
828ff0cc061SDimitry Andric return B.CreateGEP(B.getInt8Ty(), SrcStr, B.getInt64(I), "memchr");
829ff0cc061SDimitry Andric }
830ff0cc061SDimitry Andric
optimizeMemCmp(CallInst * CI,IRBuilder<> & B)83139d628a0SDimitry Andric Value *LibCallSimplifier::optimizeMemCmp(CallInst *CI, IRBuilder<> &B) {
8323861d79fSDimitry Andric Value *LHS = CI->getArgOperand(0), *RHS = CI->getArgOperand(1);
8333861d79fSDimitry Andric
8343861d79fSDimitry Andric if (LHS == RHS) // memcmp(s,s,x) -> 0
8353861d79fSDimitry Andric return Constant::getNullValue(CI->getType());
8363861d79fSDimitry Andric
8373861d79fSDimitry Andric // Make sure we have a constant length.
8383861d79fSDimitry Andric ConstantInt *LenC = dyn_cast<ConstantInt>(CI->getArgOperand(2));
83939d628a0SDimitry Andric if (!LenC)
84039d628a0SDimitry Andric return nullptr;
8413861d79fSDimitry Andric
842db17bf38SDimitry Andric uint64_t Len = LenC->getZExtValue();
8433861d79fSDimitry Andric if (Len == 0) // memcmp(s1,s2,0) -> 0
8443861d79fSDimitry Andric return Constant::getNullValue(CI->getType());
8453861d79fSDimitry Andric
8463861d79fSDimitry Andric // memcmp(S1,S2,1) -> *(unsigned char*)LHS - *(unsigned char*)RHS
8473861d79fSDimitry Andric if (Len == 1) {
8483ca95b02SDimitry Andric Value *LHSV = B.CreateZExt(B.CreateLoad(castToCStr(LHS, B), "lhsc"),
8493861d79fSDimitry Andric CI->getType(), "lhsv");
8503ca95b02SDimitry Andric Value *RHSV = B.CreateZExt(B.CreateLoad(castToCStr(RHS, B), "rhsc"),
8513861d79fSDimitry Andric CI->getType(), "rhsv");
8523861d79fSDimitry Andric return B.CreateSub(LHSV, RHSV, "chardiff");
8533861d79fSDimitry Andric }
8543861d79fSDimitry Andric
8557d523365SDimitry Andric // memcmp(S1,S2,N/8)==0 -> (*(intN_t*)S1 != *(intN_t*)S2)==0
8562cab237bSDimitry Andric // TODO: The case where both inputs are constants does not need to be limited
8572cab237bSDimitry Andric // to legal integers or equality comparison. See block below this.
8587d523365SDimitry Andric if (DL.isLegalInteger(Len * 8) && isOnlyUsedInZeroEqualityComparison(CI)) {
8597d523365SDimitry Andric IntegerType *IntType = IntegerType::get(CI->getContext(), Len * 8);
8607d523365SDimitry Andric unsigned PrefAlignment = DL.getPrefTypeAlignment(IntType);
8617d523365SDimitry Andric
8622cab237bSDimitry Andric // First, see if we can fold either argument to a constant.
8632cab237bSDimitry Andric Value *LHSV = nullptr;
8642cab237bSDimitry Andric if (auto *LHSC = dyn_cast<Constant>(LHS)) {
8652cab237bSDimitry Andric LHSC = ConstantExpr::getBitCast(LHSC, IntType->getPointerTo());
8662cab237bSDimitry Andric LHSV = ConstantFoldLoadFromConstPtr(LHSC, IntType, DL);
8672cab237bSDimitry Andric }
8682cab237bSDimitry Andric Value *RHSV = nullptr;
8692cab237bSDimitry Andric if (auto *RHSC = dyn_cast<Constant>(RHS)) {
8702cab237bSDimitry Andric RHSC = ConstantExpr::getBitCast(RHSC, IntType->getPointerTo());
8712cab237bSDimitry Andric RHSV = ConstantFoldLoadFromConstPtr(RHSC, IntType, DL);
8722cab237bSDimitry Andric }
8737d523365SDimitry Andric
8742cab237bSDimitry Andric // Don't generate unaligned loads. If either source is constant data,
8752cab237bSDimitry Andric // alignment doesn't matter for that source because there is no load.
8762cab237bSDimitry Andric if ((LHSV || getKnownAlignment(LHS, DL, CI) >= PrefAlignment) &&
8772cab237bSDimitry Andric (RHSV || getKnownAlignment(RHS, DL, CI) >= PrefAlignment)) {
8782cab237bSDimitry Andric if (!LHSV) {
8797d523365SDimitry Andric Type *LHSPtrTy =
8807d523365SDimitry Andric IntType->getPointerTo(LHS->getType()->getPointerAddressSpace());
8812cab237bSDimitry Andric LHSV = B.CreateLoad(B.CreateBitCast(LHS, LHSPtrTy), "lhsv");
8822cab237bSDimitry Andric }
8832cab237bSDimitry Andric if (!RHSV) {
8847d523365SDimitry Andric Type *RHSPtrTy =
8857d523365SDimitry Andric IntType->getPointerTo(RHS->getType()->getPointerAddressSpace());
8862cab237bSDimitry Andric RHSV = B.CreateLoad(B.CreateBitCast(RHS, RHSPtrTy), "rhsv");
8872cab237bSDimitry Andric }
8887d523365SDimitry Andric return B.CreateZExt(B.CreateICmpNE(LHSV, RHSV), CI->getType(), "memcmp");
8897d523365SDimitry Andric }
8907d523365SDimitry Andric }
8917d523365SDimitry Andric
8922cab237bSDimitry Andric // Constant folding: memcmp(x, y, Len) -> constant (all arguments are const).
8932cab237bSDimitry Andric // TODO: This is limited to i8 arrays.
8943861d79fSDimitry Andric StringRef LHSStr, RHSStr;
8953861d79fSDimitry Andric if (getConstantStringInfo(LHS, LHSStr) &&
8963861d79fSDimitry Andric getConstantStringInfo(RHS, RHSStr)) {
8973861d79fSDimitry Andric // Make sure we're not reading out-of-bounds memory.
8983861d79fSDimitry Andric if (Len > LHSStr.size() || Len > RHSStr.size())
89991bc56edSDimitry Andric return nullptr;
900139f7f9bSDimitry Andric // Fold the memcmp and normalize the result. This way we get consistent
901139f7f9bSDimitry Andric // results across multiple platforms.
902139f7f9bSDimitry Andric uint64_t Ret = 0;
903139f7f9bSDimitry Andric int Cmp = memcmp(LHSStr.data(), RHSStr.data(), Len);
904139f7f9bSDimitry Andric if (Cmp < 0)
905139f7f9bSDimitry Andric Ret = -1;
906139f7f9bSDimitry Andric else if (Cmp > 0)
907139f7f9bSDimitry Andric Ret = 1;
9083861d79fSDimitry Andric return ConstantInt::get(CI->getType(), Ret);
9093861d79fSDimitry Andric }
9103861d79fSDimitry Andric
91191bc56edSDimitry Andric return nullptr;
9123861d79fSDimitry Andric }
9133861d79fSDimitry Andric
optimizeMemCpy(CallInst * CI,IRBuilder<> & B)91439d628a0SDimitry Andric Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilder<> &B) {
9154ba319b5SDimitry Andric // memcpy(x, y, n) -> llvm.memcpy(align 1 x, align 1 y, n)
9164ba319b5SDimitry Andric B.CreateMemCpy(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1,
9174ba319b5SDimitry Andric CI->getArgOperand(2));
9183861d79fSDimitry Andric return CI->getArgOperand(0);
9193861d79fSDimitry Andric }
9203861d79fSDimitry Andric
optimizeMemMove(CallInst * CI,IRBuilder<> & B)92139d628a0SDimitry Andric Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B) {
9224ba319b5SDimitry Andric // memmove(x, y, n) -> llvm.memmove(align 1 x, align 1 y, n)
9234ba319b5SDimitry Andric B.CreateMemMove(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1,
9244ba319b5SDimitry Andric CI->getArgOperand(2));
9253861d79fSDimitry Andric return CI->getArgOperand(0);
9263861d79fSDimitry Andric }
9273861d79fSDimitry Andric
9283ca95b02SDimitry Andric /// Fold memset[_chk](malloc(n), 0, n) --> calloc(1, n).
foldMallocMemset(CallInst * Memset,IRBuilder<> & B)929*b5893f02SDimitry Andric Value *LibCallSimplifier::foldMallocMemset(CallInst *Memset, IRBuilder<> &B) {
9303ca95b02SDimitry Andric // This has to be a memset of zeros (bzero).
9313ca95b02SDimitry Andric auto *FillValue = dyn_cast<ConstantInt>(Memset->getArgOperand(1));
9323ca95b02SDimitry Andric if (!FillValue || FillValue->getZExtValue() != 0)
9333ca95b02SDimitry Andric return nullptr;
9343ca95b02SDimitry Andric
9353ca95b02SDimitry Andric // TODO: We should handle the case where the malloc has more than one use.
9363ca95b02SDimitry Andric // This is necessary to optimize common patterns such as when the result of
9373ca95b02SDimitry Andric // the malloc is checked against null or when a memset intrinsic is used in
9383ca95b02SDimitry Andric // place of a memset library call.
9393ca95b02SDimitry Andric auto *Malloc = dyn_cast<CallInst>(Memset->getArgOperand(0));
9403ca95b02SDimitry Andric if (!Malloc || !Malloc->hasOneUse())
9413ca95b02SDimitry Andric return nullptr;
9423ca95b02SDimitry Andric
9433ca95b02SDimitry Andric // Is the inner call really malloc()?
9443ca95b02SDimitry Andric Function *InnerCallee = Malloc->getCalledFunction();
94551690af2SDimitry Andric if (!InnerCallee)
94651690af2SDimitry Andric return nullptr;
94751690af2SDimitry Andric
9487a7e6055SDimitry Andric LibFunc Func;
949*b5893f02SDimitry Andric if (!TLI->getLibFunc(*InnerCallee, Func) || !TLI->has(Func) ||
9507a7e6055SDimitry Andric Func != LibFunc_malloc)
9513ca95b02SDimitry Andric return nullptr;
9523ca95b02SDimitry Andric
9533ca95b02SDimitry Andric // The memset must cover the same number of bytes that are malloc'd.
9543ca95b02SDimitry Andric if (Memset->getArgOperand(2) != Malloc->getArgOperand(0))
9553ca95b02SDimitry Andric return nullptr;
9563ca95b02SDimitry Andric
9573ca95b02SDimitry Andric // Replace the malloc with a calloc. We need the data layout to know what the
9583ca95b02SDimitry Andric // actual size of a 'size_t' parameter is.
9593ca95b02SDimitry Andric B.SetInsertPoint(Malloc->getParent(), ++Malloc->getIterator());
9603ca95b02SDimitry Andric const DataLayout &DL = Malloc->getModule()->getDataLayout();
9613ca95b02SDimitry Andric IntegerType *SizeType = DL.getIntPtrType(B.GetInsertBlock()->getContext());
9623ca95b02SDimitry Andric Value *Calloc = emitCalloc(ConstantInt::get(SizeType, 1),
9633ca95b02SDimitry Andric Malloc->getArgOperand(0), Malloc->getAttributes(),
964*b5893f02SDimitry Andric B, *TLI);
9653ca95b02SDimitry Andric if (!Calloc)
9663ca95b02SDimitry Andric return nullptr;
9673ca95b02SDimitry Andric
9683ca95b02SDimitry Andric Malloc->replaceAllUsesWith(Calloc);
969*b5893f02SDimitry Andric eraseFromParent(Malloc);
9703ca95b02SDimitry Andric
9713ca95b02SDimitry Andric return Calloc;
9723ca95b02SDimitry Andric }
9733ca95b02SDimitry Andric
optimizeMemSet(CallInst * CI,IRBuilder<> & B)9743ca95b02SDimitry Andric Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilder<> &B) {
975*b5893f02SDimitry Andric if (auto *Calloc = foldMallocMemset(CI, B))
9763ca95b02SDimitry Andric return Calloc;
9773ca95b02SDimitry Andric
9784ba319b5SDimitry Andric // memset(p, v, n) -> llvm.memset(align 1 p, v, n)
9793861d79fSDimitry Andric Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(), false);
9803861d79fSDimitry Andric B.CreateMemSet(CI->getArgOperand(0), Val, CI->getArgOperand(2), 1);
9813861d79fSDimitry Andric return CI->getArgOperand(0);
9823861d79fSDimitry Andric }
9833861d79fSDimitry Andric
optimizeRealloc(CallInst * CI,IRBuilder<> & B)9844ba319b5SDimitry Andric Value *LibCallSimplifier::optimizeRealloc(CallInst *CI, IRBuilder<> &B) {
9854ba319b5SDimitry Andric if (isa<ConstantPointerNull>(CI->getArgOperand(0)))
9864ba319b5SDimitry Andric return emitMalloc(CI->getArgOperand(1), B, DL, TLI);
9874ba319b5SDimitry Andric
9884ba319b5SDimitry Andric return nullptr;
9894ba319b5SDimitry Andric }
9904ba319b5SDimitry Andric
991139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
992139f7f9bSDimitry Andric // Math Library Optimizations
993139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
994139f7f9bSDimitry Andric
995*b5893f02SDimitry Andric // Replace a libcall \p CI with a call to intrinsic \p IID
replaceUnaryCall(CallInst * CI,IRBuilder<> & B,Intrinsic::ID IID)996*b5893f02SDimitry Andric static Value *replaceUnaryCall(CallInst *CI, IRBuilder<> &B, Intrinsic::ID IID) {
997*b5893f02SDimitry Andric // Propagate fast-math flags from the existing call to the new call.
998*b5893f02SDimitry Andric IRBuilder<>::FastMathFlagGuard Guard(B);
999*b5893f02SDimitry Andric B.setFastMathFlags(CI->getFastMathFlags());
1000*b5893f02SDimitry Andric
1001*b5893f02SDimitry Andric Module *M = CI->getModule();
1002*b5893f02SDimitry Andric Value *V = CI->getArgOperand(0);
1003*b5893f02SDimitry Andric Function *F = Intrinsic::getDeclaration(M, IID, CI->getType());
1004*b5893f02SDimitry Andric CallInst *NewCall = B.CreateCall(F, V);
1005*b5893f02SDimitry Andric NewCall->takeName(CI);
1006*b5893f02SDimitry Andric return NewCall;
1007*b5893f02SDimitry Andric }
1008*b5893f02SDimitry Andric
100939d628a0SDimitry Andric /// Return a variant of Val with float type.
101039d628a0SDimitry Andric /// Currently this works in two cases: If Val is an FPExtension of a float
101139d628a0SDimitry Andric /// value to something bigger, simply return the operand.
101239d628a0SDimitry Andric /// If Val is a ConstantFP but can be converted to a float ConstantFP without
101339d628a0SDimitry Andric /// loss of precision do so.
valueHasFloatPrecision(Value * Val)101439d628a0SDimitry Andric static Value *valueHasFloatPrecision(Value *Val) {
101539d628a0SDimitry Andric if (FPExtInst *Cast = dyn_cast<FPExtInst>(Val)) {
101639d628a0SDimitry Andric Value *Op = Cast->getOperand(0);
101739d628a0SDimitry Andric if (Op->getType()->isFloatTy())
101839d628a0SDimitry Andric return Op;
101939d628a0SDimitry Andric }
102039d628a0SDimitry Andric if (ConstantFP *Const = dyn_cast<ConstantFP>(Val)) {
102139d628a0SDimitry Andric APFloat F = Const->getValueAPF();
102239d628a0SDimitry Andric bool losesInfo;
1023d88c1a5aSDimitry Andric (void)F.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
102439d628a0SDimitry Andric &losesInfo);
102539d628a0SDimitry Andric if (!losesInfo)
102639d628a0SDimitry Andric return ConstantFP::get(Const->getContext(), F);
102739d628a0SDimitry Andric }
102839d628a0SDimitry Andric return nullptr;
102939d628a0SDimitry Andric }
103039d628a0SDimitry Andric
1031*b5893f02SDimitry Andric /// Shrink double -> float functions.
optimizeDoubleFP(CallInst * CI,IRBuilder<> & B,bool isBinary,bool isPrecise=false)1032*b5893f02SDimitry Andric static Value *optimizeDoubleFP(CallInst *CI, IRBuilder<> &B,
1033*b5893f02SDimitry Andric bool isBinary, bool isPrecise = false) {
10343ca95b02SDimitry Andric if (!CI->getType()->isDoubleTy())
103591bc56edSDimitry Andric return nullptr;
1036139f7f9bSDimitry Andric
1037*b5893f02SDimitry Andric // If not all the uses of the function are converted to float, then bail out.
1038*b5893f02SDimitry Andric // This matters if the precision of the result is more important than the
1039*b5893f02SDimitry Andric // precision of the arguments.
1040*b5893f02SDimitry Andric if (isPrecise)
104191bc56edSDimitry Andric for (User *U : CI->users()) {
104291bc56edSDimitry Andric FPTruncInst *Cast = dyn_cast<FPTruncInst>(U);
104391bc56edSDimitry Andric if (!Cast || !Cast->getType()->isFloatTy())
104491bc56edSDimitry Andric return nullptr;
1045139f7f9bSDimitry Andric }
1046139f7f9bSDimitry Andric
1047*b5893f02SDimitry Andric // If this is something like 'g((double) float)', convert to 'gf(float)'.
1048*b5893f02SDimitry Andric Value *V[2];
1049*b5893f02SDimitry Andric V[0] = valueHasFloatPrecision(CI->getArgOperand(0));
1050*b5893f02SDimitry Andric V[1] = isBinary ? valueHasFloatPrecision(CI->getArgOperand(1)) : nullptr;
1051*b5893f02SDimitry Andric if (!V[0] || (isBinary && !V[1]))
105291bc56edSDimitry Andric return nullptr;
1053139f7f9bSDimitry Andric
105451690af2SDimitry Andric // If call isn't an intrinsic, check that it isn't within a function with the
1055*b5893f02SDimitry Andric // same name as the float version of this call, otherwise the result is an
1056*b5893f02SDimitry Andric // infinite loop. For example, from MinGW-w64:
105751690af2SDimitry Andric //
1058*b5893f02SDimitry Andric // float expf(float val) { return (float) exp((double) val); }
1059*b5893f02SDimitry Andric Function *CalleeFn = CI->getCalledFunction();
1060*b5893f02SDimitry Andric StringRef CalleeNm = CalleeFn->getName();
1061*b5893f02SDimitry Andric AttributeList CalleeAt = CalleeFn->getAttributes();
1062*b5893f02SDimitry Andric if (CalleeFn && !CalleeFn->isIntrinsic()) {
1063*b5893f02SDimitry Andric const Function *Fn = CI->getFunction();
1064*b5893f02SDimitry Andric StringRef FnName = Fn->getName();
1065*b5893f02SDimitry Andric if (FnName.back() == 'f' &&
1066*b5893f02SDimitry Andric FnName.size() == (CalleeNm.size() + 1) &&
1067*b5893f02SDimitry Andric FnName.startswith(CalleeNm))
106851690af2SDimitry Andric return nullptr;
106951690af2SDimitry Andric }
107051690af2SDimitry Andric
1071*b5893f02SDimitry Andric // Propagate the math semantics from the current function to the new function.
10724d0b32cdSDimitry Andric IRBuilder<>::FastMathFlagGuard Guard(B);
1073444ed5c5SDimitry Andric B.setFastMathFlags(CI->getFastMathFlags());
10744d0b32cdSDimitry Andric
1075*b5893f02SDimitry Andric // g((double) float) -> (double) gf(float)
1076*b5893f02SDimitry Andric Value *R;
1077*b5893f02SDimitry Andric if (CalleeFn->isIntrinsic()) {
10787d523365SDimitry Andric Module *M = CI->getModule();
1079*b5893f02SDimitry Andric Intrinsic::ID IID = CalleeFn->getIntrinsicID();
1080*b5893f02SDimitry Andric Function *Fn = Intrinsic::getDeclaration(M, IID, B.getFloatTy());
1081*b5893f02SDimitry Andric R = isBinary ? B.CreateCall(Fn, V) : B.CreateCall(Fn, V[0]);
1082*b5893f02SDimitry Andric }
1083*b5893f02SDimitry Andric else
1084*b5893f02SDimitry Andric R = isBinary ? emitBinaryFloatFnCall(V[0], V[1], CalleeNm, B, CalleeAt)
1085*b5893f02SDimitry Andric : emitUnaryFloatFnCall(V[0], CalleeNm, B, CalleeAt);
1086*b5893f02SDimitry Andric
1087*b5893f02SDimitry Andric return B.CreateFPExt(R, B.getDoubleTy());
108839d628a0SDimitry Andric }
108939d628a0SDimitry Andric
1090*b5893f02SDimitry Andric /// Shrink double -> float for unary functions.
optimizeUnaryDoubleFP(CallInst * CI,IRBuilder<> & B,bool isPrecise=false)1091*b5893f02SDimitry Andric static Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilder<> &B,
1092*b5893f02SDimitry Andric bool isPrecise = false) {
1093*b5893f02SDimitry Andric return optimizeDoubleFP(CI, B, false, isPrecise);
1094139f7f9bSDimitry Andric }
1095139f7f9bSDimitry Andric
1096*b5893f02SDimitry Andric /// Shrink double -> float for binary functions.
optimizeBinaryDoubleFP(CallInst * CI,IRBuilder<> & B,bool isPrecise=false)1097*b5893f02SDimitry Andric static Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilder<> &B,
1098*b5893f02SDimitry Andric bool isPrecise = false) {
1099*b5893f02SDimitry Andric return optimizeDoubleFP(CI, B, true, isPrecise);
110091bc56edSDimitry Andric }
110191bc56edSDimitry Andric
11022cab237bSDimitry Andric // cabs(z) -> sqrt((creal(z)*creal(z)) + (cimag(z)*cimag(z)))
optimizeCAbs(CallInst * CI,IRBuilder<> & B)11032cab237bSDimitry Andric Value *LibCallSimplifier::optimizeCAbs(CallInst *CI, IRBuilder<> &B) {
11042cab237bSDimitry Andric if (!CI->isFast())
11052cab237bSDimitry Andric return nullptr;
11062cab237bSDimitry Andric
11072cab237bSDimitry Andric // Propagate fast-math flags from the existing call to new instructions.
11082cab237bSDimitry Andric IRBuilder<>::FastMathFlagGuard Guard(B);
11092cab237bSDimitry Andric B.setFastMathFlags(CI->getFastMathFlags());
11102cab237bSDimitry Andric
11112cab237bSDimitry Andric Value *Real, *Imag;
11122cab237bSDimitry Andric if (CI->getNumArgOperands() == 1) {
11132cab237bSDimitry Andric Value *Op = CI->getArgOperand(0);
11142cab237bSDimitry Andric assert(Op->getType()->isArrayTy() && "Unexpected signature for cabs!");
11152cab237bSDimitry Andric Real = B.CreateExtractValue(Op, 0, "real");
11162cab237bSDimitry Andric Imag = B.CreateExtractValue(Op, 1, "imag");
11172cab237bSDimitry Andric } else {
11182cab237bSDimitry Andric assert(CI->getNumArgOperands() == 2 && "Unexpected signature for cabs!");
11192cab237bSDimitry Andric Real = CI->getArgOperand(0);
11202cab237bSDimitry Andric Imag = CI->getArgOperand(1);
11212cab237bSDimitry Andric }
11222cab237bSDimitry Andric
11232cab237bSDimitry Andric Value *RealReal = B.CreateFMul(Real, Real);
11242cab237bSDimitry Andric Value *ImagImag = B.CreateFMul(Imag, Imag);
11252cab237bSDimitry Andric
11262cab237bSDimitry Andric Function *FSqrt = Intrinsic::getDeclaration(CI->getModule(), Intrinsic::sqrt,
11272cab237bSDimitry Andric CI->getType());
11282cab237bSDimitry Andric return B.CreateCall(FSqrt, B.CreateFAdd(RealReal, ImagImag), "cabs");
11292cab237bSDimitry Andric }
11302cab237bSDimitry Andric
optimizeTrigReflections(CallInst * Call,LibFunc Func,IRBuilder<> & B)1131*b5893f02SDimitry Andric static Value *optimizeTrigReflections(CallInst *Call, LibFunc Func,
1132*b5893f02SDimitry Andric IRBuilder<> &B) {
1133*b5893f02SDimitry Andric if (!isa<FPMathOperator>(Call))
1134*b5893f02SDimitry Andric return nullptr;
1135139f7f9bSDimitry Andric
1136*b5893f02SDimitry Andric IRBuilder<>::FastMathFlagGuard Guard(B);
1137*b5893f02SDimitry Andric B.setFastMathFlags(Call->getFastMathFlags());
1138*b5893f02SDimitry Andric
1139*b5893f02SDimitry Andric // TODO: Can this be shared to also handle LLVM intrinsics?
1140*b5893f02SDimitry Andric Value *X;
1141*b5893f02SDimitry Andric switch (Func) {
1142*b5893f02SDimitry Andric case LibFunc_sin:
1143*b5893f02SDimitry Andric case LibFunc_sinf:
1144*b5893f02SDimitry Andric case LibFunc_sinl:
1145*b5893f02SDimitry Andric case LibFunc_tan:
1146*b5893f02SDimitry Andric case LibFunc_tanf:
1147*b5893f02SDimitry Andric case LibFunc_tanl:
1148*b5893f02SDimitry Andric // sin(-X) --> -sin(X)
1149*b5893f02SDimitry Andric // tan(-X) --> -tan(X)
1150*b5893f02SDimitry Andric if (match(Call->getArgOperand(0), m_OneUse(m_FNeg(m_Value(X)))))
1151*b5893f02SDimitry Andric return B.CreateFNeg(B.CreateCall(Call->getCalledFunction(), X));
1152*b5893f02SDimitry Andric break;
1153*b5893f02SDimitry Andric case LibFunc_cos:
1154*b5893f02SDimitry Andric case LibFunc_cosf:
1155*b5893f02SDimitry Andric case LibFunc_cosl:
1156*b5893f02SDimitry Andric // cos(-X) --> cos(X)
1157*b5893f02SDimitry Andric if (match(Call->getArgOperand(0), m_FNeg(m_Value(X))))
1158*b5893f02SDimitry Andric return B.CreateCall(Call->getCalledFunction(), X, "cos");
1159*b5893f02SDimitry Andric break;
1160*b5893f02SDimitry Andric default:
1161*b5893f02SDimitry Andric break;
1162139f7f9bSDimitry Andric }
1163*b5893f02SDimitry Andric return nullptr;
1164139f7f9bSDimitry Andric }
1165139f7f9bSDimitry Andric
getPow(Value * InnerChain[33],unsigned Exp,IRBuilder<> & B)11667d523365SDimitry Andric static Value *getPow(Value *InnerChain[33], unsigned Exp, IRBuilder<> &B) {
11677d523365SDimitry Andric // Multiplications calculated using Addition Chains.
11687d523365SDimitry Andric // Refer: http://wwwhomes.uni-bielefeld.de/achim/addition_chain.html
11697d523365SDimitry Andric
11707d523365SDimitry Andric assert(Exp != 0 && "Incorrect exponent 0 not handled");
11717d523365SDimitry Andric
11727d523365SDimitry Andric if (InnerChain[Exp])
11737d523365SDimitry Andric return InnerChain[Exp];
11747d523365SDimitry Andric
11757d523365SDimitry Andric static const unsigned AddChain[33][2] = {
11767d523365SDimitry Andric {0, 0}, // Unused.
11777d523365SDimitry Andric {0, 0}, // Unused (base case = pow1).
11787d523365SDimitry Andric {1, 1}, // Unused (pre-computed).
11797d523365SDimitry Andric {1, 2}, {2, 2}, {2, 3}, {3, 3}, {2, 5}, {4, 4},
11807d523365SDimitry Andric {1, 8}, {5, 5}, {1, 10}, {6, 6}, {4, 9}, {7, 7},
11817d523365SDimitry Andric {3, 12}, {8, 8}, {8, 9}, {2, 16}, {1, 18}, {10, 10},
11827d523365SDimitry Andric {6, 15}, {11, 11}, {3, 20}, {12, 12}, {8, 17}, {13, 13},
11837d523365SDimitry Andric {3, 24}, {14, 14}, {4, 25}, {15, 15}, {3, 28}, {16, 16},
11847d523365SDimitry Andric };
11857d523365SDimitry Andric
11867d523365SDimitry Andric InnerChain[Exp] = B.CreateFMul(getPow(InnerChain, AddChain[Exp][0], B),
11877d523365SDimitry Andric getPow(InnerChain, AddChain[Exp][1], B));
11887d523365SDimitry Andric return InnerChain[Exp];
11897d523365SDimitry Andric }
11907d523365SDimitry Andric
1191*b5893f02SDimitry Andric /// Use exp{,2}(x * y) for pow(exp{,2}(x), y);
1192*b5893f02SDimitry Andric /// exp2(n * x) for pow(2.0 ** n, x); exp10(x) for pow(10.0, x).
replacePowWithExp(CallInst * Pow,IRBuilder<> & B)1193*b5893f02SDimitry Andric Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilder<> &B) {
1194*b5893f02SDimitry Andric Value *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1);
1195*b5893f02SDimitry Andric AttributeList Attrs = Pow->getCalledFunction()->getAttributes();
1196*b5893f02SDimitry Andric Module *Mod = Pow->getModule();
1197*b5893f02SDimitry Andric Type *Ty = Pow->getType();
1198*b5893f02SDimitry Andric bool Ignored;
1199*b5893f02SDimitry Andric
1200*b5893f02SDimitry Andric // Evaluate special cases related to a nested function as the base.
1201*b5893f02SDimitry Andric
1202*b5893f02SDimitry Andric // pow(exp(x), y) -> exp(x * y)
1203*b5893f02SDimitry Andric // pow(exp2(x), y) -> exp2(x * y)
1204*b5893f02SDimitry Andric // If exp{,2}() is used only once, it is better to fold two transcendental
1205*b5893f02SDimitry Andric // math functions into one. If used again, exp{,2}() would still have to be
1206*b5893f02SDimitry Andric // called with the original argument, then keep both original transcendental
1207*b5893f02SDimitry Andric // functions. However, this transformation is only safe with fully relaxed
1208*b5893f02SDimitry Andric // math semantics, since, besides rounding differences, it changes overflow
1209*b5893f02SDimitry Andric // and underflow behavior quite dramatically. For example:
1210*b5893f02SDimitry Andric // pow(exp(1000), 0.001) = pow(inf, 0.001) = inf
1211*b5893f02SDimitry Andric // Whereas:
1212*b5893f02SDimitry Andric // exp(1000 * 0.001) = exp(1)
1213*b5893f02SDimitry Andric // TODO: Loosen the requirement for fully relaxed math semantics.
1214*b5893f02SDimitry Andric // TODO: Handle exp10() when more targets have it available.
1215*b5893f02SDimitry Andric CallInst *BaseFn = dyn_cast<CallInst>(Base);
1216*b5893f02SDimitry Andric if (BaseFn && BaseFn->hasOneUse() && BaseFn->isFast() && Pow->isFast()) {
1217*b5893f02SDimitry Andric LibFunc LibFn;
1218*b5893f02SDimitry Andric
1219*b5893f02SDimitry Andric Function *CalleeFn = BaseFn->getCalledFunction();
1220*b5893f02SDimitry Andric if (CalleeFn &&
1221*b5893f02SDimitry Andric TLI->getLibFunc(CalleeFn->getName(), LibFn) && TLI->has(LibFn)) {
1222*b5893f02SDimitry Andric StringRef ExpName;
1223*b5893f02SDimitry Andric Intrinsic::ID ID;
1224*b5893f02SDimitry Andric Value *ExpFn;
1225*b5893f02SDimitry Andric LibFunc LibFnFloat;
1226*b5893f02SDimitry Andric LibFunc LibFnDouble;
1227*b5893f02SDimitry Andric LibFunc LibFnLongDouble;
1228*b5893f02SDimitry Andric
1229*b5893f02SDimitry Andric switch (LibFn) {
1230*b5893f02SDimitry Andric default:
1231*b5893f02SDimitry Andric return nullptr;
1232*b5893f02SDimitry Andric case LibFunc_expf: case LibFunc_exp: case LibFunc_expl:
1233*b5893f02SDimitry Andric ExpName = TLI->getName(LibFunc_exp);
1234*b5893f02SDimitry Andric ID = Intrinsic::exp;
1235*b5893f02SDimitry Andric LibFnFloat = LibFunc_expf;
1236*b5893f02SDimitry Andric LibFnDouble = LibFunc_exp;
1237*b5893f02SDimitry Andric LibFnLongDouble = LibFunc_expl;
1238*b5893f02SDimitry Andric break;
1239*b5893f02SDimitry Andric case LibFunc_exp2f: case LibFunc_exp2: case LibFunc_exp2l:
1240*b5893f02SDimitry Andric ExpName = TLI->getName(LibFunc_exp2);
1241*b5893f02SDimitry Andric ID = Intrinsic::exp2;
1242*b5893f02SDimitry Andric LibFnFloat = LibFunc_exp2f;
1243*b5893f02SDimitry Andric LibFnDouble = LibFunc_exp2;
1244*b5893f02SDimitry Andric LibFnLongDouble = LibFunc_exp2l;
1245*b5893f02SDimitry Andric break;
1246*b5893f02SDimitry Andric }
1247*b5893f02SDimitry Andric
1248*b5893f02SDimitry Andric // Create new exp{,2}() with the product as its argument.
1249*b5893f02SDimitry Andric Value *FMul = B.CreateFMul(BaseFn->getArgOperand(0), Expo, "mul");
1250*b5893f02SDimitry Andric ExpFn = BaseFn->doesNotAccessMemory()
1251*b5893f02SDimitry Andric ? B.CreateCall(Intrinsic::getDeclaration(Mod, ID, Ty),
1252*b5893f02SDimitry Andric FMul, ExpName)
1253*b5893f02SDimitry Andric : emitUnaryFloatFnCall(FMul, TLI, LibFnDouble, LibFnFloat,
1254*b5893f02SDimitry Andric LibFnLongDouble, B,
1255*b5893f02SDimitry Andric BaseFn->getAttributes());
1256*b5893f02SDimitry Andric
1257*b5893f02SDimitry Andric // Since the new exp{,2}() is different from the original one, dead code
1258*b5893f02SDimitry Andric // elimination cannot be trusted to remove it, since it may have side
1259*b5893f02SDimitry Andric // effects (e.g., errno). When the only consumer for the original
1260*b5893f02SDimitry Andric // exp{,2}() is pow(), then it has to be explicitly erased.
1261*b5893f02SDimitry Andric BaseFn->replaceAllUsesWith(ExpFn);
1262*b5893f02SDimitry Andric eraseFromParent(BaseFn);
1263*b5893f02SDimitry Andric
1264*b5893f02SDimitry Andric return ExpFn;
1265*b5893f02SDimitry Andric }
1266*b5893f02SDimitry Andric }
1267*b5893f02SDimitry Andric
1268*b5893f02SDimitry Andric // Evaluate special cases related to a constant base.
1269*b5893f02SDimitry Andric
1270*b5893f02SDimitry Andric const APFloat *BaseF;
1271*b5893f02SDimitry Andric if (!match(Pow->getArgOperand(0), m_APFloat(BaseF)))
12722cab237bSDimitry Andric return nullptr;
12732cab237bSDimitry Andric
1274*b5893f02SDimitry Andric // pow(2.0 ** n, x) -> exp2(n * x)
1275*b5893f02SDimitry Andric if (hasUnaryFloatFn(TLI, Ty, LibFunc_exp2, LibFunc_exp2f, LibFunc_exp2l)) {
1276*b5893f02SDimitry Andric APFloat BaseR = APFloat(1.0);
1277*b5893f02SDimitry Andric BaseR.convert(BaseF->getSemantics(), APFloat::rmTowardZero, &Ignored);
1278*b5893f02SDimitry Andric BaseR = BaseR / *BaseF;
1279*b5893f02SDimitry Andric bool IsInteger = BaseF->isInteger(),
1280*b5893f02SDimitry Andric IsReciprocal = BaseR.isInteger();
1281*b5893f02SDimitry Andric const APFloat *NF = IsReciprocal ? &BaseR : BaseF;
1282*b5893f02SDimitry Andric APSInt NI(64, false);
1283*b5893f02SDimitry Andric if ((IsInteger || IsReciprocal) &&
1284*b5893f02SDimitry Andric !NF->convertToInteger(NI, APFloat::rmTowardZero, &Ignored) &&
1285*b5893f02SDimitry Andric NI > 1 && NI.isPowerOf2()) {
1286*b5893f02SDimitry Andric double N = NI.logBase2() * (IsReciprocal ? -1.0 : 1.0);
1287*b5893f02SDimitry Andric Value *FMul = B.CreateFMul(Expo, ConstantFP::get(Ty, N), "mul");
1288*b5893f02SDimitry Andric if (Pow->doesNotAccessMemory())
1289*b5893f02SDimitry Andric return B.CreateCall(Intrinsic::getDeclaration(Mod, Intrinsic::exp2, Ty),
1290*b5893f02SDimitry Andric FMul, "exp2");
1291*b5893f02SDimitry Andric else
1292*b5893f02SDimitry Andric return emitUnaryFloatFnCall(FMul, TLI, LibFunc_exp2, LibFunc_exp2f,
1293*b5893f02SDimitry Andric LibFunc_exp2l, B, Attrs);
1294*b5893f02SDimitry Andric }
1295*b5893f02SDimitry Andric }
1296*b5893f02SDimitry Andric
1297*b5893f02SDimitry Andric // pow(10.0, x) -> exp10(x)
1298*b5893f02SDimitry Andric // TODO: There is no exp10() intrinsic yet, but some day there shall be one.
1299*b5893f02SDimitry Andric if (match(Base, m_SpecificFP(10.0)) &&
1300*b5893f02SDimitry Andric hasUnaryFloatFn(TLI, Ty, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l))
1301*b5893f02SDimitry Andric return emitUnaryFloatFnCall(Expo, TLI, LibFunc_exp10, LibFunc_exp10f,
1302*b5893f02SDimitry Andric LibFunc_exp10l, B, Attrs);
1303*b5893f02SDimitry Andric
1304*b5893f02SDimitry Andric return nullptr;
1305*b5893f02SDimitry Andric }
1306*b5893f02SDimitry Andric
getSqrtCall(Value * V,AttributeList Attrs,bool NoErrno,Module * M,IRBuilder<> & B,const TargetLibraryInfo * TLI)1307*b5893f02SDimitry Andric static Value *getSqrtCall(Value *V, AttributeList Attrs, bool NoErrno,
1308*b5893f02SDimitry Andric Module *M, IRBuilder<> &B,
1309*b5893f02SDimitry Andric const TargetLibraryInfo *TLI) {
1310*b5893f02SDimitry Andric // If errno is never set, then use the intrinsic for sqrt().
1311*b5893f02SDimitry Andric if (NoErrno) {
1312*b5893f02SDimitry Andric Function *SqrtFn =
1313*b5893f02SDimitry Andric Intrinsic::getDeclaration(M, Intrinsic::sqrt, V->getType());
1314*b5893f02SDimitry Andric return B.CreateCall(SqrtFn, V, "sqrt");
1315*b5893f02SDimitry Andric }
1316*b5893f02SDimitry Andric
1317*b5893f02SDimitry Andric // Otherwise, use the libcall for sqrt().
1318*b5893f02SDimitry Andric if (hasUnaryFloatFn(TLI, V->getType(), LibFunc_sqrt, LibFunc_sqrtf,
1319*b5893f02SDimitry Andric LibFunc_sqrtl))
1320*b5893f02SDimitry Andric // TODO: We also should check that the target can in fact lower the sqrt()
1321*b5893f02SDimitry Andric // libcall. We currently have no way to ask this question, so we ask if
1322*b5893f02SDimitry Andric // the target has a sqrt() libcall, which is not exactly the same.
1323*b5893f02SDimitry Andric return emitUnaryFloatFnCall(V, TLI, LibFunc_sqrt, LibFunc_sqrtf,
1324*b5893f02SDimitry Andric LibFunc_sqrtl, B, Attrs);
1325*b5893f02SDimitry Andric
1326*b5893f02SDimitry Andric return nullptr;
1327*b5893f02SDimitry Andric }
1328*b5893f02SDimitry Andric
1329*b5893f02SDimitry Andric /// Use square root in place of pow(x, +/-0.5).
replacePowWithSqrt(CallInst * Pow,IRBuilder<> & B)1330*b5893f02SDimitry Andric Value *LibCallSimplifier::replacePowWithSqrt(CallInst *Pow, IRBuilder<> &B) {
13314ba319b5SDimitry Andric Value *Sqrt, *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1);
1332*b5893f02SDimitry Andric AttributeList Attrs = Pow->getCalledFunction()->getAttributes();
1333*b5893f02SDimitry Andric Module *Mod = Pow->getModule();
13342cab237bSDimitry Andric Type *Ty = Pow->getType();
13352cab237bSDimitry Andric
13364ba319b5SDimitry Andric const APFloat *ExpoF;
13374ba319b5SDimitry Andric if (!match(Expo, m_APFloat(ExpoF)) ||
13384ba319b5SDimitry Andric (!ExpoF->isExactlyValue(0.5) && !ExpoF->isExactlyValue(-0.5)))
13394ba319b5SDimitry Andric return nullptr;
13404ba319b5SDimitry Andric
1341*b5893f02SDimitry Andric Sqrt = getSqrtCall(Base, Attrs, Pow->doesNotAccessMemory(), Mod, B, TLI);
1342*b5893f02SDimitry Andric if (!Sqrt)
13434ba319b5SDimitry Andric return nullptr;
13444ba319b5SDimitry Andric
1345*b5893f02SDimitry Andric // Handle signed zero base by expanding to fabs(sqrt(x)).
1346*b5893f02SDimitry Andric if (!Pow->hasNoSignedZeros()) {
1347*b5893f02SDimitry Andric Function *FAbsFn = Intrinsic::getDeclaration(Mod, Intrinsic::fabs, Ty);
1348*b5893f02SDimitry Andric Sqrt = B.CreateCall(FAbsFn, Sqrt, "abs");
1349*b5893f02SDimitry Andric }
1350*b5893f02SDimitry Andric
1351*b5893f02SDimitry Andric // Handle non finite base by expanding to
1352*b5893f02SDimitry Andric // (x == -infinity ? +infinity : sqrt(x)).
1353*b5893f02SDimitry Andric if (!Pow->hasNoInfs()) {
1354*b5893f02SDimitry Andric Value *PosInf = ConstantFP::getInfinity(Ty),
1355*b5893f02SDimitry Andric *NegInf = ConstantFP::getInfinity(Ty, true);
1356*b5893f02SDimitry Andric Value *FCmp = B.CreateFCmpOEQ(Base, NegInf, "isinf");
1357*b5893f02SDimitry Andric Sqrt = B.CreateSelect(FCmp, PosInf, Sqrt);
1358*b5893f02SDimitry Andric }
1359*b5893f02SDimitry Andric
13604ba319b5SDimitry Andric // If the exponent is negative, then get the reciprocal.
13614ba319b5SDimitry Andric if (ExpoF->isNegative())
13624ba319b5SDimitry Andric Sqrt = B.CreateFDiv(ConstantFP::get(Ty, 1.0), Sqrt, "reciprocal");
13632cab237bSDimitry Andric
13642cab237bSDimitry Andric return Sqrt;
13652cab237bSDimitry Andric }
13662cab237bSDimitry Andric
optimizePow(CallInst * Pow,IRBuilder<> & B)13674ba319b5SDimitry Andric Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilder<> &B) {
13684ba319b5SDimitry Andric Value *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1);
13694ba319b5SDimitry Andric Function *Callee = Pow->getCalledFunction();
13707d523365SDimitry Andric StringRef Name = Callee->getName();
13714ba319b5SDimitry Andric Type *Ty = Pow->getType();
13724ba319b5SDimitry Andric Value *Shrunk = nullptr;
13734ba319b5SDimitry Andric bool Ignored;
1374139f7f9bSDimitry Andric
1375*b5893f02SDimitry Andric // Bail out if simplifying libcalls to pow() is disabled.
1376*b5893f02SDimitry Andric if (!hasUnaryFloatFn(TLI, Ty, LibFunc_pow, LibFunc_powf, LibFunc_powl))
1377*b5893f02SDimitry Andric return nullptr;
13784ba319b5SDimitry Andric
13794ba319b5SDimitry Andric // Propagate the math semantics from the call to any created instructions.
13804ba319b5SDimitry Andric IRBuilder<>::FastMathFlagGuard Guard(B);
13814ba319b5SDimitry Andric B.setFastMathFlags(Pow->getFastMathFlags());
13824ba319b5SDimitry Andric
1383*b5893f02SDimitry Andric // Shrink pow() to powf() if the arguments are single precision,
1384*b5893f02SDimitry Andric // unless the result is expected to be double precision.
1385*b5893f02SDimitry Andric if (UnsafeFPShrink &&
1386*b5893f02SDimitry Andric Name == TLI->getName(LibFunc_pow) && hasFloatVersion(Name))
1387*b5893f02SDimitry Andric Shrunk = optimizeBinaryDoubleFP(Pow, B, true);
1388*b5893f02SDimitry Andric
13894ba319b5SDimitry Andric // Evaluate special cases related to the base.
1390d88c1a5aSDimitry Andric
1391f785676fSDimitry Andric // pow(1.0, x) -> 1.0
1392*b5893f02SDimitry Andric if (match(Base, m_FPOne()))
13934ba319b5SDimitry Andric return Base;
13944ba319b5SDimitry Andric
1395*b5893f02SDimitry Andric if (Value *Exp = replacePowWithExp(Pow, B))
1396*b5893f02SDimitry Andric return Exp;
13977d523365SDimitry Andric
13984ba319b5SDimitry Andric // Evaluate special cases related to the exponent.
13994ba319b5SDimitry Andric
1400*b5893f02SDimitry Andric // pow(x, -1.0) -> 1.0 / x
1401*b5893f02SDimitry Andric if (match(Expo, m_SpecificFP(-1.0)))
1402*b5893f02SDimitry Andric return B.CreateFDiv(ConstantFP::get(Ty, 1.0), Base, "reciprocal");
1403*b5893f02SDimitry Andric
1404*b5893f02SDimitry Andric // pow(x, 0.0) -> 1.0
1405*b5893f02SDimitry Andric if (match(Expo, m_SpecificFP(0.0)))
1406*b5893f02SDimitry Andric return ConstantFP::get(Ty, 1.0);
1407*b5893f02SDimitry Andric
1408*b5893f02SDimitry Andric // pow(x, 1.0) -> x
1409*b5893f02SDimitry Andric if (match(Expo, m_FPOne()))
1410*b5893f02SDimitry Andric return Base;
1411*b5893f02SDimitry Andric
1412*b5893f02SDimitry Andric // pow(x, 2.0) -> x * x
1413*b5893f02SDimitry Andric if (match(Expo, m_SpecificFP(2.0)))
1414*b5893f02SDimitry Andric return B.CreateFMul(Base, Base, "square");
1415*b5893f02SDimitry Andric
14164ba319b5SDimitry Andric if (Value *Sqrt = replacePowWithSqrt(Pow, B))
14172cab237bSDimitry Andric return Sqrt;
14182cab237bSDimitry Andric
1419*b5893f02SDimitry Andric // pow(x, n) -> x * x * x * ...
1420*b5893f02SDimitry Andric const APFloat *ExpoF;
1421*b5893f02SDimitry Andric if (Pow->isFast() && match(Expo, m_APFloat(ExpoF))) {
1422*b5893f02SDimitry Andric // We limit to a max of 7 multiplications, thus the maximum exponent is 32.
1423*b5893f02SDimitry Andric // If the exponent is an integer+0.5 we generate a call to sqrt and an
1424*b5893f02SDimitry Andric // additional fmul.
1425*b5893f02SDimitry Andric // TODO: This whole transformation should be backend specific (e.g. some
1426*b5893f02SDimitry Andric // backends might prefer libcalls or the limit for the exponent might
1427*b5893f02SDimitry Andric // be different) and it should also consider optimizing for size.
1428*b5893f02SDimitry Andric APFloat LimF(ExpoF->getSemantics(), 33.0),
1429*b5893f02SDimitry Andric ExpoA(abs(*ExpoF));
1430*b5893f02SDimitry Andric if (ExpoA.compare(LimF) == APFloat::cmpLessThan) {
1431*b5893f02SDimitry Andric // This transformation applies to integer or integer+0.5 exponents only.
1432*b5893f02SDimitry Andric // For integer+0.5, we create a sqrt(Base) call.
1433*b5893f02SDimitry Andric Value *Sqrt = nullptr;
1434*b5893f02SDimitry Andric if (!ExpoA.isInteger()) {
1435*b5893f02SDimitry Andric APFloat Expo2 = ExpoA;
1436*b5893f02SDimitry Andric // To check if ExpoA is an integer + 0.5, we add it to itself. If there
1437*b5893f02SDimitry Andric // is no floating point exception and the result is an integer, then
1438*b5893f02SDimitry Andric // ExpoA == integer + 0.5
1439*b5893f02SDimitry Andric if (Expo2.add(ExpoA, APFloat::rmNearestTiesToEven) != APFloat::opOK)
14407d523365SDimitry Andric return nullptr;
14417d523365SDimitry Andric
1442*b5893f02SDimitry Andric if (!Expo2.isInteger())
1443*b5893f02SDimitry Andric return nullptr;
1444*b5893f02SDimitry Andric
1445*b5893f02SDimitry Andric Sqrt =
1446*b5893f02SDimitry Andric getSqrtCall(Base, Pow->getCalledFunction()->getAttributes(),
1447*b5893f02SDimitry Andric Pow->doesNotAccessMemory(), Pow->getModule(), B, TLI);
1448*b5893f02SDimitry Andric }
1449*b5893f02SDimitry Andric
14507d523365SDimitry Andric // We will memoize intermediate products of the Addition Chain.
14517d523365SDimitry Andric Value *InnerChain[33] = {nullptr};
14524ba319b5SDimitry Andric InnerChain[1] = Base;
14534ba319b5SDimitry Andric InnerChain[2] = B.CreateFMul(Base, Base, "square");
14547d523365SDimitry Andric
14557d523365SDimitry Andric // We cannot readily convert a non-double type (like float) to a double.
14564ba319b5SDimitry Andric // So we first convert it to something which could be converted to double.
14574ba319b5SDimitry Andric ExpoA.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &Ignored);
14584ba319b5SDimitry Andric Value *FMul = getPow(InnerChain, ExpoA.convertToDouble(), B);
14593ca95b02SDimitry Andric
1460*b5893f02SDimitry Andric // Expand pow(x, y+0.5) to pow(x, y) * sqrt(x).
1461*b5893f02SDimitry Andric if (Sqrt)
1462*b5893f02SDimitry Andric FMul = B.CreateFMul(FMul, Sqrt);
1463*b5893f02SDimitry Andric
14644ba319b5SDimitry Andric // If the exponent is negative, then get the reciprocal.
1465*b5893f02SDimitry Andric if (ExpoF->isNegative())
14664ba319b5SDimitry Andric FMul = B.CreateFDiv(ConstantFP::get(Ty, 1.0), FMul, "reciprocal");
1467*b5893f02SDimitry Andric
14687d523365SDimitry Andric return FMul;
14697d523365SDimitry Andric }
1470*b5893f02SDimitry Andric }
14717d523365SDimitry Andric
1472*b5893f02SDimitry Andric return Shrunk;
1473139f7f9bSDimitry Andric }
1474139f7f9bSDimitry Andric
optimizeExp2(CallInst * CI,IRBuilder<> & B)147539d628a0SDimitry Andric Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilder<> &B) {
147639d628a0SDimitry Andric Function *Callee = CI->getCalledFunction();
147791bc56edSDimitry Andric Value *Ret = nullptr;
14787d523365SDimitry Andric StringRef Name = Callee->getName();
14797d523365SDimitry Andric if (UnsafeFPShrink && Name == "exp2" && hasFloatVersion(Name))
148039d628a0SDimitry Andric Ret = optimizeUnaryDoubleFP(CI, B, true);
1481139f7f9bSDimitry Andric
1482139f7f9bSDimitry Andric Value *Op = CI->getArgOperand(0);
1483139f7f9bSDimitry Andric // Turn exp2(sitofp(x)) -> ldexp(1.0, sext(x)) if sizeof(x) <= 32
1484139f7f9bSDimitry Andric // Turn exp2(uitofp(x)) -> ldexp(1.0, zext(x)) if sizeof(x) < 32
14857a7e6055SDimitry Andric LibFunc LdExp = LibFunc_ldexpl;
148691bc56edSDimitry Andric if (Op->getType()->isFloatTy())
14877a7e6055SDimitry Andric LdExp = LibFunc_ldexpf;
148891bc56edSDimitry Andric else if (Op->getType()->isDoubleTy())
14897a7e6055SDimitry Andric LdExp = LibFunc_ldexp;
149091bc56edSDimitry Andric
149191bc56edSDimitry Andric if (TLI->has(LdExp)) {
149291bc56edSDimitry Andric Value *LdExpArg = nullptr;
1493139f7f9bSDimitry Andric if (SIToFPInst *OpC = dyn_cast<SIToFPInst>(Op)) {
1494139f7f9bSDimitry Andric if (OpC->getOperand(0)->getType()->getPrimitiveSizeInBits() <= 32)
1495139f7f9bSDimitry Andric LdExpArg = B.CreateSExt(OpC->getOperand(0), B.getInt32Ty());
1496139f7f9bSDimitry Andric } else if (UIToFPInst *OpC = dyn_cast<UIToFPInst>(Op)) {
1497139f7f9bSDimitry Andric if (OpC->getOperand(0)->getType()->getPrimitiveSizeInBits() < 32)
1498139f7f9bSDimitry Andric LdExpArg = B.CreateZExt(OpC->getOperand(0), B.getInt32Ty());
1499139f7f9bSDimitry Andric }
1500139f7f9bSDimitry Andric
1501139f7f9bSDimitry Andric if (LdExpArg) {
150239d628a0SDimitry Andric Constant *One = ConstantFP::get(CI->getContext(), APFloat(1.0f));
1503139f7f9bSDimitry Andric if (!Op->getType()->isFloatTy())
1504139f7f9bSDimitry Andric One = ConstantExpr::getFPExtend(One, Op->getType());
1505139f7f9bSDimitry Andric
15063ca95b02SDimitry Andric Module *M = CI->getModule();
15073ca95b02SDimitry Andric Value *NewCallee =
150891bc56edSDimitry Andric M->getOrInsertFunction(TLI->getName(LdExp), Op->getType(),
15097a7e6055SDimitry Andric Op->getType(), B.getInt32Ty());
15103ca95b02SDimitry Andric CallInst *CI = B.CreateCall(NewCallee, {One, LdExpArg});
1511139f7f9bSDimitry Andric if (const Function *F = dyn_cast<Function>(Callee->stripPointerCasts()))
1512139f7f9bSDimitry Andric CI->setCallingConv(F->getCallingConv());
1513139f7f9bSDimitry Andric
1514139f7f9bSDimitry Andric return CI;
1515139f7f9bSDimitry Andric }
151691bc56edSDimitry Andric }
1517139f7f9bSDimitry Andric return Ret;
1518139f7f9bSDimitry Andric }
1519139f7f9bSDimitry Andric
optimizeFMinFMax(CallInst * CI,IRBuilder<> & B)15207d523365SDimitry Andric Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilder<> &B) {
15213ca95b02SDimitry Andric Function *Callee = CI->getCalledFunction();
15227d523365SDimitry Andric // If we can shrink the call to a float function rather than a double
15237d523365SDimitry Andric // function, do that first.
15247d523365SDimitry Andric StringRef Name = Callee->getName();
15254d0b32cdSDimitry Andric if ((Name == "fmin" || Name == "fmax") && hasFloatVersion(Name))
15264d0b32cdSDimitry Andric if (Value *Ret = optimizeBinaryDoubleFP(CI, B))
15277d523365SDimitry Andric return Ret;
15287d523365SDimitry Andric
15297d523365SDimitry Andric IRBuilder<>::FastMathFlagGuard Guard(B);
15307d523365SDimitry Andric FastMathFlags FMF;
15312cab237bSDimitry Andric if (CI->isFast()) {
15322cab237bSDimitry Andric // If the call is 'fast', then anything we create here will also be 'fast'.
15332cab237bSDimitry Andric FMF.setFast();
15347d523365SDimitry Andric } else {
15357d523365SDimitry Andric // At a minimum, no-nans-fp-math must be true.
15364d0b32cdSDimitry Andric if (!CI->hasNoNaNs())
15377d523365SDimitry Andric return nullptr;
15387d523365SDimitry Andric // No-signed-zeros is implied by the definitions of fmax/fmin themselves:
15397d523365SDimitry Andric // "Ideally, fmax would be sensitive to the sign of zero, for example
15407d523365SDimitry Andric // fmax(-0. 0, +0. 0) would return +0; however, implementation in software
15417d523365SDimitry Andric // might be impractical."
15427d523365SDimitry Andric FMF.setNoSignedZeros();
15437d523365SDimitry Andric FMF.setNoNaNs();
15447d523365SDimitry Andric }
1545444ed5c5SDimitry Andric B.setFastMathFlags(FMF);
15467d523365SDimitry Andric
15477d523365SDimitry Andric // We have a relaxed floating-point environment. We can ignore NaN-handling
15487d523365SDimitry Andric // and transform to a compare and select. We do not have to consider errno or
15497d523365SDimitry Andric // exceptions, because fmin/fmax do not have those.
15507d523365SDimitry Andric Value *Op0 = CI->getArgOperand(0);
15517d523365SDimitry Andric Value *Op1 = CI->getArgOperand(1);
15527d523365SDimitry Andric Value *Cmp = Callee->getName().startswith("fmin") ?
15537d523365SDimitry Andric B.CreateFCmpOLT(Op0, Op1) : B.CreateFCmpOGT(Op0, Op1);
15547d523365SDimitry Andric return B.CreateSelect(Cmp, Op0, Op1);
15557d523365SDimitry Andric }
15567d523365SDimitry Andric
optimizeLog(CallInst * CI,IRBuilder<> & B)15577d523365SDimitry Andric Value *LibCallSimplifier::optimizeLog(CallInst *CI, IRBuilder<> &B) {
15587d523365SDimitry Andric Function *Callee = CI->getCalledFunction();
15597d523365SDimitry Andric Value *Ret = nullptr;
15607d523365SDimitry Andric StringRef Name = Callee->getName();
15617d523365SDimitry Andric if (UnsafeFPShrink && hasFloatVersion(Name))
15627d523365SDimitry Andric Ret = optimizeUnaryDoubleFP(CI, B, true);
15637d523365SDimitry Andric
15642cab237bSDimitry Andric if (!CI->isFast())
15657d523365SDimitry Andric return Ret;
15667d523365SDimitry Andric Value *Op1 = CI->getArgOperand(0);
15677d523365SDimitry Andric auto *OpC = dyn_cast<CallInst>(Op1);
1568444ed5c5SDimitry Andric
15692cab237bSDimitry Andric // The earlier call must also be 'fast' in order to do these transforms.
15702cab237bSDimitry Andric if (!OpC || !OpC->isFast())
15717d523365SDimitry Andric return Ret;
15727d523365SDimitry Andric
15737d523365SDimitry Andric // log(pow(x,y)) -> y*log(x)
15747d523365SDimitry Andric // This is only applicable to log, log2, log10.
15757d523365SDimitry Andric if (Name != "log" && Name != "log2" && Name != "log10")
15767d523365SDimitry Andric return Ret;
15777d523365SDimitry Andric
15787d523365SDimitry Andric IRBuilder<>::FastMathFlagGuard Guard(B);
15797d523365SDimitry Andric FastMathFlags FMF;
15802cab237bSDimitry Andric FMF.setFast();
1581444ed5c5SDimitry Andric B.setFastMathFlags(FMF);
15827d523365SDimitry Andric
15837a7e6055SDimitry Andric LibFunc Func;
15847d523365SDimitry Andric Function *F = OpC->getCalledFunction();
15857d523365SDimitry Andric if (F && ((TLI->getLibFunc(F->getName(), Func) && TLI->has(Func) &&
15867a7e6055SDimitry Andric Func == LibFunc_pow) || F->getIntrinsicID() == Intrinsic::pow))
15877d523365SDimitry Andric return B.CreateFMul(OpC->getArgOperand(1),
15883ca95b02SDimitry Andric emitUnaryFloatFnCall(OpC->getOperand(0), Callee->getName(), B,
15897d523365SDimitry Andric Callee->getAttributes()), "mul");
15907d523365SDimitry Andric
15917d523365SDimitry Andric // log(exp2(y)) -> y*log(2)
15927d523365SDimitry Andric if (F && Name == "log" && TLI->getLibFunc(F->getName(), Func) &&
15937a7e6055SDimitry Andric TLI->has(Func) && Func == LibFunc_exp2)
15947d523365SDimitry Andric return B.CreateFMul(
15957d523365SDimitry Andric OpC->getArgOperand(0),
15963ca95b02SDimitry Andric emitUnaryFloatFnCall(ConstantFP::get(CI->getType(), 2.0),
15977d523365SDimitry Andric Callee->getName(), B, Callee->getAttributes()),
15987d523365SDimitry Andric "logmul");
15997d523365SDimitry Andric return Ret;
16007d523365SDimitry Andric }
16017d523365SDimitry Andric
optimizeSqrt(CallInst * CI,IRBuilder<> & B)160239d628a0SDimitry Andric Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilder<> &B) {
160339d628a0SDimitry Andric Function *Callee = CI->getCalledFunction();
160439d628a0SDimitry Andric Value *Ret = nullptr;
16057a7e6055SDimitry Andric // TODO: Once we have a way (other than checking for the existince of the
16067a7e6055SDimitry Andric // libcall) to tell whether our target can lower @llvm.sqrt, relax the
16077a7e6055SDimitry Andric // condition below.
16087a7e6055SDimitry Andric if (TLI->has(LibFunc_sqrtf) && (Callee->getName() == "sqrt" ||
160939d628a0SDimitry Andric Callee->getIntrinsicID() == Intrinsic::sqrt))
161039d628a0SDimitry Andric Ret = optimizeUnaryDoubleFP(CI, B, true);
1611444ed5c5SDimitry Andric
16122cab237bSDimitry Andric if (!CI->isFast())
161339d628a0SDimitry Andric return Ret;
16147d523365SDimitry Andric
1615444ed5c5SDimitry Andric Instruction *I = dyn_cast<Instruction>(CI->getArgOperand(0));
16162cab237bSDimitry Andric if (!I || I->getOpcode() != Instruction::FMul || !I->isFast())
1617444ed5c5SDimitry Andric return Ret;
1618444ed5c5SDimitry Andric
161939d628a0SDimitry Andric // We're looking for a repeated factor in a multiplication tree,
162039d628a0SDimitry Andric // so we can do this fold: sqrt(x * x) -> fabs(x);
1621444ed5c5SDimitry Andric // or this fold: sqrt((x * x) * y) -> fabs(x) * sqrt(y).
162239d628a0SDimitry Andric Value *Op0 = I->getOperand(0);
162339d628a0SDimitry Andric Value *Op1 = I->getOperand(1);
162439d628a0SDimitry Andric Value *RepeatOp = nullptr;
162539d628a0SDimitry Andric Value *OtherOp = nullptr;
162639d628a0SDimitry Andric if (Op0 == Op1) {
162739d628a0SDimitry Andric // Simple match: the operands of the multiply are identical.
162839d628a0SDimitry Andric RepeatOp = Op0;
162939d628a0SDimitry Andric } else {
163039d628a0SDimitry Andric // Look for a more complicated pattern: one of the operands is itself
163139d628a0SDimitry Andric // a multiply, so search for a common factor in that multiply.
163239d628a0SDimitry Andric // Note: We don't bother looking any deeper than this first level or for
163339d628a0SDimitry Andric // variations of this pattern because instcombine's visitFMUL and/or the
163439d628a0SDimitry Andric // reassociation pass should give us this form.
163539d628a0SDimitry Andric Value *OtherMul0, *OtherMul1;
163639d628a0SDimitry Andric if (match(Op0, m_FMul(m_Value(OtherMul0), m_Value(OtherMul1)))) {
163739d628a0SDimitry Andric // Pattern: sqrt((x * y) * z)
16382cab237bSDimitry Andric if (OtherMul0 == OtherMul1 && cast<Instruction>(Op0)->isFast()) {
163939d628a0SDimitry Andric // Matched: sqrt((x * x) * z)
164039d628a0SDimitry Andric RepeatOp = OtherMul0;
164139d628a0SDimitry Andric OtherOp = Op1;
164239d628a0SDimitry Andric }
164339d628a0SDimitry Andric }
164439d628a0SDimitry Andric }
1645444ed5c5SDimitry Andric if (!RepeatOp)
1646444ed5c5SDimitry Andric return Ret;
1647444ed5c5SDimitry Andric
164839d628a0SDimitry Andric // Fast math flags for any created instructions should match the sqrt
164939d628a0SDimitry Andric // and multiply.
16507d523365SDimitry Andric IRBuilder<>::FastMathFlagGuard Guard(B);
1651444ed5c5SDimitry Andric B.setFastMathFlags(I->getFastMathFlags());
1652444ed5c5SDimitry Andric
165339d628a0SDimitry Andric // If we found a repeated factor, hoist it out of the square root and
165439d628a0SDimitry Andric // replace it with the fabs of that factor.
165539d628a0SDimitry Andric Module *M = Callee->getParent();
1656444ed5c5SDimitry Andric Type *ArgType = I->getType();
165739d628a0SDimitry Andric Value *Fabs = Intrinsic::getDeclaration(M, Intrinsic::fabs, ArgType);
165839d628a0SDimitry Andric Value *FabsCall = B.CreateCall(Fabs, RepeatOp, "fabs");
165939d628a0SDimitry Andric if (OtherOp) {
166039d628a0SDimitry Andric // If we found a non-repeated factor, we still need to get its square
166139d628a0SDimitry Andric // root. We then multiply that by the value that was simplified out
166239d628a0SDimitry Andric // of the square root calculation.
166339d628a0SDimitry Andric Value *Sqrt = Intrinsic::getDeclaration(M, Intrinsic::sqrt, ArgType);
166439d628a0SDimitry Andric Value *SqrtCall = B.CreateCall(Sqrt, OtherOp, "sqrt");
166539d628a0SDimitry Andric return B.CreateFMul(FabsCall, SqrtCall);
166639d628a0SDimitry Andric }
166739d628a0SDimitry Andric return FabsCall;
166839d628a0SDimitry Andric }
166939d628a0SDimitry Andric
1670444ed5c5SDimitry Andric // TODO: Generalize to handle any trig function and its inverse.
optimizeTan(CallInst * CI,IRBuilder<> & B)16717d523365SDimitry Andric Value *LibCallSimplifier::optimizeTan(CallInst *CI, IRBuilder<> &B) {
16727d523365SDimitry Andric Function *Callee = CI->getCalledFunction();
16737d523365SDimitry Andric Value *Ret = nullptr;
16747d523365SDimitry Andric StringRef Name = Callee->getName();
16757d523365SDimitry Andric if (UnsafeFPShrink && Name == "tan" && hasFloatVersion(Name))
16767d523365SDimitry Andric Ret = optimizeUnaryDoubleFP(CI, B, true);
16777d523365SDimitry Andric
16787d523365SDimitry Andric Value *Op1 = CI->getArgOperand(0);
16797d523365SDimitry Andric auto *OpC = dyn_cast<CallInst>(Op1);
16807d523365SDimitry Andric if (!OpC)
16817d523365SDimitry Andric return Ret;
16827d523365SDimitry Andric
16832cab237bSDimitry Andric // Both calls must be 'fast' in order to remove them.
16842cab237bSDimitry Andric if (!CI->isFast() || !OpC->isFast())
1685444ed5c5SDimitry Andric return Ret;
1686444ed5c5SDimitry Andric
16877d523365SDimitry Andric // tan(atan(x)) -> x
16887d523365SDimitry Andric // tanf(atanf(x)) -> x
16897d523365SDimitry Andric // tanl(atanl(x)) -> x
16907a7e6055SDimitry Andric LibFunc Func;
16917d523365SDimitry Andric Function *F = OpC->getCalledFunction();
16927d523365SDimitry Andric if (F && TLI->getLibFunc(F->getName(), Func) && TLI->has(Func) &&
16937a7e6055SDimitry Andric ((Func == LibFunc_atan && Callee->getName() == "tan") ||
16947a7e6055SDimitry Andric (Func == LibFunc_atanf && Callee->getName() == "tanf") ||
16957a7e6055SDimitry Andric (Func == LibFunc_atanl && Callee->getName() == "tanl")))
16967d523365SDimitry Andric Ret = OpC->getArgOperand(0);
16977d523365SDimitry Andric return Ret;
16987d523365SDimitry Andric }
16997d523365SDimitry Andric
isTrigLibCall(CallInst * CI)170039d628a0SDimitry Andric static bool isTrigLibCall(CallInst *CI) {
1701f785676fSDimitry Andric // We can only hope to do anything useful if we can ignore things like errno
1702f785676fSDimitry Andric // and floating-point exceptions.
17033ca95b02SDimitry Andric // We already checked the prototype.
17043ca95b02SDimitry Andric return CI->hasFnAttr(Attribute::NoUnwind) &&
17053ca95b02SDimitry Andric CI->hasFnAttr(Attribute::ReadNone);
1706f785676fSDimitry Andric }
1707f785676fSDimitry Andric
insertSinCosCall(IRBuilder<> & B,Function * OrigCallee,Value * Arg,bool UseFloat,Value * & Sin,Value * & Cos,Value * & SinCos)17083ca95b02SDimitry Andric static void insertSinCosCall(IRBuilder<> &B, Function *OrigCallee, Value *Arg,
17093ca95b02SDimitry Andric bool UseFloat, Value *&Sin, Value *&Cos,
17103ca95b02SDimitry Andric Value *&SinCos) {
1711f785676fSDimitry Andric Type *ArgTy = Arg->getType();
1712f785676fSDimitry Andric Type *ResTy;
1713f785676fSDimitry Andric StringRef Name;
1714f785676fSDimitry Andric
1715f785676fSDimitry Andric Triple T(OrigCallee->getParent()->getTargetTriple());
1716f785676fSDimitry Andric if (UseFloat) {
171791bc56edSDimitry Andric Name = "__sincospif_stret";
1718f785676fSDimitry Andric
1719f785676fSDimitry Andric assert(T.getArch() != Triple::x86 && "x86 messy and unsupported for now");
1720f785676fSDimitry Andric // x86_64 can't use {float, float} since that would be returned in both
1721f785676fSDimitry Andric // xmm0 and xmm1, which isn't what a real struct would do.
1722f785676fSDimitry Andric ResTy = T.getArch() == Triple::x86_64
1723f785676fSDimitry Andric ? static_cast<Type *>(VectorType::get(ArgTy, 2))
17245517e702SDimitry Andric : static_cast<Type *>(StructType::get(ArgTy, ArgTy));
1725f785676fSDimitry Andric } else {
1726f785676fSDimitry Andric Name = "__sincospi_stret";
17275517e702SDimitry Andric ResTy = StructType::get(ArgTy, ArgTy);
1728f785676fSDimitry Andric }
1729f785676fSDimitry Andric
1730f785676fSDimitry Andric Module *M = OrigCallee->getParent();
1731f785676fSDimitry Andric Value *Callee = M->getOrInsertFunction(Name, OrigCallee->getAttributes(),
17327a7e6055SDimitry Andric ResTy, ArgTy);
1733f785676fSDimitry Andric
1734f785676fSDimitry Andric if (Instruction *ArgInst = dyn_cast<Instruction>(Arg)) {
1735f785676fSDimitry Andric // If the argument is an instruction, it must dominate all uses so put our
1736f785676fSDimitry Andric // sincos call there.
17377d523365SDimitry Andric B.SetInsertPoint(ArgInst->getParent(), ++ArgInst->getIterator());
1738f785676fSDimitry Andric } else {
1739f785676fSDimitry Andric // Otherwise (e.g. for a constant) the beginning of the function is as
1740f785676fSDimitry Andric // good a place as any.
1741f785676fSDimitry Andric BasicBlock &EntryBB = B.GetInsertBlock()->getParent()->getEntryBlock();
1742f785676fSDimitry Andric B.SetInsertPoint(&EntryBB, EntryBB.begin());
1743f785676fSDimitry Andric }
1744f785676fSDimitry Andric
1745f785676fSDimitry Andric SinCos = B.CreateCall(Callee, Arg, "sincospi");
1746f785676fSDimitry Andric
1747f785676fSDimitry Andric if (SinCos->getType()->isStructTy()) {
1748f785676fSDimitry Andric Sin = B.CreateExtractValue(SinCos, 0, "sinpi");
1749f785676fSDimitry Andric Cos = B.CreateExtractValue(SinCos, 1, "cospi");
1750f785676fSDimitry Andric } else {
1751f785676fSDimitry Andric Sin = B.CreateExtractElement(SinCos, ConstantInt::get(B.getInt32Ty(), 0),
1752f785676fSDimitry Andric "sinpi");
1753f785676fSDimitry Andric Cos = B.CreateExtractElement(SinCos, ConstantInt::get(B.getInt32Ty(), 1),
1754f785676fSDimitry Andric "cospi");
1755f785676fSDimitry Andric }
1756f785676fSDimitry Andric }
1757f785676fSDimitry Andric
optimizeSinCosPi(CallInst * CI,IRBuilder<> & B)17583ca95b02SDimitry Andric Value *LibCallSimplifier::optimizeSinCosPi(CallInst *CI, IRBuilder<> &B) {
17593ca95b02SDimitry Andric // Make sure the prototype is as expected, otherwise the rest of the
17603ca95b02SDimitry Andric // function is probably invalid and likely to abort.
17613ca95b02SDimitry Andric if (!isTrigLibCall(CI))
17623ca95b02SDimitry Andric return nullptr;
17633ca95b02SDimitry Andric
17643ca95b02SDimitry Andric Value *Arg = CI->getArgOperand(0);
17653ca95b02SDimitry Andric SmallVector<CallInst *, 1> SinCalls;
17663ca95b02SDimitry Andric SmallVector<CallInst *, 1> CosCalls;
17673ca95b02SDimitry Andric SmallVector<CallInst *, 1> SinCosCalls;
17683ca95b02SDimitry Andric
17693ca95b02SDimitry Andric bool IsFloat = Arg->getType()->isFloatTy();
17703ca95b02SDimitry Andric
17713ca95b02SDimitry Andric // Look for all compatible sinpi, cospi and sincospi calls with the same
17723ca95b02SDimitry Andric // argument. If there are enough (in some sense) we can make the
17733ca95b02SDimitry Andric // substitution.
17743ca95b02SDimitry Andric Function *F = CI->getFunction();
17753ca95b02SDimitry Andric for (User *U : Arg->users())
17763ca95b02SDimitry Andric classifyArgUse(U, F, IsFloat, SinCalls, CosCalls, SinCosCalls);
17773ca95b02SDimitry Andric
17783ca95b02SDimitry Andric // It's only worthwhile if both sinpi and cospi are actually used.
17793ca95b02SDimitry Andric if (SinCosCalls.empty() && (SinCalls.empty() || CosCalls.empty()))
17803ca95b02SDimitry Andric return nullptr;
17813ca95b02SDimitry Andric
17823ca95b02SDimitry Andric Value *Sin, *Cos, *SinCos;
17833ca95b02SDimitry Andric insertSinCosCall(B, CI->getCalledFunction(), Arg, IsFloat, Sin, Cos, SinCos);
17843ca95b02SDimitry Andric
1785d88c1a5aSDimitry Andric auto replaceTrigInsts = [this](SmallVectorImpl<CallInst *> &Calls,
1786d88c1a5aSDimitry Andric Value *Res) {
1787d88c1a5aSDimitry Andric for (CallInst *C : Calls)
1788d88c1a5aSDimitry Andric replaceAllUsesWith(C, Res);
1789d88c1a5aSDimitry Andric };
1790d88c1a5aSDimitry Andric
17913ca95b02SDimitry Andric replaceTrigInsts(SinCalls, Sin);
17923ca95b02SDimitry Andric replaceTrigInsts(CosCalls, Cos);
17933ca95b02SDimitry Andric replaceTrigInsts(SinCosCalls, SinCos);
17943ca95b02SDimitry Andric
17953ca95b02SDimitry Andric return nullptr;
17963ca95b02SDimitry Andric }
17973ca95b02SDimitry Andric
classifyArgUse(Value * Val,Function * F,bool IsFloat,SmallVectorImpl<CallInst * > & SinCalls,SmallVectorImpl<CallInst * > & CosCalls,SmallVectorImpl<CallInst * > & SinCosCalls)17983ca95b02SDimitry Andric void LibCallSimplifier::classifyArgUse(
17993ca95b02SDimitry Andric Value *Val, Function *F, bool IsFloat,
18003ca95b02SDimitry Andric SmallVectorImpl<CallInst *> &SinCalls,
18013ca95b02SDimitry Andric SmallVectorImpl<CallInst *> &CosCalls,
18023ca95b02SDimitry Andric SmallVectorImpl<CallInst *> &SinCosCalls) {
18033ca95b02SDimitry Andric CallInst *CI = dyn_cast<CallInst>(Val);
18043ca95b02SDimitry Andric
18053ca95b02SDimitry Andric if (!CI)
18063ca95b02SDimitry Andric return;
18073ca95b02SDimitry Andric
18083ca95b02SDimitry Andric // Don't consider calls in other functions.
18093ca95b02SDimitry Andric if (CI->getFunction() != F)
18103ca95b02SDimitry Andric return;
18113ca95b02SDimitry Andric
18123ca95b02SDimitry Andric Function *Callee = CI->getCalledFunction();
18137a7e6055SDimitry Andric LibFunc Func;
18143ca95b02SDimitry Andric if (!Callee || !TLI->getLibFunc(*Callee, Func) || !TLI->has(Func) ||
18153ca95b02SDimitry Andric !isTrigLibCall(CI))
18163ca95b02SDimitry Andric return;
18173ca95b02SDimitry Andric
18183ca95b02SDimitry Andric if (IsFloat) {
18197a7e6055SDimitry Andric if (Func == LibFunc_sinpif)
18203ca95b02SDimitry Andric SinCalls.push_back(CI);
18217a7e6055SDimitry Andric else if (Func == LibFunc_cospif)
18223ca95b02SDimitry Andric CosCalls.push_back(CI);
18237a7e6055SDimitry Andric else if (Func == LibFunc_sincospif_stret)
18243ca95b02SDimitry Andric SinCosCalls.push_back(CI);
18253ca95b02SDimitry Andric } else {
18267a7e6055SDimitry Andric if (Func == LibFunc_sinpi)
18273ca95b02SDimitry Andric SinCalls.push_back(CI);
18287a7e6055SDimitry Andric else if (Func == LibFunc_cospi)
18293ca95b02SDimitry Andric CosCalls.push_back(CI);
18307a7e6055SDimitry Andric else if (Func == LibFunc_sincospi_stret)
18313ca95b02SDimitry Andric SinCosCalls.push_back(CI);
18323ca95b02SDimitry Andric }
18333ca95b02SDimitry Andric }
18343ca95b02SDimitry Andric
1835139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
1836139f7f9bSDimitry Andric // Integer Library Call Optimizations
1837139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
1838139f7f9bSDimitry Andric
optimizeFFS(CallInst * CI,IRBuilder<> & B)183939d628a0SDimitry Andric Value *LibCallSimplifier::optimizeFFS(CallInst *CI, IRBuilder<> &B) {
1840139f7f9bSDimitry Andric // ffs(x) -> x != 0 ? (i32)llvm.cttz(x)+1 : 0
1841d88c1a5aSDimitry Andric Value *Op = CI->getArgOperand(0);
1842139f7f9bSDimitry Andric Type *ArgType = Op->getType();
1843d88c1a5aSDimitry Andric Value *F = Intrinsic::getDeclaration(CI->getCalledFunction()->getParent(),
1844d88c1a5aSDimitry Andric Intrinsic::cttz, ArgType);
18457d523365SDimitry Andric Value *V = B.CreateCall(F, {Op, B.getTrue()}, "cttz");
1846139f7f9bSDimitry Andric V = B.CreateAdd(V, ConstantInt::get(V->getType(), 1));
1847139f7f9bSDimitry Andric V = B.CreateIntCast(V, B.getInt32Ty(), false);
1848139f7f9bSDimitry Andric
1849139f7f9bSDimitry Andric Value *Cond = B.CreateICmpNE(Op, Constant::getNullValue(ArgType));
1850139f7f9bSDimitry Andric return B.CreateSelect(Cond, V, B.getInt32(0));
1851139f7f9bSDimitry Andric }
1852139f7f9bSDimitry Andric
optimizeFls(CallInst * CI,IRBuilder<> & B)1853d88c1a5aSDimitry Andric Value *LibCallSimplifier::optimizeFls(CallInst *CI, IRBuilder<> &B) {
1854d88c1a5aSDimitry Andric // fls(x) -> (i32)(sizeInBits(x) - llvm.ctlz(x, false))
1855d88c1a5aSDimitry Andric Value *Op = CI->getArgOperand(0);
1856d88c1a5aSDimitry Andric Type *ArgType = Op->getType();
1857d88c1a5aSDimitry Andric Value *F = Intrinsic::getDeclaration(CI->getCalledFunction()->getParent(),
1858d88c1a5aSDimitry Andric Intrinsic::ctlz, ArgType);
1859d88c1a5aSDimitry Andric Value *V = B.CreateCall(F, {Op, B.getFalse()}, "ctlz");
1860d88c1a5aSDimitry Andric V = B.CreateSub(ConstantInt::get(V->getType(), ArgType->getIntegerBitWidth()),
1861d88c1a5aSDimitry Andric V);
1862d88c1a5aSDimitry Andric return B.CreateIntCast(V, CI->getType(), false);
1863d88c1a5aSDimitry Andric }
1864d88c1a5aSDimitry Andric
optimizeAbs(CallInst * CI,IRBuilder<> & B)186539d628a0SDimitry Andric Value *LibCallSimplifier::optimizeAbs(CallInst *CI, IRBuilder<> &B) {
18664ba319b5SDimitry Andric // abs(x) -> x <s 0 ? -x : x
18674ba319b5SDimitry Andric // The negation has 'nsw' because abs of INT_MIN is undefined.
18684ba319b5SDimitry Andric Value *X = CI->getArgOperand(0);
18694ba319b5SDimitry Andric Value *IsNeg = B.CreateICmpSLT(X, Constant::getNullValue(X->getType()));
18704ba319b5SDimitry Andric Value *NegX = B.CreateNSWNeg(X, "neg");
18714ba319b5SDimitry Andric return B.CreateSelect(IsNeg, NegX, X);
1872139f7f9bSDimitry Andric }
1873139f7f9bSDimitry Andric
optimizeIsDigit(CallInst * CI,IRBuilder<> & B)187439d628a0SDimitry Andric Value *LibCallSimplifier::optimizeIsDigit(CallInst *CI, IRBuilder<> &B) {
1875139f7f9bSDimitry Andric // isdigit(c) -> (c-'0') <u 10
1876139f7f9bSDimitry Andric Value *Op = CI->getArgOperand(0);
1877139f7f9bSDimitry Andric Op = B.CreateSub(Op, B.getInt32('0'), "isdigittmp");
1878139f7f9bSDimitry Andric Op = B.CreateICmpULT(Op, B.getInt32(10), "isdigit");
1879139f7f9bSDimitry Andric return B.CreateZExt(Op, CI->getType());
1880139f7f9bSDimitry Andric }
1881139f7f9bSDimitry Andric
optimizeIsAscii(CallInst * CI,IRBuilder<> & B)188239d628a0SDimitry Andric Value *LibCallSimplifier::optimizeIsAscii(CallInst *CI, IRBuilder<> &B) {
1883139f7f9bSDimitry Andric // isascii(c) -> c <u 128
1884139f7f9bSDimitry Andric Value *Op = CI->getArgOperand(0);
1885139f7f9bSDimitry Andric Op = B.CreateICmpULT(Op, B.getInt32(128), "isascii");
1886139f7f9bSDimitry Andric return B.CreateZExt(Op, CI->getType());
1887139f7f9bSDimitry Andric }
1888139f7f9bSDimitry Andric
optimizeToAscii(CallInst * CI,IRBuilder<> & B)188939d628a0SDimitry Andric Value *LibCallSimplifier::optimizeToAscii(CallInst *CI, IRBuilder<> &B) {
1890139f7f9bSDimitry Andric // toascii(c) -> c & 0x7f
1891139f7f9bSDimitry Andric return B.CreateAnd(CI->getArgOperand(0),
1892139f7f9bSDimitry Andric ConstantInt::get(CI->getType(), 0x7F));
1893139f7f9bSDimitry Andric }
1894139f7f9bSDimitry Andric
optimizeAtoi(CallInst * CI,IRBuilder<> & B)18954ba319b5SDimitry Andric Value *LibCallSimplifier::optimizeAtoi(CallInst *CI, IRBuilder<> &B) {
18964ba319b5SDimitry Andric StringRef Str;
18974ba319b5SDimitry Andric if (!getConstantStringInfo(CI->getArgOperand(0), Str))
18984ba319b5SDimitry Andric return nullptr;
18994ba319b5SDimitry Andric
19004ba319b5SDimitry Andric return convertStrToNumber(CI, Str, 10);
19014ba319b5SDimitry Andric }
19024ba319b5SDimitry Andric
optimizeStrtol(CallInst * CI,IRBuilder<> & B)19034ba319b5SDimitry Andric Value *LibCallSimplifier::optimizeStrtol(CallInst *CI, IRBuilder<> &B) {
19044ba319b5SDimitry Andric StringRef Str;
19054ba319b5SDimitry Andric if (!getConstantStringInfo(CI->getArgOperand(0), Str))
19064ba319b5SDimitry Andric return nullptr;
19074ba319b5SDimitry Andric
19084ba319b5SDimitry Andric if (!isa<ConstantPointerNull>(CI->getArgOperand(1)))
19094ba319b5SDimitry Andric return nullptr;
19104ba319b5SDimitry Andric
19114ba319b5SDimitry Andric if (ConstantInt *CInt = dyn_cast<ConstantInt>(CI->getArgOperand(2))) {
19124ba319b5SDimitry Andric return convertStrToNumber(CI, Str, CInt->getSExtValue());
19134ba319b5SDimitry Andric }
19144ba319b5SDimitry Andric
19154ba319b5SDimitry Andric return nullptr;
19164ba319b5SDimitry Andric }
19174ba319b5SDimitry Andric
1918139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
1919139f7f9bSDimitry Andric // Formatting and IO Library Call Optimizations
1920139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
1921139f7f9bSDimitry Andric
192239d628a0SDimitry Andric static bool isReportingError(Function *Callee, CallInst *CI, int StreamArg);
1923f785676fSDimitry Andric
optimizeErrorReporting(CallInst * CI,IRBuilder<> & B,int StreamArg)192439d628a0SDimitry Andric Value *LibCallSimplifier::optimizeErrorReporting(CallInst *CI, IRBuilder<> &B,
192539d628a0SDimitry Andric int StreamArg) {
19263ca95b02SDimitry Andric Function *Callee = CI->getCalledFunction();
1927f785676fSDimitry Andric // Error reporting calls should be cold, mark them as such.
1928f785676fSDimitry Andric // This applies even to non-builtin calls: it is only a hint and applies to
1929f785676fSDimitry Andric // functions that the frontend might not understand as builtins.
1930f785676fSDimitry Andric
1931f785676fSDimitry Andric // This heuristic was suggested in:
1932f785676fSDimitry Andric // Improving Static Branch Prediction in a Compiler
1933f785676fSDimitry Andric // Brian L. Deitrich, Ben-Chung Cheng, Wen-mei W. Hwu
1934f785676fSDimitry Andric // Proceedings of PACT'98, Oct. 1998, IEEE
193539d628a0SDimitry Andric if (!CI->hasFnAttr(Attribute::Cold) &&
193639d628a0SDimitry Andric isReportingError(Callee, CI, StreamArg)) {
19377a7e6055SDimitry Andric CI->addAttribute(AttributeList::FunctionIndex, Attribute::Cold);
1938f785676fSDimitry Andric }
1939f785676fSDimitry Andric
194091bc56edSDimitry Andric return nullptr;
1941f785676fSDimitry Andric }
1942f785676fSDimitry Andric
isReportingError(Function * Callee,CallInst * CI,int StreamArg)194339d628a0SDimitry Andric static bool isReportingError(Function *Callee, CallInst *CI, int StreamArg) {
194451690af2SDimitry Andric if (!Callee || !Callee->isDeclaration())
1945f785676fSDimitry Andric return false;
1946f785676fSDimitry Andric
1947f785676fSDimitry Andric if (StreamArg < 0)
1948f785676fSDimitry Andric return true;
1949f785676fSDimitry Andric
1950f785676fSDimitry Andric // These functions might be considered cold, but only if their stream
1951f785676fSDimitry Andric // argument is stderr.
1952f785676fSDimitry Andric
1953f785676fSDimitry Andric if (StreamArg >= (int)CI->getNumArgOperands())
1954f785676fSDimitry Andric return false;
1955f785676fSDimitry Andric LoadInst *LI = dyn_cast<LoadInst>(CI->getArgOperand(StreamArg));
1956f785676fSDimitry Andric if (!LI)
1957f785676fSDimitry Andric return false;
1958f785676fSDimitry Andric GlobalVariable *GV = dyn_cast<GlobalVariable>(LI->getPointerOperand());
1959f785676fSDimitry Andric if (!GV || !GV->isDeclaration())
1960f785676fSDimitry Andric return false;
1961f785676fSDimitry Andric return GV->getName() == "stderr";
1962f785676fSDimitry Andric }
1963f785676fSDimitry Andric
optimizePrintFString(CallInst * CI,IRBuilder<> & B)196439d628a0SDimitry Andric Value *LibCallSimplifier::optimizePrintFString(CallInst *CI, IRBuilder<> &B) {
1965139f7f9bSDimitry Andric // Check for a fixed format string.
1966139f7f9bSDimitry Andric StringRef FormatStr;
1967139f7f9bSDimitry Andric if (!getConstantStringInfo(CI->getArgOperand(0), FormatStr))
196891bc56edSDimitry Andric return nullptr;
1969139f7f9bSDimitry Andric
1970139f7f9bSDimitry Andric // Empty format string -> noop.
1971139f7f9bSDimitry Andric if (FormatStr.empty()) // Tolerate printf's declared void.
197239d628a0SDimitry Andric return CI->use_empty() ? (Value *)CI : ConstantInt::get(CI->getType(), 0);
1973139f7f9bSDimitry Andric
1974139f7f9bSDimitry Andric // Do not do any of the following transformations if the printf return value
1975139f7f9bSDimitry Andric // is used, in general the printf return value is not compatible with either
1976139f7f9bSDimitry Andric // putchar() or puts().
1977139f7f9bSDimitry Andric if (!CI->use_empty())
197891bc56edSDimitry Andric return nullptr;
1979139f7f9bSDimitry Andric
19803ca95b02SDimitry Andric // printf("x") -> putchar('x'), even for "%" and "%%".
19813ca95b02SDimitry Andric if (FormatStr.size() == 1 || FormatStr == "%%")
19823ca95b02SDimitry Andric return emitPutChar(B.getInt32(FormatStr[0]), B, TLI);
19833ca95b02SDimitry Andric
19843ca95b02SDimitry Andric // printf("%s", "a") --> putchar('a')
19853ca95b02SDimitry Andric if (FormatStr == "%s" && CI->getNumArgOperands() > 1) {
19863ca95b02SDimitry Andric StringRef ChrStr;
19873ca95b02SDimitry Andric if (!getConstantStringInfo(CI->getOperand(1), ChrStr))
19883ca95b02SDimitry Andric return nullptr;
19893ca95b02SDimitry Andric if (ChrStr.size() != 1)
19903ca95b02SDimitry Andric return nullptr;
19913ca95b02SDimitry Andric return emitPutChar(B.getInt32(ChrStr[0]), B, TLI);
1992139f7f9bSDimitry Andric }
1993139f7f9bSDimitry Andric
1994139f7f9bSDimitry Andric // printf("foo\n") --> puts("foo")
1995139f7f9bSDimitry Andric if (FormatStr[FormatStr.size() - 1] == '\n' &&
1996f785676fSDimitry Andric FormatStr.find('%') == StringRef::npos) { // No format characters.
1997139f7f9bSDimitry Andric // Create a string literal with no \n on it. We expect the constant merge
1998139f7f9bSDimitry Andric // pass to be run after this pass, to merge duplicate strings.
1999139f7f9bSDimitry Andric FormatStr = FormatStr.drop_back();
2000139f7f9bSDimitry Andric Value *GV = B.CreateGlobalString(FormatStr, "str");
20013ca95b02SDimitry Andric return emitPutS(GV, B, TLI);
2002139f7f9bSDimitry Andric }
2003139f7f9bSDimitry Andric
2004139f7f9bSDimitry Andric // Optimize specific format strings.
2005139f7f9bSDimitry Andric // printf("%c", chr) --> putchar(chr)
2006139f7f9bSDimitry Andric if (FormatStr == "%c" && CI->getNumArgOperands() > 1 &&
20073ca95b02SDimitry Andric CI->getArgOperand(1)->getType()->isIntegerTy())
20083ca95b02SDimitry Andric return emitPutChar(CI->getArgOperand(1), B, TLI);
2009139f7f9bSDimitry Andric
2010139f7f9bSDimitry Andric // printf("%s\n", str) --> puts(str)
2011139f7f9bSDimitry Andric if (FormatStr == "%s\n" && CI->getNumArgOperands() > 1 &&
20123ca95b02SDimitry Andric CI->getArgOperand(1)->getType()->isPointerTy())
20133ca95b02SDimitry Andric return emitPutS(CI->getArgOperand(1), B, TLI);
201491bc56edSDimitry Andric return nullptr;
2015139f7f9bSDimitry Andric }
2016139f7f9bSDimitry Andric
optimizePrintF(CallInst * CI,IRBuilder<> & B)201739d628a0SDimitry Andric Value *LibCallSimplifier::optimizePrintF(CallInst *CI, IRBuilder<> &B) {
201839d628a0SDimitry Andric
201939d628a0SDimitry Andric Function *Callee = CI->getCalledFunction();
2020139f7f9bSDimitry Andric FunctionType *FT = Callee->getFunctionType();
202139d628a0SDimitry Andric if (Value *V = optimizePrintFString(CI, B)) {
2022139f7f9bSDimitry Andric return V;
2023139f7f9bSDimitry Andric }
2024139f7f9bSDimitry Andric
2025139f7f9bSDimitry Andric // printf(format, ...) -> iprintf(format, ...) if no floating point
2026139f7f9bSDimitry Andric // arguments.
20277a7e6055SDimitry Andric if (TLI->has(LibFunc_iprintf) && !callHasFloatingPointArgument(CI)) {
2028139f7f9bSDimitry Andric Module *M = B.GetInsertBlock()->getParent()->getParent();
2029139f7f9bSDimitry Andric Constant *IPrintFFn =
2030139f7f9bSDimitry Andric M->getOrInsertFunction("iprintf", FT, Callee->getAttributes());
2031139f7f9bSDimitry Andric CallInst *New = cast<CallInst>(CI->clone());
2032139f7f9bSDimitry Andric New->setCalledFunction(IPrintFFn);
2033139f7f9bSDimitry Andric B.Insert(New);
2034139f7f9bSDimitry Andric return New;
2035139f7f9bSDimitry Andric }
203691bc56edSDimitry Andric return nullptr;
2037139f7f9bSDimitry Andric }
2038139f7f9bSDimitry Andric
optimizeSPrintFString(CallInst * CI,IRBuilder<> & B)203939d628a0SDimitry Andric Value *LibCallSimplifier::optimizeSPrintFString(CallInst *CI, IRBuilder<> &B) {
2040139f7f9bSDimitry Andric // Check for a fixed format string.
2041139f7f9bSDimitry Andric StringRef FormatStr;
2042139f7f9bSDimitry Andric if (!getConstantStringInfo(CI->getArgOperand(1), FormatStr))
204391bc56edSDimitry Andric return nullptr;
2044139f7f9bSDimitry Andric
2045139f7f9bSDimitry Andric // If we just have a format string (nothing else crazy) transform it.
2046139f7f9bSDimitry Andric if (CI->getNumArgOperands() == 2) {
2047139f7f9bSDimitry Andric // Make sure there's no % in the constant array. We could try to handle
2048139f7f9bSDimitry Andric // %% -> % in the future if we cared.
20494ba319b5SDimitry Andric if (FormatStr.find('%') != StringRef::npos)
205091bc56edSDimitry Andric return nullptr; // we found a format specifier, bail out.
2051139f7f9bSDimitry Andric
20524ba319b5SDimitry Andric // sprintf(str, fmt) -> llvm.memcpy(align 1 str, align 1 fmt, strlen(fmt)+1)
20534ba319b5SDimitry Andric B.CreateMemCpy(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1,
2054ff0cc061SDimitry Andric ConstantInt::get(DL.getIntPtrType(CI->getContext()),
20554ba319b5SDimitry Andric FormatStr.size() + 1)); // Copy the null byte.
2056139f7f9bSDimitry Andric return ConstantInt::get(CI->getType(), FormatStr.size());
2057139f7f9bSDimitry Andric }
2058139f7f9bSDimitry Andric
2059139f7f9bSDimitry Andric // The remaining optimizations require the format string to be "%s" or "%c"
2060139f7f9bSDimitry Andric // and have an extra operand.
2061139f7f9bSDimitry Andric if (FormatStr.size() != 2 || FormatStr[0] != '%' ||
2062139f7f9bSDimitry Andric CI->getNumArgOperands() < 3)
206391bc56edSDimitry Andric return nullptr;
2064139f7f9bSDimitry Andric
2065139f7f9bSDimitry Andric // Decode the second character of the format string.
2066139f7f9bSDimitry Andric if (FormatStr[1] == 'c') {
2067139f7f9bSDimitry Andric // sprintf(dst, "%c", chr) --> *(i8*)dst = chr; *((i8*)dst+1) = 0
206839d628a0SDimitry Andric if (!CI->getArgOperand(2)->getType()->isIntegerTy())
206939d628a0SDimitry Andric return nullptr;
2070139f7f9bSDimitry Andric Value *V = B.CreateTrunc(CI->getArgOperand(2), B.getInt8Ty(), "char");
20713ca95b02SDimitry Andric Value *Ptr = castToCStr(CI->getArgOperand(0), B);
2072139f7f9bSDimitry Andric B.CreateStore(V, Ptr);
2073ff0cc061SDimitry Andric Ptr = B.CreateGEP(B.getInt8Ty(), Ptr, B.getInt32(1), "nul");
2074139f7f9bSDimitry Andric B.CreateStore(B.getInt8(0), Ptr);
2075139f7f9bSDimitry Andric
2076139f7f9bSDimitry Andric return ConstantInt::get(CI->getType(), 1);
2077139f7f9bSDimitry Andric }
2078139f7f9bSDimitry Andric
2079139f7f9bSDimitry Andric if (FormatStr[1] == 's') {
2080139f7f9bSDimitry Andric // sprintf(dest, "%s", str) -> llvm.memcpy(dest, str, strlen(str)+1, 1)
208139d628a0SDimitry Andric if (!CI->getArgOperand(2)->getType()->isPointerTy())
208239d628a0SDimitry Andric return nullptr;
2083139f7f9bSDimitry Andric
20843ca95b02SDimitry Andric Value *Len = emitStrLen(CI->getArgOperand(2), B, DL, TLI);
2085139f7f9bSDimitry Andric if (!Len)
208691bc56edSDimitry Andric return nullptr;
208739d628a0SDimitry Andric Value *IncLen =
208839d628a0SDimitry Andric B.CreateAdd(Len, ConstantInt::get(Len->getType(), 1), "leninc");
20894ba319b5SDimitry Andric B.CreateMemCpy(CI->getArgOperand(0), 1, CI->getArgOperand(2), 1, IncLen);
2090139f7f9bSDimitry Andric
2091139f7f9bSDimitry Andric // The sprintf result is the unincremented number of bytes in the string.
2092139f7f9bSDimitry Andric return B.CreateIntCast(Len, CI->getType(), false);
2093139f7f9bSDimitry Andric }
209491bc56edSDimitry Andric return nullptr;
2095139f7f9bSDimitry Andric }
2096139f7f9bSDimitry Andric
optimizeSPrintF(CallInst * CI,IRBuilder<> & B)209739d628a0SDimitry Andric Value *LibCallSimplifier::optimizeSPrintF(CallInst *CI, IRBuilder<> &B) {
209839d628a0SDimitry Andric Function *Callee = CI->getCalledFunction();
2099139f7f9bSDimitry Andric FunctionType *FT = Callee->getFunctionType();
210039d628a0SDimitry Andric if (Value *V = optimizeSPrintFString(CI, B)) {
2101139f7f9bSDimitry Andric return V;
2102139f7f9bSDimitry Andric }
2103139f7f9bSDimitry Andric
2104139f7f9bSDimitry Andric // sprintf(str, format, ...) -> siprintf(str, format, ...) if no floating
2105139f7f9bSDimitry Andric // point arguments.
21067a7e6055SDimitry Andric if (TLI->has(LibFunc_siprintf) && !callHasFloatingPointArgument(CI)) {
2107139f7f9bSDimitry Andric Module *M = B.GetInsertBlock()->getParent()->getParent();
2108139f7f9bSDimitry Andric Constant *SIPrintFFn =
2109139f7f9bSDimitry Andric M->getOrInsertFunction("siprintf", FT, Callee->getAttributes());
2110139f7f9bSDimitry Andric CallInst *New = cast<CallInst>(CI->clone());
2111139f7f9bSDimitry Andric New->setCalledFunction(SIPrintFFn);
2112139f7f9bSDimitry Andric B.Insert(New);
2113139f7f9bSDimitry Andric return New;
2114139f7f9bSDimitry Andric }
211591bc56edSDimitry Andric return nullptr;
2116139f7f9bSDimitry Andric }
2117139f7f9bSDimitry Andric
optimizeSnPrintFString(CallInst * CI,IRBuilder<> & B)21184ba319b5SDimitry Andric Value *LibCallSimplifier::optimizeSnPrintFString(CallInst *CI, IRBuilder<> &B) {
21194ba319b5SDimitry Andric // Check for a fixed format string.
21204ba319b5SDimitry Andric StringRef FormatStr;
21214ba319b5SDimitry Andric if (!getConstantStringInfo(CI->getArgOperand(2), FormatStr))
21224ba319b5SDimitry Andric return nullptr;
21234ba319b5SDimitry Andric
21244ba319b5SDimitry Andric // Check for size
21254ba319b5SDimitry Andric ConstantInt *Size = dyn_cast<ConstantInt>(CI->getArgOperand(1));
21264ba319b5SDimitry Andric if (!Size)
21274ba319b5SDimitry Andric return nullptr;
21284ba319b5SDimitry Andric
21294ba319b5SDimitry Andric uint64_t N = Size->getZExtValue();
21304ba319b5SDimitry Andric
21314ba319b5SDimitry Andric // If we just have a format string (nothing else crazy) transform it.
21324ba319b5SDimitry Andric if (CI->getNumArgOperands() == 3) {
21334ba319b5SDimitry Andric // Make sure there's no % in the constant array. We could try to handle
21344ba319b5SDimitry Andric // %% -> % in the future if we cared.
21354ba319b5SDimitry Andric if (FormatStr.find('%') != StringRef::npos)
21364ba319b5SDimitry Andric return nullptr; // we found a format specifier, bail out.
21374ba319b5SDimitry Andric
21384ba319b5SDimitry Andric if (N == 0)
21394ba319b5SDimitry Andric return ConstantInt::get(CI->getType(), FormatStr.size());
21404ba319b5SDimitry Andric else if (N < FormatStr.size() + 1)
21414ba319b5SDimitry Andric return nullptr;
21424ba319b5SDimitry Andric
21434ba319b5SDimitry Andric // sprintf(str, size, fmt) -> llvm.memcpy(align 1 str, align 1 fmt,
21444ba319b5SDimitry Andric // strlen(fmt)+1)
21454ba319b5SDimitry Andric B.CreateMemCpy(
21464ba319b5SDimitry Andric CI->getArgOperand(0), 1, CI->getArgOperand(2), 1,
21474ba319b5SDimitry Andric ConstantInt::get(DL.getIntPtrType(CI->getContext()),
21484ba319b5SDimitry Andric FormatStr.size() + 1)); // Copy the null byte.
21494ba319b5SDimitry Andric return ConstantInt::get(CI->getType(), FormatStr.size());
21504ba319b5SDimitry Andric }
21514ba319b5SDimitry Andric
21524ba319b5SDimitry Andric // The remaining optimizations require the format string to be "%s" or "%c"
21534ba319b5SDimitry Andric // and have an extra operand.
21544ba319b5SDimitry Andric if (FormatStr.size() == 2 && FormatStr[0] == '%' &&
21554ba319b5SDimitry Andric CI->getNumArgOperands() == 4) {
21564ba319b5SDimitry Andric
21574ba319b5SDimitry Andric // Decode the second character of the format string.
21584ba319b5SDimitry Andric if (FormatStr[1] == 'c') {
21594ba319b5SDimitry Andric if (N == 0)
21604ba319b5SDimitry Andric return ConstantInt::get(CI->getType(), 1);
21614ba319b5SDimitry Andric else if (N == 1)
21624ba319b5SDimitry Andric return nullptr;
21634ba319b5SDimitry Andric
21644ba319b5SDimitry Andric // snprintf(dst, size, "%c", chr) --> *(i8*)dst = chr; *((i8*)dst+1) = 0
21654ba319b5SDimitry Andric if (!CI->getArgOperand(3)->getType()->isIntegerTy())
21664ba319b5SDimitry Andric return nullptr;
21674ba319b5SDimitry Andric Value *V = B.CreateTrunc(CI->getArgOperand(3), B.getInt8Ty(), "char");
21684ba319b5SDimitry Andric Value *Ptr = castToCStr(CI->getArgOperand(0), B);
21694ba319b5SDimitry Andric B.CreateStore(V, Ptr);
21704ba319b5SDimitry Andric Ptr = B.CreateGEP(B.getInt8Ty(), Ptr, B.getInt32(1), "nul");
21714ba319b5SDimitry Andric B.CreateStore(B.getInt8(0), Ptr);
21724ba319b5SDimitry Andric
21734ba319b5SDimitry Andric return ConstantInt::get(CI->getType(), 1);
21744ba319b5SDimitry Andric }
21754ba319b5SDimitry Andric
21764ba319b5SDimitry Andric if (FormatStr[1] == 's') {
21774ba319b5SDimitry Andric // snprintf(dest, size, "%s", str) to llvm.memcpy(dest, str, len+1, 1)
21784ba319b5SDimitry Andric StringRef Str;
21794ba319b5SDimitry Andric if (!getConstantStringInfo(CI->getArgOperand(3), Str))
21804ba319b5SDimitry Andric return nullptr;
21814ba319b5SDimitry Andric
21824ba319b5SDimitry Andric if (N == 0)
21834ba319b5SDimitry Andric return ConstantInt::get(CI->getType(), Str.size());
21844ba319b5SDimitry Andric else if (N < Str.size() + 1)
21854ba319b5SDimitry Andric return nullptr;
21864ba319b5SDimitry Andric
21874ba319b5SDimitry Andric B.CreateMemCpy(CI->getArgOperand(0), 1, CI->getArgOperand(3), 1,
21884ba319b5SDimitry Andric ConstantInt::get(CI->getType(), Str.size() + 1));
21894ba319b5SDimitry Andric
21904ba319b5SDimitry Andric // The snprintf result is the unincremented number of bytes in the string.
21914ba319b5SDimitry Andric return ConstantInt::get(CI->getType(), Str.size());
21924ba319b5SDimitry Andric }
21934ba319b5SDimitry Andric }
21944ba319b5SDimitry Andric return nullptr;
21954ba319b5SDimitry Andric }
21964ba319b5SDimitry Andric
optimizeSnPrintF(CallInst * CI,IRBuilder<> & B)21974ba319b5SDimitry Andric Value *LibCallSimplifier::optimizeSnPrintF(CallInst *CI, IRBuilder<> &B) {
21984ba319b5SDimitry Andric if (Value *V = optimizeSnPrintFString(CI, B)) {
21994ba319b5SDimitry Andric return V;
22004ba319b5SDimitry Andric }
22014ba319b5SDimitry Andric
22024ba319b5SDimitry Andric return nullptr;
22034ba319b5SDimitry Andric }
22044ba319b5SDimitry Andric
optimizeFPrintFString(CallInst * CI,IRBuilder<> & B)220539d628a0SDimitry Andric Value *LibCallSimplifier::optimizeFPrintFString(CallInst *CI, IRBuilder<> &B) {
220639d628a0SDimitry Andric optimizeErrorReporting(CI, B, 0);
2207f785676fSDimitry Andric
2208139f7f9bSDimitry Andric // All the optimizations depend on the format string.
2209139f7f9bSDimitry Andric StringRef FormatStr;
2210139f7f9bSDimitry Andric if (!getConstantStringInfo(CI->getArgOperand(1), FormatStr))
221191bc56edSDimitry Andric return nullptr;
2212139f7f9bSDimitry Andric
2213284c1978SDimitry Andric // Do not do any of the following transformations if the fprintf return
2214284c1978SDimitry Andric // value is used, in general the fprintf return value is not compatible
2215284c1978SDimitry Andric // with fwrite(), fputc() or fputs().
2216284c1978SDimitry Andric if (!CI->use_empty())
221791bc56edSDimitry Andric return nullptr;
2218284c1978SDimitry Andric
2219139f7f9bSDimitry Andric // fprintf(F, "foo") --> fwrite("foo", 3, 1, F)
2220139f7f9bSDimitry Andric if (CI->getNumArgOperands() == 2) {
22214ba319b5SDimitry Andric // Could handle %% -> % if we cared.
22224ba319b5SDimitry Andric if (FormatStr.find('%') != StringRef::npos)
222391bc56edSDimitry Andric return nullptr; // We found a format specifier.
2224139f7f9bSDimitry Andric
22253ca95b02SDimitry Andric return emitFWrite(
222639d628a0SDimitry Andric CI->getArgOperand(1),
2227ff0cc061SDimitry Andric ConstantInt::get(DL.getIntPtrType(CI->getContext()), FormatStr.size()),
222891bc56edSDimitry Andric CI->getArgOperand(0), B, DL, TLI);
2229139f7f9bSDimitry Andric }
2230139f7f9bSDimitry Andric
2231139f7f9bSDimitry Andric // The remaining optimizations require the format string to be "%s" or "%c"
2232139f7f9bSDimitry Andric // and have an extra operand.
2233139f7f9bSDimitry Andric if (FormatStr.size() != 2 || FormatStr[0] != '%' ||
2234139f7f9bSDimitry Andric CI->getNumArgOperands() < 3)
223591bc56edSDimitry Andric return nullptr;
2236139f7f9bSDimitry Andric
2237139f7f9bSDimitry Andric // Decode the second character of the format string.
2238139f7f9bSDimitry Andric if (FormatStr[1] == 'c') {
2239139f7f9bSDimitry Andric // fprintf(F, "%c", chr) --> fputc(chr, F)
224039d628a0SDimitry Andric if (!CI->getArgOperand(2)->getType()->isIntegerTy())
224139d628a0SDimitry Andric return nullptr;
22423ca95b02SDimitry Andric return emitFPutC(CI->getArgOperand(2), CI->getArgOperand(0), B, TLI);
2243139f7f9bSDimitry Andric }
2244139f7f9bSDimitry Andric
2245139f7f9bSDimitry Andric if (FormatStr[1] == 's') {
2246139f7f9bSDimitry Andric // fprintf(F, "%s", str) --> fputs(str, F)
2247284c1978SDimitry Andric if (!CI->getArgOperand(2)->getType()->isPointerTy())
224891bc56edSDimitry Andric return nullptr;
22493ca95b02SDimitry Andric return emitFPutS(CI->getArgOperand(2), CI->getArgOperand(0), B, TLI);
2250139f7f9bSDimitry Andric }
225191bc56edSDimitry Andric return nullptr;
2252139f7f9bSDimitry Andric }
2253139f7f9bSDimitry Andric
optimizeFPrintF(CallInst * CI,IRBuilder<> & B)225439d628a0SDimitry Andric Value *LibCallSimplifier::optimizeFPrintF(CallInst *CI, IRBuilder<> &B) {
225539d628a0SDimitry Andric Function *Callee = CI->getCalledFunction();
2256139f7f9bSDimitry Andric FunctionType *FT = Callee->getFunctionType();
225739d628a0SDimitry Andric if (Value *V = optimizeFPrintFString(CI, B)) {
2258139f7f9bSDimitry Andric return V;
2259139f7f9bSDimitry Andric }
2260139f7f9bSDimitry Andric
2261139f7f9bSDimitry Andric // fprintf(stream, format, ...) -> fiprintf(stream, format, ...) if no
2262139f7f9bSDimitry Andric // floating point arguments.
22637a7e6055SDimitry Andric if (TLI->has(LibFunc_fiprintf) && !callHasFloatingPointArgument(CI)) {
2264139f7f9bSDimitry Andric Module *M = B.GetInsertBlock()->getParent()->getParent();
2265139f7f9bSDimitry Andric Constant *FIPrintFFn =
2266139f7f9bSDimitry Andric M->getOrInsertFunction("fiprintf", FT, Callee->getAttributes());
2267139f7f9bSDimitry Andric CallInst *New = cast<CallInst>(CI->clone());
2268139f7f9bSDimitry Andric New->setCalledFunction(FIPrintFFn);
2269139f7f9bSDimitry Andric B.Insert(New);
2270139f7f9bSDimitry Andric return New;
2271139f7f9bSDimitry Andric }
227291bc56edSDimitry Andric return nullptr;
2273139f7f9bSDimitry Andric }
2274139f7f9bSDimitry Andric
optimizeFWrite(CallInst * CI,IRBuilder<> & B)227539d628a0SDimitry Andric Value *LibCallSimplifier::optimizeFWrite(CallInst *CI, IRBuilder<> &B) {
227639d628a0SDimitry Andric optimizeErrorReporting(CI, B, 3);
2277f785676fSDimitry Andric
2278139f7f9bSDimitry Andric // Get the element size and count.
2279139f7f9bSDimitry Andric ConstantInt *SizeC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
2280139f7f9bSDimitry Andric ConstantInt *CountC = dyn_cast<ConstantInt>(CI->getArgOperand(2));
22814ba319b5SDimitry Andric if (SizeC && CountC) {
2282139f7f9bSDimitry Andric uint64_t Bytes = SizeC->getZExtValue() * CountC->getZExtValue();
2283139f7f9bSDimitry Andric
2284139f7f9bSDimitry Andric // If this is writing zero records, remove the call (it's a noop).
2285139f7f9bSDimitry Andric if (Bytes == 0)
2286139f7f9bSDimitry Andric return ConstantInt::get(CI->getType(), 0);
2287139f7f9bSDimitry Andric
2288139f7f9bSDimitry Andric // If this is writing one byte, turn it into fputc.
2289139f7f9bSDimitry Andric // This optimisation is only valid, if the return value is unused.
2290139f7f9bSDimitry Andric if (Bytes == 1 && CI->use_empty()) { // fwrite(S,1,1,F) -> fputc(S[0],F)
22913ca95b02SDimitry Andric Value *Char = B.CreateLoad(castToCStr(CI->getArgOperand(0), B), "char");
22923ca95b02SDimitry Andric Value *NewCI = emitFPutC(Char, CI->getArgOperand(3), B, TLI);
229391bc56edSDimitry Andric return NewCI ? ConstantInt::get(CI->getType(), 1) : nullptr;
2294139f7f9bSDimitry Andric }
22954ba319b5SDimitry Andric }
22964ba319b5SDimitry Andric
22974ba319b5SDimitry Andric if (isLocallyOpenedFile(CI->getArgOperand(3), CI, B, TLI))
22984ba319b5SDimitry Andric return emitFWriteUnlocked(CI->getArgOperand(0), CI->getArgOperand(1),
22994ba319b5SDimitry Andric CI->getArgOperand(2), CI->getArgOperand(3), B, DL,
23004ba319b5SDimitry Andric TLI);
2301139f7f9bSDimitry Andric
230291bc56edSDimitry Andric return nullptr;
2303139f7f9bSDimitry Andric }
2304139f7f9bSDimitry Andric
optimizeFPuts(CallInst * CI,IRBuilder<> & B)230539d628a0SDimitry Andric Value *LibCallSimplifier::optimizeFPuts(CallInst *CI, IRBuilder<> &B) {
230639d628a0SDimitry Andric optimizeErrorReporting(CI, B, 1);
230739d628a0SDimitry Andric
23083ca95b02SDimitry Andric // Don't rewrite fputs to fwrite when optimising for size because fwrite
23093ca95b02SDimitry Andric // requires more arguments and thus extra MOVs are required.
23104ba319b5SDimitry Andric if (CI->getFunction()->optForSize())
23113ca95b02SDimitry Andric return nullptr;
2312f785676fSDimitry Andric
23134ba319b5SDimitry Andric // Check if has any use
23144ba319b5SDimitry Andric if (!CI->use_empty()) {
23154ba319b5SDimitry Andric if (isLocallyOpenedFile(CI->getArgOperand(1), CI, B, TLI))
23164ba319b5SDimitry Andric return emitFPutSUnlocked(CI->getArgOperand(0), CI->getArgOperand(1), B,
23174ba319b5SDimitry Andric TLI);
23184ba319b5SDimitry Andric else
23193ca95b02SDimitry Andric // We can't optimize if return value is used.
232091bc56edSDimitry Andric return nullptr;
23214ba319b5SDimitry Andric }
2322139f7f9bSDimitry Andric
2323139f7f9bSDimitry Andric // fputs(s,F) --> fwrite(s,1,strlen(s),F)
2324139f7f9bSDimitry Andric uint64_t Len = GetStringLength(CI->getArgOperand(0));
232539d628a0SDimitry Andric if (!Len)
232639d628a0SDimitry Andric return nullptr;
232739d628a0SDimitry Andric
2328139f7f9bSDimitry Andric // Known to have no uses (see above).
23293ca95b02SDimitry Andric return emitFWrite(
233039d628a0SDimitry Andric CI->getArgOperand(0),
2331ff0cc061SDimitry Andric ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len - 1),
233291bc56edSDimitry Andric CI->getArgOperand(1), B, DL, TLI);
2333139f7f9bSDimitry Andric }
2334139f7f9bSDimitry Andric
optimizeFPutc(CallInst * CI,IRBuilder<> & B)23354ba319b5SDimitry Andric Value *LibCallSimplifier::optimizeFPutc(CallInst *CI, IRBuilder<> &B) {
23364ba319b5SDimitry Andric optimizeErrorReporting(CI, B, 1);
23374ba319b5SDimitry Andric
23384ba319b5SDimitry Andric if (isLocallyOpenedFile(CI->getArgOperand(1), CI, B, TLI))
23394ba319b5SDimitry Andric return emitFPutCUnlocked(CI->getArgOperand(0), CI->getArgOperand(1), B,
23404ba319b5SDimitry Andric TLI);
23414ba319b5SDimitry Andric
23424ba319b5SDimitry Andric return nullptr;
23434ba319b5SDimitry Andric }
23444ba319b5SDimitry Andric
optimizeFGetc(CallInst * CI,IRBuilder<> & B)23454ba319b5SDimitry Andric Value *LibCallSimplifier::optimizeFGetc(CallInst *CI, IRBuilder<> &B) {
23464ba319b5SDimitry Andric if (isLocallyOpenedFile(CI->getArgOperand(0), CI, B, TLI))
23474ba319b5SDimitry Andric return emitFGetCUnlocked(CI->getArgOperand(0), B, TLI);
23484ba319b5SDimitry Andric
23494ba319b5SDimitry Andric return nullptr;
23504ba319b5SDimitry Andric }
23514ba319b5SDimitry Andric
optimizeFGets(CallInst * CI,IRBuilder<> & B)23524ba319b5SDimitry Andric Value *LibCallSimplifier::optimizeFGets(CallInst *CI, IRBuilder<> &B) {
23534ba319b5SDimitry Andric if (isLocallyOpenedFile(CI->getArgOperand(2), CI, B, TLI))
23544ba319b5SDimitry Andric return emitFGetSUnlocked(CI->getArgOperand(0), CI->getArgOperand(1),
23554ba319b5SDimitry Andric CI->getArgOperand(2), B, TLI);
23564ba319b5SDimitry Andric
23574ba319b5SDimitry Andric return nullptr;
23584ba319b5SDimitry Andric }
23594ba319b5SDimitry Andric
optimizeFRead(CallInst * CI,IRBuilder<> & B)23604ba319b5SDimitry Andric Value *LibCallSimplifier::optimizeFRead(CallInst *CI, IRBuilder<> &B) {
23614ba319b5SDimitry Andric if (isLocallyOpenedFile(CI->getArgOperand(3), CI, B, TLI))
23624ba319b5SDimitry Andric return emitFReadUnlocked(CI->getArgOperand(0), CI->getArgOperand(1),
23634ba319b5SDimitry Andric CI->getArgOperand(2), CI->getArgOperand(3), B, DL,
23644ba319b5SDimitry Andric TLI);
23654ba319b5SDimitry Andric
23664ba319b5SDimitry Andric return nullptr;
23674ba319b5SDimitry Andric }
23684ba319b5SDimitry Andric
optimizePuts(CallInst * CI,IRBuilder<> & B)236939d628a0SDimitry Andric Value *LibCallSimplifier::optimizePuts(CallInst *CI, IRBuilder<> &B) {
2370139f7f9bSDimitry Andric // Check for a constant string.
2371139f7f9bSDimitry Andric StringRef Str;
2372139f7f9bSDimitry Andric if (!getConstantStringInfo(CI->getArgOperand(0), Str))
237391bc56edSDimitry Andric return nullptr;
2374139f7f9bSDimitry Andric
2375139f7f9bSDimitry Andric if (Str.empty() && CI->use_empty()) {
2376139f7f9bSDimitry Andric // puts("") -> putchar('\n')
23773ca95b02SDimitry Andric Value *Res = emitPutChar(B.getInt32('\n'), B, TLI);
237839d628a0SDimitry Andric if (CI->use_empty() || !Res)
237939d628a0SDimitry Andric return Res;
2380139f7f9bSDimitry Andric return B.CreateIntCast(Res, CI->getType(), true);
2381139f7f9bSDimitry Andric }
2382139f7f9bSDimitry Andric
238391bc56edSDimitry Andric return nullptr;
2384139f7f9bSDimitry Andric }
2385139f7f9bSDimitry Andric
hasFloatVersion(StringRef FuncName)238639d628a0SDimitry Andric bool LibCallSimplifier::hasFloatVersion(StringRef FuncName) {
23877a7e6055SDimitry Andric LibFunc Func;
2388139f7f9bSDimitry Andric SmallString<20> FloatFuncName = FuncName;
2389139f7f9bSDimitry Andric FloatFuncName += 'f';
2390139f7f9bSDimitry Andric if (TLI->getLibFunc(FloatFuncName, Func))
2391139f7f9bSDimitry Andric return TLI->has(Func);
2392139f7f9bSDimitry Andric return false;
2393139f7f9bSDimitry Andric }
2394139f7f9bSDimitry Andric
optimizeStringMemoryLibCall(CallInst * CI,IRBuilder<> & Builder)239539d628a0SDimitry Andric Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI,
239639d628a0SDimitry Andric IRBuilder<> &Builder) {
23977a7e6055SDimitry Andric LibFunc Func;
2398139f7f9bSDimitry Andric Function *Callee = CI->getCalledFunction();
239939d628a0SDimitry Andric // Check for string/memory library functions.
24003ca95b02SDimitry Andric if (TLI->getLibFunc(*Callee, Func) && TLI->has(Func)) {
240139d628a0SDimitry Andric // Make sure we never change the calling convention.
240239d628a0SDimitry Andric assert((ignoreCallingConv(Func) ||
2403d88c1a5aSDimitry Andric isCallingConvCCompatible(CI)) &&
240439d628a0SDimitry Andric "Optimizing string/memory libcall would change the calling convention");
2405139f7f9bSDimitry Andric switch (Func) {
24067a7e6055SDimitry Andric case LibFunc_strcat:
240739d628a0SDimitry Andric return optimizeStrCat(CI, Builder);
24087a7e6055SDimitry Andric case LibFunc_strncat:
240939d628a0SDimitry Andric return optimizeStrNCat(CI, Builder);
24107a7e6055SDimitry Andric case LibFunc_strchr:
241139d628a0SDimitry Andric return optimizeStrChr(CI, Builder);
24127a7e6055SDimitry Andric case LibFunc_strrchr:
241339d628a0SDimitry Andric return optimizeStrRChr(CI, Builder);
24147a7e6055SDimitry Andric case LibFunc_strcmp:
241539d628a0SDimitry Andric return optimizeStrCmp(CI, Builder);
24167a7e6055SDimitry Andric case LibFunc_strncmp:
241739d628a0SDimitry Andric return optimizeStrNCmp(CI, Builder);
24187a7e6055SDimitry Andric case LibFunc_strcpy:
241939d628a0SDimitry Andric return optimizeStrCpy(CI, Builder);
24207a7e6055SDimitry Andric case LibFunc_stpcpy:
242139d628a0SDimitry Andric return optimizeStpCpy(CI, Builder);
24227a7e6055SDimitry Andric case LibFunc_strncpy:
242339d628a0SDimitry Andric return optimizeStrNCpy(CI, Builder);
24247a7e6055SDimitry Andric case LibFunc_strlen:
242539d628a0SDimitry Andric return optimizeStrLen(CI, Builder);
24267a7e6055SDimitry Andric case LibFunc_strpbrk:
242739d628a0SDimitry Andric return optimizeStrPBrk(CI, Builder);
24287a7e6055SDimitry Andric case LibFunc_strtol:
24297a7e6055SDimitry Andric case LibFunc_strtod:
24307a7e6055SDimitry Andric case LibFunc_strtof:
24317a7e6055SDimitry Andric case LibFunc_strtoul:
24327a7e6055SDimitry Andric case LibFunc_strtoll:
24337a7e6055SDimitry Andric case LibFunc_strtold:
24347a7e6055SDimitry Andric case LibFunc_strtoull:
243539d628a0SDimitry Andric return optimizeStrTo(CI, Builder);
24367a7e6055SDimitry Andric case LibFunc_strspn:
243739d628a0SDimitry Andric return optimizeStrSpn(CI, Builder);
24387a7e6055SDimitry Andric case LibFunc_strcspn:
243939d628a0SDimitry Andric return optimizeStrCSpn(CI, Builder);
24407a7e6055SDimitry Andric case LibFunc_strstr:
244139d628a0SDimitry Andric return optimizeStrStr(CI, Builder);
24427a7e6055SDimitry Andric case LibFunc_memchr:
2443ff0cc061SDimitry Andric return optimizeMemChr(CI, Builder);
24447a7e6055SDimitry Andric case LibFunc_memcmp:
244539d628a0SDimitry Andric return optimizeMemCmp(CI, Builder);
24467a7e6055SDimitry Andric case LibFunc_memcpy:
244739d628a0SDimitry Andric return optimizeMemCpy(CI, Builder);
24487a7e6055SDimitry Andric case LibFunc_memmove:
244939d628a0SDimitry Andric return optimizeMemMove(CI, Builder);
24507a7e6055SDimitry Andric case LibFunc_memset:
245139d628a0SDimitry Andric return optimizeMemSet(CI, Builder);
24524ba319b5SDimitry Andric case LibFunc_realloc:
24534ba319b5SDimitry Andric return optimizeRealloc(CI, Builder);
2454d8866befSDimitry Andric case LibFunc_wcslen:
2455d8866befSDimitry Andric return optimizeWcslen(CI, Builder);
245639d628a0SDimitry Andric default:
245739d628a0SDimitry Andric break;
245839d628a0SDimitry Andric }
245939d628a0SDimitry Andric }
246039d628a0SDimitry Andric return nullptr;
246139d628a0SDimitry Andric }
246239d628a0SDimitry Andric
optimizeFloatingPointLibCall(CallInst * CI,LibFunc Func,IRBuilder<> & Builder)24632cab237bSDimitry Andric Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
24642cab237bSDimitry Andric LibFunc Func,
24652cab237bSDimitry Andric IRBuilder<> &Builder) {
24662cab237bSDimitry Andric // Don't optimize calls that require strict floating point semantics.
24672cab237bSDimitry Andric if (CI->isStrictFP())
24682cab237bSDimitry Andric return nullptr;
24692cab237bSDimitry Andric
2470*b5893f02SDimitry Andric if (Value *V = optimizeTrigReflections(CI, Func, Builder))
2471*b5893f02SDimitry Andric return V;
2472*b5893f02SDimitry Andric
24732cab237bSDimitry Andric switch (Func) {
24742cab237bSDimitry Andric case LibFunc_sinpif:
24752cab237bSDimitry Andric case LibFunc_sinpi:
24762cab237bSDimitry Andric case LibFunc_cospif:
24772cab237bSDimitry Andric case LibFunc_cospi:
24782cab237bSDimitry Andric return optimizeSinCosPi(CI, Builder);
24792cab237bSDimitry Andric case LibFunc_powf:
24802cab237bSDimitry Andric case LibFunc_pow:
24812cab237bSDimitry Andric case LibFunc_powl:
24822cab237bSDimitry Andric return optimizePow(CI, Builder);
24832cab237bSDimitry Andric case LibFunc_exp2l:
24842cab237bSDimitry Andric case LibFunc_exp2:
24852cab237bSDimitry Andric case LibFunc_exp2f:
24862cab237bSDimitry Andric return optimizeExp2(CI, Builder);
24872cab237bSDimitry Andric case LibFunc_fabsf:
24882cab237bSDimitry Andric case LibFunc_fabs:
24892cab237bSDimitry Andric case LibFunc_fabsl:
24902cab237bSDimitry Andric return replaceUnaryCall(CI, Builder, Intrinsic::fabs);
24912cab237bSDimitry Andric case LibFunc_sqrtf:
24922cab237bSDimitry Andric case LibFunc_sqrt:
24932cab237bSDimitry Andric case LibFunc_sqrtl:
24942cab237bSDimitry Andric return optimizeSqrt(CI, Builder);
24952cab237bSDimitry Andric case LibFunc_log:
24962cab237bSDimitry Andric case LibFunc_log10:
24972cab237bSDimitry Andric case LibFunc_log1p:
24982cab237bSDimitry Andric case LibFunc_log2:
24992cab237bSDimitry Andric case LibFunc_logb:
25002cab237bSDimitry Andric return optimizeLog(CI, Builder);
25012cab237bSDimitry Andric case LibFunc_tan:
25022cab237bSDimitry Andric case LibFunc_tanf:
25032cab237bSDimitry Andric case LibFunc_tanl:
25042cab237bSDimitry Andric return optimizeTan(CI, Builder);
25052cab237bSDimitry Andric case LibFunc_ceil:
25062cab237bSDimitry Andric return replaceUnaryCall(CI, Builder, Intrinsic::ceil);
25072cab237bSDimitry Andric case LibFunc_floor:
25082cab237bSDimitry Andric return replaceUnaryCall(CI, Builder, Intrinsic::floor);
25092cab237bSDimitry Andric case LibFunc_round:
25102cab237bSDimitry Andric return replaceUnaryCall(CI, Builder, Intrinsic::round);
25112cab237bSDimitry Andric case LibFunc_nearbyint:
25122cab237bSDimitry Andric return replaceUnaryCall(CI, Builder, Intrinsic::nearbyint);
25132cab237bSDimitry Andric case LibFunc_rint:
25142cab237bSDimitry Andric return replaceUnaryCall(CI, Builder, Intrinsic::rint);
25152cab237bSDimitry Andric case LibFunc_trunc:
25162cab237bSDimitry Andric return replaceUnaryCall(CI, Builder, Intrinsic::trunc);
25172cab237bSDimitry Andric case LibFunc_acos:
25182cab237bSDimitry Andric case LibFunc_acosh:
25192cab237bSDimitry Andric case LibFunc_asin:
25202cab237bSDimitry Andric case LibFunc_asinh:
25212cab237bSDimitry Andric case LibFunc_atan:
25222cab237bSDimitry Andric case LibFunc_atanh:
25232cab237bSDimitry Andric case LibFunc_cbrt:
25242cab237bSDimitry Andric case LibFunc_cosh:
25252cab237bSDimitry Andric case LibFunc_exp:
25262cab237bSDimitry Andric case LibFunc_exp10:
25272cab237bSDimitry Andric case LibFunc_expm1:
2528*b5893f02SDimitry Andric case LibFunc_cos:
25292cab237bSDimitry Andric case LibFunc_sin:
25302cab237bSDimitry Andric case LibFunc_sinh:
25312cab237bSDimitry Andric case LibFunc_tanh:
25322cab237bSDimitry Andric if (UnsafeFPShrink && hasFloatVersion(CI->getCalledFunction()->getName()))
25332cab237bSDimitry Andric return optimizeUnaryDoubleFP(CI, Builder, true);
25342cab237bSDimitry Andric return nullptr;
25352cab237bSDimitry Andric case LibFunc_copysign:
25362cab237bSDimitry Andric if (hasFloatVersion(CI->getCalledFunction()->getName()))
25372cab237bSDimitry Andric return optimizeBinaryDoubleFP(CI, Builder);
25382cab237bSDimitry Andric return nullptr;
25392cab237bSDimitry Andric case LibFunc_fminf:
25402cab237bSDimitry Andric case LibFunc_fmin:
25412cab237bSDimitry Andric case LibFunc_fminl:
25422cab237bSDimitry Andric case LibFunc_fmaxf:
25432cab237bSDimitry Andric case LibFunc_fmax:
25442cab237bSDimitry Andric case LibFunc_fmaxl:
25452cab237bSDimitry Andric return optimizeFMinFMax(CI, Builder);
25462cab237bSDimitry Andric case LibFunc_cabs:
25472cab237bSDimitry Andric case LibFunc_cabsf:
25482cab237bSDimitry Andric case LibFunc_cabsl:
25492cab237bSDimitry Andric return optimizeCAbs(CI, Builder);
25502cab237bSDimitry Andric default:
25512cab237bSDimitry Andric return nullptr;
25522cab237bSDimitry Andric }
25532cab237bSDimitry Andric }
25542cab237bSDimitry Andric
optimizeCall(CallInst * CI)255539d628a0SDimitry Andric Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
25562cab237bSDimitry Andric // TODO: Split out the code below that operates on FP calls so that
25572cab237bSDimitry Andric // we can all non-FP calls with the StrictFP attribute to be
25582cab237bSDimitry Andric // optimized.
255939d628a0SDimitry Andric if (CI->isNoBuiltin())
256039d628a0SDimitry Andric return nullptr;
256139d628a0SDimitry Andric
25627a7e6055SDimitry Andric LibFunc Func;
256339d628a0SDimitry Andric Function *Callee = CI->getCalledFunction();
25644d0b32cdSDimitry Andric
25654d0b32cdSDimitry Andric SmallVector<OperandBundleDef, 2> OpBundles;
25664d0b32cdSDimitry Andric CI->getOperandBundlesAsDefs(OpBundles);
25674d0b32cdSDimitry Andric IRBuilder<> Builder(CI, /*FPMathTag=*/nullptr, OpBundles);
2568d88c1a5aSDimitry Andric bool isCallingConvC = isCallingConvCCompatible(CI);
256939d628a0SDimitry Andric
25703ca95b02SDimitry Andric // Command-line parameter overrides instruction attribute.
25712cab237bSDimitry Andric // This can't be moved to optimizeFloatingPointLibCall() because it may be
25722cab237bSDimitry Andric // used by the intrinsic optimizations.
257339d628a0SDimitry Andric if (EnableUnsafeFPShrink.getNumOccurrences() > 0)
257439d628a0SDimitry Andric UnsafeFPShrink = EnableUnsafeFPShrink;
25752cab237bSDimitry Andric else if (isa<FPMathOperator>(CI) && CI->isFast())
257639d628a0SDimitry Andric UnsafeFPShrink = true;
257739d628a0SDimitry Andric
257839d628a0SDimitry Andric // First, check for intrinsics.
257939d628a0SDimitry Andric if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) {
258039d628a0SDimitry Andric if (!isCallingConvC)
258139d628a0SDimitry Andric return nullptr;
25822cab237bSDimitry Andric // The FP intrinsics have corresponding constrained versions so we don't
25832cab237bSDimitry Andric // need to check for the StrictFP attribute here.
258439d628a0SDimitry Andric switch (II->getIntrinsicID()) {
258539d628a0SDimitry Andric case Intrinsic::pow:
258639d628a0SDimitry Andric return optimizePow(CI, Builder);
258739d628a0SDimitry Andric case Intrinsic::exp2:
258839d628a0SDimitry Andric return optimizeExp2(CI, Builder);
25897d523365SDimitry Andric case Intrinsic::log:
25907d523365SDimitry Andric return optimizeLog(CI, Builder);
259139d628a0SDimitry Andric case Intrinsic::sqrt:
259239d628a0SDimitry Andric return optimizeSqrt(CI, Builder);
25933ca95b02SDimitry Andric // TODO: Use foldMallocMemset() with memset intrinsic.
259439d628a0SDimitry Andric default:
259539d628a0SDimitry Andric return nullptr;
259639d628a0SDimitry Andric }
259739d628a0SDimitry Andric }
259839d628a0SDimitry Andric
259939d628a0SDimitry Andric // Also try to simplify calls to fortified library functions.
260039d628a0SDimitry Andric if (Value *SimplifiedFortifiedCI = FortifiedSimplifier.optimizeCall(CI)) {
260139d628a0SDimitry Andric // Try to further simplify the result.
260239d628a0SDimitry Andric CallInst *SimplifiedCI = dyn_cast<CallInst>(SimplifiedFortifiedCI);
26037d523365SDimitry Andric if (SimplifiedCI && SimplifiedCI->getCalledFunction()) {
26047d523365SDimitry Andric // Use an IR Builder from SimplifiedCI if available instead of CI
26057d523365SDimitry Andric // to guarantee we reach all uses we might replace later on.
26067d523365SDimitry Andric IRBuilder<> TmpBuilder(SimplifiedCI);
26077d523365SDimitry Andric if (Value *V = optimizeStringMemoryLibCall(SimplifiedCI, TmpBuilder)) {
26083de688ebSDimitry Andric // If we were able to further simplify, remove the now redundant call.
26093de688ebSDimitry Andric SimplifiedCI->replaceAllUsesWith(V);
2610*b5893f02SDimitry Andric eraseFromParent(SimplifiedCI);
261139d628a0SDimitry Andric return V;
26123de688ebSDimitry Andric }
26137d523365SDimitry Andric }
261439d628a0SDimitry Andric return SimplifiedFortifiedCI;
261539d628a0SDimitry Andric }
261639d628a0SDimitry Andric
261739d628a0SDimitry Andric // Then check for known library functions.
26183ca95b02SDimitry Andric if (TLI->getLibFunc(*Callee, Func) && TLI->has(Func)) {
261939d628a0SDimitry Andric // We never change the calling convention.
262039d628a0SDimitry Andric if (!ignoreCallingConv(Func) && !isCallingConvC)
262139d628a0SDimitry Andric return nullptr;
262239d628a0SDimitry Andric if (Value *V = optimizeStringMemoryLibCall(CI, Builder))
262339d628a0SDimitry Andric return V;
26242cab237bSDimitry Andric if (Value *V = optimizeFloatingPointLibCall(CI, Func, Builder))
26252cab237bSDimitry Andric return V;
262639d628a0SDimitry Andric switch (Func) {
26277a7e6055SDimitry Andric case LibFunc_ffs:
26287a7e6055SDimitry Andric case LibFunc_ffsl:
26297a7e6055SDimitry Andric case LibFunc_ffsll:
263039d628a0SDimitry Andric return optimizeFFS(CI, Builder);
26317a7e6055SDimitry Andric case LibFunc_fls:
26327a7e6055SDimitry Andric case LibFunc_flsl:
26337a7e6055SDimitry Andric case LibFunc_flsll:
2634d88c1a5aSDimitry Andric return optimizeFls(CI, Builder);
26357a7e6055SDimitry Andric case LibFunc_abs:
26367a7e6055SDimitry Andric case LibFunc_labs:
26377a7e6055SDimitry Andric case LibFunc_llabs:
263839d628a0SDimitry Andric return optimizeAbs(CI, Builder);
26397a7e6055SDimitry Andric case LibFunc_isdigit:
264039d628a0SDimitry Andric return optimizeIsDigit(CI, Builder);
26417a7e6055SDimitry Andric case LibFunc_isascii:
264239d628a0SDimitry Andric return optimizeIsAscii(CI, Builder);
26437a7e6055SDimitry Andric case LibFunc_toascii:
264439d628a0SDimitry Andric return optimizeToAscii(CI, Builder);
26454ba319b5SDimitry Andric case LibFunc_atoi:
26464ba319b5SDimitry Andric case LibFunc_atol:
26474ba319b5SDimitry Andric case LibFunc_atoll:
26484ba319b5SDimitry Andric return optimizeAtoi(CI, Builder);
26494ba319b5SDimitry Andric case LibFunc_strtol:
26504ba319b5SDimitry Andric case LibFunc_strtoll:
26514ba319b5SDimitry Andric return optimizeStrtol(CI, Builder);
26527a7e6055SDimitry Andric case LibFunc_printf:
265339d628a0SDimitry Andric return optimizePrintF(CI, Builder);
26547a7e6055SDimitry Andric case LibFunc_sprintf:
265539d628a0SDimitry Andric return optimizeSPrintF(CI, Builder);
26564ba319b5SDimitry Andric case LibFunc_snprintf:
26574ba319b5SDimitry Andric return optimizeSnPrintF(CI, Builder);
26587a7e6055SDimitry Andric case LibFunc_fprintf:
265939d628a0SDimitry Andric return optimizeFPrintF(CI, Builder);
26607a7e6055SDimitry Andric case LibFunc_fwrite:
266139d628a0SDimitry Andric return optimizeFWrite(CI, Builder);
26624ba319b5SDimitry Andric case LibFunc_fread:
26634ba319b5SDimitry Andric return optimizeFRead(CI, Builder);
26647a7e6055SDimitry Andric case LibFunc_fputs:
266539d628a0SDimitry Andric return optimizeFPuts(CI, Builder);
26664ba319b5SDimitry Andric case LibFunc_fgets:
26674ba319b5SDimitry Andric return optimizeFGets(CI, Builder);
26684ba319b5SDimitry Andric case LibFunc_fputc:
26694ba319b5SDimitry Andric return optimizeFPutc(CI, Builder);
26704ba319b5SDimitry Andric case LibFunc_fgetc:
26714ba319b5SDimitry Andric return optimizeFGetc(CI, Builder);
26727a7e6055SDimitry Andric case LibFunc_puts:
267339d628a0SDimitry Andric return optimizePuts(CI, Builder);
26747a7e6055SDimitry Andric case LibFunc_perror:
267539d628a0SDimitry Andric return optimizeErrorReporting(CI, Builder);
26767a7e6055SDimitry Andric case LibFunc_vfprintf:
26777a7e6055SDimitry Andric case LibFunc_fiprintf:
267839d628a0SDimitry Andric return optimizeErrorReporting(CI, Builder, 0);
2679139f7f9bSDimitry Andric default:
268091bc56edSDimitry Andric return nullptr;
2681139f7f9bSDimitry Andric }
2682139f7f9bSDimitry Andric }
268391bc56edSDimitry Andric return nullptr;
26843861d79fSDimitry Andric }
26853861d79fSDimitry Andric
LibCallSimplifier(const DataLayout & DL,const TargetLibraryInfo * TLI,OptimizationRemarkEmitter & ORE,function_ref<void (Instruction *,Value *)> Replacer,function_ref<void (Instruction *)> Eraser)2686ff0cc061SDimitry Andric LibCallSimplifier::LibCallSimplifier(
2687ff0cc061SDimitry Andric const DataLayout &DL, const TargetLibraryInfo *TLI,
26882cab237bSDimitry Andric OptimizationRemarkEmitter &ORE,
2689*b5893f02SDimitry Andric function_ref<void(Instruction *, Value *)> Replacer,
2690*b5893f02SDimitry Andric function_ref<void(Instruction *)> Eraser)
26912cab237bSDimitry Andric : FortifiedSimplifier(TLI), DL(DL), TLI(TLI), ORE(ORE),
2692*b5893f02SDimitry Andric UnsafeFPShrink(false), Replacer(Replacer), Eraser(Eraser) {}
2693ff0cc061SDimitry Andric
replaceAllUsesWith(Instruction * I,Value * With)2694ff0cc061SDimitry Andric void LibCallSimplifier::replaceAllUsesWith(Instruction *I, Value *With) {
2695ff0cc061SDimitry Andric // Indirect through the replacer used in this instance.
2696ff0cc061SDimitry Andric Replacer(I, With);
26973861d79fSDimitry Andric }
26983861d79fSDimitry Andric
eraseFromParent(Instruction * I)2699*b5893f02SDimitry Andric void LibCallSimplifier::eraseFromParent(Instruction *I) {
2700*b5893f02SDimitry Andric Eraser(I);
2701*b5893f02SDimitry Andric }
2702*b5893f02SDimitry Andric
2703f785676fSDimitry Andric // TODO:
2704f785676fSDimitry Andric // Additional cases that we need to add to this file:
2705f785676fSDimitry Andric //
2706f785676fSDimitry Andric // cbrt:
2707f785676fSDimitry Andric // * cbrt(expN(X)) -> expN(x/3)
2708f785676fSDimitry Andric // * cbrt(sqrt(x)) -> pow(x,1/6)
27097d523365SDimitry Andric // * cbrt(cbrt(x)) -> pow(x,1/9)
2710f785676fSDimitry Andric //
2711f785676fSDimitry Andric // exp, expf, expl:
2712f785676fSDimitry Andric // * exp(log(x)) -> x
2713f785676fSDimitry Andric //
2714f785676fSDimitry Andric // log, logf, logl:
2715f785676fSDimitry Andric // * log(exp(x)) -> x
2716f785676fSDimitry Andric // * log(exp(y)) -> y*log(e)
2717f785676fSDimitry Andric // * log(exp10(y)) -> y*log(10)
2718f785676fSDimitry Andric // * log(sqrt(x)) -> 0.5*log(x)
2719f785676fSDimitry Andric //
2720f785676fSDimitry Andric // pow, powf, powl:
2721f785676fSDimitry Andric // * pow(sqrt(x),y) -> pow(x,y*0.5)
2722f785676fSDimitry Andric // * pow(pow(x,y),z)-> pow(x,y*z)
2723f785676fSDimitry Andric //
2724f785676fSDimitry Andric // signbit:
2725f785676fSDimitry Andric // * signbit(cnst) -> cnst'
2726f785676fSDimitry Andric // * signbit(nncst) -> 0 (if pstv is a non-negative constant)
2727f785676fSDimitry Andric //
2728f785676fSDimitry Andric // sqrt, sqrtf, sqrtl:
2729f785676fSDimitry Andric // * sqrt(expN(x)) -> expN(x*0.5)
2730f785676fSDimitry Andric // * sqrt(Nroot(x)) -> pow(x,1/(2*N))
2731f785676fSDimitry Andric // * sqrt(pow(x,y)) -> pow(|x|,y*0.5)
2732f785676fSDimitry Andric //
273339d628a0SDimitry Andric
273439d628a0SDimitry Andric //===----------------------------------------------------------------------===//
273539d628a0SDimitry Andric // Fortified Library Call Optimizations
273639d628a0SDimitry Andric //===----------------------------------------------------------------------===//
273739d628a0SDimitry Andric
isFortifiedCallFoldable(CallInst * CI,unsigned ObjSizeOp,unsigned SizeOp,bool isString)273839d628a0SDimitry Andric bool FortifiedLibCallSimplifier::isFortifiedCallFoldable(CallInst *CI,
273939d628a0SDimitry Andric unsigned ObjSizeOp,
274039d628a0SDimitry Andric unsigned SizeOp,
274139d628a0SDimitry Andric bool isString) {
274239d628a0SDimitry Andric if (CI->getArgOperand(ObjSizeOp) == CI->getArgOperand(SizeOp))
274339d628a0SDimitry Andric return true;
274439d628a0SDimitry Andric if (ConstantInt *ObjSizeCI =
274539d628a0SDimitry Andric dyn_cast<ConstantInt>(CI->getArgOperand(ObjSizeOp))) {
2746c4394386SDimitry Andric if (ObjSizeCI->isMinusOne())
274739d628a0SDimitry Andric return true;
274839d628a0SDimitry Andric // If the object size wasn't -1 (unknown), bail out if we were asked to.
274939d628a0SDimitry Andric if (OnlyLowerUnknownSize)
275039d628a0SDimitry Andric return false;
275139d628a0SDimitry Andric if (isString) {
275239d628a0SDimitry Andric uint64_t Len = GetStringLength(CI->getArgOperand(SizeOp));
275339d628a0SDimitry Andric // If the length is 0 we don't know how long it is and so we can't
275439d628a0SDimitry Andric // remove the check.
275539d628a0SDimitry Andric if (Len == 0)
275639d628a0SDimitry Andric return false;
275739d628a0SDimitry Andric return ObjSizeCI->getZExtValue() >= Len;
275839d628a0SDimitry Andric }
275939d628a0SDimitry Andric if (ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getArgOperand(SizeOp)))
276039d628a0SDimitry Andric return ObjSizeCI->getZExtValue() >= SizeCI->getZExtValue();
276139d628a0SDimitry Andric }
276239d628a0SDimitry Andric return false;
276339d628a0SDimitry Andric }
276439d628a0SDimitry Andric
optimizeMemCpyChk(CallInst * CI,IRBuilder<> & B)27654d0b32cdSDimitry Andric Value *FortifiedLibCallSimplifier::optimizeMemCpyChk(CallInst *CI,
27664d0b32cdSDimitry Andric IRBuilder<> &B) {
276739d628a0SDimitry Andric if (isFortifiedCallFoldable(CI, 3, 2, false)) {
27684ba319b5SDimitry Andric B.CreateMemCpy(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1,
27694ba319b5SDimitry Andric CI->getArgOperand(2));
277039d628a0SDimitry Andric return CI->getArgOperand(0);
277139d628a0SDimitry Andric }
277239d628a0SDimitry Andric return nullptr;
277339d628a0SDimitry Andric }
277439d628a0SDimitry Andric
optimizeMemMoveChk(CallInst * CI,IRBuilder<> & B)27754d0b32cdSDimitry Andric Value *FortifiedLibCallSimplifier::optimizeMemMoveChk(CallInst *CI,
27764d0b32cdSDimitry Andric IRBuilder<> &B) {
277739d628a0SDimitry Andric if (isFortifiedCallFoldable(CI, 3, 2, false)) {
27784ba319b5SDimitry Andric B.CreateMemMove(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1,
27794ba319b5SDimitry Andric CI->getArgOperand(2));
278039d628a0SDimitry Andric return CI->getArgOperand(0);
278139d628a0SDimitry Andric }
278239d628a0SDimitry Andric return nullptr;
278339d628a0SDimitry Andric }
278439d628a0SDimitry Andric
optimizeMemSetChk(CallInst * CI,IRBuilder<> & B)27854d0b32cdSDimitry Andric Value *FortifiedLibCallSimplifier::optimizeMemSetChk(CallInst *CI,
27864d0b32cdSDimitry Andric IRBuilder<> &B) {
27873ca95b02SDimitry Andric // TODO: Try foldMallocMemset() here.
278839d628a0SDimitry Andric
278939d628a0SDimitry Andric if (isFortifiedCallFoldable(CI, 3, 2, false)) {
279039d628a0SDimitry Andric Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(), false);
279139d628a0SDimitry Andric B.CreateMemSet(CI->getArgOperand(0), Val, CI->getArgOperand(2), 1);
279239d628a0SDimitry Andric return CI->getArgOperand(0);
279339d628a0SDimitry Andric }
279439d628a0SDimitry Andric return nullptr;
279539d628a0SDimitry Andric }
279639d628a0SDimitry Andric
optimizeStrpCpyChk(CallInst * CI,IRBuilder<> & B,LibFunc Func)27973de688ebSDimitry Andric Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI,
27983de688ebSDimitry Andric IRBuilder<> &B,
27997a7e6055SDimitry Andric LibFunc Func) {
280039d628a0SDimitry Andric Function *Callee = CI->getCalledFunction();
280139d628a0SDimitry Andric StringRef Name = Callee->getName();
2802ff0cc061SDimitry Andric const DataLayout &DL = CI->getModule()->getDataLayout();
280339d628a0SDimitry Andric Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1),
280439d628a0SDimitry Andric *ObjSize = CI->getArgOperand(2);
280539d628a0SDimitry Andric
280639d628a0SDimitry Andric // __stpcpy_chk(x,x,...) -> x+strlen(x)
28077a7e6055SDimitry Andric if (Func == LibFunc_stpcpy_chk && !OnlyLowerUnknownSize && Dst == Src) {
28083ca95b02SDimitry Andric Value *StrLen = emitStrLen(Src, B, DL, TLI);
2809ff0cc061SDimitry Andric return StrLen ? B.CreateInBoundsGEP(B.getInt8Ty(), Dst, StrLen) : nullptr;
281039d628a0SDimitry Andric }
281139d628a0SDimitry Andric
281239d628a0SDimitry Andric // If a) we don't have any length information, or b) we know this will
281339d628a0SDimitry Andric // fit then just lower to a plain st[rp]cpy. Otherwise we'll keep our
281439d628a0SDimitry Andric // st[rp]cpy_chk call which may fail at runtime if the size is too long.
281539d628a0SDimitry Andric // TODO: It might be nice to get a maximum length out of the possible
281639d628a0SDimitry Andric // string lengths for varying.
2817ff0cc061SDimitry Andric if (isFortifiedCallFoldable(CI, 2, 1, true))
28183ca95b02SDimitry Andric return emitStrCpy(Dst, Src, B, TLI, Name.substr(2, 6));
2819ff0cc061SDimitry Andric
2820ff0cc061SDimitry Andric if (OnlyLowerUnknownSize)
2821ff0cc061SDimitry Andric return nullptr;
2822ff0cc061SDimitry Andric
282339d628a0SDimitry Andric // Maybe we can stil fold __st[rp]cpy_chk to __memcpy_chk.
282439d628a0SDimitry Andric uint64_t Len = GetStringLength(Src);
282539d628a0SDimitry Andric if (Len == 0)
282639d628a0SDimitry Andric return nullptr;
282739d628a0SDimitry Andric
2828ff0cc061SDimitry Andric Type *SizeTTy = DL.getIntPtrType(CI->getContext());
282939d628a0SDimitry Andric Value *LenV = ConstantInt::get(SizeTTy, Len);
28303ca95b02SDimitry Andric Value *Ret = emitMemCpyChk(Dst, Src, LenV, ObjSize, B, DL, TLI);
283139d628a0SDimitry Andric // If the function was an __stpcpy_chk, and we were able to fold it into
283239d628a0SDimitry Andric // a __memcpy_chk, we still need to return the correct end pointer.
28337a7e6055SDimitry Andric if (Ret && Func == LibFunc_stpcpy_chk)
2834ff0cc061SDimitry Andric return B.CreateGEP(B.getInt8Ty(), Dst, ConstantInt::get(SizeTTy, Len - 1));
283539d628a0SDimitry Andric return Ret;
283639d628a0SDimitry Andric }
283739d628a0SDimitry Andric
optimizeStrpNCpyChk(CallInst * CI,IRBuilder<> & B,LibFunc Func)28383de688ebSDimitry Andric Value *FortifiedLibCallSimplifier::optimizeStrpNCpyChk(CallInst *CI,
28393de688ebSDimitry Andric IRBuilder<> &B,
28407a7e6055SDimitry Andric LibFunc Func) {
284139d628a0SDimitry Andric Function *Callee = CI->getCalledFunction();
284239d628a0SDimitry Andric StringRef Name = Callee->getName();
284339d628a0SDimitry Andric if (isFortifiedCallFoldable(CI, 3, 2, false)) {
28443ca95b02SDimitry Andric Value *Ret = emitStrNCpy(CI->getArgOperand(0), CI->getArgOperand(1),
2845ff0cc061SDimitry Andric CI->getArgOperand(2), B, TLI, Name.substr(2, 7));
284639d628a0SDimitry Andric return Ret;
284739d628a0SDimitry Andric }
284839d628a0SDimitry Andric return nullptr;
284939d628a0SDimitry Andric }
285039d628a0SDimitry Andric
optimizeCall(CallInst * CI)285139d628a0SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI) {
2852ff0cc061SDimitry Andric // FIXME: We shouldn't be changing "nobuiltin" or TLI unavailable calls here.
2853ff0cc061SDimitry Andric // Some clang users checked for _chk libcall availability using:
2854ff0cc061SDimitry Andric // __has_builtin(__builtin___memcpy_chk)
2855ff0cc061SDimitry Andric // When compiling with -fno-builtin, this is always true.
2856ff0cc061SDimitry Andric // When passing -ffreestanding/-mkernel, which both imply -fno-builtin, we
2857ff0cc061SDimitry Andric // end up with fortified libcalls, which isn't acceptable in a freestanding
2858ff0cc061SDimitry Andric // environment which only provides their non-fortified counterparts.
2859ff0cc061SDimitry Andric //
2860ff0cc061SDimitry Andric // Until we change clang and/or teach external users to check for availability
2861ff0cc061SDimitry Andric // differently, disregard the "nobuiltin" attribute and TLI::has.
2862ff0cc061SDimitry Andric //
2863ff0cc061SDimitry Andric // PR23093.
286439d628a0SDimitry Andric
28657a7e6055SDimitry Andric LibFunc Func;
286639d628a0SDimitry Andric Function *Callee = CI->getCalledFunction();
28674d0b32cdSDimitry Andric
28684d0b32cdSDimitry Andric SmallVector<OperandBundleDef, 2> OpBundles;
28694d0b32cdSDimitry Andric CI->getOperandBundlesAsDefs(OpBundles);
28704d0b32cdSDimitry Andric IRBuilder<> Builder(CI, /*FPMathTag=*/nullptr, OpBundles);
2871d88c1a5aSDimitry Andric bool isCallingConvC = isCallingConvCCompatible(CI);
287239d628a0SDimitry Andric
28733ca95b02SDimitry Andric // First, check that this is a known library functions and that the prototype
28743ca95b02SDimitry Andric // is correct.
28753ca95b02SDimitry Andric if (!TLI->getLibFunc(*Callee, Func))
287639d628a0SDimitry Andric return nullptr;
287739d628a0SDimitry Andric
287839d628a0SDimitry Andric // We never change the calling convention.
287939d628a0SDimitry Andric if (!ignoreCallingConv(Func) && !isCallingConvC)
288039d628a0SDimitry Andric return nullptr;
288139d628a0SDimitry Andric
288239d628a0SDimitry Andric switch (Func) {
28837a7e6055SDimitry Andric case LibFunc_memcpy_chk:
288439d628a0SDimitry Andric return optimizeMemCpyChk(CI, Builder);
28857a7e6055SDimitry Andric case LibFunc_memmove_chk:
288639d628a0SDimitry Andric return optimizeMemMoveChk(CI, Builder);
28877a7e6055SDimitry Andric case LibFunc_memset_chk:
288839d628a0SDimitry Andric return optimizeMemSetChk(CI, Builder);
28897a7e6055SDimitry Andric case LibFunc_stpcpy_chk:
28907a7e6055SDimitry Andric case LibFunc_strcpy_chk:
28913de688ebSDimitry Andric return optimizeStrpCpyChk(CI, Builder, Func);
28927a7e6055SDimitry Andric case LibFunc_stpncpy_chk:
28937a7e6055SDimitry Andric case LibFunc_strncpy_chk:
28943de688ebSDimitry Andric return optimizeStrpNCpyChk(CI, Builder, Func);
289539d628a0SDimitry Andric default:
289639d628a0SDimitry Andric break;
289739d628a0SDimitry Andric }
289839d628a0SDimitry Andric return nullptr;
289939d628a0SDimitry Andric }
290039d628a0SDimitry Andric
FortifiedLibCallSimplifier(const TargetLibraryInfo * TLI,bool OnlyLowerUnknownSize)2901ff0cc061SDimitry Andric FortifiedLibCallSimplifier::FortifiedLibCallSimplifier(
2902ff0cc061SDimitry Andric const TargetLibraryInfo *TLI, bool OnlyLowerUnknownSize)
2903ff0cc061SDimitry Andric : TLI(TLI), OnlyLowerUnknownSize(OnlyLowerUnknownSize) {}
2904