[llvm] r317560 - [GlobalISel] Enable legalizing non-power-of-2 sized types.
Puyan Lotfi via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 8 10:16:08 PST 2017
I have a question: Could there be a way for this legalization to be
deployed in a way so that the individual targets can opt out?
The legalization code for the open source targets seems non-trivial and out
of tree targets that aren't doing the legalization yet will break.
Would be nice if there were a way to still be up to date on the latest top
of tree without implementing the legalization while not breaking.
PL
On Wed, Nov 8, 2017 at 8:38 AM, Kristof Beyls via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
>
> > On 7 Nov 2017, at 19:05, Amara Emerson <aemerson at apple.com> wrote:
> >
> > Thanks Kristof, nice to see this go in. We have a non power of 2 section
> in the GISel docs (https://llvm.org/docs/GlobalISel.html#non-power-of-
> 2-types) that need expanding, could you update that when you get a
> chance? Looks like this commit message is a good explanation.
> >
> > Cheers,
> > Amara
>
> Thanks for the suggestion, Amara.
> I was planning to do that and am hoping to find a bit of time in the next
> couple of days for it.
>
> >> On 7 Nov 2017, at 10:34, Kristof Beyls via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
> >>
> >> Author: kbeyls
> >> Date: Tue Nov 7 02:34:34 2017
> >> New Revision: 317560
> >>
> >> URL: http://llvm.org/viewvc/llvm-project?rev=317560&view=rev
> >> Log:
> >> [GlobalISel] Enable legalizing non-power-of-2 sized types.
> >>
> >> This changes the interface of how targets describe how to legalize, see
> >> the below description.
> >>
> >> 1. Interface for targets to describe how to legalize.
> >>
> >> In GlobalISel, the API in the LegalizerInfo class is the main interface
> >> for targets to specify which types are legal for which operations, and
> >> what to do to turn illegal type/operation combinations into legal ones.
> >>
> >> For each operation the type sizes that can be legalized without having
> >> to change the size of the type are specified with a call to setAction.
> >> This isn't different to how GlobalISel worked before. For example, for a
> >> target that supports 32 and 64 bit adds natively:
> >>
> >> for (auto Ty : {s32, s64})
> >> setAction({G_ADD, 0, s32}, Legal);
> >>
> >> or for a target that needs a library call for a 32 bit division:
> >>
> >> setAction({G_SDIV, s32}, Libcall);
> >>
> >> The main conceptual change to the LegalizerInfo API, is in specifying
> >> how to legalize the type sizes for which a change of size is needed. For
> >> example, in the above example, how to specify how all types from i1 to
> >> i8388607 (apart from s32 and s64 which are legal) need to be legalized
> >> and expressed in terms of operations on the available legal sizes
> >> (again, i32 and i64 in this case). Before, the implementation only
> >> allowed specifying power-of-2-sized types (e.g. setAction({G_ADD, 0,
> >> s128}, NarrowScalar). A worse limitation was that if you'd wanted to
> >> specify how to legalize all the sized types as allowed by the LLVM-IR
> >> LangRef, i1 to i8388607, you'd have to call setAction 8388607-3 times
> >> and probably would need a lot of memory to store all of these
> >> specifications.
> >>
> >> Instead, the legalization actions that need to change the size of the
> >> type are specified now using a "SizeChangeStrategy". For example:
> >>
> >> setLegalizeScalarToDifferentSizeStrategy(
> >> G_ADD, 0, widenToLargerAndNarrowToLargest);
> >>
> >> This example indicates that for type sizes for which there is a larger
> >> size that can be legalized towards, do it by Widening the size.
> >> For example, G_ADD on s17 will be legalized by first doing WidenScalar
> >> to make it s32, after which it's legal.
> >> The "NarrowToLargest" indicates what to do if there is no larger size
> >> that can be legalized towards. E.g. G_ADD on s92 will be legalized by
> >> doing NarrowScalar to s64.
> >>
> >> Another example, taken from the ARM backend is:
> >> for (unsigned Op : {G_SDIV, G_UDIV}) {
> >> setLegalizeScalarToDifferentSizeStrategy(Op, 0,
> >> widenToLargerTypesUnsupportedOtherwise);
> >> if (ST.hasDivideInARMMode())
> >> setAction({Op, s32}, Legal);
> >> else
> >> setAction({Op, s32}, Libcall);
> >> }
> >>
> >> For this example, G_SDIV on s8, on a target without a divide
> >> instruction, would be legalized by first doing action (WidenScalar,
> >> s32), followed by (Libcall, s32).
> >>
> >> The same principle is also followed for when the number of vector lanes
> >> on vector data types need to be changed, e.g.:
> >>
> >> setAction({G_ADD, LLT::vector(8, 8)}, LegalizerInfo::Legal);
> >> setAction({G_ADD, LLT::vector(16, 8)}, LegalizerInfo::Legal);
> >> setAction({G_ADD, LLT::vector(4, 16)}, LegalizerInfo::Legal);
> >> setAction({G_ADD, LLT::vector(8, 16)}, LegalizerInfo::Legal);
> >> setAction({G_ADD, LLT::vector(2, 32)}, LegalizerInfo::Legal);
> >> setAction({G_ADD, LLT::vector(4, 32)}, LegalizerInfo::Legal);
> >> setLegalizeVectorElementToDifferentSizeStrategy(
> >> G_ADD, 0, widenToLargerTypesUnsupportedOtherwise);
> >>
> >> As currently implemented here, vector types are legalized by first
> >> making the vector element size legal, followed by then making the number
> >> of lanes legal. The strategy to follow in the first step is set by a
> >> call to setLegalizeVectorElementToDifferentSizeStrategy, see example
> >> above. The strategy followed in the second step
> >> "moreToWiderTypesAndLessToWidest" (see code for its definition),
> >> indicating that vectors are widened to more elements so they map to
> >> natively supported vector widths, or when there isn't a legal wider
> >> vector, split the vector to map it to the widest vector supported.
> >>
> >> Therefore, for the above specification, some example legalizations are:
> >> * getAction({G_ADD, LLT::vector(3, 3)})
> >> returns {WidenScalar, LLT::vector(3, 8)}
> >> * getAction({G_ADD, LLT::vector(3, 8)})
> >> then returns {MoreElements, LLT::vector(8, 8)}
> >> * getAction({G_ADD, LLT::vector(20, 8)})
> >> returns {FewerElements, LLT::vector(16, 8)}
> >>
> >>
> >> 2. Key implementation aspects.
> >>
> >> How to legalize a specific (operation, type index, size) tuple is
> >> represented by mapping intervals of integers representing a range of
> >> size types to an action to take, e.g.:
> >>
> >> setScalarAction({G_ADD, LLT:scalar(1)},
> >> {{1, WidenScalar}, // bit sizes [ 1, 31[
> >> {32, Legal}, // bit sizes [32, 33[
> >> {33, WidenScalar}, // bit sizes [33, 64[
> >> {64, Legal}, // bit sizes [64, 65[
> >> {65, NarrowScalar} // bit sizes [65, +inf[
> >> });
> >>
> >> Please note that most of the code to do the actual lowering of
> >> non-power-of-2 sized types is currently missing, this is just trying to
> >> make it possible for targets to specify what is legal, and how non-legal
> >> types should be legalized. Probably quite a bit of further work is
> >> needed in the actual legalizing and the other passes in GlobalISel to
> >> support non-power-of-2 sized types.
> >>
> >> I hope the documentation in LegalizerInfo.h and the examples provided
> in the
> >> various {Target}LegalizerInfo.cpp and LegalizerInfoTest.cpp explains
> well
> >> enough how this is meant to be used.
> >>
> >> This drops the need for LLT::{half,double}...Size().
> >>
> >>
> >> Differential Revision: https://reviews.llvm.org/D30529
> >>
> >>
> >> Modified:
> >> llvm/trunk/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
> >> llvm/trunk/include/llvm/Support/LowLevelTypeImpl.h
> >> llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
> >> llvm/trunk/lib/CodeGen/GlobalISel/LegalizerInfo.cpp
> >> llvm/trunk/lib/Support/LowLevelType.cpp
> >> llvm/trunk/lib/Target/AArch64/AArch64LegalizerInfo.cpp
> >> llvm/trunk/lib/Target/ARM/ARMLegalizerInfo.cpp
> >> llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp
> >> llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll
> >> llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir
> >> llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir
> >> llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir
> >> llvm/trunk/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp
> >> llvm/trunk/unittests/CodeGen/LowLevelTypeTest.cpp
> >>
> >> Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/
> llvm/CodeGen/GlobalISel/LegalizerInfo.h?rev=317560&r1=
> 317559&r2=317560&view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
> (original)
> >> +++ llvm/trunk/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h Tue
> Nov 7 02:34:34 2017
> >> @@ -26,6 +26,7 @@
> >> #include <cassert>
> >> #include <tuple>
> >> #include <utility>
> >> +#include <unordered_map>
> >>
> >> namespace llvm {
> >>
> >> @@ -120,27 +121,144 @@ public:
> >> }
> >> }
> >>
> >> + typedef std::pair<uint16_t, LegalizeAction> SizeAndAction;
> >> + typedef std::vector<SizeAndAction> SizeAndActionsVec;
> >> + using SizeChangeStrategy =
> >> + std::function<SizeAndActionsVec(const SizeAndActionsVec &v)>;
> >> +
> >> /// More friendly way to set an action for common types that have an
> LLT
> >> /// representation.
> >> + /// The LegalizeAction must be one for which
> NeedsLegalizingToDifferentSize
> >> + /// returns false.
> >> void setAction(const InstrAspect &Aspect, LegalizeAction Action) {
> >> + assert(!needsLegalizingToDifferentSize(Action));
> >> TablesInitialized = false;
> >> - unsigned Opcode = Aspect.Opcode - FirstOp;
> >> - if (Actions[Opcode].size() <= Aspect.Idx)
> >> - Actions[Opcode].resize(Aspect.Idx + 1);
> >> - Actions[Aspect.Opcode - FirstOp][Aspect.Idx][Aspect.Type] =
> Action;
> >> + const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;
> >> + if (SpecifiedActions[OpcodeIdx].size() <= Aspect.Idx)
> >> + SpecifiedActions[OpcodeIdx].resize(Aspect.Idx + 1);
> >> + SpecifiedActions[OpcodeIdx][Aspect.Idx][Aspect.Type] = Action;
> >> }
> >>
> >> - /// If an operation on a given vector type (say <M x iN>) isn't
> explicitly
> >> - /// specified, we proceed in 2 stages. First we legalize the
> underlying scalar
> >> - /// (so that there's at least one legal vector with that scalar),
> then we
> >> - /// adjust the number of elements in the vector so that it is legal.
> The
> >> - /// desired action in the first step is controlled by this function.
> >> - void setScalarInVectorAction(unsigned Opcode, LLT ScalarTy,
> >> - LegalizeAction Action) {
> >> - assert(!ScalarTy.isVector());
> >> - ScalarInVectorActions[std::make_pair(Opcode, ScalarTy)] = Action;
> >> + /// The setAction calls record the non-size-changing legalization
> actions
> >> + /// to take on specificly-sized types. The SizeChangeStrategy
> defines what
> >> + /// to do when the size of the type needs to be changed to reach a
> legally
> >> + /// sized type (i.e., one that was defined through a setAction call).
> >> + /// e.g.
> >> + /// setAction ({G_ADD, 0, LLT::scalar(32)}, Legal);
> >> + /// setLegalizeScalarToDifferentSizeStrategy(
> >> + /// G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
> >> + /// will end up defining getAction({G_ADD, 0, T}) to return the
> following
> >> + /// actions for different scalar types T:
> >> + /// LLT::scalar(1)..LLT::scalar(31): {WidenScalar, 0,
> LLT::scalar(32)}
> >> + /// LLT::scalar(32): {Legal, 0, LLT::scalar(32)}
> >> + /// LLT::scalar(33)..: {NarrowScalar, 0,
> LLT::scalar(32)}
> >> + ///
> >> + /// If no SizeChangeAction gets defined, through this function,
> >> + /// the default is unsupportedForDifferentSizes.
> >> + void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode,
> >> + const unsigned TypeIdx,
> >> + SizeChangeStrategy S) {
> >> + const unsigned OpcodeIdx = Opcode - FirstOp;
> >> + if (ScalarSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
> >> + ScalarSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
> >> + ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
> >> + }
> >> +
> >> + /// See also setLegalizeScalarToDifferentSizeStrategy.
> >> + /// This function allows to set the SizeChangeStrategy for vector
> elements.
> >> + void setLegalizeVectorElementToDifferentSizeStrategy(const unsigned
> Opcode,
> >> + const unsigned
> TypeIdx,
> >> +
> SizeChangeStrategy S) {
> >> + const unsigned OpcodeIdx = Opcode - FirstOp;
> >> + if (VectorElementSizeChangeStrategies[OpcodeIdx].size() <=
> TypeIdx)
> >> + VectorElementSizeChangeStrategies[OpcodeIdx].resize(TypeIdx +
> 1);
> >> + VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
> >> + }
> >> +
> >> + /// A SizeChangeStrategy for the common case where legalization for a
> >> + /// particular operation consists of only supporting a specific set
> of type
> >> + /// sizes. E.g.
> >> + /// setAction ({G_DIV, 0, LLT::scalar(32)}, Legal);
> >> + /// setAction ({G_DIV, 0, LLT::scalar(64)}, Legal);
> >> + /// setLegalizeScalarToDifferentSizeStrategy(
> >> + /// G_DIV, 0, unsupportedForDifferentSizes);
> >> + /// will result in getAction({G_DIV, 0, T}) to return Legal for s32
> and s64,
> >> + /// and Unsupported for all other scalar types T.
> >> + static SizeAndActionsVec
> >> + unsupportedForDifferentSizes(const SizeAndActionsVec &v) {
> >> + return increaseToLargerTypesAndDecreaseToLargest(v, Unsupported,
> >> + Unsupported);
> >> + }
> >> +
> >> + /// A SizeChangeStrategy for the common case where legalization for a
> >> + /// particular operation consists of widening the type to a large
> legal type,
> >> + /// unless there is no such type and then instead it should be
> narrowed to the
> >> + /// largest legal type.
> >> + static SizeAndActionsVec
> >> + widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v) {
> >> + assert(v.size() > 0 &&
> >> + "At least one size that can be legalized towards is needed"
> >> + " for this SizeChangeStrategy");
> >> + return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
> >> + NarrowScalar);
> >> }
> >>
> >> + static SizeAndActionsVec
> >> + widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v) {
> >> + return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
> >> + Unsupported);
> >> + }
> >> +
> >> + static SizeAndActionsVec
> >> + narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v)
> {
> >> + return decreaseToSmallerTypesAndIncreaseToSmallest(v,
> NarrowScalar,
> >> + Unsupported);
> >> + }
> >> +
> >> + static SizeAndActionsVec
> >> + narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec &v) {
> >> + assert(v.size() > 0 &&
> >> + "At least one size that can be legalized towards is needed"
> >> + " for this SizeChangeStrategy");
> >> + return decreaseToSmallerTypesAndIncreaseToSmallest(v,
> NarrowScalar,
> >> + WidenScalar);
> >> + }
> >> +
> >> + /// A SizeChangeStrategy for the common case where legalization for a
> >> + /// particular vector operation consists of having more elements in
> the
> >> + /// vector, to a type that is legal. Unless there is no such type
> and then
> >> + /// instead it should be legalized towards the widest vector that's
> still
> >> + /// legal. E.g.
> >> + /// setAction({G_ADD, LLT::vector(8, 8)}, Legal);
> >> + /// setAction({G_ADD, LLT::vector(16, 8)}, Legal);
> >> + /// setAction({G_ADD, LLT::vector(2, 32)}, Legal);
> >> + /// setAction({G_ADD, LLT::vector(4, 32)}, Legal);
> >> + /// setLegalizeVectorElementToDifferentSizeStrategy(
> >> + /// G_ADD, 0, moreToWiderTypesAndLessToWidest);
> >> + /// will result in the following getAction results:
> >> + /// * getAction({G_ADD, LLT::vector(8,8)}) returns
> >> + /// (Legal, vector(8,8)).
> >> + /// * getAction({G_ADD, LLT::vector(9,8)}) returns
> >> + /// (MoreElements, vector(16,8)).
> >> + /// * getAction({G_ADD, LLT::vector(8,32)}) returns
> >> + /// (FewerElements, vector(4,32)).
> >> + static SizeAndActionsVec
> >> + moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v) {
> >> + return increaseToLargerTypesAndDecreaseToLargest(v, MoreElements,
> >> + FewerElements);
> >> + }
> >> +
> >> + /// Helper function to implement many typical SizeChangeStrategy
> functions.
> >> + static SizeAndActionsVec
> >> + increaseToLargerTypesAndDecreaseToLargest(const SizeAndActionsVec
> &v,
> >> + LegalizeAction
> IncreaseAction,
> >> + LegalizeAction
> DecreaseAction);
> >> + /// Helper function to implement many typical SizeChangeStrategy
> functions.
> >> + static SizeAndActionsVec
> >> + decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec
> &v,
> >> + LegalizeAction
> DecreaseAction,
> >> + LegalizeAction
> IncreaseAction);
> >> +
> >> /// Determine what action should be taken to legalize the given generic
> >> /// instruction opcode, type-index and type. Requires computeTables to
> have
> >> /// been called.
> >> @@ -158,58 +276,6 @@ public:
> >> std::tuple<LegalizeAction, unsigned, LLT>
> >> getAction(const MachineInstr &MI, const MachineRegisterInfo &MRI)
> const;
> >>
> >> - /// Iterate the given function (typically something like doubling
> the width)
> >> - /// on Ty until we find a legal type for this operation.
> >> - Optional<LLT> findLegalizableSize(const InstrAspect &Aspect,
> >> - function_ref<LLT(LLT)> NextType)
> const {
> >> - if (Aspect.Idx >= Actions[Aspect.Opcode - FirstOp].size())
> >> - return None;
> >> -
> >> - LegalizeAction Action;
> >> - const TypeMap &Map = Actions[Aspect.Opcode - FirstOp][Aspect.Idx];
> >> - LLT Ty = Aspect.Type;
> >> - do {
> >> - Ty = NextType(Ty);
> >> - auto ActionIt = Map.find(Ty);
> >> - if (ActionIt == Map.end()) {
> >> - auto DefaultIt = DefaultActions.find(Aspect.Opcode);
> >> - if (DefaultIt == DefaultActions.end())
> >> - return None;
> >> - Action = DefaultIt->second;
> >> - } else
> >> - Action = ActionIt->second;
> >> - } while (needsLegalizingToDifferentSize(Action));
> >> - return Ty;
> >> - }
> >> -
> >> - /// Find what type it's actually OK to perform the given operation
> on, given
> >> - /// the general approach we've decided to take.
> >> - Optional<LLT> findLegalType(const InstrAspect &Aspect,
> LegalizeAction Action) const;
> >> -
> >> - std::pair<LegalizeAction, LLT> findLegalAction(const InstrAspect
> &Aspect,
> >> - LegalizeAction
> Action) const {
> >> - auto LegalType = findLegalType(Aspect, Action);
> >> - if (!LegalType)
> >> - return std::make_pair(LegalizeAction::Unsupported, LLT());
> >> - return std::make_pair(Action, *LegalType);
> >> - }
> >> -
> >> - /// Find the specified \p Aspect in the primary (explicitly set)
> Actions
> >> - /// table. Returns either the action the target requested or
> NotFound if there
> >> - /// was no setAction call.
> >> - LegalizeAction findInActions(const InstrAspect &Aspect) const {
> >> - if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
> >> - return NotFound;
> >> - if (Aspect.Idx >= Actions[Aspect.Opcode - FirstOp].size())
> >> - return NotFound;
> >> - const TypeMap &Map = Actions[Aspect.Opcode - FirstOp][Aspect.Idx];
> >> - auto ActionIt = Map.find(Aspect.Type);
> >> - if (ActionIt == Map.end())
> >> - return NotFound;
> >> -
> >> - return ActionIt->second;
> >> - }
> >> -
> >> bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI)
> const;
> >>
> >> virtual bool legalizeCustom(MachineInstr &MI,
> >> @@ -217,20 +283,181 @@ public:
> >> MachineIRBuilder &MIRBuilder) const;
> >>
> >> private:
> >> - static const int FirstOp = TargetOpcode::PRE_ISEL_
> GENERIC_OPCODE_START;
> >> - static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
> >> + /// The SizeAndActionsVec is a representation mapping between all
> natural
> >> + /// numbers and an Action. The natural number represents the bit
> size of
> >> + /// the InstrAspect. For example, for a target with native support
> for 32-bit
> >> + /// and 64-bit additions, you'd express that as:
> >> + /// setScalarAction(G_ADD, 0,
> >> + /// {{1, WidenScalar}, // bit sizes [ 1, 31[
> >> + /// {32, Legal}, // bit sizes [32, 33[
> >> + /// {33, WidenScalar}, // bit sizes [33, 64[
> >> + /// {64, Legal}, // bit sizes [64, 65[
> >> + /// {65, NarrowScalar} // bit sizes [65, +inf[
> >> + /// });
> >> + /// It may be that only 64-bit pointers are supported on your target:
> >> + /// setPointerAction(G_GEP, 0, LLT:pointer(1),
> >> + /// {{1, Unsupported}, // bit sizes [ 1, 63[
> >> + /// {64, Legal}, // bit sizes [64, 65[
> >> + /// {65, Unsupported}, // bit sizes [65, +inf[
> >> + /// });
> >> + void setScalarAction(const unsigned Opcode, const unsigned TypeIndex,
> >> + const SizeAndActionsVec &SizeAndActions) {
> >> + const unsigned OpcodeIdx = Opcode - FirstOp;
> >> + SmallVector<SizeAndActionsVec, 1> &Actions =
> ScalarActions[OpcodeIdx];
> >> + setActions(TypeIndex, Actions, SizeAndActions);
> >> + }
> >> + void setPointerAction(const unsigned Opcode, const unsigned
> TypeIndex,
> >> + const unsigned AddressSpace,
> >> + const SizeAndActionsVec &SizeAndActions) {
> >> + const unsigned OpcodeIdx = Opcode - FirstOp;
> >> + if (AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace) ==
> >> + AddrSpace2PointerActions[OpcodeIdx].end())
> >> + AddrSpace2PointerActions[OpcodeIdx][AddressSpace] = {{}};
> >> + SmallVector<SizeAndActionsVec, 1> &Actions =
> >> + AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace)-
> >second;
> >> + setActions(TypeIndex, Actions, SizeAndActions);
> >> + }
> >>
> >> - using TypeMap = DenseMap<LLT, LegalizeAction>;
> >> - using SIVActionMap = DenseMap<std::pair<unsigned, LLT>,
> LegalizeAction>;
> >> + /// If an operation on a given vector type (say <M x iN>) isn't
> explicitly
> >> + /// specified, we proceed in 2 stages. First we legalize the
> underlying scalar
> >> + /// (so that there's at least one legal vector with that scalar),
> then we
> >> + /// adjust the number of elements in the vector so that it is legal.
> The
> >> + /// desired action in the first step is controlled by this function.
> >> + void setScalarInVectorAction(const unsigned Opcode, const unsigned
> TypeIndex,
> >> + const SizeAndActionsVec
> &SizeAndActions) {
> >> + unsigned OpcodeIdx = Opcode - FirstOp;
> >> + SmallVector<SizeAndActionsVec, 1> &Actions =
> >> + ScalarInVectorActions[OpcodeIdx];
> >> + setActions(TypeIndex, Actions, SizeAndActions);
> >> + }
> >>
> >> - SmallVector<TypeMap, 1> Actions[LastOp - FirstOp + 1];
> >> - SIVActionMap ScalarInVectorActions;
> >> - DenseMap<std::pair<unsigned, LLT>, uint16_t> MaxLegalVectorElts;
> >> - DenseMap<unsigned, LegalizeAction> DefaultActions;
> >> + /// See also setScalarInVectorAction.
> >> + /// This function let's you specify the number of elements in a
> vector that
> >> + /// are legal for a legal element size.
> >> + void setVectorNumElementAction(const unsigned Opcode,
> >> + const unsigned TypeIndex,
> >> + const unsigned ElementSize,
> >> + const SizeAndActionsVec
> &SizeAndActions) {
> >> + const unsigned OpcodeIdx = Opcode - FirstOp;
> >> + if (NumElements2Actions[OpcodeIdx].find(ElementSize) ==
> >> + NumElements2Actions[OpcodeIdx].end())
> >> + NumElements2Actions[OpcodeIdx][ElementSize] = {{}};
> >> + SmallVector<SizeAndActionsVec, 1> &Actions =
> >> + NumElements2Actions[OpcodeIdx].find(ElementSize)->second;
> >> + setActions(TypeIndex, Actions, SizeAndActions);
> >> + }
> >> +
> >> + /// A partial SizeAndActionsVec potentially doesn't cover all bit
> sizes,
> >> + /// i.e. it's OK if it doesn't start from size 1.
> >> + static void checkPartialSizeAndActionsVector(const
> SizeAndActionsVec& v) {
> >> +#ifndef NDEBUG
> >> + // The sizes should be in increasing order
> >> + int prev_size = -1;
> >> + for(auto SizeAndAction: v) {
> >> + assert(SizeAndAction.first > prev_size);
> >> + prev_size = SizeAndAction.first;
> >> + }
> >> + // - for every Widen action, there should be a larger bitsize that
> >> + // can be legalized towards (e.g. Legal, Lower, Libcall or Custom
> >> + // action).
> >> + // - for every Narrow action, there should be a smaller bitsize
> that
> >> + // can be legalized towards.
> >> + int SmallestNarrowIdx = -1;
> >> + int LargestWidenIdx = -1;
> >> + int SmallestLegalizableToSameSizeIdx = -1;
> >> + int LargestLegalizableToSameSizeIdx = -1;
> >> + for(size_t i=0; i<v.size(); ++i) {
> >> + switch (v[i].second) {
> >> + case FewerElements:
> >> + case NarrowScalar:
> >> + if (SmallestNarrowIdx == -1)
> >> + SmallestNarrowIdx = i;
> >> + break;
> >> + case WidenScalar:
> >> + case MoreElements:
> >> + LargestWidenIdx = i;
> >> + break;
> >> + case Unsupported:
> >> + break;
> >> + default:
> >> + if (SmallestLegalizableToSameSizeIdx == -1)
> >> + SmallestLegalizableToSameSizeIdx = i;
> >> + LargestLegalizableToSameSizeIdx = i;
> >> + }
> >> + }
> >> + if (SmallestNarrowIdx != -1) {
> >> + assert(SmallestLegalizableToSameSizeIdx != -1);
> >> + assert(SmallestNarrowIdx > SmallestLegalizableToSameSizeIdx);
> >> + }
> >> + if (LargestWidenIdx != -1)
> >> + assert(LargestWidenIdx < LargestLegalizableToSameSizeIdx);
> >> +#endif
> >> + }
> >> +
> >> + /// A full SizeAndActionsVec must cover all bit sizes, i.e. must
> start with
> >> + /// from size 1.
> >> + static void checkFullSizeAndActionsVector(const SizeAndActionsVec&
> v) {
> >> +#ifndef NDEBUG
> >> + // Data structure invariant: The first bit size must be size 1.
> >> + assert(v.size() >= 1);
> >> + assert(v[0].first == 1);
> >> + checkPartialSizeAndActionsVector(v);
> >> +#endif
> >> + }
> >> +
> >> + /// Sets actions for all bit sizes on a particular generic opcode,
> type
> >> + /// index and scalar or pointer type.
> >> + void setActions(unsigned TypeIndex,
> >> + SmallVector<SizeAndActionsVec, 1> &Actions,
> >> + const SizeAndActionsVec &SizeAndActions) {
> >> + checkFullSizeAndActionsVector(SizeAndActions);
> >> + if (Actions.size() <= TypeIndex)
> >> + Actions.resize(TypeIndex + 1);
> >> + Actions[TypeIndex] = SizeAndActions;
> >> + }
> >> +
> >> + static SizeAndAction findAction(const SizeAndActionsVec &Vec,
> >> + const uint32_t Size);
> >> +
> >> + /// Returns the next action needed to get the scalar or pointer type
> closer
> >> + /// to being legal
> >> + /// E.g. findLegalAction({G_REM, 13}) should return
> >> + /// (WidenScalar, 32). After that, findLegalAction({G_REM, 32}) will
> >> + /// probably be called, which should return (Lower, 32).
> >> + /// This is assuming the setScalarAction on G_REM was something like:
> >> + /// setScalarAction(G_REM, 0,
> >> + /// {{1, WidenScalar}, // bit sizes [ 1, 31[
> >> + /// {32, Lower}, // bit sizes [32, 33[
> >> + /// {33, NarrowScalar} // bit sizes [65, +inf[
> >> + /// });
> >> + std::pair<LegalizeAction, LLT>
> >> + findScalarLegalAction(const InstrAspect &Aspect) const;
> >> +
> >> + /// Returns the next action needed towards legalizing the vector
> type.
> >> + std::pair<LegalizeAction, LLT>
> >> + findVectorLegalAction(const InstrAspect &Aspect) const;
> >> +
> >> + static const int FirstOp = TargetOpcode::PRE_ISEL_
> GENERIC_OPCODE_START;
> >> + static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
> >>
> >> - bool TablesInitialized = false;
> >> + // Data structures used temporarily during construction of legality
> data:
> >> + typedef DenseMap<LLT, LegalizeAction> TypeMap;
> >> + SmallVector<TypeMap, 1> SpecifiedActions[LastOp - FirstOp + 1];
> >> + SmallVector<SizeChangeStrategy, 1>
> >> + ScalarSizeChangeStrategies[LastOp - FirstOp + 1];
> >> + SmallVector<SizeChangeStrategy, 1>
> >> + VectorElementSizeChangeStrategies[LastOp - FirstOp + 1];
> >> + bool TablesInitialized;
> >> +
> >> + // Data structures used by getAction:
> >> + SmallVector<SizeAndActionsVec, 1> ScalarActions[LastOp - FirstOp +
> 1];
> >> + SmallVector<SizeAndActionsVec, 1> ScalarInVectorActions[LastOp -
> FirstOp + 1];
> >> + std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
> >> + AddrSpace2PointerActions[LastOp - FirstOp + 1];
> >> + std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
> >> + NumElements2Actions[LastOp - FirstOp + 1];
> >> };
> >>
> >> -} // end namespace llvm
> >> +} // end namespace llvm.
> >>
> >> #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
> >>
> >> Modified: llvm/trunk/include/llvm/Support/LowLevelTypeImpl.h
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/
> llvm/Support/LowLevelTypeImpl.h?rev=317560&r1=317559&r2=317560&view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/include/llvm/Support/LowLevelTypeImpl.h (original)
> >> +++ llvm/trunk/include/llvm/Support/LowLevelTypeImpl.h Tue Nov 7
> 02:34:34 2017
> >> @@ -137,51 +137,6 @@ public:
> >> return scalar(getScalarSizeInBits());
> >> }
> >>
> >> - /// Get a low-level type with half the size of the original, by
> halving the
> >> - /// size of the scalar type involved. For example `s32` will become
> `s16`,
> >> - /// `<2 x s32>` will become `<2 x s16>`.
> >> - LLT halfScalarSize() const {
> >> - assert(!IsPointer && getScalarSizeInBits() > 1 &&
> >> - getScalarSizeInBits() % 2 == 0 && "cannot half size of this
> type");
> >> - return LLT{/*isPointer=*/false, IsVector ? true : false,
> >> - IsVector ? getNumElements() : (uint16_t)0,
> >> - getScalarSizeInBits() / 2, /*AddressSpace=*/0};
> >> - }
> >> -
> >> - /// Get a low-level type with twice the size of the original, by
> doubling the
> >> - /// size of the scalar type involved. For example `s32` will become
> `s64`,
> >> - /// `<2 x s32>` will become `<2 x s64>`.
> >> - LLT doubleScalarSize() const {
> >> - assert(!IsPointer && "cannot change size of this type");
> >> - return LLT{/*isPointer=*/false, IsVector ? true : false,
> >> - IsVector ? getNumElements() : (uint16_t)0,
> >> - getScalarSizeInBits() * 2, /*AddressSpace=*/0};
> >> - }
> >> -
> >> - /// Get a low-level type with half the size of the original, by
> halving the
> >> - /// number of vector elements of the scalar type involved. The
> source must be
> >> - /// a vector type with an even number of elements. For example `<4 x
> s32>`
> >> - /// will become `<2 x s32>`, `<2 x s32>` will become `s32`.
> >> - LLT halfElements() const {
> >> - assert(isVector() && getNumElements() % 2 == 0 && "cannot half odd
> vector");
> >> - if (getNumElements() == 2)
> >> - return scalar(getScalarSizeInBits());
> >> -
> >> - return LLT{/*isPointer=*/false, /*isVector=*/true,
> >> - (uint16_t)(getNumElements() / 2), getScalarSizeInBits(),
> >> - /*AddressSpace=*/0};
> >> - }
> >> -
> >> - /// Get a low-level type with twice the size of the original, by
> doubling the
> >> - /// number of vector elements of the scalar type involved. The
> source must be
> >> - /// a vector type. For example `<2 x s32>` will become `<4 x s32>`.
> Doubling
> >> - /// the number of elements in sN produces <2 x sN>.
> >> - LLT doubleElements() const {
> >> - return LLT{IsPointer ? true : false, /*isVector=*/true,
> >> - (uint16_t)(getNumElements() * 2), getScalarSizeInBits(),
> >> - IsPointer ? getAddressSpace() : 0};
> >> - }
> >> -
> >> void print(raw_ostream &OS) const;
> >>
> >> bool operator==(const LLT &RHS) const {
> >>
> >> Modified: llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> CodeGen/GlobalISel/LegalizerHelper.cpp?rev=317560&r1=317559&r2=317560&
> view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp (original)
> >> +++ llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp Tue Nov 7
> 02:34:34 2017
> >> @@ -173,12 +173,18 @@ LegalizerHelper::LegalizeResult Legalize
> >>
> >> MIRBuilder.setInstr(MI);
> >>
> >> + int64_t SizeOp0 = MRI.getType(MI.getOperand(0).
> getReg()).getSizeInBits();
> >> + int64_t NarrowSize = NarrowTy.getSizeInBits();
> >> +
> >> switch (MI.getOpcode()) {
> >> default:
> >> return UnableToLegalize;
> >> case TargetOpcode::G_IMPLICIT_DEF: {
> >> - int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits()
> /
> >> - NarrowTy.getSizeInBits();
> >> + // FIXME: add support for when SizeOp0 isn't an exact multiple of
> >> + // NarrowSize.
> >> + if (SizeOp0 % NarrowSize != 0)
> >> + return UnableToLegalize;
> >> + int NumParts = SizeOp0 / NarrowSize;
> >>
> >> SmallVector<unsigned, 2> DstRegs;
> >> for (int i = 0; i < NumParts; ++i) {
> >> @@ -191,9 +197,12 @@ LegalizerHelper::LegalizeResult Legalize
> >> return Legalized;
> >> }
> >> case TargetOpcode::G_ADD: {
> >> + // FIXME: add support for when SizeOp0 isn't an exact multiple of
> >> + // NarrowSize.
> >> + if (SizeOp0 % NarrowSize != 0)
> >> + return UnableToLegalize;
> >> // Expand in terms of carry-setting/consuming G_ADDE instructions.
> >> - int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits()
> /
> >> - NarrowTy.getSizeInBits();
> >> + int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
> >>
> >> SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
> >> extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts,
> Src1Regs);
> >> @@ -221,9 +230,12 @@ LegalizerHelper::LegalizeResult Legalize
> >> if (TypeIdx != 1)
> >> return UnableToLegalize;
> >>
> >> - int64_t NarrowSize = NarrowTy.getSizeInBits();
> >> - int NumParts =
> >> - MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() /
> NarrowSize;
> >> + int64_t SizeOp1 = MRI.getType(MI.getOperand(1).
> getReg()).getSizeInBits();
> >> + // FIXME: add support for when SizeOp1 isn't an exact multiple of
> >> + // NarrowSize.
> >> + if (SizeOp1 % NarrowSize != 0)
> >> + return UnableToLegalize;
> >> + int NumParts = SizeOp1 / NarrowSize;
> >>
> >> SmallVector<unsigned, 2> SrcRegs, DstRegs;
> >> SmallVector<uint64_t, 2> Indexes;
> >> @@ -270,12 +282,12 @@ LegalizerHelper::LegalizeResult Legalize
> >> return Legalized;
> >> }
> >> case TargetOpcode::G_INSERT: {
> >> - if (TypeIdx != 0)
> >> + // FIXME: add support for when SizeOp0 isn't an exact multiple of
> >> + // NarrowSize.
> >> + if (SizeOp0 % NarrowSize != 0)
> >> return UnableToLegalize;
> >>
> >> - int64_t NarrowSize = NarrowTy.getSizeInBits();
> >> - int NumParts =
> >> - MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
> NarrowSize;
> >> + int NumParts = SizeOp0 / NarrowSize;
> >>
> >> SmallVector<unsigned, 2> SrcRegs, DstRegs;
> >> SmallVector<uint64_t, 2> Indexes;
> >> @@ -330,9 +342,11 @@ LegalizerHelper::LegalizeResult Legalize
> >> return Legalized;
> >> }
> >> case TargetOpcode::G_LOAD: {
> >> - unsigned NarrowSize = NarrowTy.getSizeInBits();
> >> - int NumParts =
> >> - MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
> NarrowSize;
> >> + // FIXME: add support for when SizeOp0 isn't an exact multiple of
> >> + // NarrowSize.
> >> + if (SizeOp0 % NarrowSize != 0)
> >> + return UnableToLegalize;
> >> + int NumParts = SizeOp0 / NarrowSize;
> >> LLT OffsetTy = LLT::scalar(
> >> MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
> >>
> >> @@ -357,9 +371,11 @@ LegalizerHelper::LegalizeResult Legalize
> >> return Legalized;
> >> }
> >> case TargetOpcode::G_STORE: {
> >> - unsigned NarrowSize = NarrowTy.getSizeInBits();
> >> - int NumParts =
> >> - MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
> NarrowSize;
> >> + // FIXME: add support for when SizeOp0 isn't an exact multiple of
> >> + // NarrowSize.
> >> + if (SizeOp0 % NarrowSize != 0)
> >> + return UnableToLegalize;
> >> + int NumParts = SizeOp0 / NarrowSize;
> >> LLT OffsetTy = LLT::scalar(
> >> MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
> >>
> >> @@ -381,9 +397,11 @@ LegalizerHelper::LegalizeResult Legalize
> >> return Legalized;
> >> }
> >> case TargetOpcode::G_CONSTANT: {
> >> - unsigned NarrowSize = NarrowTy.getSizeInBits();
> >> - int NumParts =
> >> - MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
> NarrowSize;
> >> + // FIXME: add support for when SizeOp0 isn't an exact multiple of
> >> + // NarrowSize.
> >> + if (SizeOp0 % NarrowSize != 0)
> >> + return UnableToLegalize;
> >> + int NumParts = SizeOp0 / NarrowSize;
> >> const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
> >> LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
> >>
> >> @@ -410,9 +428,12 @@ LegalizerHelper::LegalizeResult Legalize
> >> // ...
> >> // AN = BinOp<Ty/N> BN, CN
> >> // A = G_MERGE_VALUES A1, ..., AN
> >> - unsigned NarrowSize = NarrowTy.getSizeInBits();
> >> - int NumParts =
> >> - MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
> NarrowSize;
> >> +
> >> + // FIXME: add support for when SizeOp0 isn't an exact multiple of
> >> + // NarrowSize.
> >> + if (SizeOp0 % NarrowSize != 0)
> >> + return UnableToLegalize;
> >> + int NumParts = SizeOp0 / NarrowSize;
> >>
> >> // List the registers where the destination will be scattered.
> >> SmallVector<unsigned, 2> DstRegs;
> >> @@ -854,7 +875,12 @@ LegalizerHelper::fewerElementsVector(Mac
> >> case TargetOpcode::G_ADD: {
> >> unsigned NarrowSize = NarrowTy.getSizeInBits();
> >> unsigned DstReg = MI.getOperand(0).getReg();
> >> - int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
> >> + unsigned Size = MRI.getType(DstReg).getSizeInBits();
> >> + int NumParts = Size / NarrowSize;
> >> + // FIXME: Don't know how to handle the situation where the small
> vectors
> >> + // aren't all the same size yet.
> >> + if (Size % NarrowSize != 0)
> >> + return UnableToLegalize;
> >>
> >> MIRBuilder.setInstr(MI);
> >>
> >>
> >> Modified: llvm/trunk/lib/CodeGen/GlobalISel/LegalizerInfo.cpp
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> CodeGen/GlobalISel/LegalizerInfo.cpp?rev=317560&
> r1=317559&r2=317560&view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/lib/CodeGen/GlobalISel/LegalizerInfo.cpp (original)
> >> +++ llvm/trunk/lib/CodeGen/GlobalISel/LegalizerInfo.cpp Tue Nov 7
> 02:34:34 2017
> >> @@ -28,46 +28,130 @@
> >> #include "llvm/Support/MathExtras.h"
> >> #include "llvm/Target/TargetOpcodes.h"
> >> #include <algorithm>
> >> -#include <cassert>
> >> -#include <tuple>
> >> -#include <utility>
> >> -
> >> +#include <map>
> >> using namespace llvm;
> >>
> >> -LegalizerInfo::LegalizerInfo() {
> >> - DefaultActions[TargetOpcode::G_IMPLICIT_DEF] = NarrowScalar;
> >> -
> >> - // FIXME: these two can be legalized to the fundamental load/store
> Jakob
> >> - // proposed. Once loads & stores are supported.
> >> - DefaultActions[TargetOpcode::G_ANYEXT] = Legal;
> >> - DefaultActions[TargetOpcode::G_TRUNC] = Legal;
> >> -
> >> - DefaultActions[TargetOpcode::G_INTRINSIC] = Legal;
> >> - DefaultActions[TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS] = Legal;
> >> -
> >> - DefaultActions[TargetOpcode::G_ADD] = NarrowScalar;
> >> - DefaultActions[TargetOpcode::G_LOAD] = NarrowScalar;
> >> - DefaultActions[TargetOpcode::G_STORE] = NarrowScalar;
> >> - DefaultActions[TargetOpcode::G_OR] = NarrowScalar;
> >> -
> >> - DefaultActions[TargetOpcode::G_BRCOND] = WidenScalar;
> >> - DefaultActions[TargetOpcode::G_INSERT] = NarrowScalar;
> >> - DefaultActions[TargetOpcode::G_EXTRACT] = NarrowScalar;
> >> - DefaultActions[TargetOpcode::G_FNEG] = Lower;
> >> +LegalizerInfo::LegalizerInfo() : TablesInitialized(false) {
> >> + // Set defaults.
> >> + // FIXME: these two (G_ANYEXT and G_TRUNC?) can be legalized to the
> >> + // fundamental load/store Jakob proposed. Once loads & stores are
> supported.
> >> + setScalarAction(TargetOpcode::G_ANYEXT, 1, {{1, Legal}});
> >> + setScalarAction(TargetOpcode::G_ZEXT, 1, {{1, Legal}});
> >> + setScalarAction(TargetOpcode::G_SEXT, 1, {{1, Legal}});
> >> + setScalarAction(TargetOpcode::G_TRUNC, 0, {{1, Legal}});
> >> + setScalarAction(TargetOpcode::G_TRUNC, 1, {{1, Legal}});
> >> +
> >> + setScalarAction(TargetOpcode::G_INTRINSIC, 0, {{1, Legal}});
> >> + setScalarAction(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS, 0, {{1,
> Legal}});
> >> +
> >> + setLegalizeScalarToDifferentSizeStrategy(
> >> + TargetOpcode::G_IMPLICIT_DEF, 0, narrowToSmallerAndUnsupportedI
> fTooSmall);
> >> + setLegalizeScalarToDifferentSizeStrategy(
> >> + TargetOpcode::G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
> >> + setLegalizeScalarToDifferentSizeStrategy(
> >> + TargetOpcode::G_OR, 0, widenToLargerTypesAndNarrowToLargest);
> >> + setLegalizeScalarToDifferentSizeStrategy(
> >> + TargetOpcode::G_LOAD, 0, narrowToSmallerAndUnsupportedI
> fTooSmall);
> >> + setLegalizeScalarToDifferentSizeStrategy(
> >> + TargetOpcode::G_STORE, 0, narrowToSmallerAndUnsupportedI
> fTooSmall);
> >> +
> >> + setLegalizeScalarToDifferentSizeStrategy(
> >> + TargetOpcode::G_BRCOND, 0, widenToLargerTypesUnsupportedO
> therwise);
> >> + setLegalizeScalarToDifferentSizeStrategy(
> >> + TargetOpcode::G_INSERT, 0, narrowToSmallerAndUnsupportedI
> fTooSmall);
> >> + setLegalizeScalarToDifferentSizeStrategy(
> >> + TargetOpcode::G_EXTRACT, 0, narrowToSmallerAndUnsupportedI
> fTooSmall);
> >> + setLegalizeScalarToDifferentSizeStrategy(
> >> + TargetOpcode::G_EXTRACT, 1, narrowToSmallerAndUnsupportedI
> fTooSmall);
> >> + setScalarAction(TargetOpcode::G_FNEG, 0, {{1, Lower}});
> >> }
> >>
> >> void LegalizerInfo::computeTables() {
> >> - for (unsigned Opcode = 0; Opcode <= LastOp - FirstOp; ++Opcode) {
> >> - for (unsigned Idx = 0, End = Actions[Opcode].size(); Idx != End;
> ++Idx) {
> >> - for (auto &Action : Actions[Opcode][Idx]) {
> >> - LLT Ty = Action.first;
> >> - if (!Ty.isVector())
> >> - continue;
> >> -
> >> - auto &Entry = MaxLegalVectorElts[std::make_pair(Opcode +
> FirstOp,
> >> -
> Ty.getElementType())];
> >> - Entry = std::max(Entry, Ty.getNumElements());
> >> + assert(TablesInitialized == false);
> >> +
> >> + for (unsigned OpcodeIdx = 0; OpcodeIdx <= LastOp - FirstOp;
> ++OpcodeIdx) {
> >> + const unsigned Opcode = FirstOp + OpcodeIdx;
> >> + for (unsigned TypeIdx = 0; TypeIdx != SpecifiedActions[OpcodeIdx].
> size();
> >> + ++TypeIdx) {
> >> + // 0. Collect information specified through the setAction API,
> i.e.
> >> + // for specific bit sizes.
> >> + // For scalar types:
> >> + SizeAndActionsVec ScalarSpecifiedActions;
> >> + // For pointer types:
> >> + std::map<uint16_t, SizeAndActionsVec>
> AddressSpace2SpecifiedActions;
> >> + // For vector types:
> >> + std::map<uint16_t, SizeAndActionsVec> ElemSize2SpecifiedActions;
> >> + for (auto LLT2Action : SpecifiedActions[OpcodeIdx][TypeIdx]) {
> >> + const LLT Type = LLT2Action.first;
> >> + const LegalizeAction Action = LLT2Action.second;
> >> +
> >> + auto SizeAction = std::make_pair(Type.getSizeInBits(),
> Action);
> >> + if (Type.isPointer())
> >> + AddressSpace2SpecifiedActions[Type.getAddressSpace()].push_
> back(
> >> + SizeAction);
> >> + else if (Type.isVector())
> >> + ElemSize2SpecifiedActions[Type.getElementType().
> getSizeInBits()]
> >> + .push_back(SizeAction);
> >> + else
> >> + ScalarSpecifiedActions.push_back(SizeAction);
> >> + }
> >> +
> >> + // 1. Handle scalar types
> >> + {
> >> + // Decide how to handle bit sizes for which no explicit
> specification
> >> + // was given.
> >> + SizeChangeStrategy S = &unsupportedForDifferentSizes;
> >> + if (TypeIdx < ScalarSizeChangeStrategies[OpcodeIdx].size() &&
> >> + ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)
> >> + S = ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx];
> >> + std::sort(ScalarSpecifiedActions.begin(),
> ScalarSpecifiedActions.end());
> >> + checkPartialSizeAndActionsVector(ScalarSpecifiedActions);
> >> + setScalarAction(Opcode, TypeIdx, S(ScalarSpecifiedActions));
> >> + }
> >> +
> >> + // 2. Handle pointer types
> >> + for (auto PointerSpecifiedActions :
> AddressSpace2SpecifiedActions) {
> >> + std::sort(PointerSpecifiedActions.second.begin(),
> >> + PointerSpecifiedActions.second.end());
> >> + checkPartialSizeAndActionsVector(PointerSpecifiedActions.
> second);
> >> + // For pointer types, we assume that there isn't a meaningfull
> way
> >> + // to change the number of bits used in the pointer.
> >> + setPointerAction(
> >> + Opcode, TypeIdx, PointerSpecifiedActions.first,
> >> + unsupportedForDifferentSizes(PointerSpecifiedActions.
> second));
> >> + }
> >> +
> >> + // 3. Handle vector types
> >> + SizeAndActionsVec ElementSizesSeen;
> >> + for (auto VectorSpecifiedActions : ElemSize2SpecifiedActions) {
> >> + std::sort(VectorSpecifiedActions.second.begin(),
> >> + VectorSpecifiedActions.second.end());
> >> + const uint16_t ElementSize = VectorSpecifiedActions.first;
> >> + ElementSizesSeen.push_back({ElementSize, Legal});
> >> + checkPartialSizeAndActionsVector(VectorSpecifiedActions.
> second);
> >> + // For vector types, we assume that the best way to adapt the
> number
> >> + // of elements is to the next larger number of elements type
> for which
> >> + // the vector type is legal, unless there is no such type. In
> that case,
> >> + // legalize towards a vector type with a smaller number of
> elements.
> >> + SizeAndActionsVec NumElementsActions;
> >> + for (SizeAndAction BitsizeAndAction :
> VectorSpecifiedActions.second) {
> >> + assert(BitsizeAndAction.first % ElementSize == 0);
> >> + const uint16_t NumElements = BitsizeAndAction.first /
> ElementSize;
> >> + NumElementsActions.push_back({NumElements,
> BitsizeAndAction.second});
> >> + }
> >> + setVectorNumElementAction(
> >> + Opcode, TypeIdx, ElementSize,
> >> + moreToWiderTypesAndLessToWidest(NumElementsActions));
> >> }
> >> + std::sort(ElementSizesSeen.begin(), ElementSizesSeen.end());
> >> + SizeChangeStrategy VectorElementSizeChangeStrategy =
> >> + &unsupportedForDifferentSizes;
> >> + if (TypeIdx < VectorElementSizeChangeStrategies[OpcodeIdx].size()
> &&
> >> + VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] !=
> nullptr)
> >> + VectorElementSizeChangeStrategy =
> >> + VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx];
> >> + setScalarInVectorAction(
> >> + Opcode, TypeIdx, VectorElementSizeChangeStrateg
> y(ElementSizesSeen));
> >> }
> >> }
> >>
> >> @@ -90,69 +174,24 @@ LegalizerInfo::getAction(const InstrAspe
> >> Aspect.Opcode == TargetOpcode::G_UNMERGE_VALUES)
> >> return std::make_pair(Legal, Aspect.Type);
> >>
> >> - LLT Ty = Aspect.Type;
> >> - LegalizeAction Action = findInActions(Aspect);
> >> - // LegalizerHelper is not able to handle non-power-of-2 types right
> now, so do
> >> - // not try to legalize them unless they are marked as Legal or
> Custom.
> >> - // FIXME: This is a temporary hack until the general non-power-of-2
> >> - // legalization works.
> >> - if (!isPowerOf2_64(Ty.getSizeInBits()) &&
> >> - !(Action == Legal || Action == Custom))
> >> - return std::make_pair(Unsupported, LLT());
> >> -
> >> - if (Action != NotFound)
> >> - return findLegalAction(Aspect, Action);
> >> -
> >> - unsigned Opcode = Aspect.Opcode;
> >> - if (!Ty.isVector()) {
> >> - auto DefaultAction = DefaultActions.find(Aspect.Opcode);
> >> - if (DefaultAction != DefaultActions.end() && DefaultAction->second
> == Legal)
> >> - return std::make_pair(Legal, Ty);
> >> -
> >> - if (DefaultAction != DefaultActions.end() && DefaultAction->second
> == Lower)
> >> - return std::make_pair(Lower, Ty);
> >> -
> >> - if (DefaultAction == DefaultActions.end() ||
> >> - DefaultAction->second != NarrowScalar)
> >> - return std::make_pair(Unsupported, LLT());
> >> - return findLegalAction(Aspect, NarrowScalar);
> >> - }
> >> -
> >> - LLT EltTy = Ty.getElementType();
> >> - int NumElts = Ty.getNumElements();
> >> -
> >> - auto ScalarAction = ScalarInVectorActions.find(std::make_pair(Opcode,
> EltTy));
> >> - if (ScalarAction != ScalarInVectorActions.end() &&
> >> - ScalarAction->second != Legal)
> >> - return findLegalAction(Aspect, ScalarAction->second);
> >> -
> >> - // The element type is legal in principle, but the number of
> elements is
> >> - // wrong.
> >> - auto MaxLegalElts = MaxLegalVectorElts.lookup(std::make_pair(Opcode,
> EltTy));
> >> - if (MaxLegalElts > NumElts)
> >> - return findLegalAction(Aspect, MoreElements);
> >> -
> >> - if (MaxLegalElts == 0) {
> >> - // Scalarize if there's no legal vector type, which is just a
> special case
> >> - // of FewerElements.
> >> - return std::make_pair(FewerElements, EltTy);
> >> - }
> >> -
> >> - return findLegalAction(Aspect, FewerElements);
> >> + if (Aspect.Type.isScalar() || Aspect.Type.isPointer())
> >> + return findScalarLegalAction(Aspect);
> >> + assert(Aspect.Type.isVector());
> >> + return findVectorLegalAction(Aspect);
> >> }
> >>
> >> std::tuple<LegalizerInfo::LegalizeAction, unsigned, LLT>
> >> LegalizerInfo::getAction(const MachineInstr &MI,
> >> const MachineRegisterInfo &MRI) const {
> >> SmallBitVector SeenTypes(8);
> >> - const MCInstrDesc &MCID = MI.getDesc();
> >> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> >> - for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) {
> >> + const MCOperandInfo *OpInfo = MI.getDesc().OpInfo;
> >> + // FIXME: probably we'll need to cache the results here somehow?
> >> + for (unsigned i = 0; i < MI.getDesc().getNumOperands(); ++i) {
> >> if (!OpInfo[i].isGenericType())
> >> continue;
> >>
> >> - // We don't want to repeatedly check the same operand index, that
> >> - // could get expensive.
> >> + // We must only record actions once for each TypeIdx; otherwise
> we'd
> >> + // try to legalize operands multiple times down the line.
> >> unsigned TypeIdx = OpInfo[i].getGenericTypeIndex();
> >> if (SeenTypes[TypeIdx])
> >> continue;
> >> @@ -172,38 +211,164 @@ bool LegalizerInfo::isLegal(const Machin
> >> return std::get<0>(getAction(MI, MRI)) == Legal;
> >> }
> >>
> >> -Optional<LLT> LegalizerInfo::findLegalType(const InstrAspect &Aspect,
> >> - LegalizeAction Action) const {
> >> - switch(Action) {
> >> - default:
> >> - llvm_unreachable("Cannot find legal type");
> >> +bool LegalizerInfo::legalizeCustom(MachineInstr &MI,
> MachineRegisterInfo &MRI,
> >> + MachineIRBuilder &MIRBuilder) const
> {
> >> + return false;
> >> +}
> >> +
> >> +LegalizerInfo::SizeAndActionsVec
> >> +LegalizerInfo::increaseToLargerTypesAndDecreaseToLargest(
> >> + const SizeAndActionsVec &v, LegalizeAction IncreaseAction,
> >> + LegalizeAction DecreaseAction) {
> >> + SizeAndActionsVec result;
> >> + unsigned LargestSizeSoFar = 0;
> >> + if (v.size() >= 1 && v[0].first != 1)
> >> + result.push_back({1, IncreaseAction});
> >> + for (size_t i = 0; i < v.size(); ++i) {
> >> + result.push_back(v[i]);
> >> + LargestSizeSoFar = v[i].first;
> >> + if (i + 1 < v.size() && v[i + 1].first != v[i].first + 1) {
> >> + result.push_back({LargestSizeSoFar + 1, IncreaseAction});
> >> + LargestSizeSoFar = v[i].first + 1;
> >> + }
> >> + }
> >> + result.push_back({LargestSizeSoFar + 1, DecreaseAction});
> >> + return result;
> >> +}
> >> +
> >> +LegalizerInfo::SizeAndActionsVec
> >> +LegalizerInfo::decreaseToSmallerTypesAndIncreaseToSmallest(
> >> + const SizeAndActionsVec &v, LegalizeAction DecreaseAction,
> >> + LegalizeAction IncreaseAction) {
> >> + SizeAndActionsVec result;
> >> + if (v.size() == 0 || v[0].first != 1)
> >> + result.push_back({1, IncreaseAction});
> >> + for (size_t i = 0; i < v.size(); ++i) {
> >> + result.push_back(v[i]);
> >> + if (i + 1 == v.size() || v[i + 1].first != v[i].first + 1) {
> >> + result.push_back({v[i].first + 1, DecreaseAction});
> >> + }
> >> + }
> >> + return result;
> >> +}
> >> +
> >> +LegalizerInfo::SizeAndAction
> >> +LegalizerInfo::findAction(const SizeAndActionsVec &Vec, const
> uint32_t Size) {
> >> + assert(Size >= 1);
> >> + // Find the last element in Vec that has a bitsize equal to or
> smaller than
> >> + // the requested bit size.
> >> + // That is the element just before the first element that is bigger
> than Size.
> >> + auto VecIt = std::upper_bound(
> >> + Vec.begin(), Vec.end(), Size,
> >> + [](const uint32_t Size, const SizeAndAction lhs) -> bool {
> >> + return Size < lhs.first;
> >> + });
> >> + assert(VecIt != Vec.begin() && "Does Vec not start with size 1?");
> >> + --VecIt;
> >> + int VecIdx = VecIt - Vec.begin();
> >> +
> >> + LegalizeAction Action = Vec[VecIdx].second;
> >> + switch (Action) {
> >> case Legal:
> >> case Lower:
> >> case Libcall:
> >> case Custom:
> >> - return Aspect.Type;
> >> + return {Size, Action};
> >> + case FewerElements:
> >> + // FIXME: is this special case still needed and correct?
> >> + // Special case for scalarization:
> >> + if (Vec == SizeAndActionsVec({{1, FewerElements}}))
> >> + return {1, FewerElements};
> >> case NarrowScalar: {
> >> - return findLegalizableSize(
> >> - Aspect, [&](LLT Ty) -> LLT { return Ty.halfScalarSize(); });
> >> - }
> >> - case WidenScalar: {
> >> - return findLegalizableSize(Aspect, [&](LLT Ty) -> LLT {
> >> - return Ty.getSizeInBits() < 8 ? LLT::scalar(8) :
> Ty.doubleScalarSize();
> >> - });
> >> - }
> >> - case FewerElements: {
> >> - return findLegalizableSize(
> >> - Aspect, [&](LLT Ty) -> LLT { return Ty.halfElements(); });
> >> + // The following needs to be a loop, as for now, we do allow
> needing to
> >> + // go over "Unsupported" bit sizes before finding a legalizable
> bit size.
> >> + // e.g. (s8, WidenScalar), (s9, Unsupported), (s32, Legal). if
> Size==8,
> >> + // we need to iterate over s9, and then to s32 to return (s32,
> Legal).
> >> + // If we want to get rid of the below loop, we should have
> stronger asserts
> >> + // when building the SizeAndActionsVecs, probably not allowing
> >> + // "Unsupported" unless at the ends of the vector.
> >> + for (int i = VecIdx - 1; i >= 0; --i)
> >> + if (!needsLegalizingToDifferentSize(Vec[i].second) &&
> >> + Vec[i].second != Unsupported)
> >> + return {Vec[i].first, Action};
> >> + llvm_unreachable("");
> >> }
> >> + case WidenScalar:
> >> case MoreElements: {
> >> - return findLegalizableSize(
> >> - Aspect, [&](LLT Ty) -> LLT { return Ty.doubleElements(); });
> >> + // See above, the following needs to be a loop, at least for now.
> >> + for (std::size_t i = VecIdx + 1; i < Vec.size(); ++i)
> >> + if (!needsLegalizingToDifferentSize(Vec[i].second) &&
> >> + Vec[i].second != Unsupported)
> >> + return {Vec[i].first, Action};
> >> + llvm_unreachable("");
> >> }
> >> + case Unsupported:
> >> + return {Size, Unsupported};
> >> + case NotFound:
> >> + llvm_unreachable("NotFound");
> >> }
> >> }
> >>
> >> -bool LegalizerInfo::legalizeCustom(MachineInstr &MI,
> >> - MachineRegisterInfo &MRI,
> >> - MachineIRBuilder &MIRBuilder) const
> {
> >> - return false;
> >> +std::pair<LegalizerInfo::LegalizeAction, LLT>
> >> +LegalizerInfo::findScalarLegalAction(const InstrAspect &Aspect) const
> {
> >> + assert(Aspect.Type.isScalar() || Aspect.Type.isPointer());
> >> + if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
> >> + return {NotFound, LLT()};
> >> + const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;
> >> + if (Aspect.Type.isPointer() &&
> >> + AddrSpace2PointerActions[OpcodeIdx].find(Aspect.Type.getAddressSpace())
> ==
> >> + AddrSpace2PointerActions[OpcodeIdx].end()) {
> >> + return {NotFound, LLT()};
> >> + }
> >> + const SmallVector<SizeAndActionsVec, 1> &Actions =
> >> + Aspect.Type.isPointer()
> >> + ? AddrSpace2PointerActions[OpcodeIdx]
> >> + .find(Aspect.Type.getAddressSpace())
> >> + ->second
> >> + : ScalarActions[OpcodeIdx];
> >> + if (Aspect.Idx >= Actions.size())
> >> + return {NotFound, LLT()};
> >> + const SizeAndActionsVec &Vec = Actions[Aspect.Idx];
> >> + // FIXME: speed up this search, e.g. by using a results cache for
> repeated
> >> + // queries?
> >> + auto SizeAndAction = findAction(Vec, Aspect.Type.getSizeInBits());
> >> + return {SizeAndAction.second,
> >> + Aspect.Type.isScalar() ? LLT::scalar(SizeAndAction.first)
> >> + : LLT::pointer(Aspect.Type.
> getAddressSpace(),
> >> + SizeAndAction.first)};
> >> +}
> >> +
> >> +std::pair<LegalizerInfo::LegalizeAction, LLT>
> >> +LegalizerInfo::findVectorLegalAction(const InstrAspect &Aspect) const
> {
> >> + assert(Aspect.Type.isVector());
> >> + // First legalize the vector element size, then legalize the number
> of
> >> + // lanes in the vector.
> >> + if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
> >> + return {NotFound, Aspect.Type};
> >> + const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;
> >> + const unsigned TypeIdx = Aspect.Idx;
> >> + if (TypeIdx >= ScalarInVectorActions[OpcodeIdx].size())
> >> + return {NotFound, Aspect.Type};
> >> + const SizeAndActionsVec &ElemSizeVec =
> >> + ScalarInVectorActions[OpcodeIdx][TypeIdx];
> >> +
> >> + LLT IntermediateType;
> >> + auto ElementSizeAndAction =
> >> + findAction(ElemSizeVec, Aspect.Type.getScalarSizeInBits());
> >> + IntermediateType =
> >> + LLT::vector(Aspect.Type.getNumElements(),
> ElementSizeAndAction.first);
> >> + if (ElementSizeAndAction.second != Legal)
> >> + return {ElementSizeAndAction.second, IntermediateType};
> >> +
> >> + auto i = NumElements2Actions[OpcodeIdx].find(
> >> + IntermediateType.getScalarSizeInBits());
> >> + if (i == NumElements2Actions[OpcodeIdx].end()) {
> >> + return {NotFound, IntermediateType};
> >> + }
> >> + const SizeAndActionsVec &NumElementsVec = (*i).second[TypeIdx];
> >> + auto NumElementsAndAction =
> >> + findAction(NumElementsVec, IntermediateType.getNumElements());
> >> + return {NumElementsAndAction.second,
> >> + LLT::vector(NumElementsAndAction.first,
> >> + IntermediateType.getScalarSizeInBits())};
> >> }
> >>
> >> Modified: llvm/trunk/lib/Support/LowLevelType.cpp
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> Support/LowLevelType.cpp?rev=317560&r1=317559&r2=317560&view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/lib/Support/LowLevelType.cpp (original)
> >> +++ llvm/trunk/lib/Support/LowLevelType.cpp Tue Nov 7 02:34:34 2017
> >> @@ -43,7 +43,7 @@ void LLT::print(raw_ostream &OS) const {
> >> assert(isScalar() && "unexpected type");
> >> OS << "s" << getScalarSizeInBits();
> >> } else
> >> - llvm_unreachable("trying to print an invalid type");
> >> + OS << "LLT_invalid";
> >> }
> >>
> >> const constexpr LLT::BitFieldInfo LLT::ScalarSizeFieldInfo;
> >>
> >> Modified: llvm/trunk/lib/Target/AArch64/AArch64LegalizerInfo.cpp
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/
> AArch64/AArch64LegalizerInfo.cpp?rev=317560&r1=317559&r2=317560&view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/lib/Target/AArch64/AArch64LegalizerInfo.cpp (original)
> >> +++ llvm/trunk/lib/Target/AArch64/AArch64LegalizerInfo.cpp Tue Nov 7
> 02:34:34 2017
> >> @@ -23,6 +23,110 @@
> >>
> >> using namespace llvm;
> >>
> >> +/// FIXME: The following static functions are SizeChangeStrategy
> functions
> >> +/// that are meant to temporarily mimic the behaviour of the old
> legalization
> >> +/// based on doubling/halving non-legal types as closely as possible.
> This is
> >> +/// not entirly possible as only legalizing the types that are exactly
> a power
> >> +/// of 2 times the size of the legal types would require specifying
> all those
> >> +/// sizes explicitly.
> >> +/// In practice, not specifying those isn't a problem, and the below
> functions
> >> +/// should disappear quickly as we add support for legalizing
> non-power-of-2
> >> +/// sized types further.
> >> +static void
> >> +addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec
> &result,
> >> + const LegalizerInfo::SizeAndActionsVec
> &v) {
> >> + for (unsigned i = 0; i < v.size(); ++i) {
> >> + result.push_back(v[i]);
> >> + if (i + 1 < v[i].first && i + 1 < v.size() &&
> >> + v[i + 1].first != v[i].first + 1)
> >> + result.push_back({v[i].first + 1, LegalizerInfo::Unsupported});
> >> + }
> >> +}
> >> +
> >> +static LegalizerInfo::SizeAndActionsVec
> >> +widen_1_narrow_128_ToLargest(const LegalizerInfo::SizeAndActionsVec
> &v) {
> >> + assert(v.size() >= 1);
> >> + assert(v[0].first > 2);
> >> + LegalizerInfo::SizeAndActionsVec result = {{1,
> LegalizerInfo::WidenScalar},
> >> + {2,
> LegalizerInfo::Unsupported}};
> >> + addAndInterleaveWithUnsupported(result, v);
> >> + auto Largest = result.back().first;
> >> + assert(Largest + 1 < 128);
> >> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});
> >> + result.push_back({128, LegalizerInfo::NarrowScalar});
> >> + result.push_back({129, LegalizerInfo::Unsupported});
> >> + return result;
> >> +}
> >> +
> >> +static LegalizerInfo::SizeAndActionsVec
> >> +widen_16(const LegalizerInfo::SizeAndActionsVec &v) {
> >> + assert(v.size() >= 1);
> >> + assert(v[0].first > 17);
> >> + LegalizerInfo::SizeAndActionsVec result = {{1,
> LegalizerInfo::Unsupported},
> >> + {16,
> LegalizerInfo::WidenScalar},
> >> + {17,
> LegalizerInfo::Unsupported}};
> >> + addAndInterleaveWithUnsupported(result, v);
> >> + auto Largest = result.back().first;
> >> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});
> >> + return result;
> >> +}
> >> +
> >> +static LegalizerInfo::SizeAndActionsVec
> >> +widen_1_8(const LegalizerInfo::SizeAndActionsVec &v) {
> >> + assert(v.size() >= 1);
> >> + assert(v[0].first > 9);
> >> + LegalizerInfo::SizeAndActionsVec result = {
> >> + {1, LegalizerInfo::WidenScalar}, {2,
> LegalizerInfo::Unsupported},
> >> + {8, LegalizerInfo::WidenScalar}, {9,
> LegalizerInfo::Unsupported}};
> >> + addAndInterleaveWithUnsupported(result, v);
> >> + auto Largest = result.back().first;
> >> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});
> >> + return result;
> >> +}
> >> +
> >> +static LegalizerInfo::SizeAndActionsVec
> >> +widen_1_8_16(const LegalizerInfo::SizeAndActionsVec &v) {
> >> + assert(v.size() >= 1);
> >> + assert(v[0].first > 17);
> >> + LegalizerInfo::SizeAndActionsVec result = {
> >> + {1, LegalizerInfo::WidenScalar}, {2,
> LegalizerInfo::Unsupported},
> >> + {8, LegalizerInfo::WidenScalar}, {9,
> LegalizerInfo::Unsupported},
> >> + {16, LegalizerInfo::WidenScalar}, {17,
> LegalizerInfo::Unsupported}};
> >> + addAndInterleaveWithUnsupported(result, v);
> >> + auto Largest = result.back().first;
> >> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});
> >> + return result;
> >> +}
> >> +
> >> +static LegalizerInfo::SizeAndActionsVec
> >> +widen_1_8_16_narrowToLargest(const LegalizerInfo::SizeAndActionsVec
> &v) {
> >> + assert(v.size() >= 1);
> >> + assert(v[0].first > 17);
> >> + LegalizerInfo::SizeAndActionsVec result = {
> >> + {1, LegalizerInfo::WidenScalar}, {2,
> LegalizerInfo::Unsupported},
> >> + {8, LegalizerInfo::WidenScalar}, {9,
> LegalizerInfo::Unsupported},
> >> + {16, LegalizerInfo::WidenScalar}, {17,
> LegalizerInfo::Unsupported}};
> >> + addAndInterleaveWithUnsupported(result, v);
> >> + auto Largest = result.back().first;
> >> + result.push_back({Largest + 1, LegalizerInfo::NarrowScalar});
> >> + return result;
> >> +}
> >> +
> >> +static LegalizerInfo::SizeAndActionsVec
> >> +widen_1_8_16_32(const LegalizerInfo::SizeAndActionsVec &v) {
> >> + assert(v.size() >= 1);
> >> + assert(v[0].first > 33);
> >> + LegalizerInfo::SizeAndActionsVec result = {
> >> + {1, LegalizerInfo::WidenScalar}, {2,
> LegalizerInfo::Unsupported},
> >> + {8, LegalizerInfo::WidenScalar}, {9,
> LegalizerInfo::Unsupported},
> >> + {16, LegalizerInfo::WidenScalar}, {17,
> LegalizerInfo::Unsupported},
> >> + {32, LegalizerInfo::WidenScalar}, {33,
> LegalizerInfo::Unsupported}};
> >> + addAndInterleaveWithUnsupported(result, v);
> >> + auto Largest = result.back().first;
> >> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});
> >> + return result;
> >> +}
> >> +
> >> AArch64LegalizerInfo::AArch64LegalizerInfo() {
> >> using namespace TargetOpcode;
> >> const LLT p0 = LLT::pointer(0, 64);
> >> @@ -42,8 +146,7 @@ AArch64LegalizerInfo::AArch64LegalizerIn
> >> for (auto Ty : {s16, s32, s64, p0})
> >> setAction({G_PHI, Ty}, Legal);
> >>
> >> - for (auto Ty : {s1, s8})
> >> - setAction({G_PHI, Ty}, WidenScalar);
> >> + setLegalizeScalarToDifferentSizeStrategy(G_PHI, 0, widen_1_8);
> >>
> >> for (auto Ty : { s32, s64 })
> >> setAction({G_BSWAP, Ty}, Legal);
> >> @@ -54,15 +157,15 @@ AArch64LegalizerInfo::AArch64LegalizerIn
> >> for (auto Ty : {s32, s64, v2s32, v4s32, v2s64})
> >> setAction({BinOp, Ty}, Legal);
> >>
> >> - for (auto Ty : {s1, s8, s16})
> >> - setAction({BinOp, Ty}, WidenScalar);
> >> + if (BinOp != G_ADD)
> >> + setLegalizeScalarToDifferentSizeStrategy(BinOp, 0,
> >> +
> widen_1_8_16_narrowToLargest);
> >> }
> >>
> >> setAction({G_GEP, p0}, Legal);
> >> setAction({G_GEP, 1, s64}, Legal);
> >>
> >> - for (auto Ty : {s1, s8, s16, s32})
> >> - setAction({G_GEP, 1, Ty}, WidenScalar);
> >> + setLegalizeScalarToDifferentSizeStrategy(G_GEP, 1, widen_1_8_16_32);
> >>
> >> setAction({G_PTR_MASK, p0}, Legal);
> >>
> >> @@ -70,16 +173,17 @@ AArch64LegalizerInfo::AArch64LegalizerIn
> >> for (auto Ty : {s32, s64})
> >> setAction({BinOp, Ty}, Legal);
> >>
> >> - for (auto Ty : {s1, s8, s16})
> >> - setAction({BinOp, Ty}, WidenScalar);
> >> + setLegalizeScalarToDifferentSizeStrategy(BinOp, 0, widen_1_8_16);
> >> }
> >>
> >> for (unsigned BinOp : {G_SREM, G_UREM})
> >> for (auto Ty : { s1, s8, s16, s32, s64 })
> >> setAction({BinOp, Ty}, Lower);
> >>
> >> - for (unsigned Op : {G_SMULO, G_UMULO})
> >> - setAction({Op, s64}, Lower);
> >> + for (unsigned Op : {G_SMULO, G_UMULO}) {
> >> + setAction({Op, 0, s64}, Lower);
> >> + setAction({Op, 1, s1}, Legal);
> >> + }
> >>
> >> for (unsigned Op : {G_UADDE, G_USUBE, G_SADDO, G_SSUBO, G_SMULH,
> G_UMULH}) {
> >> for (auto Ty : { s32, s64 })
> >> @@ -101,8 +205,9 @@ AArch64LegalizerInfo::AArch64LegalizerIn
> >> setAction({G_INSERT, Ty}, Legal);
> >> setAction({G_INSERT, 1, Ty}, Legal);
> >> }
> >> + setLegalizeScalarToDifferentSizeStrategy(G_INSERT, 0,
> >> +
> widen_1_8_16_narrowToLargest);
> >> for (auto Ty : {s1, s8, s16}) {
> >> - setAction({G_INSERT, Ty}, WidenScalar);
> >> setAction({G_INSERT, 1, Ty}, Legal);
> >> // FIXME: Can't widen the sources because that violates the
> constraints on
> >> // G_INSERT (It seems entirely reasonable that inputs shouldn't
> overlap).
> >> @@ -118,7 +223,8 @@ AArch64LegalizerInfo::AArch64LegalizerIn
> >> for (auto Ty : {s8, s16, s32, s64, p0, v2s32})
> >> setAction({MemOp, Ty}, Legal);
> >>
> >> - setAction({MemOp, s1}, WidenScalar);
> >> + setLegalizeScalarToDifferentSizeStrategy(MemOp, 0,
> >> +
> widen_1_narrow_128_ToLargest);
> >>
> >> // And everything's fine in addrspace 0.
> >> setAction({MemOp, 1, p0}, Legal);
> >> @@ -132,20 +238,16 @@ AArch64LegalizerInfo::AArch64LegalizerIn
> >>
> >> setAction({G_CONSTANT, p0}, Legal);
> >>
> >> - for (auto Ty : {s1, s8, s16})
> >> - setAction({TargetOpcode::G_CONSTANT, Ty}, WidenScalar);
> >> -
> >> - setAction({TargetOpcode::G_FCONSTANT, s16}, WidenScalar);
> >> + setLegalizeScalarToDifferentSizeStrategy(G_CONSTANT, 0,
> widen_1_8_16);
> >> + setLegalizeScalarToDifferentSizeStrategy(G_FCONSTANT, 0, widen_16);
> >>
> >> setAction({G_ICMP, 1, s32}, Legal);
> >> setAction({G_ICMP, 1, s64}, Legal);
> >> setAction({G_ICMP, 1, p0}, Legal);
> >>
> >> - for (auto Ty : {s1, s8, s16}) {
> >> - setAction({G_ICMP, Ty}, WidenScalar);
> >> - setAction({G_FCMP, Ty}, WidenScalar);
> >> - setAction({G_ICMP, 1, Ty}, WidenScalar);
> >> - }
> >> + setLegalizeScalarToDifferentSizeStrategy(G_ICMP, 0, widen_1_8_16);
> >> + setLegalizeScalarToDifferentSizeStrategy(G_FCMP, 0, widen_1_8_16);
> >> + setLegalizeScalarToDifferentSizeStrategy(G_ICMP, 1, widen_1_8_16);
> >>
> >> setAction({G_ICMP, s32}, Legal);
> >> setAction({G_FCMP, s32}, Legal);
> >> @@ -159,12 +261,6 @@ AArch64LegalizerInfo::AArch64LegalizerIn
> >> setAction({G_ANYEXT, Ty}, Legal);
> >> }
> >>
> >> - for (auto Ty : { s1, s8, s16, s32 }) {
> >> - setAction({G_ZEXT, 1, Ty}, Legal);
> >> - setAction({G_SEXT, 1, Ty}, Legal);
> >> - setAction({G_ANYEXT, 1, Ty}, Legal);
> >> - }
> >> -
> >> // FP conversions
> >> for (auto Ty : { s16, s32 }) {
> >> setAction({G_FPTRUNC, Ty}, Legal);
> >> @@ -176,12 +272,6 @@ AArch64LegalizerInfo::AArch64LegalizerIn
> >> setAction({G_FPEXT, Ty}, Legal);
> >> }
> >>
> >> - for (auto Ty : { s1, s8, s16, s32 })
> >> - setAction({G_TRUNC, Ty}, Legal);
> >> -
> >> - for (auto Ty : { s8, s16, s32, s64 })
> >> - setAction({G_TRUNC, 1, Ty}, Legal);
> >> -
> >> // Conversions
> >> for (auto Ty : { s32, s64 }) {
> >> setAction({G_FPTOSI, 0, Ty}, Legal);
> >> @@ -189,12 +279,10 @@ AArch64LegalizerInfo::AArch64LegalizerIn
> >> setAction({G_SITOFP, 1, Ty}, Legal);
> >> setAction({G_UITOFP, 1, Ty}, Legal);
> >> }
> >> - for (auto Ty : { s1, s8, s16 }) {
> >> - setAction({G_FPTOSI, 0, Ty}, WidenScalar);
> >> - setAction({G_FPTOUI, 0, Ty}, WidenScalar);
> >> - setAction({G_SITOFP, 1, Ty}, WidenScalar);
> >> - setAction({G_UITOFP, 1, Ty}, WidenScalar);
> >> - }
> >> + setLegalizeScalarToDifferentSizeStrategy(G_FPTOSI, 0, widen_1_8_16);
> >> + setLegalizeScalarToDifferentSizeStrategy(G_FPTOUI, 0, widen_1_8_16);
> >> + setLegalizeScalarToDifferentSizeStrategy(G_SITOFP, 1, widen_1_8_16);
> >> + setLegalizeScalarToDifferentSizeStrategy(G_UITOFP, 1, widen_1_8_16);
> >>
> >> for (auto Ty : { s32, s64 }) {
> >> setAction({G_FPTOSI, 1, Ty}, Legal);
> >> @@ -209,8 +297,7 @@ AArch64LegalizerInfo::AArch64LegalizerIn
> >> setAction({G_BRINDIRECT, p0}, Legal);
> >>
> >> // Select
> >> - for (auto Ty : {s1, s8, s16})
> >> - setAction({G_SELECT, Ty}, WidenScalar);
> >> + setLegalizeScalarToDifferentSizeStrategy(G_SELECT, 0, widen_1_8_16);
> >>
> >> for (auto Ty : {s32, s64, p0})
> >> setAction({G_SELECT, Ty}, Legal);
> >>
> >> Modified: llvm/trunk/lib/Target/ARM/ARMLegalizerInfo.cpp
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/
> ARM/ARMLegalizerInfo.cpp?rev=317560&r1=317559&r2=317560&view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/lib/Target/ARM/ARMLegalizerInfo.cpp (original)
> >> +++ llvm/trunk/lib/Target/ARM/ARMLegalizerInfo.cpp Tue Nov 7 02:34:34
> 2017
> >> @@ -24,6 +24,54 @@
> >>
> >> using namespace llvm;
> >>
> >> +/// FIXME: The following static functions are SizeChangeStrategy
> functions
> >> +/// that are meant to temporarily mimic the behaviour of the old
> legalization
> >> +/// based on doubling/halving non-legal types as closely as possible.
> This is
> >> +/// not entirly possible as only legalizing the types that are exactly
> a power
> >> +/// of 2 times the size of the legal types would require specifying
> all those
> >> +/// sizes explicitly.
> >> +/// In practice, not specifying those isn't a problem, and the below
> functions
> >> +/// should disappear quickly as we add support for legalizing
> non-power-of-2
> >> +/// sized types further.
> >> +static void
> >> +addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec
> &result,
> >> + const LegalizerInfo::SizeAndActionsVec
> &v) {
> >> + for (unsigned i = 0; i < v.size(); ++i) {
> >> + result.push_back(v[i]);
> >> + if (i + 1 < v[i].first && i + 1 < v.size() &&
> >> + v[i + 1].first != v[i].first + 1)
> >> + result.push_back({v[i].first + 1, LegalizerInfo::Unsupported});
> >> + }
> >> +}
> >> +
> >> +static LegalizerInfo::SizeAndActionsVec
> >> +widen_8_16(const LegalizerInfo::SizeAndActionsVec &v) {
> >> + assert(v.size() >= 1);
> >> + assert(v[0].first > 17);
> >> + LegalizerInfo::SizeAndActionsVec result = {
> >> + {1, LegalizerInfo::Unsupported},
> >> + {8, LegalizerInfo::WidenScalar}, {9,
> LegalizerInfo::Unsupported},
> >> + {16, LegalizerInfo::WidenScalar}, {17,
> LegalizerInfo::Unsupported}};
> >> + addAndInterleaveWithUnsupported(result, v);
> >> + auto Largest = result.back().first;
> >> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});
> >> + return result;
> >> +}
> >> +
> >> +static LegalizerInfo::SizeAndActionsVec
> >> +widen_1_8_16(const LegalizerInfo::SizeAndActionsVec &v) {
> >> + assert(v.size() >= 1);
> >> + assert(v[0].first > 17);
> >> + LegalizerInfo::SizeAndActionsVec result = {
> >> + {1, LegalizerInfo::WidenScalar}, {2,
> LegalizerInfo::Unsupported},
> >> + {8, LegalizerInfo::WidenScalar}, {9,
> LegalizerInfo::Unsupported},
> >> + {16, LegalizerInfo::WidenScalar}, {17,
> LegalizerInfo::Unsupported}};
> >> + addAndInterleaveWithUnsupported(result, v);
> >> + auto Largest = result.back().first;
> >> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});
> >> + return result;
> >> +}
> >> +
> >> static bool AEABI(const ARMSubtarget &ST) {
> >> return ST.isTargetAEABI() || ST.isTargetGNUAEABI() ||
> ST.isTargetMuslAEABI();
> >> }
> >> @@ -49,14 +97,15 @@ ARMLegalizerInfo::ARMLegalizerInfo(const
> >> }
> >>
> >> for (unsigned Op : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) {
> >> - for (auto Ty : {s1, s8, s16})
> >> - setAction({Op, Ty}, WidenScalar);
> >> + if (Op != G_ADD)
> >> + setLegalizeScalarToDifferentSizeStrategy(
> >> + Op, 0, widenToLargerTypesUnsupportedOtherwise);
> >> setAction({Op, s32}, Legal);
> >> }
> >>
> >> for (unsigned Op : {G_SDIV, G_UDIV}) {
> >> - for (auto Ty : {s8, s16})
> >> - setAction({Op, Ty}, WidenScalar);
> >> + setLegalizeScalarToDifferentSizeStrategy(Op, 0,
> >> + widenToLargerTypesUnsupportedOtherwise);
> >> if (ST.hasDivideInARMMode())
> >> setAction({Op, s32}, Legal);
> >> else
> >> @@ -64,8 +113,7 @@ ARMLegalizerInfo::ARMLegalizerInfo(const
> >> }
> >>
> >> for (unsigned Op : {G_SREM, G_UREM}) {
> >> - for (auto Ty : {s8, s16})
> >> - setAction({Op, Ty}, WidenScalar);
> >> + setLegalizeScalarToDifferentSizeStrategy(Op, 0, widen_8_16);
> >> if (ST.hasDivideInARMMode())
> >> setAction({Op, s32}, Lower);
> >> else if (AEABI(ST))
> >> @@ -74,10 +122,8 @@ ARMLegalizerInfo::ARMLegalizerInfo(const
> >> setAction({Op, s32}, Libcall);
> >> }
> >>
> >> - for (unsigned Op : {G_SEXT, G_ZEXT}) {
> >> + for (unsigned Op : {G_SEXT, G_ZEXT, G_ANYEXT}) {
> >> setAction({Op, s32}, Legal);
> >> - for (auto Ty : {s1, s8, s16})
> >> - setAction({Op, 1, Ty}, Legal);
> >> }
> >>
> >> for (unsigned Op : {G_ASHR, G_LSHR, G_SHL})
> >> @@ -93,12 +139,11 @@ ARMLegalizerInfo::ARMLegalizerInfo(const
> >> setAction({G_BRCOND, s1}, Legal);
> >>
> >> setAction({G_CONSTANT, s32}, Legal);
> >> - for (auto Ty : {s1, s8, s16})
> >> - setAction({G_CONSTANT, Ty}, WidenScalar);
> >> + setLegalizeScalarToDifferentSizeStrategy(G_CONSTANT, 0,
> widen_1_8_16);
> >>
> >> setAction({G_ICMP, s1}, Legal);
> >> - for (auto Ty : {s8, s16})
> >> - setAction({G_ICMP, 1, Ty}, WidenScalar);
> >> + setLegalizeScalarToDifferentSizeStrategy(G_ICMP, 1,
> >> + widenToLargerTypesUnsupportedOtherwise);
> >> for (auto Ty : {s32, p0})
> >> setAction({G_ICMP, 1, Ty}, Legal);
> >>
> >>
> >> Modified: llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/
> X86/X86LegalizerInfo.cpp?rev=317560&r1=317559&r2=317560&view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp (original)
> >> +++ llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp Tue Nov 7 02:34:34
> 2017
> >> @@ -22,6 +22,38 @@
> >> using namespace llvm;
> >> using namespace TargetOpcode;
> >>
> >> +/// FIXME: The following static functions are SizeChangeStrategy
> functions
> >> +/// that are meant to temporarily mimic the behaviour of the old
> legalization
> >> +/// based on doubling/halving non-legal types as closely as possible.
> This is
> >> +/// not entirly possible as only legalizing the types that are exactly
> a power
> >> +/// of 2 times the size of the legal types would require specifying
> all those
> >> +/// sizes explicitly.
> >> +/// In practice, not specifying those isn't a problem, and the below
> functions
> >> +/// should disappear quickly as we add support for legalizing
> non-power-of-2
> >> +/// sized types further.
> >> +static void
> >> +addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec
> &result,
> >> + const LegalizerInfo::SizeAndActionsVec
> &v) {
> >> + for (unsigned i = 0; i < v.size(); ++i) {
> >> + result.push_back(v[i]);
> >> + if (i + 1 < v[i].first && i + 1 < v.size() &&
> >> + v[i + 1].first != v[i].first + 1)
> >> + result.push_back({v[i].first + 1, LegalizerInfo::Unsupported});
> >> + }
> >> +}
> >> +
> >> +static LegalizerInfo::SizeAndActionsVec
> >> +widen_1(const LegalizerInfo::SizeAndActionsVec &v) {
> >> + assert(v.size() >= 1);
> >> + assert(v[0].first > 1);
> >> + LegalizerInfo::SizeAndActionsVec result = {{1,
> LegalizerInfo::WidenScalar},
> >> + {2,
> LegalizerInfo::Unsupported}};
> >> + addAndInterleaveWithUnsupported(result, v);
> >> + auto Largest = result.back().first;
> >> + result.push_back({Largest + 1, LegalizerInfo::Unsupported});
> >> + return result;
> >> +}
> >> +
> >> X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
> >> const X86TargetMachine &TM)
> >> : Subtarget(STI), TM(TM) {
> >> @@ -37,6 +69,17 @@ X86LegalizerInfo::X86LegalizerInfo(const
> >> setLegalizerInfoAVX512DQ();
> >> setLegalizerInfoAVX512BW();
> >>
> >> + setLegalizeScalarToDifferentSizeStrategy(G_PHI, 0, widen_1);
> >> + for (unsigned BinOp : {G_SUB, G_MUL, G_AND, G_OR, G_XOR})
> >> + setLegalizeScalarToDifferentSizeStrategy(BinOp, 0, widen_1);
> >> + for (unsigned MemOp : {G_LOAD, G_STORE})
> >> + setLegalizeScalarToDifferentSizeStrategy(MemOp, 0,
> >> + narrowToSmallerAndWidenToSmallest);
> >> + setLegalizeScalarToDifferentSizeStrategy(
> >> + G_GEP, 1, widenToLargerTypesUnsupportedOtherwise);
> >> + setLegalizeScalarToDifferentSizeStrategy(
> >> + G_CONSTANT, 0, widenToLargerTypesAndNarrowToLargest);
> >> +
> >> computeTables();
> >> }
> >>
> >> @@ -47,7 +90,6 @@ void X86LegalizerInfo::setLegalizerInfo3
> >> const LLT s8 = LLT::scalar(8);
> >> const LLT s16 = LLT::scalar(16);
> >> const LLT s32 = LLT::scalar(32);
> >> - const LLT s64 = LLT::scalar(64);
> >>
> >> for (auto Ty : {p0, s1, s8, s16, s32})
> >> setAction({G_IMPLICIT_DEF, Ty}, Legal);
> >> @@ -55,15 +97,10 @@ void X86LegalizerInfo::setLegalizerInfo3
> >> for (auto Ty : {s8, s16, s32, p0})
> >> setAction({G_PHI, Ty}, Legal);
> >>
> >> - setAction({G_PHI, s1}, WidenScalar);
> >> -
> >> - for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) {
> >> + for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
> >> for (auto Ty : {s8, s16, s32})
> >> setAction({BinOp, Ty}, Legal);
> >>
> >> - setAction({BinOp, s1}, WidenScalar);
> >> - }
> >> -
> >> for (unsigned Op : {G_UADDE}) {
> >> setAction({Op, s32}, Legal);
> >> setAction({Op, 1, s1}, Legal);
> >> @@ -73,7 +110,6 @@ void X86LegalizerInfo::setLegalizerInfo3
> >> for (auto Ty : {s8, s16, s32, p0})
> >> setAction({MemOp, Ty}, Legal);
> >>
> >> - setAction({MemOp, s1}, WidenScalar);
> >> // And everything's fine in addrspace 0.
> >> setAction({MemOp, 1, p0}, Legal);
> >> }
> >> @@ -85,9 +121,6 @@ void X86LegalizerInfo::setLegalizerInfo3
> >> setAction({G_GEP, p0}, Legal);
> >> setAction({G_GEP, 1, s32}, Legal);
> >>
> >> - for (auto Ty : {s1, s8, s16})
> >> - setAction({G_GEP, 1, Ty}, WidenScalar);
> >> -
> >> // Control-flow
> >> setAction({G_BRCOND, s1}, Legal);
> >>
> >> @@ -95,9 +128,6 @@ void X86LegalizerInfo::setLegalizerInfo3
> >> for (auto Ty : {s8, s16, s32, p0})
> >> setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
> >>
> >> - setAction({TargetOpcode::G_CONSTANT, s1}, WidenScalar);
> >> - setAction({TargetOpcode::G_CONSTANT, s64}, NarrowScalar);
> >> -
> >> // Extensions
> >> for (auto Ty : {s8, s16, s32}) {
> >> setAction({G_ZEXT, Ty}, Legal);
> >> @@ -105,12 +135,6 @@ void X86LegalizerInfo::setLegalizerInfo3
> >> setAction({G_ANYEXT, Ty}, Legal);
> >> }
> >>
> >> - for (auto Ty : {s1, s8, s16}) {
> >> - setAction({G_ZEXT, 1, Ty}, Legal);
> >> - setAction({G_SEXT, 1, Ty}, Legal);
> >> - setAction({G_ANYEXT, 1, Ty}, Legal);
> >> - }
> >> -
> >> // Comparison
> >> setAction({G_ICMP, s1}, Legal);
> >>
> >> @@ -123,7 +147,6 @@ void X86LegalizerInfo::setLegalizerInfo6
> >> if (!Subtarget.is64Bit())
> >> return;
> >>
> >> - const LLT s32 = LLT::scalar(32);
> >> const LLT s64 = LLT::scalar(64);
> >>
> >> setAction({G_IMPLICIT_DEF, s64}, Legal);
> >> @@ -145,7 +168,6 @@ void X86LegalizerInfo::setLegalizerInfo6
> >> // Extensions
> >> for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) {
> >> setAction({extOp, s64}, Legal);
> >> - setAction({extOp, 1, s32}, Legal);
> >> }
> >>
> >> // Comparison
> >>
> >> Modified: llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> CodeGen/AArch64/GlobalISel/arm64-fallback.ll?rev=317560&
> r1=317559&r2=317560&view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll
> (original)
> >> +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll Tue
> Nov 7 02:34:34 2017
> >> @@ -167,3 +167,70 @@ end:
> >> %vec = load <2 x i16*>, <2 x i16*>* undef
> >> br label %block
> >> }
> >> +
> >> +; FALLBACK-WITH-REPORT-ERR-G_IMPLICIT_DEF-LEGALIZABLE: (FIXME: this
> is what is expected once we can legalize non-pow-of-2 G_IMPLICIT_DEF)
> remark: <unknown>:0:0: unable to legalize instruction: %vreg1<def>(s96) =
> G_INSERT %vreg2, %vreg0, 0; (in function: nonpow2_insertvalue_narrowing
> >> +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize
> instruction: %vreg2<def>(s96) = G_IMPLICIT_DEF; (in function:
> nonpow2_insertvalue_narrowing
> >> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used
> fallback path for nonpow2_insertvalue_narrowing
> >> +; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_insertvalue_narrowing:
> >> +%struct96 = type { float, float, float }
> >> +define void @nonpow2_insertvalue_narrowing(float %a) {
> >> + %dummy = insertvalue %struct96 undef, float %a, 0
> >> + ret void
> >> +}
> >> +
> >> +; FALLBACK-WITH-REPORT-ERR remark: <unknown>:0:0: unable to legalize
> instruction: %vreg3<def>(s96) = G_ADD %vreg2, %vreg2; (in function:
> nonpow2_add_narrowing
> >> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used
> fallback path for nonpow2_add_narrowing
> >> +; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_add_narrowing:
> >> +define void @nonpow2_add_narrowing() {
> >> + %a = add i128 undef, undef
> >> + %b = trunc i128 %a to i96
> >> + %dummy = add i96 %b, %b
> >> + ret void
> >> +}
> >> +
> >> +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize
> instruction: %vreg3<def>(s96) = G_OR %vreg2, %vreg2; (in function:
> nonpow2_or_narrowing
> >> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used
> fallback path for nonpow2_or_narrowing
> >> +; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_or_narrowing:
> >> +define void @nonpow2_or_narrowing() {
> >> + %a = add i128 undef, undef
> >> + %b = trunc i128 %a to i96
> >> + %dummy = or i96 %b, %b
> >> + ret void
> >> +}
> >> +
> >> +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize
> instruction: %vreg0<def>(s96) = G_LOAD %vreg1; mem:LD12[undef](align=16)
> (in function: nonpow2_load_narrowing
> >> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used
> fallback path for nonpow2_load_narrowing
> >> +; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_load_narrowing:
> >> +define void @nonpow2_load_narrowing() {
> >> + %dummy = load i96, i96* undef
> >> + ret void
> >> +}
> >> +
> >> +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize
> instruction: G_STORE %vreg3, %vreg0; mem:ST12[%c](align=16) (in function:
> nonpow2_store_narrowing
> >> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used
> fallback path for nonpow2_store_narrowing
> >> +; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_store_narrowing:
> >> +define void @nonpow2_store_narrowing(i96* %c) {
> >> + %a = add i128 undef, undef
> >> + %b = trunc i128 %a to i96
> >> + store i96 %b, i96* %c
> >> + ret void
> >> +}
> >> +
> >> +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize
> instruction: %vreg0<def>(s96) = G_CONSTANT 0; (in function:
> nonpow2_constant_narrowing
> >> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used
> fallback path for nonpow2_constant_narrowing
> >> +; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_constant_narrowing:
> >> +define void @nonpow2_constant_narrowing() {
> >> + store i96 0, i96* undef
> >> + ret void
> >> +}
> >> +
> >> +; Currently can't handle vector lengths that aren't an exact multiple
> of
> >> +; natively supported vector lengths. Test that the fall-back works for
> those.
> >> +; FALLBACK-WITH-REPORT-ERR-G_IMPLICIT_DEF-LEGALIZABLE: (FIXME: this
> is what is expected once we can legalize non-pow-of-2 G_IMPLICIT_DEF)
> remark: <unknown>:0:0: unable to legalize instruction: %vreg1<def>(<7 x
> s64>) = G_ADD %vreg0, %vreg0; (in function: nonpow2_vector_add_
> fewerelements
> >> +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize
> instruction: %vreg0<def>(<7 x s64>) = G_IMPLICIT_DEF; (in function:
> nonpow2_vector_add_fewerelements
> >> +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used
> fallback path for nonpow2_vector_add_fewerelements
> >> +; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_vector_add_fewerelements:
> >> +define void @nonpow2_vector_add_fewerelements() {
> >> + %dummy = add <7 x i64> undef, undef
> >> + ret void
> >> +}
> >>
> >> Modified: llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> CodeGen/AArch64/GlobalISel/legalize-add.mir?rev=317560&
> r1=317559&r2=317560&view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir
> (original)
> >> +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir Tue
> Nov 7 02:34:34 2017
> >> @@ -8,6 +8,10 @@
> >> entry:
> >> ret void
> >> }
> >> + define void @test_scalar_add_big_nonpow2() {
> >> + entry:
> >> + ret void
> >> + }
> >> define void @test_scalar_add_small() {
> >> entry:
> >> ret void
> >> @@ -16,6 +20,10 @@
> >> entry:
> >> ret void
> >> }
> >> + define void @test_vector_add_nonpow2() {
> >> + entry:
> >> + ret void
> >> + }
> >> ...
> >>
> >> ---
> >> @@ -58,6 +66,49 @@ body: |
> >> ...
> >>
> >> ---
> >> +name: test_scalar_add_big_nonpow2
> >> +registers:
> >> + - { id: 0, class: _ }
> >> + - { id: 1, class: _ }
> >> + - { id: 2, class: _ }
> >> + - { id: 3, class: _ }
> >> + - { id: 4, class: _ }
> >> + - { id: 5, class: _ }
> >> + - { id: 6, class: _ }
> >> + - { id: 7, class: _ }
> >> + - { id: 8, class: _ }
> >> + - { id: 9, class: _ }
> >> +body: |
> >> + bb.0.entry:
> >> + liveins: %x0, %x1, %x2, %x3
> >> + ; CHECK-LABEL: name: test_scalar_add_big_nonpow2
> >> + ; CHECK-NOT: G_MERGE_VALUES
> >> + ; CHECK-NOT: G_UNMERGE_VALUES
> >> + ; CHECK-DAG: [[CARRY0_32:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
> >> + ; CHECK-DAG: [[CARRY0:%[0-9]+]]:_(s1) = G_TRUNC [[CARRY0_32]]
> >> + ; CHECK: [[RES_LO:%[0-9]+]]:_(s64), [[CARRY1:%[0-9]+]]:_(s1) =
> G_UADDE %0, %1, [[CARRY0]]
> >> + ; CHECK: [[RES_MI:%[0-9]+]]:_(s64), [[CARRY2:%[0-9]+]]:_(s1) =
> G_UADDE %1, %2, [[CARRY1]]
> >> + ; CHECK: [[RES_HI:%[0-9]+]]:_(s64), {{%.*}}(s1) = G_UADDE %2, %3,
> [[CARRY2]]
> >> + ; CHECK-NOT: G_MERGE_VALUES
> >> + ; CHECK-NOT: G_UNMERGE_VALUES
> >> + ; CHECK: %x0 = COPY [[RES_LO]]
> >> + ; CHECK: %x1 = COPY [[RES_MI]]
> >> + ; CHECK: %x2 = COPY [[RES_HI]]
> >> +
> >> + %0(s64) = COPY %x0
> >> + %1(s64) = COPY %x1
> >> + %2(s64) = COPY %x2
> >> + %3(s64) = COPY %x3
> >> + %4(s192) = G_MERGE_VALUES %0, %1, %2
> >> + %5(s192) = G_MERGE_VALUES %1, %2, %3
> >> + %6(s192) = G_ADD %4, %5
> >> + %7(s64), %8(s64), %9(s64) = G_UNMERGE_VALUES %6
> >> + %x0 = COPY %7
> >> + %x1 = COPY %8
> >> + %x2 = COPY %9
> >> +...
> >> +
> >> +---
> >> name: test_scalar_add_small
> >> registers:
> >> - { id: 0, class: _ }
> >> @@ -124,3 +175,43 @@ body: |
> >> %q0 = COPY %7
> >> %q1 = COPY %8
> >> ...
> >> +---
> >> +name: test_vector_add_nonpow2
> >> +registers:
> >> + - { id: 0, class: _ }
> >> + - { id: 1, class: _ }
> >> + - { id: 2, class: _ }
> >> + - { id: 3, class: _ }
> >> + - { id: 4, class: _ }
> >> + - { id: 5, class: _ }
> >> + - { id: 6, class: _ }
> >> + - { id: 7, class: _ }
> >> + - { id: 8, class: _ }
> >> + - { id: 9, class: _ }
> >> +body: |
> >> + bb.0.entry:
> >> + liveins: %q0, %q1, %q2, %q3
> >> + ; CHECK-LABEL: name: test_vector_add_nonpow2
> >> + ; CHECK-NOT: G_EXTRACT
> >> + ; CHECK-NOT: G_SEQUENCE
> >> + ; CHECK: [[RES_LO:%[0-9]+]]:_(<2 x s64>) = G_ADD %0, %1
> >> + ; CHECK: [[RES_MI:%[0-9]+]]:_(<2 x s64>) = G_ADD %1, %2
> >> + ; CHECK: [[RES_HI:%[0-9]+]]:_(<2 x s64>) = G_ADD %2, %3
> >> + ; CHECK-NOT: G_EXTRACT
> >> + ; CHECK-NOT: G_SEQUENCE
> >> + ; CHECK: %q0 = COPY [[RES_LO]]
> >> + ; CHECK: %q1 = COPY [[RES_MI]]
> >> + ; CHECK: %q2 = COPY [[RES_HI]]
> >> +
> >> + %0(<2 x s64>) = COPY %q0
> >> + %1(<2 x s64>) = COPY %q1
> >> + %2(<2 x s64>) = COPY %q2
> >> + %3(<2 x s64>) = COPY %q3
> >> + %4(<6 x s64>) = G_MERGE_VALUES %0, %1, %2
> >> + %5(<6 x s64>) = G_MERGE_VALUES %1, %2, %3
> >> + %6(<6 x s64>) = G_ADD %4, %5
> >> + %7(<2 x s64>), %8(<2 x s64>), %9(<2 x s64>) = G_UNMERGE_VALUES %6
> >> + %q0 = COPY %7
> >> + %q1 = COPY %8
> >> + %q2 = COPY %9
> >> +...
> >>
> >> Modified: llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-
> inserts.mir
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> CodeGen/AArch64/GlobalISel/legalize-inserts.mir?rev=
> 317560&r1=317559&r2=317560&view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir
> (original)
> >> +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir
> Tue Nov 7 02:34:34 2017
> >> @@ -9,6 +9,7 @@
> >> define void @test_inserts_4() { ret void }
> >> define void @test_inserts_5() { ret void }
> >> define void @test_inserts_6() { ret void }
> >> + define void @test_inserts_nonpow2() { ret void }
> >> ...
> >>
> >> ---
> >> @@ -141,3 +142,21 @@ body: |
> >> %4:_(s128) = G_INSERT %3, %2, 32
> >> RET_ReallyLR
> >> ...
> >> +
> >> +---
> >> +name: test_inserts_nonpow2
> >> +body: |
> >> + bb.0:
> >> + liveins: %x0, %x1, %x2
> >> +
> >> +
> >> + ; CHECK-LABEL: name: test_inserts_nonpow2
> >> + ; CHECK: %5:_(s192) = G_MERGE_VALUES %3(s64), %1(s64), %2(s64)
> >> + %0:_(s64) = COPY %x0
> >> + %1:_(s64) = COPY %x1
> >> + %2:_(s64) = COPY %x2
> >> + %3:_(s64) = COPY %x3
> >> + %4:_(s192) = G_MERGE_VALUES %0, %1, %2
> >> + %5:_(s192) = G_INSERT %4, %3, 0
> >> + RET_ReallyLR
> >> +...
> >>
> >> Modified: llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-instruction-
> select.mir
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> CodeGen/ARM/GlobalISel/arm-instruction-select.mir?rev=
> 317560&r1=317559&r2=317560&view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir
> (original)
> >> +++ llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir
> Tue Nov 7 02:34:34 2017
> >> @@ -970,9 +970,10 @@ registers:
> >> - { id: 1, class: gprb }
> >> - { id: 2, class: gprb }
> >> - { id: 3, class: gprb }
> >> + - { id: 4, class: gprb }
> >> body: |
> >> bb.0:
> >> - liveins: %r0, %r1
> >> + liveins: %r0, %r1, %r2
> >>
> >> %0(p0) = COPY %r0
> >> ; CHECK: [[VREGX:%[0-9]+]]:gpr = COPY %r0
> >> @@ -980,14 +981,17 @@ body: |
> >> %1(p0) = COPY %r1
> >> ; CHECK: [[VREGY:%[0-9]+]]:gpr = COPY %r1
> >>
> >> - %2(s1) = G_TRUNC %1(p0)
> >> - ; CHECK: [[VREGC:%[0-9]+]]:gpr = COPY [[VREGY]]
> >> + %2(s32) = COPY %r2
> >> + ; CHECK: [[VREGC:%[0-9]+]]:gpr = COPY %r2
> >>
> >> - %3(p0) = G_SELECT %2(s1), %0, %1
> >> - ; CHECK: CMPri [[VREGC]], 0, 14, _, implicit-def %cpsr
> >> + %3(s1) = G_TRUNC %2(s32)
> >> + ; CHECK: [[VREGD:%[0-9]+]]:gpr = COPY [[VREGC]]
> >> +
> >> + %4(p0) = G_SELECT %3(s1), %0, %1
> >> + ; CHECK: CMPri [[VREGD]], 0, 14, _, implicit-def %cpsr
> >> ; CHECK: [[RES:%[0-9]+]]:gpr = MOVCCr [[VREGX]], [[VREGY]], 0, %cpsr
> >>
> >> - %r0 = COPY %3(p0)
> >> + %r0 = COPY %4(p0)
> >> ; CHECK: %r0 = COPY [[RES]]
> >>
> >> BX_RET 14, _, implicit %r0
> >>
> >> Modified: llvm/trunk/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/
> CodeGen/GlobalISel/LegalizerInfoTest.cpp?rev=317560&r1=317559&r2=317560&
> view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp
> (original)
> >> +++ llvm/trunk/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp Tue
> Nov 7 02:34:34 2017
> >> @@ -49,66 +49,91 @@ TEST(LegalizerInfoTest, ScalarRISC) {
> >> using namespace TargetOpcode;
> >> LegalizerInfo L;
> >> // Typical RISCy set of operations based on AArch64.
> >> - L.setAction({G_ADD, LLT::scalar(8)}, LegalizerInfo::WidenScalar);
> >> - L.setAction({G_ADD, LLT::scalar(16)}, LegalizerInfo::WidenScalar);
> >> - L.setAction({G_ADD, LLT::scalar(32)}, LegalizerInfo::Legal);
> >> - L.setAction({G_ADD, LLT::scalar(64)}, LegalizerInfo::Legal);
> >> + for (auto Op : {G_ADD, G_SUB}) {
> >> + for (unsigned Size : {32, 64})
> >> + L.setAction({Op, 0, LLT::scalar(Size)}, LegalizerInfo::Legal);
> >> + L.setLegalizeScalarToDifferentSizeStrategy(
> >> + Op, 0, LegalizerInfo::widenToLargerTypesAndNarrowToLargest);
> >> + }
> >> +
> >> L.computeTables();
> >>
> >> - // Check we infer the correct types and actually do what we're told.
> >> - ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(8)}),
> >> - std::make_pair(LegalizerInfo::WidenScalar,
> LLT::scalar(32)));
> >> - ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(16)}),
> >> - std::make_pair(LegalizerInfo::WidenScalar,
> LLT::scalar(32)));
> >> - ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(32)}),
> >> - std::make_pair(LegalizerInfo::Legal, LLT::scalar(32)));
> >> - ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(64)}),
> >> - std::make_pair(LegalizerInfo::Legal, LLT::scalar(64)));
> >> -
> >> - // Make sure the default for over-sized types applies.
> >> - ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(128)}),
> >> - std::make_pair(LegalizerInfo::NarrowScalar,
> LLT::scalar(64)));
> >> + for (auto &opcode : {G_ADD, G_SUB}) {
> >> + // Check we infer the correct types and actually do what we're
> told.
> >> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(8)}),
> >> + std::make_pair(LegalizerInfo::WidenScalar,
> LLT::scalar(32)));
> >> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(16)}),
> >> + std::make_pair(LegalizerInfo::WidenScalar,
> LLT::scalar(32)));
> >> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(32)}),
> >> + std::make_pair(LegalizerInfo::Legal, LLT::scalar(32)));
> >> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(64)}),
> >> + std::make_pair(LegalizerInfo::Legal, LLT::scalar(64)));
> >> +
> >> + // Make sure the default for over-sized types applies.
> >> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(128)}),
> >> + std::make_pair(LegalizerInfo::NarrowScalar,
> LLT::scalar(64)));
> >> + // Make sure we also handle unusual sizes
> >> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(1)}),
> >> + std::make_pair(LegalizerInfo::WidenScalar,
> LLT::scalar(32)));
> >> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(31)}),
> >> + std::make_pair(LegalizerInfo::WidenScalar,
> LLT::scalar(32)));
> >> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(33)}),
> >> + std::make_pair(LegalizerInfo::WidenScalar,
> LLT::scalar(64)));
> >> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(63)}),
> >> + std::make_pair(LegalizerInfo::WidenScalar,
> LLT::scalar(64)));
> >> + ASSERT_EQ(L.getAction({opcode, LLT::scalar(65)}),
> >> + std::make_pair(LegalizerInfo::NarrowScalar,
> LLT::scalar(64)));
> >> + }
> >> }
> >>
> >> TEST(LegalizerInfoTest, VectorRISC) {
> >> using namespace TargetOpcode;
> >> LegalizerInfo L;
> >> // Typical RISCy set of operations based on ARM.
> >> - L.setScalarInVectorAction(G_ADD, LLT::scalar(8),
> LegalizerInfo::Legal);
> >> - L.setScalarInVectorAction(G_ADD, LLT::scalar(16),
> LegalizerInfo::Legal);
> >> - L.setScalarInVectorAction(G_ADD, LLT::scalar(32),
> LegalizerInfo::Legal);
> >> -
> >> L.setAction({G_ADD, LLT::vector(8, 8)}, LegalizerInfo::Legal);
> >> L.setAction({G_ADD, LLT::vector(16, 8)}, LegalizerInfo::Legal);
> >> L.setAction({G_ADD, LLT::vector(4, 16)}, LegalizerInfo::Legal);
> >> L.setAction({G_ADD, LLT::vector(8, 16)}, LegalizerInfo::Legal);
> >> L.setAction({G_ADD, LLT::vector(2, 32)}, LegalizerInfo::Legal);
> >> L.setAction({G_ADD, LLT::vector(4, 32)}, LegalizerInfo::Legal);
> >> +
> >> + L.setLegalizeVectorElementToDifferentSizeStrategy(
> >> + G_ADD, 0, LegalizerInfo::widenToLargerTypesUnsupportedO
> therwise);
> >> +
> >> + L.setAction({G_ADD, 0, LLT::scalar(32)}, LegalizerInfo::Legal);
> >> +
> >> L.computeTables();
> >>
> >> // Check we infer the correct types and actually do what we're told
> for some
> >> // simple cases.
> >> - ASSERT_EQ(L.getAction({G_ADD, LLT::vector(2, 8)}),
> >> - std::make_pair(LegalizerInfo::MoreElements,
> LLT::vector(8, 8)));
> >> ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 8)}),
> >> std::make_pair(LegalizerInfo::Legal, LLT::vector(8, 8)));
> >> - ASSERT_EQ(
> >> - L.getAction({G_ADD, LLT::vector(8, 32)}),
> >> - std::make_pair(LegalizerInfo::FewerElements, LLT::vector(4,
> 32)));
> >> + ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 7)}),
> >> + std::make_pair(LegalizerInfo::WidenScalar, LLT::vector(8,
> 8)));
> >> + ASSERT_EQ(L.getAction({G_ADD, LLT::vector(2, 8)}),
> >> + std::make_pair(LegalizerInfo::MoreElements,
> LLT::vector(8, 8)));
> >> + ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 32)}),
> >> + std::make_pair(LegalizerInfo::FewerElements,
> LLT::vector(4, 32)));
> >> + // Check a few non-power-of-2 sizes:
> >> + ASSERT_EQ(L.getAction({G_ADD, LLT::vector(3, 3)}),
> >> + std::make_pair(LegalizerInfo::WidenScalar, LLT::vector(3,
> 8)));
> >> + ASSERT_EQ(L.getAction({G_ADD, LLT::vector(3, 8)}),
> >> + std::make_pair(LegalizerInfo::MoreElements,
> LLT::vector(8, 8)));
> >> }
> >>
> >> TEST(LegalizerInfoTest, MultipleTypes) {
> >> using namespace TargetOpcode;
> >> LegalizerInfo L;
> >> LLT p0 = LLT::pointer(0, 64);
> >> - LLT s32 = LLT::scalar(32);
> >> LLT s64 = LLT::scalar(64);
> >>
> >> // Typical RISCy set of operations based on AArch64.
> >> L.setAction({G_PTRTOINT, 0, s64}, LegalizerInfo::Legal);
> >> L.setAction({G_PTRTOINT, 1, p0}, LegalizerInfo::Legal);
> >>
> >> - L.setAction({G_PTRTOINT, 0, s32}, LegalizerInfo::WidenScalar);
> >> + L.setLegalizeScalarToDifferentSizeStrategy(
> >> + G_PTRTOINT, 0, LegalizerInfo::widenToLargerTypesAndNarrowToL
> argest);
> >> +
> >> L.computeTables();
> >>
> >> // Check we infer the correct types and actually do what we're told.
> >> @@ -116,16 +141,21 @@ TEST(LegalizerInfoTest, MultipleTypes) {
> >> std::make_pair(LegalizerInfo::Legal, s64));
> >> ASSERT_EQ(L.getAction({G_PTRTOINT, 1, p0}),
> >> std::make_pair(LegalizerInfo::Legal, p0));
> >> + // Make sure we also handle unusual sizes
> >> + ASSERT_EQ(L.getAction({G_PTRTOINT, 0, LLT::scalar(65)}),
> >> + std::make_pair(LegalizerInfo::NarrowScalar, s64));
> >> + ASSERT_EQ(L.getAction({G_PTRTOINT, 1, LLT::pointer(0, 32)}),
> >> + std::make_pair(LegalizerInfo::Unsupported,
> LLT::pointer(0, 32)));
> >> }
> >>
> >> TEST(LegalizerInfoTest, MultipleSteps) {
> >> using namespace TargetOpcode;
> >> LegalizerInfo L;
> >> - LLT s16 = LLT::scalar(16);
> >> LLT s32 = LLT::scalar(32);
> >> LLT s64 = LLT::scalar(64);
> >>
> >> - L.setAction({G_UREM, 0, s16}, LegalizerInfo::WidenScalar);
> >> + L.setLegalizeScalarToDifferentSizeStrategy(
> >> + G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedO
> therwise);
> >> L.setAction({G_UREM, 0, s32}, LegalizerInfo::Lower);
> >> L.setAction({G_UREM, 0, s64}, LegalizerInfo::Lower);
> >>
> >> @@ -136,4 +166,33 @@ TEST(LegalizerInfoTest, MultipleSteps) {
> >> ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(32)}),
> >> std::make_pair(LegalizerInfo::Lower, LLT::scalar(32)));
> >> }
> >> +
> >> +TEST(LegalizerInfoTest, SizeChangeStrategy) {
> >> + using namespace TargetOpcode;
> >> + LegalizerInfo L;
> >> + for (unsigned Size : {1, 8, 16, 32})
> >> + L.setAction({G_UREM, 0, LLT::scalar(Size)}, LegalizerInfo::Legal);
> >> +
> >> + L.setLegalizeScalarToDifferentSizeStrategy(
> >> + G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedO
> therwise);
> >> + L.computeTables();
> >> +
> >> + // Check we infer the correct types and actually do what we're told.
> >> + for (unsigned Size : {1, 8, 16, 32}) {
> >> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(Size)}),
> >> + std::make_pair(LegalizerInfo::Legal,
> LLT::scalar(Size)));
> >> + }
> >> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(2)}),
> >> + std::make_pair(LegalizerInfo::WidenScalar,
> LLT::scalar(8)));
> >> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(7)}),
> >> + std::make_pair(LegalizerInfo::WidenScalar,
> LLT::scalar(8)));
> >> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(9)}),
> >> + std::make_pair(LegalizerInfo::WidenScalar,
> LLT::scalar(16)));
> >> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(17)}),
> >> + std::make_pair(LegalizerInfo::WidenScalar,
> LLT::scalar(32)));
> >> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(31)}),
> >> + std::make_pair(LegalizerInfo::WidenScalar,
> LLT::scalar(32)));
> >> + ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(33)}),
> >> + std::make_pair(LegalizerInfo::Unsupported,
> LLT::scalar(33)));
> >> +}
> >> }
> >>
> >> Modified: llvm/trunk/unittests/CodeGen/LowLevelTypeTest.cpp
> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/
> CodeGen/LowLevelTypeTest.cpp?rev=317560&r1=317559&r2=317560&view=diff
> >> ============================================================
> ==================
> >> --- llvm/trunk/unittests/CodeGen/LowLevelTypeTest.cpp (original)
> >> +++ llvm/trunk/unittests/CodeGen/LowLevelTypeTest.cpp Tue Nov 7
> 02:34:34 2017
> >> @@ -36,36 +36,22 @@ TEST(LowLevelTypeTest, Scalar) {
> >>
> >> for (unsigned S : {1U, 17U, 32U, 64U, 0xfffffU}) {
> >> const LLT Ty = LLT::scalar(S);
> >> - const LLT HalfTy = (S % 2) == 0 ? Ty.halfScalarSize() : Ty;
> >> - const LLT DoubleTy = Ty.doubleScalarSize();
> >>
> >> // Test kind.
> >> - for (const LLT TestTy : {Ty, HalfTy, DoubleTy}) {
> >> - ASSERT_TRUE(TestTy.isValid());
> >> - ASSERT_TRUE(TestTy.isScalar());
> >> -
> >> - ASSERT_FALSE(TestTy.isPointer());
> >> - ASSERT_FALSE(TestTy.isVector());
> >> - }
> >> + ASSERT_TRUE(Ty.isValid());
> >> + ASSERT_TRUE(Ty.isScalar());
> >> +
> >> + ASSERT_FALSE(Ty.isPointer());
> >> + ASSERT_FALSE(Ty.isVector());
> >>
> >> // Test sizes.
> >> EXPECT_EQ(S, Ty.getSizeInBits());
> >> EXPECT_EQ(S, Ty.getScalarSizeInBits());
> >>
> >> - EXPECT_EQ(S*2, DoubleTy.getSizeInBits());
> >> - EXPECT_EQ(S*2, DoubleTy.getScalarSizeInBits());
> >> -
> >> - if ((S % 2) == 0) {
> >> - EXPECT_EQ(S/2, HalfTy.getSizeInBits());
> >> - EXPECT_EQ(S/2, HalfTy.getScalarSizeInBits());
> >> - }
> >> -
> >> // Test equality operators.
> >> EXPECT_TRUE(Ty == Ty);
> >> EXPECT_FALSE(Ty != Ty);
> >>
> >> - EXPECT_NE(Ty, DoubleTy);
> >> -
> >> // Test Type->LLT conversion.
> >> Type *IRTy = IntegerType::get(C, S);
> >> EXPECT_EQ(Ty, getLLTForType(*IRTy, DL));
> >> @@ -90,62 +76,18 @@ TEST(LowLevelTypeTest, Vector) {
> >> // Test getElementType().
> >> EXPECT_EQ(STy, VTy.getElementType());
> >>
> >> - const LLT HalfSzTy = ((S % 2) == 0) ? VTy.halfScalarSize() : VTy;
> >> - const LLT DoubleSzTy = VTy.doubleScalarSize();
> >> -
> >> - // halfElements requires an even number of elements.
> >> - const LLT HalfEltIfEvenTy = ((Elts % 2) == 0) ?
> VTy.halfElements() : VTy;
> >> - const LLT DoubleEltTy = VTy.doubleElements();
> >> -
> >> // Test kind.
> >> - for (const LLT TestTy : {VTy, HalfSzTy, DoubleSzTy,
> DoubleEltTy}) {
> >> - ASSERT_TRUE(TestTy.isValid());
> >> - ASSERT_TRUE(TestTy.isVector());
> >> -
> >> - ASSERT_FALSE(TestTy.isScalar());
> >> - ASSERT_FALSE(TestTy.isPointer());
> >> - }
> >> -
> >> - // Test halving elements to a scalar.
> >> - {
> >> - ASSERT_TRUE(HalfEltIfEvenTy.isValid());
> >> - ASSERT_FALSE(HalfEltIfEvenTy.isPointer());
> >> - if (Elts > 2) {
> >> - ASSERT_TRUE(HalfEltIfEvenTy.isVector());
> >> - } else {
> >> - ASSERT_FALSE(HalfEltIfEvenTy.isVector());
> >> - EXPECT_EQ(STy, HalfEltIfEvenTy);
> >> - }
> >> - }
> >> + ASSERT_TRUE(VTy.isValid());
> >> + ASSERT_TRUE(VTy.isVector());
> >>
> >> + ASSERT_FALSE(VTy.isScalar());
> >> + ASSERT_FALSE(VTy.isPointer());
> >>
> >> // Test sizes.
> >> EXPECT_EQ(S * Elts, VTy.getSizeInBits());
> >> EXPECT_EQ(S, VTy.getScalarSizeInBits());
> >> EXPECT_EQ(Elts, VTy.getNumElements());
> >>
> >> - if ((S % 2) == 0) {
> >> - EXPECT_EQ((S / 2) * Elts, HalfSzTy.getSizeInBits());
> >> - EXPECT_EQ(S / 2, HalfSzTy.getScalarSizeInBits());
> >> - EXPECT_EQ(Elts, HalfSzTy.getNumElements());
> >> - }
> >> -
> >> - EXPECT_EQ((S * 2) * Elts, DoubleSzTy.getSizeInBits());
> >> - EXPECT_EQ(S * 2, DoubleSzTy.getScalarSizeInBits());
> >> - EXPECT_EQ(Elts, DoubleSzTy.getNumElements());
> >> -
> >> - if ((Elts % 2) == 0) {
> >> - EXPECT_EQ(S * (Elts / 2), HalfEltIfEvenTy.getSizeInBits());
> >> - EXPECT_EQ(S, HalfEltIfEvenTy.getScalarSizeInBits());
> >> - if (Elts > 2) {
> >> - EXPECT_EQ(Elts / 2, HalfEltIfEvenTy.getNumElements());
> >> - }
> >> - }
> >> -
> >> - EXPECT_EQ(S * (Elts * 2), DoubleEltTy.getSizeInBits());
> >> - EXPECT_EQ(S, DoubleEltTy.getScalarSizeInBits());
> >> - EXPECT_EQ(Elts * 2, DoubleEltTy.getNumElements());
> >> -
> >> // Test equality operators.
> >> EXPECT_TRUE(VTy == VTy);
> >> EXPECT_FALSE(VTy != VTy);
> >> @@ -153,10 +95,6 @@ TEST(LowLevelTypeTest, Vector) {
> >> // Test inequality operators on..
> >> // ..different kind.
> >> EXPECT_NE(VTy, STy);
> >> - // ..different #elts.
> >> - EXPECT_NE(VTy, DoubleEltTy);
> >> - // ..different scalar size.
> >> - EXPECT_NE(VTy, DoubleSzTy);
> >>
> >> // Test Type->LLT conversion.
> >> Type *IRSTy = IntegerType::get(C, S);
> >>
> >>
> >> _______________________________________________
> >> llvm-commits mailing list
> >> llvm-commits at lists.llvm.org
> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> >
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20171108/0c4c6926/attachment-0001.html>
More information about the llvm-commits
mailing list