blob: 8bf26cbc18e5dd8fe215810b4fda3842ff69e8d0 [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);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +000039 cl::opt<bool> EnableAlphaFTOI("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);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000336 void MoveFP2Int(unsigned src, unsigned dst, bool isDouble);
337 void MoveInt2FP(unsigned src, unsigned dst, bool isDouble);
Andrew Lenharth10c085b2005-04-02 22:32:39 +0000338 //returns whether the sense of the comparison was inverted
339 bool SelectFPSetCC(SDOperand N, unsigned dst);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000340};
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000341}
342
Andrew Lenharthe87f6c32005-03-11 17:48:05 +0000343//These describe LDAx
Andrew Lenharthc0513832005-03-29 19:24:04 +0000344static const int IMM_LOW = -32768;
345static const int IMM_HIGH = 32767;
Andrew Lenharthe87f6c32005-03-11 17:48:05 +0000346static const int IMM_MULT = 65536;
347
348static long getUpper16(long l)
349{
350 long y = l / IMM_MULT;
351 if (l % IMM_MULT > IMM_HIGH)
352 ++y;
353 return y;
354}
355
356static long getLower16(long l)
357{
358 long h = getUpper16(l);
359 return l - h * IMM_MULT;
360}
361
Andrew Lenharth65838902005-02-06 16:22:15 +0000362static unsigned GetSymVersion(unsigned opcode)
363{
364 switch (opcode) {
365 default: assert(0 && "unknown load or store"); return 0;
366 case Alpha::LDQ: return Alpha::LDQ_SYM;
367 case Alpha::LDS: return Alpha::LDS_SYM;
368 case Alpha::LDT: return Alpha::LDT_SYM;
369 case Alpha::LDL: return Alpha::LDL_SYM;
370 case Alpha::LDBU: return Alpha::LDBU_SYM;
371 case Alpha::LDWU: return Alpha::LDWU_SYM;
372 case Alpha::LDW: return Alpha::LDW_SYM;
373 case Alpha::LDB: return Alpha::LDB_SYM;
374 case Alpha::STQ: return Alpha::STQ_SYM;
375 case Alpha::STS: return Alpha::STS_SYM;
376 case Alpha::STT: return Alpha::STT_SYM;
377 case Alpha::STL: return Alpha::STL_SYM;
378 case Alpha::STW: return Alpha::STW_SYM;
379 case Alpha::STB: return Alpha::STB_SYM;
380 }
381}
382
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000383void ISel::MoveFP2Int(unsigned src, unsigned dst, bool isDouble)
384{
385 unsigned Opc;
386 if (EnableAlphaFTOI) {
387 Opc = isDouble ? Alpha::FTOIT : Alpha::FTOIS;
388 BuildMI(BB, Opc, 1, dst).addReg(src);
389 } else {
390 //The hard way:
391 // Spill the integer to memory and reload it from there.
392 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
393 MachineFunction *F = BB->getParent();
394 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
395
396 Opc = isDouble ? Alpha::STT : Alpha::STS;
397 BuildMI(BB, Opc, 3).addReg(src).addFrameIndex(FrameIdx).addReg(Alpha::F31);
398 Opc = isDouble ? Alpha::LDQ : Alpha::LDL;
399 BuildMI(BB, Alpha::LDQ, 2, dst).addFrameIndex(FrameIdx).addReg(Alpha::F31);
400 }
401}
402
403void ISel::MoveInt2FP(unsigned src, unsigned dst, bool isDouble)
404{
405 unsigned Opc;
406 if (EnableAlphaFTOI) {
407 Opc = isDouble?Alpha::ITOFT:Alpha::ITOFS;
408 BuildMI(BB, Opc, 1, dst).addReg(src);
409 } else {
410 //The hard way:
411 // Spill the integer to memory and reload it from there.
412 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
413 MachineFunction *F = BB->getParent();
414 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
415
416 Opc = isDouble ? Alpha::STQ : Alpha::STL;
417 BuildMI(BB, Opc, 3).addReg(src).addFrameIndex(FrameIdx).addReg(Alpha::F31);
418 Opc = isDouble ? Alpha::LDT : Alpha::LDS;
419 BuildMI(BB, Opc, 2, dst).addFrameIndex(FrameIdx).addReg(Alpha::F31);
420 }
421}
422
Andrew Lenharth10c085b2005-04-02 22:32:39 +0000423bool ISel::SelectFPSetCC(SDOperand N, unsigned dst)
424{
425 SDNode *Node = N.Val;
426 unsigned Opc, Tmp1, Tmp2, Tmp3;
427 SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node);
428
429 //assert(SetCC->getOperand(0).getValueType() != MVT::f32 && "SetCC f32 should have been promoted");
430 bool rev = false;
431 bool inv = false;
432
433 switch (SetCC->getCondition()) {
434 default: Node->dump(); assert(0 && "Unknown FP comparison!");
435 case ISD::SETEQ: Opc = Alpha::CMPTEQ; break;
436 case ISD::SETLT: Opc = Alpha::CMPTLT; break;
437 case ISD::SETLE: Opc = Alpha::CMPTLE; break;
438 case ISD::SETGT: Opc = Alpha::CMPTLT; rev = true; break;
439 case ISD::SETGE: Opc = Alpha::CMPTLE; rev = true; break;
440 case ISD::SETNE: Opc = Alpha::CMPTEQ; inv = true; break;
441 }
442
443 //FIXME: check for constant 0.0
444 ConstantFPSDNode *CN;
445 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
446 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
447 Tmp1 = Alpha::F31;
448 else
449 Tmp1 = SelectExpr(N.getOperand(0));
450
451 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
452 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
453 Tmp2 = Alpha::F31;
454 else
455 Tmp2 = SelectExpr(N.getOperand(1));
456
457 //Can only compare doubles, and dag won't promote for me
458 if (SetCC->getOperand(0).getValueType() == MVT::f32)
459 {
460 //assert(0 && "Setcc On float?\n");
461 std::cerr << "Setcc on float!\n";
462 Tmp3 = MakeReg(MVT::f64);
463 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp1);
464 Tmp1 = Tmp3;
465 }
466 if (SetCC->getOperand(1).getValueType() == MVT::f32)
467 {
468 //assert (0 && "Setcc On float?\n");
469 std::cerr << "Setcc on float!\n";
470 Tmp3 = MakeReg(MVT::f64);
471 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp2);
472 Tmp2 = Tmp3;
473 }
474
475 if (rev) std::swap(Tmp1, Tmp2);
476 //do the comparison
477 BuildMI(BB, Opc, 2, dst).addReg(Tmp1).addReg(Tmp2);
478 return inv;
479}
480
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000481//Check to see if the load is a constant offset from a base register
482void ISel::SelectAddr(SDOperand N, unsigned& Reg, long& offset)
483{
484 unsigned opcode = N.getOpcode();
485 if (opcode == ISD::ADD) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000486 if(N.getOperand(1).getOpcode() == ISD::Constant &&
487 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767)
488 { //Normal imm add
489 Reg = SelectExpr(N.getOperand(0));
490 offset = cast<ConstantSDNode>(N.getOperand(1))->getValue();
491 return;
492 }
493 else if(N.getOperand(0).getOpcode() == ISD::Constant &&
494 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 32767)
495 {
496 Reg = SelectExpr(N.getOperand(1));
497 offset = cast<ConstantSDNode>(N.getOperand(0))->getValue();
498 return;
499 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000500 }
501 Reg = SelectExpr(N);
502 offset = 0;
503 return;
504}
505
Andrew Lenharth445171a2005-02-08 00:40:03 +0000506void ISel::SelectBranchCC(SDOperand N)
507{
508 assert(N.getOpcode() == ISD::BRCOND && "Not a BranchCC???");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000509 MachineBasicBlock *Dest =
510 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
511 unsigned Opc = Alpha::WTF;
512
Andrew Lenharth445171a2005-02-08 00:40:03 +0000513 Select(N.getOperand(0)); //chain
514 SDOperand CC = N.getOperand(1);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000515
Andrew Lenharth445171a2005-02-08 00:40:03 +0000516 if (CC.getOpcode() == ISD::SETCC)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000517 {
518 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
519 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
520 //Dropping the CC is only useful if we are comparing to 0
Andrew Lenharth63b720a2005-04-03 20:35:21 +0000521 bool LeftZero = SetCC->getOperand(0).getOpcode() == ISD::Constant &&
522 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0;
523 bool RightZero = SetCC->getOperand(0).getOpcode() == ISD::Constant &&
524 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000525 bool isNE = false;
Andrew Lenharth63b720a2005-04-03 20:35:21 +0000526
527 //Fix up CC
528 ISD::CondCode cCode= SetCC->getCondition();
529 if (LeftZero && !RightZero) //Swap Operands
530 cCode = ISD::getSetCCSwappedOperands(cCode);
531
532 if(cCode == ISD::SETNE)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000533 isNE = true;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000534
Andrew Lenharth63b720a2005-04-03 20:35:21 +0000535 if (LeftZero || RightZero) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000536 switch (SetCC->getCondition()) {
537 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
538 case ISD::SETEQ: Opc = Alpha::BEQ; break;
539 case ISD::SETLT: Opc = Alpha::BLT; break;
540 case ISD::SETLE: Opc = Alpha::BLE; break;
541 case ISD::SETGT: Opc = Alpha::BGT; break;
542 case ISD::SETGE: Opc = Alpha::BGE; break;
543 case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break;
544 case ISD::SETUGT: Opc = Alpha::BNE; break;
545 case ISD::SETULE: Opc = Alpha::BEQ; break; //Technically you could have this CC
546 case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break;
547 case ISD::SETNE: Opc = Alpha::BNE; break;
548 }
Andrew Lenharth63b720a2005-04-03 20:35:21 +0000549 unsigned Tmp1;
550 if(LeftZero && !RightZero) //swap Operands
551 Tmp1 = SelectExpr(SetCC->getOperand(1)); //Cond
552 else
553 Tmp1 = SelectExpr(SetCC->getOperand(0)); //Cond
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000554 BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest);
555 return;
556 } else {
557 unsigned Tmp1 = SelectExpr(CC);
558 if (isNE)
559 BuildMI(BB, Alpha::BEQ, 2).addReg(CCInvMap[CC]).addMBB(Dest);
560 else
561 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000562 return;
563 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000564 } else { //FP
565 //Any comparison between 2 values should be codegened as an folded branch, as moving
566 //CC to the integer register is very expensive
567 //for a cmp b: c = a - b;
568 //a = b: c = 0
569 //a < b: c < 0
570 //a > b: c > 0
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000571
572 bool invTest = false;
573 unsigned Tmp3;
574
575 ConstantFPSDNode *CN;
576 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
577 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
578 Tmp3 = SelectExpr(SetCC->getOperand(0));
579 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
580 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
581 {
582 Tmp3 = SelectExpr(SetCC->getOperand(1));
583 invTest = true;
584 }
585 else
586 {
587 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
588 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
589 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
590 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
591 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
592 .addReg(Tmp1).addReg(Tmp2);
593 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000594
595 switch (SetCC->getCondition()) {
596 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000597 case ISD::SETEQ: Opc = invTest ? Alpha::FBNE : Alpha::FBEQ; break;
598 case ISD::SETLT: Opc = invTest ? Alpha::FBGT : Alpha::FBLT; break;
599 case ISD::SETLE: Opc = invTest ? Alpha::FBGE : Alpha::FBLE; break;
600 case ISD::SETGT: Opc = invTest ? Alpha::FBLT : Alpha::FBGT; break;
601 case ISD::SETGE: Opc = invTest ? Alpha::FBLE : Alpha::FBGE; break;
602 case ISD::SETNE: Opc = invTest ? Alpha::FBEQ : Alpha::FBNE; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000603 }
604 BuildMI(BB, Opc, 2).addReg(Tmp3).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000605 return;
606 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000607 abort(); //Should never be reached
608 } else {
609 //Giveup and do the stupid thing
610 unsigned Tmp1 = SelectExpr(CC);
611 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
612 return;
613 }
Andrew Lenharth445171a2005-02-08 00:40:03 +0000614 abort(); //Should never be reached
615}
616
Andrew Lenharth40831c52005-01-28 06:57:18 +0000617unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
618{
619 unsigned Tmp1, Tmp2, Tmp3;
620 unsigned Opc = 0;
621 SDNode *Node = N.Val;
622 MVT::ValueType DestType = N.getValueType();
623 unsigned opcode = N.getOpcode();
624
625 switch (opcode) {
626 default:
627 Node->dump();
628 assert(0 && "Node not handled!\n");
Andrew Lenharth2c594352005-01-29 15:42:07 +0000629
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000630 case ISD::UNDEF: {
631 BuildMI(BB, Alpha::IDEF, 0, Result);
632 return Result;
633 }
634
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000635 case ISD::FNEG:
636 if(ISD::FABS == N.getOperand(0).getOpcode())
637 {
638 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000639 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000640 } else {
641 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000642 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000643 }
644 return Result;
645
646 case ISD::FABS:
647 Tmp1 = SelectExpr(N.getOperand(0));
648 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
649 return Result;
650
Andrew Lenharth9818c052005-02-05 13:19:12 +0000651 case ISD::SELECT:
652 {
Andrew Lenharth45859692005-03-03 21:47:53 +0000653 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
654 unsigned TV = SelectExpr(N.getOperand(1)); //Use if TRUE
655 unsigned FV = SelectExpr(N.getOperand(2)); //Use if FALSE
656
657 SDOperand CC = N.getOperand(0);
658 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
659
660 if (CC.getOpcode() == ISD::SETCC &&
661 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
662 { //FP Setcc -> Select yay!
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000663
664
Andrew Lenharth45859692005-03-03 21:47:53 +0000665 //for a cmp b: c = a - b;
666 //a = b: c = 0
667 //a < b: c < 0
668 //a > b: c > 0
669
670 bool invTest = false;
671 unsigned Tmp3;
672
673 ConstantFPSDNode *CN;
674 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
675 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
676 Tmp3 = SelectExpr(SetCC->getOperand(0));
677 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
678 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
679 {
680 Tmp3 = SelectExpr(SetCC->getOperand(1));
681 invTest = true;
682 }
683 else
684 {
685 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
686 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
687 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
688 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
689 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
690 .addReg(Tmp1).addReg(Tmp2);
691 }
692
693 switch (SetCC->getCondition()) {
694 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
695 case ISD::SETEQ: Opc = invTest ? Alpha::FCMOVNE : Alpha::FCMOVEQ; break;
696 case ISD::SETLT: Opc = invTest ? Alpha::FCMOVGT : Alpha::FCMOVLT; break;
697 case ISD::SETLE: Opc = invTest ? Alpha::FCMOVGE : Alpha::FCMOVLE; break;
698 case ISD::SETGT: Opc = invTest ? Alpha::FCMOVLT : Alpha::FCMOVGT; break;
699 case ISD::SETGE: Opc = invTest ? Alpha::FCMOVLE : Alpha::FCMOVGE; break;
700 case ISD::SETNE: Opc = invTest ? Alpha::FCMOVEQ : Alpha::FCMOVNE; break;
701 }
Andrew Lenharth33819132005-03-04 20:09:23 +0000702 BuildMI(BB, Opc, 3, Result).addReg(FV).addReg(TV).addReg(Tmp3);
Andrew Lenharth45859692005-03-03 21:47:53 +0000703 return Result;
704 }
705 else
706 {
707 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000708 BuildMI(BB, Alpha::FCMOVEQ_INT, 3, Result).addReg(TV).addReg(FV).addReg(Tmp1);
709// // Spill the cond to memory and reload it from there.
710// unsigned Tmp4 = MakeReg(MVT::f64);
711// MoveIntFP(Tmp1, Tmp4, true);
712// //now ideally, we don't have to do anything to the flag...
713// // Get the condition into the zero flag.
714// BuildMI(BB, Alpha::FCMOVEQ, 3, Result).addReg(TV).addReg(FV).addReg(Tmp4);
Andrew Lenharth45859692005-03-03 21:47:53 +0000715 return Result;
716 }
Andrew Lenharth9818c052005-02-05 13:19:12 +0000717 }
718
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000719 case ISD::FP_ROUND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000720 assert (DestType == MVT::f32 &&
721 N.getOperand(0).getValueType() == MVT::f64 &&
722 "only f64 to f32 conversion supported here");
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000723 Tmp1 = SelectExpr(N.getOperand(0));
724 BuildMI(BB, Alpha::CVTTS, 1, Result).addReg(Tmp1);
725 return Result;
726
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000727 case ISD::FP_EXTEND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000728 assert (DestType == MVT::f64 &&
729 N.getOperand(0).getValueType() == MVT::f32 &&
730 "only f32 to f64 conversion supported here");
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000731 Tmp1 = SelectExpr(N.getOperand(0));
732 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
733 return Result;
734
Andrew Lenharth2c594352005-01-29 15:42:07 +0000735 case ISD::CopyFromReg:
736 {
737 // Make sure we generate both values.
738 if (Result != notIn)
739 ExprMap[N.getValue(1)] = notIn; // Generate the token
740 else
741 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
742
743 SDOperand Chain = N.getOperand(0);
744
745 Select(Chain);
746 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
747 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
748 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(r).addReg(r);
749 return Result;
750 }
751
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000752 case ISD::LOAD:
753 {
754 // Make sure we generate both values.
755 if (Result != notIn)
756 ExprMap[N.getValue(1)] = notIn; // Generate the token
757 else
758 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000759
Andrew Lenharth29219162005-02-07 06:31:44 +0000760 DestType = N.getValue(0).getValueType();
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000761
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000762 SDOperand Chain = N.getOperand(0);
763 SDOperand Address = N.getOperand(1);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000764 Select(Chain);
Andrew Lenharth65838902005-02-06 16:22:15 +0000765 Opc = DestType == MVT::f64 ? Alpha::LDT : Alpha::LDS;
766
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000767 if (Address.getOpcode() == ISD::GlobalAddress) {
768 AlphaLowering.restoreGP(BB);
769 Opc = GetSymVersion(Opc);
770 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
771 }
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000772 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000773 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +0000774 Opc = GetSymVersion(Opc);
Andrew Lenharth97127a12005-02-05 17:41:39 +0000775 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000776 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000777 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000778 BuildMI(BB, Opc, 2, Result)
779 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
780 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000781 } else {
782 long offset;
783 SelectAddr(Address, Tmp1, offset);
784 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
785 }
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000786 return Result;
787 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000788 case ISD::ConstantFP:
789 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
790 if (CN->isExactlyValue(+0.0)) {
791 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000792 } else if ( CN->isExactlyValue(-0.0)) {
793 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000794 } else {
795 abort();
796 }
797 }
798 return Result;
799
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +0000800 case ISD::SDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000801 case ISD::MUL:
802 case ISD::ADD:
803 case ISD::SUB:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000804 switch( opcode ) {
805 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
806 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
807 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
808 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
809 };
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000810
811 ConstantFPSDNode *CN;
812 if (opcode == ISD::SUB
813 && (CN = dyn_cast<ConstantFPSDNode>(N.getOperand(0)))
814 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
815 {
816 Tmp2 = SelectExpr(N.getOperand(1));
817 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp2).addReg(Tmp2);
818 } else {
819 Tmp1 = SelectExpr(N.getOperand(0));
820 Tmp2 = SelectExpr(N.getOperand(1));
821 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
822 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000823 return Result;
824
Andrew Lenharth2c594352005-01-29 15:42:07 +0000825 case ISD::EXTLOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000826 {
827 //include a conversion sequence for float loads to double
828 if (Result != notIn)
829 ExprMap[N.getValue(1)] = notIn; // Generate the token
830 else
831 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
832
Andrew Lenhartha549deb2005-02-07 05:33:15 +0000833 Tmp1 = MakeReg(MVT::f32);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000834
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000835 assert(cast<MVTSDNode>(Node)->getExtraValueType() == MVT::f32 &&
836 "EXTLOAD not from f32");
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000837 assert(Node->getValueType(0) == MVT::f64 && "EXTLOAD not to f64");
838
839 SDOperand Chain = N.getOperand(0);
840 SDOperand Address = N.getOperand(1);
841 Select(Chain);
842
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000843 if (Address.getOpcode() == ISD::GlobalAddress) {
844 AlphaLowering.restoreGP(BB);
845 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
846 }
847 else if (ConstantPoolSDNode *CP =
848 dyn_cast<ConstantPoolSDNode>(N.getOperand(1)))
849 {
850 AlphaLowering.restoreGP(BB);
851 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addConstantPoolIndex(CP->getIndex());
852 }
853 else if(Address.getOpcode() == ISD::FrameIndex) {
854 Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
Andrew Lenharth032f2352005-02-22 21:59:48 +0000855 BuildMI(BB, Alpha::LDS, 2, Tmp1)
856 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
857 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000858 } else {
859 long offset;
860 SelectAddr(Address, Tmp2, offset);
861 BuildMI(BB, Alpha::LDS, 1, Tmp1).addImm(offset).addReg(Tmp2);
862 }
Andrew Lenharth29219162005-02-07 06:31:44 +0000863 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000864 return Result;
865 }
Andrew Lenharth2c594352005-01-29 15:42:07 +0000866
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000867 case ISD::UINT_TO_FP:
868 case ISD::SINT_TO_FP:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000869 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000870 assert (N.getOperand(0).getValueType() == MVT::i64
871 && "only quads can be loaded from");
Andrew Lenharth40831c52005-01-28 06:57:18 +0000872 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000873 Tmp2 = MakeReg(MVT::f64);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000874 MoveInt2FP(Tmp1, Tmp2, true);
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000875 Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
876 BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000877 return Result;
878 }
879 }
880 assert(0 && "should not get here");
881 return 0;
882}
883
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000884unsigned ISel::SelectExpr(SDOperand N) {
885 unsigned Result;
886 unsigned Tmp1, Tmp2, Tmp3;
887 unsigned Opc = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000888 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000889
890 SDNode *Node = N.Val;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000891 MVT::ValueType DestType = N.getValueType();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000892
893 unsigned &Reg = ExprMap[N];
894 if (Reg) return Reg;
895
896 if (N.getOpcode() != ISD::CALL)
897 Reg = Result = (N.getValueType() != MVT::Other) ?
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000898 MakeReg(N.getValueType()) : notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000899 else {
900 // If this is a call instruction, make sure to prepare ALL of the result
901 // values as well as the chain.
902 if (Node->getNumValues() == 1)
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000903 Reg = Result = notIn; // Void call, just a chain.
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000904 else {
905 Result = MakeReg(Node->getValueType(0));
906 ExprMap[N.getValue(0)] = Result;
907 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
908 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000909 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000910 }
911 }
912
Andrew Lenharth22088bb2005-02-02 15:05:33 +0000913 if (DestType == MVT::f64 || DestType == MVT::f32 ||
Andrew Lenharth06342c32005-02-07 06:21:37 +0000914 (
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000915 (opcode == ISD::LOAD || opcode == ISD::CopyFromReg ||
916 opcode == ISD::EXTLOAD) &&
917 (N.getValue(0).getValueType() == MVT::f32 ||
918 N.getValue(0).getValueType() == MVT::f64)
Andrew Lenharth06342c32005-02-07 06:21:37 +0000919 )
920 )
Andrew Lenharth40831c52005-01-28 06:57:18 +0000921 return SelectExprFP(N, Result);
922
923 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000924 default:
925 Node->dump();
926 assert(0 && "Node not handled!\n");
927
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000928
929 case ISD::UNDEF: {
930 BuildMI(BB, Alpha::IDEF, 0, Result);
931 return Result;
932 }
933
Andrew Lenharth032f2352005-02-22 21:59:48 +0000934 case ISD::DYNAMIC_STACKALLOC:
935 // Generate both result values.
Andrew Lenharth3a7118d2005-02-23 17:33:42 +0000936 if (Result != notIn)
937 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth032f2352005-02-22 21:59:48 +0000938 else
939 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
940
941 // FIXME: We are currently ignoring the requested alignment for handling
942 // greater than the stack alignment. This will need to be revisited at some
943 // point. Align = N.getOperand(2);
944
945 if (!isa<ConstantSDNode>(N.getOperand(2)) ||
946 cast<ConstantSDNode>(N.getOperand(2))->getValue() != 0) {
947 std::cerr << "Cannot allocate stack object with greater alignment than"
948 << " the stack alignment yet!";
949 abort();
950 }
951
952 Select(N.getOperand(0));
953 if (ConstantSDNode* CN = dyn_cast<ConstantSDNode>(N.getOperand(1)))
954 {
955 if (CN->getValue() < 32000)
956 {
957 BuildMI(BB, Alpha::LDA, 2, Alpha::R30)
958 .addImm(-CN->getValue()).addReg(Alpha::R30);
959 } else {
960 Tmp1 = SelectExpr(N.getOperand(1));
961 // Subtract size from stack pointer, thereby allocating some space.
962 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
963 }
964 } else {
965 Tmp1 = SelectExpr(N.getOperand(1));
966 // Subtract size from stack pointer, thereby allocating some space.
967 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
968 }
969
970 // Put a pointer to the space into the result register, by copying the stack
971 // pointer.
Andrew Lenharth7bc47022005-02-22 23:29:25 +0000972 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R30).addReg(Alpha::R30);
Andrew Lenharth032f2352005-02-22 21:59:48 +0000973 return Result;
974
Andrew Lenharth33819132005-03-04 20:09:23 +0000975// case ISD::ConstantPool:
976// Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
977// AlphaLowering.restoreGP(BB);
978// BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(Tmp1);
979// return Result;
Andrew Lenharth2c594352005-01-29 15:42:07 +0000980
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000981 case ISD::FrameIndex:
Andrew Lenharth032f2352005-02-22 21:59:48 +0000982 BuildMI(BB, Alpha::LDA, 2, Result)
983 .addFrameIndex(cast<FrameIndexSDNode>(N)->getIndex())
984 .addReg(Alpha::F31);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000985 return Result;
986
987 case ISD::EXTLOAD:
Andrew Lenharthf311e8b2005-02-07 05:18:02 +0000988 case ISD::ZEXTLOAD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000989 case ISD::SEXTLOAD:
Andrew Lenhartha549deb2005-02-07 05:33:15 +0000990 case ISD::LOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000991 {
992 // Make sure we generate both values.
993 if (Result != notIn)
994 ExprMap[N.getValue(1)] = notIn; // Generate the token
995 else
996 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000997
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000998 SDOperand Chain = N.getOperand(0);
999 SDOperand Address = N.getOperand(1);
1000 Select(Chain);
1001
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001002 assert(Node->getValueType(0) == MVT::i64 &&
1003 "Unknown type to sign extend to.");
Andrew Lenharth03824012005-02-07 05:55:55 +00001004 if (opcode == ISD::LOAD)
1005 Opc = Alpha::LDQ;
1006 else
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001007 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
1008 default: Node->dump(); assert(0 && "Bad sign extend!");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001009 case MVT::i32: Opc = Alpha::LDL;
1010 assert(opcode != ISD::ZEXTLOAD && "Not sext"); break;
1011 case MVT::i16: Opc = Alpha::LDWU;
1012 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001013 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001014 case MVT::i8: Opc = Alpha::LDBU;
1015 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001016 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001017
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001018 if (Address.getOpcode() == ISD::GlobalAddress) {
1019 AlphaLowering.restoreGP(BB);
1020 Opc = GetSymVersion(Opc);
1021 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1022 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001023 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
1024 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +00001025 Opc = GetSymVersion(Opc);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001026 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001027 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001028 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001029 BuildMI(BB, Opc, 2, Result)
1030 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1031 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001032 } else {
1033 long offset;
1034 SelectAddr(Address, Tmp1, offset);
1035 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
1036 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001037 return Result;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001038 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001039
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001040 case ISD::GlobalAddress:
1041 AlphaLowering.restoreGP(BB);
1042 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
1043 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
1044 return Result;
1045
1046 case ISD::CALL:
1047 {
1048 Select(N.getOperand(0));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001049
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001050 // The chain for this call is now lowered.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001051 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), notIn));
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001052
1053 //grab the arguments
1054 std::vector<unsigned> argvregs;
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001055 //assert(Node->getNumOperands() < 8 && "Only 6 args supported");
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001056 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001057 argvregs.push_back(SelectExpr(N.getOperand(i)));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001058
Andrew Lenharth684f2292005-01-30 00:35:27 +00001059 //in reg args
1060 for(int i = 0, e = std::min(6, (int)argvregs.size()); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001061 {
1062 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
1063 Alpha::R19, Alpha::R20, Alpha::R21};
1064 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
1065 Alpha::F19, Alpha::F20, Alpha::F21};
1066 switch(N.getOperand(i+2).getValueType()) {
1067 default:
1068 Node->dump();
1069 N.getOperand(i).Val->dump();
1070 std::cerr << "Type for " << i << " is: " <<
1071 N.getOperand(i+2).getValueType() << "\n";
1072 assert(0 && "Unknown value type for call");
1073 case MVT::i1:
1074 case MVT::i8:
1075 case MVT::i16:
1076 case MVT::i32:
1077 case MVT::i64:
1078 BuildMI(BB, Alpha::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
1079 break;
1080 case MVT::f32:
1081 case MVT::f64:
1082 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
1083 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001084 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001085 }
Andrew Lenharth684f2292005-01-30 00:35:27 +00001086 //in mem args
1087 for (int i = 6, e = argvregs.size(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001088 {
1089 switch(N.getOperand(i+2).getValueType()) {
1090 default:
1091 Node->dump();
1092 N.getOperand(i).Val->dump();
1093 std::cerr << "Type for " << i << " is: " <<
1094 N.getOperand(i+2).getValueType() << "\n";
1095 assert(0 && "Unknown value type for call");
1096 case MVT::i1:
1097 case MVT::i8:
1098 case MVT::i16:
1099 case MVT::i32:
1100 case MVT::i64:
1101 BuildMI(BB, Alpha::STQ, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1102 break;
1103 case MVT::f32:
1104 BuildMI(BB, Alpha::STS, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1105 break;
1106 case MVT::f64:
1107 BuildMI(BB, Alpha::STT, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1108 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001109 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001110 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001111 //build the right kind of call
1112 if (GlobalAddressSDNode *GASD =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001113 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001114 {
Andrew Lenharth3e315922005-02-10 20:10:38 +00001115 //if (GASD->getGlobal()->isExternal()) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001116 //use safe calling convention
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001117 AlphaLowering.restoreGP(BB);
1118 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
Andrew Lenharth3e315922005-02-10 20:10:38 +00001119 //} else {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001120 //use PC relative branch call
Andrew Lenharth3e315922005-02-10 20:10:38 +00001121 //BuildMI(BB, Alpha::BSR, 1, Alpha::R26).addGlobalAddress(GASD->getGlobal(),true);
1122 //}
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001123 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001124 else if (ExternalSymbolSDNode *ESSDN =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001125 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001126 {
1127 AlphaLowering.restoreGP(BB);
Andrew Lenharthba05ad62005-03-30 18:22:52 +00001128 BuildMI(BB, Alpha::CALL, 1).addExternalSymbol(ESSDN->getSymbol(), true);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001129 } else {
1130 //no need to restore GP as we are doing an indirect call
1131 Tmp1 = SelectExpr(N.getOperand(1));
1132 BuildMI(BB, Alpha::BIS, 2, Alpha::R27).addReg(Tmp1).addReg(Tmp1);
1133 BuildMI(BB, Alpha::JSR, 2, Alpha::R26).addReg(Alpha::R27).addImm(0);
1134 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001135
1136 //push the result into a virtual register
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001137
1138 switch (Node->getValueType(0)) {
1139 default: Node->dump(); assert(0 && "Unknown value type for call result!");
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001140 case MVT::Other: return notIn;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001141 case MVT::i1:
1142 case MVT::i8:
1143 case MVT::i16:
1144 case MVT::i32:
1145 case MVT::i64:
1146 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
1147 break;
1148 case MVT::f32:
1149 case MVT::f64:
1150 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
1151 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001152 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001153 return Result+N.ResNo;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001154 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001155
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001156 case ISD::SIGN_EXTEND_INREG:
1157 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001158 //do SDIV opt for all levels of ints
Andrew Lenharth5e99dd92005-03-31 22:02:25 +00001159 if (EnableAlphaIDIV && N.getOperand(0).getOpcode() == ISD::SDIV)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001160 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001161 unsigned Tmp4 = MakeReg(MVT::f64);
1162 unsigned Tmp5 = MakeReg(MVT::f64);
1163 unsigned Tmp6 = MakeReg(MVT::f64);
1164 unsigned Tmp7 = MakeReg(MVT::f64);
1165 unsigned Tmp8 = MakeReg(MVT::f64);
1166 unsigned Tmp9 = MakeReg(MVT::f64);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001167
1168 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1169 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1170 MoveInt2FP(Tmp1, Tmp4, true);
1171 MoveInt2FP(Tmp2, Tmp5, true);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001172 BuildMI(BB, Alpha::CVTQT, 1, Tmp6).addReg(Tmp4);
1173 BuildMI(BB, Alpha::CVTQT, 1, Tmp7).addReg(Tmp5);
1174 BuildMI(BB, Alpha::DIVT, 2, Tmp8).addReg(Tmp6).addReg(Tmp7);
1175 BuildMI(BB, Alpha::CVTTQ, 1, Tmp9).addReg(Tmp8);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001176 MoveFP2Int(Tmp9, Result, true);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001177 return Result;
1178 }
1179
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001180 //Alpha has instructions for a bunch of signed 32 bit stuff
1181 if( dyn_cast<MVTSDNode>(Node)->getExtraValueType() == MVT::i32)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001182 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001183 switch (N.getOperand(0).getOpcode()) {
1184 case ISD::ADD:
1185 case ISD::SUB:
1186 case ISD::MUL:
1187 {
1188 bool isAdd = N.getOperand(0).getOpcode() == ISD::ADD;
1189 bool isMul = N.getOperand(0).getOpcode() == ISD::MUL;
1190 //FIXME: first check for Scaled Adds and Subs!
1191 if(N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1192 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() <= 255)
1193 { //Normal imm add/sub
1194 Opc = isAdd ? Alpha::ADDLi : (isMul ? Alpha::MULLi : Alpha::SUBLi);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001195 //if the value was really originally a i32, skip the up conversion
1196 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1197 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1198 ->getExtraValueType() == MVT::i32)
1199 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1200 else
1201 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001202 Tmp2 = cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue();
1203 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001204 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001205 else
1206 { //Normal add/sub
1207 Opc = isAdd ? Alpha::ADDL : (isMul ? Alpha::MULLi : Alpha::SUBL);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001208 //if the value was really originally a i32, skip the up conversion
1209 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1210 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1211 ->getExtraValueType() == MVT::i32)
1212 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1213 else
1214 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1215 //if the value was really originally a i32, skip the up conversion
1216 if (N.getOperand(0).getOperand(1).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1217 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(1).Val)
1218 ->getExtraValueType() == MVT::i32)
1219 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0));
1220 else
1221 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1222
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001223 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1224 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1225 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1226 }
1227 return Result;
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001228 }
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001229 case ISD::SEXTLOAD:
1230 //SelectionDag isn't deleting the signextend after sextloads
1231 Reg = Result = SelectExpr(N.getOperand(0));
1232 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001233 default: break; //Fall Though;
1234 }
1235 } //Every thing else fall though too, including unhandled opcodes above
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001236 Tmp1 = SelectExpr(N.getOperand(0));
1237 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001238 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001239 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001240 {
1241 default:
1242 Node->dump();
1243 assert(0 && "Sign Extend InReg not there yet");
1244 break;
1245 case MVT::i32:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001246 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001247 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001248 break;
1249 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001250 case MVT::i16:
1251 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
1252 break;
1253 case MVT::i8:
1254 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
1255 break;
Andrew Lenharthebce5042005-02-12 19:35:12 +00001256 case MVT::i1:
1257 Tmp2 = MakeReg(MVT::i64);
1258 BuildMI(BB, Alpha::ANDi, 2, Tmp2).addReg(Tmp1).addImm(1);
Andrew Lenharth7536eea2005-02-12 20:42:09 +00001259 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Alpha::F31).addReg(Tmp2);
Andrew Lenharthebce5042005-02-12 19:35:12 +00001260 break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001261 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001262 return Result;
1263 }
1264 case ISD::ZERO_EXTEND_INREG:
1265 {
1266 Tmp1 = SelectExpr(N.getOperand(0));
1267 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001268 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001269 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001270 {
1271 default:
1272 Node->dump();
1273 assert(0 && "Zero Extend InReg not there yet");
1274 break;
1275 case MVT::i32: Tmp2 = 0xf0; break;
1276 case MVT::i16: Tmp2 = 0xfc; break;
1277 case MVT::i8: Tmp2 = 0xfe; break;
1278 case MVT::i1: //handle this one special
1279 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
1280 return Result;
1281 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001282 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001283 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001284 }
1285
1286 case ISD::SETCC:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001287 {
1288 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
1289 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
1290 bool isConst1 = false;
1291 bool isConst2 = false;
1292 int dir;
Andrew Lenharth9818c052005-02-05 13:19:12 +00001293
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001294 //Tmp1 = SelectExpr(N.getOperand(0));
1295 if(N.getOperand(0).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001296 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1297 isConst1 = true;
1298 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001299 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1300 isConst2 = true;
1301
1302 switch (SetCC->getCondition()) {
1303 default: Node->dump(); assert(0 && "Unknown integer comparison!");
1304 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001305 case ISD::SETLT:
1306 Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
1307 case ISD::SETLE:
1308 Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
1309 case ISD::SETGT:
1310 Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
1311 case ISD::SETGE:
1312 Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
1313 case ISD::SETULT:
1314 Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
1315 case ISD::SETUGT:
1316 Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
1317 case ISD::SETULE:
1318 Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
1319 case ISD::SETUGE:
1320 Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001321 case ISD::SETNE: {//Handle this one special
1322 //std::cerr << "Alpha does not have a setne.\n";
1323 //abort();
1324 Tmp1 = SelectExpr(N.getOperand(0));
1325 Tmp2 = SelectExpr(N.getOperand(1));
1326 Tmp3 = MakeReg(MVT::i64);
1327 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth445171a2005-02-08 00:40:03 +00001328 //Remeber we have the Inv for this CC
1329 CCInvMap[N] = Tmp3;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001330 //and invert
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001331 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001332 return Result;
1333 }
1334 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001335 if (dir == 1) {
1336 Tmp1 = SelectExpr(N.getOperand(0));
1337 if (isConst2) {
1338 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1339 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1340 } else {
1341 Tmp2 = SelectExpr(N.getOperand(1));
1342 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1343 }
1344 } else if (dir == 2) {
1345 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001346 if (isConst1) {
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001347 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1348 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1349 } else {
1350 Tmp2 = SelectExpr(N.getOperand(0));
1351 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1352 }
1353 } else { //dir == 0
1354 if (isConst1) {
1355 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1356 Tmp2 = SelectExpr(N.getOperand(1));
1357 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
1358 } else if (isConst2) {
1359 Tmp1 = SelectExpr(N.getOperand(0));
1360 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1361 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
1362 } else {
1363 Tmp1 = SelectExpr(N.getOperand(0));
1364 Tmp2 = SelectExpr(N.getOperand(1));
1365 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
1366 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001367 }
1368 } else {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001369 //do the comparison
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001370 Tmp1 = MakeReg(MVT::f64);
1371 bool inv = SelectFPSetCC(N, Tmp1);
1372
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001373 //now arrange for Result (int) to have a 1 or 0
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001374 Tmp2 = MakeReg(MVT::i64);
1375 BuildMI(BB, Alpha::ADDQi, 2, Tmp2).addReg(Alpha::R31).addImm(1);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001376 Opc = inv?Alpha::CMOVNEi_FP:Alpha::CMOVEQi_FP;
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001377 BuildMI(BB, Opc, 3, Result).addReg(Tmp2).addImm(0).addReg(Tmp1);
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001378 }
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
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001402 case ISD::OR:
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001403 //Match Not
1404 if (N.getOperand(1).getOpcode() == ISD::Constant &&
1405 cast<ConstantSDNode>(N.getOperand(1))->isAllOnesValue())
1406 {
1407 Tmp1 = SelectExpr(N.getOperand(0));
1408 BuildMI(BB, Alpha::ORNOT, 2, Result).addReg(Alpha::R31).addReg(Tmp1);
1409 return Result;
1410 }
1411 //Fall through
1412 case ISD::AND:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001413 case ISD::XOR:
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001414 //Check operand(0) == Not
1415 if (N.getOperand(0).getOpcode() == ISD::OR &&
1416 N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1417 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->isAllOnesValue())
1418 {
1419 switch(opcode) {
1420 case ISD::AND: Opc = Alpha::BIC; break;
1421 case ISD::OR: Opc = Alpha::ORNOT; break;
1422 case ISD::XOR: Opc = Alpha::EQV; break;
1423 }
1424 Tmp1 = SelectExpr(N.getOperand(1));
1425 Tmp2 = SelectExpr(N.getOperand(0).getOperand(0));
1426 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1427 return Result;
1428 }
1429 //Check operand(1) == Not
1430 if (N.getOperand(1).getOpcode() == ISD::OR &&
1431 N.getOperand(1).getOperand(1).getOpcode() == ISD::Constant &&
1432 cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->isAllOnesValue())
1433 {
1434 switch(opcode) {
1435 case ISD::AND: Opc = Alpha::BIC; break;
1436 case ISD::OR: Opc = Alpha::ORNOT; break;
1437 case ISD::XOR: Opc = Alpha::EQV; break;
1438 }
1439 Tmp1 = SelectExpr(N.getOperand(0));
1440 Tmp2 = SelectExpr(N.getOperand(1).getOperand(0));
1441 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1442 return Result;
1443 }
1444 //Fall through
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001445 case ISD::SHL:
1446 case ISD::SRL:
Andrew Lenharth2c594352005-01-29 15:42:07 +00001447 case ISD::SRA:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001448 case ISD::MUL:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001449 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
1450 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001451 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001452 {
1453 switch(opcode) {
1454 case ISD::AND: Opc = Alpha::ANDi; break;
1455 case ISD::OR: Opc = Alpha::BISi; break;
1456 case ISD::XOR: Opc = Alpha::XORi; break;
1457 case ISD::SHL: Opc = Alpha::SLi; break;
1458 case ISD::SRL: Opc = Alpha::SRLi; break;
1459 case ISD::SRA: Opc = Alpha::SRAi; break;
1460 case ISD::MUL: Opc = Alpha::MULQi; break;
1461 };
1462 Tmp1 = SelectExpr(N.getOperand(0));
1463 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1464 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1465 } else {
1466 switch(opcode) {
1467 case ISD::AND: Opc = Alpha::AND; break;
1468 case ISD::OR: Opc = Alpha::BIS; break;
1469 case ISD::XOR: Opc = Alpha::XOR; break;
1470 case ISD::SHL: Opc = Alpha::SL; break;
1471 case ISD::SRL: Opc = Alpha::SRL; break;
1472 case ISD::SRA: Opc = Alpha::SRA; break;
1473 case ISD::MUL: Opc = Alpha::MULQ; break;
1474 };
1475 Tmp1 = SelectExpr(N.getOperand(0));
1476 Tmp2 = SelectExpr(N.getOperand(1));
1477 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1478 }
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001479 return Result;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001480
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001481 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001482 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001483 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001484 bool isAdd = opcode == ISD::ADD;
1485
1486 //FIXME: first check for Scaled Adds and Subs!
1487 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001488 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001489 { //Normal imm add/sub
1490 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
1491 Tmp1 = SelectExpr(N.getOperand(0));
1492 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1493 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1494 }
Andrew Lenharth40831c52005-01-28 06:57:18 +00001495 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001496 (cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767 ||
1497 (long)cast<ConstantSDNode>(N.getOperand(1))->getValue() >= -32767))
1498 { //LDA
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001499 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001500 Tmp2 = (long)cast<ConstantSDNode>(N.getOperand(1))->getValue();
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001501 if (!isAdd)
1502 Tmp2 = -Tmp2;
1503 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
1504 } else {
1505 //Normal add/sub
1506 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
1507 Tmp1 = SelectExpr(N.getOperand(0));
1508 Tmp2 = SelectExpr(N.getOperand(1));
1509 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1510 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001511 return Result;
1512 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001513
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001514 case ISD::SDIV:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001515 case ISD::UREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001516 case ISD::SREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001517 case ISD::UDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001518 //FIXME: alpha really doesn't support any of these operations,
1519 // the ops are expanded into special library calls with
1520 // special calling conventions
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001521 //Restore GP because it is a call after all...
Andrew Lenharth40831c52005-01-28 06:57:18 +00001522 switch(opcode) {
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001523 case ISD::UREM: Opc = Alpha::REMQU; break;
1524 case ISD::SREM: Opc = Alpha::REMQ; break;
1525 case ISD::UDIV: Opc = Alpha::DIVQU; break;
1526 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001527 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001528 Tmp1 = SelectExpr(N.getOperand(0));
1529 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth33819132005-03-04 20:09:23 +00001530 //set up regs explicitly (helps Reg alloc)
1531 BuildMI(BB, Alpha::BIS, 2, Alpha::R24).addReg(Tmp1).addReg(Tmp1);
1532 BuildMI(BB, Alpha::BIS, 2, Alpha::R25).addReg(Tmp2).addReg(Tmp2);
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001533 AlphaLowering.restoreGP(BB);
Andrew Lenharth33819132005-03-04 20:09:23 +00001534 BuildMI(BB, Opc, 2).addReg(Alpha::R24).addReg(Alpha::R25);
1535 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R27).addReg(Alpha::R27);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001536 return Result;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001537
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001538 case ISD::FP_TO_UINT:
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001539 case ISD::FP_TO_SINT:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001540 {
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001541 assert (DestType == MVT::i64 && "only quads can be loaded to");
1542 MVT::ValueType SrcType = N.getOperand(0).getValueType();
Andrew Lenharth03824012005-02-07 05:55:55 +00001543 assert (SrcType == MVT::f32 || SrcType == MVT::f64);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001544 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001545 if (SrcType == MVT::f32)
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001546 {
1547 Tmp2 = MakeReg(MVT::f64);
1548 BuildMI(BB, Alpha::CVTST, 1, Tmp2).addReg(Tmp1);
1549 Tmp1 = Tmp2;
1550 }
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001551 Tmp2 = MakeReg(MVT::f64);
1552 BuildMI(BB, Alpha::CVTTQ, 1, Tmp2).addReg(Tmp1);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001553 MoveFP2Int(Tmp2, Result, true);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001554
1555 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001556 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001557
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001558 case ISD::SELECT:
1559 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001560 //FIXME: look at parent to decide if intCC can be folded, or if setCC(FP) and can save stack use
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001561 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001562 //Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1563 //Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001564 // Get the condition into the zero flag.
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001565 //BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001566
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001567 SDOperand CC = N.getOperand(0);
1568 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
1569
1570 if (CC.getOpcode() == ISD::SETCC &&
1571 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
1572 { //FP Setcc -> Int Select
1573 Tmp1 = MakeReg(MVT::f64);
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001574 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1575 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001576 bool inv = SelectFPSetCC(CC, Tmp1);
1577 BuildMI(BB, inv?Alpha::CMOVNE_FP:Alpha::CMOVEQ_FP, 2, Result)
1578 .addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
1579 return Result;
1580 }
1581 if (CC.getOpcode() == ISD::SETCC) {
1582 //Int SetCC -> Select
1583 //Dropping the CC is only useful if we are comparing to 0
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001584 if((SetCC->getOperand(1).getOpcode() == ISD::Constant &&
1585 cast<ConstantSDNode>(SetCC->getOperand(1))->getValue() == 0) ||
1586 (SetCC->getOperand(0).getOpcode() == ISD::Constant &&
1587 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0))
1588 {
1589 //figure out a few things
1590 bool LeftZero = SetCC->getOperand(0).getOpcode() == ISD::Constant &&
1591 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0;
1592 bool RightZero = SetCC->getOperand(0).getOpcode() == ISD::Constant &&
1593 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0;
1594 bool LeftConst = N.getOperand(1).getOpcode() == ISD::Constant &&
1595 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255;
1596 bool RightConst = N.getOperand(2).getOpcode() == ISD::Constant &&
1597 cast<ConstantSDNode>(N.getOperand(2))->getValue() <= 255;
1598 bool useImm = LeftConst || RightConst;
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001599
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001600 //Fix up CC
1601 ISD::CondCode cCode= SetCC->getCondition();
1602 if (RightConst && !LeftConst) //Invert sense to get Imm field right
1603 cCode = ISD::getSetCCInverse(cCode, true);
1604 if (LeftZero && !RightZero) //Swap Operands
1605 cCode = ISD::getSetCCSwappedOperands(cCode);
1606
1607 //Choose the CMOV
1608 switch (cCode) {
1609 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
1610 case ISD::SETEQ: Opc = useImm?Alpha::CMOVEQi:Alpha::CMOVEQ; break;
1611 case ISD::SETLT: Opc = useImm?Alpha::CMOVLTi:Alpha::CMOVLT; break;
1612 case ISD::SETLE: Opc = useImm?Alpha::CMOVLEi:Alpha::CMOVLE; break;
1613 case ISD::SETGT: Opc = useImm?Alpha::CMOVGTi:Alpha::CMOVGT; break;
1614 case ISD::SETGE: Opc = useImm?Alpha::CMOVGEi:Alpha::CMOVGE; break;
1615 case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break;
1616 case ISD::SETUGT: Opc = useImm?Alpha::CMOVNEi:Alpha::CMOVNE; break;
1617 case ISD::SETULE: Opc = useImm?Alpha::CMOVEQi:Alpha::CMOVEQ; break; //Technically you could have this CC
1618 case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break;
1619 case ISD::SETNE: Opc = useImm?Alpha::CMOVNEi:Alpha::CMOVNE; break;
1620 }
1621 if(LeftZero && !RightZero) //swap Operands
1622 Tmp1 = SelectExpr(SetCC->getOperand(1)); //Cond
1623 else
1624 Tmp1 = SelectExpr(SetCC->getOperand(0)); //Cond
1625
1626 if (LeftConst) {
1627 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
1628 BuildMI(BB, Opc, 2, Result).addReg(Tmp3)
1629 .addImm(cast<ConstantSDNode>(N.getOperand(1))->getValue())
1630 .addReg(Tmp1);
1631 } else if (RightConst) {
1632 Tmp3 = SelectExpr(N.getOperand(1)); //Use if FALSE
1633 BuildMI(BB, Opc, 2, Result).addReg(Tmp3)
1634 .addImm(cast<ConstantSDNode>(N.getOperand(2))->getValue())
1635 .addReg(Tmp1);
1636 } else {
1637 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1638 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
1639 BuildMI(BB, Opc, 2, Result).addReg(Tmp3).addReg(Tmp2).addReg(Tmp1);
1640 }
1641 return Result;
1642 }
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001643 //Otherwise, fall though
1644 }
1645 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001646 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1647 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001648 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001649
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001650 return Result;
1651 }
1652
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001653 case ISD::Constant:
1654 {
Andrew Lenharthc0513832005-03-29 19:24:04 +00001655 int64_t val = (int64_t)cast<ConstantSDNode>(N)->getValue();
Andrew Lenharthe87f6c32005-03-11 17:48:05 +00001656 if (val <= IMM_HIGH && val >= IMM_LOW) {
1657 BuildMI(BB, Alpha::LDA, 2, Result).addImm(val).addReg(Alpha::R31);
1658 }
1659 else if (val <= (int64_t)IMM_HIGH + (int64_t)IMM_HIGH * (int64_t)IMM_MULT &&
1660 val >= (int64_t)IMM_LOW + (int64_t)IMM_LOW * (int64_t)IMM_MULT) {
1661 Tmp1 = MakeReg(MVT::i64);
1662 BuildMI(BB, Alpha::LDAH, 2, Tmp1).addImm(getUpper16(val)).addReg(Alpha::R31);
1663 BuildMI(BB, Alpha::LDA, 2, Result).addImm(getLower16(val)).addReg(Tmp1);
1664 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001665 else {
1666 MachineConstantPool *CP = BB->getParent()->getConstantPool();
1667 ConstantUInt *C = ConstantUInt::get(Type::getPrimitiveType(Type::ULongTyID) , val);
1668 unsigned CPI = CP->getConstantPoolIndex(C);
1669 AlphaLowering.restoreGP(BB);
1670 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(CPI);
1671 }
1672 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001673 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001674 }
1675
1676 return 0;
1677}
1678
1679void ISel::Select(SDOperand N) {
1680 unsigned Tmp1, Tmp2, Opc;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001681 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001682
Nate Begeman85fdeb22005-03-24 04:39:54 +00001683 if (!ExprMap.insert(std::make_pair(N, notIn)).second)
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001684 return; // Already selected.
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001685
1686 SDNode *Node = N.Val;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001687
Andrew Lenharth760270d2005-02-07 23:02:23 +00001688 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001689
1690 default:
1691 Node->dump(); std::cerr << "\n";
1692 assert(0 && "Node not handled yet!");
1693
1694 case ISD::BRCOND: {
Andrew Lenharth445171a2005-02-08 00:40:03 +00001695 SelectBranchCC(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001696 return;
1697 }
1698
1699 case ISD::BR: {
1700 MachineBasicBlock *Dest =
1701 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
1702
1703 Select(N.getOperand(0));
1704 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
1705 return;
1706 }
1707
1708 case ISD::ImplicitDef:
1709 Select(N.getOperand(0));
1710 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
1711 return;
1712
1713 case ISD::EntryToken: return; // Noop
1714
1715 case ISD::TokenFactor:
1716 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
1717 Select(Node->getOperand(i));
1718
1719 //N.Val->dump(); std::cerr << "\n";
1720 //assert(0 && "Node not handled yet!");
1721
1722 return;
1723
1724 case ISD::CopyToReg:
1725 Select(N.getOperand(0));
1726 Tmp1 = SelectExpr(N.getOperand(1));
1727 Tmp2 = cast<RegSDNode>(N)->getReg();
1728
1729 if (Tmp1 != Tmp2) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001730 if (N.getOperand(1).getValueType() == MVT::f64 ||
1731 N.getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth29219162005-02-07 06:31:44 +00001732 BuildMI(BB, Alpha::CPYS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
1733 else
1734 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001735 }
1736 return;
1737
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001738 case ISD::RET:
1739 switch (N.getNumOperands()) {
1740 default:
1741 std::cerr << N.getNumOperands() << "\n";
1742 for (unsigned i = 0; i < N.getNumOperands(); ++i)
1743 std::cerr << N.getOperand(i).getValueType() << "\n";
1744 Node->dump();
1745 assert(0 && "Unknown return instruction!");
1746 case 2:
1747 Select(N.getOperand(0));
1748 Tmp1 = SelectExpr(N.getOperand(1));
1749 switch (N.getOperand(1).getValueType()) {
1750 default: Node->dump();
1751 assert(0 && "All other types should have been promoted!!");
1752 case MVT::f64:
1753 case MVT::f32:
1754 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
1755 break;
1756 case MVT::i32:
1757 case MVT::i64:
1758 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
1759 break;
1760 }
1761 break;
1762 case 1:
1763 Select(N.getOperand(0));
1764 break;
1765 }
1766 //Tmp2 = AlphaLowering.getRetAddr();
1767 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
1768 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
1769 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001770
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001771 case ISD::TRUNCSTORE:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001772 case ISD::STORE:
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001773 {
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001774 SDOperand Chain = N.getOperand(0);
1775 SDOperand Value = N.getOperand(1);
1776 SDOperand Address = N.getOperand(2);
1777 Select(Chain);
1778
1779 Tmp1 = SelectExpr(Value); //value
Andrew Lenharth760270d2005-02-07 23:02:23 +00001780
1781 if (opcode == ISD::STORE) {
1782 switch(Value.getValueType()) {
1783 default: assert(0 && "unknown Type in store");
1784 case MVT::i64: Opc = Alpha::STQ; break;
1785 case MVT::f64: Opc = Alpha::STT; break;
1786 case MVT::f32: Opc = Alpha::STS; break;
1787 }
1788 } else { //ISD::TRUNCSTORE
1789 switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
1790 default: assert(0 && "unknown Type in store");
1791 case MVT::i1: //FIXME: DAG does not promote this load
1792 case MVT::i8: Opc = Alpha::STB; break;
1793 case MVT::i16: Opc = Alpha::STW; break;
1794 case MVT::i32: Opc = Alpha::STL; break;
1795 }
Andrew Lenharth65838902005-02-06 16:22:15 +00001796 }
Andrew Lenharth760270d2005-02-07 23:02:23 +00001797
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001798 if (Address.getOpcode() == ISD::GlobalAddress)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001799 {
1800 AlphaLowering.restoreGP(BB);
1801 Opc = GetSymVersion(Opc);
1802 BuildMI(BB, Opc, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1803 }
Andrew Lenharth05380342005-02-07 05:07:00 +00001804 else if(Address.getOpcode() == ISD::FrameIndex)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001805 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001806 BuildMI(BB, Opc, 3).addReg(Tmp1)
1807 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1808 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001809 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001810 else
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001811 {
1812 long offset;
1813 SelectAddr(Address, Tmp2, offset);
1814 BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
1815 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001816 return;
1817 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001818
1819 case ISD::EXTLOAD:
1820 case ISD::SEXTLOAD:
1821 case ISD::ZEXTLOAD:
1822 case ISD::LOAD:
1823 case ISD::CopyFromReg:
1824 case ISD::CALL:
Andrew Lenharth032f2352005-02-22 21:59:48 +00001825 case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001826 ExprMap.erase(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001827 SelectExpr(N);
1828 return;
1829
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001830 case ISD::ADJCALLSTACKDOWN:
1831 case ISD::ADJCALLSTACKUP:
1832 Select(N.getOperand(0));
1833 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1834
1835 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
1836 Alpha::ADJUSTSTACKUP;
1837 BuildMI(BB, Opc, 1).addImm(Tmp1);
1838 return;
Andrew Lenharth95762122005-03-31 21:24:06 +00001839
1840 case ISD::PCMARKER:
1841 Select(N.getOperand(0)); //Chain
1842 BuildMI(BB, Alpha::PCLABEL, 2).addImm( cast<ConstantSDNode>(N.getOperand(1))->getValue());
1843 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001844 }
1845 assert(0 && "Should not be reached!");
1846}
1847
1848
1849/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
1850/// into a machine code representation using pattern matching and a machine
1851/// description file.
1852///
1853FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
1854 return new ISel(TM);
1855}