blob: 4a40aa93e117975e05404729393a43751de40282 [file] [log] [blame]
Misha Brukmanffe99682005-02-05 02:24:26 +00001//===- AlphaISelPattern.cpp - A pattern matching inst selector for Alpha --===//
Andrew Lenhartha1b5ca22005-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 Lenhartha1b5ca22005-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 Lenharth7ac01432005-02-22 21:59:48 +000029#include "llvm/Support/Debug.h"
Andrew Lenharthdec53922005-03-31 21:24:06 +000030#include "llvm/Support/CommandLine.h"
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +000031#include <set>
Andrew Lenharth918a29f2005-01-30 00:35:27 +000032#include <algorithm>
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +000033using namespace llvm;
34
Andrew Lenharthdec53922005-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 Lenharth3bf6f802005-03-31 22:02:25 +000040 cl::desc("Enable use of ftoi* and itof* instructions (ev6 and higher)"),
Andrew Lenharthdec53922005-03-31 21:24:06 +000041 cl::Hidden);
42}
43
Andrew Lenhartha1b5ca22005-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 Lenharth3c361fd2005-01-27 03:49:45 +000053 //I am having problems with shr n ubyte 1
Andrew Lenharthfe6e7a32005-02-02 17:00:21 +000054 setShiftAmountType(MVT::i64);
55 setSetCCResultType(MVT::i64);
Andrew Lenharth3c361fd2005-01-27 03:49:45 +000056
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +000057 addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass);
58 addRegisterClass(MVT::f64, Alpha::FPRCRegisterClass);
Andrew Lenharth3c361fd2005-01-27 03:49:45 +000059 addRegisterClass(MVT::f32, Alpha::FPRCRegisterClass);
Andrew Lenharthe0b789f2005-02-10 06:25:22 +000060
Andrew Lenharth0cceb512005-01-27 07:50:35 +000061 setOperationAction(ISD::EXTLOAD , MVT::i1 , Promote);
Andrew Lenharth8df62dd2005-03-04 20:09:23 +000062 setOperationAction(ISD::EXTLOAD , MVT::f32 , Promote);
Andrew Lenharth122489b2005-01-25 00:35:34 +000063
Andrew Lenharth4a0d2002005-01-28 23:17:54 +000064 setOperationAction(ISD::ZEXTLOAD , MVT::i1 , Expand);
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +000065 setOperationAction(ISD::ZEXTLOAD , MVT::i32 , Expand);
Andrew Lenharth122489b2005-01-25 00:35:34 +000066
Andrew Lenharth4a0d2002005-01-28 23:17:54 +000067 setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand);
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +000068 setOperationAction(ISD::SEXTLOAD , MVT::i8 , Expand);
69 setOperationAction(ISD::SEXTLOAD , MVT::i16 , Expand);
70
Andrew Lenharth060d58b2005-02-05 13:19:12 +000071 setOperationAction(ISD::SREM , MVT::f32 , Expand);
72 setOperationAction(ISD::SREM , MVT::f64 , Expand);
Andrew Lenharth5ae5f812005-01-26 21:54:09 +000073
Andrew Lenharth0f42d922005-02-02 05:49:42 +000074 setOperationAction(ISD::MEMMOVE , MVT::Other, Expand);
Andrew Lenharth060d58b2005-02-05 13:19:12 +000075 setOperationAction(ISD::MEMSET , MVT::Other, Expand);
76 setOperationAction(ISD::MEMCPY , MVT::Other, Expand);
77
Andrew Lenharth8df62dd2005-03-04 20:09:23 +000078 //Doesn't work yet
Andrew Lenharthcae2f212005-02-14 05:41:43 +000079 setOperationAction(ISD::SETCC , MVT::f32, Promote);
80
Andrew Lenharthe0b789f2005-02-10 06:25:22 +000081 computeRegisterProperties();
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +000082
Andrew Lenharthe0b789f2005-02-10 06:25:22 +000083 addLegalFPImmediate(+0.0); //F31
84 addLegalFPImmediate(-0.0); //-F31
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +000085 }
86
87 /// LowerArguments - This hook must be implemented to indicate how we should
88 /// lower the arguments for the specified function, into the specified DAG.
89 virtual std::vector<SDOperand>
90 LowerArguments(Function &F, SelectionDAG &DAG);
Andrew Lenharthe0b789f2005-02-10 06:25:22 +000091
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +000092 /// LowerCallTo - This hook lowers an abstract call to a function into an
93 /// actual call.
94 virtual std::pair<SDOperand, SDOperand>
Nate Begemanf6565252005-03-26 01:29:23 +000095 LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
96 SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG);
Andrew Lenharthe0b789f2005-02-10 06:25:22 +000097
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +000098 virtual std::pair<SDOperand, SDOperand>
99 LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000100
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000101 virtual std::pair<SDOperand,SDOperand>
102 LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
103 const Type *ArgTy, SelectionDAG &DAG);
104
105 virtual std::pair<SDOperand, SDOperand>
106 LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
107 SelectionDAG &DAG);
108
109 void restoreGP(MachineBasicBlock* BB)
110 {
111 BuildMI(BB, Alpha::BIS, 2, Alpha::R29).addReg(GP).addReg(GP);
112 }
113 };
114}
115
116//http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PY8AC-TET1_html/callCH3.html#BLOCK21
117
118//For now, just use variable size stack frame format
119
120//In a standard call, the first six items are passed in registers $16
121//- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
122//of argument-to-register correspondence.) The remaining items are
123//collected in a memory argument list that is a naturally aligned
124//array of quadwords. In a standard call, this list, if present, must
125//be passed at 0(SP).
126//7 ... n 0(SP) ... (n-7)*8(SP)
127
128std::vector<SDOperand>
129AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
130{
131 std::vector<SDOperand> ArgValues;
132
133 // //#define FP $15
134 // //#define RA $26
135 // //#define PV $27
136 // //#define GP $29
137 // //#define SP $30
138
139 // assert(0 && "TODO");
140 MachineFunction &MF = DAG.getMachineFunction();
Andrew Lenhartha9e02152005-02-07 05:07:00 +0000141 MachineFrameInfo*MFI = MF.getFrameInfo();
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000142
143 GP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
144 MachineBasicBlock& BB = MF.front();
145
146 //Handle the return address
147 //BuildMI(&BB, Alpha::IDEF, 0, Alpha::R26);
148
Andrew Lenharth5ae5f812005-01-26 21:54:09 +0000149 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
150 Alpha::R19, Alpha::R20, Alpha::R21};
151 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
152 Alpha::F19, Alpha::F20, Alpha::F21};
Andrew Lenharth0021f552005-02-06 21:07:31 +0000153 unsigned argVreg[6];
154 unsigned argPreg[6];
155 unsigned argOpc[6];
156
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000157 int count = 0;
Andrew Lenharth0021f552005-02-06 21:07:31 +0000158
Chris Lattner531f9e92005-03-15 04:54:21 +0000159 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000160 {
161 SDOperand newroot, argt;
162 if (count < 6) {
163 switch (getValueType(I->getType())) {
164 default:
165 std::cerr << "Unknown Type " << getValueType(I->getType()) << "\n";
166 abort();
167 case MVT::f64:
168 case MVT::f32:
169 BuildMI(&BB, Alpha::IDEF, 0, args_float[count]);
170 argVreg[count] =
171 MF.getSSARegMap()->createVirtualRegister(
Andrew Lenharth7ac01432005-02-22 21:59:48 +0000172 getRegClassFor(getValueType(I->getType())));
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000173 argPreg[count] = args_float[count];
174 argOpc[count] = Alpha::CPYS;
175 argt = newroot = DAG.getCopyFromReg(argVreg[count],
176 getValueType(I->getType()),
177 DAG.getRoot());
178 break;
179 case MVT::i1:
180 case MVT::i8:
181 case MVT::i16:
182 case MVT::i32:
183 case MVT::i64:
184 BuildMI(&BB, Alpha::IDEF, 0, args_int[count]);
185 argVreg[count] =
186 MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
187 argPreg[count] = args_int[count];
188 argOpc[count] = Alpha::BIS;
189 argt = newroot =
190 DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot());
191 if (getValueType(I->getType()) != MVT::i64)
192 argt =
193 DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()), newroot);
194 break;
Andrew Lenharth479bc612005-01-28 06:57:18 +0000195 }
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000196 } else { //more args
197 // Create the frame index object for this incoming parameter...
198 int FI = MFI->CreateFixedObject(8, 8 * (count - 6));
199
200 // Create the SelectionDAG nodes corresponding to a load
201 //from this parameter
202 SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
203 argt = newroot = DAG.getLoad(getValueType(I->getType()),
204 DAG.getEntryNode(), FIN);
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000205 }
Andrew Lenharth7ac01432005-02-22 21:59:48 +0000206 ++count;
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000207 DAG.setRoot(newroot.getValue(1));
208 ArgValues.push_back(argt);
209 }
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000210
211 BuildMI(&BB, Alpha::IDEF, 0, Alpha::R29);
212 BuildMI(&BB, Alpha::BIS, 2, GP).addReg(Alpha::R29).addReg(Alpha::R29);
Andrew Lenharth7ac01432005-02-22 21:59:48 +0000213 for (int i = 0; i < count && i < 6; ++i) {
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000214 BuildMI(&BB, argOpc[i], 2,
215 argVreg[i]).addReg(argPreg[i]).addReg(argPreg[i]);
216 }
Andrew Lenharth479bc612005-01-28 06:57:18 +0000217
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000218 return ArgValues;
219}
220
221std::pair<SDOperand, SDOperand>
222AlphaTargetLowering::LowerCallTo(SDOperand Chain,
Nate Begemanf6565252005-03-26 01:29:23 +0000223 const Type *RetTy, bool isVarArg,
224 SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG) {
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000225 int NumBytes = 0;
Andrew Lenharth918a29f2005-01-30 00:35:27 +0000226 if (Args.size() > 6)
227 NumBytes = (Args.size() - 6) * 8;
228
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000229 Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
230 DAG.getConstant(NumBytes, getPointerTy()));
231 std::vector<SDOperand> args_to_use;
232 for (unsigned i = 0, e = Args.size(); i != e; ++i)
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000233 {
234 switch (getValueType(Args[i].second)) {
235 default: assert(0 && "Unexpected ValueType for argument!");
236 case MVT::i1:
237 case MVT::i8:
238 case MVT::i16:
239 case MVT::i32:
240 // Promote the integer to 64 bits. If the input type is signed use a
241 // sign extend, otherwise use a zero extend.
242 if (Args[i].second->isSigned())
243 Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first);
244 else
245 Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first);
246 break;
247 case MVT::i64:
248 case MVT::f64:
249 case MVT::f32:
250 break;
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000251 }
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000252 args_to_use.push_back(Args[i].first);
253 }
Andrew Lenharth479bc612005-01-28 06:57:18 +0000254
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000255 std::vector<MVT::ValueType> RetVals;
256 MVT::ValueType RetTyVT = getValueType(RetTy);
257 if (RetTyVT != MVT::isVoid)
258 RetVals.push_back(RetTyVT);
259 RetVals.push_back(MVT::Other);
260
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000261 SDOperand TheCall = SDOperand(DAG.getCall(RetVals,
262 Chain, Callee, args_to_use), 0);
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000263 Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
264 Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
265 DAG.getConstant(NumBytes, getPointerTy()));
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000266 return std::make_pair(TheCall, Chain);
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000267}
268
269std::pair<SDOperand, SDOperand>
270AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
271 //vastart just returns the address of the VarArgsFrameIndex slot.
272 return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain);
273}
274
275std::pair<SDOperand,SDOperand> AlphaTargetLowering::
276LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000277 const Type *ArgTy, SelectionDAG &DAG) {
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000278 abort();
279}
280
281
282std::pair<SDOperand, SDOperand> AlphaTargetLowering::
283LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
284 SelectionDAG &DAG) {
285 abort();
286}
287
288
289
290
291
292namespace {
293
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000294//===--------------------------------------------------------------------===//
295/// ISel - Alpha specific code to select Alpha machine instructions for
296/// SelectionDAG operations.
297//===--------------------------------------------------------------------===//
298class ISel : public SelectionDAGISel {
299
300 /// AlphaLowering - This object fully describes how to lower LLVM code to an
301 /// Alpha-specific SelectionDAG.
302 AlphaTargetLowering AlphaLowering;
303
304
305 /// ExprMap - As shared expressions are codegen'd, we keep track of which
306 /// vreg the value is produced in, so we only emit one copy of each compiled
307 /// tree.
308 static const unsigned notIn = (unsigned)(-1);
309 std::map<SDOperand, unsigned> ExprMap;
310
311 //CCInvMap sometimes (SetNE) we have the inverse CC code for free
312 std::map<SDOperand, unsigned> CCInvMap;
313
314public:
315 ISel(TargetMachine &TM) : SelectionDAGISel(AlphaLowering), AlphaLowering(TM)
316 {}
317
318 /// InstructionSelectBasicBlock - This callback is invoked by
319 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
320 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
Andrew Lenharth7ac01432005-02-22 21:59:48 +0000321 DEBUG(BB->dump());
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000322 // Codegen the basic block.
323 Select(DAG.getRoot());
324
325 // Clear state used for selection.
326 ExprMap.clear();
327 CCInvMap.clear();
328 }
329
330 unsigned SelectExpr(SDOperand N);
331 unsigned SelectExprFP(SDOperand N, unsigned Result);
332 void Select(SDOperand N);
333
334 void SelectAddr(SDOperand N, unsigned& Reg, long& offset);
335 void SelectBranchCC(SDOperand N);
336};
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000337}
338
Andrew Lenharth27a3df02005-03-11 17:48:05 +0000339//These describe LDAx
Andrew Lenharth93d00892005-03-29 19:24:04 +0000340static const int IMM_LOW = -32768;
341static const int IMM_HIGH = 32767;
Andrew Lenharth27a3df02005-03-11 17:48:05 +0000342static const int IMM_MULT = 65536;
343
344static long getUpper16(long l)
345{
346 long y = l / IMM_MULT;
347 if (l % IMM_MULT > IMM_HIGH)
348 ++y;
349 return y;
350}
351
352static long getLower16(long l)
353{
354 long h = getUpper16(l);
355 return l - h * IMM_MULT;
356}
357
Andrew Lenhartheefd4102005-02-06 16:22:15 +0000358static unsigned GetSymVersion(unsigned opcode)
359{
360 switch (opcode) {
361 default: assert(0 && "unknown load or store"); return 0;
362 case Alpha::LDQ: return Alpha::LDQ_SYM;
363 case Alpha::LDS: return Alpha::LDS_SYM;
364 case Alpha::LDT: return Alpha::LDT_SYM;
365 case Alpha::LDL: return Alpha::LDL_SYM;
366 case Alpha::LDBU: return Alpha::LDBU_SYM;
367 case Alpha::LDWU: return Alpha::LDWU_SYM;
368 case Alpha::LDW: return Alpha::LDW_SYM;
369 case Alpha::LDB: return Alpha::LDB_SYM;
370 case Alpha::STQ: return Alpha::STQ_SYM;
371 case Alpha::STS: return Alpha::STS_SYM;
372 case Alpha::STT: return Alpha::STT_SYM;
373 case Alpha::STL: return Alpha::STL_SYM;
374 case Alpha::STW: return Alpha::STW_SYM;
375 case Alpha::STB: return Alpha::STB_SYM;
376 }
377}
378
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000379//Check to see if the load is a constant offset from a base register
380void ISel::SelectAddr(SDOperand N, unsigned& Reg, long& offset)
381{
382 unsigned opcode = N.getOpcode();
383 if (opcode == ISD::ADD) {
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000384 if(N.getOperand(1).getOpcode() == ISD::Constant &&
385 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767)
386 { //Normal imm add
387 Reg = SelectExpr(N.getOperand(0));
388 offset = cast<ConstantSDNode>(N.getOperand(1))->getValue();
389 return;
390 }
391 else if(N.getOperand(0).getOpcode() == ISD::Constant &&
392 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 32767)
393 {
394 Reg = SelectExpr(N.getOperand(1));
395 offset = cast<ConstantSDNode>(N.getOperand(0))->getValue();
396 return;
397 }
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000398 }
399 Reg = SelectExpr(N);
400 offset = 0;
401 return;
402}
403
Andrew Lenharth8ec0a2b2005-02-08 00:40:03 +0000404void ISel::SelectBranchCC(SDOperand N)
405{
406 assert(N.getOpcode() == ISD::BRCOND && "Not a BranchCC???");
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000407 MachineBasicBlock *Dest =
408 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
409 unsigned Opc = Alpha::WTF;
410
Andrew Lenharth8ec0a2b2005-02-08 00:40:03 +0000411 Select(N.getOperand(0)); //chain
412 SDOperand CC = N.getOperand(1);
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000413
Andrew Lenharth8ec0a2b2005-02-08 00:40:03 +0000414 if (CC.getOpcode() == ISD::SETCC)
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000415 {
416 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
417 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
418 //Dropping the CC is only useful if we are comparing to 0
419 bool isZero0 = false;
420 bool isZero1 = false;
421 bool isNE = false;
Andrew Lenharth8ec0a2b2005-02-08 00:40:03 +0000422
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000423 if(SetCC->getOperand(0).getOpcode() == ISD::Constant &&
424 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0)
425 isZero0 = true;
426 if(SetCC->getOperand(1).getOpcode() == ISD::Constant &&
427 cast<ConstantSDNode>(SetCC->getOperand(1))->getValue() == 0)
428 isZero1 = true;
429 if(SetCC->getCondition() == ISD::SETNE)
430 isNE = true;
Andrew Lenharth8ec0a2b2005-02-08 00:40:03 +0000431
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000432 if (isZero0) {
Andrew Lenharth8ec0a2b2005-02-08 00:40:03 +0000433 switch (SetCC->getCondition()) {
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000434 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
435 case ISD::SETEQ: Opc = Alpha::BEQ; break;
436 case ISD::SETLT: Opc = Alpha::BGT; break;
437 case ISD::SETLE: Opc = Alpha::BGE; break;
438 case ISD::SETGT: Opc = Alpha::BLT; break;
439 case ISD::SETGE: Opc = Alpha::BLE; break;
440 case ISD::SETULT: Opc = Alpha::BNE; break;
441 case ISD::SETUGT: assert(0 && "0 > (unsigned) x is never true"); break;
442 case ISD::SETULE: assert(0 && "0 <= (unsigned) x is always true"); break;
443 case ISD::SETUGE: Opc = Alpha::BEQ; break; //Technically you could have this CC
444 case ISD::SETNE: Opc = Alpha::BNE; break;
Andrew Lenharth8ec0a2b2005-02-08 00:40:03 +0000445 }
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000446 unsigned Tmp1 = SelectExpr(SetCC->getOperand(1));
447 BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest);
448 return;
449 } else if (isZero1) {
450 switch (SetCC->getCondition()) {
451 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
452 case ISD::SETEQ: Opc = Alpha::BEQ; break;
453 case ISD::SETLT: Opc = Alpha::BLT; break;
454 case ISD::SETLE: Opc = Alpha::BLE; break;
455 case ISD::SETGT: Opc = Alpha::BGT; break;
456 case ISD::SETGE: Opc = Alpha::BGE; break;
457 case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break;
458 case ISD::SETUGT: Opc = Alpha::BNE; break;
459 case ISD::SETULE: Opc = Alpha::BEQ; break; //Technically you could have this CC
460 case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break;
461 case ISD::SETNE: Opc = Alpha::BNE; break;
462 }
463 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
464 BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest);
465 return;
466 } else {
467 unsigned Tmp1 = SelectExpr(CC);
468 if (isNE)
469 BuildMI(BB, Alpha::BEQ, 2).addReg(CCInvMap[CC]).addMBB(Dest);
470 else
471 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
Andrew Lenharth8ec0a2b2005-02-08 00:40:03 +0000472 return;
473 }
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000474 } else { //FP
475 //Any comparison between 2 values should be codegened as an folded branch, as moving
476 //CC to the integer register is very expensive
477 //for a cmp b: c = a - b;
478 //a = b: c = 0
479 //a < b: c < 0
480 //a > b: c > 0
Andrew Lenharth10bc4c02005-02-25 22:55:15 +0000481
482 bool invTest = false;
483 unsigned Tmp3;
484
485 ConstantFPSDNode *CN;
486 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
487 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
488 Tmp3 = SelectExpr(SetCC->getOperand(0));
489 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
490 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
491 {
492 Tmp3 = SelectExpr(SetCC->getOperand(1));
493 invTest = true;
494 }
495 else
496 {
497 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
498 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
499 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
500 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
501 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
502 .addReg(Tmp1).addReg(Tmp2);
503 }
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000504
505 switch (SetCC->getCondition()) {
506 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
Andrew Lenharth10bc4c02005-02-25 22:55:15 +0000507 case ISD::SETEQ: Opc = invTest ? Alpha::FBNE : Alpha::FBEQ; break;
508 case ISD::SETLT: Opc = invTest ? Alpha::FBGT : Alpha::FBLT; break;
509 case ISD::SETLE: Opc = invTest ? Alpha::FBGE : Alpha::FBLE; break;
510 case ISD::SETGT: Opc = invTest ? Alpha::FBLT : Alpha::FBGT; break;
511 case ISD::SETGE: Opc = invTest ? Alpha::FBLE : Alpha::FBGE; break;
512 case ISD::SETNE: Opc = invTest ? Alpha::FBEQ : Alpha::FBNE; break;
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000513 }
514 BuildMI(BB, Opc, 2).addReg(Tmp3).addMBB(Dest);
Andrew Lenharth8ec0a2b2005-02-08 00:40:03 +0000515 return;
516 }
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000517 abort(); //Should never be reached
518 } else {
519 //Giveup and do the stupid thing
520 unsigned Tmp1 = SelectExpr(CC);
521 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
522 return;
523 }
Andrew Lenharth8ec0a2b2005-02-08 00:40:03 +0000524 abort(); //Should never be reached
525}
526
Andrew Lenharth479bc612005-01-28 06:57:18 +0000527unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
528{
529 unsigned Tmp1, Tmp2, Tmp3;
530 unsigned Opc = 0;
531 SDNode *Node = N.Val;
532 MVT::ValueType DestType = N.getValueType();
533 unsigned opcode = N.getOpcode();
534
535 switch (opcode) {
536 default:
537 Node->dump();
538 assert(0 && "Node not handled!\n");
Andrew Lenharth41bc2c22005-01-29 15:42:07 +0000539
Andrew Lenharthe7ae4002005-04-02 19:11:07 +0000540 case ISD::UNDEF: {
541 BuildMI(BB, Alpha::IDEF, 0, Result);
542 return Result;
543 }
544
Andrew Lenharth7ad36972005-04-02 19:04:58 +0000545 case ISD::FNEG:
546 if(ISD::FABS == N.getOperand(0).getOpcode())
547 {
548 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharthe7ae4002005-04-02 19:11:07 +0000549 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
Andrew Lenharth7ad36972005-04-02 19:04:58 +0000550 } else {
551 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharthe7ae4002005-04-02 19:11:07 +0000552 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth7ad36972005-04-02 19:04:58 +0000553 }
554 return Result;
555
556 case ISD::FABS:
557 Tmp1 = SelectExpr(N.getOperand(0));
558 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
559 return Result;
560
Andrew Lenharth060d58b2005-02-05 13:19:12 +0000561 case ISD::SELECT:
562 {
Andrew Lenharth6a5f52d2005-03-03 21:47:53 +0000563 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
564 unsigned TV = SelectExpr(N.getOperand(1)); //Use if TRUE
565 unsigned FV = SelectExpr(N.getOperand(2)); //Use if FALSE
566
567 SDOperand CC = N.getOperand(0);
568 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
569
570 if (CC.getOpcode() == ISD::SETCC &&
571 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
572 { //FP Setcc -> Select yay!
Andrew Lenharthea9224a2005-02-05 16:41:03 +0000573
574
Andrew Lenharth6a5f52d2005-03-03 21:47:53 +0000575 //for a cmp b: c = a - b;
576 //a = b: c = 0
577 //a < b: c < 0
578 //a > b: c > 0
579
580 bool invTest = false;
581 unsigned Tmp3;
582
583 ConstantFPSDNode *CN;
584 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
585 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
586 Tmp3 = SelectExpr(SetCC->getOperand(0));
587 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
588 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
589 {
590 Tmp3 = SelectExpr(SetCC->getOperand(1));
591 invTest = true;
592 }
593 else
594 {
595 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
596 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
597 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
598 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
599 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
600 .addReg(Tmp1).addReg(Tmp2);
601 }
602
603 switch (SetCC->getCondition()) {
604 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
605 case ISD::SETEQ: Opc = invTest ? Alpha::FCMOVNE : Alpha::FCMOVEQ; break;
606 case ISD::SETLT: Opc = invTest ? Alpha::FCMOVGT : Alpha::FCMOVLT; break;
607 case ISD::SETLE: Opc = invTest ? Alpha::FCMOVGE : Alpha::FCMOVLE; break;
608 case ISD::SETGT: Opc = invTest ? Alpha::FCMOVLT : Alpha::FCMOVGT; break;
609 case ISD::SETGE: Opc = invTest ? Alpha::FCMOVLE : Alpha::FCMOVGE; break;
610 case ISD::SETNE: Opc = invTest ? Alpha::FCMOVEQ : Alpha::FCMOVNE; break;
611 }
Andrew Lenharth8df62dd2005-03-04 20:09:23 +0000612 BuildMI(BB, Opc, 3, Result).addReg(FV).addReg(TV).addReg(Tmp3);
Andrew Lenharth6a5f52d2005-03-03 21:47:53 +0000613 return Result;
614 }
615 else
616 {
617 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
618 // Spill the cond to memory and reload it from there.
619 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
620 MachineFunction *F = BB->getParent();
621 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
622 unsigned Tmp4 = MakeReg(MVT::f64);
623 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdx).addReg(Alpha::F31);
624 BuildMI(BB, Alpha::LDT, 2, Tmp4).addFrameIndex(FrameIdx).addReg(Alpha::F31);
625 //now ideally, we don't have to do anything to the flag...
626 // Get the condition into the zero flag.
627 BuildMI(BB, Alpha::FCMOVEQ, 3, Result).addReg(TV).addReg(FV).addReg(Tmp4);
628 return Result;
629 }
Andrew Lenharth060d58b2005-02-05 13:19:12 +0000630 }
631
Andrew Lenharthcdc9e332005-02-01 01:37:24 +0000632 case ISD::FP_ROUND:
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000633 assert (DestType == MVT::f32 &&
634 N.getOperand(0).getValueType() == MVT::f64 &&
635 "only f64 to f32 conversion supported here");
Andrew Lenharthcdc9e332005-02-01 01:37:24 +0000636 Tmp1 = SelectExpr(N.getOperand(0));
637 BuildMI(BB, Alpha::CVTTS, 1, Result).addReg(Tmp1);
638 return Result;
639
Andrew Lenharth71413342005-01-30 20:42:36 +0000640 case ISD::FP_EXTEND:
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000641 assert (DestType == MVT::f64 &&
642 N.getOperand(0).getValueType() == MVT::f32 &&
643 "only f32 to f64 conversion supported here");
Andrew Lenharth71413342005-01-30 20:42:36 +0000644 Tmp1 = SelectExpr(N.getOperand(0));
645 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
646 return Result;
647
Andrew Lenharth41bc2c22005-01-29 15:42:07 +0000648 case ISD::CopyFromReg:
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());
655
656 SDOperand Chain = N.getOperand(0);
657
658 Select(Chain);
659 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
660 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
661 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(r).addReg(r);
662 return Result;
663 }
664
Andrew Lenharth4a0d2002005-01-28 23:17:54 +0000665 case ISD::LOAD:
666 {
667 // Make sure we generate both values.
668 if (Result != notIn)
669 ExprMap[N.getValue(1)] = notIn; // Generate the token
670 else
671 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth79947912005-02-03 21:01:15 +0000672
Andrew Lenharth9d3f7702005-02-07 06:31:44 +0000673 DestType = N.getValue(0).getValueType();
Andrew Lenharth79947912005-02-03 21:01:15 +0000674
Andrew Lenharth4a0d2002005-01-28 23:17:54 +0000675 SDOperand Chain = N.getOperand(0);
676 SDOperand Address = N.getOperand(1);
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000677 Select(Chain);
Andrew Lenhartheefd4102005-02-06 16:22:15 +0000678 Opc = DestType == MVT::f64 ? Alpha::LDT : Alpha::LDS;
679
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000680 if (Address.getOpcode() == ISD::GlobalAddress) {
681 AlphaLowering.restoreGP(BB);
682 Opc = GetSymVersion(Opc);
683 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
684 }
Andrew Lenharth9df6a762005-02-01 20:40:27 +0000685 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
Andrew Lenharthea9224a2005-02-05 16:41:03 +0000686 AlphaLowering.restoreGP(BB);
Andrew Lenhartheefd4102005-02-06 16:22:15 +0000687 Opc = GetSymVersion(Opc);
Andrew Lenharth7be98542005-02-05 17:41:39 +0000688 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharth9df6a762005-02-01 20:40:27 +0000689 }
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000690 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth7ac01432005-02-22 21:59:48 +0000691 BuildMI(BB, Opc, 2, Result)
692 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
693 .addReg(Alpha::F31);
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000694 } else {
695 long offset;
696 SelectAddr(Address, Tmp1, offset);
697 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
698 }
Andrew Lenharth4a0d2002005-01-28 23:17:54 +0000699 return Result;
700 }
Andrew Lenharth479bc612005-01-28 06:57:18 +0000701 case ISD::ConstantFP:
702 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
703 if (CN->isExactlyValue(+0.0)) {
704 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth79947912005-02-03 21:01:15 +0000705 } else if ( CN->isExactlyValue(-0.0)) {
706 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth479bc612005-01-28 06:57:18 +0000707 } else {
708 abort();
709 }
710 }
711 return Result;
712
Andrew Lenharth6294dee2005-03-22 00:24:07 +0000713 case ISD::SDIV:
Andrew Lenharth479bc612005-01-28 06:57:18 +0000714 case ISD::MUL:
715 case ISD::ADD:
716 case ISD::SUB:
Andrew Lenharth479bc612005-01-28 06:57:18 +0000717 switch( opcode ) {
718 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
719 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
720 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
721 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
722 };
Andrew Lenharth10bc4c02005-02-25 22:55:15 +0000723
724 ConstantFPSDNode *CN;
725 if (opcode == ISD::SUB
726 && (CN = dyn_cast<ConstantFPSDNode>(N.getOperand(0)))
727 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
728 {
729 Tmp2 = SelectExpr(N.getOperand(1));
730 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp2).addReg(Tmp2);
731 } else {
732 Tmp1 = SelectExpr(N.getOperand(0));
733 Tmp2 = SelectExpr(N.getOperand(1));
734 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
735 }
Andrew Lenharth479bc612005-01-28 06:57:18 +0000736 return Result;
737
Andrew Lenharth41bc2c22005-01-29 15:42:07 +0000738 case ISD::EXTLOAD:
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000739 {
740 //include a conversion sequence for float loads to double
741 if (Result != notIn)
742 ExprMap[N.getValue(1)] = notIn; // Generate the token
743 else
744 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
745
Andrew Lenharth5d004ed2005-02-07 05:33:15 +0000746 Tmp1 = MakeReg(MVT::f32);
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000747
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000748 assert(cast<MVTSDNode>(Node)->getExtraValueType() == MVT::f32 &&
749 "EXTLOAD not from f32");
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000750 assert(Node->getValueType(0) == MVT::f64 && "EXTLOAD not to f64");
751
752 SDOperand Chain = N.getOperand(0);
753 SDOperand Address = N.getOperand(1);
754 Select(Chain);
755
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000756 if (Address.getOpcode() == ISD::GlobalAddress) {
757 AlphaLowering.restoreGP(BB);
758 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
759 }
760 else if (ConstantPoolSDNode *CP =
761 dyn_cast<ConstantPoolSDNode>(N.getOperand(1)))
762 {
763 AlphaLowering.restoreGP(BB);
764 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addConstantPoolIndex(CP->getIndex());
765 }
766 else if(Address.getOpcode() == ISD::FrameIndex) {
767 Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
Andrew Lenharth7ac01432005-02-22 21:59:48 +0000768 BuildMI(BB, Alpha::LDS, 2, Tmp1)
769 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
770 .addReg(Alpha::F31);
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000771 } else {
772 long offset;
773 SelectAddr(Address, Tmp2, offset);
774 BuildMI(BB, Alpha::LDS, 1, Tmp1).addImm(offset).addReg(Tmp2);
775 }
Andrew Lenharth9d3f7702005-02-07 06:31:44 +0000776 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
Andrew Lenharth79947912005-02-03 21:01:15 +0000777 return Result;
778 }
Andrew Lenharth41bc2c22005-01-29 15:42:07 +0000779
Andrew Lenharth9df6a762005-02-01 20:40:27 +0000780 case ISD::UINT_TO_FP:
781 case ISD::SINT_TO_FP:
Andrew Lenharth479bc612005-01-28 06:57:18 +0000782 {
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000783 assert (N.getOperand(0).getValueType() == MVT::i64
784 && "only quads can be loaded from");
Andrew Lenharth479bc612005-01-28 06:57:18 +0000785 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharthc40d1562005-01-31 01:44:26 +0000786 Tmp2 = MakeReg(MVT::f64);
Andrew Lenharth41bc2c22005-01-29 15:42:07 +0000787
788 //The hard way:
789 // Spill the integer to memory and reload it from there.
790 unsigned Size = MVT::getSizeInBits(MVT::i64)/8;
791 MachineFunction *F = BB->getParent();
792 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, Size);
793
Andrew Lenharthc40d1562005-01-31 01:44:26 +0000794 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdx).addReg(Alpha::F31);
795 BuildMI(BB, Alpha::LDT, 2, Tmp2).addFrameIndex(FrameIdx).addReg(Alpha::F31);
796 Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
797 BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
Andrew Lenharth41bc2c22005-01-29 15:42:07 +0000798
799 //The easy way: doesn't work
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000800 // //so these instructions are not supported on ev56
801 // Opc = DestType == MVT::f64 ? Alpha::ITOFT : Alpha::ITOFS;
802 // BuildMI(BB, Opc, 1, Tmp2).addReg(Tmp1);
803 // Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
804 // BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
Andrew Lenharth41bc2c22005-01-29 15:42:07 +0000805
Andrew Lenharth479bc612005-01-28 06:57:18 +0000806 return Result;
807 }
808 }
809 assert(0 && "should not get here");
810 return 0;
811}
812
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000813unsigned ISel::SelectExpr(SDOperand N) {
814 unsigned Result;
815 unsigned Tmp1, Tmp2, Tmp3;
816 unsigned Opc = 0;
Andrew Lenharth479bc612005-01-28 06:57:18 +0000817 unsigned opcode = N.getOpcode();
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000818
819 SDNode *Node = N.Val;
Andrew Lenharth479bc612005-01-28 06:57:18 +0000820 MVT::ValueType DestType = N.getValueType();
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000821
822 unsigned &Reg = ExprMap[N];
823 if (Reg) return Reg;
824
825 if (N.getOpcode() != ISD::CALL)
826 Reg = Result = (N.getValueType() != MVT::Other) ?
Andrew Lenharth4a0d2002005-01-28 23:17:54 +0000827 MakeReg(N.getValueType()) : notIn;
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000828 else {
829 // If this is a call instruction, make sure to prepare ALL of the result
830 // values as well as the chain.
831 if (Node->getNumValues() == 1)
Andrew Lenharth4a0d2002005-01-28 23:17:54 +0000832 Reg = Result = notIn; // Void call, just a chain.
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000833 else {
834 Result = MakeReg(Node->getValueType(0));
835 ExprMap[N.getValue(0)] = Result;
836 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
837 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
Andrew Lenharth4a0d2002005-01-28 23:17:54 +0000838 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000839 }
840 }
841
Andrew Lenharthc7042c22005-02-02 15:05:33 +0000842 if (DestType == MVT::f64 || DestType == MVT::f32 ||
Andrew Lenharth57047722005-02-07 06:21:37 +0000843 (
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000844 (opcode == ISD::LOAD || opcode == ISD::CopyFromReg ||
845 opcode == ISD::EXTLOAD) &&
846 (N.getValue(0).getValueType() == MVT::f32 ||
847 N.getValue(0).getValueType() == MVT::f64)
Andrew Lenharth57047722005-02-07 06:21:37 +0000848 )
849 )
Andrew Lenharth479bc612005-01-28 06:57:18 +0000850 return SelectExprFP(N, Result);
851
852 switch (opcode) {
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000853 default:
854 Node->dump();
855 assert(0 && "Node not handled!\n");
856
Andrew Lenharthe7ae4002005-04-02 19:11:07 +0000857
858 case ISD::UNDEF: {
859 BuildMI(BB, Alpha::IDEF, 0, Result);
860 return Result;
861 }
862
Andrew Lenharth7ac01432005-02-22 21:59:48 +0000863 case ISD::DYNAMIC_STACKALLOC:
864 // Generate both result values.
Andrew Lenharth27cf4eb2005-02-23 17:33:42 +0000865 if (Result != notIn)
866 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth7ac01432005-02-22 21:59:48 +0000867 else
868 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
869
870 // FIXME: We are currently ignoring the requested alignment for handling
871 // greater than the stack alignment. This will need to be revisited at some
872 // point. Align = N.getOperand(2);
873
874 if (!isa<ConstantSDNode>(N.getOperand(2)) ||
875 cast<ConstantSDNode>(N.getOperand(2))->getValue() != 0) {
876 std::cerr << "Cannot allocate stack object with greater alignment than"
877 << " the stack alignment yet!";
878 abort();
879 }
880
881 Select(N.getOperand(0));
882 if (ConstantSDNode* CN = dyn_cast<ConstantSDNode>(N.getOperand(1)))
883 {
884 if (CN->getValue() < 32000)
885 {
886 BuildMI(BB, Alpha::LDA, 2, Alpha::R30)
887 .addImm(-CN->getValue()).addReg(Alpha::R30);
888 } else {
889 Tmp1 = SelectExpr(N.getOperand(1));
890 // Subtract size from stack pointer, thereby allocating some space.
891 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
892 }
893 } else {
894 Tmp1 = SelectExpr(N.getOperand(1));
895 // Subtract size from stack pointer, thereby allocating some space.
896 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
897 }
898
899 // Put a pointer to the space into the result register, by copying the stack
900 // pointer.
Andrew Lenharthccdfdd72005-02-22 23:29:25 +0000901 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R30).addReg(Alpha::R30);
Andrew Lenharth7ac01432005-02-22 21:59:48 +0000902 return Result;
903
Andrew Lenharth8df62dd2005-03-04 20:09:23 +0000904// case ISD::ConstantPool:
905// Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
906// AlphaLowering.restoreGP(BB);
907// BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(Tmp1);
908// return Result;
Andrew Lenharth41bc2c22005-01-29 15:42:07 +0000909
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000910 case ISD::FrameIndex:
Andrew Lenharth7ac01432005-02-22 21:59:48 +0000911 BuildMI(BB, Alpha::LDA, 2, Result)
912 .addFrameIndex(cast<FrameIndexSDNode>(N)->getIndex())
913 .addReg(Alpha::F31);
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000914 return Result;
915
916 case ISD::EXTLOAD:
Andrew Lenharth5fb9b532005-02-07 05:18:02 +0000917 case ISD::ZEXTLOAD:
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000918 case ISD::SEXTLOAD:
Andrew Lenharth5d004ed2005-02-07 05:33:15 +0000919 case ISD::LOAD:
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000920 {
921 // Make sure we generate both values.
922 if (Result != notIn)
923 ExprMap[N.getValue(1)] = notIn; // Generate the token
924 else
925 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000926
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000927 SDOperand Chain = N.getOperand(0);
928 SDOperand Address = N.getOperand(1);
929 Select(Chain);
930
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000931 assert(Node->getValueType(0) == MVT::i64 &&
932 "Unknown type to sign extend to.");
Andrew Lenharth351df0c2005-02-07 05:55:55 +0000933 if (opcode == ISD::LOAD)
934 Opc = Alpha::LDQ;
935 else
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000936 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
937 default: Node->dump(); assert(0 && "Bad sign extend!");
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000938 case MVT::i32: Opc = Alpha::LDL;
939 assert(opcode != ISD::ZEXTLOAD && "Not sext"); break;
940 case MVT::i16: Opc = Alpha::LDWU;
941 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharth5fb9b532005-02-07 05:18:02 +0000942 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000943 case MVT::i8: Opc = Alpha::LDBU;
944 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000945 }
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000946
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000947 if (Address.getOpcode() == ISD::GlobalAddress) {
948 AlphaLowering.restoreGP(BB);
949 Opc = GetSymVersion(Opc);
950 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
951 }
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000952 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
953 AlphaLowering.restoreGP(BB);
Andrew Lenhartheefd4102005-02-06 16:22:15 +0000954 Opc = GetSymVersion(Opc);
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000955 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000956 }
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000957 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth7ac01432005-02-22 21:59:48 +0000958 BuildMI(BB, Opc, 2, Result)
959 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
960 .addReg(Alpha::F31);
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000961 } else {
962 long offset;
963 SelectAddr(Address, Tmp1, offset);
964 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
965 }
Andrew Lenharth6c018f72005-02-06 15:40:40 +0000966 return Result;
Andrew Lenharth122489b2005-01-25 00:35:34 +0000967 }
Andrew Lenharth122489b2005-01-25 00:35:34 +0000968
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000969 case ISD::GlobalAddress:
970 AlphaLowering.restoreGP(BB);
971 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
972 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
973 return Result;
974
975 case ISD::CALL:
976 {
977 Select(N.getOperand(0));
Andrew Lenharth5ae5f812005-01-26 21:54:09 +0000978
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000979 // The chain for this call is now lowered.
Andrew Lenharth4a0d2002005-01-28 23:17:54 +0000980 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), notIn));
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000981
982 //grab the arguments
983 std::vector<unsigned> argvregs;
Andrew Lenharth71413342005-01-30 20:42:36 +0000984 //assert(Node->getNumOperands() < 8 && "Only 6 args supported");
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +0000985 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000986 argvregs.push_back(SelectExpr(N.getOperand(i)));
Andrew Lenharth5ae5f812005-01-26 21:54:09 +0000987
Andrew Lenharth918a29f2005-01-30 00:35:27 +0000988 //in reg args
989 for(int i = 0, e = std::min(6, (int)argvregs.size()); i < e; ++i)
Andrew Lenharthe0b789f2005-02-10 06:25:22 +0000990 {
991 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
992 Alpha::R19, Alpha::R20, Alpha::R21};
993 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
994 Alpha::F19, Alpha::F20, Alpha::F21};
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::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
1008 break;
1009 case MVT::f32:
1010 case MVT::f64:
1011 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
1012 break;
Andrew Lenharth918a29f2005-01-30 00:35:27 +00001013 }
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001014 }
Andrew Lenharth918a29f2005-01-30 00:35:27 +00001015 //in mem args
1016 for (int i = 6, e = argvregs.size(); i < e; ++i)
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001017 {
1018 switch(N.getOperand(i+2).getValueType()) {
1019 default:
1020 Node->dump();
1021 N.getOperand(i).Val->dump();
1022 std::cerr << "Type for " << i << " is: " <<
1023 N.getOperand(i+2).getValueType() << "\n";
1024 assert(0 && "Unknown value type for call");
1025 case MVT::i1:
1026 case MVT::i8:
1027 case MVT::i16:
1028 case MVT::i32:
1029 case MVT::i64:
1030 BuildMI(BB, Alpha::STQ, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1031 break;
1032 case MVT::f32:
1033 BuildMI(BB, Alpha::STS, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1034 break;
1035 case MVT::f64:
1036 BuildMI(BB, Alpha::STT, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1037 break;
Andrew Lenharth918a29f2005-01-30 00:35:27 +00001038 }
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001039 }
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001040 //build the right kind of call
1041 if (GlobalAddressSDNode *GASD =
Andrew Lenharth71413342005-01-30 20:42:36 +00001042 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001043 {
Andrew Lenharthb301af72005-02-10 20:10:38 +00001044 //if (GASD->getGlobal()->isExternal()) {
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001045 //use safe calling convention
Andrew Lenharth71413342005-01-30 20:42:36 +00001046 AlphaLowering.restoreGP(BB);
1047 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
Andrew Lenharthb301af72005-02-10 20:10:38 +00001048 //} else {
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001049 //use PC relative branch call
Andrew Lenharthb301af72005-02-10 20:10:38 +00001050 //BuildMI(BB, Alpha::BSR, 1, Alpha::R26).addGlobalAddress(GASD->getGlobal(),true);
1051 //}
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001052 }
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001053 else if (ExternalSymbolSDNode *ESSDN =
Andrew Lenharth71413342005-01-30 20:42:36 +00001054 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001055 {
1056 AlphaLowering.restoreGP(BB);
Andrew Lenharthe3d9f8c2005-03-30 18:22:52 +00001057 BuildMI(BB, Alpha::CALL, 1).addExternalSymbol(ESSDN->getSymbol(), true);
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001058 } else {
1059 //no need to restore GP as we are doing an indirect call
1060 Tmp1 = SelectExpr(N.getOperand(1));
1061 BuildMI(BB, Alpha::BIS, 2, Alpha::R27).addReg(Tmp1).addReg(Tmp1);
1062 BuildMI(BB, Alpha::JSR, 2, Alpha::R26).addReg(Alpha::R27).addImm(0);
1063 }
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001064
1065 //push the result into a virtual register
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001066
1067 switch (Node->getValueType(0)) {
1068 default: Node->dump(); assert(0 && "Unknown value type for call result!");
Andrew Lenharth4a0d2002005-01-28 23:17:54 +00001069 case MVT::Other: return notIn;
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001070 case MVT::i1:
1071 case MVT::i8:
1072 case MVT::i16:
1073 case MVT::i32:
1074 case MVT::i64:
1075 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
1076 break;
1077 case MVT::f32:
1078 case MVT::f64:
1079 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
1080 break;
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001081 }
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001082 return Result+N.ResNo;
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001083 }
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001084
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001085 case ISD::SIGN_EXTEND:
Andrew Lenharth3c361fd2005-01-27 03:49:45 +00001086 abort();
1087
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001088 case ISD::SIGN_EXTEND_INREG:
1089 {
Andrew Lenharth6294dee2005-03-22 00:24:07 +00001090 //do SDIV opt for all levels of ints
Andrew Lenharth3bf6f802005-03-31 22:02:25 +00001091 if (EnableAlphaIDIV && N.getOperand(0).getOpcode() == ISD::SDIV)
Andrew Lenharth6294dee2005-03-22 00:24:07 +00001092 {
1093 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1094 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1095 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1096 MachineFunction *F = BB->getParent();
1097 int FrameIdxL = F->getFrameInfo()->CreateStackObject(Size, 8);
1098 int FrameIdxR = F->getFrameInfo()->CreateStackObject(Size, 8);
1099 int FrameIdxF = F->getFrameInfo()->CreateStackObject(Size, 8);
1100 unsigned Tmp4 = MakeReg(MVT::f64);
1101 unsigned Tmp5 = MakeReg(MVT::f64);
1102 unsigned Tmp6 = MakeReg(MVT::f64);
1103 unsigned Tmp7 = MakeReg(MVT::f64);
1104 unsigned Tmp8 = MakeReg(MVT::f64);
1105 unsigned Tmp9 = MakeReg(MVT::f64);
1106
1107 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdxL).addReg(Alpha::F31);
Andrew Lenharth82f364512005-03-23 15:20:01 +00001108 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp2).addFrameIndex(FrameIdxR).addReg(Alpha::F31);
Andrew Lenharth6294dee2005-03-22 00:24:07 +00001109 BuildMI(BB, Alpha::LDT, 2, Tmp4).addFrameIndex(FrameIdxL).addReg(Alpha::F31);
1110 BuildMI(BB, Alpha::LDT, 2, Tmp5).addFrameIndex(FrameIdxR).addReg(Alpha::F31);
1111 BuildMI(BB, Alpha::CVTQT, 1, Tmp6).addReg(Tmp4);
1112 BuildMI(BB, Alpha::CVTQT, 1, Tmp7).addReg(Tmp5);
1113 BuildMI(BB, Alpha::DIVT, 2, Tmp8).addReg(Tmp6).addReg(Tmp7);
1114 BuildMI(BB, Alpha::CVTTQ, 1, Tmp9).addReg(Tmp8);
1115 BuildMI(BB, Alpha::STT, 3).addReg(Tmp9).addFrameIndex(FrameIdxF).addReg(Alpha::F31);
Andrew Lenharth82f364512005-03-23 15:20:01 +00001116 BuildMI(BB, Alpha::LDQ, 2, Result).addFrameIndex(FrameIdxF).addReg(Alpha::F31);
Andrew Lenharth6294dee2005-03-22 00:24:07 +00001117 return Result;
1118 }
1119
Andrew Lenharth4a0d2002005-01-28 23:17:54 +00001120 //Alpha has instructions for a bunch of signed 32 bit stuff
1121 if( dyn_cast<MVTSDNode>(Node)->getExtraValueType() == MVT::i32)
Andrew Lenharth6294dee2005-03-22 00:24:07 +00001122 {
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001123 switch (N.getOperand(0).getOpcode()) {
1124 case ISD::ADD:
1125 case ISD::SUB:
1126 case ISD::MUL:
1127 {
1128 bool isAdd = N.getOperand(0).getOpcode() == ISD::ADD;
1129 bool isMul = N.getOperand(0).getOpcode() == ISD::MUL;
1130 //FIXME: first check for Scaled Adds and Subs!
1131 if(N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1132 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() <= 255)
1133 { //Normal imm add/sub
1134 Opc = isAdd ? Alpha::ADDLi : (isMul ? Alpha::MULLi : Alpha::SUBLi);
Andrew Lenharthd39febf2005-02-12 21:11:17 +00001135 //if the value was really originally a i32, skip the up conversion
1136 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1137 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1138 ->getExtraValueType() == MVT::i32)
1139 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1140 else
1141 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001142 Tmp2 = cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue();
1143 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth4a0d2002005-01-28 23:17:54 +00001144 }
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001145 else
1146 { //Normal add/sub
1147 Opc = isAdd ? Alpha::ADDL : (isMul ? Alpha::MULLi : Alpha::SUBL);
Andrew Lenharthd39febf2005-02-12 21:11:17 +00001148 //if the value was really originally a i32, skip the up conversion
1149 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1150 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1151 ->getExtraValueType() == MVT::i32)
1152 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1153 else
1154 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1155 //if the value was really originally a i32, skip the up conversion
1156 if (N.getOperand(0).getOperand(1).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1157 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(1).Val)
1158 ->getExtraValueType() == MVT::i32)
1159 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0));
1160 else
1161 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1162
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001163 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1164 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1165 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1166 }
1167 return Result;
Andrew Lenharth4a0d2002005-01-28 23:17:54 +00001168 }
Andrew Lenharth180a04a2005-03-02 17:23:03 +00001169 case ISD::SEXTLOAD:
1170 //SelectionDag isn't deleting the signextend after sextloads
1171 Reg = Result = SelectExpr(N.getOperand(0));
1172 return Result;
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001173 default: break; //Fall Though;
1174 }
1175 } //Every thing else fall though too, including unhandled opcodes above
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001176 Tmp1 = SelectExpr(N.getOperand(0));
1177 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001178 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001179 switch(MVN->getExtraValueType())
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001180 {
1181 default:
1182 Node->dump();
1183 assert(0 && "Sign Extend InReg not there yet");
1184 break;
1185 case MVT::i32:
Andrew Lenharth3c361fd2005-01-27 03:49:45 +00001186 {
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001187 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
Andrew Lenharth3c361fd2005-01-27 03:49:45 +00001188 break;
1189 }
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001190 case MVT::i16:
1191 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
1192 break;
1193 case MVT::i8:
1194 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
1195 break;
Andrew Lenharth76c5d972005-02-12 19:35:12 +00001196 case MVT::i1:
1197 Tmp2 = MakeReg(MVT::i64);
1198 BuildMI(BB, Alpha::ANDi, 2, Tmp2).addReg(Tmp1).addImm(1);
Andrew Lenharthdf5cd082005-02-12 20:42:09 +00001199 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Alpha::F31).addReg(Tmp2);
Andrew Lenharth76c5d972005-02-12 19:35:12 +00001200 break;
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001201 }
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001202 return Result;
1203 }
1204 case ISD::ZERO_EXTEND_INREG:
1205 {
1206 Tmp1 = SelectExpr(N.getOperand(0));
1207 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001208 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001209 switch(MVN->getExtraValueType())
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001210 {
1211 default:
1212 Node->dump();
1213 assert(0 && "Zero Extend InReg not there yet");
1214 break;
1215 case MVT::i32: Tmp2 = 0xf0; break;
1216 case MVT::i16: Tmp2 = 0xfc; break;
1217 case MVT::i8: Tmp2 = 0xfe; break;
1218 case MVT::i1: //handle this one special
1219 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
1220 return Result;
1221 }
Andrew Lenharth122489b2005-01-25 00:35:34 +00001222 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3c361fd2005-01-27 03:49:45 +00001223 return Result;
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001224 }
1225
1226 case ISD::SETCC:
Andrew Lenharth3c361fd2005-01-27 03:49:45 +00001227 {
1228 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
1229 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
1230 bool isConst1 = false;
1231 bool isConst2 = false;
1232 int dir;
Andrew Lenharth060d58b2005-02-05 13:19:12 +00001233
Andrew Lenharth3c361fd2005-01-27 03:49:45 +00001234 //Tmp1 = SelectExpr(N.getOperand(0));
1235 if(N.getOperand(0).getOpcode() == ISD::Constant &&
Andrew Lenharth3c361fd2005-01-27 03:49:45 +00001236 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1237 isConst1 = true;
1238 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth3c361fd2005-01-27 03:49:45 +00001239 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1240 isConst2 = true;
1241
1242 switch (SetCC->getCondition()) {
1243 default: Node->dump(); assert(0 && "Unknown integer comparison!");
1244 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001245 case ISD::SETLT:
1246 Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
1247 case ISD::SETLE:
1248 Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
1249 case ISD::SETGT:
1250 Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
1251 case ISD::SETGE:
1252 Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
1253 case ISD::SETULT:
1254 Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
1255 case ISD::SETUGT:
1256 Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
1257 case ISD::SETULE:
1258 Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
1259 case ISD::SETUGE:
1260 Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharth0cceb512005-01-27 07:50:35 +00001261 case ISD::SETNE: {//Handle this one special
1262 //std::cerr << "Alpha does not have a setne.\n";
1263 //abort();
1264 Tmp1 = SelectExpr(N.getOperand(0));
1265 Tmp2 = SelectExpr(N.getOperand(1));
1266 Tmp3 = MakeReg(MVT::i64);
1267 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth8ec0a2b2005-02-08 00:40:03 +00001268 //Remeber we have the Inv for this CC
1269 CCInvMap[N] = Tmp3;
Andrew Lenharth0cceb512005-01-27 07:50:35 +00001270 //and invert
Andrew Lenharth4a0d2002005-01-28 23:17:54 +00001271 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
Andrew Lenharth0cceb512005-01-27 07:50:35 +00001272 return Result;
1273 }
1274 }
Andrew Lenharth3c361fd2005-01-27 03:49:45 +00001275 if (dir == 1) {
1276 Tmp1 = SelectExpr(N.getOperand(0));
1277 if (isConst2) {
1278 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1279 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1280 } else {
1281 Tmp2 = SelectExpr(N.getOperand(1));
1282 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1283 }
1284 } else if (dir == 2) {
1285 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth579a3242005-01-28 14:06:46 +00001286 if (isConst1) {
Andrew Lenharth3c361fd2005-01-27 03:49:45 +00001287 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1288 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1289 } else {
1290 Tmp2 = SelectExpr(N.getOperand(0));
1291 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1292 }
1293 } else { //dir == 0
1294 if (isConst1) {
1295 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1296 Tmp2 = SelectExpr(N.getOperand(1));
1297 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
1298 } else if (isConst2) {
1299 Tmp1 = SelectExpr(N.getOperand(0));
1300 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1301 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
1302 } else {
1303 Tmp1 = SelectExpr(N.getOperand(0));
1304 Tmp2 = SelectExpr(N.getOperand(1));
1305 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
1306 }
Andrew Lenharthea9224a2005-02-05 16:41:03 +00001307 }
1308 } else {
1309 //assert(SetCC->getOperand(0).getValueType() != MVT::f32 && "SetCC f32 should have been promoted");
1310 bool rev = false;
1311 bool inv = false;
1312
1313 switch (SetCC->getCondition()) {
1314 default: Node->dump(); assert(0 && "Unknown FP comparison!");
1315 case ISD::SETEQ: Opc = Alpha::CMPTEQ; break;
1316 case ISD::SETLT: Opc = Alpha::CMPTLT; break;
1317 case ISD::SETLE: Opc = Alpha::CMPTLE; break;
1318 case ISD::SETGT: Opc = Alpha::CMPTLT; rev = true; break;
1319 case ISD::SETGE: Opc = Alpha::CMPTLE; rev = true; break;
1320 case ISD::SETNE: Opc = Alpha::CMPTEQ; inv = true; break;
1321 }
1322
Andrew Lenharth0b9096b2005-03-14 19:23:45 +00001323 //FIXME: check for constant 0.0
1324 ConstantFPSDNode *CN;
1325 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
1326 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1327 Tmp1 = Alpha::F31;
1328 else
1329 Tmp1 = SelectExpr(N.getOperand(0));
1330
1331 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
1332 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1333 Tmp2 = Alpha::F31;
1334 else
1335 Tmp2 = SelectExpr(N.getOperand(1));
1336
Andrew Lenharthea9224a2005-02-05 16:41:03 +00001337 //Can only compare doubles, and dag won't promote for me
1338 if (SetCC->getOperand(0).getValueType() == MVT::f32)
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001339 {
Andrew Lenharth7ac01432005-02-22 21:59:48 +00001340 //assert(0 && "Setcc On float?\n");
1341 std::cerr << "Setcc on float!\n";
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001342 Tmp3 = MakeReg(MVT::f64);
1343 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp1);
1344 Tmp1 = Tmp3;
1345 }
Andrew Lenharthea9224a2005-02-05 16:41:03 +00001346 if (SetCC->getOperand(1).getValueType() == MVT::f32)
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001347 {
Andrew Lenharth7ac01432005-02-22 21:59:48 +00001348 //assert (0 && "Setcc On float?\n");
1349 std::cerr << "Setcc on float!\n";
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001350 Tmp3 = MakeReg(MVT::f64);
1351 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp2);
Andrew Lenharthcae2f212005-02-14 05:41:43 +00001352 Tmp2 = Tmp3;
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001353 }
Andrew Lenharth060d58b2005-02-05 13:19:12 +00001354
Andrew Lenharthea9224a2005-02-05 16:41:03 +00001355 if (rev) std::swap(Tmp1, Tmp2);
1356 Tmp3 = MakeReg(MVT::f64);
1357 //do the comparison
1358 BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
1359
1360 //now arrange for Result (int) to have a 1 or 0
Andrew Lenharth6294dee2005-03-22 00:24:07 +00001361 unsigned Tmp4 = MakeReg(MVT::i64);
1362 BuildMI(BB, Alpha::ADDQi, 2, Tmp4).addReg(Alpha::R31).addImm(1);
1363 Opc = inv?Alpha::CMOVNEi_FP:Alpha::CMOVEQi_FP;
1364 BuildMI(BB, Opc, 3, Result).addReg(Tmp4).addImm(0).addReg(Tmp3);
Andrew Lenharth0b9096b2005-03-14 19:23:45 +00001365
1366// // Spill the FP to memory and reload it from there.
1367// unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1368// MachineFunction *F = BB->getParent();
1369// int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
1370// unsigned Tmp4 = MakeReg(MVT::f64);
1371// BuildMI(BB, Alpha::CVTTQ, 1, Tmp4).addReg(Tmp3);
1372// BuildMI(BB, Alpha::STT, 3).addReg(Tmp4).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1373// unsigned Tmp5 = MakeReg(MVT::i64);
1374// BuildMI(BB, Alpha::LDQ, 2, Tmp5).addFrameIndex(FrameIdx).addReg(Alpha::F31);
Andrew Lenharth060d58b2005-02-05 13:19:12 +00001375
Andrew Lenharth0b9096b2005-03-14 19:23:45 +00001376// //now, set result based on Tmp5
1377// //Set Tmp6 if fp cmp was false
1378// unsigned Tmp6 = MakeReg(MVT::i64);
1379// BuildMI(BB, Alpha::CMPEQ, 2, Tmp6).addReg(Tmp5).addReg(Alpha::R31);
1380// //and invert
1381// BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp6).addReg(Alpha::R31);
Andrew Lenharthea9224a2005-02-05 16:41:03 +00001382
1383 }
1384 // else
1385 // {
1386 // Node->dump();
1387 // assert(0 && "Not a setcc in setcc");
1388 // }
Andrew Lenharth060d58b2005-02-05 13:19:12 +00001389 }
Andrew Lenharth3c361fd2005-01-27 03:49:45 +00001390 return Result;
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001391 }
Andrew Lenharth3c361fd2005-01-27 03:49:45 +00001392
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001393 case ISD::CopyFromReg:
1394 {
Andrew Lenharth479bc612005-01-28 06:57:18 +00001395 // Make sure we generate both values.
Andrew Lenharth4a0d2002005-01-28 23:17:54 +00001396 if (Result != notIn)
1397 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth479bc612005-01-28 06:57:18 +00001398 else
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001399 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth479bc612005-01-28 06:57:18 +00001400
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001401 SDOperand Chain = N.getOperand(0);
1402
1403 Select(Chain);
1404 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
1405 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
1406 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
1407 return Result;
1408 }
1409
Andrew Lenharth2f0f8452005-01-24 19:44:07 +00001410 //Most of the plain arithmetic and logic share the same form, and the same
1411 //constant immediate test
1412 case ISD::AND:
1413 case ISD::OR:
1414 case ISD::XOR:
1415 case ISD::SHL:
1416 case ISD::SRL:
Andrew Lenharth41bc2c22005-01-29 15:42:07 +00001417 case ISD::SRA:
Andrew Lenharth2f0f8452005-01-24 19:44:07 +00001418 case ISD::MUL:
Andrew Lenharth479bc612005-01-28 06:57:18 +00001419 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
1420 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth479bc612005-01-28 06:57:18 +00001421 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001422 {
1423 switch(opcode) {
1424 case ISD::AND: Opc = Alpha::ANDi; break;
1425 case ISD::OR: Opc = Alpha::BISi; break;
1426 case ISD::XOR: Opc = Alpha::XORi; break;
1427 case ISD::SHL: Opc = Alpha::SLi; break;
1428 case ISD::SRL: Opc = Alpha::SRLi; break;
1429 case ISD::SRA: Opc = Alpha::SRAi; break;
1430 case ISD::MUL: Opc = Alpha::MULQi; break;
1431 };
1432 Tmp1 = SelectExpr(N.getOperand(0));
1433 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1434 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1435 } else {
1436 switch(opcode) {
1437 case ISD::AND: Opc = Alpha::AND; break;
1438 case ISD::OR: Opc = Alpha::BIS; break;
1439 case ISD::XOR: Opc = Alpha::XOR; break;
1440 case ISD::SHL: Opc = Alpha::SL; break;
1441 case ISD::SRL: Opc = Alpha::SRL; break;
1442 case ISD::SRA: Opc = Alpha::SRA; break;
1443 case ISD::MUL: Opc = Alpha::MULQ; break;
1444 };
1445 Tmp1 = SelectExpr(N.getOperand(0));
1446 Tmp2 = SelectExpr(N.getOperand(1));
1447 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1448 }
Andrew Lenharth2f0f8452005-01-24 19:44:07 +00001449 return Result;
Andrew Lenharth479bc612005-01-28 06:57:18 +00001450
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001451 case ISD::ADD:
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001452 case ISD::SUB:
Andrew Lenharth122489b2005-01-25 00:35:34 +00001453 {
Andrew Lenharth479bc612005-01-28 06:57:18 +00001454 bool isAdd = opcode == ISD::ADD;
1455
1456 //FIXME: first check for Scaled Adds and Subs!
1457 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth479bc612005-01-28 06:57:18 +00001458 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001459 { //Normal imm add/sub
1460 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
1461 Tmp1 = SelectExpr(N.getOperand(0));
1462 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1463 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1464 }
Andrew Lenharth479bc612005-01-28 06:57:18 +00001465 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth180a04a2005-03-02 17:23:03 +00001466 (cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767 ||
1467 (long)cast<ConstantSDNode>(N.getOperand(1))->getValue() >= -32767))
1468 { //LDA
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001469 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth180a04a2005-03-02 17:23:03 +00001470 Tmp2 = (long)cast<ConstantSDNode>(N.getOperand(1))->getValue();
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001471 if (!isAdd)
1472 Tmp2 = -Tmp2;
1473 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
1474 } else {
1475 //Normal add/sub
1476 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
1477 Tmp1 = SelectExpr(N.getOperand(0));
1478 Tmp2 = SelectExpr(N.getOperand(1));
1479 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1480 }
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001481 return Result;
1482 }
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001483
Andrew Lenharth6294dee2005-03-22 00:24:07 +00001484 case ISD::SDIV:
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001485 case ISD::UREM:
Andrew Lenharth02c54592005-01-26 01:24:38 +00001486 case ISD::SREM:
Andrew Lenharth02c54592005-01-26 01:24:38 +00001487 case ISD::UDIV:
Andrew Lenharth479bc612005-01-28 06:57:18 +00001488 //FIXME: alpha really doesn't support any of these operations,
1489 // the ops are expanded into special library calls with
1490 // special calling conventions
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001491 //Restore GP because it is a call after all...
Andrew Lenharth479bc612005-01-28 06:57:18 +00001492 switch(opcode) {
Andrew Lenharth10bc4c02005-02-25 22:55:15 +00001493 case ISD::UREM: Opc = Alpha::REMQU; break;
1494 case ISD::SREM: Opc = Alpha::REMQ; break;
1495 case ISD::UDIV: Opc = Alpha::DIVQU; break;
1496 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001497 }
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001498 Tmp1 = SelectExpr(N.getOperand(0));
1499 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth8df62dd2005-03-04 20:09:23 +00001500 //set up regs explicitly (helps Reg alloc)
1501 BuildMI(BB, Alpha::BIS, 2, Alpha::R24).addReg(Tmp1).addReg(Tmp1);
1502 BuildMI(BB, Alpha::BIS, 2, Alpha::R25).addReg(Tmp2).addReg(Tmp2);
Andrew Lenharth10bc4c02005-02-25 22:55:15 +00001503 AlphaLowering.restoreGP(BB);
Andrew Lenharth8df62dd2005-03-04 20:09:23 +00001504 BuildMI(BB, Opc, 2).addReg(Alpha::R24).addReg(Alpha::R25);
1505 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R27).addReg(Alpha::R27);
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001506 return Result;
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001507
Andrew Lenharth9df6a762005-02-01 20:40:27 +00001508 case ISD::FP_TO_UINT:
Andrew Lenharthc40d1562005-01-31 01:44:26 +00001509 case ISD::FP_TO_SINT:
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001510 {
Andrew Lenharthc40d1562005-01-31 01:44:26 +00001511 assert (DestType == MVT::i64 && "only quads can be loaded to");
1512 MVT::ValueType SrcType = N.getOperand(0).getValueType();
Andrew Lenharth351df0c2005-02-07 05:55:55 +00001513 assert (SrcType == MVT::f32 || SrcType == MVT::f64);
Andrew Lenharthc40d1562005-01-31 01:44:26 +00001514 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
1515
1516 //The hard way:
1517 // Spill the integer to memory and reload it from there.
1518 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1519 MachineFunction *F = BB->getParent();
1520 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
1521
1522 //CVTTQ STT LDQ
1523 //CVTST CVTTQ STT LDQ
1524 if (SrcType == MVT::f32)
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001525 {
1526 Tmp2 = MakeReg(MVT::f64);
1527 BuildMI(BB, Alpha::CVTST, 1, Tmp2).addReg(Tmp1);
1528 Tmp1 = Tmp2;
1529 }
Andrew Lenharthc40d1562005-01-31 01:44:26 +00001530 Tmp2 = MakeReg(MVT::f64);
1531 BuildMI(BB, Alpha::CVTTQ, 1, Tmp2).addReg(Tmp1);
1532 BuildMI(BB, Alpha::STT, 3).addReg(Tmp2).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1533 BuildMI(BB, Alpha::LDQ, 2, Result).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1534
1535 return Result;
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001536 }
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001537
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001538 // // case ISD::FP_TO_UINT:
Andrew Lenharth5ae5f812005-01-26 21:54:09 +00001539
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001540 case ISD::SELECT:
1541 {
Andrew Lenharth6294dee2005-03-22 00:24:07 +00001542 //FIXME: look at parent to decide if intCC can be folded, or if setCC(FP) and can save stack use
Andrew Lenharth9df6a762005-02-01 20:40:27 +00001543 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001544 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1545 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001546 // Get the condition into the zero flag.
Andrew Lenharth9df6a762005-02-01 20:40:27 +00001547 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001548 return Result;
1549 }
1550
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001551 case ISD::Constant:
1552 {
Andrew Lenharth93d00892005-03-29 19:24:04 +00001553 int64_t val = (int64_t)cast<ConstantSDNode>(N)->getValue();
Andrew Lenharth27a3df02005-03-11 17:48:05 +00001554 if (val <= IMM_HIGH && val >= IMM_LOW) {
1555 BuildMI(BB, Alpha::LDA, 2, Result).addImm(val).addReg(Alpha::R31);
1556 }
1557 else if (val <= (int64_t)IMM_HIGH + (int64_t)IMM_HIGH * (int64_t)IMM_MULT &&
1558 val >= (int64_t)IMM_LOW + (int64_t)IMM_LOW * (int64_t)IMM_MULT) {
1559 Tmp1 = MakeReg(MVT::i64);
1560 BuildMI(BB, Alpha::LDAH, 2, Tmp1).addImm(getUpper16(val)).addReg(Alpha::R31);
1561 BuildMI(BB, Alpha::LDA, 2, Result).addImm(getLower16(val)).addReg(Tmp1);
1562 }
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001563 else {
1564 MachineConstantPool *CP = BB->getParent()->getConstantPool();
1565 ConstantUInt *C = ConstantUInt::get(Type::getPrimitiveType(Type::ULongTyID) , val);
1566 unsigned CPI = CP->getConstantPoolIndex(C);
1567 AlphaLowering.restoreGP(BB);
1568 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(CPI);
1569 }
1570 return Result;
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001571 }
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001572 }
1573
1574 return 0;
1575}
1576
1577void ISel::Select(SDOperand N) {
1578 unsigned Tmp1, Tmp2, Opc;
Andrew Lenharthd4f440d2005-02-07 23:02:23 +00001579 unsigned opcode = N.getOpcode();
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001580
Nate Begeman95210522005-03-24 04:39:54 +00001581 if (!ExprMap.insert(std::make_pair(N, notIn)).second)
Andrew Lenharth579a3242005-01-28 14:06:46 +00001582 return; // Already selected.
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001583
1584 SDNode *Node = N.Val;
Andrew Lenharthd4f440d2005-02-07 23:02:23 +00001585
Andrew Lenharthd4f440d2005-02-07 23:02:23 +00001586 switch (opcode) {
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001587
1588 default:
1589 Node->dump(); std::cerr << "\n";
1590 assert(0 && "Node not handled yet!");
1591
1592 case ISD::BRCOND: {
Andrew Lenharth8ec0a2b2005-02-08 00:40:03 +00001593 SelectBranchCC(N);
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001594 return;
1595 }
1596
1597 case ISD::BR: {
1598 MachineBasicBlock *Dest =
1599 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
1600
1601 Select(N.getOperand(0));
1602 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
1603 return;
1604 }
1605
1606 case ISD::ImplicitDef:
1607 Select(N.getOperand(0));
1608 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
1609 return;
1610
1611 case ISD::EntryToken: return; // Noop
1612
1613 case ISD::TokenFactor:
1614 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
1615 Select(Node->getOperand(i));
1616
1617 //N.Val->dump(); std::cerr << "\n";
1618 //assert(0 && "Node not handled yet!");
1619
1620 return;
1621
1622 case ISD::CopyToReg:
1623 Select(N.getOperand(0));
1624 Tmp1 = SelectExpr(N.getOperand(1));
1625 Tmp2 = cast<RegSDNode>(N)->getReg();
1626
1627 if (Tmp1 != Tmp2) {
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001628 if (N.getOperand(1).getValueType() == MVT::f64 ||
1629 N.getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth9d3f7702005-02-07 06:31:44 +00001630 BuildMI(BB, Alpha::CPYS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
1631 else
1632 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001633 }
1634 return;
1635
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001636 case ISD::RET:
1637 switch (N.getNumOperands()) {
1638 default:
1639 std::cerr << N.getNumOperands() << "\n";
1640 for (unsigned i = 0; i < N.getNumOperands(); ++i)
1641 std::cerr << N.getOperand(i).getValueType() << "\n";
1642 Node->dump();
1643 assert(0 && "Unknown return instruction!");
1644 case 2:
1645 Select(N.getOperand(0));
1646 Tmp1 = SelectExpr(N.getOperand(1));
1647 switch (N.getOperand(1).getValueType()) {
1648 default: Node->dump();
1649 assert(0 && "All other types should have been promoted!!");
1650 case MVT::f64:
1651 case MVT::f32:
1652 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
1653 break;
1654 case MVT::i32:
1655 case MVT::i64:
1656 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
1657 break;
1658 }
1659 break;
1660 case 1:
1661 Select(N.getOperand(0));
1662 break;
1663 }
1664 //Tmp2 = AlphaLowering.getRetAddr();
1665 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
1666 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
1667 return;
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001668
Andrew Lenharth5fb9b532005-02-07 05:18:02 +00001669 case ISD::TRUNCSTORE:
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001670 case ISD::STORE:
Andrew Lenharth75c62252005-02-02 17:32:39 +00001671 {
Andrew Lenharth6c018f72005-02-06 15:40:40 +00001672 SDOperand Chain = N.getOperand(0);
1673 SDOperand Value = N.getOperand(1);
1674 SDOperand Address = N.getOperand(2);
1675 Select(Chain);
1676
1677 Tmp1 = SelectExpr(Value); //value
Andrew Lenharthd4f440d2005-02-07 23:02:23 +00001678
1679 if (opcode == ISD::STORE) {
1680 switch(Value.getValueType()) {
1681 default: assert(0 && "unknown Type in store");
1682 case MVT::i64: Opc = Alpha::STQ; break;
1683 case MVT::f64: Opc = Alpha::STT; break;
1684 case MVT::f32: Opc = Alpha::STS; break;
1685 }
1686 } else { //ISD::TRUNCSTORE
1687 switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
1688 default: assert(0 && "unknown Type in store");
1689 case MVT::i1: //FIXME: DAG does not promote this load
1690 case MVT::i8: Opc = Alpha::STB; break;
1691 case MVT::i16: Opc = Alpha::STW; break;
1692 case MVT::i32: Opc = Alpha::STL; break;
1693 }
Andrew Lenhartheefd4102005-02-06 16:22:15 +00001694 }
Andrew Lenharthd4f440d2005-02-07 23:02:23 +00001695
Andrew Lenharth6c018f72005-02-06 15:40:40 +00001696 if (Address.getOpcode() == ISD::GlobalAddress)
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001697 {
1698 AlphaLowering.restoreGP(BB);
1699 Opc = GetSymVersion(Opc);
1700 BuildMI(BB, Opc, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1701 }
Andrew Lenhartha9e02152005-02-07 05:07:00 +00001702 else if(Address.getOpcode() == ISD::FrameIndex)
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001703 {
Andrew Lenharth7ac01432005-02-22 21:59:48 +00001704 BuildMI(BB, Opc, 3).addReg(Tmp1)
1705 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1706 .addReg(Alpha::F31);
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001707 }
Andrew Lenharth75c62252005-02-02 17:32:39 +00001708 else
Andrew Lenharthe0b789f2005-02-10 06:25:22 +00001709 {
1710 long offset;
1711 SelectAddr(Address, Tmp2, offset);
1712 BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
1713 }
Andrew Lenharth75c62252005-02-02 17:32:39 +00001714 return;
1715 }
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001716
1717 case ISD::EXTLOAD:
1718 case ISD::SEXTLOAD:
1719 case ISD::ZEXTLOAD:
1720 case ISD::LOAD:
1721 case ISD::CopyFromReg:
1722 case ISD::CALL:
Andrew Lenharth7ac01432005-02-22 21:59:48 +00001723 case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth579a3242005-01-28 14:06:46 +00001724 ExprMap.erase(N);
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001725 SelectExpr(N);
1726 return;
1727
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001728 case ISD::ADJCALLSTACKDOWN:
1729 case ISD::ADJCALLSTACKUP:
1730 Select(N.getOperand(0));
1731 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1732
1733 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
1734 Alpha::ADJUSTSTACKUP;
1735 BuildMI(BB, Opc, 1).addImm(Tmp1);
1736 return;
Andrew Lenharthdec53922005-03-31 21:24:06 +00001737
1738 case ISD::PCMARKER:
1739 Select(N.getOperand(0)); //Chain
1740 BuildMI(BB, Alpha::PCLABEL, 2).addImm( cast<ConstantSDNode>(N.getOperand(1))->getValue());
1741 return;
Andrew Lenhartha1b5ca22005-01-22 23:41:55 +00001742 }
1743 assert(0 && "Should not be reached!");
1744}
1745
1746
1747/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
1748/// into a machine code representation using pattern matching and a machine
1749/// description file.
1750///
1751FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
1752 return new ISel(TM);
1753}