diff options
| author | Rafael Espindola <rafael.espindola@gmail.com> | 2007-10-19 10:41:11 +0000 |
|---|---|---|
| committer | Rafael Espindola <rafael.espindola@gmail.com> | 2007-10-19 10:41:11 +0000 |
| commit | 846c19dd7003d5de701a12ecdf31af8615bdfc1a (patch) | |
| tree | 64abf09b2cdfefb3bb63ec00d0e5ce7c2b3f3c1d /llvm/lib | |
| parent | e5a64485339ecaf21f6f57350a2a8c30a60c18f9 (diff) | |
| download | bcm5719-llvm-846c19dd7003d5de701a12ecdf31af8615bdfc1a.tar.gz bcm5719-llvm-846c19dd7003d5de701a12ecdf31af8615bdfc1a.zip | |
Add support for byval function whose argument is not 32 bit aligned.
To do this it is necessary to add a "always inline" argument to the
memcpy node. For completeness I have also added this node to memmove
and memset. I have also added getMem* functions, because the extra
argument makes it cumbersome to use getNode and because I get confused
by it :-)
llvm-svn: 43172
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 17 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 24 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 17 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 25 |
4 files changed, 72 insertions, 11 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 9516dff6cb8..1ad8e802585 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -2506,18 +2506,31 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { break; } + SDOperand Tmp6; + switch (getTypeAction(Node->getOperand(5).getValueType())) { // bool + case Expand: assert(0 && "Cannot expand this yet!"); + case Legal: + Tmp6 = LegalizeOp(Node->getOperand(5)); + break; + case Promote: + Tmp6 = PromoteOp(Node->getOperand(5)); + break; + } + switch (TLI.getOperationAction(Node->getOpcode(), MVT::Other)) { default: assert(0 && "This action not implemented for this operation!"); case TargetLowering::Custom: isCustom = true; // FALLTHROUGH - case TargetLowering::Legal: - Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3, Tmp4, Tmp5); + case TargetLowering::Legal: { + SDOperand Ops[] = { Tmp1, Tmp2, Tmp3, Tmp4, Tmp5, Tmp6 }; + Result = DAG.UpdateNodeOperands(Result, Ops, 6); if (isCustom) { Tmp1 = TLI.LowerOperation(Result, DAG); if (Tmp1.Val) Result = Tmp1; } break; + } case TargetLowering::Expand: { // Otherwise, the target does not support this operation. Lower the // operation to an explicit libcall as appropriate. diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index e6ce2eb9951..09e8b579a0f 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2269,6 +2269,30 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, return getNode(Opcode, VT, Ops, 5); } +SDOperand SelectionDAG::getMemcpy(SDOperand Chain, SDOperand Dest, + SDOperand Src, SDOperand Size, + SDOperand Align, + SDOperand AlwaysInline) { + SDOperand Ops[] = { Chain, Dest, Src, Size, Align, AlwaysInline }; + return getNode(ISD::MEMCPY, MVT::Other, Ops, 6); +} + +SDOperand SelectionDAG::getMemmove(SDOperand Chain, SDOperand Dest, + SDOperand Src, SDOperand Size, + SDOperand Align, + SDOperand AlwaysInline) { + SDOperand Ops[] = { Chain, Dest, Src, Size, Align, AlwaysInline }; + return getNode(ISD::MEMMOVE, MVT::Other, Ops, 6); +} + +SDOperand SelectionDAG::getMemset(SDOperand Chain, SDOperand Dest, + SDOperand Src, SDOperand Size, + SDOperand Align, + SDOperand AlwaysInline) { + SDOperand Ops[] = { Chain, Dest, Src, Size, Align, AlwaysInline }; + return getNode(ISD::MEMSET, MVT::Other, Ops, 6); +} + SDOperand SelectionDAG::getLoad(MVT::ValueType VT, SDOperand Chain, SDOperand Ptr, const Value *SV, int SVOffset, diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index a5b6300f6e3..f69b0959400 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -4367,7 +4367,22 @@ void SelectionDAGLowering::visitMemIntrinsic(CallInst &I, unsigned Op) { } } - DAG.setRoot(DAG.getNode(Op, MVT::Other, getRoot(), Op1, Op2, Op3, Op4)); + SDOperand AlwaysInline = DAG.getConstant(0, MVT::i1); + SDOperand Node; + switch(Op) { + default: + assert(0 && "Unknown Op"); + case ISD::MEMCPY: + Node = DAG.getMemcpy(getRoot(), Op1, Op2, Op3, Op4, AlwaysInline); + break; + case ISD::MEMMOVE: + Node = DAG.getMemmove(getRoot(), Op1, Op2, Op3, Op4, AlwaysInline); + break; + case ISD::MEMSET: + Node = DAG.getMemset(getRoot(), Op1, Op2, Op3, Op4, AlwaysInline); + break; + } + DAG.setRoot(Node); } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 9c9c6a41e22..2d16c3c63c6 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -1246,9 +1246,10 @@ X86TargetLowering::LowerMemOpCallTo(SDOperand Op, SelectionDAG &DAG, SDOperand AlignNode = DAG.getConstant(Align, MVT::i32); SDOperand SizeNode = DAG.getConstant(Size, MVT::i32); + SDOperand AlwaysInline = DAG.getConstant(1, MVT::i1); - return DAG.getNode(ISD::MEMCPY, MVT::Other, Chain, PtrOff, Arg, SizeNode, - AlignNode); + return DAG.getMemcpy(Chain, PtrOff, Arg, SizeNode, AlignNode, + AlwaysInline); } else { return DAG.getStore(Chain, Arg, PtrOff, NULL, 0); } @@ -4472,9 +4473,23 @@ SDOperand X86TargetLowering::LowerMEMCPY(SDOperand Op, SelectionDAG &DAG) { SDOperand SourceOp = Op.getOperand(2); SDOperand CountOp = Op.getOperand(3); SDOperand AlignOp = Op.getOperand(4); + SDOperand AlwaysInlineOp = Op.getOperand(5); + + bool AlwaysInline = (bool)cast<ConstantSDNode>(AlwaysInlineOp)->getValue(); unsigned Align = (unsigned)cast<ConstantSDNode>(AlignOp)->getValue(); if (Align == 0) Align = 1; + // If size is unknown, call memcpy. + ConstantSDNode *I = dyn_cast<ConstantSDNode>(CountOp); + if (!I) { + assert(!AlwaysInline && "Cannot inline copy of unknown size"); + return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG); + } + unsigned Size = I->getValue(); + + if (AlwaysInline) + return LowerMEMCPYInline(ChainOp, DestOp, SourceOp, Size, Align, DAG); + // The libc version is likely to be faster for the following cases. It can // use the address value and run time information about the CPU. // With glibc 2.6.1 on a core 2, coping an array of 100M longs was 30% faster @@ -4483,13 +4498,7 @@ SDOperand X86TargetLowering::LowerMEMCPY(SDOperand Op, SelectionDAG &DAG) { if ((Align & 3) != 0) return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG); - // If size is unknown, call memcpy. - ConstantSDNode *I = dyn_cast<ConstantSDNode>(CountOp); - if (!I) - return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG); - // If size is more than the threshold, call memcpy. - unsigned Size = I->getValue(); if (Size > Subtarget->getMinRepStrSizeThreshold()) return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG); |

