blob: 236622ea1f74b83ebb448795b32d758ac4106f6b [file] [log] [blame]
Andrew Lenharthd97591a2005-10-20 00:29:02 +00001//===-- AlphaISelDAGToDAG.cpp - Alpha pattern matching inst selector ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Andrew Lenharth and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a pattern matching instruction selector for Alpha,
11// converting from a legalized dag to a Alpha dag.
12//
13//===----------------------------------------------------------------------===//
14
15#include "Alpha.h"
16#include "AlphaTargetMachine.h"
17#include "AlphaISelLowering.h"
18#include "llvm/CodeGen/MachineInstrBuilder.h"
19#include "llvm/CodeGen/MachineFunction.h"
20#include "llvm/CodeGen/SSARegMap.h"
21#include "llvm/CodeGen/SelectionDAG.h"
22#include "llvm/CodeGen/SelectionDAGISel.h"
23#include "llvm/Target/TargetOptions.h"
24#include "llvm/ADT/Statistic.h"
25#include "llvm/Constants.h"
26#include "llvm/GlobalValue.h"
27#include "llvm/Support/Debug.h"
28#include "llvm/Support/MathExtras.h"
Andrew Lenharth756fbeb2005-10-22 22:06:58 +000029#include <algorithm>
Andrew Lenharthd97591a2005-10-20 00:29:02 +000030using namespace llvm;
31
32namespace {
33
34 //===--------------------------------------------------------------------===//
35 /// AlphaDAGToDAGISel - Alpha specific code to select Alpha machine
36 /// instructions for SelectionDAG operations.
37 ///
38 class AlphaDAGToDAGISel : public SelectionDAGISel {
39 AlphaTargetLowering AlphaLowering;
40
41 public:
42 AlphaDAGToDAGISel(TargetMachine &TM)
43 : SelectionDAGISel(AlphaLowering), AlphaLowering(TM) {}
44
45 /// getI64Imm - Return a target constant with the specified value, of type
46 /// i64.
Andrew Lenharth756fbeb2005-10-22 22:06:58 +000047 inline SDOperand getI64Imm(int64_t Imm) {
Andrew Lenharthd97591a2005-10-20 00:29:02 +000048 return CurDAG->getTargetConstant(Imm, MVT::i64);
49 }
50
Andrew Lenharthd97591a2005-10-20 00:29:02 +000051 // Select - Convert the specified operand from a target-independent to a
52 // target-specific node if it hasn't already been changed.
53 SDOperand Select(SDOperand Op);
54
55 /// InstructionSelectBasicBlock - This callback is invoked by
56 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
57 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
58
59 virtual const char *getPassName() const {
60 return "Alpha DAG->DAG Pattern Instruction Selection";
61 }
62
63// Include the pieces autogenerated from the target description.
64#include "AlphaGenDAGISel.inc"
65
66private:
Andrew Lenharth756fbeb2005-10-22 22:06:58 +000067 SDOperand getGlobalBaseReg();
68 SDOperand SelectCALL(SDOperand Op);
69
Andrew Lenharthd97591a2005-10-20 00:29:02 +000070 };
71}
72
Andrew Lenharth756fbeb2005-10-22 22:06:58 +000073/// getGlobalBaseReg - Output the instructions required to put the
74/// GOT address into a register.
75///
76SDOperand AlphaDAGToDAGISel::getGlobalBaseReg() {
77 return CurDAG->getRegister(AlphaLowering.getVRegGP(), MVT::i64);
78}
79
Andrew Lenharthd97591a2005-10-20 00:29:02 +000080/// InstructionSelectBasicBlock - This callback is invoked by
81/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
82void AlphaDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
83 DEBUG(BB->dump());
84
Andrew Lenharthd97591a2005-10-20 00:29:02 +000085 // Select target instructions for the DAG.
86 DAG.setRoot(Select(DAG.getRoot()));
87 CodeGenMap.clear();
88 DAG.RemoveDeadNodes();
89
90 // Emit machine code to BB.
91 ScheduleAndEmitDAG(DAG);
92}
93
94// Select - Convert the specified operand from a target-independent to a
95// target-specific node if it hasn't already been changed.
96SDOperand AlphaDAGToDAGISel::Select(SDOperand Op) {
97 SDNode *N = Op.Val;
98 if (N->getOpcode() >= ISD::BUILTIN_OP_END &&
99 N->getOpcode() < AlphaISD::FIRST_NUMBER)
100 return Op; // Already selected.
101
102 // If this has already been converted, use it.
103 std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(Op);
104 if (CGMI != CodeGenMap.end()) return CGMI->second;
105
106 switch (N->getOpcode()) {
107 default: break;
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000108 case ISD::TAILCALL:
109 case ISD::CALL: return SelectCALL(Op);
110
Andrew Lenharthd97591a2005-10-20 00:29:02 +0000111 case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharthd97591a2005-10-20 00:29:02 +0000112 assert(0 && "You want these too?");
113
Andrew Lenharth8b7f14e2005-10-23 03:43:48 +0000114 case ISD::SETCC: {
115 ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
116 assert(MVT::isInteger(N->getOperand(0).getValueType()) && "FP numbers are unnecessary");
117 SDOperand Op1 = Select(N->getOperand(0));
118 SDOperand Op2 = Select(N->getOperand(1));
119 unsigned Opc = Alpha::WTF;
120 int dir;
121 switch (CC) {
122 default: N->dump(); assert(0 && "Unknown integer comparison!");
123 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=1; break;
124 case ISD::SETLT: Opc = Alpha::CMPLT; dir = 1; break;
125 case ISD::SETLE: Opc = Alpha::CMPLE; dir = 1; break;
126 case ISD::SETGT: Opc = Alpha::CMPLT; dir = 0; break;
127 case ISD::SETGE: Opc = Alpha::CMPLE; dir = 0; break;
128 case ISD::SETULT: Opc = Alpha::CMPULT; dir = 1; break;
129 case ISD::SETUGT: Opc = Alpha::CMPULT; dir = 0; break;
130 case ISD::SETULE: Opc = Alpha::CMPULE; dir = 1; break;
131 case ISD::SETUGE: Opc = Alpha::CMPULE; dir = 0; break;
132 case ISD::SETNE: {//Handle this one special
133 SDOperand Tmp = CurDAG->getTargetNode(Alpha::CMPEQ, MVT::i64, Op1, Op2);
134 CurDAG->SelectNodeTo(N, Alpha::CMPEQ, MVT::i64, CurDAG->getRegister(Alpha::R31, MVT::i64), Tmp);
135 return SDOperand(N, 0);
136 }
137 }
138 CurDAG->SelectNodeTo(N, Opc, MVT::i64, dir ? Op1 : Op2, dir ? Op2 : Op1);
139 return SDOperand(N, 0);
140 }
141
142 case ISD::BRCOND: {
143 SDOperand Chain = Select(N->getOperand(0));
144 SDOperand CC = Select(N->getOperand(1));
145 CurDAG->SelectNodeTo(N, Alpha::BNE, MVT::Other, CC, Chain);
146 return SDOperand(N, 0);
147 }
148 case ISD::LOAD:
149 case ISD::EXTLOAD:
150 case ISD::ZEXTLOAD:
151 case ISD::SEXTLOAD: {
152 SDOperand Chain = Select(N->getOperand(0));
153 SDOperand Address = Select(N->getOperand(1));
154 unsigned opcode = N->getOpcode();
155 unsigned Opc = Alpha::WTF;
156 if (opcode == ISD::LOAD)
157 switch (N->getValueType(0)) {
158 default: N->dump(); assert(0 && "Bad load!");
159 case MVT::i64: Opc = Alpha::LDQ; break;
160 case MVT::f64: Opc = Alpha::LDT; break;
161 case MVT::f32: Opc = Alpha::LDS; break;
162 }
163 else
164 switch (cast<VTSDNode>(N->getOperand(3))->getVT()) {
165 default: N->dump(); assert(0 && "Bad sign extend!");
166 case MVT::i32: Opc = Alpha::LDL;
167 assert(opcode != ISD::ZEXTLOAD && "Not sext"); break;
168 case MVT::i16: Opc = Alpha::LDWU;
169 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
170 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
171 case MVT::i8: Opc = Alpha::LDBU;
172 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
173 }
174
175 CurDAG->SelectNodeTo(N, Opc, N->getValueType(0), MVT::Other,
176 getI64Imm(0), Address, Chain);
177 return SDOperand(N, Op.ResNo);
178 }
179
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000180 case ISD::BR: {
181 CurDAG->SelectNodeTo(N, Alpha::BR_DAG, MVT::Other, N->getOperand(1),
182 Select(N->getOperand(0)));
183 return SDOperand(N, 0);
184 }
185
Andrew Lenharthd97591a2005-10-20 00:29:02 +0000186 case ISD::TokenFactor: {
187 SDOperand New;
188 if (N->getNumOperands() == 2) {
189 SDOperand Op0 = Select(N->getOperand(0));
190 SDOperand Op1 = Select(N->getOperand(1));
191 New = CurDAG->getNode(ISD::TokenFactor, MVT::Other, Op0, Op1);
192 } else {
193 std::vector<SDOperand> Ops;
194 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
195 Ops.push_back(Select(N->getOperand(i)));
196 New = CurDAG->getNode(ISD::TokenFactor, MVT::Other, Ops);
197 }
198
199 CodeGenMap[Op] = New;
200 return New;
201 }
202 case ISD::CopyFromReg: {
203 SDOperand Chain = Select(N->getOperand(0));
204 if (Chain == N->getOperand(0)) return Op; // No change
205 SDOperand New = CurDAG->getCopyFromReg(Chain,
206 cast<RegisterSDNode>(N->getOperand(1))->getReg(), N->getValueType(0));
207 return New.getValue(Op.ResNo);
208 }
209 case ISD::CopyToReg: {
210 SDOperand Chain = Select(N->getOperand(0));
211 SDOperand Reg = N->getOperand(1);
212 SDOperand Val = Select(N->getOperand(2));
213 SDOperand New = CurDAG->getNode(ISD::CopyToReg, MVT::Other,
214 Chain, Reg, Val);
215 CodeGenMap[Op] = New;
216 return New;
217 }
218 case ISD::UNDEF:
219 if (N->getValueType(0) == MVT::i64)
220 CurDAG->SelectNodeTo(N, Alpha::IDEF, MVT::i64);
221// else if (N->getValueType(0) == MVT::f32)
222// CurDAG->SelectNodeTo(N, PPC::IMPLICIT_DEF_F4, MVT::f32);
223// else
224// CurDAG->SelectNodeTo(N, PPC::IMPLICIT_DEF_F8, MVT::f64);
225 return SDOperand(N, 0);
226 case ISD::FrameIndex: {
227// int FI = cast<FrameIndexSDNode>(N)->getIndex();
228// CurDAG->SelectNodeTo(N, Alpha::LDA, MVT::i64,
229// CurDAG->getTargetFrameIndex(FI, MVT::i32),
230// getI32Imm(0));
231// return SDOperand(N, 0);
232 assert(0 && "Frame?, you are suppose to look through the window, not at the frame!");
233 }
234 case ISD::ConstantPool: {
235// Constant *C = cast<ConstantPoolSDNode>(N)->get();
236// SDOperand Tmp, CPI = CurDAG->getTargetConstantPool(C, MVT::i32);
237// if (PICEnabled)
238// Tmp = CurDAG->getTargetNode(PPC::ADDIS, MVT::i32, getGlobalBaseReg(),CPI);
239// else
240// Tmp = CurDAG->getTargetNode(PPC::LIS, MVT::i32, CPI);
241// CurDAG->SelectNodeTo(N, PPC::LA, MVT::i32, Tmp, CPI);
242// return SDOperand(N, 0);
243 assert(0 && "Constants are overrated");
244 }
245 case ISD::GlobalAddress: {
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000246 GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
247 SDOperand GA = CurDAG->getTargetGlobalAddress(GV, MVT::i64);
248 CurDAG->SelectNodeTo(N, Alpha::LDQl, MVT::i64, GA, getGlobalBaseReg());
249 return SDOperand(N, 0);
Andrew Lenharthd97591a2005-10-20 00:29:02 +0000250 }
Andrew Lenharth8b7f14e2005-10-23 03:43:48 +0000251 case ISD::ExternalSymbol:
252 CurDAG->SelectNodeTo(N, Alpha::LDQl, MVT::i64,
253 CurDAG->getTargetExternalSymbol(cast<ExternalSymbolSDNode>(N)->getSymbol(), MVT::i64),
254 CurDAG->getRegister(AlphaLowering.getVRegGP(), MVT::i64));
255 return SDOperand(N, 0);
Andrew Lenharthd97591a2005-10-20 00:29:02 +0000256
257 case ISD::CALLSEQ_START:
258 case ISD::CALLSEQ_END: {
259 unsigned Amt = cast<ConstantSDNode>(N->getOperand(1))->getValue();
260 unsigned Opc = N->getOpcode() == ISD::CALLSEQ_START ?
261 Alpha::ADJUSTSTACKDOWN : Alpha::ADJUSTSTACKUP;
262 CurDAG->SelectNodeTo(N, Opc, MVT::Other,
263 getI64Imm(Amt), Select(N->getOperand(0)));
264 return SDOperand(N, 0);
265 }
266 case ISD::RET: {
267 SDOperand Chain = Select(N->getOperand(0)); // Token chain.
268
269 if (N->getNumOperands() == 2) {
270 SDOperand Val = Select(N->getOperand(1));
271 if (N->getOperand(1).getValueType() == MVT::i64) {
272 Chain = CurDAG->getCopyToReg(Chain, Alpha::R0, Val);
273 }
274 }
275 //BuildMI(BB, Alpha::RET, 2, Alpha::R31).addReg(Alpha::R26).addImm(1);
276
277 // FIXME: add restoring of the RA to R26 to the chain
278 // Finally, select this to a ret instruction.
279 CurDAG->SelectNodeTo(N, Alpha::RETDAG, MVT::Other, Chain);
280 return SDOperand(N, 0);
281 }
282
283
284
285 }
286
287 return SelectCode(Op);
288}
289
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000290SDOperand AlphaDAGToDAGISel::SelectCALL(SDOperand Op) {
291 SDNode *N = Op.Val;
292 SDOperand Chain = Select(N->getOperand(0));
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000293 SDOperand Addr = Select(N->getOperand(1));
294
295// unsigned CallOpcode;
296 std::vector<SDOperand> CallOperands;
297 std::vector<MVT::ValueType> TypeOperands;
298
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000299 //grab the arguments
300 for(int i = 2, e = N->getNumOperands(); i < e; ++i) {
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000301 TypeOperands.push_back(N->getOperand(i).getValueType());
Andrew Lenharth8b7f14e2005-10-23 03:43:48 +0000302 CallOperands.push_back(Select(N->getOperand(i)));
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000303 }
Andrew Lenharth8b7f14e2005-10-23 03:43:48 +0000304 int count = N->getNumOperands() - 2;
305
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000306 static const unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
307 Alpha::R19, Alpha::R20, Alpha::R21};
308 static const unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
309 Alpha::F19, Alpha::F20, Alpha::F21};
310
Andrew Lenharth8b7f14e2005-10-23 03:43:48 +0000311 for (int i = 0; i < std::min(6, count); ++i) {
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000312 if (MVT::isInteger(TypeOperands[i])) {
Andrew Lenharth8b7f14e2005-10-23 03:43:48 +0000313 Chain = CurDAG->getCopyToReg(Chain, args_int[i], CallOperands[i]);
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000314 } else {
Andrew Lenharth8b7f14e2005-10-23 03:43:48 +0000315 assert(0 && "No FP support yet");
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000316 }
317 }
318 assert(CallOperands.size() <= 6 && "Too big a call");
319
Andrew Lenharth8b7f14e2005-10-23 03:43:48 +0000320 Chain = CurDAG->getCopyToReg(Chain, Alpha::R27, Addr);
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000321 // Finally, once everything is in registers to pass to the call, emit the
322 // call itself.
Andrew Lenharth8b7f14e2005-10-23 03:43:48 +0000323 Chain = CurDAG->getTargetNode(Alpha::JSRDAG, MVT::Other, Chain );
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000324
325 std::vector<SDOperand> CallResults;
326
327 switch (N->getValueType(0)) {
328 default: assert(0 && "Unexpected ret value!");
329 case MVT::Other: break;
330 case MVT::i64:
Andrew Lenharth8b7f14e2005-10-23 03:43:48 +0000331 Chain = CurDAG->getCopyFromReg(Chain, Alpha::R0, MVT::i64).getValue(1);
Andrew Lenharth756fbeb2005-10-22 22:06:58 +0000332 CallResults.push_back(Chain.getValue(0));
333 break;
334 }
335
336 CallResults.push_back(Chain);
337 for (unsigned i = 0, e = CallResults.size(); i != e; ++i)
338 CodeGenMap[Op.getValue(i)] = CallResults[i];
339 return CallResults[Op.ResNo];
340}
341
342
Andrew Lenharthd97591a2005-10-20 00:29:02 +0000343/// createAlphaISelDag - This pass converts a legalized DAG into a
344/// Alpha-specific DAG, ready for instruction scheduling.
345///
346FunctionPass *llvm::createAlphaISelDag(TargetMachine &TM) {
347 return new AlphaDAGToDAGISel(TM);
348}