Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/VE/VEISelDAGToDAG.cpp
35268 views
1
//===-- VEISelDAGToDAG.cpp - A dag to dag inst selector for VE ------------===//
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 VE target.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "VE.h"
14
#include "VETargetMachine.h"
15
#include "llvm/CodeGen/MachineRegisterInfo.h"
16
#include "llvm/CodeGen/SelectionDAGISel.h"
17
#include "llvm/IR/Intrinsics.h"
18
#include "llvm/Support/Debug.h"
19
#include "llvm/Support/ErrorHandling.h"
20
#include "llvm/Support/raw_ostream.h"
21
using namespace llvm;
22
23
#define DEBUG_TYPE "ve-isel"
24
#define PASS_NAME "VE DAG->DAG Pattern Instruction Selection"
25
26
//===--------------------------------------------------------------------===//
27
/// VEDAGToDAGISel - VE specific code to select VE machine
28
/// instructions for SelectionDAG operations.
29
///
30
namespace {
31
class VEDAGToDAGISel : public SelectionDAGISel {
32
/// Subtarget - Keep a pointer to the VE Subtarget around so that we can
33
/// make the right decision when generating code for different targets.
34
const VESubtarget *Subtarget;
35
36
public:
37
VEDAGToDAGISel() = delete;
38
39
explicit VEDAGToDAGISel(VETargetMachine &tm) : SelectionDAGISel(tm) {}
40
41
bool runOnMachineFunction(MachineFunction &MF) override {
42
Subtarget = &MF.getSubtarget<VESubtarget>();
43
return SelectionDAGISel::runOnMachineFunction(MF);
44
}
45
46
void Select(SDNode *N) override;
47
48
// Complex Pattern Selectors.
49
bool selectADDRrri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
50
bool selectADDRrii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
51
bool selectADDRzri(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
52
bool selectADDRzii(SDValue N, SDValue &Base, SDValue &Index, SDValue &Offset);
53
bool selectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
54
bool selectADDRzi(SDValue N, SDValue &Base, SDValue &Offset);
55
56
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
57
/// inline asm expressions.
58
bool SelectInlineAsmMemoryOperand(const SDValue &Op,
59
InlineAsm::ConstraintCode ConstraintID,
60
std::vector<SDValue> &OutOps) override;
61
62
// Include the pieces autogenerated from the target description.
63
#include "VEGenDAGISel.inc"
64
65
private:
66
SDNode *getGlobalBaseReg();
67
68
bool matchADDRrr(SDValue N, SDValue &Base, SDValue &Index);
69
bool matchADDRri(SDValue N, SDValue &Base, SDValue &Offset);
70
};
71
72
class VEDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
73
public:
74
static char ID;
75
explicit VEDAGToDAGISelLegacy(VETargetMachine &tm)
76
: SelectionDAGISelLegacy(ID, std::make_unique<VEDAGToDAGISel>(tm)) {}
77
};
78
} // end anonymous namespace
79
80
char VEDAGToDAGISelLegacy::ID = 0;
81
82
INITIALIZE_PASS(VEDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
83
84
bool VEDAGToDAGISel::selectADDRrri(SDValue Addr, SDValue &Base, SDValue &Index,
85
SDValue &Offset) {
86
if (Addr.getOpcode() == ISD::FrameIndex)
87
return false;
88
if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
89
Addr.getOpcode() == ISD::TargetGlobalAddress ||
90
Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
91
return false; // direct calls.
92
93
SDValue LHS, RHS;
94
if (matchADDRri(Addr, LHS, RHS)) {
95
if (matchADDRrr(LHS, Base, Index)) {
96
Offset = RHS;
97
return true;
98
}
99
// Return false to try selectADDRrii.
100
return false;
101
}
102
if (matchADDRrr(Addr, LHS, RHS)) {
103
// If the input is a pair of a frame-index and a register, move a
104
// frame-index to LHS. This generates MI with following operands.
105
// %dest, #FI, %reg, offset
106
// In the eliminateFrameIndex, above MI is converted to the following.
107
// %dest, %fp, %reg, fi_offset + offset
108
if (isa<FrameIndexSDNode>(RHS))
109
std::swap(LHS, RHS);
110
111
if (matchADDRri(RHS, Index, Offset)) {
112
Base = LHS;
113
return true;
114
}
115
if (matchADDRri(LHS, Base, Offset)) {
116
Index = RHS;
117
return true;
118
}
119
Base = LHS;
120
Index = RHS;
121
Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
122
return true;
123
}
124
return false; // Let the reg+imm(=0) pattern catch this!
125
}
126
127
bool VEDAGToDAGISel::selectADDRrii(SDValue Addr, SDValue &Base, SDValue &Index,
128
SDValue &Offset) {
129
if (matchADDRri(Addr, Base, Offset)) {
130
Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
131
return true;
132
}
133
134
Base = Addr;
135
Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
136
Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
137
return true;
138
}
139
140
bool VEDAGToDAGISel::selectADDRzri(SDValue Addr, SDValue &Base, SDValue &Index,
141
SDValue &Offset) {
142
// Prefer ADDRrii.
143
return false;
144
}
145
146
bool VEDAGToDAGISel::selectADDRzii(SDValue Addr, SDValue &Base, SDValue &Index,
147
SDValue &Offset) {
148
if (isa<FrameIndexSDNode>(Addr))
149
return false;
150
if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
151
Addr.getOpcode() == ISD::TargetGlobalAddress ||
152
Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
153
return false; // direct calls.
154
155
if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {
156
if (isInt<32>(CN->getSExtValue())) {
157
Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
158
Index = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
159
Offset =
160
CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
161
return true;
162
}
163
}
164
return false;
165
}
166
167
bool VEDAGToDAGISel::selectADDRri(SDValue Addr, SDValue &Base,
168
SDValue &Offset) {
169
if (matchADDRri(Addr, Base, Offset))
170
return true;
171
172
Base = Addr;
173
Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
174
return true;
175
}
176
177
bool VEDAGToDAGISel::selectADDRzi(SDValue Addr, SDValue &Base,
178
SDValue &Offset) {
179
if (isa<FrameIndexSDNode>(Addr))
180
return false;
181
if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
182
Addr.getOpcode() == ISD::TargetGlobalAddress ||
183
Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
184
return false; // direct calls.
185
186
if (auto *CN = dyn_cast<ConstantSDNode>(Addr)) {
187
if (isInt<32>(CN->getSExtValue())) {
188
Base = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
189
Offset =
190
CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
191
return true;
192
}
193
}
194
return false;
195
}
196
197
bool VEDAGToDAGISel::matchADDRrr(SDValue Addr, SDValue &Base, SDValue &Index) {
198
if (isa<FrameIndexSDNode>(Addr))
199
return false;
200
if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
201
Addr.getOpcode() == ISD::TargetGlobalAddress ||
202
Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
203
return false; // direct calls.
204
205
if (Addr.getOpcode() == ISD::ADD) {
206
; // Nothing to do here.
207
} else if (Addr.getOpcode() == ISD::OR) {
208
// We want to look through a transform in InstCombine and DAGCombiner that
209
// turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'.
210
if (!CurDAG->haveNoCommonBitsSet(Addr.getOperand(0), Addr.getOperand(1)))
211
return false;
212
} else {
213
return false;
214
}
215
216
if (Addr.getOperand(0).getOpcode() == VEISD::Lo ||
217
Addr.getOperand(1).getOpcode() == VEISD::Lo)
218
return false; // Let the LEASL patterns catch this!
219
220
Base = Addr.getOperand(0);
221
Index = Addr.getOperand(1);
222
return true;
223
}
224
225
bool VEDAGToDAGISel::matchADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) {
226
auto AddrTy = Addr->getValueType(0);
227
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
228
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
229
Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
230
return true;
231
}
232
if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
233
Addr.getOpcode() == ISD::TargetGlobalAddress ||
234
Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
235
return false; // direct calls.
236
237
if (CurDAG->isBaseWithConstantOffset(Addr)) {
238
ConstantSDNode *CN = cast<ConstantSDNode>(Addr.getOperand(1));
239
if (isInt<32>(CN->getSExtValue())) {
240
if (FrameIndexSDNode *FIN =
241
dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
242
// Constant offset from frame ref.
243
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), AddrTy);
244
} else {
245
Base = Addr.getOperand(0);
246
}
247
Offset =
248
CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), MVT::i32);
249
return true;
250
}
251
}
252
return false;
253
}
254
255
void VEDAGToDAGISel::Select(SDNode *N) {
256
SDLoc dl(N);
257
if (N->isMachineOpcode()) {
258
N->setNodeId(-1);
259
return; // Already selected.
260
}
261
262
switch (N->getOpcode()) {
263
264
// Late eliminate the LEGALAVL wrapper
265
case VEISD::LEGALAVL:
266
ReplaceNode(N, N->getOperand(0).getNode());
267
return;
268
269
// Lower (broadcast 1) and (broadcast 0) to VM[P]0
270
case VEISD::VEC_BROADCAST: {
271
MVT SplatResTy = N->getSimpleValueType(0);
272
if (SplatResTy.getVectorElementType() != MVT::i1)
273
break;
274
275
// Constant non-zero broadcast.
276
auto BConst = dyn_cast<ConstantSDNode>(N->getOperand(0));
277
if (!BConst)
278
break;
279
bool BCTrueMask = (BConst->getSExtValue() != 0);
280
if (!BCTrueMask)
281
break;
282
283
// Packed or non-packed.
284
SDValue New;
285
if (SplatResTy.getVectorNumElements() == StandardVectorWidth) {
286
New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VM0,
287
MVT::v256i1);
288
} else if (SplatResTy.getVectorNumElements() == PackedVectorWidth) {
289
New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(N), VE::VMP0,
290
MVT::v512i1);
291
} else
292
break;
293
294
// Replace.
295
ReplaceNode(N, New.getNode());
296
return;
297
}
298
299
case VEISD::GLOBAL_BASE_REG:
300
ReplaceNode(N, getGlobalBaseReg());
301
return;
302
}
303
304
SelectCode(N);
305
}
306
307
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
308
/// inline asm expressions.
309
bool VEDAGToDAGISel::SelectInlineAsmMemoryOperand(
310
const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
311
std::vector<SDValue> &OutOps) {
312
SDValue Op0, Op1;
313
switch (ConstraintID) {
314
default:
315
llvm_unreachable("Unexpected asm memory constraint");
316
case InlineAsm::ConstraintCode::o:
317
case InlineAsm::ConstraintCode::m: // memory
318
// Try to match ADDRri since reg+imm style is safe for all VE instructions
319
// with a memory operand.
320
if (selectADDRri(Op, Op0, Op1)) {
321
OutOps.push_back(Op0);
322
OutOps.push_back(Op1);
323
return false;
324
}
325
// Otherwise, require the address to be in a register and immediate 0.
326
OutOps.push_back(Op);
327
OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));
328
return false;
329
}
330
return true;
331
}
332
333
SDNode *VEDAGToDAGISel::getGlobalBaseReg() {
334
Register GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF);
335
return CurDAG
336
->getRegister(GlobalBaseReg, TLI->getPointerTy(CurDAG->getDataLayout()))
337
.getNode();
338
}
339
340
/// createVEISelDag - This pass converts a legalized DAG into a
341
/// VE-specific DAG, ready for instruction scheduling.
342
///
343
FunctionPass *llvm::createVEISelDag(VETargetMachine &TM) {
344
return new VEDAGToDAGISelLegacy(TM);
345
}
346
347