LLVM  14.0.0git
XCoreISelDAGToDAG.cpp
Go to the documentation of this file.
1 //===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines an instruction selector for the XCore target.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "XCore.h"
14 #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/IntrinsicsXCore.h"
28 #include "llvm/IR/LLVMContext.h"
29 #include "llvm/Support/Debug.h"
32 using namespace llvm;
33 
34 /// XCoreDAGToDAGISel - XCore specific code to select XCore machine
35 /// instructions for SelectionDAG operations.
36 ///
37 namespace {
38  class XCoreDAGToDAGISel : public SelectionDAGISel {
39 
40  public:
41  XCoreDAGToDAGISel(XCoreTargetMachine &TM, CodeGenOpt::Level OptLevel)
42  : SelectionDAGISel(TM, OptLevel) {}
43 
44  void Select(SDNode *N) override;
45  bool tryBRIND(SDNode *N);
46 
47  /// getI32Imm - Return a target constant with the specified value, of type
48  /// i32.
49  inline SDValue getI32Imm(unsigned Imm, const SDLoc &dl) {
50  return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
51  }
52 
53  inline bool immMskBitp(SDNode *inN) const {
54  ConstantSDNode *N = cast<ConstantSDNode>(inN);
55  uint32_t value = (uint32_t)N->getZExtValue();
56  if (!isMask_32(value)) {
57  return false;
58  }
59  int msksize = 32 - countLeadingZeros(value);
60  return (msksize >= 1 && msksize <= 8) ||
61  msksize == 16 || msksize == 24 || msksize == 32;
62  }
63 
64  // Complex Pattern Selectors.
65  bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset);
66 
67  bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
68  std::vector<SDValue> &OutOps) override;
69 
70  StringRef getPassName() const override {
71  return "XCore DAG->DAG Pattern Instruction Selection";
72  }
73 
74  // Include the pieces autogenerated from the target description.
75  #include "XCoreGenDAGISel.inc"
76  };
77 } // end anonymous namespace
78 
79 /// createXCoreISelDag - This pass converts a legalized DAG into a
80 /// XCore-specific DAG, ready for instruction scheduling.
81 ///
83  CodeGenOpt::Level OptLevel) {
84  return new XCoreDAGToDAGISel(TM, OptLevel);
85 }
86 
87 bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base,
88  SDValue &Offset) {
89  FrameIndexSDNode *FIN = nullptr;
90  if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
91  Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
92  Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
93  return true;
94  }
95  if (Addr.getOpcode() == ISD::ADD) {
96  ConstantSDNode *CN = nullptr;
97  if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
98  && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
99  && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
100  // Constant positive word offset from frame index
101  Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
102  Offset = CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr),
103  MVT::i32);
104  return true;
105  }
106  }
107  return false;
108 }
109 
110 bool XCoreDAGToDAGISel::
111 SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
112  std::vector<SDValue> &OutOps) {
113  SDValue Reg;
114  switch (ConstraintID) {
115  default: return true;
116  case InlineAsm::Constraint_m: // Memory.
117  switch (Op.getOpcode()) {
118  default: return true;
120  Reg = CurDAG->getRegister(XCore::CP, MVT::i32);
121  break;
123  Reg = CurDAG->getRegister(XCore::DP, MVT::i32);
124  break;
125  }
126  }
127  OutOps.push_back(Reg);
128  OutOps.push_back(Op.getOperand(0));
129  return false;
130 }
131 
133  SDLoc dl(N);
134  switch (N->getOpcode()) {
135  default: break;
136  case ISD::Constant: {
137  uint64_t Val = cast<ConstantSDNode>(N)->getZExtValue();
138  if (immMskBitp(N)) {
139  // Transformation function: get the size of a mask
140  // Look for the first non-zero bit
141  SDValue MskSize = getI32Imm(32 - countLeadingZeros((uint32_t)Val), dl);
142  ReplaceNode(N, CurDAG->getMachineNode(XCore::MKMSK_rus, dl,
143  MVT::i32, MskSize));
144  return;
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());
154  MF->getMachineMemOperand(MachinePointerInfo::getConstantPool(*MF),
156  CurDAG->setNodeMemRefs(cast<MachineSDNode>(node), {MemOp});
157  ReplaceNode(N, node);
158  return;
159  }
160  break;
161  }
162  case XCoreISD::LADD: {
163  SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
164  N->getOperand(2) };
165  ReplaceNode(N, CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32,
166  MVT::i32, Ops));
167  return;
168  }
169  case XCoreISD::LSUB: {
170  SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
171  N->getOperand(2) };
172  ReplaceNode(N, CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32,
173  MVT::i32, Ops));
174  return;
175  }
176  case XCoreISD::MACCU: {
177  SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
178  N->getOperand(2), N->getOperand(3) };
179  ReplaceNode(N, CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32,
180  MVT::i32, Ops));
181  return;
182  }
183  case XCoreISD::MACCS: {
184  SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
185  N->getOperand(2), N->getOperand(3) };
186  ReplaceNode(N, CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32,
187  MVT::i32, Ops));
188  return;
189  }
190  case XCoreISD::LMUL: {
191  SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
192  N->getOperand(2), N->getOperand(3) };
193  ReplaceNode(N, CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32,
194  MVT::i32, Ops));
195  return;
196  }
197  case XCoreISD::CRC8: {
198  SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2) };
199  ReplaceNode(N, CurDAG->getMachineNode(XCore::CRC8_l4r, dl, MVT::i32,
200  MVT::i32, Ops));
201  return;
202  }
203  case ISD::BRIND:
204  if (tryBRIND(N))
205  return;
206  break;
207  // Other cases are autogenerated.
208  }
209  SelectCode(N);
210 }
211 
212 /// Given a chain return a new chain where any appearance of Old is replaced
213 /// by New. There must be at most one instruction between Old and Chain and
214 /// this instruction must be a TokenFactor. Returns an empty SDValue if
215 /// these conditions don't hold.
216 static SDValue
218 {
219  if (Chain == Old)
220  return New;
221  if (Chain->getOpcode() != ISD::TokenFactor)
222  return SDValue();
224  bool found = false;
225  for (unsigned i = 0, e = Chain->getNumOperands(); i != e; ++i) {
226  if (Chain->getOperand(i) == Old) {
227  Ops.push_back(New);
228  found = true;
229  } else {
230  Ops.push_back(Chain->getOperand(i));
231  }
232  }
233  if (!found)
234  return SDValue();
235  return CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, Ops);
236 }
237 
238 bool XCoreDAGToDAGISel::tryBRIND(SDNode *N) {
239  SDLoc dl(N);
240  // (brind (int_xcore_checkevent (addr)))
241  SDValue Chain = N->getOperand(0);
242  SDValue Addr = N->getOperand(1);
243  if (Addr->getOpcode() != ISD::INTRINSIC_W_CHAIN)
244  return false;
245  unsigned IntNo = cast<ConstantSDNode>(Addr->getOperand(1))->getZExtValue();
246  if (IntNo != Intrinsic::xcore_checkevent)
247  return false;
248  SDValue nextAddr = Addr->getOperand(2);
249  SDValue CheckEventChainOut(Addr.getNode(), 1);
250  if (!CheckEventChainOut.use_empty()) {
251  // If the chain out of the checkevent intrinsic is an operand of the
252  // indirect branch or used in a TokenFactor which is the operand of the
253  // indirect branch then build a new chain which uses the chain coming into
254  // the checkevent intrinsic instead.
255  SDValue CheckEventChainIn = Addr->getOperand(0);
256  SDValue NewChain = replaceInChain(CurDAG, Chain, CheckEventChainOut,
257  CheckEventChainIn);
258  if (!NewChain.getNode())
259  return false;
260  Chain = NewChain;
261  }
262  // Enable events on the thread using setsr 1 and then disable them immediately
263  // after with clrsr 1. If any resources owned by the thread are ready an event
264  // will be taken. If no resource is ready we branch to the address which was
265  // the operand to the checkevent intrinsic.
266  SDValue constOne = getI32Imm(1, dl);
267  SDValue Glue =
268  SDValue(CurDAG->getMachineNode(XCore::SETSR_branch_u6, dl, MVT::Glue,
269  constOne, Chain), 0);
270  Glue =
271  SDValue(CurDAG->getMachineNode(XCore::CLRSR_branch_u6, dl, MVT::Glue,
272  constOne, Glue), 0);
273  if (nextAddr->getOpcode() == XCoreISD::PCRelativeWrapper &&
274  nextAddr->getOperand(0)->getOpcode() == ISD::TargetBlockAddress) {
275  CurDAG->SelectNodeTo(N, XCore::BRFU_lu6, MVT::Other,
276  nextAddr->getOperand(0), Glue);
277  return true;
278  }
279  CurDAG->SelectNodeTo(N, XCore::BAU_1r, MVT::Other, nextAddr, Glue);
280  return true;
281 }
i
i
Definition: README.txt:29
llvm::ConstantSDNode
Definition: SelectionDAGNodes.h:1556
llvm::createXCoreISelDag
FunctionPass * createXCoreISelDag(XCoreTargetMachine &TM, CodeGenOpt::Level OptLevel)
createXCoreISelDag - This pass converts a legalized DAG into a XCore-specific DAG,...
Definition: XCoreISelDAGToDAG.cpp:82
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
Reg
unsigned Reg
Definition: MachineSink.cpp:1566
llvm::XCoreISD::CPRelativeWrapper
@ CPRelativeWrapper
Definition: XCoreISelLowering.h:41
llvm::SDLoc
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Definition: SelectionDAGNodes.h:1086
llvm::SDValue::getNode
SDNode * getNode() const
get the SDNode which holds the desired result
Definition: SelectionDAGNodes.h:152
XCore.h
llvm::MachinePointerInfo::getConstantPool
static MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
Definition: MachineOperand.cpp:1002
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::XCoreISD::PCRelativeWrapper
@ PCRelativeWrapper
Definition: XCoreISelLowering.h:35
ErrorHandling.h
llvm::SDNode
Represents one node in the SelectionDAG.
Definition: SelectionDAGNodes.h:455
llvm::MVT::Glue
@ Glue
Definition: MachineValueType.h:262
llvm::MemOp
Definition: TargetLowering.h:112
llvm::XCoreISD::MACCU
@ MACCU
Definition: XCoreISelLowering.h:62
llvm::MachineMemOperand
A description of a memory reference used in the backend.
Definition: MachineMemOperand.h:128
replaceInChain
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.
Definition: XCoreISelDAGToDAG.cpp:217
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
SelectionDAG.h
llvm::Type::getInt32Ty
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:241
MachineRegisterInfo.h
llvm::ISD::BRIND
@ BRIND
BRIND - Indirect branch.
Definition: ISDOpcodes.h:942
TargetLowering.h
llvm::SDNode::getOpcode
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
Definition: SelectionDAGNodes.h:629
llvm::XCoreTargetMachine
Definition: XCoreTargetMachine.h:26
llvm::SelectionDAG
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:216
Constants.h
llvm::ISD::Constant
@ Constant
Definition: ISDOpcodes.h:76
llvm::XCoreISD::LSUB
@ LSUB
Definition: XCoreISelLowering.h:56
Intrinsics.h
llvm::XCoreISD::DPRelativeWrapper
@ DPRelativeWrapper
Definition: XCoreISelLowering.h:38
llvm::FrameIndexSDNode
Definition: SelectionDAGNodes.h:1744
llvm::ConstantInt::get
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:925
Align
uint64_t Align
Definition: ELFObjHandler.cpp:83
llvm::isUInt< 16 >
constexpr bool isUInt< 16 >(uint64_t x)
Definition: MathExtras.h:408
uint64_t
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:80
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:57
llvm::SDNode::getOperand
const SDValue & getOperand(unsigned Num) const
Definition: SelectionDAGNodes.h:904
llvm::FrameIndexSDNode::getIndex
int getIndex() const
Definition: SelectionDAGNodes.h:1755
llvm::SelectionDAG::getNode
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
Definition: SelectionDAG.cpp:8345
node
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper node
Definition: README-SSE.txt:406
llvm::MVT::Other
@ Other
Definition: MachineValueType.h:42
llvm::isMask_32
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
Definition: MathExtras.h:467
llvm::ISD::TargetBlockAddress
@ TargetBlockAddress
Definition: ISDOpcodes.h:170
SelectionDAGISel.h
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
uint32_t
llvm::ConstantSDNode::getSExtValue
int64_t getSExtValue() const
Definition: SelectionDAGNodes.h:1572
llvm::XCoreISD::LADD
@ LADD
Definition: XCoreISelLowering.h:53
llvm::CodeGenOpt::Level
Level
Definition: CodeGen.h:52
llvm::MachineMemOperand::MOLoad
@ MOLoad
The memory access reads data.
Definition: MachineMemOperand.h:135
llvm::MCID::Select
@ Select
Definition: MCInstrDesc.h:162
CallingConv.h
llvm::HexagonISD::CP
@ CP
Definition: HexagonISelLowering.h:53
llvm::InlineAsm::Constraint_m
@ Constraint_m
Definition: InlineAsm.h:247
llvm::XCoreISD::MACCS
@ MACCS
Definition: XCoreISelLowering.h:65
llvm::SDNode::getNumOperands
unsigned getNumOperands() const
Return the number of values used by this operation.
Definition: SelectionDAGNodes.h:891
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:324
MachineFrameInfo.h
Function.h
llvm::MVT::i32
@ i32
Definition: MachineValueType.h:46
llvm::SDValue
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
Definition: SelectionDAGNodes.h:138
DP
So we should use XX3Form_Rcr to implement instrinsic Convert DP outs ins xscvdpsp No builtin are required Round &Convert QP DP(dword[1] is set to zero) No builtin are required Round to Quad Precision because you need to assign rounding mode in instruction Provide builtin(set f128:$vT,(int_ppc_vsx_xsrqpi f128:$vB))(set f128 yields< n x< ty > >< result > yields< ty >< result > No builtin are required Load Store load store see def memrix16 in PPCInstrInfo td Load Store Vector load store outs ins lxsdx set load store with conversion from to DP
Definition: README_P9.txt:520
XCoreTargetMachine.h
llvm::XCoreISD::LMUL
@ LMUL
Definition: XCoreISelLowering.h:59
llvm::countLeadingZeros
unsigned 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:225
llvm::XCoreISD::CRC8
@ CRC8
Definition: XCoreISelLowering.h:68
llvm::ISD::ADD
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:239
llvm::SelectionDAGISel
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
Definition: SelectionDAGISel.h:39
MachineInstrBuilder.h
N
#define N
DerivedTypes.h
TM
const char LLVMTargetMachineRef TM
Definition: PassBuilderBindings.cpp:47
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::ISD::INTRINSIC_W_CHAIN
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition: ISDOpcodes.h:192
LLVMContext.h
raw_ostream.h
MachineFunction.h
Debug.h
llvm::ISD::TokenFactor
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition: ISDOpcodes.h:52
llvm::sampleprof::Base
@ Base
Definition: Discriminator.h:58