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 most as wide as Ty.
maxScalarOrElt(unsigned TypeIdx,const LLT Ty)954 LegalizeRuleSet &maxScalarOrElt(unsigned TypeIdx, const LLT Ty) {
955 using namespace LegalityPredicates;
956 using namespace LegalizeMutations;
957 return actionIf(LegalizeAction::NarrowScalar,
958 scalarOrEltWiderThan(TypeIdx, Ty.getScalarSizeInBits()),
959 changeElementTo(typeIdx(TypeIdx), Ty));
960 }
961
962 /// Ensure the scalar is at most as wide as Ty.
maxScalar(unsigned TypeIdx,const LLT Ty)963 LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT Ty) {
964 using namespace LegalityPredicates;
965 using namespace LegalizeMutations;
966 return actionIf(LegalizeAction::NarrowScalar,
967 scalarWiderThan(TypeIdx, Ty.getSizeInBits()),
968 changeTo(typeIdx(TypeIdx), Ty));
969 }
970
971 /// Conditionally limit the maximum size of the scalar.
972 /// For example, when the maximum size of one type depends on the size of
973 /// another such as extracting N bits from an M bit container.
maxScalarIf(LegalityPredicate Predicate,unsigned TypeIdx,const LLT Ty)974 LegalizeRuleSet &maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx,
975 const LLT Ty) {
976 using namespace LegalityPredicates;
977 using namespace LegalizeMutations;
978 return actionIf(
979 LegalizeAction::NarrowScalar,
980 [=](const LegalityQuery &Query) {
981 const LLT QueryTy = Query.Types[TypeIdx];
982 return QueryTy.isScalar() &&
983 QueryTy.getSizeInBits() > Ty.getSizeInBits() &&
984 Predicate(Query);
985 },
986 changeElementTo(typeIdx(TypeIdx), Ty));
987 }
988
989 /// Limit the range of scalar sizes to MinTy and MaxTy.
clampScalar(unsigned TypeIdx,const LLT MinTy,const LLT MaxTy)990 LegalizeRuleSet &clampScalar(unsigned TypeIdx, const LLT MinTy,
991 const LLT MaxTy) {
992 assert(MinTy.isScalar() && MaxTy.isScalar() && "Expected scalar types");
993 return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy);
994 }
995
996 /// Limit the range of scalar sizes to MinTy and MaxTy.
clampScalarOrElt(unsigned TypeIdx,const LLT MinTy,const LLT MaxTy)997 LegalizeRuleSet &clampScalarOrElt(unsigned TypeIdx, const LLT MinTy,
998 const LLT MaxTy) {
999 return minScalarOrElt(TypeIdx, MinTy).maxScalarOrElt(TypeIdx, MaxTy);
1000 }
1001
1002 /// Widen the scalar to match the size of another.
minScalarSameAs(unsigned TypeIdx,unsigned LargeTypeIdx)1003 LegalizeRuleSet &minScalarSameAs(unsigned TypeIdx, unsigned LargeTypeIdx) {
1004 typeIdx(TypeIdx);
1005 return widenScalarIf(
1006 [=](const LegalityQuery &Query) {
1007 return Query.Types[LargeTypeIdx].getScalarSizeInBits() >
1008 Query.Types[TypeIdx].getSizeInBits();
1009 },
1010 LegalizeMutations::changeElementSizeTo(TypeIdx, LargeTypeIdx));
1011 }
1012
1013 /// Narrow the scalar to match the size of another.
maxScalarSameAs(unsigned TypeIdx,unsigned NarrowTypeIdx)1014 LegalizeRuleSet &maxScalarSameAs(unsigned TypeIdx, unsigned NarrowTypeIdx) {
1015 typeIdx(TypeIdx);
1016 return narrowScalarIf(
1017 [=](const LegalityQuery &Query) {
1018 return Query.Types[NarrowTypeIdx].getScalarSizeInBits() <
1019 Query.Types[TypeIdx].getSizeInBits();
1020 },
1021 LegalizeMutations::changeElementSizeTo(TypeIdx, NarrowTypeIdx));
1022 }
1023
1024 /// Change the type \p TypeIdx to have the same scalar size as type \p
1025 /// SameSizeIdx.
scalarSameSizeAs(unsigned TypeIdx,unsigned SameSizeIdx)1026 LegalizeRuleSet &scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx) {
1027 return minScalarSameAs(TypeIdx, SameSizeIdx)
1028 .maxScalarSameAs(TypeIdx, SameSizeIdx);
1029 }
1030
1031 /// Conditionally widen the scalar or elt to match the size of another.
minScalarEltSameAsIf(LegalityPredicate Predicate,unsigned TypeIdx,unsigned LargeTypeIdx)1032 LegalizeRuleSet &minScalarEltSameAsIf(LegalityPredicate Predicate,
1033 unsigned TypeIdx, unsigned LargeTypeIdx) {
1034 typeIdx(TypeIdx);
1035 return widenScalarIf(
1036 [=](const LegalityQuery &Query) {
1037 return Query.Types[LargeTypeIdx].getScalarSizeInBits() >
1038 Query.Types[TypeIdx].getScalarSizeInBits() &&
1039 Predicate(Query);
1040 },
1041 [=](const LegalityQuery &Query) {
1042 LLT T = Query.Types[LargeTypeIdx];
1043 return std::make_pair(TypeIdx, T);
1044 });
1045 }
1046
1047 /// Conditionally narrow the scalar or elt to match the size of another.
maxScalarEltSameAsIf(LegalityPredicate Predicate,unsigned TypeIdx,unsigned SmallTypeIdx)1048 LegalizeRuleSet &maxScalarEltSameAsIf(LegalityPredicate Predicate,
1049 unsigned TypeIdx,
1050 unsigned SmallTypeIdx) {
1051 typeIdx(TypeIdx);
1052 return narrowScalarIf(
1053 [=](const LegalityQuery &Query) {
1054 return Query.Types[SmallTypeIdx].getScalarSizeInBits() <
1055 Query.Types[TypeIdx].getScalarSizeInBits() &&
1056 Predicate(Query);
1057 },
1058 [=](const LegalityQuery &Query) {
1059 LLT T = Query.Types[SmallTypeIdx];
1060 return std::make_pair(TypeIdx, T);
1061 });
1062 }
1063
1064 /// Add more elements to the vector to reach the next power of two.
1065 /// No effect if the type is not a vector or the element count is a power of
1066 /// two.
moreElementsToNextPow2(unsigned TypeIdx)1067 LegalizeRuleSet &moreElementsToNextPow2(unsigned TypeIdx) {
1068 using namespace LegalityPredicates;
1069 return actionIf(LegalizeAction::MoreElements,
1070 numElementsNotPow2(typeIdx(TypeIdx)),
1071 LegalizeMutations::moreElementsToNextPow2(TypeIdx));
1072 }
1073
1074 /// Limit the number of elements in EltTy vectors to at least MinElements.
clampMinNumElements(unsigned TypeIdx,const LLT EltTy,unsigned MinElements)1075 LegalizeRuleSet &clampMinNumElements(unsigned TypeIdx, const LLT EltTy,
1076 unsigned MinElements) {
1077 // Mark the type index as covered:
1078 typeIdx(TypeIdx);
1079 return actionIf(
1080 LegalizeAction::MoreElements,
1081 [=](const LegalityQuery &Query) {
1082 LLT VecTy = Query.Types[TypeIdx];
1083 return VecTy.isVector() && VecTy.getElementType() == EltTy &&
1084 VecTy.getNumElements() < MinElements;
1085 },
1086 [=](const LegalityQuery &Query) {
1087 LLT VecTy = Query.Types[TypeIdx];
1088 return std::make_pair(
1089 TypeIdx, LLT::fixed_vector(MinElements, VecTy.getElementType()));
1090 });
1091 }
1092
1093 /// Set number of elements to nearest larger multiple of NumElts.
alignNumElementsTo(unsigned TypeIdx,const LLT EltTy,unsigned NumElts)1094 LegalizeRuleSet &alignNumElementsTo(unsigned TypeIdx, const LLT EltTy,
1095 unsigned NumElts) {
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() % NumElts != 0);
1103 },
1104 [=](const LegalityQuery &Query) {
1105 LLT VecTy = Query.Types[TypeIdx];
1106 unsigned NewSize = alignTo(VecTy.getNumElements(), NumElts);
1107 return std::make_pair(
1108 TypeIdx, LLT::fixed_vector(NewSize, VecTy.getElementType()));
1109 });
1110 }
1111
1112 /// Limit the number of elements in EltTy vectors to at most MaxElements.
clampMaxNumElements(unsigned TypeIdx,const LLT EltTy,unsigned MaxElements)1113 LegalizeRuleSet &clampMaxNumElements(unsigned TypeIdx, const LLT EltTy,
1114 unsigned MaxElements) {
1115 // Mark the type index as covered:
1116 typeIdx(TypeIdx);
1117 return actionIf(
1118 LegalizeAction::FewerElements,
1119 [=](const LegalityQuery &Query) {
1120 LLT VecTy = Query.Types[TypeIdx];
1121 return VecTy.isVector() && VecTy.getElementType() == EltTy &&
1122 VecTy.getNumElements() > MaxElements;
1123 },
1124 [=](const LegalityQuery &Query) {
1125 LLT VecTy = Query.Types[TypeIdx];
1126 LLT NewTy = LLT::scalarOrVector(ElementCount::getFixed(MaxElements),
1127 VecTy.getElementType());
1128 return std::make_pair(TypeIdx, NewTy);
1129 });
1130 }
1131 /// Limit the number of elements for the given vectors to at least MinTy's
1132 /// number of elements and at most MaxTy's number of elements.
1133 ///
1134 /// No effect if the type is not a vector or does not have the same element
1135 /// type as the constraints.
1136 /// The element type of MinTy and MaxTy must match.
clampNumElements(unsigned TypeIdx,const LLT MinTy,const LLT MaxTy)1137 LegalizeRuleSet &clampNumElements(unsigned TypeIdx, const LLT MinTy,
1138 const LLT MaxTy) {
1139 assert(MinTy.getElementType() == MaxTy.getElementType() &&
1140 "Expected element types to agree");
1141
1142 const LLT EltTy = MinTy.getElementType();
1143 return clampMinNumElements(TypeIdx, EltTy, MinTy.getNumElements())
1144 .clampMaxNumElements(TypeIdx, EltTy, MaxTy.getNumElements());
1145 }
1146
1147 /// Express \p EltTy vectors strictly using vectors with \p NumElts elements
1148 /// (or scalars when \p NumElts equals 1).
1149 /// First pad with undef elements to nearest larger multiple of \p NumElts.
1150 /// Then perform split with all sub-instructions having the same type.
1151 /// Using clampMaxNumElements (non-strict) can result in leftover instruction
1152 /// with different type (fewer elements then \p NumElts or scalar).
1153 /// No effect if the type is not a vector.
clampMaxNumElementsStrict(unsigned TypeIdx,const LLT EltTy,unsigned NumElts)1154 LegalizeRuleSet &clampMaxNumElementsStrict(unsigned TypeIdx, const LLT EltTy,
1155 unsigned NumElts) {
1156 return alignNumElementsTo(TypeIdx, EltTy, NumElts)
1157 .clampMaxNumElements(TypeIdx, EltTy, NumElts);
1158 }
1159
1160 /// Fallback on the previous implementation. This should only be used while
1161 /// porting a rule.
fallback()1162 LegalizeRuleSet &fallback() {
1163 add({always, LegalizeAction::UseLegacyRules});
1164 return *this;
1165 }
1166
1167 /// Check if there is no type index which is obviously not handled by the
1168 /// LegalizeRuleSet in any way at all.
1169 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set.
1170 bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const;
1171 /// Check if there is no imm index which is obviously not handled by the
1172 /// LegalizeRuleSet in any way at all.
1173 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set.
1174 bool verifyImmIdxsCoverage(unsigned NumImmIdxs) const;
1175
1176 /// Apply the ruleset to the given LegalityQuery.
1177 LegalizeActionStep apply(const LegalityQuery &Query) const;
1178 };
1179
1180 class LegalizerInfo {
1181 public:
1182 virtual ~LegalizerInfo() = default;
1183
getLegacyLegalizerInfo()1184 const LegacyLegalizerInfo &getLegacyLegalizerInfo() const {
1185 return LegacyInfo;
1186 }
getLegacyLegalizerInfo()1187 LegacyLegalizerInfo &getLegacyLegalizerInfo() { return LegacyInfo; }
1188
1189 unsigned getOpcodeIdxForOpcode(unsigned Opcode) const;
1190 unsigned getActionDefinitionsIdx(unsigned Opcode) const;
1191
1192 /// Perform simple self-diagnostic and assert if there is anything obviously
1193 /// wrong with the actions set up.
1194 void verify(const MCInstrInfo &MII) const;
1195
1196 /// Get the action definitions for the given opcode. Use this to run a
1197 /// LegalityQuery through the definitions.
1198 const LegalizeRuleSet &getActionDefinitions(unsigned Opcode) const;
1199
1200 /// Get the action definition builder for the given opcode. Use this to define
1201 /// the action definitions.
1202 ///
1203 /// It is an error to request an opcode that has already been requested by the
1204 /// multiple-opcode variant.
1205 LegalizeRuleSet &getActionDefinitionsBuilder(unsigned Opcode);
1206
1207 /// Get the action definition builder for the given set of opcodes. Use this
1208 /// to define the action definitions for multiple opcodes at once. The first
1209 /// opcode given will be considered the representative opcode and will hold
1210 /// the definitions whereas the other opcodes will be configured to refer to
1211 /// the representative opcode. This lowers memory requirements and very
1212 /// slightly improves performance.
1213 ///
1214 /// It would be very easy to introduce unexpected side-effects as a result of
1215 /// this aliasing if it were permitted to request different but intersecting
1216 /// sets of opcodes but that is difficult to keep track of. It is therefore an
1217 /// error to request the same opcode twice using this API, to request an
1218 /// opcode that already has definitions, or to use the single-opcode API on an
1219 /// opcode that has already been requested by this API.
1220 LegalizeRuleSet &
1221 getActionDefinitionsBuilder(std::initializer_list<unsigned> Opcodes);
1222 void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom);
1223
1224 /// Determine what action should be taken to legalize the described
1225 /// instruction. Requires computeTables to have been called.
1226 ///
1227 /// \returns a description of the next legalization step to perform.
1228 LegalizeActionStep getAction(const LegalityQuery &Query) const;
1229
1230 /// Determine what action should be taken to legalize the given generic
1231 /// instruction.
1232 ///
1233 /// \returns a description of the next legalization step to perform.
1234 LegalizeActionStep getAction(const MachineInstr &MI,
1235 const MachineRegisterInfo &MRI) const;
1236
isLegal(const LegalityQuery & Query)1237 bool isLegal(const LegalityQuery &Query) const {
1238 return getAction(Query).Action == LegalizeAction::Legal;
1239 }
1240
isLegalOrCustom(const LegalityQuery & Query)1241 bool isLegalOrCustom(const LegalityQuery &Query) const {
1242 auto Action = getAction(Query).Action;
1243 return Action == LegalizeAction::Legal || Action == LegalizeAction::Custom;
1244 }
1245
1246 bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
1247 bool isLegalOrCustom(const MachineInstr &MI,
1248 const MachineRegisterInfo &MRI) const;
1249
1250 /// Called for instructions with the Custom LegalizationAction.
legalizeCustom(LegalizerHelper & Helper,MachineInstr & MI)1251 virtual bool legalizeCustom(LegalizerHelper &Helper,
1252 MachineInstr &MI) const {
1253 llvm_unreachable("must implement this if custom action is used");
1254 }
1255
1256 /// \returns true if MI is either legal or has been legalized and false if not
1257 /// legal.
1258 /// Return true if MI is either legal or has been legalized and false
1259 /// if not legal.
legalizeIntrinsic(LegalizerHelper & Helper,MachineInstr & MI)1260 virtual bool legalizeIntrinsic(LegalizerHelper &Helper,
1261 MachineInstr &MI) const {
1262 return true;
1263 }
1264
1265 /// Return the opcode (SEXT/ZEXT/ANYEXT) that should be performed while
1266 /// widening a constant of type SmallTy which targets can override.
1267 /// For eg, the DAG does (SmallTy.isByteSized() ? G_SEXT : G_ZEXT) which
1268 /// will be the default.
1269 virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const;
1270
1271 private:
1272 static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
1273 static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
1274
1275 LegalizeRuleSet RulesForOpcode[LastOp - FirstOp + 1];
1276 LegacyLegalizerInfo LegacyInfo;
1277 };
1278
1279 #ifndef NDEBUG
1280 /// Checks that MIR is fully legal, returns an illegal instruction if it's not,
1281 /// nullptr otherwise
1282 const MachineInstr *machineFunctionIsIllegal(const MachineFunction &MF);
1283 #endif
1284
1285 } // end namespace llvm.
1286
1287 #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
1288