blob: 787edb91897503f65704f04e3279a84e413e5763 [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);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +000042 cl::opt<bool> EnableAlphaCount("enable-alpha-count",
43 cl::desc("Print estimates on live ins and outs"),
44 cl::Hidden);
Andrew Lenharth95762122005-03-31 21:24:06 +000045}
46
Andrew Lenharth304d0f32005-01-22 23:41:55 +000047//===----------------------------------------------------------------------===//
48// AlphaTargetLowering - Alpha Implementation of the TargetLowering interface
49namespace {
50 class AlphaTargetLowering : public TargetLowering {
51 int VarArgsFrameIndex; // FrameIndex for start of varargs area.
52 unsigned GP; //GOT vreg
53 public:
54 AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) {
55 // Set up the TargetLowering object.
Andrew Lenharth3d65d312005-01-27 03:49:45 +000056 //I am having problems with shr n ubyte 1
Andrew Lenharth879ef222005-02-02 17:00:21 +000057 setShiftAmountType(MVT::i64);
58 setSetCCResultType(MVT::i64);
Andrew Lenharthd3355e22005-04-07 20:11:32 +000059 setSetCCResultContents(ZeroOrOneSetCCResult);
Andrew Lenharth3d65d312005-01-27 03:49:45 +000060
Andrew Lenharth304d0f32005-01-22 23:41:55 +000061 addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass);
62 addRegisterClass(MVT::f64, Alpha::FPRCRegisterClass);
Andrew Lenharth3d65d312005-01-27 03:49:45 +000063 addRegisterClass(MVT::f32, Alpha::FPRCRegisterClass);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000064
Chris Lattnerda4d4692005-04-09 03:22:37 +000065 setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
Andrew Lenharth4b8ac152005-04-06 20:25:34 +000066 setOperationAction(ISD::EXTLOAD , MVT::i1 , Promote);
67 setOperationAction(ISD::EXTLOAD , MVT::f32 , Promote);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000068
Andrew Lenharth4b8ac152005-04-06 20:25:34 +000069 setOperationAction(ISD::ZEXTLOAD , MVT::i1 , Expand);
70 setOperationAction(ISD::ZEXTLOAD , MVT::i32 , Expand);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000071
Andrew Lenharth4b8ac152005-04-06 20:25:34 +000072 setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand);
73 setOperationAction(ISD::SEXTLOAD , MVT::i8 , Expand);
74 setOperationAction(ISD::SEXTLOAD , MVT::i16 , Expand);
Andrew Lenharth304d0f32005-01-22 23:41:55 +000075
Andrew Lenharth4b8ac152005-04-06 20:25:34 +000076 setOperationAction(ISD::SREM , MVT::f32 , Expand);
77 setOperationAction(ISD::SREM , MVT::f64 , Expand);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +000078
Andrew Lenharth4b8ac152005-04-06 20:25:34 +000079 //If this didn't legalize into a div....
80 // setOperationAction(ISD::SREM , MVT::i64, Expand);
81 // setOperationAction(ISD::UREM , MVT::i64, Expand);
82
83 setOperationAction(ISD::MEMMOVE , MVT::Other, Expand);
84 setOperationAction(ISD::MEMSET , MVT::Other, Expand);
85 setOperationAction(ISD::MEMCPY , MVT::Other, Expand);
Andrew Lenharth9818c052005-02-05 13:19:12 +000086
Andrew Lenharth33819132005-03-04 20:09:23 +000087 //Doesn't work yet
Andrew Lenharth4b8ac152005-04-06 20:25:34 +000088 setOperationAction(ISD::SETCC , MVT::f32, Promote);
Andrew Lenharth572af902005-02-14 05:41:43 +000089
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000090 computeRegisterProperties();
Andrew Lenharth304d0f32005-01-22 23:41:55 +000091
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000092 addLegalFPImmediate(+0.0); //F31
93 addLegalFPImmediate(-0.0); //-F31
Andrew Lenharth304d0f32005-01-22 23:41:55 +000094 }
95
96 /// LowerArguments - This hook must be implemented to indicate how we should
97 /// lower the arguments for the specified function, into the specified DAG.
98 virtual std::vector<SDOperand>
99 LowerArguments(Function &F, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000100
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000101 /// LowerCallTo - This hook lowers an abstract call to a function into an
102 /// actual call.
103 virtual std::pair<SDOperand, SDOperand>
Nate Begeman8e21e712005-03-26 01:29:23 +0000104 LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
105 SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000106
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000107 virtual std::pair<SDOperand, SDOperand>
108 LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000109
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000110 virtual std::pair<SDOperand,SDOperand>
111 LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
112 const Type *ArgTy, SelectionDAG &DAG);
113
114 virtual std::pair<SDOperand, SDOperand>
115 LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
116 SelectionDAG &DAG);
117
118 void restoreGP(MachineBasicBlock* BB)
119 {
120 BuildMI(BB, Alpha::BIS, 2, Alpha::R29).addReg(GP).addReg(GP);
121 }
122 };
123}
124
125//http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PY8AC-TET1_html/callCH3.html#BLOCK21
126
127//For now, just use variable size stack frame format
128
129//In a standard call, the first six items are passed in registers $16
130//- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
131//of argument-to-register correspondence.) The remaining items are
132//collected in a memory argument list that is a naturally aligned
133//array of quadwords. In a standard call, this list, if present, must
134//be passed at 0(SP).
135//7 ... n 0(SP) ... (n-7)*8(SP)
136
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000137// //#define FP $15
138// //#define RA $26
139// //#define PV $27
140// //#define GP $29
141// //#define SP $30
142
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000143std::vector<SDOperand>
144AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
145{
146 std::vector<SDOperand> ArgValues;
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000147 std::vector<SDOperand> LS;
148 SDOperand Chain = DAG.getRoot();
149
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000150 // assert(0 && "TODO");
151 MachineFunction &MF = DAG.getMachineFunction();
Andrew Lenharth05380342005-02-07 05:07:00 +0000152 MachineFrameInfo*MFI = MF.getFrameInfo();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000153
154 GP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
155 MachineBasicBlock& BB = MF.front();
156
157 //Handle the return address
158 //BuildMI(&BB, Alpha::IDEF, 0, Alpha::R26);
159
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000160 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
161 Alpha::R19, Alpha::R20, Alpha::R21};
162 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
163 Alpha::F19, Alpha::F20, Alpha::F21};
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000164 int count = 0;
Andrew Lenharth2c9e38c2005-02-06 21:07:31 +0000165
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000166 //Def incoming registers
167 {
168 Function::arg_iterator I = F.arg_begin();
169 Function::arg_iterator E = F.arg_end();
170 for (int i = 0; i < 6; ++i)
171 {
172 if (F.isVarArg()) {
173 BuildMI(&BB, Alpha::IDEF, 0, args_int[i]);
174 BuildMI(&BB, Alpha::IDEF, 0, args_float[i]);
175 } else if (I != E)
176 {
177 if(MVT::isInteger(getValueType(I->getType())))
178 BuildMI(&BB, Alpha::IDEF, 0, args_int[i]);
179 else
180 BuildMI(&BB, Alpha::IDEF, 0, args_float[i]);
181 ++I;
182 }
183 }
184 }
185
186 BuildMI(&BB, Alpha::IDEF, 0, Alpha::R29);
187 BuildMI(&BB, Alpha::BIS, 2, GP).addReg(Alpha::R29).addReg(Alpha::R29);
188
Chris Lattnere4d5c442005-03-15 04:54:21 +0000189 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000190 {
191 SDOperand newroot, argt;
192 if (count < 6) {
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000193 unsigned Vreg;
194 MVT::ValueType VT = getValueType(I->getType());
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000195 switch (getValueType(I->getType())) {
196 default:
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000197 std::cerr << "Unknown Type " << VT << "\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000198 abort();
199 case MVT::f64:
200 case MVT::f32:
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000201 Vreg = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(VT));
202 BuildMI(&BB, Alpha::CPYS, 2, Vreg).addReg(args_float[count]).addReg(args_float[count]);
203 argt = newroot = DAG.getCopyFromReg(Vreg,
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000204 getValueType(I->getType()),
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000205 Chain);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000206 break;
207 case MVT::i1:
208 case MVT::i8:
209 case MVT::i16:
210 case MVT::i32:
211 case MVT::i64:
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000212 Vreg = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
213 BuildMI(&BB, Alpha::BIS, 2, Vreg).addReg(args_int[count]).addReg(args_int[count]);
214 argt = newroot = DAG.getCopyFromReg(Vreg, MVT::i64, Chain);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000215 if (getValueType(I->getType()) != MVT::i64)
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000216 argt = DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()), newroot);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000217 break;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000218 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000219 } else { //more args
220 // Create the frame index object for this incoming parameter...
221 int FI = MFI->CreateFixedObject(8, 8 * (count - 6));
222
223 // Create the SelectionDAG nodes corresponding to a load
224 //from this parameter
225 SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
226 argt = newroot = DAG.getLoad(getValueType(I->getType()),
227 DAG.getEntryNode(), FIN);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000228 }
Andrew Lenharth032f2352005-02-22 21:59:48 +0000229 ++count;
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000230 LS.push_back(newroot.getValue(1));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000231 ArgValues.push_back(argt);
232 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000233
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000234 // If the functions takes variable number of arguments, copy all regs to stack
235 if (F.isVarArg())
236 for (int i = 0; i < 6; ++i)
237 {
238 unsigned Vreg = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
239 BuildMI(&BB, Alpha::BIS, 2, Vreg).addReg(args_int[i]).addReg(args_int[i]);
240 SDOperand argt = DAG.getCopyFromReg(Vreg, MVT::i64, Chain);
241 int FI = MFI->CreateFixedObject(8, -8 * (6 - i));
242 SDOperand SDFI = DAG.getFrameIndex(FI, MVT::i64);
243 LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, argt, SDFI));
244
245 Vreg = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::f64));
246 BuildMI(&BB, Alpha::CPYS, 2, Vreg).addReg(args_float[i]).addReg(args_float[i]);
247 argt = DAG.getCopyFromReg(Vreg, MVT::f64, Chain);
248 FI = MFI->CreateFixedObject(8, - 8 * (12 - i));
249 SDFI = DAG.getFrameIndex(FI, MVT::i64);
250 LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, argt, SDFI));
251 }
252
253 // If the function takes variable number of arguments, make a frame index for
254 // the start of the first arg value... for expansion of llvm.va_start.
255 // if (F.isVarArg())
256 // VarArgsFrameIndex = MFI->CreateFixedObject(4, ArgOffset);
257
258 //Set up a token factor with all the stack traffic
259 DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, LS));
260 //return the arguments
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000261 return ArgValues;
262}
263
264std::pair<SDOperand, SDOperand>
265AlphaTargetLowering::LowerCallTo(SDOperand Chain,
Nate Begeman8e21e712005-03-26 01:29:23 +0000266 const Type *RetTy, bool isVarArg,
267 SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000268 int NumBytes = 0;
Andrew Lenharth684f2292005-01-30 00:35:27 +0000269 if (Args.size() > 6)
270 NumBytes = (Args.size() - 6) * 8;
271
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000272 Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
273 DAG.getConstant(NumBytes, getPointerTy()));
274 std::vector<SDOperand> args_to_use;
275 for (unsigned i = 0, e = Args.size(); i != e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000276 {
277 switch (getValueType(Args[i].second)) {
278 default: assert(0 && "Unexpected ValueType for argument!");
279 case MVT::i1:
280 case MVT::i8:
281 case MVT::i16:
282 case MVT::i32:
283 // Promote the integer to 64 bits. If the input type is signed use a
284 // sign extend, otherwise use a zero extend.
285 if (Args[i].second->isSigned())
286 Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first);
287 else
288 Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first);
289 break;
290 case MVT::i64:
291 case MVT::f64:
292 case MVT::f32:
293 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000294 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000295 args_to_use.push_back(Args[i].first);
296 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000297
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000298 std::vector<MVT::ValueType> RetVals;
299 MVT::ValueType RetTyVT = getValueType(RetTy);
300 if (RetTyVT != MVT::isVoid)
301 RetVals.push_back(RetTyVT);
302 RetVals.push_back(MVT::Other);
303
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000304 SDOperand TheCall = SDOperand(DAG.getCall(RetVals,
305 Chain, Callee, args_to_use), 0);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000306 Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
307 Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
308 DAG.getConstant(NumBytes, getPointerTy()));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000309 return std::make_pair(TheCall, Chain);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000310}
311
312std::pair<SDOperand, SDOperand>
313AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
314 //vastart just returns the address of the VarArgsFrameIndex slot.
315 return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain);
316}
317
318std::pair<SDOperand,SDOperand> AlphaTargetLowering::
319LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000320 const Type *ArgTy, SelectionDAG &DAG) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000321 abort();
322}
323
324
325std::pair<SDOperand, SDOperand> AlphaTargetLowering::
326LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
327 SelectionDAG &DAG) {
328 abort();
329}
330
331
332
333
334
335namespace {
336
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000337//===--------------------------------------------------------------------===//
338/// ISel - Alpha specific code to select Alpha machine instructions for
339/// SelectionDAG operations.
340//===--------------------------------------------------------------------===//
341class ISel : public SelectionDAGISel {
342
343 /// AlphaLowering - This object fully describes how to lower LLVM code to an
344 /// Alpha-specific SelectionDAG.
345 AlphaTargetLowering AlphaLowering;
346
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000347 SelectionDAG *ISelDAG; // Hack to support us having a dag->dag transform
348 // for sdiv and udiv until it is put into the future
349 // dag combiner.
350
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000351 /// ExprMap - As shared expressions are codegen'd, we keep track of which
352 /// vreg the value is produced in, so we only emit one copy of each compiled
353 /// tree.
354 static const unsigned notIn = (unsigned)(-1);
355 std::map<SDOperand, unsigned> ExprMap;
356
357 //CCInvMap sometimes (SetNE) we have the inverse CC code for free
358 std::map<SDOperand, unsigned> CCInvMap;
359
Andrew Lenhartha32b9e32005-04-08 17:28:49 +0000360 int count_ins;
361 int count_outs;
362 bool has_sym;
363
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000364public:
365 ISel(TargetMachine &TM) : SelectionDAGISel(AlphaLowering), AlphaLowering(TM)
366 {}
367
368 /// InstructionSelectBasicBlock - This callback is invoked by
369 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
370 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000371 DEBUG(BB->dump());
Andrew Lenhartha32b9e32005-04-08 17:28:49 +0000372 count_ins = 0;
373 count_outs = 0;
374 has_sym = false;
375
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000376 // Codegen the basic block.
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000377 ISelDAG = &DAG;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000378 Select(DAG.getRoot());
Andrew Lenhartha32b9e32005-04-08 17:28:49 +0000379
380 if(has_sym)
381 ++count_ins;
382 if(EnableAlphaCount)
383 std::cerr << "COUNT: " << BB->getParent()->getFunction ()->getName() << " "
384 << BB->getNumber() << " "
385 << count_ins << " "
386 << count_outs << "\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000387
388 // Clear state used for selection.
389 ExprMap.clear();
390 CCInvMap.clear();
391 }
392
393 unsigned SelectExpr(SDOperand N);
394 unsigned SelectExprFP(SDOperand N, unsigned Result);
395 void Select(SDOperand N);
396
397 void SelectAddr(SDOperand N, unsigned& Reg, long& offset);
398 void SelectBranchCC(SDOperand N);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000399 void MoveFP2Int(unsigned src, unsigned dst, bool isDouble);
400 void MoveInt2FP(unsigned src, unsigned dst, bool isDouble);
Andrew Lenharth10c085b2005-04-02 22:32:39 +0000401 //returns whether the sense of the comparison was inverted
402 bool SelectFPSetCC(SDOperand N, unsigned dst);
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000403
404 // dag -> dag expanders for integer divide by constant
405 SDOperand BuildSDIVSequence(SDOperand N);
406 SDOperand BuildUDIVSequence(SDOperand N);
407
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000408};
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000409}
410
Andrew Lenhartha32b9e32005-04-08 17:28:49 +0000411//Factorize a number using the list of constants
412static bool factorize(int v[], int res[], int size, uint64_t c)
413{
414 bool cont = true;
415 while (c != 1 && cont)
416 {
417 cont = false;
418 for(int i = 0; i < size; ++i)
419 {
420 if (c % v[i] == 0)
421 {
422 c /= v[i];
423 ++res[i];
424 cont=true;
425 }
426 }
427 }
428 return c == 1;
429}
430
431
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000432//Shamelessly adapted from PPC32
433// Structure used to return the necessary information to codegen an SDIV as
434// a multiply.
435struct ms {
436 int64_t m; // magic number
437 int64_t s; // shift amount
438};
439
440struct mu {
441 uint64_t m; // magic number
442 int64_t a; // add indicator
443 int64_t s; // shift amount
444};
445
446/// magic - calculate the magic numbers required to codegen an integer sdiv as
447/// a sequence of multiply and shifts. Requires that the divisor not be 0, 1,
448/// or -1.
449static struct ms magic(int64_t d) {
450 int64_t p;
451 uint64_t ad, anc, delta, q1, r1, q2, r2, t;
452 const uint64_t two63 = 9223372036854775808ULL; // 2^63
453 struct ms mag;
454
455 ad = abs(d);
456 t = two63 + ((uint64_t)d >> 63);
457 anc = t - 1 - t%ad; // absolute value of nc
Andrew Lenharth320174f2005-04-07 17:19:16 +0000458 p = 63; // initialize p
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000459 q1 = two63/anc; // initialize q1 = 2p/abs(nc)
460 r1 = two63 - q1*anc; // initialize r1 = rem(2p,abs(nc))
461 q2 = two63/ad; // initialize q2 = 2p/abs(d)
462 r2 = two63 - q2*ad; // initialize r2 = rem(2p,abs(d))
463 do {
464 p = p + 1;
465 q1 = 2*q1; // update q1 = 2p/abs(nc)
466 r1 = 2*r1; // update r1 = rem(2p/abs(nc))
467 if (r1 >= anc) { // must be unsigned comparison
468 q1 = q1 + 1;
469 r1 = r1 - anc;
470 }
471 q2 = 2*q2; // update q2 = 2p/abs(d)
472 r2 = 2*r2; // update r2 = rem(2p/abs(d))
473 if (r2 >= ad) { // must be unsigned comparison
474 q2 = q2 + 1;
475 r2 = r2 - ad;
476 }
477 delta = ad - r2;
478 } while (q1 < delta || (q1 == delta && r1 == 0));
479
480 mag.m = q2 + 1;
481 if (d < 0) mag.m = -mag.m; // resulting magic number
482 mag.s = p - 64; // resulting shift
483 return mag;
484}
485
486/// magicu - calculate the magic numbers required to codegen an integer udiv as
487/// a sequence of multiply, add and shifts. Requires that the divisor not be 0.
488static struct mu magicu(uint64_t d)
489{
490 int64_t p;
491 uint64_t nc, delta, q1, r1, q2, r2;
492 struct mu magu;
493 magu.a = 0; // initialize "add" indicator
494 nc = - 1 - (-d)%d;
Andrew Lenharth320174f2005-04-07 17:19:16 +0000495 p = 63; // initialize p
496 q1 = 0x8000000000000000ull/nc; // initialize q1 = 2p/nc
497 r1 = 0x8000000000000000ull - q1*nc; // initialize r1 = rem(2p,nc)
498 q2 = 0x7FFFFFFFFFFFFFFFull/d; // initialize q2 = (2p-1)/d
499 r2 = 0x7FFFFFFFFFFFFFFFull - q2*d; // initialize r2 = rem((2p-1),d)
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000500 do {
501 p = p + 1;
502 if (r1 >= nc - r1 ) {
503 q1 = 2*q1 + 1; // update q1
504 r1 = 2*r1 - nc; // update r1
505 }
506 else {
507 q1 = 2*q1; // update q1
508 r1 = 2*r1; // update r1
509 }
510 if (r2 + 1 >= d - r2) {
Andrew Lenharth320174f2005-04-07 17:19:16 +0000511 if (q2 >= 0x7FFFFFFFFFFFFFFFull) magu.a = 1;
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000512 q2 = 2*q2 + 1; // update q2
513 r2 = 2*r2 + 1 - d; // update r2
514 }
515 else {
Andrew Lenharth320174f2005-04-07 17:19:16 +0000516 if (q2 >= 0x8000000000000000ull) magu.a = 1;
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000517 q2 = 2*q2; // update q2
518 r2 = 2*r2 + 1; // update r2
519 }
520 delta = d - 1 - r2;
521 } while (p < 64 && (q1 < delta || (q1 == delta && r1 == 0)));
522 magu.m = q2 + 1; // resulting magic number
Andrew Lenharth320174f2005-04-07 17:19:16 +0000523 magu.s = p - 64; // resulting shift
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000524 return magu;
525}
526
527/// BuildSDIVSequence - Given an ISD::SDIV node expressing a divide by constant,
528/// return a DAG expression to select that will generate the same value by
529/// multiplying by a magic number. See:
530/// <http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html>
531SDOperand ISel::BuildSDIVSequence(SDOperand N) {
Andrew Lenharth320174f2005-04-07 17:19:16 +0000532 int64_t d = (int64_t)cast<ConstantSDNode>(N.getOperand(1))->getSignExtended();
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000533 ms magics = magic(d);
534 // Multiply the numerator (operand 0) by the magic value
535 SDOperand Q = ISelDAG->getNode(ISD::MULHS, MVT::i64, N.getOperand(0),
536 ISelDAG->getConstant(magics.m, MVT::i64));
537 // If d > 0 and m < 0, add the numerator
538 if (d > 0 && magics.m < 0)
539 Q = ISelDAG->getNode(ISD::ADD, MVT::i64, Q, N.getOperand(0));
540 // If d < 0 and m > 0, subtract the numerator.
541 if (d < 0 && magics.m > 0)
542 Q = ISelDAG->getNode(ISD::SUB, MVT::i64, Q, N.getOperand(0));
543 // Shift right algebraic if shift value is nonzero
544 if (magics.s > 0)
545 Q = ISelDAG->getNode(ISD::SRA, MVT::i64, Q,
546 ISelDAG->getConstant(magics.s, MVT::i64));
547 // Extract the sign bit and add it to the quotient
548 SDOperand T =
549 ISelDAG->getNode(ISD::SRL, MVT::i64, Q, ISelDAG->getConstant(63, MVT::i64));
550 return ISelDAG->getNode(ISD::ADD, MVT::i64, Q, T);
551}
552
553/// BuildUDIVSequence - Given an ISD::UDIV node expressing a divide by constant,
554/// return a DAG expression to select that will generate the same value by
555/// multiplying by a magic number. See:
556/// <http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html>
557SDOperand ISel::BuildUDIVSequence(SDOperand N) {
558 unsigned d =
559 (unsigned)cast<ConstantSDNode>(N.getOperand(1))->getSignExtended();
560 mu magics = magicu(d);
561 // Multiply the numerator (operand 0) by the magic value
562 SDOperand Q = ISelDAG->getNode(ISD::MULHU, MVT::i64, N.getOperand(0),
563 ISelDAG->getConstant(magics.m, MVT::i64));
564 if (magics.a == 0) {
565 Q = ISelDAG->getNode(ISD::SRL, MVT::i64, Q,
566 ISelDAG->getConstant(magics.s, MVT::i64));
567 } else {
568 SDOperand NPQ = ISelDAG->getNode(ISD::SUB, MVT::i64, N.getOperand(0), Q);
569 NPQ = ISelDAG->getNode(ISD::SRL, MVT::i64, NPQ,
570 ISelDAG->getConstant(1, MVT::i64));
571 NPQ = ISelDAG->getNode(ISD::ADD, MVT::i64, NPQ, Q);
572 Q = ISelDAG->getNode(ISD::SRL, MVT::i64, NPQ,
573 ISelDAG->getConstant(magics.s-1, MVT::i64));
574 }
575 return Q;
576}
577
Andrew Lenhartha565c272005-04-06 22:03:13 +0000578//From PPC32
579/// ExactLog2 - This function solves for (Val == 1 << (N-1)) and returns N. It
580/// returns zero when the input is not exactly a power of two.
581static unsigned ExactLog2(uint64_t Val) {
582 if (Val == 0 || (Val & (Val-1))) return 0;
583 unsigned Count = 0;
584 while (Val != 1) {
585 Val >>= 1;
586 ++Count;
587 }
588 return Count;
589}
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000590
591
Andrew Lenharthe87f6c32005-03-11 17:48:05 +0000592//These describe LDAx
Andrew Lenharthc0513832005-03-29 19:24:04 +0000593static const int IMM_LOW = -32768;
594static const int IMM_HIGH = 32767;
Andrew Lenharthe87f6c32005-03-11 17:48:05 +0000595static const int IMM_MULT = 65536;
596
597static long getUpper16(long l)
598{
599 long y = l / IMM_MULT;
600 if (l % IMM_MULT > IMM_HIGH)
601 ++y;
602 return y;
603}
604
605static long getLower16(long l)
606{
607 long h = getUpper16(l);
608 return l - h * IMM_MULT;
609}
610
Andrew Lenharth65838902005-02-06 16:22:15 +0000611static unsigned GetSymVersion(unsigned opcode)
612{
613 switch (opcode) {
614 default: assert(0 && "unknown load or store"); return 0;
615 case Alpha::LDQ: return Alpha::LDQ_SYM;
616 case Alpha::LDS: return Alpha::LDS_SYM;
617 case Alpha::LDT: return Alpha::LDT_SYM;
618 case Alpha::LDL: return Alpha::LDL_SYM;
619 case Alpha::LDBU: return Alpha::LDBU_SYM;
620 case Alpha::LDWU: return Alpha::LDWU_SYM;
621 case Alpha::LDW: return Alpha::LDW_SYM;
622 case Alpha::LDB: return Alpha::LDB_SYM;
623 case Alpha::STQ: return Alpha::STQ_SYM;
624 case Alpha::STS: return Alpha::STS_SYM;
625 case Alpha::STT: return Alpha::STT_SYM;
626 case Alpha::STL: return Alpha::STL_SYM;
627 case Alpha::STW: return Alpha::STW_SYM;
628 case Alpha::STB: return Alpha::STB_SYM;
629 }
630}
631
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000632void ISel::MoveFP2Int(unsigned src, unsigned dst, bool isDouble)
633{
634 unsigned Opc;
635 if (EnableAlphaFTOI) {
636 Opc = isDouble ? Alpha::FTOIT : Alpha::FTOIS;
637 BuildMI(BB, Opc, 1, dst).addReg(src);
638 } else {
639 //The hard way:
640 // Spill the integer to memory and reload it from there.
641 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
642 MachineFunction *F = BB->getParent();
643 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
644
645 Opc = isDouble ? Alpha::STT : Alpha::STS;
646 BuildMI(BB, Opc, 3).addReg(src).addFrameIndex(FrameIdx).addReg(Alpha::F31);
647 Opc = isDouble ? Alpha::LDQ : Alpha::LDL;
648 BuildMI(BB, Alpha::LDQ, 2, dst).addFrameIndex(FrameIdx).addReg(Alpha::F31);
649 }
650}
651
652void ISel::MoveInt2FP(unsigned src, unsigned dst, bool isDouble)
653{
654 unsigned Opc;
655 if (EnableAlphaFTOI) {
656 Opc = isDouble?Alpha::ITOFT:Alpha::ITOFS;
657 BuildMI(BB, Opc, 1, dst).addReg(src);
658 } else {
659 //The hard way:
660 // Spill the integer to memory and reload it from there.
661 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
662 MachineFunction *F = BB->getParent();
663 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
664
665 Opc = isDouble ? Alpha::STQ : Alpha::STL;
666 BuildMI(BB, Opc, 3).addReg(src).addFrameIndex(FrameIdx).addReg(Alpha::F31);
667 Opc = isDouble ? Alpha::LDT : Alpha::LDS;
668 BuildMI(BB, Opc, 2, dst).addFrameIndex(FrameIdx).addReg(Alpha::F31);
669 }
670}
671
Andrew Lenharth10c085b2005-04-02 22:32:39 +0000672bool ISel::SelectFPSetCC(SDOperand N, unsigned dst)
673{
674 SDNode *Node = N.Val;
675 unsigned Opc, Tmp1, Tmp2, Tmp3;
676 SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node);
677
678 //assert(SetCC->getOperand(0).getValueType() != MVT::f32 && "SetCC f32 should have been promoted");
679 bool rev = false;
680 bool inv = false;
681
682 switch (SetCC->getCondition()) {
683 default: Node->dump(); assert(0 && "Unknown FP comparison!");
684 case ISD::SETEQ: Opc = Alpha::CMPTEQ; break;
685 case ISD::SETLT: Opc = Alpha::CMPTLT; break;
686 case ISD::SETLE: Opc = Alpha::CMPTLE; break;
687 case ISD::SETGT: Opc = Alpha::CMPTLT; rev = true; break;
688 case ISD::SETGE: Opc = Alpha::CMPTLE; rev = true; break;
689 case ISD::SETNE: Opc = Alpha::CMPTEQ; inv = true; break;
690 }
691
692 //FIXME: check for constant 0.0
693 ConstantFPSDNode *CN;
694 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
695 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
696 Tmp1 = Alpha::F31;
697 else
698 Tmp1 = SelectExpr(N.getOperand(0));
699
700 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
701 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
702 Tmp2 = Alpha::F31;
703 else
704 Tmp2 = SelectExpr(N.getOperand(1));
705
706 //Can only compare doubles, and dag won't promote for me
707 if (SetCC->getOperand(0).getValueType() == MVT::f32)
708 {
709 //assert(0 && "Setcc On float?\n");
710 std::cerr << "Setcc on float!\n";
711 Tmp3 = MakeReg(MVT::f64);
712 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp1);
713 Tmp1 = Tmp3;
714 }
715 if (SetCC->getOperand(1).getValueType() == MVT::f32)
716 {
717 //assert (0 && "Setcc On float?\n");
718 std::cerr << "Setcc on float!\n";
719 Tmp3 = MakeReg(MVT::f64);
720 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp2);
721 Tmp2 = Tmp3;
722 }
723
724 if (rev) std::swap(Tmp1, Tmp2);
725 //do the comparison
726 BuildMI(BB, Opc, 2, dst).addReg(Tmp1).addReg(Tmp2);
727 return inv;
728}
729
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000730//Check to see if the load is a constant offset from a base register
731void ISel::SelectAddr(SDOperand N, unsigned& Reg, long& offset)
732{
733 unsigned opcode = N.getOpcode();
734 if (opcode == ISD::ADD) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000735 if(N.getOperand(1).getOpcode() == ISD::Constant &&
736 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767)
737 { //Normal imm add
738 Reg = SelectExpr(N.getOperand(0));
739 offset = cast<ConstantSDNode>(N.getOperand(1))->getValue();
740 return;
741 }
742 else if(N.getOperand(0).getOpcode() == ISD::Constant &&
743 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 32767)
744 {
745 Reg = SelectExpr(N.getOperand(1));
746 offset = cast<ConstantSDNode>(N.getOperand(0))->getValue();
747 return;
748 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000749 }
750 Reg = SelectExpr(N);
751 offset = 0;
752 return;
753}
754
Andrew Lenharth445171a2005-02-08 00:40:03 +0000755void ISel::SelectBranchCC(SDOperand N)
756{
757 assert(N.getOpcode() == ISD::BRCOND && "Not a BranchCC???");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000758 MachineBasicBlock *Dest =
759 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
760 unsigned Opc = Alpha::WTF;
761
Andrew Lenharth445171a2005-02-08 00:40:03 +0000762 Select(N.getOperand(0)); //chain
763 SDOperand CC = N.getOperand(1);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000764
Andrew Lenharth445171a2005-02-08 00:40:03 +0000765 if (CC.getOpcode() == ISD::SETCC)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000766 {
767 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
768 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
769 //Dropping the CC is only useful if we are comparing to 0
Andrew Lenharth63b720a2005-04-03 20:35:21 +0000770 bool LeftZero = SetCC->getOperand(0).getOpcode() == ISD::Constant &&
771 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0;
772 bool RightZero = SetCC->getOperand(0).getOpcode() == ISD::Constant &&
773 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000774 bool isNE = false;
Andrew Lenharth63b720a2005-04-03 20:35:21 +0000775
776 //Fix up CC
777 ISD::CondCode cCode= SetCC->getCondition();
778 if (LeftZero && !RightZero) //Swap Operands
779 cCode = ISD::getSetCCSwappedOperands(cCode);
780
781 if(cCode == ISD::SETNE)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000782 isNE = true;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000783
Andrew Lenharth63b720a2005-04-03 20:35:21 +0000784 if (LeftZero || RightZero) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000785 switch (SetCC->getCondition()) {
786 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
787 case ISD::SETEQ: Opc = Alpha::BEQ; break;
788 case ISD::SETLT: Opc = Alpha::BLT; break;
789 case ISD::SETLE: Opc = Alpha::BLE; break;
790 case ISD::SETGT: Opc = Alpha::BGT; break;
791 case ISD::SETGE: Opc = Alpha::BGE; break;
792 case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break;
793 case ISD::SETUGT: Opc = Alpha::BNE; break;
794 case ISD::SETULE: Opc = Alpha::BEQ; break; //Technically you could have this CC
795 case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break;
796 case ISD::SETNE: Opc = Alpha::BNE; break;
797 }
Andrew Lenharth63b720a2005-04-03 20:35:21 +0000798 unsigned Tmp1;
799 if(LeftZero && !RightZero) //swap Operands
800 Tmp1 = SelectExpr(SetCC->getOperand(1)); //Cond
801 else
802 Tmp1 = SelectExpr(SetCC->getOperand(0)); //Cond
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000803 BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest);
804 return;
805 } else {
806 unsigned Tmp1 = SelectExpr(CC);
807 if (isNE)
808 BuildMI(BB, Alpha::BEQ, 2).addReg(CCInvMap[CC]).addMBB(Dest);
809 else
810 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000811 return;
812 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000813 } else { //FP
814 //Any comparison between 2 values should be codegened as an folded branch, as moving
815 //CC to the integer register is very expensive
816 //for a cmp b: c = a - b;
817 //a = b: c = 0
818 //a < b: c < 0
819 //a > b: c > 0
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000820
821 bool invTest = false;
822 unsigned Tmp3;
823
824 ConstantFPSDNode *CN;
825 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
826 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
827 Tmp3 = SelectExpr(SetCC->getOperand(0));
828 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
829 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
830 {
831 Tmp3 = SelectExpr(SetCC->getOperand(1));
832 invTest = true;
833 }
834 else
835 {
836 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
837 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
838 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
839 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
840 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
841 .addReg(Tmp1).addReg(Tmp2);
842 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000843
844 switch (SetCC->getCondition()) {
845 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000846 case ISD::SETEQ: Opc = invTest ? Alpha::FBNE : Alpha::FBEQ; break;
847 case ISD::SETLT: Opc = invTest ? Alpha::FBGT : Alpha::FBLT; break;
848 case ISD::SETLE: Opc = invTest ? Alpha::FBGE : Alpha::FBLE; break;
849 case ISD::SETGT: Opc = invTest ? Alpha::FBLT : Alpha::FBGT; break;
850 case ISD::SETGE: Opc = invTest ? Alpha::FBLE : Alpha::FBGE; break;
851 case ISD::SETNE: Opc = invTest ? Alpha::FBEQ : Alpha::FBNE; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000852 }
853 BuildMI(BB, Opc, 2).addReg(Tmp3).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000854 return;
855 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000856 abort(); //Should never be reached
857 } else {
858 //Giveup and do the stupid thing
859 unsigned Tmp1 = SelectExpr(CC);
860 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
861 return;
862 }
Andrew Lenharth445171a2005-02-08 00:40:03 +0000863 abort(); //Should never be reached
864}
865
Andrew Lenharth40831c52005-01-28 06:57:18 +0000866unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
867{
868 unsigned Tmp1, Tmp2, Tmp3;
869 unsigned Opc = 0;
870 SDNode *Node = N.Val;
871 MVT::ValueType DestType = N.getValueType();
872 unsigned opcode = N.getOpcode();
873
874 switch (opcode) {
875 default:
876 Node->dump();
877 assert(0 && "Node not handled!\n");
Andrew Lenharth2c594352005-01-29 15:42:07 +0000878
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000879 case ISD::UNDEF: {
880 BuildMI(BB, Alpha::IDEF, 0, Result);
881 return Result;
882 }
883
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000884 case ISD::FNEG:
885 if(ISD::FABS == N.getOperand(0).getOpcode())
886 {
887 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000888 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000889 } else {
890 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000891 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000892 }
893 return Result;
894
895 case ISD::FABS:
896 Tmp1 = SelectExpr(N.getOperand(0));
897 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
898 return Result;
899
Andrew Lenharth9818c052005-02-05 13:19:12 +0000900 case ISD::SELECT:
901 {
Andrew Lenharth45859692005-03-03 21:47:53 +0000902 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
903 unsigned TV = SelectExpr(N.getOperand(1)); //Use if TRUE
904 unsigned FV = SelectExpr(N.getOperand(2)); //Use if FALSE
905
906 SDOperand CC = N.getOperand(0);
907 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
908
909 if (CC.getOpcode() == ISD::SETCC &&
910 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
911 { //FP Setcc -> Select yay!
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000912
913
Andrew Lenharth45859692005-03-03 21:47:53 +0000914 //for a cmp b: c = a - b;
915 //a = b: c = 0
916 //a < b: c < 0
917 //a > b: c > 0
918
919 bool invTest = false;
920 unsigned Tmp3;
921
922 ConstantFPSDNode *CN;
923 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
924 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
925 Tmp3 = SelectExpr(SetCC->getOperand(0));
926 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
927 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
928 {
929 Tmp3 = SelectExpr(SetCC->getOperand(1));
930 invTest = true;
931 }
932 else
933 {
934 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
935 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
936 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
937 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
938 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
939 .addReg(Tmp1).addReg(Tmp2);
940 }
941
942 switch (SetCC->getCondition()) {
943 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
944 case ISD::SETEQ: Opc = invTest ? Alpha::FCMOVNE : Alpha::FCMOVEQ; break;
945 case ISD::SETLT: Opc = invTest ? Alpha::FCMOVGT : Alpha::FCMOVLT; break;
946 case ISD::SETLE: Opc = invTest ? Alpha::FCMOVGE : Alpha::FCMOVLE; break;
947 case ISD::SETGT: Opc = invTest ? Alpha::FCMOVLT : Alpha::FCMOVGT; break;
948 case ISD::SETGE: Opc = invTest ? Alpha::FCMOVLE : Alpha::FCMOVGE; break;
949 case ISD::SETNE: Opc = invTest ? Alpha::FCMOVEQ : Alpha::FCMOVNE; break;
950 }
Andrew Lenharth33819132005-03-04 20:09:23 +0000951 BuildMI(BB, Opc, 3, Result).addReg(FV).addReg(TV).addReg(Tmp3);
Andrew Lenharth45859692005-03-03 21:47:53 +0000952 return Result;
953 }
954 else
955 {
956 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000957 BuildMI(BB, Alpha::FCMOVEQ_INT, 3, Result).addReg(TV).addReg(FV).addReg(Tmp1);
958// // Spill the cond to memory and reload it from there.
959// unsigned Tmp4 = MakeReg(MVT::f64);
960// MoveIntFP(Tmp1, Tmp4, true);
961// //now ideally, we don't have to do anything to the flag...
962// // Get the condition into the zero flag.
963// BuildMI(BB, Alpha::FCMOVEQ, 3, Result).addReg(TV).addReg(FV).addReg(Tmp4);
Andrew Lenharth45859692005-03-03 21:47:53 +0000964 return Result;
965 }
Andrew Lenharth9818c052005-02-05 13:19:12 +0000966 }
967
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000968 case ISD::FP_ROUND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000969 assert (DestType == MVT::f32 &&
970 N.getOperand(0).getValueType() == MVT::f64 &&
971 "only f64 to f32 conversion supported here");
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000972 Tmp1 = SelectExpr(N.getOperand(0));
973 BuildMI(BB, Alpha::CVTTS, 1, Result).addReg(Tmp1);
974 return Result;
975
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000976 case ISD::FP_EXTEND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000977 assert (DestType == MVT::f64 &&
978 N.getOperand(0).getValueType() == MVT::f32 &&
979 "only f32 to f64 conversion supported here");
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000980 Tmp1 = SelectExpr(N.getOperand(0));
981 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
982 return Result;
983
Andrew Lenharth2c594352005-01-29 15:42:07 +0000984 case ISD::CopyFromReg:
985 {
986 // Make sure we generate both values.
987 if (Result != notIn)
988 ExprMap[N.getValue(1)] = notIn; // Generate the token
989 else
990 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
991
992 SDOperand Chain = N.getOperand(0);
993
994 Select(Chain);
995 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
996 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
997 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(r).addReg(r);
998 return Result;
999 }
1000
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001001 case ISD::LOAD:
1002 {
1003 // Make sure we generate both values.
1004 if (Result != notIn)
1005 ExprMap[N.getValue(1)] = notIn; // Generate the token
1006 else
1007 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth12dd2622005-02-03 21:01:15 +00001008
Andrew Lenharth29219162005-02-07 06:31:44 +00001009 DestType = N.getValue(0).getValueType();
Andrew Lenharth12dd2622005-02-03 21:01:15 +00001010
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001011 SDOperand Chain = N.getOperand(0);
1012 SDOperand Address = N.getOperand(1);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001013 Select(Chain);
Andrew Lenharth65838902005-02-06 16:22:15 +00001014 Opc = DestType == MVT::f64 ? Alpha::LDT : Alpha::LDS;
1015
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001016 if (Address.getOpcode() == ISD::GlobalAddress) {
1017 AlphaLowering.restoreGP(BB);
1018 Opc = GetSymVersion(Opc);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001019 has_sym = true;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001020 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1021 }
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001022 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001023 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +00001024 Opc = GetSymVersion(Opc);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001025 has_sym = true;
Andrew Lenharth97127a12005-02-05 17:41:39 +00001026 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001027 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001028 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001029 BuildMI(BB, Opc, 2, Result)
1030 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1031 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001032 } else {
1033 long offset;
1034 SelectAddr(Address, Tmp1, offset);
1035 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
1036 }
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001037 return Result;
1038 }
Andrew Lenharth40831c52005-01-28 06:57:18 +00001039 case ISD::ConstantFP:
1040 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
1041 if (CN->isExactlyValue(+0.0)) {
1042 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth12dd2622005-02-03 21:01:15 +00001043 } else if ( CN->isExactlyValue(-0.0)) {
1044 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth40831c52005-01-28 06:57:18 +00001045 } else {
1046 abort();
1047 }
1048 }
1049 return Result;
1050
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001051 case ISD::SDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001052 case ISD::MUL:
1053 case ISD::ADD:
1054 case ISD::SUB:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001055 switch( opcode ) {
1056 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
1057 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
1058 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
1059 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
1060 };
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001061
1062 ConstantFPSDNode *CN;
1063 if (opcode == ISD::SUB
1064 && (CN = dyn_cast<ConstantFPSDNode>(N.getOperand(0)))
1065 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1066 {
1067 Tmp2 = SelectExpr(N.getOperand(1));
1068 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp2).addReg(Tmp2);
1069 } else {
1070 Tmp1 = SelectExpr(N.getOperand(0));
1071 Tmp2 = SelectExpr(N.getOperand(1));
1072 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1073 }
Andrew Lenharth40831c52005-01-28 06:57:18 +00001074 return Result;
1075
Andrew Lenharth2c594352005-01-29 15:42:07 +00001076 case ISD::EXTLOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001077 {
1078 //include a conversion sequence for float loads to double
1079 if (Result != notIn)
1080 ExprMap[N.getValue(1)] = notIn; // Generate the token
1081 else
1082 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
1083
Andrew Lenhartha549deb2005-02-07 05:33:15 +00001084 Tmp1 = MakeReg(MVT::f32);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001085
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001086 assert(cast<MVTSDNode>(Node)->getExtraValueType() == MVT::f32 &&
1087 "EXTLOAD not from f32");
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001088 assert(Node->getValueType(0) == MVT::f64 && "EXTLOAD not to f64");
1089
1090 SDOperand Chain = N.getOperand(0);
1091 SDOperand Address = N.getOperand(1);
1092 Select(Chain);
1093
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001094 if (Address.getOpcode() == ISD::GlobalAddress) {
1095 AlphaLowering.restoreGP(BB);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001096 has_sym = true;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001097 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1098 }
1099 else if (ConstantPoolSDNode *CP =
1100 dyn_cast<ConstantPoolSDNode>(N.getOperand(1)))
1101 {
1102 AlphaLowering.restoreGP(BB);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001103 has_sym = true;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001104 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addConstantPoolIndex(CP->getIndex());
1105 }
1106 else if(Address.getOpcode() == ISD::FrameIndex) {
1107 Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
Andrew Lenharth032f2352005-02-22 21:59:48 +00001108 BuildMI(BB, Alpha::LDS, 2, Tmp1)
1109 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1110 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001111 } else {
1112 long offset;
1113 SelectAddr(Address, Tmp2, offset);
1114 BuildMI(BB, Alpha::LDS, 1, Tmp1).addImm(offset).addReg(Tmp2);
1115 }
Andrew Lenharth29219162005-02-07 06:31:44 +00001116 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
Andrew Lenharth12dd2622005-02-03 21:01:15 +00001117 return Result;
1118 }
Andrew Lenharth2c594352005-01-29 15:42:07 +00001119
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001120 case ISD::UINT_TO_FP:
1121 case ISD::SINT_TO_FP:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001122 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001123 assert (N.getOperand(0).getValueType() == MVT::i64
1124 && "only quads can be loaded from");
Andrew Lenharth40831c52005-01-28 06:57:18 +00001125 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001126 Tmp2 = MakeReg(MVT::f64);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001127 MoveInt2FP(Tmp1, Tmp2, true);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001128 Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
1129 BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
Andrew Lenharth40831c52005-01-28 06:57:18 +00001130 return Result;
1131 }
1132 }
1133 assert(0 && "should not get here");
1134 return 0;
1135}
1136
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001137unsigned ISel::SelectExpr(SDOperand N) {
1138 unsigned Result;
Andrew Lenharth2966e842005-04-07 18:15:28 +00001139 unsigned Tmp1, Tmp2 = 0, Tmp3;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001140 unsigned Opc = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001141 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001142
1143 SDNode *Node = N.Val;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001144 MVT::ValueType DestType = N.getValueType();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001145
1146 unsigned &Reg = ExprMap[N];
1147 if (Reg) return Reg;
1148
1149 if (N.getOpcode() != ISD::CALL)
1150 Reg = Result = (N.getValueType() != MVT::Other) ?
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001151 MakeReg(N.getValueType()) : notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001152 else {
1153 // If this is a call instruction, make sure to prepare ALL of the result
1154 // values as well as the chain.
1155 if (Node->getNumValues() == 1)
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001156 Reg = Result = notIn; // Void call, just a chain.
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001157 else {
1158 Result = MakeReg(Node->getValueType(0));
1159 ExprMap[N.getValue(0)] = Result;
1160 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
1161 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001162 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001163 }
1164 }
1165
Andrew Lenharth22088bb2005-02-02 15:05:33 +00001166 if (DestType == MVT::f64 || DestType == MVT::f32 ||
Andrew Lenharth06342c32005-02-07 06:21:37 +00001167 (
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001168 (opcode == ISD::LOAD || opcode == ISD::CopyFromReg ||
1169 opcode == ISD::EXTLOAD) &&
1170 (N.getValue(0).getValueType() == MVT::f32 ||
1171 N.getValue(0).getValueType() == MVT::f64)
Andrew Lenharth06342c32005-02-07 06:21:37 +00001172 )
1173 )
Andrew Lenharth40831c52005-01-28 06:57:18 +00001174 return SelectExprFP(N, Result);
1175
1176 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001177 default:
1178 Node->dump();
1179 assert(0 && "Node not handled!\n");
1180
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001181 case ISD::MULHU:
1182 Tmp1 = SelectExpr(N.getOperand(0));
1183 Tmp2 = SelectExpr(N.getOperand(1));
1184 BuildMI(BB, Alpha::UMULH, 2, Result).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth706be912005-04-07 13:55:53 +00001185 return Result;
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001186 case ISD::MULHS:
1187 {
1188 //MULHU - Ra<63>*Rb - Rb<63>*Ra
1189 Tmp1 = SelectExpr(N.getOperand(0));
1190 Tmp2 = SelectExpr(N.getOperand(1));
1191 Tmp3 = MakeReg(MVT::i64);
1192 BuildMI(BB, Alpha::UMULH, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
1193 unsigned V1 = MakeReg(MVT::i64);
1194 unsigned V2 = MakeReg(MVT::i64);
1195 BuildMI(BB, Alpha::CMOVGE, 3, V1).addReg(Tmp2).addReg(Alpha::R31).addReg(Tmp1);
1196 BuildMI(BB, Alpha::CMOVGE, 3, V2).addReg(Tmp1).addReg(Alpha::R31).addReg(Tmp2);
1197 unsigned IRes = MakeReg(MVT::i64);
1198 BuildMI(BB, Alpha::SUBQ, 2, IRes).addReg(Tmp3).addReg(V1);
1199 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(IRes).addReg(V2);
1200 return Result;
1201 }
Andrew Lenharth7332f3e2005-04-02 19:11:07 +00001202 case ISD::UNDEF: {
1203 BuildMI(BB, Alpha::IDEF, 0, Result);
1204 return Result;
1205 }
1206
Andrew Lenharth032f2352005-02-22 21:59:48 +00001207 case ISD::DYNAMIC_STACKALLOC:
1208 // Generate both result values.
Andrew Lenharth3a7118d2005-02-23 17:33:42 +00001209 if (Result != notIn)
1210 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth032f2352005-02-22 21:59:48 +00001211 else
1212 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
1213
1214 // FIXME: We are currently ignoring the requested alignment for handling
1215 // greater than the stack alignment. This will need to be revisited at some
1216 // point. Align = N.getOperand(2);
1217
1218 if (!isa<ConstantSDNode>(N.getOperand(2)) ||
1219 cast<ConstantSDNode>(N.getOperand(2))->getValue() != 0) {
1220 std::cerr << "Cannot allocate stack object with greater alignment than"
1221 << " the stack alignment yet!";
1222 abort();
1223 }
1224
1225 Select(N.getOperand(0));
1226 if (ConstantSDNode* CN = dyn_cast<ConstantSDNode>(N.getOperand(1)))
1227 {
1228 if (CN->getValue() < 32000)
1229 {
1230 BuildMI(BB, Alpha::LDA, 2, Alpha::R30)
1231 .addImm(-CN->getValue()).addReg(Alpha::R30);
1232 } else {
1233 Tmp1 = SelectExpr(N.getOperand(1));
1234 // Subtract size from stack pointer, thereby allocating some space.
1235 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
1236 }
1237 } else {
1238 Tmp1 = SelectExpr(N.getOperand(1));
1239 // Subtract size from stack pointer, thereby allocating some space.
1240 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
1241 }
1242
1243 // Put a pointer to the space into the result register, by copying the stack
1244 // pointer.
Andrew Lenharth7bc47022005-02-22 23:29:25 +00001245 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R30).addReg(Alpha::R30);
Andrew Lenharth032f2352005-02-22 21:59:48 +00001246 return Result;
1247
Andrew Lenharth33819132005-03-04 20:09:23 +00001248// case ISD::ConstantPool:
1249// Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
1250// AlphaLowering.restoreGP(BB);
1251// BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(Tmp1);
1252// return Result;
Andrew Lenharth2c594352005-01-29 15:42:07 +00001253
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001254 case ISD::FrameIndex:
Andrew Lenharth032f2352005-02-22 21:59:48 +00001255 BuildMI(BB, Alpha::LDA, 2, Result)
1256 .addFrameIndex(cast<FrameIndexSDNode>(N)->getIndex())
1257 .addReg(Alpha::F31);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001258 return Result;
1259
1260 case ISD::EXTLOAD:
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001261 case ISD::ZEXTLOAD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001262 case ISD::SEXTLOAD:
Andrew Lenhartha549deb2005-02-07 05:33:15 +00001263 case ISD::LOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001264 {
1265 // Make sure we generate both values.
1266 if (Result != notIn)
1267 ExprMap[N.getValue(1)] = notIn; // Generate the token
1268 else
1269 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001270
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001271 SDOperand Chain = N.getOperand(0);
1272 SDOperand Address = N.getOperand(1);
1273 Select(Chain);
1274
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001275 assert(Node->getValueType(0) == MVT::i64 &&
1276 "Unknown type to sign extend to.");
Andrew Lenharth03824012005-02-07 05:55:55 +00001277 if (opcode == ISD::LOAD)
1278 Opc = Alpha::LDQ;
1279 else
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001280 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
1281 default: Node->dump(); assert(0 && "Bad sign extend!");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001282 case MVT::i32: Opc = Alpha::LDL;
1283 assert(opcode != ISD::ZEXTLOAD && "Not sext"); break;
1284 case MVT::i16: Opc = Alpha::LDWU;
1285 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001286 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001287 case MVT::i8: Opc = Alpha::LDBU;
1288 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001289 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001290
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001291 if (Address.getOpcode() == ISD::GlobalAddress) {
1292 AlphaLowering.restoreGP(BB);
1293 Opc = GetSymVersion(Opc);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001294 has_sym = true;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001295 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1296 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001297 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
1298 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +00001299 Opc = GetSymVersion(Opc);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001300 has_sym = true;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001301 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001302 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001303 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001304 BuildMI(BB, Opc, 2, Result)
1305 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1306 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001307 } else {
1308 long offset;
1309 SelectAddr(Address, Tmp1, offset);
1310 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
1311 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001312 return Result;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001313 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001314
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001315 case ISD::GlobalAddress:
1316 AlphaLowering.restoreGP(BB);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001317 has_sym = true;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001318 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
1319 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
1320 return Result;
1321
1322 case ISD::CALL:
1323 {
1324 Select(N.getOperand(0));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001325
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001326 // The chain for this call is now lowered.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001327 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), notIn));
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001328
1329 //grab the arguments
1330 std::vector<unsigned> argvregs;
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001331 //assert(Node->getNumOperands() < 8 && "Only 6 args supported");
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001332 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001333 argvregs.push_back(SelectExpr(N.getOperand(i)));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001334
Andrew Lenharth684f2292005-01-30 00:35:27 +00001335 //in reg args
1336 for(int i = 0, e = std::min(6, (int)argvregs.size()); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001337 {
1338 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
1339 Alpha::R19, Alpha::R20, Alpha::R21};
1340 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
1341 Alpha::F19, Alpha::F20, Alpha::F21};
1342 switch(N.getOperand(i+2).getValueType()) {
1343 default:
1344 Node->dump();
1345 N.getOperand(i).Val->dump();
1346 std::cerr << "Type for " << i << " is: " <<
1347 N.getOperand(i+2).getValueType() << "\n";
1348 assert(0 && "Unknown value type for call");
1349 case MVT::i1:
1350 case MVT::i8:
1351 case MVT::i16:
1352 case MVT::i32:
1353 case MVT::i64:
1354 BuildMI(BB, Alpha::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
1355 break;
1356 case MVT::f32:
1357 case MVT::f64:
1358 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
1359 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001360 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001361 }
Andrew Lenharth684f2292005-01-30 00:35:27 +00001362 //in mem args
1363 for (int i = 6, e = argvregs.size(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001364 {
1365 switch(N.getOperand(i+2).getValueType()) {
1366 default:
1367 Node->dump();
1368 N.getOperand(i).Val->dump();
1369 std::cerr << "Type for " << i << " is: " <<
1370 N.getOperand(i+2).getValueType() << "\n";
1371 assert(0 && "Unknown value type for call");
1372 case MVT::i1:
1373 case MVT::i8:
1374 case MVT::i16:
1375 case MVT::i32:
1376 case MVT::i64:
1377 BuildMI(BB, Alpha::STQ, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1378 break;
1379 case MVT::f32:
1380 BuildMI(BB, Alpha::STS, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1381 break;
1382 case MVT::f64:
1383 BuildMI(BB, Alpha::STT, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1384 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001385 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001386 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001387 //build the right kind of call
1388 if (GlobalAddressSDNode *GASD =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001389 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001390 {
Andrew Lenharth3e315922005-02-10 20:10:38 +00001391 //if (GASD->getGlobal()->isExternal()) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001392 //use safe calling convention
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001393 AlphaLowering.restoreGP(BB);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001394 has_sym = true;
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001395 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
Andrew Lenharth3e315922005-02-10 20:10:38 +00001396 //} else {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001397 //use PC relative branch call
Andrew Lenharth3e315922005-02-10 20:10:38 +00001398 //BuildMI(BB, Alpha::BSR, 1, Alpha::R26).addGlobalAddress(GASD->getGlobal(),true);
1399 //}
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001400 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001401 else if (ExternalSymbolSDNode *ESSDN =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001402 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001403 {
1404 AlphaLowering.restoreGP(BB);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001405 has_sym = true;
Andrew Lenharthba05ad62005-03-30 18:22:52 +00001406 BuildMI(BB, Alpha::CALL, 1).addExternalSymbol(ESSDN->getSymbol(), true);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001407 } else {
1408 //no need to restore GP as we are doing an indirect call
1409 Tmp1 = SelectExpr(N.getOperand(1));
1410 BuildMI(BB, Alpha::BIS, 2, Alpha::R27).addReg(Tmp1).addReg(Tmp1);
1411 BuildMI(BB, Alpha::JSR, 2, Alpha::R26).addReg(Alpha::R27).addImm(0);
1412 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001413
1414 //push the result into a virtual register
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001415
1416 switch (Node->getValueType(0)) {
1417 default: Node->dump(); assert(0 && "Unknown value type for call result!");
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001418 case MVT::Other: return notIn;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001419 case MVT::i1:
1420 case MVT::i8:
1421 case MVT::i16:
1422 case MVT::i32:
1423 case MVT::i64:
1424 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
1425 break;
1426 case MVT::f32:
1427 case MVT::f64:
1428 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
1429 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001430 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001431 return Result+N.ResNo;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001432 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001433
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001434 case ISD::SIGN_EXTEND_INREG:
1435 {
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001436 //do SDIV opt for all levels of ints if not dividing by a constant
1437 if (EnableAlphaIDIV && N.getOperand(0).getOpcode() == ISD::SDIV
1438 && N.getOperand(0).getOperand(1).getOpcode() != ISD::Constant)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001439 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001440 unsigned Tmp4 = MakeReg(MVT::f64);
1441 unsigned Tmp5 = MakeReg(MVT::f64);
1442 unsigned Tmp6 = MakeReg(MVT::f64);
1443 unsigned Tmp7 = MakeReg(MVT::f64);
1444 unsigned Tmp8 = MakeReg(MVT::f64);
1445 unsigned Tmp9 = MakeReg(MVT::f64);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001446
1447 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1448 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1449 MoveInt2FP(Tmp1, Tmp4, true);
1450 MoveInt2FP(Tmp2, Tmp5, true);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001451 BuildMI(BB, Alpha::CVTQT, 1, Tmp6).addReg(Tmp4);
1452 BuildMI(BB, Alpha::CVTQT, 1, Tmp7).addReg(Tmp5);
1453 BuildMI(BB, Alpha::DIVT, 2, Tmp8).addReg(Tmp6).addReg(Tmp7);
1454 BuildMI(BB, Alpha::CVTTQ, 1, Tmp9).addReg(Tmp8);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001455 MoveFP2Int(Tmp9, Result, true);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001456 return Result;
1457 }
1458
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001459 //Alpha has instructions for a bunch of signed 32 bit stuff
1460 if( dyn_cast<MVTSDNode>(Node)->getExtraValueType() == MVT::i32)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001461 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001462 switch (N.getOperand(0).getOpcode()) {
1463 case ISD::ADD:
1464 case ISD::SUB:
1465 case ISD::MUL:
1466 {
1467 bool isAdd = N.getOperand(0).getOpcode() == ISD::ADD;
1468 bool isMul = N.getOperand(0).getOpcode() == ISD::MUL;
1469 //FIXME: first check for Scaled Adds and Subs!
1470 if(N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1471 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() <= 255)
1472 { //Normal imm add/sub
1473 Opc = isAdd ? Alpha::ADDLi : (isMul ? Alpha::MULLi : Alpha::SUBLi);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001474 //if the value was really originally a i32, skip the up conversion
1475 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1476 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1477 ->getExtraValueType() == MVT::i32)
1478 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1479 else
1480 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001481 Tmp2 = cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue();
1482 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001483 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001484 else
1485 { //Normal add/sub
1486 Opc = isAdd ? Alpha::ADDL : (isMul ? Alpha::MULLi : Alpha::SUBL);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001487 //if the value was really originally a i32, skip the up conversion
1488 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1489 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1490 ->getExtraValueType() == MVT::i32)
1491 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1492 else
1493 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1494 //if the value was really originally a i32, skip the up conversion
1495 if (N.getOperand(0).getOperand(1).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1496 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(1).Val)
1497 ->getExtraValueType() == MVT::i32)
1498 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0));
1499 else
1500 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1501
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001502 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001503 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1504 }
1505 return Result;
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001506 }
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001507 case ISD::SEXTLOAD:
1508 //SelectionDag isn't deleting the signextend after sextloads
1509 Reg = Result = SelectExpr(N.getOperand(0));
1510 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001511 default: break; //Fall Though;
1512 }
1513 } //Every thing else fall though too, including unhandled opcodes above
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001514 Tmp1 = SelectExpr(N.getOperand(0));
1515 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001516 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001517 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001518 {
1519 default:
1520 Node->dump();
1521 assert(0 && "Sign Extend InReg not there yet");
1522 break;
1523 case MVT::i32:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001524 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001525 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001526 break;
1527 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001528 case MVT::i16:
1529 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
1530 break;
1531 case MVT::i8:
1532 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
1533 break;
Andrew Lenharthebce5042005-02-12 19:35:12 +00001534 case MVT::i1:
1535 Tmp2 = MakeReg(MVT::i64);
1536 BuildMI(BB, Alpha::ANDi, 2, Tmp2).addReg(Tmp1).addImm(1);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001537 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Alpha::R31).addReg(Tmp2);
Andrew Lenharthebce5042005-02-12 19:35:12 +00001538 break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001539 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001540 return Result;
1541 }
1542 case ISD::ZERO_EXTEND_INREG:
1543 {
1544 Tmp1 = SelectExpr(N.getOperand(0));
1545 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001546 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001547 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001548 {
1549 default:
1550 Node->dump();
1551 assert(0 && "Zero Extend InReg not there yet");
1552 break;
1553 case MVT::i32: Tmp2 = 0xf0; break;
1554 case MVT::i16: Tmp2 = 0xfc; break;
1555 case MVT::i8: Tmp2 = 0xfe; break;
1556 case MVT::i1: //handle this one special
1557 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
1558 return Result;
1559 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001560 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001561 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001562 }
1563
1564 case ISD::SETCC:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001565 {
1566 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
1567 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
1568 bool isConst1 = false;
1569 bool isConst2 = false;
1570 int dir;
Andrew Lenharth9818c052005-02-05 13:19:12 +00001571
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001572 //Tmp1 = SelectExpr(N.getOperand(0));
1573 if(N.getOperand(0).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001574 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1575 isConst1 = true;
1576 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001577 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1578 isConst2 = true;
1579
1580 switch (SetCC->getCondition()) {
1581 default: Node->dump(); assert(0 && "Unknown integer comparison!");
1582 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001583 case ISD::SETLT:
1584 Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
1585 case ISD::SETLE:
1586 Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
1587 case ISD::SETGT:
1588 Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
1589 case ISD::SETGE:
1590 Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
1591 case ISD::SETULT:
1592 Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
1593 case ISD::SETUGT:
1594 Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
1595 case ISD::SETULE:
1596 Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
1597 case ISD::SETUGE:
1598 Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001599 case ISD::SETNE: {//Handle this one special
1600 //std::cerr << "Alpha does not have a setne.\n";
1601 //abort();
1602 Tmp1 = SelectExpr(N.getOperand(0));
1603 Tmp2 = SelectExpr(N.getOperand(1));
1604 Tmp3 = MakeReg(MVT::i64);
1605 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth445171a2005-02-08 00:40:03 +00001606 //Remeber we have the Inv for this CC
1607 CCInvMap[N] = Tmp3;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001608 //and invert
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001609 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001610 return Result;
1611 }
1612 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001613 if (dir == 1) {
1614 Tmp1 = SelectExpr(N.getOperand(0));
1615 if (isConst2) {
1616 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1617 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1618 } else {
1619 Tmp2 = SelectExpr(N.getOperand(1));
1620 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1621 }
1622 } else if (dir == 2) {
1623 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001624 if (isConst1) {
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001625 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1626 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1627 } else {
1628 Tmp2 = SelectExpr(N.getOperand(0));
1629 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1630 }
1631 } else { //dir == 0
1632 if (isConst1) {
1633 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1634 Tmp2 = SelectExpr(N.getOperand(1));
1635 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
1636 } else if (isConst2) {
1637 Tmp1 = SelectExpr(N.getOperand(0));
1638 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1639 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
1640 } else {
1641 Tmp1 = SelectExpr(N.getOperand(0));
1642 Tmp2 = SelectExpr(N.getOperand(1));
1643 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
1644 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001645 }
1646 } else {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001647 //do the comparison
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001648 Tmp1 = MakeReg(MVT::f64);
1649 bool inv = SelectFPSetCC(N, Tmp1);
1650
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001651 //now arrange for Result (int) to have a 1 or 0
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001652 Tmp2 = MakeReg(MVT::i64);
1653 BuildMI(BB, Alpha::ADDQi, 2, Tmp2).addReg(Alpha::R31).addImm(1);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001654 Opc = inv?Alpha::CMOVNEi_FP:Alpha::CMOVEQi_FP;
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001655 BuildMI(BB, Opc, 3, Result).addReg(Tmp2).addImm(0).addReg(Tmp1);
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001656 }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001657 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001658 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001659 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001660
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001661 case ISD::CopyFromReg:
1662 {
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001663 ++count_ins;
1664
Andrew Lenharth40831c52005-01-28 06:57:18 +00001665 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001666 if (Result != notIn)
1667 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth40831c52005-01-28 06:57:18 +00001668 else
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001669 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth40831c52005-01-28 06:57:18 +00001670
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001671 SDOperand Chain = N.getOperand(0);
1672
1673 Select(Chain);
1674 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
1675 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
1676 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
1677 return Result;
1678 }
1679
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001680 //Most of the plain arithmetic and logic share the same form, and the same
1681 //constant immediate test
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001682 case ISD::XOR:
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001683 //Match Not
1684 if (N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001685 cast<ConstantSDNode>(N.getOperand(1))->getSignExtended() == -1)
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001686 {
1687 Tmp1 = SelectExpr(N.getOperand(0));
1688 BuildMI(BB, Alpha::ORNOT, 2, Result).addReg(Alpha::R31).addReg(Tmp1);
1689 return Result;
1690 }
1691 //Fall through
1692 case ISD::AND:
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001693 case ISD::OR:
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001694 //Check operand(0) == Not
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001695 if (N.getOperand(0).getOpcode() == ISD::XOR &&
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001696 N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001697 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getSignExtended() == -1)
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001698 {
1699 switch(opcode) {
1700 case ISD::AND: Opc = Alpha::BIC; break;
1701 case ISD::OR: Opc = Alpha::ORNOT; break;
1702 case ISD::XOR: Opc = Alpha::EQV; break;
1703 }
1704 Tmp1 = SelectExpr(N.getOperand(1));
1705 Tmp2 = SelectExpr(N.getOperand(0).getOperand(0));
1706 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1707 return Result;
1708 }
1709 //Check operand(1) == Not
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001710 if (N.getOperand(1).getOpcode() == ISD::XOR &&
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001711 N.getOperand(1).getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001712 cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->getSignExtended() == -1)
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001713 {
1714 switch(opcode) {
1715 case ISD::AND: Opc = Alpha::BIC; break;
1716 case ISD::OR: Opc = Alpha::ORNOT; break;
1717 case ISD::XOR: Opc = Alpha::EQV; break;
1718 }
1719 Tmp1 = SelectExpr(N.getOperand(0));
1720 Tmp2 = SelectExpr(N.getOperand(1).getOperand(0));
1721 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1722 return Result;
1723 }
1724 //Fall through
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001725 case ISD::SHL:
1726 case ISD::SRL:
Andrew Lenharth2c594352005-01-29 15:42:07 +00001727 case ISD::SRA:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001728 case ISD::MUL:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001729 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
1730 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001731 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001732 {
1733 switch(opcode) {
1734 case ISD::AND: Opc = Alpha::ANDi; break;
1735 case ISD::OR: Opc = Alpha::BISi; break;
1736 case ISD::XOR: Opc = Alpha::XORi; break;
1737 case ISD::SHL: Opc = Alpha::SLi; break;
1738 case ISD::SRL: Opc = Alpha::SRLi; break;
1739 case ISD::SRA: Opc = Alpha::SRAi; break;
1740 case ISD::MUL: Opc = Alpha::MULQi; break;
1741 };
1742 Tmp1 = SelectExpr(N.getOperand(0));
1743 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1744 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1745 } else {
1746 switch(opcode) {
1747 case ISD::AND: Opc = Alpha::AND; break;
1748 case ISD::OR: Opc = Alpha::BIS; break;
1749 case ISD::XOR: Opc = Alpha::XOR; break;
1750 case ISD::SHL: Opc = Alpha::SL; break;
1751 case ISD::SRL: Opc = Alpha::SRL; break;
1752 case ISD::SRA: Opc = Alpha::SRA; break;
1753 case ISD::MUL: Opc = Alpha::MULQ; break;
1754 };
1755 Tmp1 = SelectExpr(N.getOperand(0));
1756 Tmp2 = SelectExpr(N.getOperand(1));
1757 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1758 }
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001759 return Result;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001760
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001761 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001762 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001763 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001764 bool isAdd = opcode == ISD::ADD;
1765
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001766 //first check for Scaled Adds and Subs!
1767 //Valid for add and sub
1768 if(N.getOperand(0).getOpcode() == ISD::SHL &&
1769 N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1770 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() == 2)
1771 {
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001772 Tmp2 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharthf77f3952005-04-06 20:59:59 +00001773 if (N.getOperand(1).getOpcode() == ISD::Constant &&
1774 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1775 BuildMI(BB, isAdd?Alpha::S4ADDQi:Alpha::S4SUBQi, 2, Result).addReg(Tmp2)
1776 .addImm(cast<ConstantSDNode>(N.getOperand(1))->getValue());
1777 else {
1778 Tmp1 = SelectExpr(N.getOperand(1));
1779 BuildMI(BB, isAdd?Alpha::S4ADDQ:Alpha::S4SUBQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
1780 }
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001781 }
1782 else if(N.getOperand(0).getOpcode() == ISD::SHL &&
1783 N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1784 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() == 3)
1785 {
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001786 Tmp2 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharthf77f3952005-04-06 20:59:59 +00001787 if (N.getOperand(1).getOpcode() == ISD::Constant &&
1788 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1789 BuildMI(BB, isAdd?Alpha::S8ADDQi:Alpha::S8SUBQi, 2, Result).addReg(Tmp2)
1790 .addImm(cast<ConstantSDNode>(N.getOperand(1))->getValue());
1791 else {
1792 Tmp1 = SelectExpr(N.getOperand(1));
1793 BuildMI(BB, isAdd?Alpha::S8ADDQ:Alpha::S8SUBQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
1794 }
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001795 }
1796 //Position prevents subs
1797 else if(N.getOperand(1).getOpcode() == ISD::SHL && isAdd &
1798 N.getOperand(1).getOperand(1).getOpcode() == ISD::Constant &&
1799 cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->getValue() == 2)
1800 {
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001801 Tmp2 = SelectExpr(N.getOperand(1).getOperand(0));
Andrew Lenharthf77f3952005-04-06 20:59:59 +00001802 if (N.getOperand(0).getOpcode() == ISD::Constant &&
1803 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1804 BuildMI(BB, Alpha::S4ADDQi, 2, Result).addReg(Tmp2)
1805 .addImm(cast<ConstantSDNode>(N.getOperand(0))->getValue());
1806 else {
1807 Tmp1 = SelectExpr(N.getOperand(0));
1808 BuildMI(BB, Alpha::S4ADDQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
1809 }
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001810 }
Andrew Lenharth273a1f92005-04-07 14:18:13 +00001811 else if(N.getOperand(1).getOpcode() == ISD::SHL && isAdd &&
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001812 N.getOperand(1).getOperand(1).getOpcode() == ISD::Constant &&
1813 cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->getValue() == 3)
1814 {
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001815 Tmp2 = SelectExpr(N.getOperand(1).getOperand(0));
Andrew Lenharthf77f3952005-04-06 20:59:59 +00001816 if (N.getOperand(0).getOpcode() == ISD::Constant &&
1817 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1818 BuildMI(BB, Alpha::S8ADDQi, 2, Result).addReg(Tmp2)
1819 .addImm(cast<ConstantSDNode>(N.getOperand(0))->getValue());
1820 else {
1821 Tmp1 = SelectExpr(N.getOperand(0));
1822 BuildMI(BB, Alpha::S8ADDQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
1823 }
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001824 }
1825 //small addi
1826 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001827 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001828 { //Normal imm add/sub
1829 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
1830 Tmp1 = SelectExpr(N.getOperand(0));
1831 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1832 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1833 }
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001834 //larger addi
Andrew Lenharth40831c52005-01-28 06:57:18 +00001835 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001836 (cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767 ||
1837 (long)cast<ConstantSDNode>(N.getOperand(1))->getValue() >= -32767))
1838 { //LDA
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001839 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001840 Tmp2 = (long)cast<ConstantSDNode>(N.getOperand(1))->getValue();
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001841 if (!isAdd)
1842 Tmp2 = -Tmp2;
1843 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001844 }
1845 //give up and do the operation
1846 else {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001847 //Normal add/sub
1848 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
1849 Tmp1 = SelectExpr(N.getOperand(0));
1850 Tmp2 = SelectExpr(N.getOperand(1));
1851 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1852 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001853 return Result;
1854 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001855
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001856 case ISD::SDIV:
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001857 {
Andrew Lenhartha565c272005-04-06 22:03:13 +00001858 ConstantSDNode* CSD;
1859 //check if we can convert into a shift!
1860 if ((CSD = dyn_cast<ConstantSDNode>(N.getOperand(1).Val)) &&
1861 (int64_t)CSD->getSignExtended() != 0 &&
1862 ExactLog2(abs((int64_t)CSD->getSignExtended())) != 0)
1863 {
1864 unsigned k = ExactLog2(abs(CSD->getSignExtended()));
1865 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenhartha565c272005-04-06 22:03:13 +00001866 if (k == 1)
1867 Tmp2 = Tmp1;
1868 else
1869 {
1870 Tmp2 = MakeReg(MVT::i64);
1871 BuildMI(BB, Alpha::SRAi, 2, Tmp2).addReg(Tmp1).addImm(k - 1);
1872 }
1873 Tmp3 = MakeReg(MVT::i64);
1874 BuildMI(BB, Alpha::SRLi, 2, Tmp3).addReg(Tmp2).addImm(64-k);
1875 unsigned Tmp4 = MakeReg(MVT::i64);
1876 BuildMI(BB, Alpha::ADDQ, 2, Tmp4).addReg(Tmp3).addReg(Tmp1);
1877 if ((int64_t)CSD->getSignExtended() > 0)
1878 BuildMI(BB, Alpha::SRAi, 2, Result).addReg(Tmp4).addImm(k);
1879 else
1880 {
1881 unsigned Tmp5 = MakeReg(MVT::i64);
1882 BuildMI(BB, Alpha::SRAi, 2, Tmp5).addReg(Tmp4).addImm(k);
1883 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Alpha::R31).addReg(Tmp5);
1884 }
1885 return Result;
1886 }
1887 }
1888 //Else fall through
1889
1890 case ISD::UDIV:
1891 {
1892 ConstantSDNode* CSD;
1893 if ((CSD = dyn_cast<ConstantSDNode>(N.getOperand(1).Val)) &&
1894 ((int64_t)CSD->getSignExtended() >= 2 ||
1895 (int64_t)CSD->getSignExtended() <= -2))
1896 {
1897 // If this is a divide by constant, we can emit code using some magic
1898 // constants to implement it as a multiply instead.
1899 ExprMap.erase(N);
1900 if (opcode == ISD::SDIV)
1901 return SelectExpr(BuildSDIVSequence(N));
1902 else
1903 return SelectExpr(BuildUDIVSequence(N));
1904 }
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001905 }
1906 //else fall though
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001907 case ISD::UREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001908 case ISD::SREM:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001909 //FIXME: alpha really doesn't support any of these operations,
1910 // the ops are expanded into special library calls with
1911 // special calling conventions
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001912 //Restore GP because it is a call after all...
Andrew Lenharth40831c52005-01-28 06:57:18 +00001913 switch(opcode) {
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001914 case ISD::UREM: Opc = Alpha::REMQU; break;
1915 case ISD::SREM: Opc = Alpha::REMQ; break;
1916 case ISD::UDIV: Opc = Alpha::DIVQU; break;
1917 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001918 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001919 Tmp1 = SelectExpr(N.getOperand(0));
1920 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth33819132005-03-04 20:09:23 +00001921 //set up regs explicitly (helps Reg alloc)
1922 BuildMI(BB, Alpha::BIS, 2, Alpha::R24).addReg(Tmp1).addReg(Tmp1);
1923 BuildMI(BB, Alpha::BIS, 2, Alpha::R25).addReg(Tmp2).addReg(Tmp2);
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001924 AlphaLowering.restoreGP(BB);
Andrew Lenharth33819132005-03-04 20:09:23 +00001925 BuildMI(BB, Opc, 2).addReg(Alpha::R24).addReg(Alpha::R25);
1926 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R27).addReg(Alpha::R27);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001927 return Result;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001928
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001929 case ISD::FP_TO_UINT:
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001930 case ISD::FP_TO_SINT:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001931 {
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001932 assert (DestType == MVT::i64 && "only quads can be loaded to");
1933 MVT::ValueType SrcType = N.getOperand(0).getValueType();
Andrew Lenharth03824012005-02-07 05:55:55 +00001934 assert (SrcType == MVT::f32 || SrcType == MVT::f64);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001935 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001936 if (SrcType == MVT::f32)
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001937 {
1938 Tmp2 = MakeReg(MVT::f64);
1939 BuildMI(BB, Alpha::CVTST, 1, Tmp2).addReg(Tmp1);
1940 Tmp1 = Tmp2;
1941 }
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001942 Tmp2 = MakeReg(MVT::f64);
1943 BuildMI(BB, Alpha::CVTTQ, 1, Tmp2).addReg(Tmp1);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001944 MoveFP2Int(Tmp2, Result, true);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001945
1946 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001947 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001948
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001949 case ISD::SELECT:
1950 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001951 //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 +00001952 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001953 //Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1954 //Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001955 // Get the condition into the zero flag.
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001956 //BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001957
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001958 SDOperand CC = N.getOperand(0);
1959 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
1960
1961 if (CC.getOpcode() == ISD::SETCC &&
1962 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
1963 { //FP Setcc -> Int Select
1964 Tmp1 = MakeReg(MVT::f64);
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001965 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1966 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001967 bool inv = SelectFPSetCC(CC, Tmp1);
1968 BuildMI(BB, inv?Alpha::CMOVNE_FP:Alpha::CMOVEQ_FP, 2, Result)
1969 .addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
1970 return Result;
1971 }
1972 if (CC.getOpcode() == ISD::SETCC) {
1973 //Int SetCC -> Select
1974 //Dropping the CC is only useful if we are comparing to 0
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001975 if((SetCC->getOperand(1).getOpcode() == ISD::Constant &&
1976 cast<ConstantSDNode>(SetCC->getOperand(1))->getValue() == 0) ||
1977 (SetCC->getOperand(0).getOpcode() == ISD::Constant &&
1978 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0))
1979 {
1980 //figure out a few things
1981 bool LeftZero = SetCC->getOperand(0).getOpcode() == ISD::Constant &&
1982 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0;
1983 bool RightZero = SetCC->getOperand(0).getOpcode() == ISD::Constant &&
1984 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0;
1985 bool LeftConst = N.getOperand(1).getOpcode() == ISD::Constant &&
1986 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255;
1987 bool RightConst = N.getOperand(2).getOpcode() == ISD::Constant &&
1988 cast<ConstantSDNode>(N.getOperand(2))->getValue() <= 255;
1989 bool useImm = LeftConst || RightConst;
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001990
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001991 //Fix up CC
1992 ISD::CondCode cCode= SetCC->getCondition();
1993 if (RightConst && !LeftConst) //Invert sense to get Imm field right
1994 cCode = ISD::getSetCCInverse(cCode, true);
1995 if (LeftZero && !RightZero) //Swap Operands
1996 cCode = ISD::getSetCCSwappedOperands(cCode);
1997
1998 //Choose the CMOV
1999 switch (cCode) {
2000 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
2001 case ISD::SETEQ: Opc = useImm?Alpha::CMOVEQi:Alpha::CMOVEQ; break;
2002 case ISD::SETLT: Opc = useImm?Alpha::CMOVLTi:Alpha::CMOVLT; break;
2003 case ISD::SETLE: Opc = useImm?Alpha::CMOVLEi:Alpha::CMOVLE; break;
2004 case ISD::SETGT: Opc = useImm?Alpha::CMOVGTi:Alpha::CMOVGT; break;
2005 case ISD::SETGE: Opc = useImm?Alpha::CMOVGEi:Alpha::CMOVGE; break;
2006 case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break;
2007 case ISD::SETUGT: Opc = useImm?Alpha::CMOVNEi:Alpha::CMOVNE; break;
2008 case ISD::SETULE: Opc = useImm?Alpha::CMOVEQi:Alpha::CMOVEQ; break; //Technically you could have this CC
2009 case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break;
2010 case ISD::SETNE: Opc = useImm?Alpha::CMOVNEi:Alpha::CMOVNE; break;
2011 }
2012 if(LeftZero && !RightZero) //swap Operands
2013 Tmp1 = SelectExpr(SetCC->getOperand(1)); //Cond
2014 else
2015 Tmp1 = SelectExpr(SetCC->getOperand(0)); //Cond
2016
2017 if (LeftConst) {
2018 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
2019 BuildMI(BB, Opc, 2, Result).addReg(Tmp3)
2020 .addImm(cast<ConstantSDNode>(N.getOperand(1))->getValue())
2021 .addReg(Tmp1);
2022 } else if (RightConst) {
2023 Tmp3 = SelectExpr(N.getOperand(1)); //Use if FALSE
2024 BuildMI(BB, Opc, 2, Result).addReg(Tmp3)
2025 .addImm(cast<ConstantSDNode>(N.getOperand(2))->getValue())
2026 .addReg(Tmp1);
2027 } else {
2028 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
2029 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
2030 BuildMI(BB, Opc, 2, Result).addReg(Tmp3).addReg(Tmp2).addReg(Tmp1);
2031 }
2032 return Result;
2033 }
Andrew Lenharth10c085b2005-04-02 22:32:39 +00002034 //Otherwise, fall though
2035 }
2036 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth63b720a2005-04-03 20:35:21 +00002037 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
2038 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharthe76797c2005-02-01 20:40:27 +00002039 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenharth10c085b2005-04-02 22:32:39 +00002040
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002041 return Result;
2042 }
2043
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002044 case ISD::Constant:
2045 {
Andrew Lenharthc0513832005-03-29 19:24:04 +00002046 int64_t val = (int64_t)cast<ConstantSDNode>(N)->getValue();
Andrew Lenharthe87f6c32005-03-11 17:48:05 +00002047 if (val <= IMM_HIGH && val >= IMM_LOW) {
2048 BuildMI(BB, Alpha::LDA, 2, Result).addImm(val).addReg(Alpha::R31);
2049 }
2050 else if (val <= (int64_t)IMM_HIGH + (int64_t)IMM_HIGH * (int64_t)IMM_MULT &&
2051 val >= (int64_t)IMM_LOW + (int64_t)IMM_LOW * (int64_t)IMM_MULT) {
2052 Tmp1 = MakeReg(MVT::i64);
2053 BuildMI(BB, Alpha::LDAH, 2, Tmp1).addImm(getUpper16(val)).addReg(Alpha::R31);
2054 BuildMI(BB, Alpha::LDA, 2, Result).addImm(getLower16(val)).addReg(Tmp1);
2055 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002056 else {
2057 MachineConstantPool *CP = BB->getParent()->getConstantPool();
2058 ConstantUInt *C = ConstantUInt::get(Type::getPrimitiveType(Type::ULongTyID) , val);
2059 unsigned CPI = CP->getConstantPoolIndex(C);
2060 AlphaLowering.restoreGP(BB);
2061 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(CPI);
2062 }
2063 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002064 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002065 }
2066
2067 return 0;
2068}
2069
2070void ISel::Select(SDOperand N) {
2071 unsigned Tmp1, Tmp2, Opc;
Andrew Lenharth760270d2005-02-07 23:02:23 +00002072 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002073
Nate Begeman85fdeb22005-03-24 04:39:54 +00002074 if (!ExprMap.insert(std::make_pair(N, notIn)).second)
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00002075 return; // Already selected.
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002076
2077 SDNode *Node = N.Val;
Andrew Lenharth760270d2005-02-07 23:02:23 +00002078
Andrew Lenharth760270d2005-02-07 23:02:23 +00002079 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002080
2081 default:
2082 Node->dump(); std::cerr << "\n";
2083 assert(0 && "Node not handled yet!");
2084
2085 case ISD::BRCOND: {
Andrew Lenharth445171a2005-02-08 00:40:03 +00002086 SelectBranchCC(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002087 return;
2088 }
2089
2090 case ISD::BR: {
2091 MachineBasicBlock *Dest =
2092 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
2093
2094 Select(N.getOperand(0));
2095 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
2096 return;
2097 }
2098
2099 case ISD::ImplicitDef:
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00002100 ++count_ins;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002101 Select(N.getOperand(0));
2102 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
2103 return;
2104
2105 case ISD::EntryToken: return; // Noop
2106
2107 case ISD::TokenFactor:
2108 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
2109 Select(Node->getOperand(i));
2110
2111 //N.Val->dump(); std::cerr << "\n";
2112 //assert(0 && "Node not handled yet!");
2113
2114 return;
2115
2116 case ISD::CopyToReg:
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00002117 ++count_outs;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002118 Select(N.getOperand(0));
2119 Tmp1 = SelectExpr(N.getOperand(1));
2120 Tmp2 = cast<RegSDNode>(N)->getReg();
2121
2122 if (Tmp1 != Tmp2) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002123 if (N.getOperand(1).getValueType() == MVT::f64 ||
2124 N.getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth29219162005-02-07 06:31:44 +00002125 BuildMI(BB, Alpha::CPYS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
2126 else
2127 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002128 }
2129 return;
2130
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002131 case ISD::RET:
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00002132 ++count_outs;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002133 switch (N.getNumOperands()) {
2134 default:
2135 std::cerr << N.getNumOperands() << "\n";
2136 for (unsigned i = 0; i < N.getNumOperands(); ++i)
2137 std::cerr << N.getOperand(i).getValueType() << "\n";
2138 Node->dump();
2139 assert(0 && "Unknown return instruction!");
2140 case 2:
2141 Select(N.getOperand(0));
2142 Tmp1 = SelectExpr(N.getOperand(1));
2143 switch (N.getOperand(1).getValueType()) {
2144 default: Node->dump();
2145 assert(0 && "All other types should have been promoted!!");
2146 case MVT::f64:
2147 case MVT::f32:
2148 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
2149 break;
2150 case MVT::i32:
2151 case MVT::i64:
2152 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
2153 break;
2154 }
2155 break;
2156 case 1:
2157 Select(N.getOperand(0));
2158 break;
2159 }
2160 //Tmp2 = AlphaLowering.getRetAddr();
2161 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
2162 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
2163 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002164
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00002165 case ISD::TRUNCSTORE:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002166 case ISD::STORE:
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00002167 {
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00002168 SDOperand Chain = N.getOperand(0);
2169 SDOperand Value = N.getOperand(1);
2170 SDOperand Address = N.getOperand(2);
2171 Select(Chain);
2172
2173 Tmp1 = SelectExpr(Value); //value
Andrew Lenharth760270d2005-02-07 23:02:23 +00002174
2175 if (opcode == ISD::STORE) {
2176 switch(Value.getValueType()) {
2177 default: assert(0 && "unknown Type in store");
2178 case MVT::i64: Opc = Alpha::STQ; break;
2179 case MVT::f64: Opc = Alpha::STT; break;
2180 case MVT::f32: Opc = Alpha::STS; break;
2181 }
2182 } else { //ISD::TRUNCSTORE
2183 switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
2184 default: assert(0 && "unknown Type in store");
2185 case MVT::i1: //FIXME: DAG does not promote this load
2186 case MVT::i8: Opc = Alpha::STB; break;
2187 case MVT::i16: Opc = Alpha::STW; break;
2188 case MVT::i32: Opc = Alpha::STL; break;
2189 }
Andrew Lenharth65838902005-02-06 16:22:15 +00002190 }
Andrew Lenharth760270d2005-02-07 23:02:23 +00002191
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00002192 if (Address.getOpcode() == ISD::GlobalAddress)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002193 {
2194 AlphaLowering.restoreGP(BB);
2195 Opc = GetSymVersion(Opc);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00002196 has_sym = true;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002197 BuildMI(BB, Opc, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
2198 }
Andrew Lenharth05380342005-02-07 05:07:00 +00002199 else if(Address.getOpcode() == ISD::FrameIndex)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002200 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00002201 BuildMI(BB, Opc, 3).addReg(Tmp1)
2202 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
2203 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002204 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00002205 else
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002206 {
2207 long offset;
2208 SelectAddr(Address, Tmp2, offset);
2209 BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
2210 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00002211 return;
2212 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002213
2214 case ISD::EXTLOAD:
2215 case ISD::SEXTLOAD:
2216 case ISD::ZEXTLOAD:
2217 case ISD::LOAD:
2218 case ISD::CopyFromReg:
2219 case ISD::CALL:
Andrew Lenharth032f2352005-02-22 21:59:48 +00002220 case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00002221 ExprMap.erase(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002222 SelectExpr(N);
2223 return;
2224
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002225 case ISD::ADJCALLSTACKDOWN:
2226 case ISD::ADJCALLSTACKUP:
2227 Select(N.getOperand(0));
2228 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
2229
2230 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
2231 Alpha::ADJUSTSTACKUP;
2232 BuildMI(BB, Opc, 1).addImm(Tmp1);
2233 return;
Andrew Lenharth95762122005-03-31 21:24:06 +00002234
2235 case ISD::PCMARKER:
2236 Select(N.getOperand(0)); //Chain
2237 BuildMI(BB, Alpha::PCLABEL, 2).addImm( cast<ConstantSDNode>(N.getOperand(1))->getValue());
2238 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002239 }
2240 assert(0 && "Should not be reached!");
2241}
2242
2243
2244/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
2245/// into a machine code representation using pattern matching and a machine
2246/// description file.
2247///
2248FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
2249 return new ISel(TM);
2250}