blob: ad492447735f05b635e28bd27f21911d60fe1991 [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 Lenharthcc1b16f2005-01-28 23:17:54 +000051 setOperationAction(ISD::ZEXTLOAD , MVT::i1 , Expand);
Andrew Lenharth304d0f32005-01-22 23:41:55 +000052 setOperationAction(ISD::ZEXTLOAD , MVT::i32 , Expand);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000053
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +000054 setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand);
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);
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000151 newroot = DAG.getCopyFromReg(argVreg[count-1], getValueType(I->getType()), DAG.getRoot());
Andrew Lenharth40831c52005-01-28 06:57:18 +0000152 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);
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000162 argt = newroot = DAG.getCopyFromReg(argVreg[count-1], MVT::i64, DAG.getRoot());
Andrew Lenharth40831c52005-01-28 06:57:18 +0000163 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);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000173 for (int i = 0; i < count; ++i)
174 BuildMI(&BB, argOpc[i], 2, argVreg[i]).addReg(argPreg[i]).addReg(argPreg[i]);
175
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000176 return ArgValues;
177}
178
179std::pair<SDOperand, SDOperand>
180AlphaTargetLowering::LowerCallTo(SDOperand Chain,
181 const Type *RetTy, SDOperand Callee,
182 ArgListTy &Args, SelectionDAG &DAG) {
183 int NumBytes = 0;
184 Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
185 DAG.getConstant(NumBytes, getPointerTy()));
186 std::vector<SDOperand> args_to_use;
187 for (unsigned i = 0, e = Args.size(); i != e; ++i)
188 {
189 switch (getValueType(Args[i].second)) {
190 default: assert(0 && "Unexpected ValueType for argument!");
191 case MVT::i1:
192 case MVT::i8:
193 case MVT::i16:
194 case MVT::i32:
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000195 // Promote the integer to 64 bits. If the input type is signed use a
196 // sign extend, otherwise use a zero extend.
197 if (Args[i].second->isSigned())
Andrew Lenharth40831c52005-01-28 06:57:18 +0000198 Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000199 else
Andrew Lenharth40831c52005-01-28 06:57:18 +0000200 Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000201 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000202 case MVT::i64:
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000203 case MVT::f64:
204 case MVT::f32:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000205 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000206 }
207 args_to_use.push_back(Args[i].first);
208 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000209
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000210 std::vector<MVT::ValueType> RetVals;
211 MVT::ValueType RetTyVT = getValueType(RetTy);
212 if (RetTyVT != MVT::isVoid)
213 RetVals.push_back(RetTyVT);
214 RetVals.push_back(MVT::Other);
215
216 SDOperand TheCall = SDOperand(DAG.getCall(RetVals, Chain, Callee, args_to_use), 0);
217 Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
218 Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
219 DAG.getConstant(NumBytes, getPointerTy()));
220 return std::make_pair(TheCall, Chain);
221}
222
223std::pair<SDOperand, SDOperand>
224AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
225 //vastart just returns the address of the VarArgsFrameIndex slot.
226 return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain);
227}
228
229std::pair<SDOperand,SDOperand> AlphaTargetLowering::
230LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
231 const Type *ArgTy, SelectionDAG &DAG) {
232 abort();
233}
234
235
236std::pair<SDOperand, SDOperand> AlphaTargetLowering::
237LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
238 SelectionDAG &DAG) {
239 abort();
240}
241
242
243
244
245
246namespace {
247
248 //===--------------------------------------------------------------------===//
249 /// ISel - Alpha specific code to select Alpha machine instructions for
250 /// SelectionDAG operations.
251 ///
252 class ISel : public SelectionDAGISel {
253
254 /// AlphaLowering - This object fully describes how to lower LLVM code to an
255 /// Alpha-specific SelectionDAG.
256 AlphaTargetLowering AlphaLowering;
257
258
259 /// ExprMap - As shared expressions are codegen'd, we keep track of which
260 /// vreg the value is produced in, so we only emit one copy of each compiled
261 /// tree.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000262 static const unsigned notIn = (unsigned)(-1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000263 std::map<SDOperand, unsigned> ExprMap;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000264
265 public:
266 ISel(TargetMachine &TM) : SelectionDAGISel(AlphaLowering), AlphaLowering(TM) {
267 }
268
269 /// InstructionSelectBasicBlock - This callback is invoked by
270 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
271 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
272 // Codegen the basic block.
273 Select(DAG.getRoot());
274
275 // Clear state used for selection.
276 ExprMap.clear();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000277 }
278
279 unsigned SelectExpr(SDOperand N);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000280 unsigned SelectExprFP(SDOperand N, unsigned Result);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000281 void Select(SDOperand N);
282 };
283}
284
Andrew Lenharth40831c52005-01-28 06:57:18 +0000285unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
286{
287 unsigned Tmp1, Tmp2, Tmp3;
288 unsigned Opc = 0;
289 SDNode *Node = N.Val;
290 MVT::ValueType DestType = N.getValueType();
291 unsigned opcode = N.getOpcode();
292
293 switch (opcode) {
294 default:
295 Node->dump();
296 assert(0 && "Node not handled!\n");
Andrew Lenharth2c594352005-01-29 15:42:07 +0000297
298 case ISD::CopyFromReg:
299 {
300 // Make sure we generate both values.
301 if (Result != notIn)
302 ExprMap[N.getValue(1)] = notIn; // Generate the token
303 else
304 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
305
306 SDOperand Chain = N.getOperand(0);
307
308 Select(Chain);
309 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
310 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
311 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(r).addReg(r);
312 return Result;
313 }
314
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000315 case ISD::LOAD:
316 {
317 // Make sure we generate both values.
318 if (Result != notIn)
319 ExprMap[N.getValue(1)] = notIn; // Generate the token
320 else
321 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
322
323 SDOperand Chain = N.getOperand(0);
324 SDOperand Address = N.getOperand(1);
325
326 if (Address.getOpcode() == ISD::GlobalAddress)
327 {
328 Select(Chain);
329 AlphaLowering.restoreGP(BB);
330 Opc = DestType == MVT::f64 ? Alpha::LDS : Alpha::LDT;
331 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
332 }
333 else
334 {
335 Select(Chain);
336 Tmp2 = SelectExpr(Address);
337 Opc = DestType == MVT::f64 ? Alpha::LDS : Alpha::LDT;
338 BuildMI(BB, Opc, 2, Result).addImm(0).addReg(Tmp2);
339 }
340 return Result;
341 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000342 case ISD::ConstantFP:
343 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
344 if (CN->isExactlyValue(+0.0)) {
345 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
346 } else {
347 abort();
348 }
349 }
350 return Result;
351
352 case ISD::MUL:
353 case ISD::ADD:
354 case ISD::SUB:
355 case ISD::SDIV:
356 switch( opcode ) {
357 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
358 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
359 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
360 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
361 };
362 Tmp1 = SelectExpr(N.getOperand(0));
363 Tmp2 = SelectExpr(N.getOperand(1));
364 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
365 return Result;
366
Andrew Lenharth2c594352005-01-29 15:42:07 +0000367 case ISD::EXTLOAD:
368 //include a conversion sequence for float loads to double
369 if (Result != notIn)
370 ExprMap[N.getValue(1)] = notIn; // Generate the token
371 else
372 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
373
374 Tmp2 = MakeReg(MVT::f32);
375
376 if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N.getOperand(1)))
377 if (Node->getValueType(0) == MVT::f64) {
378 assert(cast<MVTSDNode>(Node)->getExtraValueType() == MVT::f32 &&
379 "Bad EXTLOAD!");
380 BuildMI(BB, Alpha::LDS, 1, Tmp2).addConstantPoolIndex(CP->getIndex());
381 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp2);
382 return Result;
383 }
384 Select(Node->getOperand(0)); // chain
385 Tmp1 = SelectExpr(Node->getOperand(1));
386 BuildMI(BB, Alpha::LDS, 1, Tmp2).addReg(Tmp1);
387 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp2);
388 return Result;
389
390
391 //case ISD::UINT_TO_FP:
392
393 case ISD::SINT_TO_FP:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000394 {
395 assert (N.getOperand(0).getValueType() == MVT::i64 && "only quads can be loaded from");
396 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth2c594352005-01-29 15:42:07 +0000397
398 //The hard way:
399 // Spill the integer to memory and reload it from there.
400 unsigned Size = MVT::getSizeInBits(MVT::i64)/8;
401 MachineFunction *F = BB->getParent();
402 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, Size);
403
404 //STL LDS
405 //STQ LDT
406 Opc = DestType == MVT::f64 ? Alpha::STQ : Alpha::STL;
407 BuildMI(BB, Opc, 2).addReg(Tmp1).addFrameIndex(FrameIdx);
408 Opc = DestType == MVT::f64 ? Alpha::LDT : Alpha::LDS;
409 BuildMI(BB, Opc, 1, Result).addFrameIndex(FrameIdx);
410
411 //The easy way: doesn't work
412// //so these instructions are not supported on ev56
413// Opc = DestType == MVT::f64 ? Alpha::ITOFT : Alpha::ITOFS;
414// BuildMI(BB, Opc, 1, Tmp2).addReg(Tmp1);
415// Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
416// BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
417
Andrew Lenharth40831c52005-01-28 06:57:18 +0000418 return Result;
419 }
420 }
421 assert(0 && "should not get here");
422 return 0;
423}
424
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000425unsigned ISel::SelectExpr(SDOperand N) {
426 unsigned Result;
427 unsigned Tmp1, Tmp2, Tmp3;
428 unsigned Opc = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000429 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000430
431 SDNode *Node = N.Val;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000432 MVT::ValueType DestType = N.getValueType();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000433
434 unsigned &Reg = ExprMap[N];
435 if (Reg) return Reg;
436
437 if (N.getOpcode() != ISD::CALL)
438 Reg = Result = (N.getValueType() != MVT::Other) ?
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000439 MakeReg(N.getValueType()) : notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000440 else {
441 // If this is a call instruction, make sure to prepare ALL of the result
442 // values as well as the chain.
443 if (Node->getNumValues() == 1)
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000444 Reg = Result = notIn; // Void call, just a chain.
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000445 else {
446 Result = MakeReg(Node->getValueType(0));
447 ExprMap[N.getValue(0)] = Result;
448 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
449 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000450 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000451 }
452 }
453
Andrew Lenharth40831c52005-01-28 06:57:18 +0000454 if (DestType == MVT::f64 || DestType == MVT::f32)
455 return SelectExprFP(N, Result);
456
457 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000458 default:
459 Node->dump();
460 assert(0 && "Node not handled!\n");
461
Andrew Lenharth2c594352005-01-29 15:42:07 +0000462 case ISD::ConstantPool:
463 Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
464 AlphaLowering.restoreGP(BB);
465 BuildMI(BB, Alpha::LOAD, 1, Result).addConstantPoolIndex(Tmp1);
466 return Result;
467
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000468 case ISD::FrameIndex:
469 Tmp1 = cast<FrameIndexSDNode>(N)->getIndex();
Andrew Lenharth2c594352005-01-29 15:42:07 +0000470 BuildMI(BB, Alpha::LDA, 2, Result).addFrameIndex(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000471 return Result;
472
473 case ISD::EXTLOAD:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000474 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000475 if (Result != notIn)
476 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000477 else
478 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
479
480 Select(Node->getOperand(0)); // chain
481 Tmp1 = SelectExpr(Node->getOperand(1));
482
483 switch(Node->getValueType(0)) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000484 default: Node->dump(); assert(0 && "Unknown type to sign extend to.");
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000485 case MVT::i64:
486 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
487 default:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000488 Node->dump();
489 assert(0 && "Bad extend load!");
Andrew Lenharthd279b412005-01-25 19:58:40 +0000490 case MVT::i64:
491 BuildMI(BB, Alpha::LDQ, 2, Result).addImm(0).addReg(Tmp1);
492 break;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000493 case MVT::i32:
494 BuildMI(BB, Alpha::LDL, 2, Result).addImm(0).addReg(Tmp1);
495 break;
496 case MVT::i16:
497 BuildMI(BB, Alpha::LDWU, 2, Result).addImm(0).addReg(Tmp1);
498 break;
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000499 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000500 case MVT::i8:
501 BuildMI(BB, Alpha::LDBU, 2, Result).addImm(0).addReg(Tmp1);
502 break;
503 }
504 break;
505 }
506 return Result;
507
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000508 case ISD::SEXTLOAD:
509 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000510 if (Result != notIn)
511 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000512 else
513 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
514
515 Select(Node->getOperand(0)); // chain
516 Tmp1 = SelectExpr(Node->getOperand(1));
517 switch(Node->getValueType(0)) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000518 default: Node->dump(); assert(0 && "Unknown type to sign extend to.");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000519 case MVT::i64:
520 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
521 default:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000522 Node->dump();
523 assert(0 && "Bad sign extend!");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000524 case MVT::i32:
525 BuildMI(BB, Alpha::LDL, 2, Result).addImm(0).addReg(Tmp1);
526 break;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000527 }
528 break;
529 }
530 return Result;
531
532 case ISD::ZEXTLOAD:
533 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000534 if (Result != notIn)
535 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000536 else
537 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
538
539 Select(Node->getOperand(0)); // chain
540 Tmp1 = SelectExpr(Node->getOperand(1));
541 switch(Node->getValueType(0)) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000542 default: Node->dump(); assert(0 && "Unknown type to zero extend to.");
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000543 case MVT::i64:
544 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
545 default:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000546 Node->dump();
547 assert(0 && "Bad sign extend!");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000548 case MVT::i16:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000549 BuildMI(BB, Alpha::LDWU, 2, Result).addImm(0).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000550 break;
551 case MVT::i8:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000552 BuildMI(BB, Alpha::LDBU, 2, Result).addImm(0).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000553 break;
554 }
555 break;
556 }
557 return Result;
558
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000559
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000560 case ISD::GlobalAddress:
561 AlphaLowering.restoreGP(BB);
562 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
563 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
564 return Result;
565
566 case ISD::CALL:
567 {
568 Select(N.getOperand(0));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000569
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000570 // The chain for this call is now lowered.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000571 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), notIn));
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000572
573 //grab the arguments
574 std::vector<unsigned> argvregs;
575 assert(Node->getNumOperands() < 8 && "Only 6 args supported");
576 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000577 argvregs.push_back(SelectExpr(N.getOperand(i)));
578
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000579 for(int i = 0, e = argvregs.size(); i < e; ++i)
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000580 {
581 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
582 Alpha::R19, Alpha::R20, Alpha::R21};
583 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
584 Alpha::F19, Alpha::F20, Alpha::F21};
Andrew Lenharth7e57bd52005-01-27 01:22:48 +0000585 switch(N.getOperand(i+2).getValueType()) {
586 default:
587 Node->dump();
588 N.getOperand(i).Val->dump();
589 std::cerr << "Type for " << i << " is: " << N.getOperand(i+2).getValueType() << "\n";
590 assert(0 && "Unknown value type for call");
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000591 case MVT::i1:
592 case MVT::i8:
593 case MVT::i16:
594 case MVT::i32:
595 case MVT::i64:
596 BuildMI(BB, Alpha::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
597 break;
598 case MVT::f32:
599 case MVT::f64:
600 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
601 break;
602 }
603
604 }
605 //build the right kind of call
606 if (GlobalAddressSDNode *GASD =
607 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
608 {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000609 AlphaLowering.restoreGP(BB);
610 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
611 }
612 else if (ExternalSymbolSDNode *ESSDN =
613 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
614 {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000615 AlphaLowering.restoreGP(BB);
616 BuildMI(BB, Alpha::CALL, 0).addExternalSymbol(ESSDN->getSymbol(), true);
617 }
618 else
619 {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000620 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000621 AlphaLowering.restoreGP(BB);
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000622 BuildMI(BB, Alpha::CALL, 1).addReg(Tmp1);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000623 }
624
625 //push the result into a virtual register
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000626
627 switch (Node->getValueType(0)) {
628 default: Node->dump(); assert(0 && "Unknown value type for call result!");
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000629 case MVT::Other: return notIn;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000630 case MVT::i1:
631 case MVT::i8:
632 case MVT::i16:
633 case MVT::i32:
634 case MVT::i64:
635 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
636 break;
637 case MVT::f32:
638 case MVT::f64:
639 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
640 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000641 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000642 return Result+N.ResNo;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000643 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000644
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000645 case ISD::SIGN_EXTEND:
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000646 abort();
647
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000648 case ISD::SIGN_EXTEND_INREG:
649 {
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000650 //Alpha has instructions for a bunch of signed 32 bit stuff
651 if( dyn_cast<MVTSDNode>(Node)->getExtraValueType() == MVT::i32)
652 {
653 switch (N.getOperand(0).getOpcode()) {
654 case ISD::ADD:
655 case ISD::SUB:
656 case ISD::MUL:
657 {
658 bool isAdd = N.getOperand(0).getOpcode() == ISD::ADD;
659 bool isMul = N.getOperand(0).getOpcode() == ISD::MUL;
660 //FIXME: first check for Scaled Adds and Subs!
661 if(N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
662 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() <= 255)
663 { //Normal imm add/sub
664 Opc = isAdd ? Alpha::ADDLi : (isMul ? Alpha::MULLi : Alpha::SUBLi);
665 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
666 Tmp2 = cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue();
667 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
668 }
669 else
670 { //Normal add/sub
671 Opc = isAdd ? Alpha::ADDL : (isMul ? Alpha::MULLi : Alpha::SUBL);
672 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
673 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
674 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
675 }
676 return Result;
677 }
678 default: break; //Fall Though;
679 }
680 } //Every thing else fall though too, including unhandled opcodes above
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000681 Tmp1 = SelectExpr(N.getOperand(0));
682 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000683 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000684 switch(MVN->getExtraValueType())
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000685 {
686 default:
687 Node->dump();
688 assert(0 && "Sign Extend InReg not there yet");
689 break;
690 case MVT::i32:
691 {
692 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
693 break;
694 }
695 case MVT::i16:
696 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
697 break;
698 case MVT::i8:
699 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
700 break;
701 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000702 return Result;
703 }
704 case ISD::ZERO_EXTEND_INREG:
705 {
706 Tmp1 = SelectExpr(N.getOperand(0));
707 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000708 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000709 switch(MVN->getExtraValueType())
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000710 {
711 default:
712 Node->dump();
713 assert(0 && "Zero Extend InReg not there yet");
714 break;
715 case MVT::i32: Tmp2 = 0xf0; break;
716 case MVT::i16: Tmp2 = 0xfc; break;
717 case MVT::i8: Tmp2 = 0xfe; break;
718 case MVT::i1: //handle this one special
719 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
720 return Result;
721 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000722 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000723 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000724 }
725
726 case ISD::SETCC:
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000727 {
728 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
729 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
730 bool isConst1 = false;
731 bool isConst2 = false;
732 int dir;
733
734 //Tmp1 = SelectExpr(N.getOperand(0));
735 if(N.getOperand(0).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000736 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
737 isConst1 = true;
738 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000739 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
740 isConst2 = true;
741
742 switch (SetCC->getCondition()) {
743 default: Node->dump(); assert(0 && "Unknown integer comparison!");
744 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
745 case ISD::SETLT: Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
746 case ISD::SETLE: Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
747 case ISD::SETGT: Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
748 case ISD::SETGE: Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
749 case ISD::SETULT: Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
750 case ISD::SETUGT: Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
751 case ISD::SETULE: Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
752 case ISD::SETUGE: Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000753 case ISD::SETNE: {//Handle this one special
754 //std::cerr << "Alpha does not have a setne.\n";
755 //abort();
756 Tmp1 = SelectExpr(N.getOperand(0));
757 Tmp2 = SelectExpr(N.getOperand(1));
758 Tmp3 = MakeReg(MVT::i64);
759 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
760 //and invert
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000761 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
762 //BuildMI(BB,Alpha::ORNOT, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000763 return Result;
764 }
765 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000766 if (dir == 1) {
767 Tmp1 = SelectExpr(N.getOperand(0));
768 if (isConst2) {
769 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
770 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
771 } else {
772 Tmp2 = SelectExpr(N.getOperand(1));
773 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
774 }
775 } else if (dir == 2) {
776 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth6b9870a2005-01-28 14:06:46 +0000777 if (isConst1) {
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000778 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
779 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
780 } else {
781 Tmp2 = SelectExpr(N.getOperand(0));
782 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
783 }
784 } else { //dir == 0
785 if (isConst1) {
786 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
787 Tmp2 = SelectExpr(N.getOperand(1));
788 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
789 } else if (isConst2) {
790 Tmp1 = SelectExpr(N.getOperand(0));
791 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
792 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
793 } else {
794 Tmp1 = SelectExpr(N.getOperand(0));
795 Tmp2 = SelectExpr(N.getOperand(1));
796 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
797 }
798 }
799 }
800 else
801 {
802 Node->dump();
803 assert(0 && "only integer");
804 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000805 }
806 else
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000807 {
808 Node->dump();
809 assert(0 && "Not a setcc in setcc");
810 }
811 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000812 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000813
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000814 case ISD::CopyFromReg:
815 {
Andrew Lenharth40831c52005-01-28 06:57:18 +0000816 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000817 if (Result != notIn)
818 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth40831c52005-01-28 06:57:18 +0000819 else
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000820 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth40831c52005-01-28 06:57:18 +0000821
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000822 SDOperand Chain = N.getOperand(0);
823
824 Select(Chain);
825 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
826 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
827 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
828 return Result;
829 }
830
Andrew Lenharth2d6f0222005-01-24 19:44:07 +0000831 //Most of the plain arithmetic and logic share the same form, and the same
832 //constant immediate test
833 case ISD::AND:
834 case ISD::OR:
835 case ISD::XOR:
836 case ISD::SHL:
837 case ISD::SRL:
Andrew Lenharth2c594352005-01-29 15:42:07 +0000838 case ISD::SRA:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +0000839 case ISD::MUL:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000840 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
841 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +0000842 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
843 {
844 switch(opcode) {
845 case ISD::AND: Opc = Alpha::ANDi; break;
846 case ISD::OR: Opc = Alpha::BISi; break;
847 case ISD::XOR: Opc = Alpha::XORi; break;
848 case ISD::SHL: Opc = Alpha::SLi; break;
849 case ISD::SRL: Opc = Alpha::SRLi; break;
850 case ISD::SRA: Opc = Alpha::SRAi; break;
851 case ISD::MUL: Opc = Alpha::MULQi; break;
852 };
853 Tmp1 = SelectExpr(N.getOperand(0));
854 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
855 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
856 }
857 else
858 {
859 switch(opcode) {
860 case ISD::AND: Opc = Alpha::AND; break;
861 case ISD::OR: Opc = Alpha::BIS; break;
862 case ISD::XOR: Opc = Alpha::XOR; break;
863 case ISD::SHL: Opc = Alpha::SL; break;
864 case ISD::SRL: Opc = Alpha::SRL; break;
865 case ISD::SRA: Opc = Alpha::SRA; break;
866 case ISD::MUL: Opc = Alpha::MULQ; break;
867 };
868 Tmp1 = SelectExpr(N.getOperand(0));
869 Tmp2 = SelectExpr(N.getOperand(1));
870 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
871 }
Andrew Lenharth2d6f0222005-01-24 19:44:07 +0000872 return Result;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000873
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000874 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000875 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000876 {
Andrew Lenharth40831c52005-01-28 06:57:18 +0000877 bool isAdd = opcode == ISD::ADD;
878
879 //FIXME: first check for Scaled Adds and Subs!
880 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +0000881 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
882 { //Normal imm add/sub
883 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
884 Tmp1 = SelectExpr(N.getOperand(0));
885 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
886 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
887 }
888 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +0000889 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767)
890 { //LDA //FIXME: expand the above condition a bit
891 Tmp1 = SelectExpr(N.getOperand(0));
892 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
893 if (!isAdd)
894 Tmp2 = -Tmp2;
895 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
896 }
897 else
898 { //Normal add/sub
899 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
900 Tmp1 = SelectExpr(N.getOperand(0));
901 Tmp2 = SelectExpr(N.getOperand(1));
902 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
903 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000904 return Result;
905 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000906
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000907 case ISD::UREM:
Andrew Lenharth02981182005-01-26 01:24:38 +0000908 case ISD::SREM:
909 case ISD::SDIV:
910 case ISD::UDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000911 //FIXME: alpha really doesn't support any of these operations,
912 // the ops are expanded into special library calls with
913 // special calling conventions
914 switch(opcode) {
915 case ISD::UREM: Opc = Alpha::REMQU; break;
916 case ISD::SREM: Opc = Alpha::REMQ; break;
917 case ISD::UDIV: Opc = Alpha::DIVQU; break;
918 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000919 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000920 Tmp1 = SelectExpr(N.getOperand(0));
921 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth02981182005-01-26 01:24:38 +0000922 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000923 return Result;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000924// // case ISD::UINT_TO_FP:
925
926// case ISD::FP_TO_SINT:
927// assert (N.getValueType() == MVT::f64 && "Only can convert for doubles");
928// Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
929// Tmp2 = MakeReg(SrcTy);
930// BuildMI(BB, CVTTQ, 1, Tmp2).addReg(Tmp1);
931// BuildMI(BB, FTOIT, 1, Result).addReg(Tmp2);
932// return result;
933
934// // case ISD::FP_TO_UINT:
935
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000936 case ISD::SELECT:
937 {
938 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
939 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
940 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
941 // Get the condition into the zero flag.
942 unsigned dummy = MakeReg(MVT::i64);
943 BuildMI(BB, Alpha::BIS, 2, dummy).addReg(Tmp3).addReg(Tmp3);
944 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
945 return Result;
946 }
947
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000948 case ISD::Constant:
949 {
950 long val = cast<ConstantSDNode>(N)->getValue();
951 BuildMI(BB, Alpha::LOAD_IMM, 1, Result).addImm(val);
952 return Result;
953 }
954
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000955 case ISD::LOAD:
956 {
957 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000958 if (Result != notIn)
959 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000960 else
961 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
962
963 SDOperand Chain = N.getOperand(0);
964 SDOperand Address = N.getOperand(1);
965
966 if (Address.getOpcode() == ISD::GlobalAddress)
967 {
968 Select(Chain);
969 AlphaLowering.restoreGP(BB);
970 BuildMI(BB, Alpha::LOAD, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
971 }
972 else
973 {
974 Select(Chain);
975 Tmp2 = SelectExpr(Address);
976 BuildMI(BB, Alpha::LDQ, 2, Result).addImm(0).addReg(Tmp2);
977 }
978 return Result;
979 }
980 }
981
982 return 0;
983}
984
985void ISel::Select(SDOperand N) {
986 unsigned Tmp1, Tmp2, Opc;
987
Andrew Lenharth6b9870a2005-01-28 14:06:46 +0000988 // FIXME: Disable for our current expansion model!
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000989 if (/*!N->hasOneUse() &&*/ !ExprMap.insert(std::make_pair(N, notIn)).second)
Andrew Lenharth6b9870a2005-01-28 14:06:46 +0000990 return; // Already selected.
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000991
992 SDNode *Node = N.Val;
993
994 switch (N.getOpcode()) {
995
996 default:
997 Node->dump(); std::cerr << "\n";
998 assert(0 && "Node not handled yet!");
999
1000 case ISD::BRCOND: {
1001 MachineBasicBlock *Dest =
1002 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
1003
1004 Select(N.getOperand(0));
1005 Tmp1 = SelectExpr(N.getOperand(1));
1006 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
1007 return;
1008 }
1009
1010 case ISD::BR: {
1011 MachineBasicBlock *Dest =
1012 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
1013
1014 Select(N.getOperand(0));
1015 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
1016 return;
1017 }
1018
1019 case ISD::ImplicitDef:
1020 Select(N.getOperand(0));
1021 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
1022 return;
1023
1024 case ISD::EntryToken: return; // Noop
1025
1026 case ISD::TokenFactor:
1027 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
1028 Select(Node->getOperand(i));
1029
1030 //N.Val->dump(); std::cerr << "\n";
1031 //assert(0 && "Node not handled yet!");
1032
1033 return;
1034
1035 case ISD::CopyToReg:
1036 Select(N.getOperand(0));
1037 Tmp1 = SelectExpr(N.getOperand(1));
1038 Tmp2 = cast<RegSDNode>(N)->getReg();
1039
1040 if (Tmp1 != Tmp2) {
1041 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
1042 }
1043 return;
1044
1045 case ISD::RET:
1046 switch (N.getNumOperands()) {
1047 default:
1048 std::cerr << N.getNumOperands() << "\n";
1049 for (unsigned i = 0; i < N.getNumOperands(); ++i)
1050 std::cerr << N.getOperand(i).getValueType() << "\n";
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001051 Node->dump();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001052 assert(0 && "Unknown return instruction!");
1053 case 2:
1054 Select(N.getOperand(0));
1055 Tmp1 = SelectExpr(N.getOperand(1));
1056 switch (N.getOperand(1).getValueType()) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001057 default: Node->dump(); assert(0 && "All other types should have been promoted!!");
1058 case MVT::f64:
1059 case MVT::f32:
1060 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
1061 break;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001062 case MVT::i32:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001063 case MVT::i64:
1064 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
1065 break;
1066 }
1067 break;
1068 case 1:
1069 Select(N.getOperand(0));
1070 break;
1071 }
1072 //Tmp2 = AlphaLowering.getRetAddr();
1073 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
1074 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
1075 return;
1076
1077 case ISD::STORE:
1078 Select(N.getOperand(0));
1079 Tmp1 = SelectExpr(N.getOperand(1)); //value
1080 if (N.getOperand(2).getOpcode() == ISD::GlobalAddress)
1081 {
1082 AlphaLowering.restoreGP(BB);
1083 BuildMI(BB, Alpha::STORE, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(N.getOperand(2))->getGlobal());
1084 }
1085 else
1086 {
1087 Tmp2 = SelectExpr(N.getOperand(2)); //address
1088 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addImm(0).addReg(Tmp2);
1089 }
1090 return;
1091
1092 case ISD::EXTLOAD:
1093 case ISD::SEXTLOAD:
1094 case ISD::ZEXTLOAD:
1095 case ISD::LOAD:
1096 case ISD::CopyFromReg:
1097 case ISD::CALL:
1098// case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001099 ExprMap.erase(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001100 SelectExpr(N);
1101 return;
1102
1103
1104 case ISD::TRUNCSTORE: { // truncstore chain, val, ptr :storety
1105 MVT::ValueType StoredTy = cast<MVTSDNode>(Node)->getExtraValueType();
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001106 if (StoredTy == MVT::i64) {
1107 Node->dump();
1108 assert(StoredTy != MVT::i64 && "Unsupported TRUNCSTORE for this target!");
1109 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001110
1111 Select(N.getOperand(0));
1112 Tmp1 = SelectExpr(N.getOperand(1));
1113 Tmp2 = SelectExpr(N.getOperand(2));
1114
1115 switch (StoredTy) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001116 default: Node->dump(); assert(0 && "Unhandled Type"); break;
Andrew Lenharthd279b412005-01-25 19:58:40 +00001117 case MVT::i1: //FIXME: DAG does not promote this load
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001118 case MVT::i8: Opc = Alpha::STB; break;
1119 case MVT::i16: Opc = Alpha::STW; break;
1120 case MVT::i32: Opc = Alpha::STL; break;
1121 }
1122
1123 BuildMI(BB, Opc, 2).addReg(Tmp1).addImm(0).addReg(Tmp2);
1124 return;
1125 }
1126
1127 case ISD::ADJCALLSTACKDOWN:
1128 case ISD::ADJCALLSTACKUP:
1129 Select(N.getOperand(0));
1130 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1131
1132 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
1133 Alpha::ADJUSTSTACKUP;
1134 BuildMI(BB, Opc, 1).addImm(Tmp1);
1135 return;
1136 }
1137 assert(0 && "Should not be reached!");
1138}
1139
1140
1141/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
1142/// into a machine code representation using pattern matching and a machine
1143/// description file.
1144///
1145FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
1146 return new ISel(TM);
1147}