[llvm] r217982 - Refactoring SimplifyLibCalls to remove static initializers and generally cleaning up the code.

David Blaikie dblaikie at gmail.com
Wed Sep 17 15:28:56 PDT 2014


On Wed, Sep 17, 2014 at 3:27 PM, Chris Bieneman <beanz at apple.com> wrote:

> I put in a change in r217988 that should have resolved it. I think your
> change will fail to build because now there are two destructors declared.
>

Yep - sorry, I seem to be a bit slow off the mark.

Reverted my fix in r217989.

Though it might be worth considering my fix over yours as it doesn't look
like objects of this type are polymorphically owned - so no virtual dtor is
necessary.

- David


>
> -Chris
>
> On Sep 17, 2014, at 3:25 PM, David Blaikie <dblaikie at gmail.com> wrote:
>
> This introduced a -Wnon-virtual-dtor warning which I've fixed in r217988.
> Let me know if that's not the right fix, etc.
>
> - David
>
> On Wed, Sep 17, 2014 at 1:55 PM, Chris Bieneman <beanz at apple.com> wrote:
>
>> Author: cbieneman
>> Date: Wed Sep 17 15:55:46 2014
>> New Revision: 217982
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=217982&view=rev
>> Log:
>> Refactoring SimplifyLibCalls to remove static initializers and generally
>> cleaning up the code.
>>
>> Summary: This eliminates ~200 lines of code mostly file scoped struct
>> definitions that were unnecessary.
>>
>> Reviewers: chandlerc, resistor
>>
>> Reviewed By: resistor
>>
>> Subscribers: morisset, resistor, llvm-commits
>>
>> Differential Revision: http://reviews.llvm.org/D5364
>>
>> Modified:
>>     llvm/trunk/include/llvm/Transforms/Utils/SimplifyLibCalls.h
>>     llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
>>     llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp
>>
>> Modified: llvm/trunk/include/llvm/Transforms/Utils/SimplifyLibCalls.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/SimplifyLibCalls.h?rev=217982&r1=217981&r2=217982&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Transforms/Utils/SimplifyLibCalls.h (original)
>> +++ llvm/trunk/include/llvm/Transforms/Utils/SimplifyLibCalls.h Wed Sep
>> 17 15:55:46 2014
>> @@ -15,40 +15,114 @@
>>  #ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H
>>  #define LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H
>>
>> +#include "llvm/ADT/StringRef.h"
>> +#include "llvm/IR/IRBuilder.h"
>> +
>>  namespace llvm {
>> -  class Value;
>> -  class CallInst;
>> -  class DataLayout;
>> -  class Instruction;
>> -  class TargetLibraryInfo;
>> -  class LibCallSimplifierImpl;
>> -
>> -  /// LibCallSimplifier - This class implements a collection of
>> optimizations
>> -  /// that replace well formed calls to library functions with a more
>> optimal
>> -  /// form.  For example, replacing 'printf("Hello!")' with
>> 'puts("Hello!")'.
>> -  class LibCallSimplifier {
>> -    /// Impl - A pointer to the actual implementation of the library call
>> -    /// simplifier.
>> -    LibCallSimplifierImpl *Impl;
>> -
>> -  public:
>> -    LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI,
>> -                      bool UnsafeFPShrink);
>> -    virtual ~LibCallSimplifier();
>> -
>> -    /// optimizeCall - Take the given call instruction and return a more
>> -    /// optimal value to replace the instruction with or 0 if a more
>> -    /// optimal form can't be found.  Note that the returned value may
>> -    /// be equal to the instruction being optimized.  In this case all
>> -    /// other instructions that use the given instruction were modified
>> -    /// and the given instruction is dead.
>> -    Value *optimizeCall(CallInst *CI);
>> -
>> -    /// replaceAllUsesWith - This method is used when the library call
>> -    /// simplifier needs to replace instructions other than the library
>> -    /// call being modified.
>> -    virtual void replaceAllUsesWith(Instruction *I, Value *With) const;
>> -  };
>> +class Value;
>> +class CallInst;
>> +class DataLayout;
>> +class Instruction;
>> +class TargetLibraryInfo;
>> +class BasicBlock;
>> +class Function;
>> +
>> +/// LibCallSimplifier - This class implements a collection of
>> optimizations
>> +/// that replace well formed calls to library functions with a more
>> optimal
>> +/// form.  For example, replacing 'printf("Hello!")' with
>> 'puts("Hello!")'.
>> +class LibCallSimplifier {
>> +private:
>> +  const DataLayout *DL;
>> +  const TargetLibraryInfo *TLI;
>> +  bool UnsafeFPShrink;
>> +
>> +public:
>> +  LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI,
>> +                    bool UnsafeFPShrink);
>> +
>> +  /// optimizeCall - Take the given call instruction and return a more
>> +  /// optimal value to replace the instruction with or 0 if a more
>> +  /// optimal form can't be found.  Note that the returned value may
>> +  /// be equal to the instruction being optimized.  In this case all
>> +  /// other instructions that use the given instruction were modified
>> +  /// and the given instruction is dead.
>> +  Value *optimizeCall(CallInst *CI);
>> +
>> +  /// replaceAllUsesWith - This method is used when the library call
>> +  /// simplifier needs to replace instructions other than the library
>> +  /// call being modified.
>> +  virtual void replaceAllUsesWith(Instruction *I, Value *With) const;
>> +
>> +private:
>> +  // Fortified Library Call Optimizations
>> +  Value *optimizeMemCpyChk(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeMemMoveChk(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeMemSetChk(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrCpyChk(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStpCpyChk(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrNCpyChk(CallInst *CI, IRBuilder<> &B);
>> +
>> +  // String and Memory Library Call Optimizations
>> +  Value *optimizeStrCat(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrNCat(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrChr(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrRChr(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrCmp(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrNCmp(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrCpy(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStpCpy(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrNCpy(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrLen(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrPBrk(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrTo(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrSpn(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrCSpn(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeStrStr(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeMemCmp(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B);
>> +
>> +  // Math Library Optimizations
>> +  Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilder<> &B, bool
>> CheckRetType);
>> +  Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeCos(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizePow(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeExp2(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeSinCosPi(CallInst *CI, IRBuilder<> &B);
>> +
>> +  // Integer Library Call Optimizations
>> +  Value *optimizeFFS(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeAbs(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeIsDigit(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeIsAscii(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeToAscii(CallInst *CI, IRBuilder<> &B);
>> +
>> +  // Formatting and IO Library Call Optimizations
>> +  Value *optimizeErrorReporting(CallInst *CI, IRBuilder<> &B,
>> +                                int StreamArg = -1);
>> +  Value *optimizePrintF(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeSPrintF(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeFPrintF(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeFWrite(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeFPuts(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizePuts(CallInst *CI, IRBuilder<> &B);
>> +
>> +  // Helper methods
>> +  Value *emitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len,
>> IRBuilder<> &B);
>> +  void classifyArgUse(Value *Val, BasicBlock *BB, bool IsFloat,
>> +                      SmallVectorImpl<CallInst *> &SinCalls,
>> +                      SmallVectorImpl<CallInst *> &CosCalls,
>> +                      SmallVectorImpl<CallInst *> &SinCosCalls);
>> +  void replaceTrigInsts(SmallVectorImpl<CallInst *> &Calls, Value *Res);
>> +  Value *optimizePrintFString(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeSPrintFString(CallInst *CI, IRBuilder<> &B);
>> +  Value *optimizeFPrintFString(CallInst *CI, IRBuilder<> &B);
>> +
>> +  /// hasFloatVersion - Checks if there is a float version of the
>> specified
>> +  /// function by checking for an existing function with name FuncName +
>> f
>> +  bool hasFloatVersion(StringRef FuncName);
>> +};
>>  } // End llvm namespace
>>
>>  #endif
>>
>> Modified: llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp?rev=217982&r1=217981&r2=217982&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
>> (original)
>> +++ llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp Wed
>> Sep 17 15:55:46 2014
>> @@ -70,10 +70,11 @@ STATISTIC(NumExpand,    "Number of expan
>>  STATISTIC(NumFactor   , "Number of factorizations");
>>  STATISTIC(NumReassoc  , "Number of reassociations");
>>
>> -static cl::opt<bool> UnsafeFPShrink("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>
>> +    EnableUnsafeFPShrink("enable-double-float-shrink", cl::Hidden,
>> +                         cl::init(false),
>> +                         cl::desc("Enable unsafe double to float "
>> +                                  "shrinking for math lib calls"));
>>
>>  // Initialization Routines
>>  void llvm::initializeInstCombine(PassRegistry &Registry) {
>> @@ -2913,7 +2914,7 @@ public:
>>    InstCombinerLibCallSimplifier(const DataLayout *DL,
>>                                  const TargetLibraryInfo *TLI,
>>                                  InstCombiner *IC)
>> -    : LibCallSimplifier(DL, TLI, UnsafeFPShrink) {
>> +    : LibCallSimplifier(DL, TLI, EnableUnsafeFPShrink) {
>>      this->IC = IC;
>>    }
>>
>>
>> Modified: llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp?rev=217982&r1=217981&r2=217982&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp (original)
>> +++ llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp Wed Sep 17
>> 15:55:46 2014
>> @@ -35,57 +35,26 @@
>>  using namespace llvm;
>>
>>  static cl::opt<bool>
>> -ColdErrorCalls("error-reporting-is-cold",  cl::init(true),
>> -  cl::Hidden, cl::desc("Treat error-reporting calls as cold"));
>> -
>> -/// This class is the abstract base class for the set of optimizations
>> that
>> -/// corresponds to one library call.
>> -namespace {
>> -class LibCallOptimization {
>> -protected:
>> -  Function *Caller;
>> -  const DataLayout *DL;
>> -  const TargetLibraryInfo *TLI;
>> -  const LibCallSimplifier *LCS;
>> -  LLVMContext* Context;
>> -public:
>> -  LibCallOptimization() { }
>> -  virtual ~LibCallOptimization() {}
>> -
>> -  /// callOptimizer - This pure virtual method is implemented by base
>> classes to
>> -  /// do various optimizations.  If this returns null then no
>> transformation was
>> -  /// performed.  If it returns CI, then it transformed the call and CI
>> is to be
>> -  /// deleted.  If it returns something else, replace CI with the new
>> value and
>> -  /// delete CI.
>> -  virtual Value *callOptimizer(Function *Callee, CallInst *CI,
>> IRBuilder<> &B)
>> -    =0;
>> -
>> -  /// ignoreCallingConv - Returns false if this transformation could
>> possibly
>> -  /// change the calling convention.
>> -  virtual bool ignoreCallingConv() { return false; }
>> -
>> -  Value *optimizeCall(CallInst *CI, const DataLayout *DL,
>> -                      const TargetLibraryInfo *TLI,
>> -                      const LibCallSimplifier *LCS, IRBuilder<> &B) {
>> -    Caller = CI->getParent()->getParent();
>> -    this->DL = DL;
>> -    this->TLI = TLI;
>> -    this->LCS = LCS;
>> -    if (CI->getCalledFunction())
>> -      Context = &CI->getCalledFunction()->getContext();
>> -
>> -    // We never change the calling convention.
>> -    if (!ignoreCallingConv() && CI->getCallingConv() !=
>> llvm::CallingConv::C)
>> -      return nullptr;
>> -
>> -    return callOptimizer(CI->getCalledFunction(), CI, B);
>> -  }
>> -};
>> +    ColdErrorCalls("error-reporting-is-cold", cl::init(true), cl::Hidden,
>> +                   cl::desc("Treat error-reporting calls as cold"));
>>
>>
>>  //===----------------------------------------------------------------------===//
>>  // Helper Functions
>>
>>  //===----------------------------------------------------------------------===//
>>
>> +static bool ignoreCallingConv(LibFunc::Func Func) {
>> +  switch (Func) {
>> +  case LibFunc::abs:
>> +  case LibFunc::labs:
>> +  case LibFunc::llabs:
>> +  case LibFunc::strlen:
>> +    return true;
>> +  default:
>> +    return false;
>> +  }
>> +  llvm_unreachable();
>> +}
>> +
>>  /// isOnlyUsedInZeroEqualityComparison - Return true if it only matters
>> that the
>>  /// value is equal or not-equal to zero.
>>  static bool isOnlyUsedInZeroEqualityComparison(Value *V) {
>> @@ -142,967 +111,912 @@ static bool hasUnaryFloatFn(const Target
>>  // Fortified Library Call Optimizations
>>
>>  //===----------------------------------------------------------------------===//
>>
>> -struct FortifiedLibCallOptimization : public LibCallOptimization {
>> -protected:
>> -  virtual bool isFoldable(unsigned SizeCIOp, unsigned SizeArgOp,
>> -                         bool isString) const = 0;
>> -};
>> -
>> -struct InstFortifiedLibCallOptimization : public
>> FortifiedLibCallOptimization {
>> -  CallInst *CI;
>> -
>> -  bool isFoldable(unsigned SizeCIOp, unsigned SizeArgOp,
>> -                  bool isString) const override {
>> -    if (CI->getArgOperand(SizeCIOp) == CI->getArgOperand(SizeArgOp))
>> +static bool isFortifiedCallFoldable(CallInst *CI, unsigned SizeCIOp,
>> unsigned SizeArgOp,
>> +                       bool isString) {
>> +  if (CI->getArgOperand(SizeCIOp) == CI->getArgOperand(SizeArgOp))
>> +    return true;
>> +  if (ConstantInt *SizeCI =
>> +          dyn_cast<ConstantInt>(CI->getArgOperand(SizeCIOp))) {
>> +    if (SizeCI->isAllOnesValue())
>>        return true;
>> -    if (ConstantInt *SizeCI =
>> -
>>  dyn_cast<ConstantInt>(CI->getArgOperand(SizeCIOp))) {
>> -      if (SizeCI->isAllOnesValue())
>> -        return true;
>> -      if (isString) {
>> -        uint64_t Len = GetStringLength(CI->getArgOperand(SizeArgOp));
>> -        // If the length is 0 we don't know how long it is and so we
>> can't
>> -        // remove the check.
>> -        if (Len == 0) return false;
>> -        return SizeCI->getZExtValue() >= Len;
>> -      }
>> -      if (ConstantInt *Arg = dyn_cast<ConstantInt>(
>> -
>> CI->getArgOperand(SizeArgOp)))
>> -        return SizeCI->getZExtValue() >= Arg->getZExtValue();
>> +    if (isString) {
>> +      uint64_t Len = GetStringLength(CI->getArgOperand(SizeArgOp));
>> +      // If the length is 0 we don't know how long it is and so we can't
>> +      // remove the check.
>> +      if (Len == 0)
>> +        return false;
>> +      return SizeCI->getZExtValue() >= Len;
>>      }
>> -    return false;
>> +    if (ConstantInt *Arg =
>> dyn_cast<ConstantInt>(CI->getArgOperand(SizeArgOp)))
>> +      return SizeCI->getZExtValue() >= Arg->getZExtValue();
>>    }
>> -};
>> +  return false;
>> +}
>>
>> -struct MemCpyChkOpt : public InstFortifiedLibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    this->CI = CI;
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    LLVMContext &Context = CI->getParent()->getContext();
>> -
>> -    // Check if this has the right signature.
>> -    if (FT->getNumParams() != 4 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> -        !FT->getParamType(0)->isPointerTy() ||
>> -        !FT->getParamType(1)->isPointerTy() ||
>> -        FT->getParamType(2) != DL->getIntPtrType(Context) ||
>> -        FT->getParamType(3) != DL->getIntPtrType(Context))
>> -      return nullptr;
>> -
>> -    if (isFoldable(3, 2, false)) {
>> -      B.CreateMemCpy(CI->getArgOperand(0), CI->getArgOperand(1),
>> -                     CI->getArgOperand(2), 1);
>> -      return CI->getArgOperand(0);
>> -    }
>> -    return nullptr;
>> -  }
>> -};
>> +Value *LibCallSimplifier::optimizeMemCpyChk(CallInst *CI, IRBuilder<>
>> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  LLVMContext &Context = CI->getContext();
>>
>> -struct MemMoveChkOpt : public InstFortifiedLibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    this->CI = CI;
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    LLVMContext &Context = CI->getParent()->getContext();
>> -
>> -    // Check if this has the right signature.
>> -    if (FT->getNumParams() != 4 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> -        !FT->getParamType(0)->isPointerTy() ||
>> -        !FT->getParamType(1)->isPointerTy() ||
>> -        FT->getParamType(2) != DL->getIntPtrType(Context) ||
>> -        FT->getParamType(3) != DL->getIntPtrType(Context))
>> -      return nullptr;
>> -
>> -    if (isFoldable(3, 2, false)) {
>> -      B.CreateMemMove(CI->getArgOperand(0), CI->getArgOperand(1),
>> -                      CI->getArgOperand(2), 1);
>> -      return CI->getArgOperand(0);
>> -    }
>> +  // Check if this has the right signature.
>> +  if (FT->getNumParams() != 4 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      !FT->getParamType(0)->isPointerTy() ||
>> +      !FT->getParamType(1)->isPointerTy() ||
>> +      FT->getParamType(2) != DL->getIntPtrType(Context) ||
>> +      FT->getParamType(3) != DL->getIntPtrType(Context))
>>      return nullptr;
>> -  }
>> -};
>>
>> -struct MemSetChkOpt : public InstFortifiedLibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    this->CI = CI;
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    LLVMContext &Context = CI->getParent()->getContext();
>> -
>> -    // Check if this has the right signature.
>> -    if (FT->getNumParams() != 4 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> -        !FT->getParamType(0)->isPointerTy() ||
>> -        !FT->getParamType(1)->isIntegerTy() ||
>> -        FT->getParamType(2) != DL->getIntPtrType(Context) ||
>> -        FT->getParamType(3) != DL->getIntPtrType(Context))
>> -      return nullptr;
>> -
>> -    if (isFoldable(3, 2, false)) {
>> -      Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(),
>> -                                   false);
>> -      B.CreateMemSet(CI->getArgOperand(0), Val, CI->getArgOperand(2), 1);
>> -      return CI->getArgOperand(0);
>> -    }
>> -    return nullptr;
>> +  if (isFortifiedCallFoldable(CI, 3, 2, false)) {
>> +    B.CreateMemCpy(CI->getArgOperand(0), CI->getArgOperand(1),
>> +                   CI->getArgOperand(2), 1);
>> +    return CI->getArgOperand(0);
>>    }
>> -};
>> +  return nullptr;
>> +}
>>
>> -struct StrCpyChkOpt : public InstFortifiedLibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    this->CI = CI;
>> -    StringRef Name = Callee->getName();
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    LLVMContext &Context = CI->getParent()->getContext();
>> -
>> -    // Check if this has the right signature.
>> -    if (FT->getNumParams() != 3 ||
>> -        FT->getReturnType() != FT->getParamType(0) ||
>> -        FT->getParamType(0) != FT->getParamType(1) ||
>> -        FT->getParamType(0) != Type::getInt8PtrTy(Context) ||
>> -        FT->getParamType(2) != DL->getIntPtrType(Context))
>> -      return nullptr;
>> -
>> -    Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
>> -    if (Dst == Src)      // __strcpy_chk(x,x)  -> x
>> -      return Src;
>> -
>> -    // If a) we don't have any length information, or b) we know this
>> will
>> -    // fit then just lower to a plain strcpy. Otherwise we'll keep our
>> -    // strcpy_chk call which may fail at runtime if the size is too long.
>> -    // TODO: It might be nice to get a maximum length out of the possible
>> -    // string lengths for varying.
>> -    if (isFoldable(2, 1, true)) {
>> -      Value *Ret = EmitStrCpy(Dst, Src, B, DL, TLI, Name.substr(2, 6));
>> -      return Ret;
>> -    } else {
>> -      // Maybe we can stil fold __strcpy_chk to __memcpy_chk.
>> -      uint64_t Len = GetStringLength(Src);
>> -      if (Len == 0) return nullptr;
>> -
>> -      // This optimization require DataLayout.
>> -      if (!DL) return nullptr;
>> -
>> -      Value *Ret =
>> -       EmitMemCpyChk(Dst, Src,
>> -                      ConstantInt::get(DL->getIntPtrType(Context), Len),
>> -                      CI->getArgOperand(2), B, DL, TLI);
>> -      return Ret;
>> -    }
>> +Value *LibCallSimplifier::optimizeMemMoveChk(CallInst *CI, IRBuilder<>
>> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  LLVMContext &Context = CI->getContext();
>> +
>> +  // Check if this has the right signature.
>> +  if (FT->getNumParams() != 4 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      !FT->getParamType(0)->isPointerTy() ||
>> +      !FT->getParamType(1)->isPointerTy() ||
>> +      FT->getParamType(2) != DL->getIntPtrType(Context) ||
>> +      FT->getParamType(3) != DL->getIntPtrType(Context))
>>      return nullptr;
>> +
>> +  if (isFortifiedCallFoldable(CI, 3, 2, false)) {
>> +    B.CreateMemMove(CI->getArgOperand(0), CI->getArgOperand(1),
>> +                    CI->getArgOperand(2), 1);
>> +    return CI->getArgOperand(0);
>>    }
>> -};
>> +  return nullptr;
>> +}
>>
>> -struct StpCpyChkOpt : public InstFortifiedLibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    this->CI = CI;
>> -    StringRef Name = Callee->getName();
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    LLVMContext &Context = CI->getParent()->getContext();
>> -
>> -    // Check if this has the right signature.
>> -    if (FT->getNumParams() != 3 ||
>> -        FT->getReturnType() != FT->getParamType(0) ||
>> -        FT->getParamType(0) != FT->getParamType(1) ||
>> -        FT->getParamType(0) != Type::getInt8PtrTy(Context) ||
>> -        FT->getParamType(2) != DL->getIntPtrType(FT->getParamType(0)))
>> -      return nullptr;
>> -
>> -    Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
>> -    if (Dst == Src) {  // stpcpy(x,x)  -> x+strlen(x)
>> -      Value *StrLen = EmitStrLen(Src, B, DL, TLI);
>> -      return StrLen ? B.CreateInBoundsGEP(Dst, StrLen) : nullptr;
>> -    }
>> +Value *LibCallSimplifier::optimizeMemSetChk(CallInst *CI, IRBuilder<>
>> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  LLVMContext &Context = CI->getContext();
>>
>> -    // If a) we don't have any length information, or b) we know this
>> will
>> -    // fit then just lower to a plain stpcpy. Otherwise we'll keep our
>> -    // stpcpy_chk call which may fail at runtime if the size is too long.
>> -    // TODO: It might be nice to get a maximum length out of the possible
>> -    // string lengths for varying.
>> -    if (isFoldable(2, 1, true)) {
>> -      Value *Ret = EmitStrCpy(Dst, Src, B, DL, TLI, Name.substr(2, 6));
>> -      return Ret;
>> -    } else {
>> -      // Maybe we can stil fold __stpcpy_chk to __memcpy_chk.
>> -      uint64_t Len = GetStringLength(Src);
>> -      if (Len == 0) return nullptr;
>> -
>> -      // This optimization require DataLayout.
>> -      if (!DL) return nullptr;
>> -
>> -      Type *PT = FT->getParamType(0);
>> -      Value *LenV = ConstantInt::get(DL->getIntPtrType(PT), Len);
>> -      Value *DstEnd = B.CreateGEP(Dst,
>> -                                  ConstantInt::get(DL->getIntPtrType(PT),
>> -                                                   Len - 1));
>> -      if (!EmitMemCpyChk(Dst, Src, LenV, CI->getArgOperand(2), B, DL,
>> TLI))
>> -        return nullptr;
>> -      return DstEnd;
>> -    }
>> +  // Check if this has the right signature.
>> +  if (FT->getNumParams() != 4 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      !FT->getParamType(0)->isPointerTy() ||
>> +      !FT->getParamType(1)->isIntegerTy() ||
>> +      FT->getParamType(2) != DL->getIntPtrType(Context) ||
>> +      FT->getParamType(3) != DL->getIntPtrType(Context))
>>      return nullptr;
>> -  }
>> -};
>>
>> -struct StrNCpyChkOpt : public InstFortifiedLibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    this->CI = CI;
>> -    StringRef Name = Callee->getName();
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    LLVMContext &Context = CI->getParent()->getContext();
>> -
>> -    // Check if this has the right signature.
>> -    if (FT->getNumParams() != 4 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> -        FT->getParamType(0) != FT->getParamType(1) ||
>> -        FT->getParamType(0) != Type::getInt8PtrTy(Context) ||
>> -        !FT->getParamType(2)->isIntegerTy() ||
>> -        FT->getParamType(3) != DL->getIntPtrType(Context))
>> -      return nullptr;
>> -
>> -    if (isFoldable(3, 2, false)) {
>> -      Value *Ret = EmitStrNCpy(CI->getArgOperand(0),
>> CI->getArgOperand(1),
>> -                               CI->getArgOperand(2), B, DL, TLI,
>> -                               Name.substr(2, 7));
>> -      return Ret;
>> -    }
>> -    return nullptr;
>> +  if (isFortifiedCallFoldable(CI, 3, 2, false)) {
>> +    Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(),
>> false);
>> +    B.CreateMemSet(CI->getArgOperand(0), Val, CI->getArgOperand(2), 1);
>> +    return CI->getArgOperand(0);
>>    }
>> -};
>> -
>>
>> -//===----------------------------------------------------------------------===//
>> -// String and Memory Library Call Optimizations
>>
>> -//===----------------------------------------------------------------------===//
>> -
>> -struct StrCatOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // Verify the "strcat" function prototype.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 2 ||
>> -        FT->getReturnType() != B.getInt8PtrTy() ||
>> -        FT->getParamType(0) != FT->getReturnType() ||
>> -        FT->getParamType(1) != FT->getReturnType())
>> -      return nullptr;
>> -
>> -    // Extract some information from the instruction
>> -    Value *Dst = CI->getArgOperand(0);
>> -    Value *Src = CI->getArgOperand(1);
>> +  return nullptr;
>> +}
>>
>> -    // See if we can get the length of the input string.
>> +Value *LibCallSimplifier::optimizeStrCpyChk(CallInst *CI, IRBuilder<>
>> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  StringRef Name = Callee->getName();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  LLVMContext &Context = CI->getContext();
>> +
>> +  // Check if this has the right signature.
>> +  if (FT->getNumParams() != 3 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      FT->getParamType(0) != FT->getParamType(1) ||
>> +      FT->getParamType(0) != Type::getInt8PtrTy(Context) ||
>> +      FT->getParamType(2) != DL->getIntPtrType(Context))
>> +    return nullptr;
>> +
>> +  Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
>> +  if (Dst == Src) // __strcpy_chk(x,x)  -> x
>> +    return Src;
>> +
>> +  // If a) we don't have any length information, or b) we know this will
>> +  // fit then just lower to a plain strcpy. Otherwise we'll keep our
>> +  // strcpy_chk call which may fail at runtime if the size is too long.
>> +  // TODO: It might be nice to get a maximum length out of the possible
>> +  // string lengths for varying.
>> +  if (isFortifiedCallFoldable(CI, 2, 1, true)) {
>> +    Value *Ret = EmitStrCpy(Dst, Src, B, DL, TLI, Name.substr(2, 6));
>> +    return Ret;
>> +  } else {
>> +    // Maybe we can stil fold __strcpy_chk to __memcpy_chk.
>>      uint64_t Len = GetStringLength(Src);
>> -    if (Len == 0) return nullptr;
>> -    --Len;  // Unbias length.
>> -
>> -    // Handle the simple, do-nothing case: strcat(x, "") -> x
>>      if (Len == 0)
>> -      return Dst;
>> +      return nullptr;
>>
>> -    // These optimizations require DataLayout.
>> -    if (!DL) return nullptr;
>> +    // This optimization require DataLayout.
>> +    if (!DL)
>> +      return nullptr;
>>
>> -    return emitStrLenMemCpy(Src, Dst, Len, B);
>> +    Value *Ret = EmitMemCpyChk(
>> +        Dst, Src, ConstantInt::get(DL->getIntPtrType(Context), Len),
>> +        CI->getArgOperand(2), B, DL, TLI);
>> +    return Ret;
>>    }
>> +  return nullptr;
>> +}
>>
>> -  Value *emitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len,
>> -                          IRBuilder<> &B) {
>> -    // We need to find the end of the destination string.  That's where
>> the
>> -    // memory is to be moved to. We just generate a call to strlen.
>> -    Value *DstLen = EmitStrLen(Dst, B, DL, TLI);
>> -    if (!DstLen)
>> +Value *LibCallSimplifier::optimizeStpCpyChk(CallInst *CI, IRBuilder<>
>> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  StringRef Name = Callee->getName();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  LLVMContext &Context = CI->getContext();
>> +
>> +  // Check if this has the right signature.
>> +  if (FT->getNumParams() != 3 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      FT->getParamType(0) != FT->getParamType(1) ||
>> +      FT->getParamType(0) != Type::getInt8PtrTy(Context) ||
>> +      FT->getParamType(2) != DL->getIntPtrType(FT->getParamType(0)))
>> +    return nullptr;
>> +
>> +  Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
>> +  if (Dst == Src) { // stpcpy(x,x)  -> x+strlen(x)
>> +    Value *StrLen = EmitStrLen(Src, B, DL, TLI);
>> +    return StrLen ? B.CreateInBoundsGEP(Dst, StrLen) : nullptr;
>> +  }
>> +
>> +  // If a) we don't have any length information, or b) we know this will
>> +  // fit then just lower to a plain stpcpy. Otherwise we'll keep our
>> +  // stpcpy_chk call which may fail at runtime if the size is too long.
>> +  // TODO: It might be nice to get a maximum length out of the possible
>> +  // string lengths for varying.
>> +  if (isFortifiedCallFoldable(CI, 2, 1, true)) {
>> +    Value *Ret = EmitStrCpy(Dst, Src, B, DL, TLI, Name.substr(2, 6));
>> +    return Ret;
>> +  } else {
>> +    // Maybe we can stil fold __stpcpy_chk to __memcpy_chk.
>> +    uint64_t Len = GetStringLength(Src);
>> +    if (Len == 0)
>>        return nullptr;
>>
>> -    // Now that we have the destination's length, we must index into the
>> -    // destination's pointer to get the actual memcpy destination (end of
>> -    // the string .. we're concatenating).
>> -    Value *CpyDst = B.CreateGEP(Dst, DstLen, "endptr");
>> +    // This optimization require DataLayout.
>> +    if (!DL)
>> +      return nullptr;
>>
>> -    // We have enough information to now generate the memcpy call to do
>> the
>> -    // concatenation for us.  Make a memcpy to copy the nul byte with
>> align = 1.
>> -    B.CreateMemCpy(CpyDst, Src,
>> -                   ConstantInt::get(DL->getIntPtrType(*Context), Len +
>> 1), 1);
>> -    return Dst;
>> +    Type *PT = FT->getParamType(0);
>> +    Value *LenV = ConstantInt::get(DL->getIntPtrType(PT), Len);
>> +    Value *DstEnd =
>> +        B.CreateGEP(Dst, ConstantInt::get(DL->getIntPtrType(PT), Len -
>> 1));
>> +    if (!EmitMemCpyChk(Dst, Src, LenV, CI->getArgOperand(2), B, DL, TLI))
>> +      return nullptr;
>> +    return DstEnd;
>>    }
>> -};
>> +  return nullptr;
>> +}
>>
>> -struct StrNCatOpt : public StrCatOpt {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // Verify the "strncat" function prototype.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 3 ||
>> -        FT->getReturnType() != B.getInt8PtrTy() ||
>> -        FT->getParamType(0) != FT->getReturnType() ||
>> -        FT->getParamType(1) != FT->getReturnType() ||
>> -        !FT->getParamType(2)->isIntegerTy())
>> -      return nullptr;
>> -
>> -    // Extract some information from the instruction
>> -    Value *Dst = CI->getArgOperand(0);
>> -    Value *Src = CI->getArgOperand(1);
>> -    uint64_t Len;
>> -
>> -    // We don't do anything if length is not constant
>> -    if (ConstantInt *LengthArg =
>> dyn_cast<ConstantInt>(CI->getArgOperand(2)))
>> -      Len = LengthArg->getZExtValue();
>> -    else
>> -      return nullptr;
>> -
>> -    // See if we can get the length of the input string.
>> -    uint64_t SrcLen = GetStringLength(Src);
>> -    if (SrcLen == 0) return nullptr;
>> -    --SrcLen;  // Unbias length.
>> -
>> -    // Handle the simple, do-nothing cases:
>> -    // strncat(x, "", c) -> x
>> -    // strncat(x,  c, 0) -> x
>> -    if (SrcLen == 0 || Len == 0) return Dst;
>> +Value *LibCallSimplifier::optimizeStrNCpyChk(CallInst *CI, IRBuilder<>
>> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  StringRef Name = Callee->getName();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  LLVMContext &Context = CI->getContext();
>> +
>> +  // Check if this has the right signature.
>> +  if (FT->getNumParams() != 4 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      FT->getParamType(0) != FT->getParamType(1) ||
>> +      FT->getParamType(0) != Type::getInt8PtrTy(Context) ||
>> +      !FT->getParamType(2)->isIntegerTy() ||
>> +      FT->getParamType(3) != DL->getIntPtrType(Context))
>> +    return nullptr;
>> +
>> +  if (isFortifiedCallFoldable(CI, 3, 2, false)) {
>> +    Value *Ret =
>> +        EmitStrNCpy(CI->getArgOperand(0), CI->getArgOperand(1),
>> +                    CI->getArgOperand(2), B, DL, TLI, Name.substr(2, 7));
>> +    return Ret;
>> +  }
>> +  return nullptr;
>> +}
>>
>> -    // These optimizations require DataLayout.
>> -    if (!DL) return nullptr;
>>
>> +//===----------------------------------------------------------------------===//
>> +// String and Memory Library Call Optimizations
>>
>> +//===----------------------------------------------------------------------===//
>>
>> -    // We don't optimize this case
>> -    if (Len < SrcLen) return nullptr;
>> +Value *LibCallSimplifier::optimizeStrCat(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // Verify the "strcat" function prototype.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 2||
>> +      FT->getReturnType() != B.getInt8PtrTy() ||
>> +      FT->getParamType(0) != FT->getReturnType() ||
>> +      FT->getParamType(1) != FT->getReturnType())
>> +    return nullptr;
>> +
>> +  // Extract some information from the instruction
>> +  Value *Dst = CI->getArgOperand(0);
>> +  Value *Src = CI->getArgOperand(1);
>> +
>> +  // See if we can get the length of the input string.
>> +  uint64_t Len = GetStringLength(Src);
>> +  if (Len == 0)
>> +    return nullptr;
>> +  --Len; // Unbias length.
>>
>> -    // strncat(x, s, c) -> strcat(x, s)
>> -    // s is constant so the strcat can be optimized further
>> -    return emitStrLenMemCpy(Src, Dst, SrcLen, B);
>> -  }
>> -};
>> -
>> -struct StrChrOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // Verify the "strchr" function prototype.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 2 ||
>> -        FT->getReturnType() != B.getInt8PtrTy() ||
>> -        FT->getParamType(0) != FT->getReturnType() ||
>> -        !FT->getParamType(1)->isIntegerTy(32))
>> -      return nullptr;
>> -
>> -    Value *SrcStr = CI->getArgOperand(0);
>> -
>> -    // If the second operand is non-constant, see if we can compute the
>> length
>> -    // of the input string and turn this into memchr.
>> -    ConstantInt *CharC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
>> -    if (!CharC) {
>> -      // These optimizations require DataLayout.
>> -      if (!DL) return nullptr;
>> +  // Handle the simple, do-nothing case: strcat(x, "") -> x
>> +  if (Len == 0)
>> +    return Dst;
>>
>> -      uint64_t Len = GetStringLength(SrcStr);
>> -      if (Len == 0 || !FT->getParamType(1)->isIntegerTy(32))// memchr
>> needs i32.
>> -        return nullptr;
>> +  // These optimizations require DataLayout.
>> +  if (!DL)
>> +    return nullptr;
>>
>> -      return EmitMemChr(SrcStr, CI->getArgOperand(1), // include nul.
>> -                        ConstantInt::get(DL->getIntPtrType(*Context),
>> Len),
>> -                        B, DL, TLI);
>> -    }
>> +  return emitStrLenMemCpy(Src, Dst, Len, B);
>> +}
>>
>> -    // Otherwise, the character is a constant, see if the first argument
>> is
>> -    // a string literal.  If so, we can constant fold.
>> -    StringRef Str;
>> -    if (!getConstantStringInfo(SrcStr, Str)) {
>> -      if (DL && CharC->isZero()) // strchr(p, 0) -> p + strlen(p)
>> -        return B.CreateGEP(SrcStr, EmitStrLen(SrcStr, B, DL, TLI),
>> "strchr");
>> -      return nullptr;
>> -    }
>> +Value *LibCallSimplifier::emitStrLenMemCpy(Value *Src, Value *Dst,
>> uint64_t Len,
>> +                                           IRBuilder<> &B) {
>> +  // We need to find the end of the destination string.  That's where the
>> +  // memory is to be moved to. We just generate a call to strlen.
>> +  Value *DstLen = EmitStrLen(Dst, B, DL, TLI);
>> +  if (!DstLen)
>> +    return nullptr;
>> +
>> +  // Now that we have the destination's length, we must index into the
>> +  // destination's pointer to get the actual memcpy destination (end of
>> +  // the string .. we're concatenating).
>> +  Value *CpyDst = B.CreateGEP(Dst, DstLen, "endptr");
>> +
>> +  // We have enough information to now generate the memcpy call to do the
>> +  // concatenation for us.  Make a memcpy to copy the nul byte with
>> align = 1.
>> +  B.CreateMemCpy(
>> +      CpyDst, Src,
>> +      ConstantInt::get(DL->getIntPtrType(Src->getContext()), Len + 1),
>> 1);
>> +  return Dst;
>> +}
>>
>> -    // Compute the offset, make sure to handle the case when we're
>> searching for
>> -    // zero (a weird way to spell strlen).
>> -    size_t I = (0xFF & CharC->getSExtValue()) == 0 ?
>> -        Str.size() : Str.find(CharC->getSExtValue());
>> -    if (I == StringRef::npos) // Didn't find the char.  strchr returns
>> null.
>> -      return Constant::getNullValue(CI->getType());
>> +Value *LibCallSimplifier::optimizeStrNCat(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // Verify the "strncat" function prototype.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 3 || FT->getReturnType() != B.getInt8PtrTy()
>> ||
>> +      FT->getParamType(0) != FT->getReturnType() ||
>> +      FT->getParamType(1) != FT->getReturnType() ||
>> +      !FT->getParamType(2)->isIntegerTy())
>> +    return nullptr;
>> +
>> +  // Extract some information from the instruction
>> +  Value *Dst = CI->getArgOperand(0);
>> +  Value *Src = CI->getArgOperand(1);
>> +  uint64_t Len;
>> +
>> +  // We don't do anything if length is not constant
>> +  if (ConstantInt *LengthArg =
>> dyn_cast<ConstantInt>(CI->getArgOperand(2)))
>> +    Len = LengthArg->getZExtValue();
>> +  else
>> +    return nullptr;
>> +
>> +  // See if we can get the length of the input string.
>> +  uint64_t SrcLen = GetStringLength(Src);
>> +  if (SrcLen == 0)
>> +    return nullptr;
>> +  --SrcLen; // Unbias length.
>> +
>> +  // Handle the simple, do-nothing cases:
>> +  // strncat(x, "", c) -> x
>> +  // strncat(x,  c, 0) -> x
>> +  if (SrcLen == 0 || Len == 0)
>> +    return Dst;
>>
>> -    // strchr(s+n,c)  -> gep(s+n+i,c)
>> -    return B.CreateGEP(SrcStr, B.getInt64(I), "strchr");
>> -  }
>> -};
>> +  // These optimizations require DataLayout.
>> +  if (!DL)
>> +    return nullptr;
>> +
>> +  // We don't optimize this case
>> +  if (Len < SrcLen)
>> +    return nullptr;
>>
>> -struct StrRChrOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // Verify the "strrchr" function prototype.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 2 ||
>> -        FT->getReturnType() != B.getInt8PtrTy() ||
>> -        FT->getParamType(0) != FT->getReturnType() ||
>> -        !FT->getParamType(1)->isIntegerTy(32))
>> -      return nullptr;
>> -
>> -    Value *SrcStr = CI->getArgOperand(0);
>> -    ConstantInt *CharC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
>> -
>> -    // Cannot fold anything if we're not looking for a constant.
>> -    if (!CharC)
>> -      return nullptr;
>> -
>> -    StringRef Str;
>> -    if (!getConstantStringInfo(SrcStr, Str)) {
>> -      // strrchr(s, 0) -> strchr(s, 0)
>> -      if (DL && CharC->isZero())
>> -        return EmitStrChr(SrcStr, '\0', B, DL, TLI);
>> +  // strncat(x, s, c) -> strcat(x, s)
>> +  // s is constant so the strcat can be optimized further
>> +  return emitStrLenMemCpy(Src, Dst, SrcLen, B);
>> +}
>> +
>> +Value *LibCallSimplifier::optimizeStrChr(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // Verify the "strchr" function prototype.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 2 || FT->getReturnType() != B.getInt8PtrTy()
>> ||
>> +      FT->getParamType(0) != FT->getReturnType() ||
>> +      !FT->getParamType(1)->isIntegerTy(32))
>> +    return nullptr;
>> +
>> +  Value *SrcStr = CI->getArgOperand(0);
>> +
>> +  // If the second operand is non-constant, see if we can compute the
>> length
>> +  // of the input string and turn this into memchr.
>> +  ConstantInt *CharC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
>> +  if (!CharC) {
>> +    // These optimizations require DataLayout.
>> +    if (!DL)
>>        return nullptr;
>> -    }
>>
>> -    // Compute the offset.
>> -    size_t I = (0xFF & CharC->getSExtValue()) == 0 ?
>> -        Str.size() : Str.rfind(CharC->getSExtValue());
>> -    if (I == StringRef::npos) // Didn't find the char. Return null.
>> -      return Constant::getNullValue(CI->getType());
>> +    uint64_t Len = GetStringLength(SrcStr);
>> +    if (Len == 0 || !FT->getParamType(1)->isIntegerTy(32)) // memchr
>> needs i32.
>> +      return nullptr;
>>
>> -    // strrchr(s+n,c) -> gep(s+n+i,c)
>> -    return B.CreateGEP(SrcStr, B.getInt64(I), "strrchr");
>> +    return EmitMemChr(
>> +        SrcStr, CI->getArgOperand(1), // include nul.
>> +        ConstantInt::get(DL->getIntPtrType(CI->getContext()), Len), B,
>> DL, TLI);
>>    }
>> -};
>> -
>> -struct StrCmpOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // Verify the "strcmp" function prototype.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 2 ||
>> -        !FT->getReturnType()->isIntegerTy(32) ||
>> -        FT->getParamType(0) != FT->getParamType(1) ||
>> -        FT->getParamType(0) != B.getInt8PtrTy())
>> -      return nullptr;
>> -
>> -    Value *Str1P = CI->getArgOperand(0), *Str2P = CI->getArgOperand(1);
>> -    if (Str1P == Str2P)      // strcmp(x,x)  -> 0
>> -      return ConstantInt::get(CI->getType(), 0);
>> -
>> -    StringRef Str1, Str2;
>> -    bool HasStr1 = getConstantStringInfo(Str1P, Str1);
>> -    bool HasStr2 = getConstantStringInfo(Str2P, Str2);
>> -
>> -    // strcmp(x, y)  -> cnst  (if both x and y are constant strings)
>> -    if (HasStr1 && HasStr2)
>> -      return ConstantInt::get(CI->getType(), Str1.compare(Str2));
>> -
>> -    if (HasStr1 && Str1.empty()) // strcmp("", x) -> -*x
>> -      return B.CreateNeg(B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"),
>> -                                      CI->getType()));
>> -
>> -    if (HasStr2 && Str2.empty()) // strcmp(x,"") -> *x
>> -      return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"),
>> CI->getType());
>> -
>> -    // strcmp(P, "x") -> memcmp(P, "x", 2)
>> -    uint64_t Len1 = GetStringLength(Str1P);
>> -    uint64_t Len2 = GetStringLength(Str2P);
>> -    if (Len1 && Len2) {
>> -      // These optimizations require DataLayout.
>> -      if (!DL) return nullptr;
>> -
>> -      return EmitMemCmp(Str1P, Str2P,
>> -                        ConstantInt::get(DL->getIntPtrType(*Context),
>> -                        std::min(Len1, Len2)), B, DL, TLI);
>> -    }
>>
>> +  // Otherwise, the character is a constant, see if the first argument is
>> +  // a string literal.  If so, we can constant fold.
>> +  StringRef Str;
>> +  if (!getConstantStringInfo(SrcStr, Str)) {
>> +    if (DL && CharC->isZero()) // strchr(p, 0) -> p + strlen(p)
>> +      return B.CreateGEP(SrcStr, EmitStrLen(SrcStr, B, DL, TLI),
>> "strchr");
>>      return nullptr;
>>    }
>> -};
>>
>> -struct StrNCmpOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // Verify the "strncmp" function prototype.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 3 ||
>> -        !FT->getReturnType()->isIntegerTy(32) ||
>> -        FT->getParamType(0) != FT->getParamType(1) ||
>> -        FT->getParamType(0) != B.getInt8PtrTy() ||
>> -        !FT->getParamType(2)->isIntegerTy())
>> -      return nullptr;
>> -
>> -    Value *Str1P = CI->getArgOperand(0), *Str2P = CI->getArgOperand(1);
>> -    if (Str1P == Str2P)      // strncmp(x,x,n)  -> 0
>> -      return ConstantInt::get(CI->getType(), 0);
>> -
>> -    // Get the length argument if it is constant.
>> -    uint64_t Length;
>> -    if (ConstantInt *LengthArg =
>> dyn_cast<ConstantInt>(CI->getArgOperand(2)))
>> -      Length = LengthArg->getZExtValue();
>> -    else
>> -      return nullptr;
>> -
>> -    if (Length == 0) // strncmp(x,y,0)   -> 0
>> -      return ConstantInt::get(CI->getType(), 0);
>> -
>> -    if (DL && Length == 1) // strncmp(x,y,1) -> memcmp(x,y,1)
>> -      return EmitMemCmp(Str1P, Str2P, CI->getArgOperand(2), B, DL, TLI);
>> -
>> -    StringRef Str1, Str2;
>> -    bool HasStr1 = getConstantStringInfo(Str1P, Str1);
>> -    bool HasStr2 = getConstantStringInfo(Str2P, Str2);
>> -
>> -    // strncmp(x, y)  -> cnst  (if both x and y are constant strings)
>> -    if (HasStr1 && HasStr2) {
>> -      StringRef SubStr1 = Str1.substr(0, Length);
>> -      StringRef SubStr2 = Str2.substr(0, Length);
>> -      return ConstantInt::get(CI->getType(), SubStr1.compare(SubStr2));
>> -    }
>> +  // Compute the offset, make sure to handle the case when we're
>> searching for
>> +  // zero (a weird way to spell strlen).
>> +  size_t I = (0xFF & CharC->getSExtValue()) == 0
>> +                 ? Str.size()
>> +                 : Str.find(CharC->getSExtValue());
>> +  if (I == StringRef::npos) // Didn't find the char.  strchr returns
>> null.
>> +    return Constant::getNullValue(CI->getType());
>>
>> -    if (HasStr1 && Str1.empty())  // strncmp("", x, n) -> -*x
>> -      return B.CreateNeg(B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"),
>> -                                      CI->getType()));
>> +  // strchr(s+n,c)  -> gep(s+n+i,c)
>> +  return B.CreateGEP(SrcStr, B.getInt64(I), "strchr");
>> +}
>>
>> -    if (HasStr2 && Str2.empty())  // strncmp(x, "", n) -> *x
>> -      return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"),
>> CI->getType());
>> +Value *LibCallSimplifier::optimizeStrRChr(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // Verify the "strrchr" function prototype.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 2 || FT->getReturnType() != B.getInt8PtrTy()
>> ||
>> +      FT->getParamType(0) != FT->getReturnType() ||
>> +      !FT->getParamType(1)->isIntegerTy(32))
>> +    return nullptr;
>> +
>> +  Value *SrcStr = CI->getArgOperand(0);
>> +  ConstantInt *CharC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
>> +
>> +  // Cannot fold anything if we're not looking for a constant.
>> +  if (!CharC)
>> +    return nullptr;
>>
>> +  StringRef Str;
>> +  if (!getConstantStringInfo(SrcStr, Str)) {
>> +    // strrchr(s, 0) -> strchr(s, 0)
>> +    if (DL && CharC->isZero())
>> +      return EmitStrChr(SrcStr, '\0', B, DL, TLI);
>>      return nullptr;
>>    }
>> -};
>>
>> -struct StrCpyOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // Verify the "strcpy" function prototype.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 2 ||
>> -        FT->getReturnType() != FT->getParamType(0) ||
>> -        FT->getParamType(0) != FT->getParamType(1) ||
>> -        FT->getParamType(0) != B.getInt8PtrTy())
>> -      return nullptr;
>> +  // Compute the offset.
>> +  size_t I = (0xFF & CharC->getSExtValue()) == 0
>> +                 ? Str.size()
>> +                 : Str.rfind(CharC->getSExtValue());
>> +  if (I == StringRef::npos) // Didn't find the char. Return null.
>> +    return Constant::getNullValue(CI->getType());
>>
>> -    Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
>> -    if (Dst == Src)      // strcpy(x,x)  -> x
>> -      return Src;
>> +  // strrchr(s+n,c) -> gep(s+n+i,c)
>> +  return B.CreateGEP(SrcStr, B.getInt64(I), "strrchr");
>> +}
>>
>> +Value *LibCallSimplifier::optimizeStrCmp(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // Verify the "strcmp" function prototype.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 2 || !FT->getReturnType()->isIntegerTy(32) ||
>> +      FT->getParamType(0) != FT->getParamType(1) ||
>> +      FT->getParamType(0) != B.getInt8PtrTy())
>> +    return nullptr;
>> +
>> +  Value *Str1P = CI->getArgOperand(0), *Str2P = CI->getArgOperand(1);
>> +  if (Str1P == Str2P) // strcmp(x,x)  -> 0
>> +    return ConstantInt::get(CI->getType(), 0);
>> +
>> +  StringRef Str1, Str2;
>> +  bool HasStr1 = getConstantStringInfo(Str1P, Str1);
>> +  bool HasStr2 = getConstantStringInfo(Str2P, Str2);
>> +
>> +  // strcmp(x, y)  -> cnst  (if both x and y are constant strings)
>> +  if (HasStr1 && HasStr2)
>> +    return ConstantInt::get(CI->getType(), Str1.compare(Str2));
>> +
>> +  if (HasStr1 && Str1.empty()) // strcmp("", x) -> -*x
>> +    return B.CreateNeg(
>> +        B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"), CI->getType()));
>> +
>> +  if (HasStr2 && Str2.empty()) // strcmp(x,"") -> *x
>> +    return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"),
>> CI->getType());
>> +
>> +  // strcmp(P, "x") -> memcmp(P, "x", 2)
>> +  uint64_t Len1 = GetStringLength(Str1P);
>> +  uint64_t Len2 = GetStringLength(Str2P);
>> +  if (Len1 && Len2) {
>>      // These optimizations require DataLayout.
>> -    if (!DL) return nullptr;
>> -
>> -    // See if we can get the length of the input string.
>> -    uint64_t Len = GetStringLength(Src);
>> -    if (Len == 0) return nullptr;
>> +    if (!DL)
>> +      return nullptr;
>>
>> -    // We have enough information to now generate the memcpy call to do
>> the
>> -    // copy for us.  Make a memcpy to copy the nul byte with align = 1.
>> -    B.CreateMemCpy(Dst, Src,
>> -                  ConstantInt::get(DL->getIntPtrType(*Context), Len), 1);
>> -    return Dst;
>> +    return EmitMemCmp(Str1P, Str2P,
>> +
>> ConstantInt::get(DL->getIntPtrType(CI->getContext()),
>> +                                       std::min(Len1, Len2)),
>> +                      B, DL, TLI);
>>    }
>> -};
>>
>> -struct StpCpyOpt: public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // Verify the "stpcpy" function prototype.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 2 ||
>> -        FT->getReturnType() != FT->getParamType(0) ||
>> -        FT->getParamType(0) != FT->getParamType(1) ||
>> -        FT->getParamType(0) != B.getInt8PtrTy())
>> -      return nullptr;
>> +  return nullptr;
>> +}
>>
>> -    // These optimizations require DataLayout.
>> -    if (!DL) return nullptr;
>> +Value *LibCallSimplifier::optimizeStrNCmp(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // Verify the "strncmp" function prototype.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 3 || !FT->getReturnType()->isIntegerTy(32) ||
>> +      FT->getParamType(0) != FT->getParamType(1) ||
>> +      FT->getParamType(0) != B.getInt8PtrTy() ||
>> +      !FT->getParamType(2)->isIntegerTy())
>> +    return nullptr;
>>
>> -    Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
>> -    if (Dst == Src) {  // stpcpy(x,x)  -> x+strlen(x)
>> -      Value *StrLen = EmitStrLen(Src, B, DL, TLI);
>> -      return StrLen ? B.CreateInBoundsGEP(Dst, StrLen) : nullptr;
>> -    }
>> +  Value *Str1P = CI->getArgOperand(0), *Str2P = CI->getArgOperand(1);
>> +  if (Str1P == Str2P) // strncmp(x,x,n)  -> 0
>> +    return ConstantInt::get(CI->getType(), 0);
>>
>> -    // See if we can get the length of the input string.
>> -    uint64_t Len = GetStringLength(Src);
>> -    if (Len == 0) return nullptr;
>> +  // Get the length argument if it is constant.
>> +  uint64_t Length;
>> +  if (ConstantInt *LengthArg =
>> dyn_cast<ConstantInt>(CI->getArgOperand(2)))
>> +    Length = LengthArg->getZExtValue();
>> +  else
>> +    return nullptr;
>>
>> -    Type *PT = FT->getParamType(0);
>> -    Value *LenV = ConstantInt::get(DL->getIntPtrType(PT), Len);
>> -    Value *DstEnd = B.CreateGEP(Dst,
>> -                                ConstantInt::get(DL->getIntPtrType(PT),
>> -                                                 Len - 1));
>> -
>> -    // We have enough information to now generate the memcpy call to do
>> the
>> -    // copy for us.  Make a memcpy to copy the nul byte with align = 1.
>> -    B.CreateMemCpy(Dst, Src, LenV, 1);
>> -    return DstEnd;
>> -  }
>> -};
>> +  if (Length == 0) // strncmp(x,y,0)   -> 0
>> +    return ConstantInt::get(CI->getType(), 0);
>>
>> -struct StrNCpyOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 3 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> -        FT->getParamType(0) != FT->getParamType(1) ||
>> -        FT->getParamType(0) != B.getInt8PtrTy() ||
>> -        !FT->getParamType(2)->isIntegerTy())
>> -      return nullptr;
>> -
>> -    Value *Dst = CI->getArgOperand(0);
>> -    Value *Src = CI->getArgOperand(1);
>> -    Value *LenOp = CI->getArgOperand(2);
>> -
>> -    // See if we can get the length of the input string.
>> -    uint64_t SrcLen = GetStringLength(Src);
>> -    if (SrcLen == 0) return nullptr;
>> -    --SrcLen;
>> -
>> -    if (SrcLen == 0) {
>> -      // strncpy(x, "", y) -> memset(x, '\0', y, 1)
>> -      B.CreateMemSet(Dst, B.getInt8('\0'), LenOp, 1);
>> -      return Dst;
>> -    }
>> +  if (DL && Length == 1) // strncmp(x,y,1) -> memcmp(x,y,1)
>> +    return EmitMemCmp(Str1P, Str2P, CI->getArgOperand(2), B, DL, TLI);
>>
>> -    uint64_t Len;
>> -    if (ConstantInt *LengthArg = dyn_cast<ConstantInt>(LenOp))
>> -      Len = LengthArg->getZExtValue();
>> -    else
>> -      return nullptr;
>> +  StringRef Str1, Str2;
>> +  bool HasStr1 = getConstantStringInfo(Str1P, Str1);
>> +  bool HasStr2 = getConstantStringInfo(Str2P, Str2);
>>
>> -    if (Len == 0) return Dst; // strncpy(x, y, 0) -> x
>> +  // strncmp(x, y)  -> cnst  (if both x and y are constant strings)
>> +  if (HasStr1 && HasStr2) {
>> +    StringRef SubStr1 = Str1.substr(0, Length);
>> +    StringRef SubStr2 = Str2.substr(0, Length);
>> +    return ConstantInt::get(CI->getType(), SubStr1.compare(SubStr2));
>> +  }
>>
>> -    // These optimizations require DataLayout.
>> -    if (!DL) return nullptr;
>> +  if (HasStr1 && Str1.empty()) // strncmp("", x, n) -> -*x
>> +    return B.CreateNeg(
>> +        B.CreateZExt(B.CreateLoad(Str2P, "strcmpload"), CI->getType()));
>>
>> -    // Let strncpy handle the zero padding
>> -    if (Len > SrcLen+1) return nullptr;
>> +  if (HasStr2 && Str2.empty()) // strncmp(x, "", n) -> *x
>> +    return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"),
>> CI->getType());
>>
>> -    Type *PT = FT->getParamType(0);
>> -    // strncpy(x, s, c) -> memcpy(x, s, c, 1) [s and c are constant]
>> -    B.CreateMemCpy(Dst, Src,
>> -                   ConstantInt::get(DL->getIntPtrType(PT), Len), 1);
>> +  return nullptr;
>> +}
>>
>> -    return Dst;
>> -  }
>> -};
>> +Value *LibCallSimplifier::optimizeStrCpy(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // Verify the "strcpy" function prototype.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 2 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      FT->getParamType(0) != FT->getParamType(1) ||
>> +      FT->getParamType(0) != B.getInt8PtrTy())
>> +    return nullptr;
>>
>> -struct StrLenOpt : public LibCallOptimization {
>> -  bool ignoreCallingConv() override { return true; }
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 1 ||
>> -        FT->getParamType(0) != B.getInt8PtrTy() ||
>> -        !FT->getReturnType()->isIntegerTy())
>> -      return nullptr;
>> -
>> -    Value *Src = CI->getArgOperand(0);
>> -
>> -    // Constant folding: strlen("xyz") -> 3
>> -    if (uint64_t Len = GetStringLength(Src))
>> -      return ConstantInt::get(CI->getType(), Len-1);
>> -
>> -    // strlen(x?"foo":"bars") --> x ? 3 : 4
>> -    if (SelectInst *SI = dyn_cast<SelectInst>(Src)) {
>> -      uint64_t LenTrue = GetStringLength(SI->getTrueValue());
>> -      uint64_t LenFalse = GetStringLength(SI->getFalseValue());
>> -      if (LenTrue && LenFalse) {
>> -        emitOptimizationRemark(*Context, "simplify-libcalls", *Caller,
>> -                               SI->getDebugLoc(),
>> -                               "folded strlen(select) to select of
>> constants");
>> -        return B.CreateSelect(SI->getCondition(),
>> -                              ConstantInt::get(CI->getType(), LenTrue-1),
>> -                              ConstantInt::get(CI->getType(),
>> LenFalse-1));
>> -      }
>> -    }
>> +  Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
>> +  if (Dst == Src) // strcpy(x,x)  -> x
>> +    return Src;
>>
>> -    // strlen(x) != 0 --> *x != 0
>> -    // strlen(x) == 0 --> *x == 0
>> -    if (isOnlyUsedInZeroEqualityComparison(CI))
>> -      return B.CreateZExt(B.CreateLoad(Src, "strlenfirst"),
>> CI->getType());
>> +  // These optimizations require DataLayout.
>> +  if (!DL)
>> +    return nullptr;
>>
>> +  // See if we can get the length of the input string.
>> +  uint64_t Len = GetStringLength(Src);
>> +  if (Len == 0)
>>      return nullptr;
>> -  }
>> -};
>>
>> -struct StrPBrkOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 2 ||
>> -        FT->getParamType(0) != B.getInt8PtrTy() ||
>> -        FT->getParamType(1) != FT->getParamType(0) ||
>> -        FT->getReturnType() != FT->getParamType(0))
>> -      return nullptr;
>> +  // We have enough information to now generate the memcpy call to do the
>> +  // copy for us.  Make a memcpy to copy the nul byte with align = 1.
>> +  B.CreateMemCpy(Dst, Src,
>> +                 ConstantInt::get(DL->getIntPtrType(CI->getContext()),
>> Len), 1);
>> +  return Dst;
>> +}
>>
>> -    StringRef S1, S2;
>> -    bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
>> -    bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
>> +Value *LibCallSimplifier::optimizeStpCpy(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // Verify the "stpcpy" function prototype.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 2 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      FT->getParamType(0) != FT->getParamType(1) ||
>> +      FT->getParamType(0) != B.getInt8PtrTy())
>> +    return nullptr;
>>
>> -    // strpbrk(s, "") -> NULL
>> -    // strpbrk("", s) -> NULL
>> -    if ((HasS1 && S1.empty()) || (HasS2 && S2.empty()))
>> -      return Constant::getNullValue(CI->getType());
>> +  // These optimizations require DataLayout.
>> +  if (!DL)
>> +    return nullptr;
>>
>> -    // Constant folding.
>> -    if (HasS1 && HasS2) {
>> -      size_t I = S1.find_first_of(S2);
>> -      if (I == StringRef::npos) // No match.
>> -        return Constant::getNullValue(CI->getType());
>> +  Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
>> +  if (Dst == Src) { // stpcpy(x,x)  -> x+strlen(x)
>> +    Value *StrLen = EmitStrLen(Src, B, DL, TLI);
>> +    return StrLen ? B.CreateInBoundsGEP(Dst, StrLen) : nullptr;
>> +  }
>>
>> -      return B.CreateGEP(CI->getArgOperand(0), B.getInt64(I), "strpbrk");
>> -    }
>> +  // See if we can get the length of the input string.
>> +  uint64_t Len = GetStringLength(Src);
>> +  if (Len == 0)
>> +    return nullptr;
>>
>> -    // strpbrk(s, "a") -> strchr(s, 'a')
>> -    if (DL && HasS2 && S2.size() == 1)
>> -      return EmitStrChr(CI->getArgOperand(0), S2[0], B, DL, TLI);
>> +  Type *PT = FT->getParamType(0);
>> +  Value *LenV = ConstantInt::get(DL->getIntPtrType(PT), Len);
>> +  Value *DstEnd =
>> +      B.CreateGEP(Dst, ConstantInt::get(DL->getIntPtrType(PT), Len - 1));
>>
>> -    return nullptr;
>> +  // We have enough information to now generate the memcpy call to do the
>> +  // copy for us.  Make a memcpy to copy the nul byte with align = 1.
>> +  B.CreateMemCpy(Dst, Src, LenV, 1);
>> +  return DstEnd;
>> +}
>> +
>> +Value *LibCallSimplifier::optimizeStrNCpy(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 3 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      FT->getParamType(0) != FT->getParamType(1) ||
>> +      FT->getParamType(0) != B.getInt8PtrTy() ||
>> +      !FT->getParamType(2)->isIntegerTy())
>> +    return nullptr;
>> +
>> +  Value *Dst = CI->getArgOperand(0);
>> +  Value *Src = CI->getArgOperand(1);
>> +  Value *LenOp = CI->getArgOperand(2);
>> +
>> +  // See if we can get the length of the input string.
>> +  uint64_t SrcLen = GetStringLength(Src);
>> +  if (SrcLen == 0)
>> +    return nullptr;
>> +  --SrcLen;
>> +
>> +  if (SrcLen == 0) {
>> +    // strncpy(x, "", y) -> memset(x, '\0', y, 1)
>> +    B.CreateMemSet(Dst, B.getInt8('\0'), LenOp, 1);
>> +    return Dst;
>>    }
>> -};
>>
>> -struct StrToOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if ((FT->getNumParams() != 2 && FT->getNumParams() != 3) ||
>> -        !FT->getParamType(0)->isPointerTy() ||
>> -        !FT->getParamType(1)->isPointerTy())
>> -      return nullptr;
>> +  uint64_t Len;
>> +  if (ConstantInt *LengthArg = dyn_cast<ConstantInt>(LenOp))
>> +    Len = LengthArg->getZExtValue();
>> +  else
>> +    return nullptr;
>>
>> -    Value *EndPtr = CI->getArgOperand(1);
>> -    if (isa<ConstantPointerNull>(EndPtr)) {
>> -      // With a null EndPtr, this function won't capture the main
>> argument.
>> -      // It would be readonly too, except that it still may write to
>> errno.
>> -      CI->addAttribute(1, Attribute::NoCapture);
>> -    }
>> +  if (Len == 0)
>> +    return Dst; // strncpy(x, y, 0) -> x
>>
>> +  // These optimizations require DataLayout.
>> +  if (!DL)
>>      return nullptr;
>> -  }
>> -};
>>
>> -struct StrSpnOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 2 ||
>> -        FT->getParamType(0) != B.getInt8PtrTy() ||
>> -        FT->getParamType(1) != FT->getParamType(0) ||
>> -        !FT->getReturnType()->isIntegerTy())
>> -      return nullptr;
>> -
>> -    StringRef S1, S2;
>> -    bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
>> -    bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
>> -
>> -    // strspn(s, "") -> 0
>> -    // strspn("", s) -> 0
>> -    if ((HasS1 && S1.empty()) || (HasS2 && S2.empty()))
>> -      return Constant::getNullValue(CI->getType());
>> +  // Let strncpy handle the zero padding
>> +  if (Len > SrcLen + 1)
>> +    return nullptr;
>>
>> -    // Constant folding.
>> -    if (HasS1 && HasS2) {
>> -      size_t Pos = S1.find_first_not_of(S2);
>> -      if (Pos == StringRef::npos) Pos = S1.size();
>> -      return ConstantInt::get(CI->getType(), Pos);
>> -    }
>> +  Type *PT = FT->getParamType(0);
>> +  // strncpy(x, s, c) -> memcpy(x, s, c, 1) [s and c are constant]
>> +  B.CreateMemCpy(Dst, Src, ConstantInt::get(DL->getIntPtrType(PT), Len),
>> 1);
>>
>> -    return nullptr;
>> +  return Dst;
>> +}
>> +
>> +Value *LibCallSimplifier::optimizeStrLen(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 1 || FT->getParamType(0) != B.getInt8PtrTy()
>> ||
>> +      !FT->getReturnType()->isIntegerTy())
>> +    return nullptr;
>> +
>> +  Value *Src = CI->getArgOperand(0);
>> +
>> +  // Constant folding: strlen("xyz") -> 3
>> +  if (uint64_t Len = GetStringLength(Src))
>> +    return ConstantInt::get(CI->getType(), Len - 1);
>> +
>> +  // strlen(x?"foo":"bars") --> x ? 3 : 4
>> +  if (SelectInst *SI = dyn_cast<SelectInst>(Src)) {
>> +    uint64_t LenTrue = GetStringLength(SI->getTrueValue());
>> +    uint64_t LenFalse = GetStringLength(SI->getFalseValue());
>> +    if (LenTrue && LenFalse) {
>> +      Function *Caller = CI->getParent()->getParent();
>> +      emitOptimizationRemark(CI->getContext(), "simplify-libcalls",
>> *Caller,
>> +                             SI->getDebugLoc(),
>> +                             "folded strlen(select) to select of
>> constants");
>> +      return B.CreateSelect(SI->getCondition(),
>> +                            ConstantInt::get(CI->getType(), LenTrue - 1),
>> +                            ConstantInt::get(CI->getType(), LenFalse -
>> 1));
>> +    }
>>    }
>> -};
>>
>> -struct StrCSpnOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 2 ||
>> -        FT->getParamType(0) != B.getInt8PtrTy() ||
>> -        FT->getParamType(1) != FT->getParamType(0) ||
>> -        !FT->getReturnType()->isIntegerTy())
>> -      return nullptr;
>> -
>> -    StringRef S1, S2;
>> -    bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
>> -    bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
>> +  // strlen(x) != 0 --> *x != 0
>> +  // strlen(x) == 0 --> *x == 0
>> +  if (isOnlyUsedInZeroEqualityComparison(CI))
>> +    return B.CreateZExt(B.CreateLoad(Src, "strlenfirst"), CI->getType());
>> +
>> +  return nullptr;
>> +}
>>
>> -    // strcspn("", s) -> 0
>> -    if (HasS1 && S1.empty())
>> +Value *LibCallSimplifier::optimizeStrPBrk(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 2 || FT->getParamType(0) != B.getInt8PtrTy()
>> ||
>> +      FT->getParamType(1) != FT->getParamType(0) ||
>> +      FT->getReturnType() != FT->getParamType(0))
>> +    return nullptr;
>> +
>> +  StringRef S1, S2;
>> +  bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
>> +  bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
>> +
>> +  // strpbrk(s, "") -> NULL
>> +  // strpbrk("", s) -> NULL
>> +  if ((HasS1 && S1.empty()) || (HasS2 && S2.empty()))
>> +    return Constant::getNullValue(CI->getType());
>> +
>> +  // Constant folding.
>> +  if (HasS1 && HasS2) {
>> +    size_t I = S1.find_first_of(S2);
>> +    if (I == StringRef::npos) // No match.
>>        return Constant::getNullValue(CI->getType());
>>
>> -    // Constant folding.
>> -    if (HasS1 && HasS2) {
>> -      size_t Pos = S1.find_first_of(S2);
>> -      if (Pos == StringRef::npos) Pos = S1.size();
>> -      return ConstantInt::get(CI->getType(), Pos);
>> -    }
>> +    return B.CreateGEP(CI->getArgOperand(0), B.getInt64(I), "strpbrk");
>> +  }
>>
>> -    // strcspn(s, "") -> strlen(s)
>> -    if (DL && HasS2 && S2.empty())
>> -      return EmitStrLen(CI->getArgOperand(0), B, DL, TLI);
>> +  // strpbrk(s, "a") -> strchr(s, 'a')
>> +  if (DL && HasS2 && S2.size() == 1)
>> +    return EmitStrChr(CI->getArgOperand(0), S2[0], B, DL, TLI);
>>
>> +  return nullptr;
>> +}
>> +
>> +Value *LibCallSimplifier::optimizeStrTo(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if ((FT->getNumParams() != 2 && FT->getNumParams() != 3) ||
>> +      !FT->getParamType(0)->isPointerTy() ||
>> +      !FT->getParamType(1)->isPointerTy())
>>      return nullptr;
>> +
>> +  Value *EndPtr = CI->getArgOperand(1);
>> +  if (isa<ConstantPointerNull>(EndPtr)) {
>> +    // With a null EndPtr, this function won't capture the main argument.
>> +    // It would be readonly too, except that it still may write to errno.
>> +    CI->addAttribute(1, Attribute::NoCapture);
>>    }
>> -};
>>
>> -struct StrStrOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 2 ||
>> -        !FT->getParamType(0)->isPointerTy() ||
>> -        !FT->getParamType(1)->isPointerTy() ||
>> -        !FT->getReturnType()->isPointerTy())
>> -      return nullptr;
>> +  return nullptr;
>> +}
>>
>> -    // fold strstr(x, x) -> x.
>> -    if (CI->getArgOperand(0) == CI->getArgOperand(1))
>> -      return B.CreateBitCast(CI->getArgOperand(0), CI->getType());
>> +Value *LibCallSimplifier::optimizeStrSpn(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 2 || FT->getParamType(0) != B.getInt8PtrTy()
>> ||
>> +      FT->getParamType(1) != FT->getParamType(0) ||
>> +      !FT->getReturnType()->isIntegerTy())
>> +    return nullptr;
>> +
>> +  StringRef S1, S2;
>> +  bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
>> +  bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
>> +
>> +  // strspn(s, "") -> 0
>> +  // strspn("", s) -> 0
>> +  if ((HasS1 && S1.empty()) || (HasS2 && S2.empty()))
>> +    return Constant::getNullValue(CI->getType());
>> +
>> +  // Constant folding.
>> +  if (HasS1 && HasS2) {
>> +    size_t Pos = S1.find_first_not_of(S2);
>> +    if (Pos == StringRef::npos)
>> +      Pos = S1.size();
>> +    return ConstantInt::get(CI->getType(), Pos);
>> +  }
>>
>> -    // fold strstr(a, b) == a -> strncmp(a, b, strlen(b)) == 0
>> -    if (DL && isOnlyUsedInEqualityComparison(CI, CI->getArgOperand(0))) {
>> -      Value *StrLen = EmitStrLen(CI->getArgOperand(1), B, DL, TLI);
>> -      if (!StrLen)
>> -        return nullptr;
>> -      Value *StrNCmp = EmitStrNCmp(CI->getArgOperand(0),
>> CI->getArgOperand(1),
>> -                                   StrLen, B, DL, TLI);
>> -      if (!StrNCmp)
>> -        return nullptr;
>> -      for (auto UI = CI->user_begin(), UE = CI->user_end(); UI != UE;) {
>> -        ICmpInst *Old = cast<ICmpInst>(*UI++);
>> -        Value *Cmp = B.CreateICmp(Old->getPredicate(), StrNCmp,
>> -
>> ConstantInt::getNullValue(StrNCmp->getType()),
>> -                                  "cmp");
>> -        LCS->replaceAllUsesWith(Old, Cmp);
>> -      }
>> -      return CI;
>> -    }
>> +  return nullptr;
>> +}
>>
>> -    // See if either input string is a constant string.
>> -    StringRef SearchStr, ToFindStr;
>> -    bool HasStr1 = getConstantStringInfo(CI->getArgOperand(0),
>> SearchStr);
>> -    bool HasStr2 = getConstantStringInfo(CI->getArgOperand(1),
>> ToFindStr);
>> -
>> -    // fold strstr(x, "") -> x.
>> -    if (HasStr2 && ToFindStr.empty())
>> -      return B.CreateBitCast(CI->getArgOperand(0), CI->getType());
>> -
>> -    // If both strings are known, constant fold it.
>> -    if (HasStr1 && HasStr2) {
>> -      size_t Offset = SearchStr.find(ToFindStr);
>> -
>> -      if (Offset == StringRef::npos) // strstr("foo", "bar") -> null
>> -        return Constant::getNullValue(CI->getType());
>> -
>> -      // strstr("abcd", "bc") -> gep((char*)"abcd", 1)
>> -      Value *Result = CastToCStr(CI->getArgOperand(0), B);
>> -      Result = B.CreateConstInBoundsGEP1_64(Result, Offset, "strstr");
>> -      return B.CreateBitCast(Result, CI->getType());
>> -    }
>> +Value *LibCallSimplifier::optimizeStrCSpn(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 2 || FT->getParamType(0) != B.getInt8PtrTy()
>> ||
>> +      FT->getParamType(1) != FT->getParamType(0) ||
>> +      !FT->getReturnType()->isIntegerTy())
>> +    return nullptr;
>> +
>> +  StringRef S1, S2;
>> +  bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1);
>> +  bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2);
>> +
>> +  // strcspn("", s) -> 0
>> +  if (HasS1 && S1.empty())
>> +    return Constant::getNullValue(CI->getType());
>> +
>> +  // Constant folding.
>> +  if (HasS1 && HasS2) {
>> +    size_t Pos = S1.find_first_of(S2);
>> +    if (Pos == StringRef::npos)
>> +      Pos = S1.size();
>> +    return ConstantInt::get(CI->getType(), Pos);
>> +  }
>> +
>> +  // strcspn(s, "") -> strlen(s)
>> +  if (DL && HasS2 && S2.empty())
>> +    return EmitStrLen(CI->getArgOperand(0), B, DL, TLI);
>>
>> -    // fold strstr(x, "y") -> strchr(x, 'y').
>> -    if (HasStr2 && ToFindStr.size() == 1) {
>> -      Value *StrChr= EmitStrChr(CI->getArgOperand(0), ToFindStr[0], B,
>> DL, TLI);
>> -      return StrChr ? B.CreateBitCast(StrChr, CI->getType()) : nullptr;
>> -    }
>> +  return nullptr;
>> +}
>> +
>> +Value *LibCallSimplifier::optimizeStrStr(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
>> +      !FT->getParamType(1)->isPointerTy() ||
>> +      !FT->getReturnType()->isPointerTy())
>>      return nullptr;
>> -  }
>> -};
>>
>> -struct MemCmpOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 3 || !FT->getParamType(0)->isPointerTy() ||
>> -        !FT->getParamType(1)->isPointerTy() ||
>> -        !FT->getReturnType()->isIntegerTy(32))
>> +  // fold strstr(x, x) -> x.
>> +  if (CI->getArgOperand(0) == CI->getArgOperand(1))
>> +    return B.CreateBitCast(CI->getArgOperand(0), CI->getType());
>> +
>> +  // fold strstr(a, b) == a -> strncmp(a, b, strlen(b)) == 0
>> +  if (DL && isOnlyUsedInEqualityComparison(CI, CI->getArgOperand(0))) {
>> +    Value *StrLen = EmitStrLen(CI->getArgOperand(1), B, DL, TLI);
>> +    if (!StrLen)
>>        return nullptr;
>> +    Value *StrNCmp = EmitStrNCmp(CI->getArgOperand(0),
>> CI->getArgOperand(1),
>> +                                 StrLen, B, DL, TLI);
>> +    if (!StrNCmp)
>> +      return nullptr;
>> +    for (auto UI = CI->user_begin(), UE = CI->user_end(); UI != UE;) {
>> +      ICmpInst *Old = cast<ICmpInst>(*UI++);
>> +      Value *Cmp =
>> +          B.CreateICmp(Old->getPredicate(), StrNCmp,
>> +                       ConstantInt::getNullValue(StrNCmp->getType()),
>> "cmp");
>> +      replaceAllUsesWith(Old, Cmp);
>> +    }
>> +    return CI;
>> +  }
>>
>> -    Value *LHS = CI->getArgOperand(0), *RHS = CI->getArgOperand(1);
>> +  // See if either input string is a constant string.
>> +  StringRef SearchStr, ToFindStr;
>> +  bool HasStr1 = getConstantStringInfo(CI->getArgOperand(0), SearchStr);
>> +  bool HasStr2 = getConstantStringInfo(CI->getArgOperand(1), ToFindStr);
>>
>> -    if (LHS == RHS)  // memcmp(s,s,x) -> 0
>> -      return Constant::getNullValue(CI->getType());
>> +  // fold strstr(x, "") -> x.
>> +  if (HasStr2 && ToFindStr.empty())
>> +    return B.CreateBitCast(CI->getArgOperand(0), CI->getType());
>>
>> -    // Make sure we have a constant length.
>> -    ConstantInt *LenC = dyn_cast<ConstantInt>(CI->getArgOperand(2));
>> -    if (!LenC) return nullptr;
>> -    uint64_t Len = LenC->getZExtValue();
>> +  // If both strings are known, constant fold it.
>> +  if (HasStr1 && HasStr2) {
>> +    size_t Offset = SearchStr.find(ToFindStr);
>>
>> -    if (Len == 0) // memcmp(s1,s2,0) -> 0
>> +    if (Offset == StringRef::npos) // strstr("foo", "bar") -> null
>>        return Constant::getNullValue(CI->getType());
>>
>> -    // memcmp(S1,S2,1) -> *(unsigned char*)LHS - *(unsigned char*)RHS
>> -    if (Len == 1) {
>> -      Value *LHSV = B.CreateZExt(B.CreateLoad(CastToCStr(LHS, B),
>> "lhsc"),
>> -                                 CI->getType(), "lhsv");
>> -      Value *RHSV = B.CreateZExt(B.CreateLoad(CastToCStr(RHS, B),
>> "rhsc"),
>> -                                 CI->getType(), "rhsv");
>> -      return B.CreateSub(LHSV, RHSV, "chardiff");
>> -    }
>> +    // strstr("abcd", "bc") -> gep((char*)"abcd", 1)
>> +    Value *Result = CastToCStr(CI->getArgOperand(0), B);
>> +    Result = B.CreateConstInBoundsGEP1_64(Result, Offset, "strstr");
>> +    return B.CreateBitCast(Result, CI->getType());
>> +  }
>>
>> -    // Constant folding: memcmp(x, y, l) -> cnst (all arguments are
>> constant)
>> -    StringRef LHSStr, RHSStr;
>> -    if (getConstantStringInfo(LHS, LHSStr) &&
>> -        getConstantStringInfo(RHS, RHSStr)) {
>> -      // Make sure we're not reading out-of-bounds memory.
>> -      if (Len > LHSStr.size() || Len > RHSStr.size())
>> -        return nullptr;
>> -      // Fold the memcmp and normalize the result.  This way we get
>> consistent
>> -      // results across multiple platforms.
>> -      uint64_t Ret = 0;
>> -      int Cmp = memcmp(LHSStr.data(), RHSStr.data(), Len);
>> -      if (Cmp < 0)
>> -        Ret = -1;
>> -      else if (Cmp > 0)
>> -        Ret = 1;
>> -      return ConstantInt::get(CI->getType(), Ret);
>> -    }
>> +  // fold strstr(x, "y") -> strchr(x, 'y').
>> +  if (HasStr2 && ToFindStr.size() == 1) {
>> +    Value *StrChr = EmitStrChr(CI->getArgOperand(0), ToFindStr[0], B,
>> DL, TLI);
>> +    return StrChr ? B.CreateBitCast(StrChr, CI->getType()) : nullptr;
>> +  }
>> +  return nullptr;
>> +}
>>
>> -    return nullptr;
>> +Value *LibCallSimplifier::optimizeMemCmp(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 3 || !FT->getParamType(0)->isPointerTy() ||
>> +      !FT->getParamType(1)->isPointerTy() ||
>> +      !FT->getReturnType()->isIntegerTy(32))
>> +    return nullptr;
>> +
>> +  Value *LHS = CI->getArgOperand(0), *RHS = CI->getArgOperand(1);
>> +
>> +  if (LHS == RHS) // memcmp(s,s,x) -> 0
>> +    return Constant::getNullValue(CI->getType());
>> +
>> +  // Make sure we have a constant length.
>> +  ConstantInt *LenC = dyn_cast<ConstantInt>(CI->getArgOperand(2));
>> +  if (!LenC)
>> +    return nullptr;
>> +  uint64_t Len = LenC->getZExtValue();
>> +
>> +  if (Len == 0) // memcmp(s1,s2,0) -> 0
>> +    return Constant::getNullValue(CI->getType());
>> +
>> +  // memcmp(S1,S2,1) -> *(unsigned char*)LHS - *(unsigned char*)RHS
>> +  if (Len == 1) {
>> +    Value *LHSV = B.CreateZExt(B.CreateLoad(CastToCStr(LHS, B), "lhsc"),
>> +                               CI->getType(), "lhsv");
>> +    Value *RHSV = B.CreateZExt(B.CreateLoad(CastToCStr(RHS, B), "rhsc"),
>> +                               CI->getType(), "rhsv");
>> +    return B.CreateSub(LHSV, RHSV, "chardiff");
>> +  }
>> +
>> +  // Constant folding: memcmp(x, y, l) -> cnst (all arguments are
>> constant)
>> +  StringRef LHSStr, RHSStr;
>> +  if (getConstantStringInfo(LHS, LHSStr) &&
>> +      getConstantStringInfo(RHS, RHSStr)) {
>> +    // Make sure we're not reading out-of-bounds memory.
>> +    if (Len > LHSStr.size() || Len > RHSStr.size())
>> +      return nullptr;
>> +    // Fold the memcmp and normalize the result.  This way we get
>> consistent
>> +    // results across multiple platforms.
>> +    uint64_t Ret = 0;
>> +    int Cmp = memcmp(LHSStr.data(), RHSStr.data(), Len);
>> +    if (Cmp < 0)
>> +      Ret = -1;
>> +    else if (Cmp > 0)
>> +      Ret = 1;
>> +    return ConstantInt::get(CI->getType(), Ret);
>>    }
>> -};
>>
>> -struct MemCpyOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // These optimizations require DataLayout.
>> -    if (!DL) return nullptr;
>> +  return nullptr;
>> +}
>>
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 3 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> -        !FT->getParamType(0)->isPointerTy() ||
>> -        !FT->getParamType(1)->isPointerTy() ||
>> -        FT->getParamType(2) != DL->getIntPtrType(*Context))
>> -      return nullptr;
>> +Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // These optimizations require DataLayout.
>> +  if (!DL)
>> +    return nullptr;
>>
>> -    // memcpy(x, y, n) -> llvm.memcpy(x, y, n, 1)
>> -    B.CreateMemCpy(CI->getArgOperand(0), CI->getArgOperand(1),
>> -                   CI->getArgOperand(2), 1);
>> -    return CI->getArgOperand(0);
>> -  }
>> -};
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 3 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      !FT->getParamType(0)->isPointerTy() ||
>> +      !FT->getParamType(1)->isPointerTy() ||
>> +      FT->getParamType(2) != DL->getIntPtrType(CI->getContext()))
>> +    return nullptr;
>>
>> -struct MemMoveOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // These optimizations require DataLayout.
>> -    if (!DL) return nullptr;
>> +  // memcpy(x, y, n) -> llvm.memcpy(x, y, n, 1)
>> +  B.CreateMemCpy(CI->getArgOperand(0), CI->getArgOperand(1),
>> +                 CI->getArgOperand(2), 1);
>> +  return CI->getArgOperand(0);
>> +}
>>
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 3 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> -        !FT->getParamType(0)->isPointerTy() ||
>> -        !FT->getParamType(1)->isPointerTy() ||
>> -        FT->getParamType(2) != DL->getIntPtrType(*Context))
>> -      return nullptr;
>> +Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // These optimizations require DataLayout.
>> +  if (!DL)
>> +    return nullptr;
>>
>> -    // memmove(x, y, n) -> llvm.memmove(x, y, n, 1)
>> -    B.CreateMemMove(CI->getArgOperand(0), CI->getArgOperand(1),
>> -                    CI->getArgOperand(2), 1);
>> -    return CI->getArgOperand(0);
>> -  }
>> -};
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 3 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      !FT->getParamType(0)->isPointerTy() ||
>> +      !FT->getParamType(1)->isPointerTy() ||
>> +      FT->getParamType(2) != DL->getIntPtrType(CI->getContext()))
>> +    return nullptr;
>>
>> -struct MemSetOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // These optimizations require DataLayout.
>> -    if (!DL) return nullptr;
>> +  // memmove(x, y, n) -> llvm.memmove(x, y, n, 1)
>> +  B.CreateMemMove(CI->getArgOperand(0), CI->getArgOperand(1),
>> +                  CI->getArgOperand(2), 1);
>> +  return CI->getArgOperand(0);
>> +}
>>
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 3 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> -        !FT->getParamType(0)->isPointerTy() ||
>> -        !FT->getParamType(1)->isIntegerTy() ||
>> -        FT->getParamType(2) != DL->getIntPtrType(FT->getParamType(0)))
>> -      return nullptr;
>> +Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // These optimizations require DataLayout.
>> +  if (!DL)
>> +    return nullptr;
>>
>> -    // memset(p, v, n) -> llvm.memset(p, v, n, 1)
>> -    Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(),
>> false);
>> -    B.CreateMemSet(CI->getArgOperand(0), Val, CI->getArgOperand(2), 1);
>> -    return CI->getArgOperand(0);
>> -  }
>> -};
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 3 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      !FT->getParamType(0)->isPointerTy() ||
>> +      !FT->getParamType(1)->isIntegerTy() ||
>> +      FT->getParamType(2) != DL->getIntPtrType(FT->getParamType(0)))
>> +    return nullptr;
>> +
>> +  // memset(p, v, n) -> llvm.memset(p, v, n, 1)
>> +  Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(),
>> false);
>> +  B.CreateMemSet(CI->getArgOperand(0), Val, CI->getArgOperand(2), 1);
>> +  return CI->getArgOperand(0);
>> +}
>>
>>
>>  //===----------------------------------------------------------------------===//
>>  // Math Library Optimizations
>> @@ -1111,935 +1025,847 @@ struct MemSetOpt : public LibCallOptimiz
>>
>>  //===----------------------------------------------------------------------===//
>>  // Double -> Float Shrinking Optimizations for Unary Functions like
>> 'floor'
>>
>> -struct UnaryDoubleFPOpt : public LibCallOptimization {
>> -  bool CheckRetType;
>> -  UnaryDoubleFPOpt(bool CheckReturnType): CheckRetType(CheckReturnType)
>> {}
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 1 || !FT->getReturnType()->isDoubleTy() ||
>> -        !FT->getParamType(0)->isDoubleTy())
>> -      return nullptr;
>> -
>> -    if (CheckRetType) {
>> -      // Check if all the uses for function like 'sin' are converted to
>> float.
>> -      for (User *U : CI->users()) {
>> -        FPTruncInst *Cast = dyn_cast<FPTruncInst>(U);
>> -        if (!Cast || !Cast->getType()->isFloatTy())
>> -          return nullptr;
>> -      }
>> +Value *LibCallSimplifier::optimizeUnaryDoubleFP(CallInst *CI,
>> IRBuilder<> &B,
>> +                                                bool CheckRetType) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 1 || !FT->getReturnType()->isDoubleTy() ||
>> +      !FT->getParamType(0)->isDoubleTy())
>> +    return nullptr;
>> +
>> +  if (CheckRetType) {
>> +    // Check if all the uses for function like 'sin' are converted to
>> float.
>> +    for (User *U : CI->users()) {
>> +      FPTruncInst *Cast = dyn_cast<FPTruncInst>(U);
>> +      if (!Cast || !Cast->getType()->isFloatTy())
>> +        return nullptr;
>>      }
>> +  }
>>
>> -    // If this is something like 'floor((double)floatval)', convert to
>> floorf.
>> -    FPExtInst *Cast = dyn_cast<FPExtInst>(CI->getArgOperand(0));
>> -    if (!Cast || !Cast->getOperand(0)->getType()->isFloatTy())
>> -      return nullptr;
>> +  // If this is something like 'floor((double)floatval)', convert to
>> floorf.
>> +  FPExtInst *Cast = dyn_cast<FPExtInst>(CI->getArgOperand(0));
>> +  if (!Cast || !Cast->getOperand(0)->getType()->isFloatTy())
>> +    return nullptr;
>>
>> -    // floor((double)floatval) -> (double)floorf(floatval)
>> -    Value *V = Cast->getOperand(0);
>> -    V = EmitUnaryFloatFnCall(V, Callee->getName(), B,
>> Callee->getAttributes());
>> -    return B.CreateFPExt(V, B.getDoubleTy());
>> -  }
>> -};
>> +  // floor((double)floatval) -> (double)floorf(floatval)
>> +  Value *V = Cast->getOperand(0);
>> +  V = EmitUnaryFloatFnCall(V, Callee->getName(), B,
>> Callee->getAttributes());
>> +  return B.CreateFPExt(V, B.getDoubleTy());
>> +}
>>
>>  // Double -> Float Shrinking Optimizations for Binary Functions like
>> 'fmin/fmax'
>> -struct BinaryDoubleFPOpt : public LibCallOptimization {
>> -  bool CheckRetType;
>> -  BinaryDoubleFPOpt(bool CheckReturnType): CheckRetType(CheckReturnType)
>> {}
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    // Just make sure this has 2 arguments of the same FP type, which
>> match the
>> -    // result type.
>> -    if (FT->getNumParams() != 2 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> -        FT->getParamType(0) != FT->getParamType(1) ||
>> -        !FT->getParamType(0)->isFloatingPointTy())
>> -      return nullptr;
>> -
>> -    if (CheckRetType) {
>> -      // Check if all the uses for function like 'fmin/fmax' are
>> converted to
>> -      // float.
>> -      for (User *U : CI->users()) {
>> -        FPTruncInst *Cast = dyn_cast<FPTruncInst>(U);
>> -        if (!Cast || !Cast->getType()->isFloatTy())
>> -          return nullptr;
>> -      }
>> -    }
>> +Value *LibCallSimplifier::optimizeBinaryDoubleFP(CallInst *CI,
>> IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  // Just make sure this has 2 arguments of the same FP type, which
>> match the
>> +  // result type.
>> +  if (FT->getNumParams() != 2 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      FT->getParamType(0) != FT->getParamType(1) ||
>> +      !FT->getParamType(0)->isFloatingPointTy())
>> +    return nullptr;
>> +
>> +  // If this is something like 'fmin((double)floatval1,
>> (double)floatval2)',
>> +  // we convert it to fminf.
>> +  FPExtInst *Cast1 = dyn_cast<FPExtInst>(CI->getArgOperand(0));
>> +  FPExtInst *Cast2 = dyn_cast<FPExtInst>(CI->getArgOperand(1));
>> +  if (!Cast1 || !Cast1->getOperand(0)->getType()->isFloatTy() || !Cast2
>> ||
>> +      !Cast2->getOperand(0)->getType()->isFloatTy())
>> +    return nullptr;
>> +
>> +  // fmin((double)floatval1, (double)floatval2)
>> +  //                      -> (double)fmin(floatval1, floatval2)
>> +  Value *V = nullptr;
>> +  Value *V1 = Cast1->getOperand(0);
>> +  Value *V2 = Cast2->getOperand(0);
>> +  V = EmitBinaryFloatFnCall(V1, V2, Callee->getName(), B,
>> +                            Callee->getAttributes());
>> +  return B.CreateFPExt(V, B.getDoubleTy());
>> +}
>>
>> -    // If this is something like 'fmin((double)floatval1,
>> (double)floatval2)',
>> -    // we convert it to fminf.
>> -    FPExtInst *Cast1 = dyn_cast<FPExtInst>(CI->getArgOperand(0));
>> -    FPExtInst *Cast2 = dyn_cast<FPExtInst>(CI->getArgOperand(1));
>> -    if (!Cast1 || !Cast1->getOperand(0)->getType()->isFloatTy() ||
>> -        !Cast2 || !Cast2->getOperand(0)->getType()->isFloatTy())
>> -      return nullptr;
>> -
>> -    // fmin((double)floatval1, (double)floatval2)
>> -    //                      -> (double)fmin(floatval1, floatval2)
>> -    Value *V = nullptr;
>> -    Value *V1 = Cast1->getOperand(0);
>> -    Value *V2 = Cast2->getOperand(0);
>> -    V = EmitBinaryFloatFnCall(V1, V2, Callee->getName(), B,
>> -                              Callee->getAttributes());
>> -    return B.CreateFPExt(V, B.getDoubleTy());
>> -  }
>> -};
>> -
>> -struct UnsafeFPLibCallOptimization : public LibCallOptimization {
>> -  bool UnsafeFPShrink;
>> -  UnsafeFPLibCallOptimization(bool UnsafeFPShrink) {
>> -    this->UnsafeFPShrink = UnsafeFPShrink;
>> -  }
>> -};
>> -
>> -struct CosOpt : public UnsafeFPLibCallOptimization {
>> -  CosOpt(bool UnsafeFPShrink) :
>> UnsafeFPLibCallOptimization(UnsafeFPShrink) {}
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    Value *Ret = nullptr;
>> -    if (UnsafeFPShrink && Callee->getName() == "cos" &&
>> -        TLI->has(LibFunc::cosf)) {
>> -      UnaryDoubleFPOpt UnsafeUnaryDoubleFP(true);
>> -      Ret = UnsafeUnaryDoubleFP.callOptimizer(Callee, CI, B);
>> -    }
>> +Value *LibCallSimplifier::optimizeCos(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  Value *Ret = nullptr;
>> +  if (UnsafeFPShrink && Callee->getName() == "cos" &&
>> TLI->has(LibFunc::cosf)) {
>> +    Ret = optimizeUnaryDoubleFP(CI, B, true);
>> +  }
>>
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    // Just make sure this has 1 argument of FP type, which matches the
>> -    // result type.
>> -    if (FT->getNumParams() != 1 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> -        !FT->getParamType(0)->isFloatingPointTy())
>> -      return Ret;
>> -
>> -    // cos(-x) -> cos(x)
>> -    Value *Op1 = CI->getArgOperand(0);
>> -    if (BinaryOperator::isFNeg(Op1)) {
>> -      BinaryOperator *BinExpr = cast<BinaryOperator>(Op1);
>> -      return B.CreateCall(Callee, BinExpr->getOperand(1), "cos");
>> -    }
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  // Just make sure this has 1 argument of FP type, which matches the
>> +  // result type.
>> +  if (FT->getNumParams() != 1 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      !FT->getParamType(0)->isFloatingPointTy())
>>      return Ret;
>> +
>> +  // cos(-x) -> cos(x)
>> +  Value *Op1 = CI->getArgOperand(0);
>> +  if (BinaryOperator::isFNeg(Op1)) {
>> +    BinaryOperator *BinExpr = cast<BinaryOperator>(Op1);
>> +    return B.CreateCall(Callee, BinExpr->getOperand(1), "cos");
>>    }
>> -};
>> +  return Ret;
>> +}
>>
>> -struct PowOpt : public UnsafeFPLibCallOptimization {
>> -  PowOpt(bool UnsafeFPShrink) :
>> UnsafeFPLibCallOptimization(UnsafeFPShrink) {}
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    Value *Ret = nullptr;
>> -    if (UnsafeFPShrink && Callee->getName() == "pow" &&
>> -        TLI->has(LibFunc::powf)) {
>> -      UnaryDoubleFPOpt UnsafeUnaryDoubleFP(true);
>> -      Ret = UnsafeUnaryDoubleFP.callOptimizer(Callee, CI, B);
>> -    }
>> +Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>>
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    // Just make sure this has 2 arguments of the same FP type, which
>> match the
>> -    // result type.
>> -    if (FT->getNumParams() != 2 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> -        FT->getParamType(0) != FT->getParamType(1) ||
>> -        !FT->getParamType(0)->isFloatingPointTy())
>> -      return Ret;
>> -
>> -    Value *Op1 = CI->getArgOperand(0), *Op2 = CI->getArgOperand(1);
>> -    if (ConstantFP *Op1C = dyn_cast<ConstantFP>(Op1)) {
>> -      // pow(1.0, x) -> 1.0
>> -      if (Op1C->isExactlyValue(1.0))
>> -        return Op1C;
>> -      // pow(2.0, x) -> exp2(x)
>> -      if (Op1C->isExactlyValue(2.0) &&
>> -          hasUnaryFloatFn(TLI, Op1->getType(), LibFunc::exp2,
>> LibFunc::exp2f,
>> -                          LibFunc::exp2l))
>> -        return EmitUnaryFloatFnCall(Op2, "exp2", B,
>> Callee->getAttributes());
>> -      // pow(10.0, x) -> exp10(x)
>> -      if (Op1C->isExactlyValue(10.0) &&
>> -          hasUnaryFloatFn(TLI, Op1->getType(), LibFunc::exp10,
>> LibFunc::exp10f,
>> -                          LibFunc::exp10l))
>> -        return EmitUnaryFloatFnCall(Op2, TLI->getName(LibFunc::exp10), B,
>> -                                    Callee->getAttributes());
>> -    }
>> +  Value *Ret = nullptr;
>> +  if (UnsafeFPShrink && Callee->getName() == "pow" &&
>> TLI->has(LibFunc::powf)) {
>> +    Ret = optimizeUnaryDoubleFP(CI, B, true);
>> +  }
>>
>> -    ConstantFP *Op2C = dyn_cast<ConstantFP>(Op2);
>> -    if (!Op2C) return Ret;
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  // Just make sure this has 2 arguments of the same FP type, which
>> match the
>> +  // result type.
>> +  if (FT->getNumParams() != 2 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      FT->getParamType(0) != FT->getParamType(1) ||
>> +      !FT->getParamType(0)->isFloatingPointTy())
>> +    return Ret;
>>
>> -    if (Op2C->getValueAPF().isZero())  // pow(x, 0.0) -> 1.0
>> -      return ConstantFP::get(CI->getType(), 1.0);
>> +  Value *Op1 = CI->getArgOperand(0), *Op2 = CI->getArgOperand(1);
>> +  if (ConstantFP *Op1C = dyn_cast<ConstantFP>(Op1)) {
>> +    // pow(1.0, x) -> 1.0
>> +    if (Op1C->isExactlyValue(1.0))
>> +      return Op1C;
>> +    // pow(2.0, x) -> exp2(x)
>> +    if (Op1C->isExactlyValue(2.0) &&
>> +        hasUnaryFloatFn(TLI, Op1->getType(), LibFunc::exp2,
>> LibFunc::exp2f,
>> +                        LibFunc::exp2l))
>> +      return EmitUnaryFloatFnCall(Op2, "exp2", B,
>> Callee->getAttributes());
>> +    // pow(10.0, x) -> exp10(x)
>> +    if (Op1C->isExactlyValue(10.0) &&
>> +        hasUnaryFloatFn(TLI, Op1->getType(), LibFunc::exp10,
>> LibFunc::exp10f,
>> +                        LibFunc::exp10l))
>> +      return EmitUnaryFloatFnCall(Op2, TLI->getName(LibFunc::exp10), B,
>> +                                  Callee->getAttributes());
>> +  }
>>
>> -    if (Op2C->isExactlyValue(0.5) &&
>> -        hasUnaryFloatFn(TLI, Op2->getType(), LibFunc::sqrt,
>> LibFunc::sqrtf,
>> -                        LibFunc::sqrtl) &&
>> -        hasUnaryFloatFn(TLI, Op2->getType(), LibFunc::fabs,
>> LibFunc::fabsf,
>> -                        LibFunc::fabsl)) {
>> -      // Expand pow(x, 0.5) to (x == -infinity ? +infinity :
>> fabs(sqrt(x))).
>> -      // This is faster than calling pow, and still handles negative zero
>> -      // and negative infinity correctly.
>> -      // TODO: In fast-math mode, this could be just sqrt(x).
>> -      // TODO: In finite-only mode, this could be just fabs(sqrt(x)).
>> -      Value *Inf = ConstantFP::getInfinity(CI->getType());
>> -      Value *NegInf = ConstantFP::getInfinity(CI->getType(), true);
>> -      Value *Sqrt = EmitUnaryFloatFnCall(Op1, "sqrt", B,
>> -                                         Callee->getAttributes());
>> -      Value *FAbs = EmitUnaryFloatFnCall(Sqrt, "fabs", B,
>> -                                         Callee->getAttributes());
>> -      Value *FCmp = B.CreateFCmpOEQ(Op1, NegInf);
>> -      Value *Sel = B.CreateSelect(FCmp, Inf, FAbs);
>> -      return Sel;
>> -    }
>> +  ConstantFP *Op2C = dyn_cast<ConstantFP>(Op2);
>> +  if (!Op2C)
>> +    return Ret;
>>
>> -    if (Op2C->isExactlyValue(1.0))  // pow(x, 1.0) -> x
>> -      return Op1;
>> -    if (Op2C->isExactlyValue(2.0))  // pow(x, 2.0) -> x*x
>> -      return B.CreateFMul(Op1, Op1, "pow2");
>> -    if (Op2C->isExactlyValue(-1.0)) // pow(x, -1.0) -> 1.0/x
>> -      return B.CreateFDiv(ConstantFP::get(CI->getType(), 1.0),
>> -                          Op1, "powrecip");
>> -    return nullptr;
>> -  }
>> -};
>> -
>> -struct Exp2Opt : public UnsafeFPLibCallOptimization {
>> -  Exp2Opt(bool UnsafeFPShrink) :
>> UnsafeFPLibCallOptimization(UnsafeFPShrink) {}
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    Value *Ret = nullptr;
>> -    if (UnsafeFPShrink && Callee->getName() == "exp2" &&
>> -        TLI->has(LibFunc::exp2f)) {
>> -      UnaryDoubleFPOpt UnsafeUnaryDoubleFP(true);
>> -      Ret = UnsafeUnaryDoubleFP.callOptimizer(Callee, CI, B);
>> -    }
>> +  if (Op2C->getValueAPF().isZero()) // pow(x, 0.0) -> 1.0
>> +    return ConstantFP::get(CI->getType(), 1.0);
>>
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    // Just make sure this has 1 argument of FP type, which matches the
>> -    // result type.
>> -    if (FT->getNumParams() != 1 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> -        !FT->getParamType(0)->isFloatingPointTy())
>> -      return Ret;
>> -
>> -    Value *Op = CI->getArgOperand(0);
>> -    // Turn exp2(sitofp(x)) -> ldexp(1.0, sext(x))  if sizeof(x) <= 32
>> -    // Turn exp2(uitofp(x)) -> ldexp(1.0, zext(x))  if sizeof(x) < 32
>> -    LibFunc::Func LdExp = LibFunc::ldexpl;
>> -    if (Op->getType()->isFloatTy())
>> -      LdExp = LibFunc::ldexpf;
>> -    else if (Op->getType()->isDoubleTy())
>> -      LdExp = LibFunc::ldexp;
>> -
>> -    if (TLI->has(LdExp)) {
>> -      Value *LdExpArg = nullptr;
>> -      if (SIToFPInst *OpC = dyn_cast<SIToFPInst>(Op)) {
>> -        if (OpC->getOperand(0)->getType()->getPrimitiveSizeInBits() <=
>> 32)
>> -          LdExpArg = B.CreateSExt(OpC->getOperand(0), B.getInt32Ty());
>> -      } else if (UIToFPInst *OpC = dyn_cast<UIToFPInst>(Op)) {
>> -        if (OpC->getOperand(0)->getType()->getPrimitiveSizeInBits() < 32)
>> -          LdExpArg = B.CreateZExt(OpC->getOperand(0), B.getInt32Ty());
>> -      }
>> -
>> -      if (LdExpArg) {
>> -        Constant *One = ConstantFP::get(*Context, APFloat(1.0f));
>> -        if (!Op->getType()->isFloatTy())
>> -          One = ConstantExpr::getFPExtend(One, Op->getType());
>> -
>> -        Module *M = Caller->getParent();
>> -        Value *Callee =
>> -            M->getOrInsertFunction(TLI->getName(LdExp), Op->getType(),
>> -                                   Op->getType(), B.getInt32Ty(), NULL);
>> -        CallInst *CI = B.CreateCall2(Callee, One, LdExpArg);
>> -        if (const Function *F =
>> dyn_cast<Function>(Callee->stripPointerCasts()))
>> -          CI->setCallingConv(F->getCallingConv());
>> +  if (Op2C->isExactlyValue(0.5) &&
>> +      hasUnaryFloatFn(TLI, Op2->getType(), LibFunc::sqrt, LibFunc::sqrtf,
>> +                      LibFunc::sqrtl) &&
>> +      hasUnaryFloatFn(TLI, Op2->getType(), LibFunc::fabs, LibFunc::fabsf,
>> +                      LibFunc::fabsl)) {
>> +    // Expand pow(x, 0.5) to (x == -infinity ? +infinity :
>> fabs(sqrt(x))).
>> +    // This is faster than calling pow, and still handles negative zero
>> +    // and negative infinity correctly.
>> +    // TODO: In fast-math mode, this could be just sqrt(x).
>> +    // TODO: In finite-only mode, this could be just fabs(sqrt(x)).
>> +    Value *Inf = ConstantFP::getInfinity(CI->getType());
>> +    Value *NegInf = ConstantFP::getInfinity(CI->getType(), true);
>> +    Value *Sqrt = EmitUnaryFloatFnCall(Op1, "sqrt", B,
>> Callee->getAttributes());
>> +    Value *FAbs =
>> +        EmitUnaryFloatFnCall(Sqrt, "fabs", B, Callee->getAttributes());
>> +    Value *FCmp = B.CreateFCmpOEQ(Op1, NegInf);
>> +    Value *Sel = B.CreateSelect(FCmp, Inf, FAbs);
>> +    return Sel;
>> +  }
>> +
>> +  if (Op2C->isExactlyValue(1.0)) // pow(x, 1.0) -> x
>> +    return Op1;
>> +  if (Op2C->isExactlyValue(2.0)) // pow(x, 2.0) -> x*x
>> +    return B.CreateFMul(Op1, Op1, "pow2");
>> +  if (Op2C->isExactlyValue(-1.0)) // pow(x, -1.0) -> 1.0/x
>> +    return B.CreateFDiv(ConstantFP::get(CI->getType(), 1.0), Op1,
>> "powrecip");
>> +  return nullptr;
>> +}
>>
>> -        return CI;
>> -      }
>> -    }
>> -    return Ret;
>> +Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  Function *Caller = CI->getParent()->getParent();
>> +
>> +  Value *Ret = nullptr;
>> +  if (UnsafeFPShrink && Callee->getName() == "exp2" &&
>> +      TLI->has(LibFunc::exp2f)) {
>> +    Ret = optimizeUnaryDoubleFP(CI, B, true);
>>    }
>> -};
>>
>> -struct SinCosPiOpt : public LibCallOptimization {
>> -  SinCosPiOpt() {}
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  // Just make sure this has 1 argument of FP type, which matches the
>> +  // result type.
>> +  if (FT->getNumParams() != 1 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      !FT->getParamType(0)->isFloatingPointTy())
>> +    return Ret;
>>
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // Make sure the prototype is as expected, otherwise the rest of the
>> -    // function is probably invalid and likely to abort.
>> -    if (!isTrigLibCall(CI))
>> -      return nullptr;
>> -
>> -    Value *Arg = CI->getArgOperand(0);
>> -    SmallVector<CallInst *, 1> SinCalls;
>> -    SmallVector<CallInst *, 1> CosCalls;
>> -    SmallVector<CallInst *, 1> SinCosCalls;
>> -
>> -    bool IsFloat = Arg->getType()->isFloatTy();
>> -
>> -    // Look for all compatible sinpi, cospi and sincospi calls with the
>> same
>> -    // argument. If there are enough (in some sense) we can make the
>> -    // substitution.
>> -    for (User *U : Arg->users())
>> -      classifyArgUse(U, CI->getParent(), IsFloat, SinCalls, CosCalls,
>> -                     SinCosCalls);
>> -
>> -    // It's only worthwhile if both sinpi and cospi are actually used.
>> -    if (SinCosCalls.empty() && (SinCalls.empty() || CosCalls.empty()))
>> -      return nullptr;
>> -
>> -    Value *Sin, *Cos, *SinCos;
>> -    insertSinCosCall(B, CI->getCalledFunction(), Arg, IsFloat, Sin, Cos,
>> -                     SinCos);
>> -
>> -    replaceTrigInsts(SinCalls, Sin);
>> -    replaceTrigInsts(CosCalls, Cos);
>> -    replaceTrigInsts(SinCosCalls, SinCos);
>> -
>> -    return nullptr;
>> -  }
>> -
>> -  bool isTrigLibCall(CallInst *CI) {
>> -    Function *Callee = CI->getCalledFunction();
>> -    FunctionType *FT = Callee->getFunctionType();
>> -
>> -    // We can only hope to do anything useful if we can ignore things
>> like errno
>> -    // and floating-point exceptions.
>> -    bool AttributesSafe = CI->hasFnAttr(Attribute::NoUnwind) &&
>> -                          CI->hasFnAttr(Attribute::ReadNone);
>> -
>> -    // Other than that we need float(float) or double(double)
>> -    return AttributesSafe && FT->getNumParams() == 1 &&
>> -           FT->getReturnType() == FT->getParamType(0) &&
>> -           (FT->getParamType(0)->isFloatTy() ||
>> -            FT->getParamType(0)->isDoubleTy());
>> -  }
>> -
>> -  void classifyArgUse(Value *Val, BasicBlock *BB, bool IsFloat,
>> -                      SmallVectorImpl<CallInst *> &SinCalls,
>> -                      SmallVectorImpl<CallInst *> &CosCalls,
>> -                      SmallVectorImpl<CallInst *> &SinCosCalls) {
>> -    CallInst *CI = dyn_cast<CallInst>(Val);
>> -
>> -    if (!CI)
>> -      return;
>> -
>> -    Function *Callee = CI->getCalledFunction();
>> -    StringRef FuncName = Callee->getName();
>> -    LibFunc::Func Func;
>> -    if (!TLI->getLibFunc(FuncName, Func) || !TLI->has(Func) ||
>> -        !isTrigLibCall(CI))
>> -      return;
>> -
>> -    if (IsFloat) {
>> -      if (Func == LibFunc::sinpif)
>> -        SinCalls.push_back(CI);
>> -      else if (Func == LibFunc::cospif)
>> -        CosCalls.push_back(CI);
>> -      else if (Func == LibFunc::sincospif_stret)
>> -        SinCosCalls.push_back(CI);
>> -    } else {
>> -      if (Func == LibFunc::sinpi)
>> -        SinCalls.push_back(CI);
>> -      else if (Func == LibFunc::cospi)
>> -        CosCalls.push_back(CI);
>> -      else if (Func == LibFunc::sincospi_stret)
>> -        SinCosCalls.push_back(CI);
>> -    }
>> -  }
>> +  Value *Op = CI->getArgOperand(0);
>> +  // Turn exp2(sitofp(x)) -> ldexp(1.0, sext(x))  if sizeof(x) <= 32
>> +  // Turn exp2(uitofp(x)) -> ldexp(1.0, zext(x))  if sizeof(x) < 32
>> +  LibFunc::Func LdExp = LibFunc::ldexpl;
>> +  if (Op->getType()->isFloatTy())
>> +    LdExp = LibFunc::ldexpf;
>> +  else if (Op->getType()->isDoubleTy())
>> +    LdExp = LibFunc::ldexp;
>> +
>> +  if (TLI->has(LdExp)) {
>> +    Value *LdExpArg = nullptr;
>> +    if (SIToFPInst *OpC = dyn_cast<SIToFPInst>(Op)) {
>> +      if (OpC->getOperand(0)->getType()->getPrimitiveSizeInBits() <= 32)
>> +        LdExpArg = B.CreateSExt(OpC->getOperand(0), B.getInt32Ty());
>> +    } else if (UIToFPInst *OpC = dyn_cast<UIToFPInst>(Op)) {
>> +      if (OpC->getOperand(0)->getType()->getPrimitiveSizeInBits() < 32)
>> +        LdExpArg = B.CreateZExt(OpC->getOperand(0), B.getInt32Ty());
>> +    }
>> +
>> +    if (LdExpArg) {
>> +      Constant *One = ConstantFP::get(CI->getContext(), APFloat(1.0f));
>> +      if (!Op->getType()->isFloatTy())
>> +        One = ConstantExpr::getFPExtend(One, Op->getType());
>> +
>> +      Module *M = Caller->getParent();
>> +      Value *Callee =
>> +          M->getOrInsertFunction(TLI->getName(LdExp), Op->getType(),
>> +                                 Op->getType(), B.getInt32Ty(), NULL);
>> +      CallInst *CI = B.CreateCall2(Callee, One, LdExpArg);
>> +      if (const Function *F =
>> dyn_cast<Function>(Callee->stripPointerCasts()))
>> +        CI->setCallingConv(F->getCallingConv());
>>
>> -  void replaceTrigInsts(SmallVectorImpl<CallInst*> &Calls, Value *Res) {
>> -    for (SmallVectorImpl<CallInst*>::iterator I = Calls.begin(),
>> -           E = Calls.end();
>> -         I != E; ++I) {
>> -      LCS->replaceAllUsesWith(*I, Res);
>> +      return CI;
>>      }
>>    }
>> +  return Ret;
>> +}
>>
>> -  void insertSinCosCall(IRBuilder<> &B, Function *OrigCallee, Value *Arg,
>> -                        bool UseFloat, Value *&Sin, Value *&Cos,
>> -                        Value *&SinCos) {
>> -    Type *ArgTy = Arg->getType();
>> -    Type *ResTy;
>> -    StringRef Name;
>> -
>> -    Triple T(OrigCallee->getParent()->getTargetTriple());
>> -    if (UseFloat) {
>> -      Name = "__sincospif_stret";
>> -
>> -      assert(T.getArch() != Triple::x86 && "x86 messy and unsupported
>> for now");
>> -      // x86_64 can't use {float, float} since that would be returned in
>> both
>> -      // xmm0 and xmm1, which isn't what a real struct would do.
>> -      ResTy = T.getArch() == Triple::x86_64
>> -                  ? static_cast<Type *>(VectorType::get(ArgTy, 2))
>> -                  : static_cast<Type *>(StructType::get(ArgTy, ArgTy,
>> NULL));
>> -    } else {
>> -      Name = "__sincospi_stret";
>> -      ResTy = StructType::get(ArgTy, ArgTy, NULL);
>> -    }
>> +static bool isTrigLibCall(CallInst *CI);
>> +static void insertSinCosCall(IRBuilder<> &B, Function *OrigCallee, Value
>> *Arg,
>> +                             bool UseFloat, Value *&Sin, Value *&Cos,
>> +                             Value *&SinCos);
>>
>> -    Module *M = OrigCallee->getParent();
>> -    Value *Callee = M->getOrInsertFunction(Name,
>> OrigCallee->getAttributes(),
>> -                                           ResTy, ArgTy, NULL);
>> -
>> -    if (Instruction *ArgInst = dyn_cast<Instruction>(Arg)) {
>> -      // If the argument is an instruction, it must dominate all uses so
>> put our
>> -      // sincos call there.
>> -      BasicBlock::iterator Loc = ArgInst;
>> -      B.SetInsertPoint(ArgInst->getParent(), ++Loc);
>> -    } else {
>> -      // Otherwise (e.g. for a constant) the beginning of the function
>> is as
>> -      // good a place as any.
>> -      BasicBlock &EntryBB =
>> B.GetInsertBlock()->getParent()->getEntryBlock();
>> -      B.SetInsertPoint(&EntryBB, EntryBB.begin());
>> -    }
>> +Value *LibCallSimplifier::optimizeSinCosPi(CallInst *CI, IRBuilder<> &B)
>> {
>>
>> -    SinCos = B.CreateCall(Callee, Arg, "sincospi");
>> +  // Make sure the prototype is as expected, otherwise the rest of the
>> +  // function is probably invalid and likely to abort.
>> +  if (!isTrigLibCall(CI))
>> +    return nullptr;
>>
>> -    if (SinCos->getType()->isStructTy()) {
>> -      Sin = B.CreateExtractValue(SinCos, 0, "sinpi");
>> -      Cos = B.CreateExtractValue(SinCos, 1, "cospi");
>> -    } else {
>> -      Sin = B.CreateExtractElement(SinCos,
>> ConstantInt::get(B.getInt32Ty(), 0),
>> -                                   "sinpi");
>> -      Cos = B.CreateExtractElement(SinCos,
>> ConstantInt::get(B.getInt32Ty(), 1),
>> -                                   "cospi");
>> -    }
>> +  Value *Arg = CI->getArgOperand(0);
>> +  SmallVector<CallInst *, 1> SinCalls;
>> +  SmallVector<CallInst *, 1> CosCalls;
>> +  SmallVector<CallInst *, 1> SinCosCalls;
>> +
>> +  bool IsFloat = Arg->getType()->isFloatTy();
>> +
>> +  // Look for all compatible sinpi, cospi and sincospi calls with the
>> same
>> +  // argument. If there are enough (in some sense) we can make the
>> +  // substitution.
>> +  for (User *U : Arg->users())
>> +    classifyArgUse(U, CI->getParent(), IsFloat, SinCalls, CosCalls,
>> +                   SinCosCalls);
>> +
>> +  // It's only worthwhile if both sinpi and cospi are actually used.
>> +  if (SinCosCalls.empty() && (SinCalls.empty() || CosCalls.empty()))
>> +    return nullptr;
>> +
>> +  Value *Sin, *Cos, *SinCos;
>> +  insertSinCosCall(B, CI->getCalledFunction(), Arg, IsFloat, Sin, Cos,
>> SinCos);
>> +
>> +  replaceTrigInsts(SinCalls, Sin);
>> +  replaceTrigInsts(CosCalls, Cos);
>> +  replaceTrigInsts(SinCosCalls, SinCos);
>> +
>> +  return nullptr;
>> +}
>> +
>> +static bool isTrigLibCall(CallInst *CI) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +
>> +  // We can only hope to do anything useful if we can ignore things like
>> errno
>> +  // and floating-point exceptions.
>> +  bool AttributesSafe =
>> +      CI->hasFnAttr(Attribute::NoUnwind) &&
>> CI->hasFnAttr(Attribute::ReadNone);
>> +
>> +  // Other than that we need float(float) or double(double)
>> +  return AttributesSafe && FT->getNumParams() == 1 &&
>> +         FT->getReturnType() == FT->getParamType(0) &&
>> +         (FT->getParamType(0)->isFloatTy() ||
>> +          FT->getParamType(0)->isDoubleTy());
>> +}
>> +
>> +void
>> +LibCallSimplifier::classifyArgUse(Value *Val, BasicBlock *BB, bool
>> IsFloat,
>> +                                  SmallVectorImpl<CallInst *> &SinCalls,
>> +                                  SmallVectorImpl<CallInst *> &CosCalls,
>> +                                  SmallVectorImpl<CallInst *>
>> &SinCosCalls) {
>> +  CallInst *CI = dyn_cast<CallInst>(Val);
>> +
>> +  if (!CI)
>> +    return;
>> +
>> +  Function *Callee = CI->getCalledFunction();
>> +  StringRef FuncName = Callee->getName();
>> +  LibFunc::Func Func;
>> +  if (!TLI->getLibFunc(FuncName, Func) || !TLI->has(Func) ||
>> !isTrigLibCall(CI))
>> +    return;
>> +
>> +  if (IsFloat) {
>> +    if (Func == LibFunc::sinpif)
>> +      SinCalls.push_back(CI);
>> +    else if (Func == LibFunc::cospif)
>> +      CosCalls.push_back(CI);
>> +    else if (Func == LibFunc::sincospif_stret)
>> +      SinCosCalls.push_back(CI);
>> +  } else {
>> +    if (Func == LibFunc::sinpi)
>> +      SinCalls.push_back(CI);
>> +    else if (Func == LibFunc::cospi)
>> +      CosCalls.push_back(CI);
>> +    else if (Func == LibFunc::sincospi_stret)
>> +      SinCosCalls.push_back(CI);
>>    }
>> +}
>>
>> -};
>> +void LibCallSimplifier::replaceTrigInsts(SmallVectorImpl<CallInst *>
>> &Calls,
>> +                                         Value *Res) {
>> +  for (SmallVectorImpl<CallInst *>::iterator I = Calls.begin(), E =
>> Calls.end();
>> +       I != E; ++I) {
>> +    replaceAllUsesWith(*I, Res);
>> +  }
>> +}
>> +
>> +void insertSinCosCall(IRBuilder<> &B, Function *OrigCallee, Value *Arg,
>> +                      bool UseFloat, Value *&Sin, Value *&Cos, Value
>> *&SinCos) {
>> +  Type *ArgTy = Arg->getType();
>> +  Type *ResTy;
>> +  StringRef Name;
>> +
>> +  Triple T(OrigCallee->getParent()->getTargetTriple());
>> +  if (UseFloat) {
>> +    Name = "__sincospif_stret";
>> +
>> +    assert(T.getArch() != Triple::x86 && "x86 messy and unsupported for
>> now");
>> +    // x86_64 can't use {float, float} since that would be returned in
>> both
>> +    // xmm0 and xmm1, which isn't what a real struct would do.
>> +    ResTy = T.getArch() == Triple::x86_64
>> +                ? static_cast<Type *>(VectorType::get(ArgTy, 2))
>> +                : static_cast<Type *>(StructType::get(ArgTy, ArgTy,
>> NULL));
>> +  } else {
>> +    Name = "__sincospi_stret";
>> +    ResTy = StructType::get(ArgTy, ArgTy, NULL);
>> +  }
>> +
>> +  Module *M = OrigCallee->getParent();
>> +  Value *Callee = M->getOrInsertFunction(Name,
>> OrigCallee->getAttributes(),
>> +                                         ResTy, ArgTy, NULL);
>> +
>> +  if (Instruction *ArgInst = dyn_cast<Instruction>(Arg)) {
>> +    // If the argument is an instruction, it must dominate all uses so
>> put our
>> +    // sincos call there.
>> +    BasicBlock::iterator Loc = ArgInst;
>> +    B.SetInsertPoint(ArgInst->getParent(), ++Loc);
>> +  } else {
>> +    // Otherwise (e.g. for a constant) the beginning of the function is
>> as
>> +    // good a place as any.
>> +    BasicBlock &EntryBB =
>> B.GetInsertBlock()->getParent()->getEntryBlock();
>> +    B.SetInsertPoint(&EntryBB, EntryBB.begin());
>> +  }
>> +
>> +  SinCos = B.CreateCall(Callee, Arg, "sincospi");
>> +
>> +  if (SinCos->getType()->isStructTy()) {
>> +    Sin = B.CreateExtractValue(SinCos, 0, "sinpi");
>> +    Cos = B.CreateExtractValue(SinCos, 1, "cospi");
>> +  } else {
>> +    Sin = B.CreateExtractElement(SinCos,
>> ConstantInt::get(B.getInt32Ty(), 0),
>> +                                 "sinpi");
>> +    Cos = B.CreateExtractElement(SinCos,
>> ConstantInt::get(B.getInt32Ty(), 1),
>> +                                 "cospi");
>> +  }
>> +}
>>
>>
>>  //===----------------------------------------------------------------------===//
>>  // Integer Library Call Optimizations
>>
>>  //===----------------------------------------------------------------------===//
>>
>> -struct FFSOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    // Just make sure this has 2 arguments of the same FP type, which
>> match the
>> -    // result type.
>> -    if (FT->getNumParams() != 1 ||
>> -        !FT->getReturnType()->isIntegerTy(32) ||
>> -        !FT->getParamType(0)->isIntegerTy())
>> -      return nullptr;
>> -
>> -    Value *Op = CI->getArgOperand(0);
>> -
>> -    // Constant fold.
>> -    if (ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
>> -      if (CI->isZero()) // ffs(0) -> 0.
>> -        return B.getInt32(0);
>> -      // ffs(c) -> cttz(c)+1
>> -      return B.getInt32(CI->getValue().countTrailingZeros() + 1);
>> -    }
>> +Value *LibCallSimplifier::optimizeFFS(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  // Just make sure this has 2 arguments of the same FP type, which
>> match the
>> +  // result type.
>> +  if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy(32) ||
>> +      !FT->getParamType(0)->isIntegerTy())
>> +    return nullptr;
>> +
>> +  Value *Op = CI->getArgOperand(0);
>> +
>> +  // Constant fold.
>> +  if (ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
>> +    if (CI->isZero()) // ffs(0) -> 0.
>> +      return B.getInt32(0);
>> +    // ffs(c) -> cttz(c)+1
>> +    return B.getInt32(CI->getValue().countTrailingZeros() + 1);
>> +  }
>> +
>> +  // ffs(x) -> x != 0 ? (i32)llvm.cttz(x)+1 : 0
>> +  Type *ArgType = Op->getType();
>> +  Value *F =
>> +      Intrinsic::getDeclaration(Callee->getParent(), Intrinsic::cttz,
>> ArgType);
>> +  Value *V = B.CreateCall2(F, Op, B.getFalse(), "cttz");
>> +  V = B.CreateAdd(V, ConstantInt::get(V->getType(), 1));
>> +  V = B.CreateIntCast(V, B.getInt32Ty(), false);
>>
>> -    // ffs(x) -> x != 0 ? (i32)llvm.cttz(x)+1 : 0
>> -    Type *ArgType = Op->getType();
>> -    Value *F = Intrinsic::getDeclaration(Callee->getParent(),
>> -                                         Intrinsic::cttz, ArgType);
>> -    Value *V = B.CreateCall2(F, Op, B.getFalse(), "cttz");
>> -    V = B.CreateAdd(V, ConstantInt::get(V->getType(), 1));
>> -    V = B.CreateIntCast(V, B.getInt32Ty(), false);
>> -
>> -    Value *Cond = B.CreateICmpNE(Op, Constant::getNullValue(ArgType));
>> -    return B.CreateSelect(Cond, V, B.getInt32(0));
>> -  }
>> -};
>> -
>> -struct AbsOpt : public LibCallOptimization {
>> -  bool ignoreCallingConv() override { return true; }
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    // We require integer(integer) where the types agree.
>> -    if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() ||
>> -        FT->getParamType(0) != FT->getReturnType())
>> -      return nullptr;
>> -
>> -    // abs(x) -> x >s -1 ? x : -x
>> -    Value *Op = CI->getArgOperand(0);
>> -    Value *Pos = B.CreateICmpSGT(Op,
>> Constant::getAllOnesValue(Op->getType()),
>> -                                 "ispos");
>> -    Value *Neg = B.CreateNeg(Op, "neg");
>> -    return B.CreateSelect(Pos, Op, Neg);
>> -  }
>> -};
>> -
>> -struct IsDigitOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    // We require integer(i32)
>> -    if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() ||
>> -        !FT->getParamType(0)->isIntegerTy(32))
>> -      return nullptr;
>> -
>> -    // isdigit(c) -> (c-'0') <u 10
>> -    Value *Op = CI->getArgOperand(0);
>> -    Op = B.CreateSub(Op, B.getInt32('0'), "isdigittmp");
>> -    Op = B.CreateICmpULT(Op, B.getInt32(10), "isdigit");
>> -    return B.CreateZExt(Op, CI->getType());
>> -  }
>> -};
>> -
>> -struct IsAsciiOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    // We require integer(i32)
>> -    if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() ||
>> -        !FT->getParamType(0)->isIntegerTy(32))
>> -      return nullptr;
>> -
>> -    // isascii(c) -> c <u 128
>> -    Value *Op = CI->getArgOperand(0);
>> -    Op = B.CreateICmpULT(Op, B.getInt32(128), "isascii");
>> -    return B.CreateZExt(Op, CI->getType());
>> -  }
>> -};
>> -
>> -struct ToAsciiOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    // We require i32(i32)
>> -    if (FT->getNumParams() != 1 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> -        !FT->getParamType(0)->isIntegerTy(32))
>> -      return nullptr;
>> -
>> -    // toascii(c) -> c & 0x7f
>> -    return B.CreateAnd(CI->getArgOperand(0),
>> -                       ConstantInt::get(CI->getType(),0x7F));
>> -  }
>> -};
>> +  Value *Cond = B.CreateICmpNE(Op, Constant::getNullValue(ArgType));
>> +  return B.CreateSelect(Cond, V, B.getInt32(0));
>> +}
>> +
>> +Value *LibCallSimplifier::optimizeAbs(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  // We require integer(integer) where the types agree.
>> +  if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() ||
>> +      FT->getParamType(0) != FT->getReturnType())
>> +    return nullptr;
>> +
>> +  // abs(x) -> x >s -1 ? x : -x
>> +  Value *Op = CI->getArgOperand(0);
>> +  Value *Pos =
>> +      B.CreateICmpSGT(Op, Constant::getAllOnesValue(Op->getType()),
>> "ispos");
>> +  Value *Neg = B.CreateNeg(Op, "neg");
>> +  return B.CreateSelect(Pos, Op, Neg);
>> +}
>> +
>> +Value *LibCallSimplifier::optimizeIsDigit(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  // We require integer(i32)
>> +  if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() ||
>> +      !FT->getParamType(0)->isIntegerTy(32))
>> +    return nullptr;
>> +
>> +  // isdigit(c) -> (c-'0') <u 10
>> +  Value *Op = CI->getArgOperand(0);
>> +  Op = B.CreateSub(Op, B.getInt32('0'), "isdigittmp");
>> +  Op = B.CreateICmpULT(Op, B.getInt32(10), "isdigit");
>> +  return B.CreateZExt(Op, CI->getType());
>> +}
>> +
>> +Value *LibCallSimplifier::optimizeIsAscii(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  // We require integer(i32)
>> +  if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() ||
>> +      !FT->getParamType(0)->isIntegerTy(32))
>> +    return nullptr;
>> +
>> +  // isascii(c) -> c <u 128
>> +  Value *Op = CI->getArgOperand(0);
>> +  Op = B.CreateICmpULT(Op, B.getInt32(128), "isascii");
>> +  return B.CreateZExt(Op, CI->getType());
>> +}
>> +
>> +Value *LibCallSimplifier::optimizeToAscii(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  // We require i32(i32)
>> +  if (FT->getNumParams() != 1 || FT->getReturnType() !=
>> FT->getParamType(0) ||
>> +      !FT->getParamType(0)->isIntegerTy(32))
>> +    return nullptr;
>> +
>> +  // toascii(c) -> c & 0x7f
>> +  return B.CreateAnd(CI->getArgOperand(0),
>> +                     ConstantInt::get(CI->getType(), 0x7F));
>> +}
>>
>>
>>  //===----------------------------------------------------------------------===//
>>  // Formatting and IO Library Call Optimizations
>>
>>  //===----------------------------------------------------------------------===//
>>
>> -struct ErrorReportingOpt : public LibCallOptimization {
>> -  ErrorReportingOpt(int S = -1) : StreamArg(S) {}
>> +static bool isReportingError(Function *Callee, CallInst *CI, int
>> StreamArg);
>>
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &) override {
>> -    // Error reporting calls should be cold, mark them as such.
>> -    // This applies even to non-builtin calls: it is only a hint and
>> applies to
>> -    // functions that the frontend might not understand as builtins.
>> -
>> -    // This heuristic was suggested in:
>> -    // Improving Static Branch Prediction in a Compiler
>> -    // Brian L. Deitrich, Ben-Chung Cheng, Wen-mei W. Hwu
>> -    // Proceedings of PACT'98, Oct. 1998, IEEE
>> -
>> -    if (!CI->hasFnAttr(Attribute::Cold) && isReportingError(Callee, CI))
>> {
>> -      CI->addAttribute(AttributeSet::FunctionIndex, Attribute::Cold);
>> -    }
>> +Value *LibCallSimplifier::optimizeErrorReporting(CallInst *CI,
>> IRBuilder<> &B,
>> +                                                 int StreamArg) {
>> +  // Error reporting calls should be cold, mark them as such.
>> +  // This applies even to non-builtin calls: it is only a hint and
>> applies to
>> +  // functions that the frontend might not understand as builtins.
>> +
>> +  // This heuristic was suggested in:
>> +  // Improving Static Branch Prediction in a Compiler
>> +  // Brian L. Deitrich, Ben-Chung Cheng, Wen-mei W. Hwu
>> +  // Proceedings of PACT'98, Oct. 1998, IEEE
>> +  Function *Callee = CI->getCalledFunction();
>>
>> -    return nullptr;
>> +  if (!CI->hasFnAttr(Attribute::Cold) &&
>> +      isReportingError(Callee, CI, StreamArg)) {
>> +    CI->addAttribute(AttributeSet::FunctionIndex, Attribute::Cold);
>>    }
>>
>> -protected:
>> -  bool isReportingError(Function *Callee, CallInst *CI) {
>> -    if (!ColdErrorCalls)
>> -      return false;
>> -
>> -    if (!Callee || !Callee->isDeclaration())
>> -      return false;
>> -
>> -    if (StreamArg < 0)
>> -      return true;
>> +  return nullptr;
>> +}
>>
>> -    // These functions might be considered cold, but only if their stream
>> -    // argument is stderr.
>> +static bool isReportingError(Function *Callee, CallInst *CI, int
>> StreamArg) {
>> +  if (!ColdErrorCalls)
>> +    return false;
>>
>> -    if (StreamArg >= (int) CI->getNumArgOperands())
>> -      return false;
>> -    LoadInst *LI = dyn_cast<LoadInst>(CI->getArgOperand(StreamArg));
>> -    if (!LI)
>> -      return false;
>> -    GlobalVariable *GV =
>> dyn_cast<GlobalVariable>(LI->getPointerOperand());
>> -    if (!GV || !GV->isDeclaration())
>> -      return false;
>> -    return GV->getName() == "stderr";
>> -  }
>> -
>> -  int StreamArg;
>> -};
>> -
>> -struct PrintFOpt : public LibCallOptimization {
>> -  Value *optimizeFixedFormatString(Function *Callee, CallInst *CI,
>> -                                   IRBuilder<> &B) {
>> -    // Check for a fixed format string.
>> -    StringRef FormatStr;
>> -    if (!getConstantStringInfo(CI->getArgOperand(0), FormatStr))
>> -      return nullptr;
>> -
>> -    // Empty format string -> noop.
>> -    if (FormatStr.empty())  // Tolerate printf's declared void.
>> -      return CI->use_empty() ? (Value*)CI :
>> -                               ConstantInt::get(CI->getType(), 0);
>> -
>> -    // Do not do any of the following transformations if the printf
>> return value
>> -    // is used, in general the printf return value is not compatible
>> with either
>> -    // putchar() or puts().
>> -    if (!CI->use_empty())
>> -      return nullptr;
>> -
>> -    // printf("x") -> putchar('x'), even for '%'.
>> -    if (FormatStr.size() == 1) {
>> -      Value *Res = EmitPutChar(B.getInt32(FormatStr[0]), B, DL, TLI);
>> -      if (CI->use_empty() || !Res) return Res;
>> -      return B.CreateIntCast(Res, CI->getType(), true);
>> -    }
>> +  if (!Callee || !Callee->isDeclaration())
>> +    return false;
>>
>> -    // printf("foo\n") --> puts("foo")
>> -    if (FormatStr[FormatStr.size()-1] == '\n' &&
>> -        FormatStr.find('%') == StringRef::npos) { // No format
>> characters.
>> -      // Create a string literal with no \n on it.  We expect the
>> constant merge
>> -      // pass to be run after this pass, to merge duplicate strings.
>> -      FormatStr = FormatStr.drop_back();
>> -      Value *GV = B.CreateGlobalString(FormatStr, "str");
>> -      Value *NewCI = EmitPutS(GV, B, DL, TLI);
>> -      return (CI->use_empty() || !NewCI) ?
>> -              NewCI :
>> -              ConstantInt::get(CI->getType(), FormatStr.size()+1);
>> -    }
>> +  if (StreamArg < 0)
>> +    return true;
>>
>> -    // Optimize specific format strings.
>> -    // printf("%c", chr) --> putchar(chr)
>> -    if (FormatStr == "%c" && CI->getNumArgOperands() > 1 &&
>> -        CI->getArgOperand(1)->getType()->isIntegerTy()) {
>> -      Value *Res = EmitPutChar(CI->getArgOperand(1), B, DL, TLI);
>> +  // These functions might be considered cold, but only if their stream
>> +  // argument is stderr.
>>
>> -      if (CI->use_empty() || !Res) return Res;
>> -      return B.CreateIntCast(Res, CI->getType(), true);
>> -    }
>> +  if (StreamArg >= (int)CI->getNumArgOperands())
>> +    return false;
>> +  LoadInst *LI = dyn_cast<LoadInst>(CI->getArgOperand(StreamArg));
>> +  if (!LI)
>> +    return false;
>> +  GlobalVariable *GV = dyn_cast<GlobalVariable>(LI->getPointerOperand());
>> +  if (!GV || !GV->isDeclaration())
>> +    return false;
>> +  return GV->getName() == "stderr";
>> +}
>>
>> -    // printf("%s\n", str) --> puts(str)
>> -    if (FormatStr == "%s\n" && CI->getNumArgOperands() > 1 &&
>> -        CI->getArgOperand(1)->getType()->isPointerTy()) {
>> -      return EmitPutS(CI->getArgOperand(1), B, DL, TLI);
>> -    }
>> -    return nullptr;
>> +Value *LibCallSimplifier::optimizePrintFString(CallInst *CI, IRBuilder<>
>> &B) {
>> +  // Check for a fixed format string.
>> +  StringRef FormatStr;
>> +  if (!getConstantStringInfo(CI->getArgOperand(0), FormatStr))
>> +    return nullptr;
>> +
>> +  // Empty format string -> noop.
>> +  if (FormatStr.empty()) // Tolerate printf's declared void.
>> +    return CI->use_empty() ? (Value *)CI :
>> ConstantInt::get(CI->getType(), 0);
>> +
>> +  // Do not do any of the following transformations if the printf return
>> value
>> +  // is used, in general the printf return value is not compatible with
>> either
>> +  // putchar() or puts().
>> +  if (!CI->use_empty())
>> +    return nullptr;
>> +
>> +  // printf("x") -> putchar('x'), even for '%'.
>> +  if (FormatStr.size() == 1) {
>> +    Value *Res = EmitPutChar(B.getInt32(FormatStr[0]), B, DL, TLI);
>> +    if (CI->use_empty() || !Res)
>> +      return Res;
>> +    return B.CreateIntCast(Res, CI->getType(), true);
>> +  }
>> +
>> +  // printf("foo\n") --> puts("foo")
>> +  if (FormatStr[FormatStr.size() - 1] == '\n' &&
>> +      FormatStr.find('%') == StringRef::npos) { // No format characters.
>> +    // Create a string literal with no \n on it.  We expect the constant
>> merge
>> +    // pass to be run after this pass, to merge duplicate strings.
>> +    FormatStr = FormatStr.drop_back();
>> +    Value *GV = B.CreateGlobalString(FormatStr, "str");
>> +    Value *NewCI = EmitPutS(GV, B, DL, TLI);
>> +    return (CI->use_empty() || !NewCI)
>> +               ? NewCI
>> +               : ConstantInt::get(CI->getType(), FormatStr.size() + 1);
>> +  }
>> +
>> +  // Optimize specific format strings.
>> +  // printf("%c", chr) --> putchar(chr)
>> +  if (FormatStr == "%c" && CI->getNumArgOperands() > 1 &&
>> +      CI->getArgOperand(1)->getType()->isIntegerTy()) {
>> +    Value *Res = EmitPutChar(CI->getArgOperand(1), B, DL, TLI);
>> +
>> +    if (CI->use_empty() || !Res)
>> +      return Res;
>> +    return B.CreateIntCast(Res, CI->getType(), true);
>> +  }
>> +
>> +  // printf("%s\n", str) --> puts(str)
>> +  if (FormatStr == "%s\n" && CI->getNumArgOperands() > 1 &&
>> +      CI->getArgOperand(1)->getType()->isPointerTy()) {
>> +    return EmitPutS(CI->getArgOperand(1), B, DL, TLI);
>>    }
>> +  return nullptr;
>> +}
>>
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // Require one fixed pointer argument and an integer/void result.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() < 1 || !FT->getParamType(0)->isPointerTy() ||
>> -        !(FT->getReturnType()->isIntegerTy() ||
>> -          FT->getReturnType()->isVoidTy()))
>> -      return nullptr;
>> +Value *LibCallSimplifier::optimizePrintF(CallInst *CI, IRBuilder<> &B) {
>>
>> -    if (Value *V = optimizeFixedFormatString(Callee, CI, B)) {
>> -      return V;
>> -    }
>> +  Function *Callee = CI->getCalledFunction();
>> +  // Require one fixed pointer argument and an integer/void result.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() < 1 || !FT->getParamType(0)->isPointerTy() ||
>> +      !(FT->getReturnType()->isIntegerTy() ||
>> FT->getReturnType()->isVoidTy()))
>> +    return nullptr;
>> +
>> +  if (Value *V = optimizePrintFString(CI, B)) {
>> +    return V;
>> +  }
>>
>> -    // printf(format, ...) -> iprintf(format, ...) if no floating point
>> -    // arguments.
>> -    if (TLI->has(LibFunc::iprintf) && !callHasFloatingPointArgument(CI))
>> {
>> -      Module *M = B.GetInsertBlock()->getParent()->getParent();
>> -      Constant *IPrintFFn =
>> +  // printf(format, ...) -> iprintf(format, ...) if no floating point
>> +  // arguments.
>> +  if (TLI->has(LibFunc::iprintf) && !callHasFloatingPointArgument(CI)) {
>> +    Module *M = B.GetInsertBlock()->getParent()->getParent();
>> +    Constant *IPrintFFn =
>>          M->getOrInsertFunction("iprintf", FT, Callee->getAttributes());
>> -      CallInst *New = cast<CallInst>(CI->clone());
>> -      New->setCalledFunction(IPrintFFn);
>> -      B.Insert(New);
>> -      return New;
>> -    }
>> -    return nullptr;
>> +    CallInst *New = cast<CallInst>(CI->clone());
>> +    New->setCalledFunction(IPrintFFn);
>> +    B.Insert(New);
>> +    return New;
>>    }
>> -};
>> +  return nullptr;
>> +}
>>
>> -struct SPrintFOpt : public LibCallOptimization {
>> -  Value *OptimizeFixedFormatString(Function *Callee, CallInst *CI,
>> -                                   IRBuilder<> &B) {
>> -    // Check for a fixed format string.
>> -    StringRef FormatStr;
>> -    if (!getConstantStringInfo(CI->getArgOperand(1), FormatStr))
>> -      return nullptr;
>> -
>> -    // If we just have a format string (nothing else crazy) transform it.
>> -    if (CI->getNumArgOperands() == 2) {
>> -      // Make sure there's no % in the constant array.  We could try to
>> handle
>> -      // %% -> % in the future if we cared.
>> -      for (unsigned i = 0, e = FormatStr.size(); i != e; ++i)
>> -        if (FormatStr[i] == '%')
>> -          return nullptr; // we found a format specifier, bail out.
>> -
>> -      // These optimizations require DataLayout.
>> -      if (!DL) return nullptr;
>> -
>> -      // sprintf(str, fmt) -> llvm.memcpy(str, fmt, strlen(fmt)+1, 1)
>> -      B.CreateMemCpy(CI->getArgOperand(0), CI->getArgOperand(1),
>> -                     ConstantInt::get(DL->getIntPtrType(*Context), //
>> Copy the
>> -                                      FormatStr.size() + 1), 1);   //
>> nul byte.
>> -      return ConstantInt::get(CI->getType(), FormatStr.size());
>> -    }
>> +Value *LibCallSimplifier::optimizeSPrintFString(CallInst *CI,
>> IRBuilder<> &B) {
>> +  // Check for a fixed format string.
>> +  StringRef FormatStr;
>> +  if (!getConstantStringInfo(CI->getArgOperand(1), FormatStr))
>> +    return nullptr;
>>
>> -    // The remaining optimizations require the format string to be "%s"
>> or "%c"
>> -    // and have an extra operand.
>> -    if (FormatStr.size() != 2 || FormatStr[0] != '%' ||
>> -        CI->getNumArgOperands() < 3)
>> -      return nullptr;
>> -
>> -    // Decode the second character of the format string.
>> -    if (FormatStr[1] == 'c') {
>> -      // sprintf(dst, "%c", chr) --> *(i8*)dst = chr; *((i8*)dst+1) = 0
>> -      if (!CI->getArgOperand(2)->getType()->isIntegerTy()) return
>> nullptr;
>> -      Value *V = B.CreateTrunc(CI->getArgOperand(2), B.getInt8Ty(),
>> "char");
>> -      Value *Ptr = CastToCStr(CI->getArgOperand(0), B);
>> -      B.CreateStore(V, Ptr);
>> -      Ptr = B.CreateGEP(Ptr, B.getInt32(1), "nul");
>> -      B.CreateStore(B.getInt8(0), Ptr);
>> +  // If we just have a format string (nothing else crazy) transform it.
>> +  if (CI->getNumArgOperands() == 2) {
>> +    // Make sure there's no % in the constant array.  We could try to
>> handle
>> +    // %% -> % in the future if we cared.
>> +    for (unsigned i = 0, e = FormatStr.size(); i != e; ++i)
>> +      if (FormatStr[i] == '%')
>> +        return nullptr; // we found a format specifier, bail out.
>>
>> -      return ConstantInt::get(CI->getType(), 1);
>> -    }
>> +    // These optimizations require DataLayout.
>> +    if (!DL)
>> +      return nullptr;
>>
>> -    if (FormatStr[1] == 's') {
>> -      // These optimizations require DataLayout.
>> -      if (!DL) return nullptr;
>> +    // sprintf(str, fmt) -> llvm.memcpy(str, fmt, strlen(fmt)+1, 1)
>> +    B.CreateMemCpy(
>> +        CI->getArgOperand(0), CI->getArgOperand(1),
>> +        ConstantInt::get(DL->getIntPtrType(CI->getContext()),
>> +                         FormatStr.size() + 1),
>> +        1); // Copy the null byte.
>> +    return ConstantInt::get(CI->getType(), FormatStr.size());
>> +  }
>>
>> -      // sprintf(dest, "%s", str) -> llvm.memcpy(dest, str,
>> strlen(str)+1, 1)
>> -      if (!CI->getArgOperand(2)->getType()->isPointerTy()) return
>> nullptr;
>> +  // The remaining optimizations require the format string to be "%s" or
>> "%c"
>> +  // and have an extra operand.
>> +  if (FormatStr.size() != 2 || FormatStr[0] != '%' ||
>> +      CI->getNumArgOperands() < 3)
>> +    return nullptr;
>>
>> -      Value *Len = EmitStrLen(CI->getArgOperand(2), B, DL, TLI);
>> -      if (!Len)
>> -        return nullptr;
>> -      Value *IncLen = B.CreateAdd(Len,
>> -                                  ConstantInt::get(Len->getType(), 1),
>> -                                  "leninc");
>> -      B.CreateMemCpy(CI->getArgOperand(0), CI->getArgOperand(2), IncLen,
>> 1);
>> +  // Decode the second character of the format string.
>> +  if (FormatStr[1] == 'c') {
>> +    // sprintf(dst, "%c", chr) --> *(i8*)dst = chr; *((i8*)dst+1) = 0
>> +    if (!CI->getArgOperand(2)->getType()->isIntegerTy())
>> +      return nullptr;
>> +    Value *V = B.CreateTrunc(CI->getArgOperand(2), B.getInt8Ty(),
>> "char");
>> +    Value *Ptr = CastToCStr(CI->getArgOperand(0), B);
>> +    B.CreateStore(V, Ptr);
>> +    Ptr = B.CreateGEP(Ptr, B.getInt32(1), "nul");
>> +    B.CreateStore(B.getInt8(0), Ptr);
>>
>> -      // The sprintf result is the unincremented number of bytes in the
>> string.
>> -      return B.CreateIntCast(Len, CI->getType(), false);
>> -    }
>> -    return nullptr;
>> +    return ConstantInt::get(CI->getType(), 1);
>>    }
>>
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // Require two fixed pointer arguments and an integer result.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
>> -        !FT->getParamType(1)->isPointerTy() ||
>> -        !FT->getReturnType()->isIntegerTy())
>> +  if (FormatStr[1] == 's') {
>> +    // These optimizations require DataLayout.
>> +    if (!DL)
>>        return nullptr;
>>
>> -    if (Value *V = OptimizeFixedFormatString(Callee, CI, B)) {
>> -      return V;
>> -    }
>> +    // sprintf(dest, "%s", str) -> llvm.memcpy(dest, str, strlen(str)+1,
>> 1)
>> +    if (!CI->getArgOperand(2)->getType()->isPointerTy())
>> +      return nullptr;
>>
>> -    // sprintf(str, format, ...) -> siprintf(str, format, ...) if no
>> floating
>> -    // point arguments.
>> -    if (TLI->has(LibFunc::siprintf) &&
>> !callHasFloatingPointArgument(CI)) {
>> -      Module *M = B.GetInsertBlock()->getParent()->getParent();
>> -      Constant *SIPrintFFn =
>> +    Value *Len = EmitStrLen(CI->getArgOperand(2), B, DL, TLI);
>> +    if (!Len)
>> +      return nullptr;
>> +    Value *IncLen =
>> +        B.CreateAdd(Len, ConstantInt::get(Len->getType(), 1), "leninc");
>> +    B.CreateMemCpy(CI->getArgOperand(0), CI->getArgOperand(2), IncLen,
>> 1);
>> +
>> +    // The sprintf result is the unincremented number of bytes in the
>> string.
>> +    return B.CreateIntCast(Len, CI->getType(), false);
>> +  }
>> +  return nullptr;
>> +}
>> +
>> +Value *LibCallSimplifier::optimizeSPrintF(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // Require two fixed pointer arguments and an integer result.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
>> +      !FT->getParamType(1)->isPointerTy() ||
>> +      !FT->getReturnType()->isIntegerTy())
>> +    return nullptr;
>> +
>> +  if (Value *V = optimizeSPrintFString(CI, B)) {
>> +    return V;
>> +  }
>> +
>> +  // sprintf(str, format, ...) -> siprintf(str, format, ...) if no
>> floating
>> +  // point arguments.
>> +  if (TLI->has(LibFunc::siprintf) && !callHasFloatingPointArgument(CI)) {
>> +    Module *M = B.GetInsertBlock()->getParent()->getParent();
>> +    Constant *SIPrintFFn =
>>          M->getOrInsertFunction("siprintf", FT, Callee->getAttributes());
>> -      CallInst *New = cast<CallInst>(CI->clone());
>> -      New->setCalledFunction(SIPrintFFn);
>> -      B.Insert(New);
>> -      return New;
>> -    }
>> -    return nullptr;
>> +    CallInst *New = cast<CallInst>(CI->clone());
>> +    New->setCalledFunction(SIPrintFFn);
>> +    B.Insert(New);
>> +    return New;
>>    }
>> -};
>> +  return nullptr;
>> +}
>>
>> -struct FPrintFOpt : public LibCallOptimization {
>> -  Value *optimizeFixedFormatString(Function *Callee, CallInst *CI,
>> -                                   IRBuilder<> &B) {
>> -    ErrorReportingOpt ER(/* StreamArg = */ 0);
>> -    (void) ER.callOptimizer(Callee, CI, B);
>> -
>> -    // All the optimizations depend on the format string.
>> -    StringRef FormatStr;
>> -    if (!getConstantStringInfo(CI->getArgOperand(1), FormatStr))
>> -      return nullptr;
>> -
>> -    // Do not do any of the following transformations if the fprintf
>> return
>> -    // value is used, in general the fprintf return value is not
>> compatible
>> -    // with fwrite(), fputc() or fputs().
>> -    if (!CI->use_empty())
>> -      return nullptr;
>> -
>> -    // fprintf(F, "foo") --> fwrite("foo", 3, 1, F)
>> -    if (CI->getNumArgOperands() == 2) {
>> -      for (unsigned i = 0, e = FormatStr.size(); i != e; ++i)
>> -        if (FormatStr[i] == '%')  // Could handle %% -> % if we cared.
>> -          return nullptr; // We found a format specifier.
>> -
>> -      // These optimizations require DataLayout.
>> -      if (!DL) return nullptr;
>> -
>> -      return EmitFWrite(CI->getArgOperand(1),
>> -                        ConstantInt::get(DL->getIntPtrType(*Context),
>> -                                         FormatStr.size()),
>> -                        CI->getArgOperand(0), B, DL, TLI);
>> -    }
>> +Value *LibCallSimplifier::optimizeFPrintFString(CallInst *CI,
>> IRBuilder<> &B) {
>> +  optimizeErrorReporting(CI, B, 0);
>> +
>> +  // All the optimizations depend on the format string.
>> +  StringRef FormatStr;
>> +  if (!getConstantStringInfo(CI->getArgOperand(1), FormatStr))
>> +    return nullptr;
>>
>> -    // The remaining optimizations require the format string to be "%s"
>> or "%c"
>> -    // and have an extra operand.
>> -    if (FormatStr.size() != 2 || FormatStr[0] != '%' ||
>> -        CI->getNumArgOperands() < 3)
>> +  // Do not do any of the following transformations if the fprintf return
>> +  // value is used, in general the fprintf return value is not compatible
>> +  // with fwrite(), fputc() or fputs().
>> +  if (!CI->use_empty())
>> +    return nullptr;
>> +
>> +  // fprintf(F, "foo") --> fwrite("foo", 3, 1, F)
>> +  if (CI->getNumArgOperands() == 2) {
>> +    for (unsigned i = 0, e = FormatStr.size(); i != e; ++i)
>> +      if (FormatStr[i] == '%') // Could handle %% -> % if we cared.
>> +        return nullptr;        // We found a format specifier.
>> +
>> +    // These optimizations require DataLayout.
>> +    if (!DL)
>>        return nullptr;
>>
>> -    // Decode the second character of the format string.
>> -    if (FormatStr[1] == 'c') {
>> -      // fprintf(F, "%c", chr) --> fputc(chr, F)
>> -      if (!CI->getArgOperand(2)->getType()->isIntegerTy()) return
>> nullptr;
>> -      return EmitFPutC(CI->getArgOperand(2), CI->getArgOperand(0), B,
>> DL, TLI);
>> -    }
>> +    return EmitFWrite(
>> +        CI->getArgOperand(1),
>> +        ConstantInt::get(DL->getIntPtrType(CI->getContext()),
>> FormatStr.size()),
>> +        CI->getArgOperand(0), B, DL, TLI);
>> +  }
>>
>> -    if (FormatStr[1] == 's') {
>> -      // fprintf(F, "%s", str) --> fputs(str, F)
>> -      if (!CI->getArgOperand(2)->getType()->isPointerTy())
>> -        return nullptr;
>> -      return EmitFPutS(CI->getArgOperand(2), CI->getArgOperand(0), B,
>> DL, TLI);
>> -    }
>> +  // The remaining optimizations require the format string to be "%s" or
>> "%c"
>> +  // and have an extra operand.
>> +  if (FormatStr.size() != 2 || FormatStr[0] != '%' ||
>> +      CI->getNumArgOperands() < 3)
>>      return nullptr;
>> -  }
>>
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // Require two fixed paramters as pointers and integer result.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
>> -        !FT->getParamType(1)->isPointerTy() ||
>> -        !FT->getReturnType()->isIntegerTy())
>> +  // Decode the second character of the format string.
>> +  if (FormatStr[1] == 'c') {
>> +    // fprintf(F, "%c", chr) --> fputc(chr, F)
>> +    if (!CI->getArgOperand(2)->getType()->isIntegerTy())
>>        return nullptr;
>> +    return EmitFPutC(CI->getArgOperand(2), CI->getArgOperand(0), B, DL,
>> TLI);
>> +  }
>>
>> -    if (Value *V = optimizeFixedFormatString(Callee, CI, B)) {
>> -      return V;
>> -    }
>> +  if (FormatStr[1] == 's') {
>> +    // fprintf(F, "%s", str) --> fputs(str, F)
>> +    if (!CI->getArgOperand(2)->getType()->isPointerTy())
>> +      return nullptr;
>> +    return EmitFPutS(CI->getArgOperand(2), CI->getArgOperand(0), B, DL,
>> TLI);
>> +  }
>> +  return nullptr;
>> +}
>>
>> -    // fprintf(stream, format, ...) -> fiprintf(stream, format, ...) if
>> no
>> -    // floating point arguments.
>> -    if (TLI->has(LibFunc::fiprintf) &&
>> !callHasFloatingPointArgument(CI)) {
>> -      Module *M = B.GetInsertBlock()->getParent()->getParent();
>> -      Constant *FIPrintFFn =
>> +Value *LibCallSimplifier::optimizeFPrintF(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // Require two fixed paramters as pointers and integer result.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
>> +      !FT->getParamType(1)->isPointerTy() ||
>> +      !FT->getReturnType()->isIntegerTy())
>> +    return nullptr;
>> +
>> +  if (Value *V = optimizeFPrintFString(CI, B)) {
>> +    return V;
>> +  }
>> +
>> +  // fprintf(stream, format, ...) -> fiprintf(stream, format, ...) if no
>> +  // floating point arguments.
>> +  if (TLI->has(LibFunc::fiprintf) && !callHasFloatingPointArgument(CI)) {
>> +    Module *M = B.GetInsertBlock()->getParent()->getParent();
>> +    Constant *FIPrintFFn =
>>          M->getOrInsertFunction("fiprintf", FT, Callee->getAttributes());
>> -      CallInst *New = cast<CallInst>(CI->clone());
>> -      New->setCalledFunction(FIPrintFFn);
>> -      B.Insert(New);
>> -      return New;
>> -    }
>> -    return nullptr;
>> +    CallInst *New = cast<CallInst>(CI->clone());
>> +    New->setCalledFunction(FIPrintFFn);
>> +    B.Insert(New);
>> +    return New;
>>    }
>> -};
>> +  return nullptr;
>> +}
>>
>> -struct FWriteOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    ErrorReportingOpt ER(/* StreamArg = */ 3);
>> -    (void) ER.callOptimizer(Callee, CI, B);
>> -
>> -    // Require a pointer, an integer, an integer, a pointer, returning
>> integer.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 4 || !FT->getParamType(0)->isPointerTy() ||
>> -        !FT->getParamType(1)->isIntegerTy() ||
>> -        !FT->getParamType(2)->isIntegerTy() ||
>> -        !FT->getParamType(3)->isPointerTy() ||
>> -        !FT->getReturnType()->isIntegerTy())
>> -      return nullptr;
>> -
>> -    // Get the element size and count.
>> -    ConstantInt *SizeC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
>> -    ConstantInt *CountC = dyn_cast<ConstantInt>(CI->getArgOperand(2));
>> -    if (!SizeC || !CountC) return nullptr;
>> -    uint64_t Bytes = SizeC->getZExtValue()*CountC->getZExtValue();
>> -
>> -    // If this is writing zero records, remove the call (it's a noop).
>> -    if (Bytes == 0)
>> -      return ConstantInt::get(CI->getType(), 0);
>> -
>> -    // If this is writing one byte, turn it into fputc.
>> -    // This optimisation is only valid, if the return value is unused.
>> -    if (Bytes == 1 && CI->use_empty()) {  // fwrite(S,1,1,F) ->
>> fputc(S[0],F)
>> -      Value *Char = B.CreateLoad(CastToCStr(CI->getArgOperand(0), B),
>> "char");
>> -      Value *NewCI = EmitFPutC(Char, CI->getArgOperand(3), B, DL, TLI);
>> -      return NewCI ? ConstantInt::get(CI->getType(), 1) : nullptr;
>> -    }
>> +Value *LibCallSimplifier::optimizeFWrite(CallInst *CI, IRBuilder<> &B) {
>> +  optimizeErrorReporting(CI, B, 3);
>>
>> -    return nullptr;
>> +  Function *Callee = CI->getCalledFunction();
>> +  // Require a pointer, an integer, an integer, a pointer, returning
>> integer.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 4 || !FT->getParamType(0)->isPointerTy() ||
>> +      !FT->getParamType(1)->isIntegerTy() ||
>> +      !FT->getParamType(2)->isIntegerTy() ||
>> +      !FT->getParamType(3)->isPointerTy() ||
>> +      !FT->getReturnType()->isIntegerTy())
>> +    return nullptr;
>> +
>> +  // Get the element size and count.
>> +  ConstantInt *SizeC = dyn_cast<ConstantInt>(CI->getArgOperand(1));
>> +  ConstantInt *CountC = dyn_cast<ConstantInt>(CI->getArgOperand(2));
>> +  if (!SizeC || !CountC)
>> +    return nullptr;
>> +  uint64_t Bytes = SizeC->getZExtValue() * CountC->getZExtValue();
>> +
>> +  // If this is writing zero records, remove the call (it's a noop).
>> +  if (Bytes == 0)
>> +    return ConstantInt::get(CI->getType(), 0);
>> +
>> +  // If this is writing one byte, turn it into fputc.
>> +  // This optimisation is only valid, if the return value is unused.
>> +  if (Bytes == 1 && CI->use_empty()) { // fwrite(S,1,1,F) ->
>> fputc(S[0],F)
>> +    Value *Char = B.CreateLoad(CastToCStr(CI->getArgOperand(0), B),
>> "char");
>> +    Value *NewCI = EmitFPutC(Char, CI->getArgOperand(3), B, DL, TLI);
>> +    return NewCI ? ConstantInt::get(CI->getType(), 1) : nullptr;
>>    }
>> -};
>>
>> -struct FPutsOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    ErrorReportingOpt ER(/* StreamArg = */ 1);
>> -    (void) ER.callOptimizer(Callee, CI, B);
>> +  return nullptr;
>> +}
>>
>> -    // These optimizations require DataLayout.
>> -    if (!DL) return nullptr;
>> +Value *LibCallSimplifier::optimizeFPuts(CallInst *CI, IRBuilder<> &B) {
>> +  optimizeErrorReporting(CI, B, 1);
>>
>> -    // Require two pointers.  Also, we can't optimize if return value is
>> used.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
>> -        !FT->getParamType(1)->isPointerTy() ||
>> -        !CI->use_empty())
>> -      return nullptr;
>> -
>> -    // fputs(s,F) --> fwrite(s,1,strlen(s),F)
>> -    uint64_t Len = GetStringLength(CI->getArgOperand(0));
>> -    if (!Len) return nullptr;
>> -    // Known to have no uses (see above).
>> -    return EmitFWrite(CI->getArgOperand(0),
>> -                      ConstantInt::get(DL->getIntPtrType(*Context),
>> Len-1),
>> -                      CI->getArgOperand(1), B, DL, TLI);
>> -  }
>> -};
>> -
>> -struct PutsOpt : public LibCallOptimization {
>> -  Value *callOptimizer(Function *Callee, CallInst *CI,
>> -                       IRBuilder<> &B) override {
>> -    // Require one fixed pointer argument and an integer/void result.
>> -    FunctionType *FT = Callee->getFunctionType();
>> -    if (FT->getNumParams() < 1 || !FT->getParamType(0)->isPointerTy() ||
>> -        !(FT->getReturnType()->isIntegerTy() ||
>> -          FT->getReturnType()->isVoidTy()))
>> -      return nullptr;
>> -
>> -    // Check for a constant string.
>> -    StringRef Str;
>> -    if (!getConstantStringInfo(CI->getArgOperand(0), Str))
>> -      return nullptr;
>> -
>> -    if (Str.empty() && CI->use_empty()) {
>> -      // puts("") -> putchar('\n')
>> -      Value *Res = EmitPutChar(B.getInt32('\n'), B, DL, TLI);
>> -      if (CI->use_empty() || !Res) return Res;
>> -      return B.CreateIntCast(Res, CI->getType(), true);
>> -    }
>> +  Function *Callee = CI->getCalledFunction();
>>
>> +  // These optimizations require DataLayout.
>> +  if (!DL)
>>      return nullptr;
>> -  }
>> -};
>>
>> -} // End anonymous namespace.
>> +  // Require two pointers.  Also, we can't optimize if return value is
>> used.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
>> +      !FT->getParamType(1)->isPointerTy() || !CI->use_empty())
>> +    return nullptr;
>>
>> -namespace llvm {
>> +  // fputs(s,F) --> fwrite(s,1,strlen(s),F)
>> +  uint64_t Len = GetStringLength(CI->getArgOperand(0));
>> +  if (!Len)
>> +    return nullptr;
>>
>> -class LibCallSimplifierImpl {
>> -  const DataLayout *DL;
>> -  const TargetLibraryInfo *TLI;
>> -  const LibCallSimplifier *LCS;
>> -  bool UnsafeFPShrink;
>> -
>> -  // Math library call optimizations.
>> -  CosOpt Cos;
>> -  PowOpt Pow;
>> -  Exp2Opt Exp2;
>> -public:
>> -  LibCallSimplifierImpl(const DataLayout *DL, const TargetLibraryInfo
>> *TLI,
>> -                        const LibCallSimplifier *LCS,
>> -                        bool UnsafeFPShrink = false)
>> -    : Cos(UnsafeFPShrink), Pow(UnsafeFPShrink), Exp2(UnsafeFPShrink) {
>> -    this->DL = DL;
>> -    this->TLI = TLI;
>> -    this->LCS = LCS;
>> -    this->UnsafeFPShrink = UnsafeFPShrink;
>> -  }
>> -
>> -  Value *optimizeCall(CallInst *CI);
>> -  LibCallOptimization *lookupOptimization(CallInst *CI);
>> -  bool hasFloatVersion(StringRef FuncName);
>> -};
>> +  // Known to have no uses (see above).
>> +  return EmitFWrite(
>> +      CI->getArgOperand(0),
>> +      ConstantInt::get(DL->getIntPtrType(CI->getContext()), Len - 1),
>> +      CI->getArgOperand(1), B, DL, TLI);
>> +}
>>
>> -bool LibCallSimplifierImpl::hasFloatVersion(StringRef FuncName) {
>> +Value *LibCallSimplifier::optimizePuts(CallInst *CI, IRBuilder<> &B) {
>> +  Function *Callee = CI->getCalledFunction();
>> +  // Require one fixed pointer argument and an integer/void result.
>> +  FunctionType *FT = Callee->getFunctionType();
>> +  if (FT->getNumParams() < 1 || !FT->getParamType(0)->isPointerTy() ||
>> +      !(FT->getReturnType()->isIntegerTy() ||
>> FT->getReturnType()->isVoidTy()))
>> +    return nullptr;
>> +
>> +  // Check for a constant string.
>> +  StringRef Str;
>> +  if (!getConstantStringInfo(CI->getArgOperand(0), Str))
>> +    return nullptr;
>> +
>> +  if (Str.empty() && CI->use_empty()) {
>> +    // puts("") -> putchar('\n')
>> +    Value *Res = EmitPutChar(B.getInt32('\n'), B, DL, TLI);
>> +    if (CI->use_empty() || !Res)
>> +      return Res;
>> +    return B.CreateIntCast(Res, CI->getType(), true);
>> +  }
>> +
>> +  return nullptr;
>> +}
>> +
>> +bool LibCallSimplifier::hasFloatVersion(StringRef FuncName) {
>>    LibFunc::Func Func;
>>    SmallString<20> FloatFuncName = FuncName;
>>    FloatFuncName += 'f';
>> @@ -2048,263 +1874,204 @@ bool LibCallSimplifierImpl::hasFloatVers
>>    return false;
>>  }
>>
>> -// Fortified library call optimizations.
>> -static MemCpyChkOpt MemCpyChk;
>> -static MemMoveChkOpt MemMoveChk;
>> -static MemSetChkOpt MemSetChk;
>> -static StrCpyChkOpt StrCpyChk;
>> -static StpCpyChkOpt StpCpyChk;
>> -static StrNCpyChkOpt StrNCpyChk;
>> -
>> -// String library call optimizations.
>> -static StrCatOpt StrCat;
>> -static StrNCatOpt StrNCat;
>> -static StrChrOpt StrChr;
>> -static StrRChrOpt StrRChr;
>> -static StrCmpOpt StrCmp;
>> -static StrNCmpOpt StrNCmp;
>> -static StrCpyOpt StrCpy;
>> -static StpCpyOpt StpCpy;
>> -static StrNCpyOpt StrNCpy;
>> -static StrLenOpt StrLen;
>> -static StrPBrkOpt StrPBrk;
>> -static StrToOpt StrTo;
>> -static StrSpnOpt StrSpn;
>> -static StrCSpnOpt StrCSpn;
>> -static StrStrOpt StrStr;
>> -
>> -// Memory library call optimizations.
>> -static MemCmpOpt MemCmp;
>> -static MemCpyOpt MemCpy;
>> -static MemMoveOpt MemMove;
>> -static MemSetOpt MemSet;
>> -
>> -// Math library call optimizations.
>> -static UnaryDoubleFPOpt UnaryDoubleFP(false);
>> -static BinaryDoubleFPOpt BinaryDoubleFP(false);
>> -static UnaryDoubleFPOpt UnsafeUnaryDoubleFP(true);
>> -static SinCosPiOpt SinCosPi;
>> -
>> -  // Integer library call optimizations.
>> -static FFSOpt FFS;
>> -static AbsOpt Abs;
>> -static IsDigitOpt IsDigit;
>> -static IsAsciiOpt IsAscii;
>> -static ToAsciiOpt ToAscii;
>> -
>> -// Formatting and IO library call optimizations.
>> -static ErrorReportingOpt ErrorReporting;
>> -static ErrorReportingOpt ErrorReporting0(0);
>> -static ErrorReportingOpt ErrorReporting1(1);
>> -static PrintFOpt PrintF;
>> -static SPrintFOpt SPrintF;
>> -static FPrintFOpt FPrintF;
>> -static FWriteOpt FWrite;
>> -static FPutsOpt FPuts;
>> -static PutsOpt Puts;
>> +Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
>> +  if (CI->isNoBuiltin())
>> +    return nullptr;
>>
>> -LibCallOptimization *LibCallSimplifierImpl::lookupOptimization(CallInst
>> *CI) {
>>    LibFunc::Func Func;
>>    Function *Callee = CI->getCalledFunction();
>>    StringRef FuncName = Callee->getName();
>> +  IRBuilder<> Builder(CI);
>> +  bool isCallingConvC = CI->getCallingConv() == llvm::CallingConv::C;
>>
>>    // Next check for intrinsics.
>>    if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) {
>> +    if (!isCallingConvC)
>> +      return nullptr;
>>      switch (II->getIntrinsicID()) {
>>      case Intrinsic::pow:
>> -       return &Pow;
>> +      return optimizePow(CI, Builder);
>>      case Intrinsic::exp2:
>> -       return &Exp2;
>> +      return optimizeExp2(CI, Builder);
>>      default:
>> -       return nullptr;
>> +      return nullptr;
>>      }
>>    }
>>
>>    // Then check for known library functions.
>>    if (TLI->getLibFunc(FuncName, Func) && TLI->has(Func)) {
>> +    // We never change the calling convention.
>> +    if (!ignoreCallingConv(Func) && !isCallingConvC)
>> +      return nullptr;
>>      switch (Func) {
>> -      case LibFunc::strcat:
>> -        return &StrCat;
>> -      case LibFunc::strncat:
>> -        return &StrNCat;
>> -      case LibFunc::strchr:
>> -        return &StrChr;
>> -      case LibFunc::strrchr:
>> -        return &StrRChr;
>> -      case LibFunc::strcmp:
>> -        return &StrCmp;
>> -      case LibFunc::strncmp:
>> -        return &StrNCmp;
>> -      case LibFunc::strcpy:
>> -        return &StrCpy;
>> -      case LibFunc::stpcpy:
>> -        return &StpCpy;
>> -      case LibFunc::strncpy:
>> -        return &StrNCpy;
>> -      case LibFunc::strlen:
>> -        return &StrLen;
>> -      case LibFunc::strpbrk:
>> -        return &StrPBrk;
>> -      case LibFunc::strtol:
>> -      case LibFunc::strtod:
>> -      case LibFunc::strtof:
>> -      case LibFunc::strtoul:
>> -      case LibFunc::strtoll:
>> -      case LibFunc::strtold:
>> -      case LibFunc::strtoull:
>> -        return &StrTo;
>> -      case LibFunc::strspn:
>> -        return &StrSpn;
>> -      case LibFunc::strcspn:
>> -        return &StrCSpn;
>> -      case LibFunc::strstr:
>> -        return &StrStr;
>> -      case LibFunc::memcmp:
>> -        return &MemCmp;
>> -      case LibFunc::memcpy:
>> -        return &MemCpy;
>> -      case LibFunc::memmove:
>> -        return &MemMove;
>> -      case LibFunc::memset:
>> -        return &MemSet;
>> -      case LibFunc::cosf:
>> -      case LibFunc::cos:
>> -      case LibFunc::cosl:
>> -        return &Cos;
>> -      case LibFunc::sinpif:
>> -      case LibFunc::sinpi:
>> -      case LibFunc::cospif:
>> -      case LibFunc::cospi:
>> -        return &SinCosPi;
>> -      case LibFunc::powf:
>> -      case LibFunc::pow:
>> -      case LibFunc::powl:
>> -        return &Pow;
>> -      case LibFunc::exp2l:
>> -      case LibFunc::exp2:
>> -      case LibFunc::exp2f:
>> -        return &Exp2;
>> -      case LibFunc::ffs:
>> -      case LibFunc::ffsl:
>> -      case LibFunc::ffsll:
>> -        return &FFS;
>> -      case LibFunc::abs:
>> -      case LibFunc::labs:
>> -      case LibFunc::llabs:
>> -        return &Abs;
>> -      case LibFunc::isdigit:
>> -        return &IsDigit;
>> -      case LibFunc::isascii:
>> -        return &IsAscii;
>> -      case LibFunc::toascii:
>> -        return &ToAscii;
>> -      case LibFunc::printf:
>> -        return &PrintF;
>> -      case LibFunc::sprintf:
>> -        return &SPrintF;
>> -      case LibFunc::fprintf:
>> -        return &FPrintF;
>> -      case LibFunc::fwrite:
>> -        return &FWrite;
>> -      case LibFunc::fputs:
>> -        return &FPuts;
>> -      case LibFunc::puts:
>> -        return &Puts;
>> -      case LibFunc::perror:
>> -        return &ErrorReporting;
>> -      case LibFunc::vfprintf:
>> -      case LibFunc::fiprintf:
>> -        return &ErrorReporting0;
>> -      case LibFunc::fputc:
>> -        return &ErrorReporting1;
>> -      case LibFunc::ceil:
>> -      case LibFunc::fabs:
>> -      case LibFunc::floor:
>> -      case LibFunc::rint:
>> -      case LibFunc::round:
>> -      case LibFunc::nearbyint:
>> -      case LibFunc::trunc:
>> -        if (hasFloatVersion(FuncName))
>> -          return &UnaryDoubleFP;
>> -        return nullptr;
>> -      case LibFunc::acos:
>> -      case LibFunc::acosh:
>> -      case LibFunc::asin:
>> -      case LibFunc::asinh:
>> -      case LibFunc::atan:
>> -      case LibFunc::atanh:
>> -      case LibFunc::cbrt:
>> -      case LibFunc::cosh:
>> -      case LibFunc::exp:
>> -      case LibFunc::exp10:
>> -      case LibFunc::expm1:
>> -      case LibFunc::log:
>> -      case LibFunc::log10:
>> -      case LibFunc::log1p:
>> -      case LibFunc::log2:
>> -      case LibFunc::logb:
>> -      case LibFunc::sin:
>> -      case LibFunc::sinh:
>> -      case LibFunc::sqrt:
>> -      case LibFunc::tan:
>> -      case LibFunc::tanh:
>> -        if (UnsafeFPShrink && hasFloatVersion(FuncName))
>> -         return &UnsafeUnaryDoubleFP;
>> -        return nullptr;
>> -      case LibFunc::fmin:
>> -      case LibFunc::fmax:
>> -        if (hasFloatVersion(FuncName))
>> -          return &BinaryDoubleFP;
>> -        return nullptr;
>> -      case LibFunc::memcpy_chk:
>> -        return &MemCpyChk;
>> -      default:
>> -        return nullptr;
>> -      }
>> +    case LibFunc::strcat:
>> +      return optimizeStrCat(CI, Builder);
>> +    case LibFunc::strncat:
>> +      return optimizeStrNCat(CI, Builder);
>> +    case LibFunc::strchr:
>> +      return optimizeStrChr(CI, Builder);
>> +    case LibFunc::strrchr:
>> +      return optimizeStrRChr(CI, Builder);
>> +    case LibFunc::strcmp:
>> +      return optimizeStrCmp(CI, Builder);
>> +    case LibFunc::strncmp:
>> +      return optimizeStrNCmp(CI, Builder);
>> +    case LibFunc::strcpy:
>> +      return optimizeStrCpy(CI, Builder);
>> +    case LibFunc::stpcpy:
>> +      return optimizeStpCpy(CI, Builder);
>> +    case LibFunc::strncpy:
>> +      return optimizeStrNCpy(CI, Builder);
>> +    case LibFunc::strlen:
>> +      return optimizeStrLen(CI, Builder);
>> +    case LibFunc::strpbrk:
>> +      return optimizeStrPBrk(CI, Builder);
>> +    case LibFunc::strtol:
>> +    case LibFunc::strtod:
>> +    case LibFunc::strtof:
>> +    case LibFunc::strtoul:
>> +    case LibFunc::strtoll:
>> +    case LibFunc::strtold:
>> +    case LibFunc::strtoull:
>> +      return optimizeStrTo(CI, Builder);
>> +    case LibFunc::strspn:
>> +      return optimizeStrSpn(CI, Builder);
>> +    case LibFunc::strcspn:
>> +      return optimizeStrCSpn(CI, Builder);
>> +    case LibFunc::strstr:
>> +      return optimizeStrStr(CI, Builder);
>> +    case LibFunc::memcmp:
>> +      return optimizeMemCmp(CI, Builder);
>> +    case LibFunc::memcpy:
>> +      return optimizeMemCpy(CI, Builder);
>> +    case LibFunc::memmove:
>> +      return optimizeMemMove(CI, Builder);
>> +    case LibFunc::memset:
>> +      return optimizeMemSet(CI, Builder);
>> +    case LibFunc::cosf:
>> +    case LibFunc::cos:
>> +    case LibFunc::cosl:
>> +      return optimizeCos(CI, Builder);
>> +    case LibFunc::sinpif:
>> +    case LibFunc::sinpi:
>> +    case LibFunc::cospif:
>> +    case LibFunc::cospi:
>> +      return optimizeSinCosPi(CI, Builder);
>> +    case LibFunc::powf:
>> +    case LibFunc::pow:
>> +    case LibFunc::powl:
>> +      return optimizePow(CI, Builder);
>> +    case LibFunc::exp2l:
>> +    case LibFunc::exp2:
>> +    case LibFunc::exp2f:
>> +      return optimizeExp2(CI, Builder);
>> +    case LibFunc::ffs:
>> +    case LibFunc::ffsl:
>> +    case LibFunc::ffsll:
>> +      return optimizeFFS(CI, Builder);
>> +    case LibFunc::abs:
>> +    case LibFunc::labs:
>> +    case LibFunc::llabs:
>> +      return optimizeAbs(CI, Builder);
>> +    case LibFunc::isdigit:
>> +      return optimizeIsDigit(CI, Builder);
>> +    case LibFunc::isascii:
>> +      return optimizeIsAscii(CI, Builder);
>> +    case LibFunc::toascii:
>> +      return optimizeToAscii(CI, Builder);
>> +    case LibFunc::printf:
>> +      return optimizePrintF(CI, Builder);
>> +    case LibFunc::sprintf:
>> +      return optimizeSPrintF(CI, Builder);
>> +    case LibFunc::fprintf:
>> +      return optimizeFPrintF(CI, Builder);
>> +    case LibFunc::fwrite:
>> +      return optimizeFWrite(CI, Builder);
>> +    case LibFunc::fputs:
>> +      return optimizeFPuts(CI, Builder);
>> +    case LibFunc::puts:
>> +      return optimizePuts(CI, Builder);
>> +    case LibFunc::perror:
>> +      return optimizeErrorReporting(CI, Builder);
>> +    case LibFunc::vfprintf:
>> +    case LibFunc::fiprintf:
>> +      return optimizeErrorReporting(CI, Builder, 0);
>> +    case LibFunc::fputc:
>> +      return optimizeErrorReporting(CI, Builder, 1);
>> +    case LibFunc::ceil:
>> +    case LibFunc::fabs:
>> +    case LibFunc::floor:
>> +    case LibFunc::rint:
>> +    case LibFunc::round:
>> +    case LibFunc::nearbyint:
>> +    case LibFunc::trunc:
>> +      if (hasFloatVersion(FuncName))
>> +        return optimizeUnaryDoubleFP(CI, Builder, false);
>> +      return nullptr;
>> +    case LibFunc::acos:
>> +    case LibFunc::acosh:
>> +    case LibFunc::asin:
>> +    case LibFunc::asinh:
>> +    case LibFunc::atan:
>> +    case LibFunc::atanh:
>> +    case LibFunc::cbrt:
>> +    case LibFunc::cosh:
>> +    case LibFunc::exp:
>> +    case LibFunc::exp10:
>> +    case LibFunc::expm1:
>> +    case LibFunc::log:
>> +    case LibFunc::log10:
>> +    case LibFunc::log1p:
>> +    case LibFunc::log2:
>> +    case LibFunc::logb:
>> +    case LibFunc::sin:
>> +    case LibFunc::sinh:
>> +    case LibFunc::sqrt:
>> +    case LibFunc::tan:
>> +    case LibFunc::tanh:
>> +      if (UnsafeFPShrink && hasFloatVersion(FuncName))
>> +        return optimizeUnaryDoubleFP(CI, Builder, true);
>> +      return nullptr;
>> +    case LibFunc::fmin:
>> +    case LibFunc::fmax:
>> +      if (hasFloatVersion(FuncName))
>> +        return optimizeBinaryDoubleFP(CI, Builder);
>> +      return nullptr;
>> +    case LibFunc::memcpy_chk:
>> +      return optimizeMemCpyChk(CI, Builder);
>> +    default:
>> +      return nullptr;
>> +    }
>>    }
>>
>> +  if (!isCallingConvC)
>> +    return nullptr;
>> +
>>    // Finally check for fortified library calls.
>>    if (FuncName.endswith("_chk")) {
>>      if (FuncName == "__memmove_chk")
>> -      return &MemMoveChk;
>> +      return optimizeMemMoveChk(CI, Builder);
>>      else if (FuncName == "__memset_chk")
>> -      return &MemSetChk;
>> +      return optimizeMemSetChk(CI, Builder);
>>      else if (FuncName == "__strcpy_chk")
>> -      return &StrCpyChk;
>> +      return optimizeStrCpyChk(CI, Builder);
>>      else if (FuncName == "__stpcpy_chk")
>> -      return &StpCpyChk;
>> +      return optimizeStpCpyChk(CI, Builder);
>>      else if (FuncName == "__strncpy_chk")
>> -      return &StrNCpyChk;
>> +      return optimizeStrNCpyChk(CI, Builder);
>>      else if (FuncName == "__stpncpy_chk")
>> -      return &StrNCpyChk;
>> +      return optimizeStrNCpyChk(CI, Builder);
>>    }
>>
>>    return nullptr;
>> -
>> -}
>> -
>> -Value *LibCallSimplifierImpl::optimizeCall(CallInst *CI) {
>> -  LibCallOptimization *LCO = lookupOptimization(CI);
>> -  if (LCO) {
>> -    IRBuilder<> Builder(CI);
>> -    return LCO->optimizeCall(CI, DL, TLI, LCS, Builder);
>> -  }
>> -  return nullptr;
>>  }
>>
>>  LibCallSimplifier::LibCallSimplifier(const DataLayout *DL,
>>                                       const TargetLibraryInfo *TLI,
>> -                                     bool UnsafeFPShrink) {
>> -  Impl = new LibCallSimplifierImpl(DL, TLI, this, UnsafeFPShrink);
>> -}
>> -
>> -LibCallSimplifier::~LibCallSimplifier() {
>> -  delete Impl;
>> -}
>> -
>> -Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
>> -  if (CI->isNoBuiltin()) return nullptr;
>> -  return Impl->optimizeCall(CI);
>> +                                     bool UnsafeFPShrink) :
>> +                                     DL(DL),
>> +                                     TLI(TLI),
>> +                                     UnsafeFPShrink(UnsafeFPShrink) {
>>  }
>>
>>  void LibCallSimplifier::replaceAllUsesWith(Instruction *I, Value *With)
>> const {
>> @@ -2312,8 +2079,6 @@ void LibCallSimplifier::replaceAllUsesWi
>>    I->eraseFromParent();
>>  }
>>
>> -}
>> -
>>  // TODO:
>>  //   Additional cases that we need to add to this file:
>>  //
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140917/129b3eac/attachment.html>


More information about the llvm-commits mailing list