8d13f241a87f1b435b2d575708729c7d04b5b32d
[oota-llvm.git] / lib / Target / SparcV8 / SparcV8ISelPattern.cpp
1 #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>
37 using namespace llvm;
38
39 //===----------------------------------------------------------------------===//
40 //  V8TargetLowering - SparcV8 Implementation of the TargetLowering interface
41 namespace {
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::BRTWOWAY_CC,  MVT::Other, Expand);
59       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.
112 static 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
120 std::vector<SDOperand>
121 V8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
122 {
123   static const unsigned IncomingArgRegs[] =
124     { V8::I0, V8::I1, V8::I2, V8::I3, V8::I4, V8::I5 };
125   std::vector<SDOperand> ArgValues;
126
127   MachineFunction &MF = DAG.getMachineFunction();
128   MachineFrameInfo*MFI = MF.getFrameInfo();
129
130   MachineBasicBlock& BB = MF.front();
131
132   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:
158         argt = DAG.getCopyFromReg(AddLiveIn(MF, IncomingArgRegs[ArgNo],
159                                             getRegClassFor(MVT::i32)),
160                                   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
194   //return the arguments
195   return ArgValues;
196 }
197
198 std::pair<SDOperand, SDOperand>
199 V8TargetLowering::LowerCallTo(SDOperand Chain,
200                                  const Type *RetTy, bool isVarArg,
201                                  unsigned CallingConv, bool isTailCall,
202                                  SDOperand Callee, ArgListTy &Args,
203                                  SelectionDAG &DAG) {
204   //FIXME
205   return std::make_pair(Chain, Chain);
206 }
207
208 namespace {
209
210 //===--------------------------------------------------------------------===//
211 /// ISel - V8 specific code to select V8 machine instructions for
212 /// SelectionDAG operations.
213 //===--------------------------------------------------------------------===//
214 class 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
230 public:
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   }
247
248   unsigned SelectExpr(SDOperand N);
249   void Select(SDOperand N);
250
251 };
252 }
253
254 //These describe LDAx
255 static const int IMM_LOW  = -32768;
256 static const int IMM_HIGH = 32767;
257 static const int IMM_MULT = 65536;
258
259 static long getUpper16(long l)
260 {
261   long y = l / IMM_MULT;
262   if (l % IMM_MULT > IMM_HIGH)
263     ++y;
264   return y;
265 }
266
267 static long getLower16(long l)
268 {
269   long h = getUpper16(l);
270   return l - h * IMM_MULT;
271 }
272
273 unsigned ISel::SelectExpr(SDOperand N) {
274   unsigned Result;
275   unsigned Tmp1, Tmp2 = 0, Tmp3;
276   unsigned Opc = 0;
277   unsigned opcode = N.getOpcode();
278
279   SDNode *Node = N.Val;
280   MVT::ValueType DestType = N.getValueType();
281
282   unsigned &Reg = ExprMap[N];
283   if (Reg) return Reg;
284
285   if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::TAILCALL)
286     Reg = Result = (N.getValueType() != MVT::Other) ?
287       MakeReg(N.getValueType()) : notIn;
288   else {
289     // If this is a call instruction, make sure to prepare ALL of the result
290     // values as well as the chain.
291     if (Node->getNumValues() == 1)
292       Reg = Result = notIn;  // Void call, just a chain.
293     else {
294       Result = MakeReg(Node->getValueType(0));
295       ExprMap[N.getValue(0)] = Result;
296       for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
297         ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
298       ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
299     }
300   }
301
302   switch (opcode) {
303   default:
304     Node->dump();
305     assert(0 && "Node not handled!\n");
306
307   case ISD::EXTLOAD:
308   case ISD::ZEXTLOAD:
309   case ISD::SEXTLOAD:
310   case ISD::LOAD:
311     {
312       // Make sure we generate both values.
313       if (Result != notIn)
314         ExprMap[N.getValue(1)] = notIn;   // Generate the token
315       else
316         Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
317
318       SDOperand Chain   = N.getOperand(0);
319       SDOperand Address = N.getOperand(1);
320       Select(Chain);
321       unsigned Adr = SelectExpr(Address);
322       switch(cast<VTSDNode>(Node->getOperand(3))->getVT()) {
323       case MVT::i32: Opc = V8::LD;
324       case MVT::i16: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUH : V8::LDSH; break;
325       case MVT::i8:  Opc = opcode == ISD::ZEXTLOAD ? V8::LDUB : V8::LDSB; break;
326       case MVT::f64: Opc = V8::LDFSRrr;
327       case MVT::f32: Opc = V8::LDDFrr;
328       default:
329         Node->dump();
330         assert(0 && "Bad type!");
331         break;
332       }
333       BuildMI(BB, Opc, 1, Result).addReg(Adr);
334       return Result;
335     }
336
337   case ISD::TAILCALL:
338   case ISD::CALL:
339     {
340       //FIXME:
341       abort();
342       return Result;
343     }
344
345   case ISD::CopyFromReg:
346     {
347       // Make sure we generate both values.
348       if (Result != notIn)
349         ExprMap[N.getValue(1)] = notIn;   // Generate the token
350       else
351         Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
352
353       SDOperand Chain   = N.getOperand(0);
354       Select(Chain);
355       unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
356
357       BuildMI(BB, V8::ORrr, 2, Result).addReg(r).addReg(V8::G0);
358       return Result;
359     }
360
361     //Most of the plain arithmetic and logic share the same form, and the same
362     //constant immediate test
363   case ISD::XOR:
364   case ISD::AND:
365   case ISD::OR:
366   case ISD::SHL:
367   case ISD::SRL:
368   case ISD::SRA:
369   case ISD::ADD:
370   case ISD::SUB:
371   case ISD::SDIV:
372   case ISD::UDIV:
373   case ISD::SMUL:
374   case ISD::UMUL:
375     switch(opcode) {
376     case ISD::XOR:  Opc = V8::XORrr; break;
377     case ISD::AND:  Opc = V8::ANDrr; break;
378     case ISD::OR:   Opc = V8::ORrr; break;
379     case ISD::SHL:  Opc = V8::SLLrr; break;
380     case ISD::SRL:  Opc = V8::SRLrr; break;
381     case ISD::SRA:  Opc = V8::SRArr; break;
382     case ISD::ADD:  Opc = V8::ADDrr; break;
383     case ISD::SUB:  Opc = V8::SUBrr; break;
384     case ISD::SDIV: Opc = V8::SDIVrr; break;
385     case ISD::UDIV: Opc = V8::UDIVrr; break;
386     case ISD::SMUL: Opc = V8::SMULrr; break;
387     case ISD::UMUL: Opc = V8::UMULrr; break;
388     }
389     Tmp1 = SelectExpr(N.getOperand(0));
390     Tmp2 = SelectExpr(N.getOperand(1));
391     BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
392     return Result;
393
394   }
395   return 0;
396 }
397
398 void ISel::Select(SDOperand N) {
399   unsigned Tmp1, Tmp2, Opc;
400   unsigned opcode = N.getOpcode();
401
402   if (!ExprMap.insert(std::make_pair(N, notIn)).second)
403     return;  // Already selected.
404
405   SDNode *Node = N.Val;
406
407   switch (opcode) {
408
409   default:
410     Node->dump(); std::cerr << "\n";
411     assert(0 && "Node not handled yet!");
412
413   case ISD::BRCOND: {
414     //FIXME
415     abort();
416     return;
417   }
418
419   case ISD::BR: {
420     MachineBasicBlock *Dest =
421       cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
422
423     Select(N.getOperand(0));
424     BuildMI(BB, V8::BA, 1).addMBB(Dest);
425     return;
426   }
427
428   case ISD::ImplicitDef:
429     Select(N.getOperand(0));
430     BuildMI(BB, V8::IMPLICIT_DEF, 0, cast<RegSDNode>(N)->getReg());
431     return;
432
433   case ISD::EntryToken: return;  // Noop
434
435   case ISD::TokenFactor:
436     for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
437       Select(Node->getOperand(i));
438     return;
439
440   case ISD::CopyToReg:
441     Select(N.getOperand(0));
442     Tmp1 = SelectExpr(N.getOperand(1));
443     Tmp2 = cast<RegSDNode>(N)->getReg();
444
445     if (Tmp1 != Tmp2) {
446       if (N.getOperand(1).getValueType() == MVT::f64 ||
447           N.getOperand(1).getValueType() == MVT::f32)
448         BuildMI(BB, V8::FMOVS, 2, Tmp2).addReg(Tmp1);
449       else
450         BuildMI(BB, V8::ORrr, 2, Tmp2).addReg(Tmp1).addReg(V8::G0);
451     }
452     return;
453
454   case ISD::RET:
455     //FIXME:
456     abort();
457     return;
458
459   case ISD::TRUNCSTORE:
460   case ISD::STORE:
461     {
462       SDOperand Chain   = N.getOperand(0);
463       SDOperand Value = N.getOperand(1);
464       SDOperand Address = N.getOperand(2);
465       Select(Chain);
466
467       Tmp1 = SelectExpr(Value);
468       Tmp2 = SelectExpr(Address);
469
470       unsigned VT = opcode == ISD::STORE ?
471         Value.getValueType() : cast<VTSDNode>(Node->getOperand(4))->getVT();
472       switch(VT) {
473       default: assert(0 && "unknown Type in store");
474       case MVT::f64: Opc = V8::STDFrr; break;
475       case MVT::f32: Opc = V8::STFrr; break;
476       case MVT::i1:  //FIXME: DAG does not promote this load
477       case MVT::i8:  Opc = V8::STBrr; break;
478       case MVT::i16: Opc = V8::STHrr; break;
479       case MVT::i32: Opc = V8::STLrr; break;
480       case MVT::i64: Opc = V8::STDrr; break;
481       }
482
483       BuildMI(BB,Opc,2).addReg(Tmp1).addReg(Tmp2);
484       return;
485     }
486
487   case ISD::EXTLOAD:
488   case ISD::SEXTLOAD:
489   case ISD::ZEXTLOAD:
490   case ISD::LOAD:
491   case ISD::CopyFromReg:
492   case ISD::TAILCALL:
493   case ISD::CALL:
494   case ISD::DYNAMIC_STACKALLOC:
495     ExprMap.erase(N);
496     SelectExpr(N);
497     return;
498
499   case ISD::CALLSEQ_START:
500   case ISD::CALLSEQ_END:
501     Select(N.getOperand(0));
502     Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
503
504     Opc = N.getOpcode() == ISD::CALLSEQ_START ? V8::ADJUSTCALLSTACKDOWN :
505       V8::ADJUSTCALLSTACKUP;
506     BuildMI(BB, Opc, 1).addImm(Tmp1);
507     return;
508   }
509   assert(0 && "Should not be reached!");
510 }
511
512
513 /// createV8PatternInstructionSelector - This pass converts an LLVM function
514 /// into a machine code representation using pattern matching and a machine
515 /// description file.
516 ///
517 FunctionPass *llvm::createV8PatternInstructionSelector(TargetMachine &TM) {
518   return new ISel(TM);
519 }
520
521 #endif