XCoreISelDAGToDAG.cpp revision 288943
1251875Speter//===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===//
2251875Speter//
3251875Speter//                     The LLVM Compiler Infrastructure
4251875Speter//
5251875Speter// This file is distributed under the University of Illinois Open Source
6251875Speter// License. See LICENSE.TXT for details.
7251875Speter//
8251875Speter//===----------------------------------------------------------------------===//
9251875Speter//
10251875Speter// This file defines an instruction selector for the XCore target.
11251875Speter//
12251875Speter//===----------------------------------------------------------------------===//
13251875Speter
14251875Speter#include "XCore.h"
15251875Speter#include "XCoreTargetMachine.h"
16251875Speter#include "llvm/CodeGen/MachineFrameInfo.h"
17251875Speter#include "llvm/CodeGen/MachineFunction.h"
18251875Speter#include "llvm/CodeGen/MachineInstrBuilder.h"
19251875Speter#include "llvm/CodeGen/MachineRegisterInfo.h"
20251875Speter#include "llvm/CodeGen/SelectionDAG.h"
21251875Speter#include "llvm/CodeGen/SelectionDAGISel.h"
22251875Speter#include "llvm/IR/CallingConv.h"
23251875Speter#include "llvm/IR/Constants.h"
24251875Speter#include "llvm/IR/DerivedTypes.h"
25251875Speter#include "llvm/IR/Function.h"
26251875Speter#include "llvm/IR/Intrinsics.h"
27251875Speter#include "llvm/IR/LLVMContext.h"
28251875Speter#include "llvm/Support/Compiler.h"
29251875Speter#include "llvm/Support/Debug.h"
30251875Speter#include "llvm/Support/ErrorHandling.h"
31251875Speter#include "llvm/Support/raw_ostream.h"
32251875Speter#include "llvm/Target/TargetLowering.h"
33251875Speterusing namespace llvm;
34251875Speter
35251875Speter/// XCoreDAGToDAGISel - XCore specific code to select XCore machine
36251875Speter/// instructions for SelectionDAG operations.
37251875Speter///
38251875Speternamespace {
39251875Speter  class XCoreDAGToDAGISel : public SelectionDAGISel {
40251875Speter
41251875Speter  public:
42251875Speter    XCoreDAGToDAGISel(XCoreTargetMachine &TM, CodeGenOpt::Level OptLevel)
43251875Speter      : SelectionDAGISel(TM, OptLevel) {}
44251875Speter
45251875Speter    SDNode *Select(SDNode *N) override;
46251875Speter    SDNode *SelectBRIND(SDNode *N);
47251875Speter
48251875Speter    /// getI32Imm - Return a target constant with the specified value, of type
49251875Speter    /// i32.
50251875Speter    inline SDValue getI32Imm(unsigned Imm, SDLoc dl) {
51251875Speter      return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
52251875Speter    }
53251875Speter
54251875Speter    inline bool immMskBitp(SDNode *inN) const {
55251875Speter      ConstantSDNode *N = cast<ConstantSDNode>(inN);
56251875Speter      uint32_t value = (uint32_t)N->getZExtValue();
57251875Speter      if (!isMask_32(value)) {
58251875Speter        return false;
59251875Speter      }
60251875Speter      int msksize = 32 - countLeadingZeros(value);
61251875Speter      return (msksize >= 1 && msksize <= 8) ||
62251875Speter              msksize == 16 || msksize == 24 || msksize == 32;
63251875Speter    }
64251875Speter
65251875Speter    // Complex Pattern Selectors.
66251875Speter    bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset);
67251875Speter
68251875Speter    bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
69251875Speter                                      std::vector<SDValue> &OutOps) override;
70251875Speter
71251875Speter    const char *getPassName() const override {
72251875Speter      return "XCore DAG->DAG Pattern Instruction Selection";
73251875Speter    }
74251875Speter
75251875Speter    // Include the pieces autogenerated from the target description.
76251875Speter  #include "XCoreGenDAGISel.inc"
77251875Speter  };
78251875Speter}  // end anonymous namespace
79251875Speter
80251875Speter/// createXCoreISelDag - This pass converts a legalized DAG into a
81251875Speter/// XCore-specific DAG, ready for instruction scheduling.
82251875Speter///
83251875SpeterFunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM,
84251875Speter                                       CodeGenOpt::Level OptLevel) {
85251875Speter  return new XCoreDAGToDAGISel(TM, OptLevel);
86251875Speter}
87251875Speter
88251875Speterbool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base,
89251875Speter                                       SDValue &Offset) {
90251875Speter  FrameIndexSDNode *FIN = nullptr;
91251875Speter  if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
92251875Speter    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
93251875Speter    Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
94251875Speter    return true;
95251875Speter  }
96251875Speter  if (Addr.getOpcode() == ISD::ADD) {
97251875Speter    ConstantSDNode *CN = nullptr;
98251875Speter    if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
99251875Speter      && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
100251875Speter      && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
101251875Speter      // Constant positive word offset from frame index
102251875Speter      Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
103251875Speter      Offset = CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr),
104251875Speter                                         MVT::i32);
105251875Speter      return true;
106251875Speter    }
107251875Speter  }
108251875Speter  return false;
109251875Speter}
110251875Speter
111251875Speterbool XCoreDAGToDAGISel::
112251875SpeterSelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
113251875Speter                             std::vector<SDValue> &OutOps) {
114251875Speter  SDValue Reg;
115251875Speter  switch (ConstraintID) {
116251875Speter  default: return true;
117251875Speter  case InlineAsm::Constraint_m: // Memory.
118251875Speter    switch (Op.getOpcode()) {
119251875Speter    default: return true;
120251875Speter    case XCoreISD::CPRelativeWrapper:
121251875Speter      Reg = CurDAG->getRegister(XCore::CP, MVT::i32);
122251875Speter      break;
123251875Speter    case XCoreISD::DPRelativeWrapper:
124251875Speter      Reg = CurDAG->getRegister(XCore::DP, MVT::i32);
125251875Speter      break;
126251875Speter    }
127251875Speter  }
128251875Speter  OutOps.push_back(Reg);
129251875Speter  OutOps.push_back(Op.getOperand(0));
130251875Speter  return false;
131251875Speter}
132251875Speter
133251875SpeterSDNode *XCoreDAGToDAGISel::Select(SDNode *N) {
134251875Speter  SDLoc dl(N);
135251875Speter  switch (N->getOpcode()) {
136251875Speter  default: break;
137251875Speter  case ISD::Constant: {
138251875Speter    uint64_t Val = cast<ConstantSDNode>(N)->getZExtValue();
139251875Speter    if (immMskBitp(N)) {
140251875Speter      // Transformation function: get the size of a mask
141251875Speter      // Look for the first non-zero bit
142251875Speter      SDValue MskSize = getI32Imm(32 - countLeadingZeros((uint32_t)Val), dl);
143251875Speter      return CurDAG->getMachineNode(XCore::MKMSK_rus, dl,
144269847Speter                                    MVT::i32, MskSize);
145269847Speter    }
146269847Speter    else if (!isUInt<16>(Val)) {
147269847Speter      SDValue CPIdx = CurDAG->getTargetConstantPool(
148269847Speter          ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
149269847Speter          getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
150269847Speter      SDNode *node = CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32,
151269847Speter                                            MVT::Other, CPIdx,
152269847Speter                                            CurDAG->getEntryNode());
153269847Speter      MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
154269847Speter      MemOp[0] = MF->getMachineMemOperand(
155269847Speter        MachinePointerInfo::getConstantPool(), MachineMemOperand::MOLoad, 4, 4);
156251875Speter      cast<MachineSDNode>(node)->setMemRefs(MemOp, MemOp + 1);
157251875Speter      return node;
158251875Speter    }
159251875Speter    break;
160251875Speter  }
161251875Speter  case XCoreISD::LADD: {
162251875Speter    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
163251875Speter                        N->getOperand(2) };
164251875Speter    return CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32,
165251875Speter                                  Ops);
166251875Speter  }
167251875Speter  case XCoreISD::LSUB: {
168251875Speter    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
169251875Speter                        N->getOperand(2) };
170251875Speter    return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
171251875Speter                                  Ops);
172251875Speter  }
173251875Speter  case XCoreISD::MACCU: {
174251875Speter    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
175251875Speter                      N->getOperand(2), N->getOperand(3) };
176251875Speter    return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32,
177251875Speter                                  Ops);
178251875Speter  }
179251875Speter  case XCoreISD::MACCS: {
180251875Speter    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
181251875Speter                      N->getOperand(2), N->getOperand(3) };
182251875Speter    return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32,
183251875Speter                                  Ops);
184251875Speter  }
185251875Speter  case XCoreISD::LMUL: {
186251875Speter    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
187251875Speter                      N->getOperand(2), N->getOperand(3) };
188251875Speter    return CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32, MVT::i32,
189251875Speter                                  Ops);
190251875Speter  }
191251875Speter  case XCoreISD::CRC8: {
192251875Speter    SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2) };
193251875Speter    return CurDAG->getMachineNode(XCore::CRC8_l4r, dl, MVT::i32, MVT::i32,
194251875Speter                                  Ops);
195251875Speter  }
196251875Speter  case ISD::BRIND:
197251875Speter    if (SDNode *ResNode = SelectBRIND(N))
198251875Speter      return ResNode;
199251875Speter    break;
200251875Speter  // Other cases are autogenerated.
201251875Speter  }
202251875Speter  return SelectCode(N);
203251875Speter}
204251875Speter
205251875Speter/// Given a chain return a new chain where any appearance of Old is replaced
206251875Speter/// by New. There must be at most one instruction between Old and Chain and
207251875Speter/// this instruction must be a TokenFactor. Returns an empty SDValue if
208251875Speter/// these conditions don't hold.
209251875Speterstatic SDValue
210251875SpeterreplaceInChain(SelectionDAG *CurDAG, SDValue Chain, SDValue Old, SDValue New)
211251875Speter{
212251875Speter  if (Chain == Old)
213251875Speter    return New;
214251875Speter  if (Chain->getOpcode() != ISD::TokenFactor)
215251875Speter    return SDValue();
216251875Speter  SmallVector<SDValue, 8> Ops;
217251875Speter  bool found = false;
218251875Speter  for (unsigned i = 0, e = Chain->getNumOperands(); i != e; ++i) {
219251875Speter    if (Chain->getOperand(i) == Old) {
220251875Speter      Ops.push_back(New);
221251875Speter      found = true;
222251875Speter    } else {
223251875Speter      Ops.push_back(Chain->getOperand(i));
224251875Speter    }
225251875Speter  }
226251875Speter  if (!found)
227251875Speter    return SDValue();
228251875Speter  return CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, Ops);
229251875Speter}
230251875Speter
231251875SpeterSDNode *XCoreDAGToDAGISel::SelectBRIND(SDNode *N) {
232251875Speter  SDLoc dl(N);
233251875Speter  // (brind (int_xcore_checkevent (addr)))
234251875Speter  SDValue Chain = N->getOperand(0);
235251875Speter  SDValue Addr = N->getOperand(1);
236251875Speter  if (Addr->getOpcode() != ISD::INTRINSIC_W_CHAIN)
237251875Speter    return nullptr;
238251875Speter  unsigned IntNo = cast<ConstantSDNode>(Addr->getOperand(1))->getZExtValue();
239251875Speter  if (IntNo != Intrinsic::xcore_checkevent)
240251875Speter    return nullptr;
241251875Speter  SDValue nextAddr = Addr->getOperand(2);
242251875Speter  SDValue CheckEventChainOut(Addr.getNode(), 1);
243251875Speter  if (!CheckEventChainOut.use_empty()) {
244251875Speter    // If the chain out of the checkevent intrinsic is an operand of the
245251875Speter    // indirect branch or used in a TokenFactor which is the operand of the
246251875Speter    // indirect branch then build a new chain which uses the chain coming into
247251875Speter    // the checkevent intrinsic instead.
248251875Speter    SDValue CheckEventChainIn = Addr->getOperand(0);
249251875Speter    SDValue NewChain = replaceInChain(CurDAG, Chain, CheckEventChainOut,
250251875Speter                                      CheckEventChainIn);
251251875Speter    if (!NewChain.getNode())
252251875Speter      return nullptr;
253251875Speter    Chain = NewChain;
254251875Speter  }
255251875Speter  // Enable events on the thread using setsr 1 and then disable them immediately
256251875Speter  // after with clrsr 1. If any resources owned by the thread are ready an event
257251875Speter  // will be taken. If no resource is ready we branch to the address which was
258251875Speter  // the operand to the checkevent intrinsic.
259251875Speter  SDValue constOne = getI32Imm(1, dl);
260251875Speter  SDValue Glue =
261251875Speter    SDValue(CurDAG->getMachineNode(XCore::SETSR_branch_u6, dl, MVT::Glue,
262251875Speter                                   constOne, Chain), 0);
263251875Speter  Glue =
264251875Speter    SDValue(CurDAG->getMachineNode(XCore::CLRSR_branch_u6, dl, MVT::Glue,
265251875Speter                                   constOne, Glue), 0);
266251875Speter  if (nextAddr->getOpcode() == XCoreISD::PCRelativeWrapper &&
267251875Speter      nextAddr->getOperand(0)->getOpcode() == ISD::TargetBlockAddress) {
268251875Speter    return CurDAG->SelectNodeTo(N, XCore::BRFU_lu6, MVT::Other,
269251875Speter                                nextAddr->getOperand(0), Glue);
270251875Speter  }
271251875Speter  return CurDAG->SelectNodeTo(N, XCore::BAU_1r, MVT::Other, nextAddr, Glue);
272251875Speter}
273251875Speter