blob: 44a8ef49b7700bf8adafcc65f06a817b3ce65702 [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
Andrew Lenharth4b8ac152005-04-06 20:25:34 +000065 setOperationAction(ISD::EXTLOAD , MVT::i1 , Promote);
66 setOperationAction(ISD::EXTLOAD , MVT::f32 , Promote);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000067
Andrew Lenharth4b8ac152005-04-06 20:25:34 +000068 setOperationAction(ISD::ZEXTLOAD , MVT::i1 , Expand);
69 setOperationAction(ISD::ZEXTLOAD , MVT::i32 , Expand);
Andrew Lenharth2f8fb772005-01-25 00:35:34 +000070
Andrew Lenharth4b8ac152005-04-06 20:25:34 +000071 setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand);
72 setOperationAction(ISD::SEXTLOAD , MVT::i8 , Expand);
73 setOperationAction(ISD::SEXTLOAD , MVT::i16 , Expand);
Andrew Lenharth304d0f32005-01-22 23:41:55 +000074
Andrew Lenharth4b8ac152005-04-06 20:25:34 +000075 setOperationAction(ISD::SREM , MVT::f32 , Expand);
76 setOperationAction(ISD::SREM , MVT::f64 , Expand);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +000077
Andrew Lenharth4b8ac152005-04-06 20:25:34 +000078 //If this didn't legalize into a div....
79 // setOperationAction(ISD::SREM , MVT::i64, Expand);
80 // setOperationAction(ISD::UREM , MVT::i64, Expand);
81
82 setOperationAction(ISD::MEMMOVE , MVT::Other, Expand);
83 setOperationAction(ISD::MEMSET , MVT::Other, Expand);
84 setOperationAction(ISD::MEMCPY , MVT::Other, Expand);
Andrew Lenharth9818c052005-02-05 13:19:12 +000085
Andrew Lenharth33819132005-03-04 20:09:23 +000086 //Doesn't work yet
Andrew Lenharth4b8ac152005-04-06 20:25:34 +000087 setOperationAction(ISD::SETCC , MVT::f32, Promote);
Andrew Lenharth572af902005-02-14 05:41:43 +000088
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000089 computeRegisterProperties();
Andrew Lenharth304d0f32005-01-22 23:41:55 +000090
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000091 addLegalFPImmediate(+0.0); //F31
92 addLegalFPImmediate(-0.0); //-F31
Andrew Lenharth304d0f32005-01-22 23:41:55 +000093 }
94
95 /// LowerArguments - This hook must be implemented to indicate how we should
96 /// lower the arguments for the specified function, into the specified DAG.
97 virtual std::vector<SDOperand>
98 LowerArguments(Function &F, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +000099
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000100 /// LowerCallTo - This hook lowers an abstract call to a function into an
101 /// actual call.
102 virtual std::pair<SDOperand, SDOperand>
Nate Begeman8e21e712005-03-26 01:29:23 +0000103 LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
104 SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000105
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000106 virtual std::pair<SDOperand, SDOperand>
107 LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000108
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000109 virtual std::pair<SDOperand,SDOperand>
110 LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
111 const Type *ArgTy, SelectionDAG &DAG);
112
113 virtual std::pair<SDOperand, SDOperand>
114 LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
115 SelectionDAG &DAG);
116
117 void restoreGP(MachineBasicBlock* BB)
118 {
119 BuildMI(BB, Alpha::BIS, 2, Alpha::R29).addReg(GP).addReg(GP);
120 }
121 };
122}
123
124//http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PY8AC-TET1_html/callCH3.html#BLOCK21
125
126//For now, just use variable size stack frame format
127
128//In a standard call, the first six items are passed in registers $16
129//- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
130//of argument-to-register correspondence.) The remaining items are
131//collected in a memory argument list that is a naturally aligned
132//array of quadwords. In a standard call, this list, if present, must
133//be passed at 0(SP).
134//7 ... n 0(SP) ... (n-7)*8(SP)
135
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000136// //#define FP $15
137// //#define RA $26
138// //#define PV $27
139// //#define GP $29
140// //#define SP $30
141
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000142std::vector<SDOperand>
143AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
144{
145 std::vector<SDOperand> ArgValues;
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000146 std::vector<SDOperand> LS;
147 SDOperand Chain = DAG.getRoot();
148
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000149 // assert(0 && "TODO");
150 MachineFunction &MF = DAG.getMachineFunction();
Andrew Lenharth05380342005-02-07 05:07:00 +0000151 MachineFrameInfo*MFI = MF.getFrameInfo();
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000152
153 GP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
154 MachineBasicBlock& BB = MF.front();
155
156 //Handle the return address
157 //BuildMI(&BB, Alpha::IDEF, 0, Alpha::R26);
158
Andrew Lenharth3e98fde2005-01-26 21:54:09 +0000159 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
160 Alpha::R19, Alpha::R20, Alpha::R21};
161 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
162 Alpha::F19, Alpha::F20, Alpha::F21};
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000163 int count = 0;
Andrew Lenharth2c9e38c2005-02-06 21:07:31 +0000164
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000165 //Def incoming registers
166 {
167 Function::arg_iterator I = F.arg_begin();
168 Function::arg_iterator E = F.arg_end();
169 for (int i = 0; i < 6; ++i)
170 {
171 if (F.isVarArg()) {
172 BuildMI(&BB, Alpha::IDEF, 0, args_int[i]);
173 BuildMI(&BB, Alpha::IDEF, 0, args_float[i]);
174 } else if (I != E)
175 {
176 if(MVT::isInteger(getValueType(I->getType())))
177 BuildMI(&BB, Alpha::IDEF, 0, args_int[i]);
178 else
179 BuildMI(&BB, Alpha::IDEF, 0, args_float[i]);
180 ++I;
181 }
182 }
183 }
184
185 BuildMI(&BB, Alpha::IDEF, 0, Alpha::R29);
186 BuildMI(&BB, Alpha::BIS, 2, GP).addReg(Alpha::R29).addReg(Alpha::R29);
187
Chris Lattnere4d5c442005-03-15 04:54:21 +0000188 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000189 {
190 SDOperand newroot, argt;
191 if (count < 6) {
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000192 unsigned Vreg;
193 MVT::ValueType VT = getValueType(I->getType());
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000194 switch (getValueType(I->getType())) {
195 default:
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000196 std::cerr << "Unknown Type " << VT << "\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000197 abort();
198 case MVT::f64:
199 case MVT::f32:
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000200 Vreg = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(VT));
201 BuildMI(&BB, Alpha::CPYS, 2, Vreg).addReg(args_float[count]).addReg(args_float[count]);
202 argt = newroot = DAG.getCopyFromReg(Vreg,
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000203 getValueType(I->getType()),
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000204 Chain);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000205 break;
206 case MVT::i1:
207 case MVT::i8:
208 case MVT::i16:
209 case MVT::i32:
210 case MVT::i64:
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000211 Vreg = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
212 BuildMI(&BB, Alpha::BIS, 2, Vreg).addReg(args_int[count]).addReg(args_int[count]);
213 argt = newroot = DAG.getCopyFromReg(Vreg, MVT::i64, Chain);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000214 if (getValueType(I->getType()) != MVT::i64)
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000215 argt = DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()), newroot);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000216 break;
Andrew Lenharth40831c52005-01-28 06:57:18 +0000217 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000218 } else { //more args
219 // Create the frame index object for this incoming parameter...
220 int FI = MFI->CreateFixedObject(8, 8 * (count - 6));
221
222 // Create the SelectionDAG nodes corresponding to a load
223 //from this parameter
224 SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
225 argt = newroot = DAG.getLoad(getValueType(I->getType()),
226 DAG.getEntryNode(), FIN);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000227 }
Andrew Lenharth032f2352005-02-22 21:59:48 +0000228 ++count;
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000229 LS.push_back(newroot.getValue(1));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000230 ArgValues.push_back(argt);
231 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000232
Andrew Lenharth2513ddc2005-04-05 20:51:46 +0000233 // If the functions takes variable number of arguments, copy all regs to stack
234 if (F.isVarArg())
235 for (int i = 0; i < 6; ++i)
236 {
237 unsigned Vreg = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64));
238 BuildMI(&BB, Alpha::BIS, 2, Vreg).addReg(args_int[i]).addReg(args_int[i]);
239 SDOperand argt = DAG.getCopyFromReg(Vreg, MVT::i64, Chain);
240 int FI = MFI->CreateFixedObject(8, -8 * (6 - i));
241 SDOperand SDFI = DAG.getFrameIndex(FI, MVT::i64);
242 LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, argt, SDFI));
243
244 Vreg = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::f64));
245 BuildMI(&BB, Alpha::CPYS, 2, Vreg).addReg(args_float[i]).addReg(args_float[i]);
246 argt = DAG.getCopyFromReg(Vreg, MVT::f64, Chain);
247 FI = MFI->CreateFixedObject(8, - 8 * (12 - i));
248 SDFI = DAG.getFrameIndex(FI, MVT::i64);
249 LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, argt, SDFI));
250 }
251
252 // If the function takes variable number of arguments, make a frame index for
253 // the start of the first arg value... for expansion of llvm.va_start.
254 // if (F.isVarArg())
255 // VarArgsFrameIndex = MFI->CreateFixedObject(4, ArgOffset);
256
257 //Set up a token factor with all the stack traffic
258 DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, LS));
259 //return the arguments
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000260 return ArgValues;
261}
262
263std::pair<SDOperand, SDOperand>
264AlphaTargetLowering::LowerCallTo(SDOperand Chain,
Nate Begeman8e21e712005-03-26 01:29:23 +0000265 const Type *RetTy, bool isVarArg,
266 SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000267 int NumBytes = 0;
Andrew Lenharth684f2292005-01-30 00:35:27 +0000268 if (Args.size() > 6)
269 NumBytes = (Args.size() - 6) * 8;
270
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000271 Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain,
272 DAG.getConstant(NumBytes, getPointerTy()));
273 std::vector<SDOperand> args_to_use;
274 for (unsigned i = 0, e = Args.size(); i != e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000275 {
276 switch (getValueType(Args[i].second)) {
277 default: assert(0 && "Unexpected ValueType for argument!");
278 case MVT::i1:
279 case MVT::i8:
280 case MVT::i16:
281 case MVT::i32:
282 // Promote the integer to 64 bits. If the input type is signed use a
283 // sign extend, otherwise use a zero extend.
284 if (Args[i].second->isSigned())
285 Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first);
286 else
287 Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first);
288 break;
289 case MVT::i64:
290 case MVT::f64:
291 case MVT::f32:
292 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000293 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000294 args_to_use.push_back(Args[i].first);
295 }
Andrew Lenharth40831c52005-01-28 06:57:18 +0000296
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000297 std::vector<MVT::ValueType> RetVals;
298 MVT::ValueType RetTyVT = getValueType(RetTy);
299 if (RetTyVT != MVT::isVoid)
300 RetVals.push_back(RetTyVT);
301 RetVals.push_back(MVT::Other);
302
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000303 SDOperand TheCall = SDOperand(DAG.getCall(RetVals,
304 Chain, Callee, args_to_use), 0);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000305 Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
306 Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
307 DAG.getConstant(NumBytes, getPointerTy()));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000308 return std::make_pair(TheCall, Chain);
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000309}
310
311std::pair<SDOperand, SDOperand>
312AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) {
313 //vastart just returns the address of the VarArgsFrameIndex slot.
314 return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain);
315}
316
317std::pair<SDOperand,SDOperand> AlphaTargetLowering::
318LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000319 const Type *ArgTy, SelectionDAG &DAG) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000320 abort();
321}
322
323
324std::pair<SDOperand, SDOperand> AlphaTargetLowering::
325LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
326 SelectionDAG &DAG) {
327 abort();
328}
329
330
331
332
333
334namespace {
335
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000336//===--------------------------------------------------------------------===//
337/// ISel - Alpha specific code to select Alpha machine instructions for
338/// SelectionDAG operations.
339//===--------------------------------------------------------------------===//
340class ISel : public SelectionDAGISel {
341
342 /// AlphaLowering - This object fully describes how to lower LLVM code to an
343 /// Alpha-specific SelectionDAG.
344 AlphaTargetLowering AlphaLowering;
345
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000346 SelectionDAG *ISelDAG; // Hack to support us having a dag->dag transform
347 // for sdiv and udiv until it is put into the future
348 // dag combiner.
349
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000350 /// ExprMap - As shared expressions are codegen'd, we keep track of which
351 /// vreg the value is produced in, so we only emit one copy of each compiled
352 /// tree.
353 static const unsigned notIn = (unsigned)(-1);
354 std::map<SDOperand, unsigned> ExprMap;
355
356 //CCInvMap sometimes (SetNE) we have the inverse CC code for free
357 std::map<SDOperand, unsigned> CCInvMap;
358
Andrew Lenhartha32b9e32005-04-08 17:28:49 +0000359 int count_ins;
360 int count_outs;
361 bool has_sym;
362
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000363public:
364 ISel(TargetMachine &TM) : SelectionDAGISel(AlphaLowering), AlphaLowering(TM)
365 {}
366
367 /// InstructionSelectBasicBlock - This callback is invoked by
368 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
369 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
Andrew Lenharth032f2352005-02-22 21:59:48 +0000370 DEBUG(BB->dump());
Andrew Lenhartha32b9e32005-04-08 17:28:49 +0000371 count_ins = 0;
372 count_outs = 0;
373 has_sym = false;
374
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000375 // Codegen the basic block.
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000376 ISelDAG = &DAG;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000377 Select(DAG.getRoot());
Andrew Lenhartha32b9e32005-04-08 17:28:49 +0000378
379 if(has_sym)
380 ++count_ins;
381 if(EnableAlphaCount)
382 std::cerr << "COUNT: " << BB->getParent()->getFunction ()->getName() << " "
383 << BB->getNumber() << " "
384 << count_ins << " "
385 << count_outs << "\n";
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000386
387 // Clear state used for selection.
388 ExprMap.clear();
389 CCInvMap.clear();
390 }
391
392 unsigned SelectExpr(SDOperand N);
393 unsigned SelectExprFP(SDOperand N, unsigned Result);
394 void Select(SDOperand N);
395
396 void SelectAddr(SDOperand N, unsigned& Reg, long& offset);
397 void SelectBranchCC(SDOperand N);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000398 void MoveFP2Int(unsigned src, unsigned dst, bool isDouble);
399 void MoveInt2FP(unsigned src, unsigned dst, bool isDouble);
Andrew Lenharth10c085b2005-04-02 22:32:39 +0000400 //returns whether the sense of the comparison was inverted
401 bool SelectFPSetCC(SDOperand N, unsigned dst);
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000402
403 // dag -> dag expanders for integer divide by constant
404 SDOperand BuildSDIVSequence(SDOperand N);
405 SDOperand BuildUDIVSequence(SDOperand N);
406
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000407};
Andrew Lenharth304d0f32005-01-22 23:41:55 +0000408}
409
Andrew Lenhartha32b9e32005-04-08 17:28:49 +0000410//Factorize a number using the list of constants
411static bool factorize(int v[], int res[], int size, uint64_t c)
412{
413 bool cont = true;
414 while (c != 1 && cont)
415 {
416 cont = false;
417 for(int i = 0; i < size; ++i)
418 {
419 if (c % v[i] == 0)
420 {
421 c /= v[i];
422 ++res[i];
423 cont=true;
424 }
425 }
426 }
427 return c == 1;
428}
429
430
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000431//Shamelessly adapted from PPC32
432// Structure used to return the necessary information to codegen an SDIV as
433// a multiply.
434struct ms {
435 int64_t m; // magic number
436 int64_t s; // shift amount
437};
438
439struct mu {
440 uint64_t m; // magic number
441 int64_t a; // add indicator
442 int64_t s; // shift amount
443};
444
445/// magic - calculate the magic numbers required to codegen an integer sdiv as
446/// a sequence of multiply and shifts. Requires that the divisor not be 0, 1,
447/// or -1.
448static struct ms magic(int64_t d) {
449 int64_t p;
450 uint64_t ad, anc, delta, q1, r1, q2, r2, t;
451 const uint64_t two63 = 9223372036854775808ULL; // 2^63
452 struct ms mag;
453
454 ad = abs(d);
455 t = two63 + ((uint64_t)d >> 63);
456 anc = t - 1 - t%ad; // absolute value of nc
Andrew Lenharth320174f2005-04-07 17:19:16 +0000457 p = 63; // initialize p
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000458 q1 = two63/anc; // initialize q1 = 2p/abs(nc)
459 r1 = two63 - q1*anc; // initialize r1 = rem(2p,abs(nc))
460 q2 = two63/ad; // initialize q2 = 2p/abs(d)
461 r2 = two63 - q2*ad; // initialize r2 = rem(2p,abs(d))
462 do {
463 p = p + 1;
464 q1 = 2*q1; // update q1 = 2p/abs(nc)
465 r1 = 2*r1; // update r1 = rem(2p/abs(nc))
466 if (r1 >= anc) { // must be unsigned comparison
467 q1 = q1 + 1;
468 r1 = r1 - anc;
469 }
470 q2 = 2*q2; // update q2 = 2p/abs(d)
471 r2 = 2*r2; // update r2 = rem(2p/abs(d))
472 if (r2 >= ad) { // must be unsigned comparison
473 q2 = q2 + 1;
474 r2 = r2 - ad;
475 }
476 delta = ad - r2;
477 } while (q1 < delta || (q1 == delta && r1 == 0));
478
479 mag.m = q2 + 1;
480 if (d < 0) mag.m = -mag.m; // resulting magic number
481 mag.s = p - 64; // resulting shift
482 return mag;
483}
484
485/// magicu - calculate the magic numbers required to codegen an integer udiv as
486/// a sequence of multiply, add and shifts. Requires that the divisor not be 0.
487static struct mu magicu(uint64_t d)
488{
489 int64_t p;
490 uint64_t nc, delta, q1, r1, q2, r2;
491 struct mu magu;
492 magu.a = 0; // initialize "add" indicator
493 nc = - 1 - (-d)%d;
Andrew Lenharth320174f2005-04-07 17:19:16 +0000494 p = 63; // initialize p
495 q1 = 0x8000000000000000ull/nc; // initialize q1 = 2p/nc
496 r1 = 0x8000000000000000ull - q1*nc; // initialize r1 = rem(2p,nc)
497 q2 = 0x7FFFFFFFFFFFFFFFull/d; // initialize q2 = (2p-1)/d
498 r2 = 0x7FFFFFFFFFFFFFFFull - q2*d; // initialize r2 = rem((2p-1),d)
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000499 do {
500 p = p + 1;
501 if (r1 >= nc - r1 ) {
502 q1 = 2*q1 + 1; // update q1
503 r1 = 2*r1 - nc; // update r1
504 }
505 else {
506 q1 = 2*q1; // update q1
507 r1 = 2*r1; // update r1
508 }
509 if (r2 + 1 >= d - r2) {
Andrew Lenharth320174f2005-04-07 17:19:16 +0000510 if (q2 >= 0x7FFFFFFFFFFFFFFFull) magu.a = 1;
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000511 q2 = 2*q2 + 1; // update q2
512 r2 = 2*r2 + 1 - d; // update r2
513 }
514 else {
Andrew Lenharth320174f2005-04-07 17:19:16 +0000515 if (q2 >= 0x8000000000000000ull) magu.a = 1;
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000516 q2 = 2*q2; // update q2
517 r2 = 2*r2 + 1; // update r2
518 }
519 delta = d - 1 - r2;
520 } while (p < 64 && (q1 < delta || (q1 == delta && r1 == 0)));
521 magu.m = q2 + 1; // resulting magic number
Andrew Lenharth320174f2005-04-07 17:19:16 +0000522 magu.s = p - 64; // resulting shift
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000523 return magu;
524}
525
526/// BuildSDIVSequence - Given an ISD::SDIV node expressing a divide by constant,
527/// return a DAG expression to select that will generate the same value by
528/// multiplying by a magic number. See:
529/// <http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html>
530SDOperand ISel::BuildSDIVSequence(SDOperand N) {
Andrew Lenharth320174f2005-04-07 17:19:16 +0000531 int64_t d = (int64_t)cast<ConstantSDNode>(N.getOperand(1))->getSignExtended();
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000532 ms magics = magic(d);
533 // Multiply the numerator (operand 0) by the magic value
534 SDOperand Q = ISelDAG->getNode(ISD::MULHS, MVT::i64, N.getOperand(0),
535 ISelDAG->getConstant(magics.m, MVT::i64));
536 // If d > 0 and m < 0, add the numerator
537 if (d > 0 && magics.m < 0)
538 Q = ISelDAG->getNode(ISD::ADD, MVT::i64, Q, N.getOperand(0));
539 // If d < 0 and m > 0, subtract the numerator.
540 if (d < 0 && magics.m > 0)
541 Q = ISelDAG->getNode(ISD::SUB, MVT::i64, Q, N.getOperand(0));
542 // Shift right algebraic if shift value is nonzero
543 if (magics.s > 0)
544 Q = ISelDAG->getNode(ISD::SRA, MVT::i64, Q,
545 ISelDAG->getConstant(magics.s, MVT::i64));
546 // Extract the sign bit and add it to the quotient
547 SDOperand T =
548 ISelDAG->getNode(ISD::SRL, MVT::i64, Q, ISelDAG->getConstant(63, MVT::i64));
549 return ISelDAG->getNode(ISD::ADD, MVT::i64, Q, T);
550}
551
552/// BuildUDIVSequence - Given an ISD::UDIV node expressing a divide by constant,
553/// return a DAG expression to select that will generate the same value by
554/// multiplying by a magic number. See:
555/// <http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html>
556SDOperand ISel::BuildUDIVSequence(SDOperand N) {
557 unsigned d =
558 (unsigned)cast<ConstantSDNode>(N.getOperand(1))->getSignExtended();
559 mu magics = magicu(d);
560 // Multiply the numerator (operand 0) by the magic value
561 SDOperand Q = ISelDAG->getNode(ISD::MULHU, MVT::i64, N.getOperand(0),
562 ISelDAG->getConstant(magics.m, MVT::i64));
563 if (magics.a == 0) {
564 Q = ISelDAG->getNode(ISD::SRL, MVT::i64, Q,
565 ISelDAG->getConstant(magics.s, MVT::i64));
566 } else {
567 SDOperand NPQ = ISelDAG->getNode(ISD::SUB, MVT::i64, N.getOperand(0), Q);
568 NPQ = ISelDAG->getNode(ISD::SRL, MVT::i64, NPQ,
569 ISelDAG->getConstant(1, MVT::i64));
570 NPQ = ISelDAG->getNode(ISD::ADD, MVT::i64, NPQ, Q);
571 Q = ISelDAG->getNode(ISD::SRL, MVT::i64, NPQ,
572 ISelDAG->getConstant(magics.s-1, MVT::i64));
573 }
574 return Q;
575}
576
Andrew Lenhartha565c272005-04-06 22:03:13 +0000577//From PPC32
578/// ExactLog2 - This function solves for (Val == 1 << (N-1)) and returns N. It
579/// returns zero when the input is not exactly a power of two.
580static unsigned ExactLog2(uint64_t Val) {
581 if (Val == 0 || (Val & (Val-1))) return 0;
582 unsigned Count = 0;
583 while (Val != 1) {
584 Val >>= 1;
585 ++Count;
586 }
587 return Count;
588}
Andrew Lenharth4b8ac152005-04-06 20:25:34 +0000589
590
Andrew Lenharthe87f6c32005-03-11 17:48:05 +0000591//These describe LDAx
Andrew Lenharthc0513832005-03-29 19:24:04 +0000592static const int IMM_LOW = -32768;
593static const int IMM_HIGH = 32767;
Andrew Lenharthe87f6c32005-03-11 17:48:05 +0000594static const int IMM_MULT = 65536;
595
596static long getUpper16(long l)
597{
598 long y = l / IMM_MULT;
599 if (l % IMM_MULT > IMM_HIGH)
600 ++y;
601 return y;
602}
603
604static long getLower16(long l)
605{
606 long h = getUpper16(l);
607 return l - h * IMM_MULT;
608}
609
Andrew Lenharth65838902005-02-06 16:22:15 +0000610static unsigned GetSymVersion(unsigned opcode)
611{
612 switch (opcode) {
613 default: assert(0 && "unknown load or store"); return 0;
614 case Alpha::LDQ: return Alpha::LDQ_SYM;
615 case Alpha::LDS: return Alpha::LDS_SYM;
616 case Alpha::LDT: return Alpha::LDT_SYM;
617 case Alpha::LDL: return Alpha::LDL_SYM;
618 case Alpha::LDBU: return Alpha::LDBU_SYM;
619 case Alpha::LDWU: return Alpha::LDWU_SYM;
620 case Alpha::LDW: return Alpha::LDW_SYM;
621 case Alpha::LDB: return Alpha::LDB_SYM;
622 case Alpha::STQ: return Alpha::STQ_SYM;
623 case Alpha::STS: return Alpha::STS_SYM;
624 case Alpha::STT: return Alpha::STT_SYM;
625 case Alpha::STL: return Alpha::STL_SYM;
626 case Alpha::STW: return Alpha::STW_SYM;
627 case Alpha::STB: return Alpha::STB_SYM;
628 }
629}
630
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000631void ISel::MoveFP2Int(unsigned src, unsigned dst, bool isDouble)
632{
633 unsigned Opc;
634 if (EnableAlphaFTOI) {
635 Opc = isDouble ? Alpha::FTOIT : Alpha::FTOIS;
636 BuildMI(BB, Opc, 1, dst).addReg(src);
637 } else {
638 //The hard way:
639 // Spill the integer to memory and reload it from there.
640 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
641 MachineFunction *F = BB->getParent();
642 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
643
644 Opc = isDouble ? Alpha::STT : Alpha::STS;
645 BuildMI(BB, Opc, 3).addReg(src).addFrameIndex(FrameIdx).addReg(Alpha::F31);
646 Opc = isDouble ? Alpha::LDQ : Alpha::LDL;
647 BuildMI(BB, Alpha::LDQ, 2, dst).addFrameIndex(FrameIdx).addReg(Alpha::F31);
648 }
649}
650
651void ISel::MoveInt2FP(unsigned src, unsigned dst, bool isDouble)
652{
653 unsigned Opc;
654 if (EnableAlphaFTOI) {
655 Opc = isDouble?Alpha::ITOFT:Alpha::ITOFS;
656 BuildMI(BB, Opc, 1, dst).addReg(src);
657 } else {
658 //The hard way:
659 // Spill the integer to memory and reload it from there.
660 unsigned Size = MVT::getSizeInBits(MVT::f64)/8;
661 MachineFunction *F = BB->getParent();
662 int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, 8);
663
664 Opc = isDouble ? Alpha::STQ : Alpha::STL;
665 BuildMI(BB, Opc, 3).addReg(src).addFrameIndex(FrameIdx).addReg(Alpha::F31);
666 Opc = isDouble ? Alpha::LDT : Alpha::LDS;
667 BuildMI(BB, Opc, 2, dst).addFrameIndex(FrameIdx).addReg(Alpha::F31);
668 }
669}
670
Andrew Lenharth10c085b2005-04-02 22:32:39 +0000671bool ISel::SelectFPSetCC(SDOperand N, unsigned dst)
672{
673 SDNode *Node = N.Val;
674 unsigned Opc, Tmp1, Tmp2, Tmp3;
675 SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node);
676
677 //assert(SetCC->getOperand(0).getValueType() != MVT::f32 && "SetCC f32 should have been promoted");
678 bool rev = false;
679 bool inv = false;
680
681 switch (SetCC->getCondition()) {
682 default: Node->dump(); assert(0 && "Unknown FP comparison!");
683 case ISD::SETEQ: Opc = Alpha::CMPTEQ; break;
684 case ISD::SETLT: Opc = Alpha::CMPTLT; break;
685 case ISD::SETLE: Opc = Alpha::CMPTLE; break;
686 case ISD::SETGT: Opc = Alpha::CMPTLT; rev = true; break;
687 case ISD::SETGE: Opc = Alpha::CMPTLE; rev = true; break;
688 case ISD::SETNE: Opc = Alpha::CMPTEQ; inv = true; break;
689 }
690
691 //FIXME: check for constant 0.0
692 ConstantFPSDNode *CN;
693 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
694 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
695 Tmp1 = Alpha::F31;
696 else
697 Tmp1 = SelectExpr(N.getOperand(0));
698
699 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
700 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
701 Tmp2 = Alpha::F31;
702 else
703 Tmp2 = SelectExpr(N.getOperand(1));
704
705 //Can only compare doubles, and dag won't promote for me
706 if (SetCC->getOperand(0).getValueType() == MVT::f32)
707 {
708 //assert(0 && "Setcc On float?\n");
709 std::cerr << "Setcc on float!\n";
710 Tmp3 = MakeReg(MVT::f64);
711 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp1);
712 Tmp1 = Tmp3;
713 }
714 if (SetCC->getOperand(1).getValueType() == MVT::f32)
715 {
716 //assert (0 && "Setcc On float?\n");
717 std::cerr << "Setcc on float!\n";
718 Tmp3 = MakeReg(MVT::f64);
719 BuildMI(BB, Alpha::CVTST, 1, Tmp3).addReg(Tmp2);
720 Tmp2 = Tmp3;
721 }
722
723 if (rev) std::swap(Tmp1, Tmp2);
724 //do the comparison
725 BuildMI(BB, Opc, 2, dst).addReg(Tmp1).addReg(Tmp2);
726 return inv;
727}
728
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000729//Check to see if the load is a constant offset from a base register
730void ISel::SelectAddr(SDOperand N, unsigned& Reg, long& offset)
731{
732 unsigned opcode = N.getOpcode();
733 if (opcode == ISD::ADD) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000734 if(N.getOperand(1).getOpcode() == ISD::Constant &&
735 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767)
736 { //Normal imm add
737 Reg = SelectExpr(N.getOperand(0));
738 offset = cast<ConstantSDNode>(N.getOperand(1))->getValue();
739 return;
740 }
741 else if(N.getOperand(0).getOpcode() == ISD::Constant &&
742 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 32767)
743 {
744 Reg = SelectExpr(N.getOperand(1));
745 offset = cast<ConstantSDNode>(N.getOperand(0))->getValue();
746 return;
747 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +0000748 }
749 Reg = SelectExpr(N);
750 offset = 0;
751 return;
752}
753
Andrew Lenharth445171a2005-02-08 00:40:03 +0000754void ISel::SelectBranchCC(SDOperand N)
755{
756 assert(N.getOpcode() == ISD::BRCOND && "Not a BranchCC???");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000757 MachineBasicBlock *Dest =
758 cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
759 unsigned Opc = Alpha::WTF;
760
Andrew Lenharth445171a2005-02-08 00:40:03 +0000761 Select(N.getOperand(0)); //chain
762 SDOperand CC = N.getOperand(1);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000763
Andrew Lenharth445171a2005-02-08 00:40:03 +0000764 if (CC.getOpcode() == ISD::SETCC)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000765 {
766 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
767 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
768 //Dropping the CC is only useful if we are comparing to 0
Andrew Lenharth63b720a2005-04-03 20:35:21 +0000769 bool LeftZero = SetCC->getOperand(0).getOpcode() == ISD::Constant &&
770 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0;
771 bool RightZero = SetCC->getOperand(0).getOpcode() == ISD::Constant &&
772 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000773 bool isNE = false;
Andrew Lenharth63b720a2005-04-03 20:35:21 +0000774
775 //Fix up CC
776 ISD::CondCode cCode= SetCC->getCondition();
777 if (LeftZero && !RightZero) //Swap Operands
778 cCode = ISD::getSetCCSwappedOperands(cCode);
779
780 if(cCode == ISD::SETNE)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000781 isNE = true;
Andrew Lenharth445171a2005-02-08 00:40:03 +0000782
Andrew Lenharth63b720a2005-04-03 20:35:21 +0000783 if (LeftZero || RightZero) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000784 switch (SetCC->getCondition()) {
785 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
786 case ISD::SETEQ: Opc = Alpha::BEQ; break;
787 case ISD::SETLT: Opc = Alpha::BLT; break;
788 case ISD::SETLE: Opc = Alpha::BLE; break;
789 case ISD::SETGT: Opc = Alpha::BGT; break;
790 case ISD::SETGE: Opc = Alpha::BGE; break;
791 case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break;
792 case ISD::SETUGT: Opc = Alpha::BNE; break;
793 case ISD::SETULE: Opc = Alpha::BEQ; break; //Technically you could have this CC
794 case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break;
795 case ISD::SETNE: Opc = Alpha::BNE; break;
796 }
Andrew Lenharth63b720a2005-04-03 20:35:21 +0000797 unsigned Tmp1;
798 if(LeftZero && !RightZero) //swap Operands
799 Tmp1 = SelectExpr(SetCC->getOperand(1)); //Cond
800 else
801 Tmp1 = SelectExpr(SetCC->getOperand(0)); //Cond
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000802 BuildMI(BB, Opc, 2).addReg(Tmp1).addMBB(Dest);
803 return;
804 } else {
805 unsigned Tmp1 = SelectExpr(CC);
806 if (isNE)
807 BuildMI(BB, Alpha::BEQ, 2).addReg(CCInvMap[CC]).addMBB(Dest);
808 else
809 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000810 return;
811 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000812 } else { //FP
813 //Any comparison between 2 values should be codegened as an folded branch, as moving
814 //CC to the integer register is very expensive
815 //for a cmp b: c = a - b;
816 //a = b: c = 0
817 //a < b: c < 0
818 //a > b: c > 0
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000819
820 bool invTest = false;
821 unsigned Tmp3;
822
823 ConstantFPSDNode *CN;
824 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
825 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
826 Tmp3 = SelectExpr(SetCC->getOperand(0));
827 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
828 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
829 {
830 Tmp3 = SelectExpr(SetCC->getOperand(1));
831 invTest = true;
832 }
833 else
834 {
835 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
836 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
837 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
838 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
839 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
840 .addReg(Tmp1).addReg(Tmp2);
841 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000842
843 switch (SetCC->getCondition()) {
844 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +0000845 case ISD::SETEQ: Opc = invTest ? Alpha::FBNE : Alpha::FBEQ; break;
846 case ISD::SETLT: Opc = invTest ? Alpha::FBGT : Alpha::FBLT; break;
847 case ISD::SETLE: Opc = invTest ? Alpha::FBGE : Alpha::FBLE; break;
848 case ISD::SETGT: Opc = invTest ? Alpha::FBLT : Alpha::FBGT; break;
849 case ISD::SETGE: Opc = invTest ? Alpha::FBLE : Alpha::FBGE; break;
850 case ISD::SETNE: Opc = invTest ? Alpha::FBEQ : Alpha::FBNE; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000851 }
852 BuildMI(BB, Opc, 2).addReg(Tmp3).addMBB(Dest);
Andrew Lenharth445171a2005-02-08 00:40:03 +0000853 return;
854 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000855 abort(); //Should never be reached
856 } else {
857 //Giveup and do the stupid thing
858 unsigned Tmp1 = SelectExpr(CC);
859 BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest);
860 return;
861 }
Andrew Lenharth445171a2005-02-08 00:40:03 +0000862 abort(); //Should never be reached
863}
864
Andrew Lenharth40831c52005-01-28 06:57:18 +0000865unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
866{
867 unsigned Tmp1, Tmp2, Tmp3;
868 unsigned Opc = 0;
869 SDNode *Node = N.Val;
870 MVT::ValueType DestType = N.getValueType();
871 unsigned opcode = N.getOpcode();
872
873 switch (opcode) {
874 default:
875 Node->dump();
876 assert(0 && "Node not handled!\n");
Andrew Lenharth2c594352005-01-29 15:42:07 +0000877
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000878 case ISD::UNDEF: {
879 BuildMI(BB, Alpha::IDEF, 0, Result);
880 return Result;
881 }
882
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000883 case ISD::FNEG:
884 if(ISD::FABS == N.getOperand(0).getOpcode())
885 {
886 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000887 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000888 } else {
889 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth7332f3e2005-04-02 19:11:07 +0000890 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth30b46d42005-04-02 19:04:58 +0000891 }
892 return Result;
893
894 case ISD::FABS:
895 Tmp1 = SelectExpr(N.getOperand(0));
896 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Tmp1);
897 return Result;
898
Andrew Lenharth9818c052005-02-05 13:19:12 +0000899 case ISD::SELECT:
900 {
Andrew Lenharth45859692005-03-03 21:47:53 +0000901 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
902 unsigned TV = SelectExpr(N.getOperand(1)); //Use if TRUE
903 unsigned FV = SelectExpr(N.getOperand(2)); //Use if FALSE
904
905 SDOperand CC = N.getOperand(0);
906 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
907
908 if (CC.getOpcode() == ISD::SETCC &&
909 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
910 { //FP Setcc -> Select yay!
Andrew Lenharthd4bdd542005-02-05 16:41:03 +0000911
912
Andrew Lenharth45859692005-03-03 21:47:53 +0000913 //for a cmp b: c = a - b;
914 //a = b: c = 0
915 //a < b: c < 0
916 //a > b: c > 0
917
918 bool invTest = false;
919 unsigned Tmp3;
920
921 ConstantFPSDNode *CN;
922 if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1)))
923 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
924 Tmp3 = SelectExpr(SetCC->getOperand(0));
925 else if ((CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(0)))
926 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
927 {
928 Tmp3 = SelectExpr(SetCC->getOperand(1));
929 invTest = true;
930 }
931 else
932 {
933 unsigned Tmp1 = SelectExpr(SetCC->getOperand(0));
934 unsigned Tmp2 = SelectExpr(SetCC->getOperand(1));
935 bool isD = SetCC->getOperand(0).getValueType() == MVT::f64;
936 Tmp3 = MakeReg(isD ? MVT::f64 : MVT::f32);
937 BuildMI(BB, isD ? Alpha::SUBT : Alpha::SUBS, 2, Tmp3)
938 .addReg(Tmp1).addReg(Tmp2);
939 }
940
941 switch (SetCC->getCondition()) {
942 default: CC.Val->dump(); assert(0 && "Unknown FP comparison!");
943 case ISD::SETEQ: Opc = invTest ? Alpha::FCMOVNE : Alpha::FCMOVEQ; break;
944 case ISD::SETLT: Opc = invTest ? Alpha::FCMOVGT : Alpha::FCMOVLT; break;
945 case ISD::SETLE: Opc = invTest ? Alpha::FCMOVGE : Alpha::FCMOVLE; break;
946 case ISD::SETGT: Opc = invTest ? Alpha::FCMOVLT : Alpha::FCMOVGT; break;
947 case ISD::SETGE: Opc = invTest ? Alpha::FCMOVLE : Alpha::FCMOVGE; break;
948 case ISD::SETNE: Opc = invTest ? Alpha::FCMOVEQ : Alpha::FCMOVNE; break;
949 }
Andrew Lenharth33819132005-03-04 20:09:23 +0000950 BuildMI(BB, Opc, 3, Result).addReg(FV).addReg(TV).addReg(Tmp3);
Andrew Lenharth45859692005-03-03 21:47:53 +0000951 return Result;
952 }
953 else
954 {
955 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +0000956 BuildMI(BB, Alpha::FCMOVEQ_INT, 3, Result).addReg(TV).addReg(FV).addReg(Tmp1);
957// // Spill the cond to memory and reload it from there.
958// unsigned Tmp4 = MakeReg(MVT::f64);
959// MoveIntFP(Tmp1, Tmp4, true);
960// //now ideally, we don't have to do anything to the flag...
961// // Get the condition into the zero flag.
962// BuildMI(BB, Alpha::FCMOVEQ, 3, Result).addReg(TV).addReg(FV).addReg(Tmp4);
Andrew Lenharth45859692005-03-03 21:47:53 +0000963 return Result;
964 }
Andrew Lenharth9818c052005-02-05 13:19:12 +0000965 }
966
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000967 case ISD::FP_ROUND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000968 assert (DestType == MVT::f32 &&
969 N.getOperand(0).getValueType() == MVT::f64 &&
970 "only f64 to f32 conversion supported here");
Andrew Lenharthc1faced2005-02-01 01:37:24 +0000971 Tmp1 = SelectExpr(N.getOperand(0));
972 BuildMI(BB, Alpha::CVTTS, 1, Result).addReg(Tmp1);
973 return Result;
974
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000975 case ISD::FP_EXTEND:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +0000976 assert (DestType == MVT::f64 &&
977 N.getOperand(0).getValueType() == MVT::f32 &&
978 "only f32 to f64 conversion supported here");
Andrew Lenharth7b2a5272005-01-30 20:42:36 +0000979 Tmp1 = SelectExpr(N.getOperand(0));
980 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
981 return Result;
982
Andrew Lenharth2c594352005-01-29 15:42:07 +0000983 case ISD::CopyFromReg:
984 {
985 // Make sure we generate both values.
986 if (Result != notIn)
987 ExprMap[N.getValue(1)] = notIn; // Generate the token
988 else
989 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
990
991 SDOperand Chain = N.getOperand(0);
992
993 Select(Chain);
994 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
995 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
996 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(r).addReg(r);
997 return Result;
998 }
999
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001000 case ISD::LOAD:
1001 {
1002 // Make sure we generate both values.
1003 if (Result != notIn)
1004 ExprMap[N.getValue(1)] = notIn; // Generate the token
1005 else
1006 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth12dd2622005-02-03 21:01:15 +00001007
Andrew Lenharth29219162005-02-07 06:31:44 +00001008 DestType = N.getValue(0).getValueType();
Andrew Lenharth12dd2622005-02-03 21:01:15 +00001009
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001010 SDOperand Chain = N.getOperand(0);
1011 SDOperand Address = N.getOperand(1);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001012 Select(Chain);
Andrew Lenharth65838902005-02-06 16:22:15 +00001013 Opc = DestType == MVT::f64 ? Alpha::LDT : Alpha::LDS;
1014
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001015 if (Address.getOpcode() == ISD::GlobalAddress) {
1016 AlphaLowering.restoreGP(BB);
1017 Opc = GetSymVersion(Opc);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001018 has_sym = true;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001019 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1020 }
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001021 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001022 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +00001023 Opc = GetSymVersion(Opc);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001024 has_sym = true;
Andrew Lenharth97127a12005-02-05 17:41:39 +00001025 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001026 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001027 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001028 BuildMI(BB, Opc, 2, Result)
1029 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1030 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001031 } else {
1032 long offset;
1033 SelectAddr(Address, Tmp1, offset);
1034 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
1035 }
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001036 return Result;
1037 }
Andrew Lenharth40831c52005-01-28 06:57:18 +00001038 case ISD::ConstantFP:
1039 if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
1040 if (CN->isExactlyValue(+0.0)) {
1041 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth12dd2622005-02-03 21:01:15 +00001042 } else if ( CN->isExactlyValue(-0.0)) {
1043 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Alpha::F31).addReg(Alpha::F31);
Andrew Lenharth40831c52005-01-28 06:57:18 +00001044 } else {
1045 abort();
1046 }
1047 }
1048 return Result;
1049
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001050 case ISD::SDIV:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001051 case ISD::MUL:
1052 case ISD::ADD:
1053 case ISD::SUB:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001054 switch( opcode ) {
1055 case ISD::MUL: Opc = DestType == MVT::f64 ? Alpha::MULT : Alpha::MULS; break;
1056 case ISD::ADD: Opc = DestType == MVT::f64 ? Alpha::ADDT : Alpha::ADDS; break;
1057 case ISD::SUB: Opc = DestType == MVT::f64 ? Alpha::SUBT : Alpha::SUBS; break;
1058 case ISD::SDIV: Opc = DestType == MVT::f64 ? Alpha::DIVT : Alpha::DIVS; break;
1059 };
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001060
1061 ConstantFPSDNode *CN;
1062 if (opcode == ISD::SUB
1063 && (CN = dyn_cast<ConstantFPSDNode>(N.getOperand(0)))
1064 && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0)))
1065 {
1066 Tmp2 = SelectExpr(N.getOperand(1));
1067 BuildMI(BB, Alpha::CPYSN, 2, Result).addReg(Tmp2).addReg(Tmp2);
1068 } else {
1069 Tmp1 = SelectExpr(N.getOperand(0));
1070 Tmp2 = SelectExpr(N.getOperand(1));
1071 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1072 }
Andrew Lenharth40831c52005-01-28 06:57:18 +00001073 return Result;
1074
Andrew Lenharth2c594352005-01-29 15:42:07 +00001075 case ISD::EXTLOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001076 {
1077 //include a conversion sequence for float loads to double
1078 if (Result != notIn)
1079 ExprMap[N.getValue(1)] = notIn; // Generate the token
1080 else
1081 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
1082
Andrew Lenhartha549deb2005-02-07 05:33:15 +00001083 Tmp1 = MakeReg(MVT::f32);
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001084
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001085 assert(cast<MVTSDNode>(Node)->getExtraValueType() == MVT::f32 &&
1086 "EXTLOAD not from f32");
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001087 assert(Node->getValueType(0) == MVT::f64 && "EXTLOAD not to f64");
1088
1089 SDOperand Chain = N.getOperand(0);
1090 SDOperand Address = N.getOperand(1);
1091 Select(Chain);
1092
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001093 if (Address.getOpcode() == ISD::GlobalAddress) {
1094 AlphaLowering.restoreGP(BB);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001095 has_sym = true;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001096 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1097 }
1098 else if (ConstantPoolSDNode *CP =
1099 dyn_cast<ConstantPoolSDNode>(N.getOperand(1)))
1100 {
1101 AlphaLowering.restoreGP(BB);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001102 has_sym = true;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001103 BuildMI(BB, Alpha::LDS_SYM, 1, Tmp1).addConstantPoolIndex(CP->getIndex());
1104 }
1105 else if(Address.getOpcode() == ISD::FrameIndex) {
1106 Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
Andrew Lenharth032f2352005-02-22 21:59:48 +00001107 BuildMI(BB, Alpha::LDS, 2, Tmp1)
1108 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1109 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001110 } else {
1111 long offset;
1112 SelectAddr(Address, Tmp2, offset);
1113 BuildMI(BB, Alpha::LDS, 1, Tmp1).addImm(offset).addReg(Tmp2);
1114 }
Andrew Lenharth29219162005-02-07 06:31:44 +00001115 BuildMI(BB, Alpha::CVTST, 1, Result).addReg(Tmp1);
Andrew Lenharth12dd2622005-02-03 21:01:15 +00001116 return Result;
1117 }
Andrew Lenharth2c594352005-01-29 15:42:07 +00001118
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001119 case ISD::UINT_TO_FP:
1120 case ISD::SINT_TO_FP:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001121 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001122 assert (N.getOperand(0).getValueType() == MVT::i64
1123 && "only quads can be loaded from");
Andrew Lenharth40831c52005-01-28 06:57:18 +00001124 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001125 Tmp2 = MakeReg(MVT::f64);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001126 MoveInt2FP(Tmp1, Tmp2, true);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001127 Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
1128 BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
Andrew Lenharth40831c52005-01-28 06:57:18 +00001129 return Result;
1130 }
1131 }
1132 assert(0 && "should not get here");
1133 return 0;
1134}
1135
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001136unsigned ISel::SelectExpr(SDOperand N) {
1137 unsigned Result;
Andrew Lenharth2966e842005-04-07 18:15:28 +00001138 unsigned Tmp1, Tmp2 = 0, Tmp3;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001139 unsigned Opc = 0;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001140 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001141
1142 SDNode *Node = N.Val;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001143 MVT::ValueType DestType = N.getValueType();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001144
1145 unsigned &Reg = ExprMap[N];
1146 if (Reg) return Reg;
1147
1148 if (N.getOpcode() != ISD::CALL)
1149 Reg = Result = (N.getValueType() != MVT::Other) ?
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001150 MakeReg(N.getValueType()) : notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001151 else {
1152 // If this is a call instruction, make sure to prepare ALL of the result
1153 // values as well as the chain.
1154 if (Node->getNumValues() == 1)
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001155 Reg = Result = notIn; // Void call, just a chain.
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001156 else {
1157 Result = MakeReg(Node->getValueType(0));
1158 ExprMap[N.getValue(0)] = Result;
1159 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
1160 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001161 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001162 }
1163 }
1164
Andrew Lenharth22088bb2005-02-02 15:05:33 +00001165 if (DestType == MVT::f64 || DestType == MVT::f32 ||
Andrew Lenharth06342c32005-02-07 06:21:37 +00001166 (
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001167 (opcode == ISD::LOAD || opcode == ISD::CopyFromReg ||
1168 opcode == ISD::EXTLOAD) &&
1169 (N.getValue(0).getValueType() == MVT::f32 ||
1170 N.getValue(0).getValueType() == MVT::f64)
Andrew Lenharth06342c32005-02-07 06:21:37 +00001171 )
1172 )
Andrew Lenharth40831c52005-01-28 06:57:18 +00001173 return SelectExprFP(N, Result);
1174
1175 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001176 default:
1177 Node->dump();
1178 assert(0 && "Node not handled!\n");
1179
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001180 case ISD::MULHU:
1181 Tmp1 = SelectExpr(N.getOperand(0));
1182 Tmp2 = SelectExpr(N.getOperand(1));
1183 BuildMI(BB, Alpha::UMULH, 2, Result).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth706be912005-04-07 13:55:53 +00001184 return Result;
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001185 case ISD::MULHS:
1186 {
1187 //MULHU - Ra<63>*Rb - Rb<63>*Ra
1188 Tmp1 = SelectExpr(N.getOperand(0));
1189 Tmp2 = SelectExpr(N.getOperand(1));
1190 Tmp3 = MakeReg(MVT::i64);
1191 BuildMI(BB, Alpha::UMULH, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
1192 unsigned V1 = MakeReg(MVT::i64);
1193 unsigned V2 = MakeReg(MVT::i64);
1194 BuildMI(BB, Alpha::CMOVGE, 3, V1).addReg(Tmp2).addReg(Alpha::R31).addReg(Tmp1);
1195 BuildMI(BB, Alpha::CMOVGE, 3, V2).addReg(Tmp1).addReg(Alpha::R31).addReg(Tmp2);
1196 unsigned IRes = MakeReg(MVT::i64);
1197 BuildMI(BB, Alpha::SUBQ, 2, IRes).addReg(Tmp3).addReg(V1);
1198 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(IRes).addReg(V2);
1199 return Result;
1200 }
Andrew Lenharth7332f3e2005-04-02 19:11:07 +00001201 case ISD::UNDEF: {
1202 BuildMI(BB, Alpha::IDEF, 0, Result);
1203 return Result;
1204 }
1205
Andrew Lenharth032f2352005-02-22 21:59:48 +00001206 case ISD::DYNAMIC_STACKALLOC:
1207 // Generate both result values.
Andrew Lenharth3a7118d2005-02-23 17:33:42 +00001208 if (Result != notIn)
1209 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth032f2352005-02-22 21:59:48 +00001210 else
1211 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
1212
1213 // FIXME: We are currently ignoring the requested alignment for handling
1214 // greater than the stack alignment. This will need to be revisited at some
1215 // point. Align = N.getOperand(2);
1216
1217 if (!isa<ConstantSDNode>(N.getOperand(2)) ||
1218 cast<ConstantSDNode>(N.getOperand(2))->getValue() != 0) {
1219 std::cerr << "Cannot allocate stack object with greater alignment than"
1220 << " the stack alignment yet!";
1221 abort();
1222 }
1223
1224 Select(N.getOperand(0));
1225 if (ConstantSDNode* CN = dyn_cast<ConstantSDNode>(N.getOperand(1)))
1226 {
1227 if (CN->getValue() < 32000)
1228 {
1229 BuildMI(BB, Alpha::LDA, 2, Alpha::R30)
1230 .addImm(-CN->getValue()).addReg(Alpha::R30);
1231 } else {
1232 Tmp1 = SelectExpr(N.getOperand(1));
1233 // Subtract size from stack pointer, thereby allocating some space.
1234 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
1235 }
1236 } else {
1237 Tmp1 = SelectExpr(N.getOperand(1));
1238 // Subtract size from stack pointer, thereby allocating some space.
1239 BuildMI(BB, Alpha::SUBQ, 2, Alpha::R30).addReg(Alpha::R30).addReg(Tmp1);
1240 }
1241
1242 // Put a pointer to the space into the result register, by copying the stack
1243 // pointer.
Andrew Lenharth7bc47022005-02-22 23:29:25 +00001244 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R30).addReg(Alpha::R30);
Andrew Lenharth032f2352005-02-22 21:59:48 +00001245 return Result;
1246
Andrew Lenharth33819132005-03-04 20:09:23 +00001247// case ISD::ConstantPool:
1248// Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
1249// AlphaLowering.restoreGP(BB);
1250// BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(Tmp1);
1251// return Result;
Andrew Lenharth2c594352005-01-29 15:42:07 +00001252
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001253 case ISD::FrameIndex:
Andrew Lenharth032f2352005-02-22 21:59:48 +00001254 BuildMI(BB, Alpha::LDA, 2, Result)
1255 .addFrameIndex(cast<FrameIndexSDNode>(N)->getIndex())
1256 .addReg(Alpha::F31);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001257 return Result;
1258
1259 case ISD::EXTLOAD:
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001260 case ISD::ZEXTLOAD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001261 case ISD::SEXTLOAD:
Andrew Lenhartha549deb2005-02-07 05:33:15 +00001262 case ISD::LOAD:
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001263 {
1264 // Make sure we generate both values.
1265 if (Result != notIn)
1266 ExprMap[N.getValue(1)] = notIn; // Generate the token
1267 else
1268 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001269
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001270 SDOperand Chain = N.getOperand(0);
1271 SDOperand Address = N.getOperand(1);
1272 Select(Chain);
1273
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001274 assert(Node->getValueType(0) == MVT::i64 &&
1275 "Unknown type to sign extend to.");
Andrew Lenharth03824012005-02-07 05:55:55 +00001276 if (opcode == ISD::LOAD)
1277 Opc = Alpha::LDQ;
1278 else
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001279 switch (cast<MVTSDNode>(Node)->getExtraValueType()) {
1280 default: Node->dump(); assert(0 && "Bad sign extend!");
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001281 case MVT::i32: Opc = Alpha::LDL;
1282 assert(opcode != ISD::ZEXTLOAD && "Not sext"); break;
1283 case MVT::i16: Opc = Alpha::LDWU;
1284 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00001285 case MVT::i1: //FIXME: Treat i1 as i8 since there are problems otherwise
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001286 case MVT::i8: Opc = Alpha::LDBU;
1287 assert(opcode != ISD::SEXTLOAD && "Not zext"); break;
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001288 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001289
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001290 if (Address.getOpcode() == ISD::GlobalAddress) {
1291 AlphaLowering.restoreGP(BB);
1292 Opc = GetSymVersion(Opc);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001293 has_sym = true;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001294 BuildMI(BB, Opc, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
1295 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001296 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
1297 AlphaLowering.restoreGP(BB);
Andrew Lenharth65838902005-02-06 16:22:15 +00001298 Opc = GetSymVersion(Opc);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001299 has_sym = true;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001300 BuildMI(BB, Opc, 1, Result).addConstantPoolIndex(CP->getIndex());
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001301 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001302 else if(Address.getOpcode() == ISD::FrameIndex) {
Andrew Lenharth032f2352005-02-22 21:59:48 +00001303 BuildMI(BB, Opc, 2, Result)
1304 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
1305 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001306 } else {
1307 long offset;
1308 SelectAddr(Address, Tmp1, offset);
1309 BuildMI(BB, Opc, 2, Result).addImm(offset).addReg(Tmp1);
1310 }
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00001311 return Result;
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001312 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001313
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001314 case ISD::GlobalAddress:
1315 AlphaLowering.restoreGP(BB);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001316 has_sym = true;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001317 BuildMI(BB, Alpha::LOAD_ADDR, 1, Result)
1318 .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal());
1319 return Result;
1320
1321 case ISD::CALL:
1322 {
1323 Select(N.getOperand(0));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001324
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001325 // The chain for this call is now lowered.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001326 ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), notIn));
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001327
1328 //grab the arguments
1329 std::vector<unsigned> argvregs;
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001330 //assert(Node->getNumOperands() < 8 && "Only 6 args supported");
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001331 for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001332 argvregs.push_back(SelectExpr(N.getOperand(i)));
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001333
Andrew Lenharth684f2292005-01-30 00:35:27 +00001334 //in reg args
1335 for(int i = 0, e = std::min(6, (int)argvregs.size()); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001336 {
1337 unsigned args_int[] = {Alpha::R16, Alpha::R17, Alpha::R18,
1338 Alpha::R19, Alpha::R20, Alpha::R21};
1339 unsigned args_float[] = {Alpha::F16, Alpha::F17, Alpha::F18,
1340 Alpha::F19, Alpha::F20, Alpha::F21};
1341 switch(N.getOperand(i+2).getValueType()) {
1342 default:
1343 Node->dump();
1344 N.getOperand(i).Val->dump();
1345 std::cerr << "Type for " << i << " is: " <<
1346 N.getOperand(i+2).getValueType() << "\n";
1347 assert(0 && "Unknown value type for call");
1348 case MVT::i1:
1349 case MVT::i8:
1350 case MVT::i16:
1351 case MVT::i32:
1352 case MVT::i64:
1353 BuildMI(BB, Alpha::BIS, 2, args_int[i]).addReg(argvregs[i]).addReg(argvregs[i]);
1354 break;
1355 case MVT::f32:
1356 case MVT::f64:
1357 BuildMI(BB, Alpha::CPYS, 2, args_float[i]).addReg(argvregs[i]).addReg(argvregs[i]);
1358 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001359 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001360 }
Andrew Lenharth684f2292005-01-30 00:35:27 +00001361 //in mem args
1362 for (int i = 6, e = argvregs.size(); i < e; ++i)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001363 {
1364 switch(N.getOperand(i+2).getValueType()) {
1365 default:
1366 Node->dump();
1367 N.getOperand(i).Val->dump();
1368 std::cerr << "Type for " << i << " is: " <<
1369 N.getOperand(i+2).getValueType() << "\n";
1370 assert(0 && "Unknown value type for call");
1371 case MVT::i1:
1372 case MVT::i8:
1373 case MVT::i16:
1374 case MVT::i32:
1375 case MVT::i64:
1376 BuildMI(BB, Alpha::STQ, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1377 break;
1378 case MVT::f32:
1379 BuildMI(BB, Alpha::STS, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1380 break;
1381 case MVT::f64:
1382 BuildMI(BB, Alpha::STT, 3).addReg(argvregs[i]).addImm((i - 6) * 8).addReg(Alpha::R30);
1383 break;
Andrew Lenharth684f2292005-01-30 00:35:27 +00001384 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001385 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001386 //build the right kind of call
1387 if (GlobalAddressSDNode *GASD =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001388 dyn_cast<GlobalAddressSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001389 {
Andrew Lenharth3e315922005-02-10 20:10:38 +00001390 //if (GASD->getGlobal()->isExternal()) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001391 //use safe calling convention
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001392 AlphaLowering.restoreGP(BB);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001393 has_sym = true;
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001394 BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true);
Andrew Lenharth3e315922005-02-10 20:10:38 +00001395 //} else {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001396 //use PC relative branch call
Andrew Lenharth3e315922005-02-10 20:10:38 +00001397 //BuildMI(BB, Alpha::BSR, 1, Alpha::R26).addGlobalAddress(GASD->getGlobal(),true);
1398 //}
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001399 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001400 else if (ExternalSymbolSDNode *ESSDN =
Andrew Lenharth7b2a5272005-01-30 20:42:36 +00001401 dyn_cast<ExternalSymbolSDNode>(N.getOperand(1)))
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001402 {
1403 AlphaLowering.restoreGP(BB);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001404 has_sym = true;
Andrew Lenharthba05ad62005-03-30 18:22:52 +00001405 BuildMI(BB, Alpha::CALL, 1).addExternalSymbol(ESSDN->getSymbol(), true);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001406 } else {
1407 //no need to restore GP as we are doing an indirect call
1408 Tmp1 = SelectExpr(N.getOperand(1));
1409 BuildMI(BB, Alpha::BIS, 2, Alpha::R27).addReg(Tmp1).addReg(Tmp1);
1410 BuildMI(BB, Alpha::JSR, 2, Alpha::R26).addReg(Alpha::R27).addImm(0);
1411 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001412
1413 //push the result into a virtual register
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001414
1415 switch (Node->getValueType(0)) {
1416 default: Node->dump(); assert(0 && "Unknown value type for call result!");
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001417 case MVT::Other: return notIn;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001418 case MVT::i1:
1419 case MVT::i8:
1420 case MVT::i16:
1421 case MVT::i32:
1422 case MVT::i64:
1423 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0);
1424 break;
1425 case MVT::f32:
1426 case MVT::f64:
1427 BuildMI(BB, Alpha::CPYS, 2, Result).addReg(Alpha::F0).addReg(Alpha::F0);
1428 break;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001429 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001430 return Result+N.ResNo;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001431 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001432
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001433 case ISD::SIGN_EXTEND_INREG:
1434 {
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001435 //do SDIV opt for all levels of ints if not dividing by a constant
1436 if (EnableAlphaIDIV && N.getOperand(0).getOpcode() == ISD::SDIV
1437 && N.getOperand(0).getOperand(1).getOpcode() != ISD::Constant)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001438 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001439 unsigned Tmp4 = MakeReg(MVT::f64);
1440 unsigned Tmp5 = MakeReg(MVT::f64);
1441 unsigned Tmp6 = MakeReg(MVT::f64);
1442 unsigned Tmp7 = MakeReg(MVT::f64);
1443 unsigned Tmp8 = MakeReg(MVT::f64);
1444 unsigned Tmp9 = MakeReg(MVT::f64);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001445
1446 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1447 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1448 MoveInt2FP(Tmp1, Tmp4, true);
1449 MoveInt2FP(Tmp2, Tmp5, true);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001450 BuildMI(BB, Alpha::CVTQT, 1, Tmp6).addReg(Tmp4);
1451 BuildMI(BB, Alpha::CVTQT, 1, Tmp7).addReg(Tmp5);
1452 BuildMI(BB, Alpha::DIVT, 2, Tmp8).addReg(Tmp6).addReg(Tmp7);
1453 BuildMI(BB, Alpha::CVTTQ, 1, Tmp9).addReg(Tmp8);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001454 MoveFP2Int(Tmp9, Result, true);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001455 return Result;
1456 }
1457
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001458 //Alpha has instructions for a bunch of signed 32 bit stuff
1459 if( dyn_cast<MVTSDNode>(Node)->getExtraValueType() == MVT::i32)
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001460 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001461 switch (N.getOperand(0).getOpcode()) {
1462 case ISD::ADD:
1463 case ISD::SUB:
1464 case ISD::MUL:
1465 {
1466 bool isAdd = N.getOperand(0).getOpcode() == ISD::ADD;
1467 bool isMul = N.getOperand(0).getOpcode() == ISD::MUL;
1468 //FIXME: first check for Scaled Adds and Subs!
1469 if(N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1470 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() <= 255)
1471 { //Normal imm add/sub
1472 Opc = isAdd ? Alpha::ADDLi : (isMul ? Alpha::MULLi : Alpha::SUBLi);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001473 //if the value was really originally a i32, skip the up conversion
1474 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1475 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1476 ->getExtraValueType() == MVT::i32)
1477 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1478 else
1479 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001480 Tmp2 = cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue();
1481 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001482 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001483 else
1484 { //Normal add/sub
1485 Opc = isAdd ? Alpha::ADDL : (isMul ? Alpha::MULLi : Alpha::SUBL);
Andrew Lenharth093f3272005-02-12 21:11:17 +00001486 //if the value was really originally a i32, skip the up conversion
1487 if (N.getOperand(0).getOperand(0).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1488 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(0).Val)
1489 ->getExtraValueType() == MVT::i32)
1490 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0));
1491 else
1492 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
1493 //if the value was really originally a i32, skip the up conversion
1494 if (N.getOperand(0).getOperand(1).getOpcode() == ISD::SIGN_EXTEND_INREG &&
1495 dyn_cast<MVTSDNode>(N.getOperand(0).getOperand(1).Val)
1496 ->getExtraValueType() == MVT::i32)
1497 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0));
1498 else
1499 Tmp2 = SelectExpr(N.getOperand(0).getOperand(1));
1500
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001501 Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001502 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1503 }
1504 return Result;
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001505 }
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001506 case ISD::SEXTLOAD:
1507 //SelectionDag isn't deleting the signextend after sextloads
1508 Reg = Result = SelectExpr(N.getOperand(0));
1509 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001510 default: break; //Fall Though;
1511 }
1512 } //Every thing else fall though too, including unhandled opcodes above
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001513 Tmp1 = SelectExpr(N.getOperand(0));
1514 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001515 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001516 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001517 {
1518 default:
1519 Node->dump();
1520 assert(0 && "Sign Extend InReg not there yet");
1521 break;
1522 case MVT::i32:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001523 {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001524 BuildMI(BB, Alpha::ADDLi, 2, Result).addReg(Tmp1).addImm(0);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001525 break;
1526 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001527 case MVT::i16:
1528 BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1);
1529 break;
1530 case MVT::i8:
1531 BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1);
1532 break;
Andrew Lenharthebce5042005-02-12 19:35:12 +00001533 case MVT::i1:
1534 Tmp2 = MakeReg(MVT::i64);
1535 BuildMI(BB, Alpha::ANDi, 2, Tmp2).addReg(Tmp1).addImm(1);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001536 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Alpha::R31).addReg(Tmp2);
Andrew Lenharthebce5042005-02-12 19:35:12 +00001537 break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001538 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001539 return Result;
1540 }
1541 case ISD::ZERO_EXTEND_INREG:
1542 {
1543 Tmp1 = SelectExpr(N.getOperand(0));
1544 MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node);
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001545 //std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n";
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001546 switch(MVN->getExtraValueType())
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001547 {
1548 default:
1549 Node->dump();
1550 assert(0 && "Zero Extend InReg not there yet");
1551 break;
1552 case MVT::i32: Tmp2 = 0xf0; break;
1553 case MVT::i16: Tmp2 = 0xfc; break;
1554 case MVT::i8: Tmp2 = 0xfe; break;
1555 case MVT::i1: //handle this one special
1556 BuildMI(BB, Alpha::ANDi, 2, Result).addReg(Tmp1).addImm(1);
1557 return Result;
1558 }
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001559 BuildMI(BB, Alpha::ZAPi, 2, Result).addReg(Tmp1).addImm(Tmp2);
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001560 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001561 }
1562
1563 case ISD::SETCC:
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001564 {
1565 if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
1566 if (MVT::isInteger(SetCC->getOperand(0).getValueType())) {
1567 bool isConst1 = false;
1568 bool isConst2 = false;
1569 int dir;
Andrew Lenharth9818c052005-02-05 13:19:12 +00001570
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001571 //Tmp1 = SelectExpr(N.getOperand(0));
1572 if(N.getOperand(0).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001573 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1574 isConst1 = true;
1575 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001576 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1577 isConst2 = true;
1578
1579 switch (SetCC->getCondition()) {
1580 default: Node->dump(); assert(0 && "Unknown integer comparison!");
1581 case ISD::SETEQ: Opc = Alpha::CMPEQ; dir=0; break;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001582 case ISD::SETLT:
1583 Opc = isConst2 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 1; break;
1584 case ISD::SETLE:
1585 Opc = isConst2 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 1; break;
1586 case ISD::SETGT:
1587 Opc = isConst1 ? Alpha::CMPLTi : Alpha::CMPLT; dir = 2; break;
1588 case ISD::SETGE:
1589 Opc = isConst1 ? Alpha::CMPLEi : Alpha::CMPLE; dir = 2; break;
1590 case ISD::SETULT:
1591 Opc = isConst2 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 1; break;
1592 case ISD::SETUGT:
1593 Opc = isConst1 ? Alpha::CMPULTi : Alpha::CMPULT; dir = 2; break;
1594 case ISD::SETULE:
1595 Opc = isConst2 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 1; break;
1596 case ISD::SETUGE:
1597 Opc = isConst1 ? Alpha::CMPULEi : Alpha::CMPULE; dir = 2; break;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001598 case ISD::SETNE: {//Handle this one special
1599 //std::cerr << "Alpha does not have a setne.\n";
1600 //abort();
1601 Tmp1 = SelectExpr(N.getOperand(0));
1602 Tmp2 = SelectExpr(N.getOperand(1));
1603 Tmp3 = MakeReg(MVT::i64);
1604 BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
Andrew Lenharth445171a2005-02-08 00:40:03 +00001605 //Remeber we have the Inv for this CC
1606 CCInvMap[N] = Tmp3;
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001607 //and invert
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001608 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Alpha::R31).addReg(Tmp3);
Andrew Lenharthd2bb9602005-01-27 07:50:35 +00001609 return Result;
1610 }
1611 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001612 if (dir == 1) {
1613 Tmp1 = SelectExpr(N.getOperand(0));
1614 if (isConst2) {
1615 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1616 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1617 } else {
1618 Tmp2 = SelectExpr(N.getOperand(1));
1619 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1620 }
1621 } else if (dir == 2) {
1622 Tmp1 = SelectExpr(N.getOperand(1));
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00001623 if (isConst1) {
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001624 Tmp2 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1625 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1626 } else {
1627 Tmp2 = SelectExpr(N.getOperand(0));
1628 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1629 }
1630 } else { //dir == 0
1631 if (isConst1) {
1632 Tmp1 = cast<ConstantSDNode>(N.getOperand(0))->getValue();
1633 Tmp2 = SelectExpr(N.getOperand(1));
1634 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp2).addImm(Tmp1);
1635 } else if (isConst2) {
1636 Tmp1 = SelectExpr(N.getOperand(0));
1637 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1638 BuildMI(BB, Alpha::CMPEQi, 2, Result).addReg(Tmp1).addImm(Tmp2);
1639 } else {
1640 Tmp1 = SelectExpr(N.getOperand(0));
1641 Tmp2 = SelectExpr(N.getOperand(1));
1642 BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2);
1643 }
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001644 }
1645 } else {
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001646 //do the comparison
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001647 Tmp1 = MakeReg(MVT::f64);
1648 bool inv = SelectFPSetCC(N, Tmp1);
1649
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001650 //now arrange for Result (int) to have a 1 or 0
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001651 Tmp2 = MakeReg(MVT::i64);
1652 BuildMI(BB, Alpha::ADDQi, 2, Tmp2).addReg(Alpha::R31).addImm(1);
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001653 Opc = inv?Alpha::CMOVNEi_FP:Alpha::CMOVEQi_FP;
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001654 BuildMI(BB, Opc, 3, Result).addReg(Tmp2).addImm(0).addReg(Tmp1);
Andrew Lenharthd4bdd542005-02-05 16:41:03 +00001655 }
Andrew Lenharth9818c052005-02-05 13:19:12 +00001656 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001657 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001658 }
Andrew Lenharth3d65d312005-01-27 03:49:45 +00001659
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001660 case ISD::CopyFromReg:
1661 {
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001662 ++count_ins;
1663
Andrew Lenharth40831c52005-01-28 06:57:18 +00001664 // Make sure we generate both values.
Andrew Lenharthcc1b16f2005-01-28 23:17:54 +00001665 if (Result != notIn)
1666 ExprMap[N.getValue(1)] = notIn; // Generate the token
Andrew Lenharth40831c52005-01-28 06:57:18 +00001667 else
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001668 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
Andrew Lenharth40831c52005-01-28 06:57:18 +00001669
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001670 SDOperand Chain = N.getOperand(0);
1671
1672 Select(Chain);
1673 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
1674 //std::cerr << "CopyFromReg " << Result << " = " << r << "\n";
1675 BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r);
1676 return Result;
1677 }
1678
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001679 //Most of the plain arithmetic and logic share the same form, and the same
1680 //constant immediate test
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001681 case ISD::XOR:
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001682 //Match Not
1683 if (N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001684 cast<ConstantSDNode>(N.getOperand(1))->getSignExtended() == -1)
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001685 {
1686 Tmp1 = SelectExpr(N.getOperand(0));
1687 BuildMI(BB, Alpha::ORNOT, 2, Result).addReg(Alpha::R31).addReg(Tmp1);
1688 return Result;
1689 }
1690 //Fall through
1691 case ISD::AND:
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001692 case ISD::OR:
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001693 //Check operand(0) == Not
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001694 if (N.getOperand(0).getOpcode() == ISD::XOR &&
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001695 N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001696 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getSignExtended() == -1)
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001697 {
1698 switch(opcode) {
1699 case ISD::AND: Opc = Alpha::BIC; break;
1700 case ISD::OR: Opc = Alpha::ORNOT; break;
1701 case ISD::XOR: Opc = Alpha::EQV; break;
1702 }
1703 Tmp1 = SelectExpr(N.getOperand(1));
1704 Tmp2 = SelectExpr(N.getOperand(0).getOperand(0));
1705 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1706 return Result;
1707 }
1708 //Check operand(1) == Not
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001709 if (N.getOperand(1).getOpcode() == ISD::XOR &&
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001710 N.getOperand(1).getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00001711 cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->getSignExtended() == -1)
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001712 {
1713 switch(opcode) {
1714 case ISD::AND: Opc = Alpha::BIC; break;
1715 case ISD::OR: Opc = Alpha::ORNOT; break;
1716 case ISD::XOR: Opc = Alpha::EQV; break;
1717 }
1718 Tmp1 = SelectExpr(N.getOperand(0));
1719 Tmp2 = SelectExpr(N.getOperand(1).getOperand(0));
1720 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1721 return Result;
1722 }
1723 //Fall through
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001724 case ISD::SHL:
1725 case ISD::SRL:
Andrew Lenharth2c594352005-01-29 15:42:07 +00001726 case ISD::SRA:
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001727 case ISD::MUL:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001728 assert (DestType == MVT::i64 && "Only do arithmetic on i64s!");
1729 if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001730 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001731 {
1732 switch(opcode) {
1733 case ISD::AND: Opc = Alpha::ANDi; break;
1734 case ISD::OR: Opc = Alpha::BISi; break;
1735 case ISD::XOR: Opc = Alpha::XORi; break;
1736 case ISD::SHL: Opc = Alpha::SLi; break;
1737 case ISD::SRL: Opc = Alpha::SRLi; break;
1738 case ISD::SRA: Opc = Alpha::SRAi; break;
1739 case ISD::MUL: Opc = Alpha::MULQi; break;
1740 };
1741 Tmp1 = SelectExpr(N.getOperand(0));
1742 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1743 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1744 } else {
1745 switch(opcode) {
1746 case ISD::AND: Opc = Alpha::AND; break;
1747 case ISD::OR: Opc = Alpha::BIS; break;
1748 case ISD::XOR: Opc = Alpha::XOR; break;
1749 case ISD::SHL: Opc = Alpha::SL; break;
1750 case ISD::SRL: Opc = Alpha::SRL; break;
1751 case ISD::SRA: Opc = Alpha::SRA; break;
1752 case ISD::MUL: Opc = Alpha::MULQ; break;
1753 };
1754 Tmp1 = SelectExpr(N.getOperand(0));
1755 Tmp2 = SelectExpr(N.getOperand(1));
1756 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1757 }
Andrew Lenharth2d6f0222005-01-24 19:44:07 +00001758 return Result;
Andrew Lenharth40831c52005-01-28 06:57:18 +00001759
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001760 case ISD::ADD:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001761 case ISD::SUB:
Andrew Lenharth2f8fb772005-01-25 00:35:34 +00001762 {
Andrew Lenharth40831c52005-01-28 06:57:18 +00001763 bool isAdd = opcode == ISD::ADD;
1764
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001765 //first check for Scaled Adds and Subs!
1766 //Valid for add and sub
1767 if(N.getOperand(0).getOpcode() == ISD::SHL &&
1768 N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1769 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() == 2)
1770 {
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001771 Tmp2 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharthf77f3952005-04-06 20:59:59 +00001772 if (N.getOperand(1).getOpcode() == ISD::Constant &&
1773 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1774 BuildMI(BB, isAdd?Alpha::S4ADDQi:Alpha::S4SUBQi, 2, Result).addReg(Tmp2)
1775 .addImm(cast<ConstantSDNode>(N.getOperand(1))->getValue());
1776 else {
1777 Tmp1 = SelectExpr(N.getOperand(1));
1778 BuildMI(BB, isAdd?Alpha::S4ADDQ:Alpha::S4SUBQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
1779 }
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001780 }
1781 else if(N.getOperand(0).getOpcode() == ISD::SHL &&
1782 N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
1783 cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->getValue() == 3)
1784 {
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001785 Tmp2 = SelectExpr(N.getOperand(0).getOperand(0));
Andrew Lenharthf77f3952005-04-06 20:59:59 +00001786 if (N.getOperand(1).getOpcode() == ISD::Constant &&
1787 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
1788 BuildMI(BB, isAdd?Alpha::S8ADDQi:Alpha::S8SUBQi, 2, Result).addReg(Tmp2)
1789 .addImm(cast<ConstantSDNode>(N.getOperand(1))->getValue());
1790 else {
1791 Tmp1 = SelectExpr(N.getOperand(1));
1792 BuildMI(BB, isAdd?Alpha::S8ADDQ:Alpha::S8SUBQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
1793 }
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001794 }
1795 //Position prevents subs
1796 else if(N.getOperand(1).getOpcode() == ISD::SHL && isAdd &
1797 N.getOperand(1).getOperand(1).getOpcode() == ISD::Constant &&
1798 cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->getValue() == 2)
1799 {
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001800 Tmp2 = SelectExpr(N.getOperand(1).getOperand(0));
Andrew Lenharthf77f3952005-04-06 20:59:59 +00001801 if (N.getOperand(0).getOpcode() == ISD::Constant &&
1802 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1803 BuildMI(BB, Alpha::S4ADDQi, 2, Result).addReg(Tmp2)
1804 .addImm(cast<ConstantSDNode>(N.getOperand(0))->getValue());
1805 else {
1806 Tmp1 = SelectExpr(N.getOperand(0));
1807 BuildMI(BB, Alpha::S4ADDQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
1808 }
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001809 }
Andrew Lenharth273a1f92005-04-07 14:18:13 +00001810 else if(N.getOperand(1).getOpcode() == ISD::SHL && isAdd &&
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001811 N.getOperand(1).getOperand(1).getOpcode() == ISD::Constant &&
1812 cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->getValue() == 3)
1813 {
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001814 Tmp2 = SelectExpr(N.getOperand(1).getOperand(0));
Andrew Lenharthf77f3952005-04-06 20:59:59 +00001815 if (N.getOperand(0).getOpcode() == ISD::Constant &&
1816 cast<ConstantSDNode>(N.getOperand(0))->getValue() <= 255)
1817 BuildMI(BB, Alpha::S8ADDQi, 2, Result).addReg(Tmp2)
1818 .addImm(cast<ConstantSDNode>(N.getOperand(0))->getValue());
1819 else {
1820 Tmp1 = SelectExpr(N.getOperand(0));
1821 BuildMI(BB, Alpha::S8ADDQ, 2, Result).addReg(Tmp2).addReg(Tmp1);
1822 }
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001823 }
1824 //small addi
1825 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth40831c52005-01-28 06:57:18 +00001826 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001827 { //Normal imm add/sub
1828 Opc = isAdd ? Alpha::ADDQi : Alpha::SUBQi;
1829 Tmp1 = SelectExpr(N.getOperand(0));
1830 Tmp2 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
1831 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addImm(Tmp2);
1832 }
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001833 //larger addi
Andrew Lenharth40831c52005-01-28 06:57:18 +00001834 else if(N.getOperand(1).getOpcode() == ISD::Constant &&
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001835 (cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 32767 ||
1836 (long)cast<ConstantSDNode>(N.getOperand(1))->getValue() >= -32767))
1837 { //LDA
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001838 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenharth74d00d82005-03-02 17:23:03 +00001839 Tmp2 = (long)cast<ConstantSDNode>(N.getOperand(1))->getValue();
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001840 if (!isAdd)
1841 Tmp2 = -Tmp2;
1842 BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp2).addReg(Tmp1);
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001843 }
1844 //give up and do the operation
1845 else {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001846 //Normal add/sub
1847 Opc = isAdd ? Alpha::ADDQ : Alpha::SUBQ;
1848 Tmp1 = SelectExpr(N.getOperand(0));
1849 Tmp2 = SelectExpr(N.getOperand(1));
1850 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
1851 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001852 return Result;
1853 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001854
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001855 case ISD::SDIV:
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001856 {
Andrew Lenhartha565c272005-04-06 22:03:13 +00001857 ConstantSDNode* CSD;
1858 //check if we can convert into a shift!
1859 if ((CSD = dyn_cast<ConstantSDNode>(N.getOperand(1).Val)) &&
1860 (int64_t)CSD->getSignExtended() != 0 &&
1861 ExactLog2(abs((int64_t)CSD->getSignExtended())) != 0)
1862 {
1863 unsigned k = ExactLog2(abs(CSD->getSignExtended()));
1864 Tmp1 = SelectExpr(N.getOperand(0));
Andrew Lenhartha565c272005-04-06 22:03:13 +00001865 if (k == 1)
1866 Tmp2 = Tmp1;
1867 else
1868 {
1869 Tmp2 = MakeReg(MVT::i64);
1870 BuildMI(BB, Alpha::SRAi, 2, Tmp2).addReg(Tmp1).addImm(k - 1);
1871 }
1872 Tmp3 = MakeReg(MVT::i64);
1873 BuildMI(BB, Alpha::SRLi, 2, Tmp3).addReg(Tmp2).addImm(64-k);
1874 unsigned Tmp4 = MakeReg(MVT::i64);
1875 BuildMI(BB, Alpha::ADDQ, 2, Tmp4).addReg(Tmp3).addReg(Tmp1);
1876 if ((int64_t)CSD->getSignExtended() > 0)
1877 BuildMI(BB, Alpha::SRAi, 2, Result).addReg(Tmp4).addImm(k);
1878 else
1879 {
1880 unsigned Tmp5 = MakeReg(MVT::i64);
1881 BuildMI(BB, Alpha::SRAi, 2, Tmp5).addReg(Tmp4).addImm(k);
1882 BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Alpha::R31).addReg(Tmp5);
1883 }
1884 return Result;
1885 }
1886 }
1887 //Else fall through
1888
1889 case ISD::UDIV:
1890 {
1891 ConstantSDNode* CSD;
1892 if ((CSD = dyn_cast<ConstantSDNode>(N.getOperand(1).Val)) &&
1893 ((int64_t)CSD->getSignExtended() >= 2 ||
1894 (int64_t)CSD->getSignExtended() <= -2))
1895 {
1896 // If this is a divide by constant, we can emit code using some magic
1897 // constants to implement it as a multiply instead.
1898 ExprMap.erase(N);
1899 if (opcode == ISD::SDIV)
1900 return SelectExpr(BuildSDIVSequence(N));
1901 else
1902 return SelectExpr(BuildUDIVSequence(N));
1903 }
Andrew Lenharth4b8ac152005-04-06 20:25:34 +00001904 }
1905 //else fall though
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001906 case ISD::UREM:
Andrew Lenharth02981182005-01-26 01:24:38 +00001907 case ISD::SREM:
Andrew Lenharth40831c52005-01-28 06:57:18 +00001908 //FIXME: alpha really doesn't support any of these operations,
1909 // the ops are expanded into special library calls with
1910 // special calling conventions
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001911 //Restore GP because it is a call after all...
Andrew Lenharth40831c52005-01-28 06:57:18 +00001912 switch(opcode) {
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001913 case ISD::UREM: Opc = Alpha::REMQU; break;
1914 case ISD::SREM: Opc = Alpha::REMQ; break;
1915 case ISD::UDIV: Opc = Alpha::DIVQU; break;
1916 case ISD::SDIV: Opc = Alpha::DIVQ; break;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001917 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001918 Tmp1 = SelectExpr(N.getOperand(0));
1919 Tmp2 = SelectExpr(N.getOperand(1));
Andrew Lenharth33819132005-03-04 20:09:23 +00001920 //set up regs explicitly (helps Reg alloc)
1921 BuildMI(BB, Alpha::BIS, 2, Alpha::R24).addReg(Tmp1).addReg(Tmp1);
1922 BuildMI(BB, Alpha::BIS, 2, Alpha::R25).addReg(Tmp2).addReg(Tmp2);
Andrew Lenharth2b6c4f52005-02-25 22:55:15 +00001923 AlphaLowering.restoreGP(BB);
Andrew Lenharth33819132005-03-04 20:09:23 +00001924 BuildMI(BB, Opc, 2).addReg(Alpha::R24).addReg(Alpha::R25);
1925 BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R27).addReg(Alpha::R27);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001926 return Result;
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001927
Andrew Lenharthe76797c2005-02-01 20:40:27 +00001928 case ISD::FP_TO_UINT:
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001929 case ISD::FP_TO_SINT:
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001930 {
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001931 assert (DestType == MVT::i64 && "only quads can be loaded to");
1932 MVT::ValueType SrcType = N.getOperand(0).getValueType();
Andrew Lenharth03824012005-02-07 05:55:55 +00001933 assert (SrcType == MVT::f32 || SrcType == MVT::f64);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001934 Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001935 if (SrcType == MVT::f32)
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001936 {
1937 Tmp2 = MakeReg(MVT::f64);
1938 BuildMI(BB, Alpha::CVTST, 1, Tmp2).addReg(Tmp1);
1939 Tmp1 = Tmp2;
1940 }
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001941 Tmp2 = MakeReg(MVT::f64);
1942 BuildMI(BB, Alpha::CVTTQ, 1, Tmp2).addReg(Tmp1);
Andrew Lenharth0eaf6ce2005-04-02 21:06:51 +00001943 MoveFP2Int(Tmp2, Result, true);
Andrew Lenharth7efadce2005-01-31 01:44:26 +00001944
1945 return Result;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00001946 }
Andrew Lenharth3e98fde2005-01-26 21:54:09 +00001947
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001948 case ISD::SELECT:
1949 {
Andrew Lenharthdc0b71b2005-03-22 00:24:07 +00001950 //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 +00001951 //Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001952 //Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1953 //Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharth304d0f32005-01-22 23:41:55 +00001954 // Get the condition into the zero flag.
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001955 //BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001956
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001957 SDOperand CC = N.getOperand(0);
1958 SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
1959
1960 if (CC.getOpcode() == ISD::SETCC &&
1961 !MVT::isInteger(SetCC->getOperand(0).getValueType()))
1962 { //FP Setcc -> Int Select
1963 Tmp1 = MakeReg(MVT::f64);
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001964 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
1965 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001966 bool inv = SelectFPSetCC(CC, Tmp1);
1967 BuildMI(BB, inv?Alpha::CMOVNE_FP:Alpha::CMOVEQ_FP, 2, Result)
1968 .addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
1969 return Result;
1970 }
1971 if (CC.getOpcode() == ISD::SETCC) {
1972 //Int SetCC -> Select
1973 //Dropping the CC is only useful if we are comparing to 0
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001974 if((SetCC->getOperand(1).getOpcode() == ISD::Constant &&
1975 cast<ConstantSDNode>(SetCC->getOperand(1))->getValue() == 0) ||
1976 (SetCC->getOperand(0).getOpcode() == ISD::Constant &&
1977 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0))
1978 {
1979 //figure out a few things
1980 bool LeftZero = SetCC->getOperand(0).getOpcode() == ISD::Constant &&
1981 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0;
1982 bool RightZero = SetCC->getOperand(0).getOpcode() == ISD::Constant &&
1983 cast<ConstantSDNode>(SetCC->getOperand(0))->getValue() == 0;
1984 bool LeftConst = N.getOperand(1).getOpcode() == ISD::Constant &&
1985 cast<ConstantSDNode>(N.getOperand(1))->getValue() <= 255;
1986 bool RightConst = N.getOperand(2).getOpcode() == ISD::Constant &&
1987 cast<ConstantSDNode>(N.getOperand(2))->getValue() <= 255;
1988 bool useImm = LeftConst || RightConst;
Andrew Lenharth10c085b2005-04-02 22:32:39 +00001989
Andrew Lenharth63b720a2005-04-03 20:35:21 +00001990 //Fix up CC
1991 ISD::CondCode cCode= SetCC->getCondition();
1992 if (RightConst && !LeftConst) //Invert sense to get Imm field right
1993 cCode = ISD::getSetCCInverse(cCode, true);
1994 if (LeftZero && !RightZero) //Swap Operands
1995 cCode = ISD::getSetCCSwappedOperands(cCode);
1996
1997 //Choose the CMOV
1998 switch (cCode) {
1999 default: CC.Val->dump(); assert(0 && "Unknown integer comparison!");
2000 case ISD::SETEQ: Opc = useImm?Alpha::CMOVEQi:Alpha::CMOVEQ; break;
2001 case ISD::SETLT: Opc = useImm?Alpha::CMOVLTi:Alpha::CMOVLT; break;
2002 case ISD::SETLE: Opc = useImm?Alpha::CMOVLEi:Alpha::CMOVLE; break;
2003 case ISD::SETGT: Opc = useImm?Alpha::CMOVGTi:Alpha::CMOVGT; break;
2004 case ISD::SETGE: Opc = useImm?Alpha::CMOVGEi:Alpha::CMOVGE; break;
2005 case ISD::SETULT: assert(0 && "x (unsigned) < 0 is never true"); break;
2006 case ISD::SETUGT: Opc = useImm?Alpha::CMOVNEi:Alpha::CMOVNE; break;
2007 case ISD::SETULE: Opc = useImm?Alpha::CMOVEQi:Alpha::CMOVEQ; break; //Technically you could have this CC
2008 case ISD::SETUGE: assert(0 && "x (unsgined >= 0 is always true"); break;
2009 case ISD::SETNE: Opc = useImm?Alpha::CMOVNEi:Alpha::CMOVNE; break;
2010 }
2011 if(LeftZero && !RightZero) //swap Operands
2012 Tmp1 = SelectExpr(SetCC->getOperand(1)); //Cond
2013 else
2014 Tmp1 = SelectExpr(SetCC->getOperand(0)); //Cond
2015
2016 if (LeftConst) {
2017 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
2018 BuildMI(BB, Opc, 2, Result).addReg(Tmp3)
2019 .addImm(cast<ConstantSDNode>(N.getOperand(1))->getValue())
2020 .addReg(Tmp1);
2021 } else if (RightConst) {
2022 Tmp3 = SelectExpr(N.getOperand(1)); //Use if FALSE
2023 BuildMI(BB, Opc, 2, Result).addReg(Tmp3)
2024 .addImm(cast<ConstantSDNode>(N.getOperand(2))->getValue())
2025 .addReg(Tmp1);
2026 } else {
2027 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
2028 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
2029 BuildMI(BB, Opc, 2, Result).addReg(Tmp3).addReg(Tmp2).addReg(Tmp1);
2030 }
2031 return Result;
2032 }
Andrew Lenharth10c085b2005-04-02 22:32:39 +00002033 //Otherwise, fall though
2034 }
2035 Tmp1 = SelectExpr(N.getOperand(0)); //Cond
Andrew Lenharth63b720a2005-04-03 20:35:21 +00002036 Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE
2037 Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE
Andrew Lenharthe76797c2005-02-01 20:40:27 +00002038 BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp3).addReg(Tmp1);
Andrew Lenharth10c085b2005-04-02 22:32:39 +00002039
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002040 return Result;
2041 }
2042
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002043 case ISD::Constant:
2044 {
Andrew Lenharthc0513832005-03-29 19:24:04 +00002045 int64_t val = (int64_t)cast<ConstantSDNode>(N)->getValue();
Andrew Lenharthe87f6c32005-03-11 17:48:05 +00002046 if (val <= IMM_HIGH && val >= IMM_LOW) {
2047 BuildMI(BB, Alpha::LDA, 2, Result).addImm(val).addReg(Alpha::R31);
2048 }
2049 else if (val <= (int64_t)IMM_HIGH + (int64_t)IMM_HIGH * (int64_t)IMM_MULT &&
2050 val >= (int64_t)IMM_LOW + (int64_t)IMM_LOW * (int64_t)IMM_MULT) {
2051 Tmp1 = MakeReg(MVT::i64);
2052 BuildMI(BB, Alpha::LDAH, 2, Tmp1).addImm(getUpper16(val)).addReg(Alpha::R31);
2053 BuildMI(BB, Alpha::LDA, 2, Result).addImm(getLower16(val)).addReg(Tmp1);
2054 }
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002055 else {
2056 MachineConstantPool *CP = BB->getParent()->getConstantPool();
2057 ConstantUInt *C = ConstantUInt::get(Type::getPrimitiveType(Type::ULongTyID) , val);
2058 unsigned CPI = CP->getConstantPoolIndex(C);
2059 AlphaLowering.restoreGP(BB);
2060 BuildMI(BB, Alpha::LDQ_SYM, 1, Result).addConstantPoolIndex(CPI);
2061 }
2062 return Result;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002063 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002064 }
2065
2066 return 0;
2067}
2068
2069void ISel::Select(SDOperand N) {
2070 unsigned Tmp1, Tmp2, Opc;
Andrew Lenharth760270d2005-02-07 23:02:23 +00002071 unsigned opcode = N.getOpcode();
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002072
Nate Begeman85fdeb22005-03-24 04:39:54 +00002073 if (!ExprMap.insert(std::make_pair(N, notIn)).second)
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00002074 return; // Already selected.
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002075
2076 SDNode *Node = N.Val;
Andrew Lenharth760270d2005-02-07 23:02:23 +00002077
Andrew Lenharth760270d2005-02-07 23:02:23 +00002078 switch (opcode) {
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002079
2080 default:
2081 Node->dump(); std::cerr << "\n";
2082 assert(0 && "Node not handled yet!");
2083
2084 case ISD::BRCOND: {
Andrew Lenharth445171a2005-02-08 00:40:03 +00002085 SelectBranchCC(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002086 return;
2087 }
2088
2089 case ISD::BR: {
2090 MachineBasicBlock *Dest =
2091 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
2092
2093 Select(N.getOperand(0));
2094 BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest);
2095 return;
2096 }
2097
2098 case ISD::ImplicitDef:
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00002099 ++count_ins;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002100 Select(N.getOperand(0));
2101 BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg());
2102 return;
2103
2104 case ISD::EntryToken: return; // Noop
2105
2106 case ISD::TokenFactor:
2107 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
2108 Select(Node->getOperand(i));
2109
2110 //N.Val->dump(); std::cerr << "\n";
2111 //assert(0 && "Node not handled yet!");
2112
2113 return;
2114
2115 case ISD::CopyToReg:
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00002116 ++count_outs;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002117 Select(N.getOperand(0));
2118 Tmp1 = SelectExpr(N.getOperand(1));
2119 Tmp2 = cast<RegSDNode>(N)->getReg();
2120
2121 if (Tmp1 != Tmp2) {
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002122 if (N.getOperand(1).getValueType() == MVT::f64 ||
2123 N.getOperand(1).getValueType() == MVT::f32)
Andrew Lenharth29219162005-02-07 06:31:44 +00002124 BuildMI(BB, Alpha::CPYS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
2125 else
2126 BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002127 }
2128 return;
2129
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002130 case ISD::RET:
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00002131 ++count_outs;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002132 switch (N.getNumOperands()) {
2133 default:
2134 std::cerr << N.getNumOperands() << "\n";
2135 for (unsigned i = 0; i < N.getNumOperands(); ++i)
2136 std::cerr << N.getOperand(i).getValueType() << "\n";
2137 Node->dump();
2138 assert(0 && "Unknown return instruction!");
2139 case 2:
2140 Select(N.getOperand(0));
2141 Tmp1 = SelectExpr(N.getOperand(1));
2142 switch (N.getOperand(1).getValueType()) {
2143 default: Node->dump();
2144 assert(0 && "All other types should have been promoted!!");
2145 case MVT::f64:
2146 case MVT::f32:
2147 BuildMI(BB, Alpha::CPYS, 2, Alpha::F0).addReg(Tmp1).addReg(Tmp1);
2148 break;
2149 case MVT::i32:
2150 case MVT::i64:
2151 BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1);
2152 break;
2153 }
2154 break;
2155 case 1:
2156 Select(N.getOperand(0));
2157 break;
2158 }
2159 //Tmp2 = AlphaLowering.getRetAddr();
2160 //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2);
2161 BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction
2162 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002163
Andrew Lenharthf311e8b2005-02-07 05:18:02 +00002164 case ISD::TRUNCSTORE:
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002165 case ISD::STORE:
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00002166 {
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00002167 SDOperand Chain = N.getOperand(0);
2168 SDOperand Value = N.getOperand(1);
2169 SDOperand Address = N.getOperand(2);
2170 Select(Chain);
2171
2172 Tmp1 = SelectExpr(Value); //value
Andrew Lenharth760270d2005-02-07 23:02:23 +00002173
2174 if (opcode == ISD::STORE) {
2175 switch(Value.getValueType()) {
2176 default: assert(0 && "unknown Type in store");
2177 case MVT::i64: Opc = Alpha::STQ; break;
2178 case MVT::f64: Opc = Alpha::STT; break;
2179 case MVT::f32: Opc = Alpha::STS; break;
2180 }
2181 } else { //ISD::TRUNCSTORE
2182 switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
2183 default: assert(0 && "unknown Type in store");
2184 case MVT::i1: //FIXME: DAG does not promote this load
2185 case MVT::i8: Opc = Alpha::STB; break;
2186 case MVT::i16: Opc = Alpha::STW; break;
2187 case MVT::i32: Opc = Alpha::STL; break;
2188 }
Andrew Lenharth65838902005-02-06 16:22:15 +00002189 }
Andrew Lenharth760270d2005-02-07 23:02:23 +00002190
Andrew Lenharth9e8d1092005-02-06 15:40:40 +00002191 if (Address.getOpcode() == ISD::GlobalAddress)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002192 {
2193 AlphaLowering.restoreGP(BB);
2194 Opc = GetSymVersion(Opc);
Andrew Lenhartha32b9e32005-04-08 17:28:49 +00002195 has_sym = true;
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002196 BuildMI(BB, Opc, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal());
2197 }
Andrew Lenharth05380342005-02-07 05:07:00 +00002198 else if(Address.getOpcode() == ISD::FrameIndex)
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002199 {
Andrew Lenharth032f2352005-02-22 21:59:48 +00002200 BuildMI(BB, Opc, 3).addReg(Tmp1)
2201 .addFrameIndex(cast<FrameIndexSDNode>(Address)->getIndex())
2202 .addReg(Alpha::F31);
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002203 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00002204 else
Andrew Lenharth63f2ab22005-02-10 06:25:22 +00002205 {
2206 long offset;
2207 SelectAddr(Address, Tmp2, offset);
2208 BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
2209 }
Andrew Lenharthb014d3e2005-02-02 17:32:39 +00002210 return;
2211 }
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002212
2213 case ISD::EXTLOAD:
2214 case ISD::SEXTLOAD:
2215 case ISD::ZEXTLOAD:
2216 case ISD::LOAD:
2217 case ISD::CopyFromReg:
2218 case ISD::CALL:
Andrew Lenharth032f2352005-02-22 21:59:48 +00002219 case ISD::DYNAMIC_STACKALLOC:
Andrew Lenharth6b9870a2005-01-28 14:06:46 +00002220 ExprMap.erase(N);
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002221 SelectExpr(N);
2222 return;
2223
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002224 case ISD::ADJCALLSTACKDOWN:
2225 case ISD::ADJCALLSTACKUP:
2226 Select(N.getOperand(0));
2227 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
2228
2229 Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN :
2230 Alpha::ADJUSTSTACKUP;
2231 BuildMI(BB, Opc, 1).addImm(Tmp1);
2232 return;
Andrew Lenharth95762122005-03-31 21:24:06 +00002233
2234 case ISD::PCMARKER:
2235 Select(N.getOperand(0)); //Chain
2236 BuildMI(BB, Alpha::PCLABEL, 2).addImm( cast<ConstantSDNode>(N.getOperand(1))->getValue());
2237 return;
Andrew Lenharth304d0f32005-01-22 23:41:55 +00002238 }
2239 assert(0 && "Should not be reached!");
2240}
2241
2242
2243/// createAlphaPatternInstructionSelector - This pass converts an LLVM function
2244/// into a machine code representation using pattern matching and a machine
2245/// description file.
2246///
2247FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) {
2248 return new ISel(TM);
2249}