blob: 754c16b6ef57c13a6f9847e64409ce428e501a97 [file] [log] [blame]
Andrew Lenharth72b16d82005-06-17 16:52:12 +00001#if 0
2//===- SparcV8ISelPattern.cpp - A pattern matching isel for SparcV8 -------===//
3//
4// The LLVM Compiler Infrastructure
5//
6// This file was developed by the LLVM research group and is distributed under
7// the University of Illinois Open Source License. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10//
11// This file defines a pattern matching instruction selector for SparcV8.
12//
13//===----------------------------------------------------------------------===//
14
15//Please note that this file is a work in progress, and not a high
16//priority for anyone.
17
18#include "SparcV8.h"
19#include "SparcV8RegisterInfo.h"
20#include "llvm/Constants.h" // FIXME: REMOVE
21#include "llvm/Function.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/MachineConstantPool.h" // FIXME: REMOVE
24#include "llvm/CodeGen/MachineFunction.h"
25#include "llvm/CodeGen/MachineFrameInfo.h"
26#include "llvm/CodeGen/SelectionDAG.h"
27#include "llvm/CodeGen/SelectionDAGISel.h"
28#include "llvm/CodeGen/SSARegMap.h"
29#include "llvm/Target/TargetData.h"
30#include "llvm/Target/TargetLowering.h"
31#include "llvm/Support/MathExtras.h"
32#include "llvm/ADT/Statistic.h"
33#include "llvm/Support/Debug.h"
34#include "llvm/Support/CommandLine.h"
35#include <set>
36#include <algorithm>
37using namespace llvm;
38
39//===----------------------------------------------------------------------===//
40// V8TargetLowering - SparcV8 Implementation of the TargetLowering interface
41namespace {
42 class V8TargetLowering : public TargetLowering {
43 int VarArgsFrameIndex; // FrameIndex for start of varargs area.
44 public:
45 V8TargetLowering(TargetMachine &TM) : TargetLowering(TM) {
46 // Set up the TargetLowering object.
47 //I am having problems with shr n ubyte 1
48 setShiftAmountType(MVT::i32);
49 setSetCCResultType(MVT::i32);
50 setSetCCResultContents(ZeroOrOneSetCCResult);
51
52 //FIXME: get these right
53 addRegisterClass(MVT::i64, V8::GPRCRegisterClass);
54 addRegisterClass(MVT::f64, V8::FPRCRegisterClass);
55 addRegisterClass(MVT::f32, V8::FPRCRegisterClass);
56
57 setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
Nate Begeman7cbd5252005-08-16 19:49:35 +000058 setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand);
Andrew Lenharth72b16d82005-06-17 16:52:12 +000059 setOperationAction(ISD::EXTLOAD, MVT::i1, Promote);
60 setOperationAction(ISD::EXTLOAD, MVT::f32, Promote);
61
62 setOperationAction(ISD::ZEXTLOAD, MVT::i1, Expand);
63 setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand);
64
65 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
66 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand);
67 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
68 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Expand);
69
70 setOperationAction(ISD::UREM, MVT::i32, Expand);
71 setOperationAction(ISD::SREM, MVT::i32, Expand);
72
73 setOperationAction(ISD::CTPOP, MVT::i32, Expand);
74 setOperationAction(ISD::CTTZ, MVT::i32, Expand);
75 setOperationAction(ISD::CTLZ, MVT::i32, Expand);
76
77 setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
78 setOperationAction(ISD::MEMSET, MVT::Other, Expand);
79 setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
80
81 // We don't support sin/cos/sqrt
82 setOperationAction(ISD::FSIN , MVT::f64, Expand);
83 setOperationAction(ISD::FCOS , MVT::f64, Expand);
84 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
85 setOperationAction(ISD::FSIN , MVT::f32, Expand);
86 setOperationAction(ISD::FCOS , MVT::f32, Expand);
87 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
88
89 computeRegisterProperties();
90
91 addLegalFPImmediate(+0.0); //F31
92 addLegalFPImmediate(-0.0); //-F31
93 }
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);
99
100 /// LowerCallTo - This hook lowers an abstract call to a function into an
101 /// actual call.
102 virtual std::pair<SDOperand, SDOperand>
103 LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC,
104 bool isTailCall, SDOperand Callee, ArgListTy &Args,
105 SelectionDAG &DAG);
106 };
107}
108
109/// AddLiveIn - This helper function adds the specified physical register to the
110/// MachineFunction as a live in value. It also creates a corresponding virtual
111/// register for it.
112static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg,
113 TargetRegisterClass *RC) {
114 assert(RC->contains(PReg) && "Not the correct regclass!");
115 unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC);
116 MF.addLiveIn(PReg, VReg);
117 return VReg;
118}
119
120std::vector<SDOperand>
121V8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
122{
Jeff Cohen00b168892005-07-27 06:12:32 +0000123 static const unsigned IncomingArgRegs[] =
Andrew Lenharthe014f892005-06-27 23:59:51 +0000124 { V8::I0, V8::I1, V8::I2, V8::I3, V8::I4, V8::I5 };
Andrew Lenharth72b16d82005-06-17 16:52:12 +0000125 std::vector<SDOperand> ArgValues;
126
127 MachineFunction &MF = DAG.getMachineFunction();
128 MachineFrameInfo*MFI = MF.getFrameInfo();
129
130 MachineBasicBlock& BB = MF.front();
131
Andrew Lenharthe014f892005-06-27 23:59:51 +0000132 unsigned ArgNo = 0;
133 unsigned ArgOffset = 92;
134 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end();
135 I != E; ++I, ++ArgNo) {
136 MVT::ValueType VT = getValueType(I->getType());
137 SDOperand argt;
138 if (ArgNo < 6) {
139 switch(VT) {
140 default:
141 std::cerr << "Unknown Type " << VT << "\n";
142 abort();
143 case MVT::f64:
144 case MVT::i64:
145 //FIXME: figure out the build pair thing
146 assert(0 && "doubles and longs not supported yet");
147 case MVT::f32:
148 argt = DAG.getCopyFromReg(AddLiveIn(MF, IncomingArgRegs[ArgNo],
149 MVT::i32),
150 VT, DAG.getRoot());
151 //copy out of Int reg
152 argt = DAG.getNode(ISD::FP_TO_UINT, MVT::f32, argt);
153 break;
154 case MVT::i1:
155 case MVT::i8:
156 case MVT::i16:
157 case MVT::i32:
Jeff Cohen00b168892005-07-27 06:12:32 +0000158 argt = DAG.getCopyFromReg(AddLiveIn(MF, IncomingArgRegs[ArgNo],
159 getRegClassFor(MVT::i32)),
Andrew Lenharthe014f892005-06-27 23:59:51 +0000160 VT, DAG.getRoot());
161 if (VT != MVT::i32)
162 argt = DAG.getNode(ISD::TRUNCATE, VT, argt);
163 break;
164 }
165 DAG.setRoot(argt.getValue(1));
166 } else {
167 //stack passed
168 switch(VT) {
169 default:
170 std::cerr << "Unknown Type " << VT << "\n";
171 abort();
172 case MVT::f64:
173 case MVT::i64:
174 //FIXME: figure out the build pair thing
175 assert(0 && "doubles and longs not supported yet");
176 case MVT::f32:
177 case MVT::i1:
178 case MVT::i8:
179 case MVT::i16:
180 case MVT::i32:
181 // Create the frame index object for this incoming parameter...
182 int FI = MFI->CreateFixedObject(4, ArgOffset);
183 argt = DAG.getLoad(VT,
184 DAG.getEntryNode(),
185 DAG.getFramIndex(FI, MVT::i32),
186 DAG.getSrcValue(NULL));
187 ArgOffset += 4;
188 break;
189 }
190 ArgValues.push_back(argt);
191 }
192 }
193
Andrew Lenharth72b16d82005-06-17 16:52:12 +0000194 //return the arguments
195 return ArgValues;
196}
197
198std::pair<SDOperand, SDOperand>
199V8TargetLowering::LowerCallTo(SDOperand Chain,
200 const Type *RetTy, bool isVarArg,
201 unsigned CallingConv, bool isTailCall,
Jeff Cohen00b168892005-07-27 06:12:32 +0000202 SDOperand Callee, ArgListTy &Args,
Andrew Lenharth72b16d82005-06-17 16:52:12 +0000203 SelectionDAG &DAG) {
204 //FIXME
205 return std::make_pair(Chain, Chain);
206}
207
208namespace {
209
210//===--------------------------------------------------------------------===//
211/// ISel - V8 specific code to select V8 machine instructions for
212/// SelectionDAG operations.
213//===--------------------------------------------------------------------===//
214class ISel : public SelectionDAGISel {
215
216 /// V8Lowering - This object fully describes how to lower LLVM code to an
217 /// V8-specific SelectionDAG.
218 V8TargetLowering V8Lowering;
219
220 SelectionDAG *ISelDAG; // Hack to support us having a dag->dag transform
221 // for sdiv and udiv until it is put into the future
222 // dag combiner.
223
224 /// ExprMap - As shared expressions are codegen'd, we keep track of which
225 /// vreg the value is produced in, so we only emit one copy of each compiled
226 /// tree.
227 static const unsigned notIn = (unsigned)(-1);
228 std::map<SDOperand, unsigned> ExprMap;
229
230public:
231 ISel(TargetMachine &TM) : SelectionDAGISel(V8Lowering), V8Lowering(TM)
232 {}
233
234 /// InstructionSelectBasicBlock - This callback is invoked by
235 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
236 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
237 DEBUG(BB->dump());
238
239 // Codegen the basic block.
240 ISelDAG = &DAG;
241 max_depth = DAG.getRoot().getNodeDepth();
242 Select(DAG.getRoot());
243
244 // Clear state used for selection.
245 ExprMap.clear();
246 }
Jeff Cohen00b168892005-07-27 06:12:32 +0000247
Andrew Lenharth72b16d82005-06-17 16:52:12 +0000248 virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
249
250 unsigned SelectExpr(SDOperand N);
251 void Select(SDOperand N);
252
253};
254}
255
256void ISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) {
257 // If this function has live-in values, emit the copies from pregs to vregs at
258 // the top of the function, before anything else.
259 MachineBasicBlock *BB = MF.begin();
260 if (MF.livein_begin() != MF.livein_end()) {
261 SSARegMap *RegMap = MF.getSSARegMap();
262 for (MachineFunction::livein_iterator LI = MF.livein_begin(),
263 E = MF.livein_end(); LI != E; ++LI) {
264 const TargetRegisterClass *RC = RegMap->getRegClass(LI->second);
265 if (RC == V8::GPRCRegisterClass) {
266 BuildMI(BB, V8::ORrr, 2, LI->second).addReg(LI->first).addReg(V8::G0);
267 } else if (RC == V8::FPRCRegisterClass) {
268 BuildMI(BB, V8::FMOVSrr, 2, LI->second).addReg(LI->first);
269 } else {
270 assert(0 && "Unknown regclass!");
271 }
272 }
273 }
274}
275
276//These describe LDAx
277static const int IMM_LOW = -32768;
278static const int IMM_HIGH = 32767;
279static const int IMM_MULT = 65536;
280
281static long getUpper16(long l)
282{
283 long y = l / IMM_MULT;
284 if (l % IMM_MULT > IMM_HIGH)
285 ++y;
286 return y;
287}
288
289static long getLower16(long l)
290{
291 long h = getUpper16(l);
292 return l - h * IMM_MULT;
293}
294
295unsigned ISel::SelectExpr(SDOperand N) {
296 unsigned Result;
297 unsigned Tmp1, Tmp2 = 0, Tmp3;
298 unsigned Opc = 0;
299 unsigned opcode = N.getOpcode();
300
301 SDNode *Node = N.Val;
302 MVT::ValueType DestType = N.getValueType();
303
304 unsigned &Reg = ExprMap[N];
305 if (Reg) return Reg;
306
307 if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::TAILCALL)
308 Reg = Result = (N.getValueType() != MVT::Other) ?
309 MakeReg(N.getValueType()) : notIn;
310 else {
311 // If this is a call instruction, make sure to prepare ALL of the result
312 // values as well as the chain.
313 if (Node->getNumValues() == 1)
314 Reg = Result = notIn; // Void call, just a chain.
315 else {
316 Result = MakeReg(Node->getValueType(0));
317 ExprMap[N.getValue(0)] = Result;
318 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
319 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
320 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
321 }
322 }
323
324 switch (opcode) {
325 default:
326 Node->dump();
327 assert(0 && "Node not handled!\n");
328
329 case ISD::EXTLOAD:
330 case ISD::ZEXTLOAD:
331 case ISD::SEXTLOAD:
332 case ISD::LOAD:
333 {
334 // Make sure we generate both values.
335 if (Result != notIn)
336 ExprMap[N.getValue(1)] = notIn; // Generate the token
337 else
338 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
339
340 SDOperand Chain = N.getOperand(0);
341 SDOperand Address = N.getOperand(1);
342 Select(Chain);
343 unsigned Adr = SelectExpr(Address);
Chris Lattnerbce81ae2005-07-10 01:56:13 +0000344 switch(cast<VTSDNode>(Node->getOperand(3))->getVT()) {
Andrew Lenharth72b16d82005-06-17 16:52:12 +0000345 case MVT::i32: Opc = V8::LD;
346 case MVT::i16: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUH : V8::LDSH; break;
347 case MVT::i8: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUB : V8::LDSB; break;
348 case MVT::f64: Opc = V8::LDFSRrr;
349 case MVT::f32: Opc = V8::LDDFrr;
350 default:
Jeff Cohen00b168892005-07-27 06:12:32 +0000351 Node->dump();
Andrew Lenharth72b16d82005-06-17 16:52:12 +0000352 assert(0 && "Bad type!");
353 break;
354 }
355 BuildMI(BB, Opc, 1, Result).addReg(Adr);
356 return Result;
357 }
358
359 case ISD::TAILCALL:
360 case ISD::CALL:
361 {
362 //FIXME:
363 abort();
364 return Result;
365 }
366
367 case ISD::CopyFromReg:
368 {
369 // Make sure we generate both values.
370 if (Result != notIn)
371 ExprMap[N.getValue(1)] = notIn; // Generate the token
372 else
373 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
374
375 SDOperand Chain = N.getOperand(0);
376 Select(Chain);
377 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
Jeff Cohen00b168892005-07-27 06:12:32 +0000378
Andrew Lenharth72b16d82005-06-17 16:52:12 +0000379 BuildMI(BB, V8::ORrr, 2, Result).addReg(r).addReg(V8::G0);
380 return Result;
381 }
382
383 //Most of the plain arithmetic and logic share the same form, and the same
384 //constant immediate test
385 case ISD::XOR:
386 case ISD::AND:
387 case ISD::OR:
388 case ISD::SHL:
389 case ISD::SRL:
390 case ISD::SRA:
391 case ISD::ADD:
392 case ISD::SUB:
393 case ISD::SDIV:
394 case ISD::UDIV:
395 case ISD::SMUL:
396 case ISD::UMUL:
397 switch(opcode) {
398 case ISD::XOR: Opc = V8::XORrr; break;
399 case ISD::AND: Opc = V8::ANDrr; break;
400 case ISD::OR: Opc = V8::ORrr; break;
401 case ISD::SHL: Opc = V8::SLLrr; break;
402 case ISD::SRL: Opc = V8::SRLrr; break;
403 case ISD::SRA: Opc = V8::SRArr; break;
404 case ISD::ADD: Opc = V8::ADDrr; break;
405 case ISD::SUB: Opc = V8::SUBrr; break;
406 case ISD::SDIV: Opc = V8::SDIVrr; break;
407 case ISD::UDIV: Opc = V8::UDIVrr; break;
408 case ISD::SMUL: Opc = V8::SMULrr; break;
409 case ISD::UMUL: Opc = V8::UMULrr; break;
410 }
411 Tmp1 = SelectExpr(N.getOperand(0));
412 Tmp2 = SelectExpr(N.getOperand(1));
413 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
414 return Result;
Jeff Cohen00b168892005-07-27 06:12:32 +0000415
Andrew Lenharth72b16d82005-06-17 16:52:12 +0000416 }
417 return 0;
418}
419
420void ISel::Select(SDOperand N) {
421 unsigned Tmp1, Tmp2, Opc;
422 unsigned opcode = N.getOpcode();
423
424 if (!ExprMap.insert(std::make_pair(N, notIn)).second)
425 return; // Already selected.
426
427 SDNode *Node = N.Val;
428
429 switch (opcode) {
430
431 default:
432 Node->dump(); std::cerr << "\n";
433 assert(0 && "Node not handled yet!");
434
435 case ISD::BRCOND: {
436 //FIXME
437 abort();
438 return;
439 }
440
441 case ISD::BR: {
442 MachineBasicBlock *Dest =
443 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
444
445 Select(N.getOperand(0));
446 BuildMI(BB, V8::BA, 1).addMBB(Dest);
447 return;
448 }
449
450 case ISD::ImplicitDef:
451 Select(N.getOperand(0));
452 BuildMI(BB, V8::IMPLICIT_DEF, 0, cast<RegSDNode>(N)->getReg());
453 return;
454
455 case ISD::EntryToken: return; // Noop
456
457 case ISD::TokenFactor:
458 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
459 Select(Node->getOperand(i));
460 return;
461
462 case ISD::CopyToReg:
463 Select(N.getOperand(0));
464 Tmp1 = SelectExpr(N.getOperand(1));
465 Tmp2 = cast<RegSDNode>(N)->getReg();
466
467 if (Tmp1 != Tmp2) {
468 if (N.getOperand(1).getValueType() == MVT::f64 ||
469 N.getOperand(1).getValueType() == MVT::f32)
470 BuildMI(BB, V8::FMOVS, 2, Tmp2).addReg(Tmp1);
471 else
472 BuildMI(BB, V8::ORrr, 2, Tmp2).addReg(Tmp1).addReg(V8::G0);
473 }
474 return;
475
476 case ISD::RET:
477 //FIXME:
478 abort();
479 return;
480
481 case ISD::TRUNCSTORE:
482 case ISD::STORE:
483 {
484 SDOperand Chain = N.getOperand(0);
485 SDOperand Value = N.getOperand(1);
486 SDOperand Address = N.getOperand(2);
487 Select(Chain);
488
489 Tmp1 = SelectExpr(Value);
490 Tmp2 = SelectExpr(Address);
491
Jeff Cohen00b168892005-07-27 06:12:32 +0000492 unsigned VT = opcode == ISD::STORE ?
Chris Lattner9fadb4c2005-07-10 00:29:18 +0000493 Value.getValueType() : cast<VTSDNode>(Node->getOperand(4))->getVT();
Andrew Lenharth72b16d82005-06-17 16:52:12 +0000494 switch(VT) {
495 default: assert(0 && "unknown Type in store");
496 case MVT::f64: Opc = V8::STDFrr; break;
497 case MVT::f32: Opc = V8::STFrr; break;
498 case MVT::i1: //FIXME: DAG does not promote this load
499 case MVT::i8: Opc = V8::STBrr; break;
500 case MVT::i16: Opc = V8::STHrr; break;
501 case MVT::i32: Opc = V8::STLrr; break;
502 case MVT::i64: Opc = V8::STDrr; break;
503 }
504
505 BuildMI(BB,Opc,2).addReg(Tmp1).addReg(Tmp2);
506 return;
507 }
508
509 case ISD::EXTLOAD:
510 case ISD::SEXTLOAD:
511 case ISD::ZEXTLOAD:
512 case ISD::LOAD:
513 case ISD::CopyFromReg:
514 case ISD::TAILCALL:
515 case ISD::CALL:
516 case ISD::DYNAMIC_STACKALLOC:
517 ExprMap.erase(N);
518 SelectExpr(N);
519 return;
520
521 case ISD::CALLSEQ_START:
522 case ISD::CALLSEQ_END:
523 Select(N.getOperand(0));
524 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
525
526 Opc = N.getOpcode() == ISD::CALLSEQ_START ? V8::ADJUSTCALLSTACKDOWN :
527 V8::ADJUSTCALLSTACKUP;
528 BuildMI(BB, Opc, 1).addImm(Tmp1);
529 return;
530 }
531 assert(0 && "Should not be reached!");
532}
533
534
535/// createV8PatternInstructionSelector - This pass converts an LLVM function
536/// into a machine code representation using pattern matching and a machine
537/// description file.
538///
539FunctionPass *llvm::createV8PatternInstructionSelector(TargetMachine &TM) {
540 return new ISel(TM);
541}
542
543#endif