123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- llvm/CodeGen/GlobalISel/LegalizerInfo.h ------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- /// \file
- /// Interface for Targets to specify which operations they can successfully
- /// select and how the others should be expanded most efficiently.
- ///
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
- #define LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
- #include "llvm/ADT/DenseMap.h"
- #include "llvm/ADT/STLExtras.h"
- #include "llvm/ADT/SmallBitVector.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h"
- #include "llvm/CodeGen/MachineFunction.h"
- #include "llvm/CodeGen/TargetOpcodes.h"
- #include "llvm/Support/CommandLine.h"
- #include "llvm/Support/LowLevelTypeImpl.h"
- #include "llvm/Support/raw_ostream.h"
- #include <cassert>
- #include <cstdint>
- #include <tuple>
- #include <unordered_map>
- #include <utility>
- namespace llvm {
- extern cl::opt<bool> DisableGISelLegalityCheck;
- class LegalizerHelper;
- class MachineInstr;
- class MachineRegisterInfo;
- class MCInstrInfo;
- namespace LegalizeActions {
- enum LegalizeAction : std::uint8_t {
- /// The operation is expected to be selectable directly by the target, and
- /// no transformation is necessary.
- Legal,
- /// The operation should be synthesized from multiple instructions acting on
- /// a narrower scalar base-type. For example a 64-bit add might be
- /// implemented in terms of 32-bit add-with-carry.
- NarrowScalar,
- /// The operation should be implemented in terms of a wider scalar
- /// base-type. For example a <2 x s8> add could be implemented as a <2
- /// x s32> add (ignoring the high bits).
- WidenScalar,
- /// The (vector) operation should be implemented by splitting it into
- /// sub-vectors where the operation is legal. For example a <8 x s64> add
- /// might be implemented as 4 separate <2 x s64> adds. There can be a leftover
- /// if there are not enough elements for last sub-vector e.g. <7 x s64> add
- /// will be implemented as 3 separate <2 x s64> adds and one s64 add. Leftover
- /// types can be avoided by doing MoreElements first.
- FewerElements,
- /// The (vector) operation should be implemented by widening the input
- /// vector and ignoring the lanes added by doing so. For example <2 x i8> is
- /// rarely legal, but you might perform an <8 x i8> and then only look at
- /// the first two results.
- MoreElements,
- /// Perform the operation on a different, but equivalently sized type.
- Bitcast,
- /// The operation itself must be expressed in terms of simpler actions on
- /// this target. E.g. a SREM replaced by an SDIV and subtraction.
- Lower,
- /// The operation should be implemented as a call to some kind of runtime
- /// support library. For example this usually happens on machines that don't
- /// support floating-point operations natively.
- Libcall,
- /// The target wants to do something special with this combination of
- /// operand and type. A callback will be issued when it is needed.
- Custom,
- /// This operation is completely unsupported on the target. A programming
- /// error has occurred.
- Unsupported,
- /// Sentinel value for when no action was found in the specified table.
- NotFound,
- /// Fall back onto the old rules.
- /// TODO: Remove this once we've migrated
- UseLegacyRules,
- };
- } // end namespace LegalizeActions
- raw_ostream &operator<<(raw_ostream &OS, LegalizeActions::LegalizeAction Action);
- using LegalizeActions::LegalizeAction;
- /// The LegalityQuery object bundles together all the information that's needed
- /// to decide whether a given operation is legal or not.
- /// For efficiency, it doesn't make a copy of Types so care must be taken not
- /// to free it before using the query.
- struct LegalityQuery {
- unsigned Opcode;
- ArrayRef<LLT> Types;
- struct MemDesc {
- LLT MemoryTy;
- uint64_t AlignInBits;
- AtomicOrdering Ordering;
- MemDesc() = default;
- MemDesc(LLT MemoryTy, uint64_t AlignInBits, AtomicOrdering Ordering)
- : MemoryTy(MemoryTy), AlignInBits(AlignInBits), Ordering(Ordering) {}
- MemDesc(const MachineMemOperand &MMO)
- : MemoryTy(MMO.getMemoryType()),
- AlignInBits(MMO.getAlign().value() * 8),
- Ordering(MMO.getSuccessOrdering()) {}
- };
- /// Operations which require memory can use this to place requirements on the
- /// memory type for each MMO.
- ArrayRef<MemDesc> MMODescrs;
- constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types,
- const ArrayRef<MemDesc> MMODescrs)
- : Opcode(Opcode), Types(Types), MMODescrs(MMODescrs) {}
- constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types)
- : LegalityQuery(Opcode, Types, {}) {}
- raw_ostream &print(raw_ostream &OS) const;
- };
- /// The result of a query. It either indicates a final answer of Legal or
- /// Unsupported or describes an action that must be taken to make an operation
- /// more legal.
- struct LegalizeActionStep {
- /// The action to take or the final answer.
- LegalizeAction Action;
- /// If describing an action, the type index to change. Otherwise zero.
- unsigned TypeIdx;
- /// If describing an action, the new type for TypeIdx. Otherwise LLT{}.
- LLT NewType;
- LegalizeActionStep(LegalizeAction Action, unsigned TypeIdx,
- const LLT NewType)
- : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {}
- LegalizeActionStep(LegacyLegalizeActionStep Step)
- : TypeIdx(Step.TypeIdx), NewType(Step.NewType) {
- switch (Step.Action) {
- case LegacyLegalizeActions::Legal:
- Action = LegalizeActions::Legal;
- break;
- case LegacyLegalizeActions::NarrowScalar:
- Action = LegalizeActions::NarrowScalar;
- break;
- case LegacyLegalizeActions::WidenScalar:
- Action = LegalizeActions::WidenScalar;
- break;
- case LegacyLegalizeActions::FewerElements:
- Action = LegalizeActions::FewerElements;
- break;
- case LegacyLegalizeActions::MoreElements:
- Action = LegalizeActions::MoreElements;
- break;
- case LegacyLegalizeActions::Bitcast:
- Action = LegalizeActions::Bitcast;
- break;
- case LegacyLegalizeActions::Lower:
- Action = LegalizeActions::Lower;
- break;
- case LegacyLegalizeActions::Libcall:
- Action = LegalizeActions::Libcall;
- break;
- case LegacyLegalizeActions::Custom:
- Action = LegalizeActions::Custom;
- break;
- case LegacyLegalizeActions::Unsupported:
- Action = LegalizeActions::Unsupported;
- break;
- case LegacyLegalizeActions::NotFound:
- Action = LegalizeActions::NotFound;
- break;
- }
- }
- bool operator==(const LegalizeActionStep &RHS) const {
- return std::tie(Action, TypeIdx, NewType) ==
- std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType);
- }
- };
- using LegalityPredicate = std::function<bool (const LegalityQuery &)>;
- using LegalizeMutation =
- std::function<std::pair<unsigned, LLT>(const LegalityQuery &)>;
- namespace LegalityPredicates {
- struct TypePairAndMemDesc {
- LLT Type0;
- LLT Type1;
- LLT MemTy;
- uint64_t Align;
- bool operator==(const TypePairAndMemDesc &Other) const {
- return Type0 == Other.Type0 && Type1 == Other.Type1 &&
- Align == Other.Align && MemTy == Other.MemTy;
- }
- /// \returns true if this memory access is legal with for the access described
- /// by \p Other (The alignment is sufficient for the size and result type).
- bool isCompatible(const TypePairAndMemDesc &Other) const {
- return Type0 == Other.Type0 && Type1 == Other.Type1 &&
- Align >= Other.Align &&
- // FIXME: This perhaps should be stricter, but the current legality
- // rules are written only considering the size.
- MemTy.getSizeInBits() == Other.MemTy.getSizeInBits();
- }
- };
- /// True iff P0 and P1 are true.
- template<typename Predicate>
- Predicate all(Predicate P0, Predicate P1) {
- return [=](const LegalityQuery &Query) {
- return P0(Query) && P1(Query);
- };
- }
- /// True iff all given predicates are true.
- template<typename Predicate, typename... Args>
- Predicate all(Predicate P0, Predicate P1, Args... args) {
- return all(all(P0, P1), args...);
- }
- /// True iff P0 or P1 are true.
- template<typename Predicate>
- Predicate any(Predicate P0, Predicate P1) {
- return [=](const LegalityQuery &Query) {
- return P0(Query) || P1(Query);
- };
- }
- /// True iff any given predicates are true.
- template<typename Predicate, typename... Args>
- Predicate any(Predicate P0, Predicate P1, Args... args) {
- return any(any(P0, P1), args...);
- }
- /// True iff the given type index is the specified type.
- LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit);
- /// True iff the given type index is one of the specified types.
- LegalityPredicate typeInSet(unsigned TypeIdx,
- std::initializer_list<LLT> TypesInit);
- /// True iff the given type index is not the specified type.
- inline LegalityPredicate typeIsNot(unsigned TypeIdx, LLT Type) {
- return [=](const LegalityQuery &Query) {
- return Query.Types[TypeIdx] != Type;
- };
- }
- /// True iff the given types for the given pair of type indexes is one of the
- /// specified type pairs.
- 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 typePairAndMemDescInSet(
- unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx,
- std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit);
- /// True iff the specified type index is a scalar.
- LegalityPredicate isScalar(unsigned TypeIdx);
- /// True iff the specified type index is a vector.
- LegalityPredicate isVector(unsigned TypeIdx);
- /// True iff the specified type index is a pointer (with any address space).
- LegalityPredicate isPointer(unsigned TypeIdx);
- /// True iff the specified type index is a pointer with the specified address
- /// space.
- LegalityPredicate isPointer(unsigned TypeIdx, unsigned AddrSpace);
- /// True if the type index is a vector with element type \p EltTy
- LegalityPredicate elementTypeIs(unsigned TypeIdx, LLT EltTy);
- /// True iff the specified type index is a scalar that's narrower than the given
- /// size.
- LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size);
- /// True iff the specified type index is a scalar that's wider than the given
- /// size.
- LegalityPredicate scalarWiderThan(unsigned TypeIdx, unsigned Size);
- /// True iff the specified type index is a scalar or vector with an element type
- /// that's narrower than the given size.
- LegalityPredicate scalarOrEltNarrowerThan(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 given size.
- LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size);
- /// True iff the specified type index is a scalar whose size is not a multiple
- /// of Size.
- LegalityPredicate sizeNotMultipleOf(unsigned TypeIdx, unsigned Size);
- /// True iff the specified type index is a scalar whose size is not a power of
- /// 2.
- LegalityPredicate sizeNotPow2(unsigned TypeIdx);
- /// True iff the specified type index is a scalar or vector whose element size
- /// is not a power of 2.
- LegalityPredicate scalarOrEltSizeNotPow2(unsigned TypeIdx);
- /// True if the total bitwidth of the specified type index is \p Size bits.
- LegalityPredicate sizeIs(unsigned TypeIdx, unsigned Size);
- /// True iff the specified type indices are both the same bit size.
- LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1);
- /// True iff the first type index has a larger total bit size than second type
- /// index.
- LegalityPredicate largerThan(unsigned TypeIdx0, unsigned TypeIdx1);
- /// True iff the first type index has a smaller total bit size than second type
- /// index.
- LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1);
- /// True iff the specified MMO index has a size that is not a power of 2
- LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx);
- /// True iff the specified type index is a vector whose element count is not a
- /// power of 2.
- LegalityPredicate numElementsNotPow2(unsigned TypeIdx);
- /// True iff the specified MMO index has at an atomic ordering of at Ordering or
- /// stronger.
- LegalityPredicate atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx,
- AtomicOrdering Ordering);
- } // end namespace LegalityPredicates
- namespace LegalizeMutations {
- /// Select this specific type for the given type index.
- LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty);
- /// Keep the same type as the given type index.
- LegalizeMutation changeTo(unsigned TypeIdx, unsigned FromTypeIdx);
- /// Keep the same scalar or element type as the given type index.
- LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx);
- /// Keep the same scalar or element type as the given type.
- LegalizeMutation changeElementTo(unsigned TypeIdx, LLT Ty);
- /// Change the scalar size or element size to have the same scalar size as type
- /// index \p FromIndex. Unlike changeElementTo, this discards pointer types and
- /// only changes the size.
- LegalizeMutation changeElementSizeTo(unsigned TypeIdx, unsigned FromTypeIdx);
- /// Widen the scalar type or vector element type for the given type index to the
- /// next power of 2.
- LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min = 0);
- /// Widen the scalar type or vector element type for the given type index to
- /// next multiple of \p Size.
- LegalizeMutation widenScalarOrEltToNextMultipleOf(unsigned TypeIdx,
- unsigned Size);
- /// Add more elements to the type for the given type index to the next power of
- /// 2.
- LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min = 0);
- /// Break up the vector type for the given type index into the element type.
- LegalizeMutation scalarize(unsigned TypeIdx);
- } // end namespace LegalizeMutations
- /// A single rule in a legalizer info ruleset.
- /// The specified action is chosen when the predicate is true. Where appropriate
- /// for the action (e.g. for WidenScalar) the new type is selected using the
- /// given mutator.
- class LegalizeRule {
- LegalityPredicate Predicate;
- LegalizeAction Action;
- LegalizeMutation Mutation;
- public:
- LegalizeRule(LegalityPredicate Predicate, LegalizeAction Action,
- LegalizeMutation Mutation = nullptr)
- : Predicate(Predicate), Action(Action), Mutation(Mutation) {}
- /// Test whether the LegalityQuery matches.
- bool match(const LegalityQuery &Query) const {
- return Predicate(Query);
- }
- LegalizeAction getAction() const { return Action; }
- /// Determine the change to make.
- std::pair<unsigned, LLT> determineMutation(const LegalityQuery &Query) const {
- if (Mutation)
- return Mutation(Query);
- return std::make_pair(0, LLT{});
- }
- };
- class LegalizeRuleSet {
- /// When non-zero, the opcode we are an alias of
- unsigned AliasOf = 0;
- /// If true, there is another opcode that aliases this one
- bool IsAliasedByAnother = false;
- SmallVector<LegalizeRule, 2> Rules;
- #ifndef NDEBUG
- /// If bit I is set, this rule set contains a rule that may handle (predicate
- /// or perform an action upon (or both)) the type index I. The uncertainty
- /// comes from free-form rules executing user-provided lambda functions. We
- /// conservatively assume such rules do the right thing and cover all type
- /// indices. The bitset is intentionally 1 bit wider than it absolutely needs
- /// to be to distinguish such cases from the cases where all type indices are
- /// individually handled.
- SmallBitVector TypeIdxsCovered{MCOI::OPERAND_LAST_GENERIC -
- MCOI::OPERAND_FIRST_GENERIC + 2};
- SmallBitVector ImmIdxsCovered{MCOI::OPERAND_LAST_GENERIC_IMM -
- MCOI::OPERAND_FIRST_GENERIC_IMM + 2};
- #endif
- unsigned typeIdx(unsigned TypeIdx) {
- assert(TypeIdx <=
- (MCOI::OPERAND_LAST_GENERIC - MCOI::OPERAND_FIRST_GENERIC) &&
- "Type Index is out of bounds");
- #ifndef NDEBUG
- TypeIdxsCovered.set(TypeIdx);
- #endif
- return TypeIdx;
- }
- void markAllIdxsAsCovered() {
- #ifndef NDEBUG
- TypeIdxsCovered.set();
- ImmIdxsCovered.set();
- #endif
- }
- void add(const LegalizeRule &Rule) {
- assert(AliasOf == 0 &&
- "RuleSet is aliased, change the representative opcode instead");
- Rules.push_back(Rule);
- }
- static bool always(const LegalityQuery &) { return true; }
- /// Use the given action when the predicate is true.
- /// Action should not be an action that requires mutation.
- LegalizeRuleSet &actionIf(LegalizeAction Action,
- LegalityPredicate Predicate) {
- add({Predicate, Action});
- return *this;
- }
- /// Use the given action when the predicate is true.
- /// Action should be an action that requires mutation.
- LegalizeRuleSet &actionIf(LegalizeAction Action, LegalityPredicate Predicate,
- LegalizeMutation Mutation) {
- add({Predicate, Action, Mutation});
- return *this;
- }
- /// Use the given action when type index 0 is any type in the given list.
- /// Action should not be an action that requires mutation.
- LegalizeRuleSet &actionFor(LegalizeAction Action,
- std::initializer_list<LLT> Types) {
- using namespace LegalityPredicates;
- return actionIf(Action, typeInSet(typeIdx(0), Types));
- }
- /// Use the given action when type index 0 is any type in the given list.
- /// Action should be an action that requires mutation.
- LegalizeRuleSet &actionFor(LegalizeAction Action,
- std::initializer_list<LLT> Types,
- LegalizeMutation Mutation) {
- using namespace LegalityPredicates;
- return actionIf(Action, typeInSet(typeIdx(0), Types), Mutation);
- }
- /// Use the given action when type indexes 0 and 1 is any type pair in the
- /// given list.
- /// Action should not be an action that requires mutation.
- LegalizeRuleSet &actionFor(LegalizeAction Action,
- std::initializer_list<std::pair<LLT, LLT>> Types) {
- using namespace LegalityPredicates;
- return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types));
- }
- /// Use the given action when type indexes 0 and 1 is any type pair in the
- /// given list.
- /// Action should be an action that requires mutation.
- LegalizeRuleSet &actionFor(LegalizeAction Action,
- std::initializer_list<std::pair<LLT, LLT>> Types,
- LegalizeMutation Mutation) {
- using namespace LegalityPredicates;
- return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types),
- Mutation);
- }
- /// Use the given action when type index 0 is any type in the given list and
- /// imm index 0 is anything. Action should not be an action that requires
- /// mutation.
- LegalizeRuleSet &actionForTypeWithAnyImm(LegalizeAction Action,
- std::initializer_list<LLT> Types) {
- using namespace LegalityPredicates;
- immIdx(0); // Inform verifier imm idx 0 is handled.
- return actionIf(Action, typeInSet(typeIdx(0), Types));
- }
- LegalizeRuleSet &actionForTypeWithAnyImm(
- LegalizeAction Action, std::initializer_list<std::pair<LLT, LLT>> Types) {
- using namespace LegalityPredicates;
- immIdx(0); // Inform verifier imm idx 0 is handled.
- return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types));
- }
- /// Use the given action when type indexes 0 and 1 are both in the given list.
- /// That is, the type pair is in the cartesian product of the list.
- /// Action should not be an action that requires mutation.
- LegalizeRuleSet &actionForCartesianProduct(LegalizeAction Action,
- std::initializer_list<LLT> Types) {
- using namespace LegalityPredicates;
- return actionIf(Action, all(typeInSet(typeIdx(0), Types),
- typeInSet(typeIdx(1), Types)));
- }
- /// Use the given action when type indexes 0 and 1 are both in their
- /// respective lists.
- /// That is, the type pair is in the cartesian product of the lists
- /// Action should not be an action that requires mutation.
- LegalizeRuleSet &
- actionForCartesianProduct(LegalizeAction Action,
- std::initializer_list<LLT> Types0,
- std::initializer_list<LLT> Types1) {
- using namespace LegalityPredicates;
- return actionIf(Action, all(typeInSet(typeIdx(0), Types0),
- typeInSet(typeIdx(1), Types1)));
- }
- /// Use the given action when type indexes 0, 1, and 2 are all in their
- /// respective lists.
- /// That is, the type triple is in the cartesian product of the lists
- /// Action should not be an action that requires mutation.
- LegalizeRuleSet &actionForCartesianProduct(
- LegalizeAction Action, std::initializer_list<LLT> Types0,
- std::initializer_list<LLT> Types1, std::initializer_list<LLT> Types2) {
- using namespace LegalityPredicates;
- return actionIf(Action, all(typeInSet(typeIdx(0), Types0),
- all(typeInSet(typeIdx(1), Types1),
- typeInSet(typeIdx(2), Types2))));
- }
- public:
- LegalizeRuleSet() = default;
- bool isAliasedByAnother() { return IsAliasedByAnother; }
- void setIsAliasedByAnother() { IsAliasedByAnother = true; }
- void aliasTo(unsigned Opcode) {
- assert((AliasOf == 0 || AliasOf == Opcode) &&
- "Opcode is already aliased to another opcode");
- assert(Rules.empty() && "Aliasing will discard rules");
- AliasOf = Opcode;
- }
- unsigned getAlias() const { return AliasOf; }
- unsigned immIdx(unsigned ImmIdx) {
- assert(ImmIdx <= (MCOI::OPERAND_LAST_GENERIC_IMM -
- MCOI::OPERAND_FIRST_GENERIC_IMM) &&
- "Imm Index is out of bounds");
- #ifndef NDEBUG
- ImmIdxsCovered.set(ImmIdx);
- #endif
- return ImmIdx;
- }
- /// The instruction is legal if predicate is true.
- LegalizeRuleSet &legalIf(LegalityPredicate Predicate) {
- // We have no choice but conservatively assume that the free-form
- // user-provided Predicate properly handles all type indices:
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::Legal, Predicate);
- }
- /// The instruction is legal when type index 0 is any type in the given list.
- LegalizeRuleSet &legalFor(std::initializer_list<LLT> Types) {
- return actionFor(LegalizeAction::Legal, Types);
- }
- /// The instruction is legal when type indexes 0 and 1 is any type pair in the
- /// given list.
- LegalizeRuleSet &legalFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
- return actionFor(LegalizeAction::Legal, Types);
- }
- /// The instruction is legal when type index 0 is any type in the given list
- /// and imm index 0 is anything.
- LegalizeRuleSet &legalForTypeWithAnyImm(std::initializer_list<LLT> Types) {
- markAllIdxsAsCovered();
- return actionForTypeWithAnyImm(LegalizeAction::Legal, Types);
- }
- LegalizeRuleSet &legalForTypeWithAnyImm(
- std::initializer_list<std::pair<LLT, LLT>> Types) {
- markAllIdxsAsCovered();
- return actionForTypeWithAnyImm(LegalizeAction::Legal, Types);
- }
- /// The instruction is legal when type indexes 0 and 1 along with the memory
- /// size and minimum alignment is any type and size tuple in the given list.
- LegalizeRuleSet &legalForTypesWithMemDesc(
- std::initializer_list<LegalityPredicates::TypePairAndMemDesc>
- TypesAndMemDesc) {
- return actionIf(LegalizeAction::Legal,
- LegalityPredicates::typePairAndMemDescInSet(
- typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemDesc));
- }
- /// The instruction is legal when type indexes 0 and 1 are both in the given
- /// list. That is, the type pair is in the cartesian product of the list.
- LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types) {
- return actionForCartesianProduct(LegalizeAction::Legal, Types);
- }
- /// The instruction is legal when type indexes 0 and 1 are both their
- /// respective lists.
- LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0,
- std::initializer_list<LLT> Types1) {
- return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1);
- }
- /// The instruction is legal when type indexes 0, 1, and 2 are both their
- /// respective lists.
- LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0,
- std::initializer_list<LLT> Types1,
- std::initializer_list<LLT> Types2) {
- return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1,
- Types2);
- }
- LegalizeRuleSet &alwaysLegal() {
- using namespace LegalizeMutations;
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::Legal, always);
- }
- /// The specified type index is coerced if predicate is true.
- LegalizeRuleSet &bitcastIf(LegalityPredicate Predicate,
- LegalizeMutation Mutation) {
- // We have no choice but conservatively assume that lowering with a
- // free-form user provided Predicate properly handles all type indices:
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::Bitcast, Predicate, Mutation);
- }
- /// The instruction is lowered.
- LegalizeRuleSet &lower() {
- using namespace LegalizeMutations;
- // We have no choice but conservatively assume that predicate-less lowering
- // properly handles all type indices by design:
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::Lower, always);
- }
- /// The instruction is lowered if predicate is true. Keep type index 0 as the
- /// same type.
- LegalizeRuleSet &lowerIf(LegalityPredicate Predicate) {
- using namespace LegalizeMutations;
- // We have no choice but conservatively assume that lowering with a
- // free-form user provided Predicate properly handles all type indices:
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::Lower, Predicate);
- }
- /// The instruction is lowered if predicate is true.
- LegalizeRuleSet &lowerIf(LegalityPredicate Predicate,
- LegalizeMutation Mutation) {
- // We have no choice but conservatively assume that lowering with a
- // free-form user provided Predicate properly handles all type indices:
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::Lower, Predicate, Mutation);
- }
- /// The instruction is lowered when type index 0 is any type in the given
- /// list. Keep type index 0 as the same type.
- LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types) {
- return actionFor(LegalizeAction::Lower, Types);
- }
- /// The instruction is lowered when type index 0 is any type in the given
- /// list.
- LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types,
- LegalizeMutation Mutation) {
- return actionFor(LegalizeAction::Lower, Types, Mutation);
- }
- /// The instruction is lowered when type indexes 0 and 1 is any type pair in
- /// the given list. Keep type index 0 as the same type.
- LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
- return actionFor(LegalizeAction::Lower, Types);
- }
- /// The instruction is lowered when type indexes 0 and 1 is any type pair in
- /// the given list.
- LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types,
- LegalizeMutation Mutation) {
- return actionFor(LegalizeAction::Lower, Types, Mutation);
- }
- /// The instruction is lowered when type indexes 0 and 1 are both in their
- /// respective lists.
- LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0,
- std::initializer_list<LLT> Types1) {
- using namespace LegalityPredicates;
- return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1);
- }
- /// The instruction is lowered when when type indexes 0, 1, and 2 are all in
- /// their respective lists.
- LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0,
- std::initializer_list<LLT> Types1,
- std::initializer_list<LLT> Types2) {
- using namespace LegalityPredicates;
- return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1,
- Types2);
- }
- /// The instruction is emitted as a library call.
- LegalizeRuleSet &libcall() {
- using namespace LegalizeMutations;
- // We have no choice but conservatively assume that predicate-less lowering
- // properly handles all type indices by design:
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::Libcall, always);
- }
- /// Like legalIf, but for the Libcall action.
- LegalizeRuleSet &libcallIf(LegalityPredicate Predicate) {
- // We have no choice but conservatively assume that a libcall with a
- // free-form user provided Predicate properly handles all type indices:
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::Libcall, Predicate);
- }
- LegalizeRuleSet &libcallFor(std::initializer_list<LLT> Types) {
- return actionFor(LegalizeAction::Libcall, Types);
- }
- LegalizeRuleSet &
- libcallFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
- return actionFor(LegalizeAction::Libcall, Types);
- }
- LegalizeRuleSet &
- libcallForCartesianProduct(std::initializer_list<LLT> Types) {
- return actionForCartesianProduct(LegalizeAction::Libcall, Types);
- }
- LegalizeRuleSet &
- libcallForCartesianProduct(std::initializer_list<LLT> Types0,
- std::initializer_list<LLT> Types1) {
- return actionForCartesianProduct(LegalizeAction::Libcall, Types0, Types1);
- }
- /// Widen the scalar to the one selected by the mutation if the predicate is
- /// true.
- LegalizeRuleSet &widenScalarIf(LegalityPredicate Predicate,
- LegalizeMutation Mutation) {
- // We have no choice but conservatively assume that an action with a
- // free-form user provided Predicate properly handles all type indices:
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::WidenScalar, Predicate, Mutation);
- }
- /// Narrow the scalar to the one selected by the mutation if the predicate is
- /// true.
- LegalizeRuleSet &narrowScalarIf(LegalityPredicate Predicate,
- LegalizeMutation Mutation) {
- // We have no choice but conservatively assume that an action with a
- // free-form user provided Predicate properly handles all type indices:
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::NarrowScalar, Predicate, Mutation);
- }
- /// Narrow the scalar, specified in mutation, when type indexes 0 and 1 is any
- /// type pair in the given list.
- LegalizeRuleSet &
- narrowScalarFor(std::initializer_list<std::pair<LLT, LLT>> Types,
- LegalizeMutation Mutation) {
- return actionFor(LegalizeAction::NarrowScalar, Types, Mutation);
- }
- /// Add more elements to reach the type selected by the mutation if the
- /// predicate is true.
- LegalizeRuleSet &moreElementsIf(LegalityPredicate Predicate,
- LegalizeMutation Mutation) {
- // We have no choice but conservatively assume that an action with a
- // free-form user provided Predicate properly handles all type indices:
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::MoreElements, Predicate, Mutation);
- }
- /// Remove elements to reach the type selected by the mutation if the
- /// predicate is true.
- LegalizeRuleSet &fewerElementsIf(LegalityPredicate Predicate,
- LegalizeMutation Mutation) {
- // We have no choice but conservatively assume that an action with a
- // free-form user provided Predicate properly handles all type indices:
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::FewerElements, Predicate, Mutation);
- }
- /// The instruction is unsupported.
- LegalizeRuleSet &unsupported() {
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::Unsupported, always);
- }
- LegalizeRuleSet &unsupportedIf(LegalityPredicate Predicate) {
- return actionIf(LegalizeAction::Unsupported, Predicate);
- }
- LegalizeRuleSet &unsupportedFor(std::initializer_list<LLT> Types) {
- return actionFor(LegalizeAction::Unsupported, Types);
- }
- LegalizeRuleSet &unsupportedIfMemSizeNotPow2() {
- return actionIf(LegalizeAction::Unsupported,
- LegalityPredicates::memSizeInBytesNotPow2(0));
- }
- LegalizeRuleSet &lowerIfMemSizeNotPow2() {
- return actionIf(LegalizeAction::Lower,
- LegalityPredicates::memSizeInBytesNotPow2(0));
- }
- LegalizeRuleSet &customIf(LegalityPredicate Predicate) {
- // We have no choice but conservatively assume that a custom action with a
- // free-form user provided Predicate properly handles all type indices:
- markAllIdxsAsCovered();
- return actionIf(LegalizeAction::Custom, Predicate);
- }
- LegalizeRuleSet &customFor(std::initializer_list<LLT> Types) {
- return actionFor(LegalizeAction::Custom, Types);
- }
- /// The instruction is custom when type indexes 0 and 1 is any type pair in the
- /// given list.
- LegalizeRuleSet &customFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
- return actionFor(LegalizeAction::Custom, Types);
- }
- LegalizeRuleSet &customForCartesianProduct(std::initializer_list<LLT> Types) {
- return actionForCartesianProduct(LegalizeAction::Custom, Types);
- }
- /// The instruction is custom when type indexes 0 and 1 are both in their
- /// respective lists.
- LegalizeRuleSet &
- customForCartesianProduct(std::initializer_list<LLT> Types0,
- std::initializer_list<LLT> Types1) {
- return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1);
- }
- /// The instruction is custom when when type indexes 0, 1, and 2 are all in
- /// their respective lists.
- LegalizeRuleSet &
- customForCartesianProduct(std::initializer_list<LLT> Types0,
- std::initializer_list<LLT> Types1,
- std::initializer_list<LLT> Types2) {
- return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1,
- Types2);
- }
- /// Unconditionally custom lower.
- LegalizeRuleSet &custom() {
- return customIf(always);
- }
- /// Widen the scalar to the next power of two that is at least MinSize.
- /// No effect if the type is not a scalar or is a power of two.
- LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx,
- unsigned MinSize = 0) {
- using namespace LegalityPredicates;
- return actionIf(
- LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)),
- LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize));
- }
- /// Widen the scalar to the next multiple of Size. No effect if the
- /// type is not a scalar or is a multiple of Size.
- LegalizeRuleSet &widenScalarToNextMultipleOf(unsigned TypeIdx,
- unsigned Size) {
- using namespace LegalityPredicates;
- return actionIf(
- LegalizeAction::WidenScalar, sizeNotMultipleOf(typeIdx(TypeIdx), Size),
- LegalizeMutations::widenScalarOrEltToNextMultipleOf(TypeIdx, Size));
- }
- /// Widen the scalar or vector element type to the next power of two that is
- /// at least MinSize. No effect if the scalar size is a power of two.
- LegalizeRuleSet &widenScalarOrEltToNextPow2(unsigned TypeIdx,
- unsigned MinSize = 0) {
- using namespace LegalityPredicates;
- return actionIf(
- LegalizeAction::WidenScalar, scalarOrEltSizeNotPow2(typeIdx(TypeIdx)),
- LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize));
- }
- LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) {
- using namespace LegalityPredicates;
- return actionIf(LegalizeAction::NarrowScalar, isScalar(typeIdx(TypeIdx)),
- Mutation);
- }
- LegalizeRuleSet &scalarize(unsigned TypeIdx) {
- using namespace LegalityPredicates;
- return actionIf(LegalizeAction::FewerElements, isVector(typeIdx(TypeIdx)),
- LegalizeMutations::scalarize(TypeIdx));
- }
- LegalizeRuleSet &scalarizeIf(LegalityPredicate Predicate, unsigned TypeIdx) {
- using namespace LegalityPredicates;
- return actionIf(LegalizeAction::FewerElements,
- all(Predicate, isVector(typeIdx(TypeIdx))),
- LegalizeMutations::scalarize(TypeIdx));
- }
- /// Ensure the scalar or element is at least as wide as Ty.
- LegalizeRuleSet &minScalarOrElt(unsigned TypeIdx, const LLT Ty) {
- using namespace LegalityPredicates;
- using namespace LegalizeMutations;
- return actionIf(LegalizeAction::WidenScalar,
- scalarOrEltNarrowerThan(TypeIdx, Ty.getScalarSizeInBits()),
- changeElementTo(typeIdx(TypeIdx), Ty));
- }
- /// Ensure the scalar or element is at least as wide as Ty.
- LegalizeRuleSet &minScalarOrEltIf(LegalityPredicate Predicate,
- unsigned TypeIdx, const LLT Ty) {
- using namespace LegalityPredicates;
- using namespace LegalizeMutations;
- return actionIf(LegalizeAction::WidenScalar,
- all(Predicate, scalarOrEltNarrowerThan(
- TypeIdx, Ty.getScalarSizeInBits())),
- changeElementTo(typeIdx(TypeIdx), Ty));
- }
- /// Ensure the scalar is at least as wide as Ty.
- LegalizeRuleSet &minScalar(unsigned TypeIdx, const LLT Ty) {
- using namespace LegalityPredicates;
- using namespace LegalizeMutations;
- return actionIf(LegalizeAction::WidenScalar,
- scalarNarrowerThan(TypeIdx, Ty.getSizeInBits()),
- changeTo(typeIdx(TypeIdx), Ty));
- }
- /// Ensure the scalar is at most as wide as Ty.
- LegalizeRuleSet &maxScalarOrElt(unsigned TypeIdx, const LLT Ty) {
- using namespace LegalityPredicates;
- using namespace LegalizeMutations;
- return actionIf(LegalizeAction::NarrowScalar,
- scalarOrEltWiderThan(TypeIdx, Ty.getScalarSizeInBits()),
- changeElementTo(typeIdx(TypeIdx), Ty));
- }
- /// Ensure the scalar is at most as wide as Ty.
- LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT Ty) {
- using namespace LegalityPredicates;
- using namespace LegalizeMutations;
- return actionIf(LegalizeAction::NarrowScalar,
- scalarWiderThan(TypeIdx, Ty.getSizeInBits()),
- changeTo(typeIdx(TypeIdx), Ty));
- }
- /// Conditionally limit the maximum size of the scalar.
- /// For example, when the maximum size of one type depends on the size of
- /// another such as extracting N bits from an M bit container.
- LegalizeRuleSet &maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx,
- const LLT Ty) {
- using namespace LegalityPredicates;
- using namespace LegalizeMutations;
- return actionIf(
- LegalizeAction::NarrowScalar,
- [=](const LegalityQuery &Query) {
- const LLT QueryTy = Query.Types[TypeIdx];
- return QueryTy.isScalar() &&
- QueryTy.getSizeInBits() > Ty.getSizeInBits() &&
- Predicate(Query);
- },
- changeElementTo(typeIdx(TypeIdx), Ty));
- }
- /// Limit the range of scalar sizes to MinTy and MaxTy.
- LegalizeRuleSet &clampScalar(unsigned TypeIdx, const LLT MinTy,
- const LLT MaxTy) {
- assert(MinTy.isScalar() && MaxTy.isScalar() && "Expected scalar types");
- return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy);
- }
- /// Limit the range of scalar sizes to MinTy and MaxTy.
- LegalizeRuleSet &clampScalarOrElt(unsigned TypeIdx, const LLT MinTy,
- const LLT MaxTy) {
- return minScalarOrElt(TypeIdx, MinTy).maxScalarOrElt(TypeIdx, MaxTy);
- }
- /// Widen the scalar to match the size of another.
- LegalizeRuleSet &minScalarSameAs(unsigned TypeIdx, unsigned LargeTypeIdx) {
- typeIdx(TypeIdx);
- return widenScalarIf(
- [=](const LegalityQuery &Query) {
- return Query.Types[LargeTypeIdx].getScalarSizeInBits() >
- Query.Types[TypeIdx].getSizeInBits();
- },
- LegalizeMutations::changeElementSizeTo(TypeIdx, LargeTypeIdx));
- }
- /// Narrow the scalar to match the size of another.
- LegalizeRuleSet &maxScalarSameAs(unsigned TypeIdx, unsigned NarrowTypeIdx) {
- typeIdx(TypeIdx);
- return narrowScalarIf(
- [=](const LegalityQuery &Query) {
- return Query.Types[NarrowTypeIdx].getScalarSizeInBits() <
- Query.Types[TypeIdx].getSizeInBits();
- },
- LegalizeMutations::changeElementSizeTo(TypeIdx, NarrowTypeIdx));
- }
- /// Change the type \p TypeIdx to have the same scalar size as type \p
- /// SameSizeIdx.
- LegalizeRuleSet &scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx) {
- return minScalarSameAs(TypeIdx, SameSizeIdx)
- .maxScalarSameAs(TypeIdx, SameSizeIdx);
- }
- /// Conditionally widen the scalar or elt to match the size of another.
- LegalizeRuleSet &minScalarEltSameAsIf(LegalityPredicate Predicate,
- unsigned TypeIdx, unsigned LargeTypeIdx) {
- typeIdx(TypeIdx);
- return widenScalarIf(
- [=](const LegalityQuery &Query) {
- return Query.Types[LargeTypeIdx].getScalarSizeInBits() >
- Query.Types[TypeIdx].getScalarSizeInBits() &&
- Predicate(Query);
- },
- [=](const LegalityQuery &Query) {
- LLT T = Query.Types[LargeTypeIdx];
- return std::make_pair(TypeIdx, T);
- });
- }
- /// Conditionally narrow the scalar or elt to match the size of another.
- LegalizeRuleSet &maxScalarEltSameAsIf(LegalityPredicate Predicate,
- unsigned TypeIdx,
- unsigned SmallTypeIdx) {
- typeIdx(TypeIdx);
- return narrowScalarIf(
- [=](const LegalityQuery &Query) {
- return Query.Types[SmallTypeIdx].getScalarSizeInBits() <
- Query.Types[TypeIdx].getScalarSizeInBits() &&
- Predicate(Query);
- },
- [=](const LegalityQuery &Query) {
- LLT T = Query.Types[SmallTypeIdx];
- return std::make_pair(TypeIdx, T);
- });
- }
- /// Add more elements to the vector to reach the next power of two.
- /// No effect if the type is not a vector or the element count is a power of
- /// two.
- LegalizeRuleSet &moreElementsToNextPow2(unsigned TypeIdx) {
- using namespace LegalityPredicates;
- return actionIf(LegalizeAction::MoreElements,
- numElementsNotPow2(typeIdx(TypeIdx)),
- LegalizeMutations::moreElementsToNextPow2(TypeIdx));
- }
- /// Limit the number of elements in EltTy vectors to at least MinElements.
- LegalizeRuleSet &clampMinNumElements(unsigned TypeIdx, const LLT EltTy,
- unsigned MinElements) {
- // Mark the type index as covered:
- typeIdx(TypeIdx);
- return actionIf(
- LegalizeAction::MoreElements,
- [=](const LegalityQuery &Query) {
- LLT VecTy = Query.Types[TypeIdx];
- return VecTy.isVector() && VecTy.getElementType() == EltTy &&
- VecTy.getNumElements() < MinElements;
- },
- [=](const LegalityQuery &Query) {
- LLT VecTy = Query.Types[TypeIdx];
- return std::make_pair(
- TypeIdx, LLT::fixed_vector(MinElements, VecTy.getElementType()));
- });
- }
- /// Set number of elements to nearest larger multiple of NumElts.
- LegalizeRuleSet &alignNumElementsTo(unsigned TypeIdx, const LLT EltTy,
- unsigned NumElts) {
- typeIdx(TypeIdx);
- return actionIf(
- LegalizeAction::MoreElements,
- [=](const LegalityQuery &Query) {
- LLT VecTy = Query.Types[TypeIdx];
- return VecTy.isVector() && VecTy.getElementType() == EltTy &&
- (VecTy.getNumElements() % NumElts != 0);
- },
- [=](const LegalityQuery &Query) {
- LLT VecTy = Query.Types[TypeIdx];
- unsigned NewSize = alignTo(VecTy.getNumElements(), NumElts);
- return std::make_pair(
- TypeIdx, LLT::fixed_vector(NewSize, VecTy.getElementType()));
- });
- }
- /// Limit the number of elements in EltTy vectors to at most MaxElements.
- LegalizeRuleSet &clampMaxNumElements(unsigned TypeIdx, const LLT EltTy,
- unsigned MaxElements) {
- // Mark the type index as covered:
- typeIdx(TypeIdx);
- return actionIf(
- LegalizeAction::FewerElements,
- [=](const LegalityQuery &Query) {
- LLT VecTy = Query.Types[TypeIdx];
- return VecTy.isVector() && VecTy.getElementType() == EltTy &&
- VecTy.getNumElements() > MaxElements;
- },
- [=](const LegalityQuery &Query) {
- LLT VecTy = Query.Types[TypeIdx];
- LLT NewTy = LLT::scalarOrVector(ElementCount::getFixed(MaxElements),
- VecTy.getElementType());
- return std::make_pair(TypeIdx, NewTy);
- });
- }
- /// Limit the number of elements for the given vectors to at least MinTy's
- /// number of elements and at most MaxTy's number of elements.
- ///
- /// No effect if the type is not a vector or does not have the same element
- /// type as the constraints.
- /// The element type of MinTy and MaxTy must match.
- LegalizeRuleSet &clampNumElements(unsigned TypeIdx, const LLT MinTy,
- const LLT MaxTy) {
- assert(MinTy.getElementType() == MaxTy.getElementType() &&
- "Expected element types to agree");
- const LLT EltTy = MinTy.getElementType();
- return clampMinNumElements(TypeIdx, EltTy, MinTy.getNumElements())
- .clampMaxNumElements(TypeIdx, EltTy, MaxTy.getNumElements());
- }
- /// Express \p EltTy vectors strictly using vectors with \p NumElts elements
- /// (or scalars when \p NumElts equals 1).
- /// First pad with undef elements to nearest larger multiple of \p NumElts.
- /// Then perform split with all sub-instructions having the same type.
- /// Using clampMaxNumElements (non-strict) can result in leftover instruction
- /// with different type (fewer elements then \p NumElts or scalar).
- /// No effect if the type is not a vector.
- LegalizeRuleSet &clampMaxNumElementsStrict(unsigned TypeIdx, const LLT EltTy,
- unsigned NumElts) {
- return alignNumElementsTo(TypeIdx, EltTy, NumElts)
- .clampMaxNumElements(TypeIdx, EltTy, NumElts);
- }
- /// Fallback on the previous implementation. This should only be used while
- /// porting a rule.
- LegalizeRuleSet &fallback() {
- add({always, LegalizeAction::UseLegacyRules});
- return *this;
- }
- /// Check if there is no type index which is obviously not handled by the
- /// LegalizeRuleSet in any way at all.
- /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set.
- bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const;
- /// Check if there is no imm index which is obviously not handled by the
- /// LegalizeRuleSet in any way at all.
- /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set.
- bool verifyImmIdxsCoverage(unsigned NumImmIdxs) const;
- /// Apply the ruleset to the given LegalityQuery.
- LegalizeActionStep apply(const LegalityQuery &Query) const;
- };
- class LegalizerInfo {
- public:
- virtual ~LegalizerInfo() = default;
- const LegacyLegalizerInfo &getLegacyLegalizerInfo() const {
- return LegacyInfo;
- }
- LegacyLegalizerInfo &getLegacyLegalizerInfo() { return LegacyInfo; }
- unsigned getOpcodeIdxForOpcode(unsigned Opcode) const;
- unsigned getActionDefinitionsIdx(unsigned Opcode) const;
- /// Perform simple self-diagnostic and assert if there is anything obviously
- /// wrong with the actions set up.
- void verify(const MCInstrInfo &MII) const;
- /// Get the action definitions for the given opcode. Use this to run a
- /// LegalityQuery through the definitions.
- const LegalizeRuleSet &getActionDefinitions(unsigned Opcode) const;
- /// Get the action definition builder for the given opcode. Use this to define
- /// the action definitions.
- ///
- /// It is an error to request an opcode that has already been requested by the
- /// multiple-opcode variant.
- LegalizeRuleSet &getActionDefinitionsBuilder(unsigned Opcode);
- /// Get the action definition builder for the given set of opcodes. Use this
- /// to define the action definitions for multiple opcodes at once. The first
- /// opcode given will be considered the representative opcode and will hold
- /// the definitions whereas the other opcodes will be configured to refer to
- /// the representative opcode. This lowers memory requirements and very
- /// slightly improves performance.
- ///
- /// It would be very easy to introduce unexpected side-effects as a result of
- /// this aliasing if it were permitted to request different but intersecting
- /// sets of opcodes but that is difficult to keep track of. It is therefore an
- /// error to request the same opcode twice using this API, to request an
- /// opcode that already has definitions, or to use the single-opcode API on an
- /// opcode that has already been requested by this API.
- LegalizeRuleSet &
- getActionDefinitionsBuilder(std::initializer_list<unsigned> Opcodes);
- void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom);
- /// Determine what action should be taken to legalize the described
- /// instruction. Requires computeTables to have been called.
- ///
- /// \returns a description of the next legalization step to perform.
- LegalizeActionStep getAction(const LegalityQuery &Query) const;
- /// Determine what action should be taken to legalize the given generic
- /// instruction.
- ///
- /// \returns a description of the next legalization step to perform.
- LegalizeActionStep getAction(const MachineInstr &MI,
- const MachineRegisterInfo &MRI) const;
- bool isLegal(const LegalityQuery &Query) const {
- return getAction(Query).Action == LegalizeAction::Legal;
- }
- bool isLegalOrCustom(const LegalityQuery &Query) const {
- auto Action = getAction(Query).Action;
- return Action == LegalizeAction::Legal || Action == LegalizeAction::Custom;
- }
- bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
- bool isLegalOrCustom(const MachineInstr &MI,
- const MachineRegisterInfo &MRI) const;
- /// Called for instructions with the Custom LegalizationAction.
- virtual bool legalizeCustom(LegalizerHelper &Helper,
- MachineInstr &MI) const {
- llvm_unreachable("must implement this if custom action is used");
- }
- /// \returns true if MI is either legal or has been legalized and false if not
- /// legal.
- /// Return true if MI is either legal or has been legalized and false
- /// if not legal.
- virtual bool legalizeIntrinsic(LegalizerHelper &Helper,
- MachineInstr &MI) const {
- return true;
- }
- /// Return the opcode (SEXT/ZEXT/ANYEXT) that should be performed while
- /// widening a constant of type SmallTy which targets can override.
- /// For eg, the DAG does (SmallTy.isByteSized() ? G_SEXT : G_ZEXT) which
- /// will be the default.
- virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const;
- private:
- static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
- static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
- LegalizeRuleSet RulesForOpcode[LastOp - FirstOp + 1];
- LegacyLegalizerInfo LegacyInfo;
- };
- #ifndef NDEBUG
- /// Checks that MIR is fully legal, returns an illegal instruction if it's not,
- /// nullptr otherwise
- const MachineInstr *machineFunctionIsIllegal(const MachineFunction &MF);
- #endif
- } // end namespace llvm.
- #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|