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