diff options
Diffstat (limited to 'lib/Transforms/Scalar/SimplifyLibCalls.cpp')
| -rw-r--r-- | lib/Transforms/Scalar/SimplifyLibCalls.cpp | 179 | 
1 files changed, 144 insertions, 35 deletions
diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 611505ef363a..f9b929c7e838 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -81,6 +81,11 @@ public:    Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len,                      unsigned Align, IRBuilder<> &B); +  /// EmitMemMove - Emit a call to the memmove function to the builder.  This +  /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. +  Value *EmitMemMove(Value *Dst, Value *Src, Value *Len, +		     unsigned Align, IRBuilder<> &B); +    /// EmitMemChr - Emit a call to the memchr function.  This assumes that Ptr is    /// a pointer, Val is an i32 value, and Len is an 'intptr_t' value.    Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B); @@ -160,6 +165,21 @@ Value *LibCallOptimization::EmitMemCpy(Value *Dst, Value *Src, Value *Len,                         ConstantInt::get(Type::getInt32Ty(*Context), Align));  } +/// EmitMemMOve - Emit a call to the memmove function to the builder.  This +/// always expects that the size has type 'intptr_t' and Dst/Src are pointers. +Value *LibCallOptimization::EmitMemMove(Value *Dst, Value *Src, Value *Len, +					unsigned Align, IRBuilder<> &B) { +  Module *M = Caller->getParent(); +  Intrinsic::ID IID = Intrinsic::memmove; +  const Type *Tys[1]; +  Tys[0] = TD->getIntPtrType(*Context); +  Value *MemMove = Intrinsic::getDeclaration(M, IID, Tys, 1); +  Value *D = CastToCStr(Dst, B); +  Value *S = CastToCStr(Src, B); +  Value *A = ConstantInt::get(Type::getInt32Ty(*Context), Align); +  return B.CreateCall4(MemMove, D, S, Len, A); +} +  /// EmitMemChr - Emit a call to the memchr function.  This assumes that Ptr is  /// a pointer, Val is an i32 value, and Len is an 'intptr_t' value.  Value *LibCallOptimization::EmitMemChr(Value *Ptr, Value *Val, @@ -512,27 +532,6 @@ static bool IsOnlyUsedInZeroEqualityComparison(Value *V) {  }  //===----------------------------------------------------------------------===// -// Miscellaneous LibCall/Intrinsic Optimizations -//===----------------------------------------------------------------------===// - -namespace { -struct SizeOpt : public LibCallOptimization { -  virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { -    // TODO: We can do more with this, but delaying to here should be no change -    // in behavior. -    ConstantInt *Const = dyn_cast<ConstantInt>(CI->getOperand(2)); -     -    if (!Const) return 0; -     -    if (Const->getZExtValue() < 2) -      return Constant::getAllOnesValue(Const->getType()); -    else -      return ConstantInt::get(Const->getType(), 0); -  } -}; -} - -//===----------------------------------------------------------------------===//  // String and Memory LibCall Optimizations  //===----------------------------------------------------------------------===// @@ -1010,16 +1009,7 @@ struct MemMoveOpt : public LibCallOptimization {        return 0;      // memmove(x, y, n) -> llvm.memmove(x, y, n, 1) -    Module *M = Caller->getParent(); -    Intrinsic::ID IID = Intrinsic::memmove; -    const Type *Tys[1]; -    Tys[0] = TD->getIntPtrType(*Context); -    Value *MemMove = Intrinsic::getDeclaration(M, IID, Tys, 1); -    Value *Dst = CastToCStr(CI->getOperand(1), B); -    Value *Src = CastToCStr(CI->getOperand(2), B); -    Value *Size = CI->getOperand(3); -    Value *Align = ConstantInt::get(Type::getInt32Ty(*Context), 1); -    B.CreateCall4(MemMove, Dst, Src, Size, Align); +    EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), 1, B);      return CI->getOperand(1);    }  }; @@ -1048,6 +1038,118 @@ struct MemSetOpt : public LibCallOptimization {  };  //===----------------------------------------------------------------------===// +// Object Size Checking Optimizations +//===----------------------------------------------------------------------===// + +//===---------------------------------------===// +// 'object size' +namespace { +struct SizeOpt : public LibCallOptimization { +  virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { +    // TODO: We can do more with this, but delaying to here should be no change +    // in behavior. +    ConstantInt *Const = dyn_cast<ConstantInt>(CI->getOperand(2)); + +    if (!Const) return 0; + +    const Type *Ty = Callee->getFunctionType()->getReturnType(); + +    if (Const->getZExtValue() < 2) +      return Constant::getAllOnesValue(Ty); +    else +      return ConstantInt::get(Ty, 0); +  } +}; +} + +//===---------------------------------------===// +// 'memcpy_chk' Optimizations + +struct MemCpyChkOpt : public LibCallOptimization { +  virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { +    // These optimizations require TargetData. +    if (!TD) return 0; + +    const FunctionType *FT = Callee->getFunctionType(); +    if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || +        !isa<PointerType>(FT->getParamType(0)) || +        !isa<PointerType>(FT->getParamType(1)) || +	!isa<IntegerType>(FT->getParamType(3)) || +	FT->getParamType(2) != TD->getIntPtrType(*Context)) +      return 0; + +    ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); +    if (!SizeCI) +      return 0; +    if (SizeCI->isAllOnesValue()) { +      EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), 1, B); +      return CI->getOperand(1); +    } + +    return 0; +  } +}; + +//===---------------------------------------===// +// 'memset_chk' Optimizations + +struct MemSetChkOpt : public LibCallOptimization { +  virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { +    // These optimizations require TargetData. +    if (!TD) return 0; + +    const FunctionType *FT = Callee->getFunctionType(); +    if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || +        !isa<PointerType>(FT->getParamType(0)) || +        !isa<IntegerType>(FT->getParamType(1)) || +	!isa<IntegerType>(FT->getParamType(3)) || +        FT->getParamType(2) != TD->getIntPtrType(*Context)) +      return 0; + +    ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); +    if (!SizeCI) +      return 0; +    if (SizeCI->isAllOnesValue()) { +      Value *Val = B.CreateIntCast(CI->getOperand(2), Type::getInt8Ty(*Context), +				   false); +      EmitMemSet(CI->getOperand(1), Val,  CI->getOperand(3), B); +      return CI->getOperand(1); +    } + +    return 0; +  } +}; + +//===---------------------------------------===// +// 'memmove_chk' Optimizations + +struct MemMoveChkOpt : public LibCallOptimization { +  virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { +    // These optimizations require TargetData. +    if (!TD) return 0; + +    const FunctionType *FT = Callee->getFunctionType(); +    if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || +        !isa<PointerType>(FT->getParamType(0)) || +        !isa<PointerType>(FT->getParamType(1)) || +	!isa<IntegerType>(FT->getParamType(3)) || +        FT->getParamType(2) != TD->getIntPtrType(*Context)) +      return 0; + +    ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4)); +    if (!SizeCI) +      return 0; +    if (SizeCI->isAllOnesValue()) { +      EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), +		  1, B); +      return CI->getOperand(1); +    } + +    return 0; +  } +}; + +//===----------------------------------------------------------------------===//  // Math Library Optimizations  //===----------------------------------------------------------------------===// @@ -1356,7 +1458,7 @@ struct PrintFOpt : public LibCallOptimization {      if (FormatStr == "%c" && CI->getNumOperands() > 2 &&          isa<IntegerType>(CI->getOperand(2)->getType())) {        Value *Res = EmitPutChar(CI->getOperand(2), B); -       +        if (CI->use_empty()) return CI;        return B.CreateIntCast(Res, CI->getType(), true);      } @@ -1586,7 +1688,10 @@ namespace {      // Formatting and IO Optimizations      SPrintFOpt SPrintF; PrintFOpt PrintF;      FWriteOpt FWrite; FPutsOpt FPuts; FPrintFOpt FPrintF; + +    // Object Size Checking      SizeOpt ObjectSize; +    MemCpyChkOpt MemCpyChk; MemSetChkOpt MemSetChk; MemMoveChkOpt MemMoveChk;      bool Modified;  // This is only used by doInitialization.    public: @@ -1692,9 +1797,13 @@ void SimplifyLibCalls::InitOptimizations() {    Optimizations["fwrite"] = &FWrite;    Optimizations["fputs"] = &FPuts;    Optimizations["fprintf"] = &FPrintF; -   -  // Miscellaneous -  Optimizations["llvm.objectsize"] = &ObjectSize; + +  // Object Size Checking +  Optimizations["llvm.objectsize.i32"] = &ObjectSize; +  Optimizations["llvm.objectsize.i64"] = &ObjectSize; +  Optimizations["__memcpy_chk"] = &MemCpyChk; +  Optimizations["__memset_chk"] = &MemSetChk; +  Optimizations["__memmove_chk"] = &MemMoveChk;  }  | 
