[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:49:30 PST 2017


We've done our porting, so everything is ok now. You're right it wasn't
that difficult.
I was just curious if there could be a way to make legalization like this
optional in the future, but I understand if its too core a part of GISel to
opt out of.

PL

On Wed, Nov 8, 2017 at 10:33 AM, Kristof Beyls <Kristof.Beyls at arm.com>
wrote:

> Hi Puyan,
>
> Given this changes the core of GlobalISel legalization, I don’t think
> there is a straightforward way to support both the old API and the new API.
> FWIW, the target-specific diff in the open source backends isn’t that big,
> and I didn’t find it too hard to move over the open source backends.
> So I’d expect that it shouldn’t be too hard to port your out-of-tree
> backend to this new API too. I hope that the diffs for the 4 existing open
> source backends should give you enough examples of how your backend could
> be ported over?
>
> Thanks,
>
> Kristof
>
>
> On 8 Nov 2017, at 19:16, Puyan Lotfi <puyan.lotfi.llvm at gmail.com> wrote:
>
> 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/GlobalI
>> Sel.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).g
>> etReg()).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).g
>> etReg()).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.sec
>> ond);
>> >> +        // 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(P
>> ointerSpecifiedActions.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.seco
>> nd);
>> >> +        // 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.getAd
>> dressSpace(),
>> >> +                                                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/AA
>> rch64/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/AR
>> M/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/X8
>> 6/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_fewerelemen
>> ts
>> >> +; 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-selec
>> t.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.cp
>> p
>> >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Cod
>> eGen/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::widenToLargerTy
>> pesUnsupportedOtherwise);
>> >> +
>> >> +  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::widenToLargerTy
>> pesAndNarrowToLargest);
>> >> +
>> >>  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::widenToLargerTy
>> pesUnsupportedOtherwise);
>> >>  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::widenToLargerTy
>> pesUnsupportedOtherwise);
>> >> +  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/Cod
>> eGen/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/75e8959b/attachment-0001.html>


More information about the llvm-commits mailing list