ARMISelDAGToDAG.cpp revision 06c1e7eacb11edd1671eabfc11291b7716be2608
1//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===//
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 ARM target.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ARM.h"
15#include "ARMTargetMachine.h"
16#include "llvm/CallingConv.h"
17#include "llvm/DerivedTypes.h"
18#include "llvm/Function.h"
19#include "llvm/Intrinsics.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/SelectionDAG.h"
24#include "llvm/CodeGen/SelectionDAGISel.h"
25#include "llvm/CodeGen/SSARegMap.h"
26#include "llvm/Target/TargetLowering.h"
27#include "llvm/Support/Debug.h"
28#include <iostream>
29#include <set>
30using namespace llvm;
31
32namespace {
33  class ARMTargetLowering : public TargetLowering {
34  public:
35    ARMTargetLowering(TargetMachine &TM);
36    virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
37    virtual const char *getTargetNodeName(unsigned Opcode) const;
38  };
39
40}
41
42ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
43  : TargetLowering(TM) {
44  setOperationAction(ISD::RET,           MVT::Other, Custom);
45  setOperationAction(ISD::GlobalAddress, MVT::i32,   Custom);
46  setOperationAction(ISD::ConstantPool,  MVT::i32,   Custom);
47}
48
49namespace llvm {
50  namespace ARMISD {
51    enum NodeType {
52      // Start the numbering where the builting ops and target ops leave off.
53      FIRST_NUMBER = ISD::BUILTIN_OP_END+ARM::INSTRUCTION_LIST_END,
54      /// CALL - A direct function call.
55      CALL
56    };
57  }
58}
59
60const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
61  switch (Opcode) {
62  default: return 0;
63  case ARMISD::CALL:          return "ARMISD::CALL";
64  }
65}
66
67// This transforms a ISD::CALL node into a
68// callseq_star <- ARMISD:CALL <- callseq_end
69// chain
70static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
71  SDOperand Chain    = Op.getOperand(0);
72  unsigned CallConv  = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
73  assert(CallConv == CallingConv::C && "unknown calling convention");
74  bool isVarArg      = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
75  assert(isVarArg == false && "VarArg not supported");
76  bool isTailCall    = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0;
77  assert(isTailCall == false && "tail call not supported");
78  SDOperand Callee   = Op.getOperand(4);
79  unsigned NumOps    = (Op.getNumOperands() - 5) / 2;
80
81  // Count how many bytes are to be pushed on the stack. Initially
82  // only the link register.
83  unsigned NumBytes = 4;
84
85  assert(NumOps <= 4); //no args on the stack
86
87  // Adjust the stack pointer for the new arguments...
88  // These operations are automatically eliminated by the prolog/epilog pass
89  Chain = DAG.getCALLSEQ_START(Chain,
90                               DAG.getConstant(NumBytes, MVT::i32));
91
92  static const unsigned regs[] = {
93    ARM::R0, ARM::R1, ARM::R2, ARM::R3
94  };
95
96  std::vector<std::pair<unsigned, SDOperand> > RegsToPass;
97
98  for (unsigned i = 0; i != NumOps; ++i) {
99    SDOperand Arg = Op.getOperand(5+2*i);
100    RegsToPass.push_back(std::make_pair(regs[i], Arg));
101  }
102
103  // Build a sequence of copy-to-reg nodes chained together with token chain
104  // and flag operands which copy the outgoing args into the appropriate regs.
105  SDOperand InFlag;
106  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
107    Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
108                             InFlag);
109    InFlag = Chain.getValue(1);
110  }
111
112  std::vector<MVT::ValueType> NodeTys;
113  NodeTys.push_back(MVT::Other);   // Returns a chain
114  NodeTys.push_back(MVT::Flag);    // Returns a flag for retval copy to use.
115
116  // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
117  // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
118  // node so that legalize doesn't hack it.
119  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
120    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType());
121
122  // If this is a direct call, pass the chain and the callee.
123  assert (Callee.Val);
124  std::vector<SDOperand> Ops;
125  Ops.push_back(Chain);
126  Ops.push_back(Callee);
127
128  unsigned CallOpc = ARMISD::CALL;
129  if (InFlag.Val)
130    Ops.push_back(InFlag);
131  Chain = DAG.getNode(CallOpc, NodeTys, Ops);
132  InFlag = Chain.getValue(1);
133
134  std::vector<SDOperand> ResultVals;
135  NodeTys.clear();
136
137  // If the call has results, copy the values out of the ret val registers.
138  switch (Op.Val->getValueType(0)) {
139  default: assert(0 && "Unexpected ret value!");
140  case MVT::Other:
141    break;
142  case MVT::i32:
143    Chain = DAG.getCopyFromReg(Chain, ARM::R0, MVT::i32, InFlag).getValue(1);
144    ResultVals.push_back(Chain.getValue(0));
145    NodeTys.push_back(MVT::i32);
146  }
147
148  Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
149                      DAG.getConstant(NumBytes, MVT::i32));
150  NodeTys.push_back(MVT::Other);
151
152  if (ResultVals.empty())
153    return Chain;
154
155  ResultVals.push_back(Chain);
156  SDOperand Res = DAG.getNode(ISD::MERGE_VALUES, NodeTys, ResultVals);
157  return Res.getValue(Op.ResNo);
158}
159
160static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) {
161  SDOperand Copy;
162  SDOperand Chain = Op.getOperand(0);
163  switch(Op.getNumOperands()) {
164  default:
165    assert(0 && "Do not know how to return this many arguments!");
166    abort();
167  case 1: {
168    SDOperand LR = DAG.getRegister(ARM::R14, MVT::i32);
169    return DAG.getNode(ISD::BRIND, MVT::Other, Chain, LR);
170  }
171  case 3:
172    Copy = DAG.getCopyToReg(Chain, ARM::R0, Op.getOperand(1), SDOperand());
173    if (DAG.getMachineFunction().liveout_empty())
174      DAG.getMachineFunction().addLiveOut(ARM::R0);
175    break;
176  }
177
178  SDOperand LR = DAG.getRegister(ARM::R14, MVT::i32);
179
180  //bug: the copy and branch should be linked with a flag so that the
181  //scheduller can't move an instruction that destroys R0 in between them
182  //return DAG.getNode(ISD::BRIND, MVT::Other, Copy, LR, Copy.getValue(1));
183
184  return DAG.getNode(ISD::BRIND, MVT::Other, Copy, LR);
185}
186
187static SDOperand LowerFORMAL_ARGUMENT(SDOperand Op, SelectionDAG &DAG,
188				      unsigned ArgNo) {
189  MachineFunction &MF = DAG.getMachineFunction();
190  MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType();
191  assert (ObjectVT == MVT::i32);
192  SDOperand Root = Op.getOperand(0);
193  SSARegMap *RegMap = MF.getSSARegMap();
194
195  unsigned num_regs = 4;
196  static const unsigned REGS[] = {
197    ARM::R0, ARM::R1, ARM::R2, ARM::R3
198  };
199
200  if(ArgNo < num_regs) {
201    unsigned VReg = RegMap->createVirtualRegister(&ARM::IntRegsRegClass);
202    MF.addLiveIn(REGS[ArgNo], VReg);
203    return DAG.getCopyFromReg(Root, VReg, MVT::i32);
204  } else {
205    // If the argument is actually used, emit a load from the right stack
206      // slot.
207    if (!Op.Val->hasNUsesOfValue(0, ArgNo)) {
208      unsigned ArgOffset = (ArgNo - num_regs) * 4;
209
210      MachineFrameInfo *MFI = MF.getFrameInfo();
211      unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8;
212      int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
213      SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
214      return DAG.getLoad(ObjectVT, Root, FIN,
215			 DAG.getSrcValue(NULL));
216    } else {
217      // Don't emit a dead load.
218      return DAG.getNode(ISD::UNDEF, ObjectVT);
219    }
220  }
221}
222
223static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {
224  MVT::ValueType PtrVT = Op.getValueType();
225  ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
226  Constant *C = CP->get();
227  SDOperand CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
228
229  return CPI;
230}
231
232static SDOperand LowerGlobalAddress(SDOperand Op,
233				    SelectionDAG &DAG) {
234  GlobalValue  *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
235  SDOperand CPAddr = DAG.getConstantPool(GV, MVT::i32, 2);
236  return DAG.getLoad(MVT::i32, DAG.getEntryNode(), CPAddr,
237		     DAG.getSrcValue(NULL));
238}
239
240static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) {
241  std::vector<SDOperand> ArgValues;
242  SDOperand Root = Op.getOperand(0);
243
244  for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) {
245    SDOperand ArgVal = LowerFORMAL_ARGUMENT(Op, DAG, ArgNo);
246
247    ArgValues.push_back(ArgVal);
248  }
249
250  bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
251  assert(!isVarArg);
252
253  ArgValues.push_back(Root);
254
255  // Return the new list of results.
256  std::vector<MVT::ValueType> RetVT(Op.Val->value_begin(),
257                                    Op.Val->value_end());
258  return DAG.getNode(ISD::MERGE_VALUES, RetVT, ArgValues);
259}
260
261SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
262  switch (Op.getOpcode()) {
263  default:
264    assert(0 && "Should not custom lower this!");
265    abort();
266  case ISD::ConstantPool:
267    return LowerConstantPool(Op, DAG);
268  case ISD::GlobalAddress:
269    return LowerGlobalAddress(Op, DAG);
270  case ISD::FORMAL_ARGUMENTS:
271    return LowerFORMAL_ARGUMENTS(Op, DAG);
272  case ISD::CALL:
273    return LowerCALL(Op, DAG);
274  case ISD::RET:
275    return LowerRET(Op, DAG);
276  }
277}
278
279//===----------------------------------------------------------------------===//
280// Instruction Selector Implementation
281//===----------------------------------------------------------------------===//
282
283//===--------------------------------------------------------------------===//
284/// ARMDAGToDAGISel - ARM specific code to select ARM machine
285/// instructions for SelectionDAG operations.
286///
287namespace {
288class ARMDAGToDAGISel : public SelectionDAGISel {
289  ARMTargetLowering Lowering;
290
291public:
292  ARMDAGToDAGISel(TargetMachine &TM)
293    : SelectionDAGISel(Lowering), Lowering(TM) {
294  }
295
296  void Select(SDOperand &Result, SDOperand Op);
297  virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
298  bool SelectAddrRegImm(SDOperand N, SDOperand &Offset, SDOperand &Base);
299
300  // Include the pieces autogenerated from the target description.
301#include "ARMGenDAGISel.inc"
302};
303
304void ARMDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
305  DEBUG(BB->dump());
306
307  DAG.setRoot(SelectRoot(DAG.getRoot()));
308  CodeGenMap.clear();
309  HandleMap.clear();
310  ReplaceMap.clear();
311  DAG.RemoveDeadNodes();
312
313  ScheduleAndEmitDAG(DAG);
314}
315
316//register plus/minus 12 bit offset
317bool ARMDAGToDAGISel::SelectAddrRegImm(SDOperand N, SDOperand &Offset,
318				    SDOperand &Base) {
319  Offset = CurDAG->getTargetConstant(0, MVT::i32);
320  if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N)) {
321    Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType());
322  }
323  else
324    Base = N;
325  return true;      //any address fits in a register
326}
327
328void ARMDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
329  SDNode *N = Op.Val;
330
331  switch (N->getOpcode()) {
332  default:
333    SelectCode(Result, Op);
334    break;
335  }
336}
337
338}  // end anonymous namespace
339
340/// createARMISelDag - This pass converts a legalized DAG into a
341/// ARM-specific DAG, ready for instruction scheduling.
342///
343FunctionPass *llvm::createARMISelDag(TargetMachine &TM) {
344  return new ARMDAGToDAGISel(TM);
345}
346