1 //===- llvm/CodeGen/GlobalISel/LegalizerInfo.h ------------------*- 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 //
9 /// Interface for Targets to specify which operations they can successfully
10 /// select and how the others should be expanded most efficiently.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
15 #define LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
16
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/None.h"
19 #include "llvm/ADT/Optional.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/SmallBitVector.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/CodeGen/MachineFunction.h"
24 #include "llvm/CodeGen/TargetOpcodes.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Support/LowLevelTypeImpl.h"
27 #include "llvm/Support/raw_ostream.h"
28 #include <cassert>
29 #include <cstdint>
30 #include <tuple>
31 #include <unordered_map>
32 #include <utility>
33
34 namespace llvm {
35
36 extern cl::opt<bool> DisableGISelLegalityCheck;
37
38 class LegalizerHelper;
39 class MachineInstr;
40 class MachineIRBuilder;
41 class MachineRegisterInfo;
42 class MCInstrInfo;
43 class GISelChangeObserver;
44
45 namespace LegalizeActions {
46 enum LegalizeAction : std::uint8_t {
47 /// The operation is expected to be selectable directly by the target, and
48 /// no transformation is necessary.
49 Legal,
50
51 /// The operation should be synthesized from multiple instructions acting on
52 /// a narrower scalar base-type. For example a 64-bit add might be
53 /// implemented in terms of 32-bit add-with-carry.
54 NarrowScalar,
55
56 /// The operation should be implemented in terms of a wider scalar
57 /// base-type. For example a <2 x s8> add could be implemented as a <2
58 /// x s32> add (ignoring the high bits).
59 WidenScalar,
60
61 /// The (vector) operation should be implemented by splitting it into
62 /// sub-vectors where the operation is legal. For example a <8 x s64> add
63 /// might be implemented as 4 separate <2 x s64> adds.
64 FewerElements,
65
66 /// The (vector) operation should be implemented by widening the input
67 /// vector and ignoring the lanes added by doing so. For example <2 x i8> is
68 /// rarely legal, but you might perform an <8 x i8> and then only look at
69 /// the first two results.
70 MoreElements,
71
72 /// Perform the operation on a different, but equivalently sized type.
73 Bitcast,
74
75 /// The operation itself must be expressed in terms of simpler actions on
76 /// this target. E.g. a SREM replaced by an SDIV and subtraction.
77 Lower,
78
79 /// The operation should be implemented as a call to some kind of runtime
80 /// support library. For example this usually happens on machines that don't
81 /// support floating-point operations natively.
82 Libcall,
83
84 /// The target wants to do something special with this combination of
85 /// operand and type. A callback will be issued when it is needed.
86 Custom,
87
88 /// This operation is completely unsupported on the target. A programming
89 /// error has occurred.
90 Unsupported,
91
92 /// Sentinel value for when no action was found in the specified table.
93 NotFound,
94
95 /// Fall back onto the old rules.
96 /// TODO: Remove this once we've migrated
97 UseLegacyRules,
98 };
99 } // end namespace LegalizeActions
100 raw_ostream &operator<<(raw_ostream &OS, LegalizeActions::LegalizeAction Action);
101
102 using LegalizeActions::LegalizeAction;
103
104 /// Legalization is decided based on an instruction's opcode, which type slot
105 /// we're considering, and what the existing type is. These aspects are gathered
106 /// together for convenience in the InstrAspect class.
107 struct InstrAspect {
108 unsigned Opcode;
109 unsigned Idx = 0;
110 LLT Type;
111
InstrAspectInstrAspect112 InstrAspect(unsigned Opcode, LLT Type) : Opcode(Opcode), Type(Type) {}
InstrAspectInstrAspect113 InstrAspect(unsigned Opcode, unsigned Idx, LLT Type)
114 : Opcode(Opcode), Idx(Idx), Type(Type) {}
115
116 bool operator==(const InstrAspect &RHS) const {
117 return Opcode == RHS.Opcode && Idx == RHS.Idx && Type == RHS.Type;
118 }
119 };
120
121 /// The LegalityQuery object bundles together all the information that's needed
122 /// to decide whether a given operation is legal or not.
123 /// For efficiency, it doesn't make a copy of Types so care must be taken not
124 /// to free it before using the query.
125 struct LegalityQuery {
126 unsigned Opcode;
127 ArrayRef<LLT> Types;
128
129 struct MemDesc {
130 uint64_t SizeInBits;
131 uint64_t AlignInBits;
132 AtomicOrdering Ordering;
133 };
134
135 /// Operations which require memory can use this to place requirements on the
136 /// memory type for each MMO.
137 ArrayRef<MemDesc> MMODescrs;
138
LegalityQueryLegalityQuery139 constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types,
140 const ArrayRef<MemDesc> MMODescrs)
141 : Opcode(Opcode), Types(Types), MMODescrs(MMODescrs) {}
LegalityQueryLegalityQuery142 constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types)
143 : LegalityQuery(Opcode, Types, {}) {}
144
145 raw_ostream &print(raw_ostream &OS) const;
146 };
147
148 /// The result of a query. It either indicates a final answer of Legal or
149 /// Unsupported or describes an action that must be taken to make an operation
150 /// more legal.
151 struct LegalizeActionStep {
152 /// The action to take or the final answer.
153 LegalizeAction Action;
154 /// If describing an action, the type index to change. Otherwise zero.
155 unsigned TypeIdx;
156 /// If describing an action, the new type for TypeIdx. Otherwise LLT{}.
157 LLT NewType;
158
LegalizeActionStepLegalizeActionStep159 LegalizeActionStep(LegalizeAction Action, unsigned TypeIdx,
160 const LLT NewType)
161 : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {}
162
163 bool operator==(const LegalizeActionStep &RHS) const {
164 return std::tie(Action, TypeIdx, NewType) ==
165 std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType);
166 }
167 };
168
169 using LegalityPredicate = std::function<bool (const LegalityQuery &)>;
170 using LegalizeMutation =
171 std::function<std::pair<unsigned, LLT>(const LegalityQuery &)>;
172
173 namespace LegalityPredicates {
174 struct TypePairAndMemDesc {
175 LLT Type0;
176 LLT Type1;
177 uint64_t MemSize;
178 uint64_t Align;
179
180 bool operator==(const TypePairAndMemDesc &Other) const {
181 return Type0 == Other.Type0 && Type1 == Other.Type1 &&
182 Align == Other.Align &&
183 MemSize == Other.MemSize;
184 }
185
186 /// \returns true if this memory access is legal with for the access described
187 /// by \p Other (The alignment is sufficient for the size and result type).
isCompatibleTypePairAndMemDesc188 bool isCompatible(const TypePairAndMemDesc &Other) const {
189 return Type0 == Other.Type0 && Type1 == Other.Type1 &&
190 Align >= Other.Align &&
191 MemSize == Other.MemSize;
192 }
193 };
194
195 /// True iff P0 and P1 are true.
196 template<typename Predicate>
all(Predicate P0,Predicate P1)197 Predicate all(Predicate P0, Predicate P1) {
198 return [=](const LegalityQuery &Query) {
199 return P0(Query) && P1(Query);
200 };
201 }
202 /// True iff all given predicates are true.
203 template<typename Predicate, typename... Args>
all(Predicate P0,Predicate P1,Args...args)204 Predicate all(Predicate P0, Predicate P1, Args... args) {
205 return all(all(P0, P1), args...);
206 }
207
208 /// True iff P0 or P1 are true.
209 template<typename Predicate>
any(Predicate P0,Predicate P1)210 Predicate any(Predicate P0, Predicate P1) {
211 return [=](const LegalityQuery &Query) {
212 return P0(Query) || P1(Query);
213 };
214 }
215 /// True iff any given predicates are true.
216 template<typename Predicate, typename... Args>
any(Predicate P0,Predicate P1,Args...args)217 Predicate any(Predicate P0, Predicate P1, Args... args) {
218 return any(any(P0, P1), args...);
219 }
220
221 /// True iff the given type index is the specified type.
222 LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit);
223 /// True iff the given type index is one of the specified types.
224 LegalityPredicate typeInSet(unsigned TypeIdx,
225 std::initializer_list<LLT> TypesInit);
226
227 /// True iff the given type index is not the specified type.
typeIsNot(unsigned TypeIdx,LLT Type)228 inline LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type) {
229 return [=](const LegalityQuery &Query) {
230 return Query.Types[TypeIdx] != Type;
231 };
232 }
233
234 /// True iff the given types for the given pair of type indexes is one of the
235 /// specified type pairs.
236 LegalityPredicate
237 typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1,
238 std::initializer_list<std::pair<LLT, LLT>> TypesInit);
239 /// True iff the given types for the given pair of type indexes is one of the
240 /// specified type pairs.
241 LegalityPredicate typePairAndMemDescInSet(
242 unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx,
243 std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit);
244 /// True iff the specified type index is a scalar.
245 LegalityPredicate isScalar(unsigned TypeIdx);
246 /// True iff the specified type index is a vector.
247 LegalityPredicate isVector(unsigned TypeIdx);
248 /// True iff the specified type index is a pointer (with any address space).
249 LegalityPredicate isPointer(unsigned TypeIdx);
250 /// True iff the specified type index is a pointer with the specified address
251 /// space.
252 LegalityPredicate isPointer(unsigned TypeIdx, unsigned AddrSpace);
253
254 /// True if the type index is a vector with element type \p EltTy
255 LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT EltTy);
256
257 /// True iff the specified type index is a scalar that's narrower than the given
258 /// size.
259 LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size);
260
261 /// True iff the specified type index is a scalar that's wider than the given
262 /// size.
263 LegalityPredicate scalarWiderThan(unsigned TypeIdx, unsigned Size);
264
265 /// True iff the specified type index is a scalar or vector with an element type
266 /// that's narrower than the given size.
267 LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size);
268
269 /// True iff the specified type index is a scalar or a vector with an element
270 /// type that's wider than the given size.
271 LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size);
272
273 /// True iff the specified type index is a scalar whose size is not a power of
274 /// 2.
275 LegalityPredicate sizeNotPow2(unsigned TypeIdx);
276
277 /// True iff the specified type index is a scalar or vector whose element size
278 /// is not a power of 2.
279 LegalityPredicate scalarOrEltSizeNotPow2(unsigned TypeIdx);
280
281 /// True if the total bitwidth of the specified type index is \p Size bits.
282 LegalityPredicate sizeIs(unsigned TypeIdx, unsigned Size);
283
284 /// True iff the specified type indices are both the same bit size.
285 LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1);
286
287 /// True iff the first type index has a larger total bit size than second type
288 /// index.
289 LegalityPredicate largerThan(unsigned TypeIdx0, unsigned TypeIdx1);
290
291 /// True iff the first type index has a smaller total bit size than second type
292 /// index.
293 LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1);
294
295 /// True iff the specified MMO index has a size that is not a power of 2
296 LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx);
297 /// True iff the specified type index is a vector whose element count is not a
298 /// power of 2.
299 LegalityPredicate numElementsNotPow2(unsigned TypeIdx);
300 /// True iff the specified MMO index has at an atomic ordering of at Ordering or
301 /// stronger.
302 LegalityPredicate atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx,
303 AtomicOrdering Ordering);
304 } // end namespace LegalityPredicates
305
306 namespace LegalizeMutations {
307 /// Select this specific type for the given type index.
308 LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty);
309
310 /// Keep the same type as the given type index.
311 LegalizeMutation changeTo(unsigned TypeIdx, unsigned FromTypeIdx);
312
313 /// Keep the same scalar or element type as the given type index.
314 LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx);
315
316 /// Keep the same scalar or element type as the given type.
317 LegalizeMutation changeElementTo(unsigned TypeIdx, LLT Ty);
318
319 /// Change the scalar size or element size to have the same scalar size as type
320 /// index \p FromIndex. Unlike changeElementTo, this discards pointer types and
321 /// only changes the size.
322 LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx);
323
324 /// Widen the scalar type or vector element type for the given type index to the
325 /// next power of 2.
326 LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min = 0);
327
328 /// Add more elements to the type for the given type index to the next power of
329 /// 2.
330 LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min = 0);
331 /// Break up the vector type for the given type index into the element type.
332 LegalizeMutation scalarize(unsigned TypeIdx);
333 } // end namespace LegalizeMutations
334
335 /// A single rule in a legalizer info ruleset.
336 /// The specified action is chosen when the predicate is true. Where appropriate
337 /// for the action (e.g. for WidenScalar) the new type is selected using the
338 /// given mutator.
339 class LegalizeRule {
340 LegalityPredicate Predicate;
341 LegalizeAction Action;
342 LegalizeMutation Mutation;
343
344 public:
345 LegalizeRule(LegalityPredicate Predicate, LegalizeAction Action,
346 LegalizeMutation Mutation = nullptr)
Predicate(Predicate)347 : Predicate(Predicate), Action(Action), Mutation(Mutation) {}
348
349 /// Test whether the LegalityQuery matches.
match(const LegalityQuery & Query)350 bool match(const LegalityQuery &Query) const {
351 return Predicate(Query);
352 }
353
getAction()354 LegalizeAction getAction() const { return Action; }
355
356 /// Determine the change to make.
determineMutation(const LegalityQuery & Query)357 std::pair<unsigned, LLT> determineMutation(const LegalityQuery &Query) const {
358 if (Mutation)
359 return Mutation(Query);
360 return std::make_pair(0, LLT{});
361 }
362 };
363
364 class LegalizeRuleSet {
365 /// When non-zero, the opcode we are an alias of
366 unsigned AliasOf;
367 /// If true, there is another opcode that aliases this one
368 bool IsAliasedByAnother;
369 SmallVector<LegalizeRule, 2> Rules;
370
371 #ifndef NDEBUG
372 /// If bit I is set, this rule set contains a rule that may handle (predicate
373 /// or perform an action upon (or both)) the type index I. The uncertainty
374 /// comes from free-form rules executing user-provided lambda functions. We
375 /// conservatively assume such rules do the right thing and cover all type
376 /// indices. The bitset is intentionally 1 bit wider than it absolutely needs
377 /// to be to distinguish such cases from the cases where all type indices are
378 /// individually handled.
379 SmallBitVector TypeIdxsCovered{MCOI::OPERAND_LAST_GENERIC -
380 MCOI::OPERAND_FIRST_GENERIC + 2};
381 SmallBitVector ImmIdxsCovered{MCOI::OPERAND_LAST_GENERIC_IMM -
382 MCOI::OPERAND_FIRST_GENERIC_IMM + 2};
383 #endif
384
typeIdx(unsigned TypeIdx)385 unsigned typeIdx(unsigned TypeIdx) {
386 assert(TypeIdx <=
387 (MCOI::OPERAND_LAST_GENERIC - MCOI::OPERAND_FIRST_GENERIC) &&
388 "Type Index is out of bounds");
389 #ifndef NDEBUG
390 TypeIdxsCovered.set(TypeIdx);
391 #endif
392 return TypeIdx;
393 }
394
immIdx(unsigned ImmIdx)395 unsigned immIdx(unsigned ImmIdx) {
396 assert(ImmIdx <= (MCOI::OPERAND_LAST_GENERIC_IMM -
397 MCOI::OPERAND_FIRST_GENERIC_IMM) &&
398 "Imm Index is out of bounds");
399 #ifndef NDEBUG
400 ImmIdxsCovered.set(ImmIdx);
401 #endif
402 return ImmIdx;
403 }
404
markAllIdxsAsCovered()405 void markAllIdxsAsCovered() {
406 #ifndef NDEBUG
407 TypeIdxsCovered.set();
408 ImmIdxsCovered.set();
409 #endif
410 }
411
add(const LegalizeRule & Rule)412 void add(const LegalizeRule &Rule) {
413 assert(AliasOf == 0 &&
414 "RuleSet is aliased, change the representative opcode instead");
415 Rules.push_back(Rule);
416 }
417
always(const LegalityQuery &)418 static bool always(const LegalityQuery &) { return true; }
419
420 /// Use the given action when the predicate is true.
421 /// Action should not be an action that requires mutation.
actionIf(LegalizeAction Action,LegalityPredicate Predicate)422 LegalizeRuleSet &actionIf(LegalizeAction Action,
423 LegalityPredicate Predicate) {
424 add({Predicate, Action});
425 return *this;
426 }
427 /// Use the given action when the predicate is true.
428 /// Action should be an action that requires mutation.
actionIf(LegalizeAction Action,LegalityPredicate Predicate,LegalizeMutation Mutation)429 LegalizeRuleSet &actionIf(LegalizeAction Action, LegalityPredicate Predicate,
430 LegalizeMutation Mutation) {
431 add({Predicate, Action, Mutation});
432 return *this;
433 }
434 /// Use the given action when type index 0 is any type in the given list.
435 /// Action should not be an action that requires mutation.
actionFor(LegalizeAction Action,std::initializer_list<LLT> Types)436 LegalizeRuleSet &actionFor(LegalizeAction Action,
437 std::initializer_list<LLT> Types) {
438 using namespace LegalityPredicates;
439 return actionIf(Action, typeInSet(typeIdx(0), Types));
440 }
441 /// Use the given action when type index 0 is any type in the given list.
442 /// Action should be an action that requires mutation.
actionFor(LegalizeAction Action,std::initializer_list<LLT> Types,LegalizeMutation Mutation)443 LegalizeRuleSet &actionFor(LegalizeAction Action,
444 std::initializer_list<LLT> Types,
445 LegalizeMutation Mutation) {
446 using namespace LegalityPredicates;
447 return actionIf(Action, typeInSet(typeIdx(0), Types), Mutation);
448 }
449 /// Use the given action when type indexes 0 and 1 is any type pair in the
450 /// given list.
451 /// Action should not be an action that requires mutation.
actionFor(LegalizeAction Action,std::initializer_list<std::pair<LLT,LLT>> Types)452 LegalizeRuleSet &actionFor(LegalizeAction Action,
453 std::initializer_list<std::pair<LLT, LLT>> Types) {
454 using namespace LegalityPredicates;
455 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types));
456 }
457 /// Use the given action when type indexes 0 and 1 is any type pair in the
458 /// given list.
459 /// Action should be an action that requires mutation.
actionFor(LegalizeAction Action,std::initializer_list<std::pair<LLT,LLT>> Types,LegalizeMutation Mutation)460 LegalizeRuleSet &actionFor(LegalizeAction Action,
461 std::initializer_list<std::pair<LLT, LLT>> Types,
462 LegalizeMutation Mutation) {
463 using namespace LegalityPredicates;
464 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types),
465 Mutation);
466 }
467 /// Use the given action when type index 0 is any type in the given list and
468 /// imm index 0 is anything. Action should not be an action that requires
469 /// mutation.
actionForTypeWithAnyImm(LegalizeAction Action,std::initializer_list<LLT> Types)470 LegalizeRuleSet &actionForTypeWithAnyImm(LegalizeAction Action,
471 std::initializer_list<LLT> Types) {
472 using namespace LegalityPredicates;
473 immIdx(0); // Inform verifier imm idx 0 is handled.
474 return actionIf(Action, typeInSet(typeIdx(0), Types));
475 }
476
actionForTypeWithAnyImm(LegalizeAction Action,std::initializer_list<std::pair<LLT,LLT>> Types)477 LegalizeRuleSet &actionForTypeWithAnyImm(
478 LegalizeAction Action, std::initializer_list<std::pair<LLT, LLT>> Types) {
479 using namespace LegalityPredicates;
480 immIdx(0); // Inform verifier imm idx 0 is handled.
481 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types));
482 }
483
484 /// Use the given action when type indexes 0 and 1 are both in the given list.
485 /// That is, the type pair is in the cartesian product of the list.
486 /// Action should not be an action that requires mutation.
actionForCartesianProduct(LegalizeAction Action,std::initializer_list<LLT> Types)487 LegalizeRuleSet &actionForCartesianProduct(LegalizeAction Action,
488 std::initializer_list<LLT> Types) {
489 using namespace LegalityPredicates;
490 return actionIf(Action, all(typeInSet(typeIdx(0), Types),
491 typeInSet(typeIdx(1), Types)));
492 }
493 /// Use the given action when type indexes 0 and 1 are both in their
494 /// respective lists.
495 /// That is, the type pair is in the cartesian product of the lists
496 /// Action should not be an action that requires mutation.
497 LegalizeRuleSet &
actionForCartesianProduct(LegalizeAction Action,std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1)498 actionForCartesianProduct(LegalizeAction Action,
499 std::initializer_list<LLT> Types0,
500 std::initializer_list<LLT> Types1) {
501 using namespace LegalityPredicates;
502 return actionIf(Action, all(typeInSet(typeIdx(0), Types0),
503 typeInSet(typeIdx(1), Types1)));
504 }
505 /// Use the given action when type indexes 0, 1, and 2 are all in their
506 /// respective lists.
507 /// That is, the type triple is in the cartesian product of the lists
508 /// Action should not be an action that requires mutation.
actionForCartesianProduct(LegalizeAction Action,std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1,std::initializer_list<LLT> Types2)509 LegalizeRuleSet &actionForCartesianProduct(
510 LegalizeAction Action, std::initializer_list<LLT> Types0,
511 std::initializer_list<LLT> Types1, std::initializer_list<LLT> Types2) {
512 using namespace LegalityPredicates;
513 return actionIf(Action, all(typeInSet(typeIdx(0), Types0),
514 all(typeInSet(typeIdx(1), Types1),
515 typeInSet(typeIdx(2), Types2))));
516 }
517
518 public:
LegalizeRuleSet()519 LegalizeRuleSet() : AliasOf(0), IsAliasedByAnother(false), Rules() {}
520
isAliasedByAnother()521 bool isAliasedByAnother() { return IsAliasedByAnother; }
setIsAliasedByAnother()522 void setIsAliasedByAnother() { IsAliasedByAnother = true; }
aliasTo(unsigned Opcode)523 void aliasTo(unsigned Opcode) {
524 assert((AliasOf == 0 || AliasOf == Opcode) &&
525 "Opcode is already aliased to another opcode");
526 assert(Rules.empty() && "Aliasing will discard rules");
527 AliasOf = Opcode;
528 }
getAlias()529 unsigned getAlias() const { return AliasOf; }
530
531 /// The instruction is legal if predicate is true.
legalIf(LegalityPredicate Predicate)532 LegalizeRuleSet &legalIf(LegalityPredicate Predicate) {
533 // We have no choice but conservatively assume that the free-form
534 // user-provided Predicate properly handles all type indices:
535 markAllIdxsAsCovered();
536 return actionIf(LegalizeAction::Legal, Predicate);
537 }
538 /// The instruction is legal when type index 0 is any type in the given list.
legalFor(std::initializer_list<LLT> Types)539 LegalizeRuleSet &legalFor(std::initializer_list<LLT> Types) {
540 return actionFor(LegalizeAction::Legal, Types);
541 }
542 /// The instruction is legal when type indexes 0 and 1 is any type pair in the
543 /// given list.
legalFor(std::initializer_list<std::pair<LLT,LLT>> Types)544 LegalizeRuleSet &legalFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
545 return actionFor(LegalizeAction::Legal, Types);
546 }
547 /// The instruction is legal when type index 0 is any type in the given list
548 /// and imm index 0 is anything.
legalForTypeWithAnyImm(std::initializer_list<LLT> Types)549 LegalizeRuleSet &legalForTypeWithAnyImm(std::initializer_list<LLT> Types) {
550 markAllIdxsAsCovered();
551 return actionForTypeWithAnyImm(LegalizeAction::Legal, Types);
552 }
553
legalForTypeWithAnyImm(std::initializer_list<std::pair<LLT,LLT>> Types)554 LegalizeRuleSet &legalForTypeWithAnyImm(
555 std::initializer_list<std::pair<LLT, LLT>> Types) {
556 markAllIdxsAsCovered();
557 return actionForTypeWithAnyImm(LegalizeAction::Legal, Types);
558 }
559
560 /// The instruction is legal when type indexes 0 and 1 along with the memory
561 /// size and minimum alignment is any type and size tuple in the given list.
legalForTypesWithMemDesc(std::initializer_list<LegalityPredicates::TypePairAndMemDesc> TypesAndMemDesc)562 LegalizeRuleSet &legalForTypesWithMemDesc(
563 std::initializer_list<LegalityPredicates::TypePairAndMemDesc>
564 TypesAndMemDesc) {
565 return actionIf(LegalizeAction::Legal,
566 LegalityPredicates::typePairAndMemDescInSet(
567 typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemDesc));
568 }
569 /// The instruction is legal when type indexes 0 and 1 are both in the given
570 /// list. That is, the type pair is in the cartesian product of the list.
legalForCartesianProduct(std::initializer_list<LLT> Types)571 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types) {
572 return actionForCartesianProduct(LegalizeAction::Legal, Types);
573 }
574 /// The instruction is legal when type indexes 0 and 1 are both their
575 /// respective lists.
legalForCartesianProduct(std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1)576 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0,
577 std::initializer_list<LLT> Types1) {
578 return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1);
579 }
580 /// The instruction is legal when type indexes 0, 1, and 2 are both their
581 /// respective lists.
legalForCartesianProduct(std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1,std::initializer_list<LLT> Types2)582 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0,
583 std::initializer_list<LLT> Types1,
584 std::initializer_list<LLT> Types2) {
585 return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1,
586 Types2);
587 }
588
alwaysLegal()589 LegalizeRuleSet &alwaysLegal() {
590 using namespace LegalizeMutations;
591 markAllIdxsAsCovered();
592 return actionIf(LegalizeAction::Legal, always);
593 }
594
595 /// The specified type index is coerced if predicate is true.
bitcastIf(LegalityPredicate Predicate,LegalizeMutation Mutation)596 LegalizeRuleSet &bitcastIf(LegalityPredicate Predicate,
597 LegalizeMutation Mutation) {
598 // We have no choice but conservatively assume that lowering with a
599 // free-form user provided Predicate properly handles all type indices:
600 markAllIdxsAsCovered();
601 return actionIf(LegalizeAction::Bitcast, Predicate, Mutation);
602 }
603
604 /// The instruction is lowered.
lower()605 LegalizeRuleSet &lower() {
606 using namespace LegalizeMutations;
607 // We have no choice but conservatively assume that predicate-less lowering
608 // properly handles all type indices by design:
609 markAllIdxsAsCovered();
610 return actionIf(LegalizeAction::Lower, always);
611 }
612 /// The instruction is lowered if predicate is true. Keep type index 0 as the
613 /// same type.
lowerIf(LegalityPredicate Predicate)614 LegalizeRuleSet &lowerIf(LegalityPredicate Predicate) {
615 using namespace LegalizeMutations;
616 // We have no choice but conservatively assume that lowering with a
617 // free-form user provided Predicate properly handles all type indices:
618 markAllIdxsAsCovered();
619 return actionIf(LegalizeAction::Lower, Predicate);
620 }
621 /// The instruction is lowered if predicate is true.
lowerIf(LegalityPredicate Predicate,LegalizeMutation Mutation)622 LegalizeRuleSet &lowerIf(LegalityPredicate Predicate,
623 LegalizeMutation Mutation) {
624 // We have no choice but conservatively assume that lowering with a
625 // free-form user provided Predicate properly handles all type indices:
626 markAllIdxsAsCovered();
627 return actionIf(LegalizeAction::Lower, Predicate, Mutation);
628 }
629 /// The instruction is lowered when type index 0 is any type in the given
630 /// list. Keep type index 0 as the same type.
lowerFor(std::initializer_list<LLT> Types)631 LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types) {
632 return actionFor(LegalizeAction::Lower, Types);
633 }
634 /// The instruction is lowered when type index 0 is any type in the given
635 /// list.
lowerFor(std::initializer_list<LLT> Types,LegalizeMutation Mutation)636 LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types,
637 LegalizeMutation Mutation) {
638 return actionFor(LegalizeAction::Lower, Types, Mutation);
639 }
640 /// The instruction is lowered when type indexes 0 and 1 is any type pair in
641 /// the given list. Keep type index 0 as the same type.
lowerFor(std::initializer_list<std::pair<LLT,LLT>> Types)642 LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
643 return actionFor(LegalizeAction::Lower, Types);
644 }
645 /// The instruction is lowered when type indexes 0 and 1 is any type pair in
646 /// the given list.
lowerFor(std::initializer_list<std::pair<LLT,LLT>> Types,LegalizeMutation Mutation)647 LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types,
648 LegalizeMutation Mutation) {
649 return actionFor(LegalizeAction::Lower, Types, Mutation);
650 }
651 /// The instruction is lowered when type indexes 0 and 1 are both in their
652 /// respective lists.
lowerForCartesianProduct(std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1)653 LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0,
654 std::initializer_list<LLT> Types1) {
655 using namespace LegalityPredicates;
656 return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1);
657 }
658 /// The instruction is lowered when when type indexes 0, 1, and 2 are all in
659 /// their respective lists.
lowerForCartesianProduct(std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1,std::initializer_list<LLT> Types2)660 LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0,
661 std::initializer_list<LLT> Types1,
662 std::initializer_list<LLT> Types2) {
663 using namespace LegalityPredicates;
664 return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1,
665 Types2);
666 }
667
668 /// The instruction is emitted as a library call.
libcall()669 LegalizeRuleSet &libcall() {
670 using namespace LegalizeMutations;
671 // We have no choice but conservatively assume that predicate-less lowering
672 // properly handles all type indices by design:
673 markAllIdxsAsCovered();
674 return actionIf(LegalizeAction::Libcall, always);
675 }
676
677 /// Like legalIf, but for the Libcall action.
libcallIf(LegalityPredicate Predicate)678 LegalizeRuleSet &libcallIf(LegalityPredicate Predicate) {
679 // We have no choice but conservatively assume that a libcall with a
680 // free-form user provided Predicate properly handles all type indices:
681 markAllIdxsAsCovered();
682 return actionIf(LegalizeAction::Libcall, Predicate);
683 }
libcallFor(std::initializer_list<LLT> Types)684 LegalizeRuleSet &libcallFor(std::initializer_list<LLT> Types) {
685 return actionFor(LegalizeAction::Libcall, Types);
686 }
687 LegalizeRuleSet &
libcallFor(std::initializer_list<std::pair<LLT,LLT>> Types)688 libcallFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
689 return actionFor(LegalizeAction::Libcall, Types);
690 }
691 LegalizeRuleSet &
libcallForCartesianProduct(std::initializer_list<LLT> Types)692 libcallForCartesianProduct(std::initializer_list<LLT> Types) {
693 return actionForCartesianProduct(LegalizeAction::Libcall, Types);
694 }
695 LegalizeRuleSet &
libcallForCartesianProduct(std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1)696 libcallForCartesianProduct(std::initializer_list<LLT> Types0,
697 std::initializer_list<LLT> Types1) {
698 return actionForCartesianProduct(LegalizeAction::Libcall, Types0, Types1);
699 }
700
701 /// Widen the scalar to the one selected by the mutation if the predicate is
702 /// true.
widenScalarIf(LegalityPredicate Predicate,LegalizeMutation Mutation)703 LegalizeRuleSet &widenScalarIf(LegalityPredicate Predicate,
704 LegalizeMutation Mutation) {
705 // We have no choice but conservatively assume that an action with a
706 // free-form user provided Predicate properly handles all type indices:
707 markAllIdxsAsCovered();
708 return actionIf(LegalizeAction::WidenScalar, Predicate, Mutation);
709 }
710 /// Narrow the scalar to the one selected by the mutation if the predicate is
711 /// true.
narrowScalarIf(LegalityPredicate Predicate,LegalizeMutation Mutation)712 LegalizeRuleSet &narrowScalarIf(LegalityPredicate Predicate,
713 LegalizeMutation Mutation) {
714 // We have no choice but conservatively assume that an action with a
715 // free-form user provided Predicate properly handles all type indices:
716 markAllIdxsAsCovered();
717 return actionIf(LegalizeAction::NarrowScalar, Predicate, Mutation);
718 }
719 /// Narrow the scalar, specified in mutation, when type indexes 0 and 1 is any
720 /// type pair in the given list.
721 LegalizeRuleSet &
narrowScalarFor(std::initializer_list<std::pair<LLT,LLT>> Types,LegalizeMutation Mutation)722 narrowScalarFor(std::initializer_list<std::pair<LLT, LLT>> Types,
723 LegalizeMutation Mutation) {
724 return actionFor(LegalizeAction::NarrowScalar, Types, Mutation);
725 }
726
727 /// Add more elements to reach the type selected by the mutation if the
728 /// predicate is true.
moreElementsIf(LegalityPredicate Predicate,LegalizeMutation Mutation)729 LegalizeRuleSet &moreElementsIf(LegalityPredicate Predicate,
730 LegalizeMutation Mutation) {
731 // We have no choice but conservatively assume that an action with a
732 // free-form user provided Predicate properly handles all type indices:
733 markAllIdxsAsCovered();
734 return actionIf(LegalizeAction::MoreElements, Predicate, Mutation);
735 }
736 /// Remove elements to reach the type selected by the mutation if the
737 /// predicate is true.
fewerElementsIf(LegalityPredicate Predicate,LegalizeMutation Mutation)738 LegalizeRuleSet &fewerElementsIf(LegalityPredicate Predicate,
739 LegalizeMutation Mutation) {
740 // We have no choice but conservatively assume that an action with a
741 // free-form user provided Predicate properly handles all type indices:
742 markAllIdxsAsCovered();
743 return actionIf(LegalizeAction::FewerElements, Predicate, Mutation);
744 }
745
746 /// The instruction is unsupported.
unsupported()747 LegalizeRuleSet &unsupported() {
748 markAllIdxsAsCovered();
749 return actionIf(LegalizeAction::Unsupported, always);
750 }
unsupportedIf(LegalityPredicate Predicate)751 LegalizeRuleSet &unsupportedIf(LegalityPredicate Predicate) {
752 return actionIf(LegalizeAction::Unsupported, Predicate);
753 }
754
unsupportedFor(std::initializer_list<LLT> Types)755 LegalizeRuleSet &unsupportedFor(std::initializer_list<LLT> Types) {
756 return actionFor(LegalizeAction::Unsupported, Types);
757 }
758
unsupportedIfMemSizeNotPow2()759 LegalizeRuleSet &unsupportedIfMemSizeNotPow2() {
760 return actionIf(LegalizeAction::Unsupported,
761 LegalityPredicates::memSizeInBytesNotPow2(0));
762 }
lowerIfMemSizeNotPow2()763 LegalizeRuleSet &lowerIfMemSizeNotPow2() {
764 return actionIf(LegalizeAction::Lower,
765 LegalityPredicates::memSizeInBytesNotPow2(0));
766 }
767
customIf(LegalityPredicate Predicate)768 LegalizeRuleSet &customIf(LegalityPredicate Predicate) {
769 // We have no choice but conservatively assume that a custom action with a
770 // free-form user provided Predicate properly handles all type indices:
771 markAllIdxsAsCovered();
772 return actionIf(LegalizeAction::Custom, Predicate);
773 }
customFor(std::initializer_list<LLT> Types)774 LegalizeRuleSet &customFor(std::initializer_list<LLT> Types) {
775 return actionFor(LegalizeAction::Custom, Types);
776 }
777
778 /// The instruction is custom when type indexes 0 and 1 is any type pair in the
779 /// given list.
customFor(std::initializer_list<std::pair<LLT,LLT>> Types)780 LegalizeRuleSet &customFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
781 return actionFor(LegalizeAction::Custom, Types);
782 }
783
customForCartesianProduct(std::initializer_list<LLT> Types)784 LegalizeRuleSet &customForCartesianProduct(std::initializer_list<LLT> Types) {
785 return actionForCartesianProduct(LegalizeAction::Custom, Types);
786 }
787 LegalizeRuleSet &
customForCartesianProduct(std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1)788 customForCartesianProduct(std::initializer_list<LLT> Types0,
789 std::initializer_list<LLT> Types1) {
790 return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1);
791 }
792
793 /// Unconditionally custom lower.
custom()794 LegalizeRuleSet &custom() {
795 return customIf(always);
796 }
797
798 /// Widen the scalar to the next power of two that is at least MinSize.
799 /// No effect if the type is not a scalar or is a power of two.
800 LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx,
801 unsigned MinSize = 0) {
802 using namespace LegalityPredicates;
803 return actionIf(
804 LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)),
805 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize));
806 }
807
808 /// Widen the scalar or vector element type to the next power of two that is
809 /// at least MinSize. No effect if the scalar size is a power of two.
810 LegalizeRuleSet &widenScalarOrEltToNextPow2(unsigned TypeIdx,
811 unsigned MinSize = 0) {
812 using namespace LegalityPredicates;
813 return actionIf(
814 LegalizeAction::WidenScalar, scalarOrEltSizeNotPow2(typeIdx(TypeIdx)),
815 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize));
816 }
817
narrowScalar(unsigned TypeIdx,LegalizeMutation Mutation)818 LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) {
819 using namespace LegalityPredicates;
820 return actionIf(LegalizeAction::NarrowScalar, isScalar(typeIdx(TypeIdx)),
821 Mutation);
822 }
823
scalarize(unsigned TypeIdx)824 LegalizeRuleSet &scalarize(unsigned TypeIdx) {
825 using namespace LegalityPredicates;
826 return actionIf(LegalizeAction::FewerElements, isVector(typeIdx(TypeIdx)),
827 LegalizeMutations::scalarize(TypeIdx));
828 }
829
scalarizeIf(LegalityPredicate Predicate,unsigned TypeIdx)830 LegalizeRuleSet &scalarizeIf(LegalityPredicate Predicate, unsigned TypeIdx) {
831 using namespace LegalityPredicates;
832 return actionIf(LegalizeAction::FewerElements,
833 all(Predicate, isVector(typeIdx(TypeIdx))),
834 LegalizeMutations::scalarize(TypeIdx));
835 }
836
837 /// Ensure the scalar or element is at least as wide as Ty.
minScalarOrElt(unsigned TypeIdx,const LLT Ty)838 LegalizeRuleSet &minScalarOrElt(unsigned TypeIdx, const LLT Ty) {
839 using namespace LegalityPredicates;
840 using namespace LegalizeMutations;
841 return actionIf(LegalizeAction::WidenScalar,
842 scalarOrEltNarrowerThan(TypeIdx, Ty.getScalarSizeInBits()),
843 changeElementTo(typeIdx(TypeIdx), Ty));
844 }
845
846 /// Ensure the scalar or element is at least as wide as Ty.
minScalarOrEltIf(LegalityPredicate Predicate,unsigned TypeIdx,const LLT Ty)847 LegalizeRuleSet &minScalarOrEltIf(LegalityPredicate Predicate,
848 unsigned TypeIdx, const LLT Ty) {
849 using namespace LegalityPredicates;
850 using namespace LegalizeMutations;
851 return actionIf(LegalizeAction::WidenScalar,
852 all(Predicate, scalarOrEltNarrowerThan(
853 TypeIdx, Ty.getScalarSizeInBits())),
854 changeElementTo(typeIdx(TypeIdx), Ty));
855 }
856
857 /// Ensure the scalar is at least as wide as Ty.
minScalar(unsigned TypeIdx,const LLT Ty)858 LegalizeRuleSet &minScalar(unsigned TypeIdx, const LLT Ty) {
859 using namespace LegalityPredicates;
860 using namespace LegalizeMutations;
861 return actionIf(LegalizeAction::WidenScalar,
862 scalarNarrowerThan(TypeIdx, Ty.getSizeInBits()),
863 changeTo(typeIdx(TypeIdx), Ty));
864 }
865
866 /// Ensure the scalar is at most as wide as Ty.
maxScalarOrElt(unsigned TypeIdx,const LLT Ty)867 LegalizeRuleSet &maxScalarOrElt(unsigned TypeIdx, const LLT Ty) {
868 using namespace LegalityPredicates;
869 using namespace LegalizeMutations;
870 return actionIf(LegalizeAction::NarrowScalar,
871 scalarOrEltWiderThan(TypeIdx, Ty.getScalarSizeInBits()),
872 changeElementTo(typeIdx(TypeIdx), Ty));
873 }
874
875 /// Ensure the scalar is at most as wide as Ty.
maxScalar(unsigned TypeIdx,const LLT Ty)876 LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT Ty) {
877 using namespace LegalityPredicates;
878 using namespace LegalizeMutations;
879 return actionIf(LegalizeAction::NarrowScalar,
880 scalarWiderThan(TypeIdx, Ty.getSizeInBits()),
881 changeTo(typeIdx(TypeIdx), Ty));
882 }
883
884 /// Conditionally limit the maximum size of the scalar.
885 /// For example, when the maximum size of one type depends on the size of
886 /// another such as extracting N bits from an M bit container.
maxScalarIf(LegalityPredicate Predicate,unsigned TypeIdx,const LLT Ty)887 LegalizeRuleSet &maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx,
888 const LLT Ty) {
889 using namespace LegalityPredicates;
890 using namespace LegalizeMutations;
891 return actionIf(
892 LegalizeAction::NarrowScalar,
893 [=](const LegalityQuery &Query) {
894 const LLT QueryTy = Query.Types[TypeIdx];
895 return QueryTy.isScalar() &&
896 QueryTy.getSizeInBits() > Ty.getSizeInBits() &&
897 Predicate(Query);
898 },
899 changeElementTo(typeIdx(TypeIdx), Ty));
900 }
901
902 /// Limit the range of scalar sizes to MinTy and MaxTy.
clampScalar(unsigned TypeIdx,const LLT MinTy,const LLT MaxTy)903 LegalizeRuleSet &clampScalar(unsigned TypeIdx, const LLT MinTy,
904 const LLT MaxTy) {
905 assert(MinTy.isScalar() && MaxTy.isScalar() && "Expected scalar types");
906 return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy);
907 }
908
909 /// Limit the range of scalar sizes to MinTy and MaxTy.
clampScalarOrElt(unsigned TypeIdx,const LLT MinTy,const LLT MaxTy)910 LegalizeRuleSet &clampScalarOrElt(unsigned TypeIdx, const LLT MinTy,
911 const LLT MaxTy) {
912 return minScalarOrElt(TypeIdx, MinTy).maxScalarOrElt(TypeIdx, MaxTy);
913 }
914
915 /// Widen the scalar to match the size of another.
minScalarSameAs(unsigned TypeIdx,unsigned LargeTypeIdx)916 LegalizeRuleSet &minScalarSameAs(unsigned TypeIdx, unsigned LargeTypeIdx) {
917 typeIdx(TypeIdx);
918 return widenScalarIf(
919 [=](const LegalityQuery &Query) {
920 return Query.Types[LargeTypeIdx].getScalarSizeInBits() >
921 Query.Types[TypeIdx].getSizeInBits();
922 },
923 LegalizeMutations::changeElementSizeTo(TypeIdx, LargeTypeIdx));
924 }
925
926 /// Narrow the scalar to match the size of another.
maxScalarSameAs(unsigned TypeIdx,unsigned NarrowTypeIdx)927 LegalizeRuleSet &maxScalarSameAs(unsigned TypeIdx, unsigned NarrowTypeIdx) {
928 typeIdx(TypeIdx);
929 return narrowScalarIf(
930 [=](const LegalityQuery &Query) {
931 return Query.Types[NarrowTypeIdx].getScalarSizeInBits() <
932 Query.Types[TypeIdx].getSizeInBits();
933 },
934 LegalizeMutations::changeElementSizeTo(TypeIdx, NarrowTypeIdx));
935 }
936
937 /// Change the type \p TypeIdx to have the same scalar size as type \p
938 /// SameSizeIdx.
scalarSameSizeAs(unsigned TypeIdx,unsigned SameSizeIdx)939 LegalizeRuleSet &scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx) {
940 return minScalarSameAs(TypeIdx, SameSizeIdx)
941 .maxScalarSameAs(TypeIdx, SameSizeIdx);
942 }
943
944 /// Conditionally widen the scalar or elt to match the size of another.
minScalarEltSameAsIf(LegalityPredicate Predicate,unsigned TypeIdx,unsigned LargeTypeIdx)945 LegalizeRuleSet &minScalarEltSameAsIf(LegalityPredicate Predicate,
946 unsigned TypeIdx, unsigned LargeTypeIdx) {
947 typeIdx(TypeIdx);
948 return widenScalarIf(
949 [=](const LegalityQuery &Query) {
950 return Query.Types[LargeTypeIdx].getScalarSizeInBits() >
951 Query.Types[TypeIdx].getScalarSizeInBits() &&
952 Predicate(Query);
953 },
954 [=](const LegalityQuery &Query) {
955 LLT T = Query.Types[LargeTypeIdx];
956 return std::make_pair(TypeIdx, T);
957 });
958 }
959
960 /// Add more elements to the vector to reach the next power of two.
961 /// No effect if the type is not a vector or the element count is a power of
962 /// two.
moreElementsToNextPow2(unsigned TypeIdx)963 LegalizeRuleSet &moreElementsToNextPow2(unsigned TypeIdx) {
964 using namespace LegalityPredicates;
965 return actionIf(LegalizeAction::MoreElements,
966 numElementsNotPow2(typeIdx(TypeIdx)),
967 LegalizeMutations::moreElementsToNextPow2(TypeIdx));
968 }
969
970 /// Limit the number of elements in EltTy vectors to at least MinElements.
clampMinNumElements(unsigned TypeIdx,const LLT EltTy,unsigned MinElements)971 LegalizeRuleSet &clampMinNumElements(unsigned TypeIdx, const LLT EltTy,
972 unsigned MinElements) {
973 // Mark the type index as covered:
974 typeIdx(TypeIdx);
975 return actionIf(
976 LegalizeAction::MoreElements,
977 [=](const LegalityQuery &Query) {
978 LLT VecTy = Query.Types[TypeIdx];
979 return VecTy.isVector() && VecTy.getElementType() == EltTy &&
980 VecTy.getNumElements() < MinElements;
981 },
982 [=](const LegalityQuery &Query) {
983 LLT VecTy = Query.Types[TypeIdx];
984 return std::make_pair(
985 TypeIdx, LLT::vector(MinElements, VecTy.getElementType()));
986 });
987 }
988 /// Limit the number of elements in EltTy vectors to at most MaxElements.
clampMaxNumElements(unsigned TypeIdx,const LLT EltTy,unsigned MaxElements)989 LegalizeRuleSet &clampMaxNumElements(unsigned TypeIdx, const LLT EltTy,
990 unsigned MaxElements) {
991 // Mark the type index as covered:
992 typeIdx(TypeIdx);
993 return actionIf(
994 LegalizeAction::FewerElements,
995 [=](const LegalityQuery &Query) {
996 LLT VecTy = Query.Types[TypeIdx];
997 return VecTy.isVector() && VecTy.getElementType() == EltTy &&
998 VecTy.getNumElements() > MaxElements;
999 },
1000 [=](const LegalityQuery &Query) {
1001 LLT VecTy = Query.Types[TypeIdx];
1002 LLT NewTy = LLT::scalarOrVector(MaxElements, VecTy.getElementType());
1003 return std::make_pair(TypeIdx, NewTy);
1004 });
1005 }
1006 /// Limit the number of elements for the given vectors to at least MinTy's
1007 /// number of elements and at most MaxTy's number of elements.
1008 ///
1009 /// No effect if the type is not a vector or does not have the same element
1010 /// type as the constraints.
1011 /// The element type of MinTy and MaxTy must match.
clampNumElements(unsigned TypeIdx,const LLT MinTy,const LLT MaxTy)1012 LegalizeRuleSet &clampNumElements(unsigned TypeIdx, const LLT MinTy,
1013 const LLT MaxTy) {
1014 assert(MinTy.getElementType() == MaxTy.getElementType() &&
1015 "Expected element types to agree");
1016
1017 const LLT EltTy = MinTy.getElementType();
1018 return clampMinNumElements(TypeIdx, EltTy, MinTy.getNumElements())
1019 .clampMaxNumElements(TypeIdx, EltTy, MaxTy.getNumElements());
1020 }
1021
1022 /// Fallback on the previous implementation. This should only be used while
1023 /// porting a rule.
fallback()1024 LegalizeRuleSet &fallback() {
1025 add({always, LegalizeAction::UseLegacyRules});
1026 return *this;
1027 }
1028
1029 /// Check if there is no type index which is obviously not handled by the
1030 /// LegalizeRuleSet in any way at all.
1031 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set.
1032 bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const;
1033 /// Check if there is no imm index which is obviously not handled by the
1034 /// LegalizeRuleSet in any way at all.
1035 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set.
1036 bool verifyImmIdxsCoverage(unsigned NumImmIdxs) const;
1037
1038 /// Apply the ruleset to the given LegalityQuery.
1039 LegalizeActionStep apply(const LegalityQuery &Query) const;
1040 };
1041
1042 class LegalizerInfo {
1043 public:
1044 LegalizerInfo();
1045 virtual ~LegalizerInfo() = default;
1046
1047 unsigned getOpcodeIdxForOpcode(unsigned Opcode) const;
1048 unsigned getActionDefinitionsIdx(unsigned Opcode) const;
1049
1050 /// Compute any ancillary tables needed to quickly decide how an operation
1051 /// should be handled. This must be called after all "set*Action"methods but
1052 /// before any query is made or incorrect results may be returned.
1053 void computeTables();
1054
1055 /// Perform simple self-diagnostic and assert if there is anything obviously
1056 /// wrong with the actions set up.
1057 void verify(const MCInstrInfo &MII) const;
1058
needsLegalizingToDifferentSize(const LegalizeAction Action)1059 static bool needsLegalizingToDifferentSize(const LegalizeAction Action) {
1060 using namespace LegalizeActions;
1061 switch (Action) {
1062 case NarrowScalar:
1063 case WidenScalar:
1064 case FewerElements:
1065 case MoreElements:
1066 case Unsupported:
1067 return true;
1068 default:
1069 return false;
1070 }
1071 }
1072
1073 using SizeAndAction = std::pair<uint16_t, LegalizeAction>;
1074 using SizeAndActionsVec = std::vector<SizeAndAction>;
1075 using SizeChangeStrategy =
1076 std::function<SizeAndActionsVec(const SizeAndActionsVec &v)>;
1077
1078 /// More friendly way to set an action for common types that have an LLT
1079 /// representation.
1080 /// The LegalizeAction must be one for which NeedsLegalizingToDifferentSize
1081 /// returns false.
setAction(const InstrAspect & Aspect,LegalizeAction Action)1082 void setAction(const InstrAspect &Aspect, LegalizeAction Action) {
1083 assert(!needsLegalizingToDifferentSize(Action));
1084 TablesInitialized = false;
1085 const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;
1086 if (SpecifiedActions[OpcodeIdx].size() <= Aspect.Idx)
1087 SpecifiedActions[OpcodeIdx].resize(Aspect.Idx + 1);
1088 SpecifiedActions[OpcodeIdx][Aspect.Idx][Aspect.Type] = Action;
1089 }
1090
1091 /// The setAction calls record the non-size-changing legalization actions
1092 /// to take on specificly-sized types. The SizeChangeStrategy defines what
1093 /// to do when the size of the type needs to be changed to reach a legally
1094 /// sized type (i.e., one that was defined through a setAction call).
1095 /// e.g.
1096 /// setAction ({G_ADD, 0, LLT::scalar(32)}, Legal);
1097 /// setLegalizeScalarToDifferentSizeStrategy(
1098 /// G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
1099 /// will end up defining getAction({G_ADD, 0, T}) to return the following
1100 /// actions for different scalar types T:
1101 /// LLT::scalar(1)..LLT::scalar(31): {WidenScalar, 0, LLT::scalar(32)}
1102 /// LLT::scalar(32): {Legal, 0, LLT::scalar(32)}
1103 /// LLT::scalar(33)..: {NarrowScalar, 0, LLT::scalar(32)}
1104 ///
1105 /// If no SizeChangeAction gets defined, through this function,
1106 /// the default is unsupportedForDifferentSizes.
setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode,const unsigned TypeIdx,SizeChangeStrategy S)1107 void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode,
1108 const unsigned TypeIdx,
1109 SizeChangeStrategy S) {
1110 const unsigned OpcodeIdx = Opcode - FirstOp;
1111 if (ScalarSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
1112 ScalarSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
1113 ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
1114 }
1115
1116 /// See also setLegalizeScalarToDifferentSizeStrategy.
1117 /// This function allows to set the SizeChangeStrategy for vector elements.
setLegalizeVectorElementToDifferentSizeStrategy(const unsigned Opcode,const unsigned TypeIdx,SizeChangeStrategy S)1118 void setLegalizeVectorElementToDifferentSizeStrategy(const unsigned Opcode,
1119 const unsigned TypeIdx,
1120 SizeChangeStrategy S) {
1121 const unsigned OpcodeIdx = Opcode - FirstOp;
1122 if (VectorElementSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
1123 VectorElementSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
1124 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
1125 }
1126
1127 /// A SizeChangeStrategy for the common case where legalization for a
1128 /// particular operation consists of only supporting a specific set of type
1129 /// sizes. E.g.
1130 /// setAction ({G_DIV, 0, LLT::scalar(32)}, Legal);
1131 /// setAction ({G_DIV, 0, LLT::scalar(64)}, Legal);
1132 /// setLegalizeScalarToDifferentSizeStrategy(
1133 /// G_DIV, 0, unsupportedForDifferentSizes);
1134 /// will result in getAction({G_DIV, 0, T}) to return Legal for s32 and s64,
1135 /// and Unsupported for all other scalar types T.
1136 static SizeAndActionsVec
unsupportedForDifferentSizes(const SizeAndActionsVec & v)1137 unsupportedForDifferentSizes(const SizeAndActionsVec &v) {
1138 using namespace LegalizeActions;
1139 return increaseToLargerTypesAndDecreaseToLargest(v, Unsupported,
1140 Unsupported);
1141 }
1142
1143 /// A SizeChangeStrategy for the common case where legalization for a
1144 /// particular operation consists of widening the type to a large legal type,
1145 /// unless there is no such type and then instead it should be narrowed to the
1146 /// largest legal type.
1147 static SizeAndActionsVec
widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec & v)1148 widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v) {
1149 using namespace LegalizeActions;
1150 assert(v.size() > 0 &&
1151 "At least one size that can be legalized towards is needed"
1152 " for this SizeChangeStrategy");
1153 return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
1154 NarrowScalar);
1155 }
1156
1157 static SizeAndActionsVec
widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec & v)1158 widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v) {
1159 using namespace LegalizeActions;
1160 return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
1161 Unsupported);
1162 }
1163
1164 static SizeAndActionsVec
narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec & v)1165 narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v) {
1166 using namespace LegalizeActions;
1167 return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
1168 Unsupported);
1169 }
1170
1171 static SizeAndActionsVec
narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec & v)1172 narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec &v) {
1173 using namespace LegalizeActions;
1174 assert(v.size() > 0 &&
1175 "At least one size that can be legalized towards is needed"
1176 " for this SizeChangeStrategy");
1177 return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
1178 WidenScalar);
1179 }
1180
1181 /// A SizeChangeStrategy for the common case where legalization for a
1182 /// particular vector operation consists of having more elements in the
1183 /// vector, to a type that is legal. Unless there is no such type and then
1184 /// instead it should be legalized towards the widest vector that's still
1185 /// legal. E.g.
1186 /// setAction({G_ADD, LLT::vector(8, 8)}, Legal);
1187 /// setAction({G_ADD, LLT::vector(16, 8)}, Legal);
1188 /// setAction({G_ADD, LLT::vector(2, 32)}, Legal);
1189 /// setAction({G_ADD, LLT::vector(4, 32)}, Legal);
1190 /// setLegalizeVectorElementToDifferentSizeStrategy(
1191 /// G_ADD, 0, moreToWiderTypesAndLessToWidest);
1192 /// will result in the following getAction results:
1193 /// * getAction({G_ADD, LLT::vector(8,8)}) returns
1194 /// (Legal, vector(8,8)).
1195 /// * getAction({G_ADD, LLT::vector(9,8)}) returns
1196 /// (MoreElements, vector(16,8)).
1197 /// * getAction({G_ADD, LLT::vector(8,32)}) returns
1198 /// (FewerElements, vector(4,32)).
1199 static SizeAndActionsVec
moreToWiderTypesAndLessToWidest(const SizeAndActionsVec & v)1200 moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v) {
1201 using namespace LegalizeActions;
1202 return increaseToLargerTypesAndDecreaseToLargest(v, MoreElements,
1203 FewerElements);
1204 }
1205
1206 /// Helper function to implement many typical SizeChangeStrategy functions.
1207 static SizeAndActionsVec
1208 increaseToLargerTypesAndDecreaseToLargest(const SizeAndActionsVec &v,
1209 LegalizeAction IncreaseAction,
1210 LegalizeAction DecreaseAction);
1211 /// Helper function to implement many typical SizeChangeStrategy functions.
1212 static SizeAndActionsVec
1213 decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec &v,
1214 LegalizeAction DecreaseAction,
1215 LegalizeAction IncreaseAction);
1216
1217 /// Get the action definitions for the given opcode. Use this to run a
1218 /// LegalityQuery through the definitions.
1219 const LegalizeRuleSet &getActionDefinitions(unsigned Opcode) const;
1220
1221 /// Get the action definition builder for the given opcode. Use this to define
1222 /// the action definitions.
1223 ///
1224 /// It is an error to request an opcode that has already been requested by the
1225 /// multiple-opcode variant.
1226 LegalizeRuleSet &getActionDefinitionsBuilder(unsigned Opcode);
1227
1228 /// Get the action definition builder for the given set of opcodes. Use this
1229 /// to define the action definitions for multiple opcodes at once. The first
1230 /// opcode given will be considered the representative opcode and will hold
1231 /// the definitions whereas the other opcodes will be configured to refer to
1232 /// the representative opcode. This lowers memory requirements and very
1233 /// slightly improves performance.
1234 ///
1235 /// It would be very easy to introduce unexpected side-effects as a result of
1236 /// this aliasing if it were permitted to request different but intersecting
1237 /// sets of opcodes but that is difficult to keep track of. It is therefore an
1238 /// error to request the same opcode twice using this API, to request an
1239 /// opcode that already has definitions, or to use the single-opcode API on an
1240 /// opcode that has already been requested by this API.
1241 LegalizeRuleSet &
1242 getActionDefinitionsBuilder(std::initializer_list<unsigned> Opcodes);
1243 void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom);
1244
1245 /// Determine what action should be taken to legalize the described
1246 /// instruction. Requires computeTables to have been called.
1247 ///
1248 /// \returns a description of the next legalization step to perform.
1249 LegalizeActionStep getAction(const LegalityQuery &Query) const;
1250
1251 /// Determine what action should be taken to legalize the given generic
1252 /// instruction.
1253 ///
1254 /// \returns a description of the next legalization step to perform.
1255 LegalizeActionStep getAction(const MachineInstr &MI,
1256 const MachineRegisterInfo &MRI) const;
1257
isLegal(const LegalityQuery & Query)1258 bool isLegal(const LegalityQuery &Query) const {
1259 return getAction(Query).Action == LegalizeAction::Legal;
1260 }
1261
isLegalOrCustom(const LegalityQuery & Query)1262 bool isLegalOrCustom(const LegalityQuery &Query) const {
1263 auto Action = getAction(Query).Action;
1264 return Action == LegalizeAction::Legal || Action == LegalizeAction::Custom;
1265 }
1266
1267 bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
1268 bool isLegalOrCustom(const MachineInstr &MI,
1269 const MachineRegisterInfo &MRI) const;
1270
1271 /// Called for instructions with the Custom LegalizationAction.
legalizeCustom(LegalizerHelper & Helper,MachineInstr & MI)1272 virtual bool legalizeCustom(LegalizerHelper &Helper,
1273 MachineInstr &MI) const {
1274 llvm_unreachable("must implement this if custom action is used");
1275 }
1276
1277 /// \returns true if MI is either legal or has been legalized and false if not
1278 /// legal.
1279 /// Return true if MI is either legal or has been legalized and false
1280 /// if not legal.
legalizeIntrinsic(LegalizerHelper & Helper,MachineInstr & MI)1281 virtual bool legalizeIntrinsic(LegalizerHelper &Helper,
1282 MachineInstr &MI) const {
1283 return true;
1284 }
1285
1286 /// Return the opcode (SEXT/ZEXT/ANYEXT) that should be performed while
1287 /// widening a constant of type SmallTy which targets can override.
1288 /// For eg, the DAG does (SmallTy.isByteSized() ? G_SEXT : G_ZEXT) which
1289 /// will be the default.
1290 virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const;
1291
1292 private:
1293 /// Determine what action should be taken to legalize the given generic
1294 /// instruction opcode, type-index and type. Requires computeTables to have
1295 /// been called.
1296 ///
1297 /// \returns a pair consisting of the kind of legalization that should be
1298 /// performed and the destination type.
1299 std::pair<LegalizeAction, LLT>
1300 getAspectAction(const InstrAspect &Aspect) const;
1301
1302 /// The SizeAndActionsVec is a representation mapping between all natural
1303 /// numbers and an Action. The natural number represents the bit size of
1304 /// the InstrAspect. For example, for a target with native support for 32-bit
1305 /// and 64-bit additions, you'd express that as:
1306 /// setScalarAction(G_ADD, 0,
1307 /// {{1, WidenScalar}, // bit sizes [ 1, 31[
1308 /// {32, Legal}, // bit sizes [32, 33[
1309 /// {33, WidenScalar}, // bit sizes [33, 64[
1310 /// {64, Legal}, // bit sizes [64, 65[
1311 /// {65, NarrowScalar} // bit sizes [65, +inf[
1312 /// });
1313 /// It may be that only 64-bit pointers are supported on your target:
1314 /// setPointerAction(G_PTR_ADD, 0, LLT:pointer(1),
1315 /// {{1, Unsupported}, // bit sizes [ 1, 63[
1316 /// {64, Legal}, // bit sizes [64, 65[
1317 /// {65, Unsupported}, // bit sizes [65, +inf[
1318 /// });
setScalarAction(const unsigned Opcode,const unsigned TypeIndex,const SizeAndActionsVec & SizeAndActions)1319 void setScalarAction(const unsigned Opcode, const unsigned TypeIndex,
1320 const SizeAndActionsVec &SizeAndActions) {
1321 const unsigned OpcodeIdx = Opcode - FirstOp;
1322 SmallVector<SizeAndActionsVec, 1> &Actions = ScalarActions[OpcodeIdx];
1323 setActions(TypeIndex, Actions, SizeAndActions);
1324 }
setPointerAction(const unsigned Opcode,const unsigned TypeIndex,const unsigned AddressSpace,const SizeAndActionsVec & SizeAndActions)1325 void setPointerAction(const unsigned Opcode, const unsigned TypeIndex,
1326 const unsigned AddressSpace,
1327 const SizeAndActionsVec &SizeAndActions) {
1328 const unsigned OpcodeIdx = Opcode - FirstOp;
1329 if (AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace) ==
1330 AddrSpace2PointerActions[OpcodeIdx].end())
1331 AddrSpace2PointerActions[OpcodeIdx][AddressSpace] = {{}};
1332 SmallVector<SizeAndActionsVec, 1> &Actions =
1333 AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace)->second;
1334 setActions(TypeIndex, Actions, SizeAndActions);
1335 }
1336
1337 /// If an operation on a given vector type (say <M x iN>) isn't explicitly
1338 /// specified, we proceed in 2 stages. First we legalize the underlying scalar
1339 /// (so that there's at least one legal vector with that scalar), then we
1340 /// adjust the number of elements in the vector so that it is legal. The
1341 /// desired action in the first step is controlled by this function.
setScalarInVectorAction(const unsigned Opcode,const unsigned TypeIndex,const SizeAndActionsVec & SizeAndActions)1342 void setScalarInVectorAction(const unsigned Opcode, const unsigned TypeIndex,
1343 const SizeAndActionsVec &SizeAndActions) {
1344 unsigned OpcodeIdx = Opcode - FirstOp;
1345 SmallVector<SizeAndActionsVec, 1> &Actions =
1346 ScalarInVectorActions[OpcodeIdx];
1347 setActions(TypeIndex, Actions, SizeAndActions);
1348 }
1349
1350 /// See also setScalarInVectorAction.
1351 /// This function let's you specify the number of elements in a vector that
1352 /// are legal for a legal element size.
setVectorNumElementAction(const unsigned Opcode,const unsigned TypeIndex,const unsigned ElementSize,const SizeAndActionsVec & SizeAndActions)1353 void setVectorNumElementAction(const unsigned Opcode,
1354 const unsigned TypeIndex,
1355 const unsigned ElementSize,
1356 const SizeAndActionsVec &SizeAndActions) {
1357 const unsigned OpcodeIdx = Opcode - FirstOp;
1358 if (NumElements2Actions[OpcodeIdx].find(ElementSize) ==
1359 NumElements2Actions[OpcodeIdx].end())
1360 NumElements2Actions[OpcodeIdx][ElementSize] = {{}};
1361 SmallVector<SizeAndActionsVec, 1> &Actions =
1362 NumElements2Actions[OpcodeIdx].find(ElementSize)->second;
1363 setActions(TypeIndex, Actions, SizeAndActions);
1364 }
1365
1366 /// A partial SizeAndActionsVec potentially doesn't cover all bit sizes,
1367 /// i.e. it's OK if it doesn't start from size 1.
checkPartialSizeAndActionsVector(const SizeAndActionsVec & v)1368 static void checkPartialSizeAndActionsVector(const SizeAndActionsVec& v) {
1369 using namespace LegalizeActions;
1370 #ifndef NDEBUG
1371 // The sizes should be in increasing order
1372 int prev_size = -1;
1373 for(auto SizeAndAction: v) {
1374 assert(SizeAndAction.first > prev_size);
1375 prev_size = SizeAndAction.first;
1376 }
1377 // - for every Widen action, there should be a larger bitsize that
1378 // can be legalized towards (e.g. Legal, Lower, Libcall or Custom
1379 // action).
1380 // - for every Narrow action, there should be a smaller bitsize that
1381 // can be legalized towards.
1382 int SmallestNarrowIdx = -1;
1383 int LargestWidenIdx = -1;
1384 int SmallestLegalizableToSameSizeIdx = -1;
1385 int LargestLegalizableToSameSizeIdx = -1;
1386 for(size_t i=0; i<v.size(); ++i) {
1387 switch (v[i].second) {
1388 case FewerElements:
1389 case NarrowScalar:
1390 if (SmallestNarrowIdx == -1)
1391 SmallestNarrowIdx = i;
1392 break;
1393 case WidenScalar:
1394 case MoreElements:
1395 LargestWidenIdx = i;
1396 break;
1397 case Unsupported:
1398 break;
1399 default:
1400 if (SmallestLegalizableToSameSizeIdx == -1)
1401 SmallestLegalizableToSameSizeIdx = i;
1402 LargestLegalizableToSameSizeIdx = i;
1403 }
1404 }
1405 if (SmallestNarrowIdx != -1) {
1406 assert(SmallestLegalizableToSameSizeIdx != -1);
1407 assert(SmallestNarrowIdx > SmallestLegalizableToSameSizeIdx);
1408 }
1409 if (LargestWidenIdx != -1)
1410 assert(LargestWidenIdx < LargestLegalizableToSameSizeIdx);
1411 #endif
1412 }
1413
1414 /// A full SizeAndActionsVec must cover all bit sizes, i.e. must start with
1415 /// from size 1.
checkFullSizeAndActionsVector(const SizeAndActionsVec & v)1416 static void checkFullSizeAndActionsVector(const SizeAndActionsVec& v) {
1417 #ifndef NDEBUG
1418 // Data structure invariant: The first bit size must be size 1.
1419 assert(v.size() >= 1);
1420 assert(v[0].first == 1);
1421 checkPartialSizeAndActionsVector(v);
1422 #endif
1423 }
1424
1425 /// Sets actions for all bit sizes on a particular generic opcode, type
1426 /// index and scalar or pointer type.
setActions(unsigned TypeIndex,SmallVector<SizeAndActionsVec,1> & Actions,const SizeAndActionsVec & SizeAndActions)1427 void setActions(unsigned TypeIndex,
1428 SmallVector<SizeAndActionsVec, 1> &Actions,
1429 const SizeAndActionsVec &SizeAndActions) {
1430 checkFullSizeAndActionsVector(SizeAndActions);
1431 if (Actions.size() <= TypeIndex)
1432 Actions.resize(TypeIndex + 1);
1433 Actions[TypeIndex] = SizeAndActions;
1434 }
1435
1436 static SizeAndAction findAction(const SizeAndActionsVec &Vec,
1437 const uint32_t Size);
1438
1439 /// Returns the next action needed to get the scalar or pointer type closer
1440 /// to being legal
1441 /// E.g. findLegalAction({G_REM, 13}) should return
1442 /// (WidenScalar, 32). After that, findLegalAction({G_REM, 32}) will
1443 /// probably be called, which should return (Lower, 32).
1444 /// This is assuming the setScalarAction on G_REM was something like:
1445 /// setScalarAction(G_REM, 0,
1446 /// {{1, WidenScalar}, // bit sizes [ 1, 31[
1447 /// {32, Lower}, // bit sizes [32, 33[
1448 /// {33, NarrowScalar} // bit sizes [65, +inf[
1449 /// });
1450 std::pair<LegalizeAction, LLT>
1451 findScalarLegalAction(const InstrAspect &Aspect) const;
1452
1453 /// Returns the next action needed towards legalizing the vector type.
1454 std::pair<LegalizeAction, LLT>
1455 findVectorLegalAction(const InstrAspect &Aspect) const;
1456
1457 static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
1458 static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
1459
1460 // Data structures used temporarily during construction of legality data:
1461 using TypeMap = DenseMap<LLT, LegalizeAction>;
1462 SmallVector<TypeMap, 1> SpecifiedActions[LastOp - FirstOp + 1];
1463 SmallVector<SizeChangeStrategy, 1>
1464 ScalarSizeChangeStrategies[LastOp - FirstOp + 1];
1465 SmallVector<SizeChangeStrategy, 1>
1466 VectorElementSizeChangeStrategies[LastOp - FirstOp + 1];
1467 bool TablesInitialized;
1468
1469 // Data structures used by getAction:
1470 SmallVector<SizeAndActionsVec, 1> ScalarActions[LastOp - FirstOp + 1];
1471 SmallVector<SizeAndActionsVec, 1> ScalarInVectorActions[LastOp - FirstOp + 1];
1472 std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
1473 AddrSpace2PointerActions[LastOp - FirstOp + 1];
1474 std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
1475 NumElements2Actions[LastOp - FirstOp + 1];
1476
1477 LegalizeRuleSet RulesForOpcode[LastOp - FirstOp + 1];
1478 };
1479
1480 #ifndef NDEBUG
1481 /// Checks that MIR is fully legal, returns an illegal instruction if it's not,
1482 /// nullptr otherwise
1483 const MachineInstr *machineFunctionIsIllegal(const MachineFunction &MF);
1484 #endif
1485
1486 } // end namespace llvm.
1487
1488 #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
1489