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
This commit is contained in:
Rafael Espindola 2007-11-05 23:12:20 +00:00
parent 0a6d98e10e
commit f1ba1cad38
7 changed files with 84 additions and 107 deletions

View File

@ -41,6 +41,7 @@ namespace llvm {
class MachineBasicBlock; class MachineBasicBlock;
class MachineInstr; class MachineInstr;
class VectorType; class VectorType;
class TargetSubtarget;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// TargetLowering - This class defines information used to lower LLVM code to /// TargetLowering - This class defines information used to lower LLVM code to
@ -845,6 +846,9 @@ protected:
public: public:
virtual const TargetSubtarget *getSubtarget() {
assert(0 && "Not Implemented");
}
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// Lowering methods - These methods must be implemented by targets so that // Lowering methods - These methods must be implemented by targets so that
// the SelectionDAGLowering code knows how to lower these. // the SelectionDAGLowering code knows how to lower these.
@ -878,6 +882,18 @@ public:
bool isVarArg, unsigned CallingConv, bool isTailCall, bool isVarArg, unsigned CallingConv, bool isTailCall,
SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG); 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 /// LowerOperation - This callback is invoked for operations that are
/// unsupported by the target, which are registered to use 'custom' lowering, /// unsupported by the target, which are registered to use 'custom' lowering,
/// and whose defined values are all legal. /// and whose defined values are all legal.

View File

@ -28,6 +28,9 @@ class TargetSubtarget {
protected: // Can only create subclasses... protected: // Can only create subclasses...
TargetSubtarget(); TargetSubtarget();
public: 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(); virtual ~TargetSubtarget();
}; };

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetSubtarget.h"
#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MRegisterInfo.h" #include "llvm/Target/MRegisterInfo.h"
@ -21,6 +22,7 @@
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetAsmInfo.h"
#include "llvm/CallingConv.h"
using namespace llvm; using namespace llvm;
/// InitLibcallNames - Set default libcall names. /// InitLibcallNames - Set default libcall names.
@ -194,6 +196,59 @@ TargetLowering::TargetLowering(TargetMachine &tm)
TargetLowering::~TargetLowering() {} 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<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);
}
// 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<SDOperand,SDOperand> 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, /// computeRegisterProperties - Once all of the register classes are added,
/// this allows us to compute derived properties we expose. /// this allows us to compute derived properties we expose.
void TargetLowering::computeRegisterProperties() { void TargetLowering::computeRegisterProperties() {

View File

@ -1287,55 +1287,6 @@ static SDOperand LowerSRx(SDOperand Op, SelectionDAG &DAG,
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi); 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<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);
}
// 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<SDOperand,SDOperand> 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 ARMTargetLowering::LowerMEMCPYInline(SDOperand Chain,
SDOperand Dest, SDOperand Dest,
SDOperand Source, SDOperand Source,

View File

@ -15,13 +15,13 @@
#ifndef ARMISELLOWERING_H #ifndef ARMISELLOWERING_H
#define ARMISELLOWERING_H #define ARMISELLOWERING_H
#include "ARMSubtarget.h"
#include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetLowering.h"
#include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAG.h"
#include <vector> #include <vector>
namespace llvm { namespace llvm {
class ARMConstantPoolValue; class ARMConstantPoolValue;
class ARMSubtarget;
namespace ARMISD { namespace ARMISD {
// ARM Specific DAG Nodes // ARM Specific DAG Nodes
@ -114,6 +114,11 @@ namespace llvm {
std::vector<unsigned> std::vector<unsigned>
getRegClassForInlineAsmConstraint(const std::string &Constraint, getRegClassForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const; MVT::ValueType VT) const;
virtual const TargetSubtarget* getSubtarget() {
return static_cast<const TargetSubtarget*>(Subtarget);
}
private: private:
/// Subtarget - Keep a pointer to the ARMSubtarget around so that we can /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
/// make the right decision when generating code for different targets. /// 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 LowerGLOBAL_OFFSET_TABLE(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG); SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerBR_JT(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 LowerMEMCPYInline(SDOperand Chain, SDOperand Dest,
SDOperand Source, unsigned Size, SDOperand Source, unsigned Size,
unsigned Align, SelectionDAG &DAG); unsigned Align, SelectionDAG &DAG);

View File

@ -4481,55 +4481,6 @@ SDOperand X86TargetLowering::LowerMEMSET(SDOperand Op, SelectionDAG &DAG) {
return Chain; 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<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);
}
// 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<SDOperand,SDOperand> 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 X86TargetLowering::LowerMEMCPYInline(SDOperand Chain,
SDOperand Dest, SDOperand Dest,
SDOperand Source, SDOperand Source,

View File

@ -386,6 +386,10 @@ namespace llvm {
SDOperand Ret, SDOperand Ret,
SelectionDAG &DAG) const; SelectionDAG &DAG) const;
virtual const TargetSubtarget* getSubtarget() {
return static_cast<const TargetSubtarget*>(Subtarget);
}
private: private:
/// Subtarget - Keep a pointer to the X86Subtarget around so that we can /// Subtarget - Keep a pointer to the X86Subtarget around so that we can
/// make the right decision when generating code for different targets. /// make the right decision when generating code for different targets.
@ -454,10 +458,6 @@ namespace llvm {
SDOperand LowerMEMCPYInline(SDOperand Dest, SDOperand Source, SDOperand LowerMEMCPYInline(SDOperand Dest, SDOperand Source,
SDOperand Chain, unsigned Size, unsigned Align, SDOperand Chain, unsigned Size, unsigned Align,
SelectionDAG &DAG); 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 LowerJumpTable(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG); SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG); SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG);