From f1ba1cad387dc52f3c2c5afc665edf9caad00992 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 5 Nov 2007 23:12:20 +0000 Subject: [PATCH] Move the LowerMEMCPY and LowerMEMCPYCall to a common place. Thanks for the suggestions Bill :-) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43742 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetLowering.h | 16 ++++++ include/llvm/Target/TargetSubtarget.h | 3 ++ lib/CodeGen/SelectionDAG/TargetLowering.cpp | 55 +++++++++++++++++++++ lib/Target/ARM/ARMISelLowering.cpp | 49 ------------------ lib/Target/ARM/ARMISelLowering.h | 11 +++-- lib/Target/X86/X86ISelLowering.cpp | 49 ------------------ lib/Target/X86/X86ISelLowering.h | 8 +-- 7 files changed, 84 insertions(+), 107 deletions(-) diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 9d7a1ec60f9..e8f8c12ac62 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -41,6 +41,7 @@ namespace llvm { class MachineBasicBlock; class MachineInstr; class VectorType; + class TargetSubtarget; //===----------------------------------------------------------------------===// /// TargetLowering - This class defines information used to lower LLVM code to @@ -845,6 +846,9 @@ protected: public: + virtual const TargetSubtarget *getSubtarget() { + assert(0 && "Not Implemented"); + } //===--------------------------------------------------------------------===// // Lowering methods - These methods must be implemented by targets so that // the SelectionDAGLowering code knows how to lower these. @@ -878,6 +882,18 @@ public: bool isVarArg, unsigned CallingConv, bool isTailCall, SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG); + + virtual SDOperand LowerMEMCPY(SDOperand Op, SelectionDAG &DAG); + virtual SDOperand LowerMEMCPYCall(SDOperand Chain, SDOperand Dest, + SDOperand Source, SDOperand Count, + SelectionDAG &DAG); + virtual SDOperand LowerMEMCPYInline(SDOperand Chain, SDOperand Dest, + SDOperand Source, unsigned Size, + unsigned Align, SelectionDAG &DAG) { + assert(0 && "Not Implemented"); + } + + /// LowerOperation - This callback is invoked for operations that are /// unsupported by the target, which are registered to use 'custom' lowering, /// and whose defined values are all legal. diff --git a/include/llvm/Target/TargetSubtarget.h b/include/llvm/Target/TargetSubtarget.h index 3b174c2ee46..1185b09bd99 100644 --- a/include/llvm/Target/TargetSubtarget.h +++ b/include/llvm/Target/TargetSubtarget.h @@ -28,6 +28,9 @@ class TargetSubtarget { protected: // Can only create subclasses... TargetSubtarget(); public: + /// getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size + /// that still makes it profitable to inline the call. + virtual unsigned getMaxInlineSizeThreshold() const {return 0; } virtual ~TargetSubtarget(); }; diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 9309cf46bd2..3708b1cb9a7 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetSubtarget.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/MRegisterInfo.h" @@ -21,6 +22,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/MathExtras.h" #include "llvm/Target/TargetAsmInfo.h" +#include "llvm/CallingConv.h" using namespace llvm; /// InitLibcallNames - Set default libcall names. @@ -194,6 +196,59 @@ TargetLowering::TargetLowering(TargetMachine &tm) TargetLowering::~TargetLowering() {} + +SDOperand TargetLowering::LowerMEMCPY(SDOperand Op, SelectionDAG &DAG) { + assert(getSubtarget() && "Subtarget not defined"); + SDOperand ChainOp = Op.getOperand(0); + SDOperand DestOp = Op.getOperand(1); + SDOperand SourceOp = Op.getOperand(2); + SDOperand CountOp = Op.getOperand(3); + SDOperand AlignOp = Op.getOperand(4); + SDOperand AlwaysInlineOp = Op.getOperand(5); + + bool AlwaysInline = (bool)cast(AlwaysInlineOp)->getValue(); + unsigned Align = (unsigned)cast(AlignOp)->getValue(); + if (Align == 0) Align = 1; + + // If size is unknown, call memcpy. + ConstantSDNode *I = dyn_cast(CountOp); + if (!I) { + assert(!AlwaysInline && "Cannot inline copy of unknown size"); + return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG); + } + + // If not DWORD aligned or if size is more than threshold, then call memcpy. + // 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 + unsigned Size = I->getValue(); + if (AlwaysInline || + (Size <= getSubtarget()->getMaxInlineSizeThreshold() && + (Align & 3) == 0)) + return LowerMEMCPYInline(ChainOp, DestOp, SourceOp, Size, Align, DAG); + return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG); +} + + +SDOperand TargetLowering::LowerMEMCPYCall(SDOperand Chain, + SDOperand Dest, + SDOperand Source, + SDOperand Count, + SelectionDAG &DAG) { + MVT::ValueType IntPtr = getPointerTy(); + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + Entry.Ty = getTargetData()->getIntPtrType(); + Entry.Node = Dest; Args.push_back(Entry); + Entry.Node = Source; Args.push_back(Entry); + Entry.Node = Count; Args.push_back(Entry); + std::pair CallResult = + LowerCallTo(Chain, Type::VoidTy, false, false, CallingConv::C, false, + DAG.getExternalSymbol("memcpy", IntPtr), Args, DAG); + return CallResult.second; +} + + /// computeRegisterProperties - Once all of the register classes are added, /// this allows us to compute derived properties we expose. void TargetLowering::computeRegisterProperties() { diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index b7e37660a7b..bc2c7c3e1ef 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -1287,55 +1287,6 @@ static SDOperand LowerSRx(SDOperand Op, SelectionDAG &DAG, return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi); } -SDOperand ARMTargetLowering::LowerMEMCPY(SDOperand Op, SelectionDAG &DAG) { - SDOperand ChainOp = Op.getOperand(0); - SDOperand DestOp = Op.getOperand(1); - SDOperand SourceOp = Op.getOperand(2); - SDOperand CountOp = Op.getOperand(3); - SDOperand AlignOp = Op.getOperand(4); - SDOperand AlwaysInlineOp = Op.getOperand(5); - - bool AlwaysInline = (bool)cast(AlwaysInlineOp)->getValue(); - unsigned Align = (unsigned)cast(AlignOp)->getValue(); - if (Align == 0) Align = 1; - - // If size is unknown, call memcpy. - ConstantSDNode *I = dyn_cast(CountOp); - if (!I) { - assert(!AlwaysInline && "Cannot inline copy of unknown size"); - return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG); - } - - // If not DWORD aligned or if size is more than threshold, then call memcpy. - // The libc version is likely to be faster for the these 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 - unsigned Size = I->getValue(); - if (AlwaysInline || - (Size <= Subtarget->getMaxInlineSizeThreshold() && - (Align & 3) == 0)) - return LowerMEMCPYInline(ChainOp, DestOp, SourceOp, Size, Align, DAG); - return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG); -} - -SDOperand ARMTargetLowering::LowerMEMCPYCall(SDOperand Chain, - SDOperand Dest, - SDOperand Source, - SDOperand Count, - SelectionDAG &DAG) { - MVT::ValueType IntPtr = getPointerTy(); - TargetLowering::ArgListTy Args; - TargetLowering::ArgListEntry Entry; - Entry.Ty = getTargetData()->getIntPtrType(); - Entry.Node = Dest; Args.push_back(Entry); - Entry.Node = Source; Args.push_back(Entry); - Entry.Node = Count; Args.push_back(Entry); - std::pair CallResult = - LowerCallTo(Chain, Type::VoidTy, false, false, CallingConv::C, false, - DAG.getExternalSymbol("memcpy", IntPtr), Args, DAG); - return CallResult.second; -} - SDOperand ARMTargetLowering::LowerMEMCPYInline(SDOperand Chain, SDOperand Dest, SDOperand Source, diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index 41045e75696..e6fb9458b6c 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -15,13 +15,13 @@ #ifndef ARMISELLOWERING_H #define ARMISELLOWERING_H +#include "ARMSubtarget.h" #include "llvm/Target/TargetLowering.h" #include "llvm/CodeGen/SelectionDAG.h" #include namespace llvm { class ARMConstantPoolValue; - class ARMSubtarget; namespace ARMISD { // ARM Specific DAG Nodes @@ -114,6 +114,11 @@ namespace llvm { std::vector getRegClassForInlineAsmConstraint(const std::string &Constraint, MVT::ValueType VT) const; + + virtual const TargetSubtarget* getSubtarget() { + return static_cast(Subtarget); + } + private: /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can /// make the right decision when generating code for different targets. @@ -134,10 +139,6 @@ namespace llvm { SDOperand LowerGLOBAL_OFFSET_TABLE(SDOperand Op, SelectionDAG &DAG); SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG); SDOperand LowerBR_JT(SDOperand Op, SelectionDAG &DAG); - SDOperand LowerMEMCPY(SDOperand Op, SelectionDAG &DAG); - SDOperand LowerMEMCPYCall(SDOperand Chain, SDOperand Dest, - SDOperand Source, SDOperand Count, - SelectionDAG &DAG); SDOperand LowerMEMCPYInline(SDOperand Chain, SDOperand Dest, SDOperand Source, unsigned Size, unsigned Align, SelectionDAG &DAG); diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 58004f0201e..e9df3f53375 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -4481,55 +4481,6 @@ SDOperand X86TargetLowering::LowerMEMSET(SDOperand Op, SelectionDAG &DAG) { return Chain; } -SDOperand X86TargetLowering::LowerMEMCPY(SDOperand Op, SelectionDAG &DAG) { - SDOperand ChainOp = Op.getOperand(0); - SDOperand DestOp = Op.getOperand(1); - SDOperand SourceOp = Op.getOperand(2); - SDOperand CountOp = Op.getOperand(3); - SDOperand AlignOp = Op.getOperand(4); - SDOperand AlwaysInlineOp = Op.getOperand(5); - - bool AlwaysInline = (bool)cast(AlwaysInlineOp)->getValue(); - unsigned Align = (unsigned)cast(AlignOp)->getValue(); - if (Align == 0) Align = 1; - - // If size is unknown, call memcpy. - ConstantSDNode *I = dyn_cast(CountOp); - if (!I) { - assert(!AlwaysInline && "Cannot inline copy of unknown size"); - return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG); - } - - // If not DWORD aligned or if size is more than threshold, then call memcpy. - // 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 - unsigned Size = I->getValue(); - if (AlwaysInline || - (Size <= Subtarget->getMaxInlineSizeThreshold() && - (Align & 3) == 0)) - return LowerMEMCPYInline(ChainOp, DestOp, SourceOp, Size, Align, DAG); - return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG); -} - -SDOperand X86TargetLowering::LowerMEMCPYCall(SDOperand Chain, - SDOperand Dest, - SDOperand Source, - SDOperand Count, - SelectionDAG &DAG) { - MVT::ValueType IntPtr = getPointerTy(); - TargetLowering::ArgListTy Args; - TargetLowering::ArgListEntry Entry; - Entry.Ty = getTargetData()->getIntPtrType(); - Entry.Node = Dest; Args.push_back(Entry); - Entry.Node = Source; Args.push_back(Entry); - Entry.Node = Count; Args.push_back(Entry); - std::pair CallResult = - LowerCallTo(Chain, Type::VoidTy, false, false, CallingConv::C, false, - DAG.getExternalSymbol("memcpy", IntPtr), Args, DAG); - return CallResult.second; -} - SDOperand X86TargetLowering::LowerMEMCPYInline(SDOperand Chain, SDOperand Dest, SDOperand Source, diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 2330f98bb8f..4f422a9aae1 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -386,6 +386,10 @@ namespace llvm { SDOperand Ret, SelectionDAG &DAG) const; + virtual const TargetSubtarget* getSubtarget() { + return static_cast(Subtarget); + } + private: /// Subtarget - Keep a pointer to the X86Subtarget around so that we can /// make the right decision when generating code for different targets. @@ -454,10 +458,6 @@ namespace llvm { SDOperand LowerMEMCPYInline(SDOperand Dest, SDOperand Source, SDOperand Chain, unsigned Size, unsigned Align, SelectionDAG &DAG); - SDOperand LowerMEMCPYCall(SDOperand ChainOp, SDOperand DestOp, - SDOperand SourceOp, SDOperand CountOp, - SelectionDAG &DAG); - SDOperand LowerMEMCPY(SDOperand Op, SelectionDAG &DAG); SDOperand LowerJumpTable(SDOperand Op, SelectionDAG &DAG); SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG); SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG); -- 2.34.1