blob: 6f093ba65f8d0e857f6a7f88237e68d3e93d2317 [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
521 bool isZero0 = false;
522 bool isZero1 = false;
523 bool isNE = false;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000524
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000525 if(SetCC->getOperand(0).getOpcode() == ISD::Constant &&
526 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0)
527 isZero0 = true;
528 if(SetCC->getOperand(1).getOpcode() == ISD::Constant &&
529 cast<ConstantSDNode>(SetCC->getOperand(1))->getValue() == 0)
530 isZero1 = true;
531 if(SetCC->getCondition() == ISD::SETNE)
532 isNE = true;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000533
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000534 if (isZero0) {
Andrew Lenharth445171a2005-02-08 00:40:03 +0000535 switch (SetCC->getCondition()) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000536 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
537 case ISD::SETEQ: Opc = Alpha::BEQ; break;
538 case ISD::SETLT: Opc = Alpha::BGT; break;
539 case ISD::SETLE: Opc = Alpha::BGE; break;
540 case ISD::SETGT: Opc = Alpha::BLT; break;
541 case ISD::SETGE: Opc = Alpha::BLE; break;
542 case ISD::SETULT: Opc = Alpha::BNE; break;
543 case ISD::SETUGT: assert(0 && "0 > (unsigned) x is never true"); break;
544 case ISD::SETULE: assert(0 && "0 <= (unsigned) x is always true"); break;
545 case ISD::SETUGE: Opc = Alpha::BEQ; break; //Technically you could have this CC
546 case ISD::SETNE: Opc = Alpha::BNE; break;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000547 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000548 unsigned Tmp1 = SelectExpr(SetCC->getOperand(1));
549 BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest);
550 return;
551 } else if (isZero1) {
552 switch (SetCC->getCondition()) {
553 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
554 case ISD::SETEQ: Opc = Alpha::BEQ; break;
555 case ISD::SETLT: Opc = Alpha::BLT; break;
556 case ISD::SETLE: Opc = Alpha::BLE; break;
557 case ISD::SETGT: Opc = Alpha::BGT; break;
558 case ISD::SETGE: Opc = Alpha::BGE; break;
559 case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break;
560 case ISD::SETUGT: Opc = Alpha::BNE; break;
561 case ISD::SETULE: Opc = Alpha::BEQ; break; //Technically you could have this CC
562 case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break;
563 case ISD::SETNE: Opc = Alpha::BNE; break;
564 }
565 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
566 BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest);
567 return;
568 } else {
569 unsigned Tmp1 = SelectExpr(CC);
570 if (isNE)
571 BuildMI(BB, Alpha::BEQ, 2).addReg(CCInvMap[CC]).addMBB(Dest);
572 else
573 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000574 return;
575 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000576 } else { //FP
577 //Any comparison between 2 values should be codegened as an folded branch, as moving
578 //CC to the integer register is very expensive
579 //for a cmp b: c = a - b;
580 //a = b: c = 0
581 //a < b: c < 0
582 //a > b: c > 0
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000583
584 bool invTest = false;
585 unsigned Tmp3;
586
587 ConstantFPSDNode *CN;
588 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
589 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
590 Tmp3 = SelectExpr(SetCC->getOperand(0));
591 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
592 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
593 {
594 Tmp3 = SelectExpr(SetCC->getOperand(1));
595 invTest = true;
596 }
597 else
598 {
599 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
600 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
601 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
602 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
603 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
604 .addReg(Tmp1).addReg(Tmp2);
605 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000606
607 switch (SetCC->getCondition()) {
608 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000609 case ISD::SETEQ: Opc = invTest ? Alpha::FBNE : Alpha::FBEQ; break;
610 case ISD::SETLT: Opc = invTest ? Alpha::FBGT : Alpha::FBLT; break;
611 case ISD::SETLE: Opc = invTest ? Alpha::FBGE : Alpha::FBLE; break;
612 case ISD::SETGT: Opc = invTest ? Alpha::FBLT : Alpha::FBGT; break;
613 case ISD::SETGE: Opc = invTest ? Alpha::FBLE : Alpha::FBGE; break;
614 case ISD::SETNE: Opc = invTest ? Alpha::FBEQ : Alpha::FBNE; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000615 }
616 BuildMI(BB, Opc, 2).addReg(Tmp3).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000617 return;
618 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000619 abort(); //Should never be reached
620 } else {
621 //Giveup and do the stupid thing
622 unsigned Tmp1 = SelectExpr(CC);
623 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
624 return;
625 }
Andrew Lenharth445171a2005-02-08 00:40:03 +0000626 abort(); //Should never be reached
627}
628
Andrew Lenharth40831c52005-01-28 06:57:18 +0000629unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
630{
631 unsigned Tmp1, Tmp2, Tmp3;
632 unsigned Opc = 0;
633 SDNode *Node = N.Val;
634 MVT::ValueType DestType = N.getValueType();
635 unsigned opcode = N.getOpcode();
636
637 switch (opcode) {
638 default:
639 Node->dump();
640 assert(0 && "Node not handled!\n");
Andrew Lenharth2c594352005-01-29 15:42:07 +0000641
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000642 case ISD::UNDEF: {
643 BuildMI(BB, Alpha::IDEF, 0, Result);
644 return Result;
645 }
646
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000647 case ISD::FNEG:
648 if(ISD::FABS == N.getOperand(0).getOpcode())
649 {
650 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000651 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000652 } else {
653 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000654 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000655 }
656 return Result;
657
658 case ISD::FABS:
659 Tmp1 = SelectExpr(N.getOperand(0));
660 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
661 return Result;
662
Andrew Lenharth9818c052005-02-05 13:19:12 +0000663 case ISD::SELECT:
664 {
Andrew Lenharth45859692005-03-03 21:47:53 +0000665 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
666 unsigned TV = SelectExpr(N.getOperand(1)); //Use if TRUE
667 unsigned FV = SelectExpr(N.getOperand(2)); //Use if FALSE
668
669 SDOperand CC = N.getOperand(0);
670 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
671
672 if (CC.getOpcode() == ISD::SETCC &&
673 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
674 { //FP Setcc -> Select yay!
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000675
676
Andrew Lenharth45859692005-03-03 21:47:53 +0000677 //for a cmp b: c = a - b;
678 //a = b: c = 0
679 //a < b: c < 0
680 //a > b: c > 0
681
682 bool invTest = false;
683 unsigned Tmp3;
684
685 ConstantFPSDNode *CN;
686 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
687 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
688 Tmp3 = SelectExpr(SetCC->getOperand(0));
689 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
690 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
691 {
692 Tmp3 = SelectExpr(SetCC->getOperand(1));
693 invTest = true;
694 }
695 else
696 {
697 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
698 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
699 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
700 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
701 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
702 .addReg(Tmp1).addReg(Tmp2);
703 }
704
705 switch (SetCC->getCondition()) {
706 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
707 case ISD::SETEQ: Opc = invTest ? Alpha::FCMOVNE : Alpha::FCMOVEQ; break;
708 case ISD::SETLT: Opc = invTest ? Alpha::FCMOVGT : Alpha::FCMOVLT; break;
709 case ISD::SETLE: Opc = invTest ? Alpha::FCMOVGE : Alpha::FCMOVLE; break;
710 case ISD::SETGT: Opc = invTest ? Alpha::FCMOVLT : Alpha::FCMOVGT; break;
711 case ISD::SETGE: Opc = invTest ? Alpha::FCMOVLE : Alpha::FCMOVGE; break;
712 case ISD::SETNE: Opc = invTest ? Alpha::FCMOVEQ : Alpha::FCMOVNE; break;
713 }
Andrew Lenharth33819132005-03-04 20:09:23 +0000714 BuildMI(BB, Opc, 3, Result).addReg(FV).addReg(TV).addReg(Tmp3);
Andrew Lenharth45859692005-03-03 21:47:53 +0000715 return Result;
716 }
717 else
718 {
719 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000720 BuildMI(BB, Alpha::FCMOVEQ_INT, 3, Result).addReg(TV).addReg(FV).addReg(Tmp1);
721// // Spill the cond to memory and reload it from there.
722// unsigned Tmp4 = MakeReg(MVT::f64);
723// MoveIntFP(Tmp1, Tmp4, true);
724// //now ideally, we don't have to do anything to the flag...
725// // Get the condition into the zero flag.
726// BuildMI(BB, Alpha::FCMOVEQ, 3, Result).addReg(TV).addReg(FV).addReg(Tmp4);
Andrew Lenharth45859692005-03-03 21:47:53 +0000727 return Result;
728 }
Andrew Lenharth9818c052005-02-05 13:19:12 +0000729 }
730
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000731 case ISD::FP_ROUND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000732 assert (DestType == MVT::f32 &&
733 N.getOperand(0).getValueType() == MVT::f64 &&
734 "only f64 to f32 conversion supported here");
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000735 Tmp1 = SelectExpr(N.getOperand(0));
736 BuildMI(BB, Alpha::CVTTS, 1, Result).addReg(Tmp1);
737 return Result;
738
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000739 case ISD::FP_EXTEND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000740 assert (DestType == MVT::f64 &&
741 N.getOperand(0).getValueType() == MVT::f32 &&
742 "only f32 to f64 conversion supported here");
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000743 Tmp1 = SelectExpr(N.getOperand(0));
744 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
745 return Result;
746
Andrew Lenharth2c594352005-01-29 15:42:07 +0000747 case ISD::CopyFromReg:
748 {
749 // Make sure we generate both values.
750 if (Result != notIn)
751 ExprMap[N.getValue(1)] = notIn; // Generate the token
752 else
753 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
754
755 SDOperand Chain = N.getOperand(0);
756
757 Select(Chain);
758 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
759 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
760 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(r).addReg(r);
761 return Result;
762 }
763
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000764 case ISD::LOAD:
765 {
766 // Make sure we generate both values.
767 if (Result != notIn)
768 ExprMap[N.getValue(1)] = notIn; // Generate the token
769 else
770 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000771
Andrew Lenharth29219162005-02-07 06:31:44 +0000772 DestType = N.getValue(0).getValueType();
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000773
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000774 SDOperand Chain = N.getOperand(0);
775 SDOperand Address = N.getOperand(1);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000776 Select(Chain);
Andrew Lenharth65838902005-02-06 16:22:15 +0000777 Opc = DestType == MVT::f64 ? Alpha::LDT : Alpha::LDS;
778
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000779 if (Address.getOpcode() == ISD::GlobalAddress) {
780 AlphaLowering.restoreGP(BB);
781 Opc = GetSymVersion(Opc);
782 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
783 }
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000784 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000785 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +0000786 Opc = GetSymVersion(Opc);
Andrew Lenharth97127a12005-02-05 17:41:39 +0000787 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000788 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000789 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000790 BuildMI(BB, Opc, 2, Result)
791 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
792 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000793 } else {
794 long offset;
795 SelectAddr(Address, Tmp1, offset);
796 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
797 }
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000798 return Result;
799 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000800 case ISD::ConstantFP:
801 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
802 if (CN->isExactlyValue(+0.0)) {
803 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000804 } else if ( CN->isExactlyValue(-0.0)) {
805 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000806 } else {
807 abort();
808 }
809 }
810 return Result;
811
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +0000812 case ISD::SDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000813 case ISD::MUL:
814 case ISD::ADD:
815 case ISD::SUB:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000816 switch( opcode ) {
817 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
818 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
819 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
820 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
821 };
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000822
823 ConstantFPSDNode *CN;
824 if (opcode == ISD::SUB
825 && (CN = dyn_cast<ConstantFPSDNode>(N.getOperand(0)))
826 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
827 {
828 Tmp2 = SelectExpr(N.getOperand(1));
829 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp2).addReg(Tmp2);
830 } else {
831 Tmp1 = SelectExpr(N.getOperand(0));
832 Tmp2 = SelectExpr(N.getOperand(1));
833 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
834 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000835 return Result;
836
Andrew Lenharth2c594352005-01-29 15:42:07 +0000837 case ISD::EXTLOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000838 {
839 //include a conversion sequence for float loads to double
840 if (Result != notIn)
841 ExprMap[N.getValue(1)] = notIn; // Generate the token
842 else
843 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
844
Andrew Lenhartha549deb2005-02-07 05:33:15 +0000845 Tmp1 = MakeReg(MVT::f32);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000846
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000847 assert(cast<MVTSDNode>(Node)->getExtraValueType() == MVT::f32 &&
848 "EXTLOAD not from f32");
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000849 assert(Node->getValueType(0) == MVT::f64 && "EXTLOAD not to f64");
850
851 SDOperand Chain = N.getOperand(0);
852 SDOperand Address = N.getOperand(1);
853 Select(Chain);
854
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000855 if (Address.getOpcode() == ISD::GlobalAddress) {
856 AlphaLowering.restoreGP(BB);
857 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
858 }
859 else if (ConstantPoolSDNode *CP =
860 dyn_cast<ConstantPoolSDNode>(N.getOperand(1)))
861 {
862 AlphaLowering.restoreGP(BB);
863 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addConstantPoolIndex(CP->getIndex());
864 }
865 else if(Address.getOpcode() == ISD::FrameIndex) {
866 Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
Andrew Lenharth032f2352005-02-22 21:59:48 +0000867 BuildMI(BB, Alpha::LDS, 2, Tmp1)
868 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
869 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000870 } else {
871 long offset;
872 SelectAddr(Address, Tmp2, offset);
873 BuildMI(BB, Alpha::LDS, 1, Tmp1).addImm(offset).addReg(Tmp2);
874 }
Andrew Lenharth29219162005-02-07 06:31:44 +0000875 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000876 return Result;
877 }
Andrew Lenharth2c594352005-01-29 15:42:07 +0000878
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000879 case ISD::UINT_TO_FP:
880 case ISD::SINT_TO_FP:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000881 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000882 assert (N.getOperand(0).getValueType() == MVT::i64
883 && "only quads can be loaded from");
Andrew Lenharth40831c52005-01-28 06:57:18 +0000884 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000885 Tmp2 = MakeReg(MVT::f64);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000886 MoveInt2FP(Tmp1, Tmp2, true);
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000887 Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
888 BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000889 return Result;
890 }
891 }
892 assert(0 && "should not get here");
893 return 0;
894}
895
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000896unsigned ISel::SelectExpr(SDOperand N) {
897 unsigned Result;
898 unsigned Tmp1, Tmp2, Tmp3;
899 unsigned Opc = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000900 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000901
902 SDNode *Node = N.Val;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000903 MVT::ValueType DestType = N.getValueType();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000904
905 unsigned &Reg = ExprMap[N];
906 if (Reg) return Reg;
907
908 if (N.getOpcode() != ISD::CALL)
909 Reg = Result = (N.getValueType() != MVT::Other) ?
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000910 MakeReg(N.getValueType()) : notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000911 else {
912 // If this is a call instruction, make sure to prepare ALL of the result
913 // values as well as the chain.
914 if (Node->getNumValues() == 1)
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000915 Reg = Result = notIn; // Void call, just a chain.
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000916 else {
917 Result = MakeReg(Node->getValueType(0));
918 ExprMap[N.getValue(0)] = Result;
919 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
920 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000921 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000922 }
923 }
924
Andrew Lenharth22088bb2005-02-02 15:05:33 +0000925 if (DestType == MVT::f64 || DestType == MVT::f32 ||
Andrew Lenharth06342c32005-02-07 06:21:37 +0000926 (
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000927 (opcode == ISD::LOAD || opcode == ISD::CopyFromReg ||
928 opcode == ISD::EXTLOAD) &&
929 (N.getValue(0).getValueType() == MVT::f32 ||
930 N.getValue(0).getValueType() == MVT::f64)
Andrew Lenharth06342c32005-02-07 06:21:37 +0000931 )
932 )
Andrew Lenharth40831c52005-01-28 06:57:18 +0000933 return SelectExprFP(N, Result);
934
935 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000936 default:
937 Node->dump();
938 assert(0 && "Node not handled!\n");
939
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000940
941 case ISD::UNDEF: {
942 BuildMI(BB, Alpha::IDEF, 0, Result);
943 return Result;
944 }
945
Andrew Lenharth032f2352005-02-22 21:59:48 +0000946 case ISD::DYNAMIC_STACKALLOC:
947 // Generate both result values.
Andrew Lenharth3a7118d2005-02-23 17:33:42 +0000948 if (Result != notIn)
949 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth032f2352005-02-22 21:59:48 +0000950 else
951 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
952
953 // FIXME: We are currently ignoring the requested alignment for handling
954 // greater than the stack alignment. This will need to be revisited at some
955 // point. Align = N.getOperand(2);
956
957 if (!isa<ConstantSDNode>(N.getOperand(2)) ||
958 cast<ConstantSDNode>(N.getOperand(2))->getValue() != 0) {
959 std::cerr << "Cannot allocate stack object with greater alignment than"
960 << " the stack alignment yet!";
961 abort();
962 }
963
964 Select(N.getOperand(0));
965 if (ConstantSDNode* CN = dyn_cast<ConstantSDNode>(N.getOperand(1)))
966 {
967 if (CN->getValue() < 32000)
968 {
969 BuildMI(BB, Alpha::LDA, 2, Alpha::R30)
970 .addImm(-CN->getValue()).addReg(Alpha::R30);
971 } else {
972 Tmp1 = SelectExpr(N.getOperand(1));
973 // Subtract size from stack pointer, thereby allocating some space.
974 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
975 }
976 } else {
977 Tmp1 = SelectExpr(N.getOperand(1));
978 // Subtract size from stack pointer, thereby allocating some space.
979 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
980 }
981
982 // Put a pointer to the space into the result register, by copying the stack
983 // pointer.
Andrew Lenharth7bc47022005-02-22 23:29:25 +0000984 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R30).addReg(Alpha::R30);
Andrew Lenharth032f2352005-02-22 21:59:48 +0000985 return Result;
986
Andrew Lenharth33819132005-03-04 20:09:23 +0000987// case ISD::ConstantPool:
988// Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
989// AlphaLowering.restoreGP(BB);
990// BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(Tmp1);
991// return Result;
Andrew Lenharth2c594352005-01-29 15:42:07 +0000992
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000993 case ISD::FrameIndex:
Andrew Lenharth032f2352005-02-22 21:59:48 +0000994 BuildMI(BB, Alpha::LDA, 2, Result)
995 .addFrameIndex(cast<FrameIndexSDNode>(N)->getIndex())
996 .addReg(Alpha::F31);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000997 return Result;
998
999 case ISD::EXTLOAD:
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001000 case ISD::ZEXTLOAD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001001 case ISD::SEXTLOAD:
Andrew Lenhartha549deb2005-02-07 05:33:15 +00001002 case ISD::LOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001003 {
1004 // Make sure we generate both values.
1005 if (Result != notIn)
1006 ExprMap[N.getValue(1)] = notIn; // Generate the token
1007 else
1008 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001009
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001010 SDOperand Chain = N.getOperand(0);
1011 SDOperand Address = N.getOperand(1);
1012 Select(Chain);
1013
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001014 assert(Node->getValueType(0) == MVT::i64 &&
1015 "Unknown type to sign extend to.");
Andrew Lenharth03824012005-02-07 05:55:55 +00001016 if (opcode == ISD::LOAD)
1017 Opc = Alpha::LDQ;
1018 else
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001019 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
1020 default: Node->dump(); assert(0 && "Bad sign extend!");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001021 case MVT::i32: Opc = Alpha::LDL;
1022 assert(opcode != ISD::ZEXTLOAD && "Not sext"); break;
1023 case MVT::i16: Opc = Alpha::LDWU;
1024 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001025 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001026 case MVT::i8: Opc = Alpha::LDBU;
1027 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001028 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001029
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001030 if (Address.getOpcode() == ISD::GlobalAddress) {
1031 AlphaLowering.restoreGP(BB);
1032 Opc = GetSymVersion(Opc);
1033 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1034 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001035 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
1036 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +00001037 Opc = GetSymVersion(Opc);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001038 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001039 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001040 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001041 BuildMI(BB, Opc, 2, Result)
1042 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1043 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001044 } else {
1045 long offset;
1046 SelectAddr(Address, Tmp1, offset);
1047 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
1048 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001049 return Result;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001050 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001051
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001052 case ISD::GlobalAddress:
1053 AlphaLowering.restoreGP(BB);
1054 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
1055 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
1056 return Result;
1057
1058 case ISD::CALL:
1059 {
1060 Select(N.getOperand(0));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001061
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001062 // The chain for this call is now lowered.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001063 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), notIn));
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001064
1065 //grab the arguments
1066 std::vector<unsigned> argvregs;
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001067 //assert(Node->getNumOperands() < 8 && "Only 6 args supported");
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001068 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001069 argvregs.push_back(SelectExpr(N.getOperand(i)));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001070
Andrew Lenharth684f2292005-01-30 00:35:27 +00001071 //in reg args
1072 for(int i = 0, e = std::min(6, (int)argvregs.size()); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001073 {
1074 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
1075 Alpha::R19, Alpha::R20, Alpha::R21};
1076 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
1077 Alpha::F19, Alpha::F20, Alpha::F21};
1078 switch(N.getOperand(i+2).getValueType()) {
1079 default:
1080 Node->dump();
1081 N.getOperand(i).Val->dump();
1082 std::cerr << "Type for " << i << " is: " <<
1083 N.getOperand(i+2).getValueType() << "\n";
1084 assert(0 && "Unknown value type for call");
1085 case MVT::i1:
1086 case MVT::i8:
1087 case MVT::i16:
1088 case MVT::i32:
1089 case MVT::i64:
1090 BuildMI(BB, Alpha::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
1091 break;
1092 case MVT::f32:
1093 case MVT::f64:
1094 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
1095 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001096 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001097 }
Andrew Lenharth684f2292005-01-30 00:35:27 +00001098 //in mem args
1099 for (int i = 6, e = argvregs.size(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001100 {
1101 switch(N.getOperand(i+2).getValueType()) {
1102 default:
1103 Node->dump();
1104 N.getOperand(i).Val->dump();
1105 std::cerr << "Type for " << i << " is: " <<
1106 N.getOperand(i+2).getValueType() << "\n";
1107 assert(0 && "Unknown value type for call");
1108 case MVT::i1:
1109 case MVT::i8:
1110 case MVT::i16:
1111 case MVT::i32:
1112 case MVT::i64:
1113 BuildMI(BB, Alpha::STQ, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1114 break;
1115 case MVT::f32:
1116 BuildMI(BB, Alpha::STS, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1117 break;
1118 case MVT::f64:
1119 BuildMI(BB, Alpha::STT, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1120 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001121 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001122 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001123 //build the right kind of call
1124 if (GlobalAddressSDNode *GASD =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001125 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001126 {
Andrew Lenharth3e315922005-02-10 20:10:38 +00001127 //if (GASD->getGlobal()->isExternal()) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001128 //use safe calling convention
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001129 AlphaLowering.restoreGP(BB);
1130 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
Andrew Lenharth3e315922005-02-10 20:10:38 +00001131 //} else {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001132 //use PC relative branch call
Andrew Lenharth3e315922005-02-10 20:10:38 +00001133 //BuildMI(BB, Alpha::BSR, 1, Alpha::R26).addGlobalAddress(GASD->getGlobal(),true);
1134 //}
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001135 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001136 else if (ExternalSymbolSDNode *ESSDN =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001137 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001138 {
1139 AlphaLowering.restoreGP(BB);
Andrew Lenharthba05ad62005-03-30 18:22:52 +00001140 BuildMI(BB, Alpha::CALL, 1).addExternalSymbol(ESSDN->getSymbol(), true);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001141 } else {
1142 //no need to restore GP as we are doing an indirect call
1143 Tmp1 = SelectExpr(N.getOperand(1));
1144 BuildMI(BB, Alpha::BIS, 2, Alpha::R27).addReg(Tmp1).addReg(Tmp1);
1145 BuildMI(BB, Alpha::JSR, 2, Alpha::R26).addReg(Alpha::R27).addImm(0);
1146 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001147
1148 //push the result into a virtual register
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001149
1150 switch (Node->getValueType(0)) {
1151 default: Node->dump(); assert(0 && "Unknown value type for call result!");
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001152 case MVT::Other: return notIn;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001153 case MVT::i1:
1154 case MVT::i8:
1155 case MVT::i16:
1156 case MVT::i32:
1157 case MVT::i64:
1158 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
1159 break;
1160 case MVT::f32:
1161 case MVT::f64:
1162 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
1163 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001164 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001165 return Result+N.ResNo;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001166 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001167
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001168 case ISD::SIGN_EXTEND_INREG:
1169 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001170 //do SDIV opt for all levels of ints
Andrew Lenharth5e99dd92005-03-31 22:02:25 +00001171 if (EnableAlphaIDIV && N.getOperand(0).getOpcode() == ISD::SDIV)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001172 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001173 unsigned Tmp4 = MakeReg(MVT::f64);
1174 unsigned Tmp5 = MakeReg(MVT::f64);
1175 unsigned Tmp6 = MakeReg(MVT::f64);
1176 unsigned Tmp7 = MakeReg(MVT::f64);
1177 unsigned Tmp8 = MakeReg(MVT::f64);
1178 unsigned Tmp9 = MakeReg(MVT::f64);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001179
1180 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1181 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1182 MoveInt2FP(Tmp1, Tmp4, true);
1183 MoveInt2FP(Tmp2, Tmp5, true);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001184 BuildMI(BB, Alpha::CVTQT, 1, Tmp6).addReg(Tmp4);
1185 BuildMI(BB, Alpha::CVTQT, 1, Tmp7).addReg(Tmp5);
1186 BuildMI(BB, Alpha::DIVT, 2, Tmp8).addReg(Tmp6).addReg(Tmp7);
1187 BuildMI(BB, Alpha::CVTTQ, 1, Tmp9).addReg(Tmp8);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001188 MoveFP2Int(Tmp9, Result, true);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001189 return Result;
1190 }
1191
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001192 //Alpha has instructions for a bunch of signed 32 bit stuff
1193 if( dyn_cast<MVTSDNode>(Node)->getExtraValueType() == MVT::i32)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001194 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001195 switch (N.getOperand(0).getOpcode()) {
1196 case ISD::ADD:
1197 case ISD::SUB:
1198 case ISD::MUL:
1199 {
1200 bool isAdd = N.getOperand(0).getOpcode() == ISD::ADD;
1201 bool isMul = N.getOperand(0).getOpcode() == ISD::MUL;
1202 //FIXME: first check for Scaled Adds and Subs!
1203 if(N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1204 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() <= 255)
1205 { //Normal imm add/sub
1206 Opc = isAdd ? Alpha::ADDLi : (isMul ? Alpha::MULLi : Alpha::SUBLi);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001207 //if the value was really originally a i32, skip the up conversion
1208 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1209 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1210 ->getExtraValueType() == MVT::i32)
1211 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1212 else
1213 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001214 Tmp2 = cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue();
1215 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001216 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001217 else
1218 { //Normal add/sub
1219 Opc = isAdd ? Alpha::ADDL : (isMul ? Alpha::MULLi : Alpha::SUBL);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001220 //if the value was really originally a i32, skip the up conversion
1221 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1222 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1223 ->getExtraValueType() == MVT::i32)
1224 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1225 else
1226 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1227 //if the value was really originally a i32, skip the up conversion
1228 if (N.getOperand(0).getOperand(1).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1229 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(1).Val)
1230 ->getExtraValueType() == MVT::i32)
1231 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0));
1232 else
1233 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1234
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001235 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1236 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1237 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1238 }
1239 return Result;
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001240 }
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001241 case ISD::SEXTLOAD:
1242 //SelectionDag isn't deleting the signextend after sextloads
1243 Reg = Result = SelectExpr(N.getOperand(0));
1244 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001245 default: break; //Fall Though;
1246 }
1247 } //Every thing else fall though too, including unhandled opcodes above
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001248 Tmp1 = SelectExpr(N.getOperand(0));
1249 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001250 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001251 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001252 {
1253 default:
1254 Node->dump();
1255 assert(0 && "Sign Extend InReg not there yet");
1256 break;
1257 case MVT::i32:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001258 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001259 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001260 break;
1261 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001262 case MVT::i16:
1263 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
1264 break;
1265 case MVT::i8:
1266 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
1267 break;
Andrew Lenharthebce5042005-02-12 19:35:12 +00001268 case MVT::i1:
1269 Tmp2 = MakeReg(MVT::i64);
1270 BuildMI(BB, Alpha::ANDi, 2, Tmp2).addReg(Tmp1).addImm(1);
Andrew Lenharth7536eea2005-02-12 20:42:09 +00001271 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Alpha::F31).addReg(Tmp2);
Andrew Lenharthebce5042005-02-12 19:35:12 +00001272 break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001273 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001274 return Result;
1275 }
1276 case ISD::ZERO_EXTEND_INREG:
1277 {
1278 Tmp1 = SelectExpr(N.getOperand(0));
1279 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001280 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001281 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001282 {
1283 default:
1284 Node->dump();
1285 assert(0 && "Zero Extend InReg not there yet");
1286 break;
1287 case MVT::i32: Tmp2 = 0xf0; break;
1288 case MVT::i16: Tmp2 = 0xfc; break;
1289 case MVT::i8: Tmp2 = 0xfe; break;
1290 case MVT::i1: //handle this one special
1291 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
1292 return Result;
1293 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001294 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001295 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001296 }
1297
1298 case ISD::SETCC:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001299 {
1300 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
1301 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
1302 bool isConst1 = false;
1303 bool isConst2 = false;
1304 int dir;
Andrew Lenharth9818c052005-02-05 13:19:12 +00001305
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001306 //Tmp1 = SelectExpr(N.getOperand(0));
1307 if(N.getOperand(0).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001308 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1309 isConst1 = true;
1310 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001311 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1312 isConst2 = true;
1313
1314 switch (SetCC->getCondition()) {
1315 default: Node->dump(); assert(0 && "Unknown integer comparison!");
1316 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001317 case ISD::SETLT:
1318 Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
1319 case ISD::SETLE:
1320 Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
1321 case ISD::SETGT:
1322 Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
1323 case ISD::SETGE:
1324 Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
1325 case ISD::SETULT:
1326 Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
1327 case ISD::SETUGT:
1328 Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
1329 case ISD::SETULE:
1330 Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
1331 case ISD::SETUGE:
1332 Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001333 case ISD::SETNE: {//Handle this one special
1334 //std::cerr << "Alpha does not have a setne.\n";
1335 //abort();
1336 Tmp1 = SelectExpr(N.getOperand(0));
1337 Tmp2 = SelectExpr(N.getOperand(1));
1338 Tmp3 = MakeReg(MVT::i64);
1339 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth445171a2005-02-08 00:40:03 +00001340 //Remeber we have the Inv for this CC
1341 CCInvMap[N] = Tmp3;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001342 //and invert
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001343 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001344 return Result;
1345 }
1346 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001347 if (dir == 1) {
1348 Tmp1 = SelectExpr(N.getOperand(0));
1349 if (isConst2) {
1350 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1351 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1352 } else {
1353 Tmp2 = SelectExpr(N.getOperand(1));
1354 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1355 }
1356 } else if (dir == 2) {
1357 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001358 if (isConst1) {
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001359 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1360 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1361 } else {
1362 Tmp2 = SelectExpr(N.getOperand(0));
1363 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1364 }
1365 } else { //dir == 0
1366 if (isConst1) {
1367 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1368 Tmp2 = SelectExpr(N.getOperand(1));
1369 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
1370 } else if (isConst2) {
1371 Tmp1 = SelectExpr(N.getOperand(0));
1372 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1373 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
1374 } else {
1375 Tmp1 = SelectExpr(N.getOperand(0));
1376 Tmp2 = SelectExpr(N.getOperand(1));
1377 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
1378 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001379 }
1380 } else {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001381 //do the comparison
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001382 Tmp1 = MakeReg(MVT::f64);
1383 bool inv = SelectFPSetCC(N, Tmp1);
1384
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001385 //now arrange for Result (int) to have a 1 or 0
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001386 Tmp2 = MakeReg(MVT::i64);
1387 BuildMI(BB, Alpha::ADDQi, 2, Tmp2).addReg(Alpha::R31).addImm(1);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001388 Opc = inv?Alpha::CMOVNEi_FP:Alpha::CMOVEQi_FP;
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001389 BuildMI(BB, Opc, 3, Result).addReg(Tmp2).addImm(0).addReg(Tmp1);
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001390 }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001391 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001392 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001393 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001394
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001395 case ISD::CopyFromReg:
1396 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001397 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001398 if (Result != notIn)
1399 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth40831c52005-01-28 06:57:18 +00001400 else
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001401 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth40831c52005-01-28 06:57:18 +00001402
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001403 SDOperand Chain = N.getOperand(0);
1404
1405 Select(Chain);
1406 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
1407 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
1408 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
1409 return Result;
1410 }
1411
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001412 //Most of the plain arithmetic and logic share the same form, and the same
1413 //constant immediate test
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001414 case ISD::OR:
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001415 //Match Not
1416 if (N.getOperand(1).getOpcode() == ISD::Constant &&
1417 cast<ConstantSDNode>(N.getOperand(1))->isAllOnesValue())
1418 {
1419 Tmp1 = SelectExpr(N.getOperand(0));
1420 BuildMI(BB, Alpha::ORNOT, 2, Result).addReg(Alpha::R31).addReg(Tmp1);
1421 return Result;
1422 }
1423 //Fall through
1424 case ISD::AND:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001425 case ISD::XOR:
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001426 //Check operand(0) == Not
1427 if (N.getOperand(0).getOpcode() == ISD::OR &&
1428 N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1429 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->isAllOnesValue())
1430 {
1431 switch(opcode) {
1432 case ISD::AND: Opc = Alpha::BIC; break;
1433 case ISD::OR: Opc = Alpha::ORNOT; break;
1434 case ISD::XOR: Opc = Alpha::EQV; break;
1435 }
1436 Tmp1 = SelectExpr(N.getOperand(1));
1437 Tmp2 = SelectExpr(N.getOperand(0).getOperand(0));
1438 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1439 return Result;
1440 }
1441 //Check operand(1) == Not
1442 if (N.getOperand(1).getOpcode() == ISD::OR &&
1443 N.getOperand(1).getOperand(1).getOpcode() == ISD::Constant &&
1444 cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->isAllOnesValue())
1445 {
1446 switch(opcode) {
1447 case ISD::AND: Opc = Alpha::BIC; break;
1448 case ISD::OR: Opc = Alpha::ORNOT; break;
1449 case ISD::XOR: Opc = Alpha::EQV; break;
1450 }
1451 Tmp1 = SelectExpr(N.getOperand(0));
1452 Tmp2 = SelectExpr(N.getOperand(1).getOperand(0));
1453 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1454 return Result;
1455 }
1456 //Fall through
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001457 case ISD::SHL:
1458 case ISD::SRL:
Andrew Lenharth2c594352005-01-29 15:42:07 +00001459 case ISD::SRA:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001460 case ISD::MUL:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001461 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
1462 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001463 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001464 {
1465 switch(opcode) {
1466 case ISD::AND: Opc = Alpha::ANDi; break;
1467 case ISD::OR: Opc = Alpha::BISi; break;
1468 case ISD::XOR: Opc = Alpha::XORi; break;
1469 case ISD::SHL: Opc = Alpha::SLi; break;
1470 case ISD::SRL: Opc = Alpha::SRLi; break;
1471 case ISD::SRA: Opc = Alpha::SRAi; break;
1472 case ISD::MUL: Opc = Alpha::MULQi; break;
1473 };
1474 Tmp1 = SelectExpr(N.getOperand(0));
1475 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1476 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1477 } else {
1478 switch(opcode) {
1479 case ISD::AND: Opc = Alpha::AND; break;
1480 case ISD::OR: Opc = Alpha::BIS; break;
1481 case ISD::XOR: Opc = Alpha::XOR; break;
1482 case ISD::SHL: Opc = Alpha::SL; break;
1483 case ISD::SRL: Opc = Alpha::SRL; break;
1484 case ISD::SRA: Opc = Alpha::SRA; break;
1485 case ISD::MUL: Opc = Alpha::MULQ; break;
1486 };
1487 Tmp1 = SelectExpr(N.getOperand(0));
1488 Tmp2 = SelectExpr(N.getOperand(1));
1489 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1490 }
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001491 return Result;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001492
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001493 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001494 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001495 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001496 bool isAdd = opcode == ISD::ADD;
1497
1498 //FIXME: first check for Scaled Adds and Subs!
1499 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001500 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001501 { //Normal imm add/sub
1502 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
1503 Tmp1 = SelectExpr(N.getOperand(0));
1504 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1505 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1506 }
Andrew Lenharth40831c52005-01-28 06:57:18 +00001507 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001508 (cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767 ||
1509 (long)cast<ConstantSDNode>(N.getOperand(1))->getValue() >= -32767))
1510 { //LDA
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001511 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001512 Tmp2 = (long)cast<ConstantSDNode>(N.getOperand(1))->getValue();
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001513 if (!isAdd)
1514 Tmp2 = -Tmp2;
1515 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
1516 } else {
1517 //Normal add/sub
1518 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
1519 Tmp1 = SelectExpr(N.getOperand(0));
1520 Tmp2 = SelectExpr(N.getOperand(1));
1521 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1522 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001523 return Result;
1524 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001525
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001526 case ISD::SDIV:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001527 case ISD::UREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001528 case ISD::SREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001529 case ISD::UDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001530 //FIXME: alpha really doesn't support any of these operations,
1531 // the ops are expanded into special library calls with
1532 // special calling conventions
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001533 //Restore GP because it is a call after all...
Andrew Lenharth40831c52005-01-28 06:57:18 +00001534 switch(opcode) {
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001535 case ISD::UREM: Opc = Alpha::REMQU; break;
1536 case ISD::SREM: Opc = Alpha::REMQ; break;
1537 case ISD::UDIV: Opc = Alpha::DIVQU; break;
1538 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001539 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001540 Tmp1 = SelectExpr(N.getOperand(0));
1541 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth33819132005-03-04 20:09:23 +00001542 //set up regs explicitly (helps Reg alloc)
1543 BuildMI(BB, Alpha::BIS, 2, Alpha::R24).addReg(Tmp1).addReg(Tmp1);
1544 BuildMI(BB, Alpha::BIS, 2, Alpha::R25).addReg(Tmp2).addReg(Tmp2);
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001545 AlphaLowering.restoreGP(BB);
Andrew Lenharth33819132005-03-04 20:09:23 +00001546 BuildMI(BB, Opc, 2).addReg(Alpha::R24).addReg(Alpha::R25);
1547 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R27).addReg(Alpha::R27);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001548 return Result;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001549
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001550 case ISD::FP_TO_UINT:
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001551 case ISD::FP_TO_SINT:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001552 {
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001553 assert (DestType == MVT::i64 && "only quads can be loaded to");
1554 MVT::ValueType SrcType = N.getOperand(0).getValueType();
Andrew Lenharth03824012005-02-07 05:55:55 +00001555 assert (SrcType == MVT::f32 || SrcType == MVT::f64);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001556 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001557 if (SrcType == MVT::f32)
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001558 {
1559 Tmp2 = MakeReg(MVT::f64);
1560 BuildMI(BB, Alpha::CVTST, 1, Tmp2).addReg(Tmp1);
1561 Tmp1 = Tmp2;
1562 }
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001563 Tmp2 = MakeReg(MVT::f64);
1564 BuildMI(BB, Alpha::CVTTQ, 1, Tmp2).addReg(Tmp1);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001565 MoveFP2Int(Tmp2, Result, true);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001566
1567 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001568 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001569
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001570 case ISD::SELECT:
1571 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001572 //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 +00001573 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001574 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1575 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001576 // Get the condition into the zero flag.
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001577 //BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
1578 SDOperand CC = N.getOperand(0);
1579 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
1580
1581 if (CC.getOpcode() == ISD::SETCC &&
1582 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
1583 { //FP Setcc -> Int Select
1584 Tmp1 = MakeReg(MVT::f64);
1585 bool inv = SelectFPSetCC(CC, Tmp1);
1586 BuildMI(BB, inv?Alpha::CMOVNE_FP:Alpha::CMOVEQ_FP, 2, Result)
1587 .addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
1588 return Result;
1589 }
1590 if (CC.getOpcode() == ISD::SETCC) {
1591 //Int SetCC -> Select
1592 //Dropping the CC is only useful if we are comparing to 0
1593 if(SetCC->getOperand(1).getOpcode() == ISD::Constant &&
1594 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0)
1595 {
1596 bool useI = (SetCC->getOperand(1).getOpcode() == ISD::Constant &&
1597 cast<ConstantSDNode>(SetCC->getOperand(1))->getValue() <= 255);
1598
1599 switch (SetCC->getCondition()) {
1600 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
1601 case ISD::SETEQ: Opc = useI?Alpha::CMOVEQi:Alpha::CMOVEQ; break;
1602 case ISD::SETLT: Opc = useI?Alpha::CMOVGTi:Alpha::CMOVGT; break;
1603 case ISD::SETLE: Opc = useI?Alpha::CMOVGEi:Alpha::CMOVGE; break;
1604 case ISD::SETGT: Opc = useI?Alpha::CMOVLTi:Alpha::CMOVLT; break;
1605 case ISD::SETGE: Opc = useI?Alpha::CMOVLEi:Alpha::CMOVLE; break;
1606 case ISD::SETULT: Opc = useI?Alpha::CMOVNEi:Alpha::CMOVNE; break;
1607 case ISD::SETUGT: assert(0 && "0 > (unsigned) x is never true"); break;
1608 case ISD::SETULE: assert(0 && "0 <= (unsigned) x is always true"); break;
1609 case ISD::SETUGE: Opc = useI?Alpha::CMOVEQi:Alpha::CMOVEQ; break; //Technically you could have this CC
1610 case ISD::SETNE: Opc = useI?Alpha::CMOVNEi:Alpha::CMOVNE; break;
1611 }
1612 if (useI)
1613 BuildMI(BB, Opc, 2, Result).addReg(Tmp2).addReg(Tmp3)
1614 .addImm(cast<ConstantSDNode>(SetCC->getOperand(1))->getValue());
1615 else
1616 BuildMI(BB, Opc, 2, Result).addReg(Tmp2).addReg(Tmp3)
1617 .addReg(SelectExpr(SetCC->getOperand(1)));
1618 return Result;
1619 }
1620 if(SetCC->getOperand(1).getOpcode() == ISD::Constant &&
1621 cast<ConstantSDNode>(SetCC->getOperand(1))->getValue() == 0)
1622 {
1623 bool useI = (SetCC->getOperand(0).getOpcode() == ISD::Constant &&
1624 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() <= 255);
1625
1626 switch (SetCC->getCondition()) {
1627 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
1628 case ISD::SETEQ: Opc = useI?Alpha::CMOVEQi:Alpha::CMOVEQ; break;
1629 case ISD::SETLT: Opc = useI?Alpha::CMOVLTi:Alpha::CMOVLT; break;
1630 case ISD::SETLE: Opc = useI?Alpha::CMOVLEi:Alpha::CMOVLE; break;
1631 case ISD::SETGT: Opc = useI?Alpha::CMOVGTi:Alpha::CMOVGT; break;
1632 case ISD::SETGE: Opc = useI?Alpha::CMOVGEi:Alpha::CMOVGE; break;
1633 case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break;
1634 case ISD::SETUGT: Opc = useI?Alpha::CMOVNEi:Alpha::CMOVNE; break;
1635 case ISD::SETULE: Opc = useI?Alpha::CMOVEQi:Alpha::CMOVEQ; break; //Technically you could have this CC
1636 case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break;
1637 case ISD::SETNE: Opc = useI?Alpha::CMOVNEi:Alpha::CMOVNE; break;
1638 }
1639 if (useI)
1640 BuildMI(BB, Opc, 2, Result).addReg(Tmp2).addReg(Tmp3)
1641 .addImm(cast<ConstantSDNode>(SetCC->getOperand(0))->getValue());
1642 else
1643 BuildMI(BB, Opc, 2, Result).addReg(Tmp2).addReg(Tmp3)
1644 .addReg(SelectExpr(SetCC->getOperand(0)));
1645 return Result;
1646 }
1647 //Otherwise, fall though
1648 }
1649 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001650 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001651
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001652 return Result;
1653 }
1654
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001655 case ISD::Constant:
1656 {
Andrew Lenharthc0513832005-03-29 19:24:04 +00001657 int64_t val = (int64_t)cast<ConstantSDNode>(N)->getValue();
Andrew Lenharthe87f6c32005-03-11 17:48:05 +00001658 if (val <= IMM_HIGH && val >= IMM_LOW) {
1659 BuildMI(BB, Alpha::LDA, 2, Result).addImm(val).addReg(Alpha::R31);
1660 }
1661 else if (val <= (int64_t)IMM_HIGH + (int64_t)IMM_HIGH * (int64_t)IMM_MULT &&
1662 val >= (int64_t)IMM_LOW + (int64_t)IMM_LOW * (int64_t)IMM_MULT) {
1663 Tmp1 = MakeReg(MVT::i64);
1664 BuildMI(BB, Alpha::LDAH, 2, Tmp1).addImm(getUpper16(val)).addReg(Alpha::R31);
1665 BuildMI(BB, Alpha::LDA, 2, Result).addImm(getLower16(val)).addReg(Tmp1);
1666 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001667 else {
1668 MachineConstantPool *CP = BB->getParent()->getConstantPool();
1669 ConstantUInt *C = ConstantUInt::get(Type::getPrimitiveType(Type::ULongTyID) , val);
1670 unsigned CPI = CP->getConstantPoolIndex(C);
1671 AlphaLowering.restoreGP(BB);
1672 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(CPI);
1673 }
1674 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001675 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001676 }
1677
1678 return 0;
1679}
1680
1681void ISel::Select(SDOperand N) {
1682 unsigned Tmp1, Tmp2, Opc;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001683 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001684
Nate Begeman85fdeb22005-03-24 04:39:54 +00001685 if (!ExprMap.insert(std::make_pair(N, notIn)).second)
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001686 return; // Already selected.
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001687
1688 SDNode *Node = N.Val;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001689
Andrew Lenharth760270d2005-02-07 23:02:23 +00001690 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001691
1692 default:
1693 Node->dump(); std::cerr << "\n";
1694 assert(0 && "Node not handled yet!");
1695
1696 case ISD::BRCOND: {
Andrew Lenharth445171a2005-02-08 00:40:03 +00001697 SelectBranchCC(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001698 return;
1699 }
1700
1701 case ISD::BR: {
1702 MachineBasicBlock *Dest =
1703 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
1704
1705 Select(N.getOperand(0));
1706 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
1707 return;
1708 }
1709
1710 case ISD::ImplicitDef:
1711 Select(N.getOperand(0));
1712 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
1713 return;
1714
1715 case ISD::EntryToken: return; // Noop
1716
1717 case ISD::TokenFactor:
1718 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
1719 Select(Node->getOperand(i));
1720
1721 //N.Val->dump(); std::cerr << "\n";
1722 //assert(0 && "Node not handled yet!");
1723
1724 return;
1725
1726 case ISD::CopyToReg:
1727 Select(N.getOperand(0));
1728 Tmp1 = SelectExpr(N.getOperand(1));
1729 Tmp2 = cast<RegSDNode>(N)->getReg();
1730
1731 if (Tmp1 != Tmp2) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001732 if (N.getOperand(1).getValueType() == MVT::f64 ||
1733 N.getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth29219162005-02-07 06:31:44 +00001734 BuildMI(BB, Alpha::CPYS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
1735 else
1736 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001737 }
1738 return;
1739
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001740 case ISD::RET:
1741 switch (N.getNumOperands()) {
1742 default:
1743 std::cerr << N.getNumOperands() << "\n";
1744 for (unsigned i = 0; i < N.getNumOperands(); ++i)
1745 std::cerr << N.getOperand(i).getValueType() << "\n";
1746 Node->dump();
1747 assert(0 && "Unknown return instruction!");
1748 case 2:
1749 Select(N.getOperand(0));
1750 Tmp1 = SelectExpr(N.getOperand(1));
1751 switch (N.getOperand(1).getValueType()) {
1752 default: Node->dump();
1753 assert(0 && "All other types should have been promoted!!");
1754 case MVT::f64:
1755 case MVT::f32:
1756 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
1757 break;
1758 case MVT::i32:
1759 case MVT::i64:
1760 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
1761 break;
1762 }
1763 break;
1764 case 1:
1765 Select(N.getOperand(0));
1766 break;
1767 }
1768 //Tmp2 = AlphaLowering.getRetAddr();
1769 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
1770 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
1771 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001772
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001773 case ISD::TRUNCSTORE:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001774 case ISD::STORE:
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001775 {
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001776 SDOperand Chain = N.getOperand(0);
1777 SDOperand Value = N.getOperand(1);
1778 SDOperand Address = N.getOperand(2);
1779 Select(Chain);
1780
1781 Tmp1 = SelectExpr(Value); //value
Andrew Lenharth760270d2005-02-07 23:02:23 +00001782
1783 if (opcode == ISD::STORE) {
1784 switch(Value.getValueType()) {
1785 default: assert(0 && "unknown Type in store");
1786 case MVT::i64: Opc = Alpha::STQ; break;
1787 case MVT::f64: Opc = Alpha::STT; break;
1788 case MVT::f32: Opc = Alpha::STS; break;
1789 }
1790 } else { //ISD::TRUNCSTORE
1791 switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
1792 default: assert(0 && "unknown Type in store");
1793 case MVT::i1: //FIXME: DAG does not promote this load
1794 case MVT::i8: Opc = Alpha::STB; break;
1795 case MVT::i16: Opc = Alpha::STW; break;
1796 case MVT::i32: Opc = Alpha::STL; break;
1797 }
Andrew Lenharth65838902005-02-06 16:22:15 +00001798 }
Andrew Lenharth760270d2005-02-07 23:02:23 +00001799
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001800 if (Address.getOpcode() == ISD::GlobalAddress)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001801 {
1802 AlphaLowering.restoreGP(BB);
1803 Opc = GetSymVersion(Opc);
1804 BuildMI(BB, Opc, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1805 }
Andrew Lenharth05380342005-02-07 05:07:00 +00001806 else if(Address.getOpcode() == ISD::FrameIndex)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001807 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001808 BuildMI(BB, Opc, 3).addReg(Tmp1)
1809 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1810 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001811 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001812 else
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001813 {
1814 long offset;
1815 SelectAddr(Address, Tmp2, offset);
1816 BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
1817 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001818 return;
1819 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001820
1821 case ISD::EXTLOAD:
1822 case ISD::SEXTLOAD:
1823 case ISD::ZEXTLOAD:
1824 case ISD::LOAD:
1825 case ISD::CopyFromReg:
1826 case ISD::CALL:
Andrew Lenharth032f2352005-02-22 21:59:48 +00001827 case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001828 ExprMap.erase(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001829 SelectExpr(N);
1830 return;
1831
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001832 case ISD::ADJCALLSTACKDOWN:
1833 case ISD::ADJCALLSTACKUP:
1834 Select(N.getOperand(0));
1835 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1836
1837 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
1838 Alpha::ADJUSTSTACKUP;
1839 BuildMI(BB, Opc, 1).addImm(Tmp1);
1840 return;
Andrew Lenharth95762122005-03-31 21:24:06 +00001841
1842 case ISD::PCMARKER:
1843 Select(N.getOperand(0)); //Chain
1844 BuildMI(BB, Alpha::PCLABEL, 2).addImm( cast<ConstantSDNode>(N.getOperand(1))->getValue());
1845 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001846 }
1847 assert(0 && "Should not be reached!");
1848}
1849
1850
1851/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
1852/// into a machine code representation using pattern matching and a machine
1853/// description file.
1854///
1855FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
1856 return new ISel(TM);
1857}