LLVM 24.0.0git
RISCVLegalizerInfo.cpp
Go to the documentation of this file.
1//===-- RISCVLegalizerInfo.cpp ----------------------------------*- C++ -*-===//
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/// \file
9/// This file implements the targeting of the Machinelegalizer class for RISC-V.
10/// \todo This should be generated by TableGen.
11//===----------------------------------------------------------------------===//
12
13#include "RISCVLegalizerInfo.h"
16#include "RISCVSubtarget.h"
30#include "llvm/IR/Intrinsics.h"
31#include "llvm/IR/IntrinsicsRISCV.h"
32#include "llvm/IR/Type.h"
33
34using namespace llvm;
35using namespace LegalityPredicates;
36using namespace LegalizeMutations;
37using namespace MIPatternMatch;
38
40typeIsLegalIntOrFPVec(unsigned TypeIdx,
41 std::initializer_list<LLT> IntOrFPVecTys,
42 const RISCVSubtarget &ST) {
43 LegalityPredicate P = [=, &ST](const LegalityQuery &Query) {
44 return ST.hasVInstructions() &&
45 (Query.Types[TypeIdx].getScalarSizeInBits() != 64 ||
46 ST.hasVInstructionsI64()) &&
47 (Query.Types[TypeIdx].getElementCount().getKnownMinValue() != 1 ||
48 ST.getELen() == 64);
49 };
50
51 return all(typeInSet(TypeIdx, IntOrFPVecTys), P);
52}
53
55typeIsLegalBoolVec(unsigned TypeIdx, std::initializer_list<LLT> BoolVecTys,
56 const RISCVSubtarget &ST) {
57 LegalityPredicate P = [=, &ST](const LegalityQuery &Query) {
58 return ST.hasVInstructions() &&
59 (Query.Types[TypeIdx].getElementCount().getKnownMinValue() != 1 ||
60 ST.getELen() == 64);
61 };
62 return all(typeInSet(TypeIdx, BoolVecTys), P);
63}
64
65static LegalityPredicate typeIsLegalPtrVec(unsigned TypeIdx,
66 std::initializer_list<LLT> PtrVecTys,
67 const RISCVSubtarget &ST) {
68 LegalityPredicate P = [=, &ST](const LegalityQuery &Query) {
69 return ST.hasVInstructions() &&
70 (Query.Types[TypeIdx].getElementCount().getKnownMinValue() != 1 ||
71 ST.getELen() == 64) &&
72 (Query.Types[TypeIdx].getElementCount().getKnownMinValue() != 16 ||
73 Query.Types[TypeIdx].getScalarSizeInBits() == 32);
74 };
75 return all(typeInSet(TypeIdx, PtrVecTys), P);
76}
77
79 : STI(ST), XLen(STI.getXLen()), sXLen(LLT::scalar(XLen)) {
80 const LLT sDoubleXLen = LLT::scalar(2 * XLen);
81 const LLT p0 = LLT::pointer(0, XLen);
82 const LLT s1 = LLT::scalar(1);
83 const LLT s8 = LLT::scalar(8);
84 const LLT s16 = LLT::scalar(16);
85 const LLT f16 = LLT::float16();
86 const LLT s32 = LLT::scalar(32);
87 const LLT s64 = LLT::scalar(64);
88 const LLT s128 = LLT::scalar(128);
89
90 const LLT nxv1s1 = LLT::scalable_vector(1, s1);
91 const LLT nxv2s1 = LLT::scalable_vector(2, s1);
92 const LLT nxv4s1 = LLT::scalable_vector(4, s1);
93 const LLT nxv8s1 = LLT::scalable_vector(8, s1);
94 const LLT nxv16s1 = LLT::scalable_vector(16, s1);
95 const LLT nxv32s1 = LLT::scalable_vector(32, s1);
96 const LLT nxv64s1 = LLT::scalable_vector(64, s1);
97
98 const LLT nxv1s8 = LLT::scalable_vector(1, s8);
99 const LLT nxv2s8 = LLT::scalable_vector(2, s8);
100 const LLT nxv4s8 = LLT::scalable_vector(4, s8);
101 const LLT nxv8s8 = LLT::scalable_vector(8, s8);
102 const LLT nxv16s8 = LLT::scalable_vector(16, s8);
103 const LLT nxv32s8 = LLT::scalable_vector(32, s8);
104 const LLT nxv64s8 = LLT::scalable_vector(64, s8);
105
106 const LLT nxv1s16 = LLT::scalable_vector(1, s16);
107 const LLT nxv2s16 = LLT::scalable_vector(2, s16);
108 const LLT nxv4s16 = LLT::scalable_vector(4, s16);
109 const LLT nxv8s16 = LLT::scalable_vector(8, s16);
110 const LLT nxv16s16 = LLT::scalable_vector(16, s16);
111 const LLT nxv32s16 = LLT::scalable_vector(32, s16);
112
113 const LLT nxv1s32 = LLT::scalable_vector(1, s32);
114 const LLT nxv2s32 = LLT::scalable_vector(2, s32);
115 const LLT nxv4s32 = LLT::scalable_vector(4, s32);
116 const LLT nxv8s32 = LLT::scalable_vector(8, s32);
117 const LLT nxv16s32 = LLT::scalable_vector(16, s32);
118
119 const LLT nxv1s64 = LLT::scalable_vector(1, s64);
120 const LLT nxv2s64 = LLT::scalable_vector(2, s64);
121 const LLT nxv4s64 = LLT::scalable_vector(4, s64);
122 const LLT nxv8s64 = LLT::scalable_vector(8, s64);
123
124 const LLT nxv1p0 = LLT::scalable_vector(1, p0);
125 const LLT nxv2p0 = LLT::scalable_vector(2, p0);
126 const LLT nxv4p0 = LLT::scalable_vector(4, p0);
127 const LLT nxv8p0 = LLT::scalable_vector(8, p0);
128 const LLT nxv16p0 = LLT::scalable_vector(16, p0);
129
130 using namespace TargetOpcode;
131
132 auto BoolVecTys = {nxv1s1, nxv2s1, nxv4s1, nxv8s1, nxv16s1, nxv32s1, nxv64s1};
133
134 auto IntOrFPVecTys = {nxv1s8, nxv2s8, nxv4s8, nxv8s8, nxv16s8, nxv32s8,
135 nxv64s8, nxv1s16, nxv2s16, nxv4s16, nxv8s16, nxv16s16,
136 nxv32s16, nxv1s32, nxv2s32, nxv4s32, nxv8s32, nxv16s32,
137 nxv1s64, nxv2s64, nxv4s64, nxv8s64};
138
139 auto PtrVecTys = {nxv1p0, nxv2p0, nxv4p0, nxv8p0, nxv16p0};
140
141 getActionDefinitionsBuilder({G_ADD, G_SUB})
142 .legalFor({sXLen})
143 .legalIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST))
144 .customFor(ST.is64Bit(), {s32})
146 .clampScalar(0, sXLen, sXLen);
147
148 getActionDefinitionsBuilder({G_AND, G_OR, G_XOR})
149 .legalFor({sXLen})
150 .legalIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST))
152 .clampScalar(0, sXLen, sXLen);
153
155 {G_UADDE, G_UADDO, G_USUBE, G_USUBO, G_READ_REGISTER, G_WRITE_REGISTER})
156 .lower();
157
158 getActionDefinitionsBuilder({G_SADDE, G_SADDO, G_SSUBE, G_SSUBO})
159 .minScalar(0, sXLen)
160 .lower();
161
162 // TODO: Use Vector Single-Width Saturating Instructions for vector types.
164 {G_UADDSAT, G_SADDSAT, G_USUBSAT, G_SSUBSAT, G_SSHLSAT, G_USHLSAT})
165 .lower();
166
167 getActionDefinitionsBuilder({G_SHL, G_ASHR, G_LSHR})
168 .legalFor({{sXLen, sXLen}})
169 .customFor(ST.is64Bit(), {{s32, s32}})
170 .widenScalarToNextPow2(0)
171 .clampScalar(1, sXLen, sXLen)
172 .clampScalar(0, sXLen, sXLen);
173
174 getActionDefinitionsBuilder({G_ZEXT, G_SEXT, G_ANYEXT})
175 .legalFor({{s32, s16}})
176 .legalFor(ST.is64Bit(), {{s64, s16}, {s64, s32}})
177 .legalIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
178 typeIsLegalIntOrFPVec(1, IntOrFPVecTys, ST)))
179 .customIf(typeIsLegalBoolVec(1, BoolVecTys, ST))
180 .maxScalar(0, sXLen);
181
182 getActionDefinitionsBuilder(G_TRUNC).alwaysLegal();
183
184 {
185 LegalityPredicate ValidSextInRegWidth = all(sizeIs(0, 64), immIs(0, 32));
186
187 if (STI.hasStdExtZbb())
188 ValidSextInRegWidth =
189 LegalityPredicates::any(ValidSextInRegWidth, immInSet(0, {8, 16}));
190
191 getActionDefinitionsBuilder(G_SEXT_INREG)
192 .legalIf(all(typeIs(0, sXLen), ValidSextInRegWidth))
193 .clampScalar(0, sXLen, sXLen)
194 .lower();
195 }
196
197 // Merge/Unmerge
198 for (unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
199 auto &MergeUnmergeActions = getActionDefinitionsBuilder(Op);
200 unsigned BigTyIdx = Op == G_MERGE_VALUES ? 0 : 1;
201 unsigned LitTyIdx = Op == G_MERGE_VALUES ? 1 : 0;
202 if (XLen == 32 && (ST.hasStdExtD() || ST.hasStdExtZilsd())) {
203 MergeUnmergeActions.legalIf(
204 all(typeIs(BigTyIdx, s64), typeIs(LitTyIdx, s32)));
205 }
206 MergeUnmergeActions.widenScalarToNextPow2(LitTyIdx, XLen)
207 .widenScalarToNextPow2(BigTyIdx, XLen)
208 .clampScalar(LitTyIdx, sXLen, sXLen)
209 .clampScalar(BigTyIdx, sXLen, sXLen);
210 }
211
212 getActionDefinitionsBuilder({G_FSHL, G_FSHR}).lower();
213
214 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
215 .legalFor(ST.hasStdExtZbb() || ST.hasStdExtZbkb(), {{sXLen, sXLen}})
216 .customFor(ST.is64Bit() && (ST.hasStdExtZbb() || ST.hasStdExtZbkb()),
217 {{s32, s32}})
218 .lower();
219
220 getActionDefinitionsBuilder(G_BITREVERSE)
221 .customFor(ST.hasStdExtZbkb(), {s8})
222 .maxScalar(0, sXLen)
223 .lower();
224
225 getActionDefinitionsBuilder(G_BITCAST).legalIf(
227 typeIsLegalBoolVec(0, BoolVecTys, ST)),
229 typeIsLegalBoolVec(1, BoolVecTys, ST))));
230
231 auto &BSWAPActions = getActionDefinitionsBuilder(G_BSWAP);
232 if (ST.hasStdExtZbb() || ST.hasStdExtZbkb())
233 BSWAPActions.legalFor({sXLen}).clampScalar(0, sXLen, sXLen);
234 else
235 BSWAPActions.maxScalar(0, sXLen).lower();
236
237 getActionDefinitionsBuilder(G_CLMUL)
238 .legalFor(ST.hasStdExtZbkc(), {sXLen})
239 .unsupported();
240
241 getActionDefinitionsBuilder(G_CLMULH)
242 .legalFor(ST.hasStdExtZbkc(), {sXLen})
243 .customFor(ST.is64Bit() && ST.hasStdExtZbkc(), {s32})
244 .unsupported();
245
246 // CLMULR is Zbc-only; Zbkc is a subset that has CLMUL/CLMULH but not CLMULR.
247 getActionDefinitionsBuilder(G_CLMULR)
248 .legalFor(ST.hasStdExtZbc(), {sXLen})
249 .customFor(ST.is64Bit() && ST.hasStdExtZbc(), {s32})
250 .unsupported();
251
252 auto &CountZerosActions = getActionDefinitionsBuilder({G_CTLZ, G_CTTZ});
253 auto &CountZerosPoisonActions =
254 getActionDefinitionsBuilder({G_CTLZ_ZERO_POISON, G_CTTZ_ZERO_POISON});
255 if (ST.hasStdExtZbb()) {
256 CountZerosActions.legalFor({{sXLen, sXLen}})
257 .customFor({{s32, s32}})
258 .clampScalar(0, s32, sXLen)
259 .widenScalarToNextPow2(0)
260 .scalarSameSizeAs(1, 0);
261 } else {
262 CountZerosActions.maxScalar(0, sXLen).scalarSameSizeAs(1, 0).lower();
263 CountZerosPoisonActions.maxScalar(0, sXLen).scalarSameSizeAs(1, 0);
264 }
265 CountZerosPoisonActions.lower();
266
267 auto &CountSignActions = getActionDefinitionsBuilder(G_CTLS);
268 if (ST.hasStdExtP()) {
269 CountSignActions.legalFor({{sXLen, sXLen}})
270 .customFor({{s32, s32}})
271 .clampScalar(0, s32, sXLen)
272 .widenScalarToNextPow2(0)
273 .scalarSameSizeAs(1, 0);
274 } else {
275 CountSignActions.maxScalar(0, sXLen).scalarSameSizeAs(1, 0).lower();
276 }
277
278 auto &CTPOPActions = getActionDefinitionsBuilder(G_CTPOP);
279 if (ST.hasStdExtZbb()) {
280 CTPOPActions.legalFor({{sXLen, sXLen}})
281 .clampScalar(0, sXLen, sXLen)
282 .scalarSameSizeAs(1, 0);
283 } else {
284 CTPOPActions.widenScalarToNextPow2(0, /*Min*/ 8)
285 .clampScalar(0, s8, sXLen)
286 .scalarSameSizeAs(1, 0)
287 .lower();
288 }
289
290 getActionDefinitionsBuilder(G_CONSTANT)
291 .legalFor({p0})
292 .legalFor(!ST.is64Bit(), {s32})
293 .customFor(ST.is64Bit(), {s64})
294 .widenScalarToNextPow2(0)
295 .clampScalar(0, sXLen, sXLen);
296
297 // TODO: transform illegal vector types into legal vector type
298 getActionDefinitionsBuilder(G_FREEZE)
299 .legalFor({s16, s32, p0})
300 .legalFor(ST.is64Bit(), {s64})
301 .legalIf(typeIsLegalBoolVec(0, BoolVecTys, ST))
302 .legalIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST))
303 .widenScalarToNextPow2(0)
304 .clampScalar(0, s16, sXLen);
305
306 // TODO: transform illegal vector types into legal vector type
307 // TODO: Merge with G_FREEZE?
308 getActionDefinitionsBuilder(
309 {G_IMPLICIT_DEF, G_CONSTANT_FOLD_BARRIER})
310 .legalFor({s32, sXLen, p0})
311 .legalIf(typeIsLegalBoolVec(0, BoolVecTys, ST))
312 .legalIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST))
313 .widenScalarToNextPow2(0)
314 .clampScalar(0, s32, sXLen);
315
316 getActionDefinitionsBuilder(G_ICMP)
317 .legalFor({{sXLen, sXLen}, {sXLen, p0}})
318 .legalIf(all(typeIsLegalBoolVec(0, BoolVecTys, ST),
319 typeIsLegalIntOrFPVec(1, IntOrFPVecTys, ST)))
320 .widenScalarOrEltToNextPow2OrMinSize(1, 8)
321 .clampScalar(1, sXLen, sXLen)
322 .clampScalar(0, sXLen, sXLen);
323
324 getActionDefinitionsBuilder(G_SELECT)
325 .legalFor({{s32, sXLen}, {p0, sXLen}})
326 .legalIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
327 typeIsLegalBoolVec(1, BoolVecTys, ST)))
328 .legalFor(XLen == 64 || ST.hasStdExtD(), {{s64, sXLen}})
329 .widenScalarToNextPow2(0)
330 .clampScalar(0, s32, (XLen == 64 || ST.hasStdExtD()) ? s64 : s32)
331 .clampScalar(1, sXLen, sXLen);
332
333 auto &LoadActions = getActionDefinitionsBuilder(G_LOAD);
334 auto &StoreActions = getActionDefinitionsBuilder(G_STORE);
335 auto &ExtLoadActions = getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD});
336
337 // Return the alignment needed for scalar memory ops. If unaligned scalar mem
338 // is supported, we only require byte alignment. Otherwise, we need the memory
339 // op to be natively aligned.
340 auto getScalarMemAlign = [&ST](unsigned Size) {
341 return ST.enableUnalignedScalarMem() ? 8 : Size;
342 };
343
344 LoadActions.legalForTypesWithMemDesc(
345 {{s16, p0, s8, getScalarMemAlign(8)},
346 {s32, p0, s8, getScalarMemAlign(8)},
347 {s16, p0, s16, getScalarMemAlign(16)},
348 {s32, p0, s16, getScalarMemAlign(16)},
349 {s32, p0, s32, getScalarMemAlign(32)},
350 {p0, p0, sXLen, getScalarMemAlign(XLen)}});
351 StoreActions.legalForTypesWithMemDesc(
352 {{s16, p0, s8, getScalarMemAlign(8)},
353 {s32, p0, s8, getScalarMemAlign(8)},
354 {s16, p0, s16, getScalarMemAlign(16)},
355 {s32, p0, s16, getScalarMemAlign(16)},
356 {s32, p0, s32, getScalarMemAlign(32)},
357 {p0, p0, sXLen, getScalarMemAlign(XLen)}});
358 ExtLoadActions.legalForTypesWithMemDesc(
359 {{sXLen, p0, s8, getScalarMemAlign(8)},
360 {sXLen, p0, s16, getScalarMemAlign(16)}});
361 if (XLen == 64) {
362 LoadActions.legalForTypesWithMemDesc(
363 {{s64, p0, s8, getScalarMemAlign(8)},
364 {s64, p0, s16, getScalarMemAlign(16)},
365 {s64, p0, s32, getScalarMemAlign(32)},
366 {s64, p0, s64, getScalarMemAlign(64)}});
367 StoreActions.legalForTypesWithMemDesc(
368 {{s64, p0, s8, getScalarMemAlign(8)},
369 {s64, p0, s16, getScalarMemAlign(16)},
370 {s64, p0, s32, getScalarMemAlign(32)},
371 {s64, p0, s64, getScalarMemAlign(64)}});
372 ExtLoadActions.legalForTypesWithMemDesc(
373 {{s64, p0, s32, getScalarMemAlign(32)}});
374 } else if (ST.hasStdExtD() || ST.hasStdExtZilsd()) {
375 // RV32: s64 is legal for f64 (D/Zdinx) or i64 (Zilsd); LLT cannot tell the
376 // two apart, so one rule covers both.
377 // FIXME: We require natural alignment, so under -mzilsd-word-align an
378 // align-4 i64 access is split into two s32 ones. riscv-prera-zilsd-opt
379 // merges them back into LD_RV32/SD_RV32, but it is skipped at -O0.
380 LoadActions.legalForTypesWithMemDesc(
381 {{s64, p0, s64, getScalarMemAlign(64)}});
382 StoreActions.legalForTypesWithMemDesc(
383 {{s64, p0, s64, getScalarMemAlign(64)}});
384 }
385
386 // Vector loads/stores.
387 if (ST.hasVInstructions()) {
388 LoadActions.legalForTypesWithMemDesc({{nxv2s8, p0, nxv2s8, 8},
389 {nxv4s8, p0, nxv4s8, 8},
390 {nxv8s8, p0, nxv8s8, 8},
391 {nxv16s8, p0, nxv16s8, 8},
392 {nxv32s8, p0, nxv32s8, 8},
393 {nxv64s8, p0, nxv64s8, 8},
394 {nxv2s16, p0, nxv2s16, 16},
395 {nxv4s16, p0, nxv4s16, 16},
396 {nxv8s16, p0, nxv8s16, 16},
397 {nxv16s16, p0, nxv16s16, 16},
398 {nxv32s16, p0, nxv32s16, 16},
399 {nxv2s32, p0, nxv2s32, 32},
400 {nxv4s32, p0, nxv4s32, 32},
401 {nxv8s32, p0, nxv8s32, 32},
402 {nxv16s32, p0, nxv16s32, 32}});
403 StoreActions.legalForTypesWithMemDesc({{nxv2s8, p0, nxv2s8, 8},
404 {nxv4s8, p0, nxv4s8, 8},
405 {nxv8s8, p0, nxv8s8, 8},
406 {nxv16s8, p0, nxv16s8, 8},
407 {nxv32s8, p0, nxv32s8, 8},
408 {nxv64s8, p0, nxv64s8, 8},
409 {nxv2s16, p0, nxv2s16, 16},
410 {nxv4s16, p0, nxv4s16, 16},
411 {nxv8s16, p0, nxv8s16, 16},
412 {nxv16s16, p0, nxv16s16, 16},
413 {nxv32s16, p0, nxv32s16, 16},
414 {nxv2s32, p0, nxv2s32, 32},
415 {nxv4s32, p0, nxv4s32, 32},
416 {nxv8s32, p0, nxv8s32, 32},
417 {nxv16s32, p0, nxv16s32, 32}});
418
419 if (ST.getELen() == 64) {
420 LoadActions.legalForTypesWithMemDesc({{nxv1s8, p0, nxv1s8, 8},
421 {nxv1s16, p0, nxv1s16, 16},
422 {nxv1s32, p0, nxv1s32, 32}});
423 StoreActions.legalForTypesWithMemDesc({{nxv1s8, p0, nxv1s8, 8},
424 {nxv1s16, p0, nxv1s16, 16},
425 {nxv1s32, p0, nxv1s32, 32}});
426 }
427
428 if (ST.hasVInstructionsI64()) {
429 LoadActions.legalForTypesWithMemDesc({{nxv1s64, p0, nxv1s64, 64},
430 {nxv2s64, p0, nxv2s64, 64},
431 {nxv4s64, p0, nxv4s64, 64},
432 {nxv8s64, p0, nxv8s64, 64}});
433 StoreActions.legalForTypesWithMemDesc({{nxv1s64, p0, nxv1s64, 64},
434 {nxv2s64, p0, nxv2s64, 64},
435 {nxv4s64, p0, nxv4s64, 64},
436 {nxv8s64, p0, nxv8s64, 64}});
437 }
438
439 // we will take the custom lowering logic if we have scalable vector types
440 // with non-standard alignments
441 LoadActions.customIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST));
442 StoreActions.customIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST));
443
444 // Pointers require that XLen sized elements are legal.
445 if (XLen <= ST.getELen()) {
446 LoadActions.customIf(typeIsLegalPtrVec(0, PtrVecTys, ST));
447 StoreActions.customIf(typeIsLegalPtrVec(0, PtrVecTys, ST));
448 }
449 }
450
451 LoadActions.widenScalarToNextPow2(0, /* MinSize = */ 8)
452 .lowerIfMemSizeNotByteSizePow2()
453 .clampScalar(0, s16, sXLen)
454 .lower();
455 StoreActions
456 .clampScalar(0, s16, sXLen)
457 .lowerIfMemSizeNotByteSizePow2()
458 .lower();
459
460 ExtLoadActions.widenScalarToNextPow2(0).clampScalar(0, sXLen, sXLen).lower();
461
462 getActionDefinitionsBuilder({G_PTR_ADD, G_PTRMASK}).legalFor({{p0, sXLen}});
463
464 getActionDefinitionsBuilder(G_PTRTOINT)
465 .legalFor({{sXLen, p0}})
466 .clampScalar(0, sXLen, sXLen);
467
468 getActionDefinitionsBuilder(G_INTTOPTR)
469 .legalFor({{p0, sXLen}})
470 .clampScalar(1, sXLen, sXLen);
471
472 getActionDefinitionsBuilder(G_BR).alwaysLegal();
473
474 getActionDefinitionsBuilder(G_BRCOND).legalFor({sXLen}).minScalar(0, sXLen);
475
476 getActionDefinitionsBuilder(G_BRJT).customFor({{p0, sXLen}});
477
478 getActionDefinitionsBuilder(G_BRINDIRECT).legalFor({p0});
479
480 getActionDefinitionsBuilder(G_PHI)
481 .legalFor({p0, s32, sXLen})
482 .widenScalarToNextPow2(0)
483 .clampScalar(0, s32, sXLen);
484
485 getActionDefinitionsBuilder({G_GLOBAL_VALUE, G_JUMP_TABLE, G_CONSTANT_POOL})
486 .legalFor({p0});
487
488 if (ST.hasStdExtZmmul()) {
489 getActionDefinitionsBuilder(G_MUL)
490 .legalFor({sXLen})
491 .widenScalarToNextPow2(0)
492 .clampScalar(0, sXLen, sXLen);
493
494 // clang-format off
495 getActionDefinitionsBuilder({G_SMULH, G_UMULH})
496 .legalFor({sXLen})
497 .lower();
498 // clang-format on
499
500 getActionDefinitionsBuilder({G_SMULO, G_UMULO}).minScalar(0, sXLen).lower();
501 } else {
502 getActionDefinitionsBuilder(G_MUL)
503 .libcallFor({sXLen, sDoubleXLen})
504 .widenScalarToNextPow2(0)
505 .clampScalar(0, sXLen, sDoubleXLen);
506
507 getActionDefinitionsBuilder({G_SMULH, G_UMULH}).lowerFor({sXLen});
508
509 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
510 .minScalar(0, sXLen)
511 // Widen sXLen to sDoubleXLen so we can use a single libcall to get
512 // the low bits for the mul result and high bits to do the overflow
513 // check.
514 .widenScalarIf(typeIs(0, sXLen),
515 LegalizeMutations::changeTo(0, sDoubleXLen))
516 .lower();
517 }
518
519 if (ST.hasStdExtM()) {
520 getActionDefinitionsBuilder({G_SDIV, G_UDIV, G_UREM})
521 .legalFor({sXLen})
522 .customFor({s32})
523 .libcallFor({sDoubleXLen})
524 .clampScalar(0, s32, sDoubleXLen)
525 .widenScalarToNextPow2(0);
526 getActionDefinitionsBuilder(G_SREM)
527 .legalFor({sXLen})
528 .libcallFor({sDoubleXLen})
529 .clampScalar(0, sXLen, sDoubleXLen)
530 .widenScalarToNextPow2(0);
531 } else {
532 getActionDefinitionsBuilder({G_UDIV, G_SDIV, G_UREM, G_SREM})
533 .libcallFor({sXLen, sDoubleXLen})
534 .clampScalar(0, sXLen, sDoubleXLen)
535 .widenScalarToNextPow2(0);
536 }
537
538 // TODO: Use libcall for sDoubleXLen.
539 getActionDefinitionsBuilder({G_SDIVREM, G_UDIVREM}).lower();
540
541 getActionDefinitionsBuilder(G_ABS)
542 .customFor(ST.hasStdExtZbb(), {sXLen})
543 .minScalar(ST.hasStdExtZbb(), 0, sXLen)
544 .lower();
545
546 getActionDefinitionsBuilder({G_ABDS, G_ABDU})
547 .minScalar(ST.hasStdExtZbb(), 0, sXLen)
548 .lower();
549
550 getActionDefinitionsBuilder({G_UMAX, G_UMIN, G_SMAX, G_SMIN})
551 .legalFor(ST.hasStdExtZbb(), {sXLen})
552 .minScalar(ST.hasStdExtZbb(), 0, sXLen)
553 .lower();
554
555 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
556
557 getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});
558
559 getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();
560
561 getActionDefinitionsBuilder({G_MEMCPY_INLINE, G_MEMSET_INLINE}).lower();
562
563 getActionDefinitionsBuilder({G_DYN_STACKALLOC, G_STACKSAVE, G_STACKRESTORE})
564 .lower();
565
566 // On RV64 the 64-bit counter CSRs (cycle/time) are read directly. On RV32
567 // they are custom-legally lowered to a re-read-the-high-half loop (see
568 // legalizeReadCounter).
569 getActionDefinitionsBuilder({G_READCYCLECOUNTER, G_READSTEADYCOUNTER})
570 .legalFor(ST.is64Bit(), {s64})
571 .customFor(!ST.is64Bit(), {s64});
572
573 // FP Operations
574
575 // FIXME: Support s128 for rv32 when libcall handling is able to use sret.
576 getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMA, G_FSQRT,
577 G_FMAXNUM, G_FMINNUM, G_FMAXIMUMNUM,
578 G_FMINIMUMNUM})
579 .legalFor(ST.hasStdExtF(), {s32})
580 .legalFor(ST.hasStdExtD(), {s64})
581 .legalFor(ST.hasStdExtZfh(), {s16})
582 .libcallFor({s32, s64})
583 .libcallFor(ST.is64Bit(), {s128});
584
585 getActionDefinitionsBuilder({G_FNEG, G_FABS})
586 .legalFor(ST.hasStdExtF(), {s32})
587 .legalFor(ST.hasStdExtD(), {s64})
588 .legalFor(ST.hasStdExtZfh(), {s16})
589 .lowerFor({s32, s64, s128});
590
591 getActionDefinitionsBuilder(G_FREM)
592 .libcallFor({s32, s64})
593 .libcallFor(ST.is64Bit(), {s128})
594 .minScalar(0, s32)
595 .scalarize(0);
596
597 getActionDefinitionsBuilder(G_FCOPYSIGN)
598 .legalFor(ST.hasStdExtF(), {{s32, s32}})
599 .legalFor(ST.hasStdExtD(), {{s64, s64}, {s32, s64}, {s64, s32}})
600 .legalFor(ST.hasStdExtZfh(), {{s16, s16}, {s16, s32}, {s32, s16}})
601 .legalFor(ST.hasStdExtZfh() && ST.hasStdExtD(), {{s16, s64}, {s64, s16}})
602 .lower();
603
604 getActionDefinitionsBuilder(G_FPTRUNC)
605 .legalFor(ST.hasStdExtD(), {{s32, s64}})
606 .legalFor(ST.hasStdExtZfhmin(), {{s16, s32}})
607 .legalFor(ST.hasStdExtZfhmin() && ST.hasStdExtD(), {{s16, s64}})
608 .libcallFor({{s16, s32}, {s16, s64}, {s32, s64}})
609 .libcallFor(ST.is64Bit(), {{s32, s128}, {s64, s128}});
610 getActionDefinitionsBuilder(G_FPEXT)
611 .legalFor(ST.hasStdExtD(), {{s64, s32}})
612 .legalFor(ST.hasStdExtZfhmin(), {{s32, s16}})
613 .legalFor(ST.hasStdExtZfhmin() && ST.hasStdExtD(), {{s64, s16}})
614 .libcallFor(!ST.hasStdExtZfhmin(), {{s32, s16}})
615 .libcallFor(!(ST.hasStdExtZfhmin() && ST.hasStdExtD()), {{s64, s16}})
616 .libcallFor({{s64, s32}})
617 .libcallFor(ST.is64Bit(), {{s128, s32}, {s128, s64}});
618
619 getActionDefinitionsBuilder(G_FCMP)
620 .legalFor(ST.hasStdExtF(), {{sXLen, s32}})
621 .legalFor(ST.hasStdExtD(), {{sXLen, s64}})
622 .legalFor(ST.hasStdExtZfh(), {{sXLen, s16}})
623 .clampScalar(0, sXLen, sXLen)
624 .minScalar(1, s32)
625 .libcallFor({{sXLen, s32}, {sXLen, s64}})
626 .libcallFor(ST.is64Bit(), {{sXLen, s128}});
627
628 // TODO: Support vector version of G_IS_FPCLASS.
629 getActionDefinitionsBuilder(G_IS_FPCLASS)
630 .customFor(ST.hasStdExtF(), {{s1, s32}})
631 .customFor(ST.hasStdExtD(), {{s1, s64}})
632 .customFor(ST.hasStdExtZfh(), {{s1, s16}})
633 .lower();
634
635 getActionDefinitionsBuilder(G_FCONSTANT)
636 .legalFor(ST.hasStdExtF(), {s32})
637 .legalFor(ST.hasStdExtD(), {s64})
638 .legalFor(ST.hasStdExtZfhmin(), {s16})
639 .lowerFor({s32, s64, s128});
640
641 getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
642 .legalFor(ST.hasStdExtF(), {{sXLen, s32}})
643 .legalFor(ST.hasStdExtD(), {{sXLen, s64}})
644 .legalFor(ST.hasStdExtZfh(), {{sXLen, s16}})
645 .customFor(ST.is64Bit() && ST.hasStdExtF(), {{s32, s32}})
646 .customFor(ST.is64Bit() && ST.hasStdExtD(), {{s32, s64}})
647 .customFor(ST.is64Bit() && ST.hasStdExtZfh(), {{s32, s16}})
648 .widenScalarToNextPow2(0)
649 .minScalar(0, s32)
650 // The magnitude of a half is at most 65504, so with Zfh use fcvt.w[u].h
651 // and extend the i32 result. Otherwise promote the half source to float
652 // (via fcvt.s.h with Zfhmin, __extendhfsf2 without) and use the float
653 // conversion. On RV32, exclude i64 results here so that they get
654 // narrowed to i32 first.
655 .widenScalarIf(
656 [=, &ST](const LegalityQuery &Query) {
657 return Query.Types[1] == f16 && !ST.hasStdExtZfh() &&
658 (ST.is64Bit() || Query.Types[0] == s32);
659 },
660 changeTo(1, s32))
661 .libcallFor(!ST.hasStdExtZfhmin(), {{s64, f16}})
662 .narrowScalarFor({{s64, f16}}, changeTo(0, s32))
663 .libcallFor({{s32, s32}, {s64, s32}, {s32, s64}, {s64, s64}})
664 .libcallFor(ST.is64Bit(), {{s32, s128}, {s64, s128}}) // FIXME RV32.
665 .libcallFor(ST.is64Bit(), {{s128, s32}, {s128, s64}, {s128, s128}});
666
667 // Unlike G_FPTOSI/G_FPTOUI these need no libcalls for out-of-range values:
668 // the RISC-V conversions already saturate. There is no legalFor() because
669 // they do not produce 0 for NaN, which legalizeCustom fixes up with a
670 // compare and a select. The remaining cases fall back to the generic
671 // lowering, which clamps before converting and only handles scalars.
672 getActionDefinitionsBuilder({G_FPTOSI_SAT, G_FPTOUI_SAT})
673 .customFor(ST.hasStdExtF(), {{sXLen, s32}})
674 .customFor(ST.hasStdExtD(), {{sXLen, s64}})
675 .customFor(ST.hasStdExtZfh(), {{sXLen, s16}})
676 .customFor(ST.is64Bit() && ST.hasStdExtF(), {{s32, s32}})
677 .customFor(ST.is64Bit() && ST.hasStdExtD(), {{s32, s64}})
678 .customFor(ST.is64Bit() && ST.hasStdExtZfh(), {{s32, s16}})
679 // f16 extends exactly to f32; converting via f32 avoids needing rules
680 // for every {sXX, s16} combination.
681 .widenScalarIf(typeIs(1, s16), changeTo(1, s32))
682 .lowerIf(all(isScalar(0), isScalar(1)));
683
684 getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
685 .legalFor(ST.hasStdExtF(), {{sXLen, s32}})
686 .legalFor(ST.hasStdExtD(), {{sXLen, s64}})
687 .legalFor(ST.hasStdExtZfh(), {{sXLen, s16}})
688 .customFor(ST.is64Bit() && ST.hasStdExtF(), {{s32, s32}})
689 .customFor(ST.is64Bit() && ST.hasStdExtD(), {{s32, s64}})
690 .customFor(ST.is64Bit() && ST.hasStdExtZfh(), {{s32, s16}})
691 .minScalar(1, s32)
692 .libcallFor({{s32, s32},
693 {s64, s32},
694 {s32, s64},
695 {s64, s64},
696 {s32, s128},
697 {s64, s128}});
698
699 getActionDefinitionsBuilder({G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT})
700 .legalFor(ST.hasStdExtF(), {{sXLen, s32}})
701 .legalFor(ST.hasStdExtD(), {{sXLen, s64}})
702 .legalFor(ST.hasStdExtZfh(), {{sXLen, s16}})
703 .minScalar(0, sXLen)
704 .minScalar(1, s32)
705 .libcallFor({{s32, s32},
706 {s64, s32},
707 {s32, s64},
708 {s64, s64},
709 {s32, s128},
710 {s64, s128}});
711
712 getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
713 .legalFor(ST.hasStdExtF(), {{s32, sXLen}})
714 .legalFor(ST.hasStdExtD(), {{s64, sXLen}})
715 .legalFor(ST.hasStdExtZfh(), {{s16, sXLen}})
716 .widenScalarToNextPow2(1)
717 // Promote to XLen if the operation is legal.
718 .widenScalarIf(
719 [=, &ST](const LegalityQuery &Query) {
720 return Query.Types[0].isScalar() && Query.Types[1].isScalar() &&
721 (Query.Types[1].getSizeInBits() < ST.getXLen()) &&
722 ((ST.hasStdExtF() && Query.Types[0].getSizeInBits() == 32) ||
723 (ST.hasStdExtD() && Query.Types[0].getSizeInBits() == 64) ||
724 (ST.hasStdExtZfh() &&
725 Query.Types[0].getSizeInBits() == 16));
726 },
728 // Otherwise only promote to s32 since we have si libcalls.
729 .minScalar(1, s32)
730 .libcallFor({{s32, s32}, {s64, s32}, {s32, s64}, {s64, s64}})
731 .libcallFor(ST.is64Bit(), {{s128, s32}, {s128, s64}}) // FIXME RV32.
732 .libcallFor(ST.is64Bit(), {{s32, s128}, {s64, s128}, {s128, s128}});
733
734 // FIXME: We can do custom inline expansion like SelectionDAG.
735 getActionDefinitionsBuilder({G_FCEIL, G_FFLOOR, G_FRINT, G_FNEARBYINT,
736 G_INTRINSIC_TRUNC, G_INTRINSIC_ROUND,
737 G_INTRINSIC_ROUNDEVEN})
738 .legalFor(ST.hasStdExtZfa(), {s32})
739 .legalFor(ST.hasStdExtZfa() && ST.hasStdExtD(), {s64})
740 .legalFor(ST.hasStdExtZfa() && ST.hasStdExtZfh(), {s16})
741 .libcallFor({s32, s64})
742 .libcallFor(ST.is64Bit(), {s128});
743
744 getActionDefinitionsBuilder({G_FMAXIMUM, G_FMINIMUM})
745 .legalFor(ST.hasStdExtZfa(), {s32})
746 .legalFor(ST.hasStdExtZfa() && ST.hasStdExtD(), {s64})
747 .legalFor(ST.hasStdExtZfa() && ST.hasStdExtZfh(), {s16});
748
749 getActionDefinitionsBuilder({G_FCOS, G_FSIN, G_FTAN, G_FPOW, G_FLOG, G_FLOG2,
750 G_FLOG10, G_FEXP, G_FEXP2, G_FEXP10, G_FACOS,
751 G_FASIN, G_FATAN, G_FATAN2, G_FCOSH, G_FSINH,
752 G_FTANH, G_FMODF, G_FSINCOS})
753 .libcallFor({s32, s64})
754 .libcallFor(ST.is64Bit(), {s128});
755 getActionDefinitionsBuilder({G_FPOWI, G_FLDEXP})
756 .libcallFor({{s32, s32}, {s64, s32}})
757 .libcallFor(ST.is64Bit(), {s128, s32});
758
759 getActionDefinitionsBuilder(G_FCANONICALIZE)
760 .legalFor(ST.hasStdExtF(), {s32})
761 .legalFor(ST.hasStdExtD(), {s64})
762 .legalFor(ST.hasStdExtZfh(), {s16});
763
764 getActionDefinitionsBuilder(G_VASTART).customFor({p0});
765
766 // va_list must be a pointer, but most sized types are pretty easy to handle
767 // as the destination.
768 getActionDefinitionsBuilder(G_VAARG)
769 // TODO: Implement narrowScalar and widenScalar for G_VAARG for types
770 // other than sXLen.
771 .clampScalar(0, sXLen, sXLen)
772 .lowerForCartesianProduct({sXLen, p0}, {p0});
773
774 getActionDefinitionsBuilder(G_VSCALE)
775 .clampScalar(0, sXLen, sXLen)
776 .customFor({sXLen});
777
778 auto &SplatActions =
779 getActionDefinitionsBuilder(G_SPLAT_VECTOR)
780 .legalIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
781 typeIs(1, sXLen)))
782 .customIf(all(typeIsLegalBoolVec(0, BoolVecTys, ST), typeIs(1, s1)));
783 // Handle case of s64 element vectors on RV32. If the subtarget does not have
784 // f64, then try to lower it to G_SPLAT_VECTOR_SPLIT_64_VL. If the subtarget
785 // does have f64, then we don't know whether the type is an f64 or an i64,
786 // so mark the G_SPLAT_VECTOR as legal and decide later what to do with it,
787 // depending on how the instructions it consumes are legalized. They are not
788 // legalized yet since legalization is in reverse postorder, so we cannot
789 // make the decision at this moment.
790 if (XLen == 32) {
791 if (ST.hasVInstructionsF64() && ST.hasStdExtD())
792 SplatActions.legalIf(all(
793 typeInSet(0, {nxv1s64, nxv2s64, nxv4s64, nxv8s64}), typeIs(1, s64)));
794 else if (ST.hasVInstructionsI64())
795 SplatActions.customIf(all(
796 typeInSet(0, {nxv1s64, nxv2s64, nxv4s64, nxv8s64}), typeIs(1, s64)));
797 }
798
799 SplatActions.clampScalar(1, sXLen, sXLen);
800
801 LegalityPredicate ExtractSubvecBitcastPred = [=](const LegalityQuery &Query) {
802 LLT DstTy = Query.Types[0];
803 LLT SrcTy = Query.Types[1];
804 return DstTy.getElementType() == LLT::scalar(1) &&
805 DstTy.getElementCount().getKnownMinValue() >= 8 &&
806 SrcTy.getElementCount().getKnownMinValue() >= 8;
807 };
808 getActionDefinitionsBuilder(G_EXTRACT_SUBVECTOR)
809 // We don't have the ability to slide mask vectors down indexed by their
810 // i1 elements; the smallest we can do is i8. Often we are able to bitcast
811 // to equivalent i8 vectors.
812 .bitcastIf(
813 all(typeIsLegalBoolVec(0, BoolVecTys, ST),
814 typeIsLegalBoolVec(1, BoolVecTys, ST), ExtractSubvecBitcastPred),
815 [=](const LegalityQuery &Query) {
816 LLT CastTy = LLT::vector(
817 Query.Types[0].getElementCount().divideCoefficientBy(8), 8);
818 return std::pair(0, CastTy);
819 })
820 .customIf(LegalityPredicates::any(
821 all(typeIsLegalBoolVec(0, BoolVecTys, ST),
822 typeIsLegalBoolVec(1, BoolVecTys, ST)),
823 all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
824 typeIsLegalIntOrFPVec(1, IntOrFPVecTys, ST))));
825
826 getActionDefinitionsBuilder(G_INSERT_SUBVECTOR)
827 .customIf(all(typeIsLegalBoolVec(0, BoolVecTys, ST),
828 typeIsLegalBoolVec(1, BoolVecTys, ST)))
829 .customIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
830 typeIsLegalIntOrFPVec(1, IntOrFPVecTys, ST)));
831
832 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG_WITH_SUCCESS)
833 .lowerIf(all(typeInSet(0, {s8, s16, s32, s64}), typeIs(2, p0)));
834
835 getActionDefinitionsBuilder({G_ATOMIC_CMPXCHG, G_ATOMICRMW_ADD,
836 G_ATOMICRMW_XCHG, G_ATOMICRMW_AND,
837 G_ATOMICRMW_OR, G_ATOMICRMW_XOR})
838 .legalFor(ST.hasStdExtA(), {{sXLen, p0}})
839 .libcallFor(!ST.hasStdExtA(), {{s8, p0}, {s16, p0}, {s32, p0}, {s64, p0}})
840 .clampScalar(0, sXLen, sXLen);
841
842 getActionDefinitionsBuilder(G_ATOMICRMW_SUB)
843 .libcallFor(!ST.hasStdExtA(), {{s8, p0}, {s16, p0}, {s32, p0}, {s64, p0}})
844 .clampScalar(0, sXLen, sXLen)
845 .lower();
846
847 getActionDefinitionsBuilder(
848 {G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX, G_ATOMICRMW_UMIN})
849 .legalFor(ST.hasStdExtA(), {{sXLen, p0}})
850 .clampScalar(0, sXLen, sXLen)
851 .unsupported();
852
853 getActionDefinitionsBuilder(G_PREFETCH).legalIf(typeIs(0, p0));
854
855 LegalityPredicate InsertVectorEltPred = [=](const LegalityQuery &Query) {
856 LLT VecTy = Query.Types[0];
857 LLT EltTy = Query.Types[1];
858 return VecTy.getElementType() == EltTy;
859 };
860
861 getActionDefinitionsBuilder(G_INSERT_VECTOR_ELT)
862 .legalIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
863 InsertVectorEltPred, typeIs(2, sXLen)))
864 .legalIf(all(typeIsLegalBoolVec(0, BoolVecTys, ST), InsertVectorEltPred,
865 typeIs(2, sXLen)));
866
867 getActionDefinitionsBuilder({G_INTRINSIC, G_INTRINSIC_W_SIDE_EFFECTS})
868 .alwaysLegal();
869
870 getActionDefinitionsBuilder(G_FENCE).alwaysLegal();
871
872 getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP, G_UBSANTRAP}).alwaysLegal();
873
874 verify(*ST.getInstrInfo());
875}
876
878 MachineInstr &MI) const {
879 Intrinsic::ID IntrinsicID = cast<GIntrinsic>(MI).getIntrinsicID();
880
882 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntrinsicID)) {
883 if (II->hasScalarOperand() && !II->IsFPIntrinsic) {
884 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
885 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
886
887 auto OldScalar = MI.getOperand(II->ScalarOperand + 2).getReg();
888 // Legalize integer vx form intrinsic.
889 if (MRI.getType(OldScalar).isScalar()) {
890 if (MRI.getType(OldScalar).getSizeInBits() < sXLen.getSizeInBits()) {
891 Helper.Observer.changingInstr(MI);
892 Helper.widenScalarSrc(MI, sXLen, II->ScalarOperand + 2,
893 TargetOpcode::G_ANYEXT);
894 Helper.Observer.changedInstr(MI);
895 } else if (MRI.getType(OldScalar).getSizeInBits() >
896 sXLen.getSizeInBits()) {
897 // TODO: i64 in riscv32.
898 return false;
899 }
900 }
901 }
902 return true;
903 }
904
905 switch (IntrinsicID) {
906 default:
907 return false;
908 case Intrinsic::riscv_orc_b: {
909 if (!STI.hasStdExtZbb())
910 return false;
911
912 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
913 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
914 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
915 if (Ty == sXLen)
916 return true;
917 if (!STI.is64Bit() || Ty != LLT::scalar(32))
918 return false;
919
920 // Each output byte depends only on the corresponding input byte.
921 auto Src = MIRBuilder.buildAnyExt(sXLen, MI.getOperand(2));
922 auto Result = MIRBuilder.buildIntrinsic(IntrinsicID, {DstOp(sXLen)})
923 .addUse(Src.getReg(0));
924 MIRBuilder.buildTrunc(MI.getOperand(0), Result);
925 MI.eraseFromParent();
926 return true;
927 }
928 case Intrinsic::riscv_clmulh:
929 Helper.MIRBuilder.buildInstr(TargetOpcode::G_CLMULH, {MI.getOperand(0)},
930 {MI.getOperand(2), MI.getOperand(3)});
931 MI.eraseFromParent();
932 return true;
933 case Intrinsic::riscv_clmulr:
934 Helper.MIRBuilder.buildInstr(TargetOpcode::G_CLMULR, {MI.getOperand(0)},
935 {MI.getOperand(2), MI.getOperand(3)});
936 MI.eraseFromParent();
937 return true;
938 case Intrinsic::vacopy: {
939 // vacopy arguments must be legal because of the intrinsic signature.
940 // No need to check here.
941
942 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
943 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
944 MachineFunction &MF = *MI.getMF();
945 const DataLayout &DL = MIRBuilder.getDataLayout();
946 LLVMContext &Ctx = MF.getFunction().getContext();
947
948 Register DstLst = MI.getOperand(1).getReg();
949 LLT PtrTy = MRI.getType(DstLst);
950
951 // Load the source va_list
952 Align Alignment = DL.getABITypeAlign(getTypeForLLT(PtrTy, Ctx));
954 MachinePointerInfo(), MachineMemOperand::MOLoad, PtrTy, Alignment);
955 auto Tmp = MIRBuilder.buildLoad(PtrTy, MI.getOperand(2), *LoadMMO);
956
957 // Store the result in the destination va_list
960 MIRBuilder.buildStore(Tmp, DstLst, *StoreMMO);
961
962 MI.eraseFromParent();
963 return true;
964 }
965 case Intrinsic::riscv_vsetvli:
966 case Intrinsic::riscv_vsetvlimax:
967 case Intrinsic::riscv_masked_atomicrmw_add:
968 case Intrinsic::riscv_masked_atomicrmw_sub:
969 case Intrinsic::riscv_masked_atomicrmw_xchg:
970 case Intrinsic::riscv_masked_atomicrmw_max:
971 case Intrinsic::riscv_masked_atomicrmw_min:
972 case Intrinsic::riscv_masked_atomicrmw_umax:
973 case Intrinsic::riscv_masked_atomicrmw_umin:
974 case Intrinsic::riscv_masked_cmpxchg:
975 return true;
976 }
977}
978
979bool RISCVLegalizerInfo::legalizeVAStart(MachineInstr &MI,
980 MachineIRBuilder &MIRBuilder) const {
981 // Stores the address of the VarArgsFrameIndex slot into the memory location
982 assert(MI.getOpcode() == TargetOpcode::G_VASTART);
983 MachineFunction *MF = MI.getParent()->getParent();
985 int FI = FuncInfo->getVarArgsFrameIndex();
986 LLT AddrTy = MIRBuilder.getMRI()->getType(MI.getOperand(0).getReg());
987 auto FINAddr = MIRBuilder.buildFrameIndex(AddrTy, FI);
988 assert(MI.hasOneMemOperand());
989 MIRBuilder.buildStore(FINAddr, MI.getOperand(0).getReg(),
990 *MI.memoperands()[0]);
991 MI.eraseFromParent();
992 return true;
993}
994
995bool RISCVLegalizerInfo::legalizeReadCounter(
996 MachineInstr &MI, MachineIRBuilder &MIRBuilder,
997 GISelChangeObserver &Observer) const {
998 assert((MI.getOpcode() == TargetOpcode::G_READCYCLECOUNTER ||
999 MI.getOpcode() == TargetOpcode::G_READSTEADYCOUNTER) &&
1000 "Unexpected opcode");
1001 assert(!STI.is64Bit() && "READCYCLECOUNTER/READSTEADYCOUNTER only "
1002 "has custom type legalization on riscv32");
1003
1004 // On RV32 a 64-bit counter CSR must be read as two 32-bit halves. Because
1005 // the count may wrap between the two reads, re-read the high half and loop
1006 // until the two high reads agree.
1007 int64_t LoCounter, HiCounter;
1008 if (MI.getOpcode() == TargetOpcode::G_READCYCLECOUNTER) {
1009 LoCounter = RISCVSysReg::cycle;
1010 HiCounter = RISCVSysReg::cycleh;
1011 } else {
1012 LoCounter = RISCVSysReg::time;
1013 HiCounter = RISCVSysReg::timeh;
1014 }
1015
1016 MachineBasicBlock *BB = MI.getParent();
1017 MachineFunction &MF = *BB->getParent();
1018 const BasicBlock *LLVMBB = BB->getBasicBlock();
1019 DebugLoc DL = MI.getDebugLoc();
1020 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
1021
1022 // Split BB into an entry that falls through into a loop block, and a done
1023 // block that receives the remainder of BB and its original successors.
1024 MachineFunction::iterator It = std::next(BB->getIterator());
1025 MachineBasicBlock *LoopMBB = MF.CreateMachineBasicBlock(LLVMBB);
1026 MachineBasicBlock *DoneMBB = MF.CreateMachineBasicBlock(LLVMBB);
1027 MF.insert(It, LoopMBB);
1028 MF.insert(It, DoneMBB);
1029
1030 // Splice the instructions after the readcyclecounter into DoneMBB, notifying
1031 // the observer about each moved instruction so CSEInfo stays consistent.
1032 for (MachineBasicBlock::iterator I = std::next(MI.getIterator()),
1033 E = BB->end();
1034 I != E; ++I)
1035 Observer.changingInstr(*I);
1036 DoneMBB->splice(DoneMBB->begin(), BB,
1037 std::next(MachineBasicBlock::iterator(MI)), BB->end());
1038 for (MachineInstr &MovedMI : DoneMBB->instrs())
1039 Observer.changedInstr(MovedMI);
1041 BB->addSuccessor(LoopMBB);
1042
1043 LLT S32 = LLT::scalar(32);
1044 // Generic vregs carry the s32 type for G_MERGE_VALUES below, but are also
1045 // constrained to GPR so the target CSRRS/BNE instructions satisfy the
1046 // verifier's register-class constraints.
1047 auto CreateGPR = [&]() {
1049 MRI.setRegClass(R, &RISCV::GPRRegClass);
1050 return R;
1051 };
1052 Register LoReg = CreateGPR();
1053 Register HiReg = CreateGPR();
1054 Register ReadAgainReg = CreateGPR();
1055
1056 // read:
1057 // csrrs HiReg, counterh # high word
1058 // csrrs LoReg, counter # low word
1059 // csrrs ReadAgainReg, counterh
1060 // bne HiReg, ReadAgainReg, read
1061 // Emit the target instructions directly with BuildMI.
1062 const RISCVInstrInfo *TII = STI.getInstrInfo();
1063 BuildMI(LoopMBB, DL, TII->get(RISCV::CSRRS), HiReg)
1064 .addImm(HiCounter)
1065 .addReg(RISCV::X0);
1066 BuildMI(LoopMBB, DL, TII->get(RISCV::CSRRS), LoReg)
1067 .addImm(LoCounter)
1068 .addReg(RISCV::X0);
1069 BuildMI(LoopMBB, DL, TII->get(RISCV::CSRRS), ReadAgainReg)
1070 .addImm(HiCounter)
1071 .addReg(RISCV::X0);
1072
1073 BuildMI(LoopMBB, DL, TII->get(RISCV::BNE))
1074 .addReg(HiReg)
1075 .addReg(ReadAgainReg)
1076 .addMBB(LoopMBB);
1077
1078 LoopMBB->addSuccessor(LoopMBB);
1079 LoopMBB->addSuccessor(DoneMBB);
1080
1081 // Re-pair the two halves into the 64-bit result.
1082 Register DstReg = MI.getOperand(0).getReg();
1083 Observer.erasingInstr(MI);
1084 MI.eraseFromParent();
1085
1086 MIRBuilder.setInsertPt(*DoneMBB, DoneMBB->begin());
1087 MIRBuilder.setDebugLoc(DL);
1088 MIRBuilder.buildMergeValues(DstReg, {LoReg, HiReg});
1089 return true;
1090}
1091
1092bool RISCVLegalizerInfo::legalizeBRJT(MachineInstr &MI,
1093 MachineIRBuilder &MIRBuilder) const {
1094 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
1095 auto &MF = *MI.getParent()->getParent();
1096 const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
1097 unsigned EntrySize = MJTI->getEntrySize(MF.getDataLayout());
1098
1099 Register PtrReg = MI.getOperand(0).getReg();
1100 LLT PtrTy = MRI.getType(PtrReg);
1101 Register IndexReg = MI.getOperand(2).getReg();
1102 LLT IndexTy = MRI.getType(IndexReg);
1103
1104 if (!isPowerOf2_32(EntrySize))
1105 return false;
1106
1107 auto ShiftAmt = MIRBuilder.buildConstant(IndexTy, Log2_32(EntrySize));
1108 IndexReg = MIRBuilder.buildShl(IndexTy, IndexReg, ShiftAmt).getReg(0);
1109
1110 auto Addr = MIRBuilder.buildPtrAdd(PtrTy, PtrReg, IndexReg);
1111
1112 MachineMemOperand *MMO = MF.getMachineMemOperand(
1114 EntrySize, Align(MJTI->getEntryAlignment(MF.getDataLayout())));
1115
1116 Register TargetReg;
1117 switch (MJTI->getEntryKind()) {
1118 default:
1119 return false;
1121 // For PIC, the sequence is:
1122 // BRIND(load(Jumptable + index) + RelocBase)
1123 // RelocBase can be JumpTable, GOT or some sort of global base.
1124 unsigned LoadOpc =
1125 STI.is64Bit() ? TargetOpcode::G_SEXTLOAD : TargetOpcode::G_LOAD;
1126 auto Load = MIRBuilder.buildLoadInstr(LoadOpc, IndexTy, Addr, *MMO);
1127 TargetReg = MIRBuilder.buildPtrAdd(PtrTy, PtrReg, Load).getReg(0);
1128 break;
1129 }
1131 auto Load = MIRBuilder.buildLoadInstr(TargetOpcode::G_SEXTLOAD, IndexTy,
1132 Addr, *MMO);
1133 TargetReg = MIRBuilder.buildIntToPtr(PtrTy, Load).getReg(0);
1134 break;
1135 }
1137 TargetReg = MIRBuilder.buildLoad(PtrTy, Addr, *MMO).getReg(0);
1138 break;
1139 }
1140
1141 if (MF.getInfo<RISCVMachineFunctionInfo>()->hasCFProtectionBranch()) {
1142 // When cf-protection-branch is enabled, we need to use a software
1143 // guarded branch for jump table branch.
1144 MIRBuilder.buildInstr(RISCV::G_SW_GUARDED_BRIND, {}, {TargetReg});
1145 } else {
1146 MIRBuilder.buildBrIndirect(TargetReg);
1147 }
1148
1149 MI.eraseFromParent();
1150 return true;
1151}
1152
1153bool RISCVLegalizerInfo::shouldBeInConstantPool(const APInt &APImm,
1154 bool ShouldOptForSize) const {
1155 assert(APImm.getBitWidth() == 32 || APImm.getBitWidth() == 64);
1156 int64_t Imm = APImm.getSExtValue();
1157 // All simm32 constants should be handled by isel.
1158 // NOTE: The getMaxBuildIntsCost call below should return a value >= 2 making
1159 // this check redundant, but small immediates are common so this check
1160 // should have better compile time.
1161 if (isInt<32>(Imm))
1162 return false;
1163
1164 // We only need to cost the immediate, if constant pool lowering is enabled.
1165 if (!STI.useConstantPoolForLargeInts())
1166 return false;
1167
1169 if (Seq.size() <= STI.getMaxBuildIntsCost())
1170 return false;
1171
1172 // Optimizations below are disabled for opt size. If we're optimizing for
1173 // size, use a constant pool.
1174 if (ShouldOptForSize)
1175 return true;
1176 //
1177 // Special case. See if we can build the constant as (ADD (SLLI X, C), X) do
1178 // that if it will avoid a constant pool.
1179 // It will require an extra temporary register though.
1180 // If we have Zba we can use (ADD_UW X, (SLLI X, 32)) to handle cases where
1181 // low and high 32 bits are the same and bit 31 and 63 are set.
1182 unsigned ShiftAmt, AddOpc;
1183 RISCVMatInt::InstSeq SeqLo =
1184 RISCVMatInt::generateTwoRegInstSeq(Imm, STI, ShiftAmt, AddOpc);
1185 return !(!SeqLo.empty() && (SeqLo.size() + 2) <= STI.getMaxBuildIntsCost());
1186}
1187
1188bool RISCVLegalizerInfo::legalizeVScale(MachineInstr &MI,
1189 MachineIRBuilder &MIB) const {
1190 Register Dst = MI.getOperand(0).getReg();
1191
1192 // We define our scalable vector types for lmul=1 to use a 64 bit known
1193 // minimum size. e.g. <vscale x 2 x i32>. VLENB is in bytes so we calculate
1194 // vscale as VLENB / 8.
1195 static_assert(RISCV::RVVBitsPerBlock == 64, "Unexpected bits per block!");
1196 if (STI.getRealMinVLen() < RISCV::RVVBitsPerBlock)
1197 // Support for VLEN==32 is incomplete.
1198 return false;
1199
1200 // We assume VLENB is a multiple of 8. We manually choose the best shift
1201 // here because SimplifyDemandedBits isn't always able to simplify it.
1202 uint64_t Val = MI.getOperand(1).getCImm()->getZExtValue();
1203 if (isPowerOf2_64(Val)) {
1204 uint64_t Log2 = Log2_64(Val);
1205 if (Log2 < 3) {
1206 auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {sXLen}, {});
1207 MIB.buildLShr(Dst, VLENB, MIB.buildConstant(sXLen, 3 - Log2),
1209 } else if (Log2 > 3) {
1210 auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {sXLen}, {});
1211 MIB.buildShl(Dst, VLENB, MIB.buildConstant(sXLen, Log2 - 3));
1212 } else {
1213 MIB.buildInstr(RISCV::G_READ_VLENB, {Dst}, {});
1214 }
1215 } else if ((Val % 8) == 0) {
1216 // If the multiplier is a multiple of 8, scale it down to avoid needing
1217 // to shift the VLENB value.
1218 auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {sXLen}, {});
1219 MIB.buildMul(Dst, VLENB, MIB.buildConstant(sXLen, Val / 8));
1220 } else {
1221 auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {sXLen}, {});
1222 auto VScale = MIB.buildLShr(sXLen, VLENB, MIB.buildConstant(sXLen, 3),
1224 MIB.buildMul(Dst, VScale, MIB.buildConstant(sXLen, Val));
1225 }
1226 MI.eraseFromParent();
1227 return true;
1228}
1229
1230// Custom-lower extensions from mask vectors by using a vselect either with 1
1231// for zero/any-extension or -1 for sign-extension:
1232// (vXiN = (s|z)ext vXi1:vmask) -> (vXiN = vselect vmask, (-1 or 1), 0)
1233// Note that any-extension is lowered identically to zero-extension.
1234bool RISCVLegalizerInfo::legalizeExt(MachineInstr &MI,
1235 MachineIRBuilder &MIB) const {
1236
1237 unsigned Opc = MI.getOpcode();
1238 assert(Opc == TargetOpcode::G_ZEXT || Opc == TargetOpcode::G_SEXT ||
1239 Opc == TargetOpcode::G_ANYEXT);
1240
1241 MachineRegisterInfo &MRI = *MIB.getMRI();
1242 Register Dst = MI.getOperand(0).getReg();
1243 Register Src = MI.getOperand(1).getReg();
1244
1245 LLT DstTy = MRI.getType(Dst);
1246 int64_t ExtTrueVal = Opc == TargetOpcode::G_SEXT ? -1 : 1;
1247 LLT DstEltTy = DstTy.getElementType();
1248 auto SplatZero = MIB.buildSplatVector(DstTy, MIB.buildConstant(DstEltTy, 0));
1249 auto SplatTrue =
1250 MIB.buildSplatVector(DstTy, MIB.buildConstant(DstEltTy, ExtTrueVal));
1251 MIB.buildSelect(Dst, Src, SplatTrue, SplatZero);
1252
1253 MI.eraseFromParent();
1254 return true;
1255}
1256
1257bool RISCVLegalizerInfo::legalizeLoadStore(MachineInstr &MI,
1258 LegalizerHelper &Helper,
1259 MachineIRBuilder &MIB) const {
1261 "Machine instructions must be Load/Store.");
1262 MachineRegisterInfo &MRI = *MIB.getMRI();
1263 MachineFunction *MF = MI.getMF();
1264 const DataLayout &DL = MIB.getDataLayout();
1265 LLVMContext &Ctx = MF->getFunction().getContext();
1266
1267 Register DstReg = MI.getOperand(0).getReg();
1268 LLT DataTy = MRI.getType(DstReg);
1269 if (!DataTy.isVector())
1270 return false;
1271
1272 if (!MI.hasOneMemOperand())
1273 return false;
1274
1275 MachineMemOperand *MMO = *MI.memoperands_begin();
1276
1277 const auto *TLI = STI.getTargetLowering();
1278 EVT VT = EVT::getEVT(getTypeForLLT(DataTy, Ctx));
1279
1280 if (TLI->allowsMemoryAccessForAlignment(Ctx, DL, VT, *MMO))
1281 return true;
1282
1283 unsigned EltSizeBits = DataTy.getScalarSizeInBits();
1284 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
1285 "Unexpected unaligned RVV load type");
1286
1287 // Calculate the new vector type with i8 elements
1288 unsigned NumElements =
1289 DataTy.getElementCount().getKnownMinValue() * (EltSizeBits / 8);
1290 LLT NewDataTy = LLT::scalable_vector(NumElements, 8);
1291
1292 Helper.bitcast(MI, 0, NewDataTy);
1293
1294 return true;
1295}
1296
1297/// Return the type of the mask type suitable for masking the provided
1298/// vector type. This is simply an i1 element type vector of the same
1299/// (possibly scalable) length.
1300static LLT getMaskTypeFor(LLT VecTy) {
1301 assert(VecTy.isVector());
1302 ElementCount EC = VecTy.getElementCount();
1303 return LLT::vector(EC, LLT::scalar(1));
1304}
1305
1306/// Creates an all ones mask suitable for masking a vector of type VecTy with
1307/// vector length VL.
1309 MachineIRBuilder &MIB,
1311 LLT MaskTy = getMaskTypeFor(VecTy);
1312 return MIB.buildInstr(RISCV::G_VMSET_VL, {MaskTy}, {VL});
1313}
1314
1315/// Gets the two common "VL" operands: an all-ones mask and the vector length.
1316/// VecTy is a scalable vector type.
1317static std::pair<MachineInstrBuilder, MachineInstrBuilder>
1319 assert(VecTy.isScalableVector() && "Expecting scalable container type");
1320 const RISCVSubtarget &STI = MIB.getMF().getSubtarget<RISCVSubtarget>();
1321 LLT XLenTy(STI.getXLenVT());
1322 auto VL = MIB.buildConstant(XLenTy, -1);
1323 auto Mask = buildAllOnesMask(VecTy, VL, MIB, MRI);
1324 return {Mask, VL};
1325}
1326
1328buildSplatPartsS64WithVL(const DstOp &Dst, const SrcOp &Passthru, Register Lo,
1329 Register Hi, const SrcOp &VL, MachineIRBuilder &MIB,
1331 // TODO: If the Hi bits of the splat are undefined, then it's fine to just
1332 // splat Lo even if it might be sign extended. I don't think we have
1333 // introduced a case where we're build a s64 where the upper bits are undef
1334 // yet.
1335
1336 // Fall back to a stack store and stride x0 vector load.
1337 // TODO: need to lower G_SPLAT_VECTOR_SPLIT_I64. This is done in
1338 // preprocessDAG in SDAG.
1339 return MIB.buildInstr(RISCV::G_SPLAT_VECTOR_SPLIT_I64_VL, {Dst},
1340 {Passthru, Lo, Hi, VL});
1341}
1342
1344buildSplatSplitS64WithVL(const DstOp &Dst, const SrcOp &Passthru,
1345 const SrcOp &Scalar, const SrcOp &VL,
1347 assert(Scalar.getLLTTy(MRI) == LLT::scalar(64) && "Unexpected VecTy!");
1348 auto Unmerge = MIB.buildUnmerge(LLT::scalar(32), Scalar);
1349 return buildSplatPartsS64WithVL(Dst, Passthru, Unmerge.getReg(0),
1350 Unmerge.getReg(1), VL, MIB, MRI);
1351}
1352
1353// Lower splats of s1 types to G_ICMP. For each mask vector type, we have a
1354// legal equivalently-sized i8 type, so we can use that as a go-between.
1355// Splats of s1 types that have constant value can be legalized as VMSET_VL or
1356// VMCLR_VL.
1357bool RISCVLegalizerInfo::legalizeSplatVector(MachineInstr &MI,
1358 MachineIRBuilder &MIB) const {
1359 assert(MI.getOpcode() == TargetOpcode::G_SPLAT_VECTOR);
1360
1361 MachineRegisterInfo &MRI = *MIB.getMRI();
1362
1363 Register Dst = MI.getOperand(0).getReg();
1364 Register SplatVal = MI.getOperand(1).getReg();
1365
1366 LLT VecTy = MRI.getType(Dst);
1367 LLT XLenTy(STI.getXLenVT());
1368
1369 // Handle case of s64 element vectors on rv32
1370 if (XLenTy.getSizeInBits() == 32 &&
1371 VecTy.getElementType().getSizeInBits() == 64) {
1372 auto [_, VL] = buildDefaultVLOps(MRI.getType(Dst), MIB, MRI);
1373 buildSplatSplitS64WithVL(Dst, MIB.buildUndef(VecTy), SplatVal, VL, MIB,
1374 MRI);
1375 MI.eraseFromParent();
1376 return true;
1377 }
1378
1379 // All-zeros or all-ones splats are handled specially.
1380 MachineInstr &SplatValMI = *MRI.getVRegDef(SplatVal);
1381 if (isAllOnesOrAllOnesSplat(SplatValMI, MRI)) {
1382 auto VL = buildDefaultVLOps(VecTy, MIB, MRI).second;
1383 MIB.buildInstr(RISCV::G_VMSET_VL, {Dst}, {VL});
1384 MI.eraseFromParent();
1385 return true;
1386 }
1387 if (isNullOrNullSplat(SplatValMI, MRI)) {
1388 auto VL = buildDefaultVLOps(VecTy, MIB, MRI).second;
1389 MIB.buildInstr(RISCV::G_VMCLR_VL, {Dst}, {VL});
1390 MI.eraseFromParent();
1391 return true;
1392 }
1393
1394 // Handle non-constant mask splat (i.e. not sure if it's all zeros or all
1395 // ones) by promoting it to an s8 splat.
1396 LLT InterEltTy = LLT::scalar(8);
1397 LLT InterTy = VecTy.changeElementType(InterEltTy);
1398 auto ZExtSplatVal = MIB.buildZExt(InterEltTy, SplatVal);
1399 auto And =
1400 MIB.buildAnd(InterEltTy, ZExtSplatVal, MIB.buildConstant(InterEltTy, 1));
1401 auto LHS = MIB.buildSplatVector(InterTy, And);
1402 auto ZeroSplat =
1403 MIB.buildSplatVector(InterTy, MIB.buildConstant(InterEltTy, 0));
1404 MIB.buildICmp(CmpInst::Predicate::ICMP_NE, Dst, LHS, ZeroSplat);
1405 MI.eraseFromParent();
1406 return true;
1407}
1408
1409static LLT getLMUL1Ty(LLT VecTy) {
1410 assert(VecTy.getElementType().getSizeInBits() <= 64 &&
1411 "Unexpected vector LLT");
1413 VecTy.getElementType().getSizeInBits(),
1414 VecTy.getElementType());
1415}
1416
1417bool RISCVLegalizerInfo::legalizeExtractSubvector(MachineInstr &MI,
1418 MachineIRBuilder &MIB) const {
1419 GExtractSubvector &ES = cast<GExtractSubvector>(MI);
1420
1421 MachineRegisterInfo &MRI = *MIB.getMRI();
1422
1423 Register Dst = ES.getReg(0);
1424 Register Src = ES.getSrcVec();
1425 uint64_t Idx = ES.getIndexImm();
1426
1427 // With an index of 0 this is a cast-like subvector, which can be performed
1428 // with subregister operations.
1429 if (Idx == 0)
1430 return true;
1431
1432 LLT LitTy = MRI.getType(Dst);
1433 LLT BigTy = MRI.getType(Src);
1434
1435 if (LitTy.getElementType() == LLT::scalar(1)) {
1436 // We can't slide this mask vector up indexed by its i1 elements.
1437 // This poses a problem when we wish to insert a scalable vector which
1438 // can't be re-expressed as a larger type. Just choose the slow path and
1439 // extend to a larger type, then truncate back down.
1440 LLT ExtBigTy = BigTy.changeElementType(LLT::scalar(8));
1441 LLT ExtLitTy = LitTy.changeElementType(LLT::scalar(8));
1442 auto BigZExt = MIB.buildZExt(ExtBigTy, Src);
1443 auto ExtractZExt = MIB.buildExtractSubvector(ExtLitTy, BigZExt, Idx);
1444 auto SplatZero = MIB.buildSplatVector(
1445 ExtLitTy, MIB.buildConstant(ExtLitTy.getElementType(), 0));
1446 MIB.buildICmp(CmpInst::Predicate::ICMP_NE, Dst, ExtractZExt, SplatZero);
1447 MI.eraseFromParent();
1448 return true;
1449 }
1450
1451 // extract_subvector scales the index by vscale if the subvector is scalable,
1452 // and decomposeSubvectorInsertExtractToSubRegs takes this into account.
1453 const RISCVRegisterInfo *TRI = STI.getRegisterInfo();
1454 MVT LitTyMVT = getMVTForLLT(LitTy);
1455 auto Decompose =
1457 getMVTForLLT(BigTy), LitTyMVT, Idx, TRI);
1458 unsigned RemIdx = Decompose.second;
1459
1460 // If the Idx has been completely eliminated then this is a subvector extract
1461 // which naturally aligns to a vector register. These can easily be handled
1462 // using subregister manipulation.
1463 if (RemIdx == 0)
1464 return true;
1465
1466 // Else LitTy is M1 or smaller and may need to be slid down: if LitTy
1467 // was > M1 then the index would need to be a multiple of VLMAX, and so would
1468 // divide exactly.
1469 assert(
1472
1473 // If the vector type is an LMUL-group type, extract a subvector equal to the
1474 // nearest full vector register type.
1475 LLT InterLitTy = BigTy;
1476 Register Vec = Src;
1478 getLMUL1Ty(BigTy).getSizeInBits())) {
1479 // If BigTy has an LMUL > 1, then LitTy should have a smaller LMUL, and
1480 // we should have successfully decomposed the extract into a subregister.
1481 assert(Decompose.first != RISCV::NoSubRegister);
1482 InterLitTy = getLMUL1Ty(BigTy);
1483 // SDAG builds a TargetExtractSubreg. We cannot create a a Copy with SubReg
1484 // specified on the source Register (the equivalent) since generic virtual
1485 // register does not allow subregister index.
1486 Vec = MIB.buildExtractSubvector(InterLitTy, Src, Idx - RemIdx).getReg(0);
1487 }
1488
1489 // Slide this vector register down by the desired number of elements in order
1490 // to place the desired subvector starting at element 0.
1491 const LLT XLenTy(STI.getXLenVT());
1492 auto SlidedownAmt = MIB.buildVScale(XLenTy, RemIdx);
1493 auto [Mask, VL] = buildDefaultVLOps(InterLitTy, MIB, MRI);
1495 auto Slidedown = MIB.buildInstr(
1496 RISCV::G_VSLIDEDOWN_VL, {InterLitTy},
1497 {MIB.buildUndef(InterLitTy), Vec, SlidedownAmt, Mask, VL, Policy});
1498
1499 // Now the vector is in the right position, extract our final subvector. This
1500 // should resolve to a COPY.
1501 MIB.buildExtractSubvector(Dst, Slidedown, 0);
1502
1503 MI.eraseFromParent();
1504 return true;
1505}
1506
1507bool RISCVLegalizerInfo::legalizeInsertSubvector(MachineInstr &MI,
1508 LegalizerHelper &Helper,
1509 MachineIRBuilder &MIB) const {
1510 GInsertSubvector &IS = cast<GInsertSubvector>(MI);
1511
1512 MachineRegisterInfo &MRI = *MIB.getMRI();
1513
1514 Register Dst = IS.getReg(0);
1515 Register BigVec = IS.getBigVec();
1516 Register LitVec = IS.getSubVec();
1517 uint64_t Idx = IS.getIndexImm();
1518
1519 LLT BigTy = MRI.getType(BigVec);
1520 LLT LitTy = MRI.getType(LitVec);
1521
1522 if (Idx == 0 && mi_match(BigVec, MRI, m_GImplicitDef()))
1523 return true;
1524
1525 // We don't have the ability to slide mask vectors up indexed by their i1
1526 // elements; the smallest we can do is i8. Often we are able to bitcast to
1527 // equivalent i8 vectors. Otherwise, we can must zeroextend to equivalent i8
1528 // vectors and truncate down after the insert.
1529 if (LitTy.getElementType() == LLT::scalar(1)) {
1530 auto BigTyMinElts = BigTy.getElementCount().getKnownMinValue();
1531 auto LitTyMinElts = LitTy.getElementCount().getKnownMinValue();
1532 if (BigTyMinElts >= 8 && LitTyMinElts >= 8)
1533 return Helper.bitcast(
1534 IS, 0,
1536
1537 // We can't slide this mask vector up indexed by its i1 elements.
1538 // This poses a problem when we wish to insert a scalable vector which
1539 // can't be re-expressed as a larger type. Just choose the slow path and
1540 // extend to a larger type, then truncate back down.
1541 LLT ExtBigTy = BigTy.changeElementType(LLT::scalar(8));
1542 return Helper.widenScalar(IS, 0, ExtBigTy);
1543 }
1544
1545 const RISCVRegisterInfo *TRI = STI.getRegisterInfo();
1546 unsigned SubRegIdx, RemIdx;
1547 std::tie(SubRegIdx, RemIdx) =
1549 getMVTForLLT(BigTy), getMVTForLLT(LitTy), Idx, TRI);
1550
1551 TypeSize VecRegSize = TypeSize::getScalable(RISCV::RVVBitsPerBlock);
1553 STI.expandVScale(LitTy.getSizeInBits()).getKnownMinValue()));
1554 bool ExactlyVecRegSized =
1555 STI.expandVScale(LitTy.getSizeInBits())
1556 .isKnownMultipleOf(STI.expandVScale(VecRegSize));
1557
1558 // If the Idx has been completely eliminated and this subvector's size is a
1559 // vector register or a multiple thereof, or the surrounding elements are
1560 // undef, then this is a subvector insert which naturally aligns to a vector
1561 // register. These can easily be handled using subregister manipulation.
1562 if (RemIdx == 0 && ExactlyVecRegSized)
1563 return true;
1564
1565 // If the subvector is smaller than a vector register, then the insertion
1566 // must preserve the undisturbed elements of the register. We do this by
1567 // lowering to an EXTRACT_SUBVECTOR grabbing the nearest LMUL=1 vector type
1568 // (which resolves to a subregister copy), performing a VSLIDEUP to place the
1569 // subvector within the vector register, and an INSERT_SUBVECTOR of that
1570 // LMUL=1 type back into the larger vector (resolving to another subregister
1571 // operation). See below for how our VSLIDEUP works. We go via a LMUL=1 type
1572 // to avoid allocating a large register group to hold our subvector.
1573
1574 // VSLIDEUP works by leaving elements 0<i<OFFSET undisturbed, elements
1575 // OFFSET<=i<VL set to the "subvector" and vl<=i<VLMAX set to the tail policy
1576 // (in our case undisturbed). This means we can set up a subvector insertion
1577 // where OFFSET is the insertion offset, and the VL is the OFFSET plus the
1578 // size of the subvector.
1579 const LLT XLenTy(STI.getXLenVT());
1580 LLT InterLitTy = BigTy;
1581 Register AlignedExtract = BigVec;
1582 unsigned AlignedIdx = Idx - RemIdx;
1584 getLMUL1Ty(BigTy).getSizeInBits())) {
1585 InterLitTy = getLMUL1Ty(BigTy);
1586 // Extract a subvector equal to the nearest full vector register type. This
1587 // should resolve to a G_EXTRACT on a subreg.
1588 AlignedExtract =
1589 MIB.buildExtractSubvector(InterLitTy, BigVec, AlignedIdx).getReg(0);
1590 }
1591
1592 auto Insert = MIB.buildInsertSubvector(InterLitTy, MIB.buildUndef(InterLitTy),
1593 LitVec, 0);
1594
1595 auto [Mask, _] = buildDefaultVLOps(InterLitTy, MIB, MRI);
1596 auto VL = MIB.buildVScale(XLenTy, LitTy.getElementCount().getKnownMinValue());
1597
1598 // If we're inserting into the lowest elements, use a tail undisturbed
1599 // vmv.v.v.
1600 MachineInstrBuilder Inserted;
1601 bool NeedInsertSubvec =
1602 TypeSize::isKnownGT(BigTy.getSizeInBits(), InterLitTy.getSizeInBits());
1603 Register InsertedDst =
1604 NeedInsertSubvec ? MRI.createGenericVirtualRegister(InterLitTy) : Dst;
1605 if (RemIdx == 0) {
1606 Inserted = MIB.buildInstr(RISCV::G_VMV_V_V_VL, {InsertedDst},
1607 {AlignedExtract, Insert, VL});
1608 } else {
1609 auto SlideupAmt = MIB.buildVScale(XLenTy, RemIdx);
1610 // Construct the vector length corresponding to RemIdx + length(LitTy).
1611 VL = MIB.buildAdd(XLenTy, SlideupAmt, VL);
1612 // Use tail agnostic policy if we're inserting over InterLitTy's tail.
1613 ElementCount EndIndex =
1616 if (STI.expandVScale(EndIndex) ==
1617 STI.expandVScale(InterLitTy.getElementCount()))
1619
1620 Inserted =
1621 MIB.buildInstr(RISCV::G_VSLIDEUP_VL, {InsertedDst},
1622 {AlignedExtract, Insert, SlideupAmt, Mask, VL, Policy});
1623 }
1624
1625 // If required, insert this subvector back into the correct vector register.
1626 // This should resolve to an INSERT_SUBREG instruction.
1627 if (NeedInsertSubvec)
1628 MIB.buildInsertSubvector(Dst, BigVec, Inserted, AlignedIdx);
1629
1630 MI.eraseFromParent();
1631 return true;
1632}
1633
1634bool RISCVLegalizerInfo::legalizeBitreverse(MachineInstr &MI,
1635 MachineIRBuilder &MIB) const {
1636 assert(MI.getOpcode() == TargetOpcode::G_BITREVERSE && "Unexpected opcode");
1637
1638 if (!STI.hasStdExtZbkb())
1639 return false;
1640
1641 MachineRegisterInfo &MRI = *MIB.getMRI();
1642
1643 Register Dst = MI.getOperand(0).getReg();
1644 Register Src = MI.getOperand(1).getReg();
1645
1646 if (!MRI.getType(Dst).isScalar(8))
1647 return false;
1648
1649 auto WideSrc = MIB.buildAnyExt(sXLen, Src);
1650 auto Brev = MIB.buildInstr(RISCV::G_BREV8, {sXLen}, {WideSrc.getReg(0)});
1651 MIB.buildTrunc(Dst, Brev.getReg(0));
1652
1653 MI.eraseFromParent();
1654 return true;
1655}
1656
1657static unsigned getRISCVWOpcode(unsigned Opcode) {
1658 switch (Opcode) {
1659 default:
1660 llvm_unreachable("Unexpected opcode");
1661 case TargetOpcode::G_ASHR:
1662 return RISCV::G_SRAW;
1663 case TargetOpcode::G_LSHR:
1664 return RISCV::G_SRLW;
1665 case TargetOpcode::G_SHL:
1666 return RISCV::G_SLLW;
1667 case TargetOpcode::G_SDIV:
1668 return RISCV::G_DIVW;
1669 case TargetOpcode::G_UDIV:
1670 return RISCV::G_DIVUW;
1671 case TargetOpcode::G_UREM:
1672 return RISCV::G_REMUW;
1673 case TargetOpcode::G_ROTL:
1674 return RISCV::G_ROLW;
1675 case TargetOpcode::G_ROTR:
1676 return RISCV::G_RORW;
1677 case TargetOpcode::G_CTLZ:
1678 return RISCV::G_CLZW;
1679 case TargetOpcode::G_CTTZ:
1680 return RISCV::G_CTZW;
1681 case TargetOpcode::G_CTLS:
1682 return RISCV::G_CLSW;
1683 case TargetOpcode::G_FPTOSI:
1684 return RISCV::G_FCVT_W_RV64;
1685 case TargetOpcode::G_FPTOUI:
1686 return RISCV::G_FCVT_WU_RV64;
1687 }
1688}
1689
1692 LostDebugLocObserver &LocObserver) const {
1693 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
1694 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
1695 MachineFunction &MF = *MI.getParent()->getParent();
1696 switch (MI.getOpcode()) {
1697 default:
1698 // No idea what to do.
1699 return false;
1700 case TargetOpcode::G_ABS:
1701 return Helper.lowerAbsToMaxNeg(MI);
1702 case TargetOpcode::G_CLMULH:
1703 case TargetOpcode::G_CLMULR: {
1704 assert(STI.is64Bit() &&
1705 MRI.getType(MI.getOperand(0).getReg()) == LLT::scalar(32) &&
1706 "Unexpected custom legalization");
1707 // Shift both inputs by 32 so the full product has 64 trailing zeros.
1708 // Perform CLMULH or CLMULR on the shifted inputs, then extract the upper
1709 // 32 bits of the result.
1710 auto Shift = MIRBuilder.buildConstant(sXLen, 32);
1711 auto LHS = MIRBuilder.buildAnyExt(sXLen, MI.getOperand(1));
1712 auto RHS = MIRBuilder.buildAnyExt(sXLen, MI.getOperand(2));
1713 auto ShiftedLHS = MIRBuilder.buildShl(sXLen, LHS, Shift);
1714 auto ShiftedRHS = MIRBuilder.buildShl(sXLen, RHS, Shift);
1715 auto Product = MIRBuilder.buildInstr(MI.getOpcode(), {sXLen},
1716 {ShiftedLHS, ShiftedRHS});
1717 auto High = MIRBuilder.buildLShr(sXLen, Product, Shift);
1718 MIRBuilder.buildTrunc(MI.getOperand(0), High);
1719 MI.eraseFromParent();
1720 return true;
1721 }
1722 case TargetOpcode::G_CONSTANT: {
1723 const Function &F = MF.getFunction();
1724 // TODO: if PSI and BFI are present, add " ||
1725 // llvm::shouldOptForSize(*CurMBB, PSI, BFI)".
1726 bool ShouldOptForSize = F.hasOptSize();
1727 const ConstantInt *ConstVal = MI.getOperand(1).getCImm();
1728 if (!shouldBeInConstantPool(ConstVal->getValue(), ShouldOptForSize))
1729 return true;
1730 return Helper.lowerConstant(MI);
1731 }
1732 case TargetOpcode::G_SUB:
1733 case TargetOpcode::G_ADD: {
1734 Helper.Observer.changingInstr(MI);
1735 Helper.widenScalarSrc(MI, sXLen, 1, TargetOpcode::G_ANYEXT);
1736 Helper.widenScalarSrc(MI, sXLen, 2, TargetOpcode::G_ANYEXT);
1737
1738 Register DstALU = MRI.createGenericVirtualRegister(sXLen);
1739
1740 MachineOperand &MO = MI.getOperand(0);
1741 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
1742 auto DstSext = MIRBuilder.buildSExtInReg(sXLen, DstALU, 32);
1743
1744 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {MO}, {DstSext});
1745 MO.setReg(DstALU);
1746
1747 Helper.Observer.changedInstr(MI);
1748 return true;
1749 }
1750 case TargetOpcode::G_ASHR:
1751 case TargetOpcode::G_LSHR:
1752 case TargetOpcode::G_SHL: {
1753 if (getIConstantVRegValWithLookThrough(MI.getOperand(2).getReg(), MRI)) {
1754 // We don't need a custom node for shift by constant. Just widen the
1755 // source and the shift amount.
1756 unsigned ExtOpc = TargetOpcode::G_ANYEXT;
1757 if (MI.getOpcode() == TargetOpcode::G_ASHR)
1758 ExtOpc = TargetOpcode::G_SEXT;
1759 else if (MI.getOpcode() == TargetOpcode::G_LSHR)
1760 ExtOpc = TargetOpcode::G_ZEXT;
1761
1762 Helper.Observer.changingInstr(MI);
1763 Helper.widenScalarSrc(MI, sXLen, 1, ExtOpc);
1764 Helper.widenScalarSrc(MI, sXLen, 2, TargetOpcode::G_ZEXT);
1765 Helper.widenScalarDst(MI, sXLen);
1766 Helper.Observer.changedInstr(MI);
1767 return true;
1768 }
1769
1770 Helper.Observer.changingInstr(MI);
1771 Helper.widenScalarSrc(MI, sXLen, 1, TargetOpcode::G_ANYEXT);
1772 Helper.widenScalarSrc(MI, sXLen, 2, TargetOpcode::G_ANYEXT);
1773 Helper.widenScalarDst(MI, sXLen);
1774 MI.setDesc(MIRBuilder.getTII().get(getRISCVWOpcode(MI.getOpcode())));
1775 Helper.Observer.changedInstr(MI);
1776 return true;
1777 }
1778 case TargetOpcode::G_SDIV:
1779 case TargetOpcode::G_UDIV:
1780 case TargetOpcode::G_UREM:
1781 case TargetOpcode::G_ROTL:
1782 case TargetOpcode::G_ROTR: {
1783 Helper.Observer.changingInstr(MI);
1784 Helper.widenScalarSrc(MI, sXLen, 1, TargetOpcode::G_ANYEXT);
1785 Helper.widenScalarSrc(MI, sXLen, 2, TargetOpcode::G_ANYEXT);
1786 Helper.widenScalarDst(MI, sXLen);
1787 MI.setDesc(MIRBuilder.getTII().get(getRISCVWOpcode(MI.getOpcode())));
1788 Helper.Observer.changedInstr(MI);
1789 return true;
1790 }
1791 case TargetOpcode::G_CTLZ:
1792 case TargetOpcode::G_CTTZ:
1793 case TargetOpcode::G_CTLS: {
1794 Helper.Observer.changingInstr(MI);
1795 Helper.widenScalarSrc(MI, sXLen, 1, TargetOpcode::G_ANYEXT);
1796 Helper.widenScalarDst(MI, sXLen);
1797 MI.setDesc(MIRBuilder.getTII().get(getRISCVWOpcode(MI.getOpcode())));
1798 Helper.Observer.changedInstr(MI);
1799 return true;
1800 }
1801 case TargetOpcode::G_FPTOSI:
1802 case TargetOpcode::G_FPTOUI: {
1803 Helper.Observer.changingInstr(MI);
1804 Helper.widenScalarDst(MI, sXLen);
1805 MI.setDesc(MIRBuilder.getTII().get(getRISCVWOpcode(MI.getOpcode())));
1807 Helper.Observer.changedInstr(MI);
1808 return true;
1809 }
1810 case TargetOpcode::G_FPTOSI_SAT:
1811 case TargetOpcode::G_FPTOUI_SAT: {
1812 // Mirror lowerFP_TO_INT_SAT (RISCVISelLowering.cpp): the conversion
1813 // saturates out-of-range values, but we need to select 0 for NaN as
1814 // required by the intrinsics.
1815 Register Dst = MI.getOperand(0).getReg();
1816 Register Src = MI.getOperand(1).getReg();
1817 LLT DstTy = MRI.getType(Dst);
1818 unsigned DstBits = DstTy.getScalarSizeInBits();
1819 bool IsSigned = MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
1820
1821 unsigned FCvtOp;
1822 if (DstBits == XLen) {
1823 FCvtOp = IsSigned ? RISCV::G_FCVT_X : RISCV::G_FCVT_XU;
1824 } else {
1825 assert(STI.is64Bit() && "Non-XLen results are only custom on RV64");
1826 FCvtOp = IsSigned ? RISCV::G_FCVT_W_RV64 : RISCV::G_FCVT_WU_RV64;
1827 }
1828
1829 auto FCvt = MIRBuilder.buildInstr(FCvtOp, {sXLen}, {Src})
1830 .addImm(RISCVFPRndMode::RTZ);
1831
1832 // RISC-V G_FCMP results are XLen wide, and so are G_SELECT conditions.
1833 auto IsNaN = MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, sXLen, Src, Src);
1834
1835 Register FCvtReg = FCvt.getReg(0);
1836 if (DstBits != XLen)
1837 FCvtReg = MIRBuilder.buildTrunc(DstTy, FCvtReg).getReg(0);
1838
1839 MIRBuilder.buildSelect(Dst, IsNaN, MIRBuilder.buildConstant(DstTy, 0),
1840 FCvtReg);
1841
1842 MI.eraseFromParent();
1843 return true;
1844 }
1845 case TargetOpcode::G_LROUND: {
1846 // The (i32 any_lround) Pat is IsRV32-only; on RV64 lower to
1847 // riscv_fcvt_w_rv64 with FRM_RMM.
1848 Helper.Observer.changingInstr(MI);
1849 Helper.widenScalarDst(MI, sXLen);
1850 MI.setDesc(MIRBuilder.getTII().get(RISCV::G_FCVT_W_RV64));
1852 Helper.Observer.changedInstr(MI);
1853 return true;
1854 }
1855 case TargetOpcode::G_READCYCLECOUNTER:
1856 case TargetOpcode::G_READSTEADYCOUNTER:
1857 return legalizeReadCounter(MI, MIRBuilder, Helper.Observer);
1858 case TargetOpcode::G_IS_FPCLASS: {
1859 Register GISFPCLASS = MI.getOperand(0).getReg();
1860 Register Src = MI.getOperand(1).getReg();
1861 const MachineOperand &ImmOp = MI.getOperand(2);
1862 MachineIRBuilder MIB(MI);
1863
1864 // Turn LLVM IR's floating point classes to that in RISC-V,
1865 // by simply rotating the 10-bit immediate right by two bits.
1866 APInt GFpClassImm(10, static_cast<uint64_t>(ImmOp.getImm()));
1867 auto FClassMask = MIB.buildConstant(sXLen, GFpClassImm.rotr(2).zext(XLen));
1868 auto ConstZero = MIB.buildConstant(sXLen, 0);
1869
1870 auto GFClass = MIB.buildInstr(RISCV::G_FCLASS, {sXLen}, {Src});
1871 auto And = MIB.buildAnd(sXLen, GFClass, FClassMask);
1872 MIB.buildICmp(CmpInst::ICMP_NE, GISFPCLASS, And, ConstZero);
1873
1874 MI.eraseFromParent();
1875 return true;
1876 }
1877 case TargetOpcode::G_BRJT:
1878 return legalizeBRJT(MI, MIRBuilder);
1879 case TargetOpcode::G_VASTART:
1880 return legalizeVAStart(MI, MIRBuilder);
1881 case TargetOpcode::G_VSCALE:
1882 return legalizeVScale(MI, MIRBuilder);
1883 case TargetOpcode::G_ZEXT:
1884 case TargetOpcode::G_SEXT:
1885 case TargetOpcode::G_ANYEXT:
1886 return legalizeExt(MI, MIRBuilder);
1887 case TargetOpcode::G_SPLAT_VECTOR:
1888 return legalizeSplatVector(MI, MIRBuilder);
1889 case TargetOpcode::G_EXTRACT_SUBVECTOR:
1890 return legalizeExtractSubvector(MI, MIRBuilder);
1891 case TargetOpcode::G_INSERT_SUBVECTOR:
1892 return legalizeInsertSubvector(MI, Helper, MIRBuilder);
1893 case TargetOpcode::G_BITREVERSE:
1894 return legalizeBitreverse(MI, MIRBuilder);
1895 case TargetOpcode::G_LOAD:
1896 case TargetOpcode::G_STORE:
1897 return legalizeLoadStore(MI, Helper, MIRBuilder);
1898 }
1899
1900 llvm_unreachable("expected switch to return");
1901}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
uint64_t Imm
constexpr LLT S32
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
#define _
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
uint64_t High
uint64_t IntrinsicInst * II
#define P(N)
ppc ctr loops verify
MachineRegisterInfo & MRI
static LLT getLMUL1Ty(LLT VecTy)
static MachineInstrBuilder buildAllOnesMask(LLT VecTy, const SrcOp &VL, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Creates an all ones mask suitable for masking a vector of type VecTy with vector length VL.
static std::pair< MachineInstrBuilder, MachineInstrBuilder > buildDefaultVLOps(LLT VecTy, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Gets the two common "VL" operands: an all-ones mask and the vector length.
static LegalityPredicate typeIsLegalBoolVec(unsigned TypeIdx, std::initializer_list< LLT > BoolVecTys, const RISCVSubtarget &ST)
static MachineInstrBuilder buildSplatSplitS64WithVL(const DstOp &Dst, const SrcOp &Passthru, const SrcOp &Scalar, const SrcOp &VL, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
static LegalityPredicate typeIsLegalIntOrFPVec(unsigned TypeIdx, std::initializer_list< LLT > IntOrFPVecTys, const RISCVSubtarget &ST)
static MachineInstrBuilder buildSplatPartsS64WithVL(const DstOp &Dst, const SrcOp &Passthru, Register Lo, Register Hi, const SrcOp &VL, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
static LLT getMaskTypeFor(LLT VecTy)
Return the type of the mask type suitable for masking the provided vector type.
static LegalityPredicate typeIsLegalPtrVec(unsigned TypeIdx, std::initializer_list< LLT > PtrVecTys, const RISCVSubtarget &ST)
static unsigned getRISCVWOpcode(unsigned Opcode)
This file declares the targeting of the Machinelegalizer class for RISC-V.
MachineInstr *& Lo
Value * LHS
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1057
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1508
LLVM_ABI APInt rotr(unsigned rotateAmt) const
Rotate right by rotateAmt.
Definition APInt.cpp:1199
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1582
@ ICMP_NE
not equal
Definition InstrTypes.h:762
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:750
This is the shared class of boolean and integer constants.
Definition Constants.h:87
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:309
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:352
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
virtual void erasingInstr(MachineInstr &MI)=0
An instruction is about to be erased.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
constexpr bool isScalableVector() const
Returns true if the LLT is a scalable vector.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
static constexpr LLT scalable_vector(unsigned MinNumElements, unsigned ScalarSizeInBits)
Get a low-level scalable vector of some number of elements and element width.
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr ElementCount getElementCount() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
LegalizeRuleSet & maxScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at most as wide as Ty.
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & alwaysLegal()
LegalizeRuleSet & customIf(LegalityPredicate Predicate)
LegalizeRuleSet & widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize=0)
Widen the scalar to the next power of two that is at least MinSize.
LegalizeRuleSet & customFor(std::initializer_list< LLT > Types)
LLVM_ABI void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx, unsigned ExtOpcode)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
LLVM_ABI LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcast(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by replacing the value type.
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy)
Legalize an instruction by performing the operation on a wider scalar type (for example a 16-bit addi...
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI LegalizeResult lowerConstant(MachineInstr &MI)
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:89
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
Helper class to build MachineInstr.
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)
Set the insertion point before the specified position.
MachineInstrBuilder buildAdd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ADD Op0, Op1.
MachineInstrBuilder buildUndef(const DstOp &Res)
Build and insert Res = IMPLICIT_DEF.
MachineInstrBuilder buildUnmerge(ArrayRef< LLT > Res, const SrcOp &Op)
Build and insert Res0, ... = G_UNMERGE_VALUES Op.
MachineInstrBuilder buildSelect(const DstOp &Res, const SrcOp &Tst, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_SELECT Tst, Op0, Op1.
MachineInstrBuilder buildMul(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_MUL Op0, Op1.
MachineInstrBuilder buildInsertSubvector(const DstOp &Res, const SrcOp &Src0, const SrcOp &Src1, unsigned Index)
Build and insert Res = G_INSERT_SUBVECTOR Src0, Src1, Idx.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_ICMP Pred, Op0, Op1.
MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ZEXT Op.
MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, ArrayRef< Register > Res, bool HasSideEffects, bool isConvergent)
Build and insert a G_INTRINSIC instruction.
MachineInstrBuilder buildVScale(const DstOp &Res, unsigned MinElts)
Build and insert Res = G_VSCALE MinElts.
MachineInstrBuilder buildIntToPtr(const DstOp &Dst, const SrcOp &Src)
Build and insert a G_INTTOPTR instruction.
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildPtrAdd(const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_PTR_ADD Op0, Op1.
MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert G_STORE Val, Addr, MMO.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildFrameIndex(const DstOp &Res, int Idx)
Build and insert Res = G_FRAME_INDEX Idx.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildMergeValues(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ...
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
void setDebugLoc(const DebugLoc &DL)
Set the debug location to DL for all the next build instructions.
const MachineBasicBlock & getMBB() const
Getter for the basic block we currently build.
MachineInstrBuilder buildAnyExt(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ANYEXT Op0.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildExtractSubvector(const DstOp &Res, const SrcOp &Src, unsigned Index)
Build and insert Res = G_EXTRACT_SUBVECTOR Src, Idx0.
const DataLayout & getDataLayout() const
MachineInstrBuilder buildBrIndirect(Register Tgt)
Build and insert G_BRINDIRECT Tgt.
MachineInstrBuilder buildSplatVector(const DstOp &Res, const SrcOp &Val)
Build and insert Res = G_SPLAT_VECTOR Val.
MachineInstrBuilder buildLoadInstr(unsigned Opcode, const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = <opcode> Addr, MMO.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
MachineInstrBuilder buildFCmp(CmpInst::Predicate Pred, const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_FCMP PredOp0, Op1.
MachineInstrBuilder buildSExtInReg(const DstOp &Res, const SrcOp &Op, int64_t ImmOp)
Build and insert Res = G_SEXT_INREG Op, ImmOp.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
LLVM_ABI unsigned getEntrySize(const DataLayout &TD) const
getEntrySize - Return the size of each entry in the jump table.
@ EK_LabelDifference32
EK_LabelDifference32 - Each entry is the address of the block minus the address of the jump table.
@ EK_Custom32
EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the TargetLowering::LowerCustomJ...
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
LLVM_ABI unsigned getEntryAlignment(const DataLayout &TD) const
getEntryAlignment - Return the alignment of each entry in the jump table.
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
static MachineOperand CreateImm(int64_t Val)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override
RISCVLegalizerInfo(const RISCVSubtarget &ST)
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
static std::pair< unsigned, unsigned > decomposeSubvectorInsertExtractToSubRegs(MVT VecVT, MVT SubVecVT, unsigned InsertExtractIdx, const RISCVRegisterInfo *TRI)
static RISCVVType::VLMUL getLMUL(MVT VT)
Wrapper class representing virtual and physical registers.
Definition Register.h:20
Register getReg() const
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:355
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:224
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
Definition TypeSize.h:253
self_iterator getIterator()
Definition ilist_node.h:123
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
LLVM_ABI LegalityPredicate isScalar(unsigned TypeIdx)
True iff the specified type index is a scalar.
LLVM_ABI LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
LLVM_ABI LegalityPredicate immIs(unsigned ImmIdx, int64_t Imm)
True iff the immediate at the given index has the specified value.
Predicate any(Predicate P0, Predicate P1)
True iff P0 or P1 are true.
LLVM_ABI LegalityPredicate sizeIs(unsigned TypeIdx, unsigned Size)
True if the total bitwidth of the specified type index is Size bits.
Predicate all(Predicate P0, Predicate P1)
True iff P0 and P1 are true.
LLVM_ABI LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit)
True iff the given type index is the specified type.
LLVM_ABI LegalityPredicate immInSet(unsigned ImmIdx, std::initializer_list< int64_t > ImmsInit)
True iff the immediate at the given index has one of the specified values.
LLVM_ABI LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty)
Select this specific type for the given type index.
ImplicitDefMatch m_GImplicitDef()
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
InstSeq generateTwoRegInstSeq(int64_t Val, const MCSubtargetInfo &STI, unsigned &ShiftAmt, unsigned &AddOpc)
SmallVector< Inst, 8 > InstSeq
Definition RISCVMatInt.h:43
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
static constexpr unsigned RVVBitsPerBlock
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
Definition Utils.cpp:1979
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
LLVM_ABI bool isAllOnesOrAllOnesSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant -1 integer or a splatted vector of a constant -1 integer (with...
Definition Utils.cpp:1558
@ Load
The value being inserted comes from a load (InsertElement only).
LLVM_ABI MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
LLVM_ABI bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
Definition Utils.cpp:1540
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
std::function< bool(const LegalityQuery &)> LegalityPredicate
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Definition Utils.cpp:436
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition Alignment.h:202
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
ArrayRef< LLT > Types
Matching combinators.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getJumpTable(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a jump table entry.