Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h ------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. /// \file
  9. /// Interface for Targets to specify which operations they can successfully
  10. /// select and how the others should be expanded most efficiently.
  11. /// This implementation has been deprecated for a long time but it still in use
  12. /// in a few places.
  13. //===----------------------------------------------------------------------===//
  14.  
  15. #ifndef LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H
  16. #define LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H
  17.  
  18. #include "llvm/ADT/DenseMap.h"
  19. #include "llvm/CodeGen/TargetOpcodes.h"
  20. #include "llvm/Support/LowLevelTypeImpl.h"
  21. #include <unordered_map>
  22.  
  23. namespace llvm {
  24. struct LegalityQuery;
  25.  
  26. namespace LegacyLegalizeActions {
  27. enum LegacyLegalizeAction : std::uint8_t {
  28.   /// The operation is expected to be selectable directly by the target, and
  29.   /// no transformation is necessary.
  30.   Legal,
  31.  
  32.   /// The operation should be synthesized from multiple instructions acting on
  33.   /// a narrower scalar base-type. For example a 64-bit add might be
  34.   /// implemented in terms of 32-bit add-with-carry.
  35.   NarrowScalar,
  36.  
  37.   /// The operation should be implemented in terms of a wider scalar
  38.   /// base-type. For example a <2 x s8> add could be implemented as a <2
  39.   /// x s32> add (ignoring the high bits).
  40.   WidenScalar,
  41.  
  42.   /// The (vector) operation should be implemented by splitting it into
  43.   /// sub-vectors where the operation is legal. For example a <8 x s64> add
  44.   /// might be implemented as 4 separate <2 x s64> adds.
  45.   FewerElements,
  46.  
  47.   /// The (vector) operation should be implemented by widening the input
  48.   /// vector and ignoring the lanes added by doing so. For example <2 x i8> is
  49.   /// rarely legal, but you might perform an <8 x i8> and then only look at
  50.   /// the first two results.
  51.   MoreElements,
  52.  
  53.   /// Perform the operation on a different, but equivalently sized type.
  54.   Bitcast,
  55.  
  56.   /// The operation itself must be expressed in terms of simpler actions on
  57.   /// this target. E.g. a SREM replaced by an SDIV and subtraction.
  58.   Lower,
  59.  
  60.   /// The operation should be implemented as a call to some kind of runtime
  61.   /// support library. For example this usually happens on machines that don't
  62.   /// support floating-point operations natively.
  63.   Libcall,
  64.  
  65.   /// The target wants to do something special with this combination of
  66.   /// operand and type. A callback will be issued when it is needed.
  67.   Custom,
  68.  
  69.   /// This operation is completely unsupported on the target. A programming
  70.   /// error has occurred.
  71.   Unsupported,
  72.  
  73.   /// Sentinel value for when no action was found in the specified table.
  74.   NotFound,
  75. };
  76. } // end namespace LegacyLegalizeActions
  77. raw_ostream &operator<<(raw_ostream &OS,
  78.                         LegacyLegalizeActions::LegacyLegalizeAction Action);
  79.  
  80. /// Legalization is decided based on an instruction's opcode, which type slot
  81. /// we're considering, and what the existing type is. These aspects are gathered
  82. /// together for convenience in the InstrAspect class.
  83. struct InstrAspect {
  84.   unsigned Opcode;
  85.   unsigned Idx = 0;
  86.   LLT Type;
  87.  
  88.   InstrAspect(unsigned Opcode, LLT Type) : Opcode(Opcode), Type(Type) {}
  89.   InstrAspect(unsigned Opcode, unsigned Idx, LLT Type)
  90.       : Opcode(Opcode), Idx(Idx), Type(Type) {}
  91.  
  92.   bool operator==(const InstrAspect &RHS) const {
  93.     return Opcode == RHS.Opcode && Idx == RHS.Idx && Type == RHS.Type;
  94.   }
  95. };
  96.  
  97. /// The result of a query. It either indicates a final answer of Legal or
  98. /// Unsupported or describes an action that must be taken to make an operation
  99. /// more legal.
  100. struct LegacyLegalizeActionStep {
  101.   /// The action to take or the final answer.
  102.   LegacyLegalizeActions::LegacyLegalizeAction Action;
  103.   /// If describing an action, the type index to change. Otherwise zero.
  104.   unsigned TypeIdx;
  105.   /// If describing an action, the new type for TypeIdx. Otherwise LLT{}.
  106.   LLT NewType;
  107.  
  108.   LegacyLegalizeActionStep(LegacyLegalizeActions::LegacyLegalizeAction Action,
  109.                            unsigned TypeIdx, const LLT NewType)
  110.       : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {}
  111.  
  112.   bool operator==(const LegacyLegalizeActionStep &RHS) const {
  113.     return std::tie(Action, TypeIdx, NewType) ==
  114.         std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType);
  115.   }
  116. };
  117.  
  118.  
  119. class LegacyLegalizerInfo {
  120. public:
  121.   using SizeAndAction =
  122.       std::pair<uint16_t, LegacyLegalizeActions::LegacyLegalizeAction>;
  123.   using SizeAndActionsVec = std::vector<SizeAndAction>;
  124.   using SizeChangeStrategy =
  125.       std::function<SizeAndActionsVec(const SizeAndActionsVec &v)>;
  126.  
  127.   LegacyLegalizerInfo();
  128.  
  129.   static bool needsLegalizingToDifferentSize(
  130.       const LegacyLegalizeActions::LegacyLegalizeAction Action) {
  131.     using namespace LegacyLegalizeActions;
  132.     switch (Action) {
  133.     case NarrowScalar:
  134.     case WidenScalar:
  135.     case FewerElements:
  136.     case MoreElements:
  137.     case Unsupported:
  138.       return true;
  139.     default:
  140.       return false;
  141.     }
  142.   }
  143.  
  144.   /// Compute any ancillary tables needed to quickly decide how an operation
  145.   /// should be handled. This must be called after all "set*Action"methods but
  146.   /// before any query is made or incorrect results may be returned.
  147.   void computeTables();
  148.  
  149.   /// More friendly way to set an action for common types that have an LLT
  150.   /// representation.
  151.   /// The LegacyLegalizeAction must be one for which
  152.   /// NeedsLegalizingToDifferentSize returns false.
  153.   void setAction(const InstrAspect &Aspect,
  154.                  LegacyLegalizeActions::LegacyLegalizeAction Action) {
  155.     assert(!needsLegalizingToDifferentSize(Action));
  156.     TablesInitialized = false;
  157.     const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;
  158.     if (SpecifiedActions[OpcodeIdx].size() <= Aspect.Idx)
  159.       SpecifiedActions[OpcodeIdx].resize(Aspect.Idx + 1);
  160.     SpecifiedActions[OpcodeIdx][Aspect.Idx][Aspect.Type] = Action;
  161.   }
  162.  
  163.   /// The setAction calls record the non-size-changing legalization actions
  164.   /// to take on specificly-sized types. The SizeChangeStrategy defines what
  165.   /// to do when the size of the type needs to be changed to reach a legally
  166.   /// sized type (i.e., one that was defined through a setAction call).
  167.   /// e.g.
  168.   /// setAction ({G_ADD, 0, LLT::scalar(32)}, Legal);
  169.   /// setLegalizeScalarToDifferentSizeStrategy(
  170.   ///   G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
  171.   /// will end up defining getAction({G_ADD, 0, T}) to return the following
  172.   /// actions for different scalar types T:
  173.   ///  LLT::scalar(1)..LLT::scalar(31): {WidenScalar, 0, LLT::scalar(32)}
  174.   ///  LLT::scalar(32):                 {Legal, 0, LLT::scalar(32)}
  175.   ///  LLT::scalar(33)..:               {NarrowScalar, 0, LLT::scalar(32)}
  176.   ///
  177.   /// If no SizeChangeAction gets defined, through this function,
  178.   /// the default is unsupportedForDifferentSizes.
  179.   void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode,
  180.                                                 const unsigned TypeIdx,
  181.                                                 SizeChangeStrategy S) {
  182.     const unsigned OpcodeIdx = Opcode - FirstOp;
  183.     if (ScalarSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
  184.       ScalarSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
  185.     ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
  186.   }
  187.  
  188.   /// See also setLegalizeScalarToDifferentSizeStrategy.
  189.   /// This function allows to set the SizeChangeStrategy for vector elements.
  190.   void setLegalizeVectorElementToDifferentSizeStrategy(const unsigned Opcode,
  191.                                                        const unsigned TypeIdx,
  192.                                                        SizeChangeStrategy S) {
  193.     const unsigned OpcodeIdx = Opcode - FirstOp;
  194.     if (VectorElementSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
  195.       VectorElementSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
  196.     VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
  197.   }
  198.  
  199.   /// A SizeChangeStrategy for the common case where legalization for a
  200.   /// particular operation consists of only supporting a specific set of type
  201.   /// sizes. E.g.
  202.   ///   setAction ({G_DIV, 0, LLT::scalar(32)}, Legal);
  203.   ///   setAction ({G_DIV, 0, LLT::scalar(64)}, Legal);
  204.   ///   setLegalizeScalarToDifferentSizeStrategy(
  205.   ///     G_DIV, 0, unsupportedForDifferentSizes);
  206.   /// will result in getAction({G_DIV, 0, T}) to return Legal for s32 and s64,
  207.   /// and Unsupported for all other scalar types T.
  208.   static SizeAndActionsVec
  209.   unsupportedForDifferentSizes(const SizeAndActionsVec &v) {
  210.     using namespace LegacyLegalizeActions;
  211.     return increaseToLargerTypesAndDecreaseToLargest(v, Unsupported,
  212.                                                      Unsupported);
  213.   }
  214.  
  215.   /// A SizeChangeStrategy for the common case where legalization for a
  216.   /// particular operation consists of widening the type to a large legal type,
  217.   /// unless there is no such type and then instead it should be narrowed to the
  218.   /// largest legal type.
  219.   static SizeAndActionsVec
  220.   widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v) {
  221.     using namespace LegacyLegalizeActions;
  222.     assert(v.size() > 0 &&
  223.            "At least one size that can be legalized towards is needed"
  224.            " for this SizeChangeStrategy");
  225.     return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
  226.                                                      NarrowScalar);
  227.   }
  228.  
  229.   static SizeAndActionsVec
  230.   widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v) {
  231.     using namespace LegacyLegalizeActions;
  232.     return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
  233.                                                      Unsupported);
  234.   }
  235.  
  236.   static SizeAndActionsVec
  237.   narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v) {
  238.     using namespace LegacyLegalizeActions;
  239.     return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
  240.                                                        Unsupported);
  241.   }
  242.  
  243.   static SizeAndActionsVec
  244.   narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec &v) {
  245.     using namespace LegacyLegalizeActions;
  246.     assert(v.size() > 0 &&
  247.            "At least one size that can be legalized towards is needed"
  248.            " for this SizeChangeStrategy");
  249.     return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
  250.                                                        WidenScalar);
  251.   }
  252.  
  253.   /// A SizeChangeStrategy for the common case where legalization for a
  254.   /// particular vector operation consists of having more elements in the
  255.   /// vector, to a type that is legal. Unless there is no such type and then
  256.   /// instead it should be legalized towards the widest vector that's still
  257.   /// legal. E.g.
  258.   ///   setAction({G_ADD, LLT::vector(8, 8)}, Legal);
  259.   ///   setAction({G_ADD, LLT::vector(16, 8)}, Legal);
  260.   ///   setAction({G_ADD, LLT::vector(2, 32)}, Legal);
  261.   ///   setAction({G_ADD, LLT::vector(4, 32)}, Legal);
  262.   ///   setLegalizeVectorElementToDifferentSizeStrategy(
  263.   ///     G_ADD, 0, moreToWiderTypesAndLessToWidest);
  264.   /// will result in the following getAction results:
  265.   ///   * getAction({G_ADD, LLT::vector(8,8)}) returns
  266.   ///       (Legal, vector(8,8)).
  267.   ///   * getAction({G_ADD, LLT::vector(9,8)}) returns
  268.   ///       (MoreElements, vector(16,8)).
  269.   ///   * getAction({G_ADD, LLT::vector(8,32)}) returns
  270.   ///       (FewerElements, vector(4,32)).
  271.   static SizeAndActionsVec
  272.   moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v) {
  273.     using namespace LegacyLegalizeActions;
  274.     return increaseToLargerTypesAndDecreaseToLargest(v, MoreElements,
  275.                                                      FewerElements);
  276.   }
  277.  
  278.   /// Helper function to implement many typical SizeChangeStrategy functions.
  279.   static SizeAndActionsVec increaseToLargerTypesAndDecreaseToLargest(
  280.       const SizeAndActionsVec &v,
  281.       LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction,
  282.       LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction);
  283.   /// Helper function to implement many typical SizeChangeStrategy functions.
  284.   static SizeAndActionsVec decreaseToSmallerTypesAndIncreaseToSmallest(
  285.       const SizeAndActionsVec &v,
  286.       LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction,
  287.       LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction);
  288.  
  289.   LegacyLegalizeActionStep getAction(const LegalityQuery &Query) const;
  290.  
  291.   unsigned getOpcodeIdxForOpcode(unsigned Opcode) const;
  292.  
  293. private:
  294.   /// Determine what action should be taken to legalize the given generic
  295.   /// instruction opcode, type-index and type. Requires computeTables to have
  296.   /// been called.
  297.   ///
  298.   /// \returns a pair consisting of the kind of legalization that should be
  299.   /// performed and the destination type.
  300.   std::pair<LegacyLegalizeActions::LegacyLegalizeAction, LLT>
  301.   getAspectAction(const InstrAspect &Aspect) const;
  302.  
  303.   /// The SizeAndActionsVec is a representation mapping between all natural
  304.   /// numbers and an Action. The natural number represents the bit size of
  305.   /// the InstrAspect. For example, for a target with native support for 32-bit
  306.   /// and 64-bit additions, you'd express that as:
  307.   /// setScalarAction(G_ADD, 0,
  308.   ///           {{1, WidenScalar},  // bit sizes [ 1, 31[
  309.   ///            {32, Legal},       // bit sizes [32, 33[
  310.   ///            {33, WidenScalar}, // bit sizes [33, 64[
  311.   ///            {64, Legal},       // bit sizes [64, 65[
  312.   ///            {65, NarrowScalar} // bit sizes [65, +inf[
  313.   ///           });
  314.   /// It may be that only 64-bit pointers are supported on your target:
  315.   /// setPointerAction(G_PTR_ADD, 0, LLT:pointer(1),
  316.   ///           {{1, Unsupported},  // bit sizes [ 1, 63[
  317.   ///            {64, Legal},       // bit sizes [64, 65[
  318.   ///            {65, Unsupported}, // bit sizes [65, +inf[
  319.   ///           });
  320.   void setScalarAction(const unsigned Opcode, const unsigned TypeIndex,
  321.                        const SizeAndActionsVec &SizeAndActions) {
  322.     const unsigned OpcodeIdx = Opcode - FirstOp;
  323.     SmallVector<SizeAndActionsVec, 1> &Actions = ScalarActions[OpcodeIdx];
  324.     setActions(TypeIndex, Actions, SizeAndActions);
  325.   }
  326.   void setPointerAction(const unsigned Opcode, const unsigned TypeIndex,
  327.                         const unsigned AddressSpace,
  328.                         const SizeAndActionsVec &SizeAndActions) {
  329.     const unsigned OpcodeIdx = Opcode - FirstOp;
  330.     if (AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace) ==
  331.         AddrSpace2PointerActions[OpcodeIdx].end())
  332.       AddrSpace2PointerActions[OpcodeIdx][AddressSpace] = {{}};
  333.     SmallVector<SizeAndActionsVec, 1> &Actions =
  334.         AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace)->second;
  335.     setActions(TypeIndex, Actions, SizeAndActions);
  336.   }
  337.  
  338.   /// If an operation on a given vector type (say <M x iN>) isn't explicitly
  339.   /// specified, we proceed in 2 stages. First we legalize the underlying scalar
  340.   /// (so that there's at least one legal vector with that scalar), then we
  341.   /// adjust the number of elements in the vector so that it is legal. The
  342.   /// desired action in the first step is controlled by this function.
  343.   void setScalarInVectorAction(const unsigned Opcode, const unsigned TypeIndex,
  344.                                const SizeAndActionsVec &SizeAndActions) {
  345.     unsigned OpcodeIdx = Opcode - FirstOp;
  346.     SmallVector<SizeAndActionsVec, 1> &Actions =
  347.         ScalarInVectorActions[OpcodeIdx];
  348.     setActions(TypeIndex, Actions, SizeAndActions);
  349.   }
  350.  
  351.   /// See also setScalarInVectorAction.
  352.   /// This function let's you specify the number of elements in a vector that
  353.   /// are legal for a legal element size.
  354.   void setVectorNumElementAction(const unsigned Opcode,
  355.                                  const unsigned TypeIndex,
  356.                                  const unsigned ElementSize,
  357.                                  const SizeAndActionsVec &SizeAndActions) {
  358.     const unsigned OpcodeIdx = Opcode - FirstOp;
  359.     if (NumElements2Actions[OpcodeIdx].find(ElementSize) ==
  360.         NumElements2Actions[OpcodeIdx].end())
  361.       NumElements2Actions[OpcodeIdx][ElementSize] = {{}};
  362.     SmallVector<SizeAndActionsVec, 1> &Actions =
  363.         NumElements2Actions[OpcodeIdx].find(ElementSize)->second;
  364.     setActions(TypeIndex, Actions, SizeAndActions);
  365.   }
  366.  
  367.   /// A partial SizeAndActionsVec potentially doesn't cover all bit sizes,
  368.   /// i.e. it's OK if it doesn't start from size 1.
  369.   static void checkPartialSizeAndActionsVector(const SizeAndActionsVec& v) {
  370.     using namespace LegacyLegalizeActions;
  371. #ifndef NDEBUG
  372.     // The sizes should be in increasing order
  373.     int prev_size = -1;
  374.     for(auto SizeAndAction: v) {
  375.       assert(SizeAndAction.first > prev_size);
  376.       prev_size = SizeAndAction.first;
  377.     }
  378.     // - for every Widen action, there should be a larger bitsize that
  379.     //   can be legalized towards (e.g. Legal, Lower, Libcall or Custom
  380.     //   action).
  381.     // - for every Narrow action, there should be a smaller bitsize that
  382.     //   can be legalized towards.
  383.     int SmallestNarrowIdx = -1;
  384.     int LargestWidenIdx = -1;
  385.     int SmallestLegalizableToSameSizeIdx = -1;
  386.     int LargestLegalizableToSameSizeIdx = -1;
  387.     for(size_t i=0; i<v.size(); ++i) {
  388.       switch (v[i].second) {
  389.         case FewerElements:
  390.         case NarrowScalar:
  391.           if (SmallestNarrowIdx == -1)
  392.             SmallestNarrowIdx = i;
  393.           break;
  394.         case WidenScalar:
  395.         case MoreElements:
  396.           LargestWidenIdx = i;
  397.           break;
  398.         case Unsupported:
  399.           break;
  400.         default:
  401.           if (SmallestLegalizableToSameSizeIdx == -1)
  402.             SmallestLegalizableToSameSizeIdx = i;
  403.           LargestLegalizableToSameSizeIdx = i;
  404.       }
  405.     }
  406.     if (SmallestNarrowIdx != -1) {
  407.       assert(SmallestLegalizableToSameSizeIdx != -1);
  408.       assert(SmallestNarrowIdx > SmallestLegalizableToSameSizeIdx);
  409.     }
  410.     if (LargestWidenIdx != -1)
  411.       assert(LargestWidenIdx < LargestLegalizableToSameSizeIdx);
  412. #endif
  413.   }
  414.  
  415.   /// A full SizeAndActionsVec must cover all bit sizes, i.e. must start with
  416.   /// from size 1.
  417.   static void checkFullSizeAndActionsVector(const SizeAndActionsVec& v) {
  418. #ifndef NDEBUG
  419.     // Data structure invariant: The first bit size must be size 1.
  420.     assert(v.size() >= 1);
  421.     assert(v[0].first == 1);
  422.     checkPartialSizeAndActionsVector(v);
  423. #endif
  424.   }
  425.  
  426.   /// Sets actions for all bit sizes on a particular generic opcode, type
  427.   /// index and scalar or pointer type.
  428.   void setActions(unsigned TypeIndex,
  429.                   SmallVector<SizeAndActionsVec, 1> &Actions,
  430.                   const SizeAndActionsVec &SizeAndActions) {
  431.     checkFullSizeAndActionsVector(SizeAndActions);
  432.     if (Actions.size() <= TypeIndex)
  433.       Actions.resize(TypeIndex + 1);
  434.     Actions[TypeIndex] = SizeAndActions;
  435.   }
  436.  
  437.   static SizeAndAction findAction(const SizeAndActionsVec &Vec,
  438.                                   const uint32_t Size);
  439.  
  440.   /// Returns the next action needed to get the scalar or pointer type closer
  441.   /// to being legal
  442.   /// E.g. findLegalAction({G_REM, 13}) should return
  443.   /// (WidenScalar, 32). After that, findLegalAction({G_REM, 32}) will
  444.   /// probably be called, which should return (Lower, 32).
  445.   /// This is assuming the setScalarAction on G_REM was something like:
  446.   /// setScalarAction(G_REM, 0,
  447.   ///           {{1, WidenScalar},  // bit sizes [ 1, 31[
  448.   ///            {32, Lower},       // bit sizes [32, 33[
  449.   ///            {33, NarrowScalar} // bit sizes [65, +inf[
  450.   ///           });
  451.   std::pair<LegacyLegalizeActions::LegacyLegalizeAction, LLT>
  452.   findScalarLegalAction(const InstrAspect &Aspect) const;
  453.  
  454.   /// Returns the next action needed towards legalizing the vector type.
  455.   std::pair<LegacyLegalizeActions::LegacyLegalizeAction, LLT>
  456.   findVectorLegalAction(const InstrAspect &Aspect) const;
  457.  
  458.   static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
  459.   static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
  460.  
  461.   // Data structures used temporarily during construction of legality data:
  462.   using TypeMap = DenseMap<LLT, LegacyLegalizeActions::LegacyLegalizeAction>;
  463.   SmallVector<TypeMap, 1> SpecifiedActions[LastOp - FirstOp + 1];
  464.   SmallVector<SizeChangeStrategy, 1>
  465.       ScalarSizeChangeStrategies[LastOp - FirstOp + 1];
  466.   SmallVector<SizeChangeStrategy, 1>
  467.       VectorElementSizeChangeStrategies[LastOp - FirstOp + 1];
  468.   bool TablesInitialized = false;
  469.  
  470.   // Data structures used by getAction:
  471.   SmallVector<SizeAndActionsVec, 1> ScalarActions[LastOp - FirstOp + 1];
  472.   SmallVector<SizeAndActionsVec, 1> ScalarInVectorActions[LastOp - FirstOp + 1];
  473.   std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
  474.       AddrSpace2PointerActions[LastOp - FirstOp + 1];
  475.   std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
  476.       NumElements2Actions[LastOp - FirstOp + 1];
  477. };
  478.  
  479. } // end namespace llvm
  480.  
  481. #endif // LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H
  482.