blob: 437ab2357ba9d8f457573a4d8aafbc57a85443ab [file] [log] [blame]
Misha Brukman2a8350a2005-02-05 02:24:26 +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>
Andrew Lenharth684f2292005-01-30 00:35:27 +000030#include <algorithm>
Andrew Lenharth304d0f32005-01-22 23:41:55 +000031using namespace llvm;
32
33//===----------------------------------------------------------------------===//
34// AlphaTargetLowering - Alpha Implementation of the TargetLowering interface
35namespace {
36 class AlphaTargetLowering : public TargetLowering {
37 int VarArgsFrameIndex; // FrameIndex for start of varargs area.
38 unsigned GP; //GOT vreg
39 public:
40 AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) {
41 // Set up the TargetLowering object.
Andrew Lenharth3d65d312005-01-27 03:49:45 +000042 //I am having problems with shr n ubyte 1
Andrew Lenharth879ef222005-02-02 17:00:21 +000043 setShiftAmountType(MVT::i64);
44 setSetCCResultType(MVT::i64);
Andrew Lenharth3d65d312005-01-27 03:49:45 +000045
Andrew Lenharth304d0f32005-01-22 23:41:55 +000046 addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass);
47 addRegisterClass(MVT::f64, Alpha::FPRCRegisterClass);
Andrew Lenharth3d65d312005-01-27 03:49:45 +000048 addRegisterClass(MVT::f32, Alpha::FPRCRegisterClass);
Andrew Lenharth304d0f32005-01-22 23:41:55 +000049
Andrew Lenharthd2bb9602005-01-27 07:50:35 +000050 setOperationAction(ISD::EXTLOAD , MVT::i1 , Promote);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000051
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +000052 setOperationAction(ISD::ZEXTLOAD , MVT::i1 , Expand);
Andrew Lenharth304d0f32005-01-22 23:41:55 +000053 setOperationAction(ISD::ZEXTLOAD , MVT::i32 , Expand);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000054
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +000055 setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand);
Andrew Lenharth304d0f32005-01-22 23:41:55 +000056 setOperationAction(ISD::SEXTLOAD , MVT::i8 , Expand);
57 setOperationAction(ISD::SEXTLOAD , MVT::i16 , Expand);
58
Andrew Lenharth3d65d312005-01-27 03:49:45 +000059 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 +000060
Andrew Lenharth9818c052005-02-05 13:19:12 +000061 setOperationAction(ISD::SREM , MVT::f32 , Expand);
62 setOperationAction(ISD::SREM , MVT::f64 , Expand);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +000063
Andrew Lenharth8d163d22005-02-02 05:49:42 +000064 setOperationAction(ISD::MEMMOVE , MVT::Other, Expand);
Andrew Lenharth9818c052005-02-05 13:19:12 +000065 setOperationAction(ISD::MEMSET , MVT::Other, Expand);
66 setOperationAction(ISD::MEMCPY , MVT::Other, Expand);
67
Andrew Lenharth3d65d312005-01-27 03:49:45 +000068 computeRegisterProperties();
Andrew Lenharth304d0f32005-01-22 23:41:55 +000069
Andrew Lenharthd2bb9602005-01-27 07:50:35 +000070 addLegalFPImmediate(+0.0); //F31
Andrew Lenharth12dd2622005-02-03 21:01:15 +000071 addLegalFPImmediate(-0.0); //-F31
Andrew Lenharth304d0f32005-01-22 23:41:55 +000072 }
73
74 /// LowerArguments - This hook must be implemented to indicate how we should
75 /// lower the arguments for the specified function, into the specified DAG.
76 virtual std::vector<SDOperand>
77 LowerArguments(Function &F, SelectionDAG &DAG);
78
79 /// LowerCallTo - This hook lowers an abstract call to a function into an
80 /// actual call.
81 virtual std::pair<SDOperand, SDOperand>
82 LowerCallTo(SDOperand Chain, const Type *RetTy, SDOperand Callee,
83 ArgListTy &Args, SelectionDAG &DAG);
84
85 virtual std::pair<SDOperand, SDOperand>
86 LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
87
88 virtual std::pair<SDOperand,SDOperand>
89 LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
90 const Type *ArgTy, SelectionDAG &DAG);
91
92 virtual std::pair<SDOperand, SDOperand>
93 LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
94 SelectionDAG &DAG);
95
96 void restoreGP(MachineBasicBlock* BB)
97 {
98 BuildMI(BB, Alpha::BIS, 2, Alpha::R29).addReg(GP).addReg(GP);
99 }
100 };
101}
102
103//http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PY8AC-TET1_html/callCH3.html#BLOCK21
104
105//For now, just use variable size stack frame format
106
107//In a standard call, the first six items are passed in registers $16
108//- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
109//of argument-to-register correspondence.) The remaining items are
110//collected in a memory argument list that is a naturally aligned
111//array of quadwords. In a standard call, this list, if present, must
112//be passed at 0(SP).
113//7 ... n 0(SP) ... (n-7)*8(SP)
114
115std::vector<SDOperand>
116AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
117{
118 std::vector<SDOperand> ArgValues;
119
120 // //#define FP $15
121 // //#define RA $26
122 // //#define PV $27
123 // //#define GP $29
124 // //#define SP $30
125
126 // assert(0 && "TODO");
127 MachineFunction &MF = DAG.getMachineFunction();
128 MachineFrameInfo *MFI = MF.getFrameInfo();
129
130 GP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
131 MachineBasicBlock& BB = MF.front();
132
133 //Handle the return address
134 //BuildMI(&BB, Alpha::IDEF, 0, Alpha::R26);
135
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000136 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
137 Alpha::R19, Alpha::R20, Alpha::R21};
138 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
139 Alpha::F19, Alpha::F20, Alpha::F21};
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000140 std::vector<unsigned> argVreg;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000141 std::vector<unsigned> argPreg;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000142 std::vector<unsigned> argOpc;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000143 int count = 0;
144 for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I)
145 {
Andrew Lenharth40831c52005-01-28 06:57:18 +0000146 SDOperand newroot, argt;
Andrew Lenharth684f2292005-01-30 00:35:27 +0000147 if (count < 6) {
148 switch (getValueType(I->getType())) {
149 default: std::cerr << "Unknown Type " << getValueType(I->getType()) << "\n"; abort();
150 case MVT::f64:
151 case MVT::f32:
152 BuildMI(&BB, Alpha::IDEF, 0, args_float[count]);
153 argVreg.push_back(MF.getSSARegMap()->createVirtualRegister(getRegClassFor(getValueType(I->getType()))));
154 argPreg.push_back(args_float[count]);
155 argOpc.push_back(Alpha::CPYS);
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000156 argt = newroot = DAG.getCopyFromReg(argVreg[count], getValueType(I->getType()), DAG.getRoot());
Andrew Lenharth684f2292005-01-30 00:35:27 +0000157 break;
158 case MVT::i1:
159 case MVT::i8:
160 case MVT::i16:
161 case MVT::i32:
162 case MVT::i64:
163 BuildMI(&BB, Alpha::IDEF, 0, args_int[count]);
164 argVreg.push_back(MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64)));
165 argPreg.push_back(args_int[count]);
166 argOpc.push_back(Alpha::BIS);
167 argt = newroot = DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot());
168 if (getValueType(I->getType()) != MVT::i64)
169 argt = DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()), newroot);
170 break;
171 }
172 } else { //more args
173 // Create the frame index object for this incoming parameter...
174 int FI = MFI->CreateFixedObject(8, 8 * (count - 6));
175
176 // Create the SelectionDAG nodes corresponding to a load from this parameter
177 SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
178 argt = newroot = DAG.getLoad(getValueType(I->getType()), DAG.getEntryNode(), FIN);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000179 }
180 DAG.setRoot(newroot.getValue(1));
181 ArgValues.push_back(argt);
Andrew Lenharth684f2292005-01-30 00:35:27 +0000182 ++count;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000183 }
184
185 BuildMI(&BB, Alpha::IDEF, 0, Alpha::R29);
186 BuildMI(&BB, Alpha::BIS, 2, GP).addReg(Alpha::R29).addReg(Alpha::R29);
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000187 for (int i = 0; i < std::min(count,6); ++i)
Andrew Lenharth40831c52005-01-28 06:57:18 +0000188 BuildMI(&BB, argOpc[i], 2, argVreg[i]).addReg(argPreg[i]).addReg(argPreg[i]);
189
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000190 return ArgValues;
191}
192
193std::pair<SDOperand, SDOperand>
194AlphaTargetLowering::LowerCallTo(SDOperand Chain,
195 const Type *RetTy, SDOperand Callee,
196 ArgListTy &Args, SelectionDAG &DAG) {
197 int NumBytes = 0;
Andrew Lenharth684f2292005-01-30 00:35:27 +0000198 if (Args.size() > 6)
199 NumBytes = (Args.size() - 6) * 8;
200
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000201 Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
202 DAG.getConstant(NumBytes, getPointerTy()));
203 std::vector<SDOperand> args_to_use;
204 for (unsigned i = 0, e = Args.size(); i != e; ++i)
205 {
206 switch (getValueType(Args[i].second)) {
207 default: assert(0 && "Unexpected ValueType for argument!");
208 case MVT::i1:
209 case MVT::i8:
210 case MVT::i16:
211 case MVT::i32:
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000212 // Promote the integer to 64 bits. If the input type is signed use a
213 // sign extend, otherwise use a zero extend.
214 if (Args[i].second->isSigned())
Andrew Lenharth40831c52005-01-28 06:57:18 +0000215 Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000216 else
Andrew Lenharth40831c52005-01-28 06:57:18 +0000217 Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000218 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000219 case MVT::i64:
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000220 case MVT::f64:
221 case MVT::f32:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000222 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000223 }
224 args_to_use.push_back(Args[i].first);
225 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000226
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000227 std::vector<MVT::ValueType> RetVals;
228 MVT::ValueType RetTyVT = getValueType(RetTy);
229 if (RetTyVT != MVT::isVoid)
230 RetVals.push_back(RetTyVT);
231 RetVals.push_back(MVT::Other);
232
233 SDOperand TheCall = SDOperand(DAG.getCall(RetVals, Chain, Callee, args_to_use), 0);
234 Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
235 Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
236 DAG.getConstant(NumBytes, getPointerTy()));
237 return std::make_pair(TheCall, Chain);
238}
239
240std::pair<SDOperand, SDOperand>
241AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
242 //vastart just returns the address of the VarArgsFrameIndex slot.
243 return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain);
244}
245
246std::pair<SDOperand,SDOperand> AlphaTargetLowering::
247LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
248 const Type *ArgTy, SelectionDAG &DAG) {
249 abort();
250}
251
252
253std::pair<SDOperand, SDOperand> AlphaTargetLowering::
254LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
255 SelectionDAG &DAG) {
256 abort();
257}
258
259
260
261
262
263namespace {
264
265 //===--------------------------------------------------------------------===//
266 /// ISel - Alpha specific code to select Alpha machine instructions for
267 /// SelectionDAG operations.
268 ///
269 class ISel : public SelectionDAGISel {
270
271 /// AlphaLowering - This object fully describes how to lower LLVM code to an
272 /// Alpha-specific SelectionDAG.
273 AlphaTargetLowering AlphaLowering;
274
275
276 /// ExprMap - As shared expressions are codegen'd, we keep track of which
277 /// vreg the value is produced in, so we only emit one copy of each compiled
278 /// tree.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000279 static const unsigned notIn = (unsigned)(-1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000280 std::map<SDOperand, unsigned> ExprMap;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000281
282 public:
283 ISel(TargetMachine &TM) : SelectionDAGISel(AlphaLowering), AlphaLowering(TM) {
284 }
285
286 /// InstructionSelectBasicBlock - This callback is invoked by
287 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
288 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
289 // Codegen the basic block.
290 Select(DAG.getRoot());
291
292 // Clear state used for selection.
293 ExprMap.clear();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000294 }
295
296 unsigned SelectExpr(SDOperand N);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000297 unsigned SelectExprFP(SDOperand N, unsigned Result);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000298 void Select(SDOperand N);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000299
300 void SelectAddr(SDOperand N, unsigned& Reg, long& offset);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000301 };
302}
303
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000304//Check to see if the load is a constant offset from a base register
305void ISel::SelectAddr(SDOperand N, unsigned& Reg, long& offset)
306{
307 unsigned opcode = N.getOpcode();
308 if (opcode == ISD::ADD) {
309 if(N.getOperand(1).getOpcode() == ISD::Constant && cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767)
310 { //Normal imm add
311 Reg = SelectExpr(N.getOperand(0));
312 offset = cast<ConstantSDNode>(N.getOperand(1))->getValue();
313 return;
314 }
315 else if(N.getOperand(0).getOpcode() == ISD::Constant && cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 32767)
316 {
317 Reg = SelectExpr(N.getOperand(1));
318 offset = cast<ConstantSDNode>(N.getOperand(0))->getValue();
319 return;
320 }
321 }
322 Reg = SelectExpr(N);
323 offset = 0;
324 return;
325}
326
Andrew Lenharth40831c52005-01-28 06:57:18 +0000327unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
328{
329 unsigned Tmp1, Tmp2, Tmp3;
330 unsigned Opc = 0;
331 SDNode *Node = N.Val;
332 MVT::ValueType DestType = N.getValueType();
333 unsigned opcode = N.getOpcode();
334
335 switch (opcode) {
336 default:
337 Node->dump();
338 assert(0 && "Node not handled!\n");
Andrew Lenharth2c594352005-01-29 15:42:07 +0000339
Andrew Lenharth9818c052005-02-05 13:19:12 +0000340 case ISD::SELECT:
341 {
342 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
343 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
344 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000345
346
347 // Spill the cond to memory and reload it from there.
348 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
349 MachineFunction *F = BB->getParent();
350 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
351 unsigned Tmp4 = MakeReg(MVT::f64);
352 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdx).addReg(Alpha::F31);
353 BuildMI(BB, Alpha::LDT, 2, Tmp4).addFrameIndex(FrameIdx).addReg(Alpha::F31);
354 //now ideally, we don't have to do anything to the flag...
Andrew Lenharth9818c052005-02-05 13:19:12 +0000355 // Get the condition into the zero flag.
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000356 BuildMI(BB, Alpha::FCMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp4);
Andrew Lenharth9818c052005-02-05 13:19:12 +0000357 return Result;
358 }
359
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000360 case ISD::FP_ROUND:
361 assert (DestType == MVT::f32 && N.getOperand(0).getValueType() == MVT::f64 && "only f64 to f32 conversion supported here");
362 Tmp1 = SelectExpr(N.getOperand(0));
363 BuildMI(BB, Alpha::CVTTS, 1, Result).addReg(Tmp1);
364 return Result;
365
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000366 case ISD::FP_EXTEND:
367 assert (DestType == MVT::f64 && N.getOperand(0).getValueType() == MVT::f32 && "only f32 to f64 conversion supported here");
368 Tmp1 = SelectExpr(N.getOperand(0));
369 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
370 return Result;
371
Andrew Lenharth2c594352005-01-29 15:42:07 +0000372 case ISD::CopyFromReg:
373 {
374 // Make sure we generate both values.
375 if (Result != notIn)
376 ExprMap[N.getValue(1)] = notIn; // Generate the token
377 else
378 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
379
380 SDOperand Chain = N.getOperand(0);
381
382 Select(Chain);
383 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
384 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
385 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(r).addReg(r);
386 return Result;
387 }
388
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000389 case ISD::LOAD:
390 {
391 // Make sure we generate both values.
392 if (Result != notIn)
393 ExprMap[N.getValue(1)] = notIn; // Generate the token
394 else
395 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000396
397 //DestType = N.getValue(0).getValueType();
398
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000399 SDOperand Chain = N.getOperand(0);
400 SDOperand Address = N.getOperand(1);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000401 Select(Chain);
402
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000403 if (Address.getOpcode() == ISD::GlobalAddress)
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000404 {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000405 AlphaLowering.restoreGP(BB);
406 Opc = DestType == MVT::f64 ? Alpha::LDT_SYM : Alpha::LDS_SYM;
407 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
408 }
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000409 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000410 AlphaLowering.restoreGP(BB);
Andrew Lenharth97127a12005-02-05 17:41:39 +0000411 Opc = DestType == MVT::f64 ? Alpha::LDT_SYM : Alpha::LDS_SYM;
412 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000413 }
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000414 else
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000415 {
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000416 long offset;
417 SelectAddr(Address, Tmp1, offset);
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000418 Opc = DestType == MVT::f64 ? Alpha::LDT : Alpha::LDS;
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000419 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000420 }
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000421 return Result;
422 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000423 case ISD::ConstantFP:
424 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
425 if (CN->isExactlyValue(+0.0)) {
426 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000427 } else if ( CN->isExactlyValue(-0.0)) {
428 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000429 } else {
430 abort();
431 }
432 }
433 return Result;
434
435 case ISD::MUL:
436 case ISD::ADD:
437 case ISD::SUB:
438 case ISD::SDIV:
439 switch( opcode ) {
440 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
441 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
442 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
443 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
444 };
445 Tmp1 = SelectExpr(N.getOperand(0));
446 Tmp2 = SelectExpr(N.getOperand(1));
447 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
448 return Result;
449
Andrew Lenharth2c594352005-01-29 15:42:07 +0000450 case ISD::EXTLOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000451 {
452 //include a conversion sequence for float loads to double
453 if (Result != notIn)
454 ExprMap[N.getValue(1)] = notIn; // Generate the token
455 else
456 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
457
458 Tmp2 = MakeReg(MVT::f32);
459
460 assert(cast<MVTSDNode>(Node)->getExtraValueType() == MVT::f32 && "EXTLOAD not from f32");
461 assert(Node->getValueType(0) == MVT::f64 && "EXTLOAD not to f64");
462
463 SDOperand Chain = N.getOperand(0);
464 SDOperand Address = N.getOperand(1);
465 Select(Chain);
466
467 if (Address.getOpcode() == ISD::GlobalAddress)
468 {
469 AlphaLowering.restoreGP(BB);
470 BuildMI(BB, Alpha::LDS_SYM, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
471 }
472 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N.getOperand(1)))
473 {
474 AlphaLowering.restoreGP(BB);
475 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp2).addConstantPoolIndex(CP->getIndex());
476 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp2);
477 }
478 else
479 {
480 long offset;
481 SelectAddr(Address, Tmp1, offset);
482 BuildMI(BB, Alpha::LDS, 1, Tmp2).addImm(offset).addReg(Tmp1);
483 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp2);
484 }
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000485 return Result;
486 }
Andrew Lenharth2c594352005-01-29 15:42:07 +0000487
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000488 case ISD::UINT_TO_FP:
489 case ISD::SINT_TO_FP:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000490 {
491 assert (N.getOperand(0).getValueType() == MVT::i64 && "only quads can be loaded from");
492 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000493 Tmp2 = MakeReg(MVT::f64);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000494
495 //The hard way:
496 // Spill the integer to memory and reload it from there.
497 unsigned Size = MVT::getSizeInBits(MVT::i64)/8;
498 MachineFunction *F = BB->getParent();
499 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, Size);
500
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000501 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdx).addReg(Alpha::F31);
502 BuildMI(BB, Alpha::LDT, 2, Tmp2).addFrameIndex(FrameIdx).addReg(Alpha::F31);
503 Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
504 BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000505
506 //The easy way: doesn't work
507// //so these instructions are not supported on ev56
508// Opc = DestType == MVT::f64 ? Alpha::ITOFT : Alpha::ITOFS;
509// BuildMI(BB, Opc, 1, Tmp2).addReg(Tmp1);
510// Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
511// BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
512
Andrew Lenharth40831c52005-01-28 06:57:18 +0000513 return Result;
514 }
515 }
516 assert(0 && "should not get here");
517 return 0;
518}
519
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000520unsigned ISel::SelectExpr(SDOperand N) {
521 unsigned Result;
522 unsigned Tmp1, Tmp2, Tmp3;
523 unsigned Opc = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000524 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000525
526 SDNode *Node = N.Val;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000527 MVT::ValueType DestType = N.getValueType();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000528
529 unsigned &Reg = ExprMap[N];
530 if (Reg) return Reg;
531
532 if (N.getOpcode() != ISD::CALL)
533 Reg = Result = (N.getValueType() != MVT::Other) ?
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000534 MakeReg(N.getValueType()) : notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000535 else {
536 // If this is a call instruction, make sure to prepare ALL of the result
537 // values as well as the chain.
538 if (Node->getNumValues() == 1)
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000539 Reg = Result = notIn; // Void call, just a chain.
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000540 else {
541 Result = MakeReg(Node->getValueType(0));
542 ExprMap[N.getValue(0)] = Result;
543 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
544 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000545 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000546 }
547 }
548
Andrew Lenharth22088bb2005-02-02 15:05:33 +0000549 if (DestType == MVT::f64 || DestType == MVT::f32 ||
550 (opcode == ISD::LOAD &&
551 (N.getValue(0).getValueType() == MVT::f32 || N.getValue(0).getValueType() == MVT::f64)))
Andrew Lenharth40831c52005-01-28 06:57:18 +0000552 return SelectExprFP(N, Result);
553
554 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000555 default:
556 Node->dump();
557 assert(0 && "Node not handled!\n");
558
Andrew Lenharth2c594352005-01-29 15:42:07 +0000559 case ISD::ConstantPool:
560 Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
561 AlphaLowering.restoreGP(BB);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000562 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(Tmp1);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000563 return Result;
564
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000565 case ISD::FrameIndex:
566 Tmp1 = cast<FrameIndexSDNode>(N)->getIndex();
Andrew Lenharth684f2292005-01-30 00:35:27 +0000567 BuildMI(BB, Alpha::LDA, 2, Result).addFrameIndex(Tmp1).addReg(Alpha::F31);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000568 return Result;
569
570 case ISD::EXTLOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000571 {
572 // Make sure we generate both values.
573 if (Result != notIn)
574 ExprMap[N.getValue(1)] = notIn; // Generate the token
575 else
576 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
577
578 SDOperand Chain = N.getOperand(0);
579 SDOperand Address = N.getOperand(1);
580 Select(Chain);
581
582 switch(Node->getValueType(0)) {
583 default: Node->dump(); assert(0 && "Unknown type to sign extend to.");
Andrew Lenharthd279b412005-01-25 19:58:40 +0000584 case MVT::i64:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000585 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
586 default:
587 Node->dump();
588 assert(0 && "Bad extend load!");
589 case MVT::i64: Opc = Alpha::LDQ; break;
590 case MVT::i32: Opc = Alpha::LDL; break;
591 case MVT::i16: Opc = Alpha::LDWU; break;
592 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
593 case MVT::i8: Opc = Alpha::LDBU; break;
594 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000595 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000596
597 if (Address.getOpcode() == ISD::GlobalAddress)
598 {
599 AlphaLowering.restoreGP(BB);
600 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
601 }
602 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address))
603 {
604 AlphaLowering.restoreGP(BB);
605 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
606 }
607 else
608 {
609 long offset;
610 SelectAddr(Address, Tmp1, offset);
611 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
612 }
613 return Result;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000614 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000615
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000616 case ISD::SEXTLOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000617 {
618 // Make sure we generate both values.
619 if (Result != notIn)
620 ExprMap[N.getValue(1)] = notIn; // Generate the token
621 else
622 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000623
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000624 SDOperand Chain = N.getOperand(0);
625 SDOperand Address = N.getOperand(1);
626 Select(Chain);
627
628 switch(Node->getValueType(0)) {
629 default: Node->dump(); assert(0 && "Unknown type to sign extend to.");
630 case MVT::i64:
631 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
632 default: Node->dump(); assert(0 && "Bad sign extend!");
633 case MVT::i32: Opc = Alpha::LDL; break;
634 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000635 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000636
637 if (Address.getOpcode() == ISD::GlobalAddress)
638 {
639 AlphaLowering.restoreGP(BB);
640 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
641 }
642 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
643 AlphaLowering.restoreGP(BB);
644 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
645 }
646 else
647 {
648 long offset;
649 SelectAddr(Address, Tmp1, offset);
650 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
651 }
652 return Result;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000653 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000654
655 case ISD::ZEXTLOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000656 {
657 // Make sure we generate both values.
658 if (Result != notIn)
659 ExprMap[N.getValue(1)] = notIn; // Generate the token
660 else
661 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
662
663 SDOperand Chain = N.getOperand(0);
664 SDOperand Address = N.getOperand(1);
665 Select(Chain);
666
667 switch(Node->getValueType(0)) {
668 default: Node->dump(); assert(0 && "Unknown type to zero extend to.");
669 case MVT::i64:
670 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
671 default: Node->dump(); assert(0 && "Bad sign extend!");
672 case MVT::i16: Opc = Alpha::LDWU; break;
673 case MVT::i8: Opc = Alpha::LDBU; break;
674 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000675 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000676
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000677 if (Address.getOpcode() == ISD::GlobalAddress)
678 {
679 AlphaLowering.restoreGP(BB);
680 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
681 }
682 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
683 AlphaLowering.restoreGP(BB);
684 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
685 }
686 else
687 {
688 long offset;
689 SelectAddr(Address, Tmp1, offset);
690 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
691 }
692 return Result;
693 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000694
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000695 case ISD::GlobalAddress:
696 AlphaLowering.restoreGP(BB);
697 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
698 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
699 return Result;
700
701 case ISD::CALL:
702 {
703 Select(N.getOperand(0));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000704
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000705 // The chain for this call is now lowered.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000706 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), notIn));
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000707
708 //grab the arguments
709 std::vector<unsigned> argvregs;
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000710 //assert(Node->getNumOperands() < 8 && "Only 6 args supported");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000711 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000712 argvregs.push_back(SelectExpr(N.getOperand(i)));
713
Andrew Lenharth684f2292005-01-30 00:35:27 +0000714 //in reg args
715 for(int i = 0, e = std::min(6, (int)argvregs.size()); i < e; ++i)
716 {
717 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
718 Alpha::R19, Alpha::R20, Alpha::R21};
719 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
720 Alpha::F19, Alpha::F20, Alpha::F21};
721 switch(N.getOperand(i+2).getValueType()) {
722 default:
723 Node->dump();
724 N.getOperand(i).Val->dump();
725 std::cerr << "Type for " << i << " is: " << N.getOperand(i+2).getValueType() << "\n";
726 assert(0 && "Unknown value type for call");
727 case MVT::i1:
728 case MVT::i8:
729 case MVT::i16:
730 case MVT::i32:
731 case MVT::i64:
732 BuildMI(BB, Alpha::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
733 break;
734 case MVT::f32:
735 case MVT::f64:
736 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
737 break;
738 }
739 }
740 //in mem args
741 for (int i = 6, e = argvregs.size(); i < e; ++i)
742 {
743 switch(N.getOperand(i+2).getValueType()) {
744 default:
745 Node->dump();
746 N.getOperand(i).Val->dump();
747 std::cerr << "Type for " << i << " is: " << N.getOperand(i+2).getValueType() << "\n";
748 assert(0 && "Unknown value type for call");
749 case MVT::i1:
750 case MVT::i8:
751 case MVT::i16:
752 case MVT::i32:
753 case MVT::i64:
754 BuildMI(BB, Alpha::STQ, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
755 break;
756 case MVT::f32:
757 BuildMI(BB, Alpha::STS, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
758 break;
759 case MVT::f64:
760 BuildMI(BB, Alpha::STT, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
761 break;
762 }
763 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000764 //build the right kind of call
765 if (GlobalAddressSDNode *GASD =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000766 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
767 {
768 AlphaLowering.restoreGP(BB);
769 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
770 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000771 else if (ExternalSymbolSDNode *ESSDN =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000772 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
773 {
774 AlphaLowering.restoreGP(BB);
775 BuildMI(BB, Alpha::CALL, 0).addExternalSymbol(ESSDN->getSymbol(), true);
776 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000777 else
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000778 {
779 //no need to restore GP as we are doing an indirect call
780 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000781 BuildMI(BB, Alpha::BIS, 2, Alpha::R27).addReg(Tmp1).addReg(Tmp1);
782 BuildMI(BB, Alpha::JSR, 2, Alpha::R26).addReg(Alpha::R27).addImm(0);
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000783 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000784
785 //push the result into a virtual register
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000786
787 switch (Node->getValueType(0)) {
788 default: Node->dump(); assert(0 && "Unknown value type for call result!");
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000789 case MVT::Other: return notIn;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000790 case MVT::i1:
791 case MVT::i8:
792 case MVT::i16:
793 case MVT::i32:
794 case MVT::i64:
795 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
796 break;
797 case MVT::f32:
798 case MVT::f64:
799 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
800 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000801 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000802 return Result+N.ResNo;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000803 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000804
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000805 case ISD::SIGN_EXTEND:
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000806 abort();
807
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000808 case ISD::SIGN_EXTEND_INREG:
809 {
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000810 //Alpha has instructions for a bunch of signed 32 bit stuff
811 if( dyn_cast<MVTSDNode>(Node)->getExtraValueType() == MVT::i32)
812 {
813 switch (N.getOperand(0).getOpcode()) {
814 case ISD::ADD:
815 case ISD::SUB:
816 case ISD::MUL:
817 {
818 bool isAdd = N.getOperand(0).getOpcode() == ISD::ADD;
819 bool isMul = N.getOperand(0).getOpcode() == ISD::MUL;
820 //FIXME: first check for Scaled Adds and Subs!
821 if(N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
822 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() <= 255)
823 { //Normal imm add/sub
824 Opc = isAdd ? Alpha::ADDLi : (isMul ? Alpha::MULLi : Alpha::SUBLi);
825 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
826 Tmp2 = cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue();
827 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
828 }
829 else
830 { //Normal add/sub
831 Opc = isAdd ? Alpha::ADDL : (isMul ? Alpha::MULLi : Alpha::SUBL);
832 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
833 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
834 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
835 }
836 return Result;
837 }
838 default: break; //Fall Though;
839 }
840 } //Every thing else fall though too, including unhandled opcodes above
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000841 Tmp1 = SelectExpr(N.getOperand(0));
842 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000843 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000844 switch(MVN->getExtraValueType())
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000845 {
846 default:
847 Node->dump();
848 assert(0 && "Sign Extend InReg not there yet");
849 break;
850 case MVT::i32:
851 {
852 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
853 break;
854 }
855 case MVT::i16:
856 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
857 break;
858 case MVT::i8:
859 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
860 break;
861 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000862 return Result;
863 }
864 case ISD::ZERO_EXTEND_INREG:
865 {
866 Tmp1 = SelectExpr(N.getOperand(0));
867 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000868 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000869 switch(MVN->getExtraValueType())
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000870 {
871 default:
872 Node->dump();
873 assert(0 && "Zero Extend InReg not there yet");
874 break;
875 case MVT::i32: Tmp2 = 0xf0; break;
876 case MVT::i16: Tmp2 = 0xfc; break;
877 case MVT::i8: Tmp2 = 0xfe; break;
878 case MVT::i1: //handle this one special
879 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
880 return Result;
881 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000882 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000883 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000884 }
885
886 case ISD::SETCC:
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000887 {
888 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
889 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
890 bool isConst1 = false;
891 bool isConst2 = false;
892 int dir;
Andrew Lenharth9818c052005-02-05 13:19:12 +0000893
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000894 //Tmp1 = SelectExpr(N.getOperand(0));
895 if(N.getOperand(0).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000896 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
897 isConst1 = true;
898 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000899 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
900 isConst2 = true;
901
902 switch (SetCC->getCondition()) {
903 default: Node->dump(); assert(0 && "Unknown integer comparison!");
904 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
905 case ISD::SETLT: Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
906 case ISD::SETLE: Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
907 case ISD::SETGT: Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
908 case ISD::SETGE: Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
909 case ISD::SETULT: Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
910 case ISD::SETUGT: Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
911 case ISD::SETULE: Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
912 case ISD::SETUGE: Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000913 case ISD::SETNE: {//Handle this one special
914 //std::cerr << "Alpha does not have a setne.\n";
915 //abort();
916 Tmp1 = SelectExpr(N.getOperand(0));
917 Tmp2 = SelectExpr(N.getOperand(1));
918 Tmp3 = MakeReg(MVT::i64);
919 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
920 //and invert
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000921 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +0000922 return Result;
923 }
924 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000925 if (dir == 1) {
926 Tmp1 = SelectExpr(N.getOperand(0));
927 if (isConst2) {
928 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
929 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
930 } else {
931 Tmp2 = SelectExpr(N.getOperand(1));
932 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
933 }
934 } else if (dir == 2) {
935 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth6b9870a2005-01-28 14:06:46 +0000936 if (isConst1) {
Andrew Lenharth3d65d312005-01-27 03:49:45 +0000937 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
938 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
939 } else {
940 Tmp2 = SelectExpr(N.getOperand(0));
941 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
942 }
943 } else { //dir == 0
944 if (isConst1) {
945 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
946 Tmp2 = SelectExpr(N.getOperand(1));
947 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
948 } else if (isConst2) {
949 Tmp1 = SelectExpr(N.getOperand(0));
950 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
951 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
952 } else {
953 Tmp1 = SelectExpr(N.getOperand(0));
954 Tmp2 = SelectExpr(N.getOperand(1));
955 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
956 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000957 }
958 } else {
959 //assert(SetCC->getOperand(0).getValueType() != MVT::f32 && "SetCC f32 should have been promoted");
960 bool rev = false;
961 bool inv = false;
962
963 switch (SetCC->getCondition()) {
964 default: Node->dump(); assert(0 && "Unknown FP comparison!");
965 case ISD::SETEQ: Opc = Alpha::CMPTEQ; break;
966 case ISD::SETLT: Opc = Alpha::CMPTLT; break;
967 case ISD::SETLE: Opc = Alpha::CMPTLE; break;
968 case ISD::SETGT: Opc = Alpha::CMPTLT; rev = true; break;
969 case ISD::SETGE: Opc = Alpha::CMPTLE; rev = true; break;
970 case ISD::SETNE: Opc = Alpha::CMPTEQ; inv = true; break;
971 }
972
973 Tmp1 = SelectExpr(N.getOperand(0));
974 Tmp2 = SelectExpr(N.getOperand(1));
975 //Can only compare doubles, and dag won't promote for me
976 if (SetCC->getOperand(0).getValueType() == MVT::f32)
977 {
978 Tmp3 = MakeReg(MVT::f64);
979 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp1);
980 Tmp1 = Tmp3;
981 }
982 if (SetCC->getOperand(1).getValueType() == MVT::f32)
983 {
984 Tmp3 = MakeReg(MVT::f64);
985 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp2);
986 Tmp1 = Tmp2;
987 }
Andrew Lenharth9818c052005-02-05 13:19:12 +0000988
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000989 if (rev) std::swap(Tmp1, Tmp2);
990 Tmp3 = MakeReg(MVT::f64);
991 //do the comparison
992 BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
993
994 //now arrange for Result (int) to have a 1 or 0
995
996 // Spill the FP to memory and reload it from there.
997 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
998 MachineFunction *F = BB->getParent();
999 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
1000 unsigned Tmp4 = MakeReg(MVT::f64);
1001 BuildMI(BB, Alpha::CVTTQ, 1, Tmp4).addReg(Tmp3);
1002 BuildMI(BB, Alpha::STT, 3).addReg(Tmp4).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1003 unsigned Tmp5 = MakeReg(MVT::i64);
1004 BuildMI(BB, Alpha::LDQ, 2, Tmp5).addFrameIndex(FrameIdx).addReg(Alpha::F31);
Andrew Lenharth9818c052005-02-05 13:19:12 +00001005
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001006 //now, set result based on Tmp5
1007 //Set Tmp6 if fp cmp was false
1008 unsigned Tmp6 = MakeReg(MVT::i64);
1009 BuildMI(BB, Alpha::CMPEQ, 2, Tmp6).addReg(Tmp5).addReg(Alpha::R31);
1010 //and invert
1011 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp6).addReg(Alpha::R31);
1012
1013 }
1014 // else
1015 // {
1016 // Node->dump();
1017 // assert(0 && "Not a setcc in setcc");
1018 // }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001019 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001020 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001021 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001022
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001023 case ISD::CopyFromReg:
1024 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001025 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001026 if (Result != notIn)
1027 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth40831c52005-01-28 06:57:18 +00001028 else
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001029 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth40831c52005-01-28 06:57:18 +00001030
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001031 SDOperand Chain = N.getOperand(0);
1032
1033 Select(Chain);
1034 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
1035 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
1036 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
1037 return Result;
1038 }
1039
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001040 //Most of the plain arithmetic and logic share the same form, and the same
1041 //constant immediate test
1042 case ISD::AND:
1043 case ISD::OR:
1044 case ISD::XOR:
1045 case ISD::SHL:
1046 case ISD::SRL:
Andrew Lenharth2c594352005-01-29 15:42:07 +00001047 case ISD::SRA:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001048 case ISD::MUL:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001049 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
1050 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001051 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1052 {
1053 switch(opcode) {
1054 case ISD::AND: Opc = Alpha::ANDi; break;
1055 case ISD::OR: Opc = Alpha::BISi; break;
1056 case ISD::XOR: Opc = Alpha::XORi; break;
1057 case ISD::SHL: Opc = Alpha::SLi; break;
1058 case ISD::SRL: Opc = Alpha::SRLi; break;
1059 case ISD::SRA: Opc = Alpha::SRAi; break;
1060 case ISD::MUL: Opc = Alpha::MULQi; break;
1061 };
1062 Tmp1 = SelectExpr(N.getOperand(0));
1063 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1064 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1065 }
1066 else
1067 {
1068 switch(opcode) {
1069 case ISD::AND: Opc = Alpha::AND; break;
1070 case ISD::OR: Opc = Alpha::BIS; break;
1071 case ISD::XOR: Opc = Alpha::XOR; break;
1072 case ISD::SHL: Opc = Alpha::SL; break;
1073 case ISD::SRL: Opc = Alpha::SRL; break;
1074 case ISD::SRA: Opc = Alpha::SRA; break;
1075 case ISD::MUL: Opc = Alpha::MULQ; break;
1076 };
1077 Tmp1 = SelectExpr(N.getOperand(0));
1078 Tmp2 = SelectExpr(N.getOperand(1));
1079 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1080 }
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001081 return Result;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001082
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001083 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001084 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001085 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001086 bool isAdd = opcode == ISD::ADD;
1087
1088 //FIXME: first check for Scaled Adds and Subs!
1089 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001090 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1091 { //Normal imm add/sub
1092 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
1093 Tmp1 = SelectExpr(N.getOperand(0));
1094 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1095 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1096 }
1097 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001098 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767)
1099 { //LDA //FIXME: expand the above condition a bit
1100 Tmp1 = SelectExpr(N.getOperand(0));
1101 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1102 if (!isAdd)
1103 Tmp2 = -Tmp2;
1104 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
1105 }
1106 else
1107 { //Normal add/sub
1108 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
1109 Tmp1 = SelectExpr(N.getOperand(0));
1110 Tmp2 = SelectExpr(N.getOperand(1));
1111 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1112 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001113 return Result;
1114 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001115
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001116 case ISD::UREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001117 case ISD::SREM:
1118 case ISD::SDIV:
1119 case ISD::UDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001120 //FIXME: alpha really doesn't support any of these operations,
1121 // the ops are expanded into special library calls with
1122 // special calling conventions
1123 switch(opcode) {
1124 case ISD::UREM: Opc = Alpha::REMQU; break;
1125 case ISD::SREM: Opc = Alpha::REMQ; break;
1126 case ISD::UDIV: Opc = Alpha::DIVQU; break;
1127 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001128 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001129 Tmp1 = SelectExpr(N.getOperand(0));
1130 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth02981182005-01-26 01:24:38 +00001131 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001132 return Result;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001133
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001134 case ISD::FP_TO_UINT:
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001135 case ISD::FP_TO_SINT:
1136 {
1137 assert (DestType == MVT::i64 && "only quads can be loaded to");
1138 MVT::ValueType SrcType = N.getOperand(0).getValueType();
1139 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
1140
1141 //The hard way:
1142 // Spill the integer to memory and reload it from there.
1143 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1144 MachineFunction *F = BB->getParent();
1145 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
1146
1147 //CVTTQ STT LDQ
1148 //CVTST CVTTQ STT LDQ
1149 if (SrcType == MVT::f32)
1150 {
1151 Tmp2 = MakeReg(MVT::f64);
1152 BuildMI(BB, Alpha::CVTST, 1, Tmp2).addReg(Tmp1);
1153 Tmp1 = Tmp2;
1154 }
1155 Tmp2 = MakeReg(MVT::f64);
1156 BuildMI(BB, Alpha::CVTTQ, 1, Tmp2).addReg(Tmp1);
1157 BuildMI(BB, Alpha::STT, 3).addReg(Tmp2).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1158 BuildMI(BB, Alpha::LDQ, 2, Result).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1159
1160 return Result;
1161 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001162
1163// // case ISD::FP_TO_UINT:
1164
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001165 case ISD::SELECT:
1166 {
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001167 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001168 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1169 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001170 // Get the condition into the zero flag.
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001171 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001172 return Result;
1173 }
1174
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001175 case ISD::Constant:
1176 {
Andrew Lenharth22d5a412005-02-02 00:51:15 +00001177 unsigned long val = cast<ConstantSDNode>(N)->getValue();
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001178 if (val < 32000 && (long)val > -32000)
1179 BuildMI(BB, Alpha::LOAD_IMM, 1, Result).addImm(val);
1180 else
1181 {
1182 MachineConstantPool *CP = BB->getParent()->getConstantPool();
1183 ConstantUInt *C = ConstantUInt::get(Type::getPrimitiveType(Type::ULongTyID) , val);
1184 unsigned CPI = CP->getConstantPoolIndex(C);
1185 AlphaLowering.restoreGP(BB);
1186 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(CPI);
1187 }
1188 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001189 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001190
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001191 case ISD::LOAD:
1192 {
1193 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001194 if (Result != notIn)
1195 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001196 else
1197 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
1198
1199 SDOperand Chain = N.getOperand(0);
1200 SDOperand Address = N.getOperand(1);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001201 Select(Chain);
1202
Andrew Lenharthc23d6962005-02-02 04:35:44 +00001203 assert(N.getValue(0).getValueType() == MVT::i64 && "unknown Load dest type");
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001204
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001205 if (Address.getOpcode() == ISD::GlobalAddress)
Andrew Lenharth2afc8212005-02-02 03:36:35 +00001206 {
Andrew Lenharth2afc8212005-02-02 03:36:35 +00001207 AlphaLowering.restoreGP(BB);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001208 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
Andrew Lenharth2afc8212005-02-02 03:36:35 +00001209 }
1210 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
1211 AlphaLowering.restoreGP(BB);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001212 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharth2afc8212005-02-02 03:36:35 +00001213 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001214 else
Andrew Lenharth2afc8212005-02-02 03:36:35 +00001215 {
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001216 long offset;
1217 SelectAddr(Address, Tmp1, offset);
1218 BuildMI(BB, Alpha::LDQ, 2, Result).addImm(offset).addReg(Tmp1);
Andrew Lenharth2afc8212005-02-02 03:36:35 +00001219 }
1220 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001221 }
1222 }
1223
1224 return 0;
1225}
1226
1227void ISel::Select(SDOperand N) {
1228 unsigned Tmp1, Tmp2, Opc;
1229
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001230 // FIXME: Disable for our current expansion model!
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001231 if (/*!N->hasOneUse() &&*/ !ExprMap.insert(std::make_pair(N, notIn)).second)
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001232 return; // Already selected.
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001233
1234 SDNode *Node = N.Val;
1235
1236 switch (N.getOpcode()) {
1237
1238 default:
1239 Node->dump(); std::cerr << "\n";
1240 assert(0 && "Node not handled yet!");
1241
1242 case ISD::BRCOND: {
1243 MachineBasicBlock *Dest =
1244 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
1245
Andrew Lenharth9818c052005-02-05 13:19:12 +00001246 Select(N.getOperand(0)); //chain
1247
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001248 Tmp1 = SelectExpr(N.getOperand(1));
1249 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
1250 return;
1251 }
1252
1253 case ISD::BR: {
1254 MachineBasicBlock *Dest =
1255 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
1256
1257 Select(N.getOperand(0));
1258 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
1259 return;
1260 }
1261
1262 case ISD::ImplicitDef:
1263 Select(N.getOperand(0));
1264 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
1265 return;
1266
1267 case ISD::EntryToken: return; // Noop
1268
1269 case ISD::TokenFactor:
1270 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
1271 Select(Node->getOperand(i));
1272
1273 //N.Val->dump(); std::cerr << "\n";
1274 //assert(0 && "Node not handled yet!");
1275
1276 return;
1277
1278 case ISD::CopyToReg:
1279 Select(N.getOperand(0));
1280 Tmp1 = SelectExpr(N.getOperand(1));
1281 Tmp2 = cast<RegSDNode>(N)->getReg();
1282
1283 if (Tmp1 != Tmp2) {
1284 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
1285 }
1286 return;
1287
1288 case ISD::RET:
1289 switch (N.getNumOperands()) {
1290 default:
1291 std::cerr << N.getNumOperands() << "\n";
1292 for (unsigned i = 0; i < N.getNumOperands(); ++i)
1293 std::cerr << N.getOperand(i).getValueType() << "\n";
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001294 Node->dump();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001295 assert(0 && "Unknown return instruction!");
1296 case 2:
1297 Select(N.getOperand(0));
1298 Tmp1 = SelectExpr(N.getOperand(1));
1299 switch (N.getOperand(1).getValueType()) {
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001300 default: Node->dump(); assert(0 && "All other types should have been promoted!!");
1301 case MVT::f64:
1302 case MVT::f32:
1303 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
1304 break;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001305 case MVT::i32:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001306 case MVT::i64:
1307 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
1308 break;
1309 }
1310 break;
1311 case 1:
1312 Select(N.getOperand(0));
1313 break;
1314 }
1315 //Tmp2 = AlphaLowering.getRetAddr();
1316 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
1317 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
1318 return;
1319
1320 case ISD::STORE:
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001321 {
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001322 SDOperand Chain = N.getOperand(0);
1323 SDOperand Value = N.getOperand(1);
1324 SDOperand Address = N.getOperand(2);
1325 Select(Chain);
1326
1327 Tmp1 = SelectExpr(Value); //value
1328 MVT::ValueType DestType = Value.getValueType();
1329
1330 if (Address.getOpcode() == ISD::GlobalAddress)
1331 {
1332 AlphaLowering.restoreGP(BB);
1333 switch(DestType) {
1334 default: assert(0 && "unknown Type in store");
1335 case MVT::i64: Opc = Alpha::STQ_SYM; break;
1336 case MVT::f64: Opc = Alpha::STT_SYM; break;
1337 case MVT::f32: Opc = Alpha::STS_SYM; break;
1338 }
1339 BuildMI(BB, Opc, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1340 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001341 else
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001342 {
1343 switch(DestType) {
1344 default: assert(0 && "unknown Type in store");
1345 case MVT::i64: Opc = Alpha::STQ; break;
1346 case MVT::f64: Opc = Alpha::STT; break;
1347 case MVT::f32: Opc = Alpha::STS; break;
1348 }
1349 long offset;
1350 SelectAddr(Address, Tmp2, offset);
1351 BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
1352 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001353 return;
1354 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001355
1356 case ISD::EXTLOAD:
1357 case ISD::SEXTLOAD:
1358 case ISD::ZEXTLOAD:
1359 case ISD::LOAD:
1360 case ISD::CopyFromReg:
1361 case ISD::CALL:
1362// case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001363 ExprMap.erase(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001364 SelectExpr(N);
1365 return;
1366
1367
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001368 case ISD::TRUNCSTORE:
1369 {
1370 SDOperand Chain = N.getOperand(0);
1371 SDOperand Value = N.getOperand(1);
1372 SDOperand Address = N.getOperand(2);
1373 Select(Chain);
1374
1375 MVT::ValueType DestType = cast<MVTSDNode>(Node)->getExtraValueType();
1376
1377 Tmp1 = SelectExpr(Value); //value
1378
1379 if (Address.getOpcode() == ISD::GlobalAddress)
1380 {
1381 AlphaLowering.restoreGP(BB);
1382 switch(DestType) {
1383 default: assert(0 && "unknown Type in store");
1384 case MVT::i1: //FIXME: DAG does not promote this load
1385 case MVT::i8: Opc = Alpha::STB; break;
1386 case MVT::i16: Opc = Alpha::STW; break;
1387 case MVT::i32: Opc = Alpha::STL; break;
1388 }
1389 BuildMI(BB, Opc, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1390 }
1391 else
1392 {
1393 switch(DestType) {
1394 default: assert(0 && "unknown Type in store");
1395 case MVT::i1: //FIXME: DAG does not promote this load
1396 case MVT::i8: Opc = Alpha::STB; break;
1397 case MVT::i16: Opc = Alpha::STW; break;
1398 case MVT::i32: Opc = Alpha::STL; break;
1399 }
1400 long offset;
1401 SelectAddr(Address, Tmp2, offset);
1402 BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
1403 }
1404 return;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001405 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001406
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001407 case ISD::ADJCALLSTACKDOWN:
1408 case ISD::ADJCALLSTACKUP:
1409 Select(N.getOperand(0));
1410 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1411
1412 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
1413 Alpha::ADJUSTSTACKUP;
1414 BuildMI(BB, Opc, 1).addImm(Tmp1);
1415 return;
1416 }
1417 assert(0 && "Should not be reached!");
1418}
1419
1420
1421/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
1422/// into a machine code representation using pattern matching and a machine
1423/// description file.
1424///
1425FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
1426 return new ISel(TM);
1427}