12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316 |
- #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/SmallBitVector.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h"
- #include "llvm/CodeGen/MachineMemOperand.h"
- #include "llvm/CodeGen/TargetOpcodes.h"
- #include "llvm/MC/MCInstrDesc.h"
- #include "llvm/Support/AtomicOrdering.h"
- #include "llvm/Support/CommandLine.h"
- #include "llvm/Support/LowLevelTypeImpl.h"
- #include <cassert>
- #include <cstdint>
- #include <tuple>
- #include <utility>
- namespace llvm {
- extern cl::opt<bool> DisableGISelLegalityCheck;
- class MachineFunction;
- class raw_ostream;
- 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 (rounded to bytes) that is not a
- /// power of 2.
- LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx);
- /// True iff the specified MMO index has a size that is not an even byte size,
- /// or that even byte size is not a power of 2.
- LegalityPredicate memSizeNotByteSizePow2(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);
- /// Keep the same scalar or element type as \p TypeIdx, but take the number of
- /// elements from \p FromTypeIdx.
- LegalizeMutation changeElementCountTo(unsigned TypeIdx, unsigned FromTypeIdx);
- /// Keep the same scalar or element type as \p TypeIdx, but take the number of
- /// elements from \p Ty.
- LegalizeMutation changeElementCountTo(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));
- }
- /// Lower a memory operation if the memory size, rounded to bytes, is not a
- /// power of 2. For example, this will not trigger for s1 or s7, but will for
- /// s24.
- LegalizeRuleSet &lowerIfMemSizeNotPow2() {
- return actionIf(LegalizeAction::Lower,
- LegalityPredicates::memSizeInBytesNotPow2(0));
- }
- /// Lower a memory operation if the memory access size is not a round power of
- /// 2 byte size. This is stricter than lowerIfMemSizeNotPow2, and more likely
- /// what you want (e.g. this will lower s1, s7 and s24).
- LegalizeRuleSet &lowerIfMemSizeNotByteSizePow2() {
- return actionIf(LegalizeAction::Lower,
- LegalityPredicates::memSizeNotByteSizePow2(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 least as wide as Ty if condition is met.
- LegalizeRuleSet &minScalarIf(LegalityPredicate Predicate, unsigned TypeIdx,
- const LLT Ty) {
- using namespace LegalityPredicates;
- using namespace LegalizeMutations;
- return actionIf(
- LegalizeAction::WidenScalar,
- [=](const LegalityQuery &Query) {
- const LLT QueryTy = Query.Types[TypeIdx];
- return QueryTy.isScalar() &&
- QueryTy.getSizeInBits() < Ty.getSizeInBits() &&
- Predicate(Query);
- },
- 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];
- if (T.isVector() && T.getElementType().isPointer())
- T = T.changeElementType(LLT::scalar(T.getScalarSizeInBits()));
- 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
|