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