1 //===- llvm/CodeGen/GlobalISel/LegalizerInfo.h ------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 /// Interface for Targets to specify which operations they can successfully
10 /// select and how the others should be expanded most efficiently.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
15 #define LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/None.h"
19 #include "llvm/ADT/Optional.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/SmallBitVector.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/CodeGen/MachineFunction.h"
24 #include "llvm/CodeGen/TargetOpcodes.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/Support/LowLevelTypeImpl.h"
30 #include <unordered_map>
35 extern cl::opt
<bool> DisableGISelLegalityCheck
;
38 class MachineIRBuilder
;
39 class MachineRegisterInfo
;
41 class GISelChangeObserver
;
43 namespace LegalizeActions
{
44 enum LegalizeAction
: std::uint8_t {
45 /// The operation is expected to be selectable directly by the target, and
46 /// no transformation is necessary.
49 /// The operation should be synthesized from multiple instructions acting on
50 /// a narrower scalar base-type. For example a 64-bit add might be
51 /// implemented in terms of 32-bit add-with-carry.
54 /// The operation should be implemented in terms of a wider scalar
55 /// base-type. For example a <2 x s8> add could be implemented as a <2
56 /// x s32> add (ignoring the high bits).
59 /// The (vector) operation should be implemented by splitting it into
60 /// sub-vectors where the operation is legal. For example a <8 x s64> add
61 /// might be implemented as 4 separate <2 x s64> adds.
64 /// The (vector) operation should be implemented by widening the input
65 /// vector and ignoring the lanes added by doing so. For example <2 x i8> is
66 /// rarely legal, but you might perform an <8 x i8> and then only look at
67 /// the first two results.
70 /// The operation itself must be expressed in terms of simpler actions on
71 /// this target. E.g. a SREM replaced by an SDIV and subtraction.
74 /// The operation should be implemented as a call to some kind of runtime
75 /// support library. For example this usually happens on machines that don't
76 /// support floating-point operations natively.
79 /// The target wants to do something special with this combination of
80 /// operand and type. A callback will be issued when it is needed.
83 /// This operation is completely unsupported on the target. A programming
84 /// error has occurred.
87 /// Sentinel value for when no action was found in the specified table.
90 /// Fall back onto the old rules.
91 /// TODO: Remove this once we've migrated
94 } // end namespace LegalizeActions
95 raw_ostream
&operator<<(raw_ostream
&OS
, LegalizeActions::LegalizeAction Action
);
97 using LegalizeActions::LegalizeAction
;
99 /// Legalization is decided based on an instruction's opcode, which type slot
100 /// we're considering, and what the existing type is. These aspects are gathered
101 /// together for convenience in the InstrAspect class.
107 InstrAspect(unsigned Opcode
, LLT Type
) : Opcode(Opcode
), Type(Type
) {}
108 InstrAspect(unsigned Opcode
, unsigned Idx
, LLT Type
)
109 : Opcode(Opcode
), Idx(Idx
), Type(Type
) {}
111 bool operator==(const InstrAspect
&RHS
) const {
112 return Opcode
== RHS
.Opcode
&& Idx
== RHS
.Idx
&& Type
== RHS
.Type
;
116 /// The LegalityQuery object bundles together all the information that's needed
117 /// to decide whether a given operation is legal or not.
118 /// For efficiency, it doesn't make a copy of Types so care must be taken not
119 /// to free it before using the query.
120 struct LegalityQuery
{
126 uint64_t AlignInBits
;
127 AtomicOrdering Ordering
;
130 /// Operations which require memory can use this to place requirements on the
131 /// memory type for each MMO.
132 ArrayRef
<MemDesc
> MMODescrs
;
134 constexpr LegalityQuery(unsigned Opcode
, const ArrayRef
<LLT
> Types
,
135 const ArrayRef
<MemDesc
> MMODescrs
)
136 : Opcode(Opcode
), Types(Types
), MMODescrs(MMODescrs
) {}
137 constexpr LegalityQuery(unsigned Opcode
, const ArrayRef
<LLT
> Types
)
138 : LegalityQuery(Opcode
, Types
, {}) {}
140 raw_ostream
&print(raw_ostream
&OS
) const;
143 /// The result of a query. It either indicates a final answer of Legal or
144 /// Unsupported or describes an action that must be taken to make an operation
146 struct LegalizeActionStep
{
147 /// The action to take or the final answer.
148 LegalizeAction Action
;
149 /// If describing an action, the type index to change. Otherwise zero.
151 /// If describing an action, the new type for TypeIdx. Otherwise LLT{}.
154 LegalizeActionStep(LegalizeAction Action
, unsigned TypeIdx
,
156 : Action(Action
), TypeIdx(TypeIdx
), NewType(NewType
) {}
158 bool operator==(const LegalizeActionStep
&RHS
) const {
159 return std::tie(Action
, TypeIdx
, NewType
) ==
160 std::tie(RHS
.Action
, RHS
.TypeIdx
, RHS
.NewType
);
164 using LegalityPredicate
= std::function
<bool (const LegalityQuery
&)>;
165 using LegalizeMutation
=
166 std::function
<std::pair
<unsigned, LLT
>(const LegalityQuery
&)>;
168 namespace LegalityPredicates
{
169 struct TypePairAndMemDesc
{
175 bool operator==(const TypePairAndMemDesc
&Other
) const {
176 return Type0
== Other
.Type0
&& Type1
== Other
.Type1
&&
177 Align
== Other
.Align
&&
178 MemSize
== Other
.MemSize
;
181 /// \returns true if this memory access is legal with for the acecss described
182 /// by \p Other (The alignment is sufficient for the size and result type).
183 bool isCompatible(const TypePairAndMemDesc
&Other
) const {
184 return Type0
== Other
.Type0
&& Type1
== Other
.Type1
&&
185 Align
>= Other
.Align
&&
186 MemSize
== Other
.MemSize
;
190 /// True iff P0 and P1 are true.
191 template<typename Predicate
>
192 Predicate
all(Predicate P0
, Predicate P1
) {
193 return [=](const LegalityQuery
&Query
) {
194 return P0(Query
) && P1(Query
);
197 /// True iff all given predicates are true.
198 template<typename Predicate
, typename
... Args
>
199 Predicate
all(Predicate P0
, Predicate P1
, Args
... args
) {
200 return all(all(P0
, P1
), args
...);
202 /// True iff the given type index is the specified types.
203 LegalityPredicate
typeIs(unsigned TypeIdx
, LLT TypesInit
);
204 /// True iff the given type index is one of the specified types.
205 LegalityPredicate
typeInSet(unsigned TypeIdx
,
206 std::initializer_list
<LLT
> TypesInit
);
207 /// True iff the given types for the given pair of type indexes is one of the
208 /// specified type pairs.
210 typePairInSet(unsigned TypeIdx0
, unsigned TypeIdx1
,
211 std::initializer_list
<std::pair
<LLT
, LLT
>> TypesInit
);
212 /// True iff the given types for the given pair of type indexes is one of the
213 /// specified type pairs.
214 LegalityPredicate
typePairAndMemDescInSet(
215 unsigned TypeIdx0
, unsigned TypeIdx1
, unsigned MMOIdx
,
216 std::initializer_list
<TypePairAndMemDesc
> TypesAndMemDescInit
);
217 /// True iff the specified type index is a scalar.
218 LegalityPredicate
isScalar(unsigned TypeIdx
);
219 /// True iff the specified type index is a vector.
220 LegalityPredicate
isVector(unsigned TypeIdx
);
221 /// True iff the specified type index is a pointer (with any address space).
222 LegalityPredicate
isPointer(unsigned TypeIdx
);
223 /// True iff the specified type index is a pointer with the specified address
225 LegalityPredicate
isPointer(unsigned TypeIdx
, unsigned AddrSpace
);
227 /// True iff the specified type index is a scalar that's narrower than the given
229 LegalityPredicate
narrowerThan(unsigned TypeIdx
, unsigned Size
);
231 /// True iff the specified type index is a scalar that's wider than the given
233 LegalityPredicate
widerThan(unsigned TypeIdx
, unsigned Size
);
235 /// True iff the specified type index is a scalar or vector with an element type
236 /// that's narrower than the given size.
237 LegalityPredicate
scalarOrEltNarrowerThan(unsigned TypeIdx
, unsigned Size
);
239 /// True iff the specified type index is a scalar or a vector with an element
240 /// type that's wider than the given size.
241 LegalityPredicate
scalarOrEltWiderThan(unsigned TypeIdx
, unsigned Size
);
243 /// True iff the specified type index is a scalar whose size is not a power of
245 LegalityPredicate
sizeNotPow2(unsigned TypeIdx
);
247 /// True iff the specified type index is a scalar or vector whose element size
248 /// is not a power of 2.
249 LegalityPredicate
scalarOrEltSizeNotPow2(unsigned TypeIdx
);
251 /// True iff the specified type indices are both the same bit size.
252 LegalityPredicate
sameSize(unsigned TypeIdx0
, unsigned TypeIdx1
);
253 /// True iff the specified MMO index has a size that is not a power of 2
254 LegalityPredicate
memSizeInBytesNotPow2(unsigned MMOIdx
);
255 /// True iff the specified type index is a vector whose element count is not a
257 LegalityPredicate
numElementsNotPow2(unsigned TypeIdx
);
258 /// True iff the specified MMO index has at an atomic ordering of at Ordering or
260 LegalityPredicate
atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx
,
261 AtomicOrdering Ordering
);
262 } // end namespace LegalityPredicates
264 namespace LegalizeMutations
{
265 /// Select this specific type for the given type index.
266 LegalizeMutation
changeTo(unsigned TypeIdx
, LLT Ty
);
268 /// Keep the same type as the given type index.
269 LegalizeMutation
changeTo(unsigned TypeIdx
, unsigned FromTypeIdx
);
271 /// Keep the same scalar or element type as the given type index.
272 LegalizeMutation
changeElementTo(unsigned TypeIdx
, unsigned FromTypeIdx
);
274 /// Keep the same scalar or element type as the given type.
275 LegalizeMutation
changeElementTo(unsigned TypeIdx
, LLT Ty
);
277 /// Widen the scalar type or vector element type for the given type index to the
279 LegalizeMutation
widenScalarOrEltToNextPow2(unsigned TypeIdx
, unsigned Min
= 0);
281 /// Add more elements to the type for the given type index to the next power of
283 LegalizeMutation
moreElementsToNextPow2(unsigned TypeIdx
, unsigned Min
= 0);
284 /// Break up the vector type for the given type index into the element type.
285 LegalizeMutation
scalarize(unsigned TypeIdx
);
286 } // end namespace LegalizeMutations
288 /// A single rule in a legalizer info ruleset.
289 /// The specified action is chosen when the predicate is true. Where appropriate
290 /// for the action (e.g. for WidenScalar) the new type is selected using the
293 LegalityPredicate Predicate
;
294 LegalizeAction Action
;
295 LegalizeMutation Mutation
;
298 LegalizeRule(LegalityPredicate Predicate
, LegalizeAction Action
,
299 LegalizeMutation Mutation
= nullptr)
300 : Predicate(Predicate
), Action(Action
), Mutation(Mutation
) {}
302 /// Test whether the LegalityQuery matches.
303 bool match(const LegalityQuery
&Query
) const {
304 return Predicate(Query
);
307 LegalizeAction
getAction() const { return Action
; }
309 /// Determine the change to make.
310 std::pair
<unsigned, LLT
> determineMutation(const LegalityQuery
&Query
) const {
312 return Mutation(Query
);
313 return std::make_pair(0, LLT
{});
317 class LegalizeRuleSet
{
318 /// When non-zero, the opcode we are an alias of
320 /// If true, there is another opcode that aliases this one
321 bool IsAliasedByAnother
;
322 SmallVector
<LegalizeRule
, 2> Rules
;
325 /// If bit I is set, this rule set contains a rule that may handle (predicate
326 /// or perform an action upon (or both)) the type index I. The uncertainty
327 /// comes from free-form rules executing user-provided lambda functions. We
328 /// conservatively assume such rules do the right thing and cover all type
329 /// indices. The bitset is intentionally 1 bit wider than it absolutely needs
330 /// to be to distinguish such cases from the cases where all type indices are
331 /// individually handled.
332 SmallBitVector TypeIdxsCovered
{MCOI::OPERAND_LAST_GENERIC
-
333 MCOI::OPERAND_FIRST_GENERIC
+ 2};
336 unsigned typeIdx(unsigned TypeIdx
) {
338 (MCOI::OPERAND_LAST_GENERIC
- MCOI::OPERAND_FIRST_GENERIC
) &&
339 "Type Index is out of bounds");
341 TypeIdxsCovered
.set(TypeIdx
);
345 void markAllTypeIdxsAsCovered() {
347 TypeIdxsCovered
.set();
351 void add(const LegalizeRule
&Rule
) {
352 assert(AliasOf
== 0 &&
353 "RuleSet is aliased, change the representative opcode instead");
354 Rules
.push_back(Rule
);
357 static bool always(const LegalityQuery
&) { return true; }
359 /// Use the given action when the predicate is true.
360 /// Action should not be an action that requires mutation.
361 LegalizeRuleSet
&actionIf(LegalizeAction Action
,
362 LegalityPredicate Predicate
) {
363 add({Predicate
, Action
});
366 /// Use the given action when the predicate is true.
367 /// Action should be an action that requires mutation.
368 LegalizeRuleSet
&actionIf(LegalizeAction Action
, LegalityPredicate Predicate
,
369 LegalizeMutation Mutation
) {
370 add({Predicate
, Action
, Mutation
});
373 /// Use the given action when type index 0 is any type in the given list.
374 /// Action should not be an action that requires mutation.
375 LegalizeRuleSet
&actionFor(LegalizeAction Action
,
376 std::initializer_list
<LLT
> Types
) {
377 using namespace LegalityPredicates
;
378 return actionIf(Action
, typeInSet(typeIdx(0), Types
));
380 /// Use the given action when type index 0 is any type in the given list.
381 /// Action should be an action that requires mutation.
382 LegalizeRuleSet
&actionFor(LegalizeAction Action
,
383 std::initializer_list
<LLT
> Types
,
384 LegalizeMutation Mutation
) {
385 using namespace LegalityPredicates
;
386 return actionIf(Action
, typeInSet(typeIdx(0), Types
), Mutation
);
388 /// Use the given action when type indexes 0 and 1 is any type pair in the
390 /// Action should not be an action that requires mutation.
391 LegalizeRuleSet
&actionFor(LegalizeAction Action
,
392 std::initializer_list
<std::pair
<LLT
, LLT
>> Types
) {
393 using namespace LegalityPredicates
;
394 return actionIf(Action
, typePairInSet(typeIdx(0), typeIdx(1), Types
));
396 /// Use the given action when type indexes 0 and 1 is any type pair in the
398 /// Action should be an action that requires mutation.
399 LegalizeRuleSet
&actionFor(LegalizeAction Action
,
400 std::initializer_list
<std::pair
<LLT
, LLT
>> Types
,
401 LegalizeMutation Mutation
) {
402 using namespace LegalityPredicates
;
403 return actionIf(Action
, typePairInSet(typeIdx(0), typeIdx(1), Types
),
406 /// Use the given action when type indexes 0 and 1 are both in the given list.
407 /// That is, the type pair is in the cartesian product of the list.
408 /// Action should not be an action that requires mutation.
409 LegalizeRuleSet
&actionForCartesianProduct(LegalizeAction Action
,
410 std::initializer_list
<LLT
> Types
) {
411 using namespace LegalityPredicates
;
412 return actionIf(Action
, all(typeInSet(typeIdx(0), Types
),
413 typeInSet(typeIdx(1), Types
)));
415 /// Use the given action when type indexes 0 and 1 are both in their
416 /// respective lists.
417 /// That is, the type pair is in the cartesian product of the lists
418 /// Action should not be an action that requires mutation.
420 actionForCartesianProduct(LegalizeAction Action
,
421 std::initializer_list
<LLT
> Types0
,
422 std::initializer_list
<LLT
> Types1
) {
423 using namespace LegalityPredicates
;
424 return actionIf(Action
, all(typeInSet(typeIdx(0), Types0
),
425 typeInSet(typeIdx(1), Types1
)));
427 /// Use the given action when type indexes 0, 1, and 2 are all in their
428 /// respective lists.
429 /// That is, the type triple is in the cartesian product of the lists
430 /// Action should not be an action that requires mutation.
431 LegalizeRuleSet
&actionForCartesianProduct(
432 LegalizeAction Action
, std::initializer_list
<LLT
> Types0
,
433 std::initializer_list
<LLT
> Types1
, std::initializer_list
<LLT
> Types2
) {
434 using namespace LegalityPredicates
;
435 return actionIf(Action
, all(typeInSet(typeIdx(0), Types0
),
436 all(typeInSet(typeIdx(1), Types1
),
437 typeInSet(typeIdx(2), Types2
))));
441 LegalizeRuleSet() : AliasOf(0), IsAliasedByAnother(false), Rules() {}
443 bool isAliasedByAnother() { return IsAliasedByAnother
; }
444 void setIsAliasedByAnother() { IsAliasedByAnother
= true; }
445 void aliasTo(unsigned Opcode
) {
446 assert((AliasOf
== 0 || AliasOf
== Opcode
) &&
447 "Opcode is already aliased to another opcode");
448 assert(Rules
.empty() && "Aliasing will discard rules");
451 unsigned getAlias() const { return AliasOf
; }
453 /// The instruction is legal if predicate is true.
454 LegalizeRuleSet
&legalIf(LegalityPredicate Predicate
) {
455 // We have no choice but conservatively assume that the free-form
456 // user-provided Predicate properly handles all type indices:
457 markAllTypeIdxsAsCovered();
458 return actionIf(LegalizeAction::Legal
, Predicate
);
460 /// The instruction is legal when type index 0 is any type in the given list.
461 LegalizeRuleSet
&legalFor(std::initializer_list
<LLT
> Types
) {
462 return actionFor(LegalizeAction::Legal
, Types
);
464 /// The instruction is legal when type indexes 0 and 1 is any type pair in the
466 LegalizeRuleSet
&legalFor(std::initializer_list
<std::pair
<LLT
, LLT
>> Types
) {
467 return actionFor(LegalizeAction::Legal
, Types
);
469 /// The instruction is legal when type indexes 0 and 1 along with the memory
470 /// size and minimum alignment is any type and size tuple in the given list.
471 LegalizeRuleSet
&legalForTypesWithMemDesc(
472 std::initializer_list
<LegalityPredicates::TypePairAndMemDesc
>
474 return actionIf(LegalizeAction::Legal
,
475 LegalityPredicates::typePairAndMemDescInSet(
476 typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemDesc
));
478 /// The instruction is legal when type indexes 0 and 1 are both in the given
479 /// list. That is, the type pair is in the cartesian product of the list.
480 LegalizeRuleSet
&legalForCartesianProduct(std::initializer_list
<LLT
> Types
) {
481 return actionForCartesianProduct(LegalizeAction::Legal
, Types
);
483 /// The instruction is legal when type indexes 0 and 1 are both their
484 /// respective lists.
485 LegalizeRuleSet
&legalForCartesianProduct(std::initializer_list
<LLT
> Types0
,
486 std::initializer_list
<LLT
> Types1
) {
487 return actionForCartesianProduct(LegalizeAction::Legal
, Types0
, Types1
);
489 /// The instruction is legal when type indexes 0, 1, and 2 are both their
490 /// respective lists.
491 LegalizeRuleSet
&legalForCartesianProduct(std::initializer_list
<LLT
> Types0
,
492 std::initializer_list
<LLT
> Types1
,
493 std::initializer_list
<LLT
> Types2
) {
494 return actionForCartesianProduct(LegalizeAction::Legal
, Types0
, Types1
,
498 LegalizeRuleSet
&alwaysLegal() {
499 using namespace LegalizeMutations
;
500 markAllTypeIdxsAsCovered();
501 return actionIf(LegalizeAction::Legal
, always
);
504 /// The instruction is lowered.
505 LegalizeRuleSet
&lower() {
506 using namespace LegalizeMutations
;
507 // We have no choice but conservatively assume that predicate-less lowering
508 // properly handles all type indices by design:
509 markAllTypeIdxsAsCovered();
510 return actionIf(LegalizeAction::Lower
, always
);
512 /// The instruction is lowered if predicate is true. Keep type index 0 as the
514 LegalizeRuleSet
&lowerIf(LegalityPredicate Predicate
) {
515 using namespace LegalizeMutations
;
516 // We have no choice but conservatively assume that lowering with a
517 // free-form user provided Predicate properly handles all type indices:
518 markAllTypeIdxsAsCovered();
519 return actionIf(LegalizeAction::Lower
, Predicate
);
521 /// The instruction is lowered if predicate is true.
522 LegalizeRuleSet
&lowerIf(LegalityPredicate Predicate
,
523 LegalizeMutation Mutation
) {
524 // We have no choice but conservatively assume that lowering with a
525 // free-form user provided Predicate properly handles all type indices:
526 markAllTypeIdxsAsCovered();
527 return actionIf(LegalizeAction::Lower
, Predicate
, Mutation
);
529 /// The instruction is lowered when type index 0 is any type in the given
530 /// list. Keep type index 0 as the same type.
531 LegalizeRuleSet
&lowerFor(std::initializer_list
<LLT
> Types
) {
532 return actionFor(LegalizeAction::Lower
, Types
,
533 LegalizeMutations::changeTo(0, 0));
535 /// The instruction is lowered when type index 0 is any type in the given
537 LegalizeRuleSet
&lowerFor(std::initializer_list
<LLT
> Types
,
538 LegalizeMutation Mutation
) {
539 return actionFor(LegalizeAction::Lower
, Types
, Mutation
);
541 /// The instruction is lowered when type indexes 0 and 1 is any type pair in
542 /// the given list. Keep type index 0 as the same type.
543 LegalizeRuleSet
&lowerFor(std::initializer_list
<std::pair
<LLT
, LLT
>> Types
) {
544 return actionFor(LegalizeAction::Lower
, Types
,
545 LegalizeMutations::changeTo(0, 0));
547 /// The instruction is lowered when type indexes 0 and 1 is any type pair in
549 LegalizeRuleSet
&lowerFor(std::initializer_list
<std::pair
<LLT
, LLT
>> Types
,
550 LegalizeMutation Mutation
) {
551 return actionFor(LegalizeAction::Lower
, Types
, Mutation
);
553 /// The instruction is lowered when type indexes 0 and 1 are both in their
554 /// respective lists.
555 LegalizeRuleSet
&lowerForCartesianProduct(std::initializer_list
<LLT
> Types0
,
556 std::initializer_list
<LLT
> Types1
) {
557 using namespace LegalityPredicates
;
558 return actionForCartesianProduct(LegalizeAction::Lower
, Types0
, Types1
);
560 /// The instruction is lowered when when type indexes 0, 1, and 2 are all in
561 /// their respective lists.
562 LegalizeRuleSet
&lowerForCartesianProduct(std::initializer_list
<LLT
> Types0
,
563 std::initializer_list
<LLT
> Types1
,
564 std::initializer_list
<LLT
> Types2
) {
565 using namespace LegalityPredicates
;
566 return actionForCartesianProduct(LegalizeAction::Lower
, Types0
, Types1
,
570 /// Like legalIf, but for the Libcall action.
571 LegalizeRuleSet
&libcallIf(LegalityPredicate Predicate
) {
572 // We have no choice but conservatively assume that a libcall with a
573 // free-form user provided Predicate properly handles all type indices:
574 markAllTypeIdxsAsCovered();
575 return actionIf(LegalizeAction::Libcall
, Predicate
);
577 LegalizeRuleSet
&libcallFor(std::initializer_list
<LLT
> Types
) {
578 return actionFor(LegalizeAction::Libcall
, Types
);
581 libcallFor(std::initializer_list
<std::pair
<LLT
, LLT
>> Types
) {
582 return actionFor(LegalizeAction::Libcall
, Types
);
585 libcallForCartesianProduct(std::initializer_list
<LLT
> Types
) {
586 return actionForCartesianProduct(LegalizeAction::Libcall
, Types
);
589 libcallForCartesianProduct(std::initializer_list
<LLT
> Types0
,
590 std::initializer_list
<LLT
> Types1
) {
591 return actionForCartesianProduct(LegalizeAction::Libcall
, Types0
, Types1
);
594 /// Widen the scalar to the one selected by the mutation if the predicate is
596 LegalizeRuleSet
&widenScalarIf(LegalityPredicate Predicate
,
597 LegalizeMutation Mutation
) {
598 // We have no choice but conservatively assume that an action with a
599 // free-form user provided Predicate properly handles all type indices:
600 markAllTypeIdxsAsCovered();
601 return actionIf(LegalizeAction::WidenScalar
, Predicate
, Mutation
);
603 /// Narrow the scalar to the one selected by the mutation if the predicate is
605 LegalizeRuleSet
&narrowScalarIf(LegalityPredicate Predicate
,
606 LegalizeMutation Mutation
) {
607 // We have no choice but conservatively assume that an action with a
608 // free-form user provided Predicate properly handles all type indices:
609 markAllTypeIdxsAsCovered();
610 return actionIf(LegalizeAction::NarrowScalar
, Predicate
, Mutation
);
613 /// Add more elements to reach the type selected by the mutation if the
614 /// predicate is true.
615 LegalizeRuleSet
&moreElementsIf(LegalityPredicate Predicate
,
616 LegalizeMutation Mutation
) {
617 // We have no choice but conservatively assume that an action with a
618 // free-form user provided Predicate properly handles all type indices:
619 markAllTypeIdxsAsCovered();
620 return actionIf(LegalizeAction::MoreElements
, Predicate
, Mutation
);
622 /// Remove elements to reach the type selected by the mutation if the
623 /// predicate is true.
624 LegalizeRuleSet
&fewerElementsIf(LegalityPredicate Predicate
,
625 LegalizeMutation Mutation
) {
626 // We have no choice but conservatively assume that an action with a
627 // free-form user provided Predicate properly handles all type indices:
628 markAllTypeIdxsAsCovered();
629 return actionIf(LegalizeAction::FewerElements
, Predicate
, Mutation
);
632 /// The instruction is unsupported.
633 LegalizeRuleSet
&unsupported() {
634 return actionIf(LegalizeAction::Unsupported
, always
);
636 LegalizeRuleSet
&unsupportedIf(LegalityPredicate Predicate
) {
637 return actionIf(LegalizeAction::Unsupported
, Predicate
);
639 LegalizeRuleSet
&unsupportedIfMemSizeNotPow2() {
640 return actionIf(LegalizeAction::Unsupported
,
641 LegalityPredicates::memSizeInBytesNotPow2(0));
644 LegalizeRuleSet
&customIf(LegalityPredicate Predicate
) {
645 // We have no choice but conservatively assume that a custom action with a
646 // free-form user provided Predicate properly handles all type indices:
647 markAllTypeIdxsAsCovered();
648 return actionIf(LegalizeAction::Custom
, Predicate
);
650 LegalizeRuleSet
&customFor(std::initializer_list
<LLT
> Types
) {
651 return actionFor(LegalizeAction::Custom
, Types
);
654 /// The instruction is custom when type indexes 0 and 1 is any type pair in the
656 LegalizeRuleSet
&customFor(std::initializer_list
<std::pair
<LLT
, LLT
>> Types
) {
657 return actionFor(LegalizeAction::Custom
, Types
);
660 LegalizeRuleSet
&customForCartesianProduct(std::initializer_list
<LLT
> Types
) {
661 return actionForCartesianProduct(LegalizeAction::Custom
, Types
);
664 customForCartesianProduct(std::initializer_list
<LLT
> Types0
,
665 std::initializer_list
<LLT
> Types1
) {
666 return actionForCartesianProduct(LegalizeAction::Custom
, Types0
, Types1
);
669 /// Unconditionally custom lower.
670 LegalizeRuleSet
&custom() {
671 return customIf(always
);
674 /// Widen the scalar to the next power of two that is at least MinSize.
675 /// No effect if the type is not a scalar or is a power of two.
676 LegalizeRuleSet
&widenScalarToNextPow2(unsigned TypeIdx
,
677 unsigned MinSize
= 0) {
678 using namespace LegalityPredicates
;
680 LegalizeAction::WidenScalar
, sizeNotPow2(typeIdx(TypeIdx
)),
681 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx
, MinSize
));
684 /// Widen the scalar or vector element type to the next power of two that is
685 /// at least MinSize. No effect if the scalar size is a power of two.
686 LegalizeRuleSet
&widenScalarOrEltToNextPow2(unsigned TypeIdx
,
687 unsigned MinSize
= 0) {
688 using namespace LegalityPredicates
;
690 LegalizeAction::WidenScalar
, scalarOrEltSizeNotPow2(typeIdx(TypeIdx
)),
691 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx
, MinSize
));
694 LegalizeRuleSet
&narrowScalar(unsigned TypeIdx
, LegalizeMutation Mutation
) {
695 using namespace LegalityPredicates
;
696 return actionIf(LegalizeAction::NarrowScalar
, isScalar(typeIdx(TypeIdx
)),
700 LegalizeRuleSet
&scalarize(unsigned TypeIdx
) {
701 using namespace LegalityPredicates
;
702 return actionIf(LegalizeAction::FewerElements
, isVector(typeIdx(TypeIdx
)),
703 LegalizeMutations::scalarize(TypeIdx
));
706 /// Ensure the scalar or element is at least as wide as Ty.
707 LegalizeRuleSet
&minScalarOrElt(unsigned TypeIdx
, const LLT
&Ty
) {
708 using namespace LegalityPredicates
;
709 using namespace LegalizeMutations
;
710 return actionIf(LegalizeAction::WidenScalar
,
711 scalarOrEltNarrowerThan(TypeIdx
, Ty
.getScalarSizeInBits()),
712 changeElementTo(typeIdx(TypeIdx
), Ty
));
715 /// Ensure the scalar or element is at least as wide as Ty.
716 LegalizeRuleSet
&minScalarOrEltIf(LegalityPredicate Predicate
,
717 unsigned TypeIdx
, const LLT
&Ty
) {
718 using namespace LegalityPredicates
;
719 using namespace LegalizeMutations
;
720 return actionIf(LegalizeAction::WidenScalar
,
721 all(Predicate
, scalarOrEltNarrowerThan(
722 TypeIdx
, Ty
.getScalarSizeInBits())),
723 changeElementTo(typeIdx(TypeIdx
), Ty
));
726 /// Ensure the scalar is at least as wide as Ty.
727 LegalizeRuleSet
&minScalar(unsigned TypeIdx
, const LLT
&Ty
) {
728 using namespace LegalityPredicates
;
729 using namespace LegalizeMutations
;
730 return actionIf(LegalizeAction::WidenScalar
,
731 narrowerThan(TypeIdx
, Ty
.getSizeInBits()),
732 changeTo(typeIdx(TypeIdx
), Ty
));
735 /// Ensure the scalar is at most as wide as Ty.
736 LegalizeRuleSet
&maxScalarOrElt(unsigned TypeIdx
, const LLT
&Ty
) {
737 using namespace LegalityPredicates
;
738 using namespace LegalizeMutations
;
739 return actionIf(LegalizeAction::NarrowScalar
,
740 scalarOrEltWiderThan(TypeIdx
, Ty
.getScalarSizeInBits()),
741 changeElementTo(typeIdx(TypeIdx
), Ty
));
744 /// Ensure the scalar is at most as wide as Ty.
745 LegalizeRuleSet
&maxScalar(unsigned TypeIdx
, const LLT
&Ty
) {
746 using namespace LegalityPredicates
;
747 using namespace LegalizeMutations
;
748 return actionIf(LegalizeAction::NarrowScalar
,
749 widerThan(TypeIdx
, Ty
.getSizeInBits()),
750 changeTo(typeIdx(TypeIdx
), Ty
));
753 /// Conditionally limit the maximum size of the scalar.
754 /// For example, when the maximum size of one type depends on the size of
755 /// another such as extracting N bits from an M bit container.
756 LegalizeRuleSet
&maxScalarIf(LegalityPredicate Predicate
, unsigned TypeIdx
,
758 using namespace LegalityPredicates
;
759 using namespace LegalizeMutations
;
761 LegalizeAction::NarrowScalar
,
762 [=](const LegalityQuery
&Query
) {
763 return widerThan(TypeIdx
, Ty
.getSizeInBits()) && Predicate(Query
);
765 changeElementTo(typeIdx(TypeIdx
), Ty
));
768 /// Limit the range of scalar sizes to MinTy and MaxTy.
769 LegalizeRuleSet
&clampScalar(unsigned TypeIdx
, const LLT
&MinTy
,
771 assert(MinTy
.isScalar() && MaxTy
.isScalar() && "Expected scalar types");
772 return minScalar(TypeIdx
, MinTy
).maxScalar(TypeIdx
, MaxTy
);
775 /// Limit the range of scalar sizes to MinTy and MaxTy.
776 LegalizeRuleSet
&clampScalarOrElt(unsigned TypeIdx
, const LLT
&MinTy
,
778 return minScalarOrElt(TypeIdx
, MinTy
).maxScalarOrElt(TypeIdx
, MaxTy
);
781 /// Widen the scalar to match the size of another.
782 LegalizeRuleSet
&minScalarSameAs(unsigned TypeIdx
, unsigned LargeTypeIdx
) {
784 return widenScalarIf(
785 [=](const LegalityQuery
&Query
) {
786 return Query
.Types
[LargeTypeIdx
].getScalarSizeInBits() >
787 Query
.Types
[TypeIdx
].getSizeInBits();
789 [=](const LegalityQuery
&Query
) {
790 LLT T
= Query
.Types
[LargeTypeIdx
];
791 return std::make_pair(TypeIdx
,
792 T
.isVector() ? T
.getElementType() : T
);
796 /// Conditionally widen the scalar or elt to match the size of another.
797 LegalizeRuleSet
&minScalarEltSameAsIf(LegalityPredicate Predicate
,
798 unsigned TypeIdx
, unsigned LargeTypeIdx
) {
800 return widenScalarIf(
801 [=](const LegalityQuery
&Query
) {
802 return Query
.Types
[LargeTypeIdx
].getScalarSizeInBits() >
803 Query
.Types
[TypeIdx
].getScalarSizeInBits() &&
806 [=](const LegalityQuery
&Query
) {
807 LLT T
= Query
.Types
[LargeTypeIdx
];
808 return std::make_pair(TypeIdx
, T
);
812 /// Add more elements to the vector to reach the next power of two.
813 /// No effect if the type is not a vector or the element count is a power of
815 LegalizeRuleSet
&moreElementsToNextPow2(unsigned TypeIdx
) {
816 using namespace LegalityPredicates
;
817 return actionIf(LegalizeAction::MoreElements
,
818 numElementsNotPow2(typeIdx(TypeIdx
)),
819 LegalizeMutations::moreElementsToNextPow2(TypeIdx
));
822 /// Limit the number of elements in EltTy vectors to at least MinElements.
823 LegalizeRuleSet
&clampMinNumElements(unsigned TypeIdx
, const LLT
&EltTy
,
824 unsigned MinElements
) {
825 // Mark the type index as covered:
828 LegalizeAction::MoreElements
,
829 [=](const LegalityQuery
&Query
) {
830 LLT VecTy
= Query
.Types
[TypeIdx
];
831 return VecTy
.isVector() && VecTy
.getElementType() == EltTy
&&
832 VecTy
.getNumElements() < MinElements
;
834 [=](const LegalityQuery
&Query
) {
835 LLT VecTy
= Query
.Types
[TypeIdx
];
836 return std::make_pair(
837 TypeIdx
, LLT::vector(MinElements
, VecTy
.getElementType()));
840 /// Limit the number of elements in EltTy vectors to at most MaxElements.
841 LegalizeRuleSet
&clampMaxNumElements(unsigned TypeIdx
, const LLT
&EltTy
,
842 unsigned MaxElements
) {
843 // Mark the type index as covered:
846 LegalizeAction::FewerElements
,
847 [=](const LegalityQuery
&Query
) {
848 LLT VecTy
= Query
.Types
[TypeIdx
];
849 return VecTy
.isVector() && VecTy
.getElementType() == EltTy
&&
850 VecTy
.getNumElements() > MaxElements
;
852 [=](const LegalityQuery
&Query
) {
853 LLT VecTy
= Query
.Types
[TypeIdx
];
854 LLT NewTy
= LLT::scalarOrVector(MaxElements
, VecTy
.getElementType());
855 return std::make_pair(TypeIdx
, NewTy
);
858 /// Limit the number of elements for the given vectors to at least MinTy's
859 /// number of elements and at most MaxTy's number of elements.
861 /// No effect if the type is not a vector or does not have the same element
862 /// type as the constraints.
863 /// The element type of MinTy and MaxTy must match.
864 LegalizeRuleSet
&clampNumElements(unsigned TypeIdx
, const LLT
&MinTy
,
866 assert(MinTy
.getElementType() == MaxTy
.getElementType() &&
867 "Expected element types to agree");
869 const LLT
&EltTy
= MinTy
.getElementType();
870 return clampMinNumElements(TypeIdx
, EltTy
, MinTy
.getNumElements())
871 .clampMaxNumElements(TypeIdx
, EltTy
, MaxTy
.getNumElements());
874 /// Fallback on the previous implementation. This should only be used while
876 LegalizeRuleSet
&fallback() {
877 add({always
, LegalizeAction::UseLegacyRules
});
881 /// Check if there is no type index which is obviously not handled by the
882 /// LegalizeRuleSet in any way at all.
883 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set.
884 bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs
) const;
886 /// Apply the ruleset to the given LegalityQuery.
887 LegalizeActionStep
apply(const LegalityQuery
&Query
) const;
890 class LegalizerInfo
{
893 virtual ~LegalizerInfo() = default;
895 unsigned getOpcodeIdxForOpcode(unsigned Opcode
) const;
896 unsigned getActionDefinitionsIdx(unsigned Opcode
) const;
898 /// Compute any ancillary tables needed to quickly decide how an operation
899 /// should be handled. This must be called after all "set*Action"methods but
900 /// before any query is made or incorrect results may be returned.
901 void computeTables();
903 /// Perform simple self-diagnostic and assert if there is anything obviously
904 /// wrong with the actions set up.
905 void verify(const MCInstrInfo
&MII
) const;
907 static bool needsLegalizingToDifferentSize(const LegalizeAction Action
) {
908 using namespace LegalizeActions
;
921 using SizeAndAction
= std::pair
<uint16_t, LegalizeAction
>;
922 using SizeAndActionsVec
= std::vector
<SizeAndAction
>;
923 using SizeChangeStrategy
=
924 std::function
<SizeAndActionsVec(const SizeAndActionsVec
&v
)>;
926 /// More friendly way to set an action for common types that have an LLT
928 /// The LegalizeAction must be one for which NeedsLegalizingToDifferentSize
930 void setAction(const InstrAspect
&Aspect
, LegalizeAction Action
) {
931 assert(!needsLegalizingToDifferentSize(Action
));
932 TablesInitialized
= false;
933 const unsigned OpcodeIdx
= Aspect
.Opcode
- FirstOp
;
934 if (SpecifiedActions
[OpcodeIdx
].size() <= Aspect
.Idx
)
935 SpecifiedActions
[OpcodeIdx
].resize(Aspect
.Idx
+ 1);
936 SpecifiedActions
[OpcodeIdx
][Aspect
.Idx
][Aspect
.Type
] = Action
;
939 /// The setAction calls record the non-size-changing legalization actions
940 /// to take on specificly-sized types. The SizeChangeStrategy defines what
941 /// to do when the size of the type needs to be changed to reach a legally
942 /// sized type (i.e., one that was defined through a setAction call).
944 /// setAction ({G_ADD, 0, LLT::scalar(32)}, Legal);
945 /// setLegalizeScalarToDifferentSizeStrategy(
946 /// G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
947 /// will end up defining getAction({G_ADD, 0, T}) to return the following
948 /// actions for different scalar types T:
949 /// LLT::scalar(1)..LLT::scalar(31): {WidenScalar, 0, LLT::scalar(32)}
950 /// LLT::scalar(32): {Legal, 0, LLT::scalar(32)}
951 /// LLT::scalar(33)..: {NarrowScalar, 0, LLT::scalar(32)}
953 /// If no SizeChangeAction gets defined, through this function,
954 /// the default is unsupportedForDifferentSizes.
955 void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode
,
956 const unsigned TypeIdx
,
957 SizeChangeStrategy S
) {
958 const unsigned OpcodeIdx
= Opcode
- FirstOp
;
959 if (ScalarSizeChangeStrategies
[OpcodeIdx
].size() <= TypeIdx
)
960 ScalarSizeChangeStrategies
[OpcodeIdx
].resize(TypeIdx
+ 1);
961 ScalarSizeChangeStrategies
[OpcodeIdx
][TypeIdx
] = S
;
964 /// See also setLegalizeScalarToDifferentSizeStrategy.
965 /// This function allows to set the SizeChangeStrategy for vector elements.
966 void setLegalizeVectorElementToDifferentSizeStrategy(const unsigned Opcode
,
967 const unsigned TypeIdx
,
968 SizeChangeStrategy S
) {
969 const unsigned OpcodeIdx
= Opcode
- FirstOp
;
970 if (VectorElementSizeChangeStrategies
[OpcodeIdx
].size() <= TypeIdx
)
971 VectorElementSizeChangeStrategies
[OpcodeIdx
].resize(TypeIdx
+ 1);
972 VectorElementSizeChangeStrategies
[OpcodeIdx
][TypeIdx
] = S
;
975 /// A SizeChangeStrategy for the common case where legalization for a
976 /// particular operation consists of only supporting a specific set of type
978 /// setAction ({G_DIV, 0, LLT::scalar(32)}, Legal);
979 /// setAction ({G_DIV, 0, LLT::scalar(64)}, Legal);
980 /// setLegalizeScalarToDifferentSizeStrategy(
981 /// G_DIV, 0, unsupportedForDifferentSizes);
982 /// will result in getAction({G_DIV, 0, T}) to return Legal for s32 and s64,
983 /// and Unsupported for all other scalar types T.
984 static SizeAndActionsVec
985 unsupportedForDifferentSizes(const SizeAndActionsVec
&v
) {
986 using namespace LegalizeActions
;
987 return increaseToLargerTypesAndDecreaseToLargest(v
, Unsupported
,
991 /// A SizeChangeStrategy for the common case where legalization for a
992 /// particular operation consists of widening the type to a large legal type,
993 /// unless there is no such type and then instead it should be narrowed to the
994 /// largest legal type.
995 static SizeAndActionsVec
996 widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec
&v
) {
997 using namespace LegalizeActions
;
998 assert(v
.size() > 0 &&
999 "At least one size that can be legalized towards is needed"
1000 " for this SizeChangeStrategy");
1001 return increaseToLargerTypesAndDecreaseToLargest(v
, WidenScalar
,
1005 static SizeAndActionsVec
1006 widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec
&v
) {
1007 using namespace LegalizeActions
;
1008 return increaseToLargerTypesAndDecreaseToLargest(v
, WidenScalar
,
1012 static SizeAndActionsVec
1013 narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec
&v
) {
1014 using namespace LegalizeActions
;
1015 return decreaseToSmallerTypesAndIncreaseToSmallest(v
, NarrowScalar
,
1019 static SizeAndActionsVec
1020 narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec
&v
) {
1021 using namespace LegalizeActions
;
1022 assert(v
.size() > 0 &&
1023 "At least one size that can be legalized towards is needed"
1024 " for this SizeChangeStrategy");
1025 return decreaseToSmallerTypesAndIncreaseToSmallest(v
, NarrowScalar
,
1029 /// A SizeChangeStrategy for the common case where legalization for a
1030 /// particular vector operation consists of having more elements in the
1031 /// vector, to a type that is legal. Unless there is no such type and then
1032 /// instead it should be legalized towards the widest vector that's still
1034 /// setAction({G_ADD, LLT::vector(8, 8)}, Legal);
1035 /// setAction({G_ADD, LLT::vector(16, 8)}, Legal);
1036 /// setAction({G_ADD, LLT::vector(2, 32)}, Legal);
1037 /// setAction({G_ADD, LLT::vector(4, 32)}, Legal);
1038 /// setLegalizeVectorElementToDifferentSizeStrategy(
1039 /// G_ADD, 0, moreToWiderTypesAndLessToWidest);
1040 /// will result in the following getAction results:
1041 /// * getAction({G_ADD, LLT::vector(8,8)}) returns
1042 /// (Legal, vector(8,8)).
1043 /// * getAction({G_ADD, LLT::vector(9,8)}) returns
1044 /// (MoreElements, vector(16,8)).
1045 /// * getAction({G_ADD, LLT::vector(8,32)}) returns
1046 /// (FewerElements, vector(4,32)).
1047 static SizeAndActionsVec
1048 moreToWiderTypesAndLessToWidest(const SizeAndActionsVec
&v
) {
1049 using namespace LegalizeActions
;
1050 return increaseToLargerTypesAndDecreaseToLargest(v
, MoreElements
,
1054 /// Helper function to implement many typical SizeChangeStrategy functions.
1055 static SizeAndActionsVec
1056 increaseToLargerTypesAndDecreaseToLargest(const SizeAndActionsVec
&v
,
1057 LegalizeAction IncreaseAction
,
1058 LegalizeAction DecreaseAction
);
1059 /// Helper function to implement many typical SizeChangeStrategy functions.
1060 static SizeAndActionsVec
1061 decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec
&v
,
1062 LegalizeAction DecreaseAction
,
1063 LegalizeAction IncreaseAction
);
1065 /// Get the action definitions for the given opcode. Use this to run a
1066 /// LegalityQuery through the definitions.
1067 const LegalizeRuleSet
&getActionDefinitions(unsigned Opcode
) const;
1069 /// Get the action definition builder for the given opcode. Use this to define
1070 /// the action definitions.
1072 /// It is an error to request an opcode that has already been requested by the
1073 /// multiple-opcode variant.
1074 LegalizeRuleSet
&getActionDefinitionsBuilder(unsigned Opcode
);
1076 /// Get the action definition builder for the given set of opcodes. Use this
1077 /// to define the action definitions for multiple opcodes at once. The first
1078 /// opcode given will be considered the representative opcode and will hold
1079 /// the definitions whereas the other opcodes will be configured to refer to
1080 /// the representative opcode. This lowers memory requirements and very
1081 /// slightly improves performance.
1083 /// It would be very easy to introduce unexpected side-effects as a result of
1084 /// this aliasing if it were permitted to request different but intersecting
1085 /// sets of opcodes but that is difficult to keep track of. It is therefore an
1086 /// error to request the same opcode twice using this API, to request an
1087 /// opcode that already has definitions, or to use the single-opcode API on an
1088 /// opcode that has already been requested by this API.
1090 getActionDefinitionsBuilder(std::initializer_list
<unsigned> Opcodes
);
1091 void aliasActionDefinitions(unsigned OpcodeTo
, unsigned OpcodeFrom
);
1093 /// Determine what action should be taken to legalize the described
1094 /// instruction. Requires computeTables to have been called.
1096 /// \returns a description of the next legalization step to perform.
1097 LegalizeActionStep
getAction(const LegalityQuery
&Query
) const;
1099 /// Determine what action should be taken to legalize the given generic
1102 /// \returns a description of the next legalization step to perform.
1103 LegalizeActionStep
getAction(const MachineInstr
&MI
,
1104 const MachineRegisterInfo
&MRI
) const;
1106 bool isLegal(const LegalityQuery
&Query
) const {
1107 return getAction(Query
).Action
== LegalizeAction::Legal
;
1109 bool isLegal(const MachineInstr
&MI
, const MachineRegisterInfo
&MRI
) const;
1110 bool isLegalOrCustom(const MachineInstr
&MI
,
1111 const MachineRegisterInfo
&MRI
) const;
1113 virtual bool legalizeCustom(MachineInstr
&MI
, MachineRegisterInfo
&MRI
,
1114 MachineIRBuilder
&MIRBuilder
,
1115 GISelChangeObserver
&Observer
) const;
1117 /// Return true if MI is either legal or has been legalized and false
1119 virtual bool legalizeIntrinsic(MachineInstr
&MI
, MachineRegisterInfo
&MRI
,
1120 MachineIRBuilder
&MIRBuilder
) const;
1123 /// Determine what action should be taken to legalize the given generic
1124 /// instruction opcode, type-index and type. Requires computeTables to have
1127 /// \returns a pair consisting of the kind of legalization that should be
1128 /// performed and the destination type.
1129 std::pair
<LegalizeAction
, LLT
>
1130 getAspectAction(const InstrAspect
&Aspect
) const;
1132 /// The SizeAndActionsVec is a representation mapping between all natural
1133 /// numbers and an Action. The natural number represents the bit size of
1134 /// the InstrAspect. For example, for a target with native support for 32-bit
1135 /// and 64-bit additions, you'd express that as:
1136 /// setScalarAction(G_ADD, 0,
1137 /// {{1, WidenScalar}, // bit sizes [ 1, 31[
1138 /// {32, Legal}, // bit sizes [32, 33[
1139 /// {33, WidenScalar}, // bit sizes [33, 64[
1140 /// {64, Legal}, // bit sizes [64, 65[
1141 /// {65, NarrowScalar} // bit sizes [65, +inf[
1143 /// It may be that only 64-bit pointers are supported on your target:
1144 /// setPointerAction(G_GEP, 0, LLT:pointer(1),
1145 /// {{1, Unsupported}, // bit sizes [ 1, 63[
1146 /// {64, Legal}, // bit sizes [64, 65[
1147 /// {65, Unsupported}, // bit sizes [65, +inf[
1149 void setScalarAction(const unsigned Opcode
, const unsigned TypeIndex
,
1150 const SizeAndActionsVec
&SizeAndActions
) {
1151 const unsigned OpcodeIdx
= Opcode
- FirstOp
;
1152 SmallVector
<SizeAndActionsVec
, 1> &Actions
= ScalarActions
[OpcodeIdx
];
1153 setActions(TypeIndex
, Actions
, SizeAndActions
);
1155 void setPointerAction(const unsigned Opcode
, const unsigned TypeIndex
,
1156 const unsigned AddressSpace
,
1157 const SizeAndActionsVec
&SizeAndActions
) {
1158 const unsigned OpcodeIdx
= Opcode
- FirstOp
;
1159 if (AddrSpace2PointerActions
[OpcodeIdx
].find(AddressSpace
) ==
1160 AddrSpace2PointerActions
[OpcodeIdx
].end())
1161 AddrSpace2PointerActions
[OpcodeIdx
][AddressSpace
] = {{}};
1162 SmallVector
<SizeAndActionsVec
, 1> &Actions
=
1163 AddrSpace2PointerActions
[OpcodeIdx
].find(AddressSpace
)->second
;
1164 setActions(TypeIndex
, Actions
, SizeAndActions
);
1167 /// If an operation on a given vector type (say <M x iN>) isn't explicitly
1168 /// specified, we proceed in 2 stages. First we legalize the underlying scalar
1169 /// (so that there's at least one legal vector with that scalar), then we
1170 /// adjust the number of elements in the vector so that it is legal. The
1171 /// desired action in the first step is controlled by this function.
1172 void setScalarInVectorAction(const unsigned Opcode
, const unsigned TypeIndex
,
1173 const SizeAndActionsVec
&SizeAndActions
) {
1174 unsigned OpcodeIdx
= Opcode
- FirstOp
;
1175 SmallVector
<SizeAndActionsVec
, 1> &Actions
=
1176 ScalarInVectorActions
[OpcodeIdx
];
1177 setActions(TypeIndex
, Actions
, SizeAndActions
);
1180 /// See also setScalarInVectorAction.
1181 /// This function let's you specify the number of elements in a vector that
1182 /// are legal for a legal element size.
1183 void setVectorNumElementAction(const unsigned Opcode
,
1184 const unsigned TypeIndex
,
1185 const unsigned ElementSize
,
1186 const SizeAndActionsVec
&SizeAndActions
) {
1187 const unsigned OpcodeIdx
= Opcode
- FirstOp
;
1188 if (NumElements2Actions
[OpcodeIdx
].find(ElementSize
) ==
1189 NumElements2Actions
[OpcodeIdx
].end())
1190 NumElements2Actions
[OpcodeIdx
][ElementSize
] = {{}};
1191 SmallVector
<SizeAndActionsVec
, 1> &Actions
=
1192 NumElements2Actions
[OpcodeIdx
].find(ElementSize
)->second
;
1193 setActions(TypeIndex
, Actions
, SizeAndActions
);
1196 /// A partial SizeAndActionsVec potentially doesn't cover all bit sizes,
1197 /// i.e. it's OK if it doesn't start from size 1.
1198 static void checkPartialSizeAndActionsVector(const SizeAndActionsVec
& v
) {
1199 using namespace LegalizeActions
;
1201 // The sizes should be in increasing order
1203 for(auto SizeAndAction
: v
) {
1204 assert(SizeAndAction
.first
> prev_size
);
1205 prev_size
= SizeAndAction
.first
;
1207 // - for every Widen action, there should be a larger bitsize that
1208 // can be legalized towards (e.g. Legal, Lower, Libcall or Custom
1210 // - for every Narrow action, there should be a smaller bitsize that
1211 // can be legalized towards.
1212 int SmallestNarrowIdx
= -1;
1213 int LargestWidenIdx
= -1;
1214 int SmallestLegalizableToSameSizeIdx
= -1;
1215 int LargestLegalizableToSameSizeIdx
= -1;
1216 for(size_t i
=0; i
<v
.size(); ++i
) {
1217 switch (v
[i
].second
) {
1220 if (SmallestNarrowIdx
== -1)
1221 SmallestNarrowIdx
= i
;
1225 LargestWidenIdx
= i
;
1230 if (SmallestLegalizableToSameSizeIdx
== -1)
1231 SmallestLegalizableToSameSizeIdx
= i
;
1232 LargestLegalizableToSameSizeIdx
= i
;
1235 if (SmallestNarrowIdx
!= -1) {
1236 assert(SmallestLegalizableToSameSizeIdx
!= -1);
1237 assert(SmallestNarrowIdx
> SmallestLegalizableToSameSizeIdx
);
1239 if (LargestWidenIdx
!= -1)
1240 assert(LargestWidenIdx
< LargestLegalizableToSameSizeIdx
);
1244 /// A full SizeAndActionsVec must cover all bit sizes, i.e. must start with
1246 static void checkFullSizeAndActionsVector(const SizeAndActionsVec
& v
) {
1248 // Data structure invariant: The first bit size must be size 1.
1249 assert(v
.size() >= 1);
1250 assert(v
[0].first
== 1);
1251 checkPartialSizeAndActionsVector(v
);
1255 /// Sets actions for all bit sizes on a particular generic opcode, type
1256 /// index and scalar or pointer type.
1257 void setActions(unsigned TypeIndex
,
1258 SmallVector
<SizeAndActionsVec
, 1> &Actions
,
1259 const SizeAndActionsVec
&SizeAndActions
) {
1260 checkFullSizeAndActionsVector(SizeAndActions
);
1261 if (Actions
.size() <= TypeIndex
)
1262 Actions
.resize(TypeIndex
+ 1);
1263 Actions
[TypeIndex
] = SizeAndActions
;
1266 static SizeAndAction
findAction(const SizeAndActionsVec
&Vec
,
1267 const uint32_t Size
);
1269 /// Returns the next action needed to get the scalar or pointer type closer
1271 /// E.g. findLegalAction({G_REM, 13}) should return
1272 /// (WidenScalar, 32). After that, findLegalAction({G_REM, 32}) will
1273 /// probably be called, which should return (Lower, 32).
1274 /// This is assuming the setScalarAction on G_REM was something like:
1275 /// setScalarAction(G_REM, 0,
1276 /// {{1, WidenScalar}, // bit sizes [ 1, 31[
1277 /// {32, Lower}, // bit sizes [32, 33[
1278 /// {33, NarrowScalar} // bit sizes [65, +inf[
1280 std::pair
<LegalizeAction
, LLT
>
1281 findScalarLegalAction(const InstrAspect
&Aspect
) const;
1283 /// Returns the next action needed towards legalizing the vector type.
1284 std::pair
<LegalizeAction
, LLT
>
1285 findVectorLegalAction(const InstrAspect
&Aspect
) const;
1287 static const int FirstOp
= TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START
;
1288 static const int LastOp
= TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END
;
1290 // Data structures used temporarily during construction of legality data:
1291 using TypeMap
= DenseMap
<LLT
, LegalizeAction
>;
1292 SmallVector
<TypeMap
, 1> SpecifiedActions
[LastOp
- FirstOp
+ 1];
1293 SmallVector
<SizeChangeStrategy
, 1>
1294 ScalarSizeChangeStrategies
[LastOp
- FirstOp
+ 1];
1295 SmallVector
<SizeChangeStrategy
, 1>
1296 VectorElementSizeChangeStrategies
[LastOp
- FirstOp
+ 1];
1297 bool TablesInitialized
;
1299 // Data structures used by getAction:
1300 SmallVector
<SizeAndActionsVec
, 1> ScalarActions
[LastOp
- FirstOp
+ 1];
1301 SmallVector
<SizeAndActionsVec
, 1> ScalarInVectorActions
[LastOp
- FirstOp
+ 1];
1302 std::unordered_map
<uint16_t, SmallVector
<SizeAndActionsVec
, 1>>
1303 AddrSpace2PointerActions
[LastOp
- FirstOp
+ 1];
1304 std::unordered_map
<uint16_t, SmallVector
<SizeAndActionsVec
, 1>>
1305 NumElements2Actions
[LastOp
- FirstOp
+ 1];
1307 LegalizeRuleSet RulesForOpcode
[LastOp
- FirstOp
+ 1];
1311 /// Checks that MIR is fully legal, returns an illegal instruction if it's not,
1312 /// nullptr otherwise
1313 const MachineInstr
*machineFunctionIsIllegal(const MachineFunction
&MF
);
1316 } // end namespace llvm.
1318 #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H