LCOV - code coverage report
Current view: top level - lib/CodeGen/GlobalISel - LegalizerInfo.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 173 193 89.6 %
Date: 2018-02-19 03:08:00 Functions: 18 21 85.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- lib/CodeGen/GlobalISel/LegalizerInfo.cpp - Legalizer ---------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // Implement an interface to specify and query how an illegal operation on a
      11             : // given type should be expanded.
      12             : //
      13             : // Issues to be resolved:
      14             : //   + Make it fast.
      15             : //   + Support weird types like i3, <7 x i3>, ...
      16             : //   + Operations with more than one type (ICMP, CMPXCHG, intrinsics, ...)
      17             : //
      18             : //===----------------------------------------------------------------------===//
      19             : 
      20             : #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
      21             : #include "llvm/ADT/SmallBitVector.h"
      22             : #include "llvm/CodeGen/MachineInstr.h"
      23             : #include "llvm/CodeGen/MachineOperand.h"
      24             : #include "llvm/CodeGen/MachineRegisterInfo.h"
      25             : #include "llvm/CodeGen/TargetOpcodes.h"
      26             : #include "llvm/MC/MCInstrDesc.h"
      27             : #include "llvm/Support/Debug.h"
      28             : #include "llvm/Support/ErrorHandling.h"
      29             : #include "llvm/Support/LowLevelTypeImpl.h"
      30             : #include "llvm/Support/MathExtras.h"
      31             : #include <algorithm>
      32             : #include <map>
      33             : 
      34             : using namespace llvm;
      35             : using namespace LegalizeActions;
      36             : 
      37             : #define DEBUG_TYPE "legalizer-info"
      38             : 
      39           0 : raw_ostream &LegalityQuery::print(raw_ostream &OS) const {
      40           0 :   OS << Opcode << ", {";
      41           0 :   for (const auto &Type : Types) {
      42           0 :     OS << Type << ", ";
      43             :   }
      44           0 :   OS << "}";
      45           0 :   return OS;
      46             : }
      47             : 
      48        5051 : LegalizeActionStep LegalizeRuleSet::apply(const LegalityQuery &Query) const {
      49             :   DEBUG(dbgs() << "Applying legalizer ruleset to: "; Query.print(dbgs());
      50             :         dbgs() << "\n");
      51        5051 :   if (Rules.empty()) {
      52             :     DEBUG(dbgs() << ".. fallback to legacy rules (no rules defined)\n");
      53        2024 :     return {LegalizeAction::UseLegacyRules, 0, LLT{}};
      54             :   }
      55        3925 :   for (const auto &Rule : Rules) {
      56        3473 :     if (Rule.match(Query)) {
      57             :       DEBUG(dbgs() << ".. match\n");
      58        3024 :       std::pair<unsigned, LLT> Mutation = Rule.determineMutation(Query);
      59             :       DEBUG(dbgs() << ".. .. " << (unsigned)Rule.getAction() << ", "
      60             :                    << Mutation.first << ", " << Mutation.second << "\n");
      61             :       assert((Query.Types[Mutation.first] != Mutation.second ||
      62             :               Rule.getAction() == MoreElements ||
      63             :               Rule.getAction() == FewerElements) &&
      64             :              "Simple loop detected");
      65        6048 :       return {Rule.getAction(), Mutation.first, Mutation.second};
      66             :     } else
      67             :       DEBUG(dbgs() << ".. no match\n");
      68             :   }
      69             :   DEBUG(dbgs() << ".. unsupported\n");
      70           3 :   return {LegalizeAction::Unsupported, 0, LLT{}};
      71             : }
      72             : 
      73    13543233 : LegalizerInfo::LegalizerInfo() : TablesInitialized(false) {
      74             :   // Set defaults.
      75             :   // FIXME: these two (G_ANYEXT and G_TRUNC?) can be legalized to the
      76             :   // fundamental load/store Jakob proposed. Once loads & stores are supported.
      77       19431 :   setScalarAction(TargetOpcode::G_ANYEXT, 1, {{1, Legal}});
      78       19431 :   setScalarAction(TargetOpcode::G_ZEXT, 1, {{1, Legal}});
      79       19431 :   setScalarAction(TargetOpcode::G_SEXT, 1, {{1, Legal}});
      80       19431 :   setScalarAction(TargetOpcode::G_TRUNC, 0, {{1, Legal}});
      81       19431 :   setScalarAction(TargetOpcode::G_TRUNC, 1, {{1, Legal}});
      82             : 
      83       19431 :   setScalarAction(TargetOpcode::G_INTRINSIC, 0, {{1, Legal}});
      84       19431 :   setScalarAction(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS, 0, {{1, Legal}});
      85             : 
      86       38862 :   setLegalizeScalarToDifferentSizeStrategy(
      87             :       TargetOpcode::G_IMPLICIT_DEF, 0, narrowToSmallerAndUnsupportedIfTooSmall);
      88       38862 :   setLegalizeScalarToDifferentSizeStrategy(
      89             :       TargetOpcode::G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
      90       38862 :   setLegalizeScalarToDifferentSizeStrategy(
      91             :       TargetOpcode::G_OR, 0, widenToLargerTypesAndNarrowToLargest);
      92       38862 :   setLegalizeScalarToDifferentSizeStrategy(
      93             :       TargetOpcode::G_LOAD, 0, narrowToSmallerAndUnsupportedIfTooSmall);
      94       38862 :   setLegalizeScalarToDifferentSizeStrategy(
      95             :       TargetOpcode::G_STORE, 0, narrowToSmallerAndUnsupportedIfTooSmall);
      96             : 
      97       38862 :   setLegalizeScalarToDifferentSizeStrategy(
      98             :       TargetOpcode::G_BRCOND, 0, widenToLargerTypesUnsupportedOtherwise);
      99       38862 :   setLegalizeScalarToDifferentSizeStrategy(
     100             :       TargetOpcode::G_INSERT, 0, narrowToSmallerAndUnsupportedIfTooSmall);
     101       38862 :   setLegalizeScalarToDifferentSizeStrategy(
     102             :       TargetOpcode::G_EXTRACT, 0, narrowToSmallerAndUnsupportedIfTooSmall);
     103       38862 :   setLegalizeScalarToDifferentSizeStrategy(
     104             :       TargetOpcode::G_EXTRACT, 1, narrowToSmallerAndUnsupportedIfTooSmall);
     105       19431 :   setScalarAction(TargetOpcode::G_FNEG, 0, {{1, Lower}});
     106       19431 : }
     107             : 
     108       19431 : void LegalizerInfo::computeTables() {
     109             :   assert(TablesInitialized == false);
     110             : 
     111     3400425 :   for (unsigned OpcodeIdx = 0; OpcodeIdx <= LastOp - FirstOp; ++OpcodeIdx) {
     112     1690497 :     const unsigned Opcode = FirstOp + OpcodeIdx;
     113     4802475 :     for (unsigned TypeIdx = 0; TypeIdx != SpecifiedActions[OpcodeIdx].size();
     114             :          ++TypeIdx) {
     115             :       // 0. Collect information specified through the setAction API, i.e.
     116             :       // for specific bit sizes.
     117             :       // For scalar types:
     118             :       SizeAndActionsVec ScalarSpecifiedActions;
     119             :       // For pointer types:
     120             :       std::map<uint16_t, SizeAndActionsVec> AddressSpace2SpecifiedActions;
     121             :       // For vector types:
     122             :       std::map<uint16_t, SizeAndActionsVec> ElemSize2SpecifiedActions;
     123     2817871 :       for (auto LLT2Action : SpecifiedActions[OpcodeIdx][TypeIdx]) {
     124     1870217 :         const LLT Type = LLT2Action.first;
     125             :         const LegalizeAction Action = LLT2Action.second;
     126             : 
     127     1870217 :         auto SizeAction = std::make_pair(Type.getSizeInBits(), Action);
     128             :         if (Type.isPointer())
     129      278522 :           AddressSpace2SpecifiedActions[Type.getAddressSpace()].push_back(
     130             :               SizeAction);
     131             :         else if (Type.isVector())
     132     1179482 :           ElemSize2SpecifiedActions[Type.getElementType().getSizeInBits()]
     133      589741 :               .push_back(SizeAction);
     134             :         else
     135     1141215 :           ScalarSpecifiedActions.push_back(SizeAction);
     136             :       }
     137             : 
     138             :       // 1. Handle scalar types
     139             :       {
     140             :         // Decide how to handle bit sizes for which no explicit specification
     141             :         // was given.
     142             :         SizeChangeStrategy S = &unsupportedForDifferentSizes;
     143      657656 :         if (TypeIdx < ScalarSizeChangeStrategies[OpcodeIdx].size() &&
     144             :             ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)
     145      172471 :           S = ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx];
     146             :         std::sort(ScalarSpecifiedActions.begin(), ScalarSpecifiedActions.end());
     147             :         checkPartialSizeAndActionsVector(ScalarSpecifiedActions);
     148      473827 :         setScalarAction(Opcode, TypeIdx, S(ScalarSpecifiedActions));
     149             :       }
     150             : 
     151             :       // 2. Handle pointer types
     152      613088 :       for (auto PointerSpecifiedActions : AddressSpace2SpecifiedActions) {
     153             :         std::sort(PointerSpecifiedActions.second.begin(),
     154             :                   PointerSpecifiedActions.second.end());
     155             :         checkPartialSizeAndActionsVector(PointerSpecifiedActions.second);
     156             :         // For pointer types, we assume that there isn't a meaningfull way
     157             :         // to change the number of bits used in the pointer.
     158      139261 :         setPointerAction(
     159      139261 :             Opcode, TypeIdx, PointerSpecifiedActions.first,
     160      139261 :             unsupportedForDifferentSizes(PointerSpecifiedActions.second));
     161             :       }
     162             : 
     163             :       // 3. Handle vector types
     164             :       SizeAndActionsVec ElementSizesSeen;
     165      891947 :       for (auto VectorSpecifiedActions : ElemSize2SpecifiedActions) {
     166             :         std::sort(VectorSpecifiedActions.second.begin(),
     167             :                   VectorSpecifiedActions.second.end());
     168      418120 :         const uint16_t ElementSize = VectorSpecifiedActions.first;
     169      418120 :         ElementSizesSeen.push_back({ElementSize, Legal});
     170             :         checkPartialSizeAndActionsVector(VectorSpecifiedActions.second);
     171             :         // For vector types, we assume that the best way to adapt the number
     172             :         // of elements is to the next larger number of elements type for which
     173             :         // the vector type is legal, unless there is no such type. In that case,
     174             :         // legalize towards a vector type with a smaller number of elements.
     175             :         SizeAndActionsVec NumElementsActions;
     176     1007861 :         for (SizeAndAction BitsizeAndAction : VectorSpecifiedActions.second) {
     177             :           assert(BitsizeAndAction.first % ElementSize == 0);
     178      589741 :           const uint16_t NumElements = BitsizeAndAction.first / ElementSize;
     179      589741 :           NumElementsActions.push_back({NumElements, BitsizeAndAction.second});
     180             :         }
     181      418120 :         setVectorNumElementAction(
     182             :             Opcode, TypeIdx, ElementSize,
     183      418120 :             moreToWiderTypesAndLessToWidest(NumElementsActions));
     184             :       }
     185             :       std::sort(ElementSizesSeen.begin(), ElementSizesSeen.end());
     186             :       SizeChangeStrategy VectorElementSizeChangeStrategy =
     187             :           &unsupportedForDifferentSizes;
     188      473828 :       if (TypeIdx < VectorElementSizeChangeStrategies[OpcodeIdx].size() &&
     189             :           VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)
     190           1 :         VectorElementSizeChangeStrategy =
     191             :             VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx];
     192             :       setScalarInVectorAction(
     193      473827 :           Opcode, TypeIdx, VectorElementSizeChangeStrategy(ElementSizesSeen));
     194             :     }
     195             :   }
     196             : 
     197       19431 :   TablesInitialized = true;
     198       19431 : }
     199             : 
     200             : // FIXME: inefficient implementation for now. Without ComputeValueVTs we're
     201             : // probably going to need specialized lookup structures for various types before
     202             : // we have any hope of doing well with something like <13 x i3>. Even the common
     203             : // cases should do better than what we have now.
     204             : std::pair<LegalizeAction, LLT>
     205        2953 : LegalizerInfo::getAspectAction(const InstrAspect &Aspect) const {
     206             :   assert(TablesInitialized && "backend forgot to call computeTables");
     207             :   // These *have* to be implemented for now, they're the fundamental basis of
     208             :   // how everything else is transformed.
     209             :   if (Aspect.Type.isScalar() || Aspect.Type.isPointer())
     210        2532 :     return findScalarLegalAction(Aspect);
     211             :   assert(Aspect.Type.isVector());
     212         421 :   return findVectorLegalAction(Aspect);
     213             : }
     214             : 
     215             : /// Helper function to get LLT for the given type index.
     216        6228 : static LLT getTypeFromTypeIdx(const MachineInstr &MI,
     217             :                               const MachineRegisterInfo &MRI, unsigned OpIdx,
     218             :                               unsigned TypeIdx) {
     219             :   assert(TypeIdx < MI.getNumOperands() && "Unexpected TypeIdx");
     220             :   // G_UNMERGE_VALUES has variable number of operands, but there is only
     221             :   // one source type and one destination type as all destinations must be the
     222             :   // same type. So, get the last operand if TypeIdx == 1.
     223       12456 :   if (MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES && TypeIdx == 1)
     224         158 :     return MRI.getType(MI.getOperand(MI.getNumOperands() - 1).getReg());
     225       12298 :   return MRI.getType(MI.getOperand(OpIdx).getReg());
     226             : }
     227             : 
     228      287251 : unsigned LegalizerInfo::getOpcodeIdxForOpcode(unsigned Opcode) const {
     229             :   assert(Opcode >= FirstOp && Opcode <= LastOp && "Unsupported opcode");
     230      287251 :   return Opcode - FirstOp;
     231             : }
     232             : 
     233      166986 : unsigned LegalizerInfo::getActionDefinitionsIdx(unsigned Opcode) const {
     234      166986 :   unsigned OpcodeIdx = getOpcodeIdxForOpcode(Opcode);
     235      166986 :   if (unsigned Alias = RulesForOpcode[OpcodeIdx].getAlias()) {
     236             :     DEBUG(dbgs() << ".. opcode " << Opcode << " is aliased to " << Alias
     237             :                  << "\n");
     238        1156 :     OpcodeIdx = getOpcodeIdxForOpcode(Alias);
     239             :     DEBUG(dbgs() << ".. opcode " << Alias << " is aliased to "
     240             :                  << RulesForOpcode[OpcodeIdx].getAlias() << "\n");
     241             :     assert(RulesForOpcode[OpcodeIdx].getAlias() == 0 && "Cannot chain aliases");
     242             :   }
     243             : 
     244      166986 :   return OpcodeIdx;
     245             : }
     246             : 
     247             : const LegalizeRuleSet &
     248        5051 : LegalizerInfo::getActionDefinitions(unsigned Opcode) const {
     249        5051 :   unsigned OpcodeIdx = getActionDefinitionsIdx(Opcode);
     250        5051 :   return RulesForOpcode[OpcodeIdx];
     251             : }
     252             : 
     253      161935 : LegalizeRuleSet &LegalizerInfo::getActionDefinitionsBuilder(unsigned Opcode) {
     254      161935 :   unsigned OpcodeIdx = getActionDefinitionsIdx(Opcode);
     255      161935 :   auto &Result = RulesForOpcode[OpcodeIdx];
     256             :   assert(!Result.isAliasedByAnother() && "Modifying this opcode will modify aliases");
     257      161935 :   return Result;
     258             : }
     259             : 
     260       55544 : LegalizeRuleSet &LegalizerInfo::getActionDefinitionsBuilder(
     261             :     std::initializer_list<unsigned> Opcodes) {
     262       55544 :   unsigned Representative = *Opcodes.begin();
     263             : 
     264             :   assert(Opcodes.begin() != Opcodes.end() &&
     265             :          Opcodes.begin() + 1 != Opcodes.end() &&
     266             :          "Initializer list must have at least two opcodes");
     267             : 
     268      343400 :   for (auto I = Opcodes.begin() + 1, E = Opcodes.end(); I != E; ++I)
     269      116156 :     aliasActionDefinitions(Representative, *I);
     270             : 
     271       55544 :   auto &Return = getActionDefinitionsBuilder(Representative);
     272             :   Return.setIsAliasedByAnother();
     273       55544 :   return Return;
     274             : }
     275             : 
     276      116156 : void LegalizerInfo::aliasActionDefinitions(unsigned OpcodeTo,
     277             :                                            unsigned OpcodeFrom) {
     278             :   assert(OpcodeTo != OpcodeFrom && "Cannot alias to self");
     279             :   assert(OpcodeTo >= FirstOp && OpcodeTo <= LastOp && "Unsupported opcode");
     280      116156 :   const unsigned OpcodeFromIdx = getOpcodeIdxForOpcode(OpcodeFrom);
     281      116156 :   RulesForOpcode[OpcodeFromIdx].aliasTo(OpcodeTo);
     282      116156 : }
     283             : 
     284             : LegalizeActionStep
     285        5051 : LegalizerInfo::getAction(const LegalityQuery &Query) const {
     286        5051 :   LegalizeActionStep Step = getActionDefinitions(Query.Opcode).apply(Query);
     287        5051 :   if (Step.Action != LegalizeAction::UseLegacyRules) {
     288        3027 :     return Step;
     289             :   }
     290             : 
     291        7478 :   for (unsigned i = 0; i < Query.Types.size(); ++i) {
     292        5906 :     auto Action = getAspectAction({Query.Opcode, i, Query.Types[i]});
     293        2953 :     if (Action.first != Legal) {
     294             :       DEBUG(dbgs() << ".. (legacy) Type " << i << " Action="
     295             :                    << (unsigned)Action.first << ", " << Action.second << "\n");
     296         226 :       return {Action.first, i, Action.second};
     297             :     } else
     298             :       DEBUG(dbgs() << ".. (legacy) Type " << i << " Legal\n");
     299             :   }
     300             :   DEBUG(dbgs() << ".. (legacy) Legal\n");
     301        1798 :   return {Legal, 0, LLT{}};
     302             : }
     303             : 
     304             : LegalizeActionStep
     305        4317 : LegalizerInfo::getAction(const MachineInstr &MI,
     306             :                          const MachineRegisterInfo &MRI) const {
     307             :   SmallVector<LLT, 2> Types;
     308        4317 :   SmallBitVector SeenTypes(8);
     309        4317 :   const MCOperandInfo *OpInfo = MI.getDesc().OpInfo;
     310             :   // FIXME: probably we'll need to cache the results here somehow?
     311       40080 :   for (unsigned i = 0; i < MI.getDesc().getNumOperands(); ++i) {
     312       20964 :     if (!OpInfo[i].isGenericType())
     313        5534 :       continue;
     314             : 
     315             :     // We must only record actions once for each TypeIdx; otherwise we'd
     316             :     // try to legalize operands multiple times down the line.
     317             :     unsigned TypeIdx = OpInfo[i].getGenericTypeIndex();
     318        9202 :     if (SeenTypes[TypeIdx])
     319        2974 :       continue;
     320             : 
     321        6228 :     SeenTypes.set(TypeIdx);
     322             : 
     323        6228 :     LLT Ty = getTypeFromTypeIdx(MI, MRI, i, TypeIdx);
     324        6228 :     Types.push_back(Ty);
     325             :   }
     326       12951 :   return getAction({MI.getOpcode(), Types});
     327             : }
     328             : 
     329           0 : bool LegalizerInfo::isLegal(const MachineInstr &MI,
     330             :                             const MachineRegisterInfo &MRI) const {
     331           0 :   return getAction(MI, MRI).Action == Legal;
     332             : }
     333             : 
     334           0 : bool LegalizerInfo::legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI,
     335             :                                    MachineIRBuilder &MIRBuilder) const {
     336           0 :   return false;
     337             : }
     338             : 
     339             : LegalizerInfo::SizeAndActionsVec
     340     1382094 : LegalizerInfo::increaseToLargerTypesAndDecreaseToLargest(
     341             :     const SizeAndActionsVec &v, LegalizeAction IncreaseAction,
     342             :     LegalizeAction DecreaseAction) {
     343             :   SizeAndActionsVec result;
     344             :   unsigned LargestSizeSoFar = 0;
     345     2764188 :   if (v.size() >= 1 && v[0].first != 1)
     346      948254 :     result.push_back({1, IncreaseAction});
     347     6494530 :   for (size_t i = 0; i < v.size(); ++i) {
     348     1865171 :     result.push_back(v[i]);
     349     3730342 :     LargestSizeSoFar = v[i].first;
     350     4601758 :     if (i + 1 < v.size() && v[i + 1].first != v[i].first + 1) {
     351      871416 :       result.push_back({LargestSizeSoFar + 1, IncreaseAction});
     352     1742832 :       LargestSizeSoFar = v[i].first + 1;
     353             :     }
     354             :   }
     355     2764188 :   result.push_back({LargestSizeSoFar + 1, DecreaseAction});
     356     1382094 :   return result;
     357             : }
     358             : 
     359             : LegalizerInfo::SizeAndActionsVec
     360       45393 : LegalizerInfo::decreaseToSmallerTypesAndIncreaseToSmallest(
     361             :     const SizeAndActionsVec &v, LegalizeAction DecreaseAction,
     362             :     LegalizeAction IncreaseAction) {
     363             :   SizeAndActionsVec result;
     364       90786 :   if (v.size() == 0 || v[0].first != 1)
     365       34035 :     result.push_back({1, IncreaseAction});
     366      399450 :   for (size_t i = 0; i < v.size(); ++i) {
     367      154332 :     result.push_back(v[i]);
     368      540996 :     if (i + 1 == v.size() || v[i + 1].first != v[i].first + 1) {
     369      308664 :       result.push_back({v[i].first + 1, DecreaseAction});
     370             :     }
     371             :   }
     372       45393 :   return result;
     373             : }
     374             : 
     375             : LegalizerInfo::SizeAndAction
     376        3354 : LegalizerInfo::findAction(const SizeAndActionsVec &Vec, const uint32_t Size) {
     377             :   assert(Size >= 1);
     378             :   // Find the last element in Vec that has a bitsize equal to or smaller than
     379             :   // the requested bit size.
     380             :   // That is the element just before the first element that is bigger than Size.
     381             :   auto VecIt = std::upper_bound(
     382             :       Vec.begin(), Vec.end(), Size,
     383             :       [](const uint32_t Size, const SizeAndAction lhs) -> bool {
     384        7946 :         return Size < lhs.first;
     385        3354 :       });
     386             :   assert(VecIt != Vec.begin() && "Does Vec not start with size 1?");
     387             :   --VecIt;
     388        3354 :   int VecIdx = VecIt - Vec.begin();
     389             : 
     390        6708 :   LegalizeAction Action = Vec[VecIdx].second;
     391        3354 :   switch (Action) {
     392             :   case Legal:
     393             :   case Lower:
     394             :   case Libcall:
     395             :   case Custom:
     396        3209 :     return {Size, Action};
     397             :   case FewerElements:
     398             :     // FIXME: is this special case still needed and correct?
     399             :     // Special case for scalarization:
     400          62 :     if (Vec == SizeAndActionsVec({{1, FewerElements}}))
     401           0 :       return {1, FewerElements};
     402             :     LLVM_FALLTHROUGH;
     403             :   case NarrowScalar: {
     404             :     // The following needs to be a loop, as for now, we do allow needing to
     405             :     // go over "Unsupported" bit sizes before finding a legalizable bit size.
     406             :     // e.g. (s8, WidenScalar), (s9, Unsupported), (s32, Legal). if Size==8,
     407             :     // we need to iterate over s9, and then to s32 to return (s32, Legal).
     408             :     // If we want to get rid of the below loop, we should have stronger asserts
     409             :     // when building the SizeAndActionsVecs, probably not allowing
     410             :     // "Unsupported" unless at the ends of the vector.
     411          47 :     for (int i = VecIdx - 1; i >= 0; --i)
     412          94 :       if (!needsLegalizingToDifferentSize(Vec[i].second) &&
     413             :           Vec[i].second != Unsupported)
     414          47 :         return {Vec[i].first, Action};
     415           0 :     llvm_unreachable("");
     416             :   }
     417          96 :   case WidenScalar:
     418             :   case MoreElements: {
     419             :     // See above, the following needs to be a loop, at least for now.
     420         340 :     for (std::size_t i = VecIdx + 1; i < Vec.size(); ++i)
     421         170 :       if (!needsLegalizingToDifferentSize(Vec[i].second) &&
     422             :           Vec[i].second != Unsupported)
     423          96 :         return {Vec[i].first, Action};
     424           0 :     llvm_unreachable("");
     425             :   }
     426           2 :   case Unsupported:
     427           2 :     return {Size, Unsupported};
     428           0 :   case NotFound:
     429             :   case UseLegacyRules:
     430           0 :     llvm_unreachable("NotFound");
     431             :   }
     432           0 :   llvm_unreachable("Action has an unknown enum value");
     433             : }
     434             : 
     435             : std::pair<LegalizeAction, LLT>
     436        2532 : LegalizerInfo::findScalarLegalAction(const InstrAspect &Aspect) const {
     437             :   assert(Aspect.Type.isScalar() || Aspect.Type.isPointer());
     438        2532 :   if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
     439           0 :     return {NotFound, LLT()};
     440        2532 :   const unsigned OpcodeIdx = getOpcodeIdxForOpcode(Aspect.Opcode);
     441         592 :   if (Aspect.Type.isPointer() &&
     442        3124 :       AddrSpace2PointerActions[OpcodeIdx].find(Aspect.Type.getAddressSpace()) ==
     443         592 :           AddrSpace2PointerActions[OpcodeIdx].end()) {
     444           2 :     return {NotFound, LLT()};
     445             :   }
     446             :   const SmallVector<SizeAndActionsVec, 1> &Actions =
     447             :       Aspect.Type.isPointer()
     448             :           ? AddrSpace2PointerActions[OpcodeIdx]
     449        3710 :                 .find(Aspect.Type.getAddressSpace())
     450             :                 ->second
     451        2530 :           : ScalarActions[OpcodeIdx];
     452        5060 :   if (Aspect.Idx >= Actions.size())
     453          16 :     return {NotFound, LLT()};
     454             :   const SizeAndActionsVec &Vec = Actions[Aspect.Idx];
     455             :   // FIXME: speed up this search, e.g. by using a results cache for repeated
     456             :   // queries?
     457        2514 :   auto SizeAndAction = findAction(Vec, Aspect.Type.getSizeInBits());
     458             :   return {SizeAndAction.second,
     459             :           Aspect.Type.isScalar() ? LLT::scalar(SizeAndAction.first)
     460             :                                  : LLT::pointer(Aspect.Type.getAddressSpace(),
     461        3104 :                                                 SizeAndAction.first)};
     462             : }
     463             : 
     464             : std::pair<LegalizeAction, LLT>
     465         421 : LegalizerInfo::findVectorLegalAction(const InstrAspect &Aspect) const {
     466             :   assert(Aspect.Type.isVector());
     467             :   // First legalize the vector element size, then legalize the number of
     468             :   // lanes in the vector.
     469         421 :   if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
     470           0 :     return {NotFound, Aspect.Type};
     471         421 :   const unsigned OpcodeIdx = getOpcodeIdxForOpcode(Aspect.Opcode);
     472         421 :   const unsigned TypeIdx = Aspect.Idx;
     473         842 :   if (TypeIdx >= ScalarInVectorActions[OpcodeIdx].size())
     474           0 :     return {NotFound, Aspect.Type};
     475             :   const SizeAndActionsVec &ElemSizeVec =
     476             :       ScalarInVectorActions[OpcodeIdx][TypeIdx];
     477             : 
     478             :   LLT IntermediateType;
     479             :   auto ElementSizeAndAction =
     480         421 :       findAction(ElemSizeVec, Aspect.Type.getScalarSizeInBits());
     481             :   IntermediateType =
     482         421 :       LLT::vector(Aspect.Type.getNumElements(), ElementSizeAndAction.first);
     483         421 :   if (ElementSizeAndAction.second != Legal)
     484           2 :     return {ElementSizeAndAction.second, IntermediateType};
     485             : 
     486             :   auto i = NumElements2Actions[OpcodeIdx].find(
     487        1257 :       IntermediateType.getScalarSizeInBits());
     488         419 :   if (i == NumElements2Actions[OpcodeIdx].end()) {
     489           0 :     return {NotFound, IntermediateType};
     490             :   }
     491             :   const SizeAndActionsVec &NumElementsVec = (*i).second[TypeIdx];
     492             :   auto NumElementsAndAction =
     493         419 :       findAction(NumElementsVec, IntermediateType.getNumElements());
     494             :   return {NumElementsAndAction.second,
     495         419 :           LLT::vector(NumElementsAndAction.first,
     496         419 :                       IntermediateType.getScalarSizeInBits())};
     497             : }

Generated by: LCOV version 1.13