7f6532790c7584562077c4bcf38ae6ef414c321b
[oota-llvm.git] / lib / Target / XCore / XCoreISelDAGToDAG.cpp
1 //===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines an instruction selector for the XCore target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "XCore.h"
15 #include "XCoreISelLowering.h"
16 #include "XCoreTargetMachine.h"
17 #include "llvm/DerivedTypes.h"
18 #include "llvm/Function.h"
19 #include "llvm/Intrinsics.h"
20 #include "llvm/CallingConv.h"
21 #include "llvm/Constants.h"
22 #include "llvm/LLVMContext.h"
23 #include "llvm/CodeGen/MachineFrameInfo.h"
24 #include "llvm/CodeGen/MachineFunction.h"
25 #include "llvm/CodeGen/MachineInstrBuilder.h"
26 #include "llvm/CodeGen/MachineRegisterInfo.h"
27 #include "llvm/CodeGen/SelectionDAG.h"
28 #include "llvm/CodeGen/SelectionDAGISel.h"
29 #include "llvm/Target/TargetLowering.h"
30 #include "llvm/Support/Compiler.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/ErrorHandling.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include <queue>
35 #include <set>
36 using namespace llvm;
37
38 /// XCoreDAGToDAGISel - XCore specific code to select XCore machine
39 /// instructions for SelectionDAG operations.
40 ///
41 namespace {
42   class XCoreDAGToDAGISel : public SelectionDAGISel {
43     XCoreTargetLowering &Lowering;
44     const XCoreSubtarget &Subtarget;
45
46   public:
47     XCoreDAGToDAGISel(XCoreTargetMachine &TM)
48       : SelectionDAGISel(TM),
49         Lowering(*TM.getTargetLowering()), 
50         Subtarget(*TM.getSubtargetImpl()) { }
51
52     SDNode *Select(SDValue Op);
53     
54     /// getI32Imm - Return a target constant with the specified value, of type
55     /// i32.
56     inline SDValue getI32Imm(unsigned Imm) {
57       return CurDAG->getTargetConstant(Imm, MVT::i32);
58     }
59
60     // Complex Pattern Selectors.
61     bool SelectADDRspii(SDValue Op, SDValue Addr, SDValue &Base,
62                         SDValue &Offset);
63     bool SelectADDRdpii(SDValue Op, SDValue Addr, SDValue &Base,
64                         SDValue &Offset);
65     bool SelectADDRcpii(SDValue Op, SDValue Addr, SDValue &Base,
66                         SDValue &Offset);
67     
68     virtual void InstructionSelect();
69
70     virtual const char *getPassName() const {
71       return "XCore DAG->DAG Pattern Instruction Selection";
72     } 
73     
74     // Include the pieces autogenerated from the target description.
75   #include "XCoreGenDAGISel.inc"
76   };
77 }  // end anonymous namespace
78
79 /// createXCoreISelDag - This pass converts a legalized DAG into a 
80 /// XCore-specific DAG, ready for instruction scheduling.
81 ///
82 FunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM) {
83   return new XCoreDAGToDAGISel(TM);
84 }
85
86 bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Op, SDValue Addr,
87                                   SDValue &Base, SDValue &Offset) {
88   FrameIndexSDNode *FIN = 0;
89   if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
90     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
91     Offset = CurDAG->getTargetConstant(0, MVT::i32);
92     return true;
93   }
94   if (Addr.getOpcode() == ISD::ADD) {
95     ConstantSDNode *CN = 0;
96     if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
97       && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
98       && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
99       // Constant positive word offset from frame index
100       Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
101       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
102       return true;
103     }
104   }
105   return false;
106 }
107
108 bool XCoreDAGToDAGISel::SelectADDRdpii(SDValue Op, SDValue Addr,
109                                   SDValue &Base, SDValue &Offset) {
110   if (Addr.getOpcode() == XCoreISD::DPRelativeWrapper) {
111     Base = Addr.getOperand(0);
112     Offset = CurDAG->getTargetConstant(0, MVT::i32);
113     return true;
114   }
115   if (Addr.getOpcode() == ISD::ADD) {
116     ConstantSDNode *CN = 0;
117     if ((Addr.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper)
118       && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
119       && (CN->getSExtValue() % 4 == 0)) {
120       // Constant word offset from a object in the data region
121       Base = Addr.getOperand(0).getOperand(0);
122       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
123       return true;
124     }
125   }
126   return false;
127 }
128
129 bool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Op, SDValue Addr,
130                                   SDValue &Base, SDValue &Offset) {
131   if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) {
132     Base = Addr.getOperand(0);
133     Offset = CurDAG->getTargetConstant(0, MVT::i32);
134     return true;
135   }
136   if (Addr.getOpcode() == ISD::ADD) {
137     ConstantSDNode *CN = 0;
138     if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper)
139       && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
140       && (CN->getSExtValue() % 4 == 0)) {
141       // Constant word offset from a object in the data region
142       Base = Addr.getOperand(0).getOperand(0);
143       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
144       return true;
145     }
146   }
147   return false;
148 }
149
150 /// InstructionSelect - This callback is invoked by
151 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
152 void XCoreDAGToDAGISel::
153 InstructionSelect() {
154   DEBUG(BB->dump());
155
156   // Select target instructions for the DAG.
157   SelectRoot(*CurDAG);
158   
159   CurDAG->RemoveDeadNodes();
160 }
161
162 SDNode *XCoreDAGToDAGISel::Select(SDValue Op) {
163   SDNode *N = Op.getNode();
164   DebugLoc dl = N->getDebugLoc();
165   MVT NVT = N->getValueType(0);
166   if (NVT == MVT::i32) {
167     switch (N->getOpcode()) {
168       default: break;
169       case ISD::Constant: {
170         if (Predicate_immMskBitp(N)) {
171           SDValue MskSize = Transform_msksize_xform(N);
172           return CurDAG->getTargetNode(XCore::MKMSK_rus, dl, MVT::i32, MskSize);
173         }
174         else if (! Predicate_immU16(N)) {
175           unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
176           SDValue CPIdx =
177             CurDAG->getTargetConstantPool(
178                        CurDAG->getContext()->getConstantInt(Type::Int32Ty, Val),
179                                           TLI.getPointerTy());
180           return CurDAG->getTargetNode(XCore::LDWCP_lru6, dl, MVT::i32, 
181                                        MVT::Other, CPIdx, 
182                                        CurDAG->getEntryNode());
183         }
184         break;
185       }
186       case ISD::SMUL_LOHI: {
187         // FIXME fold addition into the macc instruction
188         if (!Subtarget.isXS1A()) {
189           SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, dl, MVT::i32,
190                                   CurDAG->getTargetConstant(0, MVT::i32)), 0);
191           SDValue Ops[] = { Zero, Zero, Op.getOperand(0), Op.getOperand(1) };
192           SDNode *ResNode = CurDAG->getTargetNode(XCore::MACCS_l4r, dl,
193                                                   MVT::i32, MVT::i32, Ops, 4);
194           ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
195           ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
196           return NULL;
197         }
198         break;
199       }
200       case ISD::UMUL_LOHI: {
201         // FIXME fold addition into the macc / lmul instruction
202         SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, dl, MVT::i32,
203                                   CurDAG->getTargetConstant(0, MVT::i32)), 0);
204         SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
205                             Zero, Zero };
206         SDNode *ResNode = CurDAG->getTargetNode(XCore::LMUL_l6r, dl, MVT::i32,
207                                                 MVT::i32, Ops, 4);
208         ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
209         ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
210         return NULL;
211       }
212       case XCoreISD::LADD: {
213         if (!Subtarget.isXS1A()) {
214           SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
215                               Op.getOperand(2) };
216           return CurDAG->getTargetNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32,
217                                        Ops, 3);
218         }
219         break;
220       }
221       case XCoreISD::LSUB: {
222         if (!Subtarget.isXS1A()) {
223           SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
224                               Op.getOperand(2) };
225           return CurDAG->getTargetNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
226                                        Ops, 3);
227         }
228         break;
229       }
230       // Other cases are autogenerated.
231     }
232   }
233   return SelectCode(Op);
234 }