Index: include/llvm/Transforms/Utils/SimplifyLibCalls.h =================================================================== --- include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -124,6 +124,8 @@ Value *optimizePrintFString(CallInst *CI, IRBuilder<> &B); Value *optimizeSPrintFString(CallInst *CI, IRBuilder<> &B); Value *optimizeFPrintFString(CallInst *CI, IRBuilder<> &B); + bool isFortifiedCallFoldable(CallInst *CI, unsigned SizeCIOp, + unsigned SizeArgOp, bool isString); /// hasFloatVersion - Checks if there is a float version of the specified /// function by checking for an existing function with name FuncName + f Index: lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- lib/Transforms/Utils/SimplifyLibCalls.cpp +++ lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Triple.h" +#include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DiagnosticInfo.h" @@ -120,25 +121,41 @@ // Fortified Library Call Optimizations //===----------------------------------------------------------------------===// -static bool isFortifiedCallFoldable(CallInst *CI, unsigned SizeCIOp, unsigned SizeArgOp, - bool isString) { - if (CI->getArgOperand(SizeCIOp) == CI->getArgOperand(SizeArgOp)) +bool LibCallSimplifier::isFortifiedCallFoldable(CallInst *CI, unsigned SizeCIOp, + unsigned SizeArgOp, + bool isString) { + // The destination operand is always the first. + Value *Dest = CI->getArgOperand(0); + Value *SizeCIVal = CI->getArgOperand(SizeCIOp); + Value *SizeArg = CI->getArgOperand(SizeArgOp); + + // If the argument size and known object size are the same value, we can + // remove the check. + if (SizeCIVal == SizeArg) return true; - if (ConstantInt *SizeCI = - dyn_cast(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(CI->getArgOperand(SizeArgOp))) - return SizeCI->getZExtValue() >= Arg->getZExtValue(); + + uint64_t ObjectSizeInt = 0; + APInt SizeCIAPInt = APInt::getAllOnesValue(64U); + + if (ConstantInt *SizeCI = dyn_cast(SizeCIVal)) + SizeCIAPInt = SizeCI->getValue(); + else if (getObjectSize(Dest, ObjectSizeInt, DL, TLI)) + SizeCIAPInt = APInt(64U, ObjectSizeInt); + + // If the object size is unknown (-1), we can remove the check. + if (SizeCIAPInt.isAllOnesValue()) + return true; + if (isString) { + uint64_t Len = GetStringLength(SizeArg); + // 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 SizeCIAPInt.getZExtValue() >= Len; } + // If the libcall is known not to overflow, we can remove the check. + if (ConstantInt *Arg = dyn_cast(SizeArg)) + return SizeCIAPInt.getZExtValue() >= Arg->getZExtValue(); return false; } Index: test/CodeGen/X86/2011-02-21-VirtRegRewriter-KillSubReg.ll =================================================================== --- test/CodeGen/X86/2011-02-21-VirtRegRewriter-KillSubReg.ll +++ test/CodeGen/X86/2011-02-21-VirtRegRewriter-KillSubReg.ll @@ -25,7 +25,7 @@ %call782 = call i8* @__memmove_chk(i8* %add.ptr768, i8* undef, i32 %call747, i32 undef) br label %cond.end791 -; CHECK: calll __memmove_chk +; CHECK: calll memmove@PLT cond.false783: %call.i1035 = call i8* @__memmove_chk(i8* %add.ptr768, i8* undef, i32 %call747, i32 undef) nounwind br label %cond.end791 Index: test/Transforms/InstCombine/stpcpy_chk-1.ll =================================================================== --- test/Transforms/InstCombine/stpcpy_chk-1.ll +++ test/Transforms/InstCombine/stpcpy_chk-1.ll @@ -60,7 +60,7 @@ %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [12 x i8]* @.str, i32 0, i32 0 -; CHECK: @__memcpy_chk +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32 %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false) %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 %len) ; CHECK: ret i8* getelementptr inbounds ([60 x i8]* @a, i32 0, i32 11) Index: test/Transforms/InstCombine/strcpy_chk-1.ll =================================================================== --- test/Transforms/InstCombine/strcpy_chk-1.ll +++ test/Transforms/InstCombine/strcpy_chk-1.ll @@ -60,7 +60,7 @@ %dst = getelementptr inbounds [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [12 x i8]* @.str, i32 0, i32 0 -; CHECK: @__memcpy_chk +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32 %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false) call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 %len) ret void