summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp52
-rw-r--r--lib/Target/X86/X86ISelLowering.h7
-rw-r--r--test/CodeGen/X86/byval2.ll19
3 files changed, 56 insertions, 22 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 85c9691e5e..084c8468ad 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -1036,6 +1036,34 @@ X86TargetLowering::LowerFastCCArguments(SDOperand Op, SelectionDAG &DAG) {
&ArgValues[0], ArgValues.size()).getValue(Op.ResNo);
}
+SDOperand
+X86TargetLowering::LowerMemOpCallTo(SDOperand Op, SelectionDAG &DAG,
+ const SDOperand &StackPtr,
+ const CCValAssign &VA,
+ SDOperand Chain,
+ SDOperand Arg) {
+ SDOperand PtrOff = DAG.getConstant(VA.getLocMemOffset(), getPointerTy());
+ PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
+ SDOperand FlagsOp = Op.getOperand(6+2*VA.getValNo());
+ unsigned Flags = cast<ConstantSDNode>(FlagsOp)->getValue();
+ if (Flags & ISD::ParamFlags::ByVal) {
+ unsigned Align = 1 << ((Flags & ISD::ParamFlags::ByValAlign) >>
+ ISD::ParamFlags::ByValAlignOffs);
+
+ assert (Align >= 8);
+ unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >>
+ ISD::ParamFlags::ByValSizeOffs;
+
+ SDOperand AlignNode = DAG.getConstant(Align, MVT::i32);
+ SDOperand SizeNode = DAG.getConstant(Size, MVT::i32);
+
+ return DAG.getNode(ISD::MEMCPY, MVT::Other, Chain, PtrOff, Arg, SizeNode,
+ AlignNode);
+ } else {
+ return DAG.getStore(Chain, Arg, PtrOff, NULL, 0);
+ }
+}
+
SDOperand X86TargetLowering::LowerFastCCCallTo(SDOperand Op, SelectionDAG &DAG,
unsigned CC) {
SDOperand Chain = Op.getOperand(0);
@@ -1375,29 +1403,9 @@ X86TargetLowering::LowerX86_64CCCCallTo(SDOperand Op, SelectionDAG &DAG,
assert(VA.isMemLoc());
if (StackPtr.Val == 0)
StackPtr = DAG.getRegister(getStackPtrReg(), getPointerTy());
- SDOperand PtrOff = DAG.getConstant(VA.getLocMemOffset(), getPointerTy());
- PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
- SDOperand FlagsOp = Op.getOperand(6+2*VA.getValNo());
- unsigned Flags = cast<ConstantSDNode>(FlagsOp)->getValue();
- if (Flags & ISD::ParamFlags::ByVal) {
- unsigned Align = 1 << ((Flags & ISD::ParamFlags::ByValAlign) >>
- ISD::ParamFlags::ByValAlignOffs);
- unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >>
- ISD::ParamFlags::ByValSizeOffs;
-
- SDOperand AlignNode = DAG.getConstant(Align, MVT::i32);
- SDOperand SizeNode = DAG.getConstant(Size, MVT::i32);
-
- assert(0 && "Not Implemented");
-
- SDOperand Copy = DAG.getNode(ISD::MEMCPY, MVT::Other, Chain, PtrOff,
- Arg, SizeNode, AlignNode);
- MemOpChains.push_back(Copy);
- }
- else {
- MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
- }
+ MemOpChains.push_back(LowerMemOpCallTo(Op, DAG, StackPtr, VA, Chain,
+ Arg));
}
}
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index 24ca1ea44b..41eaec2783 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -19,6 +19,7 @@
#include "X86RegisterInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/CallingConvLower.h"
namespace llvm {
namespace X86ISD {
@@ -378,6 +379,12 @@ namespace llvm {
SDNode *LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode*TheCall,
unsigned CallingConv, SelectionDAG &DAG);
+
+ SDOperand LowerMemOpCallTo(SDOperand Op, SelectionDAG &DAG,
+ const SDOperand &StackPtr,
+ const CCValAssign &VA, SDOperand Chain,
+ SDOperand Arg);
+
// C and StdCall Calling Convention implementation.
SDOperand LowerCCCArguments(SDOperand Op, SelectionDAG &DAG,
bool isStdCall = false);
diff --git a/test/CodeGen/X86/byval2.ll b/test/CodeGen/X86/byval2.ll
new file mode 100644
index 0000000000..04d34839c0
--- /dev/null
+++ b/test/CodeGen/X86/byval2.ll
@@ -0,0 +1,19 @@
+; RUN: llvm-as < %s | llc -march=x86-64 | grep rep.movsl | count 2
+
+%struct.s = type { i64, i64, i64 }
+
+define void @g(i64 %a, i64 %b, i64 %c) {
+entry:
+ %d = alloca %struct.s, align 16
+ %tmp = getelementptr %struct.s* %d, i32 0, i32 0
+ store i64 %a, i64* %tmp, align 16
+ %tmp2 = getelementptr %struct.s* %d, i32 0, i32 1
+ store i64 %b, i64* %tmp2, align 16
+ %tmp4 = getelementptr %struct.s* %d, i32 0, i32 2
+ store i64 %c, i64* %tmp4, align 16
+ call void @f( %struct.s* %d byval)
+ call void @f( %struct.s* %d byval)
+ ret void
+}
+
+declare void @f(%struct.s* byval)