#include "llvm/Transforms/Utils/SimplifyLibCalls.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/Loads.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/AttributeMask.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/BuildLibCalls.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/SizeOpts.h"
#include <cmath>
usingnamespacellvm;
usingnamespacePatternMatch;
static cl::opt<bool>
EnableUnsafeFPShrink("enable-double-float-shrink", cl::Hidden,
cl::init(false),
cl::desc("Enable unsafe double to float "
"shrinking for math lib calls"));
static cl::opt<bool>
OptimizeHotColdNew("optimize-hot-cold-new", cl::Hidden, cl::init(false),
cl::desc("Enable hot/cold operator new library calls"));
static cl::opt<bool> OptimizeExistingHotColdNew(
"optimize-existing-hot-cold-new", cl::Hidden, cl::init(false),
cl::desc(
"Enable optimization of existing hot/cold operator new library calls"));
namespace {
struct HotColdHintParser : public cl::parser<unsigned> { … };
}
static cl::opt<unsigned, false, HotColdHintParser> ColdNewHintValue(
"cold-new-hint-value", cl::Hidden, cl::init(1),
cl::desc("Value to pass to hot/cold operator new for cold allocation"));
static cl::opt<unsigned, false, HotColdHintParser>
NotColdNewHintValue("notcold-new-hint-value", cl::Hidden, cl::init(128),
cl::desc("Value to pass to hot/cold operator new for "
"notcold (warm) allocation"));
static cl::opt<unsigned, false, HotColdHintParser> HotNewHintValue(
"hot-new-hint-value", cl::Hidden, cl::init(254),
cl::desc("Value to pass to hot/cold operator new for hot allocation"));
static bool ignoreCallingConv(LibFunc Func) { … }
static bool isOnlyUsedInEqualityComparison(Value *V, Value *With) { … }
static bool callHasFloatingPointArgument(const CallInst *CI) { … }
static bool callHasFP128Argument(const CallInst *CI) { … }
static Value *convertStrToInt(CallInst *CI, StringRef &Str, Value *EndPtr,
uint64_t Base, bool AsSigned, IRBuilderBase &B) { … }
static bool isOnlyUsedInComparisonWithZero(Value *V) { … }
static bool canTransformToMemCmp(CallInst *CI, Value *Str, uint64_t Len,
const DataLayout &DL) { … }
static void annotateDereferenceableBytes(CallInst *CI,
ArrayRef<unsigned> ArgNos,
uint64_t DereferenceableBytes) { … }
static void annotateNonNullNoUndefBasedOnAccess(CallInst *CI,
ArrayRef<unsigned> ArgNos) { … }
static void annotateNonNullAndDereferenceable(CallInst *CI, ArrayRef<unsigned> ArgNos,
Value *Size, const DataLayout &DL) { … }
static Value *copyFlags(const CallInst &Old, Value *New) { … }
static Value *mergeAttributesAndFlags(CallInst *NewCI, const CallInst &Old) { … }
static StringRef substr(StringRef Str, uint64_t Len) { … }
Value *LibCallSimplifier::optimizeStrCat(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::emitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len,
IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStrNCat(CallInst *CI, IRBuilderBase &B) { … }
static Value* memChrToCharCompare(CallInst *CI, Value *NBytes,
IRBuilderBase &B, const DataLayout &DL)
{ … }
Value *LibCallSimplifier::optimizeStrChr(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStrRChr(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStrCmp(CallInst *CI, IRBuilderBase &B) { … }
static Value *optimizeMemCmpVarSize(CallInst *CI, Value *LHS, Value *RHS,
Value *Size, bool StrNCmp,
IRBuilderBase &B, const DataLayout &DL);
Value *LibCallSimplifier::optimizeStrNCmp(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStrNDup(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStrCpy(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStpCpy(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStrLCpy(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStringNCpy(CallInst *CI, bool RetEnd,
IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B,
unsigned CharSize,
Value *Bound) { … }
Value *LibCallSimplifier::optimizeStrLen(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStrNLen(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeWcslen(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStrPBrk(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStrTo(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStrSpn(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStrCSpn(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStrStr(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeMemRChr(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilderBase &B) { … }
static Value *optimizeMemCmpVarSize(CallInst *CI, Value *LHS, Value *RHS,
Value *Size, bool StrNCmp,
IRBuilderBase &B, const DataLayout &DL) { … }
static Value *optimizeMemCmpConstantSize(CallInst *CI, Value *LHS, Value *RHS,
uint64_t Len, IRBuilderBase &B,
const DataLayout &DL) { … }
Value *LibCallSimplifier::optimizeMemCmpBCmpCommon(CallInst *CI,
IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeMemCmp(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeBCmp(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeMemCCpy(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeMemPCpy(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeRealloc(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeNew(CallInst *CI, IRBuilderBase &B,
LibFunc &Func) { … }
static Value *replaceUnaryCall(CallInst *CI, IRBuilderBase &B,
Intrinsic::ID IID) { … }
static Value *valueHasFloatPrecision(Value *Val) { … }
static Value *optimizeDoubleFP(CallInst *CI, IRBuilderBase &B,
bool isBinary, const TargetLibraryInfo *TLI,
bool isPrecise = false) { … }
static Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilderBase &B,
const TargetLibraryInfo *TLI,
bool isPrecise = false) { … }
static Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilderBase &B,
const TargetLibraryInfo *TLI,
bool isPrecise = false) { … }
Value *LibCallSimplifier::optimizeCAbs(CallInst *CI, IRBuilderBase &B) { … }
static Value *getIntToFPVal(Value *I2F, IRBuilderBase &B, unsigned DstWidth) { … }
Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { … }
static Value *getSqrtCall(Value *V, AttributeList Attrs, bool NoErrno,
Module *M, IRBuilderBase &B,
const TargetLibraryInfo *TLI) { … }
Value *LibCallSimplifier::replacePowWithSqrt(CallInst *Pow, IRBuilderBase &B) { … }
static Value *createPowWithIntegerExponent(Value *Base, Value *Expo, Module *M,
IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) { … }
Value *LibCallSimplifier::mergeSqrtToExp(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeFMod(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeTrigInversionPairs(CallInst *CI,
IRBuilderBase &B) { … }
static bool isTrigLibCall(CallInst *CI) { … }
static bool insertSinCosCall(IRBuilderBase &B, Function *OrigCallee, Value *Arg,
bool UseFloat, Value *&Sin, Value *&Cos,
Value *&SinCos, const TargetLibraryInfo *TLI) { … }
static Value *optimizeSymmetricCall(CallInst *CI, bool IsEven,
IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeSymmetric(CallInst *CI, LibFunc Func,
IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeSinCosPi(CallInst *CI, bool IsSin, IRBuilderBase &B) { … }
void LibCallSimplifier::classifyArgUse(
Value *Val, Function *F, bool IsFloat,
SmallVectorImpl<CallInst *> &SinCalls,
SmallVectorImpl<CallInst *> &CosCalls,
SmallVectorImpl<CallInst *> &SinCosCalls) { … }
Value *LibCallSimplifier::optimizeRemquo(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeFFS(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeFls(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeAbs(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeIsDigit(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeIsAscii(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeToAscii(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeAtoi(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeStrToInt(CallInst *CI, IRBuilderBase &B,
bool AsSigned) { … }
static bool isReportingError(Function *Callee, CallInst *CI, int StreamArg);
Value *LibCallSimplifier::optimizeErrorReporting(CallInst *CI, IRBuilderBase &B,
int StreamArg) { … }
static bool isReportingError(Function *Callee, CallInst *CI, int StreamArg) { … }
Value *LibCallSimplifier::optimizePrintFString(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizePrintF(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeSPrintFString(CallInst *CI,
IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeSPrintF(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::emitSnPrintfMemCpy(CallInst *CI, Value *StrArg,
StringRef Str, uint64_t N,
IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeSnPrintFString(CallInst *CI,
IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeSnPrintF(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeFPrintFString(CallInst *CI,
IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeFPrintF(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeFWrite(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeFPuts(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizePuts(CallInst *CI, IRBuilderBase &B) { … }
Value *LibCallSimplifier::optimizeExit(CallInst *CI) { … }
Value *LibCallSimplifier::optimizeBCopy(CallInst *CI, IRBuilderBase &B) { … }
bool LibCallSimplifier::hasFloatVersion(const Module *M, StringRef FuncName) { … }
Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI,
IRBuilderBase &Builder) { … }
static Value *optimizeNaN(CallInst *CI) { … }
Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
LibFunc Func,
IRBuilderBase &Builder) { … }
Value *LibCallSimplifier::optimizeCall(CallInst *CI, IRBuilderBase &Builder) { … }
LibCallSimplifier::LibCallSimplifier(
const DataLayout &DL, const TargetLibraryInfo *TLI, DominatorTree *DT,
DomConditionCache *DC, AssumptionCache *AC, OptimizationRemarkEmitter &ORE,
BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI,
function_ref<void(Instruction *, Value *)> Replacer,
function_ref<void(Instruction *)> Eraser)
: … { … }
void LibCallSimplifier::replaceAllUsesWith(Instruction *I, Value *With) { … }
void LibCallSimplifier::eraseFromParent(Instruction *I) { … }
bool FortifiedLibCallSimplifier::isFortifiedCallFoldable(
CallInst *CI, unsigned ObjSizeOp, std::optional<unsigned> SizeOp,
std::optional<unsigned> StrOp, std::optional<unsigned> FlagOp) { … }
Value *FortifiedLibCallSimplifier::optimizeMemCpyChk(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeMemMoveChk(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeMemSetChk(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeMemPCpyChk(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI,
IRBuilderBase &B,
LibFunc Func) { … }
Value *FortifiedLibCallSimplifier::optimizeStrLenChk(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeStrpNCpyChk(CallInst *CI,
IRBuilderBase &B,
LibFunc Func) { … }
Value *FortifiedLibCallSimplifier::optimizeMemCCpyChk(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeSNPrintfChk(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeSPrintfChk(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeStrCatChk(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeStrLCat(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeStrNCatChk(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeStrLCpyChk(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeVSNPrintfChk(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeVSPrintfChk(CallInst *CI,
IRBuilderBase &B) { … }
Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI,
IRBuilderBase &Builder) { … }
FortifiedLibCallSimplifier::FortifiedLibCallSimplifier(
const TargetLibraryInfo *TLI, bool OnlyLowerUnknownSize)
: … { … }