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