LLVM  3.7.0
XCoreISelDAGToDAG.cpp
Go to the documentation of this file.
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"
22 #include "llvm/IR/CallingConv.h"
23 #include "llvm/IR/Constants.h"
24 #include "llvm/IR/DerivedTypes.h"
25 #include "llvm/IR/Function.h"
26 #include "llvm/IR/Intrinsics.h"
27 #include "llvm/IR/LLVMContext.h"
28 #include "llvm/Support/Compiler.h"
29 #include "llvm/Support/Debug.h"
33 using namespace llvm;
34 
35 /// XCoreDAGToDAGISel - XCore specific code to select XCore machine
36 /// instructions for SelectionDAG operations.
37 ///
38 namespace {
39  class XCoreDAGToDAGISel : public SelectionDAGISel {
40 
41  public:
42  XCoreDAGToDAGISel(XCoreTargetMachine &TM, CodeGenOpt::Level OptLevel)
43  : SelectionDAGISel(TM, OptLevel) {}
44 
45  SDNode *Select(SDNode *N) override;
46  SDNode *SelectBRIND(SDNode *N);
47 
48  /// getI32Imm - Return a target constant with the specified value, of type
49  /// i32.
50  inline SDValue getI32Imm(unsigned Imm, SDLoc dl) {
51  return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
52  }
53 
54  inline bool immMskBitp(SDNode *inN) const {
55  ConstantSDNode *N = cast<ConstantSDNode>(inN);
56  uint32_t value = (uint32_t)N->getZExtValue();
57  if (!isMask_32(value)) {
58  return false;
59  }
60  int msksize = 32 - countLeadingZeros(value);
61  return (msksize >= 1 && msksize <= 8) ||
62  msksize == 16 || msksize == 24 || msksize == 32;
63  }
64 
65  // Complex Pattern Selectors.
66  bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset);
67 
68  bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
69  std::vector<SDValue> &OutOps) override;
70 
71  const char *getPassName() const override {
72  return "XCore DAG->DAG Pattern Instruction Selection";
73  }
74 
75  // Include the pieces autogenerated from the target description.
76  #include "XCoreGenDAGISel.inc"
77  };
78 } // end anonymous namespace
79 
80 /// createXCoreISelDag - This pass converts a legalized DAG into a
81 /// XCore-specific DAG, ready for instruction scheduling.
82 ///
84  CodeGenOpt::Level OptLevel) {
85  return new XCoreDAGToDAGISel(TM, OptLevel);
86 }
87 
88 bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base,
89  SDValue &Offset) {
90  FrameIndexSDNode *FIN = nullptr;
91  if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
92  Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
93  Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
94  return true;
95  }
96  if (Addr.getOpcode() == ISD::ADD) {
97  ConstantSDNode *CN = nullptr;
98  if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
99  && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
100  && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
101  // Constant positive word offset from frame index
102  Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
103  Offset = CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr),
104  MVT::i32);
105  return true;
106  }
107  }
108  return false;
109 }
110 
111 bool XCoreDAGToDAGISel::
112 SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
113  std::vector<SDValue> &OutOps) {
114  SDValue Reg;
115  switch (ConstraintID) {
116  default: return true;
117  case InlineAsm::Constraint_m: // Memory.
118  switch (Op.getOpcode()) {
119  default: return true;
121  Reg = CurDAG->getRegister(XCore::CP, MVT::i32);
122  break;
124  Reg = CurDAG->getRegister(XCore::DP, MVT::i32);
125  break;
126  }
127  }
128  OutOps.push_back(Reg);
129  OutOps.push_back(Op.getOperand(0));
130  return false;
131 }
132 
134  SDLoc dl(N);
135  switch (N->getOpcode()) {
136  default: break;
137  case ISD::Constant: {
138  uint64_t Val = cast<ConstantSDNode>(N)->getZExtValue();
139  if (immMskBitp(N)) {
140  // Transformation function: get the size of a mask
141  // Look for the first non-zero bit
142  SDValue MskSize = getI32Imm(32 - countLeadingZeros((uint32_t)Val), dl);
143  return CurDAG->getMachineNode(XCore::MKMSK_rus, dl,
144  MVT::i32, MskSize);
145  }
146  else if (!isUInt<16>(Val)) {
147  SDValue CPIdx = CurDAG->getTargetConstantPool(
148  ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
149  getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
150  SDNode *node = CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32,
151  MVT::Other, CPIdx,
152  CurDAG->getEntryNode());
153  MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
154  MemOp[0] = MF->getMachineMemOperand(
156  cast<MachineSDNode>(node)->setMemRefs(MemOp, MemOp + 1);
157  return node;
158  }
159  break;
160  }
161  case XCoreISD::LADD: {
162  SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
163  N->getOperand(2) };
164  return CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32,
165  Ops);
166  }
167  case XCoreISD::LSUB: {
168  SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
169  N->getOperand(2) };
170  return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
171  Ops);
172  }
173  case XCoreISD::MACCU: {
174  SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
175  N->getOperand(2), N->getOperand(3) };
176  return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32,
177  Ops);
178  }
179  case XCoreISD::MACCS: {
180  SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
181  N->getOperand(2), N->getOperand(3) };
182  return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32,
183  Ops);
184  }
185  case XCoreISD::LMUL: {
186  SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
187  N->getOperand(2), N->getOperand(3) };
188  return CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32, MVT::i32,
189  Ops);
190  }
191  case XCoreISD::CRC8: {
192  SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2) };
193  return CurDAG->getMachineNode(XCore::CRC8_l4r, dl, MVT::i32, MVT::i32,
194  Ops);
195  }
196  case ISD::BRIND:
197  if (SDNode *ResNode = SelectBRIND(N))
198  return ResNode;
199  break;
200  // Other cases are autogenerated.
201  }
202  return SelectCode(N);
203 }
204 
205 /// Given a chain return a new chain where any appearance of Old is replaced
206 /// by New. There must be at most one instruction between Old and Chain and
207 /// this instruction must be a TokenFactor. Returns an empty SDValue if
208 /// these conditions don't hold.
209 static SDValue
211 {
212  if (Chain == Old)
213  return New;
214  if (Chain->getOpcode() != ISD::TokenFactor)
215  return SDValue();
217  bool found = false;
218  for (unsigned i = 0, e = Chain->getNumOperands(); i != e; ++i) {
219  if (Chain->getOperand(i) == Old) {
220  Ops.push_back(New);
221  found = true;
222  } else {
223  Ops.push_back(Chain->getOperand(i));
224  }
225  }
226  if (!found)
227  return SDValue();
228  return CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, Ops);
229 }
230 
231 SDNode *XCoreDAGToDAGISel::SelectBRIND(SDNode *N) {
232  SDLoc dl(N);
233  // (brind (int_xcore_checkevent (addr)))
234  SDValue Chain = N->getOperand(0);
235  SDValue Addr = N->getOperand(1);
236  if (Addr->getOpcode() != ISD::INTRINSIC_W_CHAIN)
237  return nullptr;
238  unsigned IntNo = cast<ConstantSDNode>(Addr->getOperand(1))->getZExtValue();
239  if (IntNo != Intrinsic::xcore_checkevent)
240  return nullptr;
241  SDValue nextAddr = Addr->getOperand(2);
242  SDValue CheckEventChainOut(Addr.getNode(), 1);
243  if (!CheckEventChainOut.use_empty()) {
244  // If the chain out of the checkevent intrinsic is an operand of the
245  // indirect branch or used in a TokenFactor which is the operand of the
246  // indirect branch then build a new chain which uses the chain coming into
247  // the checkevent intrinsic instead.
248  SDValue CheckEventChainIn = Addr->getOperand(0);
249  SDValue NewChain = replaceInChain(CurDAG, Chain, CheckEventChainOut,
250  CheckEventChainIn);
251  if (!NewChain.getNode())
252  return nullptr;
253  Chain = NewChain;
254  }
255  // Enable events on the thread using setsr 1 and then disable them immediately
256  // after with clrsr 1. If any resources owned by the thread are ready an event
257  // will be taken. If no resource is ready we branch to the address which was
258  // the operand to the checkevent intrinsic.
259  SDValue constOne = getI32Imm(1, dl);
260  SDValue Glue =
261  SDValue(CurDAG->getMachineNode(XCore::SETSR_branch_u6, dl, MVT::Glue,
262  constOne, Chain), 0);
263  Glue =
264  SDValue(CurDAG->getMachineNode(XCore::CLRSR_branch_u6, dl, MVT::Glue,
265  constOne, Glue), 0);
266  if (nextAddr->getOpcode() == XCoreISD::PCRelativeWrapper &&
267  nextAddr->getOperand(0)->getOpcode() == ISD::TargetBlockAddress) {
268  return CurDAG->SelectNodeTo(N, XCore::BRFU_lu6, MVT::Other,
269  nextAddr->getOperand(0), Glue);
270  }
271  return CurDAG->SelectNodeTo(N, XCore::BAU_1r, MVT::Other, nextAddr, Glue);
272 }
The memory access reads data.
static SDValue replaceInChain(SelectionDAG *CurDAG, SDValue Chain, SDValue Old, SDValue New)
Given a chain return a new chain where any appearance of Old is replaced by New.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
static MachinePointerInfo getConstantPool()
getConstantPool - Return a MachinePointerInfo record that refers to the constant pool.
std::size_t countLeadingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the most significant bit to the least stopping at the first 1...
Definition: MathExtras.h:178
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition: ISDOpcodes.h:150
MachineMemOperand - A description of a memory reference used in the backend.
Reg
All possible values of the reg field in the ModR/M byte.
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:191
SDNode * getNode() const
get the SDNode which holds the desired result
const SDValue & getOperand(unsigned i) const
FunctionPass * createXCoreISelDag(XCoreTargetMachine &TM, CodeGenOpt::Level OptLevel)
createXCoreISelDag - This pass converts a legalized DAG into a XCore-specific DAG, ready for instruction scheduling.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
unsigned getOpcode() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:294
TokenFactor - This node takes multiple tokens as input and produces a single token result...
Definition: ISDOpcodes.h:50
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:179
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:861
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:582
Represents one node in the SelectionDAG.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
int64_t getSExtValue() const
bool isMask_32(uint32_t Value)
isMask_32 - This function returns true if the argument is a non-empty sequence of ones starting at th...
Definition: MathExtras.h:328
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:285
SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:239
#define N
bool isUInt< 16 >(uint64_t x)
Definition: MathExtras.h:298
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
This file describes how to lower LLVM code to machine code.
uint64_t getZExtValue() const
BRIND - Indirect branch.
Definition: ISDOpcodes.h:538