blob: 3eb38e645164e6b9b5bce74727b54526f818a17b [file] [log] [blame]
Andrew Lenharthaa38ce42005-09-02 18:46:02 +00001//===-- AlphaISelLowering.cpp - Alpha DAG Lowering Implementation ---------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Andrew Lenharth and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the AlphaISelLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AlphaISelLowering.h"
15#include "AlphaTargetMachine.h"
16#include "llvm/CodeGen/MachineFrameInfo.h"
17#include "llvm/CodeGen/MachineFunction.h"
18#include "llvm/CodeGen/MachineInstrBuilder.h"
19#include "llvm/CodeGen/SelectionDAG.h"
20#include "llvm/CodeGen/SSARegMap.h"
21#include "llvm/Constants.h"
22#include "llvm/Function.h"
Andrew Lenharth167bc6e2006-01-23 20:59:50 +000023#include "llvm/Module.h"
Andrew Lenharthaa38ce42005-09-02 18:46:02 +000024#include "llvm/Support/CommandLine.h"
25#include <iostream>
26
27using namespace llvm;
Andrew Lenharthed5d1af2006-04-02 20:13:57 +000028//Shamelessly adapted from PPC32
29// Structure used to return the necessary information to codegen an SDIV as
30// a multiply.
31struct ms {
32 int64_t m; // magic number
33 int64_t s; // shift amount
34};
35
36struct mu {
37 uint64_t m; // magic number
38 int64_t a; // add indicator
39 int64_t s; // shift amount
40};
41
42/// magic - calculate the magic numbers required to codegen an integer sdiv as
43/// a sequence of multiply and shifts. Requires that the divisor not be 0, 1,
44/// or -1.
45static struct ms magic(int64_t d) {
46 int64_t p;
47 uint64_t ad, anc, delta, q1, r1, q2, r2, t;
48 const uint64_t two63 = 9223372036854775808ULL; // 2^63
49 struct ms mag;
50
51 ad = llabs(d);
52 t = two63 + ((uint64_t)d >> 63);
53 anc = t - 1 - t%ad; // absolute value of nc
54 p = 63; // initialize p
55 q1 = two63/anc; // initialize q1 = 2p/abs(nc)
56 r1 = two63 - q1*anc; // initialize r1 = rem(2p,abs(nc))
57 q2 = two63/ad; // initialize q2 = 2p/abs(d)
58 r2 = two63 - q2*ad; // initialize r2 = rem(2p,abs(d))
59 do {
60 p = p + 1;
61 q1 = 2*q1; // update q1 = 2p/abs(nc)
62 r1 = 2*r1; // update r1 = rem(2p/abs(nc))
63 if (r1 >= anc) { // must be unsigned comparison
64 q1 = q1 + 1;
65 r1 = r1 - anc;
66 }
67 q2 = 2*q2; // update q2 = 2p/abs(d)
68 r2 = 2*r2; // update r2 = rem(2p/abs(d))
69 if (r2 >= ad) { // must be unsigned comparison
70 q2 = q2 + 1;
71 r2 = r2 - ad;
72 }
73 delta = ad - r2;
74 } while (q1 < delta || (q1 == delta && r1 == 0));
75
76 mag.m = q2 + 1;
77 if (d < 0) mag.m = -mag.m; // resulting magic number
78 mag.s = p - 64; // resulting shift
79 return mag;
80}
81
82/// magicu - calculate the magic numbers required to codegen an integer udiv as
83/// a sequence of multiply, add and shifts. Requires that the divisor not be 0.
84static struct mu magicu(uint64_t d)
85{
86 int64_t p;
87 uint64_t nc, delta, q1, r1, q2, r2;
88 struct mu magu;
89 magu.a = 0; // initialize "add" indicator
90 nc = - 1 - (-d)%d;
91 p = 63; // initialize p
92 q1 = 0x8000000000000000ull/nc; // initialize q1 = 2p/nc
93 r1 = 0x8000000000000000ull - q1*nc; // initialize r1 = rem(2p,nc)
94 q2 = 0x7FFFFFFFFFFFFFFFull/d; // initialize q2 = (2p-1)/d
95 r2 = 0x7FFFFFFFFFFFFFFFull - q2*d; // initialize r2 = rem((2p-1),d)
96 do {
97 p = p + 1;
98 if (r1 >= nc - r1 ) {
99 q1 = 2*q1 + 1; // update q1
100 r1 = 2*r1 - nc; // update r1
101 }
102 else {
103 q1 = 2*q1; // update q1
104 r1 = 2*r1; // update r1
105 }
106 if (r2 + 1 >= d - r2) {
107 if (q2 >= 0x7FFFFFFFFFFFFFFFull) magu.a = 1;
108 q2 = 2*q2 + 1; // update q2
109 r2 = 2*r2 + 1 - d; // update r2
110 }
111 else {
112 if (q2 >= 0x8000000000000000ull) magu.a = 1;
113 q2 = 2*q2; // update q2
114 r2 = 2*r2 + 1; // update r2
115 }
116 delta = d - 1 - r2;
117 } while (p < 64 && (q1 < delta || (q1 == delta && r1 == 0)));
118 magu.m = q2 + 1; // resulting magic number
119 magu.s = p - 64; // resulting shift
120 return magu;
121}
122
123/// BuildSDIVSequence - Given an ISD::SDIV node expressing a divide by constant,
124/// return a DAG expression to select that will generate the same value by
125/// multiplying by a magic number. See:
126/// <http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html>
127static SDOperand BuildSDIVSequence(SDOperand N, SelectionDAG* ISelDAG) {
128 int64_t d = (int64_t)cast<ConstantSDNode>(N.getOperand(1))->getSignExtended();
129 ms magics = magic(d);
130 // Multiply the numerator (operand 0) by the magic value
131 SDOperand Q = ISelDAG->getNode(ISD::MULHS, MVT::i64, N.getOperand(0),
132 ISelDAG->getConstant(magics.m, MVT::i64));
133 // If d > 0 and m < 0, add the numerator
134 if (d > 0 && magics.m < 0)
135 Q = ISelDAG->getNode(ISD::ADD, MVT::i64, Q, N.getOperand(0));
136 // If d < 0 and m > 0, subtract the numerator.
137 if (d < 0 && magics.m > 0)
138 Q = ISelDAG->getNode(ISD::SUB, MVT::i64, Q, N.getOperand(0));
139 // Shift right algebraic if shift value is nonzero
140 if (magics.s > 0)
141 Q = ISelDAG->getNode(ISD::SRA, MVT::i64, Q,
142 ISelDAG->getConstant(magics.s, MVT::i64));
143 // Extract the sign bit and add it to the quotient
144 SDOperand T =
145 ISelDAG->getNode(ISD::SRL, MVT::i64, Q, ISelDAG->getConstant(63, MVT::i64));
146 return ISelDAG->getNode(ISD::ADD, MVT::i64, Q, T);
147}
148
149/// BuildUDIVSequence - Given an ISD::UDIV node expressing a divide by constant,
150/// return a DAG expression to select that will generate the same value by
151/// multiplying by a magic number. See:
152/// <http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html>
153static SDOperand BuildUDIVSequence(SDOperand N, SelectionDAG* ISelDAG) {
154 unsigned d =
155 (unsigned)cast<ConstantSDNode>(N.getOperand(1))->getSignExtended();
156 mu magics = magicu(d);
157 // Multiply the numerator (operand 0) by the magic value
158 SDOperand Q = ISelDAG->getNode(ISD::MULHU, MVT::i64, N.getOperand(0),
159 ISelDAG->getConstant(magics.m, MVT::i64));
160 if (magics.a == 0) {
161 Q = ISelDAG->getNode(ISD::SRL, MVT::i64, Q,
162 ISelDAG->getConstant(magics.s, MVT::i64));
163 } else {
164 SDOperand NPQ = ISelDAG->getNode(ISD::SUB, MVT::i64, N.getOperand(0), Q);
165 NPQ = ISelDAG->getNode(ISD::SRL, MVT::i64, NPQ,
166 ISelDAG->getConstant(1, MVT::i64));
167 NPQ = ISelDAG->getNode(ISD::ADD, MVT::i64, NPQ, Q);
168 Q = ISelDAG->getNode(ISD::SRL, MVT::i64, NPQ,
169 ISelDAG->getConstant(magics.s-1, MVT::i64));
170 }
171 return Q;
172}
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000173
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000174/// AddLiveIn - This helper function adds the specified physical register to the
175/// MachineFunction as a live in value. It also creates a corresponding virtual
176/// register for it.
177static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg,
178 TargetRegisterClass *RC) {
179 assert(RC->contains(PReg) && "Not the correct regclass!");
180 unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC);
181 MF.addLiveIn(PReg, VReg);
182 return VReg;
183}
184
185AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) {
186 // Set up the TargetLowering object.
187 //I am having problems with shr n ubyte 1
188 setShiftAmountType(MVT::i64);
189 setSetCCResultType(MVT::i64);
190 setSetCCResultContents(ZeroOrOneSetCCResult);
191
192 addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass);
Andrew Lenharth5cefc5e2005-11-09 19:17:08 +0000193 addRegisterClass(MVT::f64, Alpha::F8RCRegisterClass);
194 addRegisterClass(MVT::f32, Alpha::F4RCRegisterClass);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000195
Nate Begeman750ac1b2006-02-01 07:19:44 +0000196 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
197 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000198
199 setOperationAction(ISD::EXTLOAD, MVT::i1, Promote);
200 setOperationAction(ISD::EXTLOAD, MVT::f32, Expand);
201
202 setOperationAction(ISD::ZEXTLOAD, MVT::i1, Promote);
203 setOperationAction(ISD::ZEXTLOAD, MVT::i32, Expand);
204
205 setOperationAction(ISD::SEXTLOAD, MVT::i1, Promote);
206 setOperationAction(ISD::SEXTLOAD, MVT::i8, Expand);
207 setOperationAction(ISD::SEXTLOAD, MVT::i16, Expand);
208
Andrew Lenharthf3fb71b2005-10-06 16:54:29 +0000209 setOperationAction(ISD::TRUNCSTORE, MVT::i1, Promote);
210
Chris Lattner3e2bafd2005-09-28 22:29:17 +0000211 setOperationAction(ISD::FREM, MVT::f32, Expand);
212 setOperationAction(ISD::FREM, MVT::f64, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000213
214 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand);
Andrew Lenharth7f0db912005-11-30 07:19:56 +0000215 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Andrew Lenharthcd804962005-11-30 16:10:29 +0000216 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand);
217 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
218
Andrew Lenharth120ab482005-09-29 22:54:56 +0000219 if (!TM.getSubtarget<AlphaSubtarget>().hasCT()) {
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000220 setOperationAction(ISD::CTPOP , MVT::i64 , Expand);
221 setOperationAction(ISD::CTTZ , MVT::i64 , Expand);
222 setOperationAction(ISD::CTLZ , MVT::i64 , Expand);
223 }
Nate Begemand88fc032006-01-14 03:14:10 +0000224 setOperationAction(ISD::BSWAP , MVT::i64, Expand);
Nate Begeman35ef9132006-01-11 21:21:00 +0000225 setOperationAction(ISD::ROTL , MVT::i64, Expand);
226 setOperationAction(ISD::ROTR , MVT::i64, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000227
Andrew Lenharth53d89702005-12-25 01:34:27 +0000228 setOperationAction(ISD::SREM , MVT::i64, Custom);
229 setOperationAction(ISD::UREM , MVT::i64, Custom);
230 setOperationAction(ISD::SDIV , MVT::i64, Custom);
231 setOperationAction(ISD::UDIV , MVT::i64, Custom);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000232
233 setOperationAction(ISD::MEMMOVE , MVT::Other, Expand);
234 setOperationAction(ISD::MEMSET , MVT::Other, Expand);
235 setOperationAction(ISD::MEMCPY , MVT::Other, Expand);
236
237 // We don't support sin/cos/sqrt
238 setOperationAction(ISD::FSIN , MVT::f64, Expand);
239 setOperationAction(ISD::FCOS , MVT::f64, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000240 setOperationAction(ISD::FSIN , MVT::f32, Expand);
241 setOperationAction(ISD::FCOS , MVT::f32, Expand);
Andrew Lenharth39424472006-01-19 21:10:38 +0000242
243 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000244 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Chris Lattner9601a862006-03-05 05:08:37 +0000245
246 // FIXME: Alpha supports fcopysign natively!?
247 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
248 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000249
Andrew Lenharthb2156f92005-11-30 17:11:20 +0000250 setOperationAction(ISD::SETCC, MVT::f32, Promote);
Chris Lattnerf73bae12005-11-29 06:16:21 +0000251
252 // We don't have line number support yet.
253 setOperationAction(ISD::LOCATION, MVT::Other, Expand);
Jim Laskeye0bce712006-01-05 01:47:43 +0000254 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
255 setOperationAction(ISD::DEBUG_LABEL, MVT::Other, Expand);
Chris Lattnerb99329e2006-01-13 02:42:53 +0000256
257 // Not implemented yet.
258 setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
259 setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
Andrew Lenharth739027e2006-01-16 21:22:38 +0000260 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand);
261
Andrew Lenharth53d89702005-12-25 01:34:27 +0000262 // We want to legalize GlobalAddress and ConstantPool and
263 // ExternalSymbols nodes into the appropriate instructions to
264 // materialize the address.
265 setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
266 setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
267 setOperationAction(ISD::ExternalSymbol, MVT::i64, Custom);
Andrew Lenharth4e629512005-12-24 05:36:33 +0000268
Andrew Lenharth0e538792006-01-25 21:54:38 +0000269 setOperationAction(ISD::VASTART, MVT::Other, Custom);
Andrew Lenharth677c4f22006-01-25 23:33:32 +0000270 setOperationAction(ISD::VAEND, MVT::Other, Expand);
Andrew Lenharth0e538792006-01-25 21:54:38 +0000271 setOperationAction(ISD::VACOPY, MVT::Other, Custom);
Andrew Lenharth5f8f0e22006-01-25 22:28:07 +0000272 setOperationAction(ISD::VAARG, MVT::Other, Custom);
Nate Begeman0aed7842006-01-28 03:14:31 +0000273 setOperationAction(ISD::VAARG, MVT::i32, Custom);
Andrew Lenharth0e538792006-01-25 21:54:38 +0000274
Andrew Lenharth739027e2006-01-16 21:22:38 +0000275 setStackPointerRegisterToSaveRestore(Alpha::R30);
276
Chris Lattner08a90222006-01-29 06:25:22 +0000277 setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
278 setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000279 addLegalFPImmediate(+0.0); //F31
280 addLegalFPImmediate(-0.0); //-F31
Andrew Lenharth7f0db912005-11-30 07:19:56 +0000281
282 computeRegisterProperties();
283
284 useITOF = TM.getSubtarget<AlphaSubtarget>().hasF2I();
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000285}
286
Andrew Lenharth84a06052006-01-16 19:53:25 +0000287const char *AlphaTargetLowering::getTargetNodeName(unsigned Opcode) const {
288 switch (Opcode) {
289 default: return 0;
290 case AlphaISD::ITOFT_: return "Alpha::ITOFT_";
291 case AlphaISD::FTOIT_: return "Alpha::FTOIT_";
292 case AlphaISD::CVTQT_: return "Alpha::CVTQT_";
293 case AlphaISD::CVTQS_: return "Alpha::CVTQS_";
294 case AlphaISD::CVTTQ_: return "Alpha::CVTTQ_";
295 case AlphaISD::GPRelHi: return "Alpha::GPRelHi";
296 case AlphaISD::GPRelLo: return "Alpha::GPRelLo";
297 case AlphaISD::RelLit: return "Alpha::RelLit";
298 case AlphaISD::GlobalBaseReg: return "Alpha::GlobalBaseReg";
Chris Lattner2d90bd52006-01-27 23:39:00 +0000299 case AlphaISD::CALL: return "Alpha::CALL";
Andrew Lenharth84a06052006-01-16 19:53:25 +0000300 case AlphaISD::DivCall: return "Alpha::DivCall";
301 }
302}
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000303
304//http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PY8AC-TET1_html/callCH3.html#BLOCK21
305
306//For now, just use variable size stack frame format
307
308//In a standard call, the first six items are passed in registers $16
309//- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
310//of argument-to-register correspondence.) The remaining items are
311//collected in a memory argument list that is a naturally aligned
312//array of quadwords. In a standard call, this list, if present, must
313//be passed at 0(SP).
314//7 ... n 0(SP) ... (n-7)*8(SP)
315
316// //#define FP $15
317// //#define RA $26
318// //#define PV $27
319// //#define GP $29
320// //#define SP $30
321
322std::vector<SDOperand>
323AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
324{
325 MachineFunction &MF = DAG.getMachineFunction();
326 MachineFrameInfo *MFI = MF.getFrameInfo();
327 MachineBasicBlock& BB = MF.front();
328 std::vector<SDOperand> ArgValues;
329
Andrew Lenharthf71df332005-09-04 06:12:19 +0000330 unsigned args_int[] = {
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000331 Alpha::R16, Alpha::R17, Alpha::R18, Alpha::R19, Alpha::R20, Alpha::R21};
Andrew Lenharthf71df332005-09-04 06:12:19 +0000332 unsigned args_float[] = {
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000333 Alpha::F16, Alpha::F17, Alpha::F18, Alpha::F19, Alpha::F20, Alpha::F21};
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000334
335 int count = 0;
336
337 GP = AddLiveIn(MF, Alpha::R29, getRegClassFor(MVT::i64));
338 RA = AddLiveIn(MF, Alpha::R26, getRegClassFor(MVT::i64));
339
340 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
341 {
342 SDOperand argt;
343 if (count < 6) {
344 unsigned Vreg;
345 MVT::ValueType VT = getValueType(I->getType());
346 switch (VT) {
347 default:
348 std::cerr << "Unknown Type " << VT << "\n";
349 abort();
350 case MVT::f64:
351 case MVT::f32:
Andrew Lenharthf71df332005-09-04 06:12:19 +0000352 args_float[count] = AddLiveIn(MF, args_float[count], getRegClassFor(VT));
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000353 argt = DAG.getCopyFromReg(DAG.getRoot(), args_float[count], VT);
354 DAG.setRoot(argt.getValue(1));
355 break;
356 case MVT::i1:
357 case MVT::i8:
358 case MVT::i16:
359 case MVT::i32:
360 case MVT::i64:
Andrew Lenharthf71df332005-09-04 06:12:19 +0000361 args_int[count] = AddLiveIn(MF, args_int[count], getRegClassFor(MVT::i64));
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000362 argt = DAG.getCopyFromReg(DAG.getRoot(), args_int[count], MVT::i64);
363 DAG.setRoot(argt.getValue(1));
364 if (VT != MVT::i64) {
365 unsigned AssertOp =
366 I->getType()->isSigned() ? ISD::AssertSext : ISD::AssertZext;
367 argt = DAG.getNode(AssertOp, MVT::i64, argt,
368 DAG.getValueType(VT));
369 argt = DAG.getNode(ISD::TRUNCATE, VT, argt);
370 }
371 break;
372 }
373 } else { //more args
374 // Create the frame index object for this incoming parameter...
375 int FI = MFI->CreateFixedObject(8, 8 * (count - 6));
376
377 // Create the SelectionDAG nodes corresponding to a load
378 //from this parameter
379 SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
380 argt = DAG.getLoad(getValueType(I->getType()),
381 DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL));
382 }
383 ++count;
384 ArgValues.push_back(argt);
385 }
386
387 // If the functions takes variable number of arguments, copy all regs to stack
388 if (F.isVarArg()) {
389 VarArgsOffset = count * 8;
390 std::vector<SDOperand> LS;
391 for (int i = 0; i < 6; ++i) {
Chris Lattnerf2cded72005-09-13 19:03:13 +0000392 if (MRegisterInfo::isPhysicalRegister(args_int[i]))
Andrew Lenharthf71df332005-09-04 06:12:19 +0000393 args_int[i] = AddLiveIn(MF, args_int[i], getRegClassFor(MVT::i64));
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000394 SDOperand argt = DAG.getCopyFromReg(DAG.getRoot(), args_int[i], MVT::i64);
395 int FI = MFI->CreateFixedObject(8, -8 * (6 - i));
396 if (i == 0) VarArgsBase = FI;
397 SDOperand SDFI = DAG.getFrameIndex(FI, MVT::i64);
398 LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, DAG.getRoot(), argt,
399 SDFI, DAG.getSrcValue(NULL)));
400
Chris Lattnerf2cded72005-09-13 19:03:13 +0000401 if (MRegisterInfo::isPhysicalRegister(args_float[i]))
Andrew Lenharthf71df332005-09-04 06:12:19 +0000402 args_float[i] = AddLiveIn(MF, args_float[i], getRegClassFor(MVT::f64));
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000403 argt = DAG.getCopyFromReg(DAG.getRoot(), args_float[i], MVT::f64);
404 FI = MFI->CreateFixedObject(8, - 8 * (12 - i));
405 SDFI = DAG.getFrameIndex(FI, MVT::i64);
406 LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, DAG.getRoot(), argt,
407 SDFI, DAG.getSrcValue(NULL)));
408 }
409
410 //Set up a token factor with all the stack traffic
411 DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, LS));
412 }
413
414 // Finally, inform the code generator which regs we return values in.
415 switch (getValueType(F.getReturnType())) {
416 default: assert(0 && "Unknown type!");
417 case MVT::isVoid: break;
418 case MVT::i1:
419 case MVT::i8:
420 case MVT::i16:
421 case MVT::i32:
422 case MVT::i64:
423 MF.addLiveOut(Alpha::R0);
424 break;
425 case MVT::f32:
426 case MVT::f64:
427 MF.addLiveOut(Alpha::F0);
428 break;
429 }
430
Andrew Lenharthed5d1af2006-04-02 20:13:57 +0000431 //return the arguments+
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000432 return ArgValues;
433}
434
435std::pair<SDOperand, SDOperand>
436AlphaTargetLowering::LowerCallTo(SDOperand Chain,
437 const Type *RetTy, bool isVarArg,
438 unsigned CallingConv, bool isTailCall,
439 SDOperand Callee, ArgListTy &Args,
440 SelectionDAG &DAG) {
441 int NumBytes = 0;
442 if (Args.size() > 6)
443 NumBytes = (Args.size() - 6) * 8;
444
Chris Lattner94dd2922006-02-13 09:00:43 +0000445 Chain = DAG.getCALLSEQ_START(Chain,
446 DAG.getConstant(NumBytes, getPointerTy()));
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000447 std::vector<SDOperand> args_to_use;
448 for (unsigned i = 0, e = Args.size(); i != e; ++i)
449 {
450 switch (getValueType(Args[i].second)) {
451 default: assert(0 && "Unexpected ValueType for argument!");
452 case MVT::i1:
453 case MVT::i8:
454 case MVT::i16:
455 case MVT::i32:
456 // Promote the integer to 64 bits. If the input type is signed use a
457 // sign extend, otherwise use a zero extend.
458 if (Args[i].second->isSigned())
459 Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first);
460 else
461 Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first);
462 break;
463 case MVT::i64:
464 case MVT::f64:
465 case MVT::f32:
466 break;
467 }
468 args_to_use.push_back(Args[i].first);
469 }
470
471 std::vector<MVT::ValueType> RetVals;
472 MVT::ValueType RetTyVT = getValueType(RetTy);
Andrew Lenharth46a776e2005-09-06 17:00:23 +0000473 MVT::ValueType ActualRetTyVT = RetTyVT;
474 if (RetTyVT >= MVT::i1 && RetTyVT <= MVT::i32)
475 ActualRetTyVT = MVT::i64;
476
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000477 if (RetTyVT != MVT::isVoid)
Andrew Lenharth46a776e2005-09-06 17:00:23 +0000478 RetVals.push_back(ActualRetTyVT);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000479 RetVals.push_back(MVT::Other);
480
Chris Lattner2d90bd52006-01-27 23:39:00 +0000481 std::vector<SDOperand> Ops;
482 Ops.push_back(Chain);
483 Ops.push_back(Callee);
484 Ops.insert(Ops.end(), args_to_use.begin(), args_to_use.end());
485 SDOperand TheCall = DAG.getNode(AlphaISD::CALL, RetVals, Ops);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000486 Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
487 Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
488 DAG.getConstant(NumBytes, getPointerTy()));
Andrew Lenharth46a776e2005-09-06 17:00:23 +0000489 SDOperand RetVal = TheCall;
490
491 if (RetTyVT != ActualRetTyVT) {
492 RetVal = DAG.getNode(RetTy->isSigned() ? ISD::AssertSext : ISD::AssertZext,
493 MVT::i64, RetVal, DAG.getValueType(RetTyVT));
494 RetVal = DAG.getNode(ISD::TRUNCATE, RetTyVT, RetVal);
495 }
496
497 return std::make_pair(RetVal, Chain);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000498}
499
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000500void AlphaTargetLowering::restoreGP(MachineBasicBlock* BB)
501{
502 BuildMI(BB, Alpha::BIS, 2, Alpha::R29).addReg(GP).addReg(GP);
503}
504void AlphaTargetLowering::restoreRA(MachineBasicBlock* BB)
505{
506 BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(RA).addReg(RA);
507}
508
Andrew Lenharth167bc6e2006-01-23 20:59:50 +0000509static int getUID()
510{
511 static int id = 0;
512 return ++id;
513}
514
Andrew Lenharth7f0db912005-11-30 07:19:56 +0000515/// LowerOperation - Provide custom lowering hooks for some operations.
516///
517SDOperand AlphaTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
518 switch (Op.getOpcode()) {
519 default: assert(0 && "Wasn't expecting to be able to lower this!");
520 case ISD::SINT_TO_FP: {
521 assert(MVT::i64 == Op.getOperand(0).getValueType() &&
522 "Unhandled SINT_TO_FP type in custom expander!");
523 SDOperand LD;
524 bool isDouble = MVT::f64 == Op.getValueType();
525 if (useITOF) {
526 LD = DAG.getNode(AlphaISD::ITOFT_, MVT::f64, Op.getOperand(0));
527 } else {
528 int FrameIdx =
529 DAG.getMachineFunction().getFrameInfo()->CreateStackObject(8, 8);
530 SDOperand FI = DAG.getFrameIndex(FrameIdx, MVT::i64);
531 SDOperand ST = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
532 Op.getOperand(0), FI, DAG.getSrcValue(0));
533 LD = DAG.getLoad(MVT::f64, ST, FI, DAG.getSrcValue(0));
534 }
535 SDOperand FP = DAG.getNode(isDouble?AlphaISD::CVTQT_:AlphaISD::CVTQS_,
536 isDouble?MVT::f64:MVT::f32, LD);
537 return FP;
538 }
Andrew Lenharthcd804962005-11-30 16:10:29 +0000539 case ISD::FP_TO_SINT: {
540 bool isDouble = MVT::f64 == Op.getOperand(0).getValueType();
541 SDOperand src = Op.getOperand(0);
542
543 if (!isDouble) //Promote
544 src = DAG.getNode(ISD::FP_EXTEND, MVT::f64, src);
545
546 src = DAG.getNode(AlphaISD::CVTTQ_, MVT::f64, src);
547
548 if (useITOF) {
549 return DAG.getNode(AlphaISD::FTOIT_, MVT::i64, src);
550 } else {
551 int FrameIdx =
552 DAG.getMachineFunction().getFrameInfo()->CreateStackObject(8, 8);
553 SDOperand FI = DAG.getFrameIndex(FrameIdx, MVT::i64);
554 SDOperand ST = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
555 src, FI, DAG.getSrcValue(0));
556 return DAG.getLoad(MVT::i64, ST, FI, DAG.getSrcValue(0));
557 }
Andrew Lenharth7f0db912005-11-30 07:19:56 +0000558 }
Andrew Lenharth4e629512005-12-24 05:36:33 +0000559 case ISD::ConstantPool: {
Evan Chengb8973bd2006-01-31 22:23:14 +0000560 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
561 Constant *C = CP->get();
562 SDOperand CPI = DAG.getTargetConstantPool(C, MVT::i64, CP->getAlignment());
Andrew Lenharth4e629512005-12-24 05:36:33 +0000563
564 SDOperand Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, CPI,
565 DAG.getNode(AlphaISD::GlobalBaseReg, MVT::i64));
566 SDOperand Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, CPI, Hi);
567 return Lo;
568 }
569 case ISD::GlobalAddress: {
570 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
571 GlobalValue *GV = GSDN->getGlobal();
572 SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i64, GSDN->getOffset());
573
574 if (!GV->hasWeakLinkage() && !GV->isExternal()) {
575 SDOperand Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, GA,
576 DAG.getNode(AlphaISD::GlobalBaseReg, MVT::i64));
577 SDOperand Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, GA, Hi);
578 return Lo;
579 } else
Andrew Lenharthc687b482005-12-24 08:29:32 +0000580 return DAG.getNode(AlphaISD::RelLit, MVT::i64, GA, DAG.getNode(AlphaISD::GlobalBaseReg, MVT::i64));
Andrew Lenharth4e629512005-12-24 05:36:33 +0000581 }
Andrew Lenharth53d89702005-12-25 01:34:27 +0000582 case ISD::ExternalSymbol: {
583 return DAG.getNode(AlphaISD::RelLit, MVT::i64,
584 DAG.getTargetExternalSymbol(cast<ExternalSymbolSDNode>(Op)->getSymbol(), MVT::i64),
585 DAG.getNode(AlphaISD::GlobalBaseReg, MVT::i64));
586 }
587
588 case ISD::SDIV:
589 case ISD::UDIV:
590 case ISD::UREM:
591 case ISD::SREM:
592 if (MVT::isInteger(Op.getValueType())) {
593 const char* opstr = 0;
594 switch(Op.getOpcode()) {
595 case ISD::UREM: opstr = "__remqu"; break;
596 case ISD::SREM: opstr = "__remq"; break;
597 case ISD::UDIV: opstr = "__divqu"; break;
598 case ISD::SDIV: opstr = "__divq"; break;
599 }
600 SDOperand Tmp1 = Op.getOperand(0),
601 Tmp2 = Op.getOperand(1),
602 Addr = DAG.getExternalSymbol(opstr, MVT::i64);
603 return DAG.getNode(AlphaISD::DivCall, MVT::i64, Addr, Tmp1, Tmp2);
604 }
605 break;
Andrew Lenharthcd804962005-11-30 16:10:29 +0000606
Nate Begemanacc398c2006-01-25 18:21:52 +0000607 case ISD::VAARG: {
608 SDOperand Chain = Op.getOperand(0);
609 SDOperand VAListP = Op.getOperand(1);
610 SDOperand VAListS = Op.getOperand(2);
611
612 SDOperand Base = DAG.getLoad(MVT::i64, Chain, VAListP, VAListS);
613 SDOperand Tmp = DAG.getNode(ISD::ADD, MVT::i64, VAListP,
614 DAG.getConstant(8, MVT::i64));
615 SDOperand Offset = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Base.getValue(1),
616 Tmp, DAG.getSrcValue(0), MVT::i32);
617 SDOperand DataPtr = DAG.getNode(ISD::ADD, MVT::i64, Base, Offset);
618 if (MVT::isFloatingPoint(Op.getValueType()))
619 {
620 //if fp && Offset < 6*8, then subtract 6*8 from DataPtr
621 SDOperand FPDataPtr = DAG.getNode(ISD::SUB, MVT::i64, DataPtr,
622 DAG.getConstant(8*6, MVT::i64));
623 SDOperand CC = DAG.getSetCC(MVT::i64, Offset,
624 DAG.getConstant(8*6, MVT::i64), ISD::SETLT);
625 DataPtr = DAG.getNode(ISD::SELECT, MVT::i64, CC, FPDataPtr, DataPtr);
626 }
Andrew Lenharth66e49582006-01-23 21:51:33 +0000627
Nate Begemanacc398c2006-01-25 18:21:52 +0000628 SDOperand NewOffset = DAG.getNode(ISD::ADD, MVT::i64, Offset,
629 DAG.getConstant(8, MVT::i64));
630 SDOperand Update = DAG.getNode(ISD::TRUNCSTORE, MVT::Other,
631 Offset.getValue(1), NewOffset,
632 Tmp, DAG.getSrcValue(0),
633 DAG.getValueType(MVT::i32));
634
635 SDOperand Result;
636 if (Op.getValueType() == MVT::i32)
637 Result = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Update, DataPtr,
638 DAG.getSrcValue(0), MVT::i32);
639 else
640 Result = DAG.getLoad(Op.getValueType(), Update, DataPtr,
641 DAG.getSrcValue(0));
642 return Result;
643 }
644 case ISD::VACOPY: {
645 SDOperand Chain = Op.getOperand(0);
646 SDOperand DestP = Op.getOperand(1);
647 SDOperand SrcP = Op.getOperand(2);
648 SDOperand DestS = Op.getOperand(3);
649 SDOperand SrcS = Op.getOperand(4);
650
651 SDOperand Val = DAG.getLoad(getPointerTy(), Chain, SrcP, SrcS);
652 SDOperand Result = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1), Val,
653 DestP, DestS);
654 SDOperand NP = DAG.getNode(ISD::ADD, MVT::i64, SrcP,
655 DAG.getConstant(8, MVT::i64));
656 Val = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Result, NP,
657 DAG.getSrcValue(0), MVT::i32);
658 SDOperand NPD = DAG.getNode(ISD::ADD, MVT::i64, DestP,
659 DAG.getConstant(8, MVT::i64));
660 return DAG.getNode(ISD::TRUNCSTORE, MVT::Other, Val.getValue(1),
661 Val, NPD, DAG.getSrcValue(0),DAG.getValueType(MVT::i32));
662 }
663 case ISD::VASTART: {
664 SDOperand Chain = Op.getOperand(0);
665 SDOperand VAListP = Op.getOperand(1);
666 SDOperand VAListS = Op.getOperand(2);
667
668 // vastart stores the address of the VarArgsBase and VarArgsOffset
669 SDOperand FR = DAG.getFrameIndex(VarArgsBase, MVT::i64);
670 SDOperand S1 = DAG.getNode(ISD::STORE, MVT::Other, Chain, FR, VAListP,
671 VAListS);
672 SDOperand SA2 = DAG.getNode(ISD::ADD, MVT::i64, VAListP,
673 DAG.getConstant(8, MVT::i64));
674 return DAG.getNode(ISD::TRUNCSTORE, MVT::Other, S1,
675 DAG.getConstant(VarArgsOffset, MVT::i64), SA2,
676 DAG.getSrcValue(0), DAG.getValueType(MVT::i32));
677 }
Andrew Lenharthcd804962005-11-30 16:10:29 +0000678 }
679
Andrew Lenharth7f0db912005-11-30 07:19:56 +0000680 return SDOperand();
681}
Nate Begeman0aed7842006-01-28 03:14:31 +0000682
683SDOperand AlphaTargetLowering::CustomPromoteOperation(SDOperand Op,
684 SelectionDAG &DAG) {
685 assert(Op.getValueType() == MVT::i32 &&
686 Op.getOpcode() == ISD::VAARG &&
687 "Unknown node to custom promote!");
688
689 // The code in LowerOperation already handles i32 vaarg
690 return LowerOperation(Op, DAG);
691}