blob: ba5178b621287ad089168de7fc039ed4d5400ff8 [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 Lenharth9818c052005-02-05 13:19:12 +0000540 case ISD::SELECT:
541 {
Andrew Lenharth45859692005-03-03 21:47:53 +0000542 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
543 unsigned TV = SelectExpr(N.getOperand(1)); //Use if TRUE
544 unsigned FV = SelectExpr(N.getOperand(2)); //Use if FALSE
545
546 SDOperand CC = N.getOperand(0);
547 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
548
549 if (CC.getOpcode() == ISD::SETCC &&
550 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
551 { //FP Setcc -> Select yay!
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000552
553
Andrew Lenharth45859692005-03-03 21:47:53 +0000554 //for a cmp b: c = a - b;
555 //a = b: c = 0
556 //a < b: c < 0
557 //a > b: c > 0
558
559 bool invTest = false;
560 unsigned Tmp3;
561
562 ConstantFPSDNode *CN;
563 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
564 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
565 Tmp3 = SelectExpr(SetCC->getOperand(0));
566 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
567 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
568 {
569 Tmp3 = SelectExpr(SetCC->getOperand(1));
570 invTest = true;
571 }
572 else
573 {
574 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
575 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
576 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
577 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
578 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
579 .addReg(Tmp1).addReg(Tmp2);
580 }
581
582 switch (SetCC->getCondition()) {
583 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
584 case ISD::SETEQ: Opc = invTest ? Alpha::FCMOVNE : Alpha::FCMOVEQ; break;
585 case ISD::SETLT: Opc = invTest ? Alpha::FCMOVGT : Alpha::FCMOVLT; break;
586 case ISD::SETLE: Opc = invTest ? Alpha::FCMOVGE : Alpha::FCMOVLE; break;
587 case ISD::SETGT: Opc = invTest ? Alpha::FCMOVLT : Alpha::FCMOVGT; break;
588 case ISD::SETGE: Opc = invTest ? Alpha::FCMOVLE : Alpha::FCMOVGE; break;
589 case ISD::SETNE: Opc = invTest ? Alpha::FCMOVEQ : Alpha::FCMOVNE; break;
590 }
Andrew Lenharth33819132005-03-04 20:09:23 +0000591 BuildMI(BB, Opc, 3, Result).addReg(FV).addReg(TV).addReg(Tmp3);
Andrew Lenharth45859692005-03-03 21:47:53 +0000592 return Result;
593 }
594 else
595 {
596 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
597 // Spill the cond to memory and reload it from there.
598 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
599 MachineFunction *F = BB->getParent();
600 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
601 unsigned Tmp4 = MakeReg(MVT::f64);
602 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdx).addReg(Alpha::F31);
603 BuildMI(BB, Alpha::LDT, 2, Tmp4).addFrameIndex(FrameIdx).addReg(Alpha::F31);
604 //now ideally, we don't have to do anything to the flag...
605 // Get the condition into the zero flag.
606 BuildMI(BB, Alpha::FCMOVEQ, 3, Result).addReg(TV).addReg(FV).addReg(Tmp4);
607 return Result;
608 }
Andrew Lenharth9818c052005-02-05 13:19:12 +0000609 }
610
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000611 case ISD::FP_ROUND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000612 assert (DestType == MVT::f32 &&
613 N.getOperand(0).getValueType() == MVT::f64 &&
614 "only f64 to f32 conversion supported here");
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000615 Tmp1 = SelectExpr(N.getOperand(0));
616 BuildMI(BB, Alpha::CVTTS, 1, Result).addReg(Tmp1);
617 return Result;
618
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000619 case ISD::FP_EXTEND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000620 assert (DestType == MVT::f64 &&
621 N.getOperand(0).getValueType() == MVT::f32 &&
622 "only f32 to f64 conversion supported here");
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000623 Tmp1 = SelectExpr(N.getOperand(0));
624 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
625 return Result;
626
Andrew Lenharth2c594352005-01-29 15:42:07 +0000627 case ISD::CopyFromReg:
628 {
629 // Make sure we generate both values.
630 if (Result != notIn)
631 ExprMap[N.getValue(1)] = notIn; // Generate the token
632 else
633 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
634
635 SDOperand Chain = N.getOperand(0);
636
637 Select(Chain);
638 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
639 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
640 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(r).addReg(r);
641 return Result;
642 }
643
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000644 case ISD::LOAD:
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());
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000651
Andrew Lenharth29219162005-02-07 06:31:44 +0000652 DestType = N.getValue(0).getValueType();
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000653
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000654 SDOperand Chain = N.getOperand(0);
655 SDOperand Address = N.getOperand(1);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000656 Select(Chain);
Andrew Lenharth65838902005-02-06 16:22:15 +0000657 Opc = DestType == MVT::f64 ? Alpha::LDT : Alpha::LDS;
658
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000659 if (Address.getOpcode() == ISD::GlobalAddress) {
660 AlphaLowering.restoreGP(BB);
661 Opc = GetSymVersion(Opc);
662 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
663 }
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000664 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000665 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +0000666 Opc = GetSymVersion(Opc);
Andrew Lenharth97127a12005-02-05 17:41:39 +0000667 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000668 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000669 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000670 BuildMI(BB, Opc, 2, Result)
671 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
672 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000673 } else {
674 long offset;
675 SelectAddr(Address, Tmp1, offset);
676 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
677 }
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000678 return Result;
679 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000680 case ISD::ConstantFP:
681 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
682 if (CN->isExactlyValue(+0.0)) {
683 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000684 } else if ( CN->isExactlyValue(-0.0)) {
685 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000686 } else {
687 abort();
688 }
689 }
690 return Result;
691
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +0000692 case ISD::SDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000693 case ISD::MUL:
694 case ISD::ADD:
695 case ISD::SUB:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000696 switch( opcode ) {
697 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
698 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
699 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
700 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
701 };
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000702
703 ConstantFPSDNode *CN;
704 if (opcode == ISD::SUB
705 && (CN = dyn_cast<ConstantFPSDNode>(N.getOperand(0)))
706 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
707 {
708 Tmp2 = SelectExpr(N.getOperand(1));
709 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp2).addReg(Tmp2);
710 } else {
711 Tmp1 = SelectExpr(N.getOperand(0));
712 Tmp2 = SelectExpr(N.getOperand(1));
713 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
714 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000715 return Result;
716
Andrew Lenharth2c594352005-01-29 15:42:07 +0000717 case ISD::EXTLOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000718 {
719 //include a conversion sequence for float loads to double
720 if (Result != notIn)
721 ExprMap[N.getValue(1)] = notIn; // Generate the token
722 else
723 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
724
Andrew Lenhartha549deb2005-02-07 05:33:15 +0000725 Tmp1 = MakeReg(MVT::f32);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000726
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000727 assert(cast<MVTSDNode>(Node)->getExtraValueType() == MVT::f32 &&
728 "EXTLOAD not from f32");
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000729 assert(Node->getValueType(0) == MVT::f64 && "EXTLOAD not to f64");
730
731 SDOperand Chain = N.getOperand(0);
732 SDOperand Address = N.getOperand(1);
733 Select(Chain);
734
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000735 if (Address.getOpcode() == ISD::GlobalAddress) {
736 AlphaLowering.restoreGP(BB);
737 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
738 }
739 else if (ConstantPoolSDNode *CP =
740 dyn_cast<ConstantPoolSDNode>(N.getOperand(1)))
741 {
742 AlphaLowering.restoreGP(BB);
743 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addConstantPoolIndex(CP->getIndex());
744 }
745 else if(Address.getOpcode() == ISD::FrameIndex) {
746 Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
Andrew Lenharth032f2352005-02-22 21:59:48 +0000747 BuildMI(BB, Alpha::LDS, 2, Tmp1)
748 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
749 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000750 } else {
751 long offset;
752 SelectAddr(Address, Tmp2, offset);
753 BuildMI(BB, Alpha::LDS, 1, Tmp1).addImm(offset).addReg(Tmp2);
754 }
Andrew Lenharth29219162005-02-07 06:31:44 +0000755 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000756 return Result;
757 }
Andrew Lenharth2c594352005-01-29 15:42:07 +0000758
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000759 case ISD::UINT_TO_FP:
760 case ISD::SINT_TO_FP:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000761 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000762 assert (N.getOperand(0).getValueType() == MVT::i64
763 && "only quads can be loaded from");
Andrew Lenharth40831c52005-01-28 06:57:18 +0000764 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000765 Tmp2 = MakeReg(MVT::f64);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000766
767 //The hard way:
768 // Spill the integer to memory and reload it from there.
769 unsigned Size = MVT::getSizeInBits(MVT::i64)/8;
770 MachineFunction *F = BB->getParent();
771 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, Size);
772
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000773 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdx).addReg(Alpha::F31);
774 BuildMI(BB, Alpha::LDT, 2, Tmp2).addFrameIndex(FrameIdx).addReg(Alpha::F31);
775 Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
776 BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000777
778 //The easy way: doesn't work
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000779 // //so these instructions are not supported on ev56
780 // Opc = DestType == MVT::f64 ? Alpha::ITOFT : Alpha::ITOFS;
781 // BuildMI(BB, Opc, 1, Tmp2).addReg(Tmp1);
782 // Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
783 // BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
Andrew Lenharth2c594352005-01-29 15:42:07 +0000784
Andrew Lenharth40831c52005-01-28 06:57:18 +0000785 return Result;
786 }
787 }
788 assert(0 && "should not get here");
789 return 0;
790}
791
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000792unsigned ISel::SelectExpr(SDOperand N) {
793 unsigned Result;
794 unsigned Tmp1, Tmp2, Tmp3;
795 unsigned Opc = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000796 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000797
798 SDNode *Node = N.Val;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000799 MVT::ValueType DestType = N.getValueType();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000800
801 unsigned &Reg = ExprMap[N];
802 if (Reg) return Reg;
803
804 if (N.getOpcode() != ISD::CALL)
805 Reg = Result = (N.getValueType() != MVT::Other) ?
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000806 MakeReg(N.getValueType()) : notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000807 else {
808 // If this is a call instruction, make sure to prepare ALL of the result
809 // values as well as the chain.
810 if (Node->getNumValues() == 1)
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000811 Reg = Result = notIn; // Void call, just a chain.
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000812 else {
813 Result = MakeReg(Node->getValueType(0));
814 ExprMap[N.getValue(0)] = Result;
815 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
816 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000817 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000818 }
819 }
820
Andrew Lenharth22088bb2005-02-02 15:05:33 +0000821 if (DestType == MVT::f64 || DestType == MVT::f32 ||
Andrew Lenharth06342c32005-02-07 06:21:37 +0000822 (
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000823 (opcode == ISD::LOAD || opcode == ISD::CopyFromReg ||
824 opcode == ISD::EXTLOAD) &&
825 (N.getValue(0).getValueType() == MVT::f32 ||
826 N.getValue(0).getValueType() == MVT::f64)
Andrew Lenharth06342c32005-02-07 06:21:37 +0000827 )
828 )
Andrew Lenharth40831c52005-01-28 06:57:18 +0000829 return SelectExprFP(N, Result);
830
831 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000832 default:
833 Node->dump();
834 assert(0 && "Node not handled!\n");
835
Andrew Lenharth032f2352005-02-22 21:59:48 +0000836 case ISD::DYNAMIC_STACKALLOC:
837 // Generate both result values.
Andrew Lenharth3a7118d2005-02-23 17:33:42 +0000838 if (Result != notIn)
839 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth032f2352005-02-22 21:59:48 +0000840 else
841 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
842
843 // FIXME: We are currently ignoring the requested alignment for handling
844 // greater than the stack alignment. This will need to be revisited at some
845 // point. Align = N.getOperand(2);
846
847 if (!isa<ConstantSDNode>(N.getOperand(2)) ||
848 cast<ConstantSDNode>(N.getOperand(2))->getValue() != 0) {
849 std::cerr << "Cannot allocate stack object with greater alignment than"
850 << " the stack alignment yet!";
851 abort();
852 }
853
854 Select(N.getOperand(0));
855 if (ConstantSDNode* CN = dyn_cast<ConstantSDNode>(N.getOperand(1)))
856 {
857 if (CN->getValue() < 32000)
858 {
859 BuildMI(BB, Alpha::LDA, 2, Alpha::R30)
860 .addImm(-CN->getValue()).addReg(Alpha::R30);
861 } else {
862 Tmp1 = SelectExpr(N.getOperand(1));
863 // Subtract size from stack pointer, thereby allocating some space.
864 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
865 }
866 } else {
867 Tmp1 = SelectExpr(N.getOperand(1));
868 // Subtract size from stack pointer, thereby allocating some space.
869 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
870 }
871
872 // Put a pointer to the space into the result register, by copying the stack
873 // pointer.
Andrew Lenharth7bc47022005-02-22 23:29:25 +0000874 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R30).addReg(Alpha::R30);
Andrew Lenharth032f2352005-02-22 21:59:48 +0000875 return Result;
876
Andrew Lenharth33819132005-03-04 20:09:23 +0000877// case ISD::ConstantPool:
878// Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
879// AlphaLowering.restoreGP(BB);
880// BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(Tmp1);
881// return Result;
Andrew Lenharth2c594352005-01-29 15:42:07 +0000882
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000883 case ISD::FrameIndex:
Andrew Lenharth032f2352005-02-22 21:59:48 +0000884 BuildMI(BB, Alpha::LDA, 2, Result)
885 .addFrameIndex(cast<FrameIndexSDNode>(N)->getIndex())
886 .addReg(Alpha::F31);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000887 return Result;
888
889 case ISD::EXTLOAD:
Andrew Lenharthf311e8b2005-02-07 05:18:02 +0000890 case ISD::ZEXTLOAD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000891 case ISD::SEXTLOAD:
Andrew Lenhartha549deb2005-02-07 05:33:15 +0000892 case ISD::LOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000893 {
894 // Make sure we generate both values.
895 if (Result != notIn)
896 ExprMap[N.getValue(1)] = notIn; // Generate the token
897 else
898 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000899
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000900 SDOperand Chain = N.getOperand(0);
901 SDOperand Address = N.getOperand(1);
902 Select(Chain);
903
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000904 assert(Node->getValueType(0) == MVT::i64 &&
905 "Unknown type to sign extend to.");
Andrew Lenharth03824012005-02-07 05:55:55 +0000906 if (opcode == ISD::LOAD)
907 Opc = Alpha::LDQ;
908 else
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000909 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
910 default: Node->dump(); assert(0 && "Bad sign extend!");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000911 case MVT::i32: Opc = Alpha::LDL;
912 assert(opcode != ISD::ZEXTLOAD && "Not sext"); break;
913 case MVT::i16: Opc = Alpha::LDWU;
914 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharthf311e8b2005-02-07 05:18:02 +0000915 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000916 case MVT::i8: Opc = Alpha::LDBU;
917 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000918 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000919
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000920 if (Address.getOpcode() == ISD::GlobalAddress) {
921 AlphaLowering.restoreGP(BB);
922 Opc = GetSymVersion(Opc);
923 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
924 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000925 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
926 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +0000927 Opc = GetSymVersion(Opc);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000928 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000929 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000930 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000931 BuildMI(BB, Opc, 2, Result)
932 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
933 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000934 } else {
935 long offset;
936 SelectAddr(Address, Tmp1, offset);
937 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
938 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000939 return Result;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000940 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000941
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000942 case ISD::GlobalAddress:
943 AlphaLowering.restoreGP(BB);
944 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
945 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
946 return Result;
947
948 case ISD::CALL:
949 {
950 Select(N.getOperand(0));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000951
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000952 // The chain for this call is now lowered.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000953 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), notIn));
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000954
955 //grab the arguments
956 std::vector<unsigned> argvregs;
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000957 //assert(Node->getNumOperands() < 8 && "Only 6 args supported");
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000958 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000959 argvregs.push_back(SelectExpr(N.getOperand(i)));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000960
Andrew Lenharth684f2292005-01-30 00:35:27 +0000961 //in reg args
962 for(int i = 0, e = std::min(6, (int)argvregs.size()); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000963 {
964 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
965 Alpha::R19, Alpha::R20, Alpha::R21};
966 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
967 Alpha::F19, Alpha::F20, Alpha::F21};
968 switch(N.getOperand(i+2).getValueType()) {
969 default:
970 Node->dump();
971 N.getOperand(i).Val->dump();
972 std::cerr << "Type for " << i << " is: " <<
973 N.getOperand(i+2).getValueType() << "\n";
974 assert(0 && "Unknown value type for call");
975 case MVT::i1:
976 case MVT::i8:
977 case MVT::i16:
978 case MVT::i32:
979 case MVT::i64:
980 BuildMI(BB, Alpha::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
981 break;
982 case MVT::f32:
983 case MVT::f64:
984 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
985 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +0000986 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000987 }
Andrew Lenharth684f2292005-01-30 00:35:27 +0000988 //in mem args
989 for (int i = 6, e = argvregs.size(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000990 {
991 switch(N.getOperand(i+2).getValueType()) {
992 default:
993 Node->dump();
994 N.getOperand(i).Val->dump();
995 std::cerr << "Type for " << i << " is: " <<
996 N.getOperand(i+2).getValueType() << "\n";
997 assert(0 && "Unknown value type for call");
998 case MVT::i1:
999 case MVT::i8:
1000 case MVT::i16:
1001 case MVT::i32:
1002 case MVT::i64:
1003 BuildMI(BB, Alpha::STQ, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1004 break;
1005 case MVT::f32:
1006 BuildMI(BB, Alpha::STS, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1007 break;
1008 case MVT::f64:
1009 BuildMI(BB, Alpha::STT, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1010 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001011 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001012 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001013 //build the right kind of call
1014 if (GlobalAddressSDNode *GASD =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001015 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001016 {
Andrew Lenharth3e315922005-02-10 20:10:38 +00001017 //if (GASD->getGlobal()->isExternal()) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001018 //use safe calling convention
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001019 AlphaLowering.restoreGP(BB);
1020 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
Andrew Lenharth3e315922005-02-10 20:10:38 +00001021 //} else {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001022 //use PC relative branch call
Andrew Lenharth3e315922005-02-10 20:10:38 +00001023 //BuildMI(BB, Alpha::BSR, 1, Alpha::R26).addGlobalAddress(GASD->getGlobal(),true);
1024 //}
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001025 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001026 else if (ExternalSymbolSDNode *ESSDN =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001027 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001028 {
1029 AlphaLowering.restoreGP(BB);
Andrew Lenharthba05ad62005-03-30 18:22:52 +00001030 BuildMI(BB, Alpha::CALL, 1).addExternalSymbol(ESSDN->getSymbol(), true);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001031 } else {
1032 //no need to restore GP as we are doing an indirect call
1033 Tmp1 = SelectExpr(N.getOperand(1));
1034 BuildMI(BB, Alpha::BIS, 2, Alpha::R27).addReg(Tmp1).addReg(Tmp1);
1035 BuildMI(BB, Alpha::JSR, 2, Alpha::R26).addReg(Alpha::R27).addImm(0);
1036 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001037
1038 //push the result into a virtual register
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001039
1040 switch (Node->getValueType(0)) {
1041 default: Node->dump(); assert(0 && "Unknown value type for call result!");
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001042 case MVT::Other: return notIn;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001043 case MVT::i1:
1044 case MVT::i8:
1045 case MVT::i16:
1046 case MVT::i32:
1047 case MVT::i64:
1048 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
1049 break;
1050 case MVT::f32:
1051 case MVT::f64:
1052 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
1053 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001054 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001055 return Result+N.ResNo;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001056 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001057
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001058 case ISD::SIGN_EXTEND:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001059 abort();
1060
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001061 case ISD::SIGN_EXTEND_INREG:
1062 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001063 //do SDIV opt for all levels of ints
Andrew Lenharth5e99dd92005-03-31 22:02:25 +00001064 if (EnableAlphaIDIV && N.getOperand(0).getOpcode() == ISD::SDIV)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001065 {
1066 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1067 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1068 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1069 MachineFunction *F = BB->getParent();
1070 int FrameIdxL = F->getFrameInfo()->CreateStackObject(Size, 8);
1071 int FrameIdxR = F->getFrameInfo()->CreateStackObject(Size, 8);
1072 int FrameIdxF = F->getFrameInfo()->CreateStackObject(Size, 8);
1073 unsigned Tmp4 = MakeReg(MVT::f64);
1074 unsigned Tmp5 = MakeReg(MVT::f64);
1075 unsigned Tmp6 = MakeReg(MVT::f64);
1076 unsigned Tmp7 = MakeReg(MVT::f64);
1077 unsigned Tmp8 = MakeReg(MVT::f64);
1078 unsigned Tmp9 = MakeReg(MVT::f64);
1079
1080 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addFrameIndex(FrameIdxL).addReg(Alpha::F31);
Andrew Lenharthcc59ed52005-03-23 15:20:01 +00001081 BuildMI(BB, Alpha::STQ, 3).addReg(Tmp2).addFrameIndex(FrameIdxR).addReg(Alpha::F31);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001082 BuildMI(BB, Alpha::LDT, 2, Tmp4).addFrameIndex(FrameIdxL).addReg(Alpha::F31);
1083 BuildMI(BB, Alpha::LDT, 2, Tmp5).addFrameIndex(FrameIdxR).addReg(Alpha::F31);
1084 BuildMI(BB, Alpha::CVTQT, 1, Tmp6).addReg(Tmp4);
1085 BuildMI(BB, Alpha::CVTQT, 1, Tmp7).addReg(Tmp5);
1086 BuildMI(BB, Alpha::DIVT, 2, Tmp8).addReg(Tmp6).addReg(Tmp7);
1087 BuildMI(BB, Alpha::CVTTQ, 1, Tmp9).addReg(Tmp8);
1088 BuildMI(BB, Alpha::STT, 3).addReg(Tmp9).addFrameIndex(FrameIdxF).addReg(Alpha::F31);
Andrew Lenharthcc59ed52005-03-23 15:20:01 +00001089 BuildMI(BB, Alpha::LDQ, 2, Result).addFrameIndex(FrameIdxF).addReg(Alpha::F31);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001090 return Result;
1091 }
1092
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001093 //Alpha has instructions for a bunch of signed 32 bit stuff
1094 if( dyn_cast<MVTSDNode>(Node)->getExtraValueType() == MVT::i32)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001095 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001096 switch (N.getOperand(0).getOpcode()) {
1097 case ISD::ADD:
1098 case ISD::SUB:
1099 case ISD::MUL:
1100 {
1101 bool isAdd = N.getOperand(0).getOpcode() == ISD::ADD;
1102 bool isMul = N.getOperand(0).getOpcode() == ISD::MUL;
1103 //FIXME: first check for Scaled Adds and Subs!
1104 if(N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1105 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() <= 255)
1106 { //Normal imm add/sub
1107 Opc = isAdd ? Alpha::ADDLi : (isMul ? Alpha::MULLi : Alpha::SUBLi);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001108 //if the value was really originally a i32, skip the up conversion
1109 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1110 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1111 ->getExtraValueType() == MVT::i32)
1112 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1113 else
1114 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001115 Tmp2 = cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue();
1116 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001117 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001118 else
1119 { //Normal add/sub
1120 Opc = isAdd ? Alpha::ADDL : (isMul ? Alpha::MULLi : Alpha::SUBL);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001121 //if the value was really originally a i32, skip the up conversion
1122 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1123 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1124 ->getExtraValueType() == MVT::i32)
1125 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1126 else
1127 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1128 //if the value was really originally a i32, skip the up conversion
1129 if (N.getOperand(0).getOperand(1).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1130 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(1).Val)
1131 ->getExtraValueType() == MVT::i32)
1132 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0));
1133 else
1134 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1135
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001136 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1137 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1138 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1139 }
1140 return Result;
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001141 }
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001142 case ISD::SEXTLOAD:
1143 //SelectionDag isn't deleting the signextend after sextloads
1144 Reg = Result = SelectExpr(N.getOperand(0));
1145 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001146 default: break; //Fall Though;
1147 }
1148 } //Every thing else fall though too, including unhandled opcodes above
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001149 Tmp1 = SelectExpr(N.getOperand(0));
1150 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001151 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001152 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001153 {
1154 default:
1155 Node->dump();
1156 assert(0 && "Sign Extend InReg not there yet");
1157 break;
1158 case MVT::i32:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001159 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001160 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001161 break;
1162 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001163 case MVT::i16:
1164 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
1165 break;
1166 case MVT::i8:
1167 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
1168 break;
Andrew Lenharthebce5042005-02-12 19:35:12 +00001169 case MVT::i1:
1170 Tmp2 = MakeReg(MVT::i64);
1171 BuildMI(BB, Alpha::ANDi, 2, Tmp2).addReg(Tmp1).addImm(1);
Andrew Lenharth7536eea2005-02-12 20:42:09 +00001172 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Alpha::F31).addReg(Tmp2);
Andrew Lenharthebce5042005-02-12 19:35:12 +00001173 break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001174 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001175 return Result;
1176 }
1177 case ISD::ZERO_EXTEND_INREG:
1178 {
1179 Tmp1 = SelectExpr(N.getOperand(0));
1180 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001181 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001182 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001183 {
1184 default:
1185 Node->dump();
1186 assert(0 && "Zero Extend InReg not there yet");
1187 break;
1188 case MVT::i32: Tmp2 = 0xf0; break;
1189 case MVT::i16: Tmp2 = 0xfc; break;
1190 case MVT::i8: Tmp2 = 0xfe; break;
1191 case MVT::i1: //handle this one special
1192 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
1193 return Result;
1194 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001195 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001196 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001197 }
1198
1199 case ISD::SETCC:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001200 {
1201 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
1202 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
1203 bool isConst1 = false;
1204 bool isConst2 = false;
1205 int dir;
Andrew Lenharth9818c052005-02-05 13:19:12 +00001206
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001207 //Tmp1 = SelectExpr(N.getOperand(0));
1208 if(N.getOperand(0).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001209 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1210 isConst1 = true;
1211 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001212 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1213 isConst2 = true;
1214
1215 switch (SetCC->getCondition()) {
1216 default: Node->dump(); assert(0 && "Unknown integer comparison!");
1217 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001218 case ISD::SETLT:
1219 Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
1220 case ISD::SETLE:
1221 Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
1222 case ISD::SETGT:
1223 Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
1224 case ISD::SETGE:
1225 Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
1226 case ISD::SETULT:
1227 Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
1228 case ISD::SETUGT:
1229 Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
1230 case ISD::SETULE:
1231 Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
1232 case ISD::SETUGE:
1233 Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001234 case ISD::SETNE: {//Handle this one special
1235 //std::cerr << "Alpha does not have a setne.\n";
1236 //abort();
1237 Tmp1 = SelectExpr(N.getOperand(0));
1238 Tmp2 = SelectExpr(N.getOperand(1));
1239 Tmp3 = MakeReg(MVT::i64);
1240 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth445171a2005-02-08 00:40:03 +00001241 //Remeber we have the Inv for this CC
1242 CCInvMap[N] = Tmp3;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001243 //and invert
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001244 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001245 return Result;
1246 }
1247 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001248 if (dir == 1) {
1249 Tmp1 = SelectExpr(N.getOperand(0));
1250 if (isConst2) {
1251 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1252 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1253 } else {
1254 Tmp2 = SelectExpr(N.getOperand(1));
1255 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1256 }
1257 } else if (dir == 2) {
1258 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001259 if (isConst1) {
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001260 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1261 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1262 } else {
1263 Tmp2 = SelectExpr(N.getOperand(0));
1264 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1265 }
1266 } else { //dir == 0
1267 if (isConst1) {
1268 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1269 Tmp2 = SelectExpr(N.getOperand(1));
1270 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
1271 } else if (isConst2) {
1272 Tmp1 = SelectExpr(N.getOperand(0));
1273 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1274 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
1275 } else {
1276 Tmp1 = SelectExpr(N.getOperand(0));
1277 Tmp2 = SelectExpr(N.getOperand(1));
1278 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
1279 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001280 }
1281 } else {
1282 //assert(SetCC->getOperand(0).getValueType() != MVT::f32 && "SetCC f32 should have been promoted");
1283 bool rev = false;
1284 bool inv = false;
1285
1286 switch (SetCC->getCondition()) {
1287 default: Node->dump(); assert(0 && "Unknown FP comparison!");
1288 case ISD::SETEQ: Opc = Alpha::CMPTEQ; break;
1289 case ISD::SETLT: Opc = Alpha::CMPTLT; break;
1290 case ISD::SETLE: Opc = Alpha::CMPTLE; break;
1291 case ISD::SETGT: Opc = Alpha::CMPTLT; rev = true; break;
1292 case ISD::SETGE: Opc = Alpha::CMPTLE; rev = true; break;
1293 case ISD::SETNE: Opc = Alpha::CMPTEQ; inv = true; break;
1294 }
1295
Andrew Lenharthca3d59b2005-03-14 19:23:45 +00001296 //FIXME: check for constant 0.0
1297 ConstantFPSDNode *CN;
1298 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
1299 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1300 Tmp1 = Alpha::F31;
1301 else
1302 Tmp1 = SelectExpr(N.getOperand(0));
1303
1304 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
1305 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1306 Tmp2 = Alpha::F31;
1307 else
1308 Tmp2 = SelectExpr(N.getOperand(1));
1309
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001310 //Can only compare doubles, and dag won't promote for me
1311 if (SetCC->getOperand(0).getValueType() == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001312 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001313 //assert(0 && "Setcc On float?\n");
1314 std::cerr << "Setcc on float!\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001315 Tmp3 = MakeReg(MVT::f64);
1316 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp1);
1317 Tmp1 = Tmp3;
1318 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001319 if (SetCC->getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001320 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001321 //assert (0 && "Setcc On float?\n");
1322 std::cerr << "Setcc on float!\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001323 Tmp3 = MakeReg(MVT::f64);
1324 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp2);
Andrew Lenharth572af902005-02-14 05:41:43 +00001325 Tmp2 = Tmp3;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001326 }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001327
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001328 if (rev) std::swap(Tmp1, Tmp2);
1329 Tmp3 = MakeReg(MVT::f64);
1330 //do the comparison
1331 BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
1332
1333 //now arrange for Result (int) to have a 1 or 0
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001334 unsigned Tmp4 = MakeReg(MVT::i64);
1335 BuildMI(BB, Alpha::ADDQi, 2, Tmp4).addReg(Alpha::R31).addImm(1);
1336 Opc = inv?Alpha::CMOVNEi_FP:Alpha::CMOVEQi_FP;
1337 BuildMI(BB, Opc, 3, Result).addReg(Tmp4).addImm(0).addReg(Tmp3);
Andrew Lenharthca3d59b2005-03-14 19:23:45 +00001338
1339// // Spill the FP to memory and reload it from there.
1340// unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1341// MachineFunction *F = BB->getParent();
1342// int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
1343// unsigned Tmp4 = MakeReg(MVT::f64);
1344// BuildMI(BB, Alpha::CVTTQ, 1, Tmp4).addReg(Tmp3);
1345// BuildMI(BB, Alpha::STT, 3).addReg(Tmp4).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1346// unsigned Tmp5 = MakeReg(MVT::i64);
1347// BuildMI(BB, Alpha::LDQ, 2, Tmp5).addFrameIndex(FrameIdx).addReg(Alpha::F31);
Andrew Lenharth9818c052005-02-05 13:19:12 +00001348
Andrew Lenharthca3d59b2005-03-14 19:23:45 +00001349// //now, set result based on Tmp5
1350// //Set Tmp6 if fp cmp was false
1351// unsigned Tmp6 = MakeReg(MVT::i64);
1352// BuildMI(BB, Alpha::CMPEQ, 2, Tmp6).addReg(Tmp5).addReg(Alpha::R31);
1353// //and invert
1354// BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp6).addReg(Alpha::R31);
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001355
1356 }
1357 // else
1358 // {
1359 // Node->dump();
1360 // assert(0 && "Not a setcc in setcc");
1361 // }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001362 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001363 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001364 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001365
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001366 case ISD::CopyFromReg:
1367 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001368 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001369 if (Result != notIn)
1370 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth40831c52005-01-28 06:57:18 +00001371 else
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001372 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth40831c52005-01-28 06:57:18 +00001373
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001374 SDOperand Chain = N.getOperand(0);
1375
1376 Select(Chain);
1377 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
1378 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
1379 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
1380 return Result;
1381 }
1382
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001383 //Most of the plain arithmetic and logic share the same form, and the same
1384 //constant immediate test
1385 case ISD::AND:
1386 case ISD::OR:
1387 case ISD::XOR:
1388 case ISD::SHL:
1389 case ISD::SRL:
Andrew Lenharth2c594352005-01-29 15:42:07 +00001390 case ISD::SRA:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001391 case ISD::MUL:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001392 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
1393 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001394 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001395 {
1396 switch(opcode) {
1397 case ISD::AND: Opc = Alpha::ANDi; break;
1398 case ISD::OR: Opc = Alpha::BISi; break;
1399 case ISD::XOR: Opc = Alpha::XORi; break;
1400 case ISD::SHL: Opc = Alpha::SLi; break;
1401 case ISD::SRL: Opc = Alpha::SRLi; break;
1402 case ISD::SRA: Opc = Alpha::SRAi; break;
1403 case ISD::MUL: Opc = Alpha::MULQi; break;
1404 };
1405 Tmp1 = SelectExpr(N.getOperand(0));
1406 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1407 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1408 } else {
1409 switch(opcode) {
1410 case ISD::AND: Opc = Alpha::AND; break;
1411 case ISD::OR: Opc = Alpha::BIS; break;
1412 case ISD::XOR: Opc = Alpha::XOR; break;
1413 case ISD::SHL: Opc = Alpha::SL; break;
1414 case ISD::SRL: Opc = Alpha::SRL; break;
1415 case ISD::SRA: Opc = Alpha::SRA; break;
1416 case ISD::MUL: Opc = Alpha::MULQ; break;
1417 };
1418 Tmp1 = SelectExpr(N.getOperand(0));
1419 Tmp2 = SelectExpr(N.getOperand(1));
1420 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1421 }
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001422 return Result;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001423
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001424 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001425 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001426 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001427 bool isAdd = opcode == ISD::ADD;
1428
1429 //FIXME: first check for Scaled Adds and Subs!
1430 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001431 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001432 { //Normal imm add/sub
1433 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
1434 Tmp1 = SelectExpr(N.getOperand(0));
1435 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1436 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1437 }
Andrew Lenharth40831c52005-01-28 06:57:18 +00001438 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001439 (cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767 ||
1440 (long)cast<ConstantSDNode>(N.getOperand(1))->getValue() >= -32767))
1441 { //LDA
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001442 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001443 Tmp2 = (long)cast<ConstantSDNode>(N.getOperand(1))->getValue();
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001444 if (!isAdd)
1445 Tmp2 = -Tmp2;
1446 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
1447 } else {
1448 //Normal add/sub
1449 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
1450 Tmp1 = SelectExpr(N.getOperand(0));
1451 Tmp2 = SelectExpr(N.getOperand(1));
1452 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1453 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001454 return Result;
1455 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001456
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001457 case ISD::SDIV:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001458 case ISD::UREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001459 case ISD::SREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001460 case ISD::UDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001461 //FIXME: alpha really doesn't support any of these operations,
1462 // the ops are expanded into special library calls with
1463 // special calling conventions
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001464 //Restore GP because it is a call after all...
Andrew Lenharth40831c52005-01-28 06:57:18 +00001465 switch(opcode) {
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001466 case ISD::UREM: Opc = Alpha::REMQU; break;
1467 case ISD::SREM: Opc = Alpha::REMQ; break;
1468 case ISD::UDIV: Opc = Alpha::DIVQU; break;
1469 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001470 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001471 Tmp1 = SelectExpr(N.getOperand(0));
1472 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth33819132005-03-04 20:09:23 +00001473 //set up regs explicitly (helps Reg alloc)
1474 BuildMI(BB, Alpha::BIS, 2, Alpha::R24).addReg(Tmp1).addReg(Tmp1);
1475 BuildMI(BB, Alpha::BIS, 2, Alpha::R25).addReg(Tmp2).addReg(Tmp2);
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001476 AlphaLowering.restoreGP(BB);
Andrew Lenharth33819132005-03-04 20:09:23 +00001477 BuildMI(BB, Opc, 2).addReg(Alpha::R24).addReg(Alpha::R25);
1478 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R27).addReg(Alpha::R27);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001479 return Result;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001480
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001481 case ISD::FP_TO_UINT:
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001482 case ISD::FP_TO_SINT:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001483 {
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001484 assert (DestType == MVT::i64 && "only quads can be loaded to");
1485 MVT::ValueType SrcType = N.getOperand(0).getValueType();
Andrew Lenharth03824012005-02-07 05:55:55 +00001486 assert (SrcType == MVT::f32 || SrcType == MVT::f64);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001487 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
1488
1489 //The hard way:
1490 // Spill the integer to memory and reload it from there.
1491 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
1492 MachineFunction *F = BB->getParent();
1493 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
1494
1495 //CVTTQ STT LDQ
1496 //CVTST CVTTQ STT LDQ
1497 if (SrcType == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001498 {
1499 Tmp2 = MakeReg(MVT::f64);
1500 BuildMI(BB, Alpha::CVTST, 1, Tmp2).addReg(Tmp1);
1501 Tmp1 = Tmp2;
1502 }
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001503 Tmp2 = MakeReg(MVT::f64);
1504 BuildMI(BB, Alpha::CVTTQ, 1, Tmp2).addReg(Tmp1);
1505 BuildMI(BB, Alpha::STT, 3).addReg(Tmp2).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1506 BuildMI(BB, Alpha::LDQ, 2, Result).addFrameIndex(FrameIdx).addReg(Alpha::F31);
1507
1508 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001509 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001510
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001511 // // case ISD::FP_TO_UINT:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001512
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001513 case ISD::SELECT:
1514 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001515 //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 +00001516 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001517 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1518 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001519 // Get the condition into the zero flag.
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001520 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001521 return Result;
1522 }
1523
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001524 case ISD::Constant:
1525 {
Andrew Lenharthc0513832005-03-29 19:24:04 +00001526 int64_t val = (int64_t)cast<ConstantSDNode>(N)->getValue();
Andrew Lenharthe87f6c32005-03-11 17:48:05 +00001527 if (val <= IMM_HIGH && val >= IMM_LOW) {
1528 BuildMI(BB, Alpha::LDA, 2, Result).addImm(val).addReg(Alpha::R31);
1529 }
1530 else if (val <= (int64_t)IMM_HIGH + (int64_t)IMM_HIGH * (int64_t)IMM_MULT &&
1531 val >= (int64_t)IMM_LOW + (int64_t)IMM_LOW * (int64_t)IMM_MULT) {
1532 Tmp1 = MakeReg(MVT::i64);
1533 BuildMI(BB, Alpha::LDAH, 2, Tmp1).addImm(getUpper16(val)).addReg(Alpha::R31);
1534 BuildMI(BB, Alpha::LDA, 2, Result).addImm(getLower16(val)).addReg(Tmp1);
1535 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001536 else {
1537 MachineConstantPool *CP = BB->getParent()->getConstantPool();
1538 ConstantUInt *C = ConstantUInt::get(Type::getPrimitiveType(Type::ULongTyID) , val);
1539 unsigned CPI = CP->getConstantPoolIndex(C);
1540 AlphaLowering.restoreGP(BB);
1541 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(CPI);
1542 }
1543 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001544 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001545 }
1546
1547 return 0;
1548}
1549
1550void ISel::Select(SDOperand N) {
1551 unsigned Tmp1, Tmp2, Opc;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001552 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001553
Nate Begeman85fdeb22005-03-24 04:39:54 +00001554 if (!ExprMap.insert(std::make_pair(N, notIn)).second)
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001555 return; // Already selected.
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001556
1557 SDNode *Node = N.Val;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001558
Andrew Lenharth760270d2005-02-07 23:02:23 +00001559 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001560
1561 default:
1562 Node->dump(); std::cerr << "\n";
1563 assert(0 && "Node not handled yet!");
1564
1565 case ISD::BRCOND: {
Andrew Lenharth445171a2005-02-08 00:40:03 +00001566 SelectBranchCC(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001567 return;
1568 }
1569
1570 case ISD::BR: {
1571 MachineBasicBlock *Dest =
1572 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
1573
1574 Select(N.getOperand(0));
1575 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
1576 return;
1577 }
1578
1579 case ISD::ImplicitDef:
1580 Select(N.getOperand(0));
1581 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
1582 return;
1583
1584 case ISD::EntryToken: return; // Noop
1585
1586 case ISD::TokenFactor:
1587 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
1588 Select(Node->getOperand(i));
1589
1590 //N.Val->dump(); std::cerr << "\n";
1591 //assert(0 && "Node not handled yet!");
1592
1593 return;
1594
1595 case ISD::CopyToReg:
1596 Select(N.getOperand(0));
1597 Tmp1 = SelectExpr(N.getOperand(1));
1598 Tmp2 = cast<RegSDNode>(N)->getReg();
1599
1600 if (Tmp1 != Tmp2) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001601 if (N.getOperand(1).getValueType() == MVT::f64 ||
1602 N.getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth29219162005-02-07 06:31:44 +00001603 BuildMI(BB, Alpha::CPYS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
1604 else
1605 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001606 }
1607 return;
1608
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001609 case ISD::RET:
1610 switch (N.getNumOperands()) {
1611 default:
1612 std::cerr << N.getNumOperands() << "\n";
1613 for (unsigned i = 0; i < N.getNumOperands(); ++i)
1614 std::cerr << N.getOperand(i).getValueType() << "\n";
1615 Node->dump();
1616 assert(0 && "Unknown return instruction!");
1617 case 2:
1618 Select(N.getOperand(0));
1619 Tmp1 = SelectExpr(N.getOperand(1));
1620 switch (N.getOperand(1).getValueType()) {
1621 default: Node->dump();
1622 assert(0 && "All other types should have been promoted!!");
1623 case MVT::f64:
1624 case MVT::f32:
1625 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
1626 break;
1627 case MVT::i32:
1628 case MVT::i64:
1629 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
1630 break;
1631 }
1632 break;
1633 case 1:
1634 Select(N.getOperand(0));
1635 break;
1636 }
1637 //Tmp2 = AlphaLowering.getRetAddr();
1638 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
1639 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
1640 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001641
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001642 case ISD::TRUNCSTORE:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001643 case ISD::STORE:
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001644 {
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001645 SDOperand Chain = N.getOperand(0);
1646 SDOperand Value = N.getOperand(1);
1647 SDOperand Address = N.getOperand(2);
1648 Select(Chain);
1649
1650 Tmp1 = SelectExpr(Value); //value
Andrew Lenharth760270d2005-02-07 23:02:23 +00001651
1652 if (opcode == ISD::STORE) {
1653 switch(Value.getValueType()) {
1654 default: assert(0 && "unknown Type in store");
1655 case MVT::i64: Opc = Alpha::STQ; break;
1656 case MVT::f64: Opc = Alpha::STT; break;
1657 case MVT::f32: Opc = Alpha::STS; break;
1658 }
1659 } else { //ISD::TRUNCSTORE
1660 switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
1661 default: assert(0 && "unknown Type in store");
1662 case MVT::i1: //FIXME: DAG does not promote this load
1663 case MVT::i8: Opc = Alpha::STB; break;
1664 case MVT::i16: Opc = Alpha::STW; break;
1665 case MVT::i32: Opc = Alpha::STL; break;
1666 }
Andrew Lenharth65838902005-02-06 16:22:15 +00001667 }
Andrew Lenharth760270d2005-02-07 23:02:23 +00001668
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001669 if (Address.getOpcode() == ISD::GlobalAddress)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001670 {
1671 AlphaLowering.restoreGP(BB);
1672 Opc = GetSymVersion(Opc);
1673 BuildMI(BB, Opc, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1674 }
Andrew Lenharth05380342005-02-07 05:07:00 +00001675 else if(Address.getOpcode() == ISD::FrameIndex)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001676 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001677 BuildMI(BB, Opc, 3).addReg(Tmp1)
1678 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1679 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001680 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001681 else
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001682 {
1683 long offset;
1684 SelectAddr(Address, Tmp2, offset);
1685 BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
1686 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001687 return;
1688 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001689
1690 case ISD::EXTLOAD:
1691 case ISD::SEXTLOAD:
1692 case ISD::ZEXTLOAD:
1693 case ISD::LOAD:
1694 case ISD::CopyFromReg:
1695 case ISD::CALL:
Andrew Lenharth032f2352005-02-22 21:59:48 +00001696 case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001697 ExprMap.erase(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001698 SelectExpr(N);
1699 return;
1700
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001701 case ISD::ADJCALLSTACKDOWN:
1702 case ISD::ADJCALLSTACKUP:
1703 Select(N.getOperand(0));
1704 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1705
1706 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
1707 Alpha::ADJUSTSTACKUP;
1708 BuildMI(BB, Opc, 1).addImm(Tmp1);
1709 return;
Andrew Lenharth95762122005-03-31 21:24:06 +00001710
1711 case ISD::PCMARKER:
1712 Select(N.getOperand(0)); //Chain
1713 BuildMI(BB, Alpha::PCLABEL, 2).addImm( cast<ConstantSDNode>(N.getOperand(1))->getValue());
1714 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001715 }
1716 assert(0 && "Should not be reached!");
1717}
1718
1719
1720/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
1721/// into a machine code representation using pattern matching and a machine
1722/// description file.
1723///
1724FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
1725 return new ISel(TM);
1726}