blob: 3c72e7f9815ef2f3c4f75f1be789d83449ba4af4 [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 Begeman37efe672006-04-22 18:53:45 +0000196 setOperationAction(ISD::BRIND, MVT::i64, Expand);
Nate Begeman750ac1b2006-02-01 07:19:44 +0000197 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
198 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000199
200 setOperationAction(ISD::EXTLOAD, MVT::i1, Promote);
201 setOperationAction(ISD::EXTLOAD, MVT::f32, Expand);
202
203 setOperationAction(ISD::ZEXTLOAD, MVT::i1, Promote);
204 setOperationAction(ISD::ZEXTLOAD, MVT::i32, Expand);
205
206 setOperationAction(ISD::SEXTLOAD, MVT::i1, Promote);
207 setOperationAction(ISD::SEXTLOAD, MVT::i8, Expand);
208 setOperationAction(ISD::SEXTLOAD, MVT::i16, Expand);
209
Andrew Lenharthf3fb71b2005-10-06 16:54:29 +0000210 setOperationAction(ISD::TRUNCSTORE, MVT::i1, Promote);
211
Chris Lattner3e2bafd2005-09-28 22:29:17 +0000212 setOperationAction(ISD::FREM, MVT::f32, Expand);
213 setOperationAction(ISD::FREM, MVT::f64, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000214
215 setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand);
Andrew Lenharth7f0db912005-11-30 07:19:56 +0000216 setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
Andrew Lenharthcd804962005-11-30 16:10:29 +0000217 setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand);
218 setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
219
Andrew Lenharth120ab482005-09-29 22:54:56 +0000220 if (!TM.getSubtarget<AlphaSubtarget>().hasCT()) {
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000221 setOperationAction(ISD::CTPOP , MVT::i64 , Expand);
222 setOperationAction(ISD::CTTZ , MVT::i64 , Expand);
223 setOperationAction(ISD::CTLZ , MVT::i64 , Expand);
224 }
Nate Begemand88fc032006-01-14 03:14:10 +0000225 setOperationAction(ISD::BSWAP , MVT::i64, Expand);
Nate Begeman35ef9132006-01-11 21:21:00 +0000226 setOperationAction(ISD::ROTL , MVT::i64, Expand);
227 setOperationAction(ISD::ROTR , MVT::i64, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000228
Andrew Lenharth53d89702005-12-25 01:34:27 +0000229 setOperationAction(ISD::SREM , MVT::i64, Custom);
230 setOperationAction(ISD::UREM , MVT::i64, Custom);
231 setOperationAction(ISD::SDIV , MVT::i64, Custom);
232 setOperationAction(ISD::UDIV , MVT::i64, Custom);
Andrew Lenharthafe3f492006-04-03 03:18:59 +0000233
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000234 setOperationAction(ISD::MEMMOVE , MVT::Other, Expand);
235 setOperationAction(ISD::MEMSET , MVT::Other, Expand);
236 setOperationAction(ISD::MEMCPY , MVT::Other, Expand);
237
238 // We don't support sin/cos/sqrt
239 setOperationAction(ISD::FSIN , MVT::f64, Expand);
240 setOperationAction(ISD::FCOS , MVT::f64, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000241 setOperationAction(ISD::FSIN , MVT::f32, Expand);
242 setOperationAction(ISD::FCOS , MVT::f32, Expand);
Andrew Lenharth39424472006-01-19 21:10:38 +0000243
244 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000245 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
Chris Lattner9601a862006-03-05 05:08:37 +0000246
247 // FIXME: Alpha supports fcopysign natively!?
248 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
249 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000250
Andrew Lenharthb2156f92005-11-30 17:11:20 +0000251 setOperationAction(ISD::SETCC, MVT::f32, Promote);
Chris Lattnerf73bae12005-11-29 06:16:21 +0000252
253 // We don't have line number support yet.
254 setOperationAction(ISD::LOCATION, MVT::Other, Expand);
Jim Laskeye0bce712006-01-05 01:47:43 +0000255 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
256 setOperationAction(ISD::DEBUG_LABEL, MVT::Other, Expand);
Chris Lattnerb99329e2006-01-13 02:42:53 +0000257
258 // Not implemented yet.
259 setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
260 setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
Andrew Lenharth739027e2006-01-16 21:22:38 +0000261 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand);
262
Andrew Lenharth53d89702005-12-25 01:34:27 +0000263 // We want to legalize GlobalAddress and ConstantPool and
264 // ExternalSymbols nodes into the appropriate instructions to
265 // materialize the address.
266 setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
267 setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
268 setOperationAction(ISD::ExternalSymbol, MVT::i64, Custom);
Andrew Lenharth4e629512005-12-24 05:36:33 +0000269
Andrew Lenharth0e538792006-01-25 21:54:38 +0000270 setOperationAction(ISD::VASTART, MVT::Other, Custom);
Andrew Lenharth677c4f22006-01-25 23:33:32 +0000271 setOperationAction(ISD::VAEND, MVT::Other, Expand);
Andrew Lenharth0e538792006-01-25 21:54:38 +0000272 setOperationAction(ISD::VACOPY, MVT::Other, Custom);
Andrew Lenharth5f8f0e22006-01-25 22:28:07 +0000273 setOperationAction(ISD::VAARG, MVT::Other, Custom);
Nate Begeman0aed7842006-01-28 03:14:31 +0000274 setOperationAction(ISD::VAARG, MVT::i32, Custom);
Andrew Lenharth0e538792006-01-25 21:54:38 +0000275
Andrew Lenharth739027e2006-01-16 21:22:38 +0000276 setStackPointerRegisterToSaveRestore(Alpha::R30);
277
Chris Lattner08a90222006-01-29 06:25:22 +0000278 setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
279 setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000280 addLegalFPImmediate(+0.0); //F31
281 addLegalFPImmediate(-0.0); //-F31
Andrew Lenharth7f0db912005-11-30 07:19:56 +0000282
283 computeRegisterProperties();
284
285 useITOF = TM.getSubtarget<AlphaSubtarget>().hasF2I();
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000286}
287
Andrew Lenharth84a06052006-01-16 19:53:25 +0000288const char *AlphaTargetLowering::getTargetNodeName(unsigned Opcode) const {
289 switch (Opcode) {
290 default: return 0;
291 case AlphaISD::ITOFT_: return "Alpha::ITOFT_";
292 case AlphaISD::FTOIT_: return "Alpha::FTOIT_";
293 case AlphaISD::CVTQT_: return "Alpha::CVTQT_";
294 case AlphaISD::CVTQS_: return "Alpha::CVTQS_";
295 case AlphaISD::CVTTQ_: return "Alpha::CVTTQ_";
296 case AlphaISD::GPRelHi: return "Alpha::GPRelHi";
297 case AlphaISD::GPRelLo: return "Alpha::GPRelLo";
298 case AlphaISD::RelLit: return "Alpha::RelLit";
299 case AlphaISD::GlobalBaseReg: return "Alpha::GlobalBaseReg";
Chris Lattner2d90bd52006-01-27 23:39:00 +0000300 case AlphaISD::CALL: return "Alpha::CALL";
Andrew Lenharth84a06052006-01-16 19:53:25 +0000301 case AlphaISD::DivCall: return "Alpha::DivCall";
302 }
303}
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000304
305//http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PY8AC-TET1_html/callCH3.html#BLOCK21
306
307//For now, just use variable size stack frame format
308
309//In a standard call, the first six items are passed in registers $16
310//- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
311//of argument-to-register correspondence.) The remaining items are
312//collected in a memory argument list that is a naturally aligned
313//array of quadwords. In a standard call, this list, if present, must
314//be passed at 0(SP).
315//7 ... n 0(SP) ... (n-7)*8(SP)
316
317// //#define FP $15
318// //#define RA $26
319// //#define PV $27
320// //#define GP $29
321// //#define SP $30
322
323std::vector<SDOperand>
324AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
325{
326 MachineFunction &MF = DAG.getMachineFunction();
327 MachineFrameInfo *MFI = MF.getFrameInfo();
328 MachineBasicBlock& BB = MF.front();
329 std::vector<SDOperand> ArgValues;
330
Andrew Lenharthf71df332005-09-04 06:12:19 +0000331 unsigned args_int[] = {
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000332 Alpha::R16, Alpha::R17, Alpha::R18, Alpha::R19, Alpha::R20, Alpha::R21};
Andrew Lenharthf71df332005-09-04 06:12:19 +0000333 unsigned args_float[] = {
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000334 Alpha::F16, Alpha::F17, Alpha::F18, Alpha::F19, Alpha::F20, Alpha::F21};
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000335
336 int count = 0;
337
338 GP = AddLiveIn(MF, Alpha::R29, getRegClassFor(MVT::i64));
339 RA = AddLiveIn(MF, Alpha::R26, getRegClassFor(MVT::i64));
340
341 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
342 {
343 SDOperand argt;
344 if (count < 6) {
345 unsigned Vreg;
346 MVT::ValueType VT = getValueType(I->getType());
347 switch (VT) {
348 default:
349 std::cerr << "Unknown Type " << VT << "\n";
350 abort();
351 case MVT::f64:
352 case MVT::f32:
Andrew Lenharthf71df332005-09-04 06:12:19 +0000353 args_float[count] = AddLiveIn(MF, args_float[count], getRegClassFor(VT));
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000354 argt = DAG.getCopyFromReg(DAG.getRoot(), args_float[count], VT);
355 DAG.setRoot(argt.getValue(1));
356 break;
357 case MVT::i1:
358 case MVT::i8:
359 case MVT::i16:
360 case MVT::i32:
361 case MVT::i64:
Andrew Lenharthf71df332005-09-04 06:12:19 +0000362 args_int[count] = AddLiveIn(MF, args_int[count], getRegClassFor(MVT::i64));
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000363 argt = DAG.getCopyFromReg(DAG.getRoot(), args_int[count], MVT::i64);
364 DAG.setRoot(argt.getValue(1));
365 if (VT != MVT::i64) {
366 unsigned AssertOp =
367 I->getType()->isSigned() ? ISD::AssertSext : ISD::AssertZext;
368 argt = DAG.getNode(AssertOp, MVT::i64, argt,
369 DAG.getValueType(VT));
370 argt = DAG.getNode(ISD::TRUNCATE, VT, argt);
371 }
372 break;
373 }
374 } else { //more args
375 // Create the frame index object for this incoming parameter...
376 int FI = MFI->CreateFixedObject(8, 8 * (count - 6));
377
378 // Create the SelectionDAG nodes corresponding to a load
379 //from this parameter
380 SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
381 argt = DAG.getLoad(getValueType(I->getType()),
382 DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL));
383 }
384 ++count;
385 ArgValues.push_back(argt);
386 }
387
388 // If the functions takes variable number of arguments, copy all regs to stack
389 if (F.isVarArg()) {
390 VarArgsOffset = count * 8;
391 std::vector<SDOperand> LS;
392 for (int i = 0; i < 6; ++i) {
Chris Lattnerf2cded72005-09-13 19:03:13 +0000393 if (MRegisterInfo::isPhysicalRegister(args_int[i]))
Andrew Lenharthf71df332005-09-04 06:12:19 +0000394 args_int[i] = AddLiveIn(MF, args_int[i], getRegClassFor(MVT::i64));
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000395 SDOperand argt = DAG.getCopyFromReg(DAG.getRoot(), args_int[i], MVT::i64);
396 int FI = MFI->CreateFixedObject(8, -8 * (6 - i));
397 if (i == 0) VarArgsBase = FI;
398 SDOperand SDFI = DAG.getFrameIndex(FI, MVT::i64);
399 LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, DAG.getRoot(), argt,
400 SDFI, DAG.getSrcValue(NULL)));
401
Chris Lattnerf2cded72005-09-13 19:03:13 +0000402 if (MRegisterInfo::isPhysicalRegister(args_float[i]))
Andrew Lenharthf71df332005-09-04 06:12:19 +0000403 args_float[i] = AddLiveIn(MF, args_float[i], getRegClassFor(MVT::f64));
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000404 argt = DAG.getCopyFromReg(DAG.getRoot(), args_float[i], MVT::f64);
405 FI = MFI->CreateFixedObject(8, - 8 * (12 - i));
406 SDFI = DAG.getFrameIndex(FI, MVT::i64);
407 LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, DAG.getRoot(), argt,
408 SDFI, DAG.getSrcValue(NULL)));
409 }
410
411 //Set up a token factor with all the stack traffic
412 DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, LS));
413 }
414
415 // Finally, inform the code generator which regs we return values in.
416 switch (getValueType(F.getReturnType())) {
417 default: assert(0 && "Unknown type!");
418 case MVT::isVoid: break;
419 case MVT::i1:
420 case MVT::i8:
421 case MVT::i16:
422 case MVT::i32:
423 case MVT::i64:
424 MF.addLiveOut(Alpha::R0);
425 break;
426 case MVT::f32:
427 case MVT::f64:
428 MF.addLiveOut(Alpha::F0);
429 break;
430 }
431
Andrew Lenharthed5d1af2006-04-02 20:13:57 +0000432 //return the arguments+
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000433 return ArgValues;
434}
435
436std::pair<SDOperand, SDOperand>
437AlphaTargetLowering::LowerCallTo(SDOperand Chain,
438 const Type *RetTy, bool isVarArg,
439 unsigned CallingConv, bool isTailCall,
440 SDOperand Callee, ArgListTy &Args,
441 SelectionDAG &DAG) {
442 int NumBytes = 0;
443 if (Args.size() > 6)
444 NumBytes = (Args.size() - 6) * 8;
445
Chris Lattner94dd2922006-02-13 09:00:43 +0000446 Chain = DAG.getCALLSEQ_START(Chain,
447 DAG.getConstant(NumBytes, getPointerTy()));
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000448 std::vector<SDOperand> args_to_use;
449 for (unsigned i = 0, e = Args.size(); i != e; ++i)
450 {
451 switch (getValueType(Args[i].second)) {
452 default: assert(0 && "Unexpected ValueType for argument!");
453 case MVT::i1:
454 case MVT::i8:
455 case MVT::i16:
456 case MVT::i32:
457 // Promote the integer to 64 bits. If the input type is signed use a
458 // sign extend, otherwise use a zero extend.
459 if (Args[i].second->isSigned())
460 Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first);
461 else
462 Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first);
463 break;
464 case MVT::i64:
465 case MVT::f64:
466 case MVT::f32:
467 break;
468 }
469 args_to_use.push_back(Args[i].first);
470 }
471
472 std::vector<MVT::ValueType> RetVals;
473 MVT::ValueType RetTyVT = getValueType(RetTy);
Andrew Lenharth46a776e2005-09-06 17:00:23 +0000474 MVT::ValueType ActualRetTyVT = RetTyVT;
475 if (RetTyVT >= MVT::i1 && RetTyVT <= MVT::i32)
476 ActualRetTyVT = MVT::i64;
477
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000478 if (RetTyVT != MVT::isVoid)
Andrew Lenharth46a776e2005-09-06 17:00:23 +0000479 RetVals.push_back(ActualRetTyVT);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000480 RetVals.push_back(MVT::Other);
481
Chris Lattner2d90bd52006-01-27 23:39:00 +0000482 std::vector<SDOperand> Ops;
483 Ops.push_back(Chain);
484 Ops.push_back(Callee);
485 Ops.insert(Ops.end(), args_to_use.begin(), args_to_use.end());
486 SDOperand TheCall = DAG.getNode(AlphaISD::CALL, RetVals, Ops);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000487 Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
488 Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
489 DAG.getConstant(NumBytes, getPointerTy()));
Andrew Lenharth46a776e2005-09-06 17:00:23 +0000490 SDOperand RetVal = TheCall;
491
492 if (RetTyVT != ActualRetTyVT) {
493 RetVal = DAG.getNode(RetTy->isSigned() ? ISD::AssertSext : ISD::AssertZext,
494 MVT::i64, RetVal, DAG.getValueType(RetTyVT));
495 RetVal = DAG.getNode(ISD::TRUNCATE, RetTyVT, RetVal);
496 }
497
498 return std::make_pair(RetVal, Chain);
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000499}
500
Andrew Lenharthaa38ce42005-09-02 18:46:02 +0000501void AlphaTargetLowering::restoreGP(MachineBasicBlock* BB)
502{
503 BuildMI(BB, Alpha::BIS, 2, Alpha::R29).addReg(GP).addReg(GP);
504}
505void AlphaTargetLowering::restoreRA(MachineBasicBlock* BB)
506{
507 BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(RA).addReg(RA);
508}
509
Andrew Lenharth167bc6e2006-01-23 20:59:50 +0000510static int getUID()
511{
512 static int id = 0;
513 return ++id;
514}
515
Andrew Lenharth7f0db912005-11-30 07:19:56 +0000516/// LowerOperation - Provide custom lowering hooks for some operations.
517///
518SDOperand AlphaTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
519 switch (Op.getOpcode()) {
520 default: assert(0 && "Wasn't expecting to be able to lower this!");
521 case ISD::SINT_TO_FP: {
522 assert(MVT::i64 == Op.getOperand(0).getValueType() &&
523 "Unhandled SINT_TO_FP type in custom expander!");
524 SDOperand LD;
525 bool isDouble = MVT::f64 == Op.getValueType();
526 if (useITOF) {
527 LD = DAG.getNode(AlphaISD::ITOFT_, MVT::f64, Op.getOperand(0));
528 } else {
529 int FrameIdx =
530 DAG.getMachineFunction().getFrameInfo()->CreateStackObject(8, 8);
531 SDOperand FI = DAG.getFrameIndex(FrameIdx, MVT::i64);
532 SDOperand ST = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
533 Op.getOperand(0), FI, DAG.getSrcValue(0));
534 LD = DAG.getLoad(MVT::f64, ST, FI, DAG.getSrcValue(0));
535 }
536 SDOperand FP = DAG.getNode(isDouble?AlphaISD::CVTQT_:AlphaISD::CVTQS_,
537 isDouble?MVT::f64:MVT::f32, LD);
538 return FP;
539 }
Andrew Lenharthcd804962005-11-30 16:10:29 +0000540 case ISD::FP_TO_SINT: {
541 bool isDouble = MVT::f64 == Op.getOperand(0).getValueType();
542 SDOperand src = Op.getOperand(0);
543
544 if (!isDouble) //Promote
545 src = DAG.getNode(ISD::FP_EXTEND, MVT::f64, src);
546
547 src = DAG.getNode(AlphaISD::CVTTQ_, MVT::f64, src);
548
549 if (useITOF) {
550 return DAG.getNode(AlphaISD::FTOIT_, MVT::i64, src);
551 } else {
552 int FrameIdx =
553 DAG.getMachineFunction().getFrameInfo()->CreateStackObject(8, 8);
554 SDOperand FI = DAG.getFrameIndex(FrameIdx, MVT::i64);
555 SDOperand ST = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
556 src, FI, DAG.getSrcValue(0));
557 return DAG.getLoad(MVT::i64, ST, FI, DAG.getSrcValue(0));
558 }
Andrew Lenharth7f0db912005-11-30 07:19:56 +0000559 }
Andrew Lenharth4e629512005-12-24 05:36:33 +0000560 case ISD::ConstantPool: {
Evan Chengb8973bd2006-01-31 22:23:14 +0000561 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
562 Constant *C = CP->get();
563 SDOperand CPI = DAG.getTargetConstantPool(C, MVT::i64, CP->getAlignment());
Andrew Lenharth4e629512005-12-24 05:36:33 +0000564
565 SDOperand Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, CPI,
566 DAG.getNode(AlphaISD::GlobalBaseReg, MVT::i64));
567 SDOperand Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, CPI, Hi);
568 return Lo;
569 }
570 case ISD::GlobalAddress: {
571 GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
572 GlobalValue *GV = GSDN->getGlobal();
573 SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i64, GSDN->getOffset());
574
Andrew Lenharth3e2c7452006-04-06 23:18:45 +0000575 // if (!GV->hasWeakLinkage() && !GV->isExternal() && !GV->hasLinkOnceLinkage()) {
576 if (GV->hasInternalLinkage()) {
Andrew Lenharth4e629512005-12-24 05:36:33 +0000577 SDOperand Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, GA,
578 DAG.getNode(AlphaISD::GlobalBaseReg, MVT::i64));
579 SDOperand Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, GA, Hi);
580 return Lo;
581 } else
Andrew Lenharthc687b482005-12-24 08:29:32 +0000582 return DAG.getNode(AlphaISD::RelLit, MVT::i64, GA, DAG.getNode(AlphaISD::GlobalBaseReg, MVT::i64));
Andrew Lenharth4e629512005-12-24 05:36:33 +0000583 }
Andrew Lenharth53d89702005-12-25 01:34:27 +0000584 case ISD::ExternalSymbol: {
585 return DAG.getNode(AlphaISD::RelLit, MVT::i64,
586 DAG.getTargetExternalSymbol(cast<ExternalSymbolSDNode>(Op)->getSymbol(), MVT::i64),
587 DAG.getNode(AlphaISD::GlobalBaseReg, MVT::i64));
588 }
589
Andrew Lenharth53d89702005-12-25 01:34:27 +0000590 case ISD::UREM:
591 case ISD::SREM:
Andrew Lenharthccd9f982006-04-02 21:08:39 +0000592 //Expand only on constant case
593 if (Op.getOperand(1).getOpcode() == ISD::Constant) {
594 MVT::ValueType VT = Op.Val->getValueType(0);
595 unsigned Opc = Op.Val->getOpcode() == ISD::UREM ? ISD::UDIV : ISD::SDIV;
596 SDOperand Tmp1 = Op.Val->getOpcode() == ISD::UREM ?
597 BuildUDIVSequence(Op, &DAG) :
598 BuildSDIVSequence(Op, &DAG);
599 Tmp1 = DAG.getNode(ISD::MUL, VT, Tmp1, Op.getOperand(1));
600 Tmp1 = DAG.getNode(ISD::SUB, VT, Op.getOperand(0), Tmp1);
601 return Tmp1;
602 }
603 //fall through
604 case ISD::SDIV:
605 case ISD::UDIV:
Andrew Lenharth53d89702005-12-25 01:34:27 +0000606 if (MVT::isInteger(Op.getValueType())) {
Andrew Lenharth253b9e72006-04-06 21:26:32 +0000607 if (Op.getOperand(1).getOpcode() == ISD::Constant)
608 return Op.getOpcode() == ISD::SDIV ? BuildSDIVSequence(Op, &DAG) : BuildUDIVSequence(Op, &DAG);
Andrew Lenharth53d89702005-12-25 01:34:27 +0000609 const char* opstr = 0;
610 switch(Op.getOpcode()) {
611 case ISD::UREM: opstr = "__remqu"; break;
612 case ISD::SREM: opstr = "__remq"; break;
613 case ISD::UDIV: opstr = "__divqu"; break;
614 case ISD::SDIV: opstr = "__divq"; break;
615 }
616 SDOperand Tmp1 = Op.getOperand(0),
617 Tmp2 = Op.getOperand(1),
618 Addr = DAG.getExternalSymbol(opstr, MVT::i64);
619 return DAG.getNode(AlphaISD::DivCall, MVT::i64, Addr, Tmp1, Tmp2);
620 }
621 break;
Andrew Lenharthcd804962005-11-30 16:10:29 +0000622
Nate Begemanacc398c2006-01-25 18:21:52 +0000623 case ISD::VAARG: {
624 SDOperand Chain = Op.getOperand(0);
625 SDOperand VAListP = Op.getOperand(1);
626 SDOperand VAListS = Op.getOperand(2);
627
628 SDOperand Base = DAG.getLoad(MVT::i64, Chain, VAListP, VAListS);
629 SDOperand Tmp = DAG.getNode(ISD::ADD, MVT::i64, VAListP,
630 DAG.getConstant(8, MVT::i64));
631 SDOperand Offset = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Base.getValue(1),
632 Tmp, DAG.getSrcValue(0), MVT::i32);
633 SDOperand DataPtr = DAG.getNode(ISD::ADD, MVT::i64, Base, Offset);
634 if (MVT::isFloatingPoint(Op.getValueType()))
635 {
636 //if fp && Offset < 6*8, then subtract 6*8 from DataPtr
637 SDOperand FPDataPtr = DAG.getNode(ISD::SUB, MVT::i64, DataPtr,
638 DAG.getConstant(8*6, MVT::i64));
639 SDOperand CC = DAG.getSetCC(MVT::i64, Offset,
640 DAG.getConstant(8*6, MVT::i64), ISD::SETLT);
641 DataPtr = DAG.getNode(ISD::SELECT, MVT::i64, CC, FPDataPtr, DataPtr);
642 }
Andrew Lenharth66e49582006-01-23 21:51:33 +0000643
Nate Begemanacc398c2006-01-25 18:21:52 +0000644 SDOperand NewOffset = DAG.getNode(ISD::ADD, MVT::i64, Offset,
645 DAG.getConstant(8, MVT::i64));
646 SDOperand Update = DAG.getNode(ISD::TRUNCSTORE, MVT::Other,
647 Offset.getValue(1), NewOffset,
648 Tmp, DAG.getSrcValue(0),
649 DAG.getValueType(MVT::i32));
650
651 SDOperand Result;
652 if (Op.getValueType() == MVT::i32)
653 Result = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Update, DataPtr,
654 DAG.getSrcValue(0), MVT::i32);
655 else
656 Result = DAG.getLoad(Op.getValueType(), Update, DataPtr,
657 DAG.getSrcValue(0));
658 return Result;
659 }
660 case ISD::VACOPY: {
661 SDOperand Chain = Op.getOperand(0);
662 SDOperand DestP = Op.getOperand(1);
663 SDOperand SrcP = Op.getOperand(2);
664 SDOperand DestS = Op.getOperand(3);
665 SDOperand SrcS = Op.getOperand(4);
666
667 SDOperand Val = DAG.getLoad(getPointerTy(), Chain, SrcP, SrcS);
668 SDOperand Result = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1), Val,
669 DestP, DestS);
670 SDOperand NP = DAG.getNode(ISD::ADD, MVT::i64, SrcP,
671 DAG.getConstant(8, MVT::i64));
672 Val = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Result, NP,
673 DAG.getSrcValue(0), MVT::i32);
674 SDOperand NPD = DAG.getNode(ISD::ADD, MVT::i64, DestP,
675 DAG.getConstant(8, MVT::i64));
676 return DAG.getNode(ISD::TRUNCSTORE, MVT::Other, Val.getValue(1),
677 Val, NPD, DAG.getSrcValue(0),DAG.getValueType(MVT::i32));
678 }
679 case ISD::VASTART: {
680 SDOperand Chain = Op.getOperand(0);
681 SDOperand VAListP = Op.getOperand(1);
682 SDOperand VAListS = Op.getOperand(2);
683
684 // vastart stores the address of the VarArgsBase and VarArgsOffset
685 SDOperand FR = DAG.getFrameIndex(VarArgsBase, MVT::i64);
686 SDOperand S1 = DAG.getNode(ISD::STORE, MVT::Other, Chain, FR, VAListP,
687 VAListS);
688 SDOperand SA2 = DAG.getNode(ISD::ADD, MVT::i64, VAListP,
689 DAG.getConstant(8, MVT::i64));
690 return DAG.getNode(ISD::TRUNCSTORE, MVT::Other, S1,
691 DAG.getConstant(VarArgsOffset, MVT::i64), SA2,
692 DAG.getSrcValue(0), DAG.getValueType(MVT::i32));
693 }
Andrew Lenharthcd804962005-11-30 16:10:29 +0000694 }
695
Andrew Lenharth7f0db912005-11-30 07:19:56 +0000696 return SDOperand();
697}
Nate Begeman0aed7842006-01-28 03:14:31 +0000698
699SDOperand AlphaTargetLowering::CustomPromoteOperation(SDOperand Op,
700 SelectionDAG &DAG) {
701 assert(Op.getValueType() == MVT::i32 &&
702 Op.getOpcode() == ISD::VAARG &&
703 "Unknown node to custom promote!");
704
705 // The code in LowerOperation already handles i32 vaarg
706 return LowerOperation(Op, DAG);
707}