blob: b3426a9c69f336071e4d3795e18c66140a37074a [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);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000047
Andrew Lenharth304d0f32005-01-22 23:41:55 +000048 setOperationAction(ISD::ZEXTLOAD , MVT::i1 , Expand);
Andrew Lenharth304d0f32005-01-22 23:41:55 +000049 setOperationAction(ISD::ZEXTLOAD , MVT::i32 , Expand);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000050
Andrew Lenharth304d0f32005-01-22 23:41:55 +000051 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:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000308 // Make sure we generate both values.
309 if (Result != 1)
310 ExprMap[N.getValue(1)] = 1; // Generate the token
311 else
312 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
313
314 Select(Node->getOperand(0)); // chain
315 Tmp1 = SelectExpr(Node->getOperand(1));
316
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::LDWU, 2, Result).addImm(0).addReg(Tmp1);
328 break;
329 case MVT::i8:
330 BuildMI(BB, Alpha::LDBU, 2, Result).addImm(0).addReg(Tmp1);
331 break;
332 }
333 break;
334 }
335 return Result;
336
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000337 case ISD::SEXTLOAD:
338 // Make sure we generate both values.
339 if (Result != 1)
340 ExprMap[N.getValue(1)] = 1; // Generate the token
341 else
342 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
343
344 Select(Node->getOperand(0)); // chain
345 Tmp1 = SelectExpr(Node->getOperand(1));
346 switch(Node->getValueType(0)) {
347 default: assert(0 && "Unknown type to sign extend to.");
348 case MVT::i64:
349 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
350 default:
351 assert(0 && "Bad sign extend!");
352 case MVT::i32:
353 BuildMI(BB, Alpha::LDL, 2, Result).addImm(0).addReg(Tmp1);
354 break;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000355// case MVT::i16:
356// BuildMI(BB, Alpha::LDW, 2, Result).addImm(0).addReg(Tmp1);
357// break;
358// case MVT::i8:
359// BuildMI(BB, Alpha::LDB, 2, Result).addImm(0).addReg(Tmp1);
360// break;
361 }
362 break;
363 }
364 return Result;
365
366 case ISD::ZEXTLOAD:
367 // Make sure we generate both values.
368 if (Result != 1)
369 ExprMap[N.getValue(1)] = 1; // Generate the token
370 else
371 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
372
373 Select(Node->getOperand(0)); // chain
374 Tmp1 = SelectExpr(Node->getOperand(1));
375 switch(Node->getValueType(0)) {
376 default: assert(0 && "Unknown type to zero extend to.");
377 case MVT::i64:
378 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
379 default:
380 assert(0 && "Bad sign extend!");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000381 case MVT::i16:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000382 BuildMI(BB, Alpha::LDWU, 2, Result).addImm(0).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000383 break;
384 case MVT::i8:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000385 BuildMI(BB, Alpha::LDBU, 2, Result).addImm(0).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000386 break;
387 }
388 break;
389 }
390 return Result;
391
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000392
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000393 case ISD::GlobalAddress:
394 AlphaLowering.restoreGP(BB);
395 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
396 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
397 return Result;
398
399 case ISD::CALL:
400 {
401 Select(N.getOperand(0));
402
403 // The chain for this call is now lowered.
404 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), 1));
405
406 //grab the arguments
407 std::vector<unsigned> argvregs;
408 assert(Node->getNumOperands() < 8 && "Only 6 args supported");
409 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
410 {
411 argvregs.push_back(SelectExpr(N.getOperand(i)));
412 }
413 for(int i = 0, e = argvregs.size(); i < e; ++i)
414 {
415 unsigned args[] = {Alpha::R16, Alpha::R17, Alpha::R18,
416 Alpha::R19, Alpha::R20, Alpha::R21};
417
418 BuildMI(BB, Alpha::BIS, 2, args[i]).addReg(argvregs[i]).addReg(argvregs[i]);
419 }
420
421 //build the right kind of call
422 if (GlobalAddressSDNode *GASD =
423 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
424 {
425 Select(N.getOperand(0));
426 AlphaLowering.restoreGP(BB);
427 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
428 }
429 else if (ExternalSymbolSDNode *ESSDN =
430 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
431 {
432 Select(N.getOperand(0));
433 AlphaLowering.restoreGP(BB);
434 BuildMI(BB, Alpha::CALL, 0).addExternalSymbol(ESSDN->getSymbol(), true);
435 }
436 else {
437 Select(N.getOperand(0));
438 Tmp1 = SelectExpr(N.getOperand(1));
439 BuildMI(BB, Alpha::CALL, 1).addReg(Tmp1);
440 AlphaLowering.restoreGP(BB);
441 }
442
443 //push the result into a virtual register
444 // if (Result != 1)
445 // BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
446
447 switch (Node->getValueType(0)) {
448 default: assert(0 && "Unknown value type for call result!");
449 case MVT::Other: return 1;
450 case MVT::i1:
451 case MVT::i8:
452 case MVT::i16:
453 case MVT::i32:
454 case MVT::i64:
455 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
456 break;
457 }
458 return Result+N.ResNo;
459 }
460
461 case ISD::SIGN_EXTEND:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000462 case ISD::SIGN_EXTEND_INREG:
463 {
464 Tmp1 = SelectExpr(N.getOperand(0));
465 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
466 std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
467 switch(MVN->getExtraValueType())
468 {
469 default:
470 assert(0 && "Sign Extend InReg not there yet");
471 break;
472 case MVT::i32:
473 {
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000474 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000475 break;
476 }
477 case MVT::i16:
478 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
479 break;
480 case MVT::i8:
481 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
482 break;
483 }
484 return Result;
485 }
486 case ISD::ZERO_EXTEND_INREG:
487 {
488 Tmp1 = SelectExpr(N.getOperand(0));
489 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
490 std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
491 switch(MVN->getExtraValueType())
492 {
493 default:
494 assert(0 && "Zero Extend InReg not there yet");
495 break;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000496 case MVT::i32: Tmp2 = 0xf0; break;
497 case MVT::i16: Tmp2 = 0xfc; break;
498 case MVT::i8: Tmp2 = 0xfe; break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000499 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000500 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
501 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000502 }
503
504 case ISD::SETCC:
505 Tmp1 = SelectExpr(N.getOperand(0));
506 Tmp2 = SelectExpr(N.getOperand(1));
507 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
508 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
509 switch (SetCC->getCondition()) {
510 default: assert(0 && "Unknown integer comparison!");
511 case ISD::SETEQ:
512 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
513 break;
514 case ISD::SETGT:
515 BuildMI(BB, Alpha::CMPLT, 2, Result).addReg(Tmp2).addReg(Tmp1);
516 break;
517 case ISD::SETGE:
518 BuildMI(BB, Alpha::CMPLE, 2, Result).addReg(Tmp2).addReg(Tmp1);
519 break;
520 case ISD::SETLT:
521 BuildMI(BB, Alpha::CMPLT, 2, Result).addReg(Tmp1).addReg(Tmp2);
522 break;
523 case ISD::SETLE:
524 BuildMI(BB, Alpha::CMPLE, 2, Result).addReg(Tmp1).addReg(Tmp2);
525 break;
526 case ISD::SETNE:
527 {
528 unsigned Tmp3 = MakeReg(MVT::i64);
529 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
530 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp3).addReg(Alpha::R31);
531 break;
532 }
533 case ISD::SETULT:
534 BuildMI(BB, Alpha::CMPULT, 2, Result).addReg(Tmp1).addReg(Tmp2);
535 break;
536 case ISD::SETUGT:
537 BuildMI(BB, Alpha::CMPULT, 2, Result).addReg(Tmp2).addReg(Tmp1);
538 break;
539 case ISD::SETULE:
540 BuildMI(BB, Alpha::CMPULE, 2, Result).addReg(Tmp1).addReg(Tmp2);
541 break;
542 case ISD::SETUGE:
543 BuildMI(BB, Alpha::CMPULE, 2, Result).addReg(Tmp2).addReg(Tmp1);
544 break;
545 }
546 }
547 else
548 assert(0 && "only integer");
549 }
550 else
551 assert(0 && "Not a setcc in setcc");
552
553 return Result;
554
555 case ISD::CopyFromReg:
556 {
557 if (Result == 1)
558 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
559
560 SDOperand Chain = N.getOperand(0);
561
562 Select(Chain);
563 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
564 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
565 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
566 return Result;
567 }
568
Andrew Lenharth2d6f0222005-01-24 19:44:07 +0000569 //Most of the plain arithmetic and logic share the same form, and the same
570 //constant immediate test
571 case ISD::AND:
572 case ISD::OR:
573 case ISD::XOR:
574 case ISD::SHL:
575 case ISD::SRL:
576 case ISD::MUL:
577 if(N.getOperand(1).getOpcode() == ISD::Constant &&
578 cast<ConstantSDNode>(N.getOperand(1))->getValue() >= 0 &&
579 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
580 {
581 switch(N.getOpcode()) {
582 case ISD::AND: Opc = Alpha::ANDi; break;
583 case ISD::OR: Opc = Alpha::BISi; break;
584 case ISD::XOR: Opc = Alpha::XORi; break;
585 case ISD::SHL: Opc = Alpha::SLi; break;
586 case ISD::SRL: Opc = Alpha::SRLi; break;
587 case ISD::SRA: Opc = Alpha::SRAi; break;
588 case ISD::MUL: Opc = Alpha::MULQi; break;
589 };
590 Tmp1 = SelectExpr(N.getOperand(0));
591 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
592 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
593 }
594 else
595 {
596 switch(N.getOpcode()) {
597 case ISD::AND: Opc = Alpha::AND; break;
598 case ISD::OR: Opc = Alpha::BIS; break;
599 case ISD::XOR: Opc = Alpha::XOR; break;
600 case ISD::SHL: Opc = Alpha::SL; break;
601 case ISD::SRL: Opc = Alpha::SRL; break;
602 case ISD::SRA: Opc = Alpha::SRA; break;
603 case ISD::MUL: Opc = Alpha::MULQ; break;
604 };
605 Tmp1 = SelectExpr(N.getOperand(0));
606 Tmp2 = SelectExpr(N.getOperand(1));
607 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
608 }
609 return Result;
610
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000611 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000612 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000613 {
614 bool isAdd = N.getOpcode() == ISD::ADD;
615
616 //FIXME: first check for Scaled Adds and Subs!
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 { //Normal imm add/sub
621 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
622 Tmp1 = SelectExpr(N.getOperand(0));
623 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
624 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
625 }
626 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
627 cast<ConstantSDNode>(N.getOperand(1))->getValue() >= 0 &&
628 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767)
629 { //LDA //FIXME: expand the above condition a bit
630 Tmp1 = SelectExpr(N.getOperand(0));
631 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
632 if (!isAdd)
633 Tmp2 = -Tmp2;
634 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
635 }
636 else
637 { //Normal add/sub
638 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
639 Tmp1 = SelectExpr(N.getOperand(0));
640 Tmp2 = SelectExpr(N.getOperand(1));
641 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
642
643 }
644 return Result;
645 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000646
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000647 case ISD::UREM:
648 Tmp1 = SelectExpr(N.getOperand(0));
649 Tmp2 = SelectExpr(N.getOperand(1));
650 BuildMI(BB, Alpha::REMQU, 2, Result).addReg(Tmp1).addReg(Tmp2);
651 return Result;
652
653 case ISD::SELECT:
654 {
655 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
656 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
657 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
658 // Get the condition into the zero flag.
659 unsigned dummy = MakeReg(MVT::i64);
660 BuildMI(BB, Alpha::BIS, 2, dummy).addReg(Tmp3).addReg(Tmp3);
661 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
662 return Result;
663 }
664
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000665 case ISD::Constant:
666 {
667 long val = cast<ConstantSDNode>(N)->getValue();
668 BuildMI(BB, Alpha::LOAD_IMM, 1, Result).addImm(val);
669 return Result;
670 }
671
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000672 case ISD::LOAD:
673 {
674 // Make sure we generate both values.
675 if (Result != 1)
676 ExprMap[N.getValue(1)] = 1; // Generate the token
677 else
678 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
679
680 SDOperand Chain = N.getOperand(0);
681 SDOperand Address = N.getOperand(1);
682
683 if (Address.getOpcode() == ISD::GlobalAddress)
684 {
685 Select(Chain);
686 AlphaLowering.restoreGP(BB);
687 BuildMI(BB, Alpha::LOAD, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
688 }
689 else
690 {
691 Select(Chain);
692 Tmp2 = SelectExpr(Address);
693 BuildMI(BB, Alpha::LDQ, 2, Result).addImm(0).addReg(Tmp2);
694 }
695 return Result;
696 }
697 }
698
699 return 0;
700}
701
702void ISel::Select(SDOperand N) {
703 unsigned Tmp1, Tmp2, Opc;
704
705 // FIXME: Disable for our current expansion model!
706 if (/*!N->hasOneUse() &&*/ !LoweredTokens.insert(N).second)
707 return; // Already selected.
708
709 SDNode *Node = N.Val;
710
711 switch (N.getOpcode()) {
712
713 default:
714 Node->dump(); std::cerr << "\n";
715 assert(0 && "Node not handled yet!");
716
717 case ISD::BRCOND: {
718 MachineBasicBlock *Dest =
719 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
720
721 Select(N.getOperand(0));
722 Tmp1 = SelectExpr(N.getOperand(1));
723 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
724 return;
725 }
726
727 case ISD::BR: {
728 MachineBasicBlock *Dest =
729 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
730
731 Select(N.getOperand(0));
732 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
733 return;
734 }
735
736 case ISD::ImplicitDef:
737 Select(N.getOperand(0));
738 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
739 return;
740
741 case ISD::EntryToken: return; // Noop
742
743 case ISD::TokenFactor:
744 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
745 Select(Node->getOperand(i));
746
747 //N.Val->dump(); std::cerr << "\n";
748 //assert(0 && "Node not handled yet!");
749
750 return;
751
752 case ISD::CopyToReg:
753 Select(N.getOperand(0));
754 Tmp1 = SelectExpr(N.getOperand(1));
755 Tmp2 = cast<RegSDNode>(N)->getReg();
756
757 if (Tmp1 != Tmp2) {
758 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
759 }
760 return;
761
762 case ISD::RET:
763 switch (N.getNumOperands()) {
764 default:
765 std::cerr << N.getNumOperands() << "\n";
766 for (unsigned i = 0; i < N.getNumOperands(); ++i)
767 std::cerr << N.getOperand(i).getValueType() << "\n";
768 assert(0 && "Unknown return instruction!");
769 case 2:
770 Select(N.getOperand(0));
771 Tmp1 = SelectExpr(N.getOperand(1));
772 switch (N.getOperand(1).getValueType()) {
773 default: assert(0 && "All other types should have been promoted!!");
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000774 case MVT::i32:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000775 case MVT::i64:
776 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
777 break;
778 }
779 break;
780 case 1:
781 Select(N.getOperand(0));
782 break;
783 }
784 //Tmp2 = AlphaLowering.getRetAddr();
785 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
786 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
787 return;
788
789 case ISD::STORE:
790 Select(N.getOperand(0));
791 Tmp1 = SelectExpr(N.getOperand(1)); //value
792 if (N.getOperand(2).getOpcode() == ISD::GlobalAddress)
793 {
794 AlphaLowering.restoreGP(BB);
795 BuildMI(BB, Alpha::STORE, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(N.getOperand(2))->getGlobal());
796 }
797 else
798 {
799 Tmp2 = SelectExpr(N.getOperand(2)); //address
800 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addImm(0).addReg(Tmp2);
801 }
802 return;
803
804 case ISD::EXTLOAD:
805 case ISD::SEXTLOAD:
806 case ISD::ZEXTLOAD:
807 case ISD::LOAD:
808 case ISD::CopyFromReg:
809 case ISD::CALL:
810// case ISD::DYNAMIC_STACKALLOC:
811 SelectExpr(N);
812 return;
813
814
815 case ISD::TRUNCSTORE: { // truncstore chain, val, ptr :storety
816 MVT::ValueType StoredTy = cast<MVTSDNode>(Node)->getExtraValueType();
817 assert(StoredTy != MVT::i64 && "Unsupported TRUNCSTORE for this target!");
818
819 Select(N.getOperand(0));
820 Tmp1 = SelectExpr(N.getOperand(1));
821 Tmp2 = SelectExpr(N.getOperand(2));
822
823 switch (StoredTy) {
824 default: assert(0 && "Unhandled Type"); break;
825 case MVT::i8: Opc = Alpha::STB; break;
826 case MVT::i16: Opc = Alpha::STW; break;
827 case MVT::i32: Opc = Alpha::STL; break;
828 }
829
830 BuildMI(BB, Opc, 2).addReg(Tmp1).addImm(0).addReg(Tmp2);
831 return;
832 }
833
834 case ISD::ADJCALLSTACKDOWN:
835 case ISD::ADJCALLSTACKUP:
836 Select(N.getOperand(0));
837 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
838
839 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
840 Alpha::ADJUSTSTACKUP;
841 BuildMI(BB, Opc, 1).addImm(Tmp1);
842 return;
843 }
844 assert(0 && "Should not be reached!");
845}
846
847
848/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
849/// into a machine code representation using pattern matching and a machine
850/// description file.
851///
852FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
853 return new ISel(TM);
854}