blob: 98d4f93049439bf73186bb7e701f5e21fe28e2df [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);
58 setOperationAction(ISD::EXTLOAD, MVT::i1, Promote);
59 setOperationAction(ISD::EXTLOAD, MVT::f32, Promote);
60
61 setOperationAction(ISD::ZEXTLOAD, MVT::i1, Expand);
62 setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand);
63
64 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
65 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand);
66 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
67 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Expand);
68
69 setOperationAction(ISD::UREM, MVT::i32, Expand);
70 setOperationAction(ISD::SREM, MVT::i32, Expand);
71
72 setOperationAction(ISD::CTPOP, MVT::i32, Expand);
73 setOperationAction(ISD::CTTZ, MVT::i32, Expand);
74 setOperationAction(ISD::CTLZ, MVT::i32, Expand);
75
76 setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
77 setOperationAction(ISD::MEMSET, MVT::Other, Expand);
78 setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
79
80 // We don't support sin/cos/sqrt
81 setOperationAction(ISD::FSIN , MVT::f64, Expand);
82 setOperationAction(ISD::FCOS , MVT::f64, Expand);
83 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
84 setOperationAction(ISD::FSIN , MVT::f32, Expand);
85 setOperationAction(ISD::FCOS , MVT::f32, Expand);
86 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
87
88 computeRegisterProperties();
89
90 addLegalFPImmediate(+0.0); //F31
91 addLegalFPImmediate(-0.0); //-F31
92 }
93
94 /// LowerArguments - This hook must be implemented to indicate how we should
95 /// lower the arguments for the specified function, into the specified DAG.
96 virtual std::vector<SDOperand>
97 LowerArguments(Function &F, SelectionDAG &DAG);
98
99 /// LowerCallTo - This hook lowers an abstract call to a function into an
100 /// actual call.
101 virtual std::pair<SDOperand, SDOperand>
102 LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC,
103 bool isTailCall, SDOperand Callee, ArgListTy &Args,
104 SelectionDAG &DAG);
105 };
106}
107
108/// AddLiveIn - This helper function adds the specified physical register to the
109/// MachineFunction as a live in value. It also creates a corresponding virtual
110/// register for it.
111static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg,
112 TargetRegisterClass *RC) {
113 assert(RC->contains(PReg) && "Not the correct regclass!");
114 unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC);
115 MF.addLiveIn(PReg, VReg);
116 return VReg;
117}
118
119std::vector<SDOperand>
120V8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
121{
122 //FIXME
123 std::vector<SDOperand> ArgValues;
124
125 MachineFunction &MF = DAG.getMachineFunction();
126 MachineFrameInfo*MFI = MF.getFrameInfo();
127
128 MachineBasicBlock& BB = MF.front();
129
130 //return the arguments
131 return ArgValues;
132}
133
134std::pair<SDOperand, SDOperand>
135V8TargetLowering::LowerCallTo(SDOperand Chain,
136 const Type *RetTy, bool isVarArg,
137 unsigned CallingConv, bool isTailCall,
138 SDOperand Callee, ArgListTy &Args,
139 SelectionDAG &DAG) {
140 //FIXME
141 return std::make_pair(Chain, Chain);
142}
143
144namespace {
145
146//===--------------------------------------------------------------------===//
147/// ISel - V8 specific code to select V8 machine instructions for
148/// SelectionDAG operations.
149//===--------------------------------------------------------------------===//
150class ISel : public SelectionDAGISel {
151
152 /// V8Lowering - This object fully describes how to lower LLVM code to an
153 /// V8-specific SelectionDAG.
154 V8TargetLowering V8Lowering;
155
156 SelectionDAG *ISelDAG; // Hack to support us having a dag->dag transform
157 // for sdiv and udiv until it is put into the future
158 // dag combiner.
159
160 /// ExprMap - As shared expressions are codegen'd, we keep track of which
161 /// vreg the value is produced in, so we only emit one copy of each compiled
162 /// tree.
163 static const unsigned notIn = (unsigned)(-1);
164 std::map<SDOperand, unsigned> ExprMap;
165
166public:
167 ISel(TargetMachine &TM) : SelectionDAGISel(V8Lowering), V8Lowering(TM)
168 {}
169
170 /// InstructionSelectBasicBlock - This callback is invoked by
171 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
172 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
173 DEBUG(BB->dump());
174
175 // Codegen the basic block.
176 ISelDAG = &DAG;
177 max_depth = DAG.getRoot().getNodeDepth();
178 Select(DAG.getRoot());
179
180 // Clear state used for selection.
181 ExprMap.clear();
182 }
183
184 virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
185
186 unsigned SelectExpr(SDOperand N);
187 void Select(SDOperand N);
188
189};
190}
191
192void ISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) {
193 // If this function has live-in values, emit the copies from pregs to vregs at
194 // the top of the function, before anything else.
195 MachineBasicBlock *BB = MF.begin();
196 if (MF.livein_begin() != MF.livein_end()) {
197 SSARegMap *RegMap = MF.getSSARegMap();
198 for (MachineFunction::livein_iterator LI = MF.livein_begin(),
199 E = MF.livein_end(); LI != E; ++LI) {
200 const TargetRegisterClass *RC = RegMap->getRegClass(LI->second);
201 if (RC == V8::GPRCRegisterClass) {
202 BuildMI(BB, V8::ORrr, 2, LI->second).addReg(LI->first).addReg(V8::G0);
203 } else if (RC == V8::FPRCRegisterClass) {
204 BuildMI(BB, V8::FMOVSrr, 2, LI->second).addReg(LI->first);
205 } else {
206 assert(0 && "Unknown regclass!");
207 }
208 }
209 }
210}
211
212//These describe LDAx
213static const int IMM_LOW = -32768;
214static const int IMM_HIGH = 32767;
215static const int IMM_MULT = 65536;
216
217static long getUpper16(long l)
218{
219 long y = l / IMM_MULT;
220 if (l % IMM_MULT > IMM_HIGH)
221 ++y;
222 return y;
223}
224
225static long getLower16(long l)
226{
227 long h = getUpper16(l);
228 return l - h * IMM_MULT;
229}
230
231unsigned ISel::SelectExpr(SDOperand N) {
232 unsigned Result;
233 unsigned Tmp1, Tmp2 = 0, Tmp3;
234 unsigned Opc = 0;
235 unsigned opcode = N.getOpcode();
236
237 SDNode *Node = N.Val;
238 MVT::ValueType DestType = N.getValueType();
239
240 unsigned &Reg = ExprMap[N];
241 if (Reg) return Reg;
242
243 if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::TAILCALL)
244 Reg = Result = (N.getValueType() != MVT::Other) ?
245 MakeReg(N.getValueType()) : notIn;
246 else {
247 // If this is a call instruction, make sure to prepare ALL of the result
248 // values as well as the chain.
249 if (Node->getNumValues() == 1)
250 Reg = Result = notIn; // Void call, just a chain.
251 else {
252 Result = MakeReg(Node->getValueType(0));
253 ExprMap[N.getValue(0)] = Result;
254 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
255 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
256 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
257 }
258 }
259
260 switch (opcode) {
261 default:
262 Node->dump();
263 assert(0 && "Node not handled!\n");
264
265 case ISD::EXTLOAD:
266 case ISD::ZEXTLOAD:
267 case ISD::SEXTLOAD:
268 case ISD::LOAD:
269 {
270 // Make sure we generate both values.
271 if (Result != notIn)
272 ExprMap[N.getValue(1)] = notIn; // Generate the token
273 else
274 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
275
276 SDOperand Chain = N.getOperand(0);
277 SDOperand Address = N.getOperand(1);
278 Select(Chain);
279 unsigned Adr = SelectExpr(Address);
280 switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
281 case MVT::i32: Opc = V8::LD;
282 case MVT::i16: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUH : V8::LDSH; break;
283 case MVT::i8: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUB : V8::LDSB; break;
284 case MVT::f64: Opc = V8::LDFSRrr;
285 case MVT::f32: Opc = V8::LDDFrr;
286 default:
287 Node->dump();
288 assert(0 && "Bad type!");
289 break;
290 }
291 BuildMI(BB, Opc, 1, Result).addReg(Adr);
292 return Result;
293 }
294
295 case ISD::TAILCALL:
296 case ISD::CALL:
297 {
298 //FIXME:
299 abort();
300 return Result;
301 }
302
303 case ISD::CopyFromReg:
304 {
305 // Make sure we generate both values.
306 if (Result != notIn)
307 ExprMap[N.getValue(1)] = notIn; // Generate the token
308 else
309 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
310
311 SDOperand Chain = N.getOperand(0);
312 Select(Chain);
313 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
314
315 BuildMI(BB, V8::ORrr, 2, Result).addReg(r).addReg(V8::G0);
316 return Result;
317 }
318
319 //Most of the plain arithmetic and logic share the same form, and the same
320 //constant immediate test
321 case ISD::XOR:
322 case ISD::AND:
323 case ISD::OR:
324 case ISD::SHL:
325 case ISD::SRL:
326 case ISD::SRA:
327 case ISD::ADD:
328 case ISD::SUB:
329 case ISD::SDIV:
330 case ISD::UDIV:
331 case ISD::SMUL:
332 case ISD::UMUL:
333 switch(opcode) {
334 case ISD::XOR: Opc = V8::XORrr; break;
335 case ISD::AND: Opc = V8::ANDrr; break;
336 case ISD::OR: Opc = V8::ORrr; break;
337 case ISD::SHL: Opc = V8::SLLrr; break;
338 case ISD::SRL: Opc = V8::SRLrr; break;
339 case ISD::SRA: Opc = V8::SRArr; break;
340 case ISD::ADD: Opc = V8::ADDrr; break;
341 case ISD::SUB: Opc = V8::SUBrr; break;
342 case ISD::SDIV: Opc = V8::SDIVrr; break;
343 case ISD::UDIV: Opc = V8::UDIVrr; break;
344 case ISD::SMUL: Opc = V8::SMULrr; break;
345 case ISD::UMUL: Opc = V8::UMULrr; break;
346 }
347 Tmp1 = SelectExpr(N.getOperand(0));
348 Tmp2 = SelectExpr(N.getOperand(1));
349 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
350 return Result;
351
352 }
353 return 0;
354}
355
356void ISel::Select(SDOperand N) {
357 unsigned Tmp1, Tmp2, Opc;
358 unsigned opcode = N.getOpcode();
359
360 if (!ExprMap.insert(std::make_pair(N, notIn)).second)
361 return; // Already selected.
362
363 SDNode *Node = N.Val;
364
365 switch (opcode) {
366
367 default:
368 Node->dump(); std::cerr << "\n";
369 assert(0 && "Node not handled yet!");
370
371 case ISD::BRCOND: {
372 //FIXME
373 abort();
374 return;
375 }
376
377 case ISD::BR: {
378 MachineBasicBlock *Dest =
379 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
380
381 Select(N.getOperand(0));
382 BuildMI(BB, V8::BA, 1).addMBB(Dest);
383 return;
384 }
385
386 case ISD::ImplicitDef:
387 Select(N.getOperand(0));
388 BuildMI(BB, V8::IMPLICIT_DEF, 0, cast<RegSDNode>(N)->getReg());
389 return;
390
391 case ISD::EntryToken: return; // Noop
392
393 case ISD::TokenFactor:
394 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
395 Select(Node->getOperand(i));
396 return;
397
398 case ISD::CopyToReg:
399 Select(N.getOperand(0));
400 Tmp1 = SelectExpr(N.getOperand(1));
401 Tmp2 = cast<RegSDNode>(N)->getReg();
402
403 if (Tmp1 != Tmp2) {
404 if (N.getOperand(1).getValueType() == MVT::f64 ||
405 N.getOperand(1).getValueType() == MVT::f32)
406 BuildMI(BB, V8::FMOVS, 2, Tmp2).addReg(Tmp1);
407 else
408 BuildMI(BB, V8::ORrr, 2, Tmp2).addReg(Tmp1).addReg(V8::G0);
409 }
410 return;
411
412 case ISD::RET:
413 //FIXME:
414 abort();
415 return;
416
417 case ISD::TRUNCSTORE:
418 case ISD::STORE:
419 {
420 SDOperand Chain = N.getOperand(0);
421 SDOperand Value = N.getOperand(1);
422 SDOperand Address = N.getOperand(2);
423 Select(Chain);
424
425 Tmp1 = SelectExpr(Value);
426 Tmp2 = SelectExpr(Address);
427
428 unsigned VT = opcode == ISD::STORE ?
429 Value.getValueType() : cast<MVTSDNode>(Node)->getExtraValueType();
430 switch(VT) {
431 default: assert(0 && "unknown Type in store");
432 case MVT::f64: Opc = V8::STDFrr; break;
433 case MVT::f32: Opc = V8::STFrr; break;
434 case MVT::i1: //FIXME: DAG does not promote this load
435 case MVT::i8: Opc = V8::STBrr; break;
436 case MVT::i16: Opc = V8::STHrr; break;
437 case MVT::i32: Opc = V8::STLrr; break;
438 case MVT::i64: Opc = V8::STDrr; break;
439 }
440
441 BuildMI(BB,Opc,2).addReg(Tmp1).addReg(Tmp2);
442 return;
443 }
444
445 case ISD::EXTLOAD:
446 case ISD::SEXTLOAD:
447 case ISD::ZEXTLOAD:
448 case ISD::LOAD:
449 case ISD::CopyFromReg:
450 case ISD::TAILCALL:
451 case ISD::CALL:
452 case ISD::DYNAMIC_STACKALLOC:
453 ExprMap.erase(N);
454 SelectExpr(N);
455 return;
456
457 case ISD::CALLSEQ_START:
458 case ISD::CALLSEQ_END:
459 Select(N.getOperand(0));
460 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
461
462 Opc = N.getOpcode() == ISD::CALLSEQ_START ? V8::ADJUSTCALLSTACKDOWN :
463 V8::ADJUSTCALLSTACKUP;
464 BuildMI(BB, Opc, 1).addImm(Tmp1);
465 return;
466 }
467 assert(0 && "Should not be reached!");
468}
469
470
471/// createV8PatternInstructionSelector - This pass converts an LLVM function
472/// into a machine code representation using pattern matching and a machine
473/// description file.
474///
475FunctionPass *llvm::createV8PatternInstructionSelector(TargetMachine &TM) {
476 return new ISel(TM);
477}
478
479#endif