XCoreISelDAGToDAG.cpp revision 218893
1//===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===//
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 XCore target.
11//
12//===----------------------------------------------------------------------===//
13
14#include "XCore.h"
15#include "XCoreTargetMachine.h"
16#include "llvm/DerivedTypes.h"
17#include "llvm/Function.h"
18#include "llvm/Intrinsics.h"
19#include "llvm/CallingConv.h"
20#include "llvm/Constants.h"
21#include "llvm/LLVMContext.h"
22#include "llvm/CodeGen/MachineFrameInfo.h"
23#include "llvm/CodeGen/MachineFunction.h"
24#include "llvm/CodeGen/MachineInstrBuilder.h"
25#include "llvm/CodeGen/MachineRegisterInfo.h"
26#include "llvm/CodeGen/SelectionDAG.h"
27#include "llvm/CodeGen/SelectionDAGISel.h"
28#include "llvm/Target/TargetLowering.h"
29#include "llvm/Support/Compiler.h"
30#include "llvm/Support/Debug.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/raw_ostream.h"
33#include <queue>
34#include <set>
35using namespace llvm;
36
37/// XCoreDAGToDAGISel - XCore specific code to select XCore machine
38/// instructions for SelectionDAG operations.
39///
40namespace {
41  class XCoreDAGToDAGISel : public SelectionDAGISel {
42    const XCoreTargetLowering &Lowering;
43    const XCoreSubtarget &Subtarget;
44
45  public:
46    XCoreDAGToDAGISel(XCoreTargetMachine &TM)
47      : SelectionDAGISel(TM),
48        Lowering(*TM.getTargetLowering()),
49        Subtarget(*TM.getSubtargetImpl()) { }
50
51    SDNode *Select(SDNode *N);
52
53    /// getI32Imm - Return a target constant with the specified value, of type
54    /// i32.
55    inline SDValue getI32Imm(unsigned Imm) {
56      return CurDAG->getTargetConstant(Imm, MVT::i32);
57    }
58
59    inline bool immMskBitp(SDNode *inN) const {
60      ConstantSDNode *N = cast<ConstantSDNode>(inN);
61      uint32_t value = (uint32_t)N->getZExtValue();
62      if (!isMask_32(value)) {
63        return false;
64      }
65      int msksize = 32 - CountLeadingZeros_32(value);
66      return (msksize >= 1 && msksize <= 8) ||
67              msksize == 16 || msksize == 24 || msksize == 32;
68    }
69
70    // Complex Pattern Selectors.
71    bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset);
72    bool SelectADDRdpii(SDValue Addr, SDValue &Base, SDValue &Offset);
73    bool SelectADDRcpii(SDValue Addr, SDValue &Base, SDValue &Offset);
74
75    virtual const char *getPassName() const {
76      return "XCore DAG->DAG Pattern Instruction Selection";
77    }
78
79    // Include the pieces autogenerated from the target description.
80  #include "XCoreGenDAGISel.inc"
81  };
82}  // end anonymous namespace
83
84/// createXCoreISelDag - This pass converts a legalized DAG into a
85/// XCore-specific DAG, ready for instruction scheduling.
86///
87FunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM) {
88  return new XCoreDAGToDAGISel(TM);
89}
90
91bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base,
92                                       SDValue &Offset) {
93  FrameIndexSDNode *FIN = 0;
94  if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
95    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
96    Offset = CurDAG->getTargetConstant(0, MVT::i32);
97    return true;
98  }
99  if (Addr.getOpcode() == ISD::ADD) {
100    ConstantSDNode *CN = 0;
101    if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
102      && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
103      && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
104      // Constant positive word offset from frame index
105      Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
106      Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
107      return true;
108    }
109  }
110  return false;
111}
112
113bool XCoreDAGToDAGISel::SelectADDRdpii(SDValue Addr, SDValue &Base,
114                                       SDValue &Offset) {
115  if (Addr.getOpcode() == XCoreISD::DPRelativeWrapper) {
116    Base = Addr.getOperand(0);
117    Offset = CurDAG->getTargetConstant(0, MVT::i32);
118    return true;
119  }
120  if (Addr.getOpcode() == ISD::ADD) {
121    ConstantSDNode *CN = 0;
122    if ((Addr.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper)
123      && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
124      && (CN->getSExtValue() % 4 == 0)) {
125      // Constant word offset from a object in the data region
126      Base = Addr.getOperand(0).getOperand(0);
127      Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
128      return true;
129    }
130  }
131  return false;
132}
133
134bool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Addr, SDValue &Base,
135                                       SDValue &Offset) {
136  if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) {
137    Base = Addr.getOperand(0);
138    Offset = CurDAG->getTargetConstant(0, MVT::i32);
139    return true;
140  }
141  if (Addr.getOpcode() == ISD::ADD) {
142    ConstantSDNode *CN = 0;
143    if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper)
144      && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
145      && (CN->getSExtValue() % 4 == 0)) {
146      // Constant word offset from a object in the data region
147      Base = Addr.getOperand(0).getOperand(0);
148      Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
149      return true;
150    }
151  }
152  return false;
153}
154
155SDNode *XCoreDAGToDAGISel::Select(SDNode *N) {
156  DebugLoc dl = N->getDebugLoc();
157  EVT NVT = N->getValueType(0);
158  if (NVT == MVT::i32) {
159    switch (N->getOpcode()) {
160      default: break;
161      case ISD::Constant: {
162        uint64_t Val = cast<ConstantSDNode>(N)->getZExtValue();
163        if (immMskBitp(N)) {
164          // Transformation function: get the size of a mask
165          // Look for the first non-zero bit
166          SDValue MskSize = getI32Imm(32 - CountLeadingZeros_32(Val));
167          return CurDAG->getMachineNode(XCore::MKMSK_rus, dl,
168                                        MVT::i32, MskSize);
169        }
170        else if (!isUInt<16>(Val)) {
171          SDValue CPIdx =
172            CurDAG->getTargetConstantPool(ConstantInt::get(
173                                  Type::getInt32Ty(*CurDAG->getContext()), Val),
174                                          TLI.getPointerTy());
175          return CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32,
176                                        MVT::Other, CPIdx,
177                                        CurDAG->getEntryNode());
178        }
179        break;
180      }
181      case XCoreISD::LADD: {
182        SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
183                            N->getOperand(2) };
184        return CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32,
185                                      Ops, 3);
186      }
187      case XCoreISD::LSUB: {
188        SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
189                            N->getOperand(2) };
190        return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
191                                      Ops, 3);
192      }
193      case XCoreISD::MACCU: {
194        SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
195                          N->getOperand(2), N->getOperand(3) };
196        return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32,
197                                      Ops, 4);
198      }
199      case XCoreISD::MACCS: {
200        SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
201                          N->getOperand(2), N->getOperand(3) };
202        return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32,
203                                      Ops, 4);
204      }
205      case XCoreISD::LMUL: {
206        SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
207                          N->getOperand(2), N->getOperand(3) };
208        return CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32, MVT::i32,
209                                      Ops, 4);
210      }
211      // Other cases are autogenerated.
212    }
213  }
214  return SelectCode(N);
215}
216