blob: e6efc030cc138fda85c24200bd6a48a95844568d [file] [log] [blame]
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001//===- AlphaISelPattern.cpp - A pattern matching inst selector for Alpha -===//
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group 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//
12//===----------------------------------------------------------------------===//
13
14#include "Alpha.h"
Andrew Lenharth304d0f32005-01-22 23:41:55 +000015#include "AlphaRegisterInfo.h"
16#include "llvm/Constants.h" // FIXME: REMOVE
17#include "llvm/Function.h"
18#include "llvm/CodeGen/MachineInstrBuilder.h"
19#include "llvm/CodeGen/MachineConstantPool.h" // FIXME: REMOVE
20#include "llvm/CodeGen/MachineFunction.h"
21#include "llvm/CodeGen/MachineFrameInfo.h"
22#include "llvm/CodeGen/SelectionDAG.h"
23#include "llvm/CodeGen/SelectionDAGISel.h"
24#include "llvm/CodeGen/SSARegMap.h"
25#include "llvm/Target/TargetData.h"
26#include "llvm/Target/TargetLowering.h"
27#include "llvm/Support/MathExtras.h"
28#include "llvm/ADT/Statistic.h"
29#include <set>
30using namespace llvm;
31
32//===----------------------------------------------------------------------===//
33// AlphaTargetLowering - Alpha Implementation of the TargetLowering interface
34namespace {
35 class AlphaTargetLowering : public TargetLowering {
36 int VarArgsFrameIndex; // FrameIndex for start of varargs area.
37 unsigned GP; //GOT vreg
38 public:
39 AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) {
40 // Set up the TargetLowering object.
Andrew Lenharth3d65d312005-01-27 03:49:45 +000041 //I am having problems with shr n ubyte 1
42 setShiftAmountType(MVT::i64); //are these needed?
43 setSetCCResultType(MVT::i64); //are these needed?
44
Andrew Lenharth304d0f32005-01-22 23:41:55 +000045 addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass);
46 addRegisterClass(MVT::f64, Alpha::FPRCRegisterClass);
Andrew Lenharth3d65d312005-01-27 03:49:45 +000047 addRegisterClass(MVT::f32, Alpha::FPRCRegisterClass);
Andrew Lenharth304d0f32005-01-22 23:41:55 +000048
Andrew Lenharthd2bb9602005-01-27 07:50:35 +000049 setOperationAction(ISD::EXTLOAD , MVT::i1 , Promote);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000050
Andrew Lenharth3d65d312005-01-27 03:49:45 +000051 setOperationAction(ISD::ZEXTLOAD , MVT::i1 , Expand); //Should this be Promote? Chris?
Andrew Lenharth304d0f32005-01-22 23:41:55 +000052 setOperationAction(ISD::ZEXTLOAD , MVT::i32 , Expand);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000053
Andrew Lenharth3d65d312005-01-27 03:49:45 +000054 setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand); //Should this be Promote? Chris?
Andrew Lenharth304d0f32005-01-22 23:41:55 +000055 setOperationAction(ISD::SEXTLOAD , MVT::i8 , Expand);
56 setOperationAction(ISD::SEXTLOAD , MVT::i16 , Expand);
57
Andrew Lenharth3d65d312005-01-27 03:49:45 +000058 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); //what is the sign expansion of 1? 1 or -1?
Andrew Lenharth02981182005-01-26 01:24:38 +000059
Andrew Lenharth3d65d312005-01-27 03:49:45 +000060 setOperationAction(ISD::SREM, MVT::f32, Expand);
61 setOperationAction(ISD::SREM, MVT::f64, Expand);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +000062
Andrew Lenharth3d65d312005-01-27 03:49:45 +000063 computeRegisterProperties();
Andrew Lenharth304d0f32005-01-22 23:41:55 +000064
Andrew Lenharthd2bb9602005-01-27 07:50:35 +000065 addLegalFPImmediate(+0.0); //F31
Andrew Lenharth304d0f32005-01-22 23:41:55 +000066 }
67
68 /// LowerArguments - This hook must be implemented to indicate how we should
69 /// lower the arguments for the specified function, into the specified DAG.
70 virtual std::vector<SDOperand>
71 LowerArguments(Function &F, SelectionDAG &DAG);
72
73 /// LowerCallTo - This hook lowers an abstract call to a function into an
74 /// actual call.
75 virtual std::pair<SDOperand, SDOperand>
76 LowerCallTo(SDOperand Chain, const Type *RetTy, SDOperand Callee,
77 ArgListTy &Args, SelectionDAG &DAG);
78
79 virtual std::pair<SDOperand, SDOperand>
80 LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
81
82 virtual std::pair<SDOperand,SDOperand>
83 LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
84 const Type *ArgTy, SelectionDAG &DAG);
85
86 virtual std::pair<SDOperand, SDOperand>
87 LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
88 SelectionDAG &DAG);
89
90 void restoreGP(MachineBasicBlock* BB)
91 {
92 BuildMI(BB, Alpha::BIS, 2, Alpha::R29).addReg(GP).addReg(GP);
93 }
94 };
95}
96
97//http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PY8AC-TET1_html/callCH3.html#BLOCK21
98
99//For now, just use variable size stack frame format
100
101//In a standard call, the first six items are passed in registers $16
102//- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
103//of argument-to-register correspondence.) The remaining items are
104//collected in a memory argument list that is a naturally aligned
105//array of quadwords. In a standard call, this list, if present, must
106//be passed at 0(SP).
107//7 ... n 0(SP) ... (n-7)*8(SP)
108
109std::vector<SDOperand>
110AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
111{
112 std::vector<SDOperand> ArgValues;
113
114 // //#define FP $15
115 // //#define RA $26
116 // //#define PV $27
117 // //#define GP $29
118 // //#define SP $30
119
120 // assert(0 && "TODO");
121 MachineFunction &MF = DAG.getMachineFunction();
122 MachineFrameInfo *MFI = MF.getFrameInfo();
123
124 GP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
125 MachineBasicBlock& BB = MF.front();
126
127 //Handle the return address
128 //BuildMI(&BB, Alpha::IDEF, 0, Alpha::R26);
129
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000130 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
131 Alpha::R19, Alpha::R20, Alpha::R21};
132 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
133 Alpha::F19, Alpha::F20, Alpha::F21};
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000134 std::vector<unsigned> argVreg;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000135 std::vector<unsigned> argPreg;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000136 std::vector<unsigned> argOpc;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000137 int count = 0;
138 for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I)
139 {
Andrew Lenharth40831c52005-01-28 06:57:18 +0000140 SDOperand newroot, argt;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000141 ++count;
142 assert(count <= 6 && "More than 6 args not supported");
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000143 switch (getValueType(I->getType())) {
144 default: std::cerr << "Unknown Type " << getValueType(I->getType()) << "\n"; abort();
145 case MVT::f64:
146 case MVT::f32:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000147 BuildMI(&BB, Alpha::IDEF, 0, args_float[count - 1]);
148 argVreg.push_back(MF.getSSARegMap()->createVirtualRegister(getRegClassFor(getValueType(I->getType()))));
149 argPreg.push_back(args_float[count - 1]);
150 argOpc.push_back(Alpha::CPYS);
151 newroot = DAG.getCopyFromReg(argVreg[count], getValueType(I->getType()), DAG.getRoot());
152 break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000153 case MVT::i1:
154 case MVT::i8:
155 case MVT::i16:
156 case MVT::i32:
157 case MVT::i64:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000158 BuildMI(&BB, Alpha::IDEF, 0, args_int[count - 1]);
159 argVreg.push_back(MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64)));
160 argPreg.push_back(args_int[count - 1]);
161 argOpc.push_back(Alpha::BIS);
162 argt = newroot = DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot());
163 if (getValueType(I->getType()) != MVT::i64)
164 argt = DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()), newroot);
165 break;
166 }
167 DAG.setRoot(newroot.getValue(1));
168 ArgValues.push_back(argt);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000169 }
170
171 BuildMI(&BB, Alpha::IDEF, 0, Alpha::R29);
172 BuildMI(&BB, Alpha::BIS, 2, GP).addReg(Alpha::R29).addReg(Alpha::R29);
173 count = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000174 for (int i = 0; i < count; ++i)
175 BuildMI(&BB, argOpc[i], 2, argVreg[i]).addReg(argPreg[i]).addReg(argPreg[i]);
176
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000177 return ArgValues;
178}
179
180std::pair<SDOperand, SDOperand>
181AlphaTargetLowering::LowerCallTo(SDOperand Chain,
182 const Type *RetTy, SDOperand Callee,
183 ArgListTy &Args, SelectionDAG &DAG) {
184 int NumBytes = 0;
185 Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
186 DAG.getConstant(NumBytes, getPointerTy()));
187 std::vector<SDOperand> args_to_use;
188 for (unsigned i = 0, e = Args.size(); i != e; ++i)
189 {
190 switch (getValueType(Args[i].second)) {
191 default: assert(0 && "Unexpected ValueType for argument!");
192 case MVT::i1:
193 case MVT::i8:
194 case MVT::i16:
195 case MVT::i32:
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000196 // Promote the integer to 64 bits. If the input type is signed use a
197 // sign extend, otherwise use a zero extend.
198 if (Args[i].second->isSigned())
Andrew Lenharth40831c52005-01-28 06:57:18 +0000199 Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000200 else
Andrew Lenharth40831c52005-01-28 06:57:18 +0000201 Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000202 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000203 case MVT::i64:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000204 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000205 }
206 args_to_use.push_back(Args[i].first);
207 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000208
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000209 std::vector<MVT::ValueType> RetVals;
210 MVT::ValueType RetTyVT = getValueType(RetTy);
211 if (RetTyVT != MVT::isVoid)
212 RetVals.push_back(RetTyVT);
213 RetVals.push_back(MVT::Other);
214
215 SDOperand TheCall = SDOperand(DAG.getCall(RetVals, Chain, Callee, args_to_use), 0);
216 Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
217 Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
218 DAG.getConstant(NumBytes, getPointerTy()));
219 return std::make_pair(TheCall, Chain);
220}
221
222std::pair<SDOperand, SDOperand>
223AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
224 //vastart just returns the address of the VarArgsFrameIndex slot.
225 return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain);
226}
227
228std::pair<SDOperand,SDOperand> AlphaTargetLowering::
229LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
230 const Type *ArgTy, SelectionDAG &DAG) {
231 abort();
232}
233
234
235std::pair<SDOperand, SDOperand> AlphaTargetLowering::
236LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
237 SelectionDAG &DAG) {
238 abort();
239}
240
241
242
243
244
245namespace {
246
247 //===--------------------------------------------------------------------===//
248 /// ISel - Alpha specific code to select Alpha machine instructions for
249 /// SelectionDAG operations.
250 ///
251 class ISel : public SelectionDAGISel {
252
253 /// AlphaLowering - This object fully describes how to lower LLVM code to an
254 /// Alpha-specific SelectionDAG.
255 AlphaTargetLowering AlphaLowering;
256
257
258 /// ExprMap - As shared expressions are codegen'd, we keep track of which
259 /// vreg the value is produced in, so we only emit one copy of each compiled
260 /// tree.
261 std::map<SDOperand, unsigned> ExprMap;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000262
263 public:
264 ISel(TargetMachine &TM) : SelectionDAGISel(AlphaLowering), AlphaLowering(TM) {
265 }
266
267 /// InstructionSelectBasicBlock - This callback is invoked by
268 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
269 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
270 // Codegen the basic block.
271 Select(DAG.getRoot());
272
273 // Clear state used for selection.
274 ExprMap.clear();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000275 }
276
277 unsigned SelectExpr(SDOperand N);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000278 unsigned SelectExprFP(SDOperand N, unsigned Result);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000279 void Select(SDOperand N);
280 };
281}
282
Andrew Lenharth40831c52005-01-28 06:57:18 +0000283unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
284{
285 unsigned Tmp1, Tmp2, Tmp3;
286 unsigned Opc = 0;
287 SDNode *Node = N.Val;
288 MVT::ValueType DestType = N.getValueType();
289 unsigned opcode = N.getOpcode();
290
291 switch (opcode) {
292 default:
293 Node->dump();
294 assert(0 && "Node not handled!\n");
295
296 case ISD::ConstantFP:
297 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
298 if (CN->isExactlyValue(+0.0)) {
299 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
300 } else {
301 abort();
302 }
303 }
304 return Result;
305
306 case ISD::MUL:
307 case ISD::ADD:
308 case ISD::SUB:
309 case ISD::SDIV:
310 switch( opcode ) {
311 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
312 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
313 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
314 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
315 };
316 Tmp1 = SelectExpr(N.getOperand(0));
317 Tmp2 = SelectExpr(N.getOperand(1));
318 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
319 return Result;
320
321 case ISD::SINT_TO_FP:
322 {
323 assert (N.getOperand(0).getValueType() == MVT::i64 && "only quads can be loaded from");
324 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
325 Tmp2 = MakeReg(DestType);
326 //so these instructions are not supported on ev56
327 Opc = DestType == MVT::f64 ? Alpha::ITOFT : Alpha::ITOFS;
328 BuildMI(BB, Opc, 1, Tmp2).addReg(Tmp1);
329 Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
330 BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
331 return Result;
332 }
333 }
334 assert(0 && "should not get here");
335 return 0;
336}
337
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000338unsigned ISel::SelectExpr(SDOperand N) {
339 unsigned Result;
340 unsigned Tmp1, Tmp2, Tmp3;
341 unsigned Opc = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000342 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000343
344 SDNode *Node = N.Val;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000345 MVT::ValueType DestType = N.getValueType();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000346
347 unsigned &Reg = ExprMap[N];
348 if (Reg) return Reg;
349
350 if (N.getOpcode() != ISD::CALL)
351 Reg = Result = (N.getValueType() != MVT::Other) ?
352 MakeReg(N.getValueType()) : 1;
353 else {
354 // If this is a call instruction, make sure to prepare ALL of the result
355 // values as well as the chain.
356 if (Node->getNumValues() == 1)
357 Reg = Result = 1; // Void call, just a chain.
358 else {
359 Result = MakeReg(Node->getValueType(0));
360 ExprMap[N.getValue(0)] = Result;
361 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
362 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
363 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1;
364 }
365 }
366
Andrew Lenharth40831c52005-01-28 06:57:18 +0000367 if (DestType == MVT::f64 || DestType == MVT::f32)
368 return SelectExprFP(N, Result);
369
370 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000371 default:
372 Node->dump();
373 assert(0 && "Node not handled!\n");
374
375 case ISD::FrameIndex:
376 Tmp1 = cast<FrameIndexSDNode>(N)->getIndex();
377 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp1 * 8).addReg(Alpha::R30);
378 return Result;
379
380 case ISD::EXTLOAD:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000381 // Make sure we generate both values.
382 if (Result != 1)
383 ExprMap[N.getValue(1)] = 1; // Generate the token
384 else
385 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
386
387 Select(Node->getOperand(0)); // chain
388 Tmp1 = SelectExpr(Node->getOperand(1));
389
390 switch(Node->getValueType(0)) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000391 default: Node->dump(); assert(0 && "Unknown type to sign extend to.");
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000392 case MVT::i64:
393 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
394 default:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000395 Node->dump();
396 assert(0 && "Bad extend load!");
Andrew Lenharthd279b412005-01-25 19:58:40 +0000397 case MVT::i64:
398 BuildMI(BB, Alpha::LDQ, 2, Result).addImm(0).addReg(Tmp1);
399 break;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000400 case MVT::i32:
401 BuildMI(BB, Alpha::LDL, 2, Result).addImm(0).addReg(Tmp1);
402 break;
403 case MVT::i16:
404 BuildMI(BB, Alpha::LDWU, 2, Result).addImm(0).addReg(Tmp1);
405 break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000406 case MVT::i1: //Treat i1 as i8 since there are problems otherwise
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000407 case MVT::i8:
408 BuildMI(BB, Alpha::LDBU, 2, Result).addImm(0).addReg(Tmp1);
409 break;
410 }
411 break;
412 }
413 return Result;
414
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000415 case ISD::SEXTLOAD:
416 // Make sure we generate both values.
417 if (Result != 1)
418 ExprMap[N.getValue(1)] = 1; // Generate the token
419 else
420 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
421
422 Select(Node->getOperand(0)); // chain
423 Tmp1 = SelectExpr(Node->getOperand(1));
424 switch(Node->getValueType(0)) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000425 default: Node->dump(); assert(0 && "Unknown type to sign extend to.");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000426 case MVT::i64:
427 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
428 default:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000429 Node->dump();
430 assert(0 && "Bad sign extend!");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000431 case MVT::i32:
432 BuildMI(BB, Alpha::LDL, 2, Result).addImm(0).addReg(Tmp1);
433 break;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000434 }
435 break;
436 }
437 return Result;
438
439 case ISD::ZEXTLOAD:
440 // Make sure we generate both values.
441 if (Result != 1)
442 ExprMap[N.getValue(1)] = 1; // Generate the token
443 else
444 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
445
446 Select(Node->getOperand(0)); // chain
447 Tmp1 = SelectExpr(Node->getOperand(1));
448 switch(Node->getValueType(0)) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000449 default: Node->dump(); assert(0 && "Unknown type to zero extend to.");
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000450 case MVT::i64:
451 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
452 default:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000453 Node->dump();
454 assert(0 && "Bad sign extend!");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000455 case MVT::i16:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000456 BuildMI(BB, Alpha::LDWU, 2, Result).addImm(0).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000457 break;
458 case MVT::i8:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000459 BuildMI(BB, Alpha::LDBU, 2, Result).addImm(0).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000460 break;
461 }
462 break;
463 }
464 return Result;
465
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000466
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000467 case ISD::GlobalAddress:
468 AlphaLowering.restoreGP(BB);
469 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
470 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
471 return Result;
472
473 case ISD::CALL:
474 {
475 Select(N.getOperand(0));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000476
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000477 // The chain for this call is now lowered.
478 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), 1));
479
480 //grab the arguments
481 std::vector<unsigned> argvregs;
482 assert(Node->getNumOperands() < 8 && "Only 6 args supported");
483 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000484 argvregs.push_back(SelectExpr(N.getOperand(i)));
485
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000486 for(int i = 0, e = argvregs.size(); i < e; ++i)
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000487 {
488 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
489 Alpha::R19, Alpha::R20, Alpha::R21};
490 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
491 Alpha::F19, Alpha::F20, Alpha::F21};
Andrew Lenharth7e57bd52005-01-27 01:22:48 +0000492 switch(N.getOperand(i+2).getValueType()) {
493 default:
494 Node->dump();
495 N.getOperand(i).Val->dump();
496 std::cerr << "Type for " << i << " is: " << N.getOperand(i+2).getValueType() << "\n";
497 assert(0 && "Unknown value type for call");
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000498 case MVT::i1:
499 case MVT::i8:
500 case MVT::i16:
501 case MVT::i32:
502 case MVT::i64:
503 BuildMI(BB, Alpha::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
504 break;
505 case MVT::f32:
506 case MVT::f64:
507 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
508 break;
509 }
510
511 }
512 //build the right kind of call
513 if (GlobalAddressSDNode *GASD =
514 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
515 {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000516 AlphaLowering.restoreGP(BB);
517 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
518 }
519 else if (ExternalSymbolSDNode *ESSDN =
520 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
521 {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000522 AlphaLowering.restoreGP(BB);
523 BuildMI(BB, Alpha::CALL, 0).addExternalSymbol(ESSDN->getSymbol(), true);
524 }
525 else
526 {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000527 Tmp1 = SelectExpr(N.getOperand(1));
528 BuildMI(BB, Alpha::CALL, 1).addReg(Tmp1);
529 AlphaLowering.restoreGP(BB);
530 }
531
532 //push the result into a virtual register
533 // if (Result != 1)
534 // BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
535
536 switch (Node->getValueType(0)) {
537 default: Node->dump(); assert(0 && "Unknown value type for call result!");
538 case MVT::Other: return 1;
539 case MVT::i1:
540 case MVT::i8:
541 case MVT::i16:
542 case MVT::i32:
543 case MVT::i64:
544 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
545 break;
546 case MVT::f32:
547 case MVT::f64:
548 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
549 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000550 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000551 return Result+N.ResNo;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000552 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000553
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000554 case ISD::SIGN_EXTEND:
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000555 abort();
556
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000557 case ISD::SIGN_EXTEND_INREG:
558 {
559 Tmp1 = SelectExpr(N.getOperand(0));
560 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000561 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000562 switch(MVN->getExtraValueType())
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000563 {
564 default:
565 Node->dump();
566 assert(0 && "Sign Extend InReg not there yet");
567 break;
568 case MVT::i32:
569 {
570 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
571 break;
572 }
573 case MVT::i16:
574 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
575 break;
576 case MVT::i8:
577 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
578 break;
579 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000580 return Result;
581 }
582 case ISD::ZERO_EXTEND_INREG:
583 {
584 Tmp1 = SelectExpr(N.getOperand(0));
585 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000586 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000587 switch(MVN->getExtraValueType())
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000588 {
589 default:
590 Node->dump();
591 assert(0 && "Zero Extend InReg not there yet");
592 break;
593 case MVT::i32: Tmp2 = 0xf0; break;
594 case MVT::i16: Tmp2 = 0xfc; break;
595 case MVT::i8: Tmp2 = 0xfe; break;
596 case MVT::i1: //handle this one special
597 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
598 return Result;
599 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000600 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000601 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000602 }
603
604 case ISD::SETCC:
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000605 {
606 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
607 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
608 bool isConst1 = false;
609 bool isConst2 = false;
610 int dir;
611
612 //Tmp1 = SelectExpr(N.getOperand(0));
613 if(N.getOperand(0).getOpcode() == ISD::Constant &&
614 cast<ConstantSDNode>(N.getOperand(0))->getValue() >= 0 &&
615 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
616 isConst1 = true;
617 if(N.getOperand(1).getOpcode() == ISD::Constant &&
618 cast<ConstantSDNode>(N.getOperand(1))->getValue() >= 0 &&
619 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
620 isConst2 = true;
621
622 switch (SetCC->getCondition()) {
623 default: Node->dump(); assert(0 && "Unknown integer comparison!");
624 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
625 case ISD::SETLT: Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
626 case ISD::SETLE: Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
627 case ISD::SETGT: Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
628 case ISD::SETGE: Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
629 case ISD::SETULT: Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
630 case ISD::SETUGT: Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
631 case ISD::SETULE: Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
632 case ISD::SETUGE: Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000633 case ISD::SETNE: {//Handle this one special
634 //std::cerr << "Alpha does not have a setne.\n";
635 //abort();
636 Tmp1 = SelectExpr(N.getOperand(0));
637 Tmp2 = SelectExpr(N.getOperand(1));
638 Tmp3 = MakeReg(MVT::i64);
639 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
640 //and invert
641 BuildMI(BB,Alpha::ORNOT, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
642 return Result;
643 }
644 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000645 if (dir == 1) {
646 Tmp1 = SelectExpr(N.getOperand(0));
647 if (isConst2) {
648 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
649 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
650 } else {
651 Tmp2 = SelectExpr(N.getOperand(1));
652 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
653 }
654 } else if (dir == 2) {
655 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth6b9870a2005-01-28 14:06:46 +0000656 if (isConst1) {
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000657 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
658 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
659 } else {
660 Tmp2 = SelectExpr(N.getOperand(0));
661 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
662 }
663 } else { //dir == 0
664 if (isConst1) {
665 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
666 Tmp2 = SelectExpr(N.getOperand(1));
667 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
668 } else if (isConst2) {
669 Tmp1 = SelectExpr(N.getOperand(0));
670 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
671 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
672 } else {
673 Tmp1 = SelectExpr(N.getOperand(0));
674 Tmp2 = SelectExpr(N.getOperand(1));
675 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
676 }
677 }
678 }
679 else
680 {
681 Node->dump();
682 assert(0 && "only integer");
683 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000684 }
685 else
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000686 {
687 Node->dump();
688 assert(0 && "Not a setcc in setcc");
689 }
690 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000691 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000692
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000693 case ISD::CopyFromReg:
694 {
Andrew Lenharth40831c52005-01-28 06:57:18 +0000695 // Make sure we generate both values.
696 if (Result != 1)
697 ExprMap[N.getValue(1)] = 1; // Generate the token
698 else
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000699 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth40831c52005-01-28 06:57:18 +0000700
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000701 SDOperand Chain = N.getOperand(0);
702
703 Select(Chain);
704 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
705 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
706 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
707 return Result;
708 }
709
Andrew Lenharth2d6f0222005-01-24 19:44:07 +0000710 //Most of the plain arithmetic and logic share the same form, and the same
711 //constant immediate test
712 case ISD::AND:
713 case ISD::OR:
714 case ISD::XOR:
715 case ISD::SHL:
716 case ISD::SRL:
717 case ISD::MUL:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000718 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
719 if(N.getOperand(1).getOpcode() == ISD::Constant &&
720 cast<ConstantSDNode>(N.getOperand(1))->getValue() >= 0 &&
721 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
722 {
723 switch(opcode) {
724 case ISD::AND: Opc = Alpha::ANDi; break;
725 case ISD::OR: Opc = Alpha::BISi; break;
726 case ISD::XOR: Opc = Alpha::XORi; break;
727 case ISD::SHL: Opc = Alpha::SLi; break;
728 case ISD::SRL: Opc = Alpha::SRLi; break;
729 case ISD::SRA: Opc = Alpha::SRAi; break;
730 case ISD::MUL: Opc = Alpha::MULQi; break;
731 };
732 Tmp1 = SelectExpr(N.getOperand(0));
733 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
734 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
735 }
736 else
737 {
738 switch(opcode) {
739 case ISD::AND: Opc = Alpha::AND; break;
740 case ISD::OR: Opc = Alpha::BIS; break;
741 case ISD::XOR: Opc = Alpha::XOR; break;
742 case ISD::SHL: Opc = Alpha::SL; break;
743 case ISD::SRL: Opc = Alpha::SRL; break;
744 case ISD::SRA: Opc = Alpha::SRA; break;
745 case ISD::MUL: Opc = Alpha::MULQ; break;
746 };
747 Tmp1 = SelectExpr(N.getOperand(0));
748 Tmp2 = SelectExpr(N.getOperand(1));
749 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
750 }
Andrew Lenharth2d6f0222005-01-24 19:44:07 +0000751 return Result;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000752
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000753 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000754 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000755 {
Andrew Lenharth40831c52005-01-28 06:57:18 +0000756 bool isAdd = opcode == ISD::ADD;
757
758 //FIXME: first check for Scaled Adds and Subs!
759 if(N.getOperand(1).getOpcode() == ISD::Constant &&
760 cast<ConstantSDNode>(N.getOperand(1))->getValue() >= 0 &&
761 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
762 { //Normal imm add/sub
763 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
764 Tmp1 = SelectExpr(N.getOperand(0));
765 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
766 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
767 }
768 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
769 cast<ConstantSDNode>(N.getOperand(1))->getValue() >= 0 &&
770 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767)
771 { //LDA //FIXME: expand the above condition a bit
772 Tmp1 = SelectExpr(N.getOperand(0));
773 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
774 if (!isAdd)
775 Tmp2 = -Tmp2;
776 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
777 }
778 else
779 { //Normal add/sub
780 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
781 Tmp1 = SelectExpr(N.getOperand(0));
782 Tmp2 = SelectExpr(N.getOperand(1));
783 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
784 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000785 return Result;
786 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000787
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000788 case ISD::UREM:
Andrew Lenharth02981182005-01-26 01:24:38 +0000789 case ISD::SREM:
790 case ISD::SDIV:
791 case ISD::UDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000792 //FIXME: alpha really doesn't support any of these operations,
793 // the ops are expanded into special library calls with
794 // special calling conventions
795 switch(opcode) {
796 case ISD::UREM: Opc = Alpha::REMQU; break;
797 case ISD::SREM: Opc = Alpha::REMQ; break;
798 case ISD::UDIV: Opc = Alpha::DIVQU; break;
799 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000800 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000801 Tmp1 = SelectExpr(N.getOperand(0));
802 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth02981182005-01-26 01:24:38 +0000803 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000804 return Result;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000805// // case ISD::UINT_TO_FP:
806
807// case ISD::FP_TO_SINT:
808// assert (N.getValueType() == MVT::f64 && "Only can convert for doubles");
809// Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
810// Tmp2 = MakeReg(SrcTy);
811// BuildMI(BB, CVTTQ, 1, Tmp2).addReg(Tmp1);
812// BuildMI(BB, FTOIT, 1, Result).addReg(Tmp2);
813// return result;
814
815// // case ISD::FP_TO_UINT:
816
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000817 case ISD::SELECT:
818 {
819 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
820 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
821 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
822 // Get the condition into the zero flag.
823 unsigned dummy = MakeReg(MVT::i64);
824 BuildMI(BB, Alpha::BIS, 2, dummy).addReg(Tmp3).addReg(Tmp3);
825 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
826 return Result;
827 }
828
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000829 case ISD::Constant:
830 {
831 long val = cast<ConstantSDNode>(N)->getValue();
832 BuildMI(BB, Alpha::LOAD_IMM, 1, Result).addImm(val);
833 return Result;
834 }
835
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000836 case ISD::LOAD:
837 {
838 // Make sure we generate both values.
839 if (Result != 1)
840 ExprMap[N.getValue(1)] = 1; // Generate the token
841 else
842 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
843
844 SDOperand Chain = N.getOperand(0);
845 SDOperand Address = N.getOperand(1);
846
847 if (Address.getOpcode() == ISD::GlobalAddress)
848 {
849 Select(Chain);
850 AlphaLowering.restoreGP(BB);
851 BuildMI(BB, Alpha::LOAD, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
852 }
853 else
854 {
855 Select(Chain);
856 Tmp2 = SelectExpr(Address);
857 BuildMI(BB, Alpha::LDQ, 2, Result).addImm(0).addReg(Tmp2);
858 }
859 return Result;
860 }
861 }
862
863 return 0;
864}
865
866void ISel::Select(SDOperand N) {
867 unsigned Tmp1, Tmp2, Opc;
868
Andrew Lenharth6b9870a2005-01-28 14:06:46 +0000869 // FIXME: Disable for our current expansion model!
870 if (/*!N->hasOneUse() &&*/ !ExprMap.insert(std::make_pair(N, 1)).second)
871 return; // Already selected.
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000872
873 SDNode *Node = N.Val;
874
875 switch (N.getOpcode()) {
876
877 default:
878 Node->dump(); std::cerr << "\n";
879 assert(0 && "Node not handled yet!");
880
881 case ISD::BRCOND: {
882 MachineBasicBlock *Dest =
883 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
884
885 Select(N.getOperand(0));
886 Tmp1 = SelectExpr(N.getOperand(1));
887 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
888 return;
889 }
890
891 case ISD::BR: {
892 MachineBasicBlock *Dest =
893 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
894
895 Select(N.getOperand(0));
896 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
897 return;
898 }
899
900 case ISD::ImplicitDef:
901 Select(N.getOperand(0));
902 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
903 return;
904
905 case ISD::EntryToken: return; // Noop
906
907 case ISD::TokenFactor:
908 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
909 Select(Node->getOperand(i));
910
911 //N.Val->dump(); std::cerr << "\n";
912 //assert(0 && "Node not handled yet!");
913
914 return;
915
916 case ISD::CopyToReg:
917 Select(N.getOperand(0));
918 Tmp1 = SelectExpr(N.getOperand(1));
919 Tmp2 = cast<RegSDNode>(N)->getReg();
920
921 if (Tmp1 != Tmp2) {
922 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
923 }
924 return;
925
926 case ISD::RET:
927 switch (N.getNumOperands()) {
928 default:
929 std::cerr << N.getNumOperands() << "\n";
930 for (unsigned i = 0; i < N.getNumOperands(); ++i)
931 std::cerr << N.getOperand(i).getValueType() << "\n";
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000932 Node->dump();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000933 assert(0 && "Unknown return instruction!");
934 case 2:
935 Select(N.getOperand(0));
936 Tmp1 = SelectExpr(N.getOperand(1));
937 switch (N.getOperand(1).getValueType()) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000938 default: Node->dump(); assert(0 && "All other types should have been promoted!!");
939 case MVT::f64:
940 case MVT::f32:
941 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
942 break;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000943 case MVT::i32:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000944 case MVT::i64:
945 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
946 break;
947 }
948 break;
949 case 1:
950 Select(N.getOperand(0));
951 break;
952 }
953 //Tmp2 = AlphaLowering.getRetAddr();
954 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
955 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
956 return;
957
958 case ISD::STORE:
959 Select(N.getOperand(0));
960 Tmp1 = SelectExpr(N.getOperand(1)); //value
961 if (N.getOperand(2).getOpcode() == ISD::GlobalAddress)
962 {
963 AlphaLowering.restoreGP(BB);
964 BuildMI(BB, Alpha::STORE, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(N.getOperand(2))->getGlobal());
965 }
966 else
967 {
968 Tmp2 = SelectExpr(N.getOperand(2)); //address
969 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addImm(0).addReg(Tmp2);
970 }
971 return;
972
973 case ISD::EXTLOAD:
974 case ISD::SEXTLOAD:
975 case ISD::ZEXTLOAD:
976 case ISD::LOAD:
977 case ISD::CopyFromReg:
978 case ISD::CALL:
979// case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth6b9870a2005-01-28 14:06:46 +0000980 ExprMap.erase(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000981 SelectExpr(N);
982 return;
983
984
985 case ISD::TRUNCSTORE: { // truncstore chain, val, ptr :storety
986 MVT::ValueType StoredTy = cast<MVTSDNode>(Node)->getExtraValueType();
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000987 if (StoredTy == MVT::i64) {
988 Node->dump();
989 assert(StoredTy != MVT::i64 && "Unsupported TRUNCSTORE for this target!");
990 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000991
992 Select(N.getOperand(0));
993 Tmp1 = SelectExpr(N.getOperand(1));
994 Tmp2 = SelectExpr(N.getOperand(2));
995
996 switch (StoredTy) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000997 default: Node->dump(); assert(0 && "Unhandled Type"); break;
Andrew Lenharthd279b412005-01-25 19:58:40 +0000998 case MVT::i1: //FIXME: DAG does not promote this load
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000999 case MVT::i8: Opc = Alpha::STB; break;
1000 case MVT::i16: Opc = Alpha::STW; break;
1001 case MVT::i32: Opc = Alpha::STL; break;
1002 }
1003
1004 BuildMI(BB, Opc, 2).addReg(Tmp1).addImm(0).addReg(Tmp2);
1005 return;
1006 }
1007
1008 case ISD::ADJCALLSTACKDOWN:
1009 case ISD::ADJCALLSTACKUP:
1010 Select(N.getOperand(0));
1011 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1012
1013 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
1014 Alpha::ADJUSTSTACKUP;
1015 BuildMI(BB, Opc, 1).addImm(Tmp1);
1016 return;
1017 }
1018 assert(0 && "Should not be reached!");
1019}
1020
1021
1022/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
1023/// into a machine code representation using pattern matching and a machine
1024/// description file.
1025///
1026FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
1027 return new ISel(TM);
1028}