MBlazeISelDAGToDAG.cpp revision 207618
1//===-- MBlazeISelDAGToDAG.cpp - A dag to dag inst selector for MBlaze ----===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an instruction selector for the MBlaze target.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "mblaze-isel"
15#include "MBlaze.h"
16#include "MBlazeMachineFunction.h"
17#include "MBlazeRegisterInfo.h"
18#include "MBlazeSubtarget.h"
19#include "MBlazeTargetMachine.h"
20#include "llvm/GlobalValue.h"
21#include "llvm/Instructions.h"
22#include "llvm/Intrinsics.h"
23#include "llvm/Support/CFG.h"
24#include "llvm/Type.h"
25#include "llvm/CodeGen/MachineConstantPool.h"
26#include "llvm/CodeGen/MachineFunction.h"
27#include "llvm/CodeGen/MachineFrameInfo.h"
28#include "llvm/CodeGen/MachineInstrBuilder.h"
29#include "llvm/CodeGen/MachineRegisterInfo.h"
30#include "llvm/CodeGen/SelectionDAGISel.h"
31#include "llvm/Target/TargetMachine.h"
32#include "llvm/Support/Debug.h"
33#include "llvm/Support/ErrorHandling.h"
34#include "llvm/Support/raw_ostream.h"
35using namespace llvm;
36
37//===----------------------------------------------------------------------===//
38// Instruction Selector Implementation
39//===----------------------------------------------------------------------===//
40
41//===----------------------------------------------------------------------===//
42// MBlazeDAGToDAGISel - MBlaze specific code to select MBlaze machine
43// instructions for SelectionDAG operations.
44//===----------------------------------------------------------------------===//
45namespace {
46
47class MBlazeDAGToDAGISel : public SelectionDAGISel {
48
49  /// TM - Keep a reference to MBlazeTargetMachine.
50  MBlazeTargetMachine &TM;
51
52  /// Subtarget - Keep a pointer to the MBlazeSubtarget around so that we can
53  /// make the right decision when generating code for different targets.
54  const MBlazeSubtarget &Subtarget;
55
56public:
57  explicit MBlazeDAGToDAGISel(MBlazeTargetMachine &tm) :
58  SelectionDAGISel(tm),
59  TM(tm), Subtarget(tm.getSubtarget<MBlazeSubtarget>()) {}
60
61  // Pass Name
62  virtual const char *getPassName() const {
63    return "MBlaze DAG->DAG Pattern Instruction Selection";
64  }
65private:
66  // Include the pieces autogenerated from the target description.
67  #include "MBlazeGenDAGISel.inc"
68
69  /// getTargetMachine - Return a reference to the TargetMachine, casted
70  /// to the target-specific type.
71  const MBlazeTargetMachine &getTargetMachine() {
72    return static_cast<const MBlazeTargetMachine &>(TM);
73  }
74
75  /// getInstrInfo - Return a reference to the TargetInstrInfo, casted
76  /// to the target-specific type.
77  const MBlazeInstrInfo *getInstrInfo() {
78    return getTargetMachine().getInstrInfo();
79  }
80
81  SDNode *getGlobalBaseReg();
82  SDNode *Select(SDNode *N);
83
84  // Complex Pattern.
85  bool SelectAddr(SDNode *Op, SDValue N,
86                  SDValue &Base, SDValue &Offset);
87
88  // Address Selection
89  bool SelectAddrRegReg(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index);
90  bool SelectAddrRegImm(SDNode *Op, SDValue N, SDValue &Disp, SDValue &Base);
91
92  // getI32Imm - Return a target constant with the specified value, of type i32.
93  inline SDValue getI32Imm(unsigned Imm) {
94    return CurDAG->getTargetConstant(Imm, MVT::i32);
95  }
96};
97
98}
99
100/// isIntS32Immediate - This method tests to see if the node is either a 32-bit
101/// or 64-bit immediate, and if the value can be accurately represented as a
102/// sign extension from a 32-bit value.  If so, this returns true and the
103/// immediate.
104static bool isIntS32Immediate(SDNode *N, int32_t &Imm) {
105  unsigned Opc = N->getOpcode();
106  if (Opc != ISD::Constant)
107    return false;
108
109  Imm = (int32_t)cast<ConstantSDNode>(N)->getZExtValue();
110  if (N->getValueType(0) == MVT::i32)
111    return Imm == (int32_t)cast<ConstantSDNode>(N)->getZExtValue();
112  else
113    return Imm == (int64_t)cast<ConstantSDNode>(N)->getZExtValue();
114}
115
116static bool isIntS32Immediate(SDValue Op, int32_t &Imm) {
117  return isIntS32Immediate(Op.getNode(), Imm);
118}
119
120
121/// SelectAddressRegReg - Given the specified addressed, check to see if it
122/// can be represented as an indexed [r+r] operation.  Returns false if it
123/// can be more efficiently represented with [r+imm].
124bool MBlazeDAGToDAGISel::
125SelectAddrRegReg(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index) {
126  if (N.getOpcode() == ISD::FrameIndex) return false;
127  if (N.getOpcode() == ISD::TargetExternalSymbol ||
128      N.getOpcode() == ISD::TargetGlobalAddress)
129    return false;  // direct calls.
130
131  int32_t imm = 0;
132  if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
133    if (isIntS32Immediate(N.getOperand(1), imm))
134      return false;    // r+i
135
136    if (N.getOperand(0).getOpcode() == ISD::TargetJumpTable ||
137        N.getOperand(1).getOpcode() == ISD::TargetJumpTable)
138      return false; // jump tables.
139
140    Base = N.getOperand(1);
141    Index = N.getOperand(0);
142    return true;
143  }
144
145  return false;
146}
147
148/// Returns true if the address N can be represented by a base register plus
149/// a signed 32-bit displacement [r+imm], and if it is not better
150/// represented as reg+reg.
151bool MBlazeDAGToDAGISel::
152SelectAddrRegImm(SDNode *Op, SDValue N, SDValue &Disp, SDValue &Base) {
153  // If this can be more profitably realized as r+r, fail.
154  if (SelectAddrRegReg(Op, N, Disp, Base))
155    return false;
156
157  if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
158    int32_t imm = 0;
159    if (isIntS32Immediate(N.getOperand(1), imm)) {
160      Disp = CurDAG->getTargetConstant(imm, MVT::i32);
161      if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) {
162        Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType());
163      } else {
164        Base = N.getOperand(0);
165      }
166      DEBUG( errs() << "WESLEY: Using Operand Immediate\n" );
167      return true; // [r+i]
168    }
169  } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) {
170    // Loading from a constant address.
171    uint32_t Imm = CN->getZExtValue();
172    Disp = CurDAG->getTargetConstant(Imm, CN->getValueType(0));
173    Base = CurDAG->getRegister(MBlaze::R0, CN->getValueType(0));
174    DEBUG( errs() << "WESLEY: Using Constant Node\n" );
175    return true;
176  }
177
178  Disp = CurDAG->getTargetConstant(0, TM.getTargetLowering()->getPointerTy());
179  if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N))
180    Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType());
181  else
182    Base = N;
183  return true;      // [r+0]
184}
185
186/// getGlobalBaseReg - Output the instructions required to put the
187/// GOT address into a register.
188SDNode *MBlazeDAGToDAGISel::getGlobalBaseReg() {
189  unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF);
190  return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode();
191}
192
193/// ComplexPattern used on MBlazeInstrInfo
194/// Used on MBlaze Load/Store instructions
195bool MBlazeDAGToDAGISel::
196SelectAddr(SDNode *Op, SDValue Addr, SDValue &Offset, SDValue &Base) {
197  // if Address is FI, get the TargetFrameIndex.
198  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
199    Base   = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
200    Offset = CurDAG->getTargetConstant(0, MVT::i32);
201    return true;
202  }
203
204  // on PIC code Load GA
205  if (TM.getRelocationModel() == Reloc::PIC_) {
206    if ((Addr.getOpcode() == ISD::TargetGlobalAddress) ||
207        (Addr.getOpcode() == ISD::TargetConstantPool) ||
208        (Addr.getOpcode() == ISD::TargetJumpTable)){
209      Base   = CurDAG->getRegister(MBlaze::R15, MVT::i32);
210      Offset = Addr;
211      return true;
212    }
213  } else {
214    if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
215        Addr.getOpcode() == ISD::TargetGlobalAddress))
216      return false;
217  }
218
219  // Operand is a result from an ADD.
220  if (Addr.getOpcode() == ISD::ADD) {
221    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
222      if (Predicate_immSExt16(CN)) {
223
224        // If the first operand is a FI, get the TargetFI Node
225        if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
226                                    (Addr.getOperand(0))) {
227          Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
228        } else {
229          Base = Addr.getOperand(0);
230        }
231
232        Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
233        return true;
234      }
235    }
236  }
237
238  Base   = Addr;
239  Offset = CurDAG->getTargetConstant(0, MVT::i32);
240  return true;
241}
242
243/// Select instructions not customized! Used for
244/// expanded, promoted and normal instructions
245SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) {
246  unsigned Opcode = Node->getOpcode();
247  DebugLoc dl = Node->getDebugLoc();
248
249  // Dump information about the Node being selected
250  DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n");
251
252  // If we have a custom node, we already have selected!
253  if (Node->isMachineOpcode()) {
254    DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
255    return NULL;
256  }
257
258  ///
259  // Instruction Selection not handled by the auto-generated
260  // tablegen selection should be handled here.
261  ///
262  switch(Opcode) {
263    default: break;
264
265    // Get target GOT address.
266    case ISD::GLOBAL_OFFSET_TABLE:
267      return getGlobalBaseReg();
268
269    case ISD::FrameIndex: {
270        SDValue imm = CurDAG->getTargetConstant(0, MVT::i32);
271        int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex();
272        EVT VT = Node->getValueType(0);
273        SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
274        unsigned Opc = MBlaze::ADDI;
275        if (Node->hasOneUse())
276          return CurDAG->SelectNodeTo(Node, Opc, VT, TFI, imm);
277        return CurDAG->getMachineNode(Opc, dl, VT, TFI, imm);
278    }
279
280
281    /// Handle direct and indirect calls when using PIC. On PIC, when
282    /// GOT is smaller than about 64k (small code) the GA target is
283    /// loaded with only one instruction. Otherwise GA's target must
284    /// be loaded with 3 instructions.
285    case MBlazeISD::JmpLink: {
286      if (TM.getRelocationModel() == Reloc::PIC_) {
287        SDValue Chain  = Node->getOperand(0);
288        SDValue Callee = Node->getOperand(1);
289        SDValue R20Reg = CurDAG->getRegister(MBlaze::R20, MVT::i32);
290        SDValue InFlag(0, 0);
291
292        if ( (isa<GlobalAddressSDNode>(Callee)) ||
293             (isa<ExternalSymbolSDNode>(Callee)) )
294        {
295          /// Direct call for global addresses and external symbols
296          SDValue GPReg = CurDAG->getRegister(MBlaze::R15, MVT::i32);
297
298          // Use load to get GOT target
299          SDValue Ops[] = { Callee, GPReg, Chain };
300          SDValue Load = SDValue(CurDAG->getMachineNode(MBlaze::LW, dl,
301                                 MVT::i32, MVT::Other, Ops, 3), 0);
302          Chain = Load.getValue(1);
303
304          // Call target must be on T9
305          Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Load, InFlag);
306        } else
307          /// Indirect call
308          Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Callee, InFlag);
309
310        // Emit Jump and Link Register
311        SDNode *ResNode = CurDAG->getMachineNode(MBlaze::BRLID, dl, MVT::Other,
312                                                 MVT::Flag, R20Reg, Chain);
313        Chain  = SDValue(ResNode, 0);
314        InFlag = SDValue(ResNode, 1);
315        ReplaceUses(SDValue(Node, 0), Chain);
316        ReplaceUses(SDValue(Node, 1), InFlag);
317        return ResNode;
318      }
319    }
320  }
321
322  // Select the default instruction
323  SDNode *ResNode = SelectCode(Node);
324
325  DEBUG(errs() << "=> ");
326  if (ResNode == NULL || ResNode == Node)
327    DEBUG(Node->dump(CurDAG));
328  else
329    DEBUG(ResNode->dump(CurDAG));
330  DEBUG(errs() << "\n");
331  return ResNode;
332}
333
334/// createMBlazeISelDag - This pass converts a legalized DAG into a
335/// MBlaze-specific DAG, ready for instruction scheduling.
336FunctionPass *llvm::createMBlazeISelDag(MBlazeTargetMachine &TM) {
337  return new MBlazeDAGToDAGISel(TM);
338}
339