blob: 6165d584bf85a00f1f626911073da5e79a683c81 [file] [log] [blame]
Bruno Cardoso Lopes972f5892007-06-06 07:42:06 +00001//===-- MipsISelDAGToDAG.cpp - A dag to dag inst selector for Mips --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Bruno Cardoso Lopes is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an instruction selector for the MIPS target.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "mips-isel"
15
16#include "Mips.h"
17#include "MipsISelLowering.h"
Bruno Cardoso Lopesc7db5612007-11-05 03:02:32 +000018#include "MipsMachineFunction.h"
Bruno Cardoso Lopes972f5892007-06-06 07:42:06 +000019#include "MipsRegisterInfo.h"
20#include "MipsSubtarget.h"
21#include "MipsTargetMachine.h"
22#include "llvm/GlobalValue.h"
23#include "llvm/Instructions.h"
24#include "llvm/Intrinsics.h"
25#include "llvm/Support/CFG.h"
26#include "llvm/Type.h"
27#include "llvm/CodeGen/MachineConstantPool.h"
28#include "llvm/CodeGen/MachineFunction.h"
29#include "llvm/CodeGen/MachineFrameInfo.h"
30#include "llvm/CodeGen/MachineInstrBuilder.h"
31#include "llvm/CodeGen/SelectionDAGISel.h"
32#include "llvm/Target/TargetMachine.h"
33#include "llvm/Support/Compiler.h"
34#include "llvm/Support/Debug.h"
35#include <queue>
36#include <set>
37
38using namespace llvm;
39
40//===----------------------------------------------------------------------===//
41// Instruction Selector Implementation
42//===----------------------------------------------------------------------===//
43
44//===----------------------------------------------------------------------===//
45// MipsDAGToDAGISel - MIPS specific code to select MIPS machine
46// instructions for SelectionDAG operations.
47//===----------------------------------------------------------------------===//
48namespace {
49
50class VISIBILITY_HIDDEN MipsDAGToDAGISel : public SelectionDAGISel {
51
52 /// TM - Keep a reference to MipsTargetMachine.
53 MipsTargetMachine &TM;
54
55 /// MipsLowering - This object fully describes how to lower LLVM code to an
56 /// Mips-specific SelectionDAG.
57 MipsTargetLowering MipsLowering;
58
59 /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can
60 /// make the right decision when generating code for different targets.
61 //TODO: add initialization on constructor
62 //const MipsSubtarget *Subtarget;
63
64public:
65 MipsDAGToDAGISel(MipsTargetMachine &tm) :
66 SelectionDAGISel(MipsLowering),
67 TM(tm), MipsLowering(*TM.getTargetLowering()) {}
68
69 virtual void InstructionSelectBasicBlock(SelectionDAG &SD);
70
71 // Pass Name
72 virtual const char *getPassName() const {
73 return "MIPS DAG->DAG Pattern Instruction Selection";
74 }
75
76
77private:
78 // Include the pieces autogenerated from the target description.
79 #include "MipsGenDAGISel.inc"
80
81 SDNode *Select(SDOperand N);
82
83 // Complex Pattern.
84 bool SelectAddr(SDOperand Op, SDOperand N,
85 SDOperand &Base, SDOperand &Offset);
86
87
88 // getI32Imm - Return a target constant with the specified
89 // value, of type i32.
90 inline SDOperand getI32Imm(unsigned Imm) {
91 return CurDAG->getTargetConstant(Imm, MVT::i32);
92 }
93
94
95 #ifndef NDEBUG
96 unsigned Indent;
97 #endif
98};
99
100}
101
102/// InstructionSelectBasicBlock - This callback is invoked by
103/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
104void MipsDAGToDAGISel::
105InstructionSelectBasicBlock(SelectionDAG &SD)
106{
107 DEBUG(BB->dump());
108 // Codegen the basic block.
109 #ifndef NDEBUG
110 DOUT << "===== Instruction selection begins:\n";
111 Indent = 0;
112 #endif
113
114 // Select target instructions for the DAG.
115 SD.setRoot(SelectRoot(SD.getRoot()));
116
117 #ifndef NDEBUG
118 DOUT << "===== Instruction selection ends:\n";
119 #endif
120
121 SD.RemoveDeadNodes();
122
123 // Emit machine code to BB.
124 ScheduleAndEmitDAG(SD);
125}
126
127/// ComplexPattern used on MipsInstrInfo
128/// Used on Mips Load/Store instructions
129bool MipsDAGToDAGISel::
130SelectAddr(SDOperand Op, SDOperand Addr, SDOperand &Offset, SDOperand &Base)
131{
132 // if Address is FI, get the TargetFrameIndex.
133 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
134 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
135 Offset = CurDAG->getTargetConstant(0, MVT::i32);
136 return true;
137 }
138
Bruno Cardoso Lopesc7db5612007-11-05 03:02:32 +0000139 // on PIC code Load GA
140 if (TM.getRelocationModel() == Reloc::PIC_) {
141 if (Addr.getOpcode() == ISD::TargetGlobalAddress) {
142 Base = CurDAG->getRegister(Mips::GP, MVT::i32);
143 Offset = Addr;
144 return true;
145 }
146 } else {
147 if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
148 Addr.getOpcode() == ISD::TargetGlobalAddress))
149 return false;
150 }
Bruno Cardoso Lopes972f5892007-06-06 07:42:06 +0000151
Bruno Cardoso Lopes7ff6fa22007-08-18 02:16:30 +0000152 // Operand is a result from an ADD.
Bruno Cardoso Lopesc7db5612007-11-05 03:02:32 +0000153 if (Addr.getOpcode() == ISD::ADD) {
154 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
155 if (Predicate_immSExt16(CN)) {
156
Bruno Cardoso Lopes972f5892007-06-06 07:42:06 +0000157 // If the first operand is a FI, get the TargetFI Node
158 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
159 (Addr.getOperand(0))) {
160 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
161 } else {
162 Base = Addr.getOperand(0);
163 }
164
165 Offset = CurDAG->getTargetConstant(CN->getValue(), MVT::i32);
166 return true;
167 }
168 }
169 }
170
Bruno Cardoso Lopesa4e82002007-07-11 23:24:41 +0000171 Base = Addr;
Bruno Cardoso Lopes972f5892007-06-06 07:42:06 +0000172 Offset = CurDAG->getTargetConstant(0, MVT::i32);
173 return true;
174}
175
176/// Select instructions not customized! Used for
177/// expanded, promoted and normal instructions
178SDNode* MipsDAGToDAGISel::
179Select(SDOperand N)
180{
181 SDNode *Node = N.Val;
182 unsigned Opcode = Node->getOpcode();
183
184 // Dump information about the Node being selected
185 #ifndef NDEBUG
186 DOUT << std::string(Indent, ' ') << "Selecting: ";
187 DEBUG(Node->dump(CurDAG));
188 DOUT << "\n";
189 Indent += 2;
190 #endif
191
192 // If we have a custom node, we already have selected!
193 if (Opcode >= ISD::BUILTIN_OP_END && Opcode < MipsISD::FIRST_NUMBER) {
194 #ifndef NDEBUG
195 DOUT << std::string(Indent-2, ' ') << "== ";
196 DEBUG(Node->dump(CurDAG));
197 DOUT << "\n";
198 Indent -= 2;
199 #endif
200 return NULL;
201 }
202
203 ///
Bruno Cardoso Lopesb42abeb2007-09-24 20:15:11 +0000204 // Instruction Selection not handled by the auto-generated
205 // tablegen selection should be handled here.
Bruno Cardoso Lopes972f5892007-06-06 07:42:06 +0000206 ///
207 switch(Opcode) {
208
209 default: break;
210
211 /// Special Mul operations
212 case ISD::MULHS:
213 case ISD::MULHU: {
214 SDOperand MulOp1 = Node->getOperand(0);
215 SDOperand MulOp2 = Node->getOperand(1);
216 AddToISelQueue(MulOp1);
217 AddToISelQueue(MulOp2);
218
219 unsigned MulOp = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT);
220 SDNode *MulNode = CurDAG->getTargetNode(MulOp, MVT::Flag, MulOp1, MulOp2);
221
222 SDOperand MFInFlag = SDOperand(MulNode, 0);
223 return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag);
224 }
225
226 /// Div operations
227 case ISD::SDIV:
228 case ISD::UDIV: {
229 SDOperand DivOp1 = Node->getOperand(0);
230 SDOperand DivOp2 = Node->getOperand(1);
231 AddToISelQueue(DivOp1);
232 AddToISelQueue(DivOp2);
233
234 unsigned DivOp = (Opcode == ISD::SDIV ? Mips::DIV : Mips::DIVu);
235 SDNode *DivNode = CurDAG->getTargetNode(DivOp, MVT::Flag, DivOp1, DivOp2);
236
237 SDOperand MFInFlag = SDOperand(DivNode, 0);
238 return CurDAG->getTargetNode(Mips::MFLO, MVT::i32, MFInFlag);
239 }
240
241 /// Rem operations
242 case ISD::SREM:
243 case ISD::UREM: {
244 SDOperand RemOp1 = Node->getOperand(0);
245 SDOperand RemOp2 = Node->getOperand(1);
246 AddToISelQueue(RemOp1);
247 AddToISelQueue(RemOp2);
248
249 unsigned RemOp = (Opcode == ISD::SREM ? Mips::DIV : Mips::DIVu);
250 SDNode *RemNode = CurDAG->getTargetNode(RemOp, MVT::Flag, RemOp1, RemOp2);
251
252 SDOperand MFInFlag = SDOperand(RemNode, 0);
253 return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag);
254 }
Bruno Cardoso Lopesc7db5612007-11-05 03:02:32 +0000255
256 /// Handle direct and indirect calls when using PIC. On PIC, when
257 /// GOT is smaller than about 64k (small code) the GA target is
258 /// loaded with only one instruction. Otherwise GA's target must
259 /// be loaded with 3 instructions.
260 case MipsISD::JmpLink: {
261 if (TM.getRelocationModel() == Reloc::PIC_) {
262 //bool isCodeLarge = (TM.getCodeModel() == CodeModel::Large);
263 SDOperand Chain = Node->getOperand(0);
264 SDOperand Callee = Node->getOperand(1);
265 AddToISelQueue(Chain);
266 SDOperand T9Reg = CurDAG->getRegister(Mips::T9, MVT::i32);
267 SDOperand InFlag(0, 0);
268
269 if ( (isa<GlobalAddressSDNode>(Callee)) ||
270 (isa<ExternalSymbolSDNode>(Callee)) )
271 {
272 /// Direct call for global addresses and external symbols
273 SDOperand GPReg = CurDAG->getRegister(Mips::GP, MVT::i32);
274
275 // Use load to get GOT target
276 SDOperand Ops[] = { Callee, GPReg, Chain };
277 SDOperand Load = SDOperand(CurDAG->getTargetNode(Mips::LW, MVT::i32,
278 MVT::Other, Ops, 3), 0);
279 Chain = Load.getValue(1);
280 AddToISelQueue(Chain);
281
282 // Call target must be on T9
283 Chain = CurDAG->getCopyToReg(Chain, T9Reg, Load, InFlag);
284 } else
285 /// Indirect call
286 Chain = CurDAG->getCopyToReg(Chain, T9Reg, Callee, InFlag);
287
288 AddToISelQueue(Chain);
289
290 // Emit Jump and Link Register
291 SDNode *ResNode = CurDAG->getTargetNode(Mips::JALR, MVT::Other,
292 MVT::Flag, T9Reg, Chain);
293 Chain = SDOperand(ResNode, 0);
294 InFlag = SDOperand(ResNode, 1);
295 ReplaceUses(SDOperand(Node, 0), Chain);
296 ReplaceUses(SDOperand(Node, 1), InFlag);
297 return ResNode;
298 }
299 }
Bruno Cardoso Lopes972f5892007-06-06 07:42:06 +0000300 }
301
302 // Select the default instruction
303 SDNode *ResNode = SelectCode(N);
304
305 #ifndef NDEBUG
306 DOUT << std::string(Indent-2, ' ') << "=> ";
307 if (ResNode == NULL || ResNode == N.Val)
308 DEBUG(N.Val->dump(CurDAG));
309 else
310 DEBUG(ResNode->dump(CurDAG));
311 DOUT << "\n";
312 Indent -= 2;
313 #endif
314
315 return ResNode;
316}
317
318/// createMipsISelDag - This pass converts a legalized DAG into a
319/// MIPS-specific DAG, ready for instruction scheduling.
320FunctionPass *llvm::createMipsISelDag(MipsTargetMachine &TM) {
321 return new MipsDAGToDAGISel(TM);
322}