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