LLVM 24.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"
20#include "llvm/IR/Constants.h"
21#include "llvm/IR/Function.h"
22#include "llvm/IR/Intrinsics.h"
23#include "llvm/IR/IntrinsicsXCore.h"
24#include "llvm/IR/LLVMContext.h"
26using namespace llvm;
27
28#define DEBUG_TYPE "xcore-isel"
29#define PASS_NAME "XCore DAG->DAG Pattern Instruction Selection"
30
31/// XCoreDAGToDAGISel - XCore specific code to select XCore machine
32/// instructions for SelectionDAG operations.
33///
34namespace {
35 class XCoreDAGToDAGISel : public SelectionDAGISel {
36
37 public:
38 XCoreDAGToDAGISel() = delete;
39
40 XCoreDAGToDAGISel(XCoreTargetMachine &TM, CodeGenOptLevel OptLevel)
41 : SelectionDAGISel(TM, OptLevel) {}
42
43 void Select(SDNode *N) override;
44 bool tryBRIND(SDNode *N);
45
46 /// getI32Imm - Return a target constant with the specified value, of type
47 /// i32.
48 inline SDValue getI32Imm(unsigned Imm, const SDLoc &dl) {
49 return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
50 }
51
52 inline bool immMskBitp(SDNode *inN) const {
54 uint32_t value = (uint32_t)N->getZExtValue();
55 if (!isMask_32(value)) {
56 return false;
57 }
58 int msksize = llvm::bit_width(value);
59 return (msksize >= 1 && msksize <= 8) ||
60 msksize == 16 || msksize == 24 || msksize == 32;
61 }
62
63 // Complex Pattern Selectors.
64 bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset);
65
66 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
67 InlineAsm::ConstraintCode ConstraintID,
68 std::vector<SDValue> &OutOps) override;
69
70 // Include the pieces autogenerated from the target description.
71 #include "XCoreGenDAGISel.inc"
72 };
73
74 class XCoreDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
75 public:
76 static char ID;
77 explicit XCoreDAGToDAGISelLegacy(XCoreTargetMachine &TM,
78 CodeGenOptLevel OptLevel)
80 ID, std::make_unique<XCoreDAGToDAGISel>(TM, OptLevel)) {}
81 };
82} // end anonymous namespace
83
84char XCoreDAGToDAGISelLegacy::ID = 0;
85
86INITIALIZE_PASS(XCoreDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
87
88/// createXCoreISelDagLegacyPass - This pass converts a legalized DAG into a
89/// XCore-specific DAG, ready for instruction scheduling.
90///
92 CodeGenOptLevel OptLevel) {
93 return new XCoreDAGToDAGISelLegacy(TM, OptLevel);
94}
95
97 CodeGenOptLevel OptLevel)
98 : SelectionDAGISelPass(std::make_unique<XCoreDAGToDAGISel>(TM, OptLevel)) {}
99
100bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base,
101 SDValue &Offset) {
102 FrameIndexSDNode *FIN = nullptr;
103 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
104 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
105 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
106 return true;
107 }
108 if (Addr.getOpcode() == ISD::ADD) {
109 ConstantSDNode *CN = nullptr;
110 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
111 && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
112 && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
113 // Constant positive word offset from frame index
114 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
115 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr),
116 MVT::i32);
117 return true;
118 }
119 }
120 return false;
121}
122
123bool XCoreDAGToDAGISel::SelectInlineAsmMemoryOperand(
124 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
125 std::vector<SDValue> &OutOps) {
126 SDValue Reg;
127 switch (ConstraintID) {
128 default: return true;
129 case InlineAsm::ConstraintCode::m: // Memory.
130 switch (Op.getOpcode()) {
131 default: return true;
132 case XCoreISD::CPRelativeWrapper:
133 Reg = CurDAG->getRegister(XCore::CP, MVT::i32);
134 break;
135 case XCoreISD::DPRelativeWrapper:
136 Reg = CurDAG->getRegister(XCore::DP, MVT::i32);
137 break;
138 }
139 }
140 OutOps.push_back(Reg);
141 OutOps.push_back(Op.getOperand(0));
142 return false;
143}
144
145void XCoreDAGToDAGISel::Select(SDNode *N) {
146 SDLoc dl(N);
147 switch (N->getOpcode()) {
148 default: break;
149 case ISD::Constant: {
150 uint64_t Val = N->getAsZExtVal();
151 if (immMskBitp(N)) {
152 // Transformation function: get the size of a mask
153 // Look for the first non-zero bit
154 SDValue MskSize = getI32Imm(llvm::bit_width((uint32_t)Val), dl);
155 ReplaceNode(
156 N, CurDAG->getMachineNode(XCore::MKMSK_rus, dl, MVT::i32, MskSize));
157 return;
158 }
159 else if (!isUInt<16>(Val)) {
160 SDValue CPIdx = CurDAG->getTargetConstantPool(
161 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
162 getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
163 SDNode *node = CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32,
164 MVT::Other, CPIdx,
165 CurDAG->getEntryNode());
167 MF->getMachineMemOperand(MachinePointerInfo::getConstantPool(*MF),
169 CurDAG->setNodeMemRefs(cast<MachineSDNode>(node), {MemOp});
170 ReplaceNode(N, node);
171 return;
172 }
173 break;
174 }
175 case ISD::BRIND:
176 if (tryBRIND(N))
177 return;
178 break;
179 // Other cases are autogenerated.
180 }
181 SelectCode(N);
182}
183
184/// Given a chain return a new chain where any appearance of Old is replaced
185/// by New. There must be at most one instruction between Old and Chain and
186/// this instruction must be a TokenFactor. Returns an empty SDValue if
187/// these conditions don't hold.
188static SDValue
190{
191 if (Chain == Old)
192 return New;
193 if (Chain->getOpcode() != ISD::TokenFactor)
194 return SDValue();
196 bool found = false;
197 for (unsigned i = 0, e = Chain->getNumOperands(); i != e; ++i) {
198 if (Chain->getOperand(i) == Old) {
199 Ops.push_back(New);
200 found = true;
201 } else {
202 Ops.push_back(Chain->getOperand(i));
203 }
204 }
205 if (!found)
206 return SDValue();
207 return CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, Ops);
208}
209
210bool XCoreDAGToDAGISel::tryBRIND(SDNode *N) {
211 SDLoc dl(N);
212 // (brind (int_xcore_checkevent (addr)))
213 SDValue Chain = N->getOperand(0);
214 SDValue Addr = N->getOperand(1);
215 if (Addr->getOpcode() != ISD::INTRINSIC_W_CHAIN)
216 return false;
217 unsigned IntNo = Addr->getConstantOperandVal(1);
218 if (IntNo != Intrinsic::xcore_checkevent)
219 return false;
220 SDValue nextAddr = Addr->getOperand(2);
221 SDValue CheckEventChainOut(Addr.getNode(), 1);
222 if (!CheckEventChainOut.use_empty()) {
223 // If the chain out of the checkevent intrinsic is an operand of the
224 // indirect branch or used in a TokenFactor which is the operand of the
225 // indirect branch then build a new chain which uses the chain coming into
226 // the checkevent intrinsic instead.
227 SDValue CheckEventChainIn = Addr->getOperand(0);
228 SDValue NewChain = replaceInChain(CurDAG, Chain, CheckEventChainOut,
229 CheckEventChainIn);
230 if (!NewChain.getNode())
231 return false;
232 Chain = NewChain;
233 }
234 // Enable events on the thread using setsr 1 and then disable them immediately
235 // after with clrsr 1. If any resources owned by the thread are ready an event
236 // will be taken. If no resource is ready we branch to the address which was
237 // the operand to the checkevent intrinsic.
238 SDValue constOne = getI32Imm(1, dl);
239 SDValue Glue =
240 SDValue(CurDAG->getMachineNode(XCore::SETSR_branch_u6, dl, MVT::Glue,
241 constOne, Chain), 0);
242 Glue =
243 SDValue(CurDAG->getMachineNode(XCore::CLRSR_branch_u6, dl, MVT::Glue,
244 constOne, Glue), 0);
245 if (nextAddr->getOpcode() == XCoreISD::PCRelativeWrapper &&
246 nextAddr->getOperand(0)->getOpcode() == ISD::TargetBlockAddress) {
247 CurDAG->SelectNodeTo(N, XCore::BRFU_lu6, MVT::Other,
248 nextAddr->getOperand(0), Glue);
249 return true;
250 }
251 CurDAG->SelectNodeTo(N, XCore::BAU_1r, MVT::Other, nextAddr, Glue);
252 return true;
253}
uint64_t uint64_t
uint64_t Imm
AMDGPU Register Bank Select
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define DEBUG_TYPE
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Register Reg
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file describes how to lower LLVM code to machine code.
#define PASS_NAME
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.
int64_t getSExtValue() const
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:312
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
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
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
XCoreISelDAGToDAGPass(XCoreTargetMachine &TM, CodeGenOptLevel OptLevel)
@ TargetBlockAddress
Definition ISDOpcodes.h:193
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:266
@ BRIND
BRIND - Indirect branch.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:55
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:215
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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:256
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:325
FunctionPass * createXCoreISelDagLegacyPass(XCoreTargetMachine &TM, CodeGenOptLevel OptLevel)
createXCoreISelDagLegacyPass - This pass converts a legalized DAG into a XCore-specific DAG,...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:280
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.