LLVM 22.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"
29#include "llvm/IR/Intrinsics.h"
30#include "llvm/IR/IntrinsicsRISCV.h"
31#include "llvm/IR/Type.h"
32
33using namespace llvm;
34using namespace LegalityPredicates;
35using namespace LegalizeMutations;
36
38typeIsLegalIntOrFPVec(unsigned TypeIdx,
39 std::initializer_list<LLT> IntOrFPVecTys,
40 const RISCVSubtarget &ST) {
41 LegalityPredicate P = [=, &ST](const LegalityQuery &Query) {
42 return ST.hasVInstructions() &&
43 (Query.Types[TypeIdx].getScalarSizeInBits() != 64 ||
44 ST.hasVInstructionsI64()) &&
45 (Query.Types[TypeIdx].getElementCount().getKnownMinValue() != 1 ||
46 ST.getELen() == 64);
47 };
48
49 return all(typeInSet(TypeIdx, IntOrFPVecTys), P);
50}
51
53typeIsLegalBoolVec(unsigned TypeIdx, std::initializer_list<LLT> BoolVecTys,
54 const RISCVSubtarget &ST) {
55 LegalityPredicate P = [=, &ST](const LegalityQuery &Query) {
56 return ST.hasVInstructions() &&
57 (Query.Types[TypeIdx].getElementCount().getKnownMinValue() != 1 ||
58 ST.getELen() == 64);
59 };
60 return all(typeInSet(TypeIdx, BoolVecTys), P);
61}
62
63static LegalityPredicate typeIsLegalPtrVec(unsigned TypeIdx,
64 std::initializer_list<LLT> PtrVecTys,
65 const RISCVSubtarget &ST) {
66 LegalityPredicate P = [=, &ST](const LegalityQuery &Query) {
67 return ST.hasVInstructions() &&
68 (Query.Types[TypeIdx].getElementCount().getKnownMinValue() != 1 ||
69 ST.getELen() == 64) &&
70 (Query.Types[TypeIdx].getElementCount().getKnownMinValue() != 16 ||
71 Query.Types[TypeIdx].getScalarSizeInBits() == 32);
72 };
73 return all(typeInSet(TypeIdx, PtrVecTys), P);
74}
75
77 : STI(ST), XLen(STI.getXLen()), sXLen(LLT::scalar(XLen)) {
78 const LLT sDoubleXLen = LLT::scalar(2 * XLen);
79 const LLT p0 = LLT::pointer(0, XLen);
80 const LLT s1 = LLT::scalar(1);
81 const LLT s8 = LLT::scalar(8);
82 const LLT s16 = LLT::scalar(16);
83 const LLT s32 = LLT::scalar(32);
84 const LLT s64 = LLT::scalar(64);
85 const LLT s128 = LLT::scalar(128);
86
87 const LLT nxv1s1 = LLT::scalable_vector(1, s1);
88 const LLT nxv2s1 = LLT::scalable_vector(2, s1);
89 const LLT nxv4s1 = LLT::scalable_vector(4, s1);
90 const LLT nxv8s1 = LLT::scalable_vector(8, s1);
91 const LLT nxv16s1 = LLT::scalable_vector(16, s1);
92 const LLT nxv32s1 = LLT::scalable_vector(32, s1);
93 const LLT nxv64s1 = LLT::scalable_vector(64, s1);
94
95 const LLT nxv1s8 = LLT::scalable_vector(1, s8);
96 const LLT nxv2s8 = LLT::scalable_vector(2, s8);
97 const LLT nxv4s8 = LLT::scalable_vector(4, s8);
98 const LLT nxv8s8 = LLT::scalable_vector(8, s8);
99 const LLT nxv16s8 = LLT::scalable_vector(16, s8);
100 const LLT nxv32s8 = LLT::scalable_vector(32, s8);
101 const LLT nxv64s8 = LLT::scalable_vector(64, s8);
102
103 const LLT nxv1s16 = LLT::scalable_vector(1, s16);
104 const LLT nxv2s16 = LLT::scalable_vector(2, s16);
105 const LLT nxv4s16 = LLT::scalable_vector(4, s16);
106 const LLT nxv8s16 = LLT::scalable_vector(8, s16);
107 const LLT nxv16s16 = LLT::scalable_vector(16, s16);
108 const LLT nxv32s16 = LLT::scalable_vector(32, s16);
109
110 const LLT nxv1s32 = LLT::scalable_vector(1, s32);
111 const LLT nxv2s32 = LLT::scalable_vector(2, s32);
112 const LLT nxv4s32 = LLT::scalable_vector(4, s32);
113 const LLT nxv8s32 = LLT::scalable_vector(8, s32);
114 const LLT nxv16s32 = LLT::scalable_vector(16, s32);
115
116 const LLT nxv1s64 = LLT::scalable_vector(1, s64);
117 const LLT nxv2s64 = LLT::scalable_vector(2, s64);
118 const LLT nxv4s64 = LLT::scalable_vector(4, s64);
119 const LLT nxv8s64 = LLT::scalable_vector(8, s64);
120
121 const LLT nxv1p0 = LLT::scalable_vector(1, p0);
122 const LLT nxv2p0 = LLT::scalable_vector(2, p0);
123 const LLT nxv4p0 = LLT::scalable_vector(4, p0);
124 const LLT nxv8p0 = LLT::scalable_vector(8, p0);
125 const LLT nxv16p0 = LLT::scalable_vector(16, p0);
126
127 using namespace TargetOpcode;
128
129 auto BoolVecTys = {nxv1s1, nxv2s1, nxv4s1, nxv8s1, nxv16s1, nxv32s1, nxv64s1};
130
131 auto IntOrFPVecTys = {nxv1s8, nxv2s8, nxv4s8, nxv8s8, nxv16s8, nxv32s8,
132 nxv64s8, nxv1s16, nxv2s16, nxv4s16, nxv8s16, nxv16s16,
133 nxv32s16, nxv1s32, nxv2s32, nxv4s32, nxv8s32, nxv16s32,
134 nxv1s64, nxv2s64, nxv4s64, nxv8s64};
135
136 auto PtrVecTys = {nxv1p0, nxv2p0, nxv4p0, nxv8p0, nxv16p0};
137
138 getActionDefinitionsBuilder({G_ADD, G_SUB})
139 .legalFor({sXLen})
140 .legalIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST))
141 .customFor(ST.is64Bit(), {s32})
143 .clampScalar(0, sXLen, sXLen);
144
145 getActionDefinitionsBuilder({G_AND, G_OR, G_XOR})
146 .legalFor({sXLen})
147 .legalIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST))
149 .clampScalar(0, sXLen, sXLen);
150
152 {G_UADDE, G_UADDO, G_USUBE, G_USUBO, G_READ_REGISTER, G_WRITE_REGISTER})
153 .lower();
154
155 getActionDefinitionsBuilder({G_SADDE, G_SADDO, G_SSUBE, G_SSUBO})
156 .minScalar(0, sXLen)
157 .lower();
158
159 // TODO: Use Vector Single-Width Saturating Instructions for vector types.
161 {G_UADDSAT, G_SADDSAT, G_USUBSAT, G_SSUBSAT, G_SSHLSAT, G_USHLSAT})
162 .lower();
163
164 getActionDefinitionsBuilder({G_SHL, G_ASHR, G_LSHR})
165 .legalFor({{sXLen, sXLen}})
166 .customFor(ST.is64Bit(), {{s32, s32}})
167 .widenScalarToNextPow2(0)
168 .clampScalar(1, sXLen, sXLen)
169 .clampScalar(0, sXLen, sXLen);
170
171 getActionDefinitionsBuilder({G_ZEXT, G_SEXT, G_ANYEXT})
172 .legalFor({{s32, s16}})
173 .legalFor(ST.is64Bit(), {{s64, s16}, {s64, s32}})
174 .legalIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
175 typeIsLegalIntOrFPVec(1, IntOrFPVecTys, ST)))
176 .customIf(typeIsLegalBoolVec(1, BoolVecTys, ST))
177 .maxScalar(0, sXLen);
178
179 getActionDefinitionsBuilder(G_SEXT_INREG)
180 .customFor({sXLen})
181 .clampScalar(0, sXLen, sXLen)
182 .lower();
183
184 // Merge/Unmerge
185 for (unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
186 auto &MergeUnmergeActions = getActionDefinitionsBuilder(Op);
187 unsigned BigTyIdx = Op == G_MERGE_VALUES ? 0 : 1;
188 unsigned LitTyIdx = Op == G_MERGE_VALUES ? 1 : 0;
189 if (XLen == 32 && ST.hasStdExtD()) {
190 MergeUnmergeActions.legalIf(
191 all(typeIs(BigTyIdx, s64), typeIs(LitTyIdx, s32)));
192 }
193 MergeUnmergeActions.widenScalarToNextPow2(LitTyIdx, XLen)
194 .widenScalarToNextPow2(BigTyIdx, XLen)
195 .clampScalar(LitTyIdx, sXLen, sXLen)
196 .clampScalar(BigTyIdx, sXLen, sXLen);
197 }
198
199 getActionDefinitionsBuilder({G_FSHL, G_FSHR}).lower();
200
201 getActionDefinitionsBuilder({G_ROTR, G_ROTL})
202 .legalFor(ST.hasStdExtZbb() || ST.hasStdExtZbkb(), {{sXLen, sXLen}})
203 .customFor(ST.is64Bit() && (ST.hasStdExtZbb() || ST.hasStdExtZbkb()),
204 {{s32, s32}})
205 .lower();
206
207 getActionDefinitionsBuilder(G_BITREVERSE).maxScalar(0, sXLen).lower();
208
209 getActionDefinitionsBuilder(G_BITCAST).legalIf(
211 typeIsLegalBoolVec(0, BoolVecTys, ST)),
213 typeIsLegalBoolVec(1, BoolVecTys, ST))));
214
215 auto &BSWAPActions = getActionDefinitionsBuilder(G_BSWAP);
216 if (ST.hasStdExtZbb() || ST.hasStdExtZbkb())
217 BSWAPActions.legalFor({sXLen}).clampScalar(0, sXLen, sXLen);
218 else
219 BSWAPActions.maxScalar(0, sXLen).lower();
220
221 auto &CountZerosActions = getActionDefinitionsBuilder({G_CTLZ, G_CTTZ});
222 auto &CountZerosUndefActions =
223 getActionDefinitionsBuilder({G_CTLZ_ZERO_UNDEF, G_CTTZ_ZERO_UNDEF});
224 if (ST.hasStdExtZbb()) {
225 CountZerosActions.legalFor({{sXLen, sXLen}})
226 .customFor({{s32, s32}})
227 .clampScalar(0, s32, sXLen)
228 .widenScalarToNextPow2(0)
229 .scalarSameSizeAs(1, 0);
230 } else {
231 CountZerosActions.maxScalar(0, sXLen).scalarSameSizeAs(1, 0).lower();
232 CountZerosUndefActions.maxScalar(0, sXLen).scalarSameSizeAs(1, 0);
233 }
234 CountZerosUndefActions.lower();
235
236 auto &CTPOPActions = getActionDefinitionsBuilder(G_CTPOP);
237 if (ST.hasStdExtZbb()) {
238 CTPOPActions.legalFor({{sXLen, sXLen}})
239 .clampScalar(0, sXLen, sXLen)
240 .scalarSameSizeAs(1, 0);
241 } else {
242 CTPOPActions.widenScalarToNextPow2(0, /*Min*/ 8)
243 .clampScalar(0, s8, sXLen)
244 .scalarSameSizeAs(1, 0)
245 .lower();
246 }
247
248 getActionDefinitionsBuilder(G_CONSTANT)
249 .legalFor({p0})
250 .legalFor(!ST.is64Bit(), {s32})
251 .customFor(ST.is64Bit(), {s64})
252 .widenScalarToNextPow2(0)
253 .clampScalar(0, sXLen, sXLen);
254
255 // TODO: transform illegal vector types into legal vector type
256 getActionDefinitionsBuilder(G_FREEZE)
257 .legalFor({s16, s32, p0})
258 .legalFor(ST.is64Bit(), {s64})
259 .legalIf(typeIsLegalBoolVec(0, BoolVecTys, ST))
260 .legalIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST))
261 .widenScalarToNextPow2(0)
262 .clampScalar(0, s16, sXLen);
263
264 // TODO: transform illegal vector types into legal vector type
265 // TODO: Merge with G_FREEZE?
266 getActionDefinitionsBuilder(
267 {G_IMPLICIT_DEF, G_CONSTANT_FOLD_BARRIER})
268 .legalFor({s32, sXLen, p0})
269 .legalIf(typeIsLegalBoolVec(0, BoolVecTys, ST))
270 .legalIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST))
271 .widenScalarToNextPow2(0)
272 .clampScalar(0, s32, sXLen);
273
274 getActionDefinitionsBuilder(G_ICMP)
275 .legalFor({{sXLen, sXLen}, {sXLen, p0}})
276 .legalIf(all(typeIsLegalBoolVec(0, BoolVecTys, ST),
277 typeIsLegalIntOrFPVec(1, IntOrFPVecTys, ST)))
278 .widenScalarOrEltToNextPow2OrMinSize(1, 8)
279 .clampScalar(1, sXLen, sXLen)
280 .clampScalar(0, sXLen, sXLen);
281
282 getActionDefinitionsBuilder(G_SELECT)
283 .legalFor({{s32, sXLen}, {p0, sXLen}})
284 .legalIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
285 typeIsLegalBoolVec(1, BoolVecTys, ST)))
286 .legalFor(XLen == 64 || ST.hasStdExtD(), {{s64, sXLen}})
287 .widenScalarToNextPow2(0)
288 .clampScalar(0, s32, (XLen == 64 || ST.hasStdExtD()) ? s64 : s32)
289 .clampScalar(1, sXLen, sXLen);
290
291 auto &LoadActions = getActionDefinitionsBuilder(G_LOAD);
292 auto &StoreActions = getActionDefinitionsBuilder(G_STORE);
293 auto &ExtLoadActions = getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD});
294
295 // Return the alignment needed for scalar memory ops. If unaligned scalar mem
296 // is supported, we only require byte alignment. Otherwise, we need the memory
297 // op to be natively aligned.
298 auto getScalarMemAlign = [&ST](unsigned Size) {
299 return ST.enableUnalignedScalarMem() ? 8 : Size;
300 };
301
302 LoadActions.legalForTypesWithMemDesc(
303 {{s16, p0, s8, getScalarMemAlign(8)},
304 {s32, p0, s8, getScalarMemAlign(8)},
305 {s16, p0, s16, getScalarMemAlign(16)},
306 {s32, p0, s16, getScalarMemAlign(16)},
307 {s32, p0, s32, getScalarMemAlign(32)},
308 {p0, p0, sXLen, getScalarMemAlign(XLen)}});
309 StoreActions.legalForTypesWithMemDesc(
310 {{s16, p0, s8, getScalarMemAlign(8)},
311 {s32, p0, s8, getScalarMemAlign(8)},
312 {s16, p0, s16, getScalarMemAlign(16)},
313 {s32, p0, s16, getScalarMemAlign(16)},
314 {s32, p0, s32, getScalarMemAlign(32)},
315 {p0, p0, sXLen, getScalarMemAlign(XLen)}});
316 ExtLoadActions.legalForTypesWithMemDesc(
317 {{sXLen, p0, s8, getScalarMemAlign(8)},
318 {sXLen, p0, s16, getScalarMemAlign(16)}});
319 if (XLen == 64) {
320 LoadActions.legalForTypesWithMemDesc(
321 {{s64, p0, s8, getScalarMemAlign(8)},
322 {s64, p0, s16, getScalarMemAlign(16)},
323 {s64, p0, s32, getScalarMemAlign(32)},
324 {s64, p0, s64, getScalarMemAlign(64)}});
325 StoreActions.legalForTypesWithMemDesc(
326 {{s64, p0, s8, getScalarMemAlign(8)},
327 {s64, p0, s16, getScalarMemAlign(16)},
328 {s64, p0, s32, getScalarMemAlign(32)},
329 {s64, p0, s64, getScalarMemAlign(64)}});
330 ExtLoadActions.legalForTypesWithMemDesc(
331 {{s64, p0, s32, getScalarMemAlign(32)}});
332 } else if (ST.hasStdExtD()) {
333 LoadActions.legalForTypesWithMemDesc(
334 {{s64, p0, s64, getScalarMemAlign(64)}});
335 StoreActions.legalForTypesWithMemDesc(
336 {{s64, p0, s64, getScalarMemAlign(64)}});
337 }
338
339 // Vector loads/stores.
340 if (ST.hasVInstructions()) {
341 LoadActions.legalForTypesWithMemDesc({{nxv2s8, p0, nxv2s8, 8},
342 {nxv4s8, p0, nxv4s8, 8},
343 {nxv8s8, p0, nxv8s8, 8},
344 {nxv16s8, p0, nxv16s8, 8},
345 {nxv32s8, p0, nxv32s8, 8},
346 {nxv64s8, p0, nxv64s8, 8},
347 {nxv2s16, p0, nxv2s16, 16},
348 {nxv4s16, p0, nxv4s16, 16},
349 {nxv8s16, p0, nxv8s16, 16},
350 {nxv16s16, p0, nxv16s16, 16},
351 {nxv32s16, p0, nxv32s16, 16},
352 {nxv2s32, p0, nxv2s32, 32},
353 {nxv4s32, p0, nxv4s32, 32},
354 {nxv8s32, p0, nxv8s32, 32},
355 {nxv16s32, p0, nxv16s32, 32}});
356 StoreActions.legalForTypesWithMemDesc({{nxv2s8, p0, nxv2s8, 8},
357 {nxv4s8, p0, nxv4s8, 8},
358 {nxv8s8, p0, nxv8s8, 8},
359 {nxv16s8, p0, nxv16s8, 8},
360 {nxv32s8, p0, nxv32s8, 8},
361 {nxv64s8, p0, nxv64s8, 8},
362 {nxv2s16, p0, nxv2s16, 16},
363 {nxv4s16, p0, nxv4s16, 16},
364 {nxv8s16, p0, nxv8s16, 16},
365 {nxv16s16, p0, nxv16s16, 16},
366 {nxv32s16, p0, nxv32s16, 16},
367 {nxv2s32, p0, nxv2s32, 32},
368 {nxv4s32, p0, nxv4s32, 32},
369 {nxv8s32, p0, nxv8s32, 32},
370 {nxv16s32, p0, nxv16s32, 32}});
371
372 if (ST.getELen() == 64) {
373 LoadActions.legalForTypesWithMemDesc({{nxv1s8, p0, nxv1s8, 8},
374 {nxv1s16, p0, nxv1s16, 16},
375 {nxv1s32, p0, nxv1s32, 32}});
376 StoreActions.legalForTypesWithMemDesc({{nxv1s8, p0, nxv1s8, 8},
377 {nxv1s16, p0, nxv1s16, 16},
378 {nxv1s32, p0, nxv1s32, 32}});
379 }
380
381 if (ST.hasVInstructionsI64()) {
382 LoadActions.legalForTypesWithMemDesc({{nxv1s64, p0, nxv1s64, 64},
383 {nxv2s64, p0, nxv2s64, 64},
384 {nxv4s64, p0, nxv4s64, 64},
385 {nxv8s64, p0, nxv8s64, 64}});
386 StoreActions.legalForTypesWithMemDesc({{nxv1s64, p0, nxv1s64, 64},
387 {nxv2s64, p0, nxv2s64, 64},
388 {nxv4s64, p0, nxv4s64, 64},
389 {nxv8s64, p0, nxv8s64, 64}});
390 }
391
392 // we will take the custom lowering logic if we have scalable vector types
393 // with non-standard alignments
394 LoadActions.customIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST));
395 StoreActions.customIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST));
396
397 // Pointers require that XLen sized elements are legal.
398 if (XLen <= ST.getELen()) {
399 LoadActions.customIf(typeIsLegalPtrVec(0, PtrVecTys, ST));
400 StoreActions.customIf(typeIsLegalPtrVec(0, PtrVecTys, ST));
401 }
402 }
403
404 LoadActions.widenScalarToNextPow2(0, /* MinSize = */ 8)
405 .lowerIfMemSizeNotByteSizePow2()
406 .clampScalar(0, s16, sXLen)
407 .lower();
408 StoreActions
409 .clampScalar(0, s16, sXLen)
410 .lowerIfMemSizeNotByteSizePow2()
411 .lower();
412
413 ExtLoadActions.widenScalarToNextPow2(0).clampScalar(0, sXLen, sXLen).lower();
414
415 getActionDefinitionsBuilder({G_PTR_ADD, G_PTRMASK}).legalFor({{p0, sXLen}});
416
417 getActionDefinitionsBuilder(G_PTRTOINT)
418 .legalFor({{sXLen, p0}})
419 .clampScalar(0, sXLen, sXLen);
420
421 getActionDefinitionsBuilder(G_INTTOPTR)
422 .legalFor({{p0, sXLen}})
423 .clampScalar(1, sXLen, sXLen);
424
425 getActionDefinitionsBuilder(G_BRCOND).legalFor({sXLen}).minScalar(0, sXLen);
426
427 getActionDefinitionsBuilder(G_BRJT).customFor({{p0, sXLen}});
428
429 getActionDefinitionsBuilder(G_BRINDIRECT).legalFor({p0});
430
431 getActionDefinitionsBuilder(G_PHI)
432 .legalFor({p0, s32, sXLen})
433 .widenScalarToNextPow2(0)
434 .clampScalar(0, s32, sXLen);
435
436 getActionDefinitionsBuilder({G_GLOBAL_VALUE, G_JUMP_TABLE, G_CONSTANT_POOL})
437 .legalFor({p0});
438
439 if (ST.hasStdExtZmmul()) {
440 getActionDefinitionsBuilder(G_MUL)
441 .legalFor({sXLen})
442 .widenScalarToNextPow2(0)
443 .clampScalar(0, sXLen, sXLen);
444
445 // clang-format off
446 getActionDefinitionsBuilder({G_SMULH, G_UMULH})
447 .legalFor({sXLen})
448 .lower();
449 // clang-format on
450
451 getActionDefinitionsBuilder({G_SMULO, G_UMULO}).minScalar(0, sXLen).lower();
452 } else {
453 getActionDefinitionsBuilder(G_MUL)
454 .libcallFor({sXLen, sDoubleXLen})
455 .widenScalarToNextPow2(0)
456 .clampScalar(0, sXLen, sDoubleXLen);
457
458 getActionDefinitionsBuilder({G_SMULH, G_UMULH}).lowerFor({sXLen});
459
460 getActionDefinitionsBuilder({G_SMULO, G_UMULO})
461 .minScalar(0, sXLen)
462 // Widen sXLen to sDoubleXLen so we can use a single libcall to get
463 // the low bits for the mul result and high bits to do the overflow
464 // check.
465 .widenScalarIf(typeIs(0, sXLen),
466 LegalizeMutations::changeTo(0, sDoubleXLen))
467 .lower();
468 }
469
470 if (ST.hasStdExtM()) {
471 getActionDefinitionsBuilder({G_SDIV, G_UDIV, G_UREM})
472 .legalFor({sXLen})
473 .customFor({s32})
474 .libcallFor({sDoubleXLen})
475 .clampScalar(0, s32, sDoubleXLen)
476 .widenScalarToNextPow2(0);
477 getActionDefinitionsBuilder(G_SREM)
478 .legalFor({sXLen})
479 .libcallFor({sDoubleXLen})
480 .clampScalar(0, sXLen, sDoubleXLen)
481 .widenScalarToNextPow2(0);
482 } else {
483 getActionDefinitionsBuilder({G_UDIV, G_SDIV, G_UREM, G_SREM})
484 .libcallFor({sXLen, sDoubleXLen})
485 .clampScalar(0, sXLen, sDoubleXLen)
486 .widenScalarToNextPow2(0);
487 }
488
489 // TODO: Use libcall for sDoubleXLen.
490 getActionDefinitionsBuilder({G_SDIVREM, G_UDIVREM}).lower();
491
492 getActionDefinitionsBuilder(G_ABS)
493 .customFor(ST.hasStdExtZbb(), {sXLen})
494 .minScalar(ST.hasStdExtZbb(), 0, sXLen)
495 .lower();
496
497 getActionDefinitionsBuilder({G_ABDS, G_ABDU})
498 .minScalar(ST.hasStdExtZbb(), 0, sXLen)
499 .lower();
500
501 getActionDefinitionsBuilder({G_UMAX, G_UMIN, G_SMAX, G_SMIN})
502 .legalFor(ST.hasStdExtZbb(), {sXLen})
503 .minScalar(ST.hasStdExtZbb(), 0, sXLen)
504 .lower();
505
506 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
507
508 getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});
509
510 getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();
511
512 getActionDefinitionsBuilder({G_DYN_STACKALLOC, G_STACKSAVE, G_STACKRESTORE})
513 .lower();
514
515 // FP Operations
516
517 // FIXME: Support s128 for rv32 when libcall handling is able to use sret.
518 getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMA, G_FSQRT,
519 G_FMAXNUM, G_FMINNUM, G_FMAXIMUMNUM,
520 G_FMINIMUMNUM})
521 .legalFor(ST.hasStdExtF(), {s32})
522 .legalFor(ST.hasStdExtD(), {s64})
523 .legalFor(ST.hasStdExtZfh(), {s16})
524 .libcallFor({s32, s64})
525 .libcallFor(ST.is64Bit(), {s128});
526
527 getActionDefinitionsBuilder({G_FNEG, G_FABS})
528 .legalFor(ST.hasStdExtF(), {s32})
529 .legalFor(ST.hasStdExtD(), {s64})
530 .legalFor(ST.hasStdExtZfh(), {s16})
531 .lowerFor({s32, s64, s128});
532
533 getActionDefinitionsBuilder(G_FREM)
534 .libcallFor({s32, s64})
535 .libcallFor(ST.is64Bit(), {s128})
536 .minScalar(0, s32)
537 .scalarize(0);
538
539 getActionDefinitionsBuilder(G_FCOPYSIGN)
540 .legalFor(ST.hasStdExtF(), {{s32, s32}})
541 .legalFor(ST.hasStdExtD(), {{s64, s64}, {s32, s64}, {s64, s32}})
542 .legalFor(ST.hasStdExtZfh(), {{s16, s16}, {s16, s32}, {s32, s16}})
543 .legalFor(ST.hasStdExtZfh() && ST.hasStdExtD(), {{s16, s64}, {s64, s16}})
544 .lower();
545
546 // FIXME: Use Zfhmin.
547 getActionDefinitionsBuilder(G_FPTRUNC)
548 .legalFor(ST.hasStdExtD(), {{s32, s64}})
549 .legalFor(ST.hasStdExtZfh(), {{s16, s32}})
550 .legalFor(ST.hasStdExtZfh() && ST.hasStdExtD(), {{s16, s64}})
551 .libcallFor({{s32, s64}})
552 .libcallFor(ST.is64Bit(), {{s32, s128}, {s64, s128}});
553 getActionDefinitionsBuilder(G_FPEXT)
554 .legalFor(ST.hasStdExtD(), {{s64, s32}})
555 .legalFor(ST.hasStdExtZfh(), {{s32, s16}})
556 .legalFor(ST.hasStdExtZfh() && ST.hasStdExtD(), {{s64, s16}})
557 .libcallFor({{s64, s32}})
558 .libcallFor(ST.is64Bit(), {{s128, s32}, {s128, s64}});
559
560 getActionDefinitionsBuilder(G_FCMP)
561 .legalFor(ST.hasStdExtF(), {{sXLen, s32}})
562 .legalFor(ST.hasStdExtD(), {{sXLen, s64}})
563 .legalFor(ST.hasStdExtZfh(), {{sXLen, s16}})
564 .clampScalar(0, sXLen, sXLen)
565 .libcallFor({{sXLen, s32}, {sXLen, s64}})
566 .libcallFor(ST.is64Bit(), {{sXLen, s128}});
567
568 // TODO: Support vector version of G_IS_FPCLASS.
569 getActionDefinitionsBuilder(G_IS_FPCLASS)
570 .customFor(ST.hasStdExtF(), {{s1, s32}})
571 .customFor(ST.hasStdExtD(), {{s1, s64}})
572 .customFor(ST.hasStdExtZfh(), {{s1, s16}})
573 .lowerFor({{s1, s32}, {s1, s64}});
574
575 getActionDefinitionsBuilder(G_FCONSTANT)
576 .legalFor(ST.hasStdExtF(), {s32})
577 .legalFor(ST.hasStdExtD(), {s64})
578 .legalFor(ST.hasStdExtZfh(), {s16})
579 .customFor(!ST.is64Bit(), {s32})
580 .customFor(ST.is64Bit(), {s32, s64})
581 .lowerFor({s64, s128});
582
583 getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
584 .legalFor(ST.hasStdExtF(), {{sXLen, s32}})
585 .legalFor(ST.hasStdExtD(), {{sXLen, s64}})
586 .legalFor(ST.hasStdExtZfh(), {{sXLen, s16}})
587 .customFor(ST.is64Bit() && ST.hasStdExtF(), {{s32, s32}})
588 .customFor(ST.is64Bit() && ST.hasStdExtD(), {{s32, s64}})
589 .customFor(ST.is64Bit() && ST.hasStdExtZfh(), {{s32, s16}})
590 .widenScalarToNextPow2(0)
591 .minScalar(0, s32)
592 .libcallFor({{s32, s32}, {s64, s32}, {s32, s64}, {s64, s64}})
593 .libcallFor(ST.is64Bit(), {{s32, s128}, {s64, s128}}) // FIXME RV32.
594 .libcallFor(ST.is64Bit(), {{s128, s32}, {s128, s64}, {s128, s128}});
595
596 getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
597 .legalFor(ST.hasStdExtF(), {{s32, sXLen}})
598 .legalFor(ST.hasStdExtD(), {{s64, sXLen}})
599 .legalFor(ST.hasStdExtZfh(), {{s16, sXLen}})
600 .widenScalarToNextPow2(1)
601 // Promote to XLen if the operation is legal.
602 .widenScalarIf(
603 [=, &ST](const LegalityQuery &Query) {
604 return Query.Types[0].isScalar() && Query.Types[1].isScalar() &&
605 (Query.Types[1].getSizeInBits() < ST.getXLen()) &&
606 ((ST.hasStdExtF() && Query.Types[0].getSizeInBits() == 32) ||
607 (ST.hasStdExtD() && Query.Types[0].getSizeInBits() == 64) ||
608 (ST.hasStdExtZfh() &&
609 Query.Types[0].getSizeInBits() == 16));
610 },
612 // Otherwise only promote to s32 since we have si libcalls.
613 .minScalar(1, s32)
614 .libcallFor({{s32, s32}, {s64, s32}, {s32, s64}, {s64, s64}})
615 .libcallFor(ST.is64Bit(), {{s128, s32}, {s128, s64}}) // FIXME RV32.
616 .libcallFor(ST.is64Bit(), {{s32, s128}, {s64, s128}, {s128, s128}});
617
618 // FIXME: We can do custom inline expansion like SelectionDAG.
619 getActionDefinitionsBuilder({G_FCEIL, G_FFLOOR, G_FRINT, G_FNEARBYINT,
620 G_INTRINSIC_TRUNC, G_INTRINSIC_ROUND,
621 G_INTRINSIC_ROUNDEVEN})
622 .legalFor(ST.hasStdExtZfa(), {s32})
623 .legalFor(ST.hasStdExtZfa() && ST.hasStdExtD(), {s64})
624 .legalFor(ST.hasStdExtZfa() && ST.hasStdExtZfh(), {s16})
625 .libcallFor({s32, s64})
626 .libcallFor(ST.is64Bit(), {s128});
627
628 getActionDefinitionsBuilder({G_FMAXIMUM, G_FMINIMUM})
629 .legalFor(ST.hasStdExtZfa(), {s32})
630 .legalFor(ST.hasStdExtZfa() && ST.hasStdExtD(), {s64})
631 .legalFor(ST.hasStdExtZfa() && ST.hasStdExtZfh(), {s16});
632
633 getActionDefinitionsBuilder({G_FCOS, G_FSIN, G_FTAN, G_FPOW, G_FLOG, G_FLOG2,
634 G_FLOG10, G_FEXP, G_FEXP2, G_FEXP10, G_FACOS,
635 G_FASIN, G_FATAN, G_FATAN2, G_FCOSH, G_FSINH,
636 G_FTANH, G_FMODF})
637 .libcallFor({s32, s64})
638 .libcallFor(ST.is64Bit(), {s128});
639 getActionDefinitionsBuilder({G_FPOWI, G_FLDEXP})
640 .libcallFor({{s32, s32}, {s64, s32}})
641 .libcallFor(ST.is64Bit(), {s128, s32});
642
643 getActionDefinitionsBuilder(G_FCANONICALIZE)
644 .legalFor(ST.hasStdExtF(), {s32})
645 .legalFor(ST.hasStdExtD(), {s64})
646 .legalFor(ST.hasStdExtZfh(), {s16});
647
648 getActionDefinitionsBuilder(G_VASTART).customFor({p0});
649
650 // va_list must be a pointer, but most sized types are pretty easy to handle
651 // as the destination.
652 getActionDefinitionsBuilder(G_VAARG)
653 // TODO: Implement narrowScalar and widenScalar for G_VAARG for types
654 // other than sXLen.
655 .clampScalar(0, sXLen, sXLen)
656 .lowerForCartesianProduct({sXLen, p0}, {p0});
657
658 getActionDefinitionsBuilder(G_VSCALE)
659 .clampScalar(0, sXLen, sXLen)
660 .customFor({sXLen});
661
662 auto &SplatActions =
663 getActionDefinitionsBuilder(G_SPLAT_VECTOR)
664 .legalIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
665 typeIs(1, sXLen)))
666 .customIf(all(typeIsLegalBoolVec(0, BoolVecTys, ST), typeIs(1, s1)));
667 // Handle case of s64 element vectors on RV32. If the subtarget does not have
668 // f64, then try to lower it to G_SPLAT_VECTOR_SPLIT_64_VL. If the subtarget
669 // does have f64, then we don't know whether the type is an f64 or an i64,
670 // so mark the G_SPLAT_VECTOR as legal and decide later what to do with it,
671 // depending on how the instructions it consumes are legalized. They are not
672 // legalized yet since legalization is in reverse postorder, so we cannot
673 // make the decision at this moment.
674 if (XLen == 32) {
675 if (ST.hasVInstructionsF64() && ST.hasStdExtD())
676 SplatActions.legalIf(all(
677 typeInSet(0, {nxv1s64, nxv2s64, nxv4s64, nxv8s64}), typeIs(1, s64)));
678 else if (ST.hasVInstructionsI64())
679 SplatActions.customIf(all(
680 typeInSet(0, {nxv1s64, nxv2s64, nxv4s64, nxv8s64}), typeIs(1, s64)));
681 }
682
683 SplatActions.clampScalar(1, sXLen, sXLen);
684
685 LegalityPredicate ExtractSubvecBitcastPred = [=](const LegalityQuery &Query) {
686 LLT DstTy = Query.Types[0];
687 LLT SrcTy = Query.Types[1];
688 return DstTy.getElementType() == LLT::scalar(1) &&
689 DstTy.getElementCount().getKnownMinValue() >= 8 &&
690 SrcTy.getElementCount().getKnownMinValue() >= 8;
691 };
692 getActionDefinitionsBuilder(G_EXTRACT_SUBVECTOR)
693 // We don't have the ability to slide mask vectors down indexed by their
694 // i1 elements; the smallest we can do is i8. Often we are able to bitcast
695 // to equivalent i8 vectors.
696 .bitcastIf(
697 all(typeIsLegalBoolVec(0, BoolVecTys, ST),
698 typeIsLegalBoolVec(1, BoolVecTys, ST), ExtractSubvecBitcastPred),
699 [=](const LegalityQuery &Query) {
700 LLT CastTy = LLT::vector(
701 Query.Types[0].getElementCount().divideCoefficientBy(8), 8);
702 return std::pair(0, CastTy);
703 })
704 .customIf(LegalityPredicates::any(
705 all(typeIsLegalBoolVec(0, BoolVecTys, ST),
706 typeIsLegalBoolVec(1, BoolVecTys, ST)),
707 all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
708 typeIsLegalIntOrFPVec(1, IntOrFPVecTys, ST))));
709
710 getActionDefinitionsBuilder(G_INSERT_SUBVECTOR)
711 .customIf(all(typeIsLegalBoolVec(0, BoolVecTys, ST),
712 typeIsLegalBoolVec(1, BoolVecTys, ST)))
713 .customIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
714 typeIsLegalIntOrFPVec(1, IntOrFPVecTys, ST)));
715
716 getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG_WITH_SUCCESS)
717 .lowerIf(all(typeInSet(0, {s8, s16, s32, s64}), typeIs(2, p0)));
718
719 getActionDefinitionsBuilder({G_ATOMIC_CMPXCHG, G_ATOMICRMW_ADD})
720 .legalFor(ST.hasStdExtA(), {{sXLen, p0}})
721 .libcallFor(!ST.hasStdExtA(), {{s8, p0}, {s16, p0}, {s32, p0}, {s64, p0}})
722 .clampScalar(0, sXLen, sXLen);
723
724 getActionDefinitionsBuilder(G_ATOMICRMW_SUB)
725 .libcallFor(!ST.hasStdExtA(), {{s8, p0}, {s16, p0}, {s32, p0}, {s64, p0}})
726 .clampScalar(0, sXLen, sXLen)
727 .lower();
728
729 LegalityPredicate InsertVectorEltPred = [=](const LegalityQuery &Query) {
730 LLT VecTy = Query.Types[0];
731 LLT EltTy = Query.Types[1];
732 return VecTy.getElementType() == EltTy;
733 };
734
735 getActionDefinitionsBuilder(G_INSERT_VECTOR_ELT)
736 .legalIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
737 InsertVectorEltPred, typeIs(2, sXLen)))
738 .legalIf(all(typeIsLegalBoolVec(0, BoolVecTys, ST), InsertVectorEltPred,
739 typeIs(2, sXLen)));
740
741 getLegacyLegalizerInfo().computeTables();
742 verify(*ST.getInstrInfo());
743}
744
746 MachineInstr &MI) const {
747 Intrinsic::ID IntrinsicID = cast<GIntrinsic>(MI).getIntrinsicID();
748
750 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntrinsicID)) {
751 if (II->hasScalarOperand() && !II->IsFPIntrinsic) {
752 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
753 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
754
755 auto OldScalar = MI.getOperand(II->ScalarOperand + 2).getReg();
756 // Legalize integer vx form intrinsic.
757 if (MRI.getType(OldScalar).isScalar()) {
758 if (MRI.getType(OldScalar).getSizeInBits() < sXLen.getSizeInBits()) {
759 Helper.Observer.changingInstr(MI);
760 Helper.widenScalarSrc(MI, sXLen, II->ScalarOperand + 2,
761 TargetOpcode::G_ANYEXT);
762 Helper.Observer.changedInstr(MI);
763 } else if (MRI.getType(OldScalar).getSizeInBits() >
764 sXLen.getSizeInBits()) {
765 // TODO: i64 in riscv32.
766 return false;
767 }
768 }
769 }
770 return true;
771 }
772
773 switch (IntrinsicID) {
774 default:
775 return false;
776 case Intrinsic::vacopy: {
777 // vacopy arguments must be legal because of the intrinsic signature.
778 // No need to check here.
779
780 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
781 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
782 MachineFunction &MF = *MI.getMF();
783 const DataLayout &DL = MIRBuilder.getDataLayout();
784 LLVMContext &Ctx = MF.getFunction().getContext();
785
786 Register DstLst = MI.getOperand(1).getReg();
787 LLT PtrTy = MRI.getType(DstLst);
788
789 // Load the source va_list
790 Align Alignment = DL.getABITypeAlign(getTypeForLLT(PtrTy, Ctx));
792 MachinePointerInfo(), MachineMemOperand::MOLoad, PtrTy, Alignment);
793 auto Tmp = MIRBuilder.buildLoad(PtrTy, MI.getOperand(2), *LoadMMO);
794
795 // Store the result in the destination va_list
798 MIRBuilder.buildStore(Tmp, DstLst, *StoreMMO);
799
800 MI.eraseFromParent();
801 return true;
802 }
803 case Intrinsic::riscv_vsetvli:
804 case Intrinsic::riscv_vsetvlimax:
805 case Intrinsic::riscv_masked_atomicrmw_add:
806 case Intrinsic::riscv_masked_atomicrmw_sub:
807 case Intrinsic::riscv_masked_cmpxchg:
808 return true;
809 }
810}
811
812bool RISCVLegalizerInfo::legalizeVAStart(MachineInstr &MI,
813 MachineIRBuilder &MIRBuilder) const {
814 // Stores the address of the VarArgsFrameIndex slot into the memory location
815 assert(MI.getOpcode() == TargetOpcode::G_VASTART);
816 MachineFunction *MF = MI.getParent()->getParent();
818 int FI = FuncInfo->getVarArgsFrameIndex();
819 LLT AddrTy = MIRBuilder.getMRI()->getType(MI.getOperand(0).getReg());
820 auto FINAddr = MIRBuilder.buildFrameIndex(AddrTy, FI);
821 assert(MI.hasOneMemOperand());
822 MIRBuilder.buildStore(FINAddr, MI.getOperand(0).getReg(),
823 *MI.memoperands()[0]);
824 MI.eraseFromParent();
825 return true;
826}
827
828bool RISCVLegalizerInfo::legalizeBRJT(MachineInstr &MI,
829 MachineIRBuilder &MIRBuilder) const {
830 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
831 auto &MF = *MI.getParent()->getParent();
832 const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
833 unsigned EntrySize = MJTI->getEntrySize(MF.getDataLayout());
834
835 Register PtrReg = MI.getOperand(0).getReg();
836 LLT PtrTy = MRI.getType(PtrReg);
837 Register IndexReg = MI.getOperand(2).getReg();
838 LLT IndexTy = MRI.getType(IndexReg);
839
840 if (!isPowerOf2_32(EntrySize))
841 return false;
842
843 auto ShiftAmt = MIRBuilder.buildConstant(IndexTy, Log2_32(EntrySize));
844 IndexReg = MIRBuilder.buildShl(IndexTy, IndexReg, ShiftAmt).getReg(0);
845
846 auto Addr = MIRBuilder.buildPtrAdd(PtrTy, PtrReg, IndexReg);
847
850 EntrySize, Align(MJTI->getEntryAlignment(MF.getDataLayout())));
851
852 Register TargetReg;
853 switch (MJTI->getEntryKind()) {
854 default:
855 return false;
857 // For PIC, the sequence is:
858 // BRIND(load(Jumptable + index) + RelocBase)
859 // RelocBase can be JumpTable, GOT or some sort of global base.
860 unsigned LoadOpc =
861 STI.is64Bit() ? TargetOpcode::G_SEXTLOAD : TargetOpcode::G_LOAD;
862 auto Load = MIRBuilder.buildLoadInstr(LoadOpc, IndexTy, Addr, *MMO);
863 TargetReg = MIRBuilder.buildPtrAdd(PtrTy, PtrReg, Load).getReg(0);
864 break;
865 }
867 auto Load = MIRBuilder.buildLoadInstr(TargetOpcode::G_SEXTLOAD, IndexTy,
868 Addr, *MMO);
869 TargetReg = MIRBuilder.buildIntToPtr(PtrTy, Load).getReg(0);
870 break;
871 }
873 TargetReg = MIRBuilder.buildLoad(PtrTy, Addr, *MMO).getReg(0);
874 break;
875 }
876
877 MIRBuilder.buildBrIndirect(TargetReg);
878
879 MI.eraseFromParent();
880 return true;
881}
882
883bool RISCVLegalizerInfo::shouldBeInConstantPool(const APInt &APImm,
884 bool ShouldOptForSize) const {
885 assert(APImm.getBitWidth() == 32 || APImm.getBitWidth() == 64);
886 int64_t Imm = APImm.getSExtValue();
887 // All simm32 constants should be handled by isel.
888 // NOTE: The getMaxBuildIntsCost call below should return a value >= 2 making
889 // this check redundant, but small immediates are common so this check
890 // should have better compile time.
891 if (isInt<32>(Imm))
892 return false;
893
894 // We only need to cost the immediate, if constant pool lowering is enabled.
895 if (!STI.useConstantPoolForLargeInts())
896 return false;
897
899 if (Seq.size() <= STI.getMaxBuildIntsCost())
900 return false;
901
902 // Optimizations below are disabled for opt size. If we're optimizing for
903 // size, use a constant pool.
904 if (ShouldOptForSize)
905 return true;
906 //
907 // Special case. See if we can build the constant as (ADD (SLLI X, C), X) do
908 // that if it will avoid a constant pool.
909 // It will require an extra temporary register though.
910 // If we have Zba we can use (ADD_UW X, (SLLI X, 32)) to handle cases where
911 // low and high 32 bits are the same and bit 31 and 63 are set.
912 unsigned ShiftAmt, AddOpc;
914 RISCVMatInt::generateTwoRegInstSeq(Imm, STI, ShiftAmt, AddOpc);
915 return !(!SeqLo.empty() && (SeqLo.size() + 2) <= STI.getMaxBuildIntsCost());
916}
917
918bool RISCVLegalizerInfo::legalizeVScale(MachineInstr &MI,
919 MachineIRBuilder &MIB) const {
920 const LLT XLenTy(STI.getXLenVT());
921 Register Dst = MI.getOperand(0).getReg();
922
923 // We define our scalable vector types for lmul=1 to use a 64 bit known
924 // minimum size. e.g. <vscale x 2 x i32>. VLENB is in bytes so we calculate
925 // vscale as VLENB / 8.
926 static_assert(RISCV::RVVBitsPerBlock == 64, "Unexpected bits per block!");
927 if (STI.getRealMinVLen() < RISCV::RVVBitsPerBlock)
928 // Support for VLEN==32 is incomplete.
929 return false;
930
931 // We assume VLENB is a multiple of 8. We manually choose the best shift
932 // here because SimplifyDemandedBits isn't always able to simplify it.
933 uint64_t Val = MI.getOperand(1).getCImm()->getZExtValue();
934 if (isPowerOf2_64(Val)) {
935 uint64_t Log2 = Log2_64(Val);
936 if (Log2 < 3) {
937 auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {});
938 MIB.buildLShr(Dst, VLENB, MIB.buildConstant(XLenTy, 3 - Log2));
939 } else if (Log2 > 3) {
940 auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {});
941 MIB.buildShl(Dst, VLENB, MIB.buildConstant(XLenTy, Log2 - 3));
942 } else {
943 MIB.buildInstr(RISCV::G_READ_VLENB, {Dst}, {});
944 }
945 } else if ((Val % 8) == 0) {
946 // If the multiplier is a multiple of 8, scale it down to avoid needing
947 // to shift the VLENB value.
948 auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {});
949 MIB.buildMul(Dst, VLENB, MIB.buildConstant(XLenTy, Val / 8));
950 } else {
951 auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {});
952 auto VScale = MIB.buildLShr(XLenTy, VLENB, MIB.buildConstant(XLenTy, 3));
953 MIB.buildMul(Dst, VScale, MIB.buildConstant(XLenTy, Val));
954 }
955 MI.eraseFromParent();
956 return true;
957}
958
959// Custom-lower extensions from mask vectors by using a vselect either with 1
960// for zero/any-extension or -1 for sign-extension:
961// (vXiN = (s|z)ext vXi1:vmask) -> (vXiN = vselect vmask, (-1 or 1), 0)
962// Note that any-extension is lowered identically to zero-extension.
963bool RISCVLegalizerInfo::legalizeExt(MachineInstr &MI,
964 MachineIRBuilder &MIB) const {
965
966 unsigned Opc = MI.getOpcode();
967 assert(Opc == TargetOpcode::G_ZEXT || Opc == TargetOpcode::G_SEXT ||
968 Opc == TargetOpcode::G_ANYEXT);
969
970 MachineRegisterInfo &MRI = *MIB.getMRI();
971 Register Dst = MI.getOperand(0).getReg();
972 Register Src = MI.getOperand(1).getReg();
973
974 LLT DstTy = MRI.getType(Dst);
975 int64_t ExtTrueVal = Opc == TargetOpcode::G_SEXT ? -1 : 1;
976 LLT DstEltTy = DstTy.getElementType();
977 auto SplatZero = MIB.buildSplatVector(DstTy, MIB.buildConstant(DstEltTy, 0));
978 auto SplatTrue =
979 MIB.buildSplatVector(DstTy, MIB.buildConstant(DstEltTy, ExtTrueVal));
980 MIB.buildSelect(Dst, Src, SplatTrue, SplatZero);
981
982 MI.eraseFromParent();
983 return true;
984}
985
986bool RISCVLegalizerInfo::legalizeLoadStore(MachineInstr &MI,
987 LegalizerHelper &Helper,
988 MachineIRBuilder &MIB) const {
990 "Machine instructions must be Load/Store.");
991 MachineRegisterInfo &MRI = *MIB.getMRI();
992 MachineFunction *MF = MI.getMF();
993 const DataLayout &DL = MIB.getDataLayout();
994 LLVMContext &Ctx = MF->getFunction().getContext();
995
996 Register DstReg = MI.getOperand(0).getReg();
997 LLT DataTy = MRI.getType(DstReg);
998 if (!DataTy.isVector())
999 return false;
1000
1001 if (!MI.hasOneMemOperand())
1002 return false;
1003
1004 MachineMemOperand *MMO = *MI.memoperands_begin();
1005
1006 const auto *TLI = STI.getTargetLowering();
1007 EVT VT = EVT::getEVT(getTypeForLLT(DataTy, Ctx));
1008
1009 if (TLI->allowsMemoryAccessForAlignment(Ctx, DL, VT, *MMO))
1010 return true;
1011
1012 unsigned EltSizeBits = DataTy.getScalarSizeInBits();
1013 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
1014 "Unexpected unaligned RVV load type");
1015
1016 // Calculate the new vector type with i8 elements
1017 unsigned NumElements =
1018 DataTy.getElementCount().getKnownMinValue() * (EltSizeBits / 8);
1019 LLT NewDataTy = LLT::scalable_vector(NumElements, 8);
1020
1021 Helper.bitcast(MI, 0, NewDataTy);
1022
1023 return true;
1024}
1025
1026/// Return the type of the mask type suitable for masking the provided
1027/// vector type. This is simply an i1 element type vector of the same
1028/// (possibly scalable) length.
1029static LLT getMaskTypeFor(LLT VecTy) {
1030 assert(VecTy.isVector());
1031 ElementCount EC = VecTy.getElementCount();
1032 return LLT::vector(EC, LLT::scalar(1));
1033}
1034
1035/// Creates an all ones mask suitable for masking a vector of type VecTy with
1036/// vector length VL.
1038 MachineIRBuilder &MIB,
1040 LLT MaskTy = getMaskTypeFor(VecTy);
1041 return MIB.buildInstr(RISCV::G_VMSET_VL, {MaskTy}, {VL});
1042}
1043
1044/// Gets the two common "VL" operands: an all-ones mask and the vector length.
1045/// VecTy is a scalable vector type.
1046static std::pair<MachineInstrBuilder, MachineInstrBuilder>
1048 assert(VecTy.isScalableVector() && "Expecting scalable container type");
1049 const RISCVSubtarget &STI = MIB.getMF().getSubtarget<RISCVSubtarget>();
1050 LLT XLenTy(STI.getXLenVT());
1051 auto VL = MIB.buildConstant(XLenTy, -1);
1052 auto Mask = buildAllOnesMask(VecTy, VL, MIB, MRI);
1053 return {Mask, VL};
1054}
1055
1057buildSplatPartsS64WithVL(const DstOp &Dst, const SrcOp &Passthru, Register Lo,
1058 Register Hi, const SrcOp &VL, MachineIRBuilder &MIB,
1060 // TODO: If the Hi bits of the splat are undefined, then it's fine to just
1061 // splat Lo even if it might be sign extended. I don't think we have
1062 // introduced a case where we're build a s64 where the upper bits are undef
1063 // yet.
1064
1065 // Fall back to a stack store and stride x0 vector load.
1066 // TODO: need to lower G_SPLAT_VECTOR_SPLIT_I64. This is done in
1067 // preprocessDAG in SDAG.
1068 return MIB.buildInstr(RISCV::G_SPLAT_VECTOR_SPLIT_I64_VL, {Dst},
1069 {Passthru, Lo, Hi, VL});
1070}
1071
1073buildSplatSplitS64WithVL(const DstOp &Dst, const SrcOp &Passthru,
1074 const SrcOp &Scalar, const SrcOp &VL,
1076 assert(Scalar.getLLTTy(MRI) == LLT::scalar(64) && "Unexpected VecTy!");
1077 auto Unmerge = MIB.buildUnmerge(LLT::scalar(32), Scalar);
1078 return buildSplatPartsS64WithVL(Dst, Passthru, Unmerge.getReg(0),
1079 Unmerge.getReg(1), VL, MIB, MRI);
1080}
1081
1082// Lower splats of s1 types to G_ICMP. For each mask vector type, we have a
1083// legal equivalently-sized i8 type, so we can use that as a go-between.
1084// Splats of s1 types that have constant value can be legalized as VMSET_VL or
1085// VMCLR_VL.
1086bool RISCVLegalizerInfo::legalizeSplatVector(MachineInstr &MI,
1087 MachineIRBuilder &MIB) const {
1088 assert(MI.getOpcode() == TargetOpcode::G_SPLAT_VECTOR);
1089
1090 MachineRegisterInfo &MRI = *MIB.getMRI();
1091
1092 Register Dst = MI.getOperand(0).getReg();
1093 Register SplatVal = MI.getOperand(1).getReg();
1094
1095 LLT VecTy = MRI.getType(Dst);
1096 LLT XLenTy(STI.getXLenVT());
1097
1098 // Handle case of s64 element vectors on rv32
1099 if (XLenTy.getSizeInBits() == 32 &&
1100 VecTy.getElementType().getSizeInBits() == 64) {
1101 auto [_, VL] = buildDefaultVLOps(MRI.getType(Dst), MIB, MRI);
1102 buildSplatSplitS64WithVL(Dst, MIB.buildUndef(VecTy), SplatVal, VL, MIB,
1103 MRI);
1104 MI.eraseFromParent();
1105 return true;
1106 }
1107
1108 // All-zeros or all-ones splats are handled specially.
1109 MachineInstr &SplatValMI = *MRI.getVRegDef(SplatVal);
1110 if (isAllOnesOrAllOnesSplat(SplatValMI, MRI)) {
1111 auto VL = buildDefaultVLOps(VecTy, MIB, MRI).second;
1112 MIB.buildInstr(RISCV::G_VMSET_VL, {Dst}, {VL});
1113 MI.eraseFromParent();
1114 return true;
1115 }
1116 if (isNullOrNullSplat(SplatValMI, MRI)) {
1117 auto VL = buildDefaultVLOps(VecTy, MIB, MRI).second;
1118 MIB.buildInstr(RISCV::G_VMCLR_VL, {Dst}, {VL});
1119 MI.eraseFromParent();
1120 return true;
1121 }
1122
1123 // Handle non-constant mask splat (i.e. not sure if it's all zeros or all
1124 // ones) by promoting it to an s8 splat.
1125 LLT InterEltTy = LLT::scalar(8);
1126 LLT InterTy = VecTy.changeElementType(InterEltTy);
1127 auto ZExtSplatVal = MIB.buildZExt(InterEltTy, SplatVal);
1128 auto And =
1129 MIB.buildAnd(InterEltTy, ZExtSplatVal, MIB.buildConstant(InterEltTy, 1));
1130 auto LHS = MIB.buildSplatVector(InterTy, And);
1131 auto ZeroSplat =
1132 MIB.buildSplatVector(InterTy, MIB.buildConstant(InterEltTy, 0));
1133 MIB.buildICmp(CmpInst::Predicate::ICMP_NE, Dst, LHS, ZeroSplat);
1134 MI.eraseFromParent();
1135 return true;
1136}
1137
1138static LLT getLMUL1Ty(LLT VecTy) {
1139 assert(VecTy.getElementType().getSizeInBits() <= 64 &&
1140 "Unexpected vector LLT");
1142 VecTy.getElementType().getSizeInBits(),
1143 VecTy.getElementType());
1144}
1145
1146bool RISCVLegalizerInfo::legalizeExtractSubvector(MachineInstr &MI,
1147 MachineIRBuilder &MIB) const {
1148 GExtractSubvector &ES = cast<GExtractSubvector>(MI);
1149
1150 MachineRegisterInfo &MRI = *MIB.getMRI();
1151
1152 Register Dst = ES.getReg(0);
1153 Register Src = ES.getSrcVec();
1154 uint64_t Idx = ES.getIndexImm();
1155
1156 // With an index of 0 this is a cast-like subvector, which can be performed
1157 // with subregister operations.
1158 if (Idx == 0)
1159 return true;
1160
1161 LLT LitTy = MRI.getType(Dst);
1162 LLT BigTy = MRI.getType(Src);
1163
1164 if (LitTy.getElementType() == LLT::scalar(1)) {
1165 // We can't slide this mask vector up indexed by its i1 elements.
1166 // This poses a problem when we wish to insert a scalable vector which
1167 // can't be re-expressed as a larger type. Just choose the slow path and
1168 // extend to a larger type, then truncate back down.
1169 LLT ExtBigTy = BigTy.changeElementType(LLT::scalar(8));
1170 LLT ExtLitTy = LitTy.changeElementType(LLT::scalar(8));
1171 auto BigZExt = MIB.buildZExt(ExtBigTy, Src);
1172 auto ExtractZExt = MIB.buildExtractSubvector(ExtLitTy, BigZExt, Idx);
1173 auto SplatZero = MIB.buildSplatVector(
1174 ExtLitTy, MIB.buildConstant(ExtLitTy.getElementType(), 0));
1175 MIB.buildICmp(CmpInst::Predicate::ICMP_NE, Dst, ExtractZExt, SplatZero);
1176 MI.eraseFromParent();
1177 return true;
1178 }
1179
1180 // extract_subvector scales the index by vscale if the subvector is scalable,
1181 // and decomposeSubvectorInsertExtractToSubRegs takes this into account.
1182 const RISCVRegisterInfo *TRI = STI.getRegisterInfo();
1183 MVT LitTyMVT = getMVTForLLT(LitTy);
1184 auto Decompose =
1186 getMVTForLLT(BigTy), LitTyMVT, Idx, TRI);
1187 unsigned RemIdx = Decompose.second;
1188
1189 // If the Idx has been completely eliminated then this is a subvector extract
1190 // which naturally aligns to a vector register. These can easily be handled
1191 // using subregister manipulation.
1192 if (RemIdx == 0)
1193 return true;
1194
1195 // Else LitTy is M1 or smaller and may need to be slid down: if LitTy
1196 // was > M1 then the index would need to be a multiple of VLMAX, and so would
1197 // divide exactly.
1198 assert(
1201
1202 // If the vector type is an LMUL-group type, extract a subvector equal to the
1203 // nearest full vector register type.
1204 LLT InterLitTy = BigTy;
1205 Register Vec = Src;
1207 getLMUL1Ty(BigTy).getSizeInBits())) {
1208 // If BigTy has an LMUL > 1, then LitTy should have a smaller LMUL, and
1209 // we should have successfully decomposed the extract into a subregister.
1210 assert(Decompose.first != RISCV::NoSubRegister);
1211 InterLitTy = getLMUL1Ty(BigTy);
1212 // SDAG builds a TargetExtractSubreg. We cannot create a a Copy with SubReg
1213 // specified on the source Register (the equivalent) since generic virtual
1214 // register does not allow subregister index.
1215 Vec = MIB.buildExtractSubvector(InterLitTy, Src, Idx - RemIdx).getReg(0);
1216 }
1217
1218 // Slide this vector register down by the desired number of elements in order
1219 // to place the desired subvector starting at element 0.
1220 const LLT XLenTy(STI.getXLenVT());
1221 auto SlidedownAmt = MIB.buildVScale(XLenTy, RemIdx);
1222 auto [Mask, VL] = buildDefaultVLOps(InterLitTy, MIB, MRI);
1224 auto Slidedown = MIB.buildInstr(
1225 RISCV::G_VSLIDEDOWN_VL, {InterLitTy},
1226 {MIB.buildUndef(InterLitTy), Vec, SlidedownAmt, Mask, VL, Policy});
1227
1228 // Now the vector is in the right position, extract our final subvector. This
1229 // should resolve to a COPY.
1230 MIB.buildExtractSubvector(Dst, Slidedown, 0);
1231
1232 MI.eraseFromParent();
1233 return true;
1234}
1235
1236bool RISCVLegalizerInfo::legalizeInsertSubvector(MachineInstr &MI,
1237 LegalizerHelper &Helper,
1238 MachineIRBuilder &MIB) const {
1239 GInsertSubvector &IS = cast<GInsertSubvector>(MI);
1240
1241 MachineRegisterInfo &MRI = *MIB.getMRI();
1242
1243 Register Dst = IS.getReg(0);
1244 Register BigVec = IS.getBigVec();
1245 Register LitVec = IS.getSubVec();
1246 uint64_t Idx = IS.getIndexImm();
1247
1248 LLT BigTy = MRI.getType(BigVec);
1249 LLT LitTy = MRI.getType(LitVec);
1250
1251 if (Idx == 0 &&
1252 MRI.getVRegDef(BigVec)->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
1253 return true;
1254
1255 // We don't have the ability to slide mask vectors up indexed by their i1
1256 // elements; the smallest we can do is i8. Often we are able to bitcast to
1257 // equivalent i8 vectors. Otherwise, we can must zeroextend to equivalent i8
1258 // vectors and truncate down after the insert.
1259 if (LitTy.getElementType() == LLT::scalar(1)) {
1260 auto BigTyMinElts = BigTy.getElementCount().getKnownMinValue();
1261 auto LitTyMinElts = LitTy.getElementCount().getKnownMinValue();
1262 if (BigTyMinElts >= 8 && LitTyMinElts >= 8)
1263 return Helper.bitcast(
1264 IS, 0,
1266
1267 // We can't slide this mask vector up indexed by its i1 elements.
1268 // This poses a problem when we wish to insert a scalable vector which
1269 // can't be re-expressed as a larger type. Just choose the slow path and
1270 // extend to a larger type, then truncate back down.
1271 LLT ExtBigTy = BigTy.changeElementType(LLT::scalar(8));
1272 return Helper.widenScalar(IS, 0, ExtBigTy);
1273 }
1274
1275 const RISCVRegisterInfo *TRI = STI.getRegisterInfo();
1276 unsigned SubRegIdx, RemIdx;
1277 std::tie(SubRegIdx, RemIdx) =
1279 getMVTForLLT(BigTy), getMVTForLLT(LitTy), Idx, TRI);
1280
1281 TypeSize VecRegSize = TypeSize::getScalable(RISCV::RVVBitsPerBlock);
1283 STI.expandVScale(LitTy.getSizeInBits()).getKnownMinValue()));
1284 bool ExactlyVecRegSized =
1285 STI.expandVScale(LitTy.getSizeInBits())
1286 .isKnownMultipleOf(STI.expandVScale(VecRegSize));
1287
1288 // If the Idx has been completely eliminated and this subvector's size is a
1289 // vector register or a multiple thereof, or the surrounding elements are
1290 // undef, then this is a subvector insert which naturally aligns to a vector
1291 // register. These can easily be handled using subregister manipulation.
1292 if (RemIdx == 0 && ExactlyVecRegSized)
1293 return true;
1294
1295 // If the subvector is smaller than a vector register, then the insertion
1296 // must preserve the undisturbed elements of the register. We do this by
1297 // lowering to an EXTRACT_SUBVECTOR grabbing the nearest LMUL=1 vector type
1298 // (which resolves to a subregister copy), performing a VSLIDEUP to place the
1299 // subvector within the vector register, and an INSERT_SUBVECTOR of that
1300 // LMUL=1 type back into the larger vector (resolving to another subregister
1301 // operation). See below for how our VSLIDEUP works. We go via a LMUL=1 type
1302 // to avoid allocating a large register group to hold our subvector.
1303
1304 // VSLIDEUP works by leaving elements 0<i<OFFSET undisturbed, elements
1305 // OFFSET<=i<VL set to the "subvector" and vl<=i<VLMAX set to the tail policy
1306 // (in our case undisturbed). This means we can set up a subvector insertion
1307 // where OFFSET is the insertion offset, and the VL is the OFFSET plus the
1308 // size of the subvector.
1309 const LLT XLenTy(STI.getXLenVT());
1310 LLT InterLitTy = BigTy;
1311 Register AlignedExtract = BigVec;
1312 unsigned AlignedIdx = Idx - RemIdx;
1314 getLMUL1Ty(BigTy).getSizeInBits())) {
1315 InterLitTy = getLMUL1Ty(BigTy);
1316 // Extract a subvector equal to the nearest full vector register type. This
1317 // should resolve to a G_EXTRACT on a subreg.
1318 AlignedExtract =
1319 MIB.buildExtractSubvector(InterLitTy, BigVec, AlignedIdx).getReg(0);
1320 }
1321
1322 auto Insert = MIB.buildInsertSubvector(InterLitTy, MIB.buildUndef(InterLitTy),
1323 LitVec, 0);
1324
1325 auto [Mask, _] = buildDefaultVLOps(InterLitTy, MIB, MRI);
1326 auto VL = MIB.buildVScale(XLenTy, LitTy.getElementCount().getKnownMinValue());
1327
1328 // If we're inserting into the lowest elements, use a tail undisturbed
1329 // vmv.v.v.
1330 MachineInstrBuilder Inserted;
1331 bool NeedInsertSubvec =
1332 TypeSize::isKnownGT(BigTy.getSizeInBits(), InterLitTy.getSizeInBits());
1333 Register InsertedDst =
1334 NeedInsertSubvec ? MRI.createGenericVirtualRegister(InterLitTy) : Dst;
1335 if (RemIdx == 0) {
1336 Inserted = MIB.buildInstr(RISCV::G_VMV_V_V_VL, {InsertedDst},
1337 {AlignedExtract, Insert, VL});
1338 } else {
1339 auto SlideupAmt = MIB.buildVScale(XLenTy, RemIdx);
1340 // Construct the vector length corresponding to RemIdx + length(LitTy).
1341 VL = MIB.buildAdd(XLenTy, SlideupAmt, VL);
1342 // Use tail agnostic policy if we're inserting over InterLitTy's tail.
1343 ElementCount EndIndex =
1346 if (STI.expandVScale(EndIndex) ==
1347 STI.expandVScale(InterLitTy.getElementCount()))
1349
1350 Inserted =
1351 MIB.buildInstr(RISCV::G_VSLIDEUP_VL, {InsertedDst},
1352 {AlignedExtract, Insert, SlideupAmt, Mask, VL, Policy});
1353 }
1354
1355 // If required, insert this subvector back into the correct vector register.
1356 // This should resolve to an INSERT_SUBREG instruction.
1357 if (NeedInsertSubvec)
1358 MIB.buildInsertSubvector(Dst, BigVec, Inserted, AlignedIdx);
1359
1360 MI.eraseFromParent();
1361 return true;
1362}
1363
1364static unsigned getRISCVWOpcode(unsigned Opcode) {
1365 switch (Opcode) {
1366 default:
1367 llvm_unreachable("Unexpected opcode");
1368 case TargetOpcode::G_ASHR:
1369 return RISCV::G_SRAW;
1370 case TargetOpcode::G_LSHR:
1371 return RISCV::G_SRLW;
1372 case TargetOpcode::G_SHL:
1373 return RISCV::G_SLLW;
1374 case TargetOpcode::G_SDIV:
1375 return RISCV::G_DIVW;
1376 case TargetOpcode::G_UDIV:
1377 return RISCV::G_DIVUW;
1378 case TargetOpcode::G_UREM:
1379 return RISCV::G_REMUW;
1380 case TargetOpcode::G_ROTL:
1381 return RISCV::G_ROLW;
1382 case TargetOpcode::G_ROTR:
1383 return RISCV::G_RORW;
1384 case TargetOpcode::G_CTLZ:
1385 return RISCV::G_CLZW;
1386 case TargetOpcode::G_CTTZ:
1387 return RISCV::G_CTZW;
1388 case TargetOpcode::G_FPTOSI:
1389 return RISCV::G_FCVT_W_RV64;
1390 case TargetOpcode::G_FPTOUI:
1391 return RISCV::G_FCVT_WU_RV64;
1392 }
1393}
1394
1397 LostDebugLocObserver &LocObserver) const {
1398 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
1399 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
1400 MachineFunction &MF = *MI.getParent()->getParent();
1401 switch (MI.getOpcode()) {
1402 default:
1403 // No idea what to do.
1404 return false;
1405 case TargetOpcode::G_ABS:
1406 return Helper.lowerAbsToMaxNeg(MI);
1407 case TargetOpcode::G_FCONSTANT: {
1408 const APFloat &FVal = MI.getOperand(1).getFPImm()->getValueAPF();
1409
1410 // Convert G_FCONSTANT to G_CONSTANT.
1411 Register DstReg = MI.getOperand(0).getReg();
1412 MIRBuilder.buildConstant(DstReg, FVal.bitcastToAPInt());
1413
1414 MI.eraseFromParent();
1415 return true;
1416 }
1417 case TargetOpcode::G_CONSTANT: {
1418 const Function &F = MF.getFunction();
1419 // TODO: if PSI and BFI are present, add " ||
1420 // llvm::shouldOptForSize(*CurMBB, PSI, BFI)".
1421 bool ShouldOptForSize = F.hasOptSize();
1422 const ConstantInt *ConstVal = MI.getOperand(1).getCImm();
1423 if (!shouldBeInConstantPool(ConstVal->getValue(), ShouldOptForSize))
1424 return true;
1425 return Helper.lowerConstant(MI);
1426 }
1427 case TargetOpcode::G_SUB:
1428 case TargetOpcode::G_ADD: {
1429 Helper.Observer.changingInstr(MI);
1430 Helper.widenScalarSrc(MI, sXLen, 1, TargetOpcode::G_ANYEXT);
1431 Helper.widenScalarSrc(MI, sXLen, 2, TargetOpcode::G_ANYEXT);
1432
1433 Register DstALU = MRI.createGenericVirtualRegister(sXLen);
1434
1435 MachineOperand &MO = MI.getOperand(0);
1436 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
1437 auto DstSext = MIRBuilder.buildSExtInReg(sXLen, DstALU, 32);
1438
1439 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {MO}, {DstSext});
1440 MO.setReg(DstALU);
1441
1442 Helper.Observer.changedInstr(MI);
1443 return true;
1444 }
1445 case TargetOpcode::G_SEXT_INREG: {
1446 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
1447 int64_t SizeInBits = MI.getOperand(2).getImm();
1448 // Source size of 32 is sext.w.
1449 if (DstTy.getSizeInBits() == 64 && SizeInBits == 32)
1450 return true;
1451
1452 if (STI.hasStdExtZbb() && (SizeInBits == 8 || SizeInBits == 16))
1453 return true;
1454
1455 return Helper.lower(MI, 0, /* Unused hint type */ LLT()) ==
1457 }
1458 case TargetOpcode::G_ASHR:
1459 case TargetOpcode::G_LSHR:
1460 case TargetOpcode::G_SHL: {
1461 if (getIConstantVRegValWithLookThrough(MI.getOperand(2).getReg(), MRI)) {
1462 // We don't need a custom node for shift by constant. Just widen the
1463 // source and the shift amount.
1464 unsigned ExtOpc = TargetOpcode::G_ANYEXT;
1465 if (MI.getOpcode() == TargetOpcode::G_ASHR)
1466 ExtOpc = TargetOpcode::G_SEXT;
1467 else if (MI.getOpcode() == TargetOpcode::G_LSHR)
1468 ExtOpc = TargetOpcode::G_ZEXT;
1469
1470 Helper.Observer.changingInstr(MI);
1471 Helper.widenScalarSrc(MI, sXLen, 1, ExtOpc);
1472 Helper.widenScalarSrc(MI, sXLen, 2, TargetOpcode::G_ZEXT);
1473 Helper.widenScalarDst(MI, sXLen);
1474 Helper.Observer.changedInstr(MI);
1475 return true;
1476 }
1477
1478 Helper.Observer.changingInstr(MI);
1479 Helper.widenScalarSrc(MI, sXLen, 1, TargetOpcode::G_ANYEXT);
1480 Helper.widenScalarSrc(MI, sXLen, 2, TargetOpcode::G_ANYEXT);
1481 Helper.widenScalarDst(MI, sXLen);
1482 MI.setDesc(MIRBuilder.getTII().get(getRISCVWOpcode(MI.getOpcode())));
1483 Helper.Observer.changedInstr(MI);
1484 return true;
1485 }
1486 case TargetOpcode::G_SDIV:
1487 case TargetOpcode::G_UDIV:
1488 case TargetOpcode::G_UREM:
1489 case TargetOpcode::G_ROTL:
1490 case TargetOpcode::G_ROTR: {
1491 Helper.Observer.changingInstr(MI);
1492 Helper.widenScalarSrc(MI, sXLen, 1, TargetOpcode::G_ANYEXT);
1493 Helper.widenScalarSrc(MI, sXLen, 2, TargetOpcode::G_ANYEXT);
1494 Helper.widenScalarDst(MI, sXLen);
1495 MI.setDesc(MIRBuilder.getTII().get(getRISCVWOpcode(MI.getOpcode())));
1496 Helper.Observer.changedInstr(MI);
1497 return true;
1498 }
1499 case TargetOpcode::G_CTLZ:
1500 case TargetOpcode::G_CTTZ: {
1501 Helper.Observer.changingInstr(MI);
1502 Helper.widenScalarSrc(MI, sXLen, 1, TargetOpcode::G_ANYEXT);
1503 Helper.widenScalarDst(MI, sXLen);
1504 MI.setDesc(MIRBuilder.getTII().get(getRISCVWOpcode(MI.getOpcode())));
1505 Helper.Observer.changedInstr(MI);
1506 return true;
1507 }
1508 case TargetOpcode::G_FPTOSI:
1509 case TargetOpcode::G_FPTOUI: {
1510 Helper.Observer.changingInstr(MI);
1511 Helper.widenScalarDst(MI, sXLen);
1512 MI.setDesc(MIRBuilder.getTII().get(getRISCVWOpcode(MI.getOpcode())));
1514 Helper.Observer.changedInstr(MI);
1515 return true;
1516 }
1517 case TargetOpcode::G_IS_FPCLASS: {
1518 Register GISFPCLASS = MI.getOperand(0).getReg();
1519 Register Src = MI.getOperand(1).getReg();
1520 const MachineOperand &ImmOp = MI.getOperand(2);
1521 MachineIRBuilder MIB(MI);
1522
1523 // Turn LLVM IR's floating point classes to that in RISC-V,
1524 // by simply rotating the 10-bit immediate right by two bits.
1525 APInt GFpClassImm(10, static_cast<uint64_t>(ImmOp.getImm()));
1526 auto FClassMask = MIB.buildConstant(sXLen, GFpClassImm.rotr(2).zext(XLen));
1527 auto ConstZero = MIB.buildConstant(sXLen, 0);
1528
1529 auto GFClass = MIB.buildInstr(RISCV::G_FCLASS, {sXLen}, {Src});
1530 auto And = MIB.buildAnd(sXLen, GFClass, FClassMask);
1531 MIB.buildICmp(CmpInst::ICMP_NE, GISFPCLASS, And, ConstZero);
1532
1533 MI.eraseFromParent();
1534 return true;
1535 }
1536 case TargetOpcode::G_BRJT:
1537 return legalizeBRJT(MI, MIRBuilder);
1538 case TargetOpcode::G_VASTART:
1539 return legalizeVAStart(MI, MIRBuilder);
1540 case TargetOpcode::G_VSCALE:
1541 return legalizeVScale(MI, MIRBuilder);
1542 case TargetOpcode::G_ZEXT:
1543 case TargetOpcode::G_SEXT:
1544 case TargetOpcode::G_ANYEXT:
1545 return legalizeExt(MI, MIRBuilder);
1546 case TargetOpcode::G_SPLAT_VECTOR:
1547 return legalizeSplatVector(MI, MIRBuilder);
1548 case TargetOpcode::G_EXTRACT_SUBVECTOR:
1549 return legalizeExtractSubvector(MI, MIRBuilder);
1550 case TargetOpcode::G_INSERT_SUBVECTOR:
1551 return legalizeInsertSubvector(MI, Helper, MIRBuilder);
1552 case TargetOpcode::G_LOAD:
1553 case TargetOpcode::G_STORE:
1554 return legalizeLoadStore(MI, Helper, MIRBuilder);
1555 }
1556
1557 llvm_unreachable("expected switch to return");
1558}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
#define _
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
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 IntrinsicInst * II
#define P(N)
ppc ctr loops verify
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.
Value * LHS
APInt bitcastToAPInt() const
Definition APFloat.h:1335
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:1012
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1489
LLVM_ABI APInt rotr(unsigned rotateAmt) const
Rotate right by rotateAmt.
Definition APInt.cpp:1154
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1563
@ ICMP_NE
not equal
Definition InstrTypes.h:698
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:312
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:359
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.
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
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 LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
constexpr ElementCount getElementCount() const
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
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 & 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.
@ Legalized
Instruction has been legalized and the MachineFunction changed.
LLVM_ABI LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by splitting it into simpler parts, hopefully understood by the target.
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:90
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
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.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
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 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.
const MachineBasicBlock & getMBB() const
Getter for the basic block we currently build.
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 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.
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,...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
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:346
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:223
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:252
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
LLVM_ABI LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
Predicate any(Predicate P0, Predicate P1)
True iff P0 or P1 are true.
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 LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty)
Select this specific type for the given type index.
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.
Definition Types.h:26
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
Definition Utils.cpp:2041
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
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:1613
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:284
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:1595
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:337
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:331
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:279
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:434
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition Alignment.h:197
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.