SparcISelDAGToDAG.cpp revision 217aabf89ee0316bb4bbcc460bdc24900fe50a02
1//===-- SparcV8ISelDAGToDAG.cpp - A dag to dag inst selector for SparcV8 --===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an instruction selector for the V8 target
11//
12//===----------------------------------------------------------------------===//
13
14#include "SparcV8.h"
15#include "SparcV8TargetMachine.h"
16#include "llvm/Function.h"
17#include "llvm/CodeGen/MachineFunction.h"
18#include "llvm/CodeGen/SelectionDAG.h"
19#include "llvm/CodeGen/SelectionDAGISel.h"
20#include "llvm/CodeGen/SSARegMap.h"
21#include "llvm/Target/TargetLowering.h"
22#include "llvm/Support/Debug.h"
23#include <iostream>
24using namespace llvm;
25
26//===----------------------------------------------------------------------===//
27// TargetLowering Implementation
28//===----------------------------------------------------------------------===//
29
30namespace {
31  class SparcV8TargetLowering : public TargetLowering {
32  public:
33    SparcV8TargetLowering(TargetMachine &TM);
34
35    virtual std::vector<SDOperand>
36      LowerArguments(Function &F, SelectionDAG &DAG);
37    virtual std::pair<SDOperand, SDOperand>
38      LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
39                  unsigned CC,
40                  bool isTailCall, SDOperand Callee, ArgListTy &Args,
41                  SelectionDAG &DAG);
42
43    virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
44                                    SelectionDAG &DAG);
45    virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP,
46                                   Value *VAListV, SelectionDAG &DAG);
47    virtual std::pair<SDOperand,SDOperand>
48      LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
49                 const Type *ArgTy, SelectionDAG &DAG);
50    virtual std::pair<SDOperand, SDOperand>
51      LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
52                              SelectionDAG &DAG);
53  };
54}
55
56SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM)
57  : TargetLowering(TM) {
58
59  // Set up the register classes.
60  addRegisterClass(MVT::i32, V8::IntRegsRegisterClass);
61  addRegisterClass(MVT::f32, V8::FPRegsRegisterClass);
62  addRegisterClass(MVT::f64, V8::DFPRegsRegisterClass);
63
64  // Sparc doesn't have sext_inreg, replace them with shl/sra
65  setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16  , Expand);
66  setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8   , Expand);
67  setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1   , Expand);
68
69  computeRegisterProperties();
70}
71
72std::vector<SDOperand>
73SparcV8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
74  MachineFunction &MF = DAG.getMachineFunction();
75  SSARegMap *RegMap = MF.getSSARegMap();
76  std::vector<SDOperand> ArgValues;
77
78  static const unsigned GPR[] = {
79    V8::I0, V8::I1, V8::I2, V8::I3, V8::I4, V8::I5
80  };
81  unsigned ArgNo = 0;
82  for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
83    MVT::ValueType ObjectVT = getValueType(I->getType());
84    assert(ArgNo < 6 && "Only args in regs for now");
85
86    switch (ObjectVT) {
87    default: assert(0 && "Unhandled argument type!");
88    // TODO: MVT::i64 & FP
89    case MVT::i1:
90    case MVT::i8:
91    case MVT::i16:
92    case MVT::i32: {
93      unsigned VReg = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
94      MF.addLiveIn(GPR[ArgNo++], VReg);
95      SDOperand Arg = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
96      DAG.setRoot(Arg.getValue(1));
97      if (ObjectVT != MVT::i32) {
98        unsigned AssertOp = I->getType()->isSigned() ? ISD::AssertSext
99                                                     : ISD::AssertZext;
100        Arg = DAG.getNode(AssertOp, MVT::i32, Arg,
101                          DAG.getValueType(ObjectVT));
102        Arg = DAG.getNode(ISD::TRUNCATE, ObjectVT, Arg);
103      }
104      ArgValues.push_back(Arg);
105      break;
106    }
107    case MVT::i64: {
108      unsigned VRegLo = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
109      MF.addLiveIn(GPR[ArgNo++], VRegLo);
110      unsigned VRegHi = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
111      MF.addLiveIn(GPR[ArgNo++], VRegHi);
112      SDOperand ArgLo = DAG.getCopyFromReg(DAG.getRoot(), VRegLo, MVT::i32);
113      SDOperand ArgHi = DAG.getCopyFromReg(ArgLo.getValue(1), VRegHi, MVT::i32);
114      DAG.setRoot(ArgHi.getValue(1));
115      ArgValues.push_back(DAG.getNode(ISD::BUILD_PAIR, MVT::i64, ArgLo, ArgHi));
116      break;
117    }
118    }
119  }
120
121  assert(!F.isVarArg() && "Unimp");
122
123  // Finally, inform the code generator which regs we return values in.
124  switch (getValueType(F.getReturnType())) {
125  default: assert(0 && "Unknown type!");
126  case MVT::isVoid: break;
127  case MVT::i1:
128  case MVT::i8:
129  case MVT::i16:
130  case MVT::i32:
131    MF.addLiveOut(V8::I0);
132    break;
133  case MVT::i64:
134    MF.addLiveOut(V8::I0);
135    MF.addLiveOut(V8::I1);
136    break;
137  case MVT::f32:
138    MF.addLiveOut(V8::F0);
139    break;
140  case MVT::f64:
141    MF.addLiveOut(V8::D0);
142    break;
143  }
144
145  return ArgValues;
146}
147
148std::pair<SDOperand, SDOperand>
149SparcV8TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
150                                   bool isVarArg, unsigned CC,
151                                   bool isTailCall, SDOperand Callee,
152                                   ArgListTy &Args, SelectionDAG &DAG) {
153  assert(0 && "Unimp");
154  abort();
155}
156
157SDOperand SparcV8TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
158                                               SelectionDAG &DAG) {
159  if (Op.getValueType() == MVT::i64) {
160    SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
161                               DAG.getConstant(1, MVT::i32));
162    SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
163                               DAG.getConstant(0, MVT::i32));
164    return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Hi);
165  } else {
166    return DAG.getNode(ISD::RET, MVT::Other, Chain, Op);
167  }
168}
169
170SDOperand SparcV8TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
171                                              Value *VAListV, SelectionDAG &DAG) {
172  assert(0 && "Unimp");
173  abort();
174}
175
176std::pair<SDOperand,SDOperand>
177SparcV8TargetLowering::LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
178                                  const Type *ArgTy, SelectionDAG &DAG) {
179  assert(0 && "Unimp");
180  abort();
181}
182
183std::pair<SDOperand, SDOperand>
184SparcV8TargetLowering::LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
185                                               SelectionDAG &DAG) {
186  assert(0 && "Unimp");
187  abort();
188}
189
190//===----------------------------------------------------------------------===//
191// Instruction Selector Implementation
192//===----------------------------------------------------------------------===//
193
194//===--------------------------------------------------------------------===//
195/// SparcV8DAGToDAGISel - PPC specific code to select Sparc V8 machine
196/// instructions for SelectionDAG operations.
197///
198namespace {
199class SparcV8DAGToDAGISel : public SelectionDAGISel {
200  SparcV8TargetLowering V8Lowering;
201public:
202  SparcV8DAGToDAGISel(TargetMachine &TM)
203    : SelectionDAGISel(V8Lowering), V8Lowering(TM) {}
204
205  SDOperand Select(SDOperand Op);
206
207  // Complex Pattern Selectors.
208  bool SelectADDRrr(SDOperand N, SDOperand &R1, SDOperand &R2);
209  bool SelectADDRri(SDOperand N, SDOperand &Base, SDOperand &Offset);
210
211  /// InstructionSelectBasicBlock - This callback is invoked by
212  /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
213  virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
214
215  virtual const char *getPassName() const {
216    return "PowerPC DAG->DAG Pattern Instruction Selection";
217  }
218
219  // Include the pieces autogenerated from the target description.
220#include "SparcV8GenDAGISel.inc"
221};
222}  // end anonymous namespace
223
224/// InstructionSelectBasicBlock - This callback is invoked by
225/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
226void SparcV8DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
227  DEBUG(BB->dump());
228
229  // Select target instructions for the DAG.
230  DAG.setRoot(Select(DAG.getRoot()));
231  CodeGenMap.clear();
232  DAG.RemoveDeadNodes();
233
234  // Emit machine code to BB.
235  ScheduleAndEmitDAG(DAG);
236}
237
238bool SparcV8DAGToDAGISel::SelectADDRrr(SDOperand N, SDOperand &R1,
239                                       SDOperand &R2) {
240  // FIXME: This should obviously be smarter.
241  R1 = Select(N);
242  R2 = CurDAG->getRegister(V8::G0, MVT::i32);
243  return true;
244}
245
246bool SparcV8DAGToDAGISel::SelectADDRri(SDOperand N, SDOperand &Base,
247                                       SDOperand &Offset) {
248  // FIXME: This should obviously be smarter.
249  Base = Select(N);
250  Offset = CurDAG->getTargetConstant(0, MVT::i32);
251  return true;
252}
253
254
255SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) {
256  SDNode *N = Op.Val;
257  if (N->getOpcode() >= ISD::BUILTIN_OP_END/* &&
258      N->getOpcode() < V8ISD::FIRST_NUMBER*/)
259    return Op;   // Already selected.
260                 // If this has already been converted, use it.
261  std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(Op);
262  if (CGMI != CodeGenMap.end()) return CGMI->second;
263
264  switch (N->getOpcode()) {
265  default: break;
266  case ISD::RET: {
267    if (N->getNumOperands() == 2) {
268      SDOperand Chain = Select(N->getOperand(0));     // Token chain.
269      SDOperand Val = Select(N->getOperand(1));
270      if (N->getOperand(1).getValueType() == MVT::i32) {
271        Chain = CurDAG->getCopyToReg(Chain, V8::I0, Val);
272      } else if (N->getOperand(1).getValueType() == MVT::f32) {
273        Chain = CurDAG->getCopyToReg(Chain, V8::F0, Val);
274      } else {
275        assert(N->getOperand(1).getValueType() == MVT::f64);
276        Chain = CurDAG->getCopyToReg(Chain, V8::D0, Val);
277      }
278      return CurDAG->SelectNodeTo(N, V8::RETL, MVT::Other, Chain);
279    } else if (N->getNumOperands() > 1) {
280      SDOperand Chain = Select(N->getOperand(0));     // Token chain.
281      assert(N->getOperand(1).getValueType() == MVT::i32 &&
282             N->getOperand(2).getValueType() == MVT::i32 &&
283             N->getNumOperands() == 3 && "Unknown two-register ret value!");
284      Chain = CurDAG->getCopyToReg(Chain, V8::I0, Select(N->getOperand(1)));
285      Chain = CurDAG->getCopyToReg(Chain, V8::I1, Select(N->getOperand(2)));
286      return CurDAG->SelectNodeTo(N, V8::RETL, MVT::Other, Chain);
287    }
288    break;  // Generated code handles the void case.
289  }
290  }
291
292  return SelectCode(Op);
293}
294
295
296/// createPPCISelDag - This pass converts a legalized DAG into a
297/// PowerPC-specific DAG, ready for instruction scheduling.
298///
299FunctionPass *llvm::createSparcV8ISelDag(TargetMachine &TM) {
300  return new SparcV8DAGToDAGISel(TM);
301}
302