blob: a0f3e8e93fee6508881cebdd5b5c55c30e83f7f6 [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
Andrew Lenharth33819132005-03-04 20:09:23 +000078 //Doesn't work yet
Andrew Lenharth572af902005-02-14 05:41:43 +000079 setOperationAction(ISD::SETCC , MVT::f32, Promote);
80
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000081 computeRegisterProperties();
Andrew Lenharth304d0f32005-01-22 23:41:55 +000082
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000083 addLegalFPImmediate(+0.0); //F31
84 addLegalFPImmediate(-0.0); //-F31
Andrew Lenharth304d0f32005-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 Lenharth63f2ab22005-02-10 06:25:22 +000091
Andrew Lenharth304d0f32005-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 Begeman8e21e712005-03-26 01:29:23 +000095 LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
96 SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000097
Andrew Lenharth304d0f32005-01-22 23:41:55 +000098 virtual std::pair<SDOperand, SDOperand>
99 LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000100
Andrew Lenharth304d0f32005-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 Lenharth05380342005-02-07 05:07:00 +0000141 MachineFrameInfo*MFI = MF.getFrameInfo();
Andrew Lenharth304d0f32005-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 Lenharth3e98fde2005-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 Lenharth2c9e38c2005-02-06 21:07:31 +0000153 unsigned argVreg[6];
154 unsigned argPreg[6];
155 unsigned argOpc[6];
156
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000157 int count = 0;
Andrew Lenharth2c9e38c2005-02-06 21:07:31 +0000158
Chris Lattnere4d5c442005-03-15 04:54:21 +0000159 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
Andrew Lenharth63f2ab22005-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 Lenharth032f2352005-02-22 21:59:48 +0000172 getRegClassFor(getValueType(I->getType())));
Andrew Lenharth63f2ab22005-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 Lenharth40831c52005-01-28 06:57:18 +0000195 }
Andrew Lenharth63f2ab22005-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 Lenharth304d0f32005-01-22 23:41:55 +0000205 }
Andrew Lenharth032f2352005-02-22 21:59:48 +0000206 ++count;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000207 DAG.setRoot(newroot.getValue(1));
208 ArgValues.push_back(argt);
209 }
Andrew Lenharth304d0f32005-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 Lenharth032f2352005-02-22 21:59:48 +0000213 for (int i = 0; i < count && i < 6; ++i) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000214 BuildMI(&BB, argOpc[i], 2,
215 argVreg[i]).addReg(argPreg[i]).addReg(argPreg[i]);
216 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000217
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000218 return ArgValues;
219}
220
221std::pair<SDOperand, SDOperand>
222AlphaTargetLowering::LowerCallTo(SDOperand Chain,
Nate Begeman8e21e712005-03-26 01:29:23 +0000223 const Type *RetTy, bool isVarArg,
224 SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000225 int NumBytes = 0;
Andrew Lenharth684f2292005-01-30 00:35:27 +0000226 if (Args.size() > 6)
227 NumBytes = (Args.size() - 6) * 8;
228
Andrew Lenharth304d0f32005-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 Lenharth63f2ab22005-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 Lenharth304d0f32005-01-22 23:41:55 +0000251 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000252 args_to_use.push_back(Args[i].first);
253 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000254
Andrew Lenharth304d0f32005-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 Lenharth63f2ab22005-02-10 06:25:22 +0000261 SDOperand TheCall = SDOperand(DAG.getCall(RetVals,
262 Chain, Callee, args_to_use), 0);
Andrew Lenharth304d0f32005-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 Lenharth63f2ab22005-02-10 06:25:22 +0000266 return std::make_pair(TheCall, Chain);
Andrew Lenharth304d0f32005-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 Lenharth63f2ab22005-02-10 06:25:22 +0000277 const Type *ArgTy, SelectionDAG &DAG) {
Andrew Lenharth304d0f32005-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 Lenharth63f2ab22005-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 Lenharth032f2352005-02-22 21:59:48 +0000321 DEBUG(BB->dump());
Andrew Lenharth63f2ab22005-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 Lenharth304d0f32005-01-22 23:41:55 +0000337}
338
Andrew Lenharthe87f6c32005-03-11 17:48:05 +0000339//These describe LDAx
Andrew Lenharthc0513832005-03-29 19:24:04 +0000340static const int IMM_LOW = -32768;
341static const int IMM_HIGH = 32767;
Andrew Lenharthe87f6c32005-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 Lenharth65838902005-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 Lenharth9e8d1092005-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 Lenharth63f2ab22005-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 Lenharth9e8d1092005-02-06 15:40:40 +0000398 }
399 Reg = SelectExpr(N);
400 offset = 0;
401 return;
402}
403
Andrew Lenharth445171a2005-02-08 00:40:03 +0000404void ISel::SelectBranchCC(SDOperand N)
405{
406 assert(N.getOpcode() == ISD::BRCOND && "Not a BranchCC???");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000407 MachineBasicBlock *Dest =
408 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
409 unsigned Opc = Alpha::WTF;
410
Andrew Lenharth445171a2005-02-08 00:40:03 +0000411 Select(N.getOperand(0)); //chain
412 SDOperand CC = N.getOperand(1);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000413
Andrew Lenharth445171a2005-02-08 00:40:03 +0000414 if (CC.getOpcode() == ISD::SETCC)
Andrew Lenharth63f2ab22005-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 Lenharth445171a2005-02-08 00:40:03 +0000422
Andrew Lenharth63f2ab22005-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 Lenharth445171a2005-02-08 00:40:03 +0000431
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000432 if (isZero0) {
Andrew Lenharth445171a2005-02-08 00:40:03 +0000433 switch (SetCC->getCondition()) {
Andrew Lenharth63f2ab22005-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 Lenharth445171a2005-02-08 00:40:03 +0000445 }
Andrew Lenharth63f2ab22005-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 Lenharth445171a2005-02-08 00:40:03 +0000472 return;
473 }
Andrew Lenharth63f2ab22005-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 Lenharth2b6c4f52005-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 Lenharth63f2ab22005-02-10 06:25:22 +0000504
505 switch (SetCC->getCondition()) {
506 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
Andrew Lenharth2b6c4f52005-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 Lenharth63f2ab22005-02-10 06:25:22 +0000513 }
514 BuildMI(BB, Opc, 2).addReg(Tmp3).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000515 return;
516 }
Andrew Lenharth63f2ab22005-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 Lenharth445171a2005-02-08 00:40:03 +0000524 abort(); //Should never be reached
525}
526
Andrew Lenharth40831c52005-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 Lenharth2c594352005-01-29 15:42:07 +0000539
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000540 case ISD::FNEG:
541 if(ISD::FABS == N.getOperand(0).getOpcode())
542 {
543 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
544 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp1).addReg(Tmp1);
545 } else {
546 Tmp1 = SelectExpr(N.getOperand(0));
547 Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS ;
548 BuildMI(BB, Opc, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
549 }
550 return Result;
551
552 case ISD::FABS:
553 Tmp1 = SelectExpr(N.getOperand(0));
554 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
555 return Result;
556
Andrew Lenharth9818c052005-02-05 13:19:12 +0000557 case ISD::SELECT:
558 {
Andrew Lenharth45859692005-03-03 21:47:53 +0000559 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
560 unsigned TV = SelectExpr(N.getOperand(1)); //Use if TRUE
561 unsigned FV = SelectExpr(N.getOperand(2)); //Use if FALSE
562
563 SDOperand CC = N.getOperand(0);
564 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
565
566 if (CC.getOpcode() == ISD::SETCC &&
567 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
568 { //FP Setcc -> Select yay!
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000569
570
Andrew Lenharth45859692005-03-03 21:47:53 +0000571 //for a cmp b: c = a - b;
572 //a = b: c = 0
573 //a < b: c < 0
574 //a > b: c > 0
575
576 bool invTest = false;
577 unsigned Tmp3;
578
579 ConstantFPSDNode *CN;
580 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
581 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
582 Tmp3 = SelectExpr(SetCC->getOperand(0));
583 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
584 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
585 {
586 Tmp3 = SelectExpr(SetCC->getOperand(1));
587 invTest = true;
588 }
589 else
590 {
591 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
592 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
593 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
594 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
595 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
596 .addReg(Tmp1).addReg(Tmp2);
597 }
598
599 switch (SetCC->getCondition()) {
600 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
601 case ISD::SETEQ: Opc = invTest ? Alpha::FCMOVNE : Alpha::FCMOVEQ; break;
602 case ISD::SETLT: Opc = invTest ? Alpha::FCMOVGT : Alpha::FCMOVLT; break;
603 case ISD::SETLE: Opc = invTest ? Alpha::FCMOVGE : Alpha::FCMOVLE; break;
604 case ISD::SETGT: Opc = invTest ? Alpha::FCMOVLT : Alpha::FCMOVGT; break;
605 case ISD::SETGE: Opc = invTest ? Alpha::FCMOVLE : Alpha::FCMOVGE; break;
606 case ISD::SETNE: Opc = invTest ? Alpha::FCMOVEQ : Alpha::FCMOVNE; break;
607 }
Andrew Lenharth33819132005-03-04 20:09:23 +0000608 BuildMI(BB, Opc, 3, Result).addReg(FV).addReg(TV).addReg(Tmp3);
Andrew Lenharth45859692005-03-03 21:47:53 +0000609 return Result;
610 }
611 else
612 {
613 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
614 // Spill the cond to memory and reload it from there.
615 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
616 MachineFunction *F = BB->getParent();
617 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
618 unsigned Tmp4 = MakeReg(MVT::f64);
619 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdx).addReg(Alpha::F31);
620 BuildMI(BB, Alpha::LDT, 2, Tmp4).addFrameIndex(FrameIdx).addReg(Alpha::F31);
621 //now ideally, we don't have to do anything to the flag...
622 // Get the condition into the zero flag.
623 BuildMI(BB, Alpha::FCMOVEQ, 3, Result).addReg(TV).addReg(FV).addReg(Tmp4);
624 return Result;
625 }
Andrew Lenharth9818c052005-02-05 13:19:12 +0000626 }
627
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000628 case ISD::FP_ROUND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000629 assert (DestType == MVT::f32 &&
630 N.getOperand(0).getValueType() == MVT::f64 &&
631 "only f64 to f32 conversion supported here");
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000632 Tmp1 = SelectExpr(N.getOperand(0));
633 BuildMI(BB, Alpha::CVTTS, 1, Result).addReg(Tmp1);
634 return Result;
635
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000636 case ISD::FP_EXTEND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000637 assert (DestType == MVT::f64 &&
638 N.getOperand(0).getValueType() == MVT::f32 &&
639 "only f32 to f64 conversion supported here");
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000640 Tmp1 = SelectExpr(N.getOperand(0));
641 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
642 return Result;
643
Andrew Lenharth2c594352005-01-29 15:42:07 +0000644 case ISD::CopyFromReg:
645 {
646 // Make sure we generate both values.
647 if (Result != notIn)
648 ExprMap[N.getValue(1)] = notIn; // Generate the token
649 else
650 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
651
652 SDOperand Chain = N.getOperand(0);
653
654 Select(Chain);
655 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
656 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
657 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(r).addReg(r);
658 return Result;
659 }
660
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000661 case ISD::LOAD:
662 {
663 // Make sure we generate both values.
664 if (Result != notIn)
665 ExprMap[N.getValue(1)] = notIn; // Generate the token
666 else
667 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000668
Andrew Lenharth29219162005-02-07 06:31:44 +0000669 DestType = N.getValue(0).getValueType();
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000670
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000671 SDOperand Chain = N.getOperand(0);
672 SDOperand Address = N.getOperand(1);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000673 Select(Chain);
Andrew Lenharth65838902005-02-06 16:22:15 +0000674 Opc = DestType == MVT::f64 ? Alpha::LDT : Alpha::LDS;
675
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000676 if (Address.getOpcode() == ISD::GlobalAddress) {
677 AlphaLowering.restoreGP(BB);
678 Opc = GetSymVersion(Opc);
679 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
680 }
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000681 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000682 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +0000683 Opc = GetSymVersion(Opc);
Andrew Lenharth97127a12005-02-05 17:41:39 +0000684 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000685 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000686 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000687 BuildMI(BB, Opc, 2, Result)
688 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
689 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000690 } else {
691 long offset;
692 SelectAddr(Address, Tmp1, offset);
693 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
694 }
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000695 return Result;
696 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000697 case ISD::ConstantFP:
698 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
699 if (CN->isExactlyValue(+0.0)) {
700 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000701 } else if ( CN->isExactlyValue(-0.0)) {
702 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000703 } else {
704 abort();
705 }
706 }
707 return Result;
708
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +0000709 case ISD::SDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000710 case ISD::MUL:
711 case ISD::ADD:
712 case ISD::SUB:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000713 switch( opcode ) {
714 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
715 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
716 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
717 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
718 };
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000719
720 ConstantFPSDNode *CN;
721 if (opcode == ISD::SUB
722 && (CN = dyn_cast<ConstantFPSDNode>(N.getOperand(0)))
723 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
724 {
725 Tmp2 = SelectExpr(N.getOperand(1));
726 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp2).addReg(Tmp2);
727 } else {
728 Tmp1 = SelectExpr(N.getOperand(0));
729 Tmp2 = SelectExpr(N.getOperand(1));
730 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
731 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000732 return Result;
733
Andrew Lenharth2c594352005-01-29 15:42:07 +0000734 case ISD::EXTLOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000735 {
736 //include a conversion sequence for float loads to double
737 if (Result != notIn)
738 ExprMap[N.getValue(1)] = notIn; // Generate the token
739 else
740 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
741
Andrew Lenhartha549deb2005-02-07 05:33:15 +0000742 Tmp1 = MakeReg(MVT::f32);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000743
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000744 assert(cast<MVTSDNode>(Node)->getExtraValueType() == MVT::f32 &&
745 "EXTLOAD not from f32");
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000746 assert(Node->getValueType(0) == MVT::f64 && "EXTLOAD not to f64");
747
748 SDOperand Chain = N.getOperand(0);
749 SDOperand Address = N.getOperand(1);
750 Select(Chain);
751
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000752 if (Address.getOpcode() == ISD::GlobalAddress) {
753 AlphaLowering.restoreGP(BB);
754 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
755 }
756 else if (ConstantPoolSDNode *CP =
757 dyn_cast<ConstantPoolSDNode>(N.getOperand(1)))
758 {
759 AlphaLowering.restoreGP(BB);
760 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addConstantPoolIndex(CP->getIndex());
761 }
762 else if(Address.getOpcode() == ISD::FrameIndex) {
763 Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
Andrew Lenharth032f2352005-02-22 21:59:48 +0000764 BuildMI(BB, Alpha::LDS, 2, Tmp1)
765 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
766 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000767 } else {
768 long offset;
769 SelectAddr(Address, Tmp2, offset);
770 BuildMI(BB, Alpha::LDS, 1, Tmp1).addImm(offset).addReg(Tmp2);
771 }
Andrew Lenharth29219162005-02-07 06:31:44 +0000772 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000773 return Result;
774 }
Andrew Lenharth2c594352005-01-29 15:42:07 +0000775
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000776 case ISD::UINT_TO_FP:
777 case ISD::SINT_TO_FP:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000778 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000779 assert (N.getOperand(0).getValueType() == MVT::i64
780 && "only quads can be loaded from");
Andrew Lenharth40831c52005-01-28 06:57:18 +0000781 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000782 Tmp2 = MakeReg(MVT::f64);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000783
784 //The hard way:
785 // Spill the integer to memory and reload it from there.
786 unsigned Size = MVT::getSizeInBits(MVT::i64)/8;
787 MachineFunction *F = BB->getParent();
788 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, Size);
789
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000790 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdx).addReg(Alpha::F31);
791 BuildMI(BB, Alpha::LDT, 2, Tmp2).addFrameIndex(FrameIdx).addReg(Alpha::F31);
792 Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
793 BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000794
795 //The easy way: doesn't work
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000796 // //so these instructions are not supported on ev56
797 // Opc = DestType == MVT::f64 ? Alpha::ITOFT : Alpha::ITOFS;
798 // BuildMI(BB, Opc, 1, Tmp2).addReg(Tmp1);
799 // Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
800 // BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000801
Andrew Lenharth40831c52005-01-28 06:57:18 +0000802 return Result;
803 }
804 }
805 assert(0 && "should not get here");
806 return 0;
807}
808
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000809unsigned ISel::SelectExpr(SDOperand N) {
810 unsigned Result;
811 unsigned Tmp1, Tmp2, Tmp3;
812 unsigned Opc = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000813 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000814
815 SDNode *Node = N.Val;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000816 MVT::ValueType DestType = N.getValueType();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000817
818 unsigned &Reg = ExprMap[N];
819 if (Reg) return Reg;
820
821 if (N.getOpcode() != ISD::CALL)
822 Reg = Result = (N.getValueType() != MVT::Other) ?
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000823 MakeReg(N.getValueType()) : notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000824 else {
825 // If this is a call instruction, make sure to prepare ALL of the result
826 // values as well as the chain.
827 if (Node->getNumValues() == 1)
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000828 Reg = Result = notIn; // Void call, just a chain.
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000829 else {
830 Result = MakeReg(Node->getValueType(0));
831 ExprMap[N.getValue(0)] = Result;
832 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
833 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000834 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000835 }
836 }
837
Andrew Lenharth22088bb2005-02-02 15:05:33 +0000838 if (DestType == MVT::f64 || DestType == MVT::f32 ||
Andrew Lenharth06342c32005-02-07 06:21:37 +0000839 (
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000840 (opcode == ISD::LOAD || opcode == ISD::CopyFromReg ||
841 opcode == ISD::EXTLOAD) &&
842 (N.getValue(0).getValueType() == MVT::f32 ||
843 N.getValue(0).getValueType() == MVT::f64)
Andrew Lenharth06342c32005-02-07 06:21:37 +0000844 )
845 )
Andrew Lenharth40831c52005-01-28 06:57:18 +0000846 return SelectExprFP(N, Result);
847
848 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000849 default:
850 Node->dump();
851 assert(0 && "Node not handled!\n");
852
Andrew Lenharth032f2352005-02-22 21:59:48 +0000853 case ISD::DYNAMIC_STACKALLOC:
854 // Generate both result values.
Andrew Lenharth3a7118d2005-02-23 17:33:42 +0000855 if (Result != notIn)
856 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth032f2352005-02-22 21:59:48 +0000857 else
858 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
859
860 // FIXME: We are currently ignoring the requested alignment for handling
861 // greater than the stack alignment. This will need to be revisited at some
862 // point. Align = N.getOperand(2);
863
864 if (!isa<ConstantSDNode>(N.getOperand(2)) ||
865 cast<ConstantSDNode>(N.getOperand(2))->getValue() != 0) {
866 std::cerr << "Cannot allocate stack object with greater alignment than"
867 << " the stack alignment yet!";
868 abort();
869 }
870
871 Select(N.getOperand(0));
872 if (ConstantSDNode* CN = dyn_cast<ConstantSDNode>(N.getOperand(1)))
873 {
874 if (CN->getValue() < 32000)
875 {
876 BuildMI(BB, Alpha::LDA, 2, Alpha::R30)
877 .addImm(-CN->getValue()).addReg(Alpha::R30);
878 } else {
879 Tmp1 = SelectExpr(N.getOperand(1));
880 // Subtract size from stack pointer, thereby allocating some space.
881 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
882 }
883 } else {
884 Tmp1 = SelectExpr(N.getOperand(1));
885 // Subtract size from stack pointer, thereby allocating some space.
886 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
887 }
888
889 // Put a pointer to the space into the result register, by copying the stack
890 // pointer.
Andrew Lenharth7bc47022005-02-22 23:29:25 +0000891 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R30).addReg(Alpha::R30);
Andrew Lenharth032f2352005-02-22 21:59:48 +0000892 return Result;
893
Andrew Lenharth33819132005-03-04 20:09:23 +0000894// case ISD::ConstantPool:
895// Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
896// AlphaLowering.restoreGP(BB);
897// BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(Tmp1);
898// return Result;
Andrew Lenharth2c594352005-01-29 15:42:07 +0000899
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000900 case ISD::FrameIndex:
Andrew Lenharth032f2352005-02-22 21:59:48 +0000901 BuildMI(BB, Alpha::LDA, 2, Result)
902 .addFrameIndex(cast<FrameIndexSDNode>(N)->getIndex())
903 .addReg(Alpha::F31);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000904 return Result;
905
906 case ISD::EXTLOAD:
Andrew Lenharthf311e8b2005-02-07 05:18:02 +0000907 case ISD::ZEXTLOAD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000908 case ISD::SEXTLOAD:
Andrew Lenhartha549deb2005-02-07 05:33:15 +0000909 case ISD::LOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000910 {
911 // Make sure we generate both values.
912 if (Result != notIn)
913 ExprMap[N.getValue(1)] = notIn; // Generate the token
914 else
915 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000916
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000917 SDOperand Chain = N.getOperand(0);
918 SDOperand Address = N.getOperand(1);
919 Select(Chain);
920
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000921 assert(Node->getValueType(0) == MVT::i64 &&
922 "Unknown type to sign extend to.");
Andrew Lenharth03824012005-02-07 05:55:55 +0000923 if (opcode == ISD::LOAD)
924 Opc = Alpha::LDQ;
925 else
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000926 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
927 default: Node->dump(); assert(0 && "Bad sign extend!");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000928 case MVT::i32: Opc = Alpha::LDL;
929 assert(opcode != ISD::ZEXTLOAD && "Not sext"); break;
930 case MVT::i16: Opc = Alpha::LDWU;
931 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharthf311e8b2005-02-07 05:18:02 +0000932 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000933 case MVT::i8: Opc = Alpha::LDBU;
934 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000935 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000936
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000937 if (Address.getOpcode() == ISD::GlobalAddress) {
938 AlphaLowering.restoreGP(BB);
939 Opc = GetSymVersion(Opc);
940 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
941 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000942 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
943 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +0000944 Opc = GetSymVersion(Opc);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000945 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000946 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000947 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000948 BuildMI(BB, Opc, 2, Result)
949 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
950 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000951 } else {
952 long offset;
953 SelectAddr(Address, Tmp1, offset);
954 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
955 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000956 return Result;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000957 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000958
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000959 case ISD::GlobalAddress:
960 AlphaLowering.restoreGP(BB);
961 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
962 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
963 return Result;
964
965 case ISD::CALL:
966 {
967 Select(N.getOperand(0));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000968
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000969 // The chain for this call is now lowered.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000970 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), notIn));
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000971
972 //grab the arguments
973 std::vector<unsigned> argvregs;
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000974 //assert(Node->getNumOperands() < 8 && "Only 6 args supported");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000975 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000976 argvregs.push_back(SelectExpr(N.getOperand(i)));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000977
Andrew Lenharth684f2292005-01-30 00:35:27 +0000978 //in reg args
979 for(int i = 0, e = std::min(6, (int)argvregs.size()); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000980 {
981 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
982 Alpha::R19, Alpha::R20, Alpha::R21};
983 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
984 Alpha::F19, Alpha::F20, Alpha::F21};
985 switch(N.getOperand(i+2).getValueType()) {
986 default:
987 Node->dump();
988 N.getOperand(i).Val->dump();
989 std::cerr << "Type for " << i << " is: " <<
990 N.getOperand(i+2).getValueType() << "\n";
991 assert(0 && "Unknown value type for call");
992 case MVT::i1:
993 case MVT::i8:
994 case MVT::i16:
995 case MVT::i32:
996 case MVT::i64:
997 BuildMI(BB, Alpha::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
998 break;
999 case MVT::f32:
1000 case MVT::f64:
1001 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
1002 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001003 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001004 }
Andrew Lenharth684f2292005-01-30 00:35:27 +00001005 //in mem args
1006 for (int i = 6, e = argvregs.size(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001007 {
1008 switch(N.getOperand(i+2).getValueType()) {
1009 default:
1010 Node->dump();
1011 N.getOperand(i).Val->dump();
1012 std::cerr << "Type for " << i << " is: " <<
1013 N.getOperand(i+2).getValueType() << "\n";
1014 assert(0 && "Unknown value type for call");
1015 case MVT::i1:
1016 case MVT::i8:
1017 case MVT::i16:
1018 case MVT::i32:
1019 case MVT::i64:
1020 BuildMI(BB, Alpha::STQ, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1021 break;
1022 case MVT::f32:
1023 BuildMI(BB, Alpha::STS, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1024 break;
1025 case MVT::f64:
1026 BuildMI(BB, Alpha::STT, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1027 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001028 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001029 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001030 //build the right kind of call
1031 if (GlobalAddressSDNode *GASD =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001032 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001033 {
Andrew Lenharth3e315922005-02-10 20:10:38 +00001034 //if (GASD->getGlobal()->isExternal()) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001035 //use safe calling convention
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001036 AlphaLowering.restoreGP(BB);
1037 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
Andrew Lenharth3e315922005-02-10 20:10:38 +00001038 //} else {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001039 //use PC relative branch call
Andrew Lenharth3e315922005-02-10 20:10:38 +00001040 //BuildMI(BB, Alpha::BSR, 1, Alpha::R26).addGlobalAddress(GASD->getGlobal(),true);
1041 //}
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001042 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001043 else if (ExternalSymbolSDNode *ESSDN =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001044 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001045 {
1046 AlphaLowering.restoreGP(BB);
Andrew Lenharthba05ad62005-03-30 18:22:52 +00001047 BuildMI(BB, Alpha::CALL, 1).addExternalSymbol(ESSDN->getSymbol(), true);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001048 } else {
1049 //no need to restore GP as we are doing an indirect call
1050 Tmp1 = SelectExpr(N.getOperand(1));
1051 BuildMI(BB, Alpha::BIS, 2, Alpha::R27).addReg(Tmp1).addReg(Tmp1);
1052 BuildMI(BB, Alpha::JSR, 2, Alpha::R26).addReg(Alpha::R27).addImm(0);
1053 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001054
1055 //push the result into a virtual register
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001056
1057 switch (Node->getValueType(0)) {
1058 default: Node->dump(); assert(0 && "Unknown value type for call result!");
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001059 case MVT::Other: return notIn;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001060 case MVT::i1:
1061 case MVT::i8:
1062 case MVT::i16:
1063 case MVT::i32:
1064 case MVT::i64:
1065 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
1066 break;
1067 case MVT::f32:
1068 case MVT::f64:
1069 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
1070 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001071 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001072 return Result+N.ResNo;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001073 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001074
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001075 case ISD::SIGN_EXTEND:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001076 abort();
1077
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001078 case ISD::SIGN_EXTEND_INREG:
1079 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001080 //do SDIV opt for all levels of ints
Andrew Lenharth5e99dd92005-03-31 22:02:25 +00001081 if (EnableAlphaIDIV && N.getOperand(0).getOpcode() == ISD::SDIV)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001082 {
1083 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1084 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1085 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1086 MachineFunction *F = BB->getParent();
1087 int FrameIdxL = F->getFrameInfo()->CreateStackObject(Size, 8);
1088 int FrameIdxR = F->getFrameInfo()->CreateStackObject(Size, 8);
1089 int FrameIdxF = F->getFrameInfo()->CreateStackObject(Size, 8);
1090 unsigned Tmp4 = MakeReg(MVT::f64);
1091 unsigned Tmp5 = MakeReg(MVT::f64);
1092 unsigned Tmp6 = MakeReg(MVT::f64);
1093 unsigned Tmp7 = MakeReg(MVT::f64);
1094 unsigned Tmp8 = MakeReg(MVT::f64);
1095 unsigned Tmp9 = MakeReg(MVT::f64);
1096
1097 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdxL).addReg(Alpha::F31);
Andrew Lenharthcc59ed52005-03-23 15:20:01 +00001098 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp2).addFrameIndex(FrameIdxR).addReg(Alpha::F31);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001099 BuildMI(BB, Alpha::LDT, 2, Tmp4).addFrameIndex(FrameIdxL).addReg(Alpha::F31);
1100 BuildMI(BB, Alpha::LDT, 2, Tmp5).addFrameIndex(FrameIdxR).addReg(Alpha::F31);
1101 BuildMI(BB, Alpha::CVTQT, 1, Tmp6).addReg(Tmp4);
1102 BuildMI(BB, Alpha::CVTQT, 1, Tmp7).addReg(Tmp5);
1103 BuildMI(BB, Alpha::DIVT, 2, Tmp8).addReg(Tmp6).addReg(Tmp7);
1104 BuildMI(BB, Alpha::CVTTQ, 1, Tmp9).addReg(Tmp8);
1105 BuildMI(BB, Alpha::STT, 3).addReg(Tmp9).addFrameIndex(FrameIdxF).addReg(Alpha::F31);
Andrew Lenharthcc59ed52005-03-23 15:20:01 +00001106 BuildMI(BB, Alpha::LDQ, 2, Result).addFrameIndex(FrameIdxF).addReg(Alpha::F31);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001107 return Result;
1108 }
1109
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001110 //Alpha has instructions for a bunch of signed 32 bit stuff
1111 if( dyn_cast<MVTSDNode>(Node)->getExtraValueType() == MVT::i32)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001112 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001113 switch (N.getOperand(0).getOpcode()) {
1114 case ISD::ADD:
1115 case ISD::SUB:
1116 case ISD::MUL:
1117 {
1118 bool isAdd = N.getOperand(0).getOpcode() == ISD::ADD;
1119 bool isMul = N.getOperand(0).getOpcode() == ISD::MUL;
1120 //FIXME: first check for Scaled Adds and Subs!
1121 if(N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1122 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() <= 255)
1123 { //Normal imm add/sub
1124 Opc = isAdd ? Alpha::ADDLi : (isMul ? Alpha::MULLi : Alpha::SUBLi);
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));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001132 Tmp2 = cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue();
1133 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001134 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001135 else
1136 { //Normal add/sub
1137 Opc = isAdd ? Alpha::ADDL : (isMul ? Alpha::MULLi : Alpha::SUBL);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001138 //if the value was really originally a i32, skip the up conversion
1139 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1140 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1141 ->getExtraValueType() == MVT::i32)
1142 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1143 else
1144 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1145 //if the value was really originally a i32, skip the up conversion
1146 if (N.getOperand(0).getOperand(1).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1147 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(1).Val)
1148 ->getExtraValueType() == MVT::i32)
1149 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0));
1150 else
1151 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1152
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001153 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1154 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1155 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1156 }
1157 return Result;
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001158 }
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001159 case ISD::SEXTLOAD:
1160 //SelectionDag isn't deleting the signextend after sextloads
1161 Reg = Result = SelectExpr(N.getOperand(0));
1162 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001163 default: break; //Fall Though;
1164 }
1165 } //Every thing else fall though too, including unhandled opcodes above
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001166 Tmp1 = SelectExpr(N.getOperand(0));
1167 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001168 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001169 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001170 {
1171 default:
1172 Node->dump();
1173 assert(0 && "Sign Extend InReg not there yet");
1174 break;
1175 case MVT::i32:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001176 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001177 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001178 break;
1179 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001180 case MVT::i16:
1181 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
1182 break;
1183 case MVT::i8:
1184 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
1185 break;
Andrew Lenharthebce5042005-02-12 19:35:12 +00001186 case MVT::i1:
1187 Tmp2 = MakeReg(MVT::i64);
1188 BuildMI(BB, Alpha::ANDi, 2, Tmp2).addReg(Tmp1).addImm(1);
Andrew Lenharth7536eea2005-02-12 20:42:09 +00001189 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Alpha::F31).addReg(Tmp2);
Andrew Lenharthebce5042005-02-12 19:35:12 +00001190 break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001191 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001192 return Result;
1193 }
1194 case ISD::ZERO_EXTEND_INREG:
1195 {
1196 Tmp1 = SelectExpr(N.getOperand(0));
1197 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001198 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001199 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001200 {
1201 default:
1202 Node->dump();
1203 assert(0 && "Zero Extend InReg not there yet");
1204 break;
1205 case MVT::i32: Tmp2 = 0xf0; break;
1206 case MVT::i16: Tmp2 = 0xfc; break;
1207 case MVT::i8: Tmp2 = 0xfe; break;
1208 case MVT::i1: //handle this one special
1209 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
1210 return Result;
1211 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001212 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001213 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001214 }
1215
1216 case ISD::SETCC:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001217 {
1218 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
1219 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
1220 bool isConst1 = false;
1221 bool isConst2 = false;
1222 int dir;
Andrew Lenharth9818c052005-02-05 13:19:12 +00001223
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001224 //Tmp1 = SelectExpr(N.getOperand(0));
1225 if(N.getOperand(0).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001226 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1227 isConst1 = true;
1228 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001229 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1230 isConst2 = true;
1231
1232 switch (SetCC->getCondition()) {
1233 default: Node->dump(); assert(0 && "Unknown integer comparison!");
1234 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001235 case ISD::SETLT:
1236 Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
1237 case ISD::SETLE:
1238 Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
1239 case ISD::SETGT:
1240 Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
1241 case ISD::SETGE:
1242 Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
1243 case ISD::SETULT:
1244 Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
1245 case ISD::SETUGT:
1246 Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
1247 case ISD::SETULE:
1248 Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
1249 case ISD::SETUGE:
1250 Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001251 case ISD::SETNE: {//Handle this one special
1252 //std::cerr << "Alpha does not have a setne.\n";
1253 //abort();
1254 Tmp1 = SelectExpr(N.getOperand(0));
1255 Tmp2 = SelectExpr(N.getOperand(1));
1256 Tmp3 = MakeReg(MVT::i64);
1257 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth445171a2005-02-08 00:40:03 +00001258 //Remeber we have the Inv for this CC
1259 CCInvMap[N] = Tmp3;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001260 //and invert
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001261 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001262 return Result;
1263 }
1264 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001265 if (dir == 1) {
1266 Tmp1 = SelectExpr(N.getOperand(0));
1267 if (isConst2) {
1268 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1269 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1270 } else {
1271 Tmp2 = SelectExpr(N.getOperand(1));
1272 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1273 }
1274 } else if (dir == 2) {
1275 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001276 if (isConst1) {
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001277 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1278 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1279 } else {
1280 Tmp2 = SelectExpr(N.getOperand(0));
1281 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1282 }
1283 } else { //dir == 0
1284 if (isConst1) {
1285 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1286 Tmp2 = SelectExpr(N.getOperand(1));
1287 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
1288 } else if (isConst2) {
1289 Tmp1 = SelectExpr(N.getOperand(0));
1290 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1291 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
1292 } else {
1293 Tmp1 = SelectExpr(N.getOperand(0));
1294 Tmp2 = SelectExpr(N.getOperand(1));
1295 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
1296 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001297 }
1298 } else {
1299 //assert(SetCC->getOperand(0).getValueType() != MVT::f32 && "SetCC f32 should have been promoted");
1300 bool rev = false;
1301 bool inv = false;
1302
1303 switch (SetCC->getCondition()) {
1304 default: Node->dump(); assert(0 && "Unknown FP comparison!");
1305 case ISD::SETEQ: Opc = Alpha::CMPTEQ; break;
1306 case ISD::SETLT: Opc = Alpha::CMPTLT; break;
1307 case ISD::SETLE: Opc = Alpha::CMPTLE; break;
1308 case ISD::SETGT: Opc = Alpha::CMPTLT; rev = true; break;
1309 case ISD::SETGE: Opc = Alpha::CMPTLE; rev = true; break;
1310 case ISD::SETNE: Opc = Alpha::CMPTEQ; inv = true; break;
1311 }
1312
Andrew Lenharthca3d59b2005-03-14 19:23:45 +00001313 //FIXME: check for constant 0.0
1314 ConstantFPSDNode *CN;
1315 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
1316 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1317 Tmp1 = Alpha::F31;
1318 else
1319 Tmp1 = SelectExpr(N.getOperand(0));
1320
1321 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
1322 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1323 Tmp2 = Alpha::F31;
1324 else
1325 Tmp2 = SelectExpr(N.getOperand(1));
1326
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001327 //Can only compare doubles, and dag won't promote for me
1328 if (SetCC->getOperand(0).getValueType() == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001329 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001330 //assert(0 && "Setcc On float?\n");
1331 std::cerr << "Setcc on float!\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001332 Tmp3 = MakeReg(MVT::f64);
1333 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp1);
1334 Tmp1 = Tmp3;
1335 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001336 if (SetCC->getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001337 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001338 //assert (0 && "Setcc On float?\n");
1339 std::cerr << "Setcc on float!\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001340 Tmp3 = MakeReg(MVT::f64);
1341 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp2);
Andrew Lenharth572af902005-02-14 05:41:43 +00001342 Tmp2 = Tmp3;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001343 }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001344
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001345 if (rev) std::swap(Tmp1, Tmp2);
1346 Tmp3 = MakeReg(MVT::f64);
1347 //do the comparison
1348 BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
1349
1350 //now arrange for Result (int) to have a 1 or 0
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001351 unsigned Tmp4 = MakeReg(MVT::i64);
1352 BuildMI(BB, Alpha::ADDQi, 2, Tmp4).addReg(Alpha::R31).addImm(1);
1353 Opc = inv?Alpha::CMOVNEi_FP:Alpha::CMOVEQi_FP;
1354 BuildMI(BB, Opc, 3, Result).addReg(Tmp4).addImm(0).addReg(Tmp3);
Andrew Lenharthca3d59b2005-03-14 19:23:45 +00001355
1356// // Spill the FP to memory and reload it from there.
1357// unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1358// MachineFunction *F = BB->getParent();
1359// int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
1360// unsigned Tmp4 = MakeReg(MVT::f64);
1361// BuildMI(BB, Alpha::CVTTQ, 1, Tmp4).addReg(Tmp3);
1362// BuildMI(BB, Alpha::STT, 3).addReg(Tmp4).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1363// unsigned Tmp5 = MakeReg(MVT::i64);
1364// BuildMI(BB, Alpha::LDQ, 2, Tmp5).addFrameIndex(FrameIdx).addReg(Alpha::F31);
Andrew Lenharth9818c052005-02-05 13:19:12 +00001365
Andrew Lenharthca3d59b2005-03-14 19:23:45 +00001366// //now, set result based on Tmp5
1367// //Set Tmp6 if fp cmp was false
1368// unsigned Tmp6 = MakeReg(MVT::i64);
1369// BuildMI(BB, Alpha::CMPEQ, 2, Tmp6).addReg(Tmp5).addReg(Alpha::R31);
1370// //and invert
1371// BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp6).addReg(Alpha::R31);
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001372
1373 }
1374 // else
1375 // {
1376 // Node->dump();
1377 // assert(0 && "Not a setcc in setcc");
1378 // }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001379 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001380 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001381 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001382
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001383 case ISD::CopyFromReg:
1384 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001385 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001386 if (Result != notIn)
1387 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth40831c52005-01-28 06:57:18 +00001388 else
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001389 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth40831c52005-01-28 06:57:18 +00001390
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001391 SDOperand Chain = N.getOperand(0);
1392
1393 Select(Chain);
1394 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
1395 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
1396 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
1397 return Result;
1398 }
1399
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001400 //Most of the plain arithmetic and logic share the same form, and the same
1401 //constant immediate test
1402 case ISD::AND:
1403 case ISD::OR:
1404 case ISD::XOR:
1405 case ISD::SHL:
1406 case ISD::SRL:
Andrew Lenharth2c594352005-01-29 15:42:07 +00001407 case ISD::SRA:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001408 case ISD::MUL:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001409 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
1410 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001411 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001412 {
1413 switch(opcode) {
1414 case ISD::AND: Opc = Alpha::ANDi; break;
1415 case ISD::OR: Opc = Alpha::BISi; break;
1416 case ISD::XOR: Opc = Alpha::XORi; break;
1417 case ISD::SHL: Opc = Alpha::SLi; break;
1418 case ISD::SRL: Opc = Alpha::SRLi; break;
1419 case ISD::SRA: Opc = Alpha::SRAi; break;
1420 case ISD::MUL: Opc = Alpha::MULQi; break;
1421 };
1422 Tmp1 = SelectExpr(N.getOperand(0));
1423 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1424 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1425 } else {
1426 switch(opcode) {
1427 case ISD::AND: Opc = Alpha::AND; break;
1428 case ISD::OR: Opc = Alpha::BIS; break;
1429 case ISD::XOR: Opc = Alpha::XOR; break;
1430 case ISD::SHL: Opc = Alpha::SL; break;
1431 case ISD::SRL: Opc = Alpha::SRL; break;
1432 case ISD::SRA: Opc = Alpha::SRA; break;
1433 case ISD::MUL: Opc = Alpha::MULQ; break;
1434 };
1435 Tmp1 = SelectExpr(N.getOperand(0));
1436 Tmp2 = SelectExpr(N.getOperand(1));
1437 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1438 }
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001439 return Result;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001440
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001441 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001442 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001443 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001444 bool isAdd = opcode == ISD::ADD;
1445
1446 //FIXME: first check for Scaled Adds and Subs!
1447 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001448 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001449 { //Normal imm add/sub
1450 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
1451 Tmp1 = SelectExpr(N.getOperand(0));
1452 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1453 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1454 }
Andrew Lenharth40831c52005-01-28 06:57:18 +00001455 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001456 (cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767 ||
1457 (long)cast<ConstantSDNode>(N.getOperand(1))->getValue() >= -32767))
1458 { //LDA
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001459 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001460 Tmp2 = (long)cast<ConstantSDNode>(N.getOperand(1))->getValue();
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001461 if (!isAdd)
1462 Tmp2 = -Tmp2;
1463 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
1464 } else {
1465 //Normal add/sub
1466 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
1467 Tmp1 = SelectExpr(N.getOperand(0));
1468 Tmp2 = SelectExpr(N.getOperand(1));
1469 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1470 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001471 return Result;
1472 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001473
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001474 case ISD::SDIV:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001475 case ISD::UREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001476 case ISD::SREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001477 case ISD::UDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001478 //FIXME: alpha really doesn't support any of these operations,
1479 // the ops are expanded into special library calls with
1480 // special calling conventions
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001481 //Restore GP because it is a call after all...
Andrew Lenharth40831c52005-01-28 06:57:18 +00001482 switch(opcode) {
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001483 case ISD::UREM: Opc = Alpha::REMQU; break;
1484 case ISD::SREM: Opc = Alpha::REMQ; break;
1485 case ISD::UDIV: Opc = Alpha::DIVQU; break;
1486 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001487 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001488 Tmp1 = SelectExpr(N.getOperand(0));
1489 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth33819132005-03-04 20:09:23 +00001490 //set up regs explicitly (helps Reg alloc)
1491 BuildMI(BB, Alpha::BIS, 2, Alpha::R24).addReg(Tmp1).addReg(Tmp1);
1492 BuildMI(BB, Alpha::BIS, 2, Alpha::R25).addReg(Tmp2).addReg(Tmp2);
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001493 AlphaLowering.restoreGP(BB);
Andrew Lenharth33819132005-03-04 20:09:23 +00001494 BuildMI(BB, Opc, 2).addReg(Alpha::R24).addReg(Alpha::R25);
1495 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R27).addReg(Alpha::R27);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001496 return Result;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001497
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001498 case ISD::FP_TO_UINT:
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001499 case ISD::FP_TO_SINT:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001500 {
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001501 assert (DestType == MVT::i64 && "only quads can be loaded to");
1502 MVT::ValueType SrcType = N.getOperand(0).getValueType();
Andrew Lenharth03824012005-02-07 05:55:55 +00001503 assert (SrcType == MVT::f32 || SrcType == MVT::f64);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001504 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
1505
1506 //The hard way:
1507 // Spill the integer to memory and reload it from there.
1508 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1509 MachineFunction *F = BB->getParent();
1510 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
1511
1512 //CVTTQ STT LDQ
1513 //CVTST CVTTQ STT LDQ
1514 if (SrcType == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001515 {
1516 Tmp2 = MakeReg(MVT::f64);
1517 BuildMI(BB, Alpha::CVTST, 1, Tmp2).addReg(Tmp1);
1518 Tmp1 = Tmp2;
1519 }
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001520 Tmp2 = MakeReg(MVT::f64);
1521 BuildMI(BB, Alpha::CVTTQ, 1, Tmp2).addReg(Tmp1);
1522 BuildMI(BB, Alpha::STT, 3).addReg(Tmp2).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1523 BuildMI(BB, Alpha::LDQ, 2, Result).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1524
1525 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001526 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001527
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001528 // // case ISD::FP_TO_UINT:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001529
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001530 case ISD::SELECT:
1531 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001532 //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 +00001533 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001534 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1535 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001536 // Get the condition into the zero flag.
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001537 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001538 return Result;
1539 }
1540
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001541 case ISD::Constant:
1542 {
Andrew Lenharthc0513832005-03-29 19:24:04 +00001543 int64_t val = (int64_t)cast<ConstantSDNode>(N)->getValue();
Andrew Lenharthe87f6c32005-03-11 17:48:05 +00001544 if (val <= IMM_HIGH && val >= IMM_LOW) {
1545 BuildMI(BB, Alpha::LDA, 2, Result).addImm(val).addReg(Alpha::R31);
1546 }
1547 else if (val <= (int64_t)IMM_HIGH + (int64_t)IMM_HIGH * (int64_t)IMM_MULT &&
1548 val >= (int64_t)IMM_LOW + (int64_t)IMM_LOW * (int64_t)IMM_MULT) {
1549 Tmp1 = MakeReg(MVT::i64);
1550 BuildMI(BB, Alpha::LDAH, 2, Tmp1).addImm(getUpper16(val)).addReg(Alpha::R31);
1551 BuildMI(BB, Alpha::LDA, 2, Result).addImm(getLower16(val)).addReg(Tmp1);
1552 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001553 else {
1554 MachineConstantPool *CP = BB->getParent()->getConstantPool();
1555 ConstantUInt *C = ConstantUInt::get(Type::getPrimitiveType(Type::ULongTyID) , val);
1556 unsigned CPI = CP->getConstantPoolIndex(C);
1557 AlphaLowering.restoreGP(BB);
1558 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(CPI);
1559 }
1560 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001561 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001562 }
1563
1564 return 0;
1565}
1566
1567void ISel::Select(SDOperand N) {
1568 unsigned Tmp1, Tmp2, Opc;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001569 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001570
Nate Begeman85fdeb22005-03-24 04:39:54 +00001571 if (!ExprMap.insert(std::make_pair(N, notIn)).second)
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001572 return; // Already selected.
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001573
1574 SDNode *Node = N.Val;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001575
Andrew Lenharth760270d2005-02-07 23:02:23 +00001576 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001577
1578 default:
1579 Node->dump(); std::cerr << "\n";
1580 assert(0 && "Node not handled yet!");
1581
1582 case ISD::BRCOND: {
Andrew Lenharth445171a2005-02-08 00:40:03 +00001583 SelectBranchCC(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001584 return;
1585 }
1586
1587 case ISD::BR: {
1588 MachineBasicBlock *Dest =
1589 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
1590
1591 Select(N.getOperand(0));
1592 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
1593 return;
1594 }
1595
1596 case ISD::ImplicitDef:
1597 Select(N.getOperand(0));
1598 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
1599 return;
1600
1601 case ISD::EntryToken: return; // Noop
1602
1603 case ISD::TokenFactor:
1604 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
1605 Select(Node->getOperand(i));
1606
1607 //N.Val->dump(); std::cerr << "\n";
1608 //assert(0 && "Node not handled yet!");
1609
1610 return;
1611
1612 case ISD::CopyToReg:
1613 Select(N.getOperand(0));
1614 Tmp1 = SelectExpr(N.getOperand(1));
1615 Tmp2 = cast<RegSDNode>(N)->getReg();
1616
1617 if (Tmp1 != Tmp2) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001618 if (N.getOperand(1).getValueType() == MVT::f64 ||
1619 N.getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth29219162005-02-07 06:31:44 +00001620 BuildMI(BB, Alpha::CPYS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
1621 else
1622 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001623 }
1624 return;
1625
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001626 case ISD::RET:
1627 switch (N.getNumOperands()) {
1628 default:
1629 std::cerr << N.getNumOperands() << "\n";
1630 for (unsigned i = 0; i < N.getNumOperands(); ++i)
1631 std::cerr << N.getOperand(i).getValueType() << "\n";
1632 Node->dump();
1633 assert(0 && "Unknown return instruction!");
1634 case 2:
1635 Select(N.getOperand(0));
1636 Tmp1 = SelectExpr(N.getOperand(1));
1637 switch (N.getOperand(1).getValueType()) {
1638 default: Node->dump();
1639 assert(0 && "All other types should have been promoted!!");
1640 case MVT::f64:
1641 case MVT::f32:
1642 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
1643 break;
1644 case MVT::i32:
1645 case MVT::i64:
1646 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
1647 break;
1648 }
1649 break;
1650 case 1:
1651 Select(N.getOperand(0));
1652 break;
1653 }
1654 //Tmp2 = AlphaLowering.getRetAddr();
1655 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
1656 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
1657 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001658
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001659 case ISD::TRUNCSTORE:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001660 case ISD::STORE:
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001661 {
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001662 SDOperand Chain = N.getOperand(0);
1663 SDOperand Value = N.getOperand(1);
1664 SDOperand Address = N.getOperand(2);
1665 Select(Chain);
1666
1667 Tmp1 = SelectExpr(Value); //value
Andrew Lenharth760270d2005-02-07 23:02:23 +00001668
1669 if (opcode == ISD::STORE) {
1670 switch(Value.getValueType()) {
1671 default: assert(0 && "unknown Type in store");
1672 case MVT::i64: Opc = Alpha::STQ; break;
1673 case MVT::f64: Opc = Alpha::STT; break;
1674 case MVT::f32: Opc = Alpha::STS; break;
1675 }
1676 } else { //ISD::TRUNCSTORE
1677 switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
1678 default: assert(0 && "unknown Type in store");
1679 case MVT::i1: //FIXME: DAG does not promote this load
1680 case MVT::i8: Opc = Alpha::STB; break;
1681 case MVT::i16: Opc = Alpha::STW; break;
1682 case MVT::i32: Opc = Alpha::STL; break;
1683 }
Andrew Lenharth65838902005-02-06 16:22:15 +00001684 }
Andrew Lenharth760270d2005-02-07 23:02:23 +00001685
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001686 if (Address.getOpcode() == ISD::GlobalAddress)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001687 {
1688 AlphaLowering.restoreGP(BB);
1689 Opc = GetSymVersion(Opc);
1690 BuildMI(BB, Opc, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1691 }
Andrew Lenharth05380342005-02-07 05:07:00 +00001692 else if(Address.getOpcode() == ISD::FrameIndex)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001693 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001694 BuildMI(BB, Opc, 3).addReg(Tmp1)
1695 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1696 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001697 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001698 else
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001699 {
1700 long offset;
1701 SelectAddr(Address, Tmp2, offset);
1702 BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
1703 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001704 return;
1705 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001706
1707 case ISD::EXTLOAD:
1708 case ISD::SEXTLOAD:
1709 case ISD::ZEXTLOAD:
1710 case ISD::LOAD:
1711 case ISD::CopyFromReg:
1712 case ISD::CALL:
Andrew Lenharth032f2352005-02-22 21:59:48 +00001713 case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001714 ExprMap.erase(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001715 SelectExpr(N);
1716 return;
1717
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001718 case ISD::ADJCALLSTACKDOWN:
1719 case ISD::ADJCALLSTACKUP:
1720 Select(N.getOperand(0));
1721 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1722
1723 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
1724 Alpha::ADJUSTSTACKUP;
1725 BuildMI(BB, Opc, 1).addImm(Tmp1);
1726 return;
Andrew Lenharth95762122005-03-31 21:24:06 +00001727
1728 case ISD::PCMARKER:
1729 Select(N.getOperand(0)); //Chain
1730 BuildMI(BB, Alpha::PCLABEL, 2).addImm( cast<ConstantSDNode>(N.getOperand(1))->getValue());
1731 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001732 }
1733 assert(0 && "Should not be reached!");
1734}
1735
1736
1737/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
1738/// into a machine code representation using pattern matching and a machine
1739/// description file.
1740///
1741FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
1742 return new ISel(TM);
1743}