diff options
author | Richard Osborne <richard@xmos.com> | 2008-11-07 10:59:00 +0000 |
---|---|---|
committer | Richard Osborne <richard@xmos.com> | 2008-11-07 10:59:00 +0000 |
commit | ab8167a19e0999867011e2fa79417203f512f4d3 (patch) | |
tree | f03bc8e40b55feab99b0f32e4428d215fa45f988 /lib/Target/XCore/XCoreISelDAGToDAG.cpp | |
parent | 0f63ae111d5a509911fc61246c1acc62f8c58f18 (diff) | |
download | external_llvm-ab8167a19e0999867011e2fa79417203f512f4d3.zip external_llvm-ab8167a19e0999867011e2fa79417203f512f4d3.tar.gz external_llvm-ab8167a19e0999867011e2fa79417203f512f4d3.tar.bz2 |
Add XCore backend.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58838 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/XCore/XCoreISelDAGToDAG.cpp')
-rw-r--r-- | lib/Target/XCore/XCoreISelDAGToDAG.cpp | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/lib/Target/XCore/XCoreISelDAGToDAG.cpp b/lib/Target/XCore/XCoreISelDAGToDAG.cpp new file mode 100644 index 0000000..338f98e --- /dev/null +++ b/lib/Target/XCore/XCoreISelDAGToDAG.cpp @@ -0,0 +1,228 @@ +//===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an instruction selector for the XCore target. +// +//===----------------------------------------------------------------------===// + +#include "XCore.h" +#include "XCoreISelLowering.h" +#include "XCoreTargetMachine.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Intrinsics.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include <queue> +#include <set> +using namespace llvm; + +/// XCoreDAGToDAGISel - XCore specific code to select XCore machine +/// instructions for SelectionDAG operations. +/// +namespace { + class XCoreDAGToDAGISel : public SelectionDAGISel { + XCoreTargetLowering &Lowering; + const XCoreSubtarget &Subtarget; + + public: + XCoreDAGToDAGISel(XCoreTargetMachine &TM) + : SelectionDAGISel(*TM.getTargetLowering()), + Lowering(*TM.getTargetLowering()), + Subtarget(*TM.getSubtargetImpl()) { } + + SDNode *Select(SDValue Op); + + /// getI32Imm - Return a target constant with the specified value, of type + /// i32. + inline SDValue getI32Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i32); + } + + // Complex Pattern Selectors. + bool SelectADDRspii(SDValue Op, SDValue Addr, SDValue &Base, + SDValue &Offset); + bool SelectADDRdpii(SDValue Op, SDValue Addr, SDValue &Base, + SDValue &Offset); + bool SelectADDRcpii(SDValue Op, SDValue Addr, SDValue &Base, + SDValue &Offset); + + virtual void InstructionSelect(); + + virtual const char *getPassName() const { + return "XCore DAG->DAG Pattern Instruction Selection"; + } + + // Include the pieces autogenerated from the target description. + #include "XCoreGenDAGISel.inc" + }; +} // end anonymous namespace + +/// createXCoreISelDag - This pass converts a legalized DAG into a +/// XCore-specific DAG, ready for instruction scheduling. +/// +FunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM) { + return new XCoreDAGToDAGISel(TM); +} + +bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Op, SDValue Addr, + SDValue &Base, SDValue &Offset) { + FrameIndexSDNode *FIN = 0; + if (FIN = dyn_cast<FrameIndexSDNode>(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + if (Addr.getOpcode() == ISD::ADD) { + ConstantSDNode *CN = 0; + if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) + && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) + && (CN->getSExtValue() % 4 == 0)) { + // Constant word offset from frame pointer + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); + return true; + } + } + return false; +} + +bool XCoreDAGToDAGISel::SelectADDRdpii(SDValue Op, SDValue Addr, + SDValue &Base, SDValue &Offset) { + if (Addr.getOpcode() == XCoreISD::DPRelativeWrapper) { + Base = Addr.getOperand(0); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + if (Addr.getOpcode() == ISD::ADD) { + ConstantSDNode *CN = 0; + if ((Addr.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper) + && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) + && (CN->getSExtValue() % 4 == 0)) { + // Constant word offset from a object in the data region + Base = Addr.getOperand(0).getOperand(0); + Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); + return true; + } + } + return false; +} + +bool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Op, SDValue Addr, + SDValue &Base, SDValue &Offset) { + if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) { + Base = Addr.getOperand(0); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + if (Addr.getOpcode() == ISD::ADD) { + ConstantSDNode *CN = 0; + if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper) + && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) + && (CN->getSExtValue() % 4 == 0)) { + // Constant word offset from a object in the data region + Base = Addr.getOperand(0).getOperand(0); + Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); + return true; + } + } + return false; +} + +/// InstructionSelect - This callback is invoked by +/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. +void XCoreDAGToDAGISel:: +InstructionSelect() { + DEBUG(BB->dump()); + + // Select target instructions for the DAG. + SelectRoot(*CurDAG); + + CurDAG->RemoveDeadNodes(); +} + +SDNode *XCoreDAGToDAGISel::Select(SDValue Op) { + SDNode *N = Op.getNode(); + MVT NVT = N->getValueType(0); + if (NVT == MVT::i32) { + switch (N->getOpcode()) { + default: break; + case ISD::Constant: { + if (Predicate_immMskBitp(N)) { + SDValue MskSize = Transform_msksize_xform(N); + return CurDAG->getTargetNode(XCore::MKMSK_rus, MVT::i32, MskSize); + } + else if (! Predicate_immU16(N)) { + unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); + SDValue CPIdx = + CurDAG->getTargetConstantPool(ConstantInt::get(Type::Int32Ty, Val), + TLI.getPointerTy()); + return CurDAG->getTargetNode(XCore::LDWCP_lru6, MVT::i32, MVT::Other, + CPIdx, CurDAG->getEntryNode()); + } + break; + } + case ISD::SMUL_LOHI: { + // FIXME fold addition into the macc instruction + if (!Subtarget.isXS1A()) { + SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, MVT::i32, + CurDAG->getTargetConstant(0, MVT::i32)), 0); + SDValue Ops[] = { Zero, Zero, Op.getOperand(0), Op.getOperand(1) }; + SDNode *ResNode = CurDAG->getTargetNode(XCore::MACCS_l4r, MVT::i32, + MVT::i32, Ops, 4); + ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1)); + ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0)); + return NULL; + } + break; + } + case ISD::UMUL_LOHI: { + // FIXME fold addition into the macc / lmul instruction + SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, MVT::i32, + CurDAG->getTargetConstant(0, MVT::i32)), 0); + SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), + Zero, Zero }; + SDNode *ResNode = CurDAG->getTargetNode(XCore::LMUL_l6r, MVT::i32, + MVT::i32, Ops, 4); + ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1)); + ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0)); + return NULL; + } + case XCoreISD::LADD: { + if (!Subtarget.isXS1A()) { + SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), + Op.getOperand(2) }; + return CurDAG->getTargetNode(XCore::LADD_l5r, MVT::i32, MVT::i32, + Ops, 3); + } + break; + } + case XCoreISD::LSUB: { + if (!Subtarget.isXS1A()) { + SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), + Op.getOperand(2) }; + return CurDAG->getTargetNode(XCore::LSUB_l5r, MVT::i32, MVT::i32, + Ops, 3); + } + break; + } + // Other cases are autogenerated. + } + } + return SelectCode(Op); +} |