class MachineBasicBlock;
class MachineInstr;
class VectorType;
+ class TargetSubtarget;
//===----------------------------------------------------------------------===//
/// TargetLowering - This class defines information used to lower LLVM code to
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.
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.
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();
};
//===----------------------------------------------------------------------===//
#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"
#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.
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,
/// this allows us to compute derived properties we expose.
void TargetLowering::computeRegisterProperties() {
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 Dest,
SDOperand Source,
#ifndef ARMISELLOWERING_H
#define ARMISELLOWERING_H
+#include "ARMSubtarget.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include <vector>
namespace llvm {
class ARMConstantPoolValue;
- class ARMSubtarget;
namespace ARMISD {
// ARM Specific DAG Nodes
std::vector<unsigned>
getRegClassForInlineAsmConstraint(const std::string &Constraint,
MVT::ValueType VT) const;
+
+ virtual const TargetSubtarget* getSubtarget() {
+ return static_cast<const TargetSubtarget*>(Subtarget);
+ }
+
private:
/// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
/// make the right decision when generating code for different targets.
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);
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 Dest,
SDOperand Source,
SDOperand Ret,
SelectionDAG &DAG) const;
+ virtual const TargetSubtarget* getSubtarget() {
+ return static_cast<const TargetSubtarget*>(Subtarget);
+ }
+
private:
/// Subtarget - Keep a pointer to the X86Subtarget around so that we can
/// make the right decision when generating code for different targets.
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);