SparcISelDAGToDAG.cpp revision 4b4863188fe226c00d961ec611f2eb1ee8aac4c0
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  computeRegisterProperties();
65}
66
67std::vector<SDOperand>
68SparcV8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
69  MachineFunction &MF = DAG.getMachineFunction();
70  SSARegMap *RegMap = MF.getSSARegMap();
71  std::vector<SDOperand> ArgValues;
72
73  static const unsigned GPR[] = {
74    V8::I0, V8::I1, V8::I2, V8::I3, V8::I4, V8::I5
75  };
76  unsigned ArgNo = 0;
77  for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
78    MVT::ValueType ObjectVT = getValueType(I->getType());
79    assert(ArgNo < 6 && "Only args in regs for now");
80
81    switch (ObjectVT) {
82    default: assert(0 && "Unhandled argument type!");
83    // TODO: MVT::i64 & FP
84    case MVT::i1:
85    case MVT::i8:
86    case MVT::i16:
87    case MVT::i32: {
88      unsigned VReg = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
89      MF.addLiveIn(GPR[ArgNo++], VReg);
90      SDOperand Arg = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
91      DAG.setRoot(Arg.getValue(1));
92      if (ObjectVT != MVT::i32) {
93        unsigned AssertOp = I->getType()->isSigned() ? ISD::AssertSext
94                                                     : ISD::AssertZext;
95        Arg = DAG.getNode(AssertOp, MVT::i32, Arg,
96                          DAG.getValueType(ObjectVT));
97        Arg = DAG.getNode(ISD::TRUNCATE, ObjectVT, Arg);
98      }
99      ArgValues.push_back(Arg);
100    }
101    }
102  }
103
104  assert(!F.isVarArg() && "Unimp");
105
106  // Finally, inform the code generator which regs we return values in.
107  switch (getValueType(F.getReturnType())) {
108  default: assert(0 && "Unknown type!");
109  case MVT::isVoid: break;
110  case MVT::i1:
111  case MVT::i8:
112  case MVT::i16:
113  case MVT::i32:
114    MF.addLiveOut(V8::I0);
115    break;
116  case MVT::i64:
117    MF.addLiveOut(V8::I0);
118    MF.addLiveOut(V8::I1);
119    break;
120  case MVT::f32:
121    MF.addLiveOut(V8::F0);
122    break;
123  case MVT::f64:
124    MF.addLiveOut(V8::D0);
125    break;
126  }
127
128  return ArgValues;
129}
130
131std::pair<SDOperand, SDOperand>
132SparcV8TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
133                                   bool isVarArg, unsigned CC,
134                                   bool isTailCall, SDOperand Callee,
135                                   ArgListTy &Args, SelectionDAG &DAG) {
136  assert(0 && "Unimp");
137  abort();
138}
139
140SDOperand SparcV8TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
141                                               SelectionDAG &DAG) {
142  if (Op.getValueType() == MVT::i64) {
143    SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
144                               DAG.getConstant(1, MVT::i32));
145    SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
146                               DAG.getConstant(0, MVT::i32));
147    return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Hi);
148  } else {
149    return DAG.getNode(ISD::RET, MVT::Other, Chain, Op);
150  }
151}
152
153SDOperand SparcV8TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
154                                              Value *VAListV, SelectionDAG &DAG) {
155  assert(0 && "Unimp");
156  abort();
157}
158
159std::pair<SDOperand,SDOperand>
160SparcV8TargetLowering::LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
161                                  const Type *ArgTy, SelectionDAG &DAG) {
162  assert(0 && "Unimp");
163  abort();
164}
165
166std::pair<SDOperand, SDOperand>
167SparcV8TargetLowering::LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
168                                               SelectionDAG &DAG) {
169  assert(0 && "Unimp");
170  abort();
171}
172
173//===----------------------------------------------------------------------===//
174// Instruction Selector Implementation
175//===----------------------------------------------------------------------===//
176
177//===--------------------------------------------------------------------===//
178/// SparcV8DAGToDAGISel - PPC specific code to select Sparc V8 machine
179/// instructions for SelectionDAG operations.
180///
181namespace {
182class SparcV8DAGToDAGISel : public SelectionDAGISel {
183  SparcV8TargetLowering V8Lowering;
184public:
185  SparcV8DAGToDAGISel(TargetMachine &TM)
186    : SelectionDAGISel(V8Lowering), V8Lowering(TM) {}
187
188  SDOperand Select(SDOperand Op);
189
190  /// InstructionSelectBasicBlock - This callback is invoked by
191  /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
192  virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
193
194  virtual const char *getPassName() const {
195    return "PowerPC DAG->DAG Pattern Instruction Selection";
196  }
197
198  // Include the pieces autogenerated from the target description.
199#include "SparcV8GenDAGISel.inc"
200};
201}  // end anonymous namespace
202
203/// InstructionSelectBasicBlock - This callback is invoked by
204/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
205void SparcV8DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
206  DEBUG(BB->dump());
207
208  // Select target instructions for the DAG.
209  DAG.setRoot(Select(DAG.getRoot()));
210  CodeGenMap.clear();
211  DAG.RemoveDeadNodes();
212
213  // Emit machine code to BB.
214  ScheduleAndEmitDAG(DAG);
215}
216
217
218SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) {
219  SDNode *N = Op.Val;
220  if (N->getOpcode() >= ISD::BUILTIN_OP_END/* &&
221      N->getOpcode() < V8ISD::FIRST_NUMBER*/)
222    return Op;   // Already selected.
223                 // If this has already been converted, use it.
224  std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(Op);
225  if (CGMI != CodeGenMap.end()) return CGMI->second;
226
227  switch (N->getOpcode()) {
228  default: break;
229  case ISD::RET: {
230    if (N->getNumOperands() == 2) {
231      SDOperand Chain = Select(N->getOperand(0));     // Token chain.
232      SDOperand Val = Select(N->getOperand(1));
233      if (N->getOperand(1).getValueType() == MVT::i32) {
234        Chain = CurDAG->getCopyToReg(Chain, V8::I0, Val);
235      } else if (N->getOperand(1).getValueType() == MVT::f32) {
236        Chain = CurDAG->getCopyToReg(Chain, V8::F0, Val);
237      } else {
238        assert(N->getOperand(1).getValueType() == MVT::f64);
239        Chain = CurDAG->getCopyToReg(Chain, V8::D0, Val);
240      }
241      return CurDAG->SelectNodeTo(N, V8::RETL, MVT::Other, Chain);
242    } else if (N->getNumOperands() > 1) {
243      SDOperand Chain = Select(N->getOperand(0));     // Token chain.
244      assert(N->getOperand(1).getValueType() == MVT::i32 &&
245             N->getOperand(2).getValueType() == MVT::i32 &&
246             N->getNumOperands() == 3 && "Unknown two-register ret value!");
247      Chain = CurDAG->getCopyToReg(Chain, V8::I0, Select(N->getOperand(1)));
248      Chain = CurDAG->getCopyToReg(Chain, V8::I1, Select(N->getOperand(2)));
249      return CurDAG->SelectNodeTo(N, V8::RETL, MVT::Other, Chain);
250    }
251    break;  // Generated code handles the void case.
252  }
253  }
254
255  return SelectCode(Op);
256}
257
258
259/// createPPCISelDag - This pass converts a legalized DAG into a
260/// PowerPC-specific DAG, ready for instruction scheduling.
261///
262FunctionPass *llvm::createSparcV8ISelDag(TargetMachine &TM) {
263  return new SparcV8DAGToDAGISel(TM);
264}
265