xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===------ SimplifyLibCalls.cpp - Library calls simplifier ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the library calls simplifier. It does not implement
100b57cec5SDimitry Andric // any pass, but can't be used by other passes to do simplifications.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/Transforms/Utils/SimplifyLibCalls.h"
150b57cec5SDimitry Andric #include "llvm/ADT/APSInt.h"
160b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
1706c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
180b57cec5SDimitry Andric #include "llvm/Analysis/ConstantFolding.h"
190b57cec5SDimitry Andric #include "llvm/Analysis/Loads.h"
2081ad6265SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h"
2181ad6265SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
2206c3fb27SDimitry Andric #include "llvm/IR/AttributeMask.h"
230b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
240b57cec5SDimitry Andric #include "llvm/IR/Function.h"
250b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h"
260b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
270b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
280b57cec5SDimitry Andric #include "llvm/IR/Module.h"
290b57cec5SDimitry Andric #include "llvm/IR/PatternMatch.h"
30*0fca6ea1SDimitry Andric #include "llvm/Support/Casting.h"
310b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
320b57cec5SDimitry Andric #include "llvm/Support/KnownBits.h"
338bcb0991SDimitry Andric #include "llvm/Support/MathExtras.h"
3406c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
350b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BuildLibCalls.h"
3681ad6265SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
370b57cec5SDimitry Andric #include "llvm/Transforms/Utils/SizeOpts.h"
380b57cec5SDimitry Andric 
39bdd1243dSDimitry Andric #include <cmath>
40bdd1243dSDimitry Andric 
410b57cec5SDimitry Andric using namespace llvm;
420b57cec5SDimitry Andric using namespace PatternMatch;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric static cl::opt<bool>
450b57cec5SDimitry Andric     EnableUnsafeFPShrink("enable-double-float-shrink", cl::Hidden,
460b57cec5SDimitry Andric                          cl::init(false),
470b57cec5SDimitry Andric                          cl::desc("Enable unsafe double to float "
480b57cec5SDimitry Andric                                   "shrinking for math lib calls"));
490b57cec5SDimitry Andric 
5006c3fb27SDimitry Andric // Enable conversion of operator new calls with a MemProf hot or cold hint
5106c3fb27SDimitry Andric // to an operator new call that takes a hot/cold hint. Off by default since
5206c3fb27SDimitry Andric // not all allocators currently support this extension.
5306c3fb27SDimitry Andric static cl::opt<bool>
5406c3fb27SDimitry Andric     OptimizeHotColdNew("optimize-hot-cold-new", cl::Hidden, cl::init(false),
5506c3fb27SDimitry Andric                        cl::desc("Enable hot/cold operator new library calls"));
56*0fca6ea1SDimitry Andric static cl::opt<bool> OptimizeExistingHotColdNew(
57*0fca6ea1SDimitry Andric     "optimize-existing-hot-cold-new", cl::Hidden, cl::init(false),
58*0fca6ea1SDimitry Andric     cl::desc(
59*0fca6ea1SDimitry Andric         "Enable optimization of existing hot/cold operator new library calls"));
6006c3fb27SDimitry Andric 
6106c3fb27SDimitry Andric namespace {
6206c3fb27SDimitry Andric 
6306c3fb27SDimitry Andric // Specialized parser to ensure the hint is an 8 bit value (we can't specify
6406c3fb27SDimitry Andric // uint8_t to opt<> as that is interpreted to mean that we are passing a char
6506c3fb27SDimitry Andric // option with a specific set of values.
6606c3fb27SDimitry Andric struct HotColdHintParser : public cl::parser<unsigned> {
6706c3fb27SDimitry Andric   HotColdHintParser(cl::Option &O) : cl::parser<unsigned>(O) {}
6806c3fb27SDimitry Andric 
6906c3fb27SDimitry Andric   bool parse(cl::Option &O, StringRef ArgName, StringRef Arg, unsigned &Value) {
7006c3fb27SDimitry Andric     if (Arg.getAsInteger(0, Value))
7106c3fb27SDimitry Andric       return O.error("'" + Arg + "' value invalid for uint argument!");
7206c3fb27SDimitry Andric 
7306c3fb27SDimitry Andric     if (Value > 255)
7406c3fb27SDimitry Andric       return O.error("'" + Arg + "' value must be in the range [0, 255]!");
7506c3fb27SDimitry Andric 
7606c3fb27SDimitry Andric     return false;
7706c3fb27SDimitry Andric   }
7806c3fb27SDimitry Andric };
7906c3fb27SDimitry Andric 
8006c3fb27SDimitry Andric } // end anonymous namespace
8106c3fb27SDimitry Andric 
8206c3fb27SDimitry Andric // Hot/cold operator new takes an 8 bit hotness hint, where 0 is the coldest
8306c3fb27SDimitry Andric // and 255 is the hottest. Default to 1 value away from the coldest and hottest
8406c3fb27SDimitry Andric // hints, so that the compiler hinted allocations are slightly less strong than
8506c3fb27SDimitry Andric // manually inserted hints at the two extremes.
8606c3fb27SDimitry Andric static cl::opt<unsigned, false, HotColdHintParser> ColdNewHintValue(
8706c3fb27SDimitry Andric     "cold-new-hint-value", cl::Hidden, cl::init(1),
8806c3fb27SDimitry Andric     cl::desc("Value to pass to hot/cold operator new for cold allocation"));
89*0fca6ea1SDimitry Andric static cl::opt<unsigned, false, HotColdHintParser>
90*0fca6ea1SDimitry Andric     NotColdNewHintValue("notcold-new-hint-value", cl::Hidden, cl::init(128),
91*0fca6ea1SDimitry Andric                         cl::desc("Value to pass to hot/cold operator new for "
92*0fca6ea1SDimitry Andric                                  "notcold (warm) allocation"));
9306c3fb27SDimitry Andric static cl::opt<unsigned, false, HotColdHintParser> HotNewHintValue(
9406c3fb27SDimitry Andric     "hot-new-hint-value", cl::Hidden, cl::init(254),
9506c3fb27SDimitry Andric     cl::desc("Value to pass to hot/cold operator new for hot allocation"));
9606c3fb27SDimitry Andric 
970b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
980b57cec5SDimitry Andric // Helper Functions
990b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric static bool ignoreCallingConv(LibFunc Func) {
1020b57cec5SDimitry Andric   return Func == LibFunc_abs || Func == LibFunc_labs ||
1030b57cec5SDimitry Andric          Func == LibFunc_llabs || Func == LibFunc_strlen;
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric /// Return true if it is only used in equality comparisons with With.
1070b57cec5SDimitry Andric static bool isOnlyUsedInEqualityComparison(Value *V, Value *With) {
1080b57cec5SDimitry Andric   for (User *U : V->users()) {
1090b57cec5SDimitry Andric     if (ICmpInst *IC = dyn_cast<ICmpInst>(U))
1100b57cec5SDimitry Andric       if (IC->isEquality() && IC->getOperand(1) == With)
1110b57cec5SDimitry Andric         continue;
1120b57cec5SDimitry Andric     // Unknown instruction.
1130b57cec5SDimitry Andric     return false;
1140b57cec5SDimitry Andric   }
1150b57cec5SDimitry Andric   return true;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric static bool callHasFloatingPointArgument(const CallInst *CI) {
1190b57cec5SDimitry Andric   return any_of(CI->operands(), [](const Use &OI) {
1200b57cec5SDimitry Andric     return OI->getType()->isFloatingPointTy();
1210b57cec5SDimitry Andric   });
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric static bool callHasFP128Argument(const CallInst *CI) {
1250b57cec5SDimitry Andric   return any_of(CI->operands(), [](const Use &OI) {
1260b57cec5SDimitry Andric     return OI->getType()->isFP128Ty();
1270b57cec5SDimitry Andric   });
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric 
130972a253aSDimitry Andric // Convert the entire string Str representing an integer in Base, up to
131972a253aSDimitry Andric // the terminating nul if present, to a constant according to the rules
132972a253aSDimitry Andric // of strtoul[l] or, when AsSigned is set, of strtol[l].  On success
133972a253aSDimitry Andric // return the result, otherwise null.
134972a253aSDimitry Andric // The function assumes the string is encoded in ASCII and carefully
135972a253aSDimitry Andric // avoids converting sequences (including "") that the corresponding
136972a253aSDimitry Andric // library call might fail and set errno for.
137972a253aSDimitry Andric static Value *convertStrToInt(CallInst *CI, StringRef &Str, Value *EndPtr,
138972a253aSDimitry Andric                               uint64_t Base, bool AsSigned, IRBuilderBase &B) {
1390b57cec5SDimitry Andric   if (Base < 2 || Base > 36)
1400b57cec5SDimitry Andric     if (Base != 0)
141972a253aSDimitry Andric       // Fail for an invalid base (required by POSIX).
1420b57cec5SDimitry Andric       return nullptr;
1430b57cec5SDimitry Andric 
144a4a491e2SDimitry Andric   // Current offset into the original string to reflect in EndPtr.
145a4a491e2SDimitry Andric   size_t Offset = 0;
146972a253aSDimitry Andric   // Strip leading whitespace.
147a4a491e2SDimitry Andric   for ( ; Offset != Str.size(); ++Offset)
148a4a491e2SDimitry Andric     if (!isSpace((unsigned char)Str[Offset])) {
149a4a491e2SDimitry Andric       Str = Str.substr(Offset);
150972a253aSDimitry Andric       break;
151972a253aSDimitry Andric     }
152972a253aSDimitry Andric 
153972a253aSDimitry Andric   if (Str.empty())
154972a253aSDimitry Andric     // Fail for empty subject sequences (POSIX allows but doesn't require
155972a253aSDimitry Andric     // strtol[l]/strtoul[l] to fail with EINVAL).
1560b57cec5SDimitry Andric     return nullptr;
1570b57cec5SDimitry Andric 
158972a253aSDimitry Andric   // Strip but remember the sign.
159972a253aSDimitry Andric   bool Negate = Str[0] == '-';
160972a253aSDimitry Andric   if (Str[0] == '-' || Str[0] == '+') {
161972a253aSDimitry Andric     Str = Str.drop_front();
162972a253aSDimitry Andric     if (Str.empty())
163972a253aSDimitry Andric       // Fail for a sign with nothing after it.
164972a253aSDimitry Andric       return nullptr;
165a4a491e2SDimitry Andric     ++Offset;
166972a253aSDimitry Andric   }
167972a253aSDimitry Andric 
168972a253aSDimitry Andric   // Set Max to the absolute value of the minimum (for signed), or
169972a253aSDimitry Andric   // to the maximum (for unsigned) value representable in the type.
170972a253aSDimitry Andric   Type *RetTy = CI->getType();
171972a253aSDimitry Andric   unsigned NBits = RetTy->getPrimitiveSizeInBits();
172972a253aSDimitry Andric   uint64_t Max = AsSigned && Negate ? 1 : 0;
173972a253aSDimitry Andric   Max += AsSigned ? maxIntN(NBits) : maxUIntN(NBits);
174972a253aSDimitry Andric 
175972a253aSDimitry Andric   // Autodetect Base if it's zero and consume the "0x" prefix.
176972a253aSDimitry Andric   if (Str.size() > 1) {
177972a253aSDimitry Andric     if (Str[0] == '0') {
178972a253aSDimitry Andric       if (toUpper((unsigned char)Str[1]) == 'X') {
179972a253aSDimitry Andric         if (Str.size() == 2 || (Base && Base != 16))
180972a253aSDimitry Andric           // Fail if Base doesn't allow the "0x" prefix or for the prefix
181972a253aSDimitry Andric           // alone that implementations like BSD set errno to EINVAL for.
1820b57cec5SDimitry Andric           return nullptr;
1830b57cec5SDimitry Andric 
184972a253aSDimitry Andric         Str = Str.drop_front(2);
185a4a491e2SDimitry Andric         Offset += 2;
186972a253aSDimitry Andric         Base = 16;
187972a253aSDimitry Andric       }
188972a253aSDimitry Andric       else if (Base == 0)
189972a253aSDimitry Andric         Base = 8;
190972a253aSDimitry Andric     } else if (Base == 0)
191972a253aSDimitry Andric       Base = 10;
192972a253aSDimitry Andric   }
193972a253aSDimitry Andric   else if (Base == 0)
194972a253aSDimitry Andric     Base = 10;
195972a253aSDimitry Andric 
196972a253aSDimitry Andric   // Convert the rest of the subject sequence, not including the sign,
197972a253aSDimitry Andric   // to its uint64_t representation (this assumes the source character
198972a253aSDimitry Andric   // set is ASCII).
199972a253aSDimitry Andric   uint64_t Result = 0;
200972a253aSDimitry Andric   for (unsigned i = 0; i != Str.size(); ++i) {
201972a253aSDimitry Andric     unsigned char DigVal = Str[i];
202972a253aSDimitry Andric     if (isDigit(DigVal))
203972a253aSDimitry Andric       DigVal = DigVal - '0';
204972a253aSDimitry Andric     else {
205972a253aSDimitry Andric       DigVal = toUpper(DigVal);
206972a253aSDimitry Andric       if (isAlpha(DigVal))
207972a253aSDimitry Andric         DigVal = DigVal - 'A' + 10;
208972a253aSDimitry Andric       else
2090b57cec5SDimitry Andric         return nullptr;
210972a253aSDimitry Andric     }
211972a253aSDimitry Andric 
212972a253aSDimitry Andric     if (DigVal >= Base)
213972a253aSDimitry Andric       // Fail if the digit is not valid in the Base.
214972a253aSDimitry Andric       return nullptr;
215972a253aSDimitry Andric 
216972a253aSDimitry Andric     // Add the digit and fail if the result is not representable in
217972a253aSDimitry Andric     // the (unsigned form of the) destination type.
218972a253aSDimitry Andric     bool VFlow;
219972a253aSDimitry Andric     Result = SaturatingMultiplyAdd(Result, Base, (uint64_t)DigVal, &VFlow);
220972a253aSDimitry Andric     if (VFlow || Result > Max)
221972a253aSDimitry Andric       return nullptr;
222972a253aSDimitry Andric   }
2230b57cec5SDimitry Andric 
224753f127fSDimitry Andric   if (EndPtr) {
225753f127fSDimitry Andric     // Store the pointer to the end.
226a4a491e2SDimitry Andric     Value *Off = B.getInt64(Offset + Str.size());
227753f127fSDimitry Andric     Value *StrBeg = CI->getArgOperand(0);
228753f127fSDimitry Andric     Value *StrEnd = B.CreateInBoundsGEP(B.getInt8Ty(), StrBeg, Off, "endptr");
229753f127fSDimitry Andric     B.CreateStore(StrEnd, EndPtr);
230753f127fSDimitry Andric   }
231753f127fSDimitry Andric 
232972a253aSDimitry Andric   if (Negate)
233972a253aSDimitry Andric     // Unsigned negation doesn't overflow.
234972a253aSDimitry Andric     Result = -Result;
235972a253aSDimitry Andric 
236972a253aSDimitry Andric   return ConstantInt::get(RetTy, Result);
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
2398a4dda33SDimitry Andric static bool isOnlyUsedInComparisonWithZero(Value *V) {
2408a4dda33SDimitry Andric   for (User *U : V->users()) {
2418a4dda33SDimitry Andric     if (ICmpInst *IC = dyn_cast<ICmpInst>(U))
2428a4dda33SDimitry Andric       if (Constant *C = dyn_cast<Constant>(IC->getOperand(1)))
2438a4dda33SDimitry Andric         if (C->isNullValue())
2448a4dda33SDimitry Andric           continue;
2458a4dda33SDimitry Andric     // Unknown instruction.
2468a4dda33SDimitry Andric     return false;
2478a4dda33SDimitry Andric   }
2488a4dda33SDimitry Andric   return true;
2498a4dda33SDimitry Andric }
2508a4dda33SDimitry Andric 
2510b57cec5SDimitry Andric static bool canTransformToMemCmp(CallInst *CI, Value *Str, uint64_t Len,
2520b57cec5SDimitry Andric                                  const DataLayout &DL) {
2538a4dda33SDimitry Andric   if (!isOnlyUsedInComparisonWithZero(CI))
2540b57cec5SDimitry Andric     return false;
2550b57cec5SDimitry Andric 
2565ffd83dbSDimitry Andric   if (!isDereferenceableAndAlignedPointer(Str, Align(1), APInt(64, Len), DL))
2570b57cec5SDimitry Andric     return false;
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   if (CI->getFunction()->hasFnAttribute(Attribute::SanitizeMemory))
2600b57cec5SDimitry Andric     return false;
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   return true;
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric 
2658bcb0991SDimitry Andric static void annotateDereferenceableBytes(CallInst *CI,
2668bcb0991SDimitry Andric                                          ArrayRef<unsigned> ArgNos,
2678bcb0991SDimitry Andric                                          uint64_t DereferenceableBytes) {
2688bcb0991SDimitry Andric   const Function *F = CI->getCaller();
2698bcb0991SDimitry Andric   if (!F)
2708bcb0991SDimitry Andric     return;
2718bcb0991SDimitry Andric   for (unsigned ArgNo : ArgNos) {
2728bcb0991SDimitry Andric     uint64_t DerefBytes = DereferenceableBytes;
2738bcb0991SDimitry Andric     unsigned AS = CI->getArgOperand(ArgNo)->getType()->getPointerAddressSpace();
2748bcb0991SDimitry Andric     if (!llvm::NullPointerIsDefined(F, AS) ||
2758bcb0991SDimitry Andric         CI->paramHasAttr(ArgNo, Attribute::NonNull))
276349cc55cSDimitry Andric       DerefBytes = std::max(CI->getParamDereferenceableOrNullBytes(ArgNo),
2778bcb0991SDimitry Andric                             DereferenceableBytes);
2788bcb0991SDimitry Andric 
279349cc55cSDimitry Andric     if (CI->getParamDereferenceableBytes(ArgNo) < DerefBytes) {
2808bcb0991SDimitry Andric       CI->removeParamAttr(ArgNo, Attribute::Dereferenceable);
2818bcb0991SDimitry Andric       if (!llvm::NullPointerIsDefined(F, AS) ||
2828bcb0991SDimitry Andric           CI->paramHasAttr(ArgNo, Attribute::NonNull))
2838bcb0991SDimitry Andric         CI->removeParamAttr(ArgNo, Attribute::DereferenceableOrNull);
2848bcb0991SDimitry Andric       CI->addParamAttr(ArgNo, Attribute::getWithDereferenceableBytes(
2858bcb0991SDimitry Andric                                   CI->getContext(), DerefBytes));
2868bcb0991SDimitry Andric     }
2878bcb0991SDimitry Andric   }
2888bcb0991SDimitry Andric }
2898bcb0991SDimitry Andric 
290fe6060f1SDimitry Andric static void annotateNonNullNoUndefBasedOnAccess(CallInst *CI,
2918bcb0991SDimitry Andric                                          ArrayRef<unsigned> ArgNos) {
2928bcb0991SDimitry Andric   Function *F = CI->getCaller();
2938bcb0991SDimitry Andric   if (!F)
2948bcb0991SDimitry Andric     return;
2958bcb0991SDimitry Andric 
2968bcb0991SDimitry Andric   for (unsigned ArgNo : ArgNos) {
297fe6060f1SDimitry Andric     if (!CI->paramHasAttr(ArgNo, Attribute::NoUndef))
298fe6060f1SDimitry Andric       CI->addParamAttr(ArgNo, Attribute::NoUndef);
299fe6060f1SDimitry Andric 
300bdd1243dSDimitry Andric     if (!CI->paramHasAttr(ArgNo, Attribute::NonNull)) {
301bdd1243dSDimitry Andric       unsigned AS =
302bdd1243dSDimitry Andric           CI->getArgOperand(ArgNo)->getType()->getPointerAddressSpace();
3038bcb0991SDimitry Andric       if (llvm::NullPointerIsDefined(F, AS))
3048bcb0991SDimitry Andric         continue;
3058bcb0991SDimitry Andric       CI->addParamAttr(ArgNo, Attribute::NonNull);
306bdd1243dSDimitry Andric     }
307bdd1243dSDimitry Andric 
3088bcb0991SDimitry Andric     annotateDereferenceableBytes(CI, ArgNo, 1);
3098bcb0991SDimitry Andric   }
3108bcb0991SDimitry Andric }
3118bcb0991SDimitry Andric 
3128bcb0991SDimitry Andric static void annotateNonNullAndDereferenceable(CallInst *CI, ArrayRef<unsigned> ArgNos,
3138bcb0991SDimitry Andric                                Value *Size, const DataLayout &DL) {
3148bcb0991SDimitry Andric   if (ConstantInt *LenC = dyn_cast<ConstantInt>(Size)) {
315fe6060f1SDimitry Andric     annotateNonNullNoUndefBasedOnAccess(CI, ArgNos);
3168bcb0991SDimitry Andric     annotateDereferenceableBytes(CI, ArgNos, LenC->getZExtValue());
3178bcb0991SDimitry Andric   } else if (isKnownNonZero(Size, DL)) {
318fe6060f1SDimitry Andric     annotateNonNullNoUndefBasedOnAccess(CI, ArgNos);
3198bcb0991SDimitry Andric     const APInt *X, *Y;
3208bcb0991SDimitry Andric     uint64_t DerefMin = 1;
3218bcb0991SDimitry Andric     if (match(Size, m_Select(m_Value(), m_APInt(X), m_APInt(Y)))) {
3228bcb0991SDimitry Andric       DerefMin = std::min(X->getZExtValue(), Y->getZExtValue());
3238bcb0991SDimitry Andric       annotateDereferenceableBytes(CI, ArgNos, DerefMin);
3248bcb0991SDimitry Andric     }
3258bcb0991SDimitry Andric   }
3268bcb0991SDimitry Andric }
3278bcb0991SDimitry Andric 
3280eae32dcSDimitry Andric // Copy CallInst "flags" like musttail, notail, and tail. Return New param for
3290eae32dcSDimitry Andric // easier chaining. Calls to emit* and B.createCall should probably be wrapped
3300eae32dcSDimitry Andric // in this function when New is created to replace Old. Callers should take
3310eae32dcSDimitry Andric // care to check Old.isMustTailCall() if they aren't replacing Old directly
3320eae32dcSDimitry Andric // with New.
3330eae32dcSDimitry Andric static Value *copyFlags(const CallInst &Old, Value *New) {
3340eae32dcSDimitry Andric   assert(!Old.isMustTailCall() && "do not copy musttail call flags");
3350eae32dcSDimitry Andric   assert(!Old.isNoTailCall() && "do not copy notail call flags");
3360eae32dcSDimitry Andric   if (auto *NewCI = dyn_cast_or_null<CallInst>(New))
3370eae32dcSDimitry Andric     NewCI->setTailCallKind(Old.getTailCallKind());
3380eae32dcSDimitry Andric   return New;
3390eae32dcSDimitry Andric }
3400eae32dcSDimitry Andric 
341bdd1243dSDimitry Andric static Value *mergeAttributesAndFlags(CallInst *NewCI, const CallInst &Old) {
342bdd1243dSDimitry Andric   NewCI->setAttributes(AttributeList::get(
343bdd1243dSDimitry Andric       NewCI->getContext(), {NewCI->getAttributes(), Old.getAttributes()}));
344bdd1243dSDimitry Andric   NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(NewCI->getType()));
345bdd1243dSDimitry Andric   return copyFlags(Old, NewCI);
346bdd1243dSDimitry Andric }
347bdd1243dSDimitry Andric 
34881ad6265SDimitry Andric // Helper to avoid truncating the length if size_t is 32-bits.
34981ad6265SDimitry Andric static StringRef substr(StringRef Str, uint64_t Len) {
35081ad6265SDimitry Andric   return Len >= Str.size() ? Str : Str.substr(0, Len);
35181ad6265SDimitry Andric }
35281ad6265SDimitry Andric 
3530b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
3540b57cec5SDimitry Andric // String and Memory Library Call Optimizations
3550b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
3560b57cec5SDimitry Andric 
3575ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrCat(CallInst *CI, IRBuilderBase &B) {
3580b57cec5SDimitry Andric   // Extract some information from the instruction
3590b57cec5SDimitry Andric   Value *Dst = CI->getArgOperand(0);
3600b57cec5SDimitry Andric   Value *Src = CI->getArgOperand(1);
361fe6060f1SDimitry Andric   annotateNonNullNoUndefBasedOnAccess(CI, {0, 1});
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   // See if we can get the length of the input string.
3640b57cec5SDimitry Andric   uint64_t Len = GetStringLength(Src);
3658bcb0991SDimitry Andric   if (Len)
3668bcb0991SDimitry Andric     annotateDereferenceableBytes(CI, 1, Len);
3678bcb0991SDimitry Andric   else
3680b57cec5SDimitry Andric     return nullptr;
3690b57cec5SDimitry Andric   --Len; // Unbias length.
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric   // Handle the simple, do-nothing case: strcat(x, "") -> x
3720b57cec5SDimitry Andric   if (Len == 0)
3730b57cec5SDimitry Andric     return Dst;
3740b57cec5SDimitry Andric 
3750eae32dcSDimitry Andric   return copyFlags(*CI, emitStrLenMemCpy(Src, Dst, Len, B));
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric Value *LibCallSimplifier::emitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len,
3795ffd83dbSDimitry Andric                                            IRBuilderBase &B) {
3800b57cec5SDimitry Andric   // We need to find the end of the destination string.  That's where the
3810b57cec5SDimitry Andric   // memory is to be moved to. We just generate a call to strlen.
3820b57cec5SDimitry Andric   Value *DstLen = emitStrLen(Dst, B, DL, TLI);
3830b57cec5SDimitry Andric   if (!DstLen)
3840b57cec5SDimitry Andric     return nullptr;
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   // Now that we have the destination's length, we must index into the
3870b57cec5SDimitry Andric   // destination's pointer to get the actual memcpy destination (end of
3880b57cec5SDimitry Andric   // the string .. we're concatenating).
38981ad6265SDimitry Andric   Value *CpyDst = B.CreateInBoundsGEP(B.getInt8Ty(), Dst, DstLen, "endptr");
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   // We have enough information to now generate the memcpy call to do the
3920b57cec5SDimitry Andric   // concatenation for us.  Make a memcpy to copy the nul byte with align = 1.
393480093f4SDimitry Andric   B.CreateMemCpy(
3945ffd83dbSDimitry Andric       CpyDst, Align(1), Src, Align(1),
3950b57cec5SDimitry Andric       ConstantInt::get(DL.getIntPtrType(Src->getContext()), Len + 1));
3960b57cec5SDimitry Andric   return Dst;
3970b57cec5SDimitry Andric }
3980b57cec5SDimitry Andric 
3995ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrNCat(CallInst *CI, IRBuilderBase &B) {
4000b57cec5SDimitry Andric   // Extract some information from the instruction.
4010b57cec5SDimitry Andric   Value *Dst = CI->getArgOperand(0);
4020b57cec5SDimitry Andric   Value *Src = CI->getArgOperand(1);
4038bcb0991SDimitry Andric   Value *Size = CI->getArgOperand(2);
4040b57cec5SDimitry Andric   uint64_t Len;
405fe6060f1SDimitry Andric   annotateNonNullNoUndefBasedOnAccess(CI, 0);
4068bcb0991SDimitry Andric   if (isKnownNonZero(Size, DL))
407fe6060f1SDimitry Andric     annotateNonNullNoUndefBasedOnAccess(CI, 1);
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   // We don't do anything if length is not constant.
4108bcb0991SDimitry Andric   ConstantInt *LengthArg = dyn_cast<ConstantInt>(Size);
4118bcb0991SDimitry Andric   if (LengthArg) {
4120b57cec5SDimitry Andric     Len = LengthArg->getZExtValue();
4138bcb0991SDimitry Andric     // strncat(x, c, 0) -> x
4148bcb0991SDimitry Andric     if (!Len)
4158bcb0991SDimitry Andric       return Dst;
4168bcb0991SDimitry Andric   } else {
4170b57cec5SDimitry Andric     return nullptr;
4188bcb0991SDimitry Andric   }
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric   // See if we can get the length of the input string.
4210b57cec5SDimitry Andric   uint64_t SrcLen = GetStringLength(Src);
4228bcb0991SDimitry Andric   if (SrcLen) {
4238bcb0991SDimitry Andric     annotateDereferenceableBytes(CI, 1, SrcLen);
4240b57cec5SDimitry Andric     --SrcLen; // Unbias length.
4258bcb0991SDimitry Andric   } else {
4268bcb0991SDimitry Andric     return nullptr;
4278bcb0991SDimitry Andric   }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   // strncat(x, "", c) -> x
4308bcb0991SDimitry Andric   if (SrcLen == 0)
4310b57cec5SDimitry Andric     return Dst;
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric   // We don't optimize this case.
4340b57cec5SDimitry Andric   if (Len < SrcLen)
4350b57cec5SDimitry Andric     return nullptr;
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   // strncat(x, s, c) -> strcat(x, s)
4380b57cec5SDimitry Andric   // s is constant so the strcat can be optimized further.
4390eae32dcSDimitry Andric   return copyFlags(*CI, emitStrLenMemCpy(Src, Dst, SrcLen, B));
4400b57cec5SDimitry Andric }
4410b57cec5SDimitry Andric 
442753f127fSDimitry Andric // Helper to transform memchr(S, C, N) == S to N && *S == C and, when
443753f127fSDimitry Andric // NBytes is null, strchr(S, C) to *S == C.  A precondition of the function
444753f127fSDimitry Andric // is that either S is dereferenceable or the value of N is nonzero.
445753f127fSDimitry Andric static Value* memChrToCharCompare(CallInst *CI, Value *NBytes,
446753f127fSDimitry Andric                                   IRBuilderBase &B, const DataLayout &DL)
447753f127fSDimitry Andric {
448753f127fSDimitry Andric   Value *Src = CI->getArgOperand(0);
449753f127fSDimitry Andric   Value *CharVal = CI->getArgOperand(1);
450753f127fSDimitry Andric 
451753f127fSDimitry Andric   // Fold memchr(A, C, N) == A to N && *A == C.
452753f127fSDimitry Andric   Type *CharTy = B.getInt8Ty();
453753f127fSDimitry Andric   Value *Char0 = B.CreateLoad(CharTy, Src);
454753f127fSDimitry Andric   CharVal = B.CreateTrunc(CharVal, CharTy);
455753f127fSDimitry Andric   Value *Cmp = B.CreateICmpEQ(Char0, CharVal, "char0cmp");
456753f127fSDimitry Andric 
457753f127fSDimitry Andric   if (NBytes) {
458753f127fSDimitry Andric     Value *Zero = ConstantInt::get(NBytes->getType(), 0);
459753f127fSDimitry Andric     Value *And = B.CreateICmpNE(NBytes, Zero);
460753f127fSDimitry Andric     Cmp = B.CreateLogicalAnd(And, Cmp);
461753f127fSDimitry Andric   }
462753f127fSDimitry Andric 
463753f127fSDimitry Andric   Value *NullPtr = Constant::getNullValue(CI->getType());
464753f127fSDimitry Andric   return B.CreateSelect(Cmp, Src, NullPtr);
465753f127fSDimitry Andric }
466753f127fSDimitry Andric 
4675ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrChr(CallInst *CI, IRBuilderBase &B) {
4680b57cec5SDimitry Andric   Value *SrcStr = CI->getArgOperand(0);
469753f127fSDimitry Andric   Value *CharVal = CI->getArgOperand(1);
470fe6060f1SDimitry Andric   annotateNonNullNoUndefBasedOnAccess(CI, 0);
4710b57cec5SDimitry Andric 
472753f127fSDimitry Andric   if (isOnlyUsedInEqualityComparison(CI, SrcStr))
473753f127fSDimitry Andric     return memChrToCharCompare(CI, nullptr, B, DL);
474753f127fSDimitry Andric 
4750b57cec5SDimitry Andric   // If the second operand is non-constant, see if we can compute the length
4760b57cec5SDimitry Andric   // of the input string and turn this into memchr.
477753f127fSDimitry Andric   ConstantInt *CharC = dyn_cast<ConstantInt>(CharVal);
4780b57cec5SDimitry Andric   if (!CharC) {
4790b57cec5SDimitry Andric     uint64_t Len = GetStringLength(SrcStr);
4808bcb0991SDimitry Andric     if (Len)
4818bcb0991SDimitry Andric       annotateDereferenceableBytes(CI, 0, Len);
4828bcb0991SDimitry Andric     else
4838bcb0991SDimitry Andric       return nullptr;
484753f127fSDimitry Andric 
485753f127fSDimitry Andric     Function *Callee = CI->getCalledFunction();
486753f127fSDimitry Andric     FunctionType *FT = Callee->getFunctionType();
487bdd1243dSDimitry Andric     unsigned IntBits = TLI->getIntSize();
488bdd1243dSDimitry Andric     if (!FT->getParamType(1)->isIntegerTy(IntBits)) // memchr needs 'int'.
4890b57cec5SDimitry Andric       return nullptr;
4900b57cec5SDimitry Andric 
491bdd1243dSDimitry Andric     unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule());
492bdd1243dSDimitry Andric     Type *SizeTTy = IntegerType::get(CI->getContext(), SizeTBits);
493bdd1243dSDimitry Andric     return copyFlags(*CI,
494753f127fSDimitry Andric                      emitMemChr(SrcStr, CharVal, // include nul.
495bdd1243dSDimitry Andric                                 ConstantInt::get(SizeTTy, Len), B,
4960eae32dcSDimitry Andric                                 DL, TLI));
4970b57cec5SDimitry Andric   }
4980b57cec5SDimitry Andric 
499753f127fSDimitry Andric   if (CharC->isZero()) {
500753f127fSDimitry Andric     Value *NullPtr = Constant::getNullValue(CI->getType());
501753f127fSDimitry Andric     if (isOnlyUsedInEqualityComparison(CI, NullPtr))
502753f127fSDimitry Andric       // Pre-empt the transformation to strlen below and fold
503753f127fSDimitry Andric       // strchr(A, '\0') == null to false.
504753f127fSDimitry Andric       return B.CreateIntToPtr(B.getTrue(), CI->getType());
505753f127fSDimitry Andric   }
506753f127fSDimitry Andric 
5070b57cec5SDimitry Andric   // Otherwise, the character is a constant, see if the first argument is
5080b57cec5SDimitry Andric   // a string literal.  If so, we can constant fold.
5090b57cec5SDimitry Andric   StringRef Str;
5100b57cec5SDimitry Andric   if (!getConstantStringInfo(SrcStr, Str)) {
5110b57cec5SDimitry Andric     if (CharC->isZero()) // strchr(p, 0) -> p + strlen(p)
512480093f4SDimitry Andric       if (Value *StrLen = emitStrLen(SrcStr, B, DL, TLI))
51381ad6265SDimitry Andric         return B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, StrLen, "strchr");
5140b57cec5SDimitry Andric     return nullptr;
5150b57cec5SDimitry Andric   }
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric   // Compute the offset, make sure to handle the case when we're searching for
5180b57cec5SDimitry Andric   // zero (a weird way to spell strlen).
5190b57cec5SDimitry Andric   size_t I = (0xFF & CharC->getSExtValue()) == 0
5200b57cec5SDimitry Andric                  ? Str.size()
5210b57cec5SDimitry Andric                  : Str.find(CharC->getSExtValue());
5220b57cec5SDimitry Andric   if (I == StringRef::npos) // Didn't find the char.  strchr returns null.
5230b57cec5SDimitry Andric     return Constant::getNullValue(CI->getType());
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric   // strchr(s+n,c)  -> gep(s+n+i,c)
52681ad6265SDimitry Andric   return B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, B.getInt64(I), "strchr");
5270b57cec5SDimitry Andric }
5280b57cec5SDimitry Andric 
5295ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrRChr(CallInst *CI, IRBuilderBase &B) {
5300b57cec5SDimitry Andric   Value *SrcStr = CI->getArgOperand(0);
53181ad6265SDimitry Andric   Value *CharVal = CI->getArgOperand(1);
53281ad6265SDimitry Andric   ConstantInt *CharC = dyn_cast<ConstantInt>(CharVal);
533fe6060f1SDimitry Andric   annotateNonNullNoUndefBasedOnAccess(CI, 0);
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   StringRef Str;
5360b57cec5SDimitry Andric   if (!getConstantStringInfo(SrcStr, Str)) {
5370b57cec5SDimitry Andric     // strrchr(s, 0) -> strchr(s, 0)
53881ad6265SDimitry Andric     if (CharC && CharC->isZero())
5390eae32dcSDimitry Andric       return copyFlags(*CI, emitStrChr(SrcStr, '\0', B, TLI));
5400b57cec5SDimitry Andric     return nullptr;
5410b57cec5SDimitry Andric   }
5420b57cec5SDimitry Andric 
543bdd1243dSDimitry Andric   unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule());
544bdd1243dSDimitry Andric   Type *SizeTTy = IntegerType::get(CI->getContext(), SizeTBits);
545bdd1243dSDimitry Andric 
54681ad6265SDimitry Andric   // Try to expand strrchr to the memrchr nonstandard extension if it's
54781ad6265SDimitry Andric   // available, or simply fail otherwise.
54881ad6265SDimitry Andric   uint64_t NBytes = Str.size() + 1;   // Include the terminating nul.
549bdd1243dSDimitry Andric   Value *Size = ConstantInt::get(SizeTTy, NBytes);
55081ad6265SDimitry Andric   return copyFlags(*CI, emitMemRChr(SrcStr, CharVal, Size, B, DL, TLI));
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric 
5535ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrCmp(CallInst *CI, IRBuilderBase &B) {
5540b57cec5SDimitry Andric   Value *Str1P = CI->getArgOperand(0), *Str2P = CI->getArgOperand(1);
5550b57cec5SDimitry Andric   if (Str1P == Str2P) // strcmp(x,x)  -> 0
5560b57cec5SDimitry Andric     return ConstantInt::get(CI->getType(), 0);
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric   StringRef Str1, Str2;
5590b57cec5SDimitry Andric   bool HasStr1 = getConstantStringInfo(Str1P, Str1);
5600b57cec5SDimitry Andric   bool HasStr2 = getConstantStringInfo(Str2P, Str2);
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric   // strcmp(x, y)  -> cnst  (if both x and y are constant strings)
5630b57cec5SDimitry Andric   if (HasStr1 && HasStr2)
564bdd1243dSDimitry Andric     return ConstantInt::get(CI->getType(),
565bdd1243dSDimitry Andric                             std::clamp(Str1.compare(Str2), -1, 1));
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric   if (HasStr1 && Str1.empty()) // strcmp("", x) -> -*x
5680b57cec5SDimitry Andric     return B.CreateNeg(B.CreateZExt(
5690b57cec5SDimitry Andric         B.CreateLoad(B.getInt8Ty(), Str2P, "strcmpload"), CI->getType()));
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   if (HasStr2 && Str2.empty()) // strcmp(x,"") -> *x
5720b57cec5SDimitry Andric     return B.CreateZExt(B.CreateLoad(B.getInt8Ty(), Str1P, "strcmpload"),
5730b57cec5SDimitry Andric                         CI->getType());
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric   // strcmp(P, "x") -> memcmp(P, "x", 2)
5760b57cec5SDimitry Andric   uint64_t Len1 = GetStringLength(Str1P);
5778bcb0991SDimitry Andric   if (Len1)
5788bcb0991SDimitry Andric     annotateDereferenceableBytes(CI, 0, Len1);
5790b57cec5SDimitry Andric   uint64_t Len2 = GetStringLength(Str2P);
5808bcb0991SDimitry Andric   if (Len2)
5818bcb0991SDimitry Andric     annotateDereferenceableBytes(CI, 1, Len2);
5828bcb0991SDimitry Andric 
5830b57cec5SDimitry Andric   if (Len1 && Len2) {
5840eae32dcSDimitry Andric     return copyFlags(
5850eae32dcSDimitry Andric         *CI, emitMemCmp(Str1P, Str2P,
5860b57cec5SDimitry Andric                         ConstantInt::get(DL.getIntPtrType(CI->getContext()),
5870b57cec5SDimitry Andric                                          std::min(Len1, Len2)),
5880eae32dcSDimitry Andric                         B, DL, TLI));
5890b57cec5SDimitry Andric   }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric   // strcmp to memcmp
5920b57cec5SDimitry Andric   if (!HasStr1 && HasStr2) {
5930b57cec5SDimitry Andric     if (canTransformToMemCmp(CI, Str1P, Len2, DL))
5940eae32dcSDimitry Andric       return copyFlags(
5950eae32dcSDimitry Andric           *CI,
5960eae32dcSDimitry Andric           emitMemCmp(Str1P, Str2P,
5970eae32dcSDimitry Andric                      ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len2),
5980eae32dcSDimitry Andric                      B, DL, TLI));
5990b57cec5SDimitry Andric   } else if (HasStr1 && !HasStr2) {
6000b57cec5SDimitry Andric     if (canTransformToMemCmp(CI, Str2P, Len1, DL))
6010eae32dcSDimitry Andric       return copyFlags(
6020eae32dcSDimitry Andric           *CI,
6030eae32dcSDimitry Andric           emitMemCmp(Str1P, Str2P,
6040eae32dcSDimitry Andric                      ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len1),
6050eae32dcSDimitry Andric                      B, DL, TLI));
6060b57cec5SDimitry Andric   }
6070b57cec5SDimitry Andric 
608fe6060f1SDimitry Andric   annotateNonNullNoUndefBasedOnAccess(CI, {0, 1});
6090b57cec5SDimitry Andric   return nullptr;
6100b57cec5SDimitry Andric }
6110b57cec5SDimitry Andric 
61281ad6265SDimitry Andric // Optimize a memcmp or, when StrNCmp is true, strncmp call CI with constant
61381ad6265SDimitry Andric // arrays LHS and RHS and nonconstant Size.
61481ad6265SDimitry Andric static Value *optimizeMemCmpVarSize(CallInst *CI, Value *LHS, Value *RHS,
61581ad6265SDimitry Andric                                     Value *Size, bool StrNCmp,
61681ad6265SDimitry Andric                                     IRBuilderBase &B, const DataLayout &DL);
61781ad6265SDimitry Andric 
6185ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrNCmp(CallInst *CI, IRBuilderBase &B) {
6198bcb0991SDimitry Andric   Value *Str1P = CI->getArgOperand(0);
6208bcb0991SDimitry Andric   Value *Str2P = CI->getArgOperand(1);
6218bcb0991SDimitry Andric   Value *Size = CI->getArgOperand(2);
6220b57cec5SDimitry Andric   if (Str1P == Str2P) // strncmp(x,x,n)  -> 0
6230b57cec5SDimitry Andric     return ConstantInt::get(CI->getType(), 0);
6240b57cec5SDimitry Andric 
6258bcb0991SDimitry Andric   if (isKnownNonZero(Size, DL))
626fe6060f1SDimitry Andric     annotateNonNullNoUndefBasedOnAccess(CI, {0, 1});
6270b57cec5SDimitry Andric   // Get the length argument if it is constant.
6280b57cec5SDimitry Andric   uint64_t Length;
6298bcb0991SDimitry Andric   if (ConstantInt *LengthArg = dyn_cast<ConstantInt>(Size))
6300b57cec5SDimitry Andric     Length = LengthArg->getZExtValue();
6310b57cec5SDimitry Andric   else
63281ad6265SDimitry Andric     return optimizeMemCmpVarSize(CI, Str1P, Str2P, Size, true, B, DL);
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric   if (Length == 0) // strncmp(x,y,0)   -> 0
6350b57cec5SDimitry Andric     return ConstantInt::get(CI->getType(), 0);
6360b57cec5SDimitry Andric 
6370b57cec5SDimitry Andric   if (Length == 1) // strncmp(x,y,1) -> memcmp(x,y,1)
6380eae32dcSDimitry Andric     return copyFlags(*CI, emitMemCmp(Str1P, Str2P, Size, B, DL, TLI));
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric   StringRef Str1, Str2;
6410b57cec5SDimitry Andric   bool HasStr1 = getConstantStringInfo(Str1P, Str1);
6420b57cec5SDimitry Andric   bool HasStr2 = getConstantStringInfo(Str2P, Str2);
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric   // strncmp(x, y)  -> cnst  (if both x and y are constant strings)
6450b57cec5SDimitry Andric   if (HasStr1 && HasStr2) {
64681ad6265SDimitry Andric     // Avoid truncating the 64-bit Length to 32 bits in ILP32.
64781ad6265SDimitry Andric     StringRef SubStr1 = substr(Str1, Length);
64881ad6265SDimitry Andric     StringRef SubStr2 = substr(Str2, Length);
649bdd1243dSDimitry Andric     return ConstantInt::get(CI->getType(),
650bdd1243dSDimitry Andric                             std::clamp(SubStr1.compare(SubStr2), -1, 1));
6510b57cec5SDimitry Andric   }
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric   if (HasStr1 && Str1.empty()) // strncmp("", x, n) -> -*x
6540b57cec5SDimitry Andric     return B.CreateNeg(B.CreateZExt(
6550b57cec5SDimitry Andric         B.CreateLoad(B.getInt8Ty(), Str2P, "strcmpload"), CI->getType()));
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric   if (HasStr2 && Str2.empty()) // strncmp(x, "", n) -> *x
6580b57cec5SDimitry Andric     return B.CreateZExt(B.CreateLoad(B.getInt8Ty(), Str1P, "strcmpload"),
6590b57cec5SDimitry Andric                         CI->getType());
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric   uint64_t Len1 = GetStringLength(Str1P);
6628bcb0991SDimitry Andric   if (Len1)
6638bcb0991SDimitry Andric     annotateDereferenceableBytes(CI, 0, Len1);
6640b57cec5SDimitry Andric   uint64_t Len2 = GetStringLength(Str2P);
6658bcb0991SDimitry Andric   if (Len2)
6668bcb0991SDimitry Andric     annotateDereferenceableBytes(CI, 1, Len2);
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric   // strncmp to memcmp
6690b57cec5SDimitry Andric   if (!HasStr1 && HasStr2) {
6700b57cec5SDimitry Andric     Len2 = std::min(Len2, Length);
6710b57cec5SDimitry Andric     if (canTransformToMemCmp(CI, Str1P, Len2, DL))
6720eae32dcSDimitry Andric       return copyFlags(
6730eae32dcSDimitry Andric           *CI,
6740eae32dcSDimitry Andric           emitMemCmp(Str1P, Str2P,
6750eae32dcSDimitry Andric                      ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len2),
6760eae32dcSDimitry Andric                      B, DL, TLI));
6770b57cec5SDimitry Andric   } else if (HasStr1 && !HasStr2) {
6780b57cec5SDimitry Andric     Len1 = std::min(Len1, Length);
6790b57cec5SDimitry Andric     if (canTransformToMemCmp(CI, Str2P, Len1, DL))
6800eae32dcSDimitry Andric       return copyFlags(
6810eae32dcSDimitry Andric           *CI,
6820eae32dcSDimitry Andric           emitMemCmp(Str1P, Str2P,
6830eae32dcSDimitry Andric                      ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len1),
6840eae32dcSDimitry Andric                      B, DL, TLI));
6850b57cec5SDimitry Andric   }
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric   return nullptr;
6880b57cec5SDimitry Andric }
6890b57cec5SDimitry Andric 
6905ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrNDup(CallInst *CI, IRBuilderBase &B) {
6918bcb0991SDimitry Andric   Value *Src = CI->getArgOperand(0);
6928bcb0991SDimitry Andric   ConstantInt *Size = dyn_cast<ConstantInt>(CI->getArgOperand(1));
6938bcb0991SDimitry Andric   uint64_t SrcLen = GetStringLength(Src);
6948bcb0991SDimitry Andric   if (SrcLen && Size) {
6958bcb0991SDimitry Andric     annotateDereferenceableBytes(CI, 0, SrcLen);
6968bcb0991SDimitry Andric     if (SrcLen <= Size->getZExtValue() + 1)
6970eae32dcSDimitry Andric       return copyFlags(*CI, emitStrDup(Src, B, TLI));
6988bcb0991SDimitry Andric   }
6998bcb0991SDimitry Andric 
7008bcb0991SDimitry Andric   return nullptr;
7018bcb0991SDimitry Andric }
7028bcb0991SDimitry Andric 
7035ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrCpy(CallInst *CI, IRBuilderBase &B) {
7040b57cec5SDimitry Andric   Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
7050b57cec5SDimitry Andric   if (Dst == Src) // strcpy(x,x)  -> x
7060b57cec5SDimitry Andric     return Src;
7070b57cec5SDimitry Andric 
708fe6060f1SDimitry Andric   annotateNonNullNoUndefBasedOnAccess(CI, {0, 1});
7090b57cec5SDimitry Andric   // See if we can get the length of the input string.
7100b57cec5SDimitry Andric   uint64_t Len = GetStringLength(Src);
7118bcb0991SDimitry Andric   if (Len)
7128bcb0991SDimitry Andric     annotateDereferenceableBytes(CI, 1, Len);
7138bcb0991SDimitry Andric   else
7140b57cec5SDimitry Andric     return nullptr;
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric   // We have enough information to now generate the memcpy call to do the
7170b57cec5SDimitry Andric   // copy for us.  Make a memcpy to copy the nul byte with align = 1.
7188bcb0991SDimitry Andric   CallInst *NewCI =
7195ffd83dbSDimitry Andric       B.CreateMemCpy(Dst, Align(1), Src, Align(1),
7200b57cec5SDimitry Andric                      ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len));
721bdd1243dSDimitry Andric   mergeAttributesAndFlags(NewCI, *CI);
7220b57cec5SDimitry Andric   return Dst;
7230b57cec5SDimitry Andric }
7240b57cec5SDimitry Andric 
7255ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStpCpy(CallInst *CI, IRBuilderBase &B) {
7260b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
7270b57cec5SDimitry Andric   Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
728349cc55cSDimitry Andric 
729349cc55cSDimitry Andric   // stpcpy(d,s) -> strcpy(d,s) if the result is not used.
730349cc55cSDimitry Andric   if (CI->use_empty())
7310eae32dcSDimitry Andric     return copyFlags(*CI, emitStrCpy(Dst, Src, B, TLI));
732349cc55cSDimitry Andric 
7330b57cec5SDimitry Andric   if (Dst == Src) { // stpcpy(x,x)  -> x+strlen(x)
7340b57cec5SDimitry Andric     Value *StrLen = emitStrLen(Src, B, DL, TLI);
7350b57cec5SDimitry Andric     return StrLen ? B.CreateInBoundsGEP(B.getInt8Ty(), Dst, StrLen) : nullptr;
7360b57cec5SDimitry Andric   }
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric   // See if we can get the length of the input string.
7390b57cec5SDimitry Andric   uint64_t Len = GetStringLength(Src);
7408bcb0991SDimitry Andric   if (Len)
7418bcb0991SDimitry Andric     annotateDereferenceableBytes(CI, 1, Len);
7428bcb0991SDimitry Andric   else
7430b57cec5SDimitry Andric     return nullptr;
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric   Type *PT = Callee->getFunctionType()->getParamType(0);
7460b57cec5SDimitry Andric   Value *LenV = ConstantInt::get(DL.getIntPtrType(PT), Len);
74781ad6265SDimitry Andric   Value *DstEnd = B.CreateInBoundsGEP(
74881ad6265SDimitry Andric       B.getInt8Ty(), Dst, ConstantInt::get(DL.getIntPtrType(PT), Len - 1));
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric   // We have enough information to now generate the memcpy call to do the
7510b57cec5SDimitry Andric   // copy for us.  Make a memcpy to copy the nul byte with align = 1.
7525ffd83dbSDimitry Andric   CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1), LenV);
753bdd1243dSDimitry Andric   mergeAttributesAndFlags(NewCI, *CI);
7540b57cec5SDimitry Andric   return DstEnd;
7550b57cec5SDimitry Andric }
7560b57cec5SDimitry Andric 
757bdd1243dSDimitry Andric // Optimize a call to size_t strlcpy(char*, const char*, size_t).
758bdd1243dSDimitry Andric 
759bdd1243dSDimitry Andric Value *LibCallSimplifier::optimizeStrLCpy(CallInst *CI, IRBuilderBase &B) {
760bdd1243dSDimitry Andric   Value *Size = CI->getArgOperand(2);
761bdd1243dSDimitry Andric   if (isKnownNonZero(Size, DL))
762bdd1243dSDimitry Andric     // Like snprintf, the function stores into the destination only when
763bdd1243dSDimitry Andric     // the size argument is nonzero.
764bdd1243dSDimitry Andric     annotateNonNullNoUndefBasedOnAccess(CI, 0);
765bdd1243dSDimitry Andric   // The function reads the source argument regardless of Size (it returns
766bdd1243dSDimitry Andric   // its length).
767bdd1243dSDimitry Andric   annotateNonNullNoUndefBasedOnAccess(CI, 1);
768bdd1243dSDimitry Andric 
769bdd1243dSDimitry Andric   uint64_t NBytes;
770bdd1243dSDimitry Andric   if (ConstantInt *SizeC = dyn_cast<ConstantInt>(Size))
771bdd1243dSDimitry Andric     NBytes = SizeC->getZExtValue();
772bdd1243dSDimitry Andric   else
773bdd1243dSDimitry Andric     return nullptr;
774bdd1243dSDimitry Andric 
775bdd1243dSDimitry Andric   Value *Dst = CI->getArgOperand(0);
776bdd1243dSDimitry Andric   Value *Src = CI->getArgOperand(1);
777bdd1243dSDimitry Andric   if (NBytes <= 1) {
778bdd1243dSDimitry Andric     if (NBytes == 1)
779bdd1243dSDimitry Andric       // For a call to strlcpy(D, S, 1) first store a nul in *D.
780bdd1243dSDimitry Andric       B.CreateStore(B.getInt8(0), Dst);
781bdd1243dSDimitry Andric 
782bdd1243dSDimitry Andric     // Transform strlcpy(D, S, 0) to a call to strlen(S).
783bdd1243dSDimitry Andric     return copyFlags(*CI, emitStrLen(Src, B, DL, TLI));
784bdd1243dSDimitry Andric   }
785bdd1243dSDimitry Andric 
786bdd1243dSDimitry Andric   // Try to determine the length of the source, substituting its size
787bdd1243dSDimitry Andric   // when it's not nul-terminated (as it's required to be) to avoid
788bdd1243dSDimitry Andric   // reading past its end.
789bdd1243dSDimitry Andric   StringRef Str;
790bdd1243dSDimitry Andric   if (!getConstantStringInfo(Src, Str, /*TrimAtNul=*/false))
791bdd1243dSDimitry Andric     return nullptr;
792bdd1243dSDimitry Andric 
793bdd1243dSDimitry Andric   uint64_t SrcLen = Str.find('\0');
794bdd1243dSDimitry Andric   // Set if the terminating nul should be copied by the call to memcpy
795bdd1243dSDimitry Andric   // below.
796bdd1243dSDimitry Andric   bool NulTerm = SrcLen < NBytes;
797bdd1243dSDimitry Andric 
798bdd1243dSDimitry Andric   if (NulTerm)
799bdd1243dSDimitry Andric     // Overwrite NBytes with the number of bytes to copy, including
800bdd1243dSDimitry Andric     // the terminating nul.
801bdd1243dSDimitry Andric     NBytes = SrcLen + 1;
802bdd1243dSDimitry Andric   else {
803bdd1243dSDimitry Andric     // Set the length of the source for the function to return to its
804bdd1243dSDimitry Andric     // size, and cap NBytes at the same.
805bdd1243dSDimitry Andric     SrcLen = std::min(SrcLen, uint64_t(Str.size()));
806bdd1243dSDimitry Andric     NBytes = std::min(NBytes - 1, SrcLen);
807bdd1243dSDimitry Andric   }
808bdd1243dSDimitry Andric 
809bdd1243dSDimitry Andric   if (SrcLen == 0) {
810bdd1243dSDimitry Andric     // Transform strlcpy(D, "", N) to (*D = '\0, 0).
811bdd1243dSDimitry Andric     B.CreateStore(B.getInt8(0), Dst);
812bdd1243dSDimitry Andric     return ConstantInt::get(CI->getType(), 0);
813bdd1243dSDimitry Andric   }
814bdd1243dSDimitry Andric 
815bdd1243dSDimitry Andric   Function *Callee = CI->getCalledFunction();
816bdd1243dSDimitry Andric   Type *PT = Callee->getFunctionType()->getParamType(0);
817bdd1243dSDimitry Andric   // Transform strlcpy(D, S, N) to memcpy(D, S, N') where N' is the lower
818bdd1243dSDimitry Andric   // bound on strlen(S) + 1 and N, optionally followed by a nul store to
819bdd1243dSDimitry Andric   // D[N' - 1] if necessary.
820bdd1243dSDimitry Andric   CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1),
821bdd1243dSDimitry Andric                         ConstantInt::get(DL.getIntPtrType(PT), NBytes));
822bdd1243dSDimitry Andric   mergeAttributesAndFlags(NewCI, *CI);
823bdd1243dSDimitry Andric 
824bdd1243dSDimitry Andric   if (!NulTerm) {
825bdd1243dSDimitry Andric     Value *EndOff = ConstantInt::get(CI->getType(), NBytes);
826bdd1243dSDimitry Andric     Value *EndPtr = B.CreateInBoundsGEP(B.getInt8Ty(), Dst, EndOff);
827bdd1243dSDimitry Andric     B.CreateStore(B.getInt8(0), EndPtr);
828bdd1243dSDimitry Andric   }
829bdd1243dSDimitry Andric 
830bdd1243dSDimitry Andric   // Like snprintf, strlcpy returns the number of nonzero bytes that would
831bdd1243dSDimitry Andric   // have been copied if the bound had been sufficiently big (which in this
832bdd1243dSDimitry Andric   // case is strlen(Src)).
833bdd1243dSDimitry Andric   return ConstantInt::get(CI->getType(), SrcLen);
834bdd1243dSDimitry Andric }
835bdd1243dSDimitry Andric 
836bdd1243dSDimitry Andric // Optimize a call CI to either stpncpy when RetEnd is true, or to strncpy
837bdd1243dSDimitry Andric // otherwise.
838bdd1243dSDimitry Andric Value *LibCallSimplifier::optimizeStringNCpy(CallInst *CI, bool RetEnd,
839bdd1243dSDimitry Andric                                              IRBuilderBase &B) {
8400b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
8410b57cec5SDimitry Andric   Value *Dst = CI->getArgOperand(0);
8420b57cec5SDimitry Andric   Value *Src = CI->getArgOperand(1);
8438bcb0991SDimitry Andric   Value *Size = CI->getArgOperand(2);
8440b57cec5SDimitry Andric 
845bdd1243dSDimitry Andric   if (isKnownNonZero(Size, DL)) {
846bdd1243dSDimitry Andric     // Both st{p,r}ncpy(D, S, N) access the source and destination arrays
847bdd1243dSDimitry Andric     // only when N is nonzero.
848bdd1243dSDimitry Andric     annotateNonNullNoUndefBasedOnAccess(CI, 0);
849bdd1243dSDimitry Andric     annotateNonNullNoUndefBasedOnAccess(CI, 1);
850bdd1243dSDimitry Andric   }
851bdd1243dSDimitry Andric 
852bdd1243dSDimitry Andric   // If the "bound" argument is known set N to it.  Otherwise set it to
853bdd1243dSDimitry Andric   // UINT64_MAX and handle it later.
854bdd1243dSDimitry Andric   uint64_t N = UINT64_MAX;
855bdd1243dSDimitry Andric   if (ConstantInt *SizeC = dyn_cast<ConstantInt>(Size))
856bdd1243dSDimitry Andric     N = SizeC->getZExtValue();
857bdd1243dSDimitry Andric 
858bdd1243dSDimitry Andric   if (N == 0)
859bdd1243dSDimitry Andric     // Fold st{p,r}ncpy(D, S, 0) to D.
860bdd1243dSDimitry Andric     return Dst;
861bdd1243dSDimitry Andric 
862bdd1243dSDimitry Andric   if (N == 1) {
863bdd1243dSDimitry Andric     Type *CharTy = B.getInt8Ty();
864bdd1243dSDimitry Andric     Value *CharVal = B.CreateLoad(CharTy, Src, "stxncpy.char0");
865bdd1243dSDimitry Andric     B.CreateStore(CharVal, Dst);
866bdd1243dSDimitry Andric     if (!RetEnd)
867bdd1243dSDimitry Andric       // Transform strncpy(D, S, 1) to return (*D = *S), D.
868bdd1243dSDimitry Andric       return Dst;
869bdd1243dSDimitry Andric 
870bdd1243dSDimitry Andric     // Transform stpncpy(D, S, 1) to return (*D = *S) ? D + 1 : D.
871bdd1243dSDimitry Andric     Value *ZeroChar = ConstantInt::get(CharTy, 0);
872bdd1243dSDimitry Andric     Value *Cmp = B.CreateICmpEQ(CharVal, ZeroChar, "stpncpy.char0cmp");
873bdd1243dSDimitry Andric 
874bdd1243dSDimitry Andric     Value *Off1 = B.getInt32(1);
875bdd1243dSDimitry Andric     Value *EndPtr = B.CreateInBoundsGEP(CharTy, Dst, Off1, "stpncpy.end");
876bdd1243dSDimitry Andric     return B.CreateSelect(Cmp, Dst, EndPtr, "stpncpy.sel");
877bdd1243dSDimitry Andric   }
878bdd1243dSDimitry Andric 
879bdd1243dSDimitry Andric   // If the length of the input string is known set SrcLen to it.
880bdd1243dSDimitry Andric   uint64_t SrcLen = GetStringLength(Src);
881bdd1243dSDimitry Andric   if (SrcLen)
882bdd1243dSDimitry Andric     annotateDereferenceableBytes(CI, 1, SrcLen);
8830b57cec5SDimitry Andric   else
8840b57cec5SDimitry Andric     return nullptr;
8850b57cec5SDimitry Andric 
8868bcb0991SDimitry Andric   --SrcLen; // Unbias length.
8878bcb0991SDimitry Andric 
8888bcb0991SDimitry Andric   if (SrcLen == 0) {
889bdd1243dSDimitry Andric     // Transform st{p,r}ncpy(D, "", N) to memset(D, '\0', N) for any N.
890fe6060f1SDimitry Andric     Align MemSetAlign =
891349cc55cSDimitry Andric       CI->getAttributes().getParamAttrs(0).getAlignment().valueOrOne();
892fe6060f1SDimitry Andric     CallInst *NewCI = B.CreateMemSet(Dst, B.getInt8('\0'), Size, MemSetAlign);
89304eeddc0SDimitry Andric     AttrBuilder ArgAttrs(CI->getContext(), CI->getAttributes().getParamAttrs(0));
8948bcb0991SDimitry Andric     NewCI->setAttributes(NewCI->getAttributes().addParamAttributes(
8958bcb0991SDimitry Andric         CI->getContext(), 0, ArgAttrs));
8960eae32dcSDimitry Andric     copyFlags(*CI, NewCI);
8978bcb0991SDimitry Andric     return Dst;
8988bcb0991SDimitry Andric   }
8990b57cec5SDimitry Andric 
900bdd1243dSDimitry Andric   if (N > SrcLen + 1) {
901bdd1243dSDimitry Andric     if (N > 128)
902bdd1243dSDimitry Andric       // Bail if N is large or unknown.
903bdd1243dSDimitry Andric       return nullptr;
904bdd1243dSDimitry Andric 
905bdd1243dSDimitry Andric     // st{p,r}ncpy(D, "a", N) -> memcpy(D, "a\0\0\0", N) for N <= 128.
906e8d8bef9SDimitry Andric     StringRef Str;
907e8d8bef9SDimitry Andric     if (!getConstantStringInfo(Src, Str))
9080b57cec5SDimitry Andric       return nullptr;
909e8d8bef9SDimitry Andric     std::string SrcStr = Str.str();
910bdd1243dSDimitry Andric     // Create a bigger, nul-padded array with the same length, SrcLen,
911bdd1243dSDimitry Andric     // as the original string.
912bdd1243dSDimitry Andric     SrcStr.resize(N, '\0');
913e8d8bef9SDimitry Andric     Src = B.CreateGlobalString(SrcStr, "str");
914e8d8bef9SDimitry Andric   }
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric   Type *PT = Callee->getFunctionType()->getParamType(0);
917bdd1243dSDimitry Andric   // st{p,r}ncpy(D, S, N) -> memcpy(align 1 D, align 1 S, N) when both
918bdd1243dSDimitry Andric   // S and N are constant.
9195ffd83dbSDimitry Andric   CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1),
920bdd1243dSDimitry Andric                                    ConstantInt::get(DL.getIntPtrType(PT), N));
921bdd1243dSDimitry Andric   mergeAttributesAndFlags(NewCI, *CI);
922bdd1243dSDimitry Andric   if (!RetEnd)
9230b57cec5SDimitry Andric     return Dst;
924bdd1243dSDimitry Andric 
925bdd1243dSDimitry Andric   // stpncpy(D, S, N) returns the address of the first null in D if it writes
926bdd1243dSDimitry Andric   // one, otherwise D + N.
927bdd1243dSDimitry Andric   Value *Off = B.getInt64(std::min(SrcLen, N));
928bdd1243dSDimitry Andric   return B.CreateInBoundsGEP(B.getInt8Ty(), Dst, Off, "endptr");
9290b57cec5SDimitry Andric }
9300b57cec5SDimitry Andric 
9315ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B,
93281ad6265SDimitry Andric                                                unsigned CharSize,
93381ad6265SDimitry Andric                                                Value *Bound) {
9340b57cec5SDimitry Andric   Value *Src = CI->getArgOperand(0);
93581ad6265SDimitry Andric   Type *CharTy = B.getIntNTy(CharSize);
9360b57cec5SDimitry Andric 
93781ad6265SDimitry Andric   if (isOnlyUsedInZeroEqualityComparison(CI) &&
93881ad6265SDimitry Andric       (!Bound || isKnownNonZero(Bound, DL))) {
93981ad6265SDimitry Andric     // Fold strlen:
94081ad6265SDimitry Andric     //   strlen(x) != 0 --> *x != 0
94181ad6265SDimitry Andric     //   strlen(x) == 0 --> *x == 0
94281ad6265SDimitry Andric     // and likewise strnlen with constant N > 0:
94381ad6265SDimitry Andric     //   strnlen(x, N) != 0 --> *x != 0
94481ad6265SDimitry Andric     //   strnlen(x, N) == 0 --> *x == 0
94581ad6265SDimitry Andric     return B.CreateZExt(B.CreateLoad(CharTy, Src, "char0"),
94681ad6265SDimitry Andric                         CI->getType());
94781ad6265SDimitry Andric   }
94881ad6265SDimitry Andric 
94981ad6265SDimitry Andric   if (Bound) {
95081ad6265SDimitry Andric     if (ConstantInt *BoundCst = dyn_cast<ConstantInt>(Bound)) {
95181ad6265SDimitry Andric       if (BoundCst->isZero())
95281ad6265SDimitry Andric         // Fold strnlen(s, 0) -> 0 for any s, constant or otherwise.
95381ad6265SDimitry Andric         return ConstantInt::get(CI->getType(), 0);
95481ad6265SDimitry Andric 
95581ad6265SDimitry Andric       if (BoundCst->isOne()) {
95681ad6265SDimitry Andric         // Fold strnlen(s, 1) -> *s ? 1 : 0 for any s.
95781ad6265SDimitry Andric         Value *CharVal = B.CreateLoad(CharTy, Src, "strnlen.char0");
95881ad6265SDimitry Andric         Value *ZeroChar = ConstantInt::get(CharTy, 0);
95981ad6265SDimitry Andric         Value *Cmp = B.CreateICmpNE(CharVal, ZeroChar, "strnlen.char0cmp");
96081ad6265SDimitry Andric         return B.CreateZExt(Cmp, CI->getType());
96181ad6265SDimitry Andric       }
96281ad6265SDimitry Andric     }
96381ad6265SDimitry Andric   }
96481ad6265SDimitry Andric 
96581ad6265SDimitry Andric   if (uint64_t Len = GetStringLength(Src, CharSize)) {
96681ad6265SDimitry Andric     Value *LenC = ConstantInt::get(CI->getType(), Len - 1);
96781ad6265SDimitry Andric     // Fold strlen("xyz") -> 3 and strnlen("xyz", 2) -> 2
96881ad6265SDimitry Andric     // and strnlen("xyz", Bound) -> min(3, Bound) for nonconstant Bound.
96981ad6265SDimitry Andric     if (Bound)
97081ad6265SDimitry Andric       return B.CreateBinaryIntrinsic(Intrinsic::umin, LenC, Bound);
97181ad6265SDimitry Andric     return LenC;
97281ad6265SDimitry Andric   }
97381ad6265SDimitry Andric 
97481ad6265SDimitry Andric   if (Bound)
97581ad6265SDimitry Andric     // Punt for strnlen for now.
97681ad6265SDimitry Andric     return nullptr;
9770b57cec5SDimitry Andric 
9780b57cec5SDimitry Andric   // If s is a constant pointer pointing to a string literal, we can fold
9790b57cec5SDimitry Andric   // strlen(s + x) to strlen(s) - x, when x is known to be in the range
9800b57cec5SDimitry Andric   // [0, strlen(s)] or the string has a single null terminator '\0' at the end.
9810b57cec5SDimitry Andric   // We only try to simplify strlen when the pointer s points to an array
982bdd1243dSDimitry Andric   // of CharSize elements. Otherwise, we would need to scale the offset x before
983bdd1243dSDimitry Andric   // doing the subtraction. This will make the optimization more complex, and
984bdd1243dSDimitry Andric   // it's not very useful because calling strlen for a pointer of other types is
9850b57cec5SDimitry Andric   // very uncommon.
9860b57cec5SDimitry Andric   if (GEPOperator *GEP = dyn_cast<GEPOperator>(Src)) {
98781ad6265SDimitry Andric     // TODO: Handle subobjects.
9880b57cec5SDimitry Andric     if (!isGEPBasedOnPointerToString(GEP, CharSize))
9890b57cec5SDimitry Andric       return nullptr;
9900b57cec5SDimitry Andric 
9910b57cec5SDimitry Andric     ConstantDataArraySlice Slice;
9920b57cec5SDimitry Andric     if (getConstantDataArrayInfo(GEP->getOperand(0), Slice, CharSize)) {
9930b57cec5SDimitry Andric       uint64_t NullTermIdx;
9940b57cec5SDimitry Andric       if (Slice.Array == nullptr) {
9950b57cec5SDimitry Andric         NullTermIdx = 0;
9960b57cec5SDimitry Andric       } else {
9970b57cec5SDimitry Andric         NullTermIdx = ~((uint64_t)0);
9980b57cec5SDimitry Andric         for (uint64_t I = 0, E = Slice.Length; I < E; ++I) {
9990b57cec5SDimitry Andric           if (Slice.Array->getElementAsInteger(I + Slice.Offset) == 0) {
10000b57cec5SDimitry Andric             NullTermIdx = I;
10010b57cec5SDimitry Andric             break;
10020b57cec5SDimitry Andric           }
10030b57cec5SDimitry Andric         }
10040b57cec5SDimitry Andric         // If the string does not have '\0', leave it to strlen to compute
10050b57cec5SDimitry Andric         // its length.
10060b57cec5SDimitry Andric         if (NullTermIdx == ~((uint64_t)0))
10070b57cec5SDimitry Andric           return nullptr;
10080b57cec5SDimitry Andric       }
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric       Value *Offset = GEP->getOperand(2);
10110b57cec5SDimitry Andric       KnownBits Known = computeKnownBits(Offset, DL, 0, nullptr, CI, nullptr);
10120b57cec5SDimitry Andric       uint64_t ArrSize =
10130b57cec5SDimitry Andric              cast<ArrayType>(GEP->getSourceElementType())->getNumElements();
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric       // If Offset is not provably in the range [0, NullTermIdx], we can still
10160b57cec5SDimitry Andric       // optimize if we can prove that the program has undefined behavior when
10170b57cec5SDimitry Andric       // Offset is outside that range. That is the case when GEP->getOperand(0)
10180b57cec5SDimitry Andric       // is a pointer to an object whose memory extent is NullTermIdx+1.
101981ad6265SDimitry Andric       if ((Known.isNonNegative() && Known.getMaxValue().ule(NullTermIdx)) ||
102081ad6265SDimitry Andric           (isa<GlobalVariable>(GEP->getOperand(0)) &&
10210b57cec5SDimitry Andric            NullTermIdx == ArrSize - 1)) {
10220b57cec5SDimitry Andric         Offset = B.CreateSExtOrTrunc(Offset, CI->getType());
10230b57cec5SDimitry Andric         return B.CreateSub(ConstantInt::get(CI->getType(), NullTermIdx),
10240b57cec5SDimitry Andric                            Offset);
10250b57cec5SDimitry Andric       }
10260b57cec5SDimitry Andric     }
10270b57cec5SDimitry Andric   }
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric   // strlen(x?"foo":"bars") --> x ? 3 : 4
10300b57cec5SDimitry Andric   if (SelectInst *SI = dyn_cast<SelectInst>(Src)) {
10310b57cec5SDimitry Andric     uint64_t LenTrue = GetStringLength(SI->getTrueValue(), CharSize);
10320b57cec5SDimitry Andric     uint64_t LenFalse = GetStringLength(SI->getFalseValue(), CharSize);
10330b57cec5SDimitry Andric     if (LenTrue && LenFalse) {
10340b57cec5SDimitry Andric       ORE.emit([&]() {
10350b57cec5SDimitry Andric         return OptimizationRemark("instcombine", "simplify-libcalls", CI)
10360b57cec5SDimitry Andric                << "folded strlen(select) to select of constants";
10370b57cec5SDimitry Andric       });
10380b57cec5SDimitry Andric       return B.CreateSelect(SI->getCondition(),
10390b57cec5SDimitry Andric                             ConstantInt::get(CI->getType(), LenTrue - 1),
10400b57cec5SDimitry Andric                             ConstantInt::get(CI->getType(), LenFalse - 1));
10410b57cec5SDimitry Andric     }
10420b57cec5SDimitry Andric   }
10430b57cec5SDimitry Andric 
10440b57cec5SDimitry Andric   return nullptr;
10450b57cec5SDimitry Andric }
10460b57cec5SDimitry Andric 
10475ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrLen(CallInst *CI, IRBuilderBase &B) {
10488bcb0991SDimitry Andric   if (Value *V = optimizeStringLength(CI, B, 8))
10498bcb0991SDimitry Andric     return V;
1050fe6060f1SDimitry Andric   annotateNonNullNoUndefBasedOnAccess(CI, 0);
10518bcb0991SDimitry Andric   return nullptr;
10520b57cec5SDimitry Andric }
10530b57cec5SDimitry Andric 
105481ad6265SDimitry Andric Value *LibCallSimplifier::optimizeStrNLen(CallInst *CI, IRBuilderBase &B) {
105581ad6265SDimitry Andric   Value *Bound = CI->getArgOperand(1);
105681ad6265SDimitry Andric   if (Value *V = optimizeStringLength(CI, B, 8, Bound))
105781ad6265SDimitry Andric     return V;
105881ad6265SDimitry Andric 
105981ad6265SDimitry Andric   if (isKnownNonZero(Bound, DL))
106081ad6265SDimitry Andric     annotateNonNullNoUndefBasedOnAccess(CI, 0);
106181ad6265SDimitry Andric   return nullptr;
106281ad6265SDimitry Andric }
106381ad6265SDimitry Andric 
10645ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeWcslen(CallInst *CI, IRBuilderBase &B) {
10650b57cec5SDimitry Andric   Module &M = *CI->getModule();
10660b57cec5SDimitry Andric   unsigned WCharSize = TLI->getWCharSize(M) * 8;
10670b57cec5SDimitry Andric   // We cannot perform this optimization without wchar_size metadata.
10680b57cec5SDimitry Andric   if (WCharSize == 0)
10690b57cec5SDimitry Andric     return nullptr;
10700b57cec5SDimitry Andric 
10710b57cec5SDimitry Andric   return optimizeStringLength(CI, B, WCharSize);
10720b57cec5SDimitry Andric }
10730b57cec5SDimitry Andric 
10745ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrPBrk(CallInst *CI, IRBuilderBase &B) {
10750b57cec5SDimitry Andric   StringRef S1, S2;
10760b57cec5SDimitry Andric   bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
10770b57cec5SDimitry Andric   bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric   // strpbrk(s, "") -> nullptr
10800b57cec5SDimitry Andric   // strpbrk("", s) -> nullptr
10810b57cec5SDimitry Andric   if ((HasS1 && S1.empty()) || (HasS2 && S2.empty()))
10820b57cec5SDimitry Andric     return Constant::getNullValue(CI->getType());
10830b57cec5SDimitry Andric 
10840b57cec5SDimitry Andric   // Constant folding.
10850b57cec5SDimitry Andric   if (HasS1 && HasS2) {
10860b57cec5SDimitry Andric     size_t I = S1.find_first_of(S2);
10870b57cec5SDimitry Andric     if (I == StringRef::npos) // No match.
10880b57cec5SDimitry Andric       return Constant::getNullValue(CI->getType());
10890b57cec5SDimitry Andric 
109081ad6265SDimitry Andric     return B.CreateInBoundsGEP(B.getInt8Ty(), CI->getArgOperand(0),
109181ad6265SDimitry Andric                                B.getInt64(I), "strpbrk");
10920b57cec5SDimitry Andric   }
10930b57cec5SDimitry Andric 
10940b57cec5SDimitry Andric   // strpbrk(s, "a") -> strchr(s, 'a')
10950b57cec5SDimitry Andric   if (HasS2 && S2.size() == 1)
10960eae32dcSDimitry Andric     return copyFlags(*CI, emitStrChr(CI->getArgOperand(0), S2[0], B, TLI));
10970b57cec5SDimitry Andric 
10980b57cec5SDimitry Andric   return nullptr;
10990b57cec5SDimitry Andric }
11000b57cec5SDimitry Andric 
11015ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrTo(CallInst *CI, IRBuilderBase &B) {
11020b57cec5SDimitry Andric   Value *EndPtr = CI->getArgOperand(1);
11030b57cec5SDimitry Andric   if (isa<ConstantPointerNull>(EndPtr)) {
11040b57cec5SDimitry Andric     // With a null EndPtr, this function won't capture the main argument.
11050b57cec5SDimitry Andric     // It would be readonly too, except that it still may write to errno.
11060b57cec5SDimitry Andric     CI->addParamAttr(0, Attribute::NoCapture);
11070b57cec5SDimitry Andric   }
11080b57cec5SDimitry Andric 
11090b57cec5SDimitry Andric   return nullptr;
11100b57cec5SDimitry Andric }
11110b57cec5SDimitry Andric 
11125ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrSpn(CallInst *CI, IRBuilderBase &B) {
11130b57cec5SDimitry Andric   StringRef S1, S2;
11140b57cec5SDimitry Andric   bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
11150b57cec5SDimitry Andric   bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
11160b57cec5SDimitry Andric 
11170b57cec5SDimitry Andric   // strspn(s, "") -> 0
11180b57cec5SDimitry Andric   // strspn("", s) -> 0
11190b57cec5SDimitry Andric   if ((HasS1 && S1.empty()) || (HasS2 && S2.empty()))
11200b57cec5SDimitry Andric     return Constant::getNullValue(CI->getType());
11210b57cec5SDimitry Andric 
11220b57cec5SDimitry Andric   // Constant folding.
11230b57cec5SDimitry Andric   if (HasS1 && HasS2) {
11240b57cec5SDimitry Andric     size_t Pos = S1.find_first_not_of(S2);
11250b57cec5SDimitry Andric     if (Pos == StringRef::npos)
11260b57cec5SDimitry Andric       Pos = S1.size();
11270b57cec5SDimitry Andric     return ConstantInt::get(CI->getType(), Pos);
11280b57cec5SDimitry Andric   }
11290b57cec5SDimitry Andric 
11300b57cec5SDimitry Andric   return nullptr;
11310b57cec5SDimitry Andric }
11320b57cec5SDimitry Andric 
11335ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrCSpn(CallInst *CI, IRBuilderBase &B) {
11340b57cec5SDimitry Andric   StringRef S1, S2;
11350b57cec5SDimitry Andric   bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
11360b57cec5SDimitry Andric   bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
11370b57cec5SDimitry Andric 
11380b57cec5SDimitry Andric   // strcspn("", s) -> 0
11390b57cec5SDimitry Andric   if (HasS1 && S1.empty())
11400b57cec5SDimitry Andric     return Constant::getNullValue(CI->getType());
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric   // Constant folding.
11430b57cec5SDimitry Andric   if (HasS1 && HasS2) {
11440b57cec5SDimitry Andric     size_t Pos = S1.find_first_of(S2);
11450b57cec5SDimitry Andric     if (Pos == StringRef::npos)
11460b57cec5SDimitry Andric       Pos = S1.size();
11470b57cec5SDimitry Andric     return ConstantInt::get(CI->getType(), Pos);
11480b57cec5SDimitry Andric   }
11490b57cec5SDimitry Andric 
11500b57cec5SDimitry Andric   // strcspn(s, "") -> strlen(s)
11510b57cec5SDimitry Andric   if (HasS2 && S2.empty())
11520eae32dcSDimitry Andric     return copyFlags(*CI, emitStrLen(CI->getArgOperand(0), B, DL, TLI));
11530b57cec5SDimitry Andric 
11540b57cec5SDimitry Andric   return nullptr;
11550b57cec5SDimitry Andric }
11560b57cec5SDimitry Andric 
11575ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeStrStr(CallInst *CI, IRBuilderBase &B) {
11580b57cec5SDimitry Andric   // fold strstr(x, x) -> x.
11590b57cec5SDimitry Andric   if (CI->getArgOperand(0) == CI->getArgOperand(1))
11605f757f3fSDimitry Andric     return CI->getArgOperand(0);
11610b57cec5SDimitry Andric 
11620b57cec5SDimitry Andric   // fold strstr(a, b) == a -> strncmp(a, b, strlen(b)) == 0
11630b57cec5SDimitry Andric   if (isOnlyUsedInEqualityComparison(CI, CI->getArgOperand(0))) {
11640b57cec5SDimitry Andric     Value *StrLen = emitStrLen(CI->getArgOperand(1), B, DL, TLI);
11650b57cec5SDimitry Andric     if (!StrLen)
11660b57cec5SDimitry Andric       return nullptr;
11670b57cec5SDimitry Andric     Value *StrNCmp = emitStrNCmp(CI->getArgOperand(0), CI->getArgOperand(1),
11680b57cec5SDimitry Andric                                  StrLen, B, DL, TLI);
11690b57cec5SDimitry Andric     if (!StrNCmp)
11700b57cec5SDimitry Andric       return nullptr;
1171fe6060f1SDimitry Andric     for (User *U : llvm::make_early_inc_range(CI->users())) {
1172fe6060f1SDimitry Andric       ICmpInst *Old = cast<ICmpInst>(U);
11730b57cec5SDimitry Andric       Value *Cmp =
11740b57cec5SDimitry Andric           B.CreateICmp(Old->getPredicate(), StrNCmp,
11750b57cec5SDimitry Andric                        ConstantInt::getNullValue(StrNCmp->getType()), "cmp");
11760b57cec5SDimitry Andric       replaceAllUsesWith(Old, Cmp);
11770b57cec5SDimitry Andric     }
11780b57cec5SDimitry Andric     return CI;
11790b57cec5SDimitry Andric   }
11800b57cec5SDimitry Andric 
11810b57cec5SDimitry Andric   // See if either input string is a constant string.
11820b57cec5SDimitry Andric   StringRef SearchStr, ToFindStr;
11830b57cec5SDimitry Andric   bool HasStr1 = getConstantStringInfo(CI->getArgOperand(0), SearchStr);
11840b57cec5SDimitry Andric   bool HasStr2 = getConstantStringInfo(CI->getArgOperand(1), ToFindStr);
11850b57cec5SDimitry Andric 
11860b57cec5SDimitry Andric   // fold strstr(x, "") -> x.
11870b57cec5SDimitry Andric   if (HasStr2 && ToFindStr.empty())
11885f757f3fSDimitry Andric     return CI->getArgOperand(0);
11890b57cec5SDimitry Andric 
11900b57cec5SDimitry Andric   // If both strings are known, constant fold it.
11910b57cec5SDimitry Andric   if (HasStr1 && HasStr2) {
11920b57cec5SDimitry Andric     size_t Offset = SearchStr.find(ToFindStr);
11930b57cec5SDimitry Andric 
11940b57cec5SDimitry Andric     if (Offset == StringRef::npos) // strstr("foo", "bar") -> null
11950b57cec5SDimitry Andric       return Constant::getNullValue(CI->getType());
11960b57cec5SDimitry Andric 
11970b57cec5SDimitry Andric     // strstr("abcd", "bc") -> gep((char*)"abcd", 1)
11985f757f3fSDimitry Andric     return B.CreateConstInBoundsGEP1_64(B.getInt8Ty(), CI->getArgOperand(0),
11995f757f3fSDimitry Andric                                         Offset, "strstr");
12000b57cec5SDimitry Andric   }
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric   // fold strstr(x, "y") -> strchr(x, 'y').
12030b57cec5SDimitry Andric   if (HasStr2 && ToFindStr.size() == 1) {
12045f757f3fSDimitry Andric     return emitStrChr(CI->getArgOperand(0), ToFindStr[0], B, TLI);
12050b57cec5SDimitry Andric   }
12068bcb0991SDimitry Andric 
1207fe6060f1SDimitry Andric   annotateNonNullNoUndefBasedOnAccess(CI, {0, 1});
12088bcb0991SDimitry Andric   return nullptr;
12098bcb0991SDimitry Andric }
12108bcb0991SDimitry Andric 
12115ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeMemRChr(CallInst *CI, IRBuilderBase &B) {
12120b57cec5SDimitry Andric   Value *SrcStr = CI->getArgOperand(0);
12138bcb0991SDimitry Andric   Value *Size = CI->getArgOperand(2);
12148bcb0991SDimitry Andric   annotateNonNullAndDereferenceable(CI, 0, Size, DL);
121581ad6265SDimitry Andric   Value *CharVal = CI->getArgOperand(1);
12168bcb0991SDimitry Andric   ConstantInt *LenC = dyn_cast<ConstantInt>(Size);
121781ad6265SDimitry Andric   Value *NullPtr = Constant::getNullValue(CI->getType());
12180b57cec5SDimitry Andric 
12198bcb0991SDimitry Andric   if (LenC) {
12208bcb0991SDimitry Andric     if (LenC->isZero())
122181ad6265SDimitry Andric       // Fold memrchr(x, y, 0) --> null.
122281ad6265SDimitry Andric       return NullPtr;
122381ad6265SDimitry Andric 
122481ad6265SDimitry Andric     if (LenC->isOne()) {
122581ad6265SDimitry Andric       // Fold memrchr(x, y, 1) --> *x == y ? x : null for any x and y,
122681ad6265SDimitry Andric       // constant or otherwise.
122781ad6265SDimitry Andric       Value *Val = B.CreateLoad(B.getInt8Ty(), SrcStr, "memrchr.char0");
122881ad6265SDimitry Andric       // Slice off the character's high end bits.
122981ad6265SDimitry Andric       CharVal = B.CreateTrunc(CharVal, B.getInt8Ty());
123081ad6265SDimitry Andric       Value *Cmp = B.CreateICmpEQ(Val, CharVal, "memrchr.char0cmp");
123181ad6265SDimitry Andric       return B.CreateSelect(Cmp, SrcStr, NullPtr, "memrchr.sel");
123281ad6265SDimitry Andric     }
12338bcb0991SDimitry Andric   }
12348bcb0991SDimitry Andric 
12350b57cec5SDimitry Andric   StringRef Str;
1236bdd1243dSDimitry Andric   if (!getConstantStringInfo(SrcStr, Str, /*TrimAtNul=*/false))
12370b57cec5SDimitry Andric     return nullptr;
12380b57cec5SDimitry Andric 
123981ad6265SDimitry Andric   if (Str.size() == 0)
124081ad6265SDimitry Andric     // If the array is empty fold memrchr(A, C, N) to null for any value
124181ad6265SDimitry Andric     // of C and N on the basis that the only valid value of N is zero
124281ad6265SDimitry Andric     // (otherwise the call is undefined).
124381ad6265SDimitry Andric     return NullPtr;
124481ad6265SDimitry Andric 
124581ad6265SDimitry Andric   uint64_t EndOff = UINT64_MAX;
124681ad6265SDimitry Andric   if (LenC) {
124781ad6265SDimitry Andric     EndOff = LenC->getZExtValue();
124881ad6265SDimitry Andric     if (Str.size() < EndOff)
124981ad6265SDimitry Andric       // Punt out-of-bounds accesses to sanitizers and/or libc.
125081ad6265SDimitry Andric       return nullptr;
125181ad6265SDimitry Andric   }
125281ad6265SDimitry Andric 
125381ad6265SDimitry Andric   if (ConstantInt *CharC = dyn_cast<ConstantInt>(CharVal)) {
125481ad6265SDimitry Andric     // Fold memrchr(S, C, N) for a constant C.
125581ad6265SDimitry Andric     size_t Pos = Str.rfind(CharC->getZExtValue(), EndOff);
125681ad6265SDimitry Andric     if (Pos == StringRef::npos)
125781ad6265SDimitry Andric       // When the character is not in the source array fold the result
125881ad6265SDimitry Andric       // to null regardless of Size.
125981ad6265SDimitry Andric       return NullPtr;
126081ad6265SDimitry Andric 
126181ad6265SDimitry Andric     if (LenC)
126281ad6265SDimitry Andric       // Fold memrchr(s, c, N) --> s + Pos for constant N > Pos.
126381ad6265SDimitry Andric       return B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, B.getInt64(Pos));
126481ad6265SDimitry Andric 
126581ad6265SDimitry Andric     if (Str.find(Str[Pos]) == Pos) {
126681ad6265SDimitry Andric       // When there is just a single occurrence of C in S, i.e., the one
126781ad6265SDimitry Andric       // in Str[Pos], fold
126881ad6265SDimitry Andric       //   memrchr(s, c, N) --> N <= Pos ? null : s + Pos
126981ad6265SDimitry Andric       // for nonconstant N.
127081ad6265SDimitry Andric       Value *Cmp = B.CreateICmpULE(Size, ConstantInt::get(Size->getType(), Pos),
127181ad6265SDimitry Andric                                    "memrchr.cmp");
127281ad6265SDimitry Andric       Value *SrcPlus = B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr,
127381ad6265SDimitry Andric                                            B.getInt64(Pos), "memrchr.ptr_plus");
127481ad6265SDimitry Andric       return B.CreateSelect(Cmp, NullPtr, SrcPlus, "memrchr.sel");
127581ad6265SDimitry Andric     }
127681ad6265SDimitry Andric   }
127781ad6265SDimitry Andric 
127881ad6265SDimitry Andric   // Truncate the string to search at most EndOff characters.
127981ad6265SDimitry Andric   Str = Str.substr(0, EndOff);
128081ad6265SDimitry Andric   if (Str.find_first_not_of(Str[0]) != StringRef::npos)
128181ad6265SDimitry Andric     return nullptr;
128281ad6265SDimitry Andric 
128381ad6265SDimitry Andric   // If the source array consists of all equal characters, then for any
128481ad6265SDimitry Andric   // C and N (whether in bounds or not), fold memrchr(S, C, N) to
128581ad6265SDimitry Andric   //   N != 0 && *S == C ? S + N - 1 : null
128681ad6265SDimitry Andric   Type *SizeTy = Size->getType();
128781ad6265SDimitry Andric   Type *Int8Ty = B.getInt8Ty();
128881ad6265SDimitry Andric   Value *NNeZ = B.CreateICmpNE(Size, ConstantInt::get(SizeTy, 0));
128981ad6265SDimitry Andric   // Slice off the sought character's high end bits.
129081ad6265SDimitry Andric   CharVal = B.CreateTrunc(CharVal, Int8Ty);
129181ad6265SDimitry Andric   Value *CEqS0 = B.CreateICmpEQ(ConstantInt::get(Int8Ty, Str[0]), CharVal);
129281ad6265SDimitry Andric   Value *And = B.CreateLogicalAnd(NNeZ, CEqS0);
129381ad6265SDimitry Andric   Value *SizeM1 = B.CreateSub(Size, ConstantInt::get(SizeTy, 1));
129481ad6265SDimitry Andric   Value *SrcPlus =
129581ad6265SDimitry Andric       B.CreateInBoundsGEP(Int8Ty, SrcStr, SizeM1, "memrchr.ptr_plus");
129681ad6265SDimitry Andric   return B.CreateSelect(And, SrcPlus, NullPtr, "memrchr.sel");
129781ad6265SDimitry Andric }
129881ad6265SDimitry Andric 
129981ad6265SDimitry Andric Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilderBase &B) {
130081ad6265SDimitry Andric   Value *SrcStr = CI->getArgOperand(0);
130181ad6265SDimitry Andric   Value *Size = CI->getArgOperand(2);
1302753f127fSDimitry Andric 
1303753f127fSDimitry Andric   if (isKnownNonZero(Size, DL)) {
130481ad6265SDimitry Andric     annotateNonNullNoUndefBasedOnAccess(CI, 0);
1305753f127fSDimitry Andric     if (isOnlyUsedInEqualityComparison(CI, SrcStr))
1306753f127fSDimitry Andric       return memChrToCharCompare(CI, Size, B, DL);
1307753f127fSDimitry Andric   }
130881ad6265SDimitry Andric 
130981ad6265SDimitry Andric   Value *CharVal = CI->getArgOperand(1);
131081ad6265SDimitry Andric   ConstantInt *CharC = dyn_cast<ConstantInt>(CharVal);
131181ad6265SDimitry Andric   ConstantInt *LenC = dyn_cast<ConstantInt>(Size);
131281ad6265SDimitry Andric   Value *NullPtr = Constant::getNullValue(CI->getType());
131381ad6265SDimitry Andric 
131481ad6265SDimitry Andric   // memchr(x, y, 0) -> null
131581ad6265SDimitry Andric   if (LenC) {
131681ad6265SDimitry Andric     if (LenC->isZero())
131781ad6265SDimitry Andric       return NullPtr;
131881ad6265SDimitry Andric 
131981ad6265SDimitry Andric     if (LenC->isOne()) {
132081ad6265SDimitry Andric       // Fold memchr(x, y, 1) --> *x == y ? x : null for any x and y,
132181ad6265SDimitry Andric       // constant or otherwise.
132281ad6265SDimitry Andric       Value *Val = B.CreateLoad(B.getInt8Ty(), SrcStr, "memchr.char0");
132381ad6265SDimitry Andric       // Slice off the character's high end bits.
132481ad6265SDimitry Andric       CharVal = B.CreateTrunc(CharVal, B.getInt8Ty());
132581ad6265SDimitry Andric       Value *Cmp = B.CreateICmpEQ(Val, CharVal, "memchr.char0cmp");
132681ad6265SDimitry Andric       return B.CreateSelect(Cmp, SrcStr, NullPtr, "memchr.sel");
132781ad6265SDimitry Andric     }
132881ad6265SDimitry Andric   }
132981ad6265SDimitry Andric 
133081ad6265SDimitry Andric   StringRef Str;
1331bdd1243dSDimitry Andric   if (!getConstantStringInfo(SrcStr, Str, /*TrimAtNul=*/false))
133281ad6265SDimitry Andric     return nullptr;
133381ad6265SDimitry Andric 
133481ad6265SDimitry Andric   if (CharC) {
133581ad6265SDimitry Andric     size_t Pos = Str.find(CharC->getZExtValue());
133681ad6265SDimitry Andric     if (Pos == StringRef::npos)
133781ad6265SDimitry Andric       // When the character is not in the source array fold the result
133881ad6265SDimitry Andric       // to null regardless of Size.
133981ad6265SDimitry Andric       return NullPtr;
134081ad6265SDimitry Andric 
134181ad6265SDimitry Andric     // Fold memchr(s, c, n) -> n <= Pos ? null : s + Pos
134281ad6265SDimitry Andric     // When the constant Size is less than or equal to the character
134381ad6265SDimitry Andric     // position also fold the result to null.
134481ad6265SDimitry Andric     Value *Cmp = B.CreateICmpULE(Size, ConstantInt::get(Size->getType(), Pos),
134581ad6265SDimitry Andric                                  "memchr.cmp");
134681ad6265SDimitry Andric     Value *SrcPlus = B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, B.getInt64(Pos),
134781ad6265SDimitry Andric                                          "memchr.ptr");
134881ad6265SDimitry Andric     return B.CreateSelect(Cmp, NullPtr, SrcPlus);
134981ad6265SDimitry Andric   }
135081ad6265SDimitry Andric 
135181ad6265SDimitry Andric   if (Str.size() == 0)
135281ad6265SDimitry Andric     // If the array is empty fold memchr(A, C, N) to null for any value
135381ad6265SDimitry Andric     // of C and N on the basis that the only valid value of N is zero
135481ad6265SDimitry Andric     // (otherwise the call is undefined).
135581ad6265SDimitry Andric     return NullPtr;
135681ad6265SDimitry Andric 
135781ad6265SDimitry Andric   if (LenC)
135881ad6265SDimitry Andric     Str = substr(Str, LenC->getZExtValue());
135981ad6265SDimitry Andric 
136081ad6265SDimitry Andric   size_t Pos = Str.find_first_not_of(Str[0]);
136181ad6265SDimitry Andric   if (Pos == StringRef::npos
136281ad6265SDimitry Andric       || Str.find_first_not_of(Str[Pos], Pos) == StringRef::npos) {
136381ad6265SDimitry Andric     // If the source array consists of at most two consecutive sequences
136481ad6265SDimitry Andric     // of the same characters, then for any C and N (whether in bounds or
136581ad6265SDimitry Andric     // not), fold memchr(S, C, N) to
136681ad6265SDimitry Andric     //   N != 0 && *S == C ? S : null
136781ad6265SDimitry Andric     // or for the two sequences to:
136881ad6265SDimitry Andric     //   N != 0 && *S == C ? S : (N > Pos && S[Pos] == C ? S + Pos : null)
136981ad6265SDimitry Andric     //   ^Sel2                   ^Sel1 are denoted above.
137081ad6265SDimitry Andric     // The latter makes it also possible to fold strchr() calls with strings
137181ad6265SDimitry Andric     // of the same characters.
137281ad6265SDimitry Andric     Type *SizeTy = Size->getType();
137381ad6265SDimitry Andric     Type *Int8Ty = B.getInt8Ty();
137481ad6265SDimitry Andric 
137581ad6265SDimitry Andric     // Slice off the sought character's high end bits.
137681ad6265SDimitry Andric     CharVal = B.CreateTrunc(CharVal, Int8Ty);
137781ad6265SDimitry Andric 
137881ad6265SDimitry Andric     Value *Sel1 = NullPtr;
137981ad6265SDimitry Andric     if (Pos != StringRef::npos) {
138081ad6265SDimitry Andric       // Handle two consecutive sequences of the same characters.
138181ad6265SDimitry Andric       Value *PosVal = ConstantInt::get(SizeTy, Pos);
138281ad6265SDimitry Andric       Value *StrPos = ConstantInt::get(Int8Ty, Str[Pos]);
138381ad6265SDimitry Andric       Value *CEqSPos = B.CreateICmpEQ(CharVal, StrPos);
138481ad6265SDimitry Andric       Value *NGtPos = B.CreateICmp(ICmpInst::ICMP_UGT, Size, PosVal);
138581ad6265SDimitry Andric       Value *And = B.CreateAnd(CEqSPos, NGtPos);
138681ad6265SDimitry Andric       Value *SrcPlus = B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, PosVal);
138781ad6265SDimitry Andric       Sel1 = B.CreateSelect(And, SrcPlus, NullPtr, "memchr.sel1");
138881ad6265SDimitry Andric     }
138981ad6265SDimitry Andric 
139081ad6265SDimitry Andric     Value *Str0 = ConstantInt::get(Int8Ty, Str[0]);
139181ad6265SDimitry Andric     Value *CEqS0 = B.CreateICmpEQ(Str0, CharVal);
139281ad6265SDimitry Andric     Value *NNeZ = B.CreateICmpNE(Size, ConstantInt::get(SizeTy, 0));
139381ad6265SDimitry Andric     Value *And = B.CreateAnd(NNeZ, CEqS0);
139481ad6265SDimitry Andric     return B.CreateSelect(And, SrcStr, Sel1, "memchr.sel2");
139581ad6265SDimitry Andric   }
139681ad6265SDimitry Andric 
1397753f127fSDimitry Andric   if (!LenC) {
1398753f127fSDimitry Andric     if (isOnlyUsedInEqualityComparison(CI, SrcStr))
1399753f127fSDimitry Andric       // S is dereferenceable so it's safe to load from it and fold
1400753f127fSDimitry Andric       //   memchr(S, C, N) == S to N && *S == C for any C and N.
14015f757f3fSDimitry Andric       // TODO: This is safe even for nonconstant S.
1402753f127fSDimitry Andric       return memChrToCharCompare(CI, Size, B, DL);
1403753f127fSDimitry Andric 
140481ad6265SDimitry Andric     // From now on we need a constant length and constant array.
140581ad6265SDimitry Andric     return nullptr;
1406753f127fSDimitry Andric   }
14070b57cec5SDimitry Andric 
140806c3fb27SDimitry Andric   bool OptForSize = CI->getFunction()->hasOptSize() ||
140906c3fb27SDimitry Andric                     llvm::shouldOptimizeForSize(CI->getParent(), PSI, BFI,
141006c3fb27SDimitry Andric                                                 PGSOQueryType::IRPass);
141106c3fb27SDimitry Andric 
14120b57cec5SDimitry Andric   // If the char is variable but the input str and length are not we can turn
14130b57cec5SDimitry Andric   // this memchr call into a simple bit field test. Of course this only works
14140b57cec5SDimitry Andric   // when the return value is only checked against null.
14150b57cec5SDimitry Andric   //
14160b57cec5SDimitry Andric   // It would be really nice to reuse switch lowering here but we can't change
14170b57cec5SDimitry Andric   // the CFG at this point.
14180b57cec5SDimitry Andric   //
14190b57cec5SDimitry Andric   // memchr("\r\n", C, 2) != nullptr -> (1 << C & ((1 << '\r') | (1 << '\n')))
14200b57cec5SDimitry Andric   // != 0
14210b57cec5SDimitry Andric   //   after bounds check.
142206c3fb27SDimitry Andric   if (OptForSize || Str.empty() || !isOnlyUsedInZeroEqualityComparison(CI))
142381ad6265SDimitry Andric     return nullptr;
142481ad6265SDimitry Andric 
14250b57cec5SDimitry Andric   unsigned char Max =
14260b57cec5SDimitry Andric       *std::max_element(reinterpret_cast<const unsigned char *>(Str.begin()),
14270b57cec5SDimitry Andric                         reinterpret_cast<const unsigned char *>(Str.end()));
14280b57cec5SDimitry Andric 
14290b57cec5SDimitry Andric   // Make sure the bit field we're about to create fits in a register on the
14300b57cec5SDimitry Andric   // target.
14310b57cec5SDimitry Andric   // FIXME: On a 64 bit architecture this prevents us from using the
14320b57cec5SDimitry Andric   // interesting range of alpha ascii chars. We could do better by emitting
14330b57cec5SDimitry Andric   // two bitfields or shifting the range by 64 if no lower chars are used.
143406c3fb27SDimitry Andric   if (!DL.fitsInLegalInteger(Max + 1)) {
143506c3fb27SDimitry Andric     // Build chain of ORs
143606c3fb27SDimitry Andric     // Transform:
143706c3fb27SDimitry Andric     //    memchr("abcd", C, 4) != nullptr
143806c3fb27SDimitry Andric     // to:
143906c3fb27SDimitry Andric     //    (C == 'a' || C == 'b' || C == 'c' || C == 'd') != 0
144006c3fb27SDimitry Andric     std::string SortedStr = Str.str();
144106c3fb27SDimitry Andric     llvm::sort(SortedStr);
144206c3fb27SDimitry Andric     // Compute the number of of non-contiguous ranges.
144306c3fb27SDimitry Andric     unsigned NonContRanges = 1;
144406c3fb27SDimitry Andric     for (size_t i = 1; i < SortedStr.size(); ++i) {
144506c3fb27SDimitry Andric       if (SortedStr[i] > SortedStr[i - 1] + 1) {
144606c3fb27SDimitry Andric         NonContRanges++;
144706c3fb27SDimitry Andric       }
144806c3fb27SDimitry Andric     }
144906c3fb27SDimitry Andric 
145006c3fb27SDimitry Andric     // Restrict this optimization to profitable cases with one or two range
145106c3fb27SDimitry Andric     // checks.
145206c3fb27SDimitry Andric     if (NonContRanges > 2)
14530b57cec5SDimitry Andric       return nullptr;
14540b57cec5SDimitry Andric 
145506c3fb27SDimitry Andric     SmallVector<Value *> CharCompares;
145606c3fb27SDimitry Andric     for (unsigned char C : SortedStr)
145706c3fb27SDimitry Andric       CharCompares.push_back(
145806c3fb27SDimitry Andric           B.CreateICmpEQ(CharVal, ConstantInt::get(CharVal->getType(), C)));
145906c3fb27SDimitry Andric 
146006c3fb27SDimitry Andric     return B.CreateIntToPtr(B.CreateOr(CharCompares), CI->getType());
146106c3fb27SDimitry Andric   }
146206c3fb27SDimitry Andric 
14630b57cec5SDimitry Andric   // For the bit field use a power-of-2 type with at least 8 bits to avoid
14640b57cec5SDimitry Andric   // creating unnecessary illegal types.
14650b57cec5SDimitry Andric   unsigned char Width = NextPowerOf2(std::max((unsigned char)7, Max));
14660b57cec5SDimitry Andric 
14670b57cec5SDimitry Andric   // Now build the bit field.
14680b57cec5SDimitry Andric   APInt Bitfield(Width, 0);
14690b57cec5SDimitry Andric   for (char C : Str)
14700b57cec5SDimitry Andric     Bitfield.setBit((unsigned char)C);
14710b57cec5SDimitry Andric   Value *BitfieldC = B.getInt(Bitfield);
14720b57cec5SDimitry Andric 
14730b57cec5SDimitry Andric   // Adjust width of "C" to the bitfield width, then mask off the high bits.
147481ad6265SDimitry Andric   Value *C = B.CreateZExtOrTrunc(CharVal, BitfieldC->getType());
14750b57cec5SDimitry Andric   C = B.CreateAnd(C, B.getIntN(Width, 0xFF));
14760b57cec5SDimitry Andric 
14770b57cec5SDimitry Andric   // First check that the bit field access is within bounds.
14780b57cec5SDimitry Andric   Value *Bounds = B.CreateICmp(ICmpInst::ICMP_ULT, C, B.getIntN(Width, Width),
14790b57cec5SDimitry Andric                                "memchr.bounds");
14800b57cec5SDimitry Andric 
14810b57cec5SDimitry Andric   // Create code that checks if the given bit is set in the field.
14820b57cec5SDimitry Andric   Value *Shl = B.CreateShl(B.getIntN(Width, 1ULL), C);
14830b57cec5SDimitry Andric   Value *Bits = B.CreateIsNotNull(B.CreateAnd(Shl, BitfieldC), "memchr.bits");
14840b57cec5SDimitry Andric 
14850b57cec5SDimitry Andric   // Finally merge both checks and cast to pointer type. The inttoptr
14860b57cec5SDimitry Andric   // implicitly zexts the i1 to intptr type.
1487fe6060f1SDimitry Andric   return B.CreateIntToPtr(B.CreateLogicalAnd(Bounds, Bits, "memchr"),
1488fe6060f1SDimitry Andric                           CI->getType());
14890b57cec5SDimitry Andric }
14900b57cec5SDimitry Andric 
149181ad6265SDimitry Andric // Optimize a memcmp or, when StrNCmp is true, strncmp call CI with constant
149281ad6265SDimitry Andric // arrays LHS and RHS and nonconstant Size.
149381ad6265SDimitry Andric static Value *optimizeMemCmpVarSize(CallInst *CI, Value *LHS, Value *RHS,
149481ad6265SDimitry Andric                                     Value *Size, bool StrNCmp,
149581ad6265SDimitry Andric                                     IRBuilderBase &B, const DataLayout &DL) {
149681ad6265SDimitry Andric   if (LHS == RHS) // memcmp(s,s,x) -> 0
14970b57cec5SDimitry Andric     return Constant::getNullValue(CI->getType());
14980b57cec5SDimitry Andric 
149981ad6265SDimitry Andric   StringRef LStr, RStr;
1500bdd1243dSDimitry Andric   if (!getConstantStringInfo(LHS, LStr, /*TrimAtNul=*/false) ||
1501bdd1243dSDimitry Andric       !getConstantStringInfo(RHS, RStr, /*TrimAtNul=*/false))
150281ad6265SDimitry Andric     return nullptr;
150381ad6265SDimitry Andric 
150481ad6265SDimitry Andric   // If the contents of both constant arrays are known, fold a call to
150581ad6265SDimitry Andric   // memcmp(A, B, N) to
150681ad6265SDimitry Andric   //   N <= Pos ? 0 : (A < B ? -1 : B < A ? +1 : 0)
150781ad6265SDimitry Andric   // where Pos is the first mismatch between A and B, determined below.
150881ad6265SDimitry Andric 
150981ad6265SDimitry Andric   uint64_t Pos = 0;
151081ad6265SDimitry Andric   Value *Zero = ConstantInt::get(CI->getType(), 0);
151181ad6265SDimitry Andric   for (uint64_t MinSize = std::min(LStr.size(), RStr.size()); ; ++Pos) {
151281ad6265SDimitry Andric     if (Pos == MinSize ||
151381ad6265SDimitry Andric         (StrNCmp && (LStr[Pos] == '\0' && RStr[Pos] == '\0'))) {
151481ad6265SDimitry Andric       // One array is a leading part of the other of equal or greater
151581ad6265SDimitry Andric       // size, or for strncmp, the arrays are equal strings.
151681ad6265SDimitry Andric       // Fold the result to zero.  Size is assumed to be in bounds, since
151781ad6265SDimitry Andric       // otherwise the call would be undefined.
151881ad6265SDimitry Andric       return Zero;
15190b57cec5SDimitry Andric     }
15200b57cec5SDimitry Andric 
152181ad6265SDimitry Andric     if (LStr[Pos] != RStr[Pos])
152281ad6265SDimitry Andric       break;
152381ad6265SDimitry Andric   }
152481ad6265SDimitry Andric 
152581ad6265SDimitry Andric   // Normalize the result.
152681ad6265SDimitry Andric   typedef unsigned char UChar;
152781ad6265SDimitry Andric   int IRes = UChar(LStr[Pos]) < UChar(RStr[Pos]) ? -1 : 1;
152881ad6265SDimitry Andric   Value *MaxSize = ConstantInt::get(Size->getType(), Pos);
152981ad6265SDimitry Andric   Value *Cmp = B.CreateICmp(ICmpInst::ICMP_ULE, Size, MaxSize);
153081ad6265SDimitry Andric   Value *Res = ConstantInt::get(CI->getType(), IRes);
153181ad6265SDimitry Andric   return B.CreateSelect(Cmp, Zero, Res);
153281ad6265SDimitry Andric }
153381ad6265SDimitry Andric 
153481ad6265SDimitry Andric // Optimize a memcmp call CI with constant size Len.
15350b57cec5SDimitry Andric static Value *optimizeMemCmpConstantSize(CallInst *CI, Value *LHS, Value *RHS,
15365ffd83dbSDimitry Andric                                          uint64_t Len, IRBuilderBase &B,
15370b57cec5SDimitry Andric                                          const DataLayout &DL) {
15380b57cec5SDimitry Andric   if (Len == 0) // memcmp(s1,s2,0) -> 0
15390b57cec5SDimitry Andric     return Constant::getNullValue(CI->getType());
15400b57cec5SDimitry Andric 
15410b57cec5SDimitry Andric   // memcmp(S1,S2,1) -> *(unsigned char*)LHS - *(unsigned char*)RHS
15420b57cec5SDimitry Andric   if (Len == 1) {
15435f757f3fSDimitry Andric     Value *LHSV = B.CreateZExt(B.CreateLoad(B.getInt8Ty(), LHS, "lhsc"),
15440b57cec5SDimitry Andric                                CI->getType(), "lhsv");
15455f757f3fSDimitry Andric     Value *RHSV = B.CreateZExt(B.CreateLoad(B.getInt8Ty(), RHS, "rhsc"),
15460b57cec5SDimitry Andric                                CI->getType(), "rhsv");
15470b57cec5SDimitry Andric     return B.CreateSub(LHSV, RHSV, "chardiff");
15480b57cec5SDimitry Andric   }
15490b57cec5SDimitry Andric 
15500b57cec5SDimitry Andric   // memcmp(S1,S2,N/8)==0 -> (*(intN_t*)S1 != *(intN_t*)S2)==0
15510b57cec5SDimitry Andric   // TODO: The case where both inputs are constants does not need to be limited
15520b57cec5SDimitry Andric   // to legal integers or equality comparison. See block below this.
15530b57cec5SDimitry Andric   if (DL.isLegalInteger(Len * 8) && isOnlyUsedInZeroEqualityComparison(CI)) {
15540b57cec5SDimitry Andric     IntegerType *IntType = IntegerType::get(CI->getContext(), Len * 8);
1555bdd1243dSDimitry Andric     Align PrefAlignment = DL.getPrefTypeAlign(IntType);
15560b57cec5SDimitry Andric 
15570b57cec5SDimitry Andric     // First, see if we can fold either argument to a constant.
15580b57cec5SDimitry Andric     Value *LHSV = nullptr;
155906c3fb27SDimitry Andric     if (auto *LHSC = dyn_cast<Constant>(LHS))
15600b57cec5SDimitry Andric       LHSV = ConstantFoldLoadFromConstPtr(LHSC, IntType, DL);
156106c3fb27SDimitry Andric 
15620b57cec5SDimitry Andric     Value *RHSV = nullptr;
156306c3fb27SDimitry Andric     if (auto *RHSC = dyn_cast<Constant>(RHS))
15640b57cec5SDimitry Andric       RHSV = ConstantFoldLoadFromConstPtr(RHSC, IntType, DL);
15650b57cec5SDimitry Andric 
15660b57cec5SDimitry Andric     // Don't generate unaligned loads. If either source is constant data,
15670b57cec5SDimitry Andric     // alignment doesn't matter for that source because there is no load.
15680b57cec5SDimitry Andric     if ((LHSV || getKnownAlignment(LHS, DL, CI) >= PrefAlignment) &&
15690b57cec5SDimitry Andric         (RHSV || getKnownAlignment(RHS, DL, CI) >= PrefAlignment)) {
157006c3fb27SDimitry Andric       if (!LHSV)
157106c3fb27SDimitry Andric         LHSV = B.CreateLoad(IntType, LHS, "lhsv");
157206c3fb27SDimitry Andric       if (!RHSV)
157306c3fb27SDimitry Andric         RHSV = B.CreateLoad(IntType, RHS, "rhsv");
15740b57cec5SDimitry Andric       return B.CreateZExt(B.CreateICmpNE(LHSV, RHSV), CI->getType(), "memcmp");
15750b57cec5SDimitry Andric     }
15760b57cec5SDimitry Andric   }
15770b57cec5SDimitry Andric 
15780b57cec5SDimitry Andric   return nullptr;
15790b57cec5SDimitry Andric }
15800b57cec5SDimitry Andric 
15810b57cec5SDimitry Andric // Most simplifications for memcmp also apply to bcmp.
15820b57cec5SDimitry Andric Value *LibCallSimplifier::optimizeMemCmpBCmpCommon(CallInst *CI,
15835ffd83dbSDimitry Andric                                                    IRBuilderBase &B) {
15840b57cec5SDimitry Andric   Value *LHS = CI->getArgOperand(0), *RHS = CI->getArgOperand(1);
15850b57cec5SDimitry Andric   Value *Size = CI->getArgOperand(2);
15860b57cec5SDimitry Andric 
15878bcb0991SDimitry Andric   annotateNonNullAndDereferenceable(CI, {0, 1}, Size, DL);
158881ad6265SDimitry Andric 
158981ad6265SDimitry Andric   if (Value *Res = optimizeMemCmpVarSize(CI, LHS, RHS, Size, false, B, DL))
159081ad6265SDimitry Andric     return Res;
159181ad6265SDimitry Andric 
159281ad6265SDimitry Andric   // Handle constant Size.
15938bcb0991SDimitry Andric   ConstantInt *LenC = dyn_cast<ConstantInt>(Size);
15948bcb0991SDimitry Andric   if (!LenC)
15958bcb0991SDimitry Andric     return nullptr;
15960b57cec5SDimitry Andric 
159781ad6265SDimitry Andric   return optimizeMemCmpConstantSize(CI, LHS, RHS, LenC->getZExtValue(), B, DL);
15980b57cec5SDimitry Andric }
15990b57cec5SDimitry Andric 
16005ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeMemCmp(CallInst *CI, IRBuilderBase &B) {
160181ad6265SDimitry Andric   Module *M = CI->getModule();
16020b57cec5SDimitry Andric   if (Value *V = optimizeMemCmpBCmpCommon(CI, B))
16030b57cec5SDimitry Andric     return V;
16040b57cec5SDimitry Andric 
16050b57cec5SDimitry Andric   // memcmp(x, y, Len) == 0 -> bcmp(x, y, Len) == 0
16068bcb0991SDimitry Andric   // bcmp can be more efficient than memcmp because it only has to know that
16078bcb0991SDimitry Andric   // there is a difference, not how different one is to the other.
160881ad6265SDimitry Andric   if (isLibFuncEmittable(M, TLI, LibFunc_bcmp) &&
160981ad6265SDimitry Andric       isOnlyUsedInZeroEqualityComparison(CI)) {
16100b57cec5SDimitry Andric     Value *LHS = CI->getArgOperand(0);
16110b57cec5SDimitry Andric     Value *RHS = CI->getArgOperand(1);
16120b57cec5SDimitry Andric     Value *Size = CI->getArgOperand(2);
16130eae32dcSDimitry Andric     return copyFlags(*CI, emitBCmp(LHS, RHS, Size, B, DL, TLI));
16140b57cec5SDimitry Andric   }
16150b57cec5SDimitry Andric 
16160b57cec5SDimitry Andric   return nullptr;
16170b57cec5SDimitry Andric }
16180b57cec5SDimitry Andric 
16195ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeBCmp(CallInst *CI, IRBuilderBase &B) {
16200b57cec5SDimitry Andric   return optimizeMemCmpBCmpCommon(CI, B);
16210b57cec5SDimitry Andric }
16220b57cec5SDimitry Andric 
16235ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilderBase &B) {
16248bcb0991SDimitry Andric   Value *Size = CI->getArgOperand(2);
16258bcb0991SDimitry Andric   annotateNonNullAndDereferenceable(CI, {0, 1}, Size, DL);
16268bcb0991SDimitry Andric   if (isa<IntrinsicInst>(CI))
16278bcb0991SDimitry Andric     return nullptr;
16288bcb0991SDimitry Andric 
16290b57cec5SDimitry Andric   // memcpy(x, y, n) -> llvm.memcpy(align 1 x, align 1 y, n)
16305ffd83dbSDimitry Andric   CallInst *NewCI = B.CreateMemCpy(CI->getArgOperand(0), Align(1),
16315ffd83dbSDimitry Andric                                    CI->getArgOperand(1), Align(1), Size);
1632bdd1243dSDimitry Andric   mergeAttributesAndFlags(NewCI, *CI);
16330b57cec5SDimitry Andric   return CI->getArgOperand(0);
16340b57cec5SDimitry Andric }
16350b57cec5SDimitry Andric 
16365ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeMemCCpy(CallInst *CI, IRBuilderBase &B) {
1637480093f4SDimitry Andric   Value *Dst = CI->getArgOperand(0);
1638480093f4SDimitry Andric   Value *Src = CI->getArgOperand(1);
1639480093f4SDimitry Andric   ConstantInt *StopChar = dyn_cast<ConstantInt>(CI->getArgOperand(2));
1640480093f4SDimitry Andric   ConstantInt *N = dyn_cast<ConstantInt>(CI->getArgOperand(3));
1641480093f4SDimitry Andric   StringRef SrcStr;
1642480093f4SDimitry Andric   if (CI->use_empty() && Dst == Src)
1643480093f4SDimitry Andric     return Dst;
1644480093f4SDimitry Andric   // memccpy(d, s, c, 0) -> nullptr
1645480093f4SDimitry Andric   if (N) {
1646480093f4SDimitry Andric     if (N->isNullValue())
1647480093f4SDimitry Andric       return Constant::getNullValue(CI->getType());
1648bdd1243dSDimitry Andric     if (!getConstantStringInfo(Src, SrcStr, /*TrimAtNul=*/false) ||
164981ad6265SDimitry Andric         // TODO: Handle zeroinitializer.
1650480093f4SDimitry Andric         !StopChar)
1651480093f4SDimitry Andric       return nullptr;
1652480093f4SDimitry Andric   } else {
1653480093f4SDimitry Andric     return nullptr;
1654480093f4SDimitry Andric   }
1655480093f4SDimitry Andric 
1656480093f4SDimitry Andric   // Wrap arg 'c' of type int to char
1657480093f4SDimitry Andric   size_t Pos = SrcStr.find(StopChar->getSExtValue() & 0xFF);
1658480093f4SDimitry Andric   if (Pos == StringRef::npos) {
1659480093f4SDimitry Andric     if (N->getZExtValue() <= SrcStr.size()) {
16600eae32dcSDimitry Andric       copyFlags(*CI, B.CreateMemCpy(Dst, Align(1), Src, Align(1),
16610eae32dcSDimitry Andric                                     CI->getArgOperand(3)));
1662480093f4SDimitry Andric       return Constant::getNullValue(CI->getType());
1663480093f4SDimitry Andric     }
1664480093f4SDimitry Andric     return nullptr;
1665480093f4SDimitry Andric   }
1666480093f4SDimitry Andric 
1667480093f4SDimitry Andric   Value *NewN =
1668480093f4SDimitry Andric       ConstantInt::get(N->getType(), std::min(uint64_t(Pos + 1), N->getZExtValue()));
1669480093f4SDimitry Andric   // memccpy -> llvm.memcpy
16700eae32dcSDimitry Andric   copyFlags(*CI, B.CreateMemCpy(Dst, Align(1), Src, Align(1), NewN));
1671480093f4SDimitry Andric   return Pos + 1 <= N->getZExtValue()
1672480093f4SDimitry Andric              ? B.CreateInBoundsGEP(B.getInt8Ty(), Dst, NewN)
1673480093f4SDimitry Andric              : Constant::getNullValue(CI->getType());
1674480093f4SDimitry Andric }
1675480093f4SDimitry Andric 
16765ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeMemPCpy(CallInst *CI, IRBuilderBase &B) {
16778bcb0991SDimitry Andric   Value *Dst = CI->getArgOperand(0);
16788bcb0991SDimitry Andric   Value *N = CI->getArgOperand(2);
16798bcb0991SDimitry Andric   // mempcpy(x, y, n) -> llvm.memcpy(align 1 x, align 1 y, n), x + n
16805ffd83dbSDimitry Andric   CallInst *NewCI =
16815ffd83dbSDimitry Andric       B.CreateMemCpy(Dst, Align(1), CI->getArgOperand(1), Align(1), N);
1682e8d8bef9SDimitry Andric   // Propagate attributes, but memcpy has no return value, so make sure that
1683e8d8bef9SDimitry Andric   // any return attributes are compliant.
1684e8d8bef9SDimitry Andric   // TODO: Attach return value attributes to the 1st operand to preserve them?
1685bdd1243dSDimitry Andric   mergeAttributesAndFlags(NewCI, *CI);
16868bcb0991SDimitry Andric   return B.CreateInBoundsGEP(B.getInt8Ty(), Dst, N);
16878bcb0991SDimitry Andric }
16888bcb0991SDimitry Andric 
16895ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilderBase &B) {
16908bcb0991SDimitry Andric   Value *Size = CI->getArgOperand(2);
16918bcb0991SDimitry Andric   annotateNonNullAndDereferenceable(CI, {0, 1}, Size, DL);
16928bcb0991SDimitry Andric   if (isa<IntrinsicInst>(CI))
16938bcb0991SDimitry Andric     return nullptr;
16948bcb0991SDimitry Andric 
16950b57cec5SDimitry Andric   // memmove(x, y, n) -> llvm.memmove(align 1 x, align 1 y, n)
16965ffd83dbSDimitry Andric   CallInst *NewCI = B.CreateMemMove(CI->getArgOperand(0), Align(1),
16975ffd83dbSDimitry Andric                                     CI->getArgOperand(1), Align(1), Size);
1698bdd1243dSDimitry Andric   mergeAttributesAndFlags(NewCI, *CI);
16990b57cec5SDimitry Andric   return CI->getArgOperand(0);
17000b57cec5SDimitry Andric }
17010b57cec5SDimitry Andric 
17025ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilderBase &B) {
17038bcb0991SDimitry Andric   Value *Size = CI->getArgOperand(2);
17048bcb0991SDimitry Andric   annotateNonNullAndDereferenceable(CI, 0, Size, DL);
17058bcb0991SDimitry Andric   if (isa<IntrinsicInst>(CI))
17068bcb0991SDimitry Andric     return nullptr;
17078bcb0991SDimitry Andric 
17080b57cec5SDimitry Andric   // memset(p, v, n) -> llvm.memset(align 1 p, v, n)
17090b57cec5SDimitry Andric   Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(), false);
17105ffd83dbSDimitry Andric   CallInst *NewCI = B.CreateMemSet(CI->getArgOperand(0), Val, Size, Align(1));
1711bdd1243dSDimitry Andric   mergeAttributesAndFlags(NewCI, *CI);
17120b57cec5SDimitry Andric   return CI->getArgOperand(0);
17130b57cec5SDimitry Andric }
17140b57cec5SDimitry Andric 
17155ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeRealloc(CallInst *CI, IRBuilderBase &B) {
17160b57cec5SDimitry Andric   if (isa<ConstantPointerNull>(CI->getArgOperand(0)))
17170eae32dcSDimitry Andric     return copyFlags(*CI, emitMalloc(CI->getArgOperand(1), B, DL, TLI));
17180b57cec5SDimitry Andric 
17190b57cec5SDimitry Andric   return nullptr;
17200b57cec5SDimitry Andric }
17210b57cec5SDimitry Andric 
172206c3fb27SDimitry Andric // When enabled, replace operator new() calls marked with a hot or cold memprof
172306c3fb27SDimitry Andric // attribute with an operator new() call that takes a __hot_cold_t parameter.
172406c3fb27SDimitry Andric // Currently this is supported by the open source version of tcmalloc, see:
172506c3fb27SDimitry Andric // https://github.com/google/tcmalloc/blob/master/tcmalloc/new_extension.h
172606c3fb27SDimitry Andric Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
172706c3fb27SDimitry Andric                                       LibFunc &Func) {
172806c3fb27SDimitry Andric   if (!OptimizeHotColdNew)
172906c3fb27SDimitry Andric     return nullptr;
173006c3fb27SDimitry Andric 
173106c3fb27SDimitry Andric   uint8_t HotCold;
173206c3fb27SDimitry Andric   if (CI->getAttributes().getFnAttr("memprof").getValueAsString() == "cold")
173306c3fb27SDimitry Andric     HotCold = ColdNewHintValue;
1734*0fca6ea1SDimitry Andric   else if (CI->getAttributes().getFnAttr("memprof").getValueAsString() ==
1735*0fca6ea1SDimitry Andric            "notcold")
1736*0fca6ea1SDimitry Andric     HotCold = NotColdNewHintValue;
173706c3fb27SDimitry Andric   else if (CI->getAttributes().getFnAttr("memprof").getValueAsString() == "hot")
173806c3fb27SDimitry Andric     HotCold = HotNewHintValue;
173906c3fb27SDimitry Andric   else
174006c3fb27SDimitry Andric     return nullptr;
174106c3fb27SDimitry Andric 
1742*0fca6ea1SDimitry Andric   // For calls that already pass a hot/cold hint, only update the hint if
1743*0fca6ea1SDimitry Andric   // directed by OptimizeExistingHotColdNew. For other calls to new, add a hint
1744*0fca6ea1SDimitry Andric   // if cold or hot, and leave as-is for default handling if "notcold" aka warm.
1745*0fca6ea1SDimitry Andric   // Note that in cases where we decide it is "notcold", it might be slightly
1746*0fca6ea1SDimitry Andric   // better to replace the hinted call with a non hinted call, to avoid the
1747*0fca6ea1SDimitry Andric   // extra paramter and the if condition check of the hint value in the
1748*0fca6ea1SDimitry Andric   // allocator. This can be considered in the future.
174906c3fb27SDimitry Andric   switch (Func) {
1750*0fca6ea1SDimitry Andric   case LibFunc_Znwm12__hot_cold_t:
1751*0fca6ea1SDimitry Andric     if (OptimizeExistingHotColdNew)
175206c3fb27SDimitry Andric       return emitHotColdNew(CI->getArgOperand(0), B, TLI,
175306c3fb27SDimitry Andric                             LibFunc_Znwm12__hot_cold_t, HotCold);
1754*0fca6ea1SDimitry Andric     break;
1755*0fca6ea1SDimitry Andric   case LibFunc_Znwm:
1756*0fca6ea1SDimitry Andric     if (HotCold != NotColdNewHintValue)
1757*0fca6ea1SDimitry Andric       return emitHotColdNew(CI->getArgOperand(0), B, TLI,
1758*0fca6ea1SDimitry Andric                             LibFunc_Znwm12__hot_cold_t, HotCold);
1759*0fca6ea1SDimitry Andric     break;
1760*0fca6ea1SDimitry Andric   case LibFunc_Znam12__hot_cold_t:
1761*0fca6ea1SDimitry Andric     if (OptimizeExistingHotColdNew)
176206c3fb27SDimitry Andric       return emitHotColdNew(CI->getArgOperand(0), B, TLI,
176306c3fb27SDimitry Andric                             LibFunc_Znam12__hot_cold_t, HotCold);
1764*0fca6ea1SDimitry Andric     break;
1765*0fca6ea1SDimitry Andric   case LibFunc_Znam:
1766*0fca6ea1SDimitry Andric     if (HotCold != NotColdNewHintValue)
1767*0fca6ea1SDimitry Andric       return emitHotColdNew(CI->getArgOperand(0), B, TLI,
1768*0fca6ea1SDimitry Andric                             LibFunc_Znam12__hot_cold_t, HotCold);
1769*0fca6ea1SDimitry Andric     break;
1770*0fca6ea1SDimitry Andric   case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:
1771*0fca6ea1SDimitry Andric     if (OptimizeExistingHotColdNew)
1772*0fca6ea1SDimitry Andric       return emitHotColdNewNoThrow(
1773*0fca6ea1SDimitry Andric           CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
1774*0fca6ea1SDimitry Andric           LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotCold);
1775*0fca6ea1SDimitry Andric     break;
177606c3fb27SDimitry Andric   case LibFunc_ZnwmRKSt9nothrow_t:
1777*0fca6ea1SDimitry Andric     if (HotCold != NotColdNewHintValue)
1778*0fca6ea1SDimitry Andric       return emitHotColdNewNoThrow(
1779*0fca6ea1SDimitry Andric           CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
1780*0fca6ea1SDimitry Andric           LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotCold);
1781*0fca6ea1SDimitry Andric     break;
1782*0fca6ea1SDimitry Andric   case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:
1783*0fca6ea1SDimitry Andric     if (OptimizeExistingHotColdNew)
1784*0fca6ea1SDimitry Andric       return emitHotColdNewNoThrow(
1785*0fca6ea1SDimitry Andric           CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
1786*0fca6ea1SDimitry Andric           LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotCold);
1787*0fca6ea1SDimitry Andric     break;
178806c3fb27SDimitry Andric   case LibFunc_ZnamRKSt9nothrow_t:
1789*0fca6ea1SDimitry Andric     if (HotCold != NotColdNewHintValue)
1790*0fca6ea1SDimitry Andric       return emitHotColdNewNoThrow(
1791*0fca6ea1SDimitry Andric           CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
1792*0fca6ea1SDimitry Andric           LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotCold);
1793*0fca6ea1SDimitry Andric     break;
1794*0fca6ea1SDimitry Andric   case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:
1795*0fca6ea1SDimitry Andric     if (OptimizeExistingHotColdNew)
1796*0fca6ea1SDimitry Andric       return emitHotColdNewAligned(
1797*0fca6ea1SDimitry Andric           CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
1798*0fca6ea1SDimitry Andric           LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotCold);
1799*0fca6ea1SDimitry Andric     break;
180006c3fb27SDimitry Andric   case LibFunc_ZnwmSt11align_val_t:
1801*0fca6ea1SDimitry Andric     if (HotCold != NotColdNewHintValue)
1802*0fca6ea1SDimitry Andric       return emitHotColdNewAligned(
1803*0fca6ea1SDimitry Andric           CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
1804*0fca6ea1SDimitry Andric           LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotCold);
1805*0fca6ea1SDimitry Andric     break;
1806*0fca6ea1SDimitry Andric   case LibFunc_ZnamSt11align_val_t12__hot_cold_t:
1807*0fca6ea1SDimitry Andric     if (OptimizeExistingHotColdNew)
1808*0fca6ea1SDimitry Andric       return emitHotColdNewAligned(
1809*0fca6ea1SDimitry Andric           CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
1810*0fca6ea1SDimitry Andric           LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotCold);
1811*0fca6ea1SDimitry Andric     break;
181206c3fb27SDimitry Andric   case LibFunc_ZnamSt11align_val_t:
1813*0fca6ea1SDimitry Andric     if (HotCold != NotColdNewHintValue)
1814*0fca6ea1SDimitry Andric       return emitHotColdNewAligned(
1815*0fca6ea1SDimitry Andric           CI->getArgOperand(0), CI->getArgOperand(1), B, TLI,
1816*0fca6ea1SDimitry Andric           LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotCold);
1817*0fca6ea1SDimitry Andric     break;
1818*0fca6ea1SDimitry Andric   case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
1819*0fca6ea1SDimitry Andric     if (OptimizeExistingHotColdNew)
1820*0fca6ea1SDimitry Andric       return emitHotColdNewAlignedNoThrow(
1821*0fca6ea1SDimitry Andric           CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B,
1822*0fca6ea1SDimitry Andric           TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
182306c3fb27SDimitry Andric           HotCold);
1824*0fca6ea1SDimitry Andric     break;
182506c3fb27SDimitry Andric   case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t:
1826*0fca6ea1SDimitry Andric     if (HotCold != NotColdNewHintValue)
182706c3fb27SDimitry Andric       return emitHotColdNewAlignedNoThrow(
182806c3fb27SDimitry Andric           CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B,
1829*0fca6ea1SDimitry Andric           TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
1830*0fca6ea1SDimitry Andric           HotCold);
1831*0fca6ea1SDimitry Andric     break;
1832*0fca6ea1SDimitry Andric   case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
1833*0fca6ea1SDimitry Andric     if (OptimizeExistingHotColdNew)
1834*0fca6ea1SDimitry Andric       return emitHotColdNewAlignedNoThrow(
1835*0fca6ea1SDimitry Andric           CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B,
1836*0fca6ea1SDimitry Andric           TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
1837*0fca6ea1SDimitry Andric           HotCold);
1838*0fca6ea1SDimitry Andric     break;
183906c3fb27SDimitry Andric   case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t:
1840*0fca6ea1SDimitry Andric     if (HotCold != NotColdNewHintValue)
184106c3fb27SDimitry Andric       return emitHotColdNewAlignedNoThrow(
184206c3fb27SDimitry Andric           CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B,
1843*0fca6ea1SDimitry Andric           TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
1844*0fca6ea1SDimitry Andric           HotCold);
1845*0fca6ea1SDimitry Andric     break;
184606c3fb27SDimitry Andric   default:
184706c3fb27SDimitry Andric     return nullptr;
184806c3fb27SDimitry Andric   }
1849*0fca6ea1SDimitry Andric   return nullptr;
185006c3fb27SDimitry Andric }
185106c3fb27SDimitry Andric 
18520b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
18530b57cec5SDimitry Andric // Math Library Optimizations
18540b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
18550b57cec5SDimitry Andric 
18560b57cec5SDimitry Andric // Replace a libcall \p CI with a call to intrinsic \p IID
18575ffd83dbSDimitry Andric static Value *replaceUnaryCall(CallInst *CI, IRBuilderBase &B,
18585ffd83dbSDimitry Andric                                Intrinsic::ID IID) {
1859*0fca6ea1SDimitry Andric   CallInst *NewCall = B.CreateUnaryIntrinsic(IID, CI->getArgOperand(0), CI);
18600b57cec5SDimitry Andric   NewCall->takeName(CI);
18610eae32dcSDimitry Andric   return copyFlags(*CI, NewCall);
18620b57cec5SDimitry Andric }
18630b57cec5SDimitry Andric 
18640b57cec5SDimitry Andric /// Return a variant of Val with float type.
18650b57cec5SDimitry Andric /// Currently this works in two cases: If Val is an FPExtension of a float
18660b57cec5SDimitry Andric /// value to something bigger, simply return the operand.
18670b57cec5SDimitry Andric /// If Val is a ConstantFP but can be converted to a float ConstantFP without
18680b57cec5SDimitry Andric /// loss of precision do so.
18690b57cec5SDimitry Andric static Value *valueHasFloatPrecision(Value *Val) {
18700b57cec5SDimitry Andric   if (FPExtInst *Cast = dyn_cast<FPExtInst>(Val)) {
18710b57cec5SDimitry Andric     Value *Op = Cast->getOperand(0);
18720b57cec5SDimitry Andric     if (Op->getType()->isFloatTy())
18730b57cec5SDimitry Andric       return Op;
18740b57cec5SDimitry Andric   }
18750b57cec5SDimitry Andric   if (ConstantFP *Const = dyn_cast<ConstantFP>(Val)) {
18760b57cec5SDimitry Andric     APFloat F = Const->getValueAPF();
18770b57cec5SDimitry Andric     bool losesInfo;
18780b57cec5SDimitry Andric     (void)F.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven,
18790b57cec5SDimitry Andric                     &losesInfo);
18800b57cec5SDimitry Andric     if (!losesInfo)
18810b57cec5SDimitry Andric       return ConstantFP::get(Const->getContext(), F);
18820b57cec5SDimitry Andric   }
18830b57cec5SDimitry Andric   return nullptr;
18840b57cec5SDimitry Andric }
18850b57cec5SDimitry Andric 
18860b57cec5SDimitry Andric /// Shrink double -> float functions.
18875ffd83dbSDimitry Andric static Value *optimizeDoubleFP(CallInst *CI, IRBuilderBase &B,
188881ad6265SDimitry Andric                                bool isBinary, const TargetLibraryInfo *TLI,
188981ad6265SDimitry Andric                                bool isPrecise = false) {
18900b57cec5SDimitry Andric   Function *CalleeFn = CI->getCalledFunction();
18910b57cec5SDimitry Andric   if (!CI->getType()->isDoubleTy() || !CalleeFn)
18920b57cec5SDimitry Andric     return nullptr;
18930b57cec5SDimitry Andric 
18940b57cec5SDimitry Andric   // If not all the uses of the function are converted to float, then bail out.
18950b57cec5SDimitry Andric   // This matters if the precision of the result is more important than the
18960b57cec5SDimitry Andric   // precision of the arguments.
18970b57cec5SDimitry Andric   if (isPrecise)
18980b57cec5SDimitry Andric     for (User *U : CI->users()) {
18990b57cec5SDimitry Andric       FPTruncInst *Cast = dyn_cast<FPTruncInst>(U);
19000b57cec5SDimitry Andric       if (!Cast || !Cast->getType()->isFloatTy())
19010b57cec5SDimitry Andric         return nullptr;
19020b57cec5SDimitry Andric     }
19030b57cec5SDimitry Andric 
19040b57cec5SDimitry Andric   // If this is something like 'g((double) float)', convert to 'gf(float)'.
19050b57cec5SDimitry Andric   Value *V[2];
19060b57cec5SDimitry Andric   V[0] = valueHasFloatPrecision(CI->getArgOperand(0));
19070b57cec5SDimitry Andric   V[1] = isBinary ? valueHasFloatPrecision(CI->getArgOperand(1)) : nullptr;
19080b57cec5SDimitry Andric   if (!V[0] || (isBinary && !V[1]))
19090b57cec5SDimitry Andric     return nullptr;
19100b57cec5SDimitry Andric 
19110b57cec5SDimitry Andric   // If call isn't an intrinsic, check that it isn't within a function with the
19120b57cec5SDimitry Andric   // same name as the float version of this call, otherwise the result is an
19130b57cec5SDimitry Andric   // infinite loop.  For example, from MinGW-w64:
19140b57cec5SDimitry Andric   //
19150b57cec5SDimitry Andric   // float expf(float val) { return (float) exp((double) val); }
19168bcb0991SDimitry Andric   StringRef CalleeName = CalleeFn->getName();
19178bcb0991SDimitry Andric   bool IsIntrinsic = CalleeFn->isIntrinsic();
19188bcb0991SDimitry Andric   if (!IsIntrinsic) {
19198bcb0991SDimitry Andric     StringRef CallerName = CI->getFunction()->getName();
19208bcb0991SDimitry Andric     if (!CallerName.empty() && CallerName.back() == 'f' &&
19218bcb0991SDimitry Andric         CallerName.size() == (CalleeName.size() + 1) &&
19225f757f3fSDimitry Andric         CallerName.starts_with(CalleeName))
19230b57cec5SDimitry Andric       return nullptr;
19240b57cec5SDimitry Andric   }
19250b57cec5SDimitry Andric 
19260b57cec5SDimitry Andric   // Propagate the math semantics from the current function to the new function.
19275ffd83dbSDimitry Andric   IRBuilderBase::FastMathFlagGuard Guard(B);
19280b57cec5SDimitry Andric   B.setFastMathFlags(CI->getFastMathFlags());
19290b57cec5SDimitry Andric 
19300b57cec5SDimitry Andric   // g((double) float) -> (double) gf(float)
19310b57cec5SDimitry Andric   Value *R;
19328bcb0991SDimitry Andric   if (IsIntrinsic) {
19330b57cec5SDimitry Andric     Module *M = CI->getModule();
19340b57cec5SDimitry Andric     Intrinsic::ID IID = CalleeFn->getIntrinsicID();
19350b57cec5SDimitry Andric     Function *Fn = Intrinsic::getDeclaration(M, IID, B.getFloatTy());
19360b57cec5SDimitry Andric     R = isBinary ? B.CreateCall(Fn, V) : B.CreateCall(Fn, V[0]);
19378bcb0991SDimitry Andric   } else {
19388bcb0991SDimitry Andric     AttributeList CalleeAttrs = CalleeFn->getAttributes();
193981ad6265SDimitry Andric     R = isBinary ? emitBinaryFloatFnCall(V[0], V[1], TLI, CalleeName, B,
194081ad6265SDimitry Andric                                          CalleeAttrs)
194181ad6265SDimitry Andric                  : emitUnaryFloatFnCall(V[0], TLI, CalleeName, B, CalleeAttrs);
19420b57cec5SDimitry Andric   }
19430b57cec5SDimitry Andric   return B.CreateFPExt(R, B.getDoubleTy());
19440b57cec5SDimitry Andric }
19450b57cec5SDimitry Andric 
19460b57cec5SDimitry Andric /// Shrink double -> float for unary functions.
19475ffd83dbSDimitry Andric static Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilderBase &B,
194881ad6265SDimitry Andric                                     const TargetLibraryInfo *TLI,
19490b57cec5SDimitry Andric                                     bool isPrecise = false) {
195081ad6265SDimitry Andric   return optimizeDoubleFP(CI, B, false, TLI, isPrecise);
19510b57cec5SDimitry Andric }
19520b57cec5SDimitry Andric 
19530b57cec5SDimitry Andric /// Shrink double -> float for binary functions.
19545ffd83dbSDimitry Andric static Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilderBase &B,
195581ad6265SDimitry Andric                                      const TargetLibraryInfo *TLI,
19560b57cec5SDimitry Andric                                      bool isPrecise = false) {
195781ad6265SDimitry Andric   return optimizeDoubleFP(CI, B, true, TLI, isPrecise);
19580b57cec5SDimitry Andric }
19590b57cec5SDimitry Andric 
19600b57cec5SDimitry Andric // cabs(z) -> sqrt((creal(z)*creal(z)) + (cimag(z)*cimag(z)))
19615ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeCAbs(CallInst *CI, IRBuilderBase &B) {
1962*0fca6ea1SDimitry Andric   Value *Real, *Imag;
1963*0fca6ea1SDimitry Andric 
1964*0fca6ea1SDimitry Andric   if (CI->arg_size() == 1) {
1965*0fca6ea1SDimitry Andric 
19660b57cec5SDimitry Andric     if (!CI->isFast())
19670b57cec5SDimitry Andric       return nullptr;
19680b57cec5SDimitry Andric 
1969*0fca6ea1SDimitry Andric     Value *Op = CI->getArgOperand(0);
1970*0fca6ea1SDimitry Andric     assert(Op->getType()->isArrayTy() && "Unexpected signature for cabs!");
1971*0fca6ea1SDimitry Andric 
1972*0fca6ea1SDimitry Andric     Real = B.CreateExtractValue(Op, 0, "real");
1973*0fca6ea1SDimitry Andric     Imag = B.CreateExtractValue(Op, 1, "imag");
1974*0fca6ea1SDimitry Andric 
1975*0fca6ea1SDimitry Andric   } else {
1976*0fca6ea1SDimitry Andric     assert(CI->arg_size() == 2 && "Unexpected signature for cabs!");
1977*0fca6ea1SDimitry Andric 
1978*0fca6ea1SDimitry Andric     Real = CI->getArgOperand(0);
1979*0fca6ea1SDimitry Andric     Imag = CI->getArgOperand(1);
1980*0fca6ea1SDimitry Andric 
1981*0fca6ea1SDimitry Andric     // if real or imaginary part is zero, simplify to abs(cimag(z))
1982*0fca6ea1SDimitry Andric     // or abs(creal(z))
1983*0fca6ea1SDimitry Andric     Value *AbsOp = nullptr;
1984*0fca6ea1SDimitry Andric     if (ConstantFP *ConstReal = dyn_cast<ConstantFP>(Real)) {
1985*0fca6ea1SDimitry Andric       if (ConstReal->isZero())
1986*0fca6ea1SDimitry Andric         AbsOp = Imag;
1987*0fca6ea1SDimitry Andric 
1988*0fca6ea1SDimitry Andric     } else if (ConstantFP *ConstImag = dyn_cast<ConstantFP>(Imag)) {
1989*0fca6ea1SDimitry Andric       if (ConstImag->isZero())
1990*0fca6ea1SDimitry Andric         AbsOp = Real;
1991*0fca6ea1SDimitry Andric     }
1992*0fca6ea1SDimitry Andric 
1993*0fca6ea1SDimitry Andric     if (AbsOp) {
1994*0fca6ea1SDimitry Andric       IRBuilderBase::FastMathFlagGuard Guard(B);
1995*0fca6ea1SDimitry Andric       B.setFastMathFlags(CI->getFastMathFlags());
1996*0fca6ea1SDimitry Andric 
1997*0fca6ea1SDimitry Andric       return copyFlags(
1998*0fca6ea1SDimitry Andric           *CI, B.CreateUnaryIntrinsic(Intrinsic::fabs, AbsOp, nullptr, "cabs"));
1999*0fca6ea1SDimitry Andric     }
2000*0fca6ea1SDimitry Andric 
2001*0fca6ea1SDimitry Andric     if (!CI->isFast())
2002*0fca6ea1SDimitry Andric       return nullptr;
2003*0fca6ea1SDimitry Andric   }
2004*0fca6ea1SDimitry Andric 
20050b57cec5SDimitry Andric   // Propagate fast-math flags from the existing call to new instructions.
20065ffd83dbSDimitry Andric   IRBuilderBase::FastMathFlagGuard Guard(B);
20070b57cec5SDimitry Andric   B.setFastMathFlags(CI->getFastMathFlags());
20080b57cec5SDimitry Andric 
20090b57cec5SDimitry Andric   Value *RealReal = B.CreateFMul(Real, Real);
20100b57cec5SDimitry Andric   Value *ImagImag = B.CreateFMul(Imag, Imag);
20110b57cec5SDimitry Andric 
2012*0fca6ea1SDimitry Andric   return copyFlags(*CI, B.CreateUnaryIntrinsic(Intrinsic::sqrt,
2013*0fca6ea1SDimitry Andric                                                B.CreateFAdd(RealReal, ImagImag),
2014*0fca6ea1SDimitry Andric                                                nullptr, "cabs"));
20150b57cec5SDimitry Andric }
20160b57cec5SDimitry Andric 
2017fe6060f1SDimitry Andric // Return a properly extended integer (DstWidth bits wide) if the operation is
2018fe6060f1SDimitry Andric // an itofp.
2019fe6060f1SDimitry Andric static Value *getIntToFPVal(Value *I2F, IRBuilderBase &B, unsigned DstWidth) {
20208bcb0991SDimitry Andric   if (isa<SIToFPInst>(I2F) || isa<UIToFPInst>(I2F)) {
20218bcb0991SDimitry Andric     Value *Op = cast<Instruction>(I2F)->getOperand(0);
2022fe6060f1SDimitry Andric     // Make sure that the exponent fits inside an "int" of size DstWidth,
20238bcb0991SDimitry Andric     // thus avoiding any range issues that FP has not.
2024*0fca6ea1SDimitry Andric     unsigned BitWidth = Op->getType()->getScalarSizeInBits();
2025*0fca6ea1SDimitry Andric     if (BitWidth < DstWidth || (BitWidth == DstWidth && isa<SIToFPInst>(I2F))) {
2026*0fca6ea1SDimitry Andric       Type *IntTy = Op->getType()->getWithNewBitWidth(DstWidth);
2027*0fca6ea1SDimitry Andric       return isa<SIToFPInst>(I2F) ? B.CreateSExt(Op, IntTy)
2028*0fca6ea1SDimitry Andric                                   : B.CreateZExt(Op, IntTy);
2029*0fca6ea1SDimitry Andric     }
20308bcb0991SDimitry Andric   }
20318bcb0991SDimitry Andric 
20328bcb0991SDimitry Andric   return nullptr;
20338bcb0991SDimitry Andric }
20348bcb0991SDimitry Andric 
20350b57cec5SDimitry Andric /// Use exp{,2}(x * y) for pow(exp{,2}(x), y);
20368bcb0991SDimitry Andric /// ldexp(1.0, x) for pow(2.0, itofp(x)); exp2(n * x) for pow(2.0 ** n, x);
20378bcb0991SDimitry Andric /// exp10(x) for pow(10.0, x); exp2(log2(n) * x) for pow(n, x).
20385ffd83dbSDimitry Andric Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) {
203981ad6265SDimitry Andric   Module *M = Pow->getModule();
20400b57cec5SDimitry Andric   Value *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1);
20410b57cec5SDimitry Andric   Type *Ty = Pow->getType();
20420b57cec5SDimitry Andric   bool Ignored;
20430b57cec5SDimitry Andric 
20440b57cec5SDimitry Andric   // Evaluate special cases related to a nested function as the base.
20450b57cec5SDimitry Andric 
20460b57cec5SDimitry Andric   // pow(exp(x), y) -> exp(x * y)
20470b57cec5SDimitry Andric   // pow(exp2(x), y) -> exp2(x * y)
20480b57cec5SDimitry Andric   // If exp{,2}() is used only once, it is better to fold two transcendental
20490b57cec5SDimitry Andric   // math functions into one.  If used again, exp{,2}() would still have to be
20500b57cec5SDimitry Andric   // called with the original argument, then keep both original transcendental
20510b57cec5SDimitry Andric   // functions.  However, this transformation is only safe with fully relaxed
20520b57cec5SDimitry Andric   // math semantics, since, besides rounding differences, it changes overflow
20530b57cec5SDimitry Andric   // and underflow behavior quite dramatically.  For example:
20540b57cec5SDimitry Andric   //   pow(exp(1000), 0.001) = pow(inf, 0.001) = inf
20550b57cec5SDimitry Andric   // Whereas:
20560b57cec5SDimitry Andric   //   exp(1000 * 0.001) = exp(1)
20570b57cec5SDimitry Andric   // TODO: Loosen the requirement for fully relaxed math semantics.
20580b57cec5SDimitry Andric   // TODO: Handle exp10() when more targets have it available.
20590b57cec5SDimitry Andric   CallInst *BaseFn = dyn_cast<CallInst>(Base);
20600b57cec5SDimitry Andric   if (BaseFn && BaseFn->hasOneUse() && BaseFn->isFast() && Pow->isFast()) {
20610b57cec5SDimitry Andric     LibFunc LibFn;
20620b57cec5SDimitry Andric 
20630b57cec5SDimitry Andric     Function *CalleeFn = BaseFn->getCalledFunction();
2064bdd1243dSDimitry Andric     if (CalleeFn && TLI->getLibFunc(CalleeFn->getName(), LibFn) &&
206581ad6265SDimitry Andric         isLibFuncEmittable(M, TLI, LibFn)) {
20660b57cec5SDimitry Andric       StringRef ExpName;
20670b57cec5SDimitry Andric       Intrinsic::ID ID;
20680b57cec5SDimitry Andric       Value *ExpFn;
20698bcb0991SDimitry Andric       LibFunc LibFnFloat, LibFnDouble, LibFnLongDouble;
20700b57cec5SDimitry Andric 
20710b57cec5SDimitry Andric       switch (LibFn) {
20720b57cec5SDimitry Andric       default:
20730b57cec5SDimitry Andric         return nullptr;
2074bdd1243dSDimitry Andric       case LibFunc_expf:
2075bdd1243dSDimitry Andric       case LibFunc_exp:
2076bdd1243dSDimitry Andric       case LibFunc_expl:
20770b57cec5SDimitry Andric         ExpName = TLI->getName(LibFunc_exp);
20780b57cec5SDimitry Andric         ID = Intrinsic::exp;
20790b57cec5SDimitry Andric         LibFnFloat = LibFunc_expf;
20800b57cec5SDimitry Andric         LibFnDouble = LibFunc_exp;
20810b57cec5SDimitry Andric         LibFnLongDouble = LibFunc_expl;
20820b57cec5SDimitry Andric         break;
2083bdd1243dSDimitry Andric       case LibFunc_exp2f:
2084bdd1243dSDimitry Andric       case LibFunc_exp2:
2085bdd1243dSDimitry Andric       case LibFunc_exp2l:
20860b57cec5SDimitry Andric         ExpName = TLI->getName(LibFunc_exp2);
20870b57cec5SDimitry Andric         ID = Intrinsic::exp2;
20880b57cec5SDimitry Andric         LibFnFloat = LibFunc_exp2f;
20890b57cec5SDimitry Andric         LibFnDouble = LibFunc_exp2;
20900b57cec5SDimitry Andric         LibFnLongDouble = LibFunc_exp2l;
20910b57cec5SDimitry Andric         break;
20920b57cec5SDimitry Andric       }
20930b57cec5SDimitry Andric 
20940b57cec5SDimitry Andric       // Create new exp{,2}() with the product as its argument.
20950b57cec5SDimitry Andric       Value *FMul = B.CreateFMul(BaseFn->getArgOperand(0), Expo, "mul");
20960b57cec5SDimitry Andric       ExpFn = BaseFn->doesNotAccessMemory()
2097*0fca6ea1SDimitry Andric                   ? B.CreateUnaryIntrinsic(ID, FMul, nullptr, ExpName)
20980b57cec5SDimitry Andric                   : emitUnaryFloatFnCall(FMul, TLI, LibFnDouble, LibFnFloat,
20990b57cec5SDimitry Andric                                          LibFnLongDouble, B,
21000b57cec5SDimitry Andric                                          BaseFn->getAttributes());
21010b57cec5SDimitry Andric 
21020b57cec5SDimitry Andric       // Since the new exp{,2}() is different from the original one, dead code
21030b57cec5SDimitry Andric       // elimination cannot be trusted to remove it, since it may have side
21040b57cec5SDimitry Andric       // effects (e.g., errno).  When the only consumer for the original
21050b57cec5SDimitry Andric       // exp{,2}() is pow(), then it has to be explicitly erased.
21068bcb0991SDimitry Andric       substituteInParent(BaseFn, ExpFn);
21070b57cec5SDimitry Andric       return ExpFn;
21080b57cec5SDimitry Andric     }
21090b57cec5SDimitry Andric   }
21100b57cec5SDimitry Andric 
21110b57cec5SDimitry Andric   // Evaluate special cases related to a constant base.
21120b57cec5SDimitry Andric 
21130b57cec5SDimitry Andric   const APFloat *BaseF;
2114*0fca6ea1SDimitry Andric   if (!match(Base, m_APFloat(BaseF)))
21150b57cec5SDimitry Andric     return nullptr;
21160b57cec5SDimitry Andric 
2117bdd1243dSDimitry Andric   AttributeList NoAttrs; // Attributes are only meaningful on the original call
2118bdd1243dSDimitry Andric 
2119*0fca6ea1SDimitry Andric   const bool UseIntrinsic = Pow->doesNotAccessMemory();
2120*0fca6ea1SDimitry Andric 
21218bcb0991SDimitry Andric   // pow(2.0, itofp(x)) -> ldexp(1.0, x)
2122*0fca6ea1SDimitry Andric   if ((UseIntrinsic || !Ty->isVectorTy()) && BaseF->isExactlyValue(2.0) &&
21238bcb0991SDimitry Andric       (isa<SIToFPInst>(Expo) || isa<UIToFPInst>(Expo)) &&
2124*0fca6ea1SDimitry Andric       (UseIntrinsic ||
2125*0fca6ea1SDimitry Andric        hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl))) {
2126*0fca6ea1SDimitry Andric 
2127*0fca6ea1SDimitry Andric     // TODO: Shouldn't really need to depend on getIntToFPVal for intrinsic. Can
2128*0fca6ea1SDimitry Andric     // just directly use the original integer type.
2129*0fca6ea1SDimitry Andric     if (Value *ExpoI = getIntToFPVal(Expo, B, TLI->getIntSize())) {
2130*0fca6ea1SDimitry Andric       Constant *One = ConstantFP::get(Ty, 1.0);
2131*0fca6ea1SDimitry Andric 
2132*0fca6ea1SDimitry Andric       if (UseIntrinsic) {
2133*0fca6ea1SDimitry Andric         return copyFlags(*Pow, B.CreateIntrinsic(Intrinsic::ldexp,
2134*0fca6ea1SDimitry Andric                                                  {Ty, ExpoI->getType()},
2135*0fca6ea1SDimitry Andric                                                  {One, ExpoI}, Pow, "exp2"));
2136*0fca6ea1SDimitry Andric       }
2137*0fca6ea1SDimitry Andric 
2138*0fca6ea1SDimitry Andric       return copyFlags(*Pow, emitBinaryFloatFnCall(
2139*0fca6ea1SDimitry Andric                                  One, ExpoI, TLI, LibFunc_ldexp, LibFunc_ldexpf,
2140bdd1243dSDimitry Andric                                  LibFunc_ldexpl, B, NoAttrs));
21418bcb0991SDimitry Andric     }
2142*0fca6ea1SDimitry Andric   }
21438bcb0991SDimitry Andric 
21440b57cec5SDimitry Andric   // pow(2.0 ** n, x) -> exp2(n * x)
214581ad6265SDimitry Andric   if (hasFloatFn(M, TLI, Ty, LibFunc_exp2, LibFunc_exp2f, LibFunc_exp2l)) {
21460b57cec5SDimitry Andric     APFloat BaseR = APFloat(1.0);
21470b57cec5SDimitry Andric     BaseR.convert(BaseF->getSemantics(), APFloat::rmTowardZero, &Ignored);
21480b57cec5SDimitry Andric     BaseR = BaseR / *BaseF;
21490b57cec5SDimitry Andric     bool IsInteger = BaseF->isInteger(), IsReciprocal = BaseR.isInteger();
21500b57cec5SDimitry Andric     const APFloat *NF = IsReciprocal ? &BaseR : BaseF;
21510b57cec5SDimitry Andric     APSInt NI(64, false);
21520b57cec5SDimitry Andric     if ((IsInteger || IsReciprocal) &&
21530b57cec5SDimitry Andric         NF->convertToInteger(NI, APFloat::rmTowardZero, &Ignored) ==
21540b57cec5SDimitry Andric             APFloat::opOK &&
21550b57cec5SDimitry Andric         NI > 1 && NI.isPowerOf2()) {
21560b57cec5SDimitry Andric       double N = NI.logBase2() * (IsReciprocal ? -1.0 : 1.0);
21570b57cec5SDimitry Andric       Value *FMul = B.CreateFMul(Expo, ConstantFP::get(Ty, N), "mul");
21580b57cec5SDimitry Andric       if (Pow->doesNotAccessMemory())
2159*0fca6ea1SDimitry Andric         return copyFlags(*Pow, B.CreateUnaryIntrinsic(Intrinsic::exp2, FMul,
2160*0fca6ea1SDimitry Andric                                                       nullptr, "exp2"));
21610b57cec5SDimitry Andric       else
21620eae32dcSDimitry Andric         return copyFlags(*Pow, emitUnaryFloatFnCall(FMul, TLI, LibFunc_exp2,
21630eae32dcSDimitry Andric                                                     LibFunc_exp2f,
2164bdd1243dSDimitry Andric                                                     LibFunc_exp2l, B, NoAttrs));
21650b57cec5SDimitry Andric     }
21660b57cec5SDimitry Andric   }
21670b57cec5SDimitry Andric 
21680b57cec5SDimitry Andric   // pow(10.0, x) -> exp10(x)
2169*0fca6ea1SDimitry Andric   if (BaseF->isExactlyValue(10.0) &&
2170*0fca6ea1SDimitry Andric       hasFloatFn(M, TLI, Ty, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l)) {
2171*0fca6ea1SDimitry Andric 
2172*0fca6ea1SDimitry Andric     if (Pow->doesNotAccessMemory()) {
2173*0fca6ea1SDimitry Andric       CallInst *NewExp10 =
2174*0fca6ea1SDimitry Andric           B.CreateIntrinsic(Intrinsic::exp10, {Ty}, {Expo}, Pow, "exp10");
2175*0fca6ea1SDimitry Andric       return copyFlags(*Pow, NewExp10);
2176*0fca6ea1SDimitry Andric     }
2177*0fca6ea1SDimitry Andric 
21780eae32dcSDimitry Andric     return copyFlags(*Pow, emitUnaryFloatFnCall(Expo, TLI, LibFunc_exp10,
21790eae32dcSDimitry Andric                                                 LibFunc_exp10f, LibFunc_exp10l,
2180bdd1243dSDimitry Andric                                                 B, NoAttrs));
2181*0fca6ea1SDimitry Andric   }
21820b57cec5SDimitry Andric 
21835ffd83dbSDimitry Andric   // pow(x, y) -> exp2(log2(x) * y)
21845ffd83dbSDimitry Andric   if (Pow->hasApproxFunc() && Pow->hasNoNaNs() && BaseF->isFiniteNonZero() &&
21855ffd83dbSDimitry Andric       !BaseF->isNegative()) {
21865ffd83dbSDimitry Andric     // pow(1, inf) is defined to be 1 but exp2(log2(1) * inf) evaluates to NaN.
21875ffd83dbSDimitry Andric     // Luckily optimizePow has already handled the x == 1 case.
21885ffd83dbSDimitry Andric     assert(!match(Base, m_FPOne()) &&
21895ffd83dbSDimitry Andric            "pow(1.0, y) should have been simplified earlier!");
21905ffd83dbSDimitry Andric 
21910b57cec5SDimitry Andric     Value *Log = nullptr;
21920b57cec5SDimitry Andric     if (Ty->isFloatTy())
21930b57cec5SDimitry Andric       Log = ConstantFP::get(Ty, std::log2(BaseF->convertToFloat()));
21940b57cec5SDimitry Andric     else if (Ty->isDoubleTy())
21950b57cec5SDimitry Andric       Log = ConstantFP::get(Ty, std::log2(BaseF->convertToDouble()));
21960b57cec5SDimitry Andric 
21970b57cec5SDimitry Andric     if (Log) {
21980b57cec5SDimitry Andric       Value *FMul = B.CreateFMul(Log, Expo, "mul");
21998bcb0991SDimitry Andric       if (Pow->doesNotAccessMemory())
2200*0fca6ea1SDimitry Andric         return copyFlags(*Pow, B.CreateUnaryIntrinsic(Intrinsic::exp2, FMul,
2201*0fca6ea1SDimitry Andric                                                       nullptr, "exp2"));
220281ad6265SDimitry Andric       else if (hasFloatFn(M, TLI, Ty, LibFunc_exp2, LibFunc_exp2f,
220381ad6265SDimitry Andric                           LibFunc_exp2l))
22040eae32dcSDimitry Andric         return copyFlags(*Pow, emitUnaryFloatFnCall(FMul, TLI, LibFunc_exp2,
22050eae32dcSDimitry Andric                                                     LibFunc_exp2f,
2206bdd1243dSDimitry Andric                                                     LibFunc_exp2l, B, NoAttrs));
22070b57cec5SDimitry Andric     }
22080b57cec5SDimitry Andric   }
22098bcb0991SDimitry Andric 
22100b57cec5SDimitry Andric   return nullptr;
22110b57cec5SDimitry Andric }
22120b57cec5SDimitry Andric 
22130b57cec5SDimitry Andric static Value *getSqrtCall(Value *V, AttributeList Attrs, bool NoErrno,
22145ffd83dbSDimitry Andric                           Module *M, IRBuilderBase &B,
22150b57cec5SDimitry Andric                           const TargetLibraryInfo *TLI) {
22160b57cec5SDimitry Andric   // If errno is never set, then use the intrinsic for sqrt().
2217*0fca6ea1SDimitry Andric   if (NoErrno)
2218*0fca6ea1SDimitry Andric     return B.CreateUnaryIntrinsic(Intrinsic::sqrt, V, nullptr, "sqrt");
22190b57cec5SDimitry Andric 
22200b57cec5SDimitry Andric   // Otherwise, use the libcall for sqrt().
222181ad6265SDimitry Andric   if (hasFloatFn(M, TLI, V->getType(), LibFunc_sqrt, LibFunc_sqrtf,
222281ad6265SDimitry Andric                  LibFunc_sqrtl))
22230b57cec5SDimitry Andric     // TODO: We also should check that the target can in fact lower the sqrt()
22240b57cec5SDimitry Andric     // libcall. We currently have no way to ask this question, so we ask if
22250b57cec5SDimitry Andric     // the target has a sqrt() libcall, which is not exactly the same.
22260b57cec5SDimitry Andric     return emitUnaryFloatFnCall(V, TLI, LibFunc_sqrt, LibFunc_sqrtf,
22270b57cec5SDimitry Andric                                 LibFunc_sqrtl, B, Attrs);
22280b57cec5SDimitry Andric 
22290b57cec5SDimitry Andric   return nullptr;
22300b57cec5SDimitry Andric }
22310b57cec5SDimitry Andric 
22320b57cec5SDimitry Andric /// Use square root in place of pow(x, +/-0.5).
22335ffd83dbSDimitry Andric Value *LibCallSimplifier::replacePowWithSqrt(CallInst *Pow, IRBuilderBase &B) {
22340b57cec5SDimitry Andric   Value *Sqrt, *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1);
22350b57cec5SDimitry Andric   Module *Mod = Pow->getModule();
22360b57cec5SDimitry Andric   Type *Ty = Pow->getType();
22370b57cec5SDimitry Andric 
22380b57cec5SDimitry Andric   const APFloat *ExpoF;
22390b57cec5SDimitry Andric   if (!match(Expo, m_APFloat(ExpoF)) ||
22400b57cec5SDimitry Andric       (!ExpoF->isExactlyValue(0.5) && !ExpoF->isExactlyValue(-0.5)))
22410b57cec5SDimitry Andric     return nullptr;
22420b57cec5SDimitry Andric 
2243480093f4SDimitry Andric   // Converting pow(X, -0.5) to 1/sqrt(X) may introduce an extra rounding step,
2244480093f4SDimitry Andric   // so that requires fast-math-flags (afn or reassoc).
2245480093f4SDimitry Andric   if (ExpoF->isNegative() && (!Pow->hasApproxFunc() && !Pow->hasAllowReassoc()))
2246480093f4SDimitry Andric     return nullptr;
2247480093f4SDimitry Andric 
2248e8d8bef9SDimitry Andric   // If we have a pow() library call (accesses memory) and we can't guarantee
2249e8d8bef9SDimitry Andric   // that the base is not an infinity, give up:
2250e8d8bef9SDimitry Andric   // pow(-Inf, 0.5) is optionally required to have a result of +Inf (not setting
2251e8d8bef9SDimitry Andric   // errno), but sqrt(-Inf) is required by various standards to set errno.
2252e8d8bef9SDimitry Andric   if (!Pow->doesNotAccessMemory() && !Pow->hasNoInfs() &&
2253*0fca6ea1SDimitry Andric       !isKnownNeverInfinity(Base, 0,
2254*0fca6ea1SDimitry Andric                             SimplifyQuery(DL, TLI, /*DT=*/nullptr, AC, Pow)))
2255e8d8bef9SDimitry Andric     return nullptr;
2256e8d8bef9SDimitry Andric 
2257bdd1243dSDimitry Andric   Sqrt = getSqrtCall(Base, AttributeList(), Pow->doesNotAccessMemory(), Mod, B,
2258bdd1243dSDimitry Andric                      TLI);
22590b57cec5SDimitry Andric   if (!Sqrt)
22600b57cec5SDimitry Andric     return nullptr;
22610b57cec5SDimitry Andric 
22620b57cec5SDimitry Andric   // Handle signed zero base by expanding to fabs(sqrt(x)).
2263*0fca6ea1SDimitry Andric   if (!Pow->hasNoSignedZeros())
2264*0fca6ea1SDimitry Andric     Sqrt = B.CreateUnaryIntrinsic(Intrinsic::fabs, Sqrt, nullptr, "abs");
22650b57cec5SDimitry Andric 
22660eae32dcSDimitry Andric   Sqrt = copyFlags(*Pow, Sqrt);
22670eae32dcSDimitry Andric 
22680b57cec5SDimitry Andric   // Handle non finite base by expanding to
22690b57cec5SDimitry Andric   // (x == -infinity ? +infinity : sqrt(x)).
22700b57cec5SDimitry Andric   if (!Pow->hasNoInfs()) {
22710b57cec5SDimitry Andric     Value *PosInf = ConstantFP::getInfinity(Ty),
22720b57cec5SDimitry Andric           *NegInf = ConstantFP::getInfinity(Ty, true);
22730b57cec5SDimitry Andric     Value *FCmp = B.CreateFCmpOEQ(Base, NegInf, "isinf");
22740b57cec5SDimitry Andric     Sqrt = B.CreateSelect(FCmp, PosInf, Sqrt);
22750b57cec5SDimitry Andric   }
22760b57cec5SDimitry Andric 
22770b57cec5SDimitry Andric   // If the exponent is negative, then get the reciprocal.
22780b57cec5SDimitry Andric   if (ExpoF->isNegative())
22790b57cec5SDimitry Andric     Sqrt = B.CreateFDiv(ConstantFP::get(Ty, 1.0), Sqrt, "reciprocal");
22800b57cec5SDimitry Andric 
22810b57cec5SDimitry Andric   return Sqrt;
22820b57cec5SDimitry Andric }
22830b57cec5SDimitry Andric 
22840b57cec5SDimitry Andric static Value *createPowWithIntegerExponent(Value *Base, Value *Expo, Module *M,
22855ffd83dbSDimitry Andric                                            IRBuilderBase &B) {
22860b57cec5SDimitry Andric   Value *Args[] = {Base, Expo};
2287fe6060f1SDimitry Andric   Type *Types[] = {Base->getType(), Expo->getType()};
2288*0fca6ea1SDimitry Andric   return B.CreateIntrinsic(Intrinsic::powi, Types, Args);
22890b57cec5SDimitry Andric }
22900b57cec5SDimitry Andric 
22915ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilderBase &B) {
22920b57cec5SDimitry Andric   Value *Base = Pow->getArgOperand(0);
22930b57cec5SDimitry Andric   Value *Expo = Pow->getArgOperand(1);
22940b57cec5SDimitry Andric   Function *Callee = Pow->getCalledFunction();
22950b57cec5SDimitry Andric   StringRef Name = Callee->getName();
22960b57cec5SDimitry Andric   Type *Ty = Pow->getType();
22970b57cec5SDimitry Andric   Module *M = Pow->getModule();
22980b57cec5SDimitry Andric   bool AllowApprox = Pow->hasApproxFunc();
22990b57cec5SDimitry Andric   bool Ignored;
23000b57cec5SDimitry Andric 
23010b57cec5SDimitry Andric   // Propagate the math semantics from the call to any created instructions.
23025ffd83dbSDimitry Andric   IRBuilderBase::FastMathFlagGuard Guard(B);
23030b57cec5SDimitry Andric   B.setFastMathFlags(Pow->getFastMathFlags());
23040b57cec5SDimitry Andric   // Evaluate special cases related to the base.
23050b57cec5SDimitry Andric 
23060b57cec5SDimitry Andric   // pow(1.0, x) -> 1.0
23070b57cec5SDimitry Andric   if (match(Base, m_FPOne()))
23080b57cec5SDimitry Andric     return Base;
23090b57cec5SDimitry Andric 
23100b57cec5SDimitry Andric   if (Value *Exp = replacePowWithExp(Pow, B))
23110b57cec5SDimitry Andric     return Exp;
23120b57cec5SDimitry Andric 
23130b57cec5SDimitry Andric   // Evaluate special cases related to the exponent.
23140b57cec5SDimitry Andric 
23150b57cec5SDimitry Andric   // pow(x, -1.0) -> 1.0 / x
23160b57cec5SDimitry Andric   if (match(Expo, m_SpecificFP(-1.0)))
23170b57cec5SDimitry Andric     return B.CreateFDiv(ConstantFP::get(Ty, 1.0), Base, "reciprocal");
23180b57cec5SDimitry Andric 
23190b57cec5SDimitry Andric   // pow(x, +/-0.0) -> 1.0
23200b57cec5SDimitry Andric   if (match(Expo, m_AnyZeroFP()))
23210b57cec5SDimitry Andric     return ConstantFP::get(Ty, 1.0);
23220b57cec5SDimitry Andric 
23230b57cec5SDimitry Andric   // pow(x, 1.0) -> x
23240b57cec5SDimitry Andric   if (match(Expo, m_FPOne()))
23250b57cec5SDimitry Andric     return Base;
23260b57cec5SDimitry Andric 
23270b57cec5SDimitry Andric   // pow(x, 2.0) -> x * x
23280b57cec5SDimitry Andric   if (match(Expo, m_SpecificFP(2.0)))
23290b57cec5SDimitry Andric     return B.CreateFMul(Base, Base, "square");
23300b57cec5SDimitry Andric 
23310b57cec5SDimitry Andric   if (Value *Sqrt = replacePowWithSqrt(Pow, B))
23320b57cec5SDimitry Andric     return Sqrt;
23330b57cec5SDimitry Andric 
2334fcaf7f86SDimitry Andric   // If we can approximate pow:
2335753f127fSDimitry Andric   // pow(x, n) -> powi(x, n) * sqrt(x) if n has exactly a 0.5 fraction
2336fcaf7f86SDimitry Andric   // pow(x, n) -> powi(x, n) if n is a constant signed integer value
23370b57cec5SDimitry Andric   const APFloat *ExpoF;
2338fcaf7f86SDimitry Andric   if (AllowApprox && match(Expo, m_APFloat(ExpoF)) &&
2339fcaf7f86SDimitry Andric       !ExpoF->isExactlyValue(0.5) && !ExpoF->isExactlyValue(-0.5)) {
2340753f127fSDimitry Andric     APFloat ExpoA(abs(*ExpoF));
2341753f127fSDimitry Andric     APFloat ExpoI(*ExpoF);
23420b57cec5SDimitry Andric     Value *Sqrt = nullptr;
2343fcaf7f86SDimitry Andric     if (!ExpoA.isInteger()) {
23440b57cec5SDimitry Andric       APFloat Expo2 = ExpoA;
23450b57cec5SDimitry Andric       // To check if ExpoA is an integer + 0.5, we add it to itself. If there
23460b57cec5SDimitry Andric       // is no floating point exception and the result is an integer, then
23470b57cec5SDimitry Andric       // ExpoA == integer + 0.5
23480b57cec5SDimitry Andric       if (Expo2.add(ExpoA, APFloat::rmNearestTiesToEven) != APFloat::opOK)
23490b57cec5SDimitry Andric         return nullptr;
23500b57cec5SDimitry Andric 
23510b57cec5SDimitry Andric       if (!Expo2.isInteger())
23520b57cec5SDimitry Andric         return nullptr;
23530b57cec5SDimitry Andric 
2354753f127fSDimitry Andric       if (ExpoI.roundToIntegral(APFloat::rmTowardNegative) !=
2355753f127fSDimitry Andric           APFloat::opInexact)
2356753f127fSDimitry Andric         return nullptr;
2357753f127fSDimitry Andric       if (!ExpoI.isInteger())
2358753f127fSDimitry Andric         return nullptr;
2359753f127fSDimitry Andric       ExpoF = &ExpoI;
2360753f127fSDimitry Andric 
2361bdd1243dSDimitry Andric       Sqrt = getSqrtCall(Base, AttributeList(), Pow->doesNotAccessMemory(), M,
2362bdd1243dSDimitry Andric                          B, TLI);
2363e8d8bef9SDimitry Andric       if (!Sqrt)
2364e8d8bef9SDimitry Andric         return nullptr;
23650b57cec5SDimitry Andric     }
23660b57cec5SDimitry Andric 
2367fcaf7f86SDimitry Andric     // 0.5 fraction is now optionally handled.
2368fcaf7f86SDimitry Andric     // Do pow -> powi for remaining integer exponent
2369fe6060f1SDimitry Andric     APSInt IntExpo(TLI->getIntSize(), /*isUnsigned=*/false);
23700b57cec5SDimitry Andric     if (ExpoF->isInteger() &&
23710b57cec5SDimitry Andric         ExpoF->convertToInteger(IntExpo, APFloat::rmTowardZero, &Ignored) ==
23720b57cec5SDimitry Andric             APFloat::opOK) {
2373753f127fSDimitry Andric       Value *PowI = copyFlags(
23740eae32dcSDimitry Andric           *Pow,
23750eae32dcSDimitry Andric           createPowWithIntegerExponent(
23760eae32dcSDimitry Andric               Base, ConstantInt::get(B.getIntNTy(TLI->getIntSize()), IntExpo),
23770eae32dcSDimitry Andric               M, B));
2378753f127fSDimitry Andric 
2379753f127fSDimitry Andric       if (PowI && Sqrt)
2380753f127fSDimitry Andric         return B.CreateFMul(PowI, Sqrt);
2381753f127fSDimitry Andric 
2382753f127fSDimitry Andric       return PowI;
23830b57cec5SDimitry Andric     }
23840b57cec5SDimitry Andric   }
23850b57cec5SDimitry Andric 
23860b57cec5SDimitry Andric   // powf(x, itofp(y)) -> powi(x, y)
23870b57cec5SDimitry Andric   if (AllowApprox && (isa<SIToFPInst>(Expo) || isa<UIToFPInst>(Expo))) {
2388fe6060f1SDimitry Andric     if (Value *ExpoI = getIntToFPVal(Expo, B, TLI->getIntSize()))
23890eae32dcSDimitry Andric       return copyFlags(*Pow, createPowWithIntegerExponent(Base, ExpoI, M, B));
23900b57cec5SDimitry Andric   }
23910b57cec5SDimitry Andric 
2392fe6060f1SDimitry Andric   // Shrink pow() to powf() if the arguments are single precision,
2393fe6060f1SDimitry Andric   // unless the result is expected to be double precision.
2394fe6060f1SDimitry Andric   if (UnsafeFPShrink && Name == TLI->getName(LibFunc_pow) &&
239581ad6265SDimitry Andric       hasFloatVersion(M, Name)) {
239681ad6265SDimitry Andric     if (Value *Shrunk = optimizeBinaryDoubleFP(Pow, B, TLI, true))
23970b57cec5SDimitry Andric       return Shrunk;
23980b57cec5SDimitry Andric   }
23990b57cec5SDimitry Andric 
2400fe6060f1SDimitry Andric   return nullptr;
2401fe6060f1SDimitry Andric }
2402fe6060f1SDimitry Andric 
24035ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) {
240481ad6265SDimitry Andric   Module *M = CI->getModule();
24050b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
24060b57cec5SDimitry Andric   StringRef Name = Callee->getName();
24078bcb0991SDimitry Andric   Value *Ret = nullptr;
24088bcb0991SDimitry Andric   if (UnsafeFPShrink && Name == TLI->getName(LibFunc_exp2) &&
240981ad6265SDimitry Andric       hasFloatVersion(M, Name))
241081ad6265SDimitry Andric     Ret = optimizeUnaryDoubleFP(CI, B, TLI, true);
24110b57cec5SDimitry Andric 
2412*0fca6ea1SDimitry Andric   // If we have an llvm.exp2 intrinsic, emit the llvm.ldexp intrinsic. If we
2413*0fca6ea1SDimitry Andric   // have the libcall, emit the libcall.
2414*0fca6ea1SDimitry Andric   //
2415*0fca6ea1SDimitry Andric   // TODO: In principle we should be able to just always use the intrinsic for
2416*0fca6ea1SDimitry Andric   // any doesNotAccessMemory callsite.
2417*0fca6ea1SDimitry Andric 
2418*0fca6ea1SDimitry Andric   const bool UseIntrinsic = Callee->isIntrinsic();
241906c3fb27SDimitry Andric   // Bail out for vectors because the code below only expects scalars.
24208bcb0991SDimitry Andric   Type *Ty = CI->getType();
2421*0fca6ea1SDimitry Andric   if (!UseIntrinsic && Ty->isVectorTy())
242206c3fb27SDimitry Andric     return Ret;
24238bcb0991SDimitry Andric 
2424bdd1243dSDimitry Andric   // exp2(sitofp(x)) -> ldexp(1.0, sext(x))  if sizeof(x) <= IntSize
2425bdd1243dSDimitry Andric   // exp2(uitofp(x)) -> ldexp(1.0, zext(x))  if sizeof(x) < IntSize
242606c3fb27SDimitry Andric   Value *Op = CI->getArgOperand(0);
24278bcb0991SDimitry Andric   if ((isa<SIToFPInst>(Op) || isa<UIToFPInst>(Op)) &&
2428*0fca6ea1SDimitry Andric       (UseIntrinsic ||
2429*0fca6ea1SDimitry Andric        hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl))) {
243006c3fb27SDimitry Andric     if (Value *Exp = getIntToFPVal(Op, B, TLI->getIntSize())) {
2431*0fca6ea1SDimitry Andric       Constant *One = ConstantFP::get(Ty, 1.0);
2432*0fca6ea1SDimitry Andric 
2433*0fca6ea1SDimitry Andric       if (UseIntrinsic) {
2434*0fca6ea1SDimitry Andric         return copyFlags(*CI, B.CreateIntrinsic(Intrinsic::ldexp,
2435*0fca6ea1SDimitry Andric                                                 {Ty, Exp->getType()},
2436*0fca6ea1SDimitry Andric                                                 {One, Exp}, CI));
2437*0fca6ea1SDimitry Andric       }
2438*0fca6ea1SDimitry Andric 
243906c3fb27SDimitry Andric       IRBuilderBase::FastMathFlagGuard Guard(B);
244006c3fb27SDimitry Andric       B.setFastMathFlags(CI->getFastMathFlags());
2441*0fca6ea1SDimitry Andric       return copyFlags(*CI, emitBinaryFloatFnCall(
2442*0fca6ea1SDimitry Andric                                 One, Exp, TLI, LibFunc_ldexp, LibFunc_ldexpf,
244306c3fb27SDimitry Andric                                 LibFunc_ldexpl, B, AttributeList()));
244406c3fb27SDimitry Andric     }
24450b57cec5SDimitry Andric   }
24460b57cec5SDimitry Andric 
24470b57cec5SDimitry Andric   return Ret;
24480b57cec5SDimitry Andric }
24490b57cec5SDimitry Andric 
24505ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilderBase &B) {
245181ad6265SDimitry Andric   Module *M = CI->getModule();
245281ad6265SDimitry Andric 
24530b57cec5SDimitry Andric   // If we can shrink the call to a float function rather than a double
24540b57cec5SDimitry Andric   // function, do that first.
24550b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
24560b57cec5SDimitry Andric   StringRef Name = Callee->getName();
245781ad6265SDimitry Andric   if ((Name == "fmin" || Name == "fmax") && hasFloatVersion(M, Name))
245881ad6265SDimitry Andric     if (Value *Ret = optimizeBinaryDoubleFP(CI, B, TLI))
24590b57cec5SDimitry Andric       return Ret;
24600b57cec5SDimitry Andric 
24610b57cec5SDimitry Andric   // The LLVM intrinsics minnum/maxnum correspond to fmin/fmax. Canonicalize to
24620b57cec5SDimitry Andric   // the intrinsics for improved optimization (for example, vectorization).
24630b57cec5SDimitry Andric   // No-signed-zeros is implied by the definitions of fmax/fmin themselves.
24640b57cec5SDimitry Andric   // From the C standard draft WG14/N1256:
24650b57cec5SDimitry Andric   // "Ideally, fmax would be sensitive to the sign of zero, for example
24660b57cec5SDimitry Andric   // fmax(-0.0, +0.0) would return +0; however, implementation in software
24670b57cec5SDimitry Andric   // might be impractical."
24685ffd83dbSDimitry Andric   IRBuilderBase::FastMathFlagGuard Guard(B);
24690b57cec5SDimitry Andric   FastMathFlags FMF = CI->getFastMathFlags();
24700b57cec5SDimitry Andric   FMF.setNoSignedZeros();
24710b57cec5SDimitry Andric   B.setFastMathFlags(FMF);
24720b57cec5SDimitry Andric 
24735f757f3fSDimitry Andric   Intrinsic::ID IID = Callee->getName().starts_with("fmin") ? Intrinsic::minnum
24740b57cec5SDimitry Andric                                                             : Intrinsic::maxnum;
2475*0fca6ea1SDimitry Andric   return copyFlags(*CI, B.CreateBinaryIntrinsic(IID, CI->getArgOperand(0),
2476*0fca6ea1SDimitry Andric                                                 CI->getArgOperand(1)));
24770b57cec5SDimitry Andric }
24780b57cec5SDimitry Andric 
24795ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
24808bcb0991SDimitry Andric   Function *LogFn = Log->getCalledFunction();
24818bcb0991SDimitry Andric   StringRef LogNm = LogFn->getName();
24828bcb0991SDimitry Andric   Intrinsic::ID LogID = LogFn->getIntrinsicID();
24838bcb0991SDimitry Andric   Module *Mod = Log->getModule();
24848bcb0991SDimitry Andric   Type *Ty = Log->getType();
24850b57cec5SDimitry Andric   Value *Ret = nullptr;
24860b57cec5SDimitry Andric 
248781ad6265SDimitry Andric   if (UnsafeFPShrink && hasFloatVersion(Mod, LogNm))
248881ad6265SDimitry Andric     Ret = optimizeUnaryDoubleFP(Log, B, TLI, true);
24890b57cec5SDimitry Andric 
24900b57cec5SDimitry Andric   // The earlier call must also be 'fast' in order to do these transforms.
24918bcb0991SDimitry Andric   CallInst *Arg = dyn_cast<CallInst>(Log->getArgOperand(0));
24928bcb0991SDimitry Andric   if (!Log->isFast() || !Arg || !Arg->isFast() || !Arg->hasOneUse())
24930b57cec5SDimitry Andric     return Ret;
24940b57cec5SDimitry Andric 
24958bcb0991SDimitry Andric   LibFunc LogLb, ExpLb, Exp2Lb, Exp10Lb, PowLb;
24968bcb0991SDimitry Andric 
24978bcb0991SDimitry Andric   // This is only applicable to log(), log2(), log10().
24988bcb0991SDimitry Andric   if (TLI->getLibFunc(LogNm, LogLb))
24998bcb0991SDimitry Andric     switch (LogLb) {
25008bcb0991SDimitry Andric     case LibFunc_logf:
25018bcb0991SDimitry Andric       LogID = Intrinsic::log;
25028bcb0991SDimitry Andric       ExpLb = LibFunc_expf;
25038bcb0991SDimitry Andric       Exp2Lb = LibFunc_exp2f;
25048bcb0991SDimitry Andric       Exp10Lb = LibFunc_exp10f;
25058bcb0991SDimitry Andric       PowLb = LibFunc_powf;
25068bcb0991SDimitry Andric       break;
25078bcb0991SDimitry Andric     case LibFunc_log:
25088bcb0991SDimitry Andric       LogID = Intrinsic::log;
25098bcb0991SDimitry Andric       ExpLb = LibFunc_exp;
25108bcb0991SDimitry Andric       Exp2Lb = LibFunc_exp2;
25118bcb0991SDimitry Andric       Exp10Lb = LibFunc_exp10;
25128bcb0991SDimitry Andric       PowLb = LibFunc_pow;
25138bcb0991SDimitry Andric       break;
25148bcb0991SDimitry Andric     case LibFunc_logl:
25158bcb0991SDimitry Andric       LogID = Intrinsic::log;
25168bcb0991SDimitry Andric       ExpLb = LibFunc_expl;
25178bcb0991SDimitry Andric       Exp2Lb = LibFunc_exp2l;
25188bcb0991SDimitry Andric       Exp10Lb = LibFunc_exp10l;
25198bcb0991SDimitry Andric       PowLb = LibFunc_powl;
25208bcb0991SDimitry Andric       break;
25218bcb0991SDimitry Andric     case LibFunc_log2f:
25228bcb0991SDimitry Andric       LogID = Intrinsic::log2;
25238bcb0991SDimitry Andric       ExpLb = LibFunc_expf;
25248bcb0991SDimitry Andric       Exp2Lb = LibFunc_exp2f;
25258bcb0991SDimitry Andric       Exp10Lb = LibFunc_exp10f;
25268bcb0991SDimitry Andric       PowLb = LibFunc_powf;
25278bcb0991SDimitry Andric       break;
25288bcb0991SDimitry Andric     case LibFunc_log2:
25298bcb0991SDimitry Andric       LogID = Intrinsic::log2;
25308bcb0991SDimitry Andric       ExpLb = LibFunc_exp;
25318bcb0991SDimitry Andric       Exp2Lb = LibFunc_exp2;
25328bcb0991SDimitry Andric       Exp10Lb = LibFunc_exp10;
25338bcb0991SDimitry Andric       PowLb = LibFunc_pow;
25348bcb0991SDimitry Andric       break;
25358bcb0991SDimitry Andric     case LibFunc_log2l:
25368bcb0991SDimitry Andric       LogID = Intrinsic::log2;
25378bcb0991SDimitry Andric       ExpLb = LibFunc_expl;
25388bcb0991SDimitry Andric       Exp2Lb = LibFunc_exp2l;
25398bcb0991SDimitry Andric       Exp10Lb = LibFunc_exp10l;
25408bcb0991SDimitry Andric       PowLb = LibFunc_powl;
25418bcb0991SDimitry Andric       break;
25428bcb0991SDimitry Andric     case LibFunc_log10f:
25438bcb0991SDimitry Andric       LogID = Intrinsic::log10;
25448bcb0991SDimitry Andric       ExpLb = LibFunc_expf;
25458bcb0991SDimitry Andric       Exp2Lb = LibFunc_exp2f;
25468bcb0991SDimitry Andric       Exp10Lb = LibFunc_exp10f;
25478bcb0991SDimitry Andric       PowLb = LibFunc_powf;
25488bcb0991SDimitry Andric       break;
25498bcb0991SDimitry Andric     case LibFunc_log10:
25508bcb0991SDimitry Andric       LogID = Intrinsic::log10;
25518bcb0991SDimitry Andric       ExpLb = LibFunc_exp;
25528bcb0991SDimitry Andric       Exp2Lb = LibFunc_exp2;
25538bcb0991SDimitry Andric       Exp10Lb = LibFunc_exp10;
25548bcb0991SDimitry Andric       PowLb = LibFunc_pow;
25558bcb0991SDimitry Andric       break;
25568bcb0991SDimitry Andric     case LibFunc_log10l:
25578bcb0991SDimitry Andric       LogID = Intrinsic::log10;
25588bcb0991SDimitry Andric       ExpLb = LibFunc_expl;
25598bcb0991SDimitry Andric       Exp2Lb = LibFunc_exp2l;
25608bcb0991SDimitry Andric       Exp10Lb = LibFunc_exp10l;
25618bcb0991SDimitry Andric       PowLb = LibFunc_powl;
25628bcb0991SDimitry Andric       break;
25638bcb0991SDimitry Andric     default:
25648bcb0991SDimitry Andric       return Ret;
25658bcb0991SDimitry Andric     }
25668bcb0991SDimitry Andric   else if (LogID == Intrinsic::log || LogID == Intrinsic::log2 ||
25678bcb0991SDimitry Andric            LogID == Intrinsic::log10) {
25688bcb0991SDimitry Andric     if (Ty->getScalarType()->isFloatTy()) {
25698bcb0991SDimitry Andric       ExpLb = LibFunc_expf;
25708bcb0991SDimitry Andric       Exp2Lb = LibFunc_exp2f;
25718bcb0991SDimitry Andric       Exp10Lb = LibFunc_exp10f;
25728bcb0991SDimitry Andric       PowLb = LibFunc_powf;
25738bcb0991SDimitry Andric     } else if (Ty->getScalarType()->isDoubleTy()) {
25748bcb0991SDimitry Andric       ExpLb = LibFunc_exp;
25758bcb0991SDimitry Andric       Exp2Lb = LibFunc_exp2;
25768bcb0991SDimitry Andric       Exp10Lb = LibFunc_exp10;
25778bcb0991SDimitry Andric       PowLb = LibFunc_pow;
25788bcb0991SDimitry Andric     } else
25798bcb0991SDimitry Andric       return Ret;
25808bcb0991SDimitry Andric   } else
25810b57cec5SDimitry Andric     return Ret;
25820b57cec5SDimitry Andric 
25835ffd83dbSDimitry Andric   IRBuilderBase::FastMathFlagGuard Guard(B);
25848bcb0991SDimitry Andric   B.setFastMathFlags(FastMathFlags::getFast());
25850b57cec5SDimitry Andric 
25868bcb0991SDimitry Andric   Intrinsic::ID ArgID = Arg->getIntrinsicID();
25878bcb0991SDimitry Andric   LibFunc ArgLb = NotLibFunc;
25885ffd83dbSDimitry Andric   TLI->getLibFunc(*Arg, ArgLb);
25890b57cec5SDimitry Andric 
25908bcb0991SDimitry Andric   // log(pow(x,y)) -> y*log(x)
2591bdd1243dSDimitry Andric   AttributeList NoAttrs;
25927a6dacacSDimitry Andric   if (ArgLb == PowLb || ArgID == Intrinsic::pow || ArgID == Intrinsic::powi) {
25938bcb0991SDimitry Andric     Value *LogX =
25948bcb0991SDimitry Andric         Log->doesNotAccessMemory()
2595*0fca6ea1SDimitry Andric             ? B.CreateUnaryIntrinsic(LogID, Arg->getOperand(0), nullptr, "log")
2596bdd1243dSDimitry Andric             : emitUnaryFloatFnCall(Arg->getOperand(0), TLI, LogNm, B, NoAttrs);
25977a6dacacSDimitry Andric     Value *Y = Arg->getArgOperand(1);
25987a6dacacSDimitry Andric     // Cast exponent to FP if integer.
25997a6dacacSDimitry Andric     if (ArgID == Intrinsic::powi)
26007a6dacacSDimitry Andric       Y = B.CreateSIToFP(Y, Ty, "cast");
26017a6dacacSDimitry Andric     Value *MulY = B.CreateFMul(Y, LogX, "mul");
26028bcb0991SDimitry Andric     // Since pow() may have side effects, e.g. errno,
26038bcb0991SDimitry Andric     // dead code elimination may not be trusted to remove it.
26048bcb0991SDimitry Andric     substituteInParent(Arg, MulY);
26058bcb0991SDimitry Andric     return MulY;
26068bcb0991SDimitry Andric   }
26078bcb0991SDimitry Andric 
26088bcb0991SDimitry Andric   // log(exp{,2,10}(y)) -> y*log({e,2,10})
26098bcb0991SDimitry Andric   // TODO: There is no exp10() intrinsic yet.
26108bcb0991SDimitry Andric   if (ArgLb == ExpLb || ArgLb == Exp2Lb || ArgLb == Exp10Lb ||
26118bcb0991SDimitry Andric            ArgID == Intrinsic::exp || ArgID == Intrinsic::exp2) {
26128bcb0991SDimitry Andric     Constant *Eul;
26138bcb0991SDimitry Andric     if (ArgLb == ExpLb || ArgID == Intrinsic::exp)
26148bcb0991SDimitry Andric       // FIXME: Add more precise value of e for long double.
26158bcb0991SDimitry Andric       Eul = ConstantFP::get(Log->getType(), numbers::e);
26168bcb0991SDimitry Andric     else if (ArgLb == Exp2Lb || ArgID == Intrinsic::exp2)
26178bcb0991SDimitry Andric       Eul = ConstantFP::get(Log->getType(), 2.0);
26188bcb0991SDimitry Andric     else
26198bcb0991SDimitry Andric       Eul = ConstantFP::get(Log->getType(), 10.0);
26208bcb0991SDimitry Andric     Value *LogE = Log->doesNotAccessMemory()
2621*0fca6ea1SDimitry Andric                       ? B.CreateUnaryIntrinsic(LogID, Eul, nullptr, "log")
2622bdd1243dSDimitry Andric                       : emitUnaryFloatFnCall(Eul, TLI, LogNm, B, NoAttrs);
26238bcb0991SDimitry Andric     Value *MulY = B.CreateFMul(Arg->getArgOperand(0), LogE, "mul");
26248bcb0991SDimitry Andric     // Since exp() may have side effects, e.g. errno,
26258bcb0991SDimitry Andric     // dead code elimination may not be trusted to remove it.
26268bcb0991SDimitry Andric     substituteInParent(Arg, MulY);
26278bcb0991SDimitry Andric     return MulY;
26288bcb0991SDimitry Andric   }
26298bcb0991SDimitry Andric 
26300b57cec5SDimitry Andric   return Ret;
26310b57cec5SDimitry Andric }
26320b57cec5SDimitry Andric 
2633*0fca6ea1SDimitry Andric // sqrt(exp(X)) -> exp(X * 0.5)
2634*0fca6ea1SDimitry Andric Value *LibCallSimplifier::mergeSqrtToExp(CallInst *CI, IRBuilderBase &B) {
2635*0fca6ea1SDimitry Andric   if (!CI->hasAllowReassoc())
2636*0fca6ea1SDimitry Andric     return nullptr;
2637*0fca6ea1SDimitry Andric 
2638*0fca6ea1SDimitry Andric   Function *SqrtFn = CI->getCalledFunction();
2639*0fca6ea1SDimitry Andric   CallInst *Arg = dyn_cast<CallInst>(CI->getArgOperand(0));
2640*0fca6ea1SDimitry Andric   if (!Arg || !Arg->hasAllowReassoc() || !Arg->hasOneUse())
2641*0fca6ea1SDimitry Andric     return nullptr;
2642*0fca6ea1SDimitry Andric   Intrinsic::ID ArgID = Arg->getIntrinsicID();
2643*0fca6ea1SDimitry Andric   LibFunc ArgLb = NotLibFunc;
2644*0fca6ea1SDimitry Andric   TLI->getLibFunc(*Arg, ArgLb);
2645*0fca6ea1SDimitry Andric 
2646*0fca6ea1SDimitry Andric   LibFunc SqrtLb, ExpLb, Exp2Lb, Exp10Lb;
2647*0fca6ea1SDimitry Andric 
2648*0fca6ea1SDimitry Andric   if (TLI->getLibFunc(SqrtFn->getName(), SqrtLb))
2649*0fca6ea1SDimitry Andric     switch (SqrtLb) {
2650*0fca6ea1SDimitry Andric     case LibFunc_sqrtf:
2651*0fca6ea1SDimitry Andric       ExpLb = LibFunc_expf;
2652*0fca6ea1SDimitry Andric       Exp2Lb = LibFunc_exp2f;
2653*0fca6ea1SDimitry Andric       Exp10Lb = LibFunc_exp10f;
2654*0fca6ea1SDimitry Andric       break;
2655*0fca6ea1SDimitry Andric     case LibFunc_sqrt:
2656*0fca6ea1SDimitry Andric       ExpLb = LibFunc_exp;
2657*0fca6ea1SDimitry Andric       Exp2Lb = LibFunc_exp2;
2658*0fca6ea1SDimitry Andric       Exp10Lb = LibFunc_exp10;
2659*0fca6ea1SDimitry Andric       break;
2660*0fca6ea1SDimitry Andric     case LibFunc_sqrtl:
2661*0fca6ea1SDimitry Andric       ExpLb = LibFunc_expl;
2662*0fca6ea1SDimitry Andric       Exp2Lb = LibFunc_exp2l;
2663*0fca6ea1SDimitry Andric       Exp10Lb = LibFunc_exp10l;
2664*0fca6ea1SDimitry Andric       break;
2665*0fca6ea1SDimitry Andric     default:
2666*0fca6ea1SDimitry Andric       return nullptr;
2667*0fca6ea1SDimitry Andric     }
2668*0fca6ea1SDimitry Andric   else if (SqrtFn->getIntrinsicID() == Intrinsic::sqrt) {
2669*0fca6ea1SDimitry Andric     if (CI->getType()->getScalarType()->isFloatTy()) {
2670*0fca6ea1SDimitry Andric       ExpLb = LibFunc_expf;
2671*0fca6ea1SDimitry Andric       Exp2Lb = LibFunc_exp2f;
2672*0fca6ea1SDimitry Andric       Exp10Lb = LibFunc_exp10f;
2673*0fca6ea1SDimitry Andric     } else if (CI->getType()->getScalarType()->isDoubleTy()) {
2674*0fca6ea1SDimitry Andric       ExpLb = LibFunc_exp;
2675*0fca6ea1SDimitry Andric       Exp2Lb = LibFunc_exp2;
2676*0fca6ea1SDimitry Andric       Exp10Lb = LibFunc_exp10;
2677*0fca6ea1SDimitry Andric     } else
2678*0fca6ea1SDimitry Andric       return nullptr;
2679*0fca6ea1SDimitry Andric   } else
2680*0fca6ea1SDimitry Andric     return nullptr;
2681*0fca6ea1SDimitry Andric 
2682*0fca6ea1SDimitry Andric   if (ArgLb != ExpLb && ArgLb != Exp2Lb && ArgLb != Exp10Lb &&
2683*0fca6ea1SDimitry Andric       ArgID != Intrinsic::exp && ArgID != Intrinsic::exp2)
2684*0fca6ea1SDimitry Andric     return nullptr;
2685*0fca6ea1SDimitry Andric 
2686*0fca6ea1SDimitry Andric   IRBuilderBase::InsertPointGuard Guard(B);
2687*0fca6ea1SDimitry Andric   B.SetInsertPoint(Arg);
2688*0fca6ea1SDimitry Andric   auto *ExpOperand = Arg->getOperand(0);
2689*0fca6ea1SDimitry Andric   auto *FMul =
2690*0fca6ea1SDimitry Andric       B.CreateFMulFMF(ExpOperand, ConstantFP::get(ExpOperand->getType(), 0.5),
2691*0fca6ea1SDimitry Andric                       CI, "merged.sqrt");
2692*0fca6ea1SDimitry Andric 
2693*0fca6ea1SDimitry Andric   Arg->setOperand(0, FMul);
2694*0fca6ea1SDimitry Andric   return Arg;
2695*0fca6ea1SDimitry Andric }
2696*0fca6ea1SDimitry Andric 
26975ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilderBase &B) {
269881ad6265SDimitry Andric   Module *M = CI->getModule();
26990b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
27000b57cec5SDimitry Andric   Value *Ret = nullptr;
27010b57cec5SDimitry Andric   // TODO: Once we have a way (other than checking for the existince of the
27020b57cec5SDimitry Andric   // libcall) to tell whether our target can lower @llvm.sqrt, relax the
27030b57cec5SDimitry Andric   // condition below.
270481ad6265SDimitry Andric   if (isLibFuncEmittable(M, TLI, LibFunc_sqrtf) &&
270581ad6265SDimitry Andric       (Callee->getName() == "sqrt" ||
27060b57cec5SDimitry Andric        Callee->getIntrinsicID() == Intrinsic::sqrt))
270781ad6265SDimitry Andric     Ret = optimizeUnaryDoubleFP(CI, B, TLI, true);
27080b57cec5SDimitry Andric 
2709*0fca6ea1SDimitry Andric   if (Value *Opt = mergeSqrtToExp(CI, B))
2710*0fca6ea1SDimitry Andric     return Opt;
2711*0fca6ea1SDimitry Andric 
27120b57cec5SDimitry Andric   if (!CI->isFast())
27130b57cec5SDimitry Andric     return Ret;
27140b57cec5SDimitry Andric 
27150b57cec5SDimitry Andric   Instruction *I = dyn_cast<Instruction>(CI->getArgOperand(0));
27160b57cec5SDimitry Andric   if (!I || I->getOpcode() != Instruction::FMul || !I->isFast())
27170b57cec5SDimitry Andric     return Ret;
27180b57cec5SDimitry Andric 
27190b57cec5SDimitry Andric   // We're looking for a repeated factor in a multiplication tree,
27200b57cec5SDimitry Andric   // so we can do this fold: sqrt(x * x) -> fabs(x);
27210b57cec5SDimitry Andric   // or this fold: sqrt((x * x) * y) -> fabs(x) * sqrt(y).
27220b57cec5SDimitry Andric   Value *Op0 = I->getOperand(0);
27230b57cec5SDimitry Andric   Value *Op1 = I->getOperand(1);
27240b57cec5SDimitry Andric   Value *RepeatOp = nullptr;
27250b57cec5SDimitry Andric   Value *OtherOp = nullptr;
27260b57cec5SDimitry Andric   if (Op0 == Op1) {
27270b57cec5SDimitry Andric     // Simple match: the operands of the multiply are identical.
27280b57cec5SDimitry Andric     RepeatOp = Op0;
27290b57cec5SDimitry Andric   } else {
27300b57cec5SDimitry Andric     // Look for a more complicated pattern: one of the operands is itself
27310b57cec5SDimitry Andric     // a multiply, so search for a common factor in that multiply.
27320b57cec5SDimitry Andric     // Note: We don't bother looking any deeper than this first level or for
27330b57cec5SDimitry Andric     // variations of this pattern because instcombine's visitFMUL and/or the
27340b57cec5SDimitry Andric     // reassociation pass should give us this form.
27350b57cec5SDimitry Andric     Value *OtherMul0, *OtherMul1;
27360b57cec5SDimitry Andric     if (match(Op0, m_FMul(m_Value(OtherMul0), m_Value(OtherMul1)))) {
27370b57cec5SDimitry Andric       // Pattern: sqrt((x * y) * z)
27380b57cec5SDimitry Andric       if (OtherMul0 == OtherMul1 && cast<Instruction>(Op0)->isFast()) {
27390b57cec5SDimitry Andric         // Matched: sqrt((x * x) * z)
27400b57cec5SDimitry Andric         RepeatOp = OtherMul0;
27410b57cec5SDimitry Andric         OtherOp = Op1;
27420b57cec5SDimitry Andric       }
27430b57cec5SDimitry Andric     }
27440b57cec5SDimitry Andric   }
27450b57cec5SDimitry Andric   if (!RepeatOp)
27460b57cec5SDimitry Andric     return Ret;
27470b57cec5SDimitry Andric 
27480b57cec5SDimitry Andric   // Fast math flags for any created instructions should match the sqrt
27490b57cec5SDimitry Andric   // and multiply.
27505ffd83dbSDimitry Andric   IRBuilderBase::FastMathFlagGuard Guard(B);
27510b57cec5SDimitry Andric   B.setFastMathFlags(I->getFastMathFlags());
27520b57cec5SDimitry Andric 
27530b57cec5SDimitry Andric   // If we found a repeated factor, hoist it out of the square root and
27540b57cec5SDimitry Andric   // replace it with the fabs of that factor.
2755*0fca6ea1SDimitry Andric   Value *FabsCall =
2756*0fca6ea1SDimitry Andric       B.CreateUnaryIntrinsic(Intrinsic::fabs, RepeatOp, nullptr, "fabs");
27570b57cec5SDimitry Andric   if (OtherOp) {
27580b57cec5SDimitry Andric     // If we found a non-repeated factor, we still need to get its square
27590b57cec5SDimitry Andric     // root. We then multiply that by the value that was simplified out
27600b57cec5SDimitry Andric     // of the square root calculation.
2761*0fca6ea1SDimitry Andric     Value *SqrtCall =
2762*0fca6ea1SDimitry Andric         B.CreateUnaryIntrinsic(Intrinsic::sqrt, OtherOp, nullptr, "sqrt");
27630eae32dcSDimitry Andric     return copyFlags(*CI, B.CreateFMul(FabsCall, SqrtCall));
27640b57cec5SDimitry Andric   }
27650eae32dcSDimitry Andric   return copyFlags(*CI, FabsCall);
27660b57cec5SDimitry Andric }
27670b57cec5SDimitry Andric 
2768*0fca6ea1SDimitry Andric Value *LibCallSimplifier::optimizeTrigInversionPairs(CallInst *CI,
2769*0fca6ea1SDimitry Andric                                                      IRBuilderBase &B) {
277081ad6265SDimitry Andric   Module *M = CI->getModule();
27710b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
27720b57cec5SDimitry Andric   Value *Ret = nullptr;
27730b57cec5SDimitry Andric   StringRef Name = Callee->getName();
2774*0fca6ea1SDimitry Andric   if (UnsafeFPShrink &&
2775*0fca6ea1SDimitry Andric       (Name == "tan" || Name == "atanh" || Name == "sinh" || Name == "cosh" ||
2776*0fca6ea1SDimitry Andric        Name == "asinh") &&
2777*0fca6ea1SDimitry Andric       hasFloatVersion(M, Name))
277881ad6265SDimitry Andric     Ret = optimizeUnaryDoubleFP(CI, B, TLI, true);
27790b57cec5SDimitry Andric 
27800b57cec5SDimitry Andric   Value *Op1 = CI->getArgOperand(0);
27810b57cec5SDimitry Andric   auto *OpC = dyn_cast<CallInst>(Op1);
27820b57cec5SDimitry Andric   if (!OpC)
27830b57cec5SDimitry Andric     return Ret;
27840b57cec5SDimitry Andric 
27850b57cec5SDimitry Andric   // Both calls must be 'fast' in order to remove them.
27860b57cec5SDimitry Andric   if (!CI->isFast() || !OpC->isFast())
27870b57cec5SDimitry Andric     return Ret;
27880b57cec5SDimitry Andric 
27890b57cec5SDimitry Andric   // tan(atan(x)) -> x
2790*0fca6ea1SDimitry Andric   // atanh(tanh(x)) -> x
2791*0fca6ea1SDimitry Andric   // sinh(asinh(x)) -> x
2792*0fca6ea1SDimitry Andric   // asinh(sinh(x)) -> x
2793*0fca6ea1SDimitry Andric   // cosh(acosh(x)) -> x
27940b57cec5SDimitry Andric   LibFunc Func;
27950b57cec5SDimitry Andric   Function *F = OpC->getCalledFunction();
279681ad6265SDimitry Andric   if (F && TLI->getLibFunc(F->getName(), Func) &&
2797*0fca6ea1SDimitry Andric       isLibFuncEmittable(M, TLI, Func)) {
2798*0fca6ea1SDimitry Andric     LibFunc inverseFunc = llvm::StringSwitch<LibFunc>(Callee->getName())
2799*0fca6ea1SDimitry Andric                               .Case("tan", LibFunc_atan)
2800*0fca6ea1SDimitry Andric                               .Case("atanh", LibFunc_tanh)
2801*0fca6ea1SDimitry Andric                               .Case("sinh", LibFunc_asinh)
2802*0fca6ea1SDimitry Andric                               .Case("cosh", LibFunc_acosh)
2803*0fca6ea1SDimitry Andric                               .Case("tanf", LibFunc_atanf)
2804*0fca6ea1SDimitry Andric                               .Case("atanhf", LibFunc_tanhf)
2805*0fca6ea1SDimitry Andric                               .Case("sinhf", LibFunc_asinhf)
2806*0fca6ea1SDimitry Andric                               .Case("coshf", LibFunc_acoshf)
2807*0fca6ea1SDimitry Andric                               .Case("tanl", LibFunc_atanl)
2808*0fca6ea1SDimitry Andric                               .Case("atanhl", LibFunc_tanhl)
2809*0fca6ea1SDimitry Andric                               .Case("sinhl", LibFunc_asinhl)
2810*0fca6ea1SDimitry Andric                               .Case("coshl", LibFunc_acoshl)
2811*0fca6ea1SDimitry Andric                               .Case("asinh", LibFunc_sinh)
2812*0fca6ea1SDimitry Andric                               .Case("asinhf", LibFunc_sinhf)
2813*0fca6ea1SDimitry Andric                               .Case("asinhl", LibFunc_sinhl)
2814*0fca6ea1SDimitry Andric                               .Default(NumLibFuncs); // Used as error value
2815*0fca6ea1SDimitry Andric     if (Func == inverseFunc)
28160b57cec5SDimitry Andric       Ret = OpC->getArgOperand(0);
2817*0fca6ea1SDimitry Andric   }
28180b57cec5SDimitry Andric   return Ret;
28190b57cec5SDimitry Andric }
28200b57cec5SDimitry Andric 
28210b57cec5SDimitry Andric static bool isTrigLibCall(CallInst *CI) {
28220b57cec5SDimitry Andric   // We can only hope to do anything useful if we can ignore things like errno
28230b57cec5SDimitry Andric   // and floating-point exceptions.
28240b57cec5SDimitry Andric   // We already checked the prototype.
2825bdd1243dSDimitry Andric   return CI->doesNotThrow() && CI->doesNotAccessMemory();
28260b57cec5SDimitry Andric }
28270b57cec5SDimitry Andric 
282881ad6265SDimitry Andric static bool insertSinCosCall(IRBuilderBase &B, Function *OrigCallee, Value *Arg,
28290b57cec5SDimitry Andric                              bool UseFloat, Value *&Sin, Value *&Cos,
283081ad6265SDimitry Andric                              Value *&SinCos, const TargetLibraryInfo *TLI) {
283181ad6265SDimitry Andric   Module *M = OrigCallee->getParent();
28320b57cec5SDimitry Andric   Type *ArgTy = Arg->getType();
28330b57cec5SDimitry Andric   Type *ResTy;
28340b57cec5SDimitry Andric   StringRef Name;
28350b57cec5SDimitry Andric 
28360b57cec5SDimitry Andric   Triple T(OrigCallee->getParent()->getTargetTriple());
28370b57cec5SDimitry Andric   if (UseFloat) {
28380b57cec5SDimitry Andric     Name = "__sincospif_stret";
28390b57cec5SDimitry Andric 
28400b57cec5SDimitry Andric     assert(T.getArch() != Triple::x86 && "x86 messy and unsupported for now");
28410b57cec5SDimitry Andric     // x86_64 can't use {float, float} since that would be returned in both
28420b57cec5SDimitry Andric     // xmm0 and xmm1, which isn't what a real struct would do.
28430b57cec5SDimitry Andric     ResTy = T.getArch() == Triple::x86_64
28445ffd83dbSDimitry Andric                 ? static_cast<Type *>(FixedVectorType::get(ArgTy, 2))
28450b57cec5SDimitry Andric                 : static_cast<Type *>(StructType::get(ArgTy, ArgTy));
28460b57cec5SDimitry Andric   } else {
28470b57cec5SDimitry Andric     Name = "__sincospi_stret";
28480b57cec5SDimitry Andric     ResTy = StructType::get(ArgTy, ArgTy);
28490b57cec5SDimitry Andric   }
28500b57cec5SDimitry Andric 
285181ad6265SDimitry Andric   if (!isLibFuncEmittable(M, TLI, Name))
285281ad6265SDimitry Andric     return false;
285381ad6265SDimitry Andric   LibFunc TheLibFunc;
285481ad6265SDimitry Andric   TLI->getLibFunc(Name, TheLibFunc);
285581ad6265SDimitry Andric   FunctionCallee Callee = getOrInsertLibFunc(
285681ad6265SDimitry Andric       M, *TLI, TheLibFunc, OrigCallee->getAttributes(), ResTy, ArgTy);
28570b57cec5SDimitry Andric 
28580b57cec5SDimitry Andric   if (Instruction *ArgInst = dyn_cast<Instruction>(Arg)) {
28590b57cec5SDimitry Andric     // If the argument is an instruction, it must dominate all uses so put our
28600b57cec5SDimitry Andric     // sincos call there.
28610b57cec5SDimitry Andric     B.SetInsertPoint(ArgInst->getParent(), ++ArgInst->getIterator());
28620b57cec5SDimitry Andric   } else {
28630b57cec5SDimitry Andric     // Otherwise (e.g. for a constant) the beginning of the function is as
28640b57cec5SDimitry Andric     // good a place as any.
28650b57cec5SDimitry Andric     BasicBlock &EntryBB = B.GetInsertBlock()->getParent()->getEntryBlock();
28660b57cec5SDimitry Andric     B.SetInsertPoint(&EntryBB, EntryBB.begin());
28670b57cec5SDimitry Andric   }
28680b57cec5SDimitry Andric 
28690b57cec5SDimitry Andric   SinCos = B.CreateCall(Callee, Arg, "sincospi");
28700b57cec5SDimitry Andric 
28710b57cec5SDimitry Andric   if (SinCos->getType()->isStructTy()) {
28720b57cec5SDimitry Andric     Sin = B.CreateExtractValue(SinCos, 0, "sinpi");
28730b57cec5SDimitry Andric     Cos = B.CreateExtractValue(SinCos, 1, "cospi");
28740b57cec5SDimitry Andric   } else {
28750b57cec5SDimitry Andric     Sin = B.CreateExtractElement(SinCos, ConstantInt::get(B.getInt32Ty(), 0),
28760b57cec5SDimitry Andric                                  "sinpi");
28770b57cec5SDimitry Andric     Cos = B.CreateExtractElement(SinCos, ConstantInt::get(B.getInt32Ty(), 1),
28780b57cec5SDimitry Andric                                  "cospi");
28790b57cec5SDimitry Andric   }
288081ad6265SDimitry Andric 
288181ad6265SDimitry Andric   return true;
28820b57cec5SDimitry Andric }
28830b57cec5SDimitry Andric 
2884*0fca6ea1SDimitry Andric static Value *optimizeSymmetricCall(CallInst *CI, bool IsEven,
2885*0fca6ea1SDimitry Andric                                     IRBuilderBase &B) {
2886*0fca6ea1SDimitry Andric   Value *X;
2887*0fca6ea1SDimitry Andric   Value *Src = CI->getArgOperand(0);
2888*0fca6ea1SDimitry Andric 
2889*0fca6ea1SDimitry Andric   if (match(Src, m_OneUse(m_FNeg(m_Value(X))))) {
2890*0fca6ea1SDimitry Andric     IRBuilderBase::FastMathFlagGuard Guard(B);
2891*0fca6ea1SDimitry Andric     B.setFastMathFlags(CI->getFastMathFlags());
2892*0fca6ea1SDimitry Andric 
2893*0fca6ea1SDimitry Andric     auto *CallInst = copyFlags(*CI, B.CreateCall(CI->getCalledFunction(), {X}));
2894*0fca6ea1SDimitry Andric     if (IsEven) {
2895*0fca6ea1SDimitry Andric       // Even function: f(-x) = f(x)
2896*0fca6ea1SDimitry Andric       return CallInst;
2897*0fca6ea1SDimitry Andric     }
2898*0fca6ea1SDimitry Andric     // Odd function: f(-x) = -f(x)
2899*0fca6ea1SDimitry Andric     return B.CreateFNeg(CallInst);
2900*0fca6ea1SDimitry Andric   }
2901*0fca6ea1SDimitry Andric 
2902*0fca6ea1SDimitry Andric   // Even function: f(abs(x)) = f(x), f(copysign(x, y)) = f(x)
2903*0fca6ea1SDimitry Andric   if (IsEven && (match(Src, m_FAbs(m_Value(X))) ||
2904*0fca6ea1SDimitry Andric                  match(Src, m_CopySign(m_Value(X), m_Value())))) {
2905*0fca6ea1SDimitry Andric     IRBuilderBase::FastMathFlagGuard Guard(B);
2906*0fca6ea1SDimitry Andric     B.setFastMathFlags(CI->getFastMathFlags());
2907*0fca6ea1SDimitry Andric 
2908*0fca6ea1SDimitry Andric     auto *CallInst = copyFlags(*CI, B.CreateCall(CI->getCalledFunction(), {X}));
2909*0fca6ea1SDimitry Andric     return CallInst;
2910*0fca6ea1SDimitry Andric   }
2911*0fca6ea1SDimitry Andric 
2912*0fca6ea1SDimitry Andric   return nullptr;
2913*0fca6ea1SDimitry Andric }
2914*0fca6ea1SDimitry Andric 
2915*0fca6ea1SDimitry Andric Value *LibCallSimplifier::optimizeSymmetric(CallInst *CI, LibFunc Func,
2916*0fca6ea1SDimitry Andric                                             IRBuilderBase &B) {
2917*0fca6ea1SDimitry Andric   switch (Func) {
2918*0fca6ea1SDimitry Andric   case LibFunc_cos:
2919*0fca6ea1SDimitry Andric   case LibFunc_cosf:
2920*0fca6ea1SDimitry Andric   case LibFunc_cosl:
2921*0fca6ea1SDimitry Andric     return optimizeSymmetricCall(CI, /*IsEven*/ true, B);
2922*0fca6ea1SDimitry Andric 
2923*0fca6ea1SDimitry Andric   case LibFunc_sin:
2924*0fca6ea1SDimitry Andric   case LibFunc_sinf:
2925*0fca6ea1SDimitry Andric   case LibFunc_sinl:
2926*0fca6ea1SDimitry Andric 
2927*0fca6ea1SDimitry Andric   case LibFunc_tan:
2928*0fca6ea1SDimitry Andric   case LibFunc_tanf:
2929*0fca6ea1SDimitry Andric   case LibFunc_tanl:
2930*0fca6ea1SDimitry Andric 
2931*0fca6ea1SDimitry Andric   case LibFunc_erf:
2932*0fca6ea1SDimitry Andric   case LibFunc_erff:
2933*0fca6ea1SDimitry Andric   case LibFunc_erfl:
2934*0fca6ea1SDimitry Andric     return optimizeSymmetricCall(CI, /*IsEven*/ false, B);
2935*0fca6ea1SDimitry Andric 
2936*0fca6ea1SDimitry Andric   default:
2937*0fca6ea1SDimitry Andric     return nullptr;
2938*0fca6ea1SDimitry Andric   }
2939*0fca6ea1SDimitry Andric }
2940*0fca6ea1SDimitry Andric 
294106c3fb27SDimitry Andric Value *LibCallSimplifier::optimizeSinCosPi(CallInst *CI, bool IsSin, IRBuilderBase &B) {
29420b57cec5SDimitry Andric   // Make sure the prototype is as expected, otherwise the rest of the
29430b57cec5SDimitry Andric   // function is probably invalid and likely to abort.
29440b57cec5SDimitry Andric   if (!isTrigLibCall(CI))
29450b57cec5SDimitry Andric     return nullptr;
29460b57cec5SDimitry Andric 
29470b57cec5SDimitry Andric   Value *Arg = CI->getArgOperand(0);
29480b57cec5SDimitry Andric   SmallVector<CallInst *, 1> SinCalls;
29490b57cec5SDimitry Andric   SmallVector<CallInst *, 1> CosCalls;
29500b57cec5SDimitry Andric   SmallVector<CallInst *, 1> SinCosCalls;
29510b57cec5SDimitry Andric 
29520b57cec5SDimitry Andric   bool IsFloat = Arg->getType()->isFloatTy();
29530b57cec5SDimitry Andric 
29540b57cec5SDimitry Andric   // Look for all compatible sinpi, cospi and sincospi calls with the same
29550b57cec5SDimitry Andric   // argument. If there are enough (in some sense) we can make the
29560b57cec5SDimitry Andric   // substitution.
29570b57cec5SDimitry Andric   Function *F = CI->getFunction();
29580b57cec5SDimitry Andric   for (User *U : Arg->users())
29590b57cec5SDimitry Andric     classifyArgUse(U, F, IsFloat, SinCalls, CosCalls, SinCosCalls);
29600b57cec5SDimitry Andric 
29610b57cec5SDimitry Andric   // It's only worthwhile if both sinpi and cospi are actually used.
2962e8d8bef9SDimitry Andric   if (SinCalls.empty() || CosCalls.empty())
29630b57cec5SDimitry Andric     return nullptr;
29640b57cec5SDimitry Andric 
29650b57cec5SDimitry Andric   Value *Sin, *Cos, *SinCos;
296681ad6265SDimitry Andric   if (!insertSinCosCall(B, CI->getCalledFunction(), Arg, IsFloat, Sin, Cos,
296781ad6265SDimitry Andric                         SinCos, TLI))
296881ad6265SDimitry Andric     return nullptr;
29690b57cec5SDimitry Andric 
29700b57cec5SDimitry Andric   auto replaceTrigInsts = [this](SmallVectorImpl<CallInst *> &Calls,
29710b57cec5SDimitry Andric                                  Value *Res) {
29720b57cec5SDimitry Andric     for (CallInst *C : Calls)
29730b57cec5SDimitry Andric       replaceAllUsesWith(C, Res);
29740b57cec5SDimitry Andric   };
29750b57cec5SDimitry Andric 
29760b57cec5SDimitry Andric   replaceTrigInsts(SinCalls, Sin);
29770b57cec5SDimitry Andric   replaceTrigInsts(CosCalls, Cos);
29780b57cec5SDimitry Andric   replaceTrigInsts(SinCosCalls, SinCos);
29790b57cec5SDimitry Andric 
298006c3fb27SDimitry Andric   return IsSin ? Sin : Cos;
29810b57cec5SDimitry Andric }
29820b57cec5SDimitry Andric 
29830b57cec5SDimitry Andric void LibCallSimplifier::classifyArgUse(
29840b57cec5SDimitry Andric     Value *Val, Function *F, bool IsFloat,
29850b57cec5SDimitry Andric     SmallVectorImpl<CallInst *> &SinCalls,
29860b57cec5SDimitry Andric     SmallVectorImpl<CallInst *> &CosCalls,
29870b57cec5SDimitry Andric     SmallVectorImpl<CallInst *> &SinCosCalls) {
2988bdd1243dSDimitry Andric   auto *CI = dyn_cast<CallInst>(Val);
2989e8d8bef9SDimitry Andric   if (!CI || CI->use_empty())
29900b57cec5SDimitry Andric     return;
29910b57cec5SDimitry Andric 
29920b57cec5SDimitry Andric   // Don't consider calls in other functions.
29930b57cec5SDimitry Andric   if (CI->getFunction() != F)
29940b57cec5SDimitry Andric     return;
29950b57cec5SDimitry Andric 
2996bdd1243dSDimitry Andric   Module *M = CI->getModule();
29970b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
29980b57cec5SDimitry Andric   LibFunc Func;
299981ad6265SDimitry Andric   if (!Callee || !TLI->getLibFunc(*Callee, Func) ||
300081ad6265SDimitry Andric       !isLibFuncEmittable(M, TLI, Func) ||
30010b57cec5SDimitry Andric       !isTrigLibCall(CI))
30020b57cec5SDimitry Andric     return;
30030b57cec5SDimitry Andric 
30040b57cec5SDimitry Andric   if (IsFloat) {
30050b57cec5SDimitry Andric     if (Func == LibFunc_sinpif)
30060b57cec5SDimitry Andric       SinCalls.push_back(CI);
30070b57cec5SDimitry Andric     else if (Func == LibFunc_cospif)
30080b57cec5SDimitry Andric       CosCalls.push_back(CI);
30090b57cec5SDimitry Andric     else if (Func == LibFunc_sincospif_stret)
30100b57cec5SDimitry Andric       SinCosCalls.push_back(CI);
30110b57cec5SDimitry Andric   } else {
30120b57cec5SDimitry Andric     if (Func == LibFunc_sinpi)
30130b57cec5SDimitry Andric       SinCalls.push_back(CI);
30140b57cec5SDimitry Andric     else if (Func == LibFunc_cospi)
30150b57cec5SDimitry Andric       CosCalls.push_back(CI);
30160b57cec5SDimitry Andric     else if (Func == LibFunc_sincospi_stret)
30170b57cec5SDimitry Andric       SinCosCalls.push_back(CI);
30180b57cec5SDimitry Andric   }
30190b57cec5SDimitry Andric }
30200b57cec5SDimitry Andric 
30210b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
30220b57cec5SDimitry Andric // Integer Library Call Optimizations
30230b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
30240b57cec5SDimitry Andric 
30255ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeFFS(CallInst *CI, IRBuilderBase &B) {
3026bdd1243dSDimitry Andric   // All variants of ffs return int which need not be 32 bits wide.
3027bdd1243dSDimitry Andric   // ffs{,l,ll}(x) -> x != 0 ? (int)llvm.cttz(x)+1 : 0
3028bdd1243dSDimitry Andric   Type *RetType = CI->getType();
30290b57cec5SDimitry Andric   Value *Op = CI->getArgOperand(0);
30300b57cec5SDimitry Andric   Type *ArgType = Op->getType();
3031*0fca6ea1SDimitry Andric   Value *V = B.CreateIntrinsic(Intrinsic::cttz, {ArgType}, {Op, B.getTrue()},
3032*0fca6ea1SDimitry Andric                                nullptr, "cttz");
30330b57cec5SDimitry Andric   V = B.CreateAdd(V, ConstantInt::get(V->getType(), 1));
3034bdd1243dSDimitry Andric   V = B.CreateIntCast(V, RetType, false);
30350b57cec5SDimitry Andric 
30360b57cec5SDimitry Andric   Value *Cond = B.CreateICmpNE(Op, Constant::getNullValue(ArgType));
3037bdd1243dSDimitry Andric   return B.CreateSelect(Cond, V, ConstantInt::get(RetType, 0));
30380b57cec5SDimitry Andric }
30390b57cec5SDimitry Andric 
30405ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeFls(CallInst *CI, IRBuilderBase &B) {
3041bdd1243dSDimitry Andric   // All variants of fls return int which need not be 32 bits wide.
3042bdd1243dSDimitry Andric   // fls{,l,ll}(x) -> (int)(sizeInBits(x) - llvm.ctlz(x, false))
30430b57cec5SDimitry Andric   Value *Op = CI->getArgOperand(0);
30440b57cec5SDimitry Andric   Type *ArgType = Op->getType();
3045*0fca6ea1SDimitry Andric   Value *V = B.CreateIntrinsic(Intrinsic::ctlz, {ArgType}, {Op, B.getFalse()},
3046*0fca6ea1SDimitry Andric                                nullptr, "ctlz");
30470b57cec5SDimitry Andric   V = B.CreateSub(ConstantInt::get(V->getType(), ArgType->getIntegerBitWidth()),
30480b57cec5SDimitry Andric                   V);
30490b57cec5SDimitry Andric   return B.CreateIntCast(V, CI->getType(), false);
30500b57cec5SDimitry Andric }
30510b57cec5SDimitry Andric 
30525ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeAbs(CallInst *CI, IRBuilderBase &B) {
30530b57cec5SDimitry Andric   // abs(x) -> x <s 0 ? -x : x
30540b57cec5SDimitry Andric   // The negation has 'nsw' because abs of INT_MIN is undefined.
30550b57cec5SDimitry Andric   Value *X = CI->getArgOperand(0);
305681ad6265SDimitry Andric   Value *IsNeg = B.CreateIsNeg(X);
30570b57cec5SDimitry Andric   Value *NegX = B.CreateNSWNeg(X, "neg");
30580b57cec5SDimitry Andric   return B.CreateSelect(IsNeg, NegX, X);
30590b57cec5SDimitry Andric }
30600b57cec5SDimitry Andric 
30615ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeIsDigit(CallInst *CI, IRBuilderBase &B) {
30620b57cec5SDimitry Andric   // isdigit(c) -> (c-'0') <u 10
30630b57cec5SDimitry Andric   Value *Op = CI->getArgOperand(0);
3064bdd1243dSDimitry Andric   Type *ArgType = Op->getType();
3065bdd1243dSDimitry Andric   Op = B.CreateSub(Op, ConstantInt::get(ArgType, '0'), "isdigittmp");
3066bdd1243dSDimitry Andric   Op = B.CreateICmpULT(Op, ConstantInt::get(ArgType, 10), "isdigit");
30670b57cec5SDimitry Andric   return B.CreateZExt(Op, CI->getType());
30680b57cec5SDimitry Andric }
30690b57cec5SDimitry Andric 
30705ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeIsAscii(CallInst *CI, IRBuilderBase &B) {
30710b57cec5SDimitry Andric   // isascii(c) -> c <u 128
30720b57cec5SDimitry Andric   Value *Op = CI->getArgOperand(0);
3073bdd1243dSDimitry Andric   Type *ArgType = Op->getType();
3074bdd1243dSDimitry Andric   Op = B.CreateICmpULT(Op, ConstantInt::get(ArgType, 128), "isascii");
30750b57cec5SDimitry Andric   return B.CreateZExt(Op, CI->getType());
30760b57cec5SDimitry Andric }
30770b57cec5SDimitry Andric 
30785ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeToAscii(CallInst *CI, IRBuilderBase &B) {
30790b57cec5SDimitry Andric   // toascii(c) -> c & 0x7f
30800b57cec5SDimitry Andric   return B.CreateAnd(CI->getArgOperand(0),
30810b57cec5SDimitry Andric                      ConstantInt::get(CI->getType(), 0x7F));
30820b57cec5SDimitry Andric }
30830b57cec5SDimitry Andric 
3084972a253aSDimitry Andric // Fold calls to atoi, atol, and atoll.
30855ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeAtoi(CallInst *CI, IRBuilderBase &B) {
3086972a253aSDimitry Andric   CI->addParamAttr(0, Attribute::NoCapture);
3087972a253aSDimitry Andric 
30880b57cec5SDimitry Andric   StringRef Str;
30890b57cec5SDimitry Andric   if (!getConstantStringInfo(CI->getArgOperand(0), Str))
30900b57cec5SDimitry Andric     return nullptr;
30910b57cec5SDimitry Andric 
3092972a253aSDimitry Andric   return convertStrToInt(CI, Str, nullptr, 10, /*AsSigned=*/true, B);
30930b57cec5SDimitry Andric }
30940b57cec5SDimitry Andric 
3095972a253aSDimitry Andric // Fold calls to strtol, strtoll, strtoul, and strtoull.
3096972a253aSDimitry Andric Value *LibCallSimplifier::optimizeStrToInt(CallInst *CI, IRBuilderBase &B,
3097972a253aSDimitry Andric                                            bool AsSigned) {
3098972a253aSDimitry Andric   Value *EndPtr = CI->getArgOperand(1);
3099972a253aSDimitry Andric   if (isa<ConstantPointerNull>(EndPtr)) {
3100972a253aSDimitry Andric     // With a null EndPtr, this function won't capture the main argument.
3101972a253aSDimitry Andric     // It would be readonly too, except that it still may write to errno.
3102972a253aSDimitry Andric     CI->addParamAttr(0, Attribute::NoCapture);
3103972a253aSDimitry Andric     EndPtr = nullptr;
3104972a253aSDimitry Andric   } else if (!isKnownNonZero(EndPtr, DL))
31050b57cec5SDimitry Andric     return nullptr;
31060b57cec5SDimitry Andric 
3107972a253aSDimitry Andric   StringRef Str;
3108972a253aSDimitry Andric   if (!getConstantStringInfo(CI->getArgOperand(0), Str))
31090b57cec5SDimitry Andric     return nullptr;
31100b57cec5SDimitry Andric 
31110b57cec5SDimitry Andric   if (ConstantInt *CInt = dyn_cast<ConstantInt>(CI->getArgOperand(2))) {
3112972a253aSDimitry Andric     return convertStrToInt(CI, Str, EndPtr, CInt->getSExtValue(), AsSigned, B);
31130b57cec5SDimitry Andric   }
31140b57cec5SDimitry Andric 
31150b57cec5SDimitry Andric   return nullptr;
31160b57cec5SDimitry Andric }
31170b57cec5SDimitry Andric 
31180b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
31190b57cec5SDimitry Andric // Formatting and IO Library Call Optimizations
31200b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
31210b57cec5SDimitry Andric 
31220b57cec5SDimitry Andric static bool isReportingError(Function *Callee, CallInst *CI, int StreamArg);
31230b57cec5SDimitry Andric 
31245ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeErrorReporting(CallInst *CI, IRBuilderBase &B,
31250b57cec5SDimitry Andric                                                  int StreamArg) {
31260b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
31270b57cec5SDimitry Andric   // Error reporting calls should be cold, mark them as such.
31280b57cec5SDimitry Andric   // This applies even to non-builtin calls: it is only a hint and applies to
31290b57cec5SDimitry Andric   // functions that the frontend might not understand as builtins.
31300b57cec5SDimitry Andric 
31310b57cec5SDimitry Andric   // This heuristic was suggested in:
31320b57cec5SDimitry Andric   // Improving Static Branch Prediction in a Compiler
31330b57cec5SDimitry Andric   // Brian L. Deitrich, Ben-Chung Cheng, Wen-mei W. Hwu
31340b57cec5SDimitry Andric   // Proceedings of PACT'98, Oct. 1998, IEEE
31350b57cec5SDimitry Andric   if (!CI->hasFnAttr(Attribute::Cold) &&
31360b57cec5SDimitry Andric       isReportingError(Callee, CI, StreamArg)) {
3137349cc55cSDimitry Andric     CI->addFnAttr(Attribute::Cold);
31380b57cec5SDimitry Andric   }
31390b57cec5SDimitry Andric 
31400b57cec5SDimitry Andric   return nullptr;
31410b57cec5SDimitry Andric }
31420b57cec5SDimitry Andric 
31430b57cec5SDimitry Andric static bool isReportingError(Function *Callee, CallInst *CI, int StreamArg) {
31440b57cec5SDimitry Andric   if (!Callee || !Callee->isDeclaration())
31450b57cec5SDimitry Andric     return false;
31460b57cec5SDimitry Andric 
31470b57cec5SDimitry Andric   if (StreamArg < 0)
31480b57cec5SDimitry Andric     return true;
31490b57cec5SDimitry Andric 
31500b57cec5SDimitry Andric   // These functions might be considered cold, but only if their stream
31510b57cec5SDimitry Andric   // argument is stderr.
31520b57cec5SDimitry Andric 
3153349cc55cSDimitry Andric   if (StreamArg >= (int)CI->arg_size())
31540b57cec5SDimitry Andric     return false;
31550b57cec5SDimitry Andric   LoadInst *LI = dyn_cast<LoadInst>(CI->getArgOperand(StreamArg));
31560b57cec5SDimitry Andric   if (!LI)
31570b57cec5SDimitry Andric     return false;
31580b57cec5SDimitry Andric   GlobalVariable *GV = dyn_cast<GlobalVariable>(LI->getPointerOperand());
31590b57cec5SDimitry Andric   if (!GV || !GV->isDeclaration())
31600b57cec5SDimitry Andric     return false;
31610b57cec5SDimitry Andric   return GV->getName() == "stderr";
31620b57cec5SDimitry Andric }
31630b57cec5SDimitry Andric 
31645ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizePrintFString(CallInst *CI, IRBuilderBase &B) {
31650b57cec5SDimitry Andric   // Check for a fixed format string.
31660b57cec5SDimitry Andric   StringRef FormatStr;
31670b57cec5SDimitry Andric   if (!getConstantStringInfo(CI->getArgOperand(0), FormatStr))
31680b57cec5SDimitry Andric     return nullptr;
31690b57cec5SDimitry Andric 
31700b57cec5SDimitry Andric   // Empty format string -> noop.
31710b57cec5SDimitry Andric   if (FormatStr.empty()) // Tolerate printf's declared void.
31720b57cec5SDimitry Andric     return CI->use_empty() ? (Value *)CI : ConstantInt::get(CI->getType(), 0);
31730b57cec5SDimitry Andric 
31740b57cec5SDimitry Andric   // Do not do any of the following transformations if the printf return value
31750b57cec5SDimitry Andric   // is used, in general the printf return value is not compatible with either
31760b57cec5SDimitry Andric   // putchar() or puts().
31770b57cec5SDimitry Andric   if (!CI->use_empty())
31780b57cec5SDimitry Andric     return nullptr;
31790b57cec5SDimitry Andric 
3180bdd1243dSDimitry Andric   Type *IntTy = CI->getType();
31810b57cec5SDimitry Andric   // printf("x") -> putchar('x'), even for "%" and "%%".
3182bdd1243dSDimitry Andric   if (FormatStr.size() == 1 || FormatStr == "%%") {
3183bdd1243dSDimitry Andric     // Convert the character to unsigned char before passing it to putchar
3184bdd1243dSDimitry Andric     // to avoid host-specific sign extension in the IR.  Putchar converts
3185bdd1243dSDimitry Andric     // it to unsigned char regardless.
3186bdd1243dSDimitry Andric     Value *IntChar = ConstantInt::get(IntTy, (unsigned char)FormatStr[0]);
3187bdd1243dSDimitry Andric     return copyFlags(*CI, emitPutChar(IntChar, B, TLI));
3188bdd1243dSDimitry Andric   }
31890b57cec5SDimitry Andric 
3190fe6060f1SDimitry Andric   // Try to remove call or emit putchar/puts.
3191349cc55cSDimitry Andric   if (FormatStr == "%s" && CI->arg_size() > 1) {
3192fe6060f1SDimitry Andric     StringRef OperandStr;
3193fe6060f1SDimitry Andric     if (!getConstantStringInfo(CI->getOperand(1), OperandStr))
31940b57cec5SDimitry Andric       return nullptr;
3195fe6060f1SDimitry Andric     // printf("%s", "") --> NOP
3196fe6060f1SDimitry Andric     if (OperandStr.empty())
3197fe6060f1SDimitry Andric       return (Value *)CI;
3198fe6060f1SDimitry Andric     // printf("%s", "a") --> putchar('a')
3199bdd1243dSDimitry Andric     if (OperandStr.size() == 1) {
3200bdd1243dSDimitry Andric       // Convert the character to unsigned char before passing it to putchar
3201bdd1243dSDimitry Andric       // to avoid host-specific sign extension in the IR.  Putchar converts
3202bdd1243dSDimitry Andric       // it to unsigned char regardless.
3203bdd1243dSDimitry Andric       Value *IntChar = ConstantInt::get(IntTy, (unsigned char)OperandStr[0]);
3204bdd1243dSDimitry Andric       return copyFlags(*CI, emitPutChar(IntChar, B, TLI));
3205bdd1243dSDimitry Andric     }
3206fe6060f1SDimitry Andric     // printf("%s", str"\n") --> puts(str)
3207fe6060f1SDimitry Andric     if (OperandStr.back() == '\n') {
3208fe6060f1SDimitry Andric       OperandStr = OperandStr.drop_back();
3209fe6060f1SDimitry Andric       Value *GV = B.CreateGlobalString(OperandStr, "str");
32100eae32dcSDimitry Andric       return copyFlags(*CI, emitPutS(GV, B, TLI));
3211fe6060f1SDimitry Andric     }
32120b57cec5SDimitry Andric     return nullptr;
32130b57cec5SDimitry Andric   }
32140b57cec5SDimitry Andric 
32150b57cec5SDimitry Andric   // printf("foo\n") --> puts("foo")
3216fe6060f1SDimitry Andric   if (FormatStr.back() == '\n' &&
3217349cc55cSDimitry Andric       !FormatStr.contains('%')) { // No format characters.
32180b57cec5SDimitry Andric     // Create a string literal with no \n on it.  We expect the constant merge
32190b57cec5SDimitry Andric     // pass to be run after this pass, to merge duplicate strings.
32200b57cec5SDimitry Andric     FormatStr = FormatStr.drop_back();
32210b57cec5SDimitry Andric     Value *GV = B.CreateGlobalString(FormatStr, "str");
32220eae32dcSDimitry Andric     return copyFlags(*CI, emitPutS(GV, B, TLI));
32230b57cec5SDimitry Andric   }
32240b57cec5SDimitry Andric 
32250b57cec5SDimitry Andric   // Optimize specific format strings.
32260b57cec5SDimitry Andric   // printf("%c", chr) --> putchar(chr)
3227349cc55cSDimitry Andric   if (FormatStr == "%c" && CI->arg_size() > 1 &&
3228bdd1243dSDimitry Andric       CI->getArgOperand(1)->getType()->isIntegerTy()) {
3229bdd1243dSDimitry Andric     // Convert the argument to the type expected by putchar, i.e., int, which
3230bdd1243dSDimitry Andric     // need not be 32 bits wide but which is the same as printf's return type.
3231bdd1243dSDimitry Andric     Value *IntChar = B.CreateIntCast(CI->getArgOperand(1), IntTy, false);
3232bdd1243dSDimitry Andric     return copyFlags(*CI, emitPutChar(IntChar, B, TLI));
3233bdd1243dSDimitry Andric   }
32340b57cec5SDimitry Andric 
32350b57cec5SDimitry Andric   // printf("%s\n", str) --> puts(str)
3236349cc55cSDimitry Andric   if (FormatStr == "%s\n" && CI->arg_size() > 1 &&
32370b57cec5SDimitry Andric       CI->getArgOperand(1)->getType()->isPointerTy())
32380eae32dcSDimitry Andric     return copyFlags(*CI, emitPutS(CI->getArgOperand(1), B, TLI));
32390b57cec5SDimitry Andric   return nullptr;
32400b57cec5SDimitry Andric }
32410b57cec5SDimitry Andric 
32425ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizePrintF(CallInst *CI, IRBuilderBase &B) {
32430b57cec5SDimitry Andric 
324481ad6265SDimitry Andric   Module *M = CI->getModule();
32450b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
32460b57cec5SDimitry Andric   FunctionType *FT = Callee->getFunctionType();
32470b57cec5SDimitry Andric   if (Value *V = optimizePrintFString(CI, B)) {
32480b57cec5SDimitry Andric     return V;
32490b57cec5SDimitry Andric   }
32500b57cec5SDimitry Andric 
3251bdd1243dSDimitry Andric   annotateNonNullNoUndefBasedOnAccess(CI, 0);
3252bdd1243dSDimitry Andric 
32530b57cec5SDimitry Andric   // printf(format, ...) -> iprintf(format, ...) if no floating point
32540b57cec5SDimitry Andric   // arguments.
325581ad6265SDimitry Andric   if (isLibFuncEmittable(M, TLI, LibFunc_iprintf) &&
325681ad6265SDimitry Andric       !callHasFloatingPointArgument(CI)) {
325781ad6265SDimitry Andric     FunctionCallee IPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_iprintf, FT,
325881ad6265SDimitry Andric                                                   Callee->getAttributes());
32590b57cec5SDimitry Andric     CallInst *New = cast<CallInst>(CI->clone());
32600b57cec5SDimitry Andric     New->setCalledFunction(IPrintFFn);
32610b57cec5SDimitry Andric     B.Insert(New);
32620b57cec5SDimitry Andric     return New;
32630b57cec5SDimitry Andric   }
32640b57cec5SDimitry Andric 
32650b57cec5SDimitry Andric   // printf(format, ...) -> __small_printf(format, ...) if no 128-bit floating point
32660b57cec5SDimitry Andric   // arguments.
326781ad6265SDimitry Andric   if (isLibFuncEmittable(M, TLI, LibFunc_small_printf) &&
326881ad6265SDimitry Andric       !callHasFP128Argument(CI)) {
326981ad6265SDimitry Andric     auto SmallPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_small_printf, FT,
327081ad6265SDimitry Andric                                             Callee->getAttributes());
32710b57cec5SDimitry Andric     CallInst *New = cast<CallInst>(CI->clone());
32720b57cec5SDimitry Andric     New->setCalledFunction(SmallPrintFFn);
32730b57cec5SDimitry Andric     B.Insert(New);
32740b57cec5SDimitry Andric     return New;
32750b57cec5SDimitry Andric   }
32760b57cec5SDimitry Andric 
32770b57cec5SDimitry Andric   return nullptr;
32780b57cec5SDimitry Andric }
32790b57cec5SDimitry Andric 
32805ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeSPrintFString(CallInst *CI,
32815ffd83dbSDimitry Andric                                                 IRBuilderBase &B) {
32820b57cec5SDimitry Andric   // Check for a fixed format string.
32830b57cec5SDimitry Andric   StringRef FormatStr;
32840b57cec5SDimitry Andric   if (!getConstantStringInfo(CI->getArgOperand(1), FormatStr))
32850b57cec5SDimitry Andric     return nullptr;
32860b57cec5SDimitry Andric 
32870b57cec5SDimitry Andric   // If we just have a format string (nothing else crazy) transform it.
3288fe6060f1SDimitry Andric   Value *Dest = CI->getArgOperand(0);
3289349cc55cSDimitry Andric   if (CI->arg_size() == 2) {
32900b57cec5SDimitry Andric     // Make sure there's no % in the constant array.  We could try to handle
32910b57cec5SDimitry Andric     // %% -> % in the future if we cared.
3292349cc55cSDimitry Andric     if (FormatStr.contains('%'))
32930b57cec5SDimitry Andric       return nullptr; // we found a format specifier, bail out.
32940b57cec5SDimitry Andric 
32950b57cec5SDimitry Andric     // sprintf(str, fmt) -> llvm.memcpy(align 1 str, align 1 fmt, strlen(fmt)+1)
3296480093f4SDimitry Andric     B.CreateMemCpy(
3297fe6060f1SDimitry Andric         Dest, Align(1), CI->getArgOperand(1), Align(1),
32980b57cec5SDimitry Andric         ConstantInt::get(DL.getIntPtrType(CI->getContext()),
32990b57cec5SDimitry Andric                          FormatStr.size() + 1)); // Copy the null byte.
33000b57cec5SDimitry Andric     return ConstantInt::get(CI->getType(), FormatStr.size());
33010b57cec5SDimitry Andric   }
33020b57cec5SDimitry Andric 
33030b57cec5SDimitry Andric   // The remaining optimizations require the format string to be "%s" or "%c"
33040b57cec5SDimitry Andric   // and have an extra operand.
3305349cc55cSDimitry Andric   if (FormatStr.size() != 2 || FormatStr[0] != '%' || CI->arg_size() < 3)
33060b57cec5SDimitry Andric     return nullptr;
33070b57cec5SDimitry Andric 
33080b57cec5SDimitry Andric   // Decode the second character of the format string.
33090b57cec5SDimitry Andric   if (FormatStr[1] == 'c') {
33100b57cec5SDimitry Andric     // sprintf(dst, "%c", chr) --> *(i8*)dst = chr; *((i8*)dst+1) = 0
33110b57cec5SDimitry Andric     if (!CI->getArgOperand(2)->getType()->isIntegerTy())
33120b57cec5SDimitry Andric       return nullptr;
33130b57cec5SDimitry Andric     Value *V = B.CreateTrunc(CI->getArgOperand(2), B.getInt8Ty(), "char");
33145f757f3fSDimitry Andric     Value *Ptr = Dest;
33150b57cec5SDimitry Andric     B.CreateStore(V, Ptr);
331681ad6265SDimitry Andric     Ptr = B.CreateInBoundsGEP(B.getInt8Ty(), Ptr, B.getInt32(1), "nul");
33170b57cec5SDimitry Andric     B.CreateStore(B.getInt8(0), Ptr);
33180b57cec5SDimitry Andric 
33190b57cec5SDimitry Andric     return ConstantInt::get(CI->getType(), 1);
33200b57cec5SDimitry Andric   }
33210b57cec5SDimitry Andric 
33220b57cec5SDimitry Andric   if (FormatStr[1] == 's') {
33230b57cec5SDimitry Andric     // sprintf(dest, "%s", str) -> llvm.memcpy(align 1 dest, align 1 str,
33240b57cec5SDimitry Andric     // strlen(str)+1)
33250b57cec5SDimitry Andric     if (!CI->getArgOperand(2)->getType()->isPointerTy())
33260b57cec5SDimitry Andric       return nullptr;
33270b57cec5SDimitry Andric 
3328e8d8bef9SDimitry Andric     if (CI->use_empty())
3329e8d8bef9SDimitry Andric       // sprintf(dest, "%s", str) -> strcpy(dest, str)
33300eae32dcSDimitry Andric       return copyFlags(*CI, emitStrCpy(Dest, CI->getArgOperand(2), B, TLI));
3331e8d8bef9SDimitry Andric 
3332e8d8bef9SDimitry Andric     uint64_t SrcLen = GetStringLength(CI->getArgOperand(2));
3333e8d8bef9SDimitry Andric     if (SrcLen) {
3334e8d8bef9SDimitry Andric       B.CreateMemCpy(
3335fe6060f1SDimitry Andric           Dest, Align(1), CI->getArgOperand(2), Align(1),
3336e8d8bef9SDimitry Andric           ConstantInt::get(DL.getIntPtrType(CI->getContext()), SrcLen));
3337e8d8bef9SDimitry Andric       // Returns total number of characters written without null-character.
3338e8d8bef9SDimitry Andric       return ConstantInt::get(CI->getType(), SrcLen - 1);
3339fe6060f1SDimitry Andric     } else if (Value *V = emitStpCpy(Dest, CI->getArgOperand(2), B, TLI)) {
3340e8d8bef9SDimitry Andric       // sprintf(dest, "%s", str) -> stpcpy(dest, str) - dest
334104eeddc0SDimitry Andric       Value *PtrDiff = B.CreatePtrDiff(B.getInt8Ty(), V, Dest);
3342e8d8bef9SDimitry Andric       return B.CreateIntCast(PtrDiff, CI->getType(), false);
3343e8d8bef9SDimitry Andric     }
3344e8d8bef9SDimitry Andric 
3345e8d8bef9SDimitry Andric     bool OptForSize = CI->getFunction()->hasOptSize() ||
3346e8d8bef9SDimitry Andric                       llvm::shouldOptimizeForSize(CI->getParent(), PSI, BFI,
3347e8d8bef9SDimitry Andric                                                   PGSOQueryType::IRPass);
3348e8d8bef9SDimitry Andric     if (OptForSize)
3349e8d8bef9SDimitry Andric       return nullptr;
3350e8d8bef9SDimitry Andric 
33510b57cec5SDimitry Andric     Value *Len = emitStrLen(CI->getArgOperand(2), B, DL, TLI);
33520b57cec5SDimitry Andric     if (!Len)
33530b57cec5SDimitry Andric       return nullptr;
33540b57cec5SDimitry Andric     Value *IncLen =
33550b57cec5SDimitry Andric         B.CreateAdd(Len, ConstantInt::get(Len->getType(), 1), "leninc");
3356fe6060f1SDimitry Andric     B.CreateMemCpy(Dest, Align(1), CI->getArgOperand(2), Align(1), IncLen);
33570b57cec5SDimitry Andric 
33580b57cec5SDimitry Andric     // The sprintf result is the unincremented number of bytes in the string.
33590b57cec5SDimitry Andric     return B.CreateIntCast(Len, CI->getType(), false);
33600b57cec5SDimitry Andric   }
33610b57cec5SDimitry Andric   return nullptr;
33620b57cec5SDimitry Andric }
33630b57cec5SDimitry Andric 
33645ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeSPrintF(CallInst *CI, IRBuilderBase &B) {
336581ad6265SDimitry Andric   Module *M = CI->getModule();
33660b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
33670b57cec5SDimitry Andric   FunctionType *FT = Callee->getFunctionType();
33680b57cec5SDimitry Andric   if (Value *V = optimizeSPrintFString(CI, B)) {
33690b57cec5SDimitry Andric     return V;
33700b57cec5SDimitry Andric   }
33710b57cec5SDimitry Andric 
3372bdd1243dSDimitry Andric   annotateNonNullNoUndefBasedOnAccess(CI, {0, 1});
3373bdd1243dSDimitry Andric 
33740b57cec5SDimitry Andric   // sprintf(str, format, ...) -> siprintf(str, format, ...) if no floating
33750b57cec5SDimitry Andric   // point arguments.
337681ad6265SDimitry Andric   if (isLibFuncEmittable(M, TLI, LibFunc_siprintf) &&
337781ad6265SDimitry Andric       !callHasFloatingPointArgument(CI)) {
337881ad6265SDimitry Andric     FunctionCallee SIPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_siprintf,
337981ad6265SDimitry Andric                                                    FT, Callee->getAttributes());
33800b57cec5SDimitry Andric     CallInst *New = cast<CallInst>(CI->clone());
33810b57cec5SDimitry Andric     New->setCalledFunction(SIPrintFFn);
33820b57cec5SDimitry Andric     B.Insert(New);
33830b57cec5SDimitry Andric     return New;
33840b57cec5SDimitry Andric   }
33850b57cec5SDimitry Andric 
33860b57cec5SDimitry Andric   // sprintf(str, format, ...) -> __small_sprintf(str, format, ...) if no 128-bit
33870b57cec5SDimitry Andric   // floating point arguments.
338881ad6265SDimitry Andric   if (isLibFuncEmittable(M, TLI, LibFunc_small_sprintf) &&
338981ad6265SDimitry Andric       !callHasFP128Argument(CI)) {
339081ad6265SDimitry Andric     auto SmallSPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_small_sprintf, FT,
339181ad6265SDimitry Andric                                              Callee->getAttributes());
33920b57cec5SDimitry Andric     CallInst *New = cast<CallInst>(CI->clone());
33930b57cec5SDimitry Andric     New->setCalledFunction(SmallSPrintFFn);
33940b57cec5SDimitry Andric     B.Insert(New);
33950b57cec5SDimitry Andric     return New;
33960b57cec5SDimitry Andric   }
33970b57cec5SDimitry Andric 
33980b57cec5SDimitry Andric   return nullptr;
33990b57cec5SDimitry Andric }
34000b57cec5SDimitry Andric 
3401bdd1243dSDimitry Andric // Transform an snprintf call CI with the bound N to format the string Str
3402bdd1243dSDimitry Andric // either to a call to memcpy, or to single character a store, or to nothing,
3403bdd1243dSDimitry Andric // and fold the result to a constant.  A nonnull StrArg refers to the string
3404bdd1243dSDimitry Andric // argument being formatted.  Otherwise the call is one with N < 2 and
3405bdd1243dSDimitry Andric // the "%c" directive to format a single character.
3406bdd1243dSDimitry Andric Value *LibCallSimplifier::emitSnPrintfMemCpy(CallInst *CI, Value *StrArg,
3407bdd1243dSDimitry Andric                                              StringRef Str, uint64_t N,
3408bdd1243dSDimitry Andric                                              IRBuilderBase &B) {
3409bdd1243dSDimitry Andric   assert(StrArg || (N < 2 && Str.size() == 1));
3410bdd1243dSDimitry Andric 
3411bdd1243dSDimitry Andric   unsigned IntBits = TLI->getIntSize();
3412bdd1243dSDimitry Andric   uint64_t IntMax = maxIntN(IntBits);
3413bdd1243dSDimitry Andric   if (Str.size() > IntMax)
3414bdd1243dSDimitry Andric     // Bail if the string is longer than INT_MAX.  POSIX requires
3415bdd1243dSDimitry Andric     // implementations to set errno to EOVERFLOW in this case, in
3416bdd1243dSDimitry Andric     // addition to when N is larger than that (checked by the caller).
3417bdd1243dSDimitry Andric     return nullptr;
3418bdd1243dSDimitry Andric 
3419bdd1243dSDimitry Andric   Value *StrLen = ConstantInt::get(CI->getType(), Str.size());
3420bdd1243dSDimitry Andric   if (N == 0)
3421bdd1243dSDimitry Andric     return StrLen;
3422bdd1243dSDimitry Andric 
3423bdd1243dSDimitry Andric   // Set to the number of bytes to copy fron StrArg which is also
3424bdd1243dSDimitry Andric   // the offset of the terinating nul.
3425bdd1243dSDimitry Andric   uint64_t NCopy;
3426bdd1243dSDimitry Andric   if (N > Str.size())
3427bdd1243dSDimitry Andric     // Copy the full string, including the terminating nul (which must
3428bdd1243dSDimitry Andric     // be present regardless of the bound).
3429bdd1243dSDimitry Andric     NCopy = Str.size() + 1;
3430bdd1243dSDimitry Andric   else
3431bdd1243dSDimitry Andric     NCopy = N - 1;
3432bdd1243dSDimitry Andric 
3433bdd1243dSDimitry Andric   Value *DstArg = CI->getArgOperand(0);
3434bdd1243dSDimitry Andric   if (NCopy && StrArg)
3435bdd1243dSDimitry Andric     // Transform the call to lvm.memcpy(dst, fmt, N).
3436bdd1243dSDimitry Andric     copyFlags(
3437bdd1243dSDimitry Andric          *CI,
3438bdd1243dSDimitry Andric           B.CreateMemCpy(
3439bdd1243dSDimitry Andric                          DstArg, Align(1), StrArg, Align(1),
3440bdd1243dSDimitry Andric               ConstantInt::get(DL.getIntPtrType(CI->getContext()), NCopy)));
3441bdd1243dSDimitry Andric 
3442bdd1243dSDimitry Andric   if (N > Str.size())
3443bdd1243dSDimitry Andric     // Return early when the whole format string, including the final nul,
3444bdd1243dSDimitry Andric     // has been copied.
3445bdd1243dSDimitry Andric     return StrLen;
3446bdd1243dSDimitry Andric 
3447bdd1243dSDimitry Andric   // Otherwise, when truncating the string append a terminating nul.
3448bdd1243dSDimitry Andric   Type *Int8Ty = B.getInt8Ty();
3449bdd1243dSDimitry Andric   Value *NulOff = B.getIntN(IntBits, NCopy);
3450bdd1243dSDimitry Andric   Value *DstEnd = B.CreateInBoundsGEP(Int8Ty, DstArg, NulOff, "endptr");
3451bdd1243dSDimitry Andric   B.CreateStore(ConstantInt::get(Int8Ty, 0), DstEnd);
3452bdd1243dSDimitry Andric   return StrLen;
3453bdd1243dSDimitry Andric }
3454bdd1243dSDimitry Andric 
34555ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeSnPrintFString(CallInst *CI,
34565ffd83dbSDimitry Andric                                                  IRBuilderBase &B) {
34570b57cec5SDimitry Andric   // Check for size
34580b57cec5SDimitry Andric   ConstantInt *Size = dyn_cast<ConstantInt>(CI->getArgOperand(1));
34590b57cec5SDimitry Andric   if (!Size)
34600b57cec5SDimitry Andric     return nullptr;
34610b57cec5SDimitry Andric 
34620b57cec5SDimitry Andric   uint64_t N = Size->getZExtValue();
3463bdd1243dSDimitry Andric   uint64_t IntMax = maxIntN(TLI->getIntSize());
3464bdd1243dSDimitry Andric   if (N > IntMax)
3465bdd1243dSDimitry Andric     // Bail if the bound exceeds INT_MAX.  POSIX requires implementations
3466bdd1243dSDimitry Andric     // to set errno to EOVERFLOW in this case.
3467bdd1243dSDimitry Andric     return nullptr;
3468bdd1243dSDimitry Andric 
3469bdd1243dSDimitry Andric   Value *DstArg = CI->getArgOperand(0);
3470bdd1243dSDimitry Andric   Value *FmtArg = CI->getArgOperand(2);
3471bdd1243dSDimitry Andric 
34728bcb0991SDimitry Andric   // Check for a fixed format string.
34738bcb0991SDimitry Andric   StringRef FormatStr;
3474bdd1243dSDimitry Andric   if (!getConstantStringInfo(FmtArg, FormatStr))
34758bcb0991SDimitry Andric     return nullptr;
34760b57cec5SDimitry Andric 
34770b57cec5SDimitry Andric   // If we just have a format string (nothing else crazy) transform it.
3478349cc55cSDimitry Andric   if (CI->arg_size() == 3) {
3479349cc55cSDimitry Andric     if (FormatStr.contains('%'))
3480bdd1243dSDimitry Andric       // Bail if the format string contains a directive and there are
3481bdd1243dSDimitry Andric       // no arguments.  We could handle "%%" in the future.
34820b57cec5SDimitry Andric       return nullptr;
34830b57cec5SDimitry Andric 
3484bdd1243dSDimitry Andric     return emitSnPrintfMemCpy(CI, FmtArg, FormatStr, N, B);
34850b57cec5SDimitry Andric   }
34860b57cec5SDimitry Andric 
34870b57cec5SDimitry Andric   // The remaining optimizations require the format string to be "%s" or "%c"
34880b57cec5SDimitry Andric   // and have an extra operand.
3489bdd1243dSDimitry Andric   if (FormatStr.size() != 2 || FormatStr[0] != '%' || CI->arg_size() != 4)
3490bdd1243dSDimitry Andric     return nullptr;
34910b57cec5SDimitry Andric 
34920b57cec5SDimitry Andric   // Decode the second character of the format string.
34930b57cec5SDimitry Andric   if (FormatStr[1] == 'c') {
3494bdd1243dSDimitry Andric     if (N <= 1) {
3495bdd1243dSDimitry Andric       // Use an arbitary string of length 1 to transform the call into
3496bdd1243dSDimitry Andric       // either a nul store (N == 1) or a no-op (N == 0) and fold it
3497bdd1243dSDimitry Andric       // to one.
3498bdd1243dSDimitry Andric       StringRef CharStr("*");
3499bdd1243dSDimitry Andric       return emitSnPrintfMemCpy(CI, nullptr, CharStr, N, B);
3500bdd1243dSDimitry Andric     }
35010b57cec5SDimitry Andric 
35020b57cec5SDimitry Andric     // snprintf(dst, size, "%c", chr) --> *(i8*)dst = chr; *((i8*)dst+1) = 0
35030b57cec5SDimitry Andric     if (!CI->getArgOperand(3)->getType()->isIntegerTy())
35040b57cec5SDimitry Andric       return nullptr;
35050b57cec5SDimitry Andric     Value *V = B.CreateTrunc(CI->getArgOperand(3), B.getInt8Ty(), "char");
35065f757f3fSDimitry Andric     Value *Ptr = DstArg;
35070b57cec5SDimitry Andric     B.CreateStore(V, Ptr);
350881ad6265SDimitry Andric     Ptr = B.CreateInBoundsGEP(B.getInt8Ty(), Ptr, B.getInt32(1), "nul");
35090b57cec5SDimitry Andric     B.CreateStore(B.getInt8(0), Ptr);
35100b57cec5SDimitry Andric     return ConstantInt::get(CI->getType(), 1);
35110b57cec5SDimitry Andric   }
35120b57cec5SDimitry Andric 
3513bdd1243dSDimitry Andric   if (FormatStr[1] != 's')
3514bdd1243dSDimitry Andric     return nullptr;
3515bdd1243dSDimitry Andric 
3516bdd1243dSDimitry Andric   Value *StrArg = CI->getArgOperand(3);
35170b57cec5SDimitry Andric   // snprintf(dest, size, "%s", str) to llvm.memcpy(dest, str, len+1, 1)
35180b57cec5SDimitry Andric   StringRef Str;
3519bdd1243dSDimitry Andric   if (!getConstantStringInfo(StrArg, Str))
35200b57cec5SDimitry Andric     return nullptr;
35210b57cec5SDimitry Andric 
3522bdd1243dSDimitry Andric   return emitSnPrintfMemCpy(CI, StrArg, Str, N, B);
35230b57cec5SDimitry Andric }
35240b57cec5SDimitry Andric 
35255ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeSnPrintF(CallInst *CI, IRBuilderBase &B) {
35260b57cec5SDimitry Andric   if (Value *V = optimizeSnPrintFString(CI, B)) {
35270b57cec5SDimitry Andric     return V;
35280b57cec5SDimitry Andric   }
35290b57cec5SDimitry Andric 
35308bcb0991SDimitry Andric   if (isKnownNonZero(CI->getOperand(1), DL))
3531fe6060f1SDimitry Andric     annotateNonNullNoUndefBasedOnAccess(CI, 0);
35320b57cec5SDimitry Andric   return nullptr;
35330b57cec5SDimitry Andric }
35340b57cec5SDimitry Andric 
35355ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeFPrintFString(CallInst *CI,
35365ffd83dbSDimitry Andric                                                 IRBuilderBase &B) {
35370b57cec5SDimitry Andric   optimizeErrorReporting(CI, B, 0);
35380b57cec5SDimitry Andric 
35390b57cec5SDimitry Andric   // All the optimizations depend on the format string.
35400b57cec5SDimitry Andric   StringRef FormatStr;
35410b57cec5SDimitry Andric   if (!getConstantStringInfo(CI->getArgOperand(1), FormatStr))
35420b57cec5SDimitry Andric     return nullptr;
35430b57cec5SDimitry Andric 
35440b57cec5SDimitry Andric   // Do not do any of the following transformations if the fprintf return
35450b57cec5SDimitry Andric   // value is used, in general the fprintf return value is not compatible
35460b57cec5SDimitry Andric   // with fwrite(), fputc() or fputs().
35470b57cec5SDimitry Andric   if (!CI->use_empty())
35480b57cec5SDimitry Andric     return nullptr;
35490b57cec5SDimitry Andric 
35500b57cec5SDimitry Andric   // fprintf(F, "foo") --> fwrite("foo", 3, 1, F)
3551349cc55cSDimitry Andric   if (CI->arg_size() == 2) {
35520b57cec5SDimitry Andric     // Could handle %% -> % if we cared.
3553349cc55cSDimitry Andric     if (FormatStr.contains('%'))
35540b57cec5SDimitry Andric       return nullptr; // We found a format specifier.
35550b57cec5SDimitry Andric 
3556bdd1243dSDimitry Andric     unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule());
3557bdd1243dSDimitry Andric     Type *SizeTTy = IntegerType::get(CI->getContext(), SizeTBits);
35580eae32dcSDimitry Andric     return copyFlags(
35590eae32dcSDimitry Andric         *CI, emitFWrite(CI->getArgOperand(1),
3560bdd1243dSDimitry Andric                         ConstantInt::get(SizeTTy, FormatStr.size()),
35610eae32dcSDimitry Andric                         CI->getArgOperand(0), B, DL, TLI));
35620b57cec5SDimitry Andric   }
35630b57cec5SDimitry Andric 
35640b57cec5SDimitry Andric   // The remaining optimizations require the format string to be "%s" or "%c"
35650b57cec5SDimitry Andric   // and have an extra operand.
3566349cc55cSDimitry Andric   if (FormatStr.size() != 2 || FormatStr[0] != '%' || CI->arg_size() < 3)
35670b57cec5SDimitry Andric     return nullptr;
35680b57cec5SDimitry Andric 
35690b57cec5SDimitry Andric   // Decode the second character of the format string.
35700b57cec5SDimitry Andric   if (FormatStr[1] == 'c') {
3571bdd1243dSDimitry Andric     // fprintf(F, "%c", chr) --> fputc((int)chr, F)
35720b57cec5SDimitry Andric     if (!CI->getArgOperand(2)->getType()->isIntegerTy())
35730b57cec5SDimitry Andric       return nullptr;
3574bdd1243dSDimitry Andric     Type *IntTy = B.getIntNTy(TLI->getIntSize());
3575bdd1243dSDimitry Andric     Value *V = B.CreateIntCast(CI->getArgOperand(2), IntTy, /*isSigned*/ true,
3576bdd1243dSDimitry Andric                                "chari");
3577bdd1243dSDimitry Andric     return copyFlags(*CI, emitFPutC(V, CI->getArgOperand(0), B, TLI));
35780b57cec5SDimitry Andric   }
35790b57cec5SDimitry Andric 
35800b57cec5SDimitry Andric   if (FormatStr[1] == 's') {
35810b57cec5SDimitry Andric     // fprintf(F, "%s", str) --> fputs(str, F)
35820b57cec5SDimitry Andric     if (!CI->getArgOperand(2)->getType()->isPointerTy())
35830b57cec5SDimitry Andric       return nullptr;
35840eae32dcSDimitry Andric     return copyFlags(
35850eae32dcSDimitry Andric         *CI, emitFPutS(CI->getArgOperand(2), CI->getArgOperand(0), B, TLI));
35860b57cec5SDimitry Andric   }
35870b57cec5SDimitry Andric   return nullptr;
35880b57cec5SDimitry Andric }
35890b57cec5SDimitry Andric 
35905ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeFPrintF(CallInst *CI, IRBuilderBase &B) {
359181ad6265SDimitry Andric   Module *M = CI->getModule();
35920b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
35930b57cec5SDimitry Andric   FunctionType *FT = Callee->getFunctionType();
35940b57cec5SDimitry Andric   if (Value *V = optimizeFPrintFString(CI, B)) {
35950b57cec5SDimitry Andric     return V;
35960b57cec5SDimitry Andric   }
35970b57cec5SDimitry Andric 
35980b57cec5SDimitry Andric   // fprintf(stream, format, ...) -> fiprintf(stream, format, ...) if no
35990b57cec5SDimitry Andric   // floating point arguments.
360081ad6265SDimitry Andric   if (isLibFuncEmittable(M, TLI, LibFunc_fiprintf) &&
360181ad6265SDimitry Andric       !callHasFloatingPointArgument(CI)) {
360281ad6265SDimitry Andric     FunctionCallee FIPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_fiprintf,
360381ad6265SDimitry Andric                                                    FT, Callee->getAttributes());
36040b57cec5SDimitry Andric     CallInst *New = cast<CallInst>(CI->clone());
36050b57cec5SDimitry Andric     New->setCalledFunction(FIPrintFFn);
36060b57cec5SDimitry Andric     B.Insert(New);
36070b57cec5SDimitry Andric     return New;
36080b57cec5SDimitry Andric   }
36090b57cec5SDimitry Andric 
36100b57cec5SDimitry Andric   // fprintf(stream, format, ...) -> __small_fprintf(stream, format, ...) if no
36110b57cec5SDimitry Andric   // 128-bit floating point arguments.
361281ad6265SDimitry Andric   if (isLibFuncEmittable(M, TLI, LibFunc_small_fprintf) &&
361381ad6265SDimitry Andric       !callHasFP128Argument(CI)) {
36140b57cec5SDimitry Andric     auto SmallFPrintFFn =
361581ad6265SDimitry Andric         getOrInsertLibFunc(M, *TLI, LibFunc_small_fprintf, FT,
361681ad6265SDimitry Andric                            Callee->getAttributes());
36170b57cec5SDimitry Andric     CallInst *New = cast<CallInst>(CI->clone());
36180b57cec5SDimitry Andric     New->setCalledFunction(SmallFPrintFFn);
36190b57cec5SDimitry Andric     B.Insert(New);
36200b57cec5SDimitry Andric     return New;
36210b57cec5SDimitry Andric   }
36220b57cec5SDimitry Andric 
36230b57cec5SDimitry Andric   return nullptr;
36240b57cec5SDimitry Andric }
36250b57cec5SDimitry Andric 
36265ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeFWrite(CallInst *CI, IRBuilderBase &B) {
36270b57cec5SDimitry Andric   optimizeErrorReporting(CI, B, 3);
36280b57cec5SDimitry Andric 
36290b57cec5SDimitry Andric   // Get the element size and count.
36300b57cec5SDimitry Andric   ConstantInt *SizeC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
36310b57cec5SDimitry Andric   ConstantInt *CountC = dyn_cast<ConstantInt>(CI->getArgOperand(2));
36320b57cec5SDimitry Andric   if (SizeC && CountC) {
36330b57cec5SDimitry Andric     uint64_t Bytes = SizeC->getZExtValue() * CountC->getZExtValue();
36340b57cec5SDimitry Andric 
36350b57cec5SDimitry Andric     // If this is writing zero records, remove the call (it's a noop).
36360b57cec5SDimitry Andric     if (Bytes == 0)
36370b57cec5SDimitry Andric       return ConstantInt::get(CI->getType(), 0);
36380b57cec5SDimitry Andric 
36390b57cec5SDimitry Andric     // If this is writing one byte, turn it into fputc.
36400b57cec5SDimitry Andric     // This optimisation is only valid, if the return value is unused.
36410b57cec5SDimitry Andric     if (Bytes == 1 && CI->use_empty()) { // fwrite(S,1,1,F) -> fputc(S[0],F)
36425f757f3fSDimitry Andric       Value *Char = B.CreateLoad(B.getInt8Ty(), CI->getArgOperand(0), "char");
3643bdd1243dSDimitry Andric       Type *IntTy = B.getIntNTy(TLI->getIntSize());
3644bdd1243dSDimitry Andric       Value *Cast = B.CreateIntCast(Char, IntTy, /*isSigned*/ true, "chari");
3645bdd1243dSDimitry Andric       Value *NewCI = emitFPutC(Cast, CI->getArgOperand(3), B, TLI);
36460b57cec5SDimitry Andric       return NewCI ? ConstantInt::get(CI->getType(), 1) : nullptr;
36470b57cec5SDimitry Andric     }
36480b57cec5SDimitry Andric   }
36490b57cec5SDimitry Andric 
36500b57cec5SDimitry Andric   return nullptr;
36510b57cec5SDimitry Andric }
36520b57cec5SDimitry Andric 
36535ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeFPuts(CallInst *CI, IRBuilderBase &B) {
36540b57cec5SDimitry Andric   optimizeErrorReporting(CI, B, 1);
36550b57cec5SDimitry Andric 
36560b57cec5SDimitry Andric   // Don't rewrite fputs to fwrite when optimising for size because fwrite
36570b57cec5SDimitry Andric   // requires more arguments and thus extra MOVs are required.
36580b57cec5SDimitry Andric   bool OptForSize = CI->getFunction()->hasOptSize() ||
3659480093f4SDimitry Andric                     llvm::shouldOptimizeForSize(CI->getParent(), PSI, BFI,
3660480093f4SDimitry Andric                                                 PGSOQueryType::IRPass);
36610b57cec5SDimitry Andric   if (OptForSize)
36620b57cec5SDimitry Andric     return nullptr;
36630b57cec5SDimitry Andric 
36640b57cec5SDimitry Andric   // We can't optimize if return value is used.
36655ffd83dbSDimitry Andric   if (!CI->use_empty())
36660b57cec5SDimitry Andric     return nullptr;
36670b57cec5SDimitry Andric 
36680b57cec5SDimitry Andric   // fputs(s,F) --> fwrite(s,strlen(s),1,F)
36690b57cec5SDimitry Andric   uint64_t Len = GetStringLength(CI->getArgOperand(0));
36700b57cec5SDimitry Andric   if (!Len)
36710b57cec5SDimitry Andric     return nullptr;
36720b57cec5SDimitry Andric 
36730b57cec5SDimitry Andric   // Known to have no uses (see above).
3674bdd1243dSDimitry Andric   unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule());
3675bdd1243dSDimitry Andric   Type *SizeTTy = IntegerType::get(CI->getContext(), SizeTBits);
36760eae32dcSDimitry Andric   return copyFlags(
36770eae32dcSDimitry Andric       *CI,
36780eae32dcSDimitry Andric       emitFWrite(CI->getArgOperand(0),
3679bdd1243dSDimitry Andric                  ConstantInt::get(SizeTTy, Len - 1),
36800eae32dcSDimitry Andric                  CI->getArgOperand(1), B, DL, TLI));
36810b57cec5SDimitry Andric }
36820b57cec5SDimitry Andric 
36835ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizePuts(CallInst *CI, IRBuilderBase &B) {
3684fe6060f1SDimitry Andric   annotateNonNullNoUndefBasedOnAccess(CI, 0);
36850b57cec5SDimitry Andric   if (!CI->use_empty())
36860b57cec5SDimitry Andric     return nullptr;
36870b57cec5SDimitry Andric 
36880b57cec5SDimitry Andric   // Check for a constant string.
36890b57cec5SDimitry Andric   // puts("") -> putchar('\n')
36900b57cec5SDimitry Andric   StringRef Str;
3691bdd1243dSDimitry Andric   if (getConstantStringInfo(CI->getArgOperand(0), Str) && Str.empty()) {
3692bdd1243dSDimitry Andric     // putchar takes an argument of the same type as puts returns, i.e.,
3693bdd1243dSDimitry Andric     // int, which need not be 32 bits wide.
3694bdd1243dSDimitry Andric     Type *IntTy = CI->getType();
3695bdd1243dSDimitry Andric     return copyFlags(*CI, emitPutChar(ConstantInt::get(IntTy, '\n'), B, TLI));
3696bdd1243dSDimitry Andric   }
36970b57cec5SDimitry Andric 
36980b57cec5SDimitry Andric   return nullptr;
36990b57cec5SDimitry Andric }
37000b57cec5SDimitry Andric 
37015ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeBCopy(CallInst *CI, IRBuilderBase &B) {
37028bcb0991SDimitry Andric   // bcopy(src, dst, n) -> llvm.memmove(dst, src, n)
37030eae32dcSDimitry Andric   return copyFlags(*CI, B.CreateMemMove(CI->getArgOperand(1), Align(1),
37040eae32dcSDimitry Andric                                         CI->getArgOperand(0), Align(1),
37050eae32dcSDimitry Andric                                         CI->getArgOperand(2)));
37068bcb0991SDimitry Andric }
37078bcb0991SDimitry Andric 
370881ad6265SDimitry Andric bool LibCallSimplifier::hasFloatVersion(const Module *M, StringRef FuncName) {
37090b57cec5SDimitry Andric   SmallString<20> FloatFuncName = FuncName;
37100b57cec5SDimitry Andric   FloatFuncName += 'f';
371181ad6265SDimitry Andric   return isLibFuncEmittable(M, TLI, FloatFuncName);
37120b57cec5SDimitry Andric }
37130b57cec5SDimitry Andric 
37140b57cec5SDimitry Andric Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI,
37155ffd83dbSDimitry Andric                                                       IRBuilderBase &Builder) {
371681ad6265SDimitry Andric   Module *M = CI->getModule();
37170b57cec5SDimitry Andric   LibFunc Func;
37180b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
37190b57cec5SDimitry Andric   // Check for string/memory library functions.
372081ad6265SDimitry Andric   if (TLI->getLibFunc(*Callee, Func) && isLibFuncEmittable(M, TLI, Func)) {
37210b57cec5SDimitry Andric     // Make sure we never change the calling convention.
3722fe6060f1SDimitry Andric     assert(
3723fe6060f1SDimitry Andric         (ignoreCallingConv(Func) ||
3724fe6060f1SDimitry Andric          TargetLibraryInfoImpl::isCallingConvCCompatible(CI)) &&
37250b57cec5SDimitry Andric         "Optimizing string/memory libcall would change the calling convention");
37260b57cec5SDimitry Andric     switch (Func) {
37270b57cec5SDimitry Andric     case LibFunc_strcat:
37280b57cec5SDimitry Andric       return optimizeStrCat(CI, Builder);
37290b57cec5SDimitry Andric     case LibFunc_strncat:
37300b57cec5SDimitry Andric       return optimizeStrNCat(CI, Builder);
37310b57cec5SDimitry Andric     case LibFunc_strchr:
37320b57cec5SDimitry Andric       return optimizeStrChr(CI, Builder);
37330b57cec5SDimitry Andric     case LibFunc_strrchr:
37340b57cec5SDimitry Andric       return optimizeStrRChr(CI, Builder);
37350b57cec5SDimitry Andric     case LibFunc_strcmp:
37360b57cec5SDimitry Andric       return optimizeStrCmp(CI, Builder);
37370b57cec5SDimitry Andric     case LibFunc_strncmp:
37380b57cec5SDimitry Andric       return optimizeStrNCmp(CI, Builder);
37390b57cec5SDimitry Andric     case LibFunc_strcpy:
37400b57cec5SDimitry Andric       return optimizeStrCpy(CI, Builder);
37410b57cec5SDimitry Andric     case LibFunc_stpcpy:
37420b57cec5SDimitry Andric       return optimizeStpCpy(CI, Builder);
3743bdd1243dSDimitry Andric     case LibFunc_strlcpy:
3744bdd1243dSDimitry Andric       return optimizeStrLCpy(CI, Builder);
3745bdd1243dSDimitry Andric     case LibFunc_stpncpy:
3746bdd1243dSDimitry Andric       return optimizeStringNCpy(CI, /*RetEnd=*/true, Builder);
37470b57cec5SDimitry Andric     case LibFunc_strncpy:
3748bdd1243dSDimitry Andric       return optimizeStringNCpy(CI, /*RetEnd=*/false, Builder);
37490b57cec5SDimitry Andric     case LibFunc_strlen:
37500b57cec5SDimitry Andric       return optimizeStrLen(CI, Builder);
375181ad6265SDimitry Andric     case LibFunc_strnlen:
375281ad6265SDimitry Andric       return optimizeStrNLen(CI, Builder);
37530b57cec5SDimitry Andric     case LibFunc_strpbrk:
37540b57cec5SDimitry Andric       return optimizeStrPBrk(CI, Builder);
37558bcb0991SDimitry Andric     case LibFunc_strndup:
37568bcb0991SDimitry Andric       return optimizeStrNDup(CI, Builder);
37570b57cec5SDimitry Andric     case LibFunc_strtol:
37580b57cec5SDimitry Andric     case LibFunc_strtod:
37590b57cec5SDimitry Andric     case LibFunc_strtof:
37600b57cec5SDimitry Andric     case LibFunc_strtoul:
37610b57cec5SDimitry Andric     case LibFunc_strtoll:
37620b57cec5SDimitry Andric     case LibFunc_strtold:
37630b57cec5SDimitry Andric     case LibFunc_strtoull:
37640b57cec5SDimitry Andric       return optimizeStrTo(CI, Builder);
37650b57cec5SDimitry Andric     case LibFunc_strspn:
37660b57cec5SDimitry Andric       return optimizeStrSpn(CI, Builder);
37670b57cec5SDimitry Andric     case LibFunc_strcspn:
37680b57cec5SDimitry Andric       return optimizeStrCSpn(CI, Builder);
37690b57cec5SDimitry Andric     case LibFunc_strstr:
37700b57cec5SDimitry Andric       return optimizeStrStr(CI, Builder);
37710b57cec5SDimitry Andric     case LibFunc_memchr:
37720b57cec5SDimitry Andric       return optimizeMemChr(CI, Builder);
37738bcb0991SDimitry Andric     case LibFunc_memrchr:
37748bcb0991SDimitry Andric       return optimizeMemRChr(CI, Builder);
37750b57cec5SDimitry Andric     case LibFunc_bcmp:
37760b57cec5SDimitry Andric       return optimizeBCmp(CI, Builder);
37770b57cec5SDimitry Andric     case LibFunc_memcmp:
37780b57cec5SDimitry Andric       return optimizeMemCmp(CI, Builder);
37790b57cec5SDimitry Andric     case LibFunc_memcpy:
37800b57cec5SDimitry Andric       return optimizeMemCpy(CI, Builder);
3781480093f4SDimitry Andric     case LibFunc_memccpy:
3782480093f4SDimitry Andric       return optimizeMemCCpy(CI, Builder);
37838bcb0991SDimitry Andric     case LibFunc_mempcpy:
37848bcb0991SDimitry Andric       return optimizeMemPCpy(CI, Builder);
37850b57cec5SDimitry Andric     case LibFunc_memmove:
37860b57cec5SDimitry Andric       return optimizeMemMove(CI, Builder);
37870b57cec5SDimitry Andric     case LibFunc_memset:
37880b57cec5SDimitry Andric       return optimizeMemSet(CI, Builder);
37890b57cec5SDimitry Andric     case LibFunc_realloc:
37900b57cec5SDimitry Andric       return optimizeRealloc(CI, Builder);
37910b57cec5SDimitry Andric     case LibFunc_wcslen:
37920b57cec5SDimitry Andric       return optimizeWcslen(CI, Builder);
37938bcb0991SDimitry Andric     case LibFunc_bcopy:
37948bcb0991SDimitry Andric       return optimizeBCopy(CI, Builder);
379506c3fb27SDimitry Andric     case LibFunc_Znwm:
379606c3fb27SDimitry Andric     case LibFunc_ZnwmRKSt9nothrow_t:
379706c3fb27SDimitry Andric     case LibFunc_ZnwmSt11align_val_t:
379806c3fb27SDimitry Andric     case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t:
379906c3fb27SDimitry Andric     case LibFunc_Znam:
380006c3fb27SDimitry Andric     case LibFunc_ZnamRKSt9nothrow_t:
380106c3fb27SDimitry Andric     case LibFunc_ZnamSt11align_val_t:
380206c3fb27SDimitry Andric     case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t:
3803*0fca6ea1SDimitry Andric     case LibFunc_Znwm12__hot_cold_t:
3804*0fca6ea1SDimitry Andric     case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:
3805*0fca6ea1SDimitry Andric     case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:
3806*0fca6ea1SDimitry Andric     case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
3807*0fca6ea1SDimitry Andric     case LibFunc_Znam12__hot_cold_t:
3808*0fca6ea1SDimitry Andric     case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:
3809*0fca6ea1SDimitry Andric     case LibFunc_ZnamSt11align_val_t12__hot_cold_t:
3810*0fca6ea1SDimitry Andric     case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
381106c3fb27SDimitry Andric       return optimizeNew(CI, Builder, Func);
38120b57cec5SDimitry Andric     default:
38130b57cec5SDimitry Andric       break;
38140b57cec5SDimitry Andric     }
38150b57cec5SDimitry Andric   }
38160b57cec5SDimitry Andric   return nullptr;
38170b57cec5SDimitry Andric }
38180b57cec5SDimitry Andric 
38190b57cec5SDimitry Andric Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
38200b57cec5SDimitry Andric                                                        LibFunc Func,
38215ffd83dbSDimitry Andric                                                        IRBuilderBase &Builder) {
382281ad6265SDimitry Andric   const Module *M = CI->getModule();
382381ad6265SDimitry Andric 
38240b57cec5SDimitry Andric   // Don't optimize calls that require strict floating point semantics.
38250b57cec5SDimitry Andric   if (CI->isStrictFP())
38260b57cec5SDimitry Andric     return nullptr;
38270b57cec5SDimitry Andric 
3828*0fca6ea1SDimitry Andric   if (Value *V = optimizeSymmetric(CI, Func, Builder))
38290b57cec5SDimitry Andric     return V;
38300b57cec5SDimitry Andric 
38310b57cec5SDimitry Andric   switch (Func) {
38320b57cec5SDimitry Andric   case LibFunc_sinpif:
38330b57cec5SDimitry Andric   case LibFunc_sinpi:
383406c3fb27SDimitry Andric     return optimizeSinCosPi(CI, /*IsSin*/true, Builder);
38350b57cec5SDimitry Andric   case LibFunc_cospif:
38360b57cec5SDimitry Andric   case LibFunc_cospi:
383706c3fb27SDimitry Andric     return optimizeSinCosPi(CI, /*IsSin*/false, Builder);
38380b57cec5SDimitry Andric   case LibFunc_powf:
38390b57cec5SDimitry Andric   case LibFunc_pow:
38400b57cec5SDimitry Andric   case LibFunc_powl:
38410b57cec5SDimitry Andric     return optimizePow(CI, Builder);
38420b57cec5SDimitry Andric   case LibFunc_exp2l:
38430b57cec5SDimitry Andric   case LibFunc_exp2:
38440b57cec5SDimitry Andric   case LibFunc_exp2f:
38450b57cec5SDimitry Andric     return optimizeExp2(CI, Builder);
38460b57cec5SDimitry Andric   case LibFunc_fabsf:
38470b57cec5SDimitry Andric   case LibFunc_fabs:
38480b57cec5SDimitry Andric   case LibFunc_fabsl:
38490b57cec5SDimitry Andric     return replaceUnaryCall(CI, Builder, Intrinsic::fabs);
38500b57cec5SDimitry Andric   case LibFunc_sqrtf:
38510b57cec5SDimitry Andric   case LibFunc_sqrt:
38520b57cec5SDimitry Andric   case LibFunc_sqrtl:
38530b57cec5SDimitry Andric     return optimizeSqrt(CI, Builder);
38548bcb0991SDimitry Andric   case LibFunc_logf:
38550b57cec5SDimitry Andric   case LibFunc_log:
38568bcb0991SDimitry Andric   case LibFunc_logl:
38578bcb0991SDimitry Andric   case LibFunc_log10f:
38580b57cec5SDimitry Andric   case LibFunc_log10:
38598bcb0991SDimitry Andric   case LibFunc_log10l:
38608bcb0991SDimitry Andric   case LibFunc_log1pf:
38610b57cec5SDimitry Andric   case LibFunc_log1p:
38628bcb0991SDimitry Andric   case LibFunc_log1pl:
38638bcb0991SDimitry Andric   case LibFunc_log2f:
38640b57cec5SDimitry Andric   case LibFunc_log2:
38658bcb0991SDimitry Andric   case LibFunc_log2l:
38668bcb0991SDimitry Andric   case LibFunc_logbf:
38670b57cec5SDimitry Andric   case LibFunc_logb:
38688bcb0991SDimitry Andric   case LibFunc_logbl:
38690b57cec5SDimitry Andric     return optimizeLog(CI, Builder);
38700b57cec5SDimitry Andric   case LibFunc_tan:
38710b57cec5SDimitry Andric   case LibFunc_tanf:
38720b57cec5SDimitry Andric   case LibFunc_tanl:
3873*0fca6ea1SDimitry Andric   case LibFunc_sinh:
3874*0fca6ea1SDimitry Andric   case LibFunc_sinhf:
3875*0fca6ea1SDimitry Andric   case LibFunc_sinhl:
3876*0fca6ea1SDimitry Andric   case LibFunc_asinh:
3877*0fca6ea1SDimitry Andric   case LibFunc_asinhf:
3878*0fca6ea1SDimitry Andric   case LibFunc_asinhl:
3879*0fca6ea1SDimitry Andric   case LibFunc_cosh:
3880*0fca6ea1SDimitry Andric   case LibFunc_coshf:
3881*0fca6ea1SDimitry Andric   case LibFunc_coshl:
3882*0fca6ea1SDimitry Andric   case LibFunc_atanh:
3883*0fca6ea1SDimitry Andric   case LibFunc_atanhf:
3884*0fca6ea1SDimitry Andric   case LibFunc_atanhl:
3885*0fca6ea1SDimitry Andric     return optimizeTrigInversionPairs(CI, Builder);
38860b57cec5SDimitry Andric   case LibFunc_ceil:
38870b57cec5SDimitry Andric     return replaceUnaryCall(CI, Builder, Intrinsic::ceil);
38880b57cec5SDimitry Andric   case LibFunc_floor:
38890b57cec5SDimitry Andric     return replaceUnaryCall(CI, Builder, Intrinsic::floor);
38900b57cec5SDimitry Andric   case LibFunc_round:
38910b57cec5SDimitry Andric     return replaceUnaryCall(CI, Builder, Intrinsic::round);
38925ffd83dbSDimitry Andric   case LibFunc_roundeven:
38935ffd83dbSDimitry Andric     return replaceUnaryCall(CI, Builder, Intrinsic::roundeven);
38940b57cec5SDimitry Andric   case LibFunc_nearbyint:
38950b57cec5SDimitry Andric     return replaceUnaryCall(CI, Builder, Intrinsic::nearbyint);
38960b57cec5SDimitry Andric   case LibFunc_rint:
38970b57cec5SDimitry Andric     return replaceUnaryCall(CI, Builder, Intrinsic::rint);
38980b57cec5SDimitry Andric   case LibFunc_trunc:
38990b57cec5SDimitry Andric     return replaceUnaryCall(CI, Builder, Intrinsic::trunc);
39000b57cec5SDimitry Andric   case LibFunc_acos:
39010b57cec5SDimitry Andric   case LibFunc_acosh:
39020b57cec5SDimitry Andric   case LibFunc_asin:
39030b57cec5SDimitry Andric   case LibFunc_atan:
39040b57cec5SDimitry Andric   case LibFunc_cbrt:
39050b57cec5SDimitry Andric   case LibFunc_exp:
39060b57cec5SDimitry Andric   case LibFunc_exp10:
39070b57cec5SDimitry Andric   case LibFunc_expm1:
39080b57cec5SDimitry Andric   case LibFunc_cos:
39090b57cec5SDimitry Andric   case LibFunc_sin:
39100b57cec5SDimitry Andric   case LibFunc_tanh:
391181ad6265SDimitry Andric     if (UnsafeFPShrink && hasFloatVersion(M, CI->getCalledFunction()->getName()))
391281ad6265SDimitry Andric       return optimizeUnaryDoubleFP(CI, Builder, TLI, true);
39130b57cec5SDimitry Andric     return nullptr;
39140b57cec5SDimitry Andric   case LibFunc_copysign:
391581ad6265SDimitry Andric     if (hasFloatVersion(M, CI->getCalledFunction()->getName()))
391681ad6265SDimitry Andric       return optimizeBinaryDoubleFP(CI, Builder, TLI);
39170b57cec5SDimitry Andric     return nullptr;
39180b57cec5SDimitry Andric   case LibFunc_fminf:
39190b57cec5SDimitry Andric   case LibFunc_fmin:
39200b57cec5SDimitry Andric   case LibFunc_fminl:
39210b57cec5SDimitry Andric   case LibFunc_fmaxf:
39220b57cec5SDimitry Andric   case LibFunc_fmax:
39230b57cec5SDimitry Andric   case LibFunc_fmaxl:
39240b57cec5SDimitry Andric     return optimizeFMinFMax(CI, Builder);
39250b57cec5SDimitry Andric   case LibFunc_cabs:
39260b57cec5SDimitry Andric   case LibFunc_cabsf:
39270b57cec5SDimitry Andric   case LibFunc_cabsl:
39280b57cec5SDimitry Andric     return optimizeCAbs(CI, Builder);
39290b57cec5SDimitry Andric   default:
39300b57cec5SDimitry Andric     return nullptr;
39310b57cec5SDimitry Andric   }
39320b57cec5SDimitry Andric }
39330b57cec5SDimitry Andric 
39345ffd83dbSDimitry Andric Value *LibCallSimplifier::optimizeCall(CallInst *CI, IRBuilderBase &Builder) {
393581ad6265SDimitry Andric   Module *M = CI->getModule();
39360eae32dcSDimitry Andric   assert(!CI->isMustTailCall() && "These transforms aren't musttail safe.");
39370eae32dcSDimitry Andric 
39380b57cec5SDimitry Andric   // TODO: Split out the code below that operates on FP calls so that
39390b57cec5SDimitry Andric   //       we can all non-FP calls with the StrictFP attribute to be
39400b57cec5SDimitry Andric   //       optimized.
39410b57cec5SDimitry Andric   if (CI->isNoBuiltin())
39420b57cec5SDimitry Andric     return nullptr;
39430b57cec5SDimitry Andric 
39440b57cec5SDimitry Andric   LibFunc Func;
39450b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
3946fe6060f1SDimitry Andric   bool IsCallingConvC = TargetLibraryInfoImpl::isCallingConvCCompatible(CI);
39470b57cec5SDimitry Andric 
39480b57cec5SDimitry Andric   SmallVector<OperandBundleDef, 2> OpBundles;
39490b57cec5SDimitry Andric   CI->getOperandBundlesAsDefs(OpBundles);
39505ffd83dbSDimitry Andric 
39515ffd83dbSDimitry Andric   IRBuilderBase::OperandBundlesGuard Guard(Builder);
39525ffd83dbSDimitry Andric   Builder.setDefaultOperandBundles(OpBundles);
39530b57cec5SDimitry Andric 
39540b57cec5SDimitry Andric   // Command-line parameter overrides instruction attribute.
39550b57cec5SDimitry Andric   // This can't be moved to optimizeFloatingPointLibCall() because it may be
39560b57cec5SDimitry Andric   // used by the intrinsic optimizations.
39570b57cec5SDimitry Andric   if (EnableUnsafeFPShrink.getNumOccurrences() > 0)
39580b57cec5SDimitry Andric     UnsafeFPShrink = EnableUnsafeFPShrink;
39590b57cec5SDimitry Andric   else if (isa<FPMathOperator>(CI) && CI->isFast())
39600b57cec5SDimitry Andric     UnsafeFPShrink = true;
39610b57cec5SDimitry Andric 
39620b57cec5SDimitry Andric   // First, check for intrinsics.
39630b57cec5SDimitry Andric   if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) {
3964fe6060f1SDimitry Andric     if (!IsCallingConvC)
39650b57cec5SDimitry Andric       return nullptr;
39660b57cec5SDimitry Andric     // The FP intrinsics have corresponding constrained versions so we don't
39670b57cec5SDimitry Andric     // need to check for the StrictFP attribute here.
39680b57cec5SDimitry Andric     switch (II->getIntrinsicID()) {
39690b57cec5SDimitry Andric     case Intrinsic::pow:
39700b57cec5SDimitry Andric       return optimizePow(CI, Builder);
39710b57cec5SDimitry Andric     case Intrinsic::exp2:
39720b57cec5SDimitry Andric       return optimizeExp2(CI, Builder);
39730b57cec5SDimitry Andric     case Intrinsic::log:
39748bcb0991SDimitry Andric     case Intrinsic::log2:
39758bcb0991SDimitry Andric     case Intrinsic::log10:
39760b57cec5SDimitry Andric       return optimizeLog(CI, Builder);
39770b57cec5SDimitry Andric     case Intrinsic::sqrt:
39780b57cec5SDimitry Andric       return optimizeSqrt(CI, Builder);
39798bcb0991SDimitry Andric     case Intrinsic::memset:
39808bcb0991SDimitry Andric       return optimizeMemSet(CI, Builder);
39818bcb0991SDimitry Andric     case Intrinsic::memcpy:
39828bcb0991SDimitry Andric       return optimizeMemCpy(CI, Builder);
39838bcb0991SDimitry Andric     case Intrinsic::memmove:
39848bcb0991SDimitry Andric       return optimizeMemMove(CI, Builder);
39850b57cec5SDimitry Andric     default:
39860b57cec5SDimitry Andric       return nullptr;
39870b57cec5SDimitry Andric     }
39880b57cec5SDimitry Andric   }
39890b57cec5SDimitry Andric 
39900b57cec5SDimitry Andric   // Also try to simplify calls to fortified library functions.
39915ffd83dbSDimitry Andric   if (Value *SimplifiedFortifiedCI =
39921db9f3b2SDimitry Andric           FortifiedSimplifier.optimizeCall(CI, Builder))
39930b57cec5SDimitry Andric     return SimplifiedFortifiedCI;
39940b57cec5SDimitry Andric 
39950b57cec5SDimitry Andric   // Then check for known library functions.
399681ad6265SDimitry Andric   if (TLI->getLibFunc(*Callee, Func) && isLibFuncEmittable(M, TLI, Func)) {
39970b57cec5SDimitry Andric     // We never change the calling convention.
3998fe6060f1SDimitry Andric     if (!ignoreCallingConv(Func) && !IsCallingConvC)
39990b57cec5SDimitry Andric       return nullptr;
40000b57cec5SDimitry Andric     if (Value *V = optimizeStringMemoryLibCall(CI, Builder))
40010b57cec5SDimitry Andric       return V;
40020b57cec5SDimitry Andric     if (Value *V = optimizeFloatingPointLibCall(CI, Func, Builder))
40030b57cec5SDimitry Andric       return V;
40040b57cec5SDimitry Andric     switch (Func) {
40050b57cec5SDimitry Andric     case LibFunc_ffs:
40060b57cec5SDimitry Andric     case LibFunc_ffsl:
40070b57cec5SDimitry Andric     case LibFunc_ffsll:
40080b57cec5SDimitry Andric       return optimizeFFS(CI, Builder);
40090b57cec5SDimitry Andric     case LibFunc_fls:
40100b57cec5SDimitry Andric     case LibFunc_flsl:
40110b57cec5SDimitry Andric     case LibFunc_flsll:
40120b57cec5SDimitry Andric       return optimizeFls(CI, Builder);
40130b57cec5SDimitry Andric     case LibFunc_abs:
40140b57cec5SDimitry Andric     case LibFunc_labs:
40150b57cec5SDimitry Andric     case LibFunc_llabs:
40160b57cec5SDimitry Andric       return optimizeAbs(CI, Builder);
40170b57cec5SDimitry Andric     case LibFunc_isdigit:
40180b57cec5SDimitry Andric       return optimizeIsDigit(CI, Builder);
40190b57cec5SDimitry Andric     case LibFunc_isascii:
40200b57cec5SDimitry Andric       return optimizeIsAscii(CI, Builder);
40210b57cec5SDimitry Andric     case LibFunc_toascii:
40220b57cec5SDimitry Andric       return optimizeToAscii(CI, Builder);
40230b57cec5SDimitry Andric     case LibFunc_atoi:
40240b57cec5SDimitry Andric     case LibFunc_atol:
40250b57cec5SDimitry Andric     case LibFunc_atoll:
40260b57cec5SDimitry Andric       return optimizeAtoi(CI, Builder);
40270b57cec5SDimitry Andric     case LibFunc_strtol:
40280b57cec5SDimitry Andric     case LibFunc_strtoll:
4029972a253aSDimitry Andric       return optimizeStrToInt(CI, Builder, /*AsSigned=*/true);
4030972a253aSDimitry Andric     case LibFunc_strtoul:
4031972a253aSDimitry Andric     case LibFunc_strtoull:
4032972a253aSDimitry Andric       return optimizeStrToInt(CI, Builder, /*AsSigned=*/false);
40330b57cec5SDimitry Andric     case LibFunc_printf:
40340b57cec5SDimitry Andric       return optimizePrintF(CI, Builder);
40350b57cec5SDimitry Andric     case LibFunc_sprintf:
40360b57cec5SDimitry Andric       return optimizeSPrintF(CI, Builder);
40370b57cec5SDimitry Andric     case LibFunc_snprintf:
40380b57cec5SDimitry Andric       return optimizeSnPrintF(CI, Builder);
40390b57cec5SDimitry Andric     case LibFunc_fprintf:
40400b57cec5SDimitry Andric       return optimizeFPrintF(CI, Builder);
40410b57cec5SDimitry Andric     case LibFunc_fwrite:
40420b57cec5SDimitry Andric       return optimizeFWrite(CI, Builder);
40430b57cec5SDimitry Andric     case LibFunc_fputs:
40440b57cec5SDimitry Andric       return optimizeFPuts(CI, Builder);
40450b57cec5SDimitry Andric     case LibFunc_puts:
40460b57cec5SDimitry Andric       return optimizePuts(CI, Builder);
40470b57cec5SDimitry Andric     case LibFunc_perror:
40480b57cec5SDimitry Andric       return optimizeErrorReporting(CI, Builder);
40490b57cec5SDimitry Andric     case LibFunc_vfprintf:
40500b57cec5SDimitry Andric     case LibFunc_fiprintf:
40510b57cec5SDimitry Andric       return optimizeErrorReporting(CI, Builder, 0);
40520b57cec5SDimitry Andric     default:
40530b57cec5SDimitry Andric       return nullptr;
40540b57cec5SDimitry Andric     }
40550b57cec5SDimitry Andric   }
40560b57cec5SDimitry Andric   return nullptr;
40570b57cec5SDimitry Andric }
40580b57cec5SDimitry Andric 
40590b57cec5SDimitry Andric LibCallSimplifier::LibCallSimplifier(
406006c3fb27SDimitry Andric     const DataLayout &DL, const TargetLibraryInfo *TLI, AssumptionCache *AC,
406106c3fb27SDimitry Andric     OptimizationRemarkEmitter &ORE, BlockFrequencyInfo *BFI,
406206c3fb27SDimitry Andric     ProfileSummaryInfo *PSI,
40630b57cec5SDimitry Andric     function_ref<void(Instruction *, Value *)> Replacer,
40640b57cec5SDimitry Andric     function_ref<void(Instruction *)> Eraser)
406506c3fb27SDimitry Andric     : FortifiedSimplifier(TLI), DL(DL), TLI(TLI), AC(AC), ORE(ORE), BFI(BFI),
406606c3fb27SDimitry Andric       PSI(PSI), Replacer(Replacer), Eraser(Eraser) {}
40670b57cec5SDimitry Andric 
40680b57cec5SDimitry Andric void LibCallSimplifier::replaceAllUsesWith(Instruction *I, Value *With) {
40690b57cec5SDimitry Andric   // Indirect through the replacer used in this instance.
40700b57cec5SDimitry Andric   Replacer(I, With);
40710b57cec5SDimitry Andric }
40720b57cec5SDimitry Andric 
40730b57cec5SDimitry Andric void LibCallSimplifier::eraseFromParent(Instruction *I) {
40740b57cec5SDimitry Andric   Eraser(I);
40750b57cec5SDimitry Andric }
40760b57cec5SDimitry Andric 
40770b57cec5SDimitry Andric // TODO:
40780b57cec5SDimitry Andric //   Additional cases that we need to add to this file:
40790b57cec5SDimitry Andric //
40800b57cec5SDimitry Andric // cbrt:
40810b57cec5SDimitry Andric //   * cbrt(expN(X))  -> expN(x/3)
40820b57cec5SDimitry Andric //   * cbrt(sqrt(x))  -> pow(x,1/6)
40830b57cec5SDimitry Andric //   * cbrt(cbrt(x))  -> pow(x,1/9)
40840b57cec5SDimitry Andric //
40850b57cec5SDimitry Andric // exp, expf, expl:
40860b57cec5SDimitry Andric //   * exp(log(x))  -> x
40870b57cec5SDimitry Andric //
40880b57cec5SDimitry Andric // log, logf, logl:
40890b57cec5SDimitry Andric //   * log(exp(x))   -> x
40900b57cec5SDimitry Andric //   * log(exp(y))   -> y*log(e)
40910b57cec5SDimitry Andric //   * log(exp10(y)) -> y*log(10)
40920b57cec5SDimitry Andric //   * log(sqrt(x))  -> 0.5*log(x)
40930b57cec5SDimitry Andric //
40940b57cec5SDimitry Andric // pow, powf, powl:
40950b57cec5SDimitry Andric //   * pow(sqrt(x),y) -> pow(x,y*0.5)
40960b57cec5SDimitry Andric //   * pow(pow(x,y),z)-> pow(x,y*z)
40970b57cec5SDimitry Andric //
40980b57cec5SDimitry Andric // signbit:
40990b57cec5SDimitry Andric //   * signbit(cnst) -> cnst'
41000b57cec5SDimitry Andric //   * signbit(nncst) -> 0 (if pstv is a non-negative constant)
41010b57cec5SDimitry Andric //
41020b57cec5SDimitry Andric // sqrt, sqrtf, sqrtl:
41030b57cec5SDimitry Andric //   * sqrt(expN(x))  -> expN(x*0.5)
41040b57cec5SDimitry Andric //   * sqrt(Nroot(x)) -> pow(x,1/(2*N))
41050b57cec5SDimitry Andric //   * sqrt(pow(x,y)) -> pow(|x|,y*0.5)
41060b57cec5SDimitry Andric //
41070b57cec5SDimitry Andric 
41080b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
41090b57cec5SDimitry Andric // Fortified Library Call Optimizations
41100b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
41110b57cec5SDimitry Andric 
4112bdd1243dSDimitry Andric bool FortifiedLibCallSimplifier::isFortifiedCallFoldable(
4113bdd1243dSDimitry Andric     CallInst *CI, unsigned ObjSizeOp, std::optional<unsigned> SizeOp,
4114bdd1243dSDimitry Andric     std::optional<unsigned> StrOp, std::optional<unsigned> FlagOp) {
41150b57cec5SDimitry Andric   // If this function takes a flag argument, the implementation may use it to
41160b57cec5SDimitry Andric   // perform extra checks. Don't fold into the non-checking variant.
41170b57cec5SDimitry Andric   if (FlagOp) {
41180b57cec5SDimitry Andric     ConstantInt *Flag = dyn_cast<ConstantInt>(CI->getArgOperand(*FlagOp));
41190b57cec5SDimitry Andric     if (!Flag || !Flag->isZero())
41200b57cec5SDimitry Andric       return false;
41210b57cec5SDimitry Andric   }
41220b57cec5SDimitry Andric 
41230b57cec5SDimitry Andric   if (SizeOp && CI->getArgOperand(ObjSizeOp) == CI->getArgOperand(*SizeOp))
41240b57cec5SDimitry Andric     return true;
41250b57cec5SDimitry Andric 
41260b57cec5SDimitry Andric   if (ConstantInt *ObjSizeCI =
41270b57cec5SDimitry Andric           dyn_cast<ConstantInt>(CI->getArgOperand(ObjSizeOp))) {
41280b57cec5SDimitry Andric     if (ObjSizeCI->isMinusOne())
41290b57cec5SDimitry Andric       return true;
41300b57cec5SDimitry Andric     // If the object size wasn't -1 (unknown), bail out if we were asked to.
41310b57cec5SDimitry Andric     if (OnlyLowerUnknownSize)
41320b57cec5SDimitry Andric       return false;
41330b57cec5SDimitry Andric     if (StrOp) {
41340b57cec5SDimitry Andric       uint64_t Len = GetStringLength(CI->getArgOperand(*StrOp));
41350b57cec5SDimitry Andric       // If the length is 0 we don't know how long it is and so we can't
41360b57cec5SDimitry Andric       // remove the check.
41378bcb0991SDimitry Andric       if (Len)
41388bcb0991SDimitry Andric         annotateDereferenceableBytes(CI, *StrOp, Len);
41398bcb0991SDimitry Andric       else
41400b57cec5SDimitry Andric         return false;
41410b57cec5SDimitry Andric       return ObjSizeCI->getZExtValue() >= Len;
41420b57cec5SDimitry Andric     }
41430b57cec5SDimitry Andric 
41440b57cec5SDimitry Andric     if (SizeOp) {
41450b57cec5SDimitry Andric       if (ConstantInt *SizeCI =
41460b57cec5SDimitry Andric               dyn_cast<ConstantInt>(CI->getArgOperand(*SizeOp)))
41470b57cec5SDimitry Andric         return ObjSizeCI->getZExtValue() >= SizeCI->getZExtValue();
41480b57cec5SDimitry Andric     }
41490b57cec5SDimitry Andric   }
41500b57cec5SDimitry Andric   return false;
41510b57cec5SDimitry Andric }
41520b57cec5SDimitry Andric 
41530b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeMemCpyChk(CallInst *CI,
41545ffd83dbSDimitry Andric                                                      IRBuilderBase &B) {
41550b57cec5SDimitry Andric   if (isFortifiedCallFoldable(CI, 3, 2)) {
41565ffd83dbSDimitry Andric     CallInst *NewCI =
41575ffd83dbSDimitry Andric         B.CreateMemCpy(CI->getArgOperand(0), Align(1), CI->getArgOperand(1),
41585ffd83dbSDimitry Andric                        Align(1), CI->getArgOperand(2));
4159bdd1243dSDimitry Andric     mergeAttributesAndFlags(NewCI, *CI);
41600b57cec5SDimitry Andric     return CI->getArgOperand(0);
41610b57cec5SDimitry Andric   }
41620b57cec5SDimitry Andric   return nullptr;
41630b57cec5SDimitry Andric }
41640b57cec5SDimitry Andric 
41650b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeMemMoveChk(CallInst *CI,
41665ffd83dbSDimitry Andric                                                       IRBuilderBase &B) {
41670b57cec5SDimitry Andric   if (isFortifiedCallFoldable(CI, 3, 2)) {
41685ffd83dbSDimitry Andric     CallInst *NewCI =
41695ffd83dbSDimitry Andric         B.CreateMemMove(CI->getArgOperand(0), Align(1), CI->getArgOperand(1),
41705ffd83dbSDimitry Andric                         Align(1), CI->getArgOperand(2));
4171bdd1243dSDimitry Andric     mergeAttributesAndFlags(NewCI, *CI);
41720b57cec5SDimitry Andric     return CI->getArgOperand(0);
41730b57cec5SDimitry Andric   }
41740b57cec5SDimitry Andric   return nullptr;
41750b57cec5SDimitry Andric }
41760b57cec5SDimitry Andric 
41770b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeMemSetChk(CallInst *CI,
41785ffd83dbSDimitry Andric                                                      IRBuilderBase &B) {
41790b57cec5SDimitry Andric   if (isFortifiedCallFoldable(CI, 3, 2)) {
41800b57cec5SDimitry Andric     Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(), false);
4181480093f4SDimitry Andric     CallInst *NewCI = B.CreateMemSet(CI->getArgOperand(0), Val,
41825ffd83dbSDimitry Andric                                      CI->getArgOperand(2), Align(1));
4183bdd1243dSDimitry Andric     mergeAttributesAndFlags(NewCI, *CI);
41840b57cec5SDimitry Andric     return CI->getArgOperand(0);
41850b57cec5SDimitry Andric   }
41860b57cec5SDimitry Andric   return nullptr;
41870b57cec5SDimitry Andric }
41880b57cec5SDimitry Andric 
4189e8d8bef9SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeMemPCpyChk(CallInst *CI,
4190e8d8bef9SDimitry Andric                                                       IRBuilderBase &B) {
4191*0fca6ea1SDimitry Andric   const DataLayout &DL = CI->getDataLayout();
4192e8d8bef9SDimitry Andric   if (isFortifiedCallFoldable(CI, 3, 2))
4193e8d8bef9SDimitry Andric     if (Value *Call = emitMemPCpy(CI->getArgOperand(0), CI->getArgOperand(1),
4194e8d8bef9SDimitry Andric                                   CI->getArgOperand(2), B, DL, TLI)) {
4195bdd1243dSDimitry Andric       return mergeAttributesAndFlags(cast<CallInst>(Call), *CI);
4196e8d8bef9SDimitry Andric     }
4197e8d8bef9SDimitry Andric   return nullptr;
4198e8d8bef9SDimitry Andric }
4199e8d8bef9SDimitry Andric 
42000b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI,
42015ffd83dbSDimitry Andric                                                       IRBuilderBase &B,
42020b57cec5SDimitry Andric                                                       LibFunc Func) {
4203*0fca6ea1SDimitry Andric   const DataLayout &DL = CI->getDataLayout();
42040b57cec5SDimitry Andric   Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1),
42050b57cec5SDimitry Andric         *ObjSize = CI->getArgOperand(2);
42060b57cec5SDimitry Andric 
42070b57cec5SDimitry Andric   // __stpcpy_chk(x,x,...)  -> x+strlen(x)
42080b57cec5SDimitry Andric   if (Func == LibFunc_stpcpy_chk && !OnlyLowerUnknownSize && Dst == Src) {
42090b57cec5SDimitry Andric     Value *StrLen = emitStrLen(Src, B, DL, TLI);
42100b57cec5SDimitry Andric     return StrLen ? B.CreateInBoundsGEP(B.getInt8Ty(), Dst, StrLen) : nullptr;
42110b57cec5SDimitry Andric   }
42120b57cec5SDimitry Andric 
42130b57cec5SDimitry Andric   // If a) we don't have any length information, or b) we know this will
42140b57cec5SDimitry Andric   // fit then just lower to a plain st[rp]cpy. Otherwise we'll keep our
42150b57cec5SDimitry Andric   // st[rp]cpy_chk call which may fail at runtime if the size is too long.
42160b57cec5SDimitry Andric   // TODO: It might be nice to get a maximum length out of the possible
42170b57cec5SDimitry Andric   // string lengths for varying.
4218bdd1243dSDimitry Andric   if (isFortifiedCallFoldable(CI, 2, std::nullopt, 1)) {
42190b57cec5SDimitry Andric     if (Func == LibFunc_strcpy_chk)
42200eae32dcSDimitry Andric       return copyFlags(*CI, emitStrCpy(Dst, Src, B, TLI));
42210b57cec5SDimitry Andric     else
42220eae32dcSDimitry Andric       return copyFlags(*CI, emitStpCpy(Dst, Src, B, TLI));
42230b57cec5SDimitry Andric   }
42240b57cec5SDimitry Andric 
42250b57cec5SDimitry Andric   if (OnlyLowerUnknownSize)
42260b57cec5SDimitry Andric     return nullptr;
42270b57cec5SDimitry Andric 
42280b57cec5SDimitry Andric   // Maybe we can stil fold __st[rp]cpy_chk to __memcpy_chk.
42290b57cec5SDimitry Andric   uint64_t Len = GetStringLength(Src);
42308bcb0991SDimitry Andric   if (Len)
42318bcb0991SDimitry Andric     annotateDereferenceableBytes(CI, 1, Len);
42328bcb0991SDimitry Andric   else
42330b57cec5SDimitry Andric     return nullptr;
42340b57cec5SDimitry Andric 
4235bdd1243dSDimitry Andric   unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule());
4236bdd1243dSDimitry Andric   Type *SizeTTy = IntegerType::get(CI->getContext(), SizeTBits);
42370b57cec5SDimitry Andric   Value *LenV = ConstantInt::get(SizeTTy, Len);
42380b57cec5SDimitry Andric   Value *Ret = emitMemCpyChk(Dst, Src, LenV, ObjSize, B, DL, TLI);
42390b57cec5SDimitry Andric   // If the function was an __stpcpy_chk, and we were able to fold it into
42400b57cec5SDimitry Andric   // a __memcpy_chk, we still need to return the correct end pointer.
42410b57cec5SDimitry Andric   if (Ret && Func == LibFunc_stpcpy_chk)
424281ad6265SDimitry Andric     return B.CreateInBoundsGEP(B.getInt8Ty(), Dst,
424381ad6265SDimitry Andric                                ConstantInt::get(SizeTTy, Len - 1));
42440eae32dcSDimitry Andric   return copyFlags(*CI, cast<CallInst>(Ret));
42450b57cec5SDimitry Andric }
42460b57cec5SDimitry Andric 
42475ffd83dbSDimitry Andric Value *FortifiedLibCallSimplifier::optimizeStrLenChk(CallInst *CI,
42485ffd83dbSDimitry Andric                                                      IRBuilderBase &B) {
4249bdd1243dSDimitry Andric   if (isFortifiedCallFoldable(CI, 1, std::nullopt, 0))
42500eae32dcSDimitry Andric     return copyFlags(*CI, emitStrLen(CI->getArgOperand(0), B,
4251*0fca6ea1SDimitry Andric                                      CI->getDataLayout(), TLI));
42525ffd83dbSDimitry Andric   return nullptr;
42535ffd83dbSDimitry Andric }
42545ffd83dbSDimitry Andric 
42550b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeStrpNCpyChk(CallInst *CI,
42565ffd83dbSDimitry Andric                                                        IRBuilderBase &B,
42570b57cec5SDimitry Andric                                                        LibFunc Func) {
42580b57cec5SDimitry Andric   if (isFortifiedCallFoldable(CI, 3, 2)) {
42590b57cec5SDimitry Andric     if (Func == LibFunc_strncpy_chk)
42600eae32dcSDimitry Andric       return copyFlags(*CI,
42610eae32dcSDimitry Andric                        emitStrNCpy(CI->getArgOperand(0), CI->getArgOperand(1),
42620eae32dcSDimitry Andric                                    CI->getArgOperand(2), B, TLI));
42630b57cec5SDimitry Andric     else
42640eae32dcSDimitry Andric       return copyFlags(*CI,
42650eae32dcSDimitry Andric                        emitStpNCpy(CI->getArgOperand(0), CI->getArgOperand(1),
42660eae32dcSDimitry Andric                                    CI->getArgOperand(2), B, TLI));
42670b57cec5SDimitry Andric   }
42680b57cec5SDimitry Andric 
42690b57cec5SDimitry Andric   return nullptr;
42700b57cec5SDimitry Andric }
42710b57cec5SDimitry Andric 
42720b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeMemCCpyChk(CallInst *CI,
42735ffd83dbSDimitry Andric                                                       IRBuilderBase &B) {
42740b57cec5SDimitry Andric   if (isFortifiedCallFoldable(CI, 4, 3))
42750eae32dcSDimitry Andric     return copyFlags(
42760eae32dcSDimitry Andric         *CI, emitMemCCpy(CI->getArgOperand(0), CI->getArgOperand(1),
42770eae32dcSDimitry Andric                          CI->getArgOperand(2), CI->getArgOperand(3), B, TLI));
42780b57cec5SDimitry Andric 
42790b57cec5SDimitry Andric   return nullptr;
42800b57cec5SDimitry Andric }
42810b57cec5SDimitry Andric 
42820b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeSNPrintfChk(CallInst *CI,
42835ffd83dbSDimitry Andric                                                        IRBuilderBase &B) {
4284bdd1243dSDimitry Andric   if (isFortifiedCallFoldable(CI, 3, 1, std::nullopt, 2)) {
4285e8d8bef9SDimitry Andric     SmallVector<Value *, 8> VariadicArgs(drop_begin(CI->args(), 5));
42860eae32dcSDimitry Andric     return copyFlags(*CI,
42870eae32dcSDimitry Andric                      emitSNPrintf(CI->getArgOperand(0), CI->getArgOperand(1),
42880eae32dcSDimitry Andric                                   CI->getArgOperand(4), VariadicArgs, B, TLI));
42890b57cec5SDimitry Andric   }
42900b57cec5SDimitry Andric 
42910b57cec5SDimitry Andric   return nullptr;
42920b57cec5SDimitry Andric }
42930b57cec5SDimitry Andric 
42940b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeSPrintfChk(CallInst *CI,
42955ffd83dbSDimitry Andric                                                       IRBuilderBase &B) {
4296bdd1243dSDimitry Andric   if (isFortifiedCallFoldable(CI, 2, std::nullopt, std::nullopt, 1)) {
4297e8d8bef9SDimitry Andric     SmallVector<Value *, 8> VariadicArgs(drop_begin(CI->args(), 4));
42980eae32dcSDimitry Andric     return copyFlags(*CI,
42990eae32dcSDimitry Andric                      emitSPrintf(CI->getArgOperand(0), CI->getArgOperand(3),
43000eae32dcSDimitry Andric                                  VariadicArgs, B, TLI));
43010b57cec5SDimitry Andric   }
43020b57cec5SDimitry Andric 
43030b57cec5SDimitry Andric   return nullptr;
43040b57cec5SDimitry Andric }
43050b57cec5SDimitry Andric 
43060b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeStrCatChk(CallInst *CI,
43075ffd83dbSDimitry Andric                                                      IRBuilderBase &B) {
43080b57cec5SDimitry Andric   if (isFortifiedCallFoldable(CI, 2))
43090eae32dcSDimitry Andric     return copyFlags(
43100eae32dcSDimitry Andric         *CI, emitStrCat(CI->getArgOperand(0), CI->getArgOperand(1), B, TLI));
43110b57cec5SDimitry Andric 
43120b57cec5SDimitry Andric   return nullptr;
43130b57cec5SDimitry Andric }
43140b57cec5SDimitry Andric 
43150b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeStrLCat(CallInst *CI,
43165ffd83dbSDimitry Andric                                                    IRBuilderBase &B) {
43170b57cec5SDimitry Andric   if (isFortifiedCallFoldable(CI, 3))
43180eae32dcSDimitry Andric     return copyFlags(*CI,
43190eae32dcSDimitry Andric                      emitStrLCat(CI->getArgOperand(0), CI->getArgOperand(1),
43200eae32dcSDimitry Andric                                  CI->getArgOperand(2), B, TLI));
43210b57cec5SDimitry Andric 
43220b57cec5SDimitry Andric   return nullptr;
43230b57cec5SDimitry Andric }
43240b57cec5SDimitry Andric 
43250b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeStrNCatChk(CallInst *CI,
43265ffd83dbSDimitry Andric                                                       IRBuilderBase &B) {
43270b57cec5SDimitry Andric   if (isFortifiedCallFoldable(CI, 3))
43280eae32dcSDimitry Andric     return copyFlags(*CI,
43290eae32dcSDimitry Andric                      emitStrNCat(CI->getArgOperand(0), CI->getArgOperand(1),
43300eae32dcSDimitry Andric                                  CI->getArgOperand(2), B, TLI));
43310b57cec5SDimitry Andric 
43320b57cec5SDimitry Andric   return nullptr;
43330b57cec5SDimitry Andric }
43340b57cec5SDimitry Andric 
43350b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeStrLCpyChk(CallInst *CI,
43365ffd83dbSDimitry Andric                                                       IRBuilderBase &B) {
43370b57cec5SDimitry Andric   if (isFortifiedCallFoldable(CI, 3))
43380eae32dcSDimitry Andric     return copyFlags(*CI,
43390eae32dcSDimitry Andric                      emitStrLCpy(CI->getArgOperand(0), CI->getArgOperand(1),
43400eae32dcSDimitry Andric                                  CI->getArgOperand(2), B, TLI));
43410b57cec5SDimitry Andric 
43420b57cec5SDimitry Andric   return nullptr;
43430b57cec5SDimitry Andric }
43440b57cec5SDimitry Andric 
43450b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeVSNPrintfChk(CallInst *CI,
43465ffd83dbSDimitry Andric                                                         IRBuilderBase &B) {
4347bdd1243dSDimitry Andric   if (isFortifiedCallFoldable(CI, 3, 1, std::nullopt, 2))
43480eae32dcSDimitry Andric     return copyFlags(
43490eae32dcSDimitry Andric         *CI, emitVSNPrintf(CI->getArgOperand(0), CI->getArgOperand(1),
43500eae32dcSDimitry Andric                            CI->getArgOperand(4), CI->getArgOperand(5), B, TLI));
43510b57cec5SDimitry Andric 
43520b57cec5SDimitry Andric   return nullptr;
43530b57cec5SDimitry Andric }
43540b57cec5SDimitry Andric 
43550b57cec5SDimitry Andric Value *FortifiedLibCallSimplifier::optimizeVSPrintfChk(CallInst *CI,
43565ffd83dbSDimitry Andric                                                        IRBuilderBase &B) {
4357bdd1243dSDimitry Andric   if (isFortifiedCallFoldable(CI, 2, std::nullopt, std::nullopt, 1))
43580eae32dcSDimitry Andric     return copyFlags(*CI,
43590eae32dcSDimitry Andric                      emitVSPrintf(CI->getArgOperand(0), CI->getArgOperand(3),
43600eae32dcSDimitry Andric                                   CI->getArgOperand(4), B, TLI));
43610b57cec5SDimitry Andric 
43620b57cec5SDimitry Andric   return nullptr;
43630b57cec5SDimitry Andric }
43640b57cec5SDimitry Andric 
43655ffd83dbSDimitry Andric Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI,
43665ffd83dbSDimitry Andric                                                 IRBuilderBase &Builder) {
43670b57cec5SDimitry Andric   // FIXME: We shouldn't be changing "nobuiltin" or TLI unavailable calls here.
43680b57cec5SDimitry Andric   // Some clang users checked for _chk libcall availability using:
43690b57cec5SDimitry Andric   //   __has_builtin(__builtin___memcpy_chk)
43700b57cec5SDimitry Andric   // When compiling with -fno-builtin, this is always true.
43710b57cec5SDimitry Andric   // When passing -ffreestanding/-mkernel, which both imply -fno-builtin, we
43720b57cec5SDimitry Andric   // end up with fortified libcalls, which isn't acceptable in a freestanding
43730b57cec5SDimitry Andric   // environment which only provides their non-fortified counterparts.
43740b57cec5SDimitry Andric   //
43750b57cec5SDimitry Andric   // Until we change clang and/or teach external users to check for availability
43760b57cec5SDimitry Andric   // differently, disregard the "nobuiltin" attribute and TLI::has.
43770b57cec5SDimitry Andric   //
43780b57cec5SDimitry Andric   // PR23093.
43790b57cec5SDimitry Andric 
43800b57cec5SDimitry Andric   LibFunc Func;
43810b57cec5SDimitry Andric   Function *Callee = CI->getCalledFunction();
4382fe6060f1SDimitry Andric   bool IsCallingConvC = TargetLibraryInfoImpl::isCallingConvCCompatible(CI);
43830b57cec5SDimitry Andric 
43840b57cec5SDimitry Andric   SmallVector<OperandBundleDef, 2> OpBundles;
43850b57cec5SDimitry Andric   CI->getOperandBundlesAsDefs(OpBundles);
43865ffd83dbSDimitry Andric 
43875ffd83dbSDimitry Andric   IRBuilderBase::OperandBundlesGuard Guard(Builder);
43885ffd83dbSDimitry Andric   Builder.setDefaultOperandBundles(OpBundles);
43890b57cec5SDimitry Andric 
43900b57cec5SDimitry Andric   // First, check that this is a known library functions and that the prototype
43910b57cec5SDimitry Andric   // is correct.
43920b57cec5SDimitry Andric   if (!TLI->getLibFunc(*Callee, Func))
43930b57cec5SDimitry Andric     return nullptr;
43940b57cec5SDimitry Andric 
43950b57cec5SDimitry Andric   // We never change the calling convention.
4396fe6060f1SDimitry Andric   if (!ignoreCallingConv(Func) && !IsCallingConvC)
43970b57cec5SDimitry Andric     return nullptr;
43980b57cec5SDimitry Andric 
43990b57cec5SDimitry Andric   switch (Func) {
44000b57cec5SDimitry Andric   case LibFunc_memcpy_chk:
44010b57cec5SDimitry Andric     return optimizeMemCpyChk(CI, Builder);
4402e8d8bef9SDimitry Andric   case LibFunc_mempcpy_chk:
4403e8d8bef9SDimitry Andric     return optimizeMemPCpyChk(CI, Builder);
44040b57cec5SDimitry Andric   case LibFunc_memmove_chk:
44050b57cec5SDimitry Andric     return optimizeMemMoveChk(CI, Builder);
44060b57cec5SDimitry Andric   case LibFunc_memset_chk:
44070b57cec5SDimitry Andric     return optimizeMemSetChk(CI, Builder);
44080b57cec5SDimitry Andric   case LibFunc_stpcpy_chk:
44090b57cec5SDimitry Andric   case LibFunc_strcpy_chk:
44100b57cec5SDimitry Andric     return optimizeStrpCpyChk(CI, Builder, Func);
44115ffd83dbSDimitry Andric   case LibFunc_strlen_chk:
44125ffd83dbSDimitry Andric     return optimizeStrLenChk(CI, Builder);
44130b57cec5SDimitry Andric   case LibFunc_stpncpy_chk:
44140b57cec5SDimitry Andric   case LibFunc_strncpy_chk:
44150b57cec5SDimitry Andric     return optimizeStrpNCpyChk(CI, Builder, Func);
44160b57cec5SDimitry Andric   case LibFunc_memccpy_chk:
44170b57cec5SDimitry Andric     return optimizeMemCCpyChk(CI, Builder);
44180b57cec5SDimitry Andric   case LibFunc_snprintf_chk:
44190b57cec5SDimitry Andric     return optimizeSNPrintfChk(CI, Builder);
44200b57cec5SDimitry Andric   case LibFunc_sprintf_chk:
44210b57cec5SDimitry Andric     return optimizeSPrintfChk(CI, Builder);
44220b57cec5SDimitry Andric   case LibFunc_strcat_chk:
44230b57cec5SDimitry Andric     return optimizeStrCatChk(CI, Builder);
44240b57cec5SDimitry Andric   case LibFunc_strlcat_chk:
44250b57cec5SDimitry Andric     return optimizeStrLCat(CI, Builder);
44260b57cec5SDimitry Andric   case LibFunc_strncat_chk:
44270b57cec5SDimitry Andric     return optimizeStrNCatChk(CI, Builder);
44280b57cec5SDimitry Andric   case LibFunc_strlcpy_chk:
44290b57cec5SDimitry Andric     return optimizeStrLCpyChk(CI, Builder);
44300b57cec5SDimitry Andric   case LibFunc_vsnprintf_chk:
44310b57cec5SDimitry Andric     return optimizeVSNPrintfChk(CI, Builder);
44320b57cec5SDimitry Andric   case LibFunc_vsprintf_chk:
44330b57cec5SDimitry Andric     return optimizeVSPrintfChk(CI, Builder);
44340b57cec5SDimitry Andric   default:
44350b57cec5SDimitry Andric     break;
44360b57cec5SDimitry Andric   }
44370b57cec5SDimitry Andric   return nullptr;
44380b57cec5SDimitry Andric }
44390b57cec5SDimitry Andric 
44400b57cec5SDimitry Andric FortifiedLibCallSimplifier::FortifiedLibCallSimplifier(
44410b57cec5SDimitry Andric     const TargetLibraryInfo *TLI, bool OnlyLowerUnknownSize)
44420b57cec5SDimitry Andric     : TLI(TLI), OnlyLowerUnknownSize(OnlyLowerUnknownSize) {}
4443