blob: 9393b92373d6e97433b45f59d766f18202086f88 [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 Lenharth63f2ab22005-02-10 06:25:22 +0000338};
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000339}
340
Andrew Lenharthe87f6c32005-03-11 17:48:05 +0000341//These describe LDAx
Andrew Lenharthc0513832005-03-29 19:24:04 +0000342static const int IMM_LOW = -32768;
343static const int IMM_HIGH = 32767;
Andrew Lenharthe87f6c32005-03-11 17:48:05 +0000344static const int IMM_MULT = 65536;
345
346static long getUpper16(long l)
347{
348 long y = l / IMM_MULT;
349 if (l % IMM_MULT > IMM_HIGH)
350 ++y;
351 return y;
352}
353
354static long getLower16(long l)
355{
356 long h = getUpper16(l);
357 return l - h * IMM_MULT;
358}
359
Andrew Lenharth65838902005-02-06 16:22:15 +0000360static unsigned GetSymVersion(unsigned opcode)
361{
362 switch (opcode) {
363 default: assert(0 && "unknown load or store"); return 0;
364 case Alpha::LDQ: return Alpha::LDQ_SYM;
365 case Alpha::LDS: return Alpha::LDS_SYM;
366 case Alpha::LDT: return Alpha::LDT_SYM;
367 case Alpha::LDL: return Alpha::LDL_SYM;
368 case Alpha::LDBU: return Alpha::LDBU_SYM;
369 case Alpha::LDWU: return Alpha::LDWU_SYM;
370 case Alpha::LDW: return Alpha::LDW_SYM;
371 case Alpha::LDB: return Alpha::LDB_SYM;
372 case Alpha::STQ: return Alpha::STQ_SYM;
373 case Alpha::STS: return Alpha::STS_SYM;
374 case Alpha::STT: return Alpha::STT_SYM;
375 case Alpha::STL: return Alpha::STL_SYM;
376 case Alpha::STW: return Alpha::STW_SYM;
377 case Alpha::STB: return Alpha::STB_SYM;
378 }
379}
380
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000381void ISel::MoveFP2Int(unsigned src, unsigned dst, bool isDouble)
382{
383 unsigned Opc;
384 if (EnableAlphaFTOI) {
385 Opc = isDouble ? Alpha::FTOIT : Alpha::FTOIS;
386 BuildMI(BB, Opc, 1, dst).addReg(src);
387 } else {
388 //The hard way:
389 // Spill the integer to memory and reload it from there.
390 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
391 MachineFunction *F = BB->getParent();
392 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
393
394 Opc = isDouble ? Alpha::STT : Alpha::STS;
395 BuildMI(BB, Opc, 3).addReg(src).addFrameIndex(FrameIdx).addReg(Alpha::F31);
396 Opc = isDouble ? Alpha::LDQ : Alpha::LDL;
397 BuildMI(BB, Alpha::LDQ, 2, dst).addFrameIndex(FrameIdx).addReg(Alpha::F31);
398 }
399}
400
401void ISel::MoveInt2FP(unsigned src, unsigned dst, bool isDouble)
402{
403 unsigned Opc;
404 if (EnableAlphaFTOI) {
405 Opc = isDouble?Alpha::ITOFT:Alpha::ITOFS;
406 BuildMI(BB, Opc, 1, dst).addReg(src);
407 } else {
408 //The hard way:
409 // Spill the integer to memory and reload it from there.
410 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
411 MachineFunction *F = BB->getParent();
412 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
413
414 Opc = isDouble ? Alpha::STQ : Alpha::STL;
415 BuildMI(BB, Opc, 3).addReg(src).addFrameIndex(FrameIdx).addReg(Alpha::F31);
416 Opc = isDouble ? Alpha::LDT : Alpha::LDS;
417 BuildMI(BB, Opc, 2, dst).addFrameIndex(FrameIdx).addReg(Alpha::F31);
418 }
419}
420
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000421//Check to see if the load is a constant offset from a base register
422void ISel::SelectAddr(SDOperand N, unsigned& Reg, long& offset)
423{
424 unsigned opcode = N.getOpcode();
425 if (opcode == ISD::ADD) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000426 if(N.getOperand(1).getOpcode() == ISD::Constant &&
427 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767)
428 { //Normal imm add
429 Reg = SelectExpr(N.getOperand(0));
430 offset = cast<ConstantSDNode>(N.getOperand(1))->getValue();
431 return;
432 }
433 else if(N.getOperand(0).getOpcode() == ISD::Constant &&
434 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 32767)
435 {
436 Reg = SelectExpr(N.getOperand(1));
437 offset = cast<ConstantSDNode>(N.getOperand(0))->getValue();
438 return;
439 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000440 }
441 Reg = SelectExpr(N);
442 offset = 0;
443 return;
444}
445
Andrew Lenharth445171a2005-02-08 00:40:03 +0000446void ISel::SelectBranchCC(SDOperand N)
447{
448 assert(N.getOpcode() == ISD::BRCOND && "Not a BranchCC???");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000449 MachineBasicBlock *Dest =
450 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
451 unsigned Opc = Alpha::WTF;
452
Andrew Lenharth445171a2005-02-08 00:40:03 +0000453 Select(N.getOperand(0)); //chain
454 SDOperand CC = N.getOperand(1);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000455
Andrew Lenharth445171a2005-02-08 00:40:03 +0000456 if (CC.getOpcode() == ISD::SETCC)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000457 {
458 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
459 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
460 //Dropping the CC is only useful if we are comparing to 0
461 bool isZero0 = false;
462 bool isZero1 = false;
463 bool isNE = false;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000464
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000465 if(SetCC->getOperand(0).getOpcode() == ISD::Constant &&
466 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0)
467 isZero0 = true;
468 if(SetCC->getOperand(1).getOpcode() == ISD::Constant &&
469 cast<ConstantSDNode>(SetCC->getOperand(1))->getValue() == 0)
470 isZero1 = true;
471 if(SetCC->getCondition() == ISD::SETNE)
472 isNE = true;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000473
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000474 if (isZero0) {
Andrew Lenharth445171a2005-02-08 00:40:03 +0000475 switch (SetCC->getCondition()) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000476 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
477 case ISD::SETEQ: Opc = Alpha::BEQ; break;
478 case ISD::SETLT: Opc = Alpha::BGT; break;
479 case ISD::SETLE: Opc = Alpha::BGE; break;
480 case ISD::SETGT: Opc = Alpha::BLT; break;
481 case ISD::SETGE: Opc = Alpha::BLE; break;
482 case ISD::SETULT: Opc = Alpha::BNE; break;
483 case ISD::SETUGT: assert(0 && "0 > (unsigned) x is never true"); break;
484 case ISD::SETULE: assert(0 && "0 <= (unsigned) x is always true"); break;
485 case ISD::SETUGE: Opc = Alpha::BEQ; break; //Technically you could have this CC
486 case ISD::SETNE: Opc = Alpha::BNE; break;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000487 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000488 unsigned Tmp1 = SelectExpr(SetCC->getOperand(1));
489 BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest);
490 return;
491 } else if (isZero1) {
492 switch (SetCC->getCondition()) {
493 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
494 case ISD::SETEQ: Opc = Alpha::BEQ; break;
495 case ISD::SETLT: Opc = Alpha::BLT; break;
496 case ISD::SETLE: Opc = Alpha::BLE; break;
497 case ISD::SETGT: Opc = Alpha::BGT; break;
498 case ISD::SETGE: Opc = Alpha::BGE; break;
499 case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break;
500 case ISD::SETUGT: Opc = Alpha::BNE; break;
501 case ISD::SETULE: Opc = Alpha::BEQ; break; //Technically you could have this CC
502 case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break;
503 case ISD::SETNE: Opc = Alpha::BNE; break;
504 }
505 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
506 BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest);
507 return;
508 } else {
509 unsigned Tmp1 = SelectExpr(CC);
510 if (isNE)
511 BuildMI(BB, Alpha::BEQ, 2).addReg(CCInvMap[CC]).addMBB(Dest);
512 else
513 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000514 return;
515 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000516 } else { //FP
517 //Any comparison between 2 values should be codegened as an folded branch, as moving
518 //CC to the integer register is very expensive
519 //for a cmp b: c = a - b;
520 //a = b: c = 0
521 //a < b: c < 0
522 //a > b: c > 0
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000523
524 bool invTest = false;
525 unsigned Tmp3;
526
527 ConstantFPSDNode *CN;
528 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
529 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
530 Tmp3 = SelectExpr(SetCC->getOperand(0));
531 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
532 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
533 {
534 Tmp3 = SelectExpr(SetCC->getOperand(1));
535 invTest = true;
536 }
537 else
538 {
539 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
540 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
541 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
542 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
543 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
544 .addReg(Tmp1).addReg(Tmp2);
545 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000546
547 switch (SetCC->getCondition()) {
548 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000549 case ISD::SETEQ: Opc = invTest ? Alpha::FBNE : Alpha::FBEQ; break;
550 case ISD::SETLT: Opc = invTest ? Alpha::FBGT : Alpha::FBLT; break;
551 case ISD::SETLE: Opc = invTest ? Alpha::FBGE : Alpha::FBLE; break;
552 case ISD::SETGT: Opc = invTest ? Alpha::FBLT : Alpha::FBGT; break;
553 case ISD::SETGE: Opc = invTest ? Alpha::FBLE : Alpha::FBGE; break;
554 case ISD::SETNE: Opc = invTest ? Alpha::FBEQ : Alpha::FBNE; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000555 }
556 BuildMI(BB, Opc, 2).addReg(Tmp3).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000557 return;
558 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000559 abort(); //Should never be reached
560 } else {
561 //Giveup and do the stupid thing
562 unsigned Tmp1 = SelectExpr(CC);
563 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
564 return;
565 }
Andrew Lenharth445171a2005-02-08 00:40:03 +0000566 abort(); //Should never be reached
567}
568
Andrew Lenharth40831c52005-01-28 06:57:18 +0000569unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
570{
571 unsigned Tmp1, Tmp2, Tmp3;
572 unsigned Opc = 0;
573 SDNode *Node = N.Val;
574 MVT::ValueType DestType = N.getValueType();
575 unsigned opcode = N.getOpcode();
576
577 switch (opcode) {
578 default:
579 Node->dump();
580 assert(0 && "Node not handled!\n");
Andrew Lenharth2c594352005-01-29 15:42:07 +0000581
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000582 case ISD::UNDEF: {
583 BuildMI(BB, Alpha::IDEF, 0, Result);
584 return Result;
585 }
586
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000587 case ISD::FNEG:
588 if(ISD::FABS == N.getOperand(0).getOpcode())
589 {
590 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000591 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000592 } else {
593 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000594 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000595 }
596 return Result;
597
598 case ISD::FABS:
599 Tmp1 = SelectExpr(N.getOperand(0));
600 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
601 return Result;
602
Andrew Lenharth9818c052005-02-05 13:19:12 +0000603 case ISD::SELECT:
604 {
Andrew Lenharth45859692005-03-03 21:47:53 +0000605 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
606 unsigned TV = SelectExpr(N.getOperand(1)); //Use if TRUE
607 unsigned FV = SelectExpr(N.getOperand(2)); //Use if FALSE
608
609 SDOperand CC = N.getOperand(0);
610 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
611
612 if (CC.getOpcode() == ISD::SETCC &&
613 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
614 { //FP Setcc -> Select yay!
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000615
616
Andrew Lenharth45859692005-03-03 21:47:53 +0000617 //for a cmp b: c = a - b;
618 //a = b: c = 0
619 //a < b: c < 0
620 //a > b: c > 0
621
622 bool invTest = false;
623 unsigned Tmp3;
624
625 ConstantFPSDNode *CN;
626 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
627 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
628 Tmp3 = SelectExpr(SetCC->getOperand(0));
629 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
630 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
631 {
632 Tmp3 = SelectExpr(SetCC->getOperand(1));
633 invTest = true;
634 }
635 else
636 {
637 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
638 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
639 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
640 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
641 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
642 .addReg(Tmp1).addReg(Tmp2);
643 }
644
645 switch (SetCC->getCondition()) {
646 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
647 case ISD::SETEQ: Opc = invTest ? Alpha::FCMOVNE : Alpha::FCMOVEQ; break;
648 case ISD::SETLT: Opc = invTest ? Alpha::FCMOVGT : Alpha::FCMOVLT; break;
649 case ISD::SETLE: Opc = invTest ? Alpha::FCMOVGE : Alpha::FCMOVLE; break;
650 case ISD::SETGT: Opc = invTest ? Alpha::FCMOVLT : Alpha::FCMOVGT; break;
651 case ISD::SETGE: Opc = invTest ? Alpha::FCMOVLE : Alpha::FCMOVGE; break;
652 case ISD::SETNE: Opc = invTest ? Alpha::FCMOVEQ : Alpha::FCMOVNE; break;
653 }
Andrew Lenharth33819132005-03-04 20:09:23 +0000654 BuildMI(BB, Opc, 3, Result).addReg(FV).addReg(TV).addReg(Tmp3);
Andrew Lenharth45859692005-03-03 21:47:53 +0000655 return Result;
656 }
657 else
658 {
659 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000660 BuildMI(BB, Alpha::FCMOVEQ_INT, 3, Result).addReg(TV).addReg(FV).addReg(Tmp1);
661// // Spill the cond to memory and reload it from there.
662// unsigned Tmp4 = MakeReg(MVT::f64);
663// MoveIntFP(Tmp1, Tmp4, true);
664// //now ideally, we don't have to do anything to the flag...
665// // Get the condition into the zero flag.
666// BuildMI(BB, Alpha::FCMOVEQ, 3, Result).addReg(TV).addReg(FV).addReg(Tmp4);
Andrew Lenharth45859692005-03-03 21:47:53 +0000667 return Result;
668 }
Andrew Lenharth9818c052005-02-05 13:19:12 +0000669 }
670
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000671 case ISD::FP_ROUND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000672 assert (DestType == MVT::f32 &&
673 N.getOperand(0).getValueType() == MVT::f64 &&
674 "only f64 to f32 conversion supported here");
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000675 Tmp1 = SelectExpr(N.getOperand(0));
676 BuildMI(BB, Alpha::CVTTS, 1, Result).addReg(Tmp1);
677 return Result;
678
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000679 case ISD::FP_EXTEND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000680 assert (DestType == MVT::f64 &&
681 N.getOperand(0).getValueType() == MVT::f32 &&
682 "only f32 to f64 conversion supported here");
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000683 Tmp1 = SelectExpr(N.getOperand(0));
684 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
685 return Result;
686
Andrew Lenharth2c594352005-01-29 15:42:07 +0000687 case ISD::CopyFromReg:
688 {
689 // Make sure we generate both values.
690 if (Result != notIn)
691 ExprMap[N.getValue(1)] = notIn; // Generate the token
692 else
693 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
694
695 SDOperand Chain = N.getOperand(0);
696
697 Select(Chain);
698 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
699 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
700 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(r).addReg(r);
701 return Result;
702 }
703
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000704 case ISD::LOAD:
705 {
706 // Make sure we generate both values.
707 if (Result != notIn)
708 ExprMap[N.getValue(1)] = notIn; // Generate the token
709 else
710 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000711
Andrew Lenharth29219162005-02-07 06:31:44 +0000712 DestType = N.getValue(0).getValueType();
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000713
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000714 SDOperand Chain = N.getOperand(0);
715 SDOperand Address = N.getOperand(1);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000716 Select(Chain);
Andrew Lenharth65838902005-02-06 16:22:15 +0000717 Opc = DestType == MVT::f64 ? Alpha::LDT : Alpha::LDS;
718
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000719 if (Address.getOpcode() == ISD::GlobalAddress) {
720 AlphaLowering.restoreGP(BB);
721 Opc = GetSymVersion(Opc);
722 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
723 }
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000724 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000725 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +0000726 Opc = GetSymVersion(Opc);
Andrew Lenharth97127a12005-02-05 17:41:39 +0000727 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000728 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000729 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000730 BuildMI(BB, Opc, 2, Result)
731 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
732 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000733 } else {
734 long offset;
735 SelectAddr(Address, Tmp1, offset);
736 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
737 }
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000738 return Result;
739 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000740 case ISD::ConstantFP:
741 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
742 if (CN->isExactlyValue(+0.0)) {
743 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000744 } else if ( CN->isExactlyValue(-0.0)) {
745 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000746 } else {
747 abort();
748 }
749 }
750 return Result;
751
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +0000752 case ISD::SDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000753 case ISD::MUL:
754 case ISD::ADD:
755 case ISD::SUB:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000756 switch( opcode ) {
757 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
758 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
759 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
760 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
761 };
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000762
763 ConstantFPSDNode *CN;
764 if (opcode == ISD::SUB
765 && (CN = dyn_cast<ConstantFPSDNode>(N.getOperand(0)))
766 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
767 {
768 Tmp2 = SelectExpr(N.getOperand(1));
769 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp2).addReg(Tmp2);
770 } else {
771 Tmp1 = SelectExpr(N.getOperand(0));
772 Tmp2 = SelectExpr(N.getOperand(1));
773 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
774 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000775 return Result;
776
Andrew Lenharth2c594352005-01-29 15:42:07 +0000777 case ISD::EXTLOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000778 {
779 //include a conversion sequence for float loads to double
780 if (Result != notIn)
781 ExprMap[N.getValue(1)] = notIn; // Generate the token
782 else
783 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
784
Andrew Lenhartha549deb2005-02-07 05:33:15 +0000785 Tmp1 = MakeReg(MVT::f32);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000786
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000787 assert(cast<MVTSDNode>(Node)->getExtraValueType() == MVT::f32 &&
788 "EXTLOAD not from f32");
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000789 assert(Node->getValueType(0) == MVT::f64 && "EXTLOAD not to f64");
790
791 SDOperand Chain = N.getOperand(0);
792 SDOperand Address = N.getOperand(1);
793 Select(Chain);
794
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000795 if (Address.getOpcode() == ISD::GlobalAddress) {
796 AlphaLowering.restoreGP(BB);
797 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
798 }
799 else if (ConstantPoolSDNode *CP =
800 dyn_cast<ConstantPoolSDNode>(N.getOperand(1)))
801 {
802 AlphaLowering.restoreGP(BB);
803 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addConstantPoolIndex(CP->getIndex());
804 }
805 else if(Address.getOpcode() == ISD::FrameIndex) {
806 Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
Andrew Lenharth032f2352005-02-22 21:59:48 +0000807 BuildMI(BB, Alpha::LDS, 2, Tmp1)
808 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
809 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000810 } else {
811 long offset;
812 SelectAddr(Address, Tmp2, offset);
813 BuildMI(BB, Alpha::LDS, 1, Tmp1).addImm(offset).addReg(Tmp2);
814 }
Andrew Lenharth29219162005-02-07 06:31:44 +0000815 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
Andrew Lenharth12dd2622005-02-03 21:01:15 +0000816 return Result;
817 }
Andrew Lenharth2c594352005-01-29 15:42:07 +0000818
Andrew Lenharthe76797c2005-02-01 20:40:27 +0000819 case ISD::UINT_TO_FP:
820 case ISD::SINT_TO_FP:
Andrew Lenharth40831c52005-01-28 06:57:18 +0000821 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000822 assert (N.getOperand(0).getValueType() == MVT::i64
823 && "only quads can be loaded from");
Andrew Lenharth40831c52005-01-28 06:57:18 +0000824 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000825 Tmp2 = MakeReg(MVT::f64);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000826 MoveInt2FP(Tmp1, Tmp2, true);
Andrew Lenharth7efadce2005-01-31 01:44:26 +0000827 Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
828 BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
Andrew Lenharth40831c52005-01-28 06:57:18 +0000829 return Result;
830 }
831 }
832 assert(0 && "should not get here");
833 return 0;
834}
835
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000836unsigned ISel::SelectExpr(SDOperand N) {
837 unsigned Result;
838 unsigned Tmp1, Tmp2, Tmp3;
839 unsigned Opc = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000840 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000841
842 SDNode *Node = N.Val;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000843 MVT::ValueType DestType = N.getValueType();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000844
845 unsigned &Reg = ExprMap[N];
846 if (Reg) return Reg;
847
848 if (N.getOpcode() != ISD::CALL)
849 Reg = Result = (N.getValueType() != MVT::Other) ?
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000850 MakeReg(N.getValueType()) : notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000851 else {
852 // If this is a call instruction, make sure to prepare ALL of the result
853 // values as well as the chain.
854 if (Node->getNumValues() == 1)
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000855 Reg = Result = notIn; // Void call, just a chain.
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000856 else {
857 Result = MakeReg(Node->getValueType(0));
858 ExprMap[N.getValue(0)] = Result;
859 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
860 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +0000861 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000862 }
863 }
864
Andrew Lenharth22088bb2005-02-02 15:05:33 +0000865 if (DestType == MVT::f64 || DestType == MVT::f32 ||
Andrew Lenharth06342c32005-02-07 06:21:37 +0000866 (
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000867 (opcode == ISD::LOAD || opcode == ISD::CopyFromReg ||
868 opcode == ISD::EXTLOAD) &&
869 (N.getValue(0).getValueType() == MVT::f32 ||
870 N.getValue(0).getValueType() == MVT::f64)
Andrew Lenharth06342c32005-02-07 06:21:37 +0000871 )
872 )
Andrew Lenharth40831c52005-01-28 06:57:18 +0000873 return SelectExprFP(N, Result);
874
875 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000876 default:
877 Node->dump();
878 assert(0 && "Node not handled!\n");
879
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000880
881 case ISD::UNDEF: {
882 BuildMI(BB, Alpha::IDEF, 0, Result);
883 return Result;
884 }
885
Andrew Lenharth032f2352005-02-22 21:59:48 +0000886 case ISD::DYNAMIC_STACKALLOC:
887 // Generate both result values.
Andrew Lenharth3a7118d2005-02-23 17:33:42 +0000888 if (Result != notIn)
889 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth032f2352005-02-22 21:59:48 +0000890 else
891 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
892
893 // FIXME: We are currently ignoring the requested alignment for handling
894 // greater than the stack alignment. This will need to be revisited at some
895 // point. Align = N.getOperand(2);
896
897 if (!isa<ConstantSDNode>(N.getOperand(2)) ||
898 cast<ConstantSDNode>(N.getOperand(2))->getValue() != 0) {
899 std::cerr << "Cannot allocate stack object with greater alignment than"
900 << " the stack alignment yet!";
901 abort();
902 }
903
904 Select(N.getOperand(0));
905 if (ConstantSDNode* CN = dyn_cast<ConstantSDNode>(N.getOperand(1)))
906 {
907 if (CN->getValue() < 32000)
908 {
909 BuildMI(BB, Alpha::LDA, 2, Alpha::R30)
910 .addImm(-CN->getValue()).addReg(Alpha::R30);
911 } else {
912 Tmp1 = SelectExpr(N.getOperand(1));
913 // Subtract size from stack pointer, thereby allocating some space.
914 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
915 }
916 } else {
917 Tmp1 = SelectExpr(N.getOperand(1));
918 // Subtract size from stack pointer, thereby allocating some space.
919 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
920 }
921
922 // Put a pointer to the space into the result register, by copying the stack
923 // pointer.
Andrew Lenharth7bc47022005-02-22 23:29:25 +0000924 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R30).addReg(Alpha::R30);
Andrew Lenharth032f2352005-02-22 21:59:48 +0000925 return Result;
926
Andrew Lenharth33819132005-03-04 20:09:23 +0000927// case ISD::ConstantPool:
928// Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
929// AlphaLowering.restoreGP(BB);
930// BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(Tmp1);
931// return Result;
Andrew Lenharth2c594352005-01-29 15:42:07 +0000932
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000933 case ISD::FrameIndex:
Andrew Lenharth032f2352005-02-22 21:59:48 +0000934 BuildMI(BB, Alpha::LDA, 2, Result)
935 .addFrameIndex(cast<FrameIndexSDNode>(N)->getIndex())
936 .addReg(Alpha::F31);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000937 return Result;
938
939 case ISD::EXTLOAD:
Andrew Lenharthf311e8b2005-02-07 05:18:02 +0000940 case ISD::ZEXTLOAD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000941 case ISD::SEXTLOAD:
Andrew Lenhartha549deb2005-02-07 05:33:15 +0000942 case ISD::LOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000943 {
944 // Make sure we generate both values.
945 if (Result != notIn)
946 ExprMap[N.getValue(1)] = notIn; // Generate the token
947 else
948 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000949
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000950 SDOperand Chain = N.getOperand(0);
951 SDOperand Address = N.getOperand(1);
952 Select(Chain);
953
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000954 assert(Node->getValueType(0) == MVT::i64 &&
955 "Unknown type to sign extend to.");
Andrew Lenharth03824012005-02-07 05:55:55 +0000956 if (opcode == ISD::LOAD)
957 Opc = Alpha::LDQ;
958 else
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000959 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
960 default: Node->dump(); assert(0 && "Bad sign extend!");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000961 case MVT::i32: Opc = Alpha::LDL;
962 assert(opcode != ISD::ZEXTLOAD && "Not sext"); break;
963 case MVT::i16: Opc = Alpha::LDWU;
964 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharthf311e8b2005-02-07 05:18:02 +0000965 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000966 case MVT::i8: Opc = Alpha::LDBU;
967 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000968 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000969
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000970 if (Address.getOpcode() == ISD::GlobalAddress) {
971 AlphaLowering.restoreGP(BB);
972 Opc = GetSymVersion(Opc);
973 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
974 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000975 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
976 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +0000977 Opc = GetSymVersion(Opc);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000978 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000979 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000980 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000981 BuildMI(BB, Opc, 2, Result)
982 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
983 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000984 } else {
985 long offset;
986 SelectAddr(Address, Tmp1, offset);
987 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
988 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000989 return Result;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000990 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +0000991
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000992 case ISD::GlobalAddress:
993 AlphaLowering.restoreGP(BB);
994 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
995 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
996 return Result;
997
998 case ISD::CALL:
999 {
1000 Select(N.getOperand(0));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001001
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001002 // The chain for this call is now lowered.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001003 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), notIn));
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001004
1005 //grab the arguments
1006 std::vector<unsigned> argvregs;
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001007 //assert(Node->getNumOperands() < 8 && "Only 6 args supported");
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001008 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001009 argvregs.push_back(SelectExpr(N.getOperand(i)));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001010
Andrew Lenharth684f2292005-01-30 00:35:27 +00001011 //in reg args
1012 for(int i = 0, e = std::min(6, (int)argvregs.size()); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001013 {
1014 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
1015 Alpha::R19, Alpha::R20, Alpha::R21};
1016 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
1017 Alpha::F19, Alpha::F20, Alpha::F21};
1018 switch(N.getOperand(i+2).getValueType()) {
1019 default:
1020 Node->dump();
1021 N.getOperand(i).Val->dump();
1022 std::cerr << "Type for " << i << " is: " <<
1023 N.getOperand(i+2).getValueType() << "\n";
1024 assert(0 && "Unknown value type for call");
1025 case MVT::i1:
1026 case MVT::i8:
1027 case MVT::i16:
1028 case MVT::i32:
1029 case MVT::i64:
1030 BuildMI(BB, Alpha::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
1031 break;
1032 case MVT::f32:
1033 case MVT::f64:
1034 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
1035 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001036 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001037 }
Andrew Lenharth684f2292005-01-30 00:35:27 +00001038 //in mem args
1039 for (int i = 6, e = argvregs.size(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001040 {
1041 switch(N.getOperand(i+2).getValueType()) {
1042 default:
1043 Node->dump();
1044 N.getOperand(i).Val->dump();
1045 std::cerr << "Type for " << i << " is: " <<
1046 N.getOperand(i+2).getValueType() << "\n";
1047 assert(0 && "Unknown value type for call");
1048 case MVT::i1:
1049 case MVT::i8:
1050 case MVT::i16:
1051 case MVT::i32:
1052 case MVT::i64:
1053 BuildMI(BB, Alpha::STQ, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1054 break;
1055 case MVT::f32:
1056 BuildMI(BB, Alpha::STS, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1057 break;
1058 case MVT::f64:
1059 BuildMI(BB, Alpha::STT, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1060 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001061 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001062 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001063 //build the right kind of call
1064 if (GlobalAddressSDNode *GASD =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001065 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001066 {
Andrew Lenharth3e315922005-02-10 20:10:38 +00001067 //if (GASD->getGlobal()->isExternal()) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001068 //use safe calling convention
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001069 AlphaLowering.restoreGP(BB);
1070 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
Andrew Lenharth3e315922005-02-10 20:10:38 +00001071 //} else {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001072 //use PC relative branch call
Andrew Lenharth3e315922005-02-10 20:10:38 +00001073 //BuildMI(BB, Alpha::BSR, 1, Alpha::R26).addGlobalAddress(GASD->getGlobal(),true);
1074 //}
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001075 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001076 else if (ExternalSymbolSDNode *ESSDN =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001077 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001078 {
1079 AlphaLowering.restoreGP(BB);
Andrew Lenharthba05ad62005-03-30 18:22:52 +00001080 BuildMI(BB, Alpha::CALL, 1).addExternalSymbol(ESSDN->getSymbol(), true);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001081 } else {
1082 //no need to restore GP as we are doing an indirect call
1083 Tmp1 = SelectExpr(N.getOperand(1));
1084 BuildMI(BB, Alpha::BIS, 2, Alpha::R27).addReg(Tmp1).addReg(Tmp1);
1085 BuildMI(BB, Alpha::JSR, 2, Alpha::R26).addReg(Alpha::R27).addImm(0);
1086 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001087
1088 //push the result into a virtual register
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001089
1090 switch (Node->getValueType(0)) {
1091 default: Node->dump(); assert(0 && "Unknown value type for call result!");
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001092 case MVT::Other: return notIn;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001093 case MVT::i1:
1094 case MVT::i8:
1095 case MVT::i16:
1096 case MVT::i32:
1097 case MVT::i64:
1098 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
1099 break;
1100 case MVT::f32:
1101 case MVT::f64:
1102 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
1103 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001104 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001105 return Result+N.ResNo;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001106 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001107
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001108 case ISD::SIGN_EXTEND_INREG:
1109 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001110 //do SDIV opt for all levels of ints
Andrew Lenharth5e99dd92005-03-31 22:02:25 +00001111 if (EnableAlphaIDIV && N.getOperand(0).getOpcode() == ISD::SDIV)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001112 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001113 unsigned Tmp4 = MakeReg(MVT::f64);
1114 unsigned Tmp5 = MakeReg(MVT::f64);
1115 unsigned Tmp6 = MakeReg(MVT::f64);
1116 unsigned Tmp7 = MakeReg(MVT::f64);
1117 unsigned Tmp8 = MakeReg(MVT::f64);
1118 unsigned Tmp9 = MakeReg(MVT::f64);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001119
1120 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1121 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1122 MoveInt2FP(Tmp1, Tmp4, true);
1123 MoveInt2FP(Tmp2, Tmp5, true);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001124 BuildMI(BB, Alpha::CVTQT, 1, Tmp6).addReg(Tmp4);
1125 BuildMI(BB, Alpha::CVTQT, 1, Tmp7).addReg(Tmp5);
1126 BuildMI(BB, Alpha::DIVT, 2, Tmp8).addReg(Tmp6).addReg(Tmp7);
1127 BuildMI(BB, Alpha::CVTTQ, 1, Tmp9).addReg(Tmp8);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001128 MoveFP2Int(Tmp9, Result, true);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001129 return Result;
1130 }
1131
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001132 //Alpha has instructions for a bunch of signed 32 bit stuff
1133 if( dyn_cast<MVTSDNode>(Node)->getExtraValueType() == MVT::i32)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001134 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001135 switch (N.getOperand(0).getOpcode()) {
1136 case ISD::ADD:
1137 case ISD::SUB:
1138 case ISD::MUL:
1139 {
1140 bool isAdd = N.getOperand(0).getOpcode() == ISD::ADD;
1141 bool isMul = N.getOperand(0).getOpcode() == ISD::MUL;
1142 //FIXME: first check for Scaled Adds and Subs!
1143 if(N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1144 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() <= 255)
1145 { //Normal imm add/sub
1146 Opc = isAdd ? Alpha::ADDLi : (isMul ? Alpha::MULLi : Alpha::SUBLi);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001147 //if the value was really originally a i32, skip the up conversion
1148 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1149 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1150 ->getExtraValueType() == MVT::i32)
1151 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1152 else
1153 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001154 Tmp2 = cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue();
1155 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001156 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001157 else
1158 { //Normal add/sub
1159 Opc = isAdd ? Alpha::ADDL : (isMul ? Alpha::MULLi : Alpha::SUBL);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001160 //if the value was really originally a i32, skip the up conversion
1161 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1162 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1163 ->getExtraValueType() == MVT::i32)
1164 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1165 else
1166 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1167 //if the value was really originally a i32, skip the up conversion
1168 if (N.getOperand(0).getOperand(1).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1169 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(1).Val)
1170 ->getExtraValueType() == MVT::i32)
1171 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0));
1172 else
1173 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1174
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001175 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1176 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1177 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1178 }
1179 return Result;
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001180 }
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001181 case ISD::SEXTLOAD:
1182 //SelectionDag isn't deleting the signextend after sextloads
1183 Reg = Result = SelectExpr(N.getOperand(0));
1184 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001185 default: break; //Fall Though;
1186 }
1187 } //Every thing else fall though too, including unhandled opcodes above
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001188 Tmp1 = SelectExpr(N.getOperand(0));
1189 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001190 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001191 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001192 {
1193 default:
1194 Node->dump();
1195 assert(0 && "Sign Extend InReg not there yet");
1196 break;
1197 case MVT::i32:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001198 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001199 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001200 break;
1201 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001202 case MVT::i16:
1203 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
1204 break;
1205 case MVT::i8:
1206 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
1207 break;
Andrew Lenharthebce5042005-02-12 19:35:12 +00001208 case MVT::i1:
1209 Tmp2 = MakeReg(MVT::i64);
1210 BuildMI(BB, Alpha::ANDi, 2, Tmp2).addReg(Tmp1).addImm(1);
Andrew Lenharth7536eea2005-02-12 20:42:09 +00001211 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Alpha::F31).addReg(Tmp2);
Andrew Lenharthebce5042005-02-12 19:35:12 +00001212 break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001213 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001214 return Result;
1215 }
1216 case ISD::ZERO_EXTEND_INREG:
1217 {
1218 Tmp1 = SelectExpr(N.getOperand(0));
1219 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001220 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001221 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001222 {
1223 default:
1224 Node->dump();
1225 assert(0 && "Zero Extend InReg not there yet");
1226 break;
1227 case MVT::i32: Tmp2 = 0xf0; break;
1228 case MVT::i16: Tmp2 = 0xfc; break;
1229 case MVT::i8: Tmp2 = 0xfe; break;
1230 case MVT::i1: //handle this one special
1231 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
1232 return Result;
1233 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001234 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001235 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001236 }
1237
1238 case ISD::SETCC:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001239 {
1240 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
1241 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
1242 bool isConst1 = false;
1243 bool isConst2 = false;
1244 int dir;
Andrew Lenharth9818c052005-02-05 13:19:12 +00001245
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001246 //Tmp1 = SelectExpr(N.getOperand(0));
1247 if(N.getOperand(0).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001248 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1249 isConst1 = true;
1250 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001251 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1252 isConst2 = true;
1253
1254 switch (SetCC->getCondition()) {
1255 default: Node->dump(); assert(0 && "Unknown integer comparison!");
1256 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001257 case ISD::SETLT:
1258 Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
1259 case ISD::SETLE:
1260 Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
1261 case ISD::SETGT:
1262 Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
1263 case ISD::SETGE:
1264 Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
1265 case ISD::SETULT:
1266 Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
1267 case ISD::SETUGT:
1268 Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
1269 case ISD::SETULE:
1270 Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
1271 case ISD::SETUGE:
1272 Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001273 case ISD::SETNE: {//Handle this one special
1274 //std::cerr << "Alpha does not have a setne.\n";
1275 //abort();
1276 Tmp1 = SelectExpr(N.getOperand(0));
1277 Tmp2 = SelectExpr(N.getOperand(1));
1278 Tmp3 = MakeReg(MVT::i64);
1279 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth445171a2005-02-08 00:40:03 +00001280 //Remeber we have the Inv for this CC
1281 CCInvMap[N] = Tmp3;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001282 //and invert
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001283 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001284 return Result;
1285 }
1286 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001287 if (dir == 1) {
1288 Tmp1 = SelectExpr(N.getOperand(0));
1289 if (isConst2) {
1290 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1291 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1292 } else {
1293 Tmp2 = SelectExpr(N.getOperand(1));
1294 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1295 }
1296 } else if (dir == 2) {
1297 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001298 if (isConst1) {
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001299 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1300 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1301 } else {
1302 Tmp2 = SelectExpr(N.getOperand(0));
1303 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1304 }
1305 } else { //dir == 0
1306 if (isConst1) {
1307 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1308 Tmp2 = SelectExpr(N.getOperand(1));
1309 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
1310 } else if (isConst2) {
1311 Tmp1 = SelectExpr(N.getOperand(0));
1312 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1313 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
1314 } else {
1315 Tmp1 = SelectExpr(N.getOperand(0));
1316 Tmp2 = SelectExpr(N.getOperand(1));
1317 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
1318 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001319 }
1320 } else {
1321 //assert(SetCC->getOperand(0).getValueType() != MVT::f32 && "SetCC f32 should have been promoted");
1322 bool rev = false;
1323 bool inv = false;
1324
1325 switch (SetCC->getCondition()) {
1326 default: Node->dump(); assert(0 && "Unknown FP comparison!");
1327 case ISD::SETEQ: Opc = Alpha::CMPTEQ; break;
1328 case ISD::SETLT: Opc = Alpha::CMPTLT; break;
1329 case ISD::SETLE: Opc = Alpha::CMPTLE; break;
1330 case ISD::SETGT: Opc = Alpha::CMPTLT; rev = true; break;
1331 case ISD::SETGE: Opc = Alpha::CMPTLE; rev = true; break;
1332 case ISD::SETNE: Opc = Alpha::CMPTEQ; inv = true; break;
1333 }
1334
Andrew Lenharthca3d59b2005-03-14 19:23:45 +00001335 //FIXME: check for constant 0.0
1336 ConstantFPSDNode *CN;
1337 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
1338 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1339 Tmp1 = Alpha::F31;
1340 else
1341 Tmp1 = SelectExpr(N.getOperand(0));
1342
1343 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
1344 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1345 Tmp2 = Alpha::F31;
1346 else
1347 Tmp2 = SelectExpr(N.getOperand(1));
1348
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001349 //Can only compare doubles, and dag won't promote for me
1350 if (SetCC->getOperand(0).getValueType() == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001351 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001352 //assert(0 && "Setcc On float?\n");
1353 std::cerr << "Setcc on float!\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001354 Tmp3 = MakeReg(MVT::f64);
1355 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp1);
1356 Tmp1 = Tmp3;
1357 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001358 if (SetCC->getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001359 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001360 //assert (0 && "Setcc On float?\n");
1361 std::cerr << "Setcc on float!\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001362 Tmp3 = MakeReg(MVT::f64);
1363 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp2);
Andrew Lenharth572af902005-02-14 05:41:43 +00001364 Tmp2 = Tmp3;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001365 }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001366
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001367 if (rev) std::swap(Tmp1, Tmp2);
1368 Tmp3 = MakeReg(MVT::f64);
1369 //do the comparison
1370 BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
1371
1372 //now arrange for Result (int) to have a 1 or 0
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001373 unsigned Tmp4 = MakeReg(MVT::i64);
1374 BuildMI(BB, Alpha::ADDQi, 2, Tmp4).addReg(Alpha::R31).addImm(1);
1375 Opc = inv?Alpha::CMOVNEi_FP:Alpha::CMOVEQi_FP;
1376 BuildMI(BB, Opc, 3, Result).addReg(Tmp4).addImm(0).addReg(Tmp3);
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001377 }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001378 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001379 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001380 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001381
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001382 case ISD::CopyFromReg:
1383 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001384 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001385 if (Result != notIn)
1386 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth40831c52005-01-28 06:57:18 +00001387 else
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001388 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth40831c52005-01-28 06:57:18 +00001389
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001390 SDOperand Chain = N.getOperand(0);
1391
1392 Select(Chain);
1393 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
1394 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
1395 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
1396 return Result;
1397 }
1398
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001399 //Most of the plain arithmetic and logic share the same form, and the same
1400 //constant immediate test
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001401 case ISD::OR:
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001402 //Match Not
1403 if (N.getOperand(1).getOpcode() == ISD::Constant &&
1404 cast<ConstantSDNode>(N.getOperand(1))->isAllOnesValue())
1405 {
1406 Tmp1 = SelectExpr(N.getOperand(0));
1407 BuildMI(BB, Alpha::ORNOT, 2, Result).addReg(Alpha::R31).addReg(Tmp1);
1408 return Result;
1409 }
1410 //Fall through
1411 case ISD::AND:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001412 case ISD::XOR:
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001413 //Check operand(0) == Not
1414 if (N.getOperand(0).getOpcode() == ISD::OR &&
1415 N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1416 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->isAllOnesValue())
1417 {
1418 switch(opcode) {
1419 case ISD::AND: Opc = Alpha::BIC; break;
1420 case ISD::OR: Opc = Alpha::ORNOT; break;
1421 case ISD::XOR: Opc = Alpha::EQV; break;
1422 }
1423 Tmp1 = SelectExpr(N.getOperand(1));
1424 Tmp2 = SelectExpr(N.getOperand(0).getOperand(0));
1425 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1426 return Result;
1427 }
1428 //Check operand(1) == Not
1429 if (N.getOperand(1).getOpcode() == ISD::OR &&
1430 N.getOperand(1).getOperand(1).getOpcode() == ISD::Constant &&
1431 cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->isAllOnesValue())
1432 {
1433 switch(opcode) {
1434 case ISD::AND: Opc = Alpha::BIC; break;
1435 case ISD::OR: Opc = Alpha::ORNOT; break;
1436 case ISD::XOR: Opc = Alpha::EQV; break;
1437 }
1438 Tmp1 = SelectExpr(N.getOperand(0));
1439 Tmp2 = SelectExpr(N.getOperand(1).getOperand(0));
1440 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1441 return Result;
1442 }
1443 //Fall through
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001444 case ISD::SHL:
1445 case ISD::SRL:
Andrew Lenharth2c594352005-01-29 15:42:07 +00001446 case ISD::SRA:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001447 case ISD::MUL:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001448 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
1449 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001450 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001451 {
1452 switch(opcode) {
1453 case ISD::AND: Opc = Alpha::ANDi; break;
1454 case ISD::OR: Opc = Alpha::BISi; break;
1455 case ISD::XOR: Opc = Alpha::XORi; break;
1456 case ISD::SHL: Opc = Alpha::SLi; break;
1457 case ISD::SRL: Opc = Alpha::SRLi; break;
1458 case ISD::SRA: Opc = Alpha::SRAi; break;
1459 case ISD::MUL: Opc = Alpha::MULQi; break;
1460 };
1461 Tmp1 = SelectExpr(N.getOperand(0));
1462 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1463 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1464 } else {
1465 switch(opcode) {
1466 case ISD::AND: Opc = Alpha::AND; break;
1467 case ISD::OR: Opc = Alpha::BIS; break;
1468 case ISD::XOR: Opc = Alpha::XOR; break;
1469 case ISD::SHL: Opc = Alpha::SL; break;
1470 case ISD::SRL: Opc = Alpha::SRL; break;
1471 case ISD::SRA: Opc = Alpha::SRA; break;
1472 case ISD::MUL: Opc = Alpha::MULQ; break;
1473 };
1474 Tmp1 = SelectExpr(N.getOperand(0));
1475 Tmp2 = SelectExpr(N.getOperand(1));
1476 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1477 }
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001478 return Result;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001479
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001480 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001481 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001482 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001483 bool isAdd = opcode == ISD::ADD;
1484
1485 //FIXME: first check for Scaled Adds and Subs!
1486 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001487 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001488 { //Normal imm add/sub
1489 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
1490 Tmp1 = SelectExpr(N.getOperand(0));
1491 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1492 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1493 }
Andrew Lenharth40831c52005-01-28 06:57:18 +00001494 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001495 (cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767 ||
1496 (long)cast<ConstantSDNode>(N.getOperand(1))->getValue() >= -32767))
1497 { //LDA
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001498 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001499 Tmp2 = (long)cast<ConstantSDNode>(N.getOperand(1))->getValue();
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001500 if (!isAdd)
1501 Tmp2 = -Tmp2;
1502 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
1503 } else {
1504 //Normal add/sub
1505 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
1506 Tmp1 = SelectExpr(N.getOperand(0));
1507 Tmp2 = SelectExpr(N.getOperand(1));
1508 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1509 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001510 return Result;
1511 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001512
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001513 case ISD::SDIV:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001514 case ISD::UREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001515 case ISD::SREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001516 case ISD::UDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001517 //FIXME: alpha really doesn't support any of these operations,
1518 // the ops are expanded into special library calls with
1519 // special calling conventions
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001520 //Restore GP because it is a call after all...
Andrew Lenharth40831c52005-01-28 06:57:18 +00001521 switch(opcode) {
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001522 case ISD::UREM: Opc = Alpha::REMQU; break;
1523 case ISD::SREM: Opc = Alpha::REMQ; break;
1524 case ISD::UDIV: Opc = Alpha::DIVQU; break;
1525 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001526 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001527 Tmp1 = SelectExpr(N.getOperand(0));
1528 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth33819132005-03-04 20:09:23 +00001529 //set up regs explicitly (helps Reg alloc)
1530 BuildMI(BB, Alpha::BIS, 2, Alpha::R24).addReg(Tmp1).addReg(Tmp1);
1531 BuildMI(BB, Alpha::BIS, 2, Alpha::R25).addReg(Tmp2).addReg(Tmp2);
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001532 AlphaLowering.restoreGP(BB);
Andrew Lenharth33819132005-03-04 20:09:23 +00001533 BuildMI(BB, Opc, 2).addReg(Alpha::R24).addReg(Alpha::R25);
1534 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R27).addReg(Alpha::R27);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001535 return Result;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001536
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001537 case ISD::FP_TO_UINT:
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001538 case ISD::FP_TO_SINT:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001539 {
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001540 assert (DestType == MVT::i64 && "only quads can be loaded to");
1541 MVT::ValueType SrcType = N.getOperand(0).getValueType();
Andrew Lenharth03824012005-02-07 05:55:55 +00001542 assert (SrcType == MVT::f32 || SrcType == MVT::f64);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001543 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001544 if (SrcType == MVT::f32)
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001545 {
1546 Tmp2 = MakeReg(MVT::f64);
1547 BuildMI(BB, Alpha::CVTST, 1, Tmp2).addReg(Tmp1);
1548 Tmp1 = Tmp2;
1549 }
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001550 Tmp2 = MakeReg(MVT::f64);
1551 BuildMI(BB, Alpha::CVTTQ, 1, Tmp2).addReg(Tmp1);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001552 MoveFP2Int(Tmp2, Result, true);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001553
1554 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001555 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001556
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001557 // // case ISD::FP_TO_UINT:
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001558
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001559 case ISD::SELECT:
1560 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001561 //FIXME: look at parent to decide if intCC can be folded, or if setCC(FP) and can save stack use
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001562 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001563 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1564 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001565 // Get the condition into the zero flag.
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001566 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001567 return Result;
1568 }
1569
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001570 case ISD::Constant:
1571 {
Andrew Lenharthc0513832005-03-29 19:24:04 +00001572 int64_t val = (int64_t)cast<ConstantSDNode>(N)->getValue();
Andrew Lenharthe87f6c32005-03-11 17:48:05 +00001573 if (val <= IMM_HIGH && val >= IMM_LOW) {
1574 BuildMI(BB, Alpha::LDA, 2, Result).addImm(val).addReg(Alpha::R31);
1575 }
1576 else if (val <= (int64_t)IMM_HIGH + (int64_t)IMM_HIGH * (int64_t)IMM_MULT &&
1577 val >= (int64_t)IMM_LOW + (int64_t)IMM_LOW * (int64_t)IMM_MULT) {
1578 Tmp1 = MakeReg(MVT::i64);
1579 BuildMI(BB, Alpha::LDAH, 2, Tmp1).addImm(getUpper16(val)).addReg(Alpha::R31);
1580 BuildMI(BB, Alpha::LDA, 2, Result).addImm(getLower16(val)).addReg(Tmp1);
1581 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001582 else {
1583 MachineConstantPool *CP = BB->getParent()->getConstantPool();
1584 ConstantUInt *C = ConstantUInt::get(Type::getPrimitiveType(Type::ULongTyID) , val);
1585 unsigned CPI = CP->getConstantPoolIndex(C);
1586 AlphaLowering.restoreGP(BB);
1587 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(CPI);
1588 }
1589 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001590 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001591 }
1592
1593 return 0;
1594}
1595
1596void ISel::Select(SDOperand N) {
1597 unsigned Tmp1, Tmp2, Opc;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001598 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001599
Nate Begeman85fdeb22005-03-24 04:39:54 +00001600 if (!ExprMap.insert(std::make_pair(N, notIn)).second)
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001601 return; // Already selected.
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001602
1603 SDNode *Node = N.Val;
Andrew Lenharth760270d2005-02-07 23:02:23 +00001604
Andrew Lenharth760270d2005-02-07 23:02:23 +00001605 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001606
1607 default:
1608 Node->dump(); std::cerr << "\n";
1609 assert(0 && "Node not handled yet!");
1610
1611 case ISD::BRCOND: {
Andrew Lenharth445171a2005-02-08 00:40:03 +00001612 SelectBranchCC(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001613 return;
1614 }
1615
1616 case ISD::BR: {
1617 MachineBasicBlock *Dest =
1618 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
1619
1620 Select(N.getOperand(0));
1621 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
1622 return;
1623 }
1624
1625 case ISD::ImplicitDef:
1626 Select(N.getOperand(0));
1627 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
1628 return;
1629
1630 case ISD::EntryToken: return; // Noop
1631
1632 case ISD::TokenFactor:
1633 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
1634 Select(Node->getOperand(i));
1635
1636 //N.Val->dump(); std::cerr << "\n";
1637 //assert(0 && "Node not handled yet!");
1638
1639 return;
1640
1641 case ISD::CopyToReg:
1642 Select(N.getOperand(0));
1643 Tmp1 = SelectExpr(N.getOperand(1));
1644 Tmp2 = cast<RegSDNode>(N)->getReg();
1645
1646 if (Tmp1 != Tmp2) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001647 if (N.getOperand(1).getValueType() == MVT::f64 ||
1648 N.getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth29219162005-02-07 06:31:44 +00001649 BuildMI(BB, Alpha::CPYS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
1650 else
1651 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001652 }
1653 return;
1654
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001655 case ISD::RET:
1656 switch (N.getNumOperands()) {
1657 default:
1658 std::cerr << N.getNumOperands() << "\n";
1659 for (unsigned i = 0; i < N.getNumOperands(); ++i)
1660 std::cerr << N.getOperand(i).getValueType() << "\n";
1661 Node->dump();
1662 assert(0 && "Unknown return instruction!");
1663 case 2:
1664 Select(N.getOperand(0));
1665 Tmp1 = SelectExpr(N.getOperand(1));
1666 switch (N.getOperand(1).getValueType()) {
1667 default: Node->dump();
1668 assert(0 && "All other types should have been promoted!!");
1669 case MVT::f64:
1670 case MVT::f32:
1671 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
1672 break;
1673 case MVT::i32:
1674 case MVT::i64:
1675 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
1676 break;
1677 }
1678 break;
1679 case 1:
1680 Select(N.getOperand(0));
1681 break;
1682 }
1683 //Tmp2 = AlphaLowering.getRetAddr();
1684 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
1685 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
1686 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001687
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001688 case ISD::TRUNCSTORE:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001689 case ISD::STORE:
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001690 {
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001691 SDOperand Chain = N.getOperand(0);
1692 SDOperand Value = N.getOperand(1);
1693 SDOperand Address = N.getOperand(2);
1694 Select(Chain);
1695
1696 Tmp1 = SelectExpr(Value); //value
Andrew Lenharth760270d2005-02-07 23:02:23 +00001697
1698 if (opcode == ISD::STORE) {
1699 switch(Value.getValueType()) {
1700 default: assert(0 && "unknown Type in store");
1701 case MVT::i64: Opc = Alpha::STQ; break;
1702 case MVT::f64: Opc = Alpha::STT; break;
1703 case MVT::f32: Opc = Alpha::STS; break;
1704 }
1705 } else { //ISD::TRUNCSTORE
1706 switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
1707 default: assert(0 && "unknown Type in store");
1708 case MVT::i1: //FIXME: DAG does not promote this load
1709 case MVT::i8: Opc = Alpha::STB; break;
1710 case MVT::i16: Opc = Alpha::STW; break;
1711 case MVT::i32: Opc = Alpha::STL; break;
1712 }
Andrew Lenharth65838902005-02-06 16:22:15 +00001713 }
Andrew Lenharth760270d2005-02-07 23:02:23 +00001714
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001715 if (Address.getOpcode() == ISD::GlobalAddress)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001716 {
1717 AlphaLowering.restoreGP(BB);
1718 Opc = GetSymVersion(Opc);
1719 BuildMI(BB, Opc, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1720 }
Andrew Lenharth05380342005-02-07 05:07:00 +00001721 else if(Address.getOpcode() == ISD::FrameIndex)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001722 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001723 BuildMI(BB, Opc, 3).addReg(Tmp1)
1724 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1725 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001726 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001727 else
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001728 {
1729 long offset;
1730 SelectAddr(Address, Tmp2, offset);
1731 BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
1732 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00001733 return;
1734 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001735
1736 case ISD::EXTLOAD:
1737 case ISD::SEXTLOAD:
1738 case ISD::ZEXTLOAD:
1739 case ISD::LOAD:
1740 case ISD::CopyFromReg:
1741 case ISD::CALL:
Andrew Lenharth032f2352005-02-22 21:59:48 +00001742 case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001743 ExprMap.erase(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001744 SelectExpr(N);
1745 return;
1746
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001747 case ISD::ADJCALLSTACKDOWN:
1748 case ISD::ADJCALLSTACKUP:
1749 Select(N.getOperand(0));
1750 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1751
1752 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
1753 Alpha::ADJUSTSTACKUP;
1754 BuildMI(BB, Opc, 1).addImm(Tmp1);
1755 return;
Andrew Lenharth95762122005-03-31 21:24:06 +00001756
1757 case ISD::PCMARKER:
1758 Select(N.getOperand(0)); //Chain
1759 BuildMI(BB, Alpha::PCLABEL, 2).addImm( cast<ConstantSDNode>(N.getOperand(1))->getValue());
1760 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001761 }
1762 assert(0 && "Should not be reached!");
1763}
1764
1765
1766/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
1767/// into a machine code representation using pattern matching and a machine
1768/// description file.
1769///
1770FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
1771 return new ISel(TM);
1772}