diff options
| author | Andrew Kaylor <andrew.kaylor@intel.com> | 2016-07-26 17:23:13 +0000 |
|---|---|---|
| committer | Andrew Kaylor <andrew.kaylor@intel.com> | 2016-07-26 17:23:13 +0000 |
| commit | 3104a6bad05b9b1432b7afd5c31e1318bd8e1814 (patch) | |
| tree | 451d1c02b6aaefd801352f83b27c607d97921430 /llvm/lib/CodeGen | |
| parent | 75069a16680c3f2a78caeeb0eafd0882a8250544 (diff) | |
| download | bcm5719-llvm-3104a6bad05b9b1432b7afd5c31e1318bd8e1814.tar.gz bcm5719-llvm-3104a6bad05b9b1432b7afd5c31e1318bd8e1814.zip | |
Re-committing r275284: add support to inline __builtin_mempcpy
Patch by Sunita Marathe
Differential Revision: http://reviews.llvm.org/D21920
llvm-svn: 276771
Diffstat (limited to 'llvm/lib/CodeGen')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 47 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 1 |
2 files changed, 48 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index e03282cad6b..af86d876813 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6044,6 +6044,49 @@ bool SelectionDAGBuilder::visitMemChrCall(const CallInst &I) { 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) { + + // Verify argument count: void *mempcpy(void *, const void *, size_t) + if (I.getNumArgOperands() != 3) + return false; + + SDValue Dst = getValue(I.getArgOperand(0)); + SDValue Src = getValue(I.getArgOperand(1)); + SDValue Size = getValue(I.getArgOperand(2)); + + unsigned DstAlign = DAG.InferPtrAlignment(Dst); + unsigned SrcAlign = DAG.InferPtrAlignment(Src); + unsigned Align = std::min(DstAlign, SrcAlign); + if (Align == 0) // Alignment of one or both could not be inferred. + Align = 1; // 0 and 1 both specify no alignment, but 0 is reserved. + + bool isVol = false; + 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); + + // Check if Size needs to be truncated or extended. + Size = DAG.getSExtOrTrunc(Size, sdl, Dst.getValueType()); + + // 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. @@ -6334,6 +6377,10 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) { if (visitMemCmpCall(I)) return; break; + case LibFunc::mempcpy: + if (visitMemPCpyCall(I)) + return; + break; case LibFunc::memchr: if (visitMemChrCall(I)) return; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index b9888ae8763..18c39d0fccb 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -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); |

