[llvm-commits] [llvm] r89523 - /llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp

Chris Lattner clattner at apple.com
Tue Dec 1 22:24:52 PST 2009


On Nov 20, 2009, at 5:01 PM, Eric Christopher wrote:
> URL: http://llvm.org/viewvc/llvm-project?rev=89523&view=rev
> Log:
> Add more optimizations for object size checking, enable handling of
> object size intrinsic and verify return type is correct. Collect various
> code in one place.

Hi Eric,

> +//===---------------------------------------===//
> +// 'object size'
> +namespace {
> +struct SizeOpt : public LibCallOptimization {

This code (if it is kept) should be moved to instcombine, and generalized to work on more than just i32/i64.  IT should work on any llvm.objectsize.ixxx intrinsic call. 

> +  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;

This intrinsic *requires* this to be a ConstantInt, right?  If so, change this to be cast<> instead of dyn_cast.  Unlike random function calls, intrinsics have hard requirements that the optimizer can depend on.

> +    const Type *Ty = Callee->getFunctionType()->getReturnType();
> +
> +    if (Const->getZExtValue() < 2)
> +      return Constant::getAllOnesValue(Ty);
> +    else
> +      return ConstantInt::get(Ty, 0);

I don't really get this.  Why is libcalloptimizer turning these into "I don't know"?  Shouldn't codegen (e.g. codegenprepare) do this?  This seems really wrong.

> +//===---------------------------------------===//
> +// '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);
> +    }

This should also handle the case when getOperand(3) and getOperand(4) are both constant ints and op3 <= op4?  If we know that op3 > op4, I'm fine with leaving it unoptimized :)

Also, please do the check for 'SizeCI' being a constantint before anything else to avoid doing pointless validation.

> +//===---------------------------------------===//
> +// '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);
> +    }

Can this code be factored better?  Maybe introduce a new intermediate class that all of MemCpyChkOpt/MemSetChkOpt/MemMoveChkOpt inherit from that then inherits from LibCallOptimization?

-Chris


> +
> +    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 @@
>     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 @@
>     // 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 @@
>   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;
> }
> 
> 
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits





More information about the llvm-commits mailing list