summaryrefslogtreecommitdiff
path: root/lib/Target/XCore/XCoreISelDAGToDAG.cpp
diff options
context:
space:
mode:
authorRichard Osborne <richard@xmos.com>2008-11-07 10:59:00 +0000
committerRichard Osborne <richard@xmos.com>2008-11-07 10:59:00 +0000
commitb25baef26f03b9909b65dd5f762b38f93000445d (patch)
treef03bc8e40b55feab99b0f32e4428d215fa45f988 /lib/Target/XCore/XCoreISelDAGToDAG.cpp
parent4df60f5491ff35c8a48c2cf14e18a33c9793b3bb (diff)
downloadllvm-b25baef26f03b9909b65dd5f762b38f93000445d.tar.gz
llvm-b25baef26f03b9909b65dd5f762b38f93000445d.tar.bz2
llvm-b25baef26f03b9909b65dd5f762b38f93000445d.tar.xz
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.cpp228
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 0000000000..338f98e385
--- /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);
+}