blob: 58d6227eddfe58fd7db3240b0cf895b4fa9ad3d7 [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 Lenharthcc1b16f2005-01-28 23:17:54 +0000297 case ISD::LOAD:
298 {
299 // Make sure we generate both values.
300 if (Result != notIn)
301 ExprMap[N.getValue(1)] = notIn; // Generate the token
302 else
303 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
304
305 SDOperand Chain = N.getOperand(0);
306 SDOperand Address = N.getOperand(1);
307
308 if (Address.getOpcode() == ISD::GlobalAddress)
309 {
310 Select(Chain);
311 AlphaLowering.restoreGP(BB);
312 Opc = DestType == MVT::f64 ? Alpha::LDS : Alpha::LDT;
313 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
314 }
315 else
316 {
317 Select(Chain);
318 Tmp2 = SelectExpr(Address);
319 Opc = DestType == MVT::f64 ? Alpha::LDS : Alpha::LDT;
320 BuildMI(BB, Opc, 2, Result).addImm(0).addReg(Tmp2);
321 }
322 return Result;
323 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000324 case ISD::ConstantFP:
325 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
326 if (CN->isExactlyValue(+0.0)) {
327 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
328 } else {
329 abort();
330 }
331 }
332 return Result;
333
334 case ISD::MUL:
335 case ISD::ADD:
336 case ISD::SUB:
337 case ISD::SDIV:
338 switch( opcode ) {
339 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
340 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
341 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
342 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
343 };
344 Tmp1 = SelectExpr(N.getOperand(0));
345 Tmp2 = SelectExpr(N.getOperand(1));
346 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
347 return Result;
348
349 case ISD::SINT_TO_FP:
350 {
351 assert (N.getOperand(0).getValueType() == MVT::i64 && "only quads can be loaded from");
352 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
353 Tmp2 = MakeReg(DestType);
354 //so these instructions are not supported on ev56
355 Opc = DestType == MVT::f64 ? Alpha::ITOFT : Alpha::ITOFS;
356 BuildMI(BB, Opc, 1, Tmp2).addReg(Tmp1);
357 Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
358 BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
359 return Result;
360 }
361 }
362 assert(0 && "should not get here");
363 return 0;
364}
365
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000366unsigned ISel::SelectExpr(SDOperand N) {
367 unsigned Result;
368 unsigned Tmp1, Tmp2, Tmp3;
369 unsigned Opc = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000370 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000371
372 SDNode *Node = N.Val;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000373 MVT::ValueType DestType = N.getValueType();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000374
375 unsigned &Reg = ExprMap[N];
376 if (Reg) return Reg;
377
378 if (N.getOpcode() != ISD::CALL)
379 Reg = Result = (N.getValueType() != MVT::Other) ?
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000380 MakeReg(N.getValueType()) : notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000381 else {
382 // If this is a call instruction, make sure to prepare ALL of the result
383 // values as well as the chain.
384 if (Node->getNumValues() == 1)
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000385 Reg = Result = notIn; // Void call, just a chain.
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000386 else {
387 Result = MakeReg(Node->getValueType(0));
388 ExprMap[N.getValue(0)] = Result;
389 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
390 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000391 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000392 }
393 }
394
Andrew Lenharth40831c52005-01-28 06:57:18 +0000395 if (DestType == MVT::f64 || DestType == MVT::f32)
396 return SelectExprFP(N, Result);
397
398 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000399 default:
400 Node->dump();
401 assert(0 && "Node not handled!\n");
402
403 case ISD::FrameIndex:
404 Tmp1 = cast<FrameIndexSDNode>(N)->getIndex();
405 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp1 * 8).addReg(Alpha::R30);
406 return Result;
407
408 case ISD::EXTLOAD:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000409 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000410 if (Result != notIn)
411 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000412 else
413 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
414
415 Select(Node->getOperand(0)); // chain
416 Tmp1 = SelectExpr(Node->getOperand(1));
417
418 switch(Node->getValueType(0)) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000419 default: Node->dump(); assert(0 && "Unknown type to sign extend to.");
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000420 case MVT::i64:
421 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
422 default:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000423 Node->dump();
424 assert(0 && "Bad extend load!");
Andrew Lenharthd279b412005-01-25 19:58:40 +0000425 case MVT::i64:
426 BuildMI(BB, Alpha::LDQ, 2, Result).addImm(0).addReg(Tmp1);
427 break;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000428 case MVT::i32:
429 BuildMI(BB, Alpha::LDL, 2, Result).addImm(0).addReg(Tmp1);
430 break;
431 case MVT::i16:
432 BuildMI(BB, Alpha::LDWU, 2, Result).addImm(0).addReg(Tmp1);
433 break;
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000434 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000435 case MVT::i8:
436 BuildMI(BB, Alpha::LDBU, 2, Result).addImm(0).addReg(Tmp1);
437 break;
438 }
439 break;
440 }
441 return Result;
442
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000443 case ISD::SEXTLOAD:
444 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000445 if (Result != notIn)
446 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000447 else
448 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
449
450 Select(Node->getOperand(0)); // chain
451 Tmp1 = SelectExpr(Node->getOperand(1));
452 switch(Node->getValueType(0)) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000453 default: Node->dump(); assert(0 && "Unknown type to sign extend to.");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000454 case MVT::i64:
455 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
456 default:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000457 Node->dump();
458 assert(0 && "Bad sign extend!");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000459 case MVT::i32:
460 BuildMI(BB, Alpha::LDL, 2, Result).addImm(0).addReg(Tmp1);
461 break;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000462 }
463 break;
464 }
465 return Result;
466
467 case ISD::ZEXTLOAD:
468 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000469 if (Result != notIn)
470 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000471 else
472 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
473
474 Select(Node->getOperand(0)); // chain
475 Tmp1 = SelectExpr(Node->getOperand(1));
476 switch(Node->getValueType(0)) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000477 default: Node->dump(); assert(0 && "Unknown type to zero extend to.");
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000478 case MVT::i64:
479 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
480 default:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000481 Node->dump();
482 assert(0 && "Bad sign extend!");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000483 case MVT::i16:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000484 BuildMI(BB, Alpha::LDWU, 2, Result).addImm(0).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000485 break;
486 case MVT::i8:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000487 BuildMI(BB, Alpha::LDBU, 2, Result).addImm(0).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000488 break;
489 }
490 break;
491 }
492 return Result;
493
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000494
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000495 case ISD::GlobalAddress:
496 AlphaLowering.restoreGP(BB);
497 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
498 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
499 return Result;
500
501 case ISD::CALL:
502 {
503 Select(N.getOperand(0));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000504
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000505 // The chain for this call is now lowered.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000506 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), notIn));
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000507
508 //grab the arguments
509 std::vector<unsigned> argvregs;
510 assert(Node->getNumOperands() < 8 && "Only 6 args supported");
511 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000512 argvregs.push_back(SelectExpr(N.getOperand(i)));
513
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000514 for(int i = 0, e = argvregs.size(); i < e; ++i)
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000515 {
516 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
517 Alpha::R19, Alpha::R20, Alpha::R21};
518 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
519 Alpha::F19, Alpha::F20, Alpha::F21};
Andrew Lenharth7e57bd52005-01-27 01:22:48 +0000520 switch(N.getOperand(i+2).getValueType()) {
521 default:
522 Node->dump();
523 N.getOperand(i).Val->dump();
524 std::cerr << "Type for " << i << " is: " << N.getOperand(i+2).getValueType() << "\n";
525 assert(0 && "Unknown value type for call");
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000526 case MVT::i1:
527 case MVT::i8:
528 case MVT::i16:
529 case MVT::i32:
530 case MVT::i64:
531 BuildMI(BB, Alpha::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
532 break;
533 case MVT::f32:
534 case MVT::f64:
535 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
536 break;
537 }
538
539 }
540 //build the right kind of call
541 if (GlobalAddressSDNode *GASD =
542 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
543 {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000544 AlphaLowering.restoreGP(BB);
545 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
546 }
547 else if (ExternalSymbolSDNode *ESSDN =
548 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
549 {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000550 AlphaLowering.restoreGP(BB);
551 BuildMI(BB, Alpha::CALL, 0).addExternalSymbol(ESSDN->getSymbol(), true);
552 }
553 else
554 {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000555 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000556 AlphaLowering.restoreGP(BB);
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000557 BuildMI(BB, Alpha::CALL, 1).addReg(Tmp1);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000558 }
559
560 //push the result into a virtual register
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000561
562 switch (Node->getValueType(0)) {
563 default: Node->dump(); assert(0 && "Unknown value type for call result!");
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000564 case MVT::Other: return notIn;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000565 case MVT::i1:
566 case MVT::i8:
567 case MVT::i16:
568 case MVT::i32:
569 case MVT::i64:
570 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
571 break;
572 case MVT::f32:
573 case MVT::f64:
574 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
575 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000576 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000577 return Result+N.ResNo;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000578 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000579
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000580 case ISD::SIGN_EXTEND:
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000581 abort();
582
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000583 case ISD::SIGN_EXTEND_INREG:
584 {
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000585 //Alpha has instructions for a bunch of signed 32 bit stuff
586 if( dyn_cast<MVTSDNode>(Node)->getExtraValueType() == MVT::i32)
587 {
588 switch (N.getOperand(0).getOpcode()) {
589 case ISD::ADD:
590 case ISD::SUB:
591 case ISD::MUL:
592 {
593 bool isAdd = N.getOperand(0).getOpcode() == ISD::ADD;
594 bool isMul = N.getOperand(0).getOpcode() == ISD::MUL;
595 //FIXME: first check for Scaled Adds and Subs!
596 if(N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
597 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() <= 255)
598 { //Normal imm add/sub
599 Opc = isAdd ? Alpha::ADDLi : (isMul ? Alpha::MULLi : Alpha::SUBLi);
600 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
601 Tmp2 = cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue();
602 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
603 }
604 else
605 { //Normal add/sub
606 Opc = isAdd ? Alpha::ADDL : (isMul ? Alpha::MULLi : Alpha::SUBL);
607 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
608 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
609 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
610 }
611 return Result;
612 }
613 default: break; //Fall Though;
614 }
615 } //Every thing else fall though too, including unhandled opcodes above
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000616 Tmp1 = SelectExpr(N.getOperand(0));
617 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000618 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000619 switch(MVN->getExtraValueType())
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000620 {
621 default:
622 Node->dump();
623 assert(0 && "Sign Extend InReg not there yet");
624 break;
625 case MVT::i32:
626 {
627 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
628 break;
629 }
630 case MVT::i16:
631 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
632 break;
633 case MVT::i8:
634 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
635 break;
636 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000637 return Result;
638 }
639 case ISD::ZERO_EXTEND_INREG:
640 {
641 Tmp1 = SelectExpr(N.getOperand(0));
642 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000643 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000644 switch(MVN->getExtraValueType())
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000645 {
646 default:
647 Node->dump();
648 assert(0 && "Zero Extend InReg not there yet");
649 break;
650 case MVT::i32: Tmp2 = 0xf0; break;
651 case MVT::i16: Tmp2 = 0xfc; break;
652 case MVT::i8: Tmp2 = 0xfe; break;
653 case MVT::i1: //handle this one special
654 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
655 return Result;
656 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000657 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000658 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000659 }
660
661 case ISD::SETCC:
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000662 {
663 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
664 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
665 bool isConst1 = false;
666 bool isConst2 = false;
667 int dir;
668
669 //Tmp1 = SelectExpr(N.getOperand(0));
670 if(N.getOperand(0).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000671 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
672 isConst1 = true;
673 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000674 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
675 isConst2 = true;
676
677 switch (SetCC->getCondition()) {
678 default: Node->dump(); assert(0 && "Unknown integer comparison!");
679 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
680 case ISD::SETLT: Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
681 case ISD::SETLE: Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
682 case ISD::SETGT: Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
683 case ISD::SETGE: Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
684 case ISD::SETULT: Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
685 case ISD::SETUGT: Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
686 case ISD::SETULE: Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
687 case ISD::SETUGE: Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000688 case ISD::SETNE: {//Handle this one special
689 //std::cerr << "Alpha does not have a setne.\n";
690 //abort();
691 Tmp1 = SelectExpr(N.getOperand(0));
692 Tmp2 = SelectExpr(N.getOperand(1));
693 Tmp3 = MakeReg(MVT::i64);
694 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
695 //and invert
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000696 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
697 //BuildMI(BB,Alpha::ORNOT, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000698 return Result;
699 }
700 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000701 if (dir == 1) {
702 Tmp1 = SelectExpr(N.getOperand(0));
703 if (isConst2) {
704 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
705 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
706 } else {
707 Tmp2 = SelectExpr(N.getOperand(1));
708 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
709 }
710 } else if (dir == 2) {
711 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth6b9870a2005-01-28 14:06:46 +0000712 if (isConst1) {
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000713 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
714 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
715 } else {
716 Tmp2 = SelectExpr(N.getOperand(0));
717 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
718 }
719 } else { //dir == 0
720 if (isConst1) {
721 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
722 Tmp2 = SelectExpr(N.getOperand(1));
723 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
724 } else if (isConst2) {
725 Tmp1 = SelectExpr(N.getOperand(0));
726 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
727 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
728 } else {
729 Tmp1 = SelectExpr(N.getOperand(0));
730 Tmp2 = SelectExpr(N.getOperand(1));
731 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
732 }
733 }
734 }
735 else
736 {
737 Node->dump();
738 assert(0 && "only integer");
739 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000740 }
741 else
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000742 {
743 Node->dump();
744 assert(0 && "Not a setcc in setcc");
745 }
746 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000747 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000748
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000749 case ISD::CopyFromReg:
750 {
Andrew Lenharth40831c52005-01-28 06:57:18 +0000751 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000752 if (Result != notIn)
753 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth40831c52005-01-28 06:57:18 +0000754 else
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000755 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth40831c52005-01-28 06:57:18 +0000756
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000757 SDOperand Chain = N.getOperand(0);
758
759 Select(Chain);
760 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
761 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
762 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
763 return Result;
764 }
765
Andrew Lenharth2d6f0222005-01-24 19:44:07 +0000766 //Most of the plain arithmetic and logic share the same form, and the same
767 //constant immediate test
768 case ISD::AND:
769 case ISD::OR:
770 case ISD::XOR:
771 case ISD::SHL:
772 case ISD::SRL:
773 case ISD::MUL:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000774 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
775 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +0000776 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
777 {
778 switch(opcode) {
779 case ISD::AND: Opc = Alpha::ANDi; break;
780 case ISD::OR: Opc = Alpha::BISi; break;
781 case ISD::XOR: Opc = Alpha::XORi; break;
782 case ISD::SHL: Opc = Alpha::SLi; break;
783 case ISD::SRL: Opc = Alpha::SRLi; break;
784 case ISD::SRA: Opc = Alpha::SRAi; break;
785 case ISD::MUL: Opc = Alpha::MULQi; break;
786 };
787 Tmp1 = SelectExpr(N.getOperand(0));
788 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
789 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
790 }
791 else
792 {
793 switch(opcode) {
794 case ISD::AND: Opc = Alpha::AND; break;
795 case ISD::OR: Opc = Alpha::BIS; break;
796 case ISD::XOR: Opc = Alpha::XOR; break;
797 case ISD::SHL: Opc = Alpha::SL; break;
798 case ISD::SRL: Opc = Alpha::SRL; break;
799 case ISD::SRA: Opc = Alpha::SRA; break;
800 case ISD::MUL: Opc = Alpha::MULQ; break;
801 };
802 Tmp1 = SelectExpr(N.getOperand(0));
803 Tmp2 = SelectExpr(N.getOperand(1));
804 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
805 }
Andrew Lenharth2d6f0222005-01-24 19:44:07 +0000806 return Result;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000807
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000808 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000809 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000810 {
Andrew Lenharth40831c52005-01-28 06:57:18 +0000811 bool isAdd = opcode == ISD::ADD;
812
813 //FIXME: first check for Scaled Adds and Subs!
814 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +0000815 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
816 { //Normal imm add/sub
817 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
818 Tmp1 = SelectExpr(N.getOperand(0));
819 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
820 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
821 }
822 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +0000823 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767)
824 { //LDA //FIXME: expand the above condition a bit
825 Tmp1 = SelectExpr(N.getOperand(0));
826 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
827 if (!isAdd)
828 Tmp2 = -Tmp2;
829 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
830 }
831 else
832 { //Normal add/sub
833 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
834 Tmp1 = SelectExpr(N.getOperand(0));
835 Tmp2 = SelectExpr(N.getOperand(1));
836 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
837 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000838 return Result;
839 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000840
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000841 case ISD::UREM:
Andrew Lenharth02981182005-01-26 01:24:38 +0000842 case ISD::SREM:
843 case ISD::SDIV:
844 case ISD::UDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000845 //FIXME: alpha really doesn't support any of these operations,
846 // the ops are expanded into special library calls with
847 // special calling conventions
848 switch(opcode) {
849 case ISD::UREM: Opc = Alpha::REMQU; break;
850 case ISD::SREM: Opc = Alpha::REMQ; break;
851 case ISD::UDIV: Opc = Alpha::DIVQU; break;
852 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000853 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000854 Tmp1 = SelectExpr(N.getOperand(0));
855 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth02981182005-01-26 01:24:38 +0000856 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000857 return Result;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000858// // case ISD::UINT_TO_FP:
859
860// case ISD::FP_TO_SINT:
861// assert (N.getValueType() == MVT::f64 && "Only can convert for doubles");
862// Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
863// Tmp2 = MakeReg(SrcTy);
864// BuildMI(BB, CVTTQ, 1, Tmp2).addReg(Tmp1);
865// BuildMI(BB, FTOIT, 1, Result).addReg(Tmp2);
866// return result;
867
868// // case ISD::FP_TO_UINT:
869
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000870 case ISD::SELECT:
871 {
872 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
873 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
874 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
875 // Get the condition into the zero flag.
876 unsigned dummy = MakeReg(MVT::i64);
877 BuildMI(BB, Alpha::BIS, 2, dummy).addReg(Tmp3).addReg(Tmp3);
878 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
879 return Result;
880 }
881
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000882 case ISD::Constant:
883 {
884 long val = cast<ConstantSDNode>(N)->getValue();
885 BuildMI(BB, Alpha::LOAD_IMM, 1, Result).addImm(val);
886 return Result;
887 }
888
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000889 case ISD::LOAD:
890 {
891 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000892 if (Result != notIn)
893 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000894 else
895 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
896
897 SDOperand Chain = N.getOperand(0);
898 SDOperand Address = N.getOperand(1);
899
900 if (Address.getOpcode() == ISD::GlobalAddress)
901 {
902 Select(Chain);
903 AlphaLowering.restoreGP(BB);
904 BuildMI(BB, Alpha::LOAD, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
905 }
906 else
907 {
908 Select(Chain);
909 Tmp2 = SelectExpr(Address);
910 BuildMI(BB, Alpha::LDQ, 2, Result).addImm(0).addReg(Tmp2);
911 }
912 return Result;
913 }
914 }
915
916 return 0;
917}
918
919void ISel::Select(SDOperand N) {
920 unsigned Tmp1, Tmp2, Opc;
921
Andrew Lenharth6b9870a2005-01-28 14:06:46 +0000922 // FIXME: Disable for our current expansion model!
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000923 if (/*!N->hasOneUse() &&*/ !ExprMap.insert(std::make_pair(N, notIn)).second)
Andrew Lenharth6b9870a2005-01-28 14:06:46 +0000924 return; // Already selected.
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000925
926 SDNode *Node = N.Val;
927
928 switch (N.getOpcode()) {
929
930 default:
931 Node->dump(); std::cerr << "\n";
932 assert(0 && "Node not handled yet!");
933
934 case ISD::BRCOND: {
935 MachineBasicBlock *Dest =
936 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
937
938 Select(N.getOperand(0));
939 Tmp1 = SelectExpr(N.getOperand(1));
940 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
941 return;
942 }
943
944 case ISD::BR: {
945 MachineBasicBlock *Dest =
946 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
947
948 Select(N.getOperand(0));
949 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
950 return;
951 }
952
953 case ISD::ImplicitDef:
954 Select(N.getOperand(0));
955 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
956 return;
957
958 case ISD::EntryToken: return; // Noop
959
960 case ISD::TokenFactor:
961 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
962 Select(Node->getOperand(i));
963
964 //N.Val->dump(); std::cerr << "\n";
965 //assert(0 && "Node not handled yet!");
966
967 return;
968
969 case ISD::CopyToReg:
970 Select(N.getOperand(0));
971 Tmp1 = SelectExpr(N.getOperand(1));
972 Tmp2 = cast<RegSDNode>(N)->getReg();
973
974 if (Tmp1 != Tmp2) {
975 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
976 }
977 return;
978
979 case ISD::RET:
980 switch (N.getNumOperands()) {
981 default:
982 std::cerr << N.getNumOperands() << "\n";
983 for (unsigned i = 0; i < N.getNumOperands(); ++i)
984 std::cerr << N.getOperand(i).getValueType() << "\n";
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000985 Node->dump();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000986 assert(0 && "Unknown return instruction!");
987 case 2:
988 Select(N.getOperand(0));
989 Tmp1 = SelectExpr(N.getOperand(1));
990 switch (N.getOperand(1).getValueType()) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000991 default: Node->dump(); assert(0 && "All other types should have been promoted!!");
992 case MVT::f64:
993 case MVT::f32:
994 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
995 break;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000996 case MVT::i32:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000997 case MVT::i64:
998 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
999 break;
1000 }
1001 break;
1002 case 1:
1003 Select(N.getOperand(0));
1004 break;
1005 }
1006 //Tmp2 = AlphaLowering.getRetAddr();
1007 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
1008 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
1009 return;
1010
1011 case ISD::STORE:
1012 Select(N.getOperand(0));
1013 Tmp1 = SelectExpr(N.getOperand(1)); //value
1014 if (N.getOperand(2).getOpcode() == ISD::GlobalAddress)
1015 {
1016 AlphaLowering.restoreGP(BB);
1017 BuildMI(BB, Alpha::STORE, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(N.getOperand(2))->getGlobal());
1018 }
1019 else
1020 {
1021 Tmp2 = SelectExpr(N.getOperand(2)); //address
1022 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addImm(0).addReg(Tmp2);
1023 }
1024 return;
1025
1026 case ISD::EXTLOAD:
1027 case ISD::SEXTLOAD:
1028 case ISD::ZEXTLOAD:
1029 case ISD::LOAD:
1030 case ISD::CopyFromReg:
1031 case ISD::CALL:
1032// case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001033 ExprMap.erase(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001034 SelectExpr(N);
1035 return;
1036
1037
1038 case ISD::TRUNCSTORE: { // truncstore chain, val, ptr :storety
1039 MVT::ValueType StoredTy = cast<MVTSDNode>(Node)->getExtraValueType();
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001040 if (StoredTy == MVT::i64) {
1041 Node->dump();
1042 assert(StoredTy != MVT::i64 && "Unsupported TRUNCSTORE for this target!");
1043 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001044
1045 Select(N.getOperand(0));
1046 Tmp1 = SelectExpr(N.getOperand(1));
1047 Tmp2 = SelectExpr(N.getOperand(2));
1048
1049 switch (StoredTy) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001050 default: Node->dump(); assert(0 && "Unhandled Type"); break;
Andrew Lenharthd279b412005-01-25 19:58:40 +00001051 case MVT::i1: //FIXME: DAG does not promote this load
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001052 case MVT::i8: Opc = Alpha::STB; break;
1053 case MVT::i16: Opc = Alpha::STW; break;
1054 case MVT::i32: Opc = Alpha::STL; break;
1055 }
1056
1057 BuildMI(BB, Opc, 2).addReg(Tmp1).addImm(0).addReg(Tmp2);
1058 return;
1059 }
1060
1061 case ISD::ADJCALLSTACKDOWN:
1062 case ISD::ADJCALLSTACKUP:
1063 Select(N.getOperand(0));
1064 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1065
1066 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
1067 Alpha::ADJUSTSTACKUP;
1068 BuildMI(BB, Opc, 1).addImm(Tmp1);
1069 return;
1070 }
1071 assert(0 && "Should not be reached!");
1072}
1073
1074
1075/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
1076/// into a machine code representation using pattern matching and a machine
1077/// description file.
1078///
1079FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
1080 return new ISel(TM);
1081}