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