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