forked from OSchip/llvm-project
[SLC] Optimize mempcpy_chk to mempcpy
As reported in PR46735: void* f(void *d, const void *s, size_t l) { return __builtin___mempcpy_chk(d, s, l, __builtin_object_size(d, 0)); } This can be optimized to `return mempcpy(d, s, l);`. Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D86019
This commit is contained in:
parent
a506a66bd9
commit
3f1fd59de3
|
@ -366,6 +366,9 @@ TLI_DEFINE_STRING_INTERNAL("__memcpy_chk")
|
|||
/// void *__memmove_chk(void *s1, const void *s2, size_t n, size_t s1size);
|
||||
TLI_DEFINE_ENUM_INTERNAL(memmove_chk)
|
||||
TLI_DEFINE_STRING_INTERNAL("__memmove_chk")
|
||||
/// void *__mempcpy_chk(void *s1, const void *s2, size_t n, size_t s1size);
|
||||
TLI_DEFINE_ENUM_INTERNAL(mempcpy_chk)
|
||||
TLI_DEFINE_STRING_INTERNAL("__mempcpy_chk")
|
||||
/// void *__memset_chk(void *s, char v, size_t n, size_t s1size);
|
||||
TLI_DEFINE_ENUM_INTERNAL(memset_chk)
|
||||
TLI_DEFINE_STRING_INTERNAL("__memset_chk")
|
||||
|
|
|
@ -96,6 +96,10 @@ namespace llvm {
|
|||
IRBuilderBase &B, const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI);
|
||||
|
||||
/// Emit a call to the mempcpy function.
|
||||
Value *emitMemPCpy(Value *Dst, Value *Src, Value *Len, IRBuilderBase &B,
|
||||
const DataLayout &DL, const TargetLibraryInfo *TLI);
|
||||
|
||||
/// 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, IRBuilderBase &B,
|
||||
|
|
|
@ -59,6 +59,7 @@ private:
|
|||
Value *optimizeStrpCpyChk(CallInst *CI, IRBuilderBase &B, LibFunc Func);
|
||||
Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilderBase &B, LibFunc Func);
|
||||
Value *optimizeStrLenChk(CallInst *CI, IRBuilderBase &B);
|
||||
Value *optimizeMemPCpyChk(CallInst *CI, IRBuilderBase &B);
|
||||
Value *optimizeMemCCpyChk(CallInst *CI, IRBuilderBase &B);
|
||||
Value *optimizeSNPrintfChk(CallInst *CI, IRBuilderBase &B);
|
||||
Value *optimizeSPrintfChk(CallInst *CI,IRBuilderBase &B);
|
||||
|
|
|
@ -847,6 +847,7 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
|
|||
return (NumParams >= 2 && FTy.getParamType(1)->isPointerTy());
|
||||
|
||||
case LibFunc_memcpy_chk:
|
||||
case LibFunc_mempcpy_chk:
|
||||
case LibFunc_memmove_chk:
|
||||
--NumParams;
|
||||
if (!IsSizeTTy(FTy.getParamType(NumParams)))
|
||||
|
|
|
@ -1076,6 +1076,15 @@ Value *llvm::emitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize,
|
|||
return CI;
|
||||
}
|
||||
|
||||
Value *llvm::emitMemPCpy(Value *Dst, Value *Src, Value *Len, IRBuilderBase &B,
|
||||
const DataLayout &DL, const TargetLibraryInfo *TLI) {
|
||||
LLVMContext &Context = B.GetInsertBlock()->getContext();
|
||||
return emitLibCall(
|
||||
LibFunc_mempcpy, B.getInt8PtrTy(),
|
||||
{B.getInt8PtrTy(), B.getInt8PtrTy(), DL.getIntPtrType(Context)},
|
||||
{Dst, Src, Len}, B, TLI);
|
||||
}
|
||||
|
||||
Value *llvm::emitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilderBase &B,
|
||||
const DataLayout &DL, const TargetLibraryInfo *TLI) {
|
||||
LLVMContext &Context = B.GetInsertBlock()->getContext();
|
||||
|
|
|
@ -3292,6 +3292,19 @@ Value *FortifiedLibCallSimplifier::optimizeMemSetChk(CallInst *CI,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Value *FortifiedLibCallSimplifier::optimizeMemPCpyChk(CallInst *CI,
|
||||
IRBuilderBase &B) {
|
||||
const DataLayout &DL = CI->getModule()->getDataLayout();
|
||||
if (isFortifiedCallFoldable(CI, 3, 2))
|
||||
if (Value *Call = emitMemPCpy(CI->getArgOperand(0), CI->getArgOperand(1),
|
||||
CI->getArgOperand(2), B, DL, TLI)) {
|
||||
CallInst *NewCI = cast<CallInst>(Call);
|
||||
NewCI->setAttributes(CI->getAttributes());
|
||||
return NewCI;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI,
|
||||
IRBuilderBase &B,
|
||||
LibFunc Func) {
|
||||
|
@ -3481,6 +3494,8 @@ Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI,
|
|||
switch (Func) {
|
||||
case LibFunc_memcpy_chk:
|
||||
return optimizeMemCpyChk(CI, Builder);
|
||||
case LibFunc_mempcpy_chk:
|
||||
return optimizeMemPCpyChk(CI, Builder);
|
||||
case LibFunc_memmove_chk:
|
||||
return optimizeMemMoveChk(CI, Builder);
|
||||
case LibFunc_memset_chk:
|
||||
|
|
|
@ -31,6 +31,28 @@ define i8* @test_not_memccpy() {
|
|||
ret i8* %ret
|
||||
}
|
||||
|
||||
define i8* @test_mempcpy() {
|
||||
; CHECK-LABEL: @test_mempcpy(
|
||||
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(15) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull align 1 dereferenceable(15) getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 15, i1 false)
|
||||
; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 15)
|
||||
;
|
||||
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
|
||||
%src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0
|
||||
%ret = call i8* @__mempcpy_chk(i8* %dst, i8* %src, i64 15, i64 -1)
|
||||
ret i8* %ret
|
||||
}
|
||||
|
||||
define i8* @test_not_mempcpy() {
|
||||
; CHECK-LABEL: @test_not_mempcpy(
|
||||
; CHECK-NEXT: [[RET:%.*]] = call i8* @__mempcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 60, i64 59)
|
||||
; CHECK-NEXT: ret i8* [[RET]]
|
||||
;
|
||||
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
|
||||
%src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0
|
||||
%ret = call i8* @__mempcpy_chk(i8* %dst, i8* %src, i64 60, i64 59)
|
||||
ret i8* %ret
|
||||
}
|
||||
|
||||
define i32 @test_snprintf() {
|
||||
; CHECK-LABEL: @test_snprintf(
|
||||
; CHECK-NEXT: [[SNPRINTF:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 60, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0))
|
||||
|
@ -219,6 +241,7 @@ define i32 @test_not_vsprintf() {
|
|||
ret i32 %ret
|
||||
}
|
||||
|
||||
declare i8* @__mempcpy_chk(i8*, i8*, i64, i64)
|
||||
declare i8* @__memccpy_chk(i8*, i8*, i32, i64, i64)
|
||||
declare i32 @__snprintf_chk(i8*, i64, i32, i64, i8*, ...)
|
||||
declare i32 @__sprintf_chk(i8*, i32, i64, i8*, ...)
|
||||
|
|
Loading…
Reference in New Issue