xref: /llvm-project/llvm/lib/CodeGen/GlobalISel/LegacyLegalizerInfo.cpp (revision d9847cde4841140a95404ea7b7d3a57f8bfbf976)
1aaac2682SDaniel Sanders //===- lib/CodeGen/GlobalISel/LegacyLegalizerInfo.cpp - Legalizer ---------===//
2aaac2682SDaniel Sanders //
3aaac2682SDaniel Sanders // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4aaac2682SDaniel Sanders // See https://llvm.org/LICENSE.txt for license information.
5aaac2682SDaniel Sanders // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6aaac2682SDaniel Sanders //
7aaac2682SDaniel Sanders //===----------------------------------------------------------------------===//
8aaac2682SDaniel Sanders //
9aaac2682SDaniel Sanders // Implement an interface to specify and query how an illegal operation on a
10aaac2682SDaniel Sanders // given type should be expanded.
11aaac2682SDaniel Sanders //
12aaac2682SDaniel Sanders // Issues to be resolved:
13aaac2682SDaniel Sanders //   + Make it fast.
14aaac2682SDaniel Sanders //   + Support weird types like i3, <7 x i3>, ...
15aaac2682SDaniel Sanders //   + Operations with more than one type (ICMP, CMPXCHG, intrinsics, ...)
16aaac2682SDaniel Sanders //
17aaac2682SDaniel Sanders //===----------------------------------------------------------------------===//
18aaac2682SDaniel Sanders 
19aaac2682SDaniel Sanders #include "llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h"
20aaac2682SDaniel Sanders #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
21aaac2682SDaniel Sanders #include <map>
22aaac2682SDaniel Sanders 
23aaac2682SDaniel Sanders using namespace llvm;
24aaac2682SDaniel Sanders using namespace LegacyLegalizeActions;
25aaac2682SDaniel Sanders 
26aaac2682SDaniel Sanders #define DEBUG_TYPE "legalizer-info"
27aaac2682SDaniel Sanders 
operator <<(raw_ostream & OS,LegacyLegalizeAction Action)2893726620SDaniel Sanders raw_ostream &llvm::operator<<(raw_ostream &OS, LegacyLegalizeAction Action) {
2993726620SDaniel Sanders   switch (Action) {
3093726620SDaniel Sanders   case Legal:
3193726620SDaniel Sanders     OS << "Legal";
3293726620SDaniel Sanders     break;
3393726620SDaniel Sanders   case NarrowScalar:
3493726620SDaniel Sanders     OS << "NarrowScalar";
3593726620SDaniel Sanders     break;
3693726620SDaniel Sanders   case WidenScalar:
3793726620SDaniel Sanders     OS << "WidenScalar";
3893726620SDaniel Sanders     break;
3993726620SDaniel Sanders   case FewerElements:
4093726620SDaniel Sanders     OS << "FewerElements";
4193726620SDaniel Sanders     break;
4293726620SDaniel Sanders   case MoreElements:
4393726620SDaniel Sanders     OS << "MoreElements";
4493726620SDaniel Sanders     break;
4593726620SDaniel Sanders   case Bitcast:
4693726620SDaniel Sanders     OS << "Bitcast";
4793726620SDaniel Sanders     break;
4893726620SDaniel Sanders   case Lower:
4993726620SDaniel Sanders     OS << "Lower";
5093726620SDaniel Sanders     break;
5193726620SDaniel Sanders   case Libcall:
5293726620SDaniel Sanders     OS << "Libcall";
5393726620SDaniel Sanders     break;
5493726620SDaniel Sanders   case Custom:
5593726620SDaniel Sanders     OS << "Custom";
5693726620SDaniel Sanders     break;
5793726620SDaniel Sanders   case Unsupported:
5893726620SDaniel Sanders     OS << "Unsupported";
5993726620SDaniel Sanders     break;
6093726620SDaniel Sanders   case NotFound:
6193726620SDaniel Sanders     OS << "NotFound";
6293726620SDaniel Sanders     break;
6393726620SDaniel Sanders   }
6493726620SDaniel Sanders   return OS;
6593726620SDaniel Sanders }
6693726620SDaniel Sanders 
LegacyLegalizerInfo()672bea207dSKazu Hirata LegacyLegalizerInfo::LegacyLegalizerInfo() {
68aaac2682SDaniel Sanders   // Set defaults.
69aaac2682SDaniel Sanders   // FIXME: these two (G_ANYEXT and G_TRUNC?) can be legalized to the
70aaac2682SDaniel Sanders   // fundamental load/store Jakob proposed. Once loads & stores are supported.
71aaac2682SDaniel Sanders   setScalarAction(TargetOpcode::G_ANYEXT, 1, {{1, Legal}});
72aaac2682SDaniel Sanders   setScalarAction(TargetOpcode::G_ZEXT, 1, {{1, Legal}});
73aaac2682SDaniel Sanders   setScalarAction(TargetOpcode::G_SEXT, 1, {{1, Legal}});
74aaac2682SDaniel Sanders   setScalarAction(TargetOpcode::G_TRUNC, 0, {{1, Legal}});
75aaac2682SDaniel Sanders   setScalarAction(TargetOpcode::G_TRUNC, 1, {{1, Legal}});
76aaac2682SDaniel Sanders 
77aaac2682SDaniel Sanders   setScalarAction(TargetOpcode::G_INTRINSIC, 0, {{1, Legal}});
78aaac2682SDaniel Sanders   setScalarAction(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS, 0, {{1, Legal}});
79*d9847cdeSSameer Sahasrabuddhe   setScalarAction(TargetOpcode::G_INTRINSIC_CONVERGENT, 0, {{1, Legal}});
80*d9847cdeSSameer Sahasrabuddhe   setScalarAction(TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS, 0,
81*d9847cdeSSameer Sahasrabuddhe                   {{1, Legal}});
82aaac2682SDaniel Sanders 
83aaac2682SDaniel Sanders   setLegalizeScalarToDifferentSizeStrategy(
84aaac2682SDaniel Sanders       TargetOpcode::G_IMPLICIT_DEF, 0, narrowToSmallerAndUnsupportedIfTooSmall);
85aaac2682SDaniel Sanders   setLegalizeScalarToDifferentSizeStrategy(
86aaac2682SDaniel Sanders       TargetOpcode::G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
87aaac2682SDaniel Sanders   setLegalizeScalarToDifferentSizeStrategy(
88aaac2682SDaniel Sanders       TargetOpcode::G_OR, 0, widenToLargerTypesAndNarrowToLargest);
89aaac2682SDaniel Sanders   setLegalizeScalarToDifferentSizeStrategy(
90aaac2682SDaniel Sanders       TargetOpcode::G_LOAD, 0, narrowToSmallerAndUnsupportedIfTooSmall);
91aaac2682SDaniel Sanders   setLegalizeScalarToDifferentSizeStrategy(
92aaac2682SDaniel Sanders       TargetOpcode::G_STORE, 0, narrowToSmallerAndUnsupportedIfTooSmall);
93aaac2682SDaniel Sanders 
94aaac2682SDaniel Sanders   setLegalizeScalarToDifferentSizeStrategy(
95aaac2682SDaniel Sanders       TargetOpcode::G_BRCOND, 0, widenToLargerTypesUnsupportedOtherwise);
96aaac2682SDaniel Sanders   setLegalizeScalarToDifferentSizeStrategy(
97aaac2682SDaniel Sanders       TargetOpcode::G_INSERT, 0, narrowToSmallerAndUnsupportedIfTooSmall);
98aaac2682SDaniel Sanders   setLegalizeScalarToDifferentSizeStrategy(
99aaac2682SDaniel Sanders       TargetOpcode::G_EXTRACT, 0, narrowToSmallerAndUnsupportedIfTooSmall);
100aaac2682SDaniel Sanders   setLegalizeScalarToDifferentSizeStrategy(
101aaac2682SDaniel Sanders       TargetOpcode::G_EXTRACT, 1, narrowToSmallerAndUnsupportedIfTooSmall);
102aaac2682SDaniel Sanders   setScalarAction(TargetOpcode::G_FNEG, 0, {{1, Lower}});
103aaac2682SDaniel Sanders }
104aaac2682SDaniel Sanders 
computeTables()105aaac2682SDaniel Sanders void LegacyLegalizerInfo::computeTables() {
106aaac2682SDaniel Sanders   assert(TablesInitialized == false);
107aaac2682SDaniel Sanders 
108aaac2682SDaniel Sanders   for (unsigned OpcodeIdx = 0; OpcodeIdx <= LastOp - FirstOp; ++OpcodeIdx) {
109aaac2682SDaniel Sanders     const unsigned Opcode = FirstOp + OpcodeIdx;
110aaac2682SDaniel Sanders     for (unsigned TypeIdx = 0; TypeIdx != SpecifiedActions[OpcodeIdx].size();
111aaac2682SDaniel Sanders          ++TypeIdx) {
112aaac2682SDaniel Sanders       // 0. Collect information specified through the setAction API, i.e.
113aaac2682SDaniel Sanders       // for specific bit sizes.
114aaac2682SDaniel Sanders       // For scalar types:
115aaac2682SDaniel Sanders       SizeAndActionsVec ScalarSpecifiedActions;
116aaac2682SDaniel Sanders       // For pointer types:
117aaac2682SDaniel Sanders       std::map<uint16_t, SizeAndActionsVec> AddressSpace2SpecifiedActions;
118aaac2682SDaniel Sanders       // For vector types:
119aaac2682SDaniel Sanders       std::map<uint16_t, SizeAndActionsVec> ElemSize2SpecifiedActions;
120aaac2682SDaniel Sanders       for (auto LLT2Action : SpecifiedActions[OpcodeIdx][TypeIdx]) {
121aaac2682SDaniel Sanders         const LLT Type = LLT2Action.first;
122aaac2682SDaniel Sanders         const LegacyLegalizeAction Action = LLT2Action.second;
123aaac2682SDaniel Sanders 
124aaac2682SDaniel Sanders         auto SizeAction = std::make_pair(Type.getSizeInBits(), Action);
125aaac2682SDaniel Sanders         if (Type.isPointer())
126aaac2682SDaniel Sanders           AddressSpace2SpecifiedActions[Type.getAddressSpace()].push_back(
127aaac2682SDaniel Sanders               SizeAction);
128aaac2682SDaniel Sanders         else if (Type.isVector())
129aaac2682SDaniel Sanders           ElemSize2SpecifiedActions[Type.getElementType().getSizeInBits()]
130aaac2682SDaniel Sanders               .push_back(SizeAction);
131aaac2682SDaniel Sanders         else
132aaac2682SDaniel Sanders           ScalarSpecifiedActions.push_back(SizeAction);
133aaac2682SDaniel Sanders       }
134aaac2682SDaniel Sanders 
135aaac2682SDaniel Sanders       // 1. Handle scalar types
136aaac2682SDaniel Sanders       {
137aaac2682SDaniel Sanders         // Decide how to handle bit sizes for which no explicit specification
138aaac2682SDaniel Sanders         // was given.
139aaac2682SDaniel Sanders         SizeChangeStrategy S = &unsupportedForDifferentSizes;
140aaac2682SDaniel Sanders         if (TypeIdx < ScalarSizeChangeStrategies[OpcodeIdx].size() &&
141aaac2682SDaniel Sanders             ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)
142aaac2682SDaniel Sanders           S = ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx];
143aaac2682SDaniel Sanders         llvm::sort(ScalarSpecifiedActions);
144aaac2682SDaniel Sanders         checkPartialSizeAndActionsVector(ScalarSpecifiedActions);
145aaac2682SDaniel Sanders         setScalarAction(Opcode, TypeIdx, S(ScalarSpecifiedActions));
146aaac2682SDaniel Sanders       }
147aaac2682SDaniel Sanders 
148aaac2682SDaniel Sanders       // 2. Handle pointer types
149aaac2682SDaniel Sanders       for (auto PointerSpecifiedActions : AddressSpace2SpecifiedActions) {
150aaac2682SDaniel Sanders         llvm::sort(PointerSpecifiedActions.second);
151aaac2682SDaniel Sanders         checkPartialSizeAndActionsVector(PointerSpecifiedActions.second);
152aaac2682SDaniel Sanders         // For pointer types, we assume that there isn't a meaningfull way
153aaac2682SDaniel Sanders         // to change the number of bits used in the pointer.
154aaac2682SDaniel Sanders         setPointerAction(
155aaac2682SDaniel Sanders             Opcode, TypeIdx, PointerSpecifiedActions.first,
156aaac2682SDaniel Sanders             unsupportedForDifferentSizes(PointerSpecifiedActions.second));
157aaac2682SDaniel Sanders       }
158aaac2682SDaniel Sanders 
159aaac2682SDaniel Sanders       // 3. Handle vector types
160aaac2682SDaniel Sanders       SizeAndActionsVec ElementSizesSeen;
161aaac2682SDaniel Sanders       for (auto VectorSpecifiedActions : ElemSize2SpecifiedActions) {
162aaac2682SDaniel Sanders         llvm::sort(VectorSpecifiedActions.second);
163aaac2682SDaniel Sanders         const uint16_t ElementSize = VectorSpecifiedActions.first;
164aaac2682SDaniel Sanders         ElementSizesSeen.push_back({ElementSize, Legal});
165aaac2682SDaniel Sanders         checkPartialSizeAndActionsVector(VectorSpecifiedActions.second);
166aaac2682SDaniel Sanders         // For vector types, we assume that the best way to adapt the number
167aaac2682SDaniel Sanders         // of elements is to the next larger number of elements type for which
168aaac2682SDaniel Sanders         // the vector type is legal, unless there is no such type. In that case,
169aaac2682SDaniel Sanders         // legalize towards a vector type with a smaller number of elements.
170aaac2682SDaniel Sanders         SizeAndActionsVec NumElementsActions;
171aaac2682SDaniel Sanders         for (SizeAndAction BitsizeAndAction : VectorSpecifiedActions.second) {
172aaac2682SDaniel Sanders           assert(BitsizeAndAction.first % ElementSize == 0);
173aaac2682SDaniel Sanders           const uint16_t NumElements = BitsizeAndAction.first / ElementSize;
174aaac2682SDaniel Sanders           NumElementsActions.push_back({NumElements, BitsizeAndAction.second});
175aaac2682SDaniel Sanders         }
176aaac2682SDaniel Sanders         setVectorNumElementAction(
177aaac2682SDaniel Sanders             Opcode, TypeIdx, ElementSize,
178aaac2682SDaniel Sanders             moreToWiderTypesAndLessToWidest(NumElementsActions));
179aaac2682SDaniel Sanders       }
180aaac2682SDaniel Sanders       llvm::sort(ElementSizesSeen);
181aaac2682SDaniel Sanders       SizeChangeStrategy VectorElementSizeChangeStrategy =
182aaac2682SDaniel Sanders           &unsupportedForDifferentSizes;
183aaac2682SDaniel Sanders       if (TypeIdx < VectorElementSizeChangeStrategies[OpcodeIdx].size() &&
184aaac2682SDaniel Sanders           VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)
185aaac2682SDaniel Sanders         VectorElementSizeChangeStrategy =
186aaac2682SDaniel Sanders             VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx];
187aaac2682SDaniel Sanders       setScalarInVectorAction(
188aaac2682SDaniel Sanders           Opcode, TypeIdx, VectorElementSizeChangeStrategy(ElementSizesSeen));
189aaac2682SDaniel Sanders     }
190aaac2682SDaniel Sanders   }
191aaac2682SDaniel Sanders 
192aaac2682SDaniel Sanders   TablesInitialized = true;
193aaac2682SDaniel Sanders }
194aaac2682SDaniel Sanders 
195aaac2682SDaniel Sanders // FIXME: inefficient implementation for now. Without ComputeValueVTs we're
196aaac2682SDaniel Sanders // probably going to need specialized lookup structures for various types before
197aaac2682SDaniel Sanders // we have any hope of doing well with something like <13 x i3>. Even the common
198aaac2682SDaniel Sanders // cases should do better than what we have now.
199aaac2682SDaniel Sanders std::pair<LegacyLegalizeAction, LLT>
getAspectAction(const InstrAspect & Aspect) const200aaac2682SDaniel Sanders LegacyLegalizerInfo::getAspectAction(const InstrAspect &Aspect) const {
201aaac2682SDaniel Sanders   assert(TablesInitialized && "backend forgot to call computeTables");
202aaac2682SDaniel Sanders   // These *have* to be implemented for now, they're the fundamental basis of
203aaac2682SDaniel Sanders   // how everything else is transformed.
204aaac2682SDaniel Sanders   if (Aspect.Type.isScalar() || Aspect.Type.isPointer())
205aaac2682SDaniel Sanders     return findScalarLegalAction(Aspect);
206aaac2682SDaniel Sanders   assert(Aspect.Type.isVector());
207aaac2682SDaniel Sanders   return findVectorLegalAction(Aspect);
208aaac2682SDaniel Sanders }
209aaac2682SDaniel Sanders 
210aaac2682SDaniel Sanders LegacyLegalizerInfo::SizeAndActionsVec
increaseToLargerTypesAndDecreaseToLargest(const SizeAndActionsVec & v,LegacyLegalizeAction IncreaseAction,LegacyLegalizeAction DecreaseAction)211aaac2682SDaniel Sanders LegacyLegalizerInfo::increaseToLargerTypesAndDecreaseToLargest(
212aaac2682SDaniel Sanders     const SizeAndActionsVec &v, LegacyLegalizeAction IncreaseAction,
213aaac2682SDaniel Sanders     LegacyLegalizeAction DecreaseAction) {
214aaac2682SDaniel Sanders   SizeAndActionsVec result;
215aaac2682SDaniel Sanders   unsigned LargestSizeSoFar = 0;
216aaac2682SDaniel Sanders   if (v.size() >= 1 && v[0].first != 1)
217aaac2682SDaniel Sanders     result.push_back({1, IncreaseAction});
218aaac2682SDaniel Sanders   for (size_t i = 0; i < v.size(); ++i) {
219aaac2682SDaniel Sanders     result.push_back(v[i]);
220aaac2682SDaniel Sanders     LargestSizeSoFar = v[i].first;
221aaac2682SDaniel Sanders     if (i + 1 < v.size() && v[i + 1].first != v[i].first + 1) {
222aaac2682SDaniel Sanders       result.push_back({LargestSizeSoFar + 1, IncreaseAction});
223aaac2682SDaniel Sanders       LargestSizeSoFar = v[i].first + 1;
224aaac2682SDaniel Sanders     }
225aaac2682SDaniel Sanders   }
226aaac2682SDaniel Sanders   result.push_back({LargestSizeSoFar + 1, DecreaseAction});
227aaac2682SDaniel Sanders   return result;
228aaac2682SDaniel Sanders }
229aaac2682SDaniel Sanders 
230aaac2682SDaniel Sanders LegacyLegalizerInfo::SizeAndActionsVec
decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec & v,LegacyLegalizeAction DecreaseAction,LegacyLegalizeAction IncreaseAction)231aaac2682SDaniel Sanders LegacyLegalizerInfo::decreaseToSmallerTypesAndIncreaseToSmallest(
232aaac2682SDaniel Sanders     const SizeAndActionsVec &v, LegacyLegalizeAction DecreaseAction,
233aaac2682SDaniel Sanders     LegacyLegalizeAction IncreaseAction) {
234aaac2682SDaniel Sanders   SizeAndActionsVec result;
235aaac2682SDaniel Sanders   if (v.size() == 0 || v[0].first != 1)
236aaac2682SDaniel Sanders     result.push_back({1, IncreaseAction});
237aaac2682SDaniel Sanders   for (size_t i = 0; i < v.size(); ++i) {
238aaac2682SDaniel Sanders     result.push_back(v[i]);
239aaac2682SDaniel Sanders     if (i + 1 == v.size() || v[i + 1].first != v[i].first + 1) {
240aaac2682SDaniel Sanders       result.push_back({v[i].first + 1, DecreaseAction});
241aaac2682SDaniel Sanders     }
242aaac2682SDaniel Sanders   }
243aaac2682SDaniel Sanders   return result;
244aaac2682SDaniel Sanders }
245aaac2682SDaniel Sanders 
246aaac2682SDaniel Sanders LegacyLegalizerInfo::SizeAndAction
findAction(const SizeAndActionsVec & Vec,const uint32_t Size)247aaac2682SDaniel Sanders LegacyLegalizerInfo::findAction(const SizeAndActionsVec &Vec, const uint32_t Size) {
248aaac2682SDaniel Sanders   assert(Size >= 1);
249aaac2682SDaniel Sanders   // Find the last element in Vec that has a bitsize equal to or smaller than
250aaac2682SDaniel Sanders   // the requested bit size.
251aaac2682SDaniel Sanders   // That is the element just before the first element that is bigger than Size.
252aaac2682SDaniel Sanders   auto It = partition_point(
253aaac2682SDaniel Sanders       Vec, [=](const SizeAndAction &A) { return A.first <= Size; });
254aaac2682SDaniel Sanders   assert(It != Vec.begin() && "Does Vec not start with size 1?");
255aaac2682SDaniel Sanders   int VecIdx = It - Vec.begin() - 1;
256aaac2682SDaniel Sanders 
257aaac2682SDaniel Sanders   LegacyLegalizeAction Action = Vec[VecIdx].second;
258aaac2682SDaniel Sanders   switch (Action) {
259aaac2682SDaniel Sanders   case Legal:
260aaac2682SDaniel Sanders   case Bitcast:
261aaac2682SDaniel Sanders   case Lower:
262aaac2682SDaniel Sanders   case Libcall:
263aaac2682SDaniel Sanders   case Custom:
264aaac2682SDaniel Sanders     return {Size, Action};
265aaac2682SDaniel Sanders   case FewerElements:
266aaac2682SDaniel Sanders     // FIXME: is this special case still needed and correct?
267aaac2682SDaniel Sanders     // Special case for scalarization:
268aaac2682SDaniel Sanders     if (Vec == SizeAndActionsVec({{1, FewerElements}}))
269aaac2682SDaniel Sanders       return {1, FewerElements};
270de9d80c1SFangrui Song     [[fallthrough]];
271aaac2682SDaniel Sanders   case NarrowScalar: {
272aaac2682SDaniel Sanders     // The following needs to be a loop, as for now, we do allow needing to
273aaac2682SDaniel Sanders     // go over "Unsupported" bit sizes before finding a legalizable bit size.
274aaac2682SDaniel Sanders     // e.g. (s8, WidenScalar), (s9, Unsupported), (s32, Legal). if Size==8,
275aaac2682SDaniel Sanders     // we need to iterate over s9, and then to s32 to return (s32, Legal).
276aaac2682SDaniel Sanders     // If we want to get rid of the below loop, we should have stronger asserts
277aaac2682SDaniel Sanders     // when building the SizeAndActionsVecs, probably not allowing
278aaac2682SDaniel Sanders     // "Unsupported" unless at the ends of the vector.
279aaac2682SDaniel Sanders     for (int i = VecIdx - 1; i >= 0; --i)
280aaac2682SDaniel Sanders       if (!needsLegalizingToDifferentSize(Vec[i].second) &&
281aaac2682SDaniel Sanders           Vec[i].second != Unsupported)
282aaac2682SDaniel Sanders         return {Vec[i].first, Action};
283aaac2682SDaniel Sanders     llvm_unreachable("");
284aaac2682SDaniel Sanders   }
285aaac2682SDaniel Sanders   case WidenScalar:
286aaac2682SDaniel Sanders   case MoreElements: {
287aaac2682SDaniel Sanders     // See above, the following needs to be a loop, at least for now.
288aaac2682SDaniel Sanders     for (std::size_t i = VecIdx + 1; i < Vec.size(); ++i)
289aaac2682SDaniel Sanders       if (!needsLegalizingToDifferentSize(Vec[i].second) &&
290aaac2682SDaniel Sanders           Vec[i].second != Unsupported)
291aaac2682SDaniel Sanders         return {Vec[i].first, Action};
292aaac2682SDaniel Sanders     llvm_unreachable("");
293aaac2682SDaniel Sanders   }
294aaac2682SDaniel Sanders   case Unsupported:
295aaac2682SDaniel Sanders     return {Size, Unsupported};
296aaac2682SDaniel Sanders   case NotFound:
297aaac2682SDaniel Sanders     llvm_unreachable("NotFound");
298aaac2682SDaniel Sanders   }
299aaac2682SDaniel Sanders   llvm_unreachable("Action has an unknown enum value");
300aaac2682SDaniel Sanders }
301aaac2682SDaniel Sanders 
302aaac2682SDaniel Sanders std::pair<LegacyLegalizeAction, LLT>
findScalarLegalAction(const InstrAspect & Aspect) const303aaac2682SDaniel Sanders LegacyLegalizerInfo::findScalarLegalAction(const InstrAspect &Aspect) const {
304aaac2682SDaniel Sanders   assert(Aspect.Type.isScalar() || Aspect.Type.isPointer());
305aaac2682SDaniel Sanders   if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
306aaac2682SDaniel Sanders     return {NotFound, LLT()};
307aaac2682SDaniel Sanders   const unsigned OpcodeIdx = getOpcodeIdxForOpcode(Aspect.Opcode);
308aaac2682SDaniel Sanders   if (Aspect.Type.isPointer() &&
309aaac2682SDaniel Sanders       AddrSpace2PointerActions[OpcodeIdx].find(Aspect.Type.getAddressSpace()) ==
310aaac2682SDaniel Sanders           AddrSpace2PointerActions[OpcodeIdx].end()) {
311aaac2682SDaniel Sanders     return {NotFound, LLT()};
312aaac2682SDaniel Sanders   }
313aaac2682SDaniel Sanders   const SmallVector<SizeAndActionsVec, 1> &Actions =
314aaac2682SDaniel Sanders       Aspect.Type.isPointer()
315aaac2682SDaniel Sanders           ? AddrSpace2PointerActions[OpcodeIdx]
316aaac2682SDaniel Sanders                 .find(Aspect.Type.getAddressSpace())
317aaac2682SDaniel Sanders                 ->second
318aaac2682SDaniel Sanders           : ScalarActions[OpcodeIdx];
319aaac2682SDaniel Sanders   if (Aspect.Idx >= Actions.size())
320aaac2682SDaniel Sanders     return {NotFound, LLT()};
321aaac2682SDaniel Sanders   const SizeAndActionsVec &Vec = Actions[Aspect.Idx];
322aaac2682SDaniel Sanders   // FIXME: speed up this search, e.g. by using a results cache for repeated
323aaac2682SDaniel Sanders   // queries?
324aaac2682SDaniel Sanders   auto SizeAndAction = findAction(Vec, Aspect.Type.getSizeInBits());
325aaac2682SDaniel Sanders   return {SizeAndAction.second,
326aaac2682SDaniel Sanders           Aspect.Type.isScalar() ? LLT::scalar(SizeAndAction.first)
327aaac2682SDaniel Sanders                                  : LLT::pointer(Aspect.Type.getAddressSpace(),
328aaac2682SDaniel Sanders                                                 SizeAndAction.first)};
329aaac2682SDaniel Sanders }
330aaac2682SDaniel Sanders 
331aaac2682SDaniel Sanders std::pair<LegacyLegalizeAction, LLT>
findVectorLegalAction(const InstrAspect & Aspect) const332aaac2682SDaniel Sanders LegacyLegalizerInfo::findVectorLegalAction(const InstrAspect &Aspect) const {
333aaac2682SDaniel Sanders   assert(Aspect.Type.isVector());
334aaac2682SDaniel Sanders   // First legalize the vector element size, then legalize the number of
335aaac2682SDaniel Sanders   // lanes in the vector.
336aaac2682SDaniel Sanders   if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
337aaac2682SDaniel Sanders     return {NotFound, Aspect.Type};
338aaac2682SDaniel Sanders   const unsigned OpcodeIdx = getOpcodeIdxForOpcode(Aspect.Opcode);
339aaac2682SDaniel Sanders   const unsigned TypeIdx = Aspect.Idx;
340aaac2682SDaniel Sanders   if (TypeIdx >= ScalarInVectorActions[OpcodeIdx].size())
341aaac2682SDaniel Sanders     return {NotFound, Aspect.Type};
342aaac2682SDaniel Sanders   const SizeAndActionsVec &ElemSizeVec =
343aaac2682SDaniel Sanders       ScalarInVectorActions[OpcodeIdx][TypeIdx];
344aaac2682SDaniel Sanders 
345aaac2682SDaniel Sanders   LLT IntermediateType;
346aaac2682SDaniel Sanders   auto ElementSizeAndAction =
347aaac2682SDaniel Sanders       findAction(ElemSizeVec, Aspect.Type.getScalarSizeInBits());
348d5e14ba8SSander de Smalen   IntermediateType = LLT::fixed_vector(Aspect.Type.getNumElements(),
349d5e14ba8SSander de Smalen                                        ElementSizeAndAction.first);
350aaac2682SDaniel Sanders   if (ElementSizeAndAction.second != Legal)
351aaac2682SDaniel Sanders     return {ElementSizeAndAction.second, IntermediateType};
352aaac2682SDaniel Sanders 
353aaac2682SDaniel Sanders   auto i = NumElements2Actions[OpcodeIdx].find(
354aaac2682SDaniel Sanders       IntermediateType.getScalarSizeInBits());
355aaac2682SDaniel Sanders   if (i == NumElements2Actions[OpcodeIdx].end()) {
356aaac2682SDaniel Sanders     return {NotFound, IntermediateType};
357aaac2682SDaniel Sanders   }
358aaac2682SDaniel Sanders   const SizeAndActionsVec &NumElementsVec = (*i).second[TypeIdx];
359aaac2682SDaniel Sanders   auto NumElementsAndAction =
360aaac2682SDaniel Sanders       findAction(NumElementsVec, IntermediateType.getNumElements());
361aaac2682SDaniel Sanders   return {NumElementsAndAction.second,
362d5e14ba8SSander de Smalen           LLT::fixed_vector(NumElementsAndAction.first,
363aaac2682SDaniel Sanders                             IntermediateType.getScalarSizeInBits())};
364aaac2682SDaniel Sanders }
365aaac2682SDaniel Sanders 
getOpcodeIdxForOpcode(unsigned Opcode) const366aaac2682SDaniel Sanders unsigned LegacyLegalizerInfo::getOpcodeIdxForOpcode(unsigned Opcode) const {
367aaac2682SDaniel Sanders   assert(Opcode >= FirstOp && Opcode <= LastOp && "Unsupported opcode");
368aaac2682SDaniel Sanders   return Opcode - FirstOp;
369aaac2682SDaniel Sanders }
370aaac2682SDaniel Sanders 
371aaac2682SDaniel Sanders 
372aaac2682SDaniel Sanders LegacyLegalizeActionStep
getAction(const LegalityQuery & Query) const373aaac2682SDaniel Sanders LegacyLegalizerInfo::getAction(const LegalityQuery &Query) const {
374aaac2682SDaniel Sanders   for (unsigned i = 0; i < Query.Types.size(); ++i) {
375aaac2682SDaniel Sanders     auto Action = getAspectAction({Query.Opcode, i, Query.Types[i]});
376aaac2682SDaniel Sanders     if (Action.first != Legal) {
377aaac2682SDaniel Sanders       LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i << " Action="
378aaac2682SDaniel Sanders                         << Action.first << ", " << Action.second << "\n");
379aaac2682SDaniel Sanders       return {Action.first, i, Action.second};
380aaac2682SDaniel Sanders     } else
381aaac2682SDaniel Sanders       LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i << " Legal\n");
382aaac2682SDaniel Sanders   }
383aaac2682SDaniel Sanders   LLVM_DEBUG(dbgs() << ".. (legacy) Legal\n");
384aaac2682SDaniel Sanders   return {Legal, 0, LLT{}};
385aaac2682SDaniel Sanders }
386aaac2682SDaniel Sanders 
387