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