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