[llvm-commits] [llvm-gcc-4.2] r67690 - in /llvm-gcc-4.2/trunk/gcc: llvm-convert.cpp llvm-internal.h
Evan Cheng
evan.cheng at apple.com
Wed Mar 25 09:48:43 PDT 2009
Author: evancheng
Date: Wed Mar 25 11:48:43 2009
New Revision: 67690
URL: http://llvm.org/viewvc/llvm-project?rev=67690&view=rev
Log:
Lower object size checking variants of string builtins (e.g. __builtin_memcpy_chk) into plain vanilla ones if the object size is -1 (unknown) or is known to be larger than the copy/move/set length. Warn if the call is known to overflow.
Modified:
llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
llvm-gcc-4.2/trunk/gcc/llvm-internal.h
Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=67690&r1=67689&r2=67690&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Wed Mar 25 11:48:43 2009
@@ -4410,8 +4410,9 @@
AttrListPtr());
return true;
}
-
- switch (DECL_FUNCTION_CODE(fndecl)) {
+
+ enum built_in_function fcode = DECL_FUNCTION_CODE(fndecl);
+ switch (fcode) {
default: return false;
// Varargs builtins.
case BUILT_IN_VA_START:
@@ -4422,9 +4423,16 @@
case BUILT_IN_ALLOCA: return EmitBuiltinAlloca(exp, Result);
case BUILT_IN_EXTEND_POINTER: return EmitBuiltinExtendPointer(exp, Result);
case BUILT_IN_EXPECT: return EmitBuiltinExpect(exp, DestLoc, Result);
- case BUILT_IN_MEMCPY: return EmitBuiltinMemCopy(exp, Result, false);
- case BUILT_IN_MEMMOVE: return EmitBuiltinMemCopy(exp, Result, true);
- case BUILT_IN_MEMSET: return EmitBuiltinMemSet(exp, Result);
+ case BUILT_IN_MEMCPY: return EmitBuiltinMemCopy(exp, Result,
+ false, false);
+ case BUILT_IN_MEMCPY_CHK: return EmitBuiltinMemCopy(exp, Result,
+ false, true);
+ case BUILT_IN_MEMMOVE: return EmitBuiltinMemCopy(exp, Result,
+ true, false);
+ case BUILT_IN_MEMMOVE_CHK: return EmitBuiltinMemCopy(exp, Result,
+ true, true);
+ case BUILT_IN_MEMSET: return EmitBuiltinMemSet(exp, Result, false);
+ case BUILT_IN_MEMSET_CHK: return EmitBuiltinMemSet(exp, Result, true);
case BUILT_IN_BZERO: return EmitBuiltinBZero(exp, Result);
case BUILT_IN_PREFETCH: return EmitBuiltinPrefetch(exp);
case BUILT_IN_FRAME_ADDRESS: return EmitBuiltinReturnAddr(exp, Result,true);
@@ -5100,13 +5108,46 @@
return true;
}
+/// OptimizeIntoPlainBuiltIn - Return true if it's safe to lower the object
+/// size checking builtin calls (e.g. __builtin___memcpy_chk into the
+/// plain non-checking calls. If the size of the argument is either -1 (unknown)
+/// or large enough to ensure no overflow (> len), then it's safe to do so.
+static bool OptimizeIntoPlainBuiltIn(tree exp, Value *Len, Value *Size) {
+ if (BitCastInst *BC = dyn_cast<BitCastInst>(Size))
+ Size = BC->getOperand(0);
+ ConstantInt *SizeCI = dyn_cast<ConstantInt>(Size);
+ if (!SizeCI)
+ return false;
+ if (SizeCI->isAllOnesValue())
+ // If size is -1, convert to plain memcpy, etc.
+ return true;
+
+ ConstantInt *LenCI = dyn_cast<ConstantInt>(Len);
+ if (!LenCI)
+ return false;
+ if (LenCI->getZExtValue() >= SizeCI->getZExtValue()) {
+ location_t locus = EXPR_LOCATION(exp);
+ warning (0, "%Hcall to %D will always overflow destination buffer",
+ &locus, get_callee_fndecl(exp));
+ return false;
+ }
+ return true;
+}
+
/// EmitBuiltinMemCopy - Emit an llvm.memcpy or llvm.memmove intrinsic,
/// depending on the value of isMemMove.
-bool TreeToLLVM::EmitBuiltinMemCopy(tree exp, Value *&Result, bool isMemMove) {
+bool TreeToLLVM::EmitBuiltinMemCopy(tree exp, Value *&Result, bool isMemMove,
+ bool SizeCheck) {
tree arglist = TREE_OPERAND(exp, 1);
- if (!validate_arglist(arglist, POINTER_TYPE, POINTER_TYPE,
- INTEGER_TYPE, VOID_TYPE))
- return false;
+ if (SizeCheck) {
+ if (!validate_arglist(arglist, POINTER_TYPE, POINTER_TYPE,
+ INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return false;
+ } else {
+ if (!validate_arglist(arglist, POINTER_TYPE, POINTER_TYPE,
+ INTEGER_TYPE, VOID_TYPE))
+ return false;
+ }
tree Dst = TREE_VALUE(arglist);
tree Src = TREE_VALUE(TREE_CHAIN(arglist));
@@ -5116,6 +5157,13 @@
Value *DstV = Emit(Dst, 0);
Value *SrcV = Emit(Src, 0);
Value *Len = Emit(TREE_VALUE(TREE_CHAIN(TREE_CHAIN(arglist))), 0);
+ if (SizeCheck) {
+ tree SizeArg = TREE_VALUE(TREE_CHAIN(TREE_CHAIN(TREE_CHAIN(arglist))));
+ Value *Size = Emit(SizeArg, 0);
+ if (!OptimizeIntoPlainBuiltIn(exp, Len, Size))
+ return false;
+ }
+
if (isMemMove)
EmitMemMove(DstV, SrcV, Len, std::min(SrcAlign, DstAlign));
else
@@ -5124,7 +5172,7 @@
return true;
}
-bool TreeToLLVM::EmitBuiltinMemSet(tree exp, Value *&Result) {
+bool TreeToLLVM::EmitBuiltinMemSet(tree exp, Value *&Result, bool SizeCheck) {
tree arglist = TREE_OPERAND(exp, 1);
if (!validate_arglist(arglist, POINTER_TYPE, INTEGER_TYPE,
INTEGER_TYPE, VOID_TYPE))
@@ -5136,6 +5184,12 @@
Value *DstV = Emit(Dst, 0);
Value *Val = Emit(TREE_VALUE(TREE_CHAIN(arglist)), 0);
Value *Len = Emit(TREE_VALUE(TREE_CHAIN(TREE_CHAIN(arglist))), 0);
+ if (SizeCheck) {
+ tree SizeArg = TREE_VALUE(TREE_CHAIN(TREE_CHAIN(TREE_CHAIN(arglist))));
+ Value *Size = Emit(SizeArg, 0);
+ if (!OptimizeIntoPlainBuiltIn(exp, Len, Size))
+ return false;
+ }
EmitMemSet(DstV, Val, Len, DstAlign);
Result = DstV;
return true;
Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=67690&r1=67689&r2=67690&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Wed Mar 25 11:48:43 2009
@@ -547,8 +547,9 @@
bool EmitBuiltinVAStart(tree_node *exp);
bool EmitBuiltinVAEnd(tree_node *exp);
bool EmitBuiltinVACopy(tree_node *exp);
- bool EmitBuiltinMemCopy(tree_node *exp, Value *&Result, bool isMemMove);
- bool EmitBuiltinMemSet(tree_node *exp, Value *&Result);
+ bool EmitBuiltinMemCopy(tree_node *exp, Value *&Result,
+ bool isMemMove, bool SizeCheck);
+ bool EmitBuiltinMemSet(tree_node *exp, Value *&Result, bool SizeCheck);
bool EmitBuiltinBZero(tree_node *exp, Value *&Result);
bool EmitBuiltinPrefetch(tree_node *exp);
bool EmitBuiltinReturnAddr(tree_node *exp, Value *&Result, bool isFrame);
More information about the llvm-commits
mailing list