LLVM 19.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"
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"
32using namespace llvm;
33
34#define DEBUG_TYPE "xcore-isel"
35#define PASS_NAME "XCore DAG->DAG Pattern Instruction Selection"
36
37/// XCoreDAGToDAGISel - XCore specific code to select XCore machine
38/// instructions for SelectionDAG operations.
39///
40namespace {
41 class XCoreDAGToDAGISel : public SelectionDAGISel {
42
43 public:
44 static char ID;
45
46 XCoreDAGToDAGISel() = delete;
47
48 XCoreDAGToDAGISel(XCoreTargetMachine &TM, CodeGenOptLevel OptLevel)
49 : SelectionDAGISel(ID, TM, OptLevel) {}
50
51 void Select(SDNode *N) override;
52 bool tryBRIND(SDNode *N);
53
54 /// getI32Imm - Return a target constant with the specified value, of type
55 /// i32.
56 inline SDValue getI32Imm(unsigned Imm, const SDLoc &dl) {
57 return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
58 }
59
60 inline bool immMskBitp(SDNode *inN) const {
61 ConstantSDNode *N = cast<ConstantSDNode>(inN);
62 uint32_t value = (uint32_t)N->getZExtValue();
63 if (!isMask_32(value)) {
64 return false;
65 }
66 int msksize = llvm::bit_width(value);
67 return (msksize >= 1 && msksize <= 8) ||
68 msksize == 16 || msksize == 24 || msksize == 32;
69 }
70
71 // Complex Pattern Selectors.
72 bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset);
73
75 InlineAsm::ConstraintCode ConstraintID,
76 std::vector<SDValue> &OutOps) override;
77
78 // Include the pieces autogenerated from the target description.
79 #include "XCoreGenDAGISel.inc"
80 };
81} // end anonymous namespace
82
83char XCoreDAGToDAGISel::ID = 0;
84
85INITIALIZE_PASS(XCoreDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false)
86
87/// createXCoreISelDag - This pass converts a legalized DAG into a
88/// XCore-specific DAG, ready for instruction scheduling.
89///
91 CodeGenOptLevel OptLevel) {
92 return new XCoreDAGToDAGISel(TM, OptLevel);
93}
94
95bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base,
96 SDValue &Offset) {
97 FrameIndexSDNode *FIN = nullptr;
98 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
99 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
100 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
101 return true;
102 }
103 if (Addr.getOpcode() == ISD::ADD) {
104 ConstantSDNode *CN = nullptr;
105 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
106 && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
107 && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
108 // Constant positive word offset from frame index
109 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
110 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr),
111 MVT::i32);
112 return true;
113 }
114 }
115 return false;
116}
117
118bool XCoreDAGToDAGISel::SelectInlineAsmMemoryOperand(
119 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
120 std::vector<SDValue> &OutOps) {
121 SDValue Reg;
122 switch (ConstraintID) {
123 default: return true;
124 case InlineAsm::ConstraintCode::m: // Memory.
125 switch (Op.getOpcode()) {
126 default: return true;
128 Reg = CurDAG->getRegister(XCore::CP, MVT::i32);
129 break;
131 Reg = CurDAG->getRegister(XCore::DP, MVT::i32);
132 break;
133 }
134 }
135 OutOps.push_back(Reg);
136 OutOps.push_back(Op.getOperand(0));
137 return false;
138}
139
140void XCoreDAGToDAGISel::Select(SDNode *N) {
141 SDLoc dl(N);
142 switch (N->getOpcode()) {
143 default: break;
144 case ISD::Constant: {
145 uint64_t Val = N->getAsZExtVal();
146 if (immMskBitp(N)) {
147 // Transformation function: get the size of a mask
148 // Look for the first non-zero bit
149 SDValue MskSize = getI32Imm(llvm::bit_width((uint32_t)Val), dl);
150 ReplaceNode(
151 N, CurDAG->getMachineNode(XCore::MKMSK_rus, dl, MVT::i32, MskSize));
152 return;
153 }
154 else if (!isUInt<16>(Val)) {
155 SDValue CPIdx = CurDAG->getTargetConstantPool(
156 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val),
157 getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
158 SDNode *node = CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32,
159 MVT::Other, CPIdx,
160 CurDAG->getEntryNode());
162 MF->getMachineMemOperand(MachinePointerInfo::getConstantPool(*MF),
164 CurDAG->setNodeMemRefs(cast<MachineSDNode>(node), {MemOp});
165 ReplaceNode(N, node);
166 return;
167 }
168 break;
169 }
170 case XCoreISD::LADD: {
171 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
172 N->getOperand(2) };
173 ReplaceNode(N, CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32,
174 MVT::i32, Ops));
175 return;
176 }
177 case XCoreISD::LSUB: {
178 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
179 N->getOperand(2) };
180 ReplaceNode(N, CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32,
181 MVT::i32, Ops));
182 return;
183 }
184 case XCoreISD::MACCU: {
185 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
186 N->getOperand(2), N->getOperand(3) };
187 ReplaceNode(N, CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32,
188 MVT::i32, Ops));
189 return;
190 }
191 case XCoreISD::MACCS: {
192 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
193 N->getOperand(2), N->getOperand(3) };
194 ReplaceNode(N, CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32,
195 MVT::i32, Ops));
196 return;
197 }
198 case XCoreISD::LMUL: {
199 SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
200 N->getOperand(2), N->getOperand(3) };
201 ReplaceNode(N, CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32,
202 MVT::i32, Ops));
203 return;
204 }
205 case XCoreISD::CRC8: {
206 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2) };
207 ReplaceNode(N, CurDAG->getMachineNode(XCore::CRC8_l4r, dl, MVT::i32,
208 MVT::i32, Ops));
209 return;
210 }
211 case ISD::BRIND:
212 if (tryBRIND(N))
213 return;
214 break;
215 // Other cases are autogenerated.
216 }
217 SelectCode(N);
218}
219
220/// Given a chain return a new chain where any appearance of Old is replaced
221/// by New. There must be at most one instruction between Old and Chain and
222/// this instruction must be a TokenFactor. Returns an empty SDValue if
223/// these conditions don't hold.
224static SDValue
226{
227 if (Chain == Old)
228 return New;
229 if (Chain->getOpcode() != ISD::TokenFactor)
230 return SDValue();
232 bool found = false;
233 for (unsigned i = 0, e = Chain->getNumOperands(); i != e; ++i) {
234 if (Chain->getOperand(i) == Old) {
235 Ops.push_back(New);
236 found = true;
237 } else {
238 Ops.push_back(Chain->getOperand(i));
239 }
240 }
241 if (!found)
242 return SDValue();
243 return CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, Ops);
244}
245
246bool XCoreDAGToDAGISel::tryBRIND(SDNode *N) {
247 SDLoc dl(N);
248 // (brind (int_xcore_checkevent (addr)))
249 SDValue Chain = N->getOperand(0);
250 SDValue Addr = N->getOperand(1);
251 if (Addr->getOpcode() != ISD::INTRINSIC_W_CHAIN)
252 return false;
253 unsigned IntNo = Addr->getConstantOperandVal(1);
254 if (IntNo != Intrinsic::xcore_checkevent)
255 return false;
256 SDValue nextAddr = Addr->getOperand(2);
257 SDValue CheckEventChainOut(Addr.getNode(), 1);
258 if (!CheckEventChainOut.use_empty()) {
259 // If the chain out of the checkevent intrinsic is an operand of the
260 // indirect branch or used in a TokenFactor which is the operand of the
261 // indirect branch then build a new chain which uses the chain coming into
262 // the checkevent intrinsic instead.
263 SDValue CheckEventChainIn = Addr->getOperand(0);
264 SDValue NewChain = replaceInChain(CurDAG, Chain, CheckEventChainOut,
265 CheckEventChainIn);
266 if (!NewChain.getNode())
267 return false;
268 Chain = NewChain;
269 }
270 // Enable events on the thread using setsr 1 and then disable them immediately
271 // after with clrsr 1. If any resources owned by the thread are ready an event
272 // will be taken. If no resource is ready we branch to the address which was
273 // the operand to the checkevent intrinsic.
274 SDValue constOne = getI32Imm(1, dl);
275 SDValue Glue =
276 SDValue(CurDAG->getMachineNode(XCore::SETSR_branch_u6, dl, MVT::Glue,
277 constOne, Chain), 0);
278 Glue =
279 SDValue(CurDAG->getMachineNode(XCore::CLRSR_branch_u6, dl, MVT::Glue,
280 constOne, Glue), 0);
281 if (nextAddr->getOpcode() == XCoreISD::PCRelativeWrapper &&
282 nextAddr->getOperand(0)->getOpcode() == ISD::TargetBlockAddress) {
283 CurDAG->SelectNodeTo(N, XCore::BRFU_lu6, MVT::Other,
284 nextAddr->getOperand(0), Glue);
285 return true;
286 }
287 CurDAG->SelectNodeTo(N, XCore::BAU_1r, MVT::Other, nextAddr, Glue);
288 return true;
289}
amdgpu AMDGPU Register Bank Select
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Given that RA is a live value
uint64_t Addr
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
This file describes how to lower LLVM code to machine code.
#define PASS_NAME
#define DEBUG_TYPE
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
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
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
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
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:225
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
static IntegerType * getInt32Ty(LLVMContext &C)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ TargetBlockAddress
Definition: ISDOpcodes.h:170
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:239
@ BRIND
BRIND - Indirect branch.
Definition: ISDOpcodes.h:1052
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition: ISDOpcodes.h:52
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition: ISDOpcodes.h:192
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
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:240
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition: bit.h:317
CodeGenOptLevel
Code generation optimization level.
Definition: CodeGen.h:54
FunctionPass * createXCoreISelDag(XCoreTargetMachine &TM, CodeGenOptLevel OptLevel)
createXCoreISelDag - This pass converts a legalized DAG into a XCore-specific DAG,...
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
static MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.