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 /// \file
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/SmallBitVector.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h"
20 #include "llvm/CodeGen/MachineMemOperand.h"
21 #include "llvm/CodeGen/TargetOpcodes.h"
22 #include "llvm/MC/MCInstrDesc.h"
23 #include "llvm/Support/AtomicOrdering.h"
24 #include "llvm/Support/CommandLine.h"
25 #include "llvm/Support/LowLevelTypeImpl.h"
26 #include <cassert>
27 #include <cstdint>
28 #include <tuple>
29 #include <utility>
30
31 namespace llvm {
32
33 extern cl::opt<bool> DisableGISelLegalityCheck;
34
35 class MachineFunction;
36 class raw_ostream;
37 class LegalizerHelper;
38 class MachineInstr;
39 class MachineRegisterInfo;
40 class MCInstrInfo;
41
42 namespace LegalizeActions {
43 enum LegalizeAction : std::uint8_t {
44 /// The operation is expected to be selectable directly by the target, and
45 /// no transformation is necessary.
46 Legal,
47
48 /// The operation should be synthesized from multiple instructions acting on
49 /// a narrower scalar base-type. For example a 64-bit add might be
50 /// implemented in terms of 32-bit add-with-carry.
51 NarrowScalar,
52
53 /// The operation should be implemented in terms of a wider scalar
54 /// base-type. For example a <2 x s8> add could be implemented as a <2
55 /// x s32> add (ignoring the high bits).
56 WidenScalar,
57
58 /// The (vector) operation should be implemented by splitting it into
59 /// sub-vectors where the operation is legal. For example a <8 x s64> add
60 /// might be implemented as 4 separate <2 x s64> adds. There can be a leftover
61 /// if there are not enough elements for last sub-vector e.g. <7 x s64> add
62 /// will be implemented as 3 separate <2 x s64> adds and one s64 add. Leftover
63 /// types can be avoided by doing MoreElements first.
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 /// The LegalityQuery object bundles together all the information that's needed
105 /// to decide whether a given operation is legal or not.
106 /// For efficiency, it doesn't make a copy of Types so care must be taken not
107 /// to free it before using the query.
108 struct LegalityQuery {
109 unsigned Opcode;
110 ArrayRef<LLT> Types;
111
112 struct MemDesc {
113 LLT MemoryTy;
114 uint64_t AlignInBits;
115 AtomicOrdering Ordering;
116
117 MemDesc() = default;
MemDescLegalityQuery::MemDesc118 MemDesc(LLT MemoryTy, uint64_t AlignInBits, AtomicOrdering Ordering)
119 : MemoryTy(MemoryTy), AlignInBits(AlignInBits), Ordering(Ordering) {}
MemDescLegalityQuery::MemDesc120 MemDesc(const MachineMemOperand &MMO)
121 : MemoryTy(MMO.getMemoryType()),
122 AlignInBits(MMO.getAlign().value() * 8),
123 Ordering(MMO.getSuccessOrdering()) {}
124 };
125
126 /// Operations which require memory can use this to place requirements on the
127 /// memory type for each MMO.
128 ArrayRef<MemDesc> MMODescrs;
129
LegalityQueryLegalityQuery130 constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types,
131 const ArrayRef<MemDesc> MMODescrs)
132 : Opcode(Opcode), Types(Types), MMODescrs(MMODescrs) {}
LegalityQueryLegalityQuery133 constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types)
134 : LegalityQuery(Opcode, Types, {}) {}
135
136 raw_ostream &print(raw_ostream &OS) const;
137 };
138
139 /// The result of a query. It either indicates a final answer of Legal or
140 /// Unsupported or describes an action that must be taken to make an operation
141 /// more legal.
142 struct LegalizeActionStep {
143 /// The action to take or the final answer.
144 LegalizeAction Action;
145 /// If describing an action, the type index to change. Otherwise zero.
146 unsigned TypeIdx;
147 /// If describing an action, the new type for TypeIdx. Otherwise LLT{}.
148 LLT NewType;
149
LegalizeActionStepLegalizeActionStep150 LegalizeActionStep(LegalizeAction Action, unsigned TypeIdx,
151 const LLT NewType)
152 : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {}
153
LegalizeActionStepLegalizeActionStep154 LegalizeActionStep(LegacyLegalizeActionStep Step)
155 : TypeIdx(Step.TypeIdx), NewType(Step.NewType) {
156 switch (Step.Action) {
157 case LegacyLegalizeActions::Legal:
158 Action = LegalizeActions::Legal;
159 break;
160 case LegacyLegalizeActions::NarrowScalar:
161 Action = LegalizeActions::NarrowScalar;
162 break;
163 case LegacyLegalizeActions::WidenScalar:
164 Action = LegalizeActions::WidenScalar;
165 break;
166 case LegacyLegalizeActions::FewerElements:
167 Action = LegalizeActions::FewerElements;
168 break;
169 case LegacyLegalizeActions::MoreElements:
170 Action = LegalizeActions::MoreElements;
171 break;
172 case LegacyLegalizeActions::Bitcast:
173 Action = LegalizeActions::Bitcast;
174 break;
175 case LegacyLegalizeActions::Lower:
176 Action = LegalizeActions::Lower;
177 break;
178 case LegacyLegalizeActions::Libcall:
179 Action = LegalizeActions::Libcall;
180 break;
181 case LegacyLegalizeActions::Custom:
182 Action = LegalizeActions::Custom;
183 break;
184 case LegacyLegalizeActions::Unsupported:
185 Action = LegalizeActions::Unsupported;
186 break;
187 case LegacyLegalizeActions::NotFound:
188 Action = LegalizeActions::NotFound;
189 break;
190 }
191 }
192
193 bool operator==(const LegalizeActionStep &RHS) const {
194 return std::tie(Action, TypeIdx, NewType) ==
195 std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType);
196 }
197 };
198
199 using LegalityPredicate = std::function<bool (const LegalityQuery &)>;
200 using LegalizeMutation =
201 std::function<std::pair<unsigned, LLT>(const LegalityQuery &)>;
202
203 namespace LegalityPredicates {
204 struct TypePairAndMemDesc {
205 LLT Type0;
206 LLT Type1;
207 LLT MemTy;
208 uint64_t Align;
209
210 bool operator==(const TypePairAndMemDesc &Other) const {
211 return Type0 == Other.Type0 && Type1 == Other.Type1 &&
212 Align == Other.Align && MemTy == Other.MemTy;
213 }
214
215 /// \returns true if this memory access is legal with for the access described
216 /// by \p Other (The alignment is sufficient for the size and result type).
isCompatibleTypePairAndMemDesc217 bool isCompatible(const TypePairAndMemDesc &Other) const {
218 return Type0 == Other.Type0 && Type1 == Other.Type1 &&
219 Align >= Other.Align &&
220 // FIXME: This perhaps should be stricter, but the current legality
221 // rules are written only considering the size.
222 MemTy.getSizeInBits() == Other.MemTy.getSizeInBits();
223 }
224 };
225
226 /// True iff P0 and P1 are true.
227 template<typename Predicate>
all(Predicate P0,Predicate P1)228 Predicate all(Predicate P0, Predicate P1) {
229 return [=](const LegalityQuery &Query) {
230 return P0(Query) && P1(Query);
231 };
232 }
233 /// True iff all given predicates are true.
234 template<typename Predicate, typename... Args>
all(Predicate P0,Predicate P1,Args...args)235 Predicate all(Predicate P0, Predicate P1, Args... args) {
236 return all(all(P0, P1), args...);
237 }
238
239 /// True iff P0 or P1 are true.
240 template<typename Predicate>
any(Predicate P0,Predicate P1)241 Predicate any(Predicate P0, Predicate P1) {
242 return [=](const LegalityQuery &Query) {
243 return P0(Query) || P1(Query);
244 };
245 }
246 /// True iff any given predicates are true.
247 template<typename Predicate, typename... Args>
any(Predicate P0,Predicate P1,Args...args)248 Predicate any(Predicate P0, Predicate P1, Args... args) {
249 return any(any(P0, P1), args...);
250 }
251
252 /// True iff the given type index is the specified type.
253 LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit);
254 /// True iff the given type index is one of the specified types.
255 LegalityPredicate typeInSet(unsigned TypeIdx,
256 std::initializer_list<LLT> TypesInit);
257
258 /// True iff the given type index is not the specified type.
typeIsNot(unsigned TypeIdx,LLT Type)259 inline LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type) {
260 return [=](const LegalityQuery &Query) {
261 return Query.Types[TypeIdx] != Type;
262 };
263 }
264
265 /// True iff the given types for the given pair of type indexes is one of the
266 /// specified type pairs.
267 LegalityPredicate
268 typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1,
269 std::initializer_list<std::pair<LLT, LLT>> TypesInit);
270 /// True iff the given types for the given pair of type indexes is one of the
271 /// specified type pairs.
272 LegalityPredicate typePairAndMemDescInSet(
273 unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx,
274 std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit);
275 /// True iff the specified type index is a scalar.
276 LegalityPredicate isScalar(unsigned TypeIdx);
277 /// True iff the specified type index is a vector.
278 LegalityPredicate isVector(unsigned TypeIdx);
279 /// True iff the specified type index is a pointer (with any address space).
280 LegalityPredicate isPointer(unsigned TypeIdx);
281 /// True iff the specified type index is a pointer with the specified address
282 /// space.
283 LegalityPredicate isPointer(unsigned TypeIdx, unsigned AddrSpace);
284
285 /// True if the type index is a vector with element type \p EltTy
286 LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT EltTy);
287
288 /// True iff the specified type index is a scalar that's narrower than the given
289 /// size.
290 LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size);
291
292 /// True iff the specified type index is a scalar that's wider than the given
293 /// size.
294 LegalityPredicate scalarWiderThan(unsigned TypeIdx, unsigned Size);
295
296 /// True iff the specified type index is a scalar or vector with an element type
297 /// that's narrower than the given size.
298 LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size);
299
300 /// True iff the specified type index is a scalar or a vector with an element
301 /// type that's wider than the given size.
302 LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size);
303
304 /// True iff the specified type index is a scalar whose size is not a multiple
305 /// of Size.
306 LegalityPredicate sizeNotMultipleOf(unsigned TypeIdx, unsigned Size);
307
308 /// True iff the specified type index is a scalar whose size is not a power of
309 /// 2.
310 LegalityPredicate sizeNotPow2(unsigned TypeIdx);
311
312 /// True iff the specified type index is a scalar or vector whose element size
313 /// is not a power of 2.
314 LegalityPredicate scalarOrEltSizeNotPow2(unsigned TypeIdx);
315
316 /// True if the total bitwidth of the specified type index is \p Size bits.
317 LegalityPredicate sizeIs(unsigned TypeIdx, unsigned Size);
318
319 /// True iff the specified type indices are both the same bit size.
320 LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1);
321
322 /// True iff the first type index has a larger total bit size than second type
323 /// index.
324 LegalityPredicate largerThan(unsigned TypeIdx0, unsigned TypeIdx1);
325
326 /// True iff the first type index has a smaller total bit size than second type
327 /// index.
328 LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1);
329
330 /// True iff the specified MMO index has a size (rounded to bytes) that is not a
331 /// power of 2.
332 LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx);
333
334 /// True iff the specified MMO index has a size that is not an even byte size,
335 /// or that even byte size is not a power of 2.
336 LegalityPredicate memSizeNotByteSizePow2(unsigned MMOIdx);
337
338 /// True iff the specified type index is a vector whose element count is not a
339 /// power of 2.
340 LegalityPredicate numElementsNotPow2(unsigned TypeIdx);
341 /// True iff the specified MMO index has at an atomic ordering of at Ordering or
342 /// stronger.
343 LegalityPredicate atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx,
344 AtomicOrdering Ordering);
345 } // end namespace LegalityPredicates
346
347 namespace LegalizeMutations {
348 /// Select this specific type for the given type index.
349 LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty);
350
351 /// Keep the same type as the given type index.
352 LegalizeMutation changeTo(unsigned TypeIdx, unsigned FromTypeIdx);
353
354 /// Keep the same scalar or element type as the given type index.
355 LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx);
356
357 /// Keep the same scalar or element type as the given type.
358 LegalizeMutation changeElementTo(unsigned TypeIdx, LLT Ty);
359
360 /// Keep the same scalar or element type as \p TypeIdx, but take the number of
361 /// elements from \p FromTypeIdx.
362 LegalizeMutation changeElementCountTo(unsigned TypeIdx, unsigned FromTypeIdx);
363
364 /// Keep the same scalar or element type as \p TypeIdx, but take the number of
365 /// elements from \p Ty.
366 LegalizeMutation changeElementCountTo(unsigned TypeIdx, LLT Ty);
367
368 /// Change the scalar size or element size to have the same scalar size as type
369 /// index \p FromIndex. Unlike changeElementTo, this discards pointer types and
370 /// only changes the size.
371 LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx);
372
373 /// Widen the scalar type or vector element type for the given type index to the
374 /// next power of 2.
375 LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min = 0);
376
377 /// Widen the scalar type or vector element type for the given type index to
378 /// next multiple of \p Size.
379 LegalizeMutation widenScalarOrEltToNextMultipleOf(unsigned TypeIdx,
380 unsigned Size);
381
382 /// Add more elements to the type for the given type index to the next power of
383 /// 2.
384 LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min = 0);
385 /// Break up the vector type for the given type index into the element type.
386 LegalizeMutation scalarize(unsigned TypeIdx);
387 } // end namespace LegalizeMutations
388
389 /// A single rule in a legalizer info ruleset.
390 /// The specified action is chosen when the predicate is true. Where appropriate
391 /// for the action (e.g. for WidenScalar) the new type is selected using the
392 /// given mutator.
393 class LegalizeRule {
394 LegalityPredicate Predicate;
395 LegalizeAction Action;
396 LegalizeMutation Mutation;
397
398 public:
399 LegalizeRule(LegalityPredicate Predicate, LegalizeAction Action,
400 LegalizeMutation Mutation = nullptr)
Predicate(Predicate)401 : Predicate(Predicate), Action(Action), Mutation(Mutation) {}
402
403 /// Test whether the LegalityQuery matches.
match(const LegalityQuery & Query)404 bool match(const LegalityQuery &Query) const {
405 return Predicate(Query);
406 }
407
getAction()408 LegalizeAction getAction() const { return Action; }
409
410 /// Determine the change to make.
determineMutation(const LegalityQuery & Query)411 std::pair<unsigned, LLT> determineMutation(const LegalityQuery &Query) const {
412 if (Mutation)
413 return Mutation(Query);
414 return std::make_pair(0, LLT{});
415 }
416 };
417
418 class LegalizeRuleSet {
419 /// When non-zero, the opcode we are an alias of
420 unsigned AliasOf = 0;
421 /// If true, there is another opcode that aliases this one
422 bool IsAliasedByAnother = false;
423 SmallVector<LegalizeRule, 2> Rules;
424
425 #ifndef NDEBUG
426 /// If bit I is set, this rule set contains a rule that may handle (predicate
427 /// or perform an action upon (or both)) the type index I. The uncertainty
428 /// comes from free-form rules executing user-provided lambda functions. We
429 /// conservatively assume such rules do the right thing and cover all type
430 /// indices. The bitset is intentionally 1 bit wider than it absolutely needs
431 /// to be to distinguish such cases from the cases where all type indices are
432 /// individually handled.
433 SmallBitVector TypeIdxsCovered{MCOI::OPERAND_LAST_GENERIC -
434 MCOI::OPERAND_FIRST_GENERIC + 2};
435 SmallBitVector ImmIdxsCovered{MCOI::OPERAND_LAST_GENERIC_IMM -
436 MCOI::OPERAND_FIRST_GENERIC_IMM + 2};
437 #endif
438
typeIdx(unsigned TypeIdx)439 unsigned typeIdx(unsigned TypeIdx) {
440 assert(TypeIdx <=
441 (MCOI::OPERAND_LAST_GENERIC - MCOI::OPERAND_FIRST_GENERIC) &&
442 "Type Index is out of bounds");
443 #ifndef NDEBUG
444 TypeIdxsCovered.set(TypeIdx);
445 #endif
446 return TypeIdx;
447 }
448
markAllIdxsAsCovered()449 void markAllIdxsAsCovered() {
450 #ifndef NDEBUG
451 TypeIdxsCovered.set();
452 ImmIdxsCovered.set();
453 #endif
454 }
455
add(const LegalizeRule & Rule)456 void add(const LegalizeRule &Rule) {
457 assert(AliasOf == 0 &&
458 "RuleSet is aliased, change the representative opcode instead");
459 Rules.push_back(Rule);
460 }
461
always(const LegalityQuery &)462 static bool always(const LegalityQuery &) { return true; }
463
464 /// Use the given action when the predicate is true.
465 /// Action should not be an action that requires mutation.
actionIf(LegalizeAction Action,LegalityPredicate Predicate)466 LegalizeRuleSet &actionIf(LegalizeAction Action,
467 LegalityPredicate Predicate) {
468 add({Predicate, Action});
469 return *this;
470 }
471 /// Use the given action when the predicate is true.
472 /// Action should be an action that requires mutation.
actionIf(LegalizeAction Action,LegalityPredicate Predicate,LegalizeMutation Mutation)473 LegalizeRuleSet &actionIf(LegalizeAction Action, LegalityPredicate Predicate,
474 LegalizeMutation Mutation) {
475 add({Predicate, Action, Mutation});
476 return *this;
477 }
478 /// Use the given action when type index 0 is any type in the given list.
479 /// Action should not be an action that requires mutation.
actionFor(LegalizeAction Action,std::initializer_list<LLT> Types)480 LegalizeRuleSet &actionFor(LegalizeAction Action,
481 std::initializer_list<LLT> Types) {
482 using namespace LegalityPredicates;
483 return actionIf(Action, typeInSet(typeIdx(0), Types));
484 }
485 /// Use the given action when type index 0 is any type in the given list.
486 /// Action should be an action that requires mutation.
actionFor(LegalizeAction Action,std::initializer_list<LLT> Types,LegalizeMutation Mutation)487 LegalizeRuleSet &actionFor(LegalizeAction Action,
488 std::initializer_list<LLT> Types,
489 LegalizeMutation Mutation) {
490 using namespace LegalityPredicates;
491 return actionIf(Action, typeInSet(typeIdx(0), Types), Mutation);
492 }
493 /// Use the given action when type indexes 0 and 1 is any type pair in the
494 /// given list.
495 /// Action should not be an action that requires mutation.
actionFor(LegalizeAction Action,std::initializer_list<std::pair<LLT,LLT>> Types)496 LegalizeRuleSet &actionFor(LegalizeAction Action,
497 std::initializer_list<std::pair<LLT, LLT>> Types) {
498 using namespace LegalityPredicates;
499 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types));
500 }
501 /// Use the given action when type indexes 0 and 1 is any type pair in the
502 /// given list.
503 /// Action should be an action that requires mutation.
actionFor(LegalizeAction Action,std::initializer_list<std::pair<LLT,LLT>> Types,LegalizeMutation Mutation)504 LegalizeRuleSet &actionFor(LegalizeAction Action,
505 std::initializer_list<std::pair<LLT, LLT>> Types,
506 LegalizeMutation Mutation) {
507 using namespace LegalityPredicates;
508 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types),
509 Mutation);
510 }
511 /// Use the given action when type index 0 is any type in the given list and
512 /// imm index 0 is anything. Action should not be an action that requires
513 /// mutation.
actionForTypeWithAnyImm(LegalizeAction Action,std::initializer_list<LLT> Types)514 LegalizeRuleSet &actionForTypeWithAnyImm(LegalizeAction Action,
515 std::initializer_list<LLT> Types) {
516 using namespace LegalityPredicates;
517 immIdx(0); // Inform verifier imm idx 0 is handled.
518 return actionIf(Action, typeInSet(typeIdx(0), Types));
519 }
520
actionForTypeWithAnyImm(LegalizeAction Action,std::initializer_list<std::pair<LLT,LLT>> Types)521 LegalizeRuleSet &actionForTypeWithAnyImm(
522 LegalizeAction Action, std::initializer_list<std::pair<LLT, LLT>> Types) {
523 using namespace LegalityPredicates;
524 immIdx(0); // Inform verifier imm idx 0 is handled.
525 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types));
526 }
527
528 /// Use the given action when type indexes 0 and 1 are both in the given list.
529 /// That is, the type pair is in the cartesian product of the list.
530 /// Action should not be an action that requires mutation.
actionForCartesianProduct(LegalizeAction Action,std::initializer_list<LLT> Types)531 LegalizeRuleSet &actionForCartesianProduct(LegalizeAction Action,
532 std::initializer_list<LLT> Types) {
533 using namespace LegalityPredicates;
534 return actionIf(Action, all(typeInSet(typeIdx(0), Types),
535 typeInSet(typeIdx(1), Types)));
536 }
537 /// Use the given action when type indexes 0 and 1 are both in their
538 /// respective lists.
539 /// That is, the type pair is in the cartesian product of the lists
540 /// Action should not be an action that requires mutation.
541 LegalizeRuleSet &
actionForCartesianProduct(LegalizeAction Action,std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1)542 actionForCartesianProduct(LegalizeAction Action,
543 std::initializer_list<LLT> Types0,
544 std::initializer_list<LLT> Types1) {
545 using namespace LegalityPredicates;
546 return actionIf(Action, all(typeInSet(typeIdx(0), Types0),
547 typeInSet(typeIdx(1), Types1)));
548 }
549 /// Use the given action when type indexes 0, 1, and 2 are all in their
550 /// respective lists.
551 /// That is, the type triple is in the cartesian product of the lists
552 /// 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)553 LegalizeRuleSet &actionForCartesianProduct(
554 LegalizeAction Action, std::initializer_list<LLT> Types0,
555 std::initializer_list<LLT> Types1, std::initializer_list<LLT> Types2) {
556 using namespace LegalityPredicates;
557 return actionIf(Action, all(typeInSet(typeIdx(0), Types0),
558 all(typeInSet(typeIdx(1), Types1),
559 typeInSet(typeIdx(2), Types2))));
560 }
561
562 public:
563 LegalizeRuleSet() = default;
564
isAliasedByAnother()565 bool isAliasedByAnother() { return IsAliasedByAnother; }
setIsAliasedByAnother()566 void setIsAliasedByAnother() { IsAliasedByAnother = true; }
aliasTo(unsigned Opcode)567 void aliasTo(unsigned Opcode) {
568 assert((AliasOf == 0 || AliasOf == Opcode) &&
569 "Opcode is already aliased to another opcode");
570 assert(Rules.empty() && "Aliasing will discard rules");
571 AliasOf = Opcode;
572 }
getAlias()573 unsigned getAlias() const { return AliasOf; }
574
immIdx(unsigned ImmIdx)575 unsigned immIdx(unsigned ImmIdx) {
576 assert(ImmIdx <= (MCOI::OPERAND_LAST_GENERIC_IMM -
577 MCOI::OPERAND_FIRST_GENERIC_IMM) &&
578 "Imm Index is out of bounds");
579 #ifndef NDEBUG
580 ImmIdxsCovered.set(ImmIdx);
581 #endif
582 return ImmIdx;
583 }
584
585 /// The instruction is legal if predicate is true.
legalIf(LegalityPredicate Predicate)586 LegalizeRuleSet &legalIf(LegalityPredicate Predicate) {
587 // We have no choice but conservatively assume that the free-form
588 // user-provided Predicate properly handles all type indices:
589 markAllIdxsAsCovered();
590 return actionIf(LegalizeAction::Legal, Predicate);
591 }
592 /// The instruction is legal when type index 0 is any type in the given list.
legalFor(std::initializer_list<LLT> Types)593 LegalizeRuleSet &legalFor(std::initializer_list<LLT> Types) {
594 return actionFor(LegalizeAction::Legal, Types);
595 }
596 /// The instruction is legal when type indexes 0 and 1 is any type pair in the
597 /// given list.
legalFor(std::initializer_list<std::pair<LLT,LLT>> Types)598 LegalizeRuleSet &legalFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
599 return actionFor(LegalizeAction::Legal, Types);
600 }
601 /// The instruction is legal when type index 0 is any type in the given list
602 /// and imm index 0 is anything.
legalForTypeWithAnyImm(std::initializer_list<LLT> Types)603 LegalizeRuleSet &legalForTypeWithAnyImm(std::initializer_list<LLT> Types) {
604 markAllIdxsAsCovered();
605 return actionForTypeWithAnyImm(LegalizeAction::Legal, Types);
606 }
607
legalForTypeWithAnyImm(std::initializer_list<std::pair<LLT,LLT>> Types)608 LegalizeRuleSet &legalForTypeWithAnyImm(
609 std::initializer_list<std::pair<LLT, LLT>> Types) {
610 markAllIdxsAsCovered();
611 return actionForTypeWithAnyImm(LegalizeAction::Legal, Types);
612 }
613
614 /// The instruction is legal when type indexes 0 and 1 along with the memory
615 /// size and minimum alignment is any type and size tuple in the given list.
legalForTypesWithMemDesc(std::initializer_list<LegalityPredicates::TypePairAndMemDesc> TypesAndMemDesc)616 LegalizeRuleSet &legalForTypesWithMemDesc(
617 std::initializer_list<LegalityPredicates::TypePairAndMemDesc>
618 TypesAndMemDesc) {
619 return actionIf(LegalizeAction::Legal,
620 LegalityPredicates::typePairAndMemDescInSet(
621 typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemDesc));
622 }
623 /// The instruction is legal when type indexes 0 and 1 are both in the given
624 /// list. That is, the type pair is in the cartesian product of the list.
legalForCartesianProduct(std::initializer_list<LLT> Types)625 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types) {
626 return actionForCartesianProduct(LegalizeAction::Legal, Types);
627 }
628 /// The instruction is legal when type indexes 0 and 1 are both their
629 /// respective lists.
legalForCartesianProduct(std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1)630 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0,
631 std::initializer_list<LLT> Types1) {
632 return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1);
633 }
634 /// The instruction is legal when type indexes 0, 1, and 2 are both their
635 /// respective lists.
legalForCartesianProduct(std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1,std::initializer_list<LLT> Types2)636 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0,
637 std::initializer_list<LLT> Types1,
638 std::initializer_list<LLT> Types2) {
639 return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1,
640 Types2);
641 }
642
alwaysLegal()643 LegalizeRuleSet &alwaysLegal() {
644 using namespace LegalizeMutations;
645 markAllIdxsAsCovered();
646 return actionIf(LegalizeAction::Legal, always);
647 }
648
649 /// The specified type index is coerced if predicate is true.
bitcastIf(LegalityPredicate Predicate,LegalizeMutation Mutation)650 LegalizeRuleSet &bitcastIf(LegalityPredicate Predicate,
651 LegalizeMutation Mutation) {
652 // We have no choice but conservatively assume that lowering with a
653 // free-form user provided Predicate properly handles all type indices:
654 markAllIdxsAsCovered();
655 return actionIf(LegalizeAction::Bitcast, Predicate, Mutation);
656 }
657
658 /// The instruction is lowered.
lower()659 LegalizeRuleSet &lower() {
660 using namespace LegalizeMutations;
661 // We have no choice but conservatively assume that predicate-less lowering
662 // properly handles all type indices by design:
663 markAllIdxsAsCovered();
664 return actionIf(LegalizeAction::Lower, always);
665 }
666 /// The instruction is lowered if predicate is true. Keep type index 0 as the
667 /// same type.
lowerIf(LegalityPredicate Predicate)668 LegalizeRuleSet &lowerIf(LegalityPredicate Predicate) {
669 using namespace LegalizeMutations;
670 // We have no choice but conservatively assume that lowering with a
671 // free-form user provided Predicate properly handles all type indices:
672 markAllIdxsAsCovered();
673 return actionIf(LegalizeAction::Lower, Predicate);
674 }
675 /// The instruction is lowered if predicate is true.
lowerIf(LegalityPredicate Predicate,LegalizeMutation Mutation)676 LegalizeRuleSet &lowerIf(LegalityPredicate Predicate,
677 LegalizeMutation Mutation) {
678 // We have no choice but conservatively assume that lowering with a
679 // free-form user provided Predicate properly handles all type indices:
680 markAllIdxsAsCovered();
681 return actionIf(LegalizeAction::Lower, Predicate, Mutation);
682 }
683 /// The instruction is lowered when type index 0 is any type in the given
684 /// list. Keep type index 0 as the same type.
lowerFor(std::initializer_list<LLT> Types)685 LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types) {
686 return actionFor(LegalizeAction::Lower, Types);
687 }
688 /// The instruction is lowered when type index 0 is any type in the given
689 /// list.
lowerFor(std::initializer_list<LLT> Types,LegalizeMutation Mutation)690 LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types,
691 LegalizeMutation Mutation) {
692 return actionFor(LegalizeAction::Lower, Types, Mutation);
693 }
694 /// The instruction is lowered when type indexes 0 and 1 is any type pair in
695 /// the given list. Keep type index 0 as the same type.
lowerFor(std::initializer_list<std::pair<LLT,LLT>> Types)696 LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
697 return actionFor(LegalizeAction::Lower, Types);
698 }
699 /// The instruction is lowered when type indexes 0 and 1 is any type pair in
700 /// the given list.
lowerFor(std::initializer_list<std::pair<LLT,LLT>> Types,LegalizeMutation Mutation)701 LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types,
702 LegalizeMutation Mutation) {
703 return actionFor(LegalizeAction::Lower, Types, Mutation);
704 }
705 /// The instruction is lowered when type indexes 0 and 1 are both in their
706 /// respective lists.
lowerForCartesianProduct(std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1)707 LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0,
708 std::initializer_list<LLT> Types1) {
709 using namespace LegalityPredicates;
710 return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1);
711 }
712 /// The instruction is lowered when when type indexes 0, 1, and 2 are all in
713 /// their respective lists.
lowerForCartesianProduct(std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1,std::initializer_list<LLT> Types2)714 LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0,
715 std::initializer_list<LLT> Types1,
716 std::initializer_list<LLT> Types2) {
717 using namespace LegalityPredicates;
718 return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1,
719 Types2);
720 }
721
722 /// The instruction is emitted as a library call.
libcall()723 LegalizeRuleSet &libcall() {
724 using namespace LegalizeMutations;
725 // We have no choice but conservatively assume that predicate-less lowering
726 // properly handles all type indices by design:
727 markAllIdxsAsCovered();
728 return actionIf(LegalizeAction::Libcall, always);
729 }
730
731 /// Like legalIf, but for the Libcall action.
libcallIf(LegalityPredicate Predicate)732 LegalizeRuleSet &libcallIf(LegalityPredicate Predicate) {
733 // We have no choice but conservatively assume that a libcall with a
734 // free-form user provided Predicate properly handles all type indices:
735 markAllIdxsAsCovered();
736 return actionIf(LegalizeAction::Libcall, Predicate);
737 }
libcallFor(std::initializer_list<LLT> Types)738 LegalizeRuleSet &libcallFor(std::initializer_list<LLT> Types) {
739 return actionFor(LegalizeAction::Libcall, Types);
740 }
741 LegalizeRuleSet &
libcallFor(std::initializer_list<std::pair<LLT,LLT>> Types)742 libcallFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
743 return actionFor(LegalizeAction::Libcall, Types);
744 }
745 LegalizeRuleSet &
libcallForCartesianProduct(std::initializer_list<LLT> Types)746 libcallForCartesianProduct(std::initializer_list<LLT> Types) {
747 return actionForCartesianProduct(LegalizeAction::Libcall, Types);
748 }
749 LegalizeRuleSet &
libcallForCartesianProduct(std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1)750 libcallForCartesianProduct(std::initializer_list<LLT> Types0,
751 std::initializer_list<LLT> Types1) {
752 return actionForCartesianProduct(LegalizeAction::Libcall, Types0, Types1);
753 }
754
755 /// Widen the scalar to the one selected by the mutation if the predicate is
756 /// true.
widenScalarIf(LegalityPredicate Predicate,LegalizeMutation Mutation)757 LegalizeRuleSet &widenScalarIf(LegalityPredicate Predicate,
758 LegalizeMutation Mutation) {
759 // We have no choice but conservatively assume that an action with a
760 // free-form user provided Predicate properly handles all type indices:
761 markAllIdxsAsCovered();
762 return actionIf(LegalizeAction::WidenScalar, Predicate, Mutation);
763 }
764 /// Narrow the scalar to the one selected by the mutation if the predicate is
765 /// true.
narrowScalarIf(LegalityPredicate Predicate,LegalizeMutation Mutation)766 LegalizeRuleSet &narrowScalarIf(LegalityPredicate Predicate,
767 LegalizeMutation Mutation) {
768 // We have no choice but conservatively assume that an action with a
769 // free-form user provided Predicate properly handles all type indices:
770 markAllIdxsAsCovered();
771 return actionIf(LegalizeAction::NarrowScalar, Predicate, Mutation);
772 }
773 /// Narrow the scalar, specified in mutation, when type indexes 0 and 1 is any
774 /// type pair in the given list.
775 LegalizeRuleSet &
narrowScalarFor(std::initializer_list<std::pair<LLT,LLT>> Types,LegalizeMutation Mutation)776 narrowScalarFor(std::initializer_list<std::pair<LLT, LLT>> Types,
777 LegalizeMutation Mutation) {
778 return actionFor(LegalizeAction::NarrowScalar, Types, Mutation);
779 }
780
781 /// Add more elements to reach the type selected by the mutation if the
782 /// predicate is true.
moreElementsIf(LegalityPredicate Predicate,LegalizeMutation Mutation)783 LegalizeRuleSet &moreElementsIf(LegalityPredicate Predicate,
784 LegalizeMutation Mutation) {
785 // We have no choice but conservatively assume that an action with a
786 // free-form user provided Predicate properly handles all type indices:
787 markAllIdxsAsCovered();
788 return actionIf(LegalizeAction::MoreElements, Predicate, Mutation);
789 }
790 /// Remove elements to reach the type selected by the mutation if the
791 /// predicate is true.
fewerElementsIf(LegalityPredicate Predicate,LegalizeMutation Mutation)792 LegalizeRuleSet &fewerElementsIf(LegalityPredicate Predicate,
793 LegalizeMutation Mutation) {
794 // We have no choice but conservatively assume that an action with a
795 // free-form user provided Predicate properly handles all type indices:
796 markAllIdxsAsCovered();
797 return actionIf(LegalizeAction::FewerElements, Predicate, Mutation);
798 }
799
800 /// The instruction is unsupported.
unsupported()801 LegalizeRuleSet &unsupported() {
802 markAllIdxsAsCovered();
803 return actionIf(LegalizeAction::Unsupported, always);
804 }
unsupportedIf(LegalityPredicate Predicate)805 LegalizeRuleSet &unsupportedIf(LegalityPredicate Predicate) {
806 return actionIf(LegalizeAction::Unsupported, Predicate);
807 }
808
unsupportedFor(std::initializer_list<LLT> Types)809 LegalizeRuleSet &unsupportedFor(std::initializer_list<LLT> Types) {
810 return actionFor(LegalizeAction::Unsupported, Types);
811 }
812
unsupportedIfMemSizeNotPow2()813 LegalizeRuleSet &unsupportedIfMemSizeNotPow2() {
814 return actionIf(LegalizeAction::Unsupported,
815 LegalityPredicates::memSizeInBytesNotPow2(0));
816 }
817
818 /// Lower a memory operation if the memory size, rounded to bytes, is not a
819 /// power of 2. For example, this will not trigger for s1 or s7, but will for
820 /// s24.
lowerIfMemSizeNotPow2()821 LegalizeRuleSet &lowerIfMemSizeNotPow2() {
822 return actionIf(LegalizeAction::Lower,
823 LegalityPredicates::memSizeInBytesNotPow2(0));
824 }
825
826 /// Lower a memory operation if the memory access size is not a round power of
827 /// 2 byte size. This is stricter than lowerIfMemSizeNotPow2, and more likely
828 /// what you want (e.g. this will lower s1, s7 and s24).
lowerIfMemSizeNotByteSizePow2()829 LegalizeRuleSet &lowerIfMemSizeNotByteSizePow2() {
830 return actionIf(LegalizeAction::Lower,
831 LegalityPredicates::memSizeNotByteSizePow2(0));
832 }
833
customIf(LegalityPredicate Predicate)834 LegalizeRuleSet &customIf(LegalityPredicate Predicate) {
835 // We have no choice but conservatively assume that a custom action with a
836 // free-form user provided Predicate properly handles all type indices:
837 markAllIdxsAsCovered();
838 return actionIf(LegalizeAction::Custom, Predicate);
839 }
customFor(std::initializer_list<LLT> Types)840 LegalizeRuleSet &customFor(std::initializer_list<LLT> Types) {
841 return actionFor(LegalizeAction::Custom, Types);
842 }
843
844 /// The instruction is custom when type indexes 0 and 1 is any type pair in the
845 /// given list.
customFor(std::initializer_list<std::pair<LLT,LLT>> Types)846 LegalizeRuleSet &customFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
847 return actionFor(LegalizeAction::Custom, Types);
848 }
849
customForCartesianProduct(std::initializer_list<LLT> Types)850 LegalizeRuleSet &customForCartesianProduct(std::initializer_list<LLT> Types) {
851 return actionForCartesianProduct(LegalizeAction::Custom, Types);
852 }
853 /// The instruction is custom when type indexes 0 and 1 are both in their
854 /// respective lists.
855 LegalizeRuleSet &
customForCartesianProduct(std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1)856 customForCartesianProduct(std::initializer_list<LLT> Types0,
857 std::initializer_list<LLT> Types1) {
858 return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1);
859 }
860 /// The instruction is custom when when type indexes 0, 1, and 2 are all in
861 /// their respective lists.
862 LegalizeRuleSet &
customForCartesianProduct(std::initializer_list<LLT> Types0,std::initializer_list<LLT> Types1,std::initializer_list<LLT> Types2)863 customForCartesianProduct(std::initializer_list<LLT> Types0,
864 std::initializer_list<LLT> Types1,
865 std::initializer_list<LLT> Types2) {
866 return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1,
867 Types2);
868 }
869
870 /// Unconditionally custom lower.
custom()871 LegalizeRuleSet &custom() {
872 return customIf(always);
873 }
874
875 /// Widen the scalar to the next power of two that is at least MinSize.
876 /// No effect if the type is not a scalar or is a power of two.
877 LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx,
878 unsigned MinSize = 0) {
879 using namespace LegalityPredicates;
880 return actionIf(
881 LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)),
882 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize));
883 }
884
885 /// Widen the scalar to the next multiple of Size. No effect if the
886 /// type is not a scalar or is a multiple of Size.
widenScalarToNextMultipleOf(unsigned TypeIdx,unsigned Size)887 LegalizeRuleSet &widenScalarToNextMultipleOf(unsigned TypeIdx,
888 unsigned Size) {
889 using namespace LegalityPredicates;
890 return actionIf(
891 LegalizeAction::WidenScalar, sizeNotMultipleOf(typeIdx(TypeIdx), Size),
892 LegalizeMutations::widenScalarOrEltToNextMultipleOf(TypeIdx, Size));
893 }
894
895 /// Widen the scalar or vector element type to the next power of two that is
896 /// at least MinSize. No effect if the scalar size is a power of two.
897 LegalizeRuleSet &widenScalarOrEltToNextPow2(unsigned TypeIdx,
898 unsigned MinSize = 0) {
899 using namespace LegalityPredicates;
900 return actionIf(
901 LegalizeAction::WidenScalar, scalarOrEltSizeNotPow2(typeIdx(TypeIdx)),
902 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize));
903 }
904
narrowScalar(unsigned TypeIdx,LegalizeMutation Mutation)905 LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) {
906 using namespace LegalityPredicates;
907 return actionIf(LegalizeAction::NarrowScalar, isScalar(typeIdx(TypeIdx)),
908 Mutation);
909 }
910
scalarize(unsigned TypeIdx)911 LegalizeRuleSet &scalarize(unsigned TypeIdx) {
912 using namespace LegalityPredicates;
913 return actionIf(LegalizeAction::FewerElements, isVector(typeIdx(TypeIdx)),
914 LegalizeMutations::scalarize(TypeIdx));
915 }
916
scalarizeIf(LegalityPredicate Predicate,unsigned TypeIdx)917 LegalizeRuleSet &scalarizeIf(LegalityPredicate Predicate, unsigned TypeIdx) {
918 using namespace LegalityPredicates;
919 return actionIf(LegalizeAction::FewerElements,
920 all(Predicate, isVector(typeIdx(TypeIdx))),
921 LegalizeMutations::scalarize(TypeIdx));
922 }
923
924 /// Ensure the scalar or element is at least as wide as Ty.
minScalarOrElt(unsigned TypeIdx,const LLT Ty)925 LegalizeRuleSet &minScalarOrElt(unsigned TypeIdx, const LLT Ty) {
926 using namespace LegalityPredicates;
927 using namespace LegalizeMutations;
928 return actionIf(LegalizeAction::WidenScalar,
929 scalarOrEltNarrowerThan(TypeIdx, Ty.getScalarSizeInBits()),
930 changeElementTo(typeIdx(TypeIdx), Ty));
931 }
932
933 /// Ensure the scalar or element is at least as wide as Ty.
minScalarOrEltIf(LegalityPredicate Predicate,unsigned TypeIdx,const LLT Ty)934 LegalizeRuleSet &minScalarOrEltIf(LegalityPredicate Predicate,
935 unsigned TypeIdx, const LLT Ty) {
936 using namespace LegalityPredicates;
937 using namespace LegalizeMutations;
938 return actionIf(LegalizeAction::WidenScalar,
939 all(Predicate, scalarOrEltNarrowerThan(
940 TypeIdx, Ty.getScalarSizeInBits())),
941 changeElementTo(typeIdx(TypeIdx), Ty));
942 }
943
944 /// Ensure the scalar is at least as wide as Ty.
minScalar(unsigned TypeIdx,const LLT Ty)945 LegalizeRuleSet &minScalar(unsigned TypeIdx, const LLT Ty) {
946 using namespace LegalityPredicates;
947 using namespace LegalizeMutations;
948 return actionIf(LegalizeAction::WidenScalar,
949 scalarNarrowerThan(TypeIdx, Ty.getSizeInBits()),
950 changeTo(typeIdx(TypeIdx), Ty));
951 }
952
953 /// Ensure the scalar is at least as wide as Ty if condition is met.
minScalarIf(LegalityPredicate Predicate,unsigned TypeIdx,const LLT Ty)954 LegalizeRuleSet &minScalarIf(LegalityPredicate Predicate, unsigned TypeIdx,
955 const LLT Ty) {
956 using namespace LegalityPredicates;
957 using namespace LegalizeMutations;
958 return actionIf(
959 LegalizeAction::WidenScalar,
960 [=](const LegalityQuery &Query) {
961 const LLT QueryTy = Query.Types[TypeIdx];
962 return QueryTy.isScalar() &&
963 QueryTy.getSizeInBits() < Ty.getSizeInBits() &&
964 Predicate(Query);
965 },
966 changeTo(typeIdx(TypeIdx), Ty));
967 }
968
969 /// Ensure the scalar is at most as wide as Ty.
maxScalarOrElt(unsigned TypeIdx,const LLT Ty)970 LegalizeRuleSet &maxScalarOrElt(unsigned TypeIdx, const LLT Ty) {
971 using namespace LegalityPredicates;
972 using namespace LegalizeMutations;
973 return actionIf(LegalizeAction::NarrowScalar,
974 scalarOrEltWiderThan(TypeIdx, Ty.getScalarSizeInBits()),
975 changeElementTo(typeIdx(TypeIdx), Ty));
976 }
977
978 /// Ensure the scalar is at most as wide as Ty.
maxScalar(unsigned TypeIdx,const LLT Ty)979 LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT Ty) {
980 using namespace LegalityPredicates;
981 using namespace LegalizeMutations;
982 return actionIf(LegalizeAction::NarrowScalar,
983 scalarWiderThan(TypeIdx, Ty.getSizeInBits()),
984 changeTo(typeIdx(TypeIdx), Ty));
985 }
986
987 /// Conditionally limit the maximum size of the scalar.
988 /// For example, when the maximum size of one type depends on the size of
989 /// another such as extracting N bits from an M bit container.
maxScalarIf(LegalityPredicate Predicate,unsigned TypeIdx,const LLT Ty)990 LegalizeRuleSet &maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx,
991 const LLT Ty) {
992 using namespace LegalityPredicates;
993 using namespace LegalizeMutations;
994 return actionIf(
995 LegalizeAction::NarrowScalar,
996 [=](const LegalityQuery &Query) {
997 const LLT QueryTy = Query.Types[TypeIdx];
998 return QueryTy.isScalar() &&
999 QueryTy.getSizeInBits() > Ty.getSizeInBits() &&
1000 Predicate(Query);
1001 },
1002 changeElementTo(typeIdx(TypeIdx), Ty));
1003 }
1004
1005 /// Limit the range of scalar sizes to MinTy and MaxTy.
clampScalar(unsigned TypeIdx,const LLT MinTy,const LLT MaxTy)1006 LegalizeRuleSet &clampScalar(unsigned TypeIdx, const LLT MinTy,
1007 const LLT MaxTy) {
1008 assert(MinTy.isScalar() && MaxTy.isScalar() && "Expected scalar types");
1009 return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy);
1010 }
1011
1012 /// Limit the range of scalar sizes to MinTy and MaxTy.
clampScalarOrElt(unsigned TypeIdx,const LLT MinTy,const LLT MaxTy)1013 LegalizeRuleSet &clampScalarOrElt(unsigned TypeIdx, const LLT MinTy,
1014 const LLT MaxTy) {
1015 return minScalarOrElt(TypeIdx, MinTy).maxScalarOrElt(TypeIdx, MaxTy);
1016 }
1017
1018 /// Widen the scalar to match the size of another.
minScalarSameAs(unsigned TypeIdx,unsigned LargeTypeIdx)1019 LegalizeRuleSet &minScalarSameAs(unsigned TypeIdx, unsigned LargeTypeIdx) {
1020 typeIdx(TypeIdx);
1021 return widenScalarIf(
1022 [=](const LegalityQuery &Query) {
1023 return Query.Types[LargeTypeIdx].getScalarSizeInBits() >
1024 Query.Types[TypeIdx].getSizeInBits();
1025 },
1026 LegalizeMutations::changeElementSizeTo(TypeIdx, LargeTypeIdx));
1027 }
1028
1029 /// Narrow the scalar to match the size of another.
maxScalarSameAs(unsigned TypeIdx,unsigned NarrowTypeIdx)1030 LegalizeRuleSet &maxScalarSameAs(unsigned TypeIdx, unsigned NarrowTypeIdx) {
1031 typeIdx(TypeIdx);
1032 return narrowScalarIf(
1033 [=](const LegalityQuery &Query) {
1034 return Query.Types[NarrowTypeIdx].getScalarSizeInBits() <
1035 Query.Types[TypeIdx].getSizeInBits();
1036 },
1037 LegalizeMutations::changeElementSizeTo(TypeIdx, NarrowTypeIdx));
1038 }
1039
1040 /// Change the type \p TypeIdx to have the same scalar size as type \p
1041 /// SameSizeIdx.
scalarSameSizeAs(unsigned TypeIdx,unsigned SameSizeIdx)1042 LegalizeRuleSet &scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx) {
1043 return minScalarSameAs(TypeIdx, SameSizeIdx)
1044 .maxScalarSameAs(TypeIdx, SameSizeIdx);
1045 }
1046
1047 /// Conditionally widen the scalar or elt to match the size of another.
minScalarEltSameAsIf(LegalityPredicate Predicate,unsigned TypeIdx,unsigned LargeTypeIdx)1048 LegalizeRuleSet &minScalarEltSameAsIf(LegalityPredicate Predicate,
1049 unsigned TypeIdx, unsigned LargeTypeIdx) {
1050 typeIdx(TypeIdx);
1051 return widenScalarIf(
1052 [=](const LegalityQuery &Query) {
1053 return Query.Types[LargeTypeIdx].getScalarSizeInBits() >
1054 Query.Types[TypeIdx].getScalarSizeInBits() &&
1055 Predicate(Query);
1056 },
1057 [=](const LegalityQuery &Query) {
1058 LLT T = Query.Types[LargeTypeIdx];
1059 if (T.isVector() && T.getElementType().isPointer())
1060 T = T.changeElementType(LLT::scalar(T.getScalarSizeInBits()));
1061 return std::make_pair(TypeIdx, T);
1062 });
1063 }
1064
1065 /// Conditionally narrow the scalar or elt to match the size of another.
maxScalarEltSameAsIf(LegalityPredicate Predicate,unsigned TypeIdx,unsigned SmallTypeIdx)1066 LegalizeRuleSet &maxScalarEltSameAsIf(LegalityPredicate Predicate,
1067 unsigned TypeIdx,
1068 unsigned SmallTypeIdx) {
1069 typeIdx(TypeIdx);
1070 return narrowScalarIf(
1071 [=](const LegalityQuery &Query) {
1072 return Query.Types[SmallTypeIdx].getScalarSizeInBits() <
1073 Query.Types[TypeIdx].getScalarSizeInBits() &&
1074 Predicate(Query);
1075 },
1076 [=](const LegalityQuery &Query) {
1077 LLT T = Query.Types[SmallTypeIdx];
1078 return std::make_pair(TypeIdx, T);
1079 });
1080 }
1081
1082 /// Add more elements to the vector to reach the next power of two.
1083 /// No effect if the type is not a vector or the element count is a power of
1084 /// two.
moreElementsToNextPow2(unsigned TypeIdx)1085 LegalizeRuleSet &moreElementsToNextPow2(unsigned TypeIdx) {
1086 using namespace LegalityPredicates;
1087 return actionIf(LegalizeAction::MoreElements,
1088 numElementsNotPow2(typeIdx(TypeIdx)),
1089 LegalizeMutations::moreElementsToNextPow2(TypeIdx));
1090 }
1091
1092 /// Limit the number of elements in EltTy vectors to at least MinElements.
clampMinNumElements(unsigned TypeIdx,const LLT EltTy,unsigned MinElements)1093 LegalizeRuleSet &clampMinNumElements(unsigned TypeIdx, const LLT EltTy,
1094 unsigned MinElements) {
1095 // Mark the type index as covered:
1096 typeIdx(TypeIdx);
1097 return actionIf(
1098 LegalizeAction::MoreElements,
1099 [=](const LegalityQuery &Query) {
1100 LLT VecTy = Query.Types[TypeIdx];
1101 return VecTy.isVector() && VecTy.getElementType() == EltTy &&
1102 VecTy.getNumElements() < MinElements;
1103 },
1104 [=](const LegalityQuery &Query) {
1105 LLT VecTy = Query.Types[TypeIdx];
1106 return std::make_pair(
1107 TypeIdx, LLT::fixed_vector(MinElements, VecTy.getElementType()));
1108 });
1109 }
1110
1111 /// Set number of elements to nearest larger multiple of NumElts.
alignNumElementsTo(unsigned TypeIdx,const LLT EltTy,unsigned NumElts)1112 LegalizeRuleSet &alignNumElementsTo(unsigned TypeIdx, const LLT EltTy,
1113 unsigned NumElts) {
1114 typeIdx(TypeIdx);
1115 return actionIf(
1116 LegalizeAction::MoreElements,
1117 [=](const LegalityQuery &Query) {
1118 LLT VecTy = Query.Types[TypeIdx];
1119 return VecTy.isVector() && VecTy.getElementType() == EltTy &&
1120 (VecTy.getNumElements() % NumElts != 0);
1121 },
1122 [=](const LegalityQuery &Query) {
1123 LLT VecTy = Query.Types[TypeIdx];
1124 unsigned NewSize = alignTo(VecTy.getNumElements(), NumElts);
1125 return std::make_pair(
1126 TypeIdx, LLT::fixed_vector(NewSize, VecTy.getElementType()));
1127 });
1128 }
1129
1130 /// Limit the number of elements in EltTy vectors to at most MaxElements.
clampMaxNumElements(unsigned TypeIdx,const LLT EltTy,unsigned MaxElements)1131 LegalizeRuleSet &clampMaxNumElements(unsigned TypeIdx, const LLT EltTy,
1132 unsigned MaxElements) {
1133 // Mark the type index as covered:
1134 typeIdx(TypeIdx);
1135 return actionIf(
1136 LegalizeAction::FewerElements,
1137 [=](const LegalityQuery &Query) {
1138 LLT VecTy = Query.Types[TypeIdx];
1139 return VecTy.isVector() && VecTy.getElementType() == EltTy &&
1140 VecTy.getNumElements() > MaxElements;
1141 },
1142 [=](const LegalityQuery &Query) {
1143 LLT VecTy = Query.Types[TypeIdx];
1144 LLT NewTy = LLT::scalarOrVector(ElementCount::getFixed(MaxElements),
1145 VecTy.getElementType());
1146 return std::make_pair(TypeIdx, NewTy);
1147 });
1148 }
1149 /// Limit the number of elements for the given vectors to at least MinTy's
1150 /// number of elements and at most MaxTy's number of elements.
1151 ///
1152 /// No effect if the type is not a vector or does not have the same element
1153 /// type as the constraints.
1154 /// The element type of MinTy and MaxTy must match.
clampNumElements(unsigned TypeIdx,const LLT MinTy,const LLT MaxTy)1155 LegalizeRuleSet &clampNumElements(unsigned TypeIdx, const LLT MinTy,
1156 const LLT MaxTy) {
1157 assert(MinTy.getElementType() == MaxTy.getElementType() &&
1158 "Expected element types to agree");
1159
1160 const LLT EltTy = MinTy.getElementType();
1161 return clampMinNumElements(TypeIdx, EltTy, MinTy.getNumElements())
1162 .clampMaxNumElements(TypeIdx, EltTy, MaxTy.getNumElements());
1163 }
1164
1165 /// Express \p EltTy vectors strictly using vectors with \p NumElts elements
1166 /// (or scalars when \p NumElts equals 1).
1167 /// First pad with undef elements to nearest larger multiple of \p NumElts.
1168 /// Then perform split with all sub-instructions having the same type.
1169 /// Using clampMaxNumElements (non-strict) can result in leftover instruction
1170 /// with different type (fewer elements then \p NumElts or scalar).
1171 /// No effect if the type is not a vector.
clampMaxNumElementsStrict(unsigned TypeIdx,const LLT EltTy,unsigned NumElts)1172 LegalizeRuleSet &clampMaxNumElementsStrict(unsigned TypeIdx, const LLT EltTy,
1173 unsigned NumElts) {
1174 return alignNumElementsTo(TypeIdx, EltTy, NumElts)
1175 .clampMaxNumElements(TypeIdx, EltTy, NumElts);
1176 }
1177
1178 /// Fallback on the previous implementation. This should only be used while
1179 /// porting a rule.
fallback()1180 LegalizeRuleSet &fallback() {
1181 add({always, LegalizeAction::UseLegacyRules});
1182 return *this;
1183 }
1184
1185 /// Check if there is no type index which is obviously not handled by the
1186 /// LegalizeRuleSet in any way at all.
1187 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set.
1188 bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const;
1189 /// Check if there is no imm index which is obviously not handled by the
1190 /// LegalizeRuleSet in any way at all.
1191 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set.
1192 bool verifyImmIdxsCoverage(unsigned NumImmIdxs) const;
1193
1194 /// Apply the ruleset to the given LegalityQuery.
1195 LegalizeActionStep apply(const LegalityQuery &Query) const;
1196 };
1197
1198 class LegalizerInfo {
1199 public:
1200 virtual ~LegalizerInfo() = default;
1201
getLegacyLegalizerInfo()1202 const LegacyLegalizerInfo &getLegacyLegalizerInfo() const {
1203 return LegacyInfo;
1204 }
getLegacyLegalizerInfo()1205 LegacyLegalizerInfo &getLegacyLegalizerInfo() { return LegacyInfo; }
1206
1207 unsigned getOpcodeIdxForOpcode(unsigned Opcode) const;
1208 unsigned getActionDefinitionsIdx(unsigned Opcode) const;
1209
1210 /// Perform simple self-diagnostic and assert if there is anything obviously
1211 /// wrong with the actions set up.
1212 void verify(const MCInstrInfo &MII) const;
1213
1214 /// Get the action definitions for the given opcode. Use this to run a
1215 /// LegalityQuery through the definitions.
1216 const LegalizeRuleSet &getActionDefinitions(unsigned Opcode) const;
1217
1218 /// Get the action definition builder for the given opcode. Use this to define
1219 /// the action definitions.
1220 ///
1221 /// It is an error to request an opcode that has already been requested by the
1222 /// multiple-opcode variant.
1223 LegalizeRuleSet &getActionDefinitionsBuilder(unsigned Opcode);
1224
1225 /// Get the action definition builder for the given set of opcodes. Use this
1226 /// to define the action definitions for multiple opcodes at once. The first
1227 /// opcode given will be considered the representative opcode and will hold
1228 /// the definitions whereas the other opcodes will be configured to refer to
1229 /// the representative opcode. This lowers memory requirements and very
1230 /// slightly improves performance.
1231 ///
1232 /// It would be very easy to introduce unexpected side-effects as a result of
1233 /// this aliasing if it were permitted to request different but intersecting
1234 /// sets of opcodes but that is difficult to keep track of. It is therefore an
1235 /// error to request the same opcode twice using this API, to request an
1236 /// opcode that already has definitions, or to use the single-opcode API on an
1237 /// opcode that has already been requested by this API.
1238 LegalizeRuleSet &
1239 getActionDefinitionsBuilder(std::initializer_list<unsigned> Opcodes);
1240 void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom);
1241
1242 /// Determine what action should be taken to legalize the described
1243 /// instruction. Requires computeTables to have been called.
1244 ///
1245 /// \returns a description of the next legalization step to perform.
1246 LegalizeActionStep getAction(const LegalityQuery &Query) const;
1247
1248 /// Determine what action should be taken to legalize the given generic
1249 /// instruction.
1250 ///
1251 /// \returns a description of the next legalization step to perform.
1252 LegalizeActionStep getAction(const MachineInstr &MI,
1253 const MachineRegisterInfo &MRI) const;
1254
isLegal(const LegalityQuery & Query)1255 bool isLegal(const LegalityQuery &Query) const {
1256 return getAction(Query).Action == LegalizeAction::Legal;
1257 }
1258
isLegalOrCustom(const LegalityQuery & Query)1259 bool isLegalOrCustom(const LegalityQuery &Query) const {
1260 auto Action = getAction(Query).Action;
1261 return Action == LegalizeAction::Legal || Action == LegalizeAction::Custom;
1262 }
1263
1264 bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
1265 bool isLegalOrCustom(const MachineInstr &MI,
1266 const MachineRegisterInfo &MRI) const;
1267
1268 /// Called for instructions with the Custom LegalizationAction.
legalizeCustom(LegalizerHelper & Helper,MachineInstr & MI)1269 virtual bool legalizeCustom(LegalizerHelper &Helper,
1270 MachineInstr &MI) const {
1271 llvm_unreachable("must implement this if custom action is used");
1272 }
1273
1274 /// \returns true if MI is either legal or has been legalized and false if not
1275 /// legal.
1276 /// Return true if MI is either legal or has been legalized and false
1277 /// if not legal.
legalizeIntrinsic(LegalizerHelper & Helper,MachineInstr & MI)1278 virtual bool legalizeIntrinsic(LegalizerHelper &Helper,
1279 MachineInstr &MI) const {
1280 return true;
1281 }
1282
1283 /// Return the opcode (SEXT/ZEXT/ANYEXT) that should be performed while
1284 /// widening a constant of type SmallTy which targets can override.
1285 /// For eg, the DAG does (SmallTy.isByteSized() ? G_SEXT : G_ZEXT) which
1286 /// will be the default.
1287 virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const;
1288
1289 private:
1290 static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
1291 static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
1292
1293 LegalizeRuleSet RulesForOpcode[LastOp - FirstOp + 1];
1294 LegacyLegalizerInfo LegacyInfo;
1295 };
1296
1297 #ifndef NDEBUG
1298 /// Checks that MIR is fully legal, returns an illegal instruction if it's not,
1299 /// nullptr otherwise
1300 const MachineInstr *machineFunctionIsIllegal(const MachineFunction &MF);
1301 #endif
1302
1303 } // end namespace llvm.
1304
1305 #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
1306