blob: 7242f8f1fdb4a246d8dc76c7472f5916c7a7788d [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 Lenharth95762122005-03-31 21:24:06 +000030#include "llvm/Support/CommandLine.h"
Andrew Lenharth304d0f32005-01-22 23:41:55 +000031#include <set>
Andrew Lenharth684f2292005-01-30 00:35:27 +000032#include <algorithm>
Andrew Lenharth304d0f32005-01-22 23:41:55 +000033using namespace llvm;
34
Andrew Lenharth95762122005-03-31 21:24:06 +000035namespace llvm {
36 cl::opt<bool> EnableAlphaIDIV("enable-alpha-intfpdiv",
37 cl::desc("Use the FP div instruction for integer div when possible"),
38 cl::Hidden);
39 cl::opt<bool> EnableAlpha("enable-alpha-ftoi",
Andrew Lenharth5e99dd92005-03-31 22:02:25 +000040 cl::desc("Enable use of ftoi* and itof* instructions (ev6 and higher)"),
Andrew Lenharth95762122005-03-31 21:24:06 +000041 cl::Hidden);
42}
43
Andrew Lenharth304d0f32005-01-22 23:41:55 +000044//===----------------------------------------------------------------------===//
45// AlphaTargetLowering - Alpha Implementation of the TargetLowering interface
46namespace {
47 class AlphaTargetLowering : public TargetLowering {
48 int VarArgsFrameIndex; // FrameIndex for start of varargs area.
49 unsigned GP; //GOT vreg
50 public:
51 AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) {
52 // Set up the TargetLowering object.
Andrew Lenharth3d65d312005-01-27 03:49:45 +000053 //I am having problems with shr n ubyte 1
Andrew Lenharth879ef222005-02-02 17:00:21 +000054 setShiftAmountType(MVT::i64);
55 setSetCCResultType(MVT::i64);
Andrew Lenharth3d65d312005-01-27 03:49:45 +000056
Andrew Lenharth304d0f32005-01-22 23:41:55 +000057 addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass);
58 addRegisterClass(MVT::f64, Alpha::FPRCRegisterClass);
Andrew Lenharth3d65d312005-01-27 03:49:45 +000059 addRegisterClass(MVT::f32, Alpha::FPRCRegisterClass);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000060
Andrew Lenharthd2bb9602005-01-27 07:50:35 +000061 setOperationAction(ISD::EXTLOAD , MVT::i1 , Promote);
Andrew Lenharth33819132005-03-04 20:09:23 +000062 setOperationAction(ISD::EXTLOAD , MVT::f32 , Promote);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000063
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +000064 setOperationAction(ISD::ZEXTLOAD , MVT::i1 , Expand);
Andrew Lenharth304d0f32005-01-22 23:41:55 +000065 setOperationAction(ISD::ZEXTLOAD , MVT::i32 , Expand);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000066
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +000067 setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand);
Andrew Lenharth304d0f32005-01-22 23:41:55 +000068 setOperationAction(ISD::SEXTLOAD , MVT::i8 , Expand);
69 setOperationAction(ISD::SEXTLOAD , MVT::i16 , Expand);
70
Andrew Lenharth9818c052005-02-05 13:19:12 +000071 setOperationAction(ISD::SREM , MVT::f32 , Expand);
72 setOperationAction(ISD::SREM , MVT::f64 , Expand);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +000073
Andrew Lenharth8d163d22005-02-02 05:49:42 +000074 setOperationAction(ISD::MEMMOVE , MVT::Other, Expand);
Andrew Lenharth9818c052005-02-05 13:19:12 +000075 setOperationAction(ISD::MEMSET , MVT::Other, Expand);
76 setOperationAction(ISD::MEMCPY , MVT::Other, Expand);
77
Chris Lattner43fdea02005-04-02 05:03:24 +000078 // We don't support these yet.
79 setOperationAction(ISD::FNEG , MVT::f64 , Expand);
80 setOperationAction(ISD::FABS , MVT::f64 , Expand);
81
Andrew Lenharth33819132005-03-04 20:09:23 +000082 //Doesn't work yet
Andrew Lenharth572af902005-02-14 05:41:43 +000083 setOperationAction(ISD::SETCC , MVT::f32, Promote);
84
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000085 computeRegisterProperties();
Andrew Lenharth304d0f32005-01-22 23:41:55 +000086
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000087 addLegalFPImmediate(+0.0); //F31
88 addLegalFPImmediate(-0.0); //-F31
Andrew Lenharth304d0f32005-01-22 23:41:55 +000089 }
90
91 /// LowerArguments - This hook must be implemented to indicate how we should
92 /// lower the arguments for the specified function, into the specified DAG.
93 virtual std::vector<SDOperand>
94 LowerArguments(Function &F, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000095
Andrew Lenharth304d0f32005-01-22 23:41:55 +000096 /// LowerCallTo - This hook lowers an abstract call to a function into an
97 /// actual call.
98 virtual std::pair<SDOperand, SDOperand>
Nate Begeman8e21e712005-03-26 01:29:23 +000099 LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
100 SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000101
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000102 virtual std::pair<SDOperand, SDOperand>
103 LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000104
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000105 virtual std::pair<SDOperand,SDOperand>
106 LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
107 const Type *ArgTy, SelectionDAG &DAG);
108
109 virtual std::pair<SDOperand, SDOperand>
110 LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
111 SelectionDAG &DAG);
112
113 void restoreGP(MachineBasicBlock* BB)
114 {
115 BuildMI(BB, Alpha::BIS, 2, Alpha::R29).addReg(GP).addReg(GP);
116 }
117 };
118}
119
120//http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PY8AC-TET1_html/callCH3.html#BLOCK21
121
122//For now, just use variable size stack frame format
123
124//In a standard call, the first six items are passed in registers $16
125//- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
126//of argument-to-register correspondence.) The remaining items are
127//collected in a memory argument list that is a naturally aligned
128//array of quadwords. In a standard call, this list, if present, must
129//be passed at 0(SP).
130//7 ... n 0(SP) ... (n-7)*8(SP)
131
132std::vector<SDOperand>
133AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
134{
135 std::vector<SDOperand> ArgValues;
136
137 // //#define FP $15
138 // //#define RA $26
139 // //#define PV $27
140 // //#define GP $29
141 // //#define SP $30
142
143 // assert(0 && "TODO");
144 MachineFunction &MF = DAG.getMachineFunction();
Andrew Lenharth05380342005-02-07 05:07:00 +0000145 MachineFrameInfo*MFI = MF.getFrameInfo();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000146
147 GP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
148 MachineBasicBlock& BB = MF.front();
149
150 //Handle the return address
151 //BuildMI(&BB, Alpha::IDEF, 0, Alpha::R26);
152
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000153 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
154 Alpha::R19, Alpha::R20, Alpha::R21};
155 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
156 Alpha::F19, Alpha::F20, Alpha::F21};
Andrew Lenharth2c9e38c2005-02-06 21:07:31 +0000157 unsigned argVreg[6];
158 unsigned argPreg[6];
159 unsigned argOpc[6];
160
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000161 int count = 0;
Andrew Lenharth2c9e38c2005-02-06 21:07:31 +0000162
Chris Lattnere4d5c442005-03-15 04:54:21 +0000163 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000164 {
165 SDOperand newroot, argt;
166 if (count < 6) {
167 switch (getValueType(I->getType())) {
168 default:
169 std::cerr << "Unknown Type " << getValueType(I->getType()) << "\n";
170 abort();
171 case MVT::f64:
172 case MVT::f32:
173 BuildMI(&BB, Alpha::IDEF, 0, args_float[count]);
174 argVreg[count] =
175 MF.getSSARegMap()->createVirtualRegister(
Andrew Lenharth032f2352005-02-22 21:59:48 +0000176 getRegClassFor(getValueType(I->getType())));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000177 argPreg[count] = args_float[count];
178 argOpc[count] = Alpha::CPYS;
179 argt = newroot = DAG.getCopyFromReg(argVreg[count],
180 getValueType(I->getType()),
181 DAG.getRoot());
182 break;
183 case MVT::i1:
184 case MVT::i8:
185 case MVT::i16:
186 case MVT::i32:
187 case MVT::i64:
188 BuildMI(&BB, Alpha::IDEF, 0, args_int[count]);
189 argVreg[count] =
190 MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
191 argPreg[count] = args_int[count];
192 argOpc[count] = Alpha::BIS;
193 argt = newroot =
194 DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot());
195 if (getValueType(I->getType()) != MVT::i64)
196 argt =
197 DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()), newroot);
198 break;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000199 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000200 } else { //more args
201 // Create the frame index object for this incoming parameter...
202 int FI = MFI->CreateFixedObject(8, 8 * (count - 6));
203
204 // Create the SelectionDAG nodes corresponding to a load
205 //from this parameter
206 SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
207 argt = newroot = DAG.getLoad(getValueType(I->getType()),
208 DAG.getEntryNode(), FIN);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000209 }
Andrew Lenharth032f2352005-02-22 21:59:48 +0000210 ++count;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000211 DAG.setRoot(newroot.getValue(1));
212 ArgValues.push_back(argt);
213 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000214
215 BuildMI(&BB, Alpha::IDEF, 0, Alpha::R29);
216 BuildMI(&BB, Alpha::BIS, 2, GP).addReg(Alpha::R29).addReg(Alpha::R29);
Andrew Lenharth032f2352005-02-22 21:59:48 +0000217 for (int i = 0; i < count && i < 6; ++i) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000218 BuildMI(&BB, argOpc[i], 2,
219 argVreg[i]).addReg(argPreg[i]).addReg(argPreg[i]);
220 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000221
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000222 return ArgValues;
223}
224
225std::pair<SDOperand, SDOperand>
226AlphaTargetLowering::LowerCallTo(SDOperand Chain,
Nate Begeman8e21e712005-03-26 01:29:23 +0000227 const Type *RetTy, bool isVarArg,
228 SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000229 int NumBytes = 0;
Andrew Lenharth684f2292005-01-30 00:35:27 +0000230 if (Args.size() > 6)
231 NumBytes = (Args.size() - 6) * 8;
232
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000233 Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
234 DAG.getConstant(NumBytes, getPointerTy()));
235 std::vector<SDOperand> args_to_use;
236 for (unsigned i = 0, e = Args.size(); i != e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000237 {
238 switch (getValueType(Args[i].second)) {
239 default: assert(0 && "Unexpected ValueType for argument!");
240 case MVT::i1:
241 case MVT::i8:
242 case MVT::i16:
243 case MVT::i32:
244 // Promote the integer to 64 bits. If the input type is signed use a
245 // sign extend, otherwise use a zero extend.
246 if (Args[i].second->isSigned())
247 Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first);
248 else
249 Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first);
250 break;
251 case MVT::i64:
252 case MVT::f64:
253 case MVT::f32:
254 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000255 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000256 args_to_use.push_back(Args[i].first);
257 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000258
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000259 std::vector<MVT::ValueType> RetVals;
260 MVT::ValueType RetTyVT = getValueType(RetTy);
261 if (RetTyVT != MVT::isVoid)
262 RetVals.push_back(RetTyVT);
263 RetVals.push_back(MVT::Other);
264
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000265 SDOperand TheCall = SDOperand(DAG.getCall(RetVals,
266 Chain, Callee, args_to_use), 0);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000267 Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
268 Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
269 DAG.getConstant(NumBytes, getPointerTy()));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000270 return std::make_pair(TheCall, Chain);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000271}
272
273std::pair<SDOperand, SDOperand>
274AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
275 //vastart just returns the address of the VarArgsFrameIndex slot.
276 return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain);
277}
278
279std::pair<SDOperand,SDOperand> AlphaTargetLowering::
280LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000281 const Type *ArgTy, SelectionDAG &DAG) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000282 abort();
283}
284
285
286std::pair<SDOperand, SDOperand> AlphaTargetLowering::
287LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
288 SelectionDAG &DAG) {
289 abort();
290}
291
292
293
294
295
296namespace {
297
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000298//===--------------------------------------------------------------------===//
299/// ISel - Alpha specific code to select Alpha machine instructions for
300/// SelectionDAG operations.
301//===--------------------------------------------------------------------===//
302class ISel : public SelectionDAGISel {
303
304 /// AlphaLowering - This object fully describes how to lower LLVM code to an
305 /// Alpha-specific SelectionDAG.
306 AlphaTargetLowering AlphaLowering;
307
308
309 /// ExprMap - As shared expressions are codegen'd, we keep track of which
310 /// vreg the value is produced in, so we only emit one copy of each compiled
311 /// tree.
312 static const unsigned notIn = (unsigned)(-1);
313 std::map<SDOperand, unsigned> ExprMap;
314
315 //CCInvMap sometimes (SetNE) we have the inverse CC code for free
316 std::map<SDOperand, unsigned> CCInvMap;
317
318public:
319 ISel(TargetMachine &TM) : SelectionDAGISel(AlphaLowering), AlphaLowering(TM)
320 {}
321
322 /// InstructionSelectBasicBlock - This callback is invoked by
323 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
324 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000325 DEBUG(BB->dump());
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000326 // Codegen the basic block.
327 Select(DAG.getRoot());
328
329 // Clear state used for selection.
330 ExprMap.clear();
331 CCInvMap.clear();
332 }
333
334 unsigned SelectExpr(SDOperand N);
335 unsigned SelectExprFP(SDOperand N, unsigned Result);
336 void Select(SDOperand N);
337
338 void SelectAddr(SDOperand N, unsigned& Reg, long& offset);
339 void SelectBranchCC(SDOperand N);
340};
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000341}
342
Andrew Lenharthe87f6c32005-03-11 17:48:05 +0000343//These describe LDAx
Andrew Lenharthc0513832005-03-29 19:24:04 +0000344static const int IMM_LOW = -32768;
345static const int IMM_HIGH = 32767;
Andrew Lenharthe87f6c32005-03-11 17:48:05 +0000346static const int IMM_MULT = 65536;
347
348static long getUpper16(long l)
349{
350 long y = l / IMM_MULT;
351 if (l % IMM_MULT > IMM_HIGH)
352 ++y;
353 return y;
354}
355
356static long getLower16(long l)
357{
358 long h = getUpper16(l);
359 return l - h * IMM_MULT;
360}
361
Andrew Lenharth65838902005-02-06 16:22:15 +0000362static unsigned GetSymVersion(unsigned opcode)
363{
364 switch (opcode) {
365 default: assert(0 && "unknown load or store"); return 0;
366 case Alpha::LDQ: return Alpha::LDQ_SYM;
367 case Alpha::LDS: return Alpha::LDS_SYM;
368 case Alpha::LDT: return Alpha::LDT_SYM;
369 case Alpha::LDL: return Alpha::LDL_SYM;
370 case Alpha::LDBU: return Alpha::LDBU_SYM;
371 case Alpha::LDWU: return Alpha::LDWU_SYM;
372 case Alpha::LDW: return Alpha::LDW_SYM;
373 case Alpha::LDB: return Alpha::LDB_SYM;
374 case Alpha::STQ: return Alpha::STQ_SYM;
375 case Alpha::STS: return Alpha::STS_SYM;
376 case Alpha::STT: return Alpha::STT_SYM;
377 case Alpha::STL: return Alpha::STL_SYM;
378 case Alpha::STW: return Alpha::STW_SYM;
379 case Alpha::STB: return Alpha::STB_SYM;
380 }
381}
382
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000383//Check to see if the load is a constant offset from a base register
384void ISel::SelectAddr(SDOperand N, unsigned& Reg, long& offset)
385{
386 unsigned opcode = N.getOpcode();
387 if (opcode == ISD::ADD) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000388 if(N.getOperand(1).getOpcode() == ISD::Constant &&
389 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767)
390 { //Normal imm add
391 Reg = SelectExpr(N.getOperand(0));
392 offset = cast<ConstantSDNode>(N.getOperand(1))->getValue();
393 return;
394 }
395 else if(N.getOperand(0).getOpcode() == ISD::Constant &&
396 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 32767)
397 {
398 Reg = SelectExpr(N.getOperand(1));
399 offset = cast<ConstantSDNode>(N.getOperand(0))->getValue();
400 return;
401 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000402 }
403 Reg = SelectExpr(N);
404 offset = 0;
405 return;
406}
407
Andrew Lenharth445171a2005-02-08 00:40:03 +0000408void ISel::SelectBranchCC(SDOperand N)
409{
410 assert(N.getOpcode() == ISD::BRCOND && "Not a BranchCC???");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000411 MachineBasicBlock *Dest =
412 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
413 unsigned Opc = Alpha::WTF;
414
Andrew Lenharth445171a2005-02-08 00:40:03 +0000415 Select(N.getOperand(0)); //chain
416 SDOperand CC = N.getOperand(1);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000417
Andrew Lenharth445171a2005-02-08 00:40:03 +0000418 if (CC.getOpcode() == ISD::SETCC)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000419 {
420 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
421 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
422 //Dropping the CC is only useful if we are comparing to 0
423 bool isZero0 = false;
424 bool isZero1 = false;
425 bool isNE = false;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000426
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000427 if(SetCC->getOperand(0).getOpcode() == ISD::Constant &&
428 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0)
429 isZero0 = true;
430 if(SetCC->getOperand(1).getOpcode() == ISD::Constant &&
431 cast<ConstantSDNode>(SetCC->getOperand(1))->getValue() == 0)
432 isZero1 = true;
433 if(SetCC->getCondition() == ISD::SETNE)
434 isNE = true;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000435
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000436 if (isZero0) {
Andrew Lenharth445171a2005-02-08 00:40:03 +0000437 switch (SetCC->getCondition()) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000438 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
439 case ISD::SETEQ: Opc = Alpha::BEQ; break;
440 case ISD::SETLT: Opc = Alpha::BGT; break;
441 case ISD::SETLE: Opc = Alpha::BGE; break;
442 case ISD::SETGT: Opc = Alpha::BLT; break;
443 case ISD::SETGE: Opc = Alpha::BLE; break;
444 case ISD::SETULT: Opc = Alpha::BNE; break;
445 case ISD::SETUGT: assert(0 && "0 > (unsigned) x is never true"); break;
446 case ISD::SETULE: assert(0 && "0 <= (unsigned) x is always true"); break;
447 case ISD::SETUGE: Opc = Alpha::BEQ; break; //Technically you could have this CC
448 case ISD::SETNE: Opc = Alpha::BNE; break;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000449 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000450 unsigned Tmp1 = SelectExpr(SetCC->getOperand(1));
451 BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest);
452 return;
453 } else if (isZero1) {
454 switch (SetCC->getCondition()) {
455 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
456 case ISD::SETEQ: Opc = Alpha::BEQ; break;
457 case ISD::SETLT: Opc = Alpha::BLT; break;
458 case ISD::SETLE: Opc = Alpha::BLE; break;
459 case ISD::SETGT: Opc = Alpha::BGT; break;
460 case ISD::SETGE: Opc = Alpha::BGE; break;
461 case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break;
462 case ISD::SETUGT: Opc = Alpha::BNE; break;
463 case ISD::SETULE: Opc = Alpha::BEQ; break; //Technically you could have this CC
464 case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break;
465 case ISD::SETNE: Opc = Alpha::BNE; break;
466 }
467 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
468 BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest);
469 return;
470 } else {
471 unsigned Tmp1 = SelectExpr(CC);
472 if (isNE)
473 BuildMI(BB, Alpha::BEQ, 2).addReg(CCInvMap[CC]).addMBB(Dest);
474 else
475 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000476 return;
477 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000478 } else { //FP
479 //Any comparison between 2 values should be codegened as an folded branch, as moving
480 //CC to the integer register is very expensive
481 //for a cmp b: c = a - b;
482 //a = b: c = 0
483 //a < b: c < 0
484 //a > b: c > 0
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000485
486 bool invTest = false;
487 unsigned Tmp3;
488
489 ConstantFPSDNode *CN;
490 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
491 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
492 Tmp3 = SelectExpr(SetCC->getOperand(0));
493 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
494 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
495 {
496 Tmp3 = SelectExpr(SetCC->getOperand(1));
497 invTest = true;
498 }
499 else
500 {
501 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
502 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
503 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
504 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
505 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
506 .addReg(Tmp1).addReg(Tmp2);
507 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000508
509 switch (SetCC->getCondition()) {
510 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000511 case ISD::SETEQ: Opc = invTest ? Alpha::FBNE : Alpha::FBEQ; break;
512 case ISD::SETLT: Opc = invTest ? Alpha::FBGT : Alpha::FBLT; break;
513 case ISD::SETLE: Opc = invTest ? Alpha::FBGE : Alpha::FBLE; break;
514 case ISD::SETGT: Opc = invTest ? Alpha::FBLT : Alpha::FBGT; break;
515 case ISD::SETGE: Opc = invTest ? Alpha::FBLE : Alpha::FBGE; break;
516 case ISD::SETNE: Opc = invTest ? Alpha::FBEQ : Alpha::FBNE; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000517 }
518 BuildMI(BB, Opc, 2).addReg(Tmp3).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000519 return;
520 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000521 abort(); //Should never be reached
522 } else {
523 //Giveup and do the stupid thing
524 unsigned Tmp1 = SelectExpr(CC);
525 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
526 return;
527 }
Andrew Lenharth445171a2005-02-08 00:40:03 +0000528 abort(); //Should never be reached
529}
530
Andrew Lenharth40831c52005-01-28 06:57:18 +0000531unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
532{
533 unsigned Tmp1, Tmp2, Tmp3;
534 unsigned Opc = 0;
535 SDNode *Node = N.Val;
536 MVT::ValueType DestType = N.getValueType();
537 unsigned opcode = N.getOpcode();
538
539 switch (opcode) {
540 default:
541 Node->dump();
542 assert(0 && "Node not handled!\n");
Andrew Lenharth2c594352005-01-29 15:42:07 +0000543
Andrew Lenharth9818c052005-02-05 13:19:12 +0000544 case ISD::SELECT:
545 {
Andrew Lenharth45859692005-03-03 21:47:53 +0000546 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
547 unsigned TV = SelectExpr(N.getOperand(1)); //Use if TRUE
548 unsigned FV = SelectExpr(N.getOperand(2)); //Use if FALSE
549
550 SDOperand CC = N.getOperand(0);
551 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
552
553 if (CC.getOpcode() == ISD::SETCC &&
554 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
555 { //FP Setcc -> Select yay!
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000556
557
Andrew Lenharth45859692005-03-03 21:47:53 +0000558 //for a cmp b: c = a - b;
559 //a = b: c = 0
560 //a < b: c < 0
561 //a > b: c > 0
562
563 bool invTest = false;
564 unsigned Tmp3;
565
566 ConstantFPSDNode *CN;
567 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
568 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
569 Tmp3 = SelectExpr(SetCC->getOperand(0));
570 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
571 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
572 {
573 Tmp3 = SelectExpr(SetCC->getOperand(1));
574 invTest = true;
575 }
576 else
577 {
578 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
579 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
580 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
581 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
582 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
583 .addReg(Tmp1).addReg(Tmp2);
584 }
585
586 switch (SetCC->getCondition()) {
587 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
588 case ISD::SETEQ: Opc = invTest ? Alpha::FCMOVNE : Alpha::FCMOVEQ; break;
589 case ISD::SETLT: Opc = invTest ? Alpha::FCMOVGT : Alpha::FCMOVLT; break;
590 case ISD::SETLE: Opc = invTest ? Alpha::FCMOVGE : Alpha::FCMOVLE; break;
591 case ISD::SETGT: Opc = invTest ? Alpha::FCMOVLT : Alpha::FCMOVGT; break;
592 case ISD::SETGE: Opc = invTest ? Alpha::FCMOVLE : Alpha::FCMOVGE; break;
593 case ISD::SETNE: Opc = invTest ? Alpha::FCMOVEQ : Alpha::FCMOVNE; break;
594 }
Andrew Lenharth33819132005-03-04 20:09:23 +0000595 BuildMI(BB, Opc, 3, Result).addReg(FV).addReg(TV).addReg(Tmp3);
Andrew Lenharth45859692005-03-03 21:47:53 +0000596 return Result;
597 }
598 else
599 {
600 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
601 // Spill the cond to memory and reload it from there.
602 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
603 MachineFunction *F = BB->getParent();
604 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
605 unsigned Tmp4 = MakeReg(MVT::f64);
606 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdx).addReg(Alpha::F31);
607 BuildMI(BB, Alpha::LDT, 2, Tmp4).addFrameIndex(FrameIdx).addReg(Alpha::F31);
608 //now ideally, we don't have to do anything to the flag...
609 // Get the condition into the zero flag.
610 BuildMI(BB, Alpha::FCMOVEQ, 3, Result).addReg(TV).addReg(FV).addReg(Tmp4);
611 return Result;
612 }
Andrew Lenharth9818c052005-02-05 13:19:12 +0000613 }
614
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000615 case ISD::FP_ROUND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000616 assert (DestType == MVT::f32 &&
617 N.getOperand(0).getValueType() == MVT::f64 &&
618 "only f64 to f32 conversion supported here");
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000619 Tmp1 = SelectExpr(N.getOperand(0));
620 BuildMI(BB, Alpha::CVTTS, 1, Result).addReg(Tmp1);
621 return Result;
622
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000623 case ISD::FP_EXTEND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000624 assert (DestType == MVT::f64 &&
625 N.getOperand(0).getValueType() == MVT::f32 &&
626 "only f32 to f64 conversion supported here");
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000627 Tmp1 = SelectExpr(N.getOperand(0));
628 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
629 return Result;
630
Andrew Lenharth2c594352005-01-29 15:42:07 +0000631 case ISD::CopyFromReg:
632 {
633 // Make sure we generate both values.
634 if (Result != notIn)
635 ExprMap[N.getValue(1)] = notIn; // Generate the token
636 else
637 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
638
639 SDOperand Chain = N.getOperand(0);
640
641 Select(Chain);
642 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
643 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
644 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(r).addReg(r);
645 return Result;
646 }
647
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000648 case ISD::LOAD:
649 {
650 // Make sure we generate both values.
651 if (Result != notIn)
652 ExprMap[N.getValue(1)] = notIn; // Generate the token
653 else
654 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000655
Andrew Lenharth29219162005-02-07 06:31:44 +0000656 DestType = N.getValue(0).getValueType();
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000657
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000658 SDOperand Chain = N.getOperand(0);
659 SDOperand Address = N.getOperand(1);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000660 Select(Chain);
Andrew Lenharth65838902005-02-06 16:22:15 +0000661 Opc = DestType == MVT::f64 ? Alpha::LDT : Alpha::LDS;
662
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000663 if (Address.getOpcode() == ISD::GlobalAddress) {
664 AlphaLowering.restoreGP(BB);
665 Opc = GetSymVersion(Opc);
666 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
667 }
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000668 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000669 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +0000670 Opc = GetSymVersion(Opc);
Andrew Lenharth97127a12005-02-05 17:41:39 +0000671 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000672 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000673 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000674 BuildMI(BB, Opc, 2, Result)
675 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
676 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000677 } else {
678 long offset;
679 SelectAddr(Address, Tmp1, offset);
680 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
681 }
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000682 return Result;
683 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000684 case ISD::ConstantFP:
685 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
686 if (CN->isExactlyValue(+0.0)) {
687 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000688 } else if ( CN->isExactlyValue(-0.0)) {
689 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000690 } else {
691 abort();
692 }
693 }
694 return Result;
695
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +0000696 case ISD::SDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000697 case ISD::MUL:
698 case ISD::ADD:
699 case ISD::SUB:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000700 switch( opcode ) {
701 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
702 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
703 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
704 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
705 };
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000706
707 ConstantFPSDNode *CN;
708 if (opcode == ISD::SUB
709 && (CN = dyn_cast<ConstantFPSDNode>(N.getOperand(0)))
710 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
711 {
712 Tmp2 = SelectExpr(N.getOperand(1));
713 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp2).addReg(Tmp2);
714 } else {
715 Tmp1 = SelectExpr(N.getOperand(0));
716 Tmp2 = SelectExpr(N.getOperand(1));
717 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
718 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000719 return Result;
720
Andrew Lenharth2c594352005-01-29 15:42:07 +0000721 case ISD::EXTLOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000722 {
723 //include a conversion sequence for float loads to double
724 if (Result != notIn)
725 ExprMap[N.getValue(1)] = notIn; // Generate the token
726 else
727 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
728
Andrew Lenhartha549deb2005-02-07 05:33:15 +0000729 Tmp1 = MakeReg(MVT::f32);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000730
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000731 assert(cast<MVTSDNode>(Node)->getExtraValueType() == MVT::f32 &&
732 "EXTLOAD not from f32");
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000733 assert(Node->getValueType(0) == MVT::f64 && "EXTLOAD not to f64");
734
735 SDOperand Chain = N.getOperand(0);
736 SDOperand Address = N.getOperand(1);
737 Select(Chain);
738
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000739 if (Address.getOpcode() == ISD::GlobalAddress) {
740 AlphaLowering.restoreGP(BB);
741 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
742 }
743 else if (ConstantPoolSDNode *CP =
744 dyn_cast<ConstantPoolSDNode>(N.getOperand(1)))
745 {
746 AlphaLowering.restoreGP(BB);
747 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addConstantPoolIndex(CP->getIndex());
748 }
749 else if(Address.getOpcode() == ISD::FrameIndex) {
750 Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
Andrew Lenharth032f2352005-02-22 21:59:48 +0000751 BuildMI(BB, Alpha::LDS, 2, Tmp1)
752 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
753 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000754 } else {
755 long offset;
756 SelectAddr(Address, Tmp2, offset);
757 BuildMI(BB, Alpha::LDS, 1, Tmp1).addImm(offset).addReg(Tmp2);
758 }
Andrew Lenharth29219162005-02-07 06:31:44 +0000759 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000760 return Result;
761 }
Andrew Lenharth2c594352005-01-29 15:42:07 +0000762
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000763 case ISD::UINT_TO_FP:
764 case ISD::SINT_TO_FP:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000765 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000766 assert (N.getOperand(0).getValueType() == MVT::i64
767 && "only quads can be loaded from");
Andrew Lenharth40831c52005-01-28 06:57:18 +0000768 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000769 Tmp2 = MakeReg(MVT::f64);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000770
771 //The hard way:
772 // Spill the integer to memory and reload it from there.
773 unsigned Size = MVT::getSizeInBits(MVT::i64)/8;
774 MachineFunction *F = BB->getParent();
775 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, Size);
776
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000777 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdx).addReg(Alpha::F31);
778 BuildMI(BB, Alpha::LDT, 2, Tmp2).addFrameIndex(FrameIdx).addReg(Alpha::F31);
779 Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
780 BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000781
782 //The easy way: doesn't work
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000783 // //so these instructions are not supported on ev56
784 // Opc = DestType == MVT::f64 ? Alpha::ITOFT : Alpha::ITOFS;
785 // BuildMI(BB, Opc, 1, Tmp2).addReg(Tmp1);
786 // Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
787 // BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000788
Andrew Lenharth40831c52005-01-28 06:57:18 +0000789 return Result;
790 }
791 }
792 assert(0 && "should not get here");
793 return 0;
794}
795
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000796unsigned ISel::SelectExpr(SDOperand N) {
797 unsigned Result;
798 unsigned Tmp1, Tmp2, Tmp3;
799 unsigned Opc = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000800 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000801
802 SDNode *Node = N.Val;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000803 MVT::ValueType DestType = N.getValueType();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000804
805 unsigned &Reg = ExprMap[N];
806 if (Reg) return Reg;
807
808 if (N.getOpcode() != ISD::CALL)
809 Reg = Result = (N.getValueType() != MVT::Other) ?
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000810 MakeReg(N.getValueType()) : notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000811 else {
812 // If this is a call instruction, make sure to prepare ALL of the result
813 // values as well as the chain.
814 if (Node->getNumValues() == 1)
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000815 Reg = Result = notIn; // Void call, just a chain.
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000816 else {
817 Result = MakeReg(Node->getValueType(0));
818 ExprMap[N.getValue(0)] = Result;
819 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
820 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000821 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000822 }
823 }
824
Andrew Lenharth22088bb2005-02-02 15:05:33 +0000825 if (DestType == MVT::f64 || DestType == MVT::f32 ||
Andrew Lenharth06342c32005-02-07 06:21:37 +0000826 (
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000827 (opcode == ISD::LOAD || opcode == ISD::CopyFromReg ||
828 opcode == ISD::EXTLOAD) &&
829 (N.getValue(0).getValueType() == MVT::f32 ||
830 N.getValue(0).getValueType() == MVT::f64)
Andrew Lenharth06342c32005-02-07 06:21:37 +0000831 )
832 )
Andrew Lenharth40831c52005-01-28 06:57:18 +0000833 return SelectExprFP(N, Result);
834
835 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000836 default:
837 Node->dump();
838 assert(0 && "Node not handled!\n");
839
Andrew Lenharth032f2352005-02-22 21:59:48 +0000840 case ISD::DYNAMIC_STACKALLOC:
841 // Generate both result values.
Andrew Lenharth3a7118d2005-02-23 17:33:42 +0000842 if (Result != notIn)
843 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth032f2352005-02-22 21:59:48 +0000844 else
845 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
846
847 // FIXME: We are currently ignoring the requested alignment for handling
848 // greater than the stack alignment. This will need to be revisited at some
849 // point. Align = N.getOperand(2);
850
851 if (!isa<ConstantSDNode>(N.getOperand(2)) ||
852 cast<ConstantSDNode>(N.getOperand(2))->getValue() != 0) {
853 std::cerr << "Cannot allocate stack object with greater alignment than"
854 << " the stack alignment yet!";
855 abort();
856 }
857
858 Select(N.getOperand(0));
859 if (ConstantSDNode* CN = dyn_cast<ConstantSDNode>(N.getOperand(1)))
860 {
861 if (CN->getValue() < 32000)
862 {
863 BuildMI(BB, Alpha::LDA, 2, Alpha::R30)
864 .addImm(-CN->getValue()).addReg(Alpha::R30);
865 } else {
866 Tmp1 = SelectExpr(N.getOperand(1));
867 // Subtract size from stack pointer, thereby allocating some space.
868 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
869 }
870 } else {
871 Tmp1 = SelectExpr(N.getOperand(1));
872 // Subtract size from stack pointer, thereby allocating some space.
873 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
874 }
875
876 // Put a pointer to the space into the result register, by copying the stack
877 // pointer.
Andrew Lenharth7bc47022005-02-22 23:29:25 +0000878 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R30).addReg(Alpha::R30);
Andrew Lenharth032f2352005-02-22 21:59:48 +0000879 return Result;
880
Andrew Lenharth33819132005-03-04 20:09:23 +0000881// case ISD::ConstantPool:
882// Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
883// AlphaLowering.restoreGP(BB);
884// BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(Tmp1);
885// return Result;
Andrew Lenharth2c594352005-01-29 15:42:07 +0000886
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000887 case ISD::FrameIndex:
Andrew Lenharth032f2352005-02-22 21:59:48 +0000888 BuildMI(BB, Alpha::LDA, 2, Result)
889 .addFrameIndex(cast<FrameIndexSDNode>(N)->getIndex())
890 .addReg(Alpha::F31);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000891 return Result;
892
893 case ISD::EXTLOAD:
Andrew Lenharthf311e8b2005-02-07 05:18:02 +0000894 case ISD::ZEXTLOAD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000895 case ISD::SEXTLOAD:
Andrew Lenhartha549deb2005-02-07 05:33:15 +0000896 case ISD::LOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000897 {
898 // Make sure we generate both values.
899 if (Result != notIn)
900 ExprMap[N.getValue(1)] = notIn; // Generate the token
901 else
902 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000903
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000904 SDOperand Chain = N.getOperand(0);
905 SDOperand Address = N.getOperand(1);
906 Select(Chain);
907
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000908 assert(Node->getValueType(0) == MVT::i64 &&
909 "Unknown type to sign extend to.");
Andrew Lenharth03824012005-02-07 05:55:55 +0000910 if (opcode == ISD::LOAD)
911 Opc = Alpha::LDQ;
912 else
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000913 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
914 default: Node->dump(); assert(0 && "Bad sign extend!");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000915 case MVT::i32: Opc = Alpha::LDL;
916 assert(opcode != ISD::ZEXTLOAD && "Not sext"); break;
917 case MVT::i16: Opc = Alpha::LDWU;
918 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharthf311e8b2005-02-07 05:18:02 +0000919 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000920 case MVT::i8: Opc = Alpha::LDBU;
921 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000922 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000923
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000924 if (Address.getOpcode() == ISD::GlobalAddress) {
925 AlphaLowering.restoreGP(BB);
926 Opc = GetSymVersion(Opc);
927 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
928 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000929 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
930 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +0000931 Opc = GetSymVersion(Opc);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000932 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000933 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000934 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000935 BuildMI(BB, Opc, 2, Result)
936 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
937 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000938 } else {
939 long offset;
940 SelectAddr(Address, Tmp1, offset);
941 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
942 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000943 return Result;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000944 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000945
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000946 case ISD::GlobalAddress:
947 AlphaLowering.restoreGP(BB);
948 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
949 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
950 return Result;
951
952 case ISD::CALL:
953 {
954 Select(N.getOperand(0));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000955
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000956 // The chain for this call is now lowered.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000957 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), notIn));
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000958
959 //grab the arguments
960 std::vector<unsigned> argvregs;
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000961 //assert(Node->getNumOperands() < 8 && "Only 6 args supported");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000962 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000963 argvregs.push_back(SelectExpr(N.getOperand(i)));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000964
Andrew Lenharth684f2292005-01-30 00:35:27 +0000965 //in reg args
966 for(int i = 0, e = std::min(6, (int)argvregs.size()); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000967 {
968 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
969 Alpha::R19, Alpha::R20, Alpha::R21};
970 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
971 Alpha::F19, Alpha::F20, Alpha::F21};
972 switch(N.getOperand(i+2).getValueType()) {
973 default:
974 Node->dump();
975 N.getOperand(i).Val->dump();
976 std::cerr << "Type for " << i << " is: " <<
977 N.getOperand(i+2).getValueType() << "\n";
978 assert(0 && "Unknown value type for call");
979 case MVT::i1:
980 case MVT::i8:
981 case MVT::i16:
982 case MVT::i32:
983 case MVT::i64:
984 BuildMI(BB, Alpha::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
985 break;
986 case MVT::f32:
987 case MVT::f64:
988 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
989 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +0000990 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000991 }
Andrew Lenharth684f2292005-01-30 00:35:27 +0000992 //in mem args
993 for (int i = 6, e = argvregs.size(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000994 {
995 switch(N.getOperand(i+2).getValueType()) {
996 default:
997 Node->dump();
998 N.getOperand(i).Val->dump();
999 std::cerr << "Type for " << i << " is: " <<
1000 N.getOperand(i+2).getValueType() << "\n";
1001 assert(0 && "Unknown value type for call");
1002 case MVT::i1:
1003 case MVT::i8:
1004 case MVT::i16:
1005 case MVT::i32:
1006 case MVT::i64:
1007 BuildMI(BB, Alpha::STQ, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1008 break;
1009 case MVT::f32:
1010 BuildMI(BB, Alpha::STS, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1011 break;
1012 case MVT::f64:
1013 BuildMI(BB, Alpha::STT, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1014 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001015 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001016 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001017 //build the right kind of call
1018 if (GlobalAddressSDNode *GASD =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001019 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001020 {
Andrew Lenharth3e315922005-02-10 20:10:38 +00001021 //if (GASD->getGlobal()->isExternal()) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001022 //use safe calling convention
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001023 AlphaLowering.restoreGP(BB);
1024 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
Andrew Lenharth3e315922005-02-10 20:10:38 +00001025 //} else {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001026 //use PC relative branch call
Andrew Lenharth3e315922005-02-10 20:10:38 +00001027 //BuildMI(BB, Alpha::BSR, 1, Alpha::R26).addGlobalAddress(GASD->getGlobal(),true);
1028 //}
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001029 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001030 else if (ExternalSymbolSDNode *ESSDN =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001031 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001032 {
1033 AlphaLowering.restoreGP(BB);
Andrew Lenharthba05ad62005-03-30 18:22:52 +00001034 BuildMI(BB, Alpha::CALL, 1).addExternalSymbol(ESSDN->getSymbol(), true);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001035 } else {
1036 //no need to restore GP as we are doing an indirect call
1037 Tmp1 = SelectExpr(N.getOperand(1));
1038 BuildMI(BB, Alpha::BIS, 2, Alpha::R27).addReg(Tmp1).addReg(Tmp1);
1039 BuildMI(BB, Alpha::JSR, 2, Alpha::R26).addReg(Alpha::R27).addImm(0);
1040 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001041
1042 //push the result into a virtual register
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001043
1044 switch (Node->getValueType(0)) {
1045 default: Node->dump(); assert(0 && "Unknown value type for call result!");
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001046 case MVT::Other: return notIn;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001047 case MVT::i1:
1048 case MVT::i8:
1049 case MVT::i16:
1050 case MVT::i32:
1051 case MVT::i64:
1052 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
1053 break;
1054 case MVT::f32:
1055 case MVT::f64:
1056 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
1057 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001058 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001059 return Result+N.ResNo;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001060 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001061
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001062 case ISD::SIGN_EXTEND:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001063 abort();
1064
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001065 case ISD::SIGN_EXTEND_INREG:
1066 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001067 //do SDIV opt for all levels of ints
Andrew Lenharth5e99dd92005-03-31 22:02:25 +00001068 if (EnableAlphaIDIV && N.getOperand(0).getOpcode() == ISD::SDIV)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001069 {
1070 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1071 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1072 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1073 MachineFunction *F = BB->getParent();
1074 int FrameIdxL = F->getFrameInfo()->CreateStackObject(Size, 8);
1075 int FrameIdxR = F->getFrameInfo()->CreateStackObject(Size, 8);
1076 int FrameIdxF = F->getFrameInfo()->CreateStackObject(Size, 8);
1077 unsigned Tmp4 = MakeReg(MVT::f64);
1078 unsigned Tmp5 = MakeReg(MVT::f64);
1079 unsigned Tmp6 = MakeReg(MVT::f64);
1080 unsigned Tmp7 = MakeReg(MVT::f64);
1081 unsigned Tmp8 = MakeReg(MVT::f64);
1082 unsigned Tmp9 = MakeReg(MVT::f64);
1083
1084 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdxL).addReg(Alpha::F31);
Andrew Lenharthcc59ed52005-03-23 15:20:01 +00001085 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp2).addFrameIndex(FrameIdxR).addReg(Alpha::F31);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001086 BuildMI(BB, Alpha::LDT, 2, Tmp4).addFrameIndex(FrameIdxL).addReg(Alpha::F31);
1087 BuildMI(BB, Alpha::LDT, 2, Tmp5).addFrameIndex(FrameIdxR).addReg(Alpha::F31);
1088 BuildMI(BB, Alpha::CVTQT, 1, Tmp6).addReg(Tmp4);
1089 BuildMI(BB, Alpha::CVTQT, 1, Tmp7).addReg(Tmp5);
1090 BuildMI(BB, Alpha::DIVT, 2, Tmp8).addReg(Tmp6).addReg(Tmp7);
1091 BuildMI(BB, Alpha::CVTTQ, 1, Tmp9).addReg(Tmp8);
1092 BuildMI(BB, Alpha::STT, 3).addReg(Tmp9).addFrameIndex(FrameIdxF).addReg(Alpha::F31);
Andrew Lenharthcc59ed52005-03-23 15:20:01 +00001093 BuildMI(BB, Alpha::LDQ, 2, Result).addFrameIndex(FrameIdxF).addReg(Alpha::F31);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001094 return Result;
1095 }
1096
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001097 //Alpha has instructions for a bunch of signed 32 bit stuff
1098 if( dyn_cast<MVTSDNode>(Node)->getExtraValueType() == MVT::i32)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001099 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001100 switch (N.getOperand(0).getOpcode()) {
1101 case ISD::ADD:
1102 case ISD::SUB:
1103 case ISD::MUL:
1104 {
1105 bool isAdd = N.getOperand(0).getOpcode() == ISD::ADD;
1106 bool isMul = N.getOperand(0).getOpcode() == ISD::MUL;
1107 //FIXME: first check for Scaled Adds and Subs!
1108 if(N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1109 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() <= 255)
1110 { //Normal imm add/sub
1111 Opc = isAdd ? Alpha::ADDLi : (isMul ? Alpha::MULLi : Alpha::SUBLi);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001112 //if the value was really originally a i32, skip the up conversion
1113 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1114 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1115 ->getExtraValueType() == MVT::i32)
1116 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1117 else
1118 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001119 Tmp2 = cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue();
1120 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001121 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001122 else
1123 { //Normal add/sub
1124 Opc = isAdd ? Alpha::ADDL : (isMul ? Alpha::MULLi : Alpha::SUBL);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001125 //if the value was really originally a i32, skip the up conversion
1126 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1127 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1128 ->getExtraValueType() == MVT::i32)
1129 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1130 else
1131 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1132 //if the value was really originally a i32, skip the up conversion
1133 if (N.getOperand(0).getOperand(1).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1134 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(1).Val)
1135 ->getExtraValueType() == MVT::i32)
1136 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0));
1137 else
1138 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1139
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001140 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1141 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1142 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1143 }
1144 return Result;
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001145 }
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001146 case ISD::SEXTLOAD:
1147 //SelectionDag isn't deleting the signextend after sextloads
1148 Reg = Result = SelectExpr(N.getOperand(0));
1149 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001150 default: break; //Fall Though;
1151 }
1152 } //Every thing else fall though too, including unhandled opcodes above
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001153 Tmp1 = SelectExpr(N.getOperand(0));
1154 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001155 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001156 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001157 {
1158 default:
1159 Node->dump();
1160 assert(0 && "Sign Extend InReg not there yet");
1161 break;
1162 case MVT::i32:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001163 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001164 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001165 break;
1166 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001167 case MVT::i16:
1168 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
1169 break;
1170 case MVT::i8:
1171 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
1172 break;
Andrew Lenharthebce5042005-02-12 19:35:12 +00001173 case MVT::i1:
1174 Tmp2 = MakeReg(MVT::i64);
1175 BuildMI(BB, Alpha::ANDi, 2, Tmp2).addReg(Tmp1).addImm(1);
Andrew Lenharth7536eea2005-02-12 20:42:09 +00001176 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Alpha::F31).addReg(Tmp2);
Andrew Lenharthebce5042005-02-12 19:35:12 +00001177 break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001178 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001179 return Result;
1180 }
1181 case ISD::ZERO_EXTEND_INREG:
1182 {
1183 Tmp1 = SelectExpr(N.getOperand(0));
1184 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001185 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001186 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001187 {
1188 default:
1189 Node->dump();
1190 assert(0 && "Zero Extend InReg not there yet");
1191 break;
1192 case MVT::i32: Tmp2 = 0xf0; break;
1193 case MVT::i16: Tmp2 = 0xfc; break;
1194 case MVT::i8: Tmp2 = 0xfe; break;
1195 case MVT::i1: //handle this one special
1196 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
1197 return Result;
1198 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001199 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001200 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001201 }
1202
1203 case ISD::SETCC:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001204 {
1205 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
1206 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
1207 bool isConst1 = false;
1208 bool isConst2 = false;
1209 int dir;
Andrew Lenharth9818c052005-02-05 13:19:12 +00001210
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001211 //Tmp1 = SelectExpr(N.getOperand(0));
1212 if(N.getOperand(0).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001213 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1214 isConst1 = true;
1215 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001216 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1217 isConst2 = true;
1218
1219 switch (SetCC->getCondition()) {
1220 default: Node->dump(); assert(0 && "Unknown integer comparison!");
1221 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001222 case ISD::SETLT:
1223 Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
1224 case ISD::SETLE:
1225 Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
1226 case ISD::SETGT:
1227 Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
1228 case ISD::SETGE:
1229 Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
1230 case ISD::SETULT:
1231 Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
1232 case ISD::SETUGT:
1233 Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
1234 case ISD::SETULE:
1235 Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
1236 case ISD::SETUGE:
1237 Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001238 case ISD::SETNE: {//Handle this one special
1239 //std::cerr << "Alpha does not have a setne.\n";
1240 //abort();
1241 Tmp1 = SelectExpr(N.getOperand(0));
1242 Tmp2 = SelectExpr(N.getOperand(1));
1243 Tmp3 = MakeReg(MVT::i64);
1244 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth445171a2005-02-08 00:40:03 +00001245 //Remeber we have the Inv for this CC
1246 CCInvMap[N] = Tmp3;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001247 //and invert
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001248 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001249 return Result;
1250 }
1251 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001252 if (dir == 1) {
1253 Tmp1 = SelectExpr(N.getOperand(0));
1254 if (isConst2) {
1255 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1256 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1257 } else {
1258 Tmp2 = SelectExpr(N.getOperand(1));
1259 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1260 }
1261 } else if (dir == 2) {
1262 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001263 if (isConst1) {
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001264 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1265 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1266 } else {
1267 Tmp2 = SelectExpr(N.getOperand(0));
1268 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1269 }
1270 } else { //dir == 0
1271 if (isConst1) {
1272 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1273 Tmp2 = SelectExpr(N.getOperand(1));
1274 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
1275 } else if (isConst2) {
1276 Tmp1 = SelectExpr(N.getOperand(0));
1277 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1278 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
1279 } else {
1280 Tmp1 = SelectExpr(N.getOperand(0));
1281 Tmp2 = SelectExpr(N.getOperand(1));
1282 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
1283 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001284 }
1285 } else {
1286 //assert(SetCC->getOperand(0).getValueType() != MVT::f32 && "SetCC f32 should have been promoted");
1287 bool rev = false;
1288 bool inv = false;
1289
1290 switch (SetCC->getCondition()) {
1291 default: Node->dump(); assert(0 && "Unknown FP comparison!");
1292 case ISD::SETEQ: Opc = Alpha::CMPTEQ; break;
1293 case ISD::SETLT: Opc = Alpha::CMPTLT; break;
1294 case ISD::SETLE: Opc = Alpha::CMPTLE; break;
1295 case ISD::SETGT: Opc = Alpha::CMPTLT; rev = true; break;
1296 case ISD::SETGE: Opc = Alpha::CMPTLE; rev = true; break;
1297 case ISD::SETNE: Opc = Alpha::CMPTEQ; inv = true; break;
1298 }
1299
Andrew Lenharthca3d59b2005-03-14 19:23:45 +00001300 //FIXME: check for constant 0.0
1301 ConstantFPSDNode *CN;
1302 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
1303 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1304 Tmp1 = Alpha::F31;
1305 else
1306 Tmp1 = SelectExpr(N.getOperand(0));
1307
1308 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
1309 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1310 Tmp2 = Alpha::F31;
1311 else
1312 Tmp2 = SelectExpr(N.getOperand(1));
1313
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001314 //Can only compare doubles, and dag won't promote for me
1315 if (SetCC->getOperand(0).getValueType() == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001316 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001317 //assert(0 && "Setcc On float?\n");
1318 std::cerr << "Setcc on float!\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001319 Tmp3 = MakeReg(MVT::f64);
1320 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp1);
1321 Tmp1 = Tmp3;
1322 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001323 if (SetCC->getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001324 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001325 //assert (0 && "Setcc On float?\n");
1326 std::cerr << "Setcc on float!\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001327 Tmp3 = MakeReg(MVT::f64);
1328 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp2);
Andrew Lenharth572af902005-02-14 05:41:43 +00001329 Tmp2 = Tmp3;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001330 }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001331
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001332 if (rev) std::swap(Tmp1, Tmp2);
1333 Tmp3 = MakeReg(MVT::f64);
1334 //do the comparison
1335 BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
1336
1337 //now arrange for Result (int) to have a 1 or 0
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001338 unsigned Tmp4 = MakeReg(MVT::i64);
1339 BuildMI(BB, Alpha::ADDQi, 2, Tmp4).addReg(Alpha::R31).addImm(1);
1340 Opc = inv?Alpha::CMOVNEi_FP:Alpha::CMOVEQi_FP;
1341 BuildMI(BB, Opc, 3, Result).addReg(Tmp4).addImm(0).addReg(Tmp3);
Andrew Lenharthca3d59b2005-03-14 19:23:45 +00001342
1343// // Spill the FP to memory and reload it from there.
1344// unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1345// MachineFunction *F = BB->getParent();
1346// int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
1347// unsigned Tmp4 = MakeReg(MVT::f64);
1348// BuildMI(BB, Alpha::CVTTQ, 1, Tmp4).addReg(Tmp3);
1349// BuildMI(BB, Alpha::STT, 3).addReg(Tmp4).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1350// unsigned Tmp5 = MakeReg(MVT::i64);
1351// BuildMI(BB, Alpha::LDQ, 2, Tmp5).addFrameIndex(FrameIdx).addReg(Alpha::F31);
Andrew Lenharth9818c052005-02-05 13:19:12 +00001352
Andrew Lenharthca3d59b2005-03-14 19:23:45 +00001353// //now, set result based on Tmp5
1354// //Set Tmp6 if fp cmp was false
1355// unsigned Tmp6 = MakeReg(MVT::i64);
1356// BuildMI(BB, Alpha::CMPEQ, 2, Tmp6).addReg(Tmp5).addReg(Alpha::R31);
1357// //and invert
1358// BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp6).addReg(Alpha::R31);
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001359
1360 }
1361 // else
1362 // {
1363 // Node->dump();
1364 // assert(0 && "Not a setcc in setcc");
1365 // }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001366 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001367 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001368 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001369
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001370 case ISD::CopyFromReg:
1371 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001372 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001373 if (Result != notIn)
1374 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth40831c52005-01-28 06:57:18 +00001375 else
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001376 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth40831c52005-01-28 06:57:18 +00001377
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001378 SDOperand Chain = N.getOperand(0);
1379
1380 Select(Chain);
1381 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
1382 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
1383 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
1384 return Result;
1385 }
1386
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001387 //Most of the plain arithmetic and logic share the same form, and the same
1388 //constant immediate test
1389 case ISD::AND:
1390 case ISD::OR:
1391 case ISD::XOR:
1392 case ISD::SHL:
1393 case ISD::SRL:
Andrew Lenharth2c594352005-01-29 15:42:07 +00001394 case ISD::SRA:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001395 case ISD::MUL:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001396 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
1397 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001398 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001399 {
1400 switch(opcode) {
1401 case ISD::AND: Opc = Alpha::ANDi; break;
1402 case ISD::OR: Opc = Alpha::BISi; break;
1403 case ISD::XOR: Opc = Alpha::XORi; break;
1404 case ISD::SHL: Opc = Alpha::SLi; break;
1405 case ISD::SRL: Opc = Alpha::SRLi; break;
1406 case ISD::SRA: Opc = Alpha::SRAi; break;
1407 case ISD::MUL: Opc = Alpha::MULQi; break;
1408 };
1409 Tmp1 = SelectExpr(N.getOperand(0));
1410 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1411 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1412 } else {
1413 switch(opcode) {
1414 case ISD::AND: Opc = Alpha::AND; break;
1415 case ISD::OR: Opc = Alpha::BIS; break;
1416 case ISD::XOR: Opc = Alpha::XOR; break;
1417 case ISD::SHL: Opc = Alpha::SL; break;
1418 case ISD::SRL: Opc = Alpha::SRL; break;
1419 case ISD::SRA: Opc = Alpha::SRA; break;
1420 case ISD::MUL: Opc = Alpha::MULQ; break;
1421 };
1422 Tmp1 = SelectExpr(N.getOperand(0));
1423 Tmp2 = SelectExpr(N.getOperand(1));
1424 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1425 }
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001426 return Result;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001427
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001428 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001429 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001430 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001431 bool isAdd = opcode == ISD::ADD;
1432
1433 //FIXME: first check for Scaled Adds and Subs!
1434 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001435 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001436 { //Normal imm add/sub
1437 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
1438 Tmp1 = SelectExpr(N.getOperand(0));
1439 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1440 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1441 }
Andrew Lenharth40831c52005-01-28 06:57:18 +00001442 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001443 (cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767 ||
1444 (long)cast<ConstantSDNode>(N.getOperand(1))->getValue() >= -32767))
1445 { //LDA
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001446 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001447 Tmp2 = (long)cast<ConstantSDNode>(N.getOperand(1))->getValue();
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001448 if (!isAdd)
1449 Tmp2 = -Tmp2;
1450 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
1451 } else {
1452 //Normal add/sub
1453 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
1454 Tmp1 = SelectExpr(N.getOperand(0));
1455 Tmp2 = SelectExpr(N.getOperand(1));
1456 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1457 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001458 return Result;
1459 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001460
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001461 case ISD::SDIV:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001462 case ISD::UREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001463 case ISD::SREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001464 case ISD::UDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001465 //FIXME: alpha really doesn't support any of these operations,
1466 // the ops are expanded into special library calls with
1467 // special calling conventions
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001468 //Restore GP because it is a call after all...
Andrew Lenharth40831c52005-01-28 06:57:18 +00001469 switch(opcode) {
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001470 case ISD::UREM: Opc = Alpha::REMQU; break;
1471 case ISD::SREM: Opc = Alpha::REMQ; break;
1472 case ISD::UDIV: Opc = Alpha::DIVQU; break;
1473 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001474 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001475 Tmp1 = SelectExpr(N.getOperand(0));
1476 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth33819132005-03-04 20:09:23 +00001477 //set up regs explicitly (helps Reg alloc)
1478 BuildMI(BB, Alpha::BIS, 2, Alpha::R24).addReg(Tmp1).addReg(Tmp1);
1479 BuildMI(BB, Alpha::BIS, 2, Alpha::R25).addReg(Tmp2).addReg(Tmp2);
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001480 AlphaLowering.restoreGP(BB);
Andrew Lenharth33819132005-03-04 20:09:23 +00001481 BuildMI(BB, Opc, 2).addReg(Alpha::R24).addReg(Alpha::R25);
1482 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R27).addReg(Alpha::R27);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001483 return Result;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001484
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001485 case ISD::FP_TO_UINT:
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001486 case ISD::FP_TO_SINT:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001487 {
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001488 assert (DestType == MVT::i64 && "only quads can be loaded to");
1489 MVT::ValueType SrcType = N.getOperand(0).getValueType();
Andrew Lenharth03824012005-02-07 05:55:55 +00001490 assert (SrcType == MVT::f32 || SrcType == MVT::f64);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001491 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
1492
1493 //The hard way:
1494 // Spill the integer to memory and reload it from there.
1495 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1496 MachineFunction *F = BB->getParent();
1497 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
1498
1499 //CVTTQ STT LDQ
1500 //CVTST CVTTQ STT LDQ
1501 if (SrcType == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001502 {
1503 Tmp2 = MakeReg(MVT::f64);
1504 BuildMI(BB, Alpha::CVTST, 1, Tmp2).addReg(Tmp1);
1505 Tmp1 = Tmp2;
1506 }
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001507 Tmp2 = MakeReg(MVT::f64);
1508 BuildMI(BB, Alpha::CVTTQ, 1, Tmp2).addReg(Tmp1);
1509 BuildMI(BB, Alpha::STT, 3).addReg(Tmp2).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1510 BuildMI(BB, Alpha::LDQ, 2, Result).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1511
1512 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001513 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001514
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001515 // // case ISD::FP_TO_UINT:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001516
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001517 case ISD::SELECT:
1518 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001519 //FIXME: look at parent to decide if intCC can be folded, or if setCC(FP) and can save stack use
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001520 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001521 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1522 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001523 // Get the condition into the zero flag.
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001524 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001525 return Result;
1526 }
1527
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001528 case ISD::Constant:
1529 {
Andrew Lenharthc0513832005-03-29 19:24:04 +00001530 int64_t val = (int64_t)cast<ConstantSDNode>(N)->getValue();
Andrew Lenharthe87f6c32005-03-11 17:48:05 +00001531 if (val <= IMM_HIGH && val >= IMM_LOW) {
1532 BuildMI(BB, Alpha::LDA, 2, Result).addImm(val).addReg(Alpha::R31);
1533 }
1534 else if (val <= (int64_t)IMM_HIGH + (int64_t)IMM_HIGH * (int64_t)IMM_MULT &&
1535 val >= (int64_t)IMM_LOW + (int64_t)IMM_LOW * (int64_t)IMM_MULT) {
1536 Tmp1 = MakeReg(MVT::i64);
1537 BuildMI(BB, Alpha::LDAH, 2, Tmp1).addImm(getUpper16(val)).addReg(Alpha::R31);
1538 BuildMI(BB, Alpha::LDA, 2, Result).addImm(getLower16(val)).addReg(Tmp1);
1539 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001540 else {
1541 MachineConstantPool *CP = BB->getParent()->getConstantPool();
1542 ConstantUInt *C = ConstantUInt::get(Type::getPrimitiveType(Type::ULongTyID) , val);
1543 unsigned CPI = CP->getConstantPoolIndex(C);
1544 AlphaLowering.restoreGP(BB);
1545 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(CPI);
1546 }
1547 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001548 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001549 }
1550
1551 return 0;
1552}
1553
1554void ISel::Select(SDOperand N) {
1555 unsigned Tmp1, Tmp2, Opc;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001556 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001557
Nate Begeman85fdeb22005-03-24 04:39:54 +00001558 if (!ExprMap.insert(std::make_pair(N, notIn)).second)
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001559 return; // Already selected.
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001560
1561 SDNode *Node = N.Val;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001562
Andrew Lenharth760270d2005-02-07 23:02:23 +00001563 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001564
1565 default:
1566 Node->dump(); std::cerr << "\n";
1567 assert(0 && "Node not handled yet!");
1568
1569 case ISD::BRCOND: {
Andrew Lenharth445171a2005-02-08 00:40:03 +00001570 SelectBranchCC(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001571 return;
1572 }
1573
1574 case ISD::BR: {
1575 MachineBasicBlock *Dest =
1576 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
1577
1578 Select(N.getOperand(0));
1579 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
1580 return;
1581 }
1582
1583 case ISD::ImplicitDef:
1584 Select(N.getOperand(0));
1585 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
1586 return;
1587
1588 case ISD::EntryToken: return; // Noop
1589
1590 case ISD::TokenFactor:
1591 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
1592 Select(Node->getOperand(i));
1593
1594 //N.Val->dump(); std::cerr << "\n";
1595 //assert(0 && "Node not handled yet!");
1596
1597 return;
1598
1599 case ISD::CopyToReg:
1600 Select(N.getOperand(0));
1601 Tmp1 = SelectExpr(N.getOperand(1));
1602 Tmp2 = cast<RegSDNode>(N)->getReg();
1603
1604 if (Tmp1 != Tmp2) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001605 if (N.getOperand(1).getValueType() == MVT::f64 ||
1606 N.getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth29219162005-02-07 06:31:44 +00001607 BuildMI(BB, Alpha::CPYS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
1608 else
1609 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001610 }
1611 return;
1612
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001613 case ISD::RET:
1614 switch (N.getNumOperands()) {
1615 default:
1616 std::cerr << N.getNumOperands() << "\n";
1617 for (unsigned i = 0; i < N.getNumOperands(); ++i)
1618 std::cerr << N.getOperand(i).getValueType() << "\n";
1619 Node->dump();
1620 assert(0 && "Unknown return instruction!");
1621 case 2:
1622 Select(N.getOperand(0));
1623 Tmp1 = SelectExpr(N.getOperand(1));
1624 switch (N.getOperand(1).getValueType()) {
1625 default: Node->dump();
1626 assert(0 && "All other types should have been promoted!!");
1627 case MVT::f64:
1628 case MVT::f32:
1629 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
1630 break;
1631 case MVT::i32:
1632 case MVT::i64:
1633 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
1634 break;
1635 }
1636 break;
1637 case 1:
1638 Select(N.getOperand(0));
1639 break;
1640 }
1641 //Tmp2 = AlphaLowering.getRetAddr();
1642 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
1643 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
1644 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001645
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001646 case ISD::TRUNCSTORE:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001647 case ISD::STORE:
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001648 {
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001649 SDOperand Chain = N.getOperand(0);
1650 SDOperand Value = N.getOperand(1);
1651 SDOperand Address = N.getOperand(2);
1652 Select(Chain);
1653
1654 Tmp1 = SelectExpr(Value); //value
Andrew Lenharth760270d2005-02-07 23:02:23 +00001655
1656 if (opcode == ISD::STORE) {
1657 switch(Value.getValueType()) {
1658 default: assert(0 && "unknown Type in store");
1659 case MVT::i64: Opc = Alpha::STQ; break;
1660 case MVT::f64: Opc = Alpha::STT; break;
1661 case MVT::f32: Opc = Alpha::STS; break;
1662 }
1663 } else { //ISD::TRUNCSTORE
1664 switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
1665 default: assert(0 && "unknown Type in store");
1666 case MVT::i1: //FIXME: DAG does not promote this load
1667 case MVT::i8: Opc = Alpha::STB; break;
1668 case MVT::i16: Opc = Alpha::STW; break;
1669 case MVT::i32: Opc = Alpha::STL; break;
1670 }
Andrew Lenharth65838902005-02-06 16:22:15 +00001671 }
Andrew Lenharth760270d2005-02-07 23:02:23 +00001672
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001673 if (Address.getOpcode() == ISD::GlobalAddress)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001674 {
1675 AlphaLowering.restoreGP(BB);
1676 Opc = GetSymVersion(Opc);
1677 BuildMI(BB, Opc, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1678 }
Andrew Lenharth05380342005-02-07 05:07:00 +00001679 else if(Address.getOpcode() == ISD::FrameIndex)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001680 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001681 BuildMI(BB, Opc, 3).addReg(Tmp1)
1682 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1683 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001684 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001685 else
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001686 {
1687 long offset;
1688 SelectAddr(Address, Tmp2, offset);
1689 BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
1690 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001691 return;
1692 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001693
1694 case ISD::EXTLOAD:
1695 case ISD::SEXTLOAD:
1696 case ISD::ZEXTLOAD:
1697 case ISD::LOAD:
1698 case ISD::CopyFromReg:
1699 case ISD::CALL:
Andrew Lenharth032f2352005-02-22 21:59:48 +00001700 case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001701 ExprMap.erase(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001702 SelectExpr(N);
1703 return;
1704
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001705 case ISD::ADJCALLSTACKDOWN:
1706 case ISD::ADJCALLSTACKUP:
1707 Select(N.getOperand(0));
1708 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1709
1710 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
1711 Alpha::ADJUSTSTACKUP;
1712 BuildMI(BB, Opc, 1).addImm(Tmp1);
1713 return;
Andrew Lenharth95762122005-03-31 21:24:06 +00001714
1715 case ISD::PCMARKER:
1716 Select(N.getOperand(0)); //Chain
1717 BuildMI(BB, Alpha::PCLABEL, 2).addImm( cast<ConstantSDNode>(N.getOperand(1))->getValue());
1718 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001719 }
1720 assert(0 && "Should not be reached!");
1721}
1722
1723
1724/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
1725/// into a machine code representation using pattern matching and a machine
1726/// description file.
1727///
1728FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
1729 return new ISel(TM);
1730}