blob: 99bb9b9963f993488057a4390adbda10980c381d [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"
Andrew Lenharth032f2352005-02-22 21:59:48 +000029#include "llvm/Support/Debug.h"
Andrew Lenharth304d0f32005-01-22 23:41:55 +000030#include <set>
Andrew Lenharth684f2292005-01-30 00:35:27 +000031#include <algorithm>
Andrew Lenharth304d0f32005-01-22 23:41:55 +000032using namespace llvm;
33
34//===----------------------------------------------------------------------===//
35// AlphaTargetLowering - Alpha Implementation of the TargetLowering interface
36namespace {
37 class AlphaTargetLowering : public TargetLowering {
38 int VarArgsFrameIndex; // FrameIndex for start of varargs area.
39 unsigned GP; //GOT vreg
40 public:
41 AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) {
42 // Set up the TargetLowering object.
Andrew Lenharth3d65d312005-01-27 03:49:45 +000043 //I am having problems with shr n ubyte 1
Andrew Lenharth879ef222005-02-02 17:00:21 +000044 setShiftAmountType(MVT::i64);
45 setSetCCResultType(MVT::i64);
Andrew Lenharth3d65d312005-01-27 03:49:45 +000046
Andrew Lenharth304d0f32005-01-22 23:41:55 +000047 addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass);
48 addRegisterClass(MVT::f64, Alpha::FPRCRegisterClass);
Andrew Lenharth3d65d312005-01-27 03:49:45 +000049 addRegisterClass(MVT::f32, Alpha::FPRCRegisterClass);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000050
Andrew Lenharthd2bb9602005-01-27 07:50:35 +000051 setOperationAction(ISD::EXTLOAD , MVT::i1 , Promote);
Andrew Lenharth33819132005-03-04 20:09:23 +000052 setOperationAction(ISD::EXTLOAD , MVT::f32 , Promote);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000053
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +000054 setOperationAction(ISD::ZEXTLOAD , MVT::i1 , Expand);
Andrew Lenharth304d0f32005-01-22 23:41:55 +000055 setOperationAction(ISD::ZEXTLOAD , MVT::i32 , Expand);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000056
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +000057 setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand);
Andrew Lenharth304d0f32005-01-22 23:41:55 +000058 setOperationAction(ISD::SEXTLOAD , MVT::i8 , Expand);
59 setOperationAction(ISD::SEXTLOAD , MVT::i16 , Expand);
60
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 Lenharth33819132005-03-04 20:09:23 +000068 //Doesn't work yet
Andrew Lenharth572af902005-02-14 05:41:43 +000069 setOperationAction(ISD::SETCC , MVT::f32, Promote);
70
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000071 computeRegisterProperties();
Andrew Lenharth304d0f32005-01-22 23:41:55 +000072
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000073 addLegalFPImmediate(+0.0); //F31
74 addLegalFPImmediate(-0.0); //-F31
Andrew Lenharth304d0f32005-01-22 23:41:55 +000075 }
76
77 /// LowerArguments - This hook must be implemented to indicate how we should
78 /// lower the arguments for the specified function, into the specified DAG.
79 virtual std::vector<SDOperand>
80 LowerArguments(Function &F, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000081
Andrew Lenharth304d0f32005-01-22 23:41:55 +000082 /// LowerCallTo - This hook lowers an abstract call to a function into an
83 /// actual call.
84 virtual std::pair<SDOperand, SDOperand>
85 LowerCallTo(SDOperand Chain, const Type *RetTy, SDOperand Callee,
86 ArgListTy &Args, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000087
Andrew Lenharth304d0f32005-01-22 23:41:55 +000088 virtual std::pair<SDOperand, SDOperand>
89 LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000090
Andrew Lenharth304d0f32005-01-22 23:41:55 +000091 virtual std::pair<SDOperand,SDOperand>
92 LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
93 const Type *ArgTy, SelectionDAG &DAG);
94
95 virtual std::pair<SDOperand, SDOperand>
96 LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
97 SelectionDAG &DAG);
98
99 void restoreGP(MachineBasicBlock* BB)
100 {
101 BuildMI(BB, Alpha::BIS, 2, Alpha::R29).addReg(GP).addReg(GP);
102 }
103 };
104}
105
106//http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PY8AC-TET1_html/callCH3.html#BLOCK21
107
108//For now, just use variable size stack frame format
109
110//In a standard call, the first six items are passed in registers $16
111//- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
112//of argument-to-register correspondence.) The remaining items are
113//collected in a memory argument list that is a naturally aligned
114//array of quadwords. In a standard call, this list, if present, must
115//be passed at 0(SP).
116//7 ... n 0(SP) ... (n-7)*8(SP)
117
118std::vector<SDOperand>
119AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
120{
121 std::vector<SDOperand> ArgValues;
122
123 // //#define FP $15
124 // //#define RA $26
125 // //#define PV $27
126 // //#define GP $29
127 // //#define SP $30
128
129 // assert(0 && "TODO");
130 MachineFunction &MF = DAG.getMachineFunction();
Andrew Lenharth05380342005-02-07 05:07:00 +0000131 MachineFrameInfo*MFI = MF.getFrameInfo();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000132
133 GP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
134 MachineBasicBlock& BB = MF.front();
135
136 //Handle the return address
137 //BuildMI(&BB, Alpha::IDEF, 0, Alpha::R26);
138
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000139 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
140 Alpha::R19, Alpha::R20, Alpha::R21};
141 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
142 Alpha::F19, Alpha::F20, Alpha::F21};
Andrew Lenharth2c9e38c2005-02-06 21:07:31 +0000143 unsigned argVreg[6];
144 unsigned argPreg[6];
145 unsigned argOpc[6];
146
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000147 int count = 0;
Andrew Lenharth2c9e38c2005-02-06 21:07:31 +0000148
Chris Lattnere4d5c442005-03-15 04:54:21 +0000149 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000150 {
151 SDOperand newroot, argt;
152 if (count < 6) {
153 switch (getValueType(I->getType())) {
154 default:
155 std::cerr << "Unknown Type " << getValueType(I->getType()) << "\n";
156 abort();
157 case MVT::f64:
158 case MVT::f32:
159 BuildMI(&BB, Alpha::IDEF, 0, args_float[count]);
160 argVreg[count] =
161 MF.getSSARegMap()->createVirtualRegister(
Andrew Lenharth032f2352005-02-22 21:59:48 +0000162 getRegClassFor(getValueType(I->getType())));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000163 argPreg[count] = args_float[count];
164 argOpc[count] = Alpha::CPYS;
165 argt = newroot = DAG.getCopyFromReg(argVreg[count],
166 getValueType(I->getType()),
167 DAG.getRoot());
168 break;
169 case MVT::i1:
170 case MVT::i8:
171 case MVT::i16:
172 case MVT::i32:
173 case MVT::i64:
174 BuildMI(&BB, Alpha::IDEF, 0, args_int[count]);
175 argVreg[count] =
176 MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
177 argPreg[count] = args_int[count];
178 argOpc[count] = Alpha::BIS;
179 argt = newroot =
180 DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot());
181 if (getValueType(I->getType()) != MVT::i64)
182 argt =
183 DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()), newroot);
184 break;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000185 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000186 } else { //more args
187 // Create the frame index object for this incoming parameter...
188 int FI = MFI->CreateFixedObject(8, 8 * (count - 6));
189
190 // Create the SelectionDAG nodes corresponding to a load
191 //from this parameter
192 SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
193 argt = newroot = DAG.getLoad(getValueType(I->getType()),
194 DAG.getEntryNode(), FIN);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000195 }
Andrew Lenharth032f2352005-02-22 21:59:48 +0000196 ++count;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000197 DAG.setRoot(newroot.getValue(1));
198 ArgValues.push_back(argt);
199 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000200
201 BuildMI(&BB, Alpha::IDEF, 0, Alpha::R29);
202 BuildMI(&BB, Alpha::BIS, 2, GP).addReg(Alpha::R29).addReg(Alpha::R29);
Andrew Lenharth032f2352005-02-22 21:59:48 +0000203 for (int i = 0; i < count && i < 6; ++i) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000204 BuildMI(&BB, argOpc[i], 2,
205 argVreg[i]).addReg(argPreg[i]).addReg(argPreg[i]);
206 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000207
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000208 return ArgValues;
209}
210
211std::pair<SDOperand, SDOperand>
212AlphaTargetLowering::LowerCallTo(SDOperand Chain,
213 const Type *RetTy, SDOperand Callee,
214 ArgListTy &Args, SelectionDAG &DAG) {
215 int NumBytes = 0;
Andrew Lenharth684f2292005-01-30 00:35:27 +0000216 if (Args.size() > 6)
217 NumBytes = (Args.size() - 6) * 8;
218
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000219 Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
220 DAG.getConstant(NumBytes, getPointerTy()));
221 std::vector<SDOperand> args_to_use;
222 for (unsigned i = 0, e = Args.size(); i != e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000223 {
224 switch (getValueType(Args[i].second)) {
225 default: assert(0 && "Unexpected ValueType for argument!");
226 case MVT::i1:
227 case MVT::i8:
228 case MVT::i16:
229 case MVT::i32:
230 // Promote the integer to 64 bits. If the input type is signed use a
231 // sign extend, otherwise use a zero extend.
232 if (Args[i].second->isSigned())
233 Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first);
234 else
235 Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first);
236 break;
237 case MVT::i64:
238 case MVT::f64:
239 case MVT::f32:
240 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000241 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000242 args_to_use.push_back(Args[i].first);
243 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000244
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000245 std::vector<MVT::ValueType> RetVals;
246 MVT::ValueType RetTyVT = getValueType(RetTy);
247 if (RetTyVT != MVT::isVoid)
248 RetVals.push_back(RetTyVT);
249 RetVals.push_back(MVT::Other);
250
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000251 SDOperand TheCall = SDOperand(DAG.getCall(RetVals,
252 Chain, Callee, args_to_use), 0);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000253 Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
254 Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
255 DAG.getConstant(NumBytes, getPointerTy()));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000256 return std::make_pair(TheCall, Chain);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000257}
258
259std::pair<SDOperand, SDOperand>
260AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
261 //vastart just returns the address of the VarArgsFrameIndex slot.
262 return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain);
263}
264
265std::pair<SDOperand,SDOperand> AlphaTargetLowering::
266LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000267 const Type *ArgTy, SelectionDAG &DAG) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000268 abort();
269}
270
271
272std::pair<SDOperand, SDOperand> AlphaTargetLowering::
273LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
274 SelectionDAG &DAG) {
275 abort();
276}
277
278
279
280
281
282namespace {
283
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000284//===--------------------------------------------------------------------===//
285/// ISel - Alpha specific code to select Alpha machine instructions for
286/// SelectionDAG operations.
287//===--------------------------------------------------------------------===//
288class ISel : public SelectionDAGISel {
289
290 /// AlphaLowering - This object fully describes how to lower LLVM code to an
291 /// Alpha-specific SelectionDAG.
292 AlphaTargetLowering AlphaLowering;
293
294
295 /// ExprMap - As shared expressions are codegen'd, we keep track of which
296 /// vreg the value is produced in, so we only emit one copy of each compiled
297 /// tree.
298 static const unsigned notIn = (unsigned)(-1);
299 std::map<SDOperand, unsigned> ExprMap;
300
301 //CCInvMap sometimes (SetNE) we have the inverse CC code for free
302 std::map<SDOperand, unsigned> CCInvMap;
303
304public:
305 ISel(TargetMachine &TM) : SelectionDAGISel(AlphaLowering), AlphaLowering(TM)
306 {}
307
308 /// InstructionSelectBasicBlock - This callback is invoked by
309 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
310 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000311 DEBUG(BB->dump());
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000312 // Codegen the basic block.
313 Select(DAG.getRoot());
314
315 // Clear state used for selection.
316 ExprMap.clear();
317 CCInvMap.clear();
318 }
319
320 unsigned SelectExpr(SDOperand N);
321 unsigned SelectExprFP(SDOperand N, unsigned Result);
322 void Select(SDOperand N);
323
324 void SelectAddr(SDOperand N, unsigned& Reg, long& offset);
325 void SelectBranchCC(SDOperand N);
326};
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000327}
328
Andrew Lenharthe87f6c32005-03-11 17:48:05 +0000329//These describe LDAx
330static const int64_t IMM_LOW = 0xffffffffffff8000LL;
331static const int IMM_HIGH = 0x0000000000007fffLL;
332static const int IMM_MULT = 65536;
333
334static long getUpper16(long l)
335{
336 long y = l / IMM_MULT;
337 if (l % IMM_MULT > IMM_HIGH)
338 ++y;
339 return y;
340}
341
342static long getLower16(long l)
343{
344 long h = getUpper16(l);
345 return l - h * IMM_MULT;
346}
347
Andrew Lenharth65838902005-02-06 16:22:15 +0000348static unsigned GetSymVersion(unsigned opcode)
349{
350 switch (opcode) {
351 default: assert(0 && "unknown load or store"); return 0;
352 case Alpha::LDQ: return Alpha::LDQ_SYM;
353 case Alpha::LDS: return Alpha::LDS_SYM;
354 case Alpha::LDT: return Alpha::LDT_SYM;
355 case Alpha::LDL: return Alpha::LDL_SYM;
356 case Alpha::LDBU: return Alpha::LDBU_SYM;
357 case Alpha::LDWU: return Alpha::LDWU_SYM;
358 case Alpha::LDW: return Alpha::LDW_SYM;
359 case Alpha::LDB: return Alpha::LDB_SYM;
360 case Alpha::STQ: return Alpha::STQ_SYM;
361 case Alpha::STS: return Alpha::STS_SYM;
362 case Alpha::STT: return Alpha::STT_SYM;
363 case Alpha::STL: return Alpha::STL_SYM;
364 case Alpha::STW: return Alpha::STW_SYM;
365 case Alpha::STB: return Alpha::STB_SYM;
366 }
367}
368
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000369//Check to see if the load is a constant offset from a base register
370void ISel::SelectAddr(SDOperand N, unsigned& Reg, long& offset)
371{
372 unsigned opcode = N.getOpcode();
373 if (opcode == ISD::ADD) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000374 if(N.getOperand(1).getOpcode() == ISD::Constant &&
375 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767)
376 { //Normal imm add
377 Reg = SelectExpr(N.getOperand(0));
378 offset = cast<ConstantSDNode>(N.getOperand(1))->getValue();
379 return;
380 }
381 else if(N.getOperand(0).getOpcode() == ISD::Constant &&
382 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 32767)
383 {
384 Reg = SelectExpr(N.getOperand(1));
385 offset = cast<ConstantSDNode>(N.getOperand(0))->getValue();
386 return;
387 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000388 }
389 Reg = SelectExpr(N);
390 offset = 0;
391 return;
392}
393
Andrew Lenharth445171a2005-02-08 00:40:03 +0000394void ISel::SelectBranchCC(SDOperand N)
395{
396 assert(N.getOpcode() == ISD::BRCOND && "Not a BranchCC???");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000397 MachineBasicBlock *Dest =
398 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
399 unsigned Opc = Alpha::WTF;
400
Andrew Lenharth445171a2005-02-08 00:40:03 +0000401 Select(N.getOperand(0)); //chain
402 SDOperand CC = N.getOperand(1);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000403
Andrew Lenharth445171a2005-02-08 00:40:03 +0000404 if (CC.getOpcode() == ISD::SETCC)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000405 {
406 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
407 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
408 //Dropping the CC is only useful if we are comparing to 0
409 bool isZero0 = false;
410 bool isZero1 = false;
411 bool isNE = false;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000412
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000413 if(SetCC->getOperand(0).getOpcode() == ISD::Constant &&
414 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0)
415 isZero0 = true;
416 if(SetCC->getOperand(1).getOpcode() == ISD::Constant &&
417 cast<ConstantSDNode>(SetCC->getOperand(1))->getValue() == 0)
418 isZero1 = true;
419 if(SetCC->getCondition() == ISD::SETNE)
420 isNE = true;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000421
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000422 if (isZero0) {
Andrew Lenharth445171a2005-02-08 00:40:03 +0000423 switch (SetCC->getCondition()) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000424 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
425 case ISD::SETEQ: Opc = Alpha::BEQ; break;
426 case ISD::SETLT: Opc = Alpha::BGT; break;
427 case ISD::SETLE: Opc = Alpha::BGE; break;
428 case ISD::SETGT: Opc = Alpha::BLT; break;
429 case ISD::SETGE: Opc = Alpha::BLE; break;
430 case ISD::SETULT: Opc = Alpha::BNE; break;
431 case ISD::SETUGT: assert(0 && "0 > (unsigned) x is never true"); break;
432 case ISD::SETULE: assert(0 && "0 <= (unsigned) x is always true"); break;
433 case ISD::SETUGE: Opc = Alpha::BEQ; break; //Technically you could have this CC
434 case ISD::SETNE: Opc = Alpha::BNE; break;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000435 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000436 unsigned Tmp1 = SelectExpr(SetCC->getOperand(1));
437 BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest);
438 return;
439 } else if (isZero1) {
440 switch (SetCC->getCondition()) {
441 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
442 case ISD::SETEQ: Opc = Alpha::BEQ; break;
443 case ISD::SETLT: Opc = Alpha::BLT; break;
444 case ISD::SETLE: Opc = Alpha::BLE; break;
445 case ISD::SETGT: Opc = Alpha::BGT; break;
446 case ISD::SETGE: Opc = Alpha::BGE; break;
447 case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break;
448 case ISD::SETUGT: Opc = Alpha::BNE; break;
449 case ISD::SETULE: Opc = Alpha::BEQ; break; //Technically you could have this CC
450 case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break;
451 case ISD::SETNE: Opc = Alpha::BNE; break;
452 }
453 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
454 BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest);
455 return;
456 } else {
457 unsigned Tmp1 = SelectExpr(CC);
458 if (isNE)
459 BuildMI(BB, Alpha::BEQ, 2).addReg(CCInvMap[CC]).addMBB(Dest);
460 else
461 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000462 return;
463 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000464 } else { //FP
465 //Any comparison between 2 values should be codegened as an folded branch, as moving
466 //CC to the integer register is very expensive
467 //for a cmp b: c = a - b;
468 //a = b: c = 0
469 //a < b: c < 0
470 //a > b: c > 0
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000471
472 bool invTest = false;
473 unsigned Tmp3;
474
475 ConstantFPSDNode *CN;
476 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
477 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
478 Tmp3 = SelectExpr(SetCC->getOperand(0));
479 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
480 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
481 {
482 Tmp3 = SelectExpr(SetCC->getOperand(1));
483 invTest = true;
484 }
485 else
486 {
487 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
488 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
489 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
490 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
491 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
492 .addReg(Tmp1).addReg(Tmp2);
493 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000494
495 switch (SetCC->getCondition()) {
496 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000497 case ISD::SETEQ: Opc = invTest ? Alpha::FBNE : Alpha::FBEQ; break;
498 case ISD::SETLT: Opc = invTest ? Alpha::FBGT : Alpha::FBLT; break;
499 case ISD::SETLE: Opc = invTest ? Alpha::FBGE : Alpha::FBLE; break;
500 case ISD::SETGT: Opc = invTest ? Alpha::FBLT : Alpha::FBGT; break;
501 case ISD::SETGE: Opc = invTest ? Alpha::FBLE : Alpha::FBGE; break;
502 case ISD::SETNE: Opc = invTest ? Alpha::FBEQ : Alpha::FBNE; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000503 }
504 BuildMI(BB, Opc, 2).addReg(Tmp3).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000505 return;
506 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000507 abort(); //Should never be reached
508 } else {
509 //Giveup and do the stupid thing
510 unsigned Tmp1 = SelectExpr(CC);
511 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
512 return;
513 }
Andrew Lenharth445171a2005-02-08 00:40:03 +0000514 abort(); //Should never be reached
515}
516
Andrew Lenharth40831c52005-01-28 06:57:18 +0000517unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
518{
519 unsigned Tmp1, Tmp2, Tmp3;
520 unsigned Opc = 0;
521 SDNode *Node = N.Val;
522 MVT::ValueType DestType = N.getValueType();
523 unsigned opcode = N.getOpcode();
524
525 switch (opcode) {
526 default:
527 Node->dump();
528 assert(0 && "Node not handled!\n");
Andrew Lenharth2c594352005-01-29 15:42:07 +0000529
Andrew Lenharth9818c052005-02-05 13:19:12 +0000530 case ISD::SELECT:
531 {
Andrew Lenharth45859692005-03-03 21:47:53 +0000532 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
533 unsigned TV = SelectExpr(N.getOperand(1)); //Use if TRUE
534 unsigned FV = SelectExpr(N.getOperand(2)); //Use if FALSE
535
536 SDOperand CC = N.getOperand(0);
537 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
538
539 if (CC.getOpcode() == ISD::SETCC &&
540 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
541 { //FP Setcc -> Select yay!
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000542
543
Andrew Lenharth45859692005-03-03 21:47:53 +0000544 //for a cmp b: c = a - b;
545 //a = b: c = 0
546 //a < b: c < 0
547 //a > b: c > 0
548
549 bool invTest = false;
550 unsigned Tmp3;
551
552 ConstantFPSDNode *CN;
553 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
554 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
555 Tmp3 = SelectExpr(SetCC->getOperand(0));
556 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
557 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
558 {
559 Tmp3 = SelectExpr(SetCC->getOperand(1));
560 invTest = true;
561 }
562 else
563 {
564 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
565 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
566 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
567 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
568 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
569 .addReg(Tmp1).addReg(Tmp2);
570 }
571
572 switch (SetCC->getCondition()) {
573 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
574 case ISD::SETEQ: Opc = invTest ? Alpha::FCMOVNE : Alpha::FCMOVEQ; break;
575 case ISD::SETLT: Opc = invTest ? Alpha::FCMOVGT : Alpha::FCMOVLT; break;
576 case ISD::SETLE: Opc = invTest ? Alpha::FCMOVGE : Alpha::FCMOVLE; break;
577 case ISD::SETGT: Opc = invTest ? Alpha::FCMOVLT : Alpha::FCMOVGT; break;
578 case ISD::SETGE: Opc = invTest ? Alpha::FCMOVLE : Alpha::FCMOVGE; break;
579 case ISD::SETNE: Opc = invTest ? Alpha::FCMOVEQ : Alpha::FCMOVNE; break;
580 }
Andrew Lenharth33819132005-03-04 20:09:23 +0000581 BuildMI(BB, Opc, 3, Result).addReg(FV).addReg(TV).addReg(Tmp3);
Andrew Lenharth45859692005-03-03 21:47:53 +0000582 return Result;
583 }
584 else
585 {
586 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
587 // Spill the cond to memory and reload it from there.
588 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
589 MachineFunction *F = BB->getParent();
590 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
591 unsigned Tmp4 = MakeReg(MVT::f64);
592 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdx).addReg(Alpha::F31);
593 BuildMI(BB, Alpha::LDT, 2, Tmp4).addFrameIndex(FrameIdx).addReg(Alpha::F31);
594 //now ideally, we don't have to do anything to the flag...
595 // Get the condition into the zero flag.
596 BuildMI(BB, Alpha::FCMOVEQ, 3, Result).addReg(TV).addReg(FV).addReg(Tmp4);
597 return Result;
598 }
Andrew Lenharth9818c052005-02-05 13:19:12 +0000599 }
600
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000601 case ISD::FP_ROUND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000602 assert (DestType == MVT::f32 &&
603 N.getOperand(0).getValueType() == MVT::f64 &&
604 "only f64 to f32 conversion supported here");
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000605 Tmp1 = SelectExpr(N.getOperand(0));
606 BuildMI(BB, Alpha::CVTTS, 1, Result).addReg(Tmp1);
607 return Result;
608
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000609 case ISD::FP_EXTEND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000610 assert (DestType == MVT::f64 &&
611 N.getOperand(0).getValueType() == MVT::f32 &&
612 "only f32 to f64 conversion supported here");
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000613 Tmp1 = SelectExpr(N.getOperand(0));
614 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
615 return Result;
616
Andrew Lenharth2c594352005-01-29 15:42:07 +0000617 case ISD::CopyFromReg:
618 {
619 // Make sure we generate both values.
620 if (Result != notIn)
621 ExprMap[N.getValue(1)] = notIn; // Generate the token
622 else
623 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
624
625 SDOperand Chain = N.getOperand(0);
626
627 Select(Chain);
628 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
629 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
630 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(r).addReg(r);
631 return Result;
632 }
633
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000634 case ISD::LOAD:
635 {
636 // Make sure we generate both values.
637 if (Result != notIn)
638 ExprMap[N.getValue(1)] = notIn; // Generate the token
639 else
640 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000641
Andrew Lenharth29219162005-02-07 06:31:44 +0000642 DestType = N.getValue(0).getValueType();
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000643
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000644 SDOperand Chain = N.getOperand(0);
645 SDOperand Address = N.getOperand(1);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000646 Select(Chain);
Andrew Lenharth65838902005-02-06 16:22:15 +0000647 Opc = DestType == MVT::f64 ? Alpha::LDT : Alpha::LDS;
648
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000649 if (Address.getOpcode() == ISD::GlobalAddress) {
650 AlphaLowering.restoreGP(BB);
651 Opc = GetSymVersion(Opc);
652 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
653 }
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000654 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000655 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +0000656 Opc = GetSymVersion(Opc);
Andrew Lenharth97127a12005-02-05 17:41:39 +0000657 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000658 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000659 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000660 BuildMI(BB, Opc, 2, Result)
661 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
662 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000663 } else {
664 long offset;
665 SelectAddr(Address, Tmp1, offset);
666 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
667 }
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000668 return Result;
669 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000670 case ISD::ConstantFP:
671 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
672 if (CN->isExactlyValue(+0.0)) {
673 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000674 } else if ( CN->isExactlyValue(-0.0)) {
675 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000676 } else {
677 abort();
678 }
679 }
680 return Result;
681
682 case ISD::MUL:
683 case ISD::ADD:
684 case ISD::SUB:
685 case ISD::SDIV:
686 switch( opcode ) {
687 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
688 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
689 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
690 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
691 };
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000692
693 ConstantFPSDNode *CN;
694 if (opcode == ISD::SUB
695 && (CN = dyn_cast<ConstantFPSDNode>(N.getOperand(0)))
696 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
697 {
698 Tmp2 = SelectExpr(N.getOperand(1));
699 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp2).addReg(Tmp2);
700 } else {
701 Tmp1 = SelectExpr(N.getOperand(0));
702 Tmp2 = SelectExpr(N.getOperand(1));
703 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
704 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000705 return Result;
706
Andrew Lenharth2c594352005-01-29 15:42:07 +0000707 case ISD::EXTLOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000708 {
709 //include a conversion sequence for float loads to double
710 if (Result != notIn)
711 ExprMap[N.getValue(1)] = notIn; // Generate the token
712 else
713 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
714
Andrew Lenhartha549deb2005-02-07 05:33:15 +0000715 Tmp1 = MakeReg(MVT::f32);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000716
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000717 assert(cast<MVTSDNode>(Node)->getExtraValueType() == MVT::f32 &&
718 "EXTLOAD not from f32");
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000719 assert(Node->getValueType(0) == MVT::f64 && "EXTLOAD not to f64");
720
721 SDOperand Chain = N.getOperand(0);
722 SDOperand Address = N.getOperand(1);
723 Select(Chain);
724
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000725 if (Address.getOpcode() == ISD::GlobalAddress) {
726 AlphaLowering.restoreGP(BB);
727 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
728 }
729 else if (ConstantPoolSDNode *CP =
730 dyn_cast<ConstantPoolSDNode>(N.getOperand(1)))
731 {
732 AlphaLowering.restoreGP(BB);
733 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addConstantPoolIndex(CP->getIndex());
734 }
735 else if(Address.getOpcode() == ISD::FrameIndex) {
736 Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
Andrew Lenharth032f2352005-02-22 21:59:48 +0000737 BuildMI(BB, Alpha::LDS, 2, Tmp1)
738 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
739 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000740 } else {
741 long offset;
742 SelectAddr(Address, Tmp2, offset);
743 BuildMI(BB, Alpha::LDS, 1, Tmp1).addImm(offset).addReg(Tmp2);
744 }
Andrew Lenharth29219162005-02-07 06:31:44 +0000745 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000746 return Result;
747 }
Andrew Lenharth2c594352005-01-29 15:42:07 +0000748
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000749 case ISD::UINT_TO_FP:
750 case ISD::SINT_TO_FP:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000751 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000752 assert (N.getOperand(0).getValueType() == MVT::i64
753 && "only quads can be loaded from");
Andrew Lenharth40831c52005-01-28 06:57:18 +0000754 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000755 Tmp2 = MakeReg(MVT::f64);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000756
757 //The hard way:
758 // Spill the integer to memory and reload it from there.
759 unsigned Size = MVT::getSizeInBits(MVT::i64)/8;
760 MachineFunction *F = BB->getParent();
761 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, Size);
762
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000763 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdx).addReg(Alpha::F31);
764 BuildMI(BB, Alpha::LDT, 2, Tmp2).addFrameIndex(FrameIdx).addReg(Alpha::F31);
765 Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
766 BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000767
768 //The easy way: doesn't work
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000769 // //so these instructions are not supported on ev56
770 // Opc = DestType == MVT::f64 ? Alpha::ITOFT : Alpha::ITOFS;
771 // BuildMI(BB, Opc, 1, Tmp2).addReg(Tmp1);
772 // Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
773 // BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000774
Andrew Lenharth40831c52005-01-28 06:57:18 +0000775 return Result;
776 }
777 }
778 assert(0 && "should not get here");
779 return 0;
780}
781
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000782unsigned ISel::SelectExpr(SDOperand N) {
783 unsigned Result;
784 unsigned Tmp1, Tmp2, Tmp3;
785 unsigned Opc = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000786 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000787
788 SDNode *Node = N.Val;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000789 MVT::ValueType DestType = N.getValueType();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000790
791 unsigned &Reg = ExprMap[N];
792 if (Reg) return Reg;
793
794 if (N.getOpcode() != ISD::CALL)
795 Reg = Result = (N.getValueType() != MVT::Other) ?
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000796 MakeReg(N.getValueType()) : notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000797 else {
798 // If this is a call instruction, make sure to prepare ALL of the result
799 // values as well as the chain.
800 if (Node->getNumValues() == 1)
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000801 Reg = Result = notIn; // Void call, just a chain.
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000802 else {
803 Result = MakeReg(Node->getValueType(0));
804 ExprMap[N.getValue(0)] = Result;
805 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
806 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000807 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000808 }
809 }
810
Andrew Lenharth22088bb2005-02-02 15:05:33 +0000811 if (DestType == MVT::f64 || DestType == MVT::f32 ||
Andrew Lenharth06342c32005-02-07 06:21:37 +0000812 (
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000813 (opcode == ISD::LOAD || opcode == ISD::CopyFromReg ||
814 opcode == ISD::EXTLOAD) &&
815 (N.getValue(0).getValueType() == MVT::f32 ||
816 N.getValue(0).getValueType() == MVT::f64)
Andrew Lenharth06342c32005-02-07 06:21:37 +0000817 )
818 )
Andrew Lenharth40831c52005-01-28 06:57:18 +0000819 return SelectExprFP(N, Result);
820
821 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000822 default:
823 Node->dump();
824 assert(0 && "Node not handled!\n");
825
Andrew Lenharth032f2352005-02-22 21:59:48 +0000826 case ISD::DYNAMIC_STACKALLOC:
827 // Generate both result values.
Andrew Lenharth3a7118d2005-02-23 17:33:42 +0000828 if (Result != notIn)
829 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth032f2352005-02-22 21:59:48 +0000830 else
831 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
832
833 // FIXME: We are currently ignoring the requested alignment for handling
834 // greater than the stack alignment. This will need to be revisited at some
835 // point. Align = N.getOperand(2);
836
837 if (!isa<ConstantSDNode>(N.getOperand(2)) ||
838 cast<ConstantSDNode>(N.getOperand(2))->getValue() != 0) {
839 std::cerr << "Cannot allocate stack object with greater alignment than"
840 << " the stack alignment yet!";
841 abort();
842 }
843
844 Select(N.getOperand(0));
845 if (ConstantSDNode* CN = dyn_cast<ConstantSDNode>(N.getOperand(1)))
846 {
847 if (CN->getValue() < 32000)
848 {
849 BuildMI(BB, Alpha::LDA, 2, Alpha::R30)
850 .addImm(-CN->getValue()).addReg(Alpha::R30);
851 } else {
852 Tmp1 = SelectExpr(N.getOperand(1));
853 // Subtract size from stack pointer, thereby allocating some space.
854 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
855 }
856 } else {
857 Tmp1 = SelectExpr(N.getOperand(1));
858 // Subtract size from stack pointer, thereby allocating some space.
859 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
860 }
861
862 // Put a pointer to the space into the result register, by copying the stack
863 // pointer.
Andrew Lenharth7bc47022005-02-22 23:29:25 +0000864 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R30).addReg(Alpha::R30);
Andrew Lenharth032f2352005-02-22 21:59:48 +0000865 return Result;
866
Andrew Lenharth33819132005-03-04 20:09:23 +0000867// case ISD::ConstantPool:
868// Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
869// AlphaLowering.restoreGP(BB);
870// BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(Tmp1);
871// return Result;
Andrew Lenharth2c594352005-01-29 15:42:07 +0000872
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000873 case ISD::FrameIndex:
Andrew Lenharth032f2352005-02-22 21:59:48 +0000874 BuildMI(BB, Alpha::LDA, 2, Result)
875 .addFrameIndex(cast<FrameIndexSDNode>(N)->getIndex())
876 .addReg(Alpha::F31);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000877 return Result;
878
879 case ISD::EXTLOAD:
Andrew Lenharthf311e8b2005-02-07 05:18:02 +0000880 case ISD::ZEXTLOAD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000881 case ISD::SEXTLOAD:
Andrew Lenhartha549deb2005-02-07 05:33:15 +0000882 case ISD::LOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000883 {
884 // Make sure we generate both values.
885 if (Result != notIn)
886 ExprMap[N.getValue(1)] = notIn; // Generate the token
887 else
888 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000889
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000890 SDOperand Chain = N.getOperand(0);
891 SDOperand Address = N.getOperand(1);
892 Select(Chain);
893
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000894 assert(Node->getValueType(0) == MVT::i64 &&
895 "Unknown type to sign extend to.");
Andrew Lenharth03824012005-02-07 05:55:55 +0000896 if (opcode == ISD::LOAD)
897 Opc = Alpha::LDQ;
898 else
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000899 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
900 default: Node->dump(); assert(0 && "Bad sign extend!");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000901 case MVT::i32: Opc = Alpha::LDL;
902 assert(opcode != ISD::ZEXTLOAD && "Not sext"); break;
903 case MVT::i16: Opc = Alpha::LDWU;
904 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharthf311e8b2005-02-07 05:18:02 +0000905 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000906 case MVT::i8: Opc = Alpha::LDBU;
907 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000908 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000909
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000910 if (Address.getOpcode() == ISD::GlobalAddress) {
911 AlphaLowering.restoreGP(BB);
912 Opc = GetSymVersion(Opc);
913 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
914 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000915 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
916 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +0000917 Opc = GetSymVersion(Opc);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000918 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000919 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000920 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000921 BuildMI(BB, Opc, 2, Result)
922 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
923 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000924 } else {
925 long offset;
926 SelectAddr(Address, Tmp1, offset);
927 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
928 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000929 return Result;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000930 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000931
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000932 case ISD::GlobalAddress:
933 AlphaLowering.restoreGP(BB);
934 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
935 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
936 return Result;
937
938 case ISD::CALL:
939 {
940 Select(N.getOperand(0));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000941
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000942 // The chain for this call is now lowered.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000943 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), notIn));
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000944
945 //grab the arguments
946 std::vector<unsigned> argvregs;
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000947 //assert(Node->getNumOperands() < 8 && "Only 6 args supported");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000948 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000949 argvregs.push_back(SelectExpr(N.getOperand(i)));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000950
Andrew Lenharth684f2292005-01-30 00:35:27 +0000951 //in reg args
952 for(int i = 0, e = std::min(6, (int)argvregs.size()); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000953 {
954 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
955 Alpha::R19, Alpha::R20, Alpha::R21};
956 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
957 Alpha::F19, Alpha::F20, Alpha::F21};
958 switch(N.getOperand(i+2).getValueType()) {
959 default:
960 Node->dump();
961 N.getOperand(i).Val->dump();
962 std::cerr << "Type for " << i << " is: " <<
963 N.getOperand(i+2).getValueType() << "\n";
964 assert(0 && "Unknown value type for call");
965 case MVT::i1:
966 case MVT::i8:
967 case MVT::i16:
968 case MVT::i32:
969 case MVT::i64:
970 BuildMI(BB, Alpha::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
971 break;
972 case MVT::f32:
973 case MVT::f64:
974 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
975 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +0000976 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000977 }
Andrew Lenharth684f2292005-01-30 00:35:27 +0000978 //in mem args
979 for (int i = 6, e = argvregs.size(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000980 {
981 switch(N.getOperand(i+2).getValueType()) {
982 default:
983 Node->dump();
984 N.getOperand(i).Val->dump();
985 std::cerr << "Type for " << i << " is: " <<
986 N.getOperand(i+2).getValueType() << "\n";
987 assert(0 && "Unknown value type for call");
988 case MVT::i1:
989 case MVT::i8:
990 case MVT::i16:
991 case MVT::i32:
992 case MVT::i64:
993 BuildMI(BB, Alpha::STQ, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
994 break;
995 case MVT::f32:
996 BuildMI(BB, Alpha::STS, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
997 break;
998 case MVT::f64:
999 BuildMI(BB, Alpha::STT, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1000 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001001 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001002 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001003 //build the right kind of call
1004 if (GlobalAddressSDNode *GASD =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001005 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001006 {
Andrew Lenharth3e315922005-02-10 20:10:38 +00001007 //if (GASD->getGlobal()->isExternal()) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001008 //use safe calling convention
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001009 AlphaLowering.restoreGP(BB);
1010 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
Andrew Lenharth3e315922005-02-10 20:10:38 +00001011 //} else {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001012 //use PC relative branch call
Andrew Lenharth3e315922005-02-10 20:10:38 +00001013 //BuildMI(BB, Alpha::BSR, 1, Alpha::R26).addGlobalAddress(GASD->getGlobal(),true);
1014 //}
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001015 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001016 else if (ExternalSymbolSDNode *ESSDN =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001017 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001018 {
1019 AlphaLowering.restoreGP(BB);
1020 BuildMI(BB, Alpha::CALL, 0).addExternalSymbol(ESSDN->getSymbol(), true);
1021 } else {
1022 //no need to restore GP as we are doing an indirect call
1023 Tmp1 = SelectExpr(N.getOperand(1));
1024 BuildMI(BB, Alpha::BIS, 2, Alpha::R27).addReg(Tmp1).addReg(Tmp1);
1025 BuildMI(BB, Alpha::JSR, 2, Alpha::R26).addReg(Alpha::R27).addImm(0);
1026 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001027
1028 //push the result into a virtual register
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001029
1030 switch (Node->getValueType(0)) {
1031 default: Node->dump(); assert(0 && "Unknown value type for call result!");
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001032 case MVT::Other: return notIn;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001033 case MVT::i1:
1034 case MVT::i8:
1035 case MVT::i16:
1036 case MVT::i32:
1037 case MVT::i64:
1038 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
1039 break;
1040 case MVT::f32:
1041 case MVT::f64:
1042 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
1043 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001044 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001045 return Result+N.ResNo;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001046 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001047
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001048 case ISD::SIGN_EXTEND:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001049 abort();
1050
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001051 case ISD::SIGN_EXTEND_INREG:
1052 {
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001053 //Alpha has instructions for a bunch of signed 32 bit stuff
1054 if( dyn_cast<MVTSDNode>(Node)->getExtraValueType() == MVT::i32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001055 {
1056 switch (N.getOperand(0).getOpcode()) {
1057 case ISD::ADD:
1058 case ISD::SUB:
1059 case ISD::MUL:
1060 {
1061 bool isAdd = N.getOperand(0).getOpcode() == ISD::ADD;
1062 bool isMul = N.getOperand(0).getOpcode() == ISD::MUL;
1063 //FIXME: first check for Scaled Adds and Subs!
1064 if(N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1065 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() <= 255)
1066 { //Normal imm add/sub
1067 Opc = isAdd ? Alpha::ADDLi : (isMul ? Alpha::MULLi : Alpha::SUBLi);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001068 //if the value was really originally a i32, skip the up conversion
1069 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1070 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1071 ->getExtraValueType() == MVT::i32)
1072 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1073 else
1074 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001075 Tmp2 = cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue();
1076 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001077 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001078 else
1079 { //Normal add/sub
1080 Opc = isAdd ? Alpha::ADDL : (isMul ? Alpha::MULLi : Alpha::SUBL);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001081 //if the value was really originally a i32, skip the up conversion
1082 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1083 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1084 ->getExtraValueType() == MVT::i32)
1085 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1086 else
1087 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1088 //if the value was really originally a i32, skip the up conversion
1089 if (N.getOperand(0).getOperand(1).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1090 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(1).Val)
1091 ->getExtraValueType() == MVT::i32)
1092 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0));
1093 else
1094 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1095
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001096 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1097 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1098 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1099 }
1100 return Result;
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001101 }
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001102 case ISD::SEXTLOAD:
1103 //SelectionDag isn't deleting the signextend after sextloads
1104 Reg = Result = SelectExpr(N.getOperand(0));
1105 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001106 default: break; //Fall Though;
1107 }
1108 } //Every thing else fall though too, including unhandled opcodes above
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001109 Tmp1 = SelectExpr(N.getOperand(0));
1110 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001111 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001112 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001113 {
1114 default:
1115 Node->dump();
1116 assert(0 && "Sign Extend InReg not there yet");
1117 break;
1118 case MVT::i32:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001119 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001120 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001121 break;
1122 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001123 case MVT::i16:
1124 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
1125 break;
1126 case MVT::i8:
1127 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
1128 break;
Andrew Lenharthebce5042005-02-12 19:35:12 +00001129 case MVT::i1:
1130 Tmp2 = MakeReg(MVT::i64);
1131 BuildMI(BB, Alpha::ANDi, 2, Tmp2).addReg(Tmp1).addImm(1);
Andrew Lenharth7536eea2005-02-12 20:42:09 +00001132 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Alpha::F31).addReg(Tmp2);
Andrew Lenharthebce5042005-02-12 19:35:12 +00001133 break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001134 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001135 return Result;
1136 }
1137 case ISD::ZERO_EXTEND_INREG:
1138 {
1139 Tmp1 = SelectExpr(N.getOperand(0));
1140 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001141 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001142 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001143 {
1144 default:
1145 Node->dump();
1146 assert(0 && "Zero Extend InReg not there yet");
1147 break;
1148 case MVT::i32: Tmp2 = 0xf0; break;
1149 case MVT::i16: Tmp2 = 0xfc; break;
1150 case MVT::i8: Tmp2 = 0xfe; break;
1151 case MVT::i1: //handle this one special
1152 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
1153 return Result;
1154 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001155 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001156 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001157 }
1158
1159 case ISD::SETCC:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001160 {
1161 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
1162 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
1163 bool isConst1 = false;
1164 bool isConst2 = false;
1165 int dir;
Andrew Lenharth9818c052005-02-05 13:19:12 +00001166
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001167 //Tmp1 = SelectExpr(N.getOperand(0));
1168 if(N.getOperand(0).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001169 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1170 isConst1 = true;
1171 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001172 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1173 isConst2 = true;
1174
1175 switch (SetCC->getCondition()) {
1176 default: Node->dump(); assert(0 && "Unknown integer comparison!");
1177 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001178 case ISD::SETLT:
1179 Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
1180 case ISD::SETLE:
1181 Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
1182 case ISD::SETGT:
1183 Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
1184 case ISD::SETGE:
1185 Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
1186 case ISD::SETULT:
1187 Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
1188 case ISD::SETUGT:
1189 Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
1190 case ISD::SETULE:
1191 Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
1192 case ISD::SETUGE:
1193 Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001194 case ISD::SETNE: {//Handle this one special
1195 //std::cerr << "Alpha does not have a setne.\n";
1196 //abort();
1197 Tmp1 = SelectExpr(N.getOperand(0));
1198 Tmp2 = SelectExpr(N.getOperand(1));
1199 Tmp3 = MakeReg(MVT::i64);
1200 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth445171a2005-02-08 00:40:03 +00001201 //Remeber we have the Inv for this CC
1202 CCInvMap[N] = Tmp3;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001203 //and invert
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001204 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001205 return Result;
1206 }
1207 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001208 if (dir == 1) {
1209 Tmp1 = SelectExpr(N.getOperand(0));
1210 if (isConst2) {
1211 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1212 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1213 } else {
1214 Tmp2 = SelectExpr(N.getOperand(1));
1215 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1216 }
1217 } else if (dir == 2) {
1218 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001219 if (isConst1) {
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001220 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1221 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1222 } else {
1223 Tmp2 = SelectExpr(N.getOperand(0));
1224 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1225 }
1226 } else { //dir == 0
1227 if (isConst1) {
1228 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1229 Tmp2 = SelectExpr(N.getOperand(1));
1230 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
1231 } else if (isConst2) {
1232 Tmp1 = SelectExpr(N.getOperand(0));
1233 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1234 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
1235 } else {
1236 Tmp1 = SelectExpr(N.getOperand(0));
1237 Tmp2 = SelectExpr(N.getOperand(1));
1238 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
1239 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001240 }
1241 } else {
1242 //assert(SetCC->getOperand(0).getValueType() != MVT::f32 && "SetCC f32 should have been promoted");
1243 bool rev = false;
1244 bool inv = false;
1245
1246 switch (SetCC->getCondition()) {
1247 default: Node->dump(); assert(0 && "Unknown FP comparison!");
1248 case ISD::SETEQ: Opc = Alpha::CMPTEQ; break;
1249 case ISD::SETLT: Opc = Alpha::CMPTLT; break;
1250 case ISD::SETLE: Opc = Alpha::CMPTLE; break;
1251 case ISD::SETGT: Opc = Alpha::CMPTLT; rev = true; break;
1252 case ISD::SETGE: Opc = Alpha::CMPTLE; rev = true; break;
1253 case ISD::SETNE: Opc = Alpha::CMPTEQ; inv = true; break;
1254 }
1255
Andrew Lenharthca3d59b2005-03-14 19:23:45 +00001256 //FIXME: check for constant 0.0
1257 ConstantFPSDNode *CN;
1258 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
1259 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1260 Tmp1 = Alpha::F31;
1261 else
1262 Tmp1 = SelectExpr(N.getOperand(0));
1263
1264 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
1265 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1266 Tmp2 = Alpha::F31;
1267 else
1268 Tmp2 = SelectExpr(N.getOperand(1));
1269
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001270 //Can only compare doubles, and dag won't promote for me
1271 if (SetCC->getOperand(0).getValueType() == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001272 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001273 //assert(0 && "Setcc On float?\n");
1274 std::cerr << "Setcc on float!\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001275 Tmp3 = MakeReg(MVT::f64);
1276 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp1);
1277 Tmp1 = Tmp3;
1278 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001279 if (SetCC->getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001280 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001281 //assert (0 && "Setcc On float?\n");
1282 std::cerr << "Setcc on float!\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001283 Tmp3 = MakeReg(MVT::f64);
1284 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp2);
Andrew Lenharth572af902005-02-14 05:41:43 +00001285 Tmp2 = Tmp3;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001286 }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001287
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001288 if (rev) std::swap(Tmp1, Tmp2);
1289 Tmp3 = MakeReg(MVT::f64);
1290 //do the comparison
1291 BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
1292
1293 //now arrange for Result (int) to have a 1 or 0
1294
Andrew Lenharthca3d59b2005-03-14 19:23:45 +00001295 BuildMI(BB, Alpha::CC2INT, 1, Result).addReg(Tmp3);
1296
1297// // Spill the FP to memory and reload it from there.
1298// unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1299// MachineFunction *F = BB->getParent();
1300// int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
1301// unsigned Tmp4 = MakeReg(MVT::f64);
1302// BuildMI(BB, Alpha::CVTTQ, 1, Tmp4).addReg(Tmp3);
1303// BuildMI(BB, Alpha::STT, 3).addReg(Tmp4).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1304// unsigned Tmp5 = MakeReg(MVT::i64);
1305// BuildMI(BB, Alpha::LDQ, 2, Tmp5).addFrameIndex(FrameIdx).addReg(Alpha::F31);
Andrew Lenharth9818c052005-02-05 13:19:12 +00001306
Andrew Lenharthca3d59b2005-03-14 19:23:45 +00001307// //now, set result based on Tmp5
1308// //Set Tmp6 if fp cmp was false
1309// unsigned Tmp6 = MakeReg(MVT::i64);
1310// BuildMI(BB, Alpha::CMPEQ, 2, Tmp6).addReg(Tmp5).addReg(Alpha::R31);
1311// //and invert
1312// BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp6).addReg(Alpha::R31);
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001313
1314 }
1315 // else
1316 // {
1317 // Node->dump();
1318 // assert(0 && "Not a setcc in setcc");
1319 // }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001320 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001321 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001322 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001323
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001324 case ISD::CopyFromReg:
1325 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001326 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001327 if (Result != notIn)
1328 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth40831c52005-01-28 06:57:18 +00001329 else
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001330 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth40831c52005-01-28 06:57:18 +00001331
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001332 SDOperand Chain = N.getOperand(0);
1333
1334 Select(Chain);
1335 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
1336 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
1337 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
1338 return Result;
1339 }
1340
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001341 //Most of the plain arithmetic and logic share the same form, and the same
1342 //constant immediate test
1343 case ISD::AND:
1344 case ISD::OR:
1345 case ISD::XOR:
1346 case ISD::SHL:
1347 case ISD::SRL:
Andrew Lenharth2c594352005-01-29 15:42:07 +00001348 case ISD::SRA:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001349 case ISD::MUL:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001350 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
1351 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001352 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001353 {
1354 switch(opcode) {
1355 case ISD::AND: Opc = Alpha::ANDi; break;
1356 case ISD::OR: Opc = Alpha::BISi; break;
1357 case ISD::XOR: Opc = Alpha::XORi; break;
1358 case ISD::SHL: Opc = Alpha::SLi; break;
1359 case ISD::SRL: Opc = Alpha::SRLi; break;
1360 case ISD::SRA: Opc = Alpha::SRAi; break;
1361 case ISD::MUL: Opc = Alpha::MULQi; break;
1362 };
1363 Tmp1 = SelectExpr(N.getOperand(0));
1364 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1365 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1366 } else {
1367 switch(opcode) {
1368 case ISD::AND: Opc = Alpha::AND; break;
1369 case ISD::OR: Opc = Alpha::BIS; break;
1370 case ISD::XOR: Opc = Alpha::XOR; break;
1371 case ISD::SHL: Opc = Alpha::SL; break;
1372 case ISD::SRL: Opc = Alpha::SRL; break;
1373 case ISD::SRA: Opc = Alpha::SRA; break;
1374 case ISD::MUL: Opc = Alpha::MULQ; break;
1375 };
1376 Tmp1 = SelectExpr(N.getOperand(0));
1377 Tmp2 = SelectExpr(N.getOperand(1));
1378 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1379 }
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001380 return Result;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001381
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001382 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001383 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001384 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001385 bool isAdd = opcode == ISD::ADD;
1386
1387 //FIXME: first check for Scaled Adds and Subs!
1388 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001389 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001390 { //Normal imm add/sub
1391 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
1392 Tmp1 = SelectExpr(N.getOperand(0));
1393 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1394 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1395 }
Andrew Lenharth40831c52005-01-28 06:57:18 +00001396 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001397 (cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767 ||
1398 (long)cast<ConstantSDNode>(N.getOperand(1))->getValue() >= -32767))
1399 { //LDA
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001400 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001401 Tmp2 = (long)cast<ConstantSDNode>(N.getOperand(1))->getValue();
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001402 if (!isAdd)
1403 Tmp2 = -Tmp2;
1404 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
1405 } else {
1406 //Normal add/sub
1407 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
1408 Tmp1 = SelectExpr(N.getOperand(0));
1409 Tmp2 = SelectExpr(N.getOperand(1));
1410 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1411 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001412 return Result;
1413 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001414
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001415 case ISD::UREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001416 case ISD::SREM:
1417 case ISD::SDIV:
1418 case ISD::UDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001419 //FIXME: alpha really doesn't support any of these operations,
1420 // the ops are expanded into special library calls with
1421 // special calling conventions
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001422 //Restore GP because it is a call after all...
Andrew Lenharth40831c52005-01-28 06:57:18 +00001423 switch(opcode) {
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001424 case ISD::UREM: Opc = Alpha::REMQU; break;
1425 case ISD::SREM: Opc = Alpha::REMQ; break;
1426 case ISD::UDIV: Opc = Alpha::DIVQU; break;
1427 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001428 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001429 Tmp1 = SelectExpr(N.getOperand(0));
1430 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth33819132005-03-04 20:09:23 +00001431 //set up regs explicitly (helps Reg alloc)
1432 BuildMI(BB, Alpha::BIS, 2, Alpha::R24).addReg(Tmp1).addReg(Tmp1);
1433 BuildMI(BB, Alpha::BIS, 2, Alpha::R25).addReg(Tmp2).addReg(Tmp2);
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001434 AlphaLowering.restoreGP(BB);
Andrew Lenharth33819132005-03-04 20:09:23 +00001435 BuildMI(BB, Opc, 2).addReg(Alpha::R24).addReg(Alpha::R25);
1436 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R27).addReg(Alpha::R27);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001437 return Result;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001438
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001439 case ISD::FP_TO_UINT:
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001440 case ISD::FP_TO_SINT:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001441 {
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001442 assert (DestType == MVT::i64 && "only quads can be loaded to");
1443 MVT::ValueType SrcType = N.getOperand(0).getValueType();
Andrew Lenharth03824012005-02-07 05:55:55 +00001444 assert (SrcType == MVT::f32 || SrcType == MVT::f64);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001445 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
1446
1447 //The hard way:
1448 // Spill the integer to memory and reload it from there.
1449 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1450 MachineFunction *F = BB->getParent();
1451 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
1452
1453 //CVTTQ STT LDQ
1454 //CVTST CVTTQ STT LDQ
1455 if (SrcType == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001456 {
1457 Tmp2 = MakeReg(MVT::f64);
1458 BuildMI(BB, Alpha::CVTST, 1, Tmp2).addReg(Tmp1);
1459 Tmp1 = Tmp2;
1460 }
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001461 Tmp2 = MakeReg(MVT::f64);
1462 BuildMI(BB, Alpha::CVTTQ, 1, Tmp2).addReg(Tmp1);
1463 BuildMI(BB, Alpha::STT, 3).addReg(Tmp2).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1464 BuildMI(BB, Alpha::LDQ, 2, Result).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1465
1466 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001467 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001468
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001469 // // case ISD::FP_TO_UINT:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001470
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001471 case ISD::SELECT:
1472 {
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001473 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001474 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1475 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001476 // Get the condition into the zero flag.
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001477 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001478 return Result;
1479 }
1480
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001481 case ISD::Constant:
1482 {
Andrew Lenharthe87f6c32005-03-11 17:48:05 +00001483 int64_t val = (long)cast<ConstantSDNode>(N)->getValue();
1484 if (val <= IMM_HIGH && val >= IMM_LOW) {
1485 BuildMI(BB, Alpha::LDA, 2, Result).addImm(val).addReg(Alpha::R31);
1486 }
1487 else if (val <= (int64_t)IMM_HIGH + (int64_t)IMM_HIGH * (int64_t)IMM_MULT &&
1488 val >= (int64_t)IMM_LOW + (int64_t)IMM_LOW * (int64_t)IMM_MULT) {
1489 Tmp1 = MakeReg(MVT::i64);
1490 BuildMI(BB, Alpha::LDAH, 2, Tmp1).addImm(getUpper16(val)).addReg(Alpha::R31);
1491 BuildMI(BB, Alpha::LDA, 2, Result).addImm(getLower16(val)).addReg(Tmp1);
1492 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001493 else {
1494 MachineConstantPool *CP = BB->getParent()->getConstantPool();
1495 ConstantUInt *C = ConstantUInt::get(Type::getPrimitiveType(Type::ULongTyID) , val);
1496 unsigned CPI = CP->getConstantPoolIndex(C);
1497 AlphaLowering.restoreGP(BB);
1498 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(CPI);
1499 }
1500 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001501 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001502 }
1503
1504 return 0;
1505}
1506
1507void ISel::Select(SDOperand N) {
1508 unsigned Tmp1, Tmp2, Opc;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001509 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001510
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001511 // FIXME: Disable for our current expansion model!
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001512 if (/*!N->hasOneUse() &&*/ !ExprMap.insert(std::make_pair(N, notIn)).second)
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001513 return; // Already selected.
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001514
1515 SDNode *Node = N.Val;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001516
Andrew Lenharth760270d2005-02-07 23:02:23 +00001517 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001518
1519 default:
1520 Node->dump(); std::cerr << "\n";
1521 assert(0 && "Node not handled yet!");
1522
1523 case ISD::BRCOND: {
Andrew Lenharth445171a2005-02-08 00:40:03 +00001524 SelectBranchCC(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001525 return;
1526 }
1527
1528 case ISD::BR: {
1529 MachineBasicBlock *Dest =
1530 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
1531
1532 Select(N.getOperand(0));
1533 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
1534 return;
1535 }
1536
1537 case ISD::ImplicitDef:
1538 Select(N.getOperand(0));
1539 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
1540 return;
1541
1542 case ISD::EntryToken: return; // Noop
1543
1544 case ISD::TokenFactor:
1545 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
1546 Select(Node->getOperand(i));
1547
1548 //N.Val->dump(); std::cerr << "\n";
1549 //assert(0 && "Node not handled yet!");
1550
1551 return;
1552
1553 case ISD::CopyToReg:
1554 Select(N.getOperand(0));
1555 Tmp1 = SelectExpr(N.getOperand(1));
1556 Tmp2 = cast<RegSDNode>(N)->getReg();
1557
1558 if (Tmp1 != Tmp2) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001559 if (N.getOperand(1).getValueType() == MVT::f64 ||
1560 N.getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth29219162005-02-07 06:31:44 +00001561 BuildMI(BB, Alpha::CPYS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
1562 else
1563 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001564 }
1565 return;
1566
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001567 case ISD::RET:
1568 switch (N.getNumOperands()) {
1569 default:
1570 std::cerr << N.getNumOperands() << "\n";
1571 for (unsigned i = 0; i < N.getNumOperands(); ++i)
1572 std::cerr << N.getOperand(i).getValueType() << "\n";
1573 Node->dump();
1574 assert(0 && "Unknown return instruction!");
1575 case 2:
1576 Select(N.getOperand(0));
1577 Tmp1 = SelectExpr(N.getOperand(1));
1578 switch (N.getOperand(1).getValueType()) {
1579 default: Node->dump();
1580 assert(0 && "All other types should have been promoted!!");
1581 case MVT::f64:
1582 case MVT::f32:
1583 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
1584 break;
1585 case MVT::i32:
1586 case MVT::i64:
1587 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
1588 break;
1589 }
1590 break;
1591 case 1:
1592 Select(N.getOperand(0));
1593 break;
1594 }
1595 //Tmp2 = AlphaLowering.getRetAddr();
1596 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
1597 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
1598 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001599
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001600 case ISD::TRUNCSTORE:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001601 case ISD::STORE:
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001602 {
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001603 SDOperand Chain = N.getOperand(0);
1604 SDOperand Value = N.getOperand(1);
1605 SDOperand Address = N.getOperand(2);
1606 Select(Chain);
1607
1608 Tmp1 = SelectExpr(Value); //value
Andrew Lenharth760270d2005-02-07 23:02:23 +00001609
1610 if (opcode == ISD::STORE) {
1611 switch(Value.getValueType()) {
1612 default: assert(0 && "unknown Type in store");
1613 case MVT::i64: Opc = Alpha::STQ; break;
1614 case MVT::f64: Opc = Alpha::STT; break;
1615 case MVT::f32: Opc = Alpha::STS; break;
1616 }
1617 } else { //ISD::TRUNCSTORE
1618 switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
1619 default: assert(0 && "unknown Type in store");
1620 case MVT::i1: //FIXME: DAG does not promote this load
1621 case MVT::i8: Opc = Alpha::STB; break;
1622 case MVT::i16: Opc = Alpha::STW; break;
1623 case MVT::i32: Opc = Alpha::STL; break;
1624 }
Andrew Lenharth65838902005-02-06 16:22:15 +00001625 }
Andrew Lenharth760270d2005-02-07 23:02:23 +00001626
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001627 if (Address.getOpcode() == ISD::GlobalAddress)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001628 {
1629 AlphaLowering.restoreGP(BB);
1630 Opc = GetSymVersion(Opc);
1631 BuildMI(BB, Opc, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1632 }
Andrew Lenharth05380342005-02-07 05:07:00 +00001633 else if(Address.getOpcode() == ISD::FrameIndex)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001634 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001635 BuildMI(BB, Opc, 3).addReg(Tmp1)
1636 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1637 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001638 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001639 else
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001640 {
1641 long offset;
1642 SelectAddr(Address, Tmp2, offset);
1643 BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
1644 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001645 return;
1646 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001647
1648 case ISD::EXTLOAD:
1649 case ISD::SEXTLOAD:
1650 case ISD::ZEXTLOAD:
1651 case ISD::LOAD:
1652 case ISD::CopyFromReg:
1653 case ISD::CALL:
Andrew Lenharth032f2352005-02-22 21:59:48 +00001654 case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001655 ExprMap.erase(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001656 SelectExpr(N);
1657 return;
1658
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001659 case ISD::ADJCALLSTACKDOWN:
1660 case ISD::ADJCALLSTACKUP:
1661 Select(N.getOperand(0));
1662 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1663
1664 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
1665 Alpha::ADJUSTSTACKUP;
1666 BuildMI(BB, Opc, 1).addImm(Tmp1);
1667 return;
1668 }
1669 assert(0 && "Should not be reached!");
1670}
1671
1672
1673/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
1674/// into a machine code representation using pattern matching and a machine
1675/// description file.
1676///
1677FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
1678 return new ISel(TM);
1679}