blob: 1ea2aff25b1d3915cca911c050d9be9334a59a73 [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.
41 addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass);
42 addRegisterClass(MVT::f64, Alpha::FPRCRegisterClass);
43
44 setOperationAction(ISD::EXTLOAD , MVT::i1 , Expand);
45 setOperationAction(ISD::EXTLOAD , MVT::i8 , Expand);
46 setOperationAction(ISD::EXTLOAD , MVT::i16 , Expand);
47 setOperationAction(ISD::ZEXTLOAD , MVT::i1 , Expand);
48 setOperationAction(ISD::ZEXTLOAD , MVT::i8 , Expand);
49 setOperationAction(ISD::ZEXTLOAD , MVT::i16 , Expand);
50 setOperationAction(ISD::ZEXTLOAD , MVT::i32 , Expand);
51 setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand);
52 setOperationAction(ISD::SEXTLOAD , MVT::i8 , Expand);
53 setOperationAction(ISD::SEXTLOAD , MVT::i16 , Expand);
54
55 computeRegisterProperties();
56
Andrew Lenharth304d0f32005-01-22 23:41:55 +000057 // addLegalFPImmediate(+0.0); // FLD0
58 // addLegalFPImmediate(+1.0); // FLD1
59 // addLegalFPImmediate(-0.0); // FLD0/FCHS
60 // addLegalFPImmediate(-1.0); // FLD1/FCHS
61 }
62
63 /// LowerArguments - This hook must be implemented to indicate how we should
64 /// lower the arguments for the specified function, into the specified DAG.
65 virtual std::vector<SDOperand>
66 LowerArguments(Function &F, SelectionDAG &DAG);
67
68 /// LowerCallTo - This hook lowers an abstract call to a function into an
69 /// actual call.
70 virtual std::pair<SDOperand, SDOperand>
71 LowerCallTo(SDOperand Chain, const Type *RetTy, SDOperand Callee,
72 ArgListTy &Args, SelectionDAG &DAG);
73
74 virtual std::pair<SDOperand, SDOperand>
75 LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
76
77 virtual std::pair<SDOperand,SDOperand>
78 LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
79 const Type *ArgTy, SelectionDAG &DAG);
80
81 virtual std::pair<SDOperand, SDOperand>
82 LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
83 SelectionDAG &DAG);
84
85 void restoreGP(MachineBasicBlock* BB)
86 {
87 BuildMI(BB, Alpha::BIS, 2, Alpha::R29).addReg(GP).addReg(GP);
88 }
89 };
90}
91
92//http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PY8AC-TET1_html/callCH3.html#BLOCK21
93
94//For now, just use variable size stack frame format
95
96//In a standard call, the first six items are passed in registers $16
97//- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
98//of argument-to-register correspondence.) The remaining items are
99//collected in a memory argument list that is a naturally aligned
100//array of quadwords. In a standard call, this list, if present, must
101//be passed at 0(SP).
102//7 ... n 0(SP) ... (n-7)*8(SP)
103
104std::vector<SDOperand>
105AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
106{
107 std::vector<SDOperand> ArgValues;
108
109 // //#define FP $15
110 // //#define RA $26
111 // //#define PV $27
112 // //#define GP $29
113 // //#define SP $30
114
115 // assert(0 && "TODO");
116 MachineFunction &MF = DAG.getMachineFunction();
117 MachineFrameInfo *MFI = MF.getFrameInfo();
118
119 GP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
120 MachineBasicBlock& BB = MF.front();
121
122 //Handle the return address
123 //BuildMI(&BB, Alpha::IDEF, 0, Alpha::R26);
124
125 unsigned args[] = {Alpha::R16, Alpha::R17, Alpha::R18,
126 Alpha::R19, Alpha::R20, Alpha::R21};
127 std::vector<unsigned> argVreg;
128
129 int count = 0;
130 for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I)
131 {
132 ++count;
133 assert(count <= 6 && "More than 6 args not supported");
134 assert(getValueType(I->getType()) != MVT::f64 && "No floats yet");
135 BuildMI(&BB, Alpha::IDEF, 0, args[count - 1]);
136 argVreg.push_back(MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64)));
137 }
138
139 BuildMI(&BB, Alpha::IDEF, 0, Alpha::R29);
140 BuildMI(&BB, Alpha::BIS, 2, GP).addReg(Alpha::R29).addReg(Alpha::R29);
141 count = 0;
142 for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I)
143 {
144 BuildMI(&BB, Alpha::BIS, 2, argVreg[count]).addReg(args[count]).addReg(args[count]);
145
146 SDOperand argt, newroot;
147 switch (getValueType(I->getType()))
148 {
149 case MVT::i64:
150 argt = newroot = DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot());
151 break;
152 case MVT::i32:
153 argt = newroot = DAG.getCopyFromReg(argVreg[count], MVT::i32, DAG.getRoot());
154 break;
155 default:
156 newroot = DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot());
157 argt = DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()), newroot);
158 }
159 DAG.setRoot(newroot.getValue(1));
160 ArgValues.push_back(argt);
161 ++count;
162 }
163 return ArgValues;
164}
165
166std::pair<SDOperand, SDOperand>
167AlphaTargetLowering::LowerCallTo(SDOperand Chain,
168 const Type *RetTy, SDOperand Callee,
169 ArgListTy &Args, SelectionDAG &DAG) {
170 int NumBytes = 0;
171 Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
172 DAG.getConstant(NumBytes, getPointerTy()));
173 std::vector<SDOperand> args_to_use;
174 for (unsigned i = 0, e = Args.size(); i != e; ++i)
175 {
176 switch (getValueType(Args[i].second)) {
177 default: assert(0 && "Unexpected ValueType for argument!");
178 case MVT::i1:
179 case MVT::i8:
180 case MVT::i16:
181 case MVT::i32:
182 // Promote the integer to 64 bits. If the input type is signed use a
183 // sign extend, otherwise use a zero extend.
184 if (Args[i].second->isSigned())
185 Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first);
186 else
187 Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first);
188 break;
189 case MVT::i64:
190 break;
191 }
192 args_to_use.push_back(Args[i].first);
193 }
194
195 std::vector<MVT::ValueType> RetVals;
196 MVT::ValueType RetTyVT = getValueType(RetTy);
197 if (RetTyVT != MVT::isVoid)
198 RetVals.push_back(RetTyVT);
199 RetVals.push_back(MVT::Other);
200
201 SDOperand TheCall = SDOperand(DAG.getCall(RetVals, Chain, Callee, args_to_use), 0);
202 Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
203 Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
204 DAG.getConstant(NumBytes, getPointerTy()));
205 return std::make_pair(TheCall, Chain);
206}
207
208std::pair<SDOperand, SDOperand>
209AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
210 //vastart just returns the address of the VarArgsFrameIndex slot.
211 return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain);
212}
213
214std::pair<SDOperand,SDOperand> AlphaTargetLowering::
215LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
216 const Type *ArgTy, SelectionDAG &DAG) {
217 abort();
218}
219
220
221std::pair<SDOperand, SDOperand> AlphaTargetLowering::
222LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
223 SelectionDAG &DAG) {
224 abort();
225}
226
227
228
229
230
231namespace {
232
233 //===--------------------------------------------------------------------===//
234 /// ISel - Alpha specific code to select Alpha machine instructions for
235 /// SelectionDAG operations.
236 ///
237 class ISel : public SelectionDAGISel {
238
239 /// AlphaLowering - This object fully describes how to lower LLVM code to an
240 /// Alpha-specific SelectionDAG.
241 AlphaTargetLowering AlphaLowering;
242
243
244 /// ExprMap - As shared expressions are codegen'd, we keep track of which
245 /// vreg the value is produced in, so we only emit one copy of each compiled
246 /// tree.
247 std::map<SDOperand, unsigned> ExprMap;
248 std::set<SDOperand> LoweredTokens;
249
250 public:
251 ISel(TargetMachine &TM) : SelectionDAGISel(AlphaLowering), AlphaLowering(TM) {
252 }
253
254 /// InstructionSelectBasicBlock - This callback is invoked by
255 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
256 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
257 // Codegen the basic block.
258 Select(DAG.getRoot());
259
260 // Clear state used for selection.
261 ExprMap.clear();
262 LoweredTokens.clear();
263 }
264
265 unsigned SelectExpr(SDOperand N);
266 void Select(SDOperand N);
267 };
268}
269
270unsigned ISel::SelectExpr(SDOperand N) {
271 unsigned Result;
272 unsigned Tmp1, Tmp2, Tmp3;
273 unsigned Opc = 0;
274
275 SDNode *Node = N.Val;
276
277 unsigned &Reg = ExprMap[N];
278 if (Reg) return Reg;
279
280 if (N.getOpcode() != ISD::CALL)
281 Reg = Result = (N.getValueType() != MVT::Other) ?
282 MakeReg(N.getValueType()) : 1;
283 else {
284 // If this is a call instruction, make sure to prepare ALL of the result
285 // values as well as the chain.
286 if (Node->getNumValues() == 1)
287 Reg = Result = 1; // Void call, just a chain.
288 else {
289 Result = MakeReg(Node->getValueType(0));
290 ExprMap[N.getValue(0)] = Result;
291 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
292 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
293 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1;
294 }
295 }
296
297 switch (N.getOpcode()) {
298 default:
299 Node->dump();
300 assert(0 && "Node not handled!\n");
301
302 case ISD::FrameIndex:
303 Tmp1 = cast<FrameIndexSDNode>(N)->getIndex();
304 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp1 * 8).addReg(Alpha::R30);
305 return Result;
306
307 case ISD::EXTLOAD:
308 case ISD::SEXTLOAD:
309 // Make sure we generate both values.
310 if (Result != 1)
311 ExprMap[N.getValue(1)] = 1; // Generate the token
312 else
313 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
314
315 Select(Node->getOperand(0)); // chain
316 Tmp1 = SelectExpr(Node->getOperand(1));
317 switch(Node->getValueType(0)) {
318 default: assert(0 && "Unknown type to sign extend to.");
319 case MVT::i64:
320 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
321 default:
322 assert(0 && "Bad sign extend!");
323 case MVT::i32:
324 BuildMI(BB, Alpha::LDL, 2, Result).addImm(0).addReg(Tmp1);
325 break;
326 case MVT::i16:
327 BuildMI(BB, Alpha::LDW, 2, Result).addImm(0).addReg(Tmp1);
328 break;
329 case MVT::i8:
330 BuildMI(BB, Alpha::LDB, 2, Result).addImm(0).addReg(Tmp1);
331 break;
332 }
333 break;
334 }
335 return Result;
336
337 case ISD::GlobalAddress:
338 AlphaLowering.restoreGP(BB);
339 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
340 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
341 return Result;
342
343 case ISD::CALL:
344 {
345 Select(N.getOperand(0));
346
347 // The chain for this call is now lowered.
348 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), 1));
349
350 //grab the arguments
351 std::vector<unsigned> argvregs;
352 assert(Node->getNumOperands() < 8 && "Only 6 args supported");
353 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
354 {
355 argvregs.push_back(SelectExpr(N.getOperand(i)));
356 }
357 for(int i = 0, e = argvregs.size(); i < e; ++i)
358 {
359 unsigned args[] = {Alpha::R16, Alpha::R17, Alpha::R18,
360 Alpha::R19, Alpha::R20, Alpha::R21};
361
362 BuildMI(BB, Alpha::BIS, 2, args[i]).addReg(argvregs[i]).addReg(argvregs[i]);
363 }
364
365 //build the right kind of call
366 if (GlobalAddressSDNode *GASD =
367 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
368 {
369 Select(N.getOperand(0));
370 AlphaLowering.restoreGP(BB);
371 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
372 }
373 else if (ExternalSymbolSDNode *ESSDN =
374 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
375 {
376 Select(N.getOperand(0));
377 AlphaLowering.restoreGP(BB);
378 BuildMI(BB, Alpha::CALL, 0).addExternalSymbol(ESSDN->getSymbol(), true);
379 }
380 else {
381 Select(N.getOperand(0));
382 Tmp1 = SelectExpr(N.getOperand(1));
383 BuildMI(BB, Alpha::CALL, 1).addReg(Tmp1);
384 AlphaLowering.restoreGP(BB);
385 }
386
387 //push the result into a virtual register
388 // if (Result != 1)
389 // BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
390
391 switch (Node->getValueType(0)) {
392 default: assert(0 && "Unknown value type for call result!");
393 case MVT::Other: return 1;
394 case MVT::i1:
395 case MVT::i8:
396 case MVT::i16:
397 case MVT::i32:
398 case MVT::i64:
399 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
400 break;
401 }
402 return Result+N.ResNo;
403 }
404
405 case ISD::SIGN_EXTEND:
406 {
407 std::cerr << "DestT: " << N.getValueType() << "\n";
408 std::cerr << "SrcT: " << N.getOperand(0).getValueType() << "\n";
409 assert(0 && "Sign Extend not there yet");
410 return Result;
411 }
412 case ISD::SIGN_EXTEND_INREG:
413 {
414 Tmp1 = SelectExpr(N.getOperand(0));
415 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
416 std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
417 switch(MVN->getExtraValueType())
418 {
419 default:
420 assert(0 && "Sign Extend InReg not there yet");
421 break;
422 case MVT::i32:
423 {
424 Tmp2 = MakeReg(MVT::i64);
425 unsigned Tmp3 = MakeReg(MVT::i64);
426 BuildMI(BB, Alpha::LOAD_IMM, 1, Tmp2).addImm(16);
427 BuildMI(BB, Alpha::SL, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
428 BuildMI(BB, Alpha::SRA, 2, Result).addReg(Tmp3).addReg(Tmp2);
429 break;
430 }
431 case MVT::i16:
432 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
433 break;
434 case MVT::i8:
435 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
436 break;
437 }
438 return Result;
439 }
440 case ISD::ZERO_EXTEND_INREG:
441 {
442 Tmp1 = SelectExpr(N.getOperand(0));
443 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
444 std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
445 switch(MVN->getExtraValueType())
446 {
447 default:
448 assert(0 && "Zero Extend InReg not there yet");
449 break;
450 case MVT::i32:
451 {
452 Tmp2 = MakeReg(MVT::i64);
453 BuildMI(BB, Alpha::LOAD_IMM, 1, Tmp2).addImm(0xf0);
454 BuildMI(BB, Alpha::ZAP, 2, Result).addReg(Tmp1).addReg(Tmp2);
455 break;
456 }
457 case MVT::i16:
458 Tmp2 = MakeReg(MVT::i64);
459 BuildMI(BB, Alpha::LOAD_IMM, 1, Tmp2).addImm(0xfc);
460 BuildMI(BB, Alpha::ZAP, 2, Result).addReg(Tmp1).addReg(Tmp2);
461 break;
462 case MVT::i8:
463 Tmp2 = MakeReg(MVT::i64);
464 BuildMI(BB, Alpha::LOAD_IMM, 1, Tmp2).addImm(0xfe);
465 BuildMI(BB, Alpha::ZAP, 2, Result).addReg(Tmp1).addReg(Tmp2);
466 break;
467 }
468 return Result;
469 }
470
471 case ISD::SETCC:
472 Tmp1 = SelectExpr(N.getOperand(0));
473 Tmp2 = SelectExpr(N.getOperand(1));
474 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
475 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
476 switch (SetCC->getCondition()) {
477 default: assert(0 && "Unknown integer comparison!");
478 case ISD::SETEQ:
479 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
480 break;
481 case ISD::SETGT:
482 BuildMI(BB, Alpha::CMPLT, 2, Result).addReg(Tmp2).addReg(Tmp1);
483 break;
484 case ISD::SETGE:
485 BuildMI(BB, Alpha::CMPLE, 2, Result).addReg(Tmp2).addReg(Tmp1);
486 break;
487 case ISD::SETLT:
488 BuildMI(BB, Alpha::CMPLT, 2, Result).addReg(Tmp1).addReg(Tmp2);
489 break;
490 case ISD::SETLE:
491 BuildMI(BB, Alpha::CMPLE, 2, Result).addReg(Tmp1).addReg(Tmp2);
492 break;
493 case ISD::SETNE:
494 {
495 unsigned Tmp3 = MakeReg(MVT::i64);
496 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
497 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp3).addReg(Alpha::R31);
498 break;
499 }
500 case ISD::SETULT:
501 BuildMI(BB, Alpha::CMPULT, 2, Result).addReg(Tmp1).addReg(Tmp2);
502 break;
503 case ISD::SETUGT:
504 BuildMI(BB, Alpha::CMPULT, 2, Result).addReg(Tmp2).addReg(Tmp1);
505 break;
506 case ISD::SETULE:
507 BuildMI(BB, Alpha::CMPULE, 2, Result).addReg(Tmp1).addReg(Tmp2);
508 break;
509 case ISD::SETUGE:
510 BuildMI(BB, Alpha::CMPULE, 2, Result).addReg(Tmp2).addReg(Tmp1);
511 break;
512 }
513 }
514 else
515 assert(0 && "only integer");
516 }
517 else
518 assert(0 && "Not a setcc in setcc");
519
520 return Result;
521
522 case ISD::CopyFromReg:
523 {
524 if (Result == 1)
525 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
526
527 SDOperand Chain = N.getOperand(0);
528
529 Select(Chain);
530 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
531 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
532 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
533 return Result;
534 }
535
Andrew Lenharth2d6f0222005-01-24 19:44:07 +0000536 //Most of the plain arithmetic and logic share the same form, and the same
537 //constant immediate test
538 case ISD::AND:
539 case ISD::OR:
540 case ISD::XOR:
541 case ISD::SHL:
542 case ISD::SRL:
543 case ISD::MUL:
544 if(N.getOperand(1).getOpcode() == ISD::Constant &&
545 cast<ConstantSDNode>(N.getOperand(1))->getValue() >= 0 &&
546 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
547 {
548 switch(N.getOpcode()) {
549 case ISD::AND: Opc = Alpha::ANDi; break;
550 case ISD::OR: Opc = Alpha::BISi; break;
551 case ISD::XOR: Opc = Alpha::XORi; break;
552 case ISD::SHL: Opc = Alpha::SLi; break;
553 case ISD::SRL: Opc = Alpha::SRLi; break;
554 case ISD::SRA: Opc = Alpha::SRAi; break;
555 case ISD::MUL: Opc = Alpha::MULQi; break;
556 };
557 Tmp1 = SelectExpr(N.getOperand(0));
558 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
559 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
560 }
561 else
562 {
563 switch(N.getOpcode()) {
564 case ISD::AND: Opc = Alpha::AND; break;
565 case ISD::OR: Opc = Alpha::BIS; break;
566 case ISD::XOR: Opc = Alpha::XOR; break;
567 case ISD::SHL: Opc = Alpha::SL; break;
568 case ISD::SRL: Opc = Alpha::SRL; break;
569 case ISD::SRA: Opc = Alpha::SRA; break;
570 case ISD::MUL: Opc = Alpha::MULQ; break;
571 };
572 Tmp1 = SelectExpr(N.getOperand(0));
573 Tmp2 = SelectExpr(N.getOperand(1));
574 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
575 }
576 return Result;
577
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000578 case ISD::ADD:
579 Tmp1 = SelectExpr(N.getOperand(0));
580 Tmp2 = SelectExpr(N.getOperand(1));
581 BuildMI(BB, Alpha::ADDQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
582 return Result;
583 case ISD::SUB:
584 Tmp1 = SelectExpr(N.getOperand(0));
585 Tmp2 = SelectExpr(N.getOperand(1));
586 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
587 return Result;
588
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000589 case ISD::UREM:
590 Tmp1 = SelectExpr(N.getOperand(0));
591 Tmp2 = SelectExpr(N.getOperand(1));
592 BuildMI(BB, Alpha::REMQU, 2, Result).addReg(Tmp1).addReg(Tmp2);
593 return Result;
594
595 case ISD::SELECT:
596 {
597 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
598 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
599 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
600 // Get the condition into the zero flag.
601 unsigned dummy = MakeReg(MVT::i64);
602 BuildMI(BB, Alpha::BIS, 2, dummy).addReg(Tmp3).addReg(Tmp3);
603 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
604 return Result;
605 }
606
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000607 case ISD::Constant:
608 {
609 long val = cast<ConstantSDNode>(N)->getValue();
610 BuildMI(BB, Alpha::LOAD_IMM, 1, Result).addImm(val);
611 return Result;
612 }
613
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000614 case ISD::LOAD:
615 {
616 // Make sure we generate both values.
617 if (Result != 1)
618 ExprMap[N.getValue(1)] = 1; // Generate the token
619 else
620 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
621
622 SDOperand Chain = N.getOperand(0);
623 SDOperand Address = N.getOperand(1);
624
625 if (Address.getOpcode() == ISD::GlobalAddress)
626 {
627 Select(Chain);
628 AlphaLowering.restoreGP(BB);
629 BuildMI(BB, Alpha::LOAD, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
630 }
631 else
632 {
633 Select(Chain);
634 Tmp2 = SelectExpr(Address);
635 BuildMI(BB, Alpha::LDQ, 2, Result).addImm(0).addReg(Tmp2);
636 }
637 return Result;
638 }
639 }
640
641 return 0;
642}
643
644void ISel::Select(SDOperand N) {
645 unsigned Tmp1, Tmp2, Opc;
646
647 // FIXME: Disable for our current expansion model!
648 if (/*!N->hasOneUse() &&*/ !LoweredTokens.insert(N).second)
649 return; // Already selected.
650
651 SDNode *Node = N.Val;
652
653 switch (N.getOpcode()) {
654
655 default:
656 Node->dump(); std::cerr << "\n";
657 assert(0 && "Node not handled yet!");
658
659 case ISD::BRCOND: {
660 MachineBasicBlock *Dest =
661 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
662
663 Select(N.getOperand(0));
664 Tmp1 = SelectExpr(N.getOperand(1));
665 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
666 return;
667 }
668
669 case ISD::BR: {
670 MachineBasicBlock *Dest =
671 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
672
673 Select(N.getOperand(0));
674 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
675 return;
676 }
677
678 case ISD::ImplicitDef:
679 Select(N.getOperand(0));
680 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
681 return;
682
683 case ISD::EntryToken: return; // Noop
684
685 case ISD::TokenFactor:
686 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
687 Select(Node->getOperand(i));
688
689 //N.Val->dump(); std::cerr << "\n";
690 //assert(0 && "Node not handled yet!");
691
692 return;
693
694 case ISD::CopyToReg:
695 Select(N.getOperand(0));
696 Tmp1 = SelectExpr(N.getOperand(1));
697 Tmp2 = cast<RegSDNode>(N)->getReg();
698
699 if (Tmp1 != Tmp2) {
700 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
701 }
702 return;
703
704 case ISD::RET:
705 switch (N.getNumOperands()) {
706 default:
707 std::cerr << N.getNumOperands() << "\n";
708 for (unsigned i = 0; i < N.getNumOperands(); ++i)
709 std::cerr << N.getOperand(i).getValueType() << "\n";
710 assert(0 && "Unknown return instruction!");
711 case 2:
712 Select(N.getOperand(0));
713 Tmp1 = SelectExpr(N.getOperand(1));
714 switch (N.getOperand(1).getValueType()) {
715 default: assert(0 && "All other types should have been promoted!!");
716 case MVT::i64:
717 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
718 break;
719 }
720 break;
721 case 1:
722 Select(N.getOperand(0));
723 break;
724 }
725 //Tmp2 = AlphaLowering.getRetAddr();
726 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
727 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
728 return;
729
730 case ISD::STORE:
731 Select(N.getOperand(0));
732 Tmp1 = SelectExpr(N.getOperand(1)); //value
733 if (N.getOperand(2).getOpcode() == ISD::GlobalAddress)
734 {
735 AlphaLowering.restoreGP(BB);
736 BuildMI(BB, Alpha::STORE, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(N.getOperand(2))->getGlobal());
737 }
738 else
739 {
740 Tmp2 = SelectExpr(N.getOperand(2)); //address
741 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addImm(0).addReg(Tmp2);
742 }
743 return;
744
745 case ISD::EXTLOAD:
746 case ISD::SEXTLOAD:
747 case ISD::ZEXTLOAD:
748 case ISD::LOAD:
749 case ISD::CopyFromReg:
750 case ISD::CALL:
751// case ISD::DYNAMIC_STACKALLOC:
752 SelectExpr(N);
753 return;
754
755
756 case ISD::TRUNCSTORE: { // truncstore chain, val, ptr :storety
757 MVT::ValueType StoredTy = cast<MVTSDNode>(Node)->getExtraValueType();
758 assert(StoredTy != MVT::i64 && "Unsupported TRUNCSTORE for this target!");
759
760 Select(N.getOperand(0));
761 Tmp1 = SelectExpr(N.getOperand(1));
762 Tmp2 = SelectExpr(N.getOperand(2));
763
764 switch (StoredTy) {
765 default: assert(0 && "Unhandled Type"); break;
766 case MVT::i8: Opc = Alpha::STB; break;
767 case MVT::i16: Opc = Alpha::STW; break;
768 case MVT::i32: Opc = Alpha::STL; break;
769 }
770
771 BuildMI(BB, Opc, 2).addReg(Tmp1).addImm(0).addReg(Tmp2);
772 return;
773 }
774
775 case ISD::ADJCALLSTACKDOWN:
776 case ISD::ADJCALLSTACKUP:
777 Select(N.getOperand(0));
778 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
779
780 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
781 Alpha::ADJUSTSTACKUP;
782 BuildMI(BB, Opc, 1).addImm(Tmp1);
783 return;
784 }
785 assert(0 && "Should not be reached!");
786}
787
788
789/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
790/// into a machine code representation using pattern matching and a machine
791/// description file.
792///
793FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
794 return new ISel(TM);
795}