[llvm] r275284 - Fix for Bug 26903, adds support to inline __builtin_mempcpy
Andrew Kaylor via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 13 10:25:11 PDT 2016
Author: akaylor
Date: Wed Jul 13 12:25:11 2016
New Revision: 275284
URL: http://llvm.org/viewvc/llvm-project?rev=275284&view=rev
Log:
Fix for Bug 26903, adds support to inline __builtin_mempcpy
Patch by Sunita Marathe
Differential Revision: http://reviews.llvm.org/D21920
Added:
llvm/trunk/test/CodeGen/Generic/mempcpy_call.ll
llvm/trunk/test/CodeGen/X86/mempcpy_ret_val.ll
Modified:
llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.def
llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.h
llvm/trunk/lib/Analysis/TargetLibraryInfo.cpp
llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp
llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll
llvm/trunk/test/Transforms/InferFunctionAttrs/no-proto.ll
Modified: llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.def?rev=275284&r1=275283&r2=275284&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.def (original)
+++ llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.def Wed Jul 13 12:25:11 2016
@@ -734,6 +734,9 @@ TLI_DEFINE_STRING_INTERNAL("memcpy")
/// void *memmove(void *s1, const void *s2, size_t n);
TLI_DEFINE_ENUM_INTERNAL(memmove)
TLI_DEFINE_STRING_INTERNAL("memmove")
+/// void *mempcpy(void *s1, const void *s2, size_t n);
+TLI_DEFINE_ENUM_INTERNAL(mempcpy)
+TLI_DEFINE_STRING_INTERNAL("mempcpy")
// void *memrchr(const void *s, int c, size_t n);
TLI_DEFINE_ENUM_INTERNAL(memrchr)
TLI_DEFINE_STRING_INTERNAL("memrchr")
Modified: llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.h?rev=275284&r1=275283&r2=275284&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.h (original)
+++ llvm/trunk/include/llvm/Analysis/TargetLibraryInfo.h Wed Jul 13 12:25:11 2016
@@ -251,7 +251,7 @@ public:
case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l:
case LibFunc::memcmp: case LibFunc::strcmp: case LibFunc::strcpy:
case LibFunc::stpcpy: case LibFunc::strlen: case LibFunc::strnlen:
- case LibFunc::memchr:
+ case LibFunc::memchr: case LibFunc::mempcpy:
return true;
}
return false;
Modified: llvm/trunk/lib/Analysis/TargetLibraryInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/TargetLibraryInfo.cpp?rev=275284&r1=275283&r2=275284&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/TargetLibraryInfo.cpp (original)
+++ llvm/trunk/lib/Analysis/TargetLibraryInfo.cpp Wed Jul 13 12:25:11 2016
@@ -642,6 +642,7 @@ bool TargetLibraryInfoImpl::isValidProto
return false;
// fallthrough
case LibFunc::memcpy:
+ case LibFunc::mempcpy:
case LibFunc::memmove:
return (NumParams == 3 && FTy.getReturnType() == FTy.getParamType(0) &&
FTy.getParamType(0)->isPointerTy() &&
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=275284&r1=275283&r2=275284&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Wed Jul 13 12:25:11 2016
@@ -6039,6 +6039,48 @@ bool SelectionDAGBuilder::visitMemChrCal
return false;
}
+///
+/// visitMemPCpyCall -- lower a mempcpy call as a memcpy followed by code to
+/// to adjust the dst pointer by the size of the copied memory.
+bool SelectionDAGBuilder::visitMemPCpyCall(const CallInst &I) {
+
+ unsigned int NumOperands = I.getNumArgOperands();
+ if (NumOperands < 3 || NumOperands > 5)
+ return false;
+
+ SDValue Dst = getValue(I.getArgOperand(0));
+ SDValue Src = getValue(I.getArgOperand(1));
+ SDValue Size = getValue(I.getArgOperand(2));
+
+ unsigned Align = 0;
+ if (NumOperands >= 4)
+ Align = cast<ConstantInt>(I.getArgOperand(3))->getZExtValue();
+ if (!Align)
+ Align = 1; // @llvm.memcpy defines 0 and 1 to both mean no alignment.
+
+ bool isVol = false;
+ if (NumOperands == 5)
+ isVol = cast<ConstantInt>(I.getArgOperand(4))->getZExtValue();
+
+ SDLoc sdl = getCurSDLoc();
+ // In the mempcpy context we need to pass in a false value for isTailCall
+ // because the return pointer needs to be adjusted by the size of
+ // the copied memory.
+ SDValue MC = DAG.getMemcpy(getRoot(), sdl, Dst, Src, Size, Align, isVol,
+ false, /*isTailCall=*/false,
+ MachinePointerInfo(I.getArgOperand(0)),
+ MachinePointerInfo(I.getArgOperand(1)));
+ assert(MC.getNode() != nullptr &&
+ "** memcpy should not be lowered as TailCall in mempcpy context **");
+ DAG.setRoot(MC);
+
+ // Adjust return pointer to point just past the last dst byte.
+ SDValue DstPlusSize = DAG.getNode(ISD::ADD, sdl, Dst.getValueType(),
+ Dst, Size);
+ setValue(&I, DstPlusSize);
+ return true;
+}
+
/// visitStrCpyCall -- See if we can lower a strcpy or stpcpy call into an
/// optimized form. If so, return true and lower it, otherwise return false
/// and it will be lowered like a normal call.
@@ -6329,6 +6371,10 @@ void SelectionDAGBuilder::visitCall(cons
if (visitMemCmpCall(I))
return;
break;
+ case LibFunc::mempcpy:
+ if (visitMemPCpyCall(I))
+ return;
+ break;
case LibFunc::memchr:
if (visitMemChrCall(I))
return;
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h?rev=275284&r1=275283&r2=275284&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h Wed Jul 13 12:25:11 2016
@@ -885,6 +885,7 @@ private:
void visitPHI(const PHINode &I);
void visitCall(const CallInst &I);
bool visitMemCmpCall(const CallInst &I);
+ bool visitMemPCpyCall(const CallInst &I);
bool visitMemChrCall(const CallInst &I);
bool visitStrCpyCall(const CallInst &I, bool isStpcpy);
bool visitStrCmpCall(const CallInst &I);
Modified: llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp?rev=275284&r1=275283&r2=275284&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp Wed Jul 13 12:25:11 2016
@@ -250,6 +250,7 @@ bool llvm::inferLibFuncAttributes(Functi
Changed |= setDoesNotCapture(F, 2);
return Changed;
case LibFunc::memcpy:
+ case LibFunc::mempcpy:
case LibFunc::memccpy:
case LibFunc::memmove:
Changed |= setDoesNotThrow(F);
Added: llvm/trunk/test/CodeGen/Generic/mempcpy_call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Generic/mempcpy_call.ll?rev=275284&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Generic/mempcpy_call.ll (added)
+++ llvm/trunk/test/CodeGen/Generic/mempcpy_call.ll Wed Jul 13 12:25:11 2016
@@ -0,0 +1,16 @@
+; RUN: llc < %s -O2 | FileCheck %s
+
+; This test just checks that mempcpy is lowered as memcpy.
+; The test to check that the return value of mempcpy is the dst pointer adjusted
+; by the copy size is done by Codegen/X86/mempcpy_ret_val.ll
+
+; CHECK-LABEL: CALL_MEMPCPY:
+; CHECK: callq memcpy
+;
+define void @CALL_MEMPCPY(i8* %DST, i8* %SRC, i64 %N) {
+entry:
+ %call = tail call i8* @mempcpy(i8* %DST, i8* %SRC, i64 %N)
+ ret void
+}
+
+declare i8* @mempcpy(i8*, i8*, i64)
Added: llvm/trunk/test/CodeGen/X86/mempcpy_ret_val.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mempcpy_ret_val.ll?rev=275284&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/mempcpy_ret_val.ll (added)
+++ llvm/trunk/test/CodeGen/X86/mempcpy_ret_val.ll Wed Jul 13 12:25:11 2016
@@ -0,0 +1,28 @@
+; RUN: llc < %s -O2 | FileCheck %s
+
+ at G = common global i8* null, align 8
+
+; This test checks that:
+; (1) mempcpy is lowered as memcpy, and
+; (2) its return value is DST+N i.e. the dst pointer adjusted by the copy size.
+; To keep the testing of (2) independent of the exact instructions used to
+; adjust the dst pointer, DST+N is explicitly computed and stored to a global
+; variable G before the mempcpy call. This instance of DST+N causes the repeat
+; DST+N done in the context of the return value of mempcpy to be redundant, and
+; the first instance to be reused as the return value. This allows the check for
+; (2) to be expressed as verifying that the MOV to store DST+N to G and
+; the MOV to copy DST+N to %rax use the same source register.
+
+; CHECK-LABEL: RET_MEMPCPY:
+; CHECK: movq [[REG:%r[a-z0-9]+]], {{.*}}G
+; CHECK: callq memcpy
+; CHECK: movq [[REG]], %rax
+;
+define i8* @RET_MEMPCPY(i8* %DST, i8* %SRC, i64 %N) {
+ %add.ptr = getelementptr inbounds i8, i8* %DST, i64 %N
+ store i8* %add.ptr, i8** @G, align 8
+ %call = tail call i8* @mempcpy(i8* %DST, i8* %SRC, i64 %N)
+ ret i8* %call
+}
+
+declare i8* @mempcpy(i8*, i8*, i64)
Modified: llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll?rev=275284&r1=275283&r2=275284&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll (original)
+++ llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll Wed Jul 13 12:25:11 2016
@@ -499,6 +499,9 @@ declare i32 @memcmp(i8*, i8*, i64)
; CHECK: declare i8* @memcpy(i8*, i8* nocapture readonly, i64) [[G0]]
declare i8* @memcpy(i8*, i8*, i64)
+; CHECK: declare i8* @mempcpy(i8*, i8* nocapture readonly, i64) [[G0]]
+declare i8* @mempcpy(i8*, i8*, i64)
+
; CHECK: declare i8* @memmove(i8*, i8* nocapture readonly, i64) [[G0]]
declare i8* @memmove(i8*, i8*, i64)
Modified: llvm/trunk/test/Transforms/InferFunctionAttrs/no-proto.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferFunctionAttrs/no-proto.ll?rev=275284&r1=275283&r2=275284&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InferFunctionAttrs/no-proto.ll (original)
+++ llvm/trunk/test/Transforms/InferFunctionAttrs/no-proto.ll Wed Jul 13 12:25:11 2016
@@ -480,6 +480,9 @@ declare void @memcmp(...)
; CHECK: declare void @memcpy(...)
declare void @memcpy(...)
+; CHECK: declare void @mempcpy(...)
+declare void @mempcpy(...)
+
; CHECK: declare void @memmove(...)
declare void @memmove(...)
More information about the llvm-commits
mailing list