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};
334 SmallBitVector ImmIdxsCovered
{MCOI::OPERAND_LAST_GENERIC_IMM
-
335 MCOI::OPERAND_FIRST_GENERIC_IMM
+ 2};
338 unsigned typeIdx(unsigned TypeIdx
) {
340 (MCOI::OPERAND_LAST_GENERIC
- MCOI::OPERAND_FIRST_GENERIC
) &&
341 "Type Index is out of bounds");
343 TypeIdxsCovered
.set(TypeIdx
);
348 unsigned immIdx(unsigned ImmIdx
) {
349 assert(ImmIdx
<= (MCOI::OPERAND_LAST_GENERIC_IMM
-
350 MCOI::OPERAND_FIRST_GENERIC_IMM
) &&
351 "Imm Index is out of bounds");
353 ImmIdxsCovered
.set(ImmIdx
);
358 void markAllIdxsAsCovered() {
360 TypeIdxsCovered
.set();
361 ImmIdxsCovered
.set();
365 void add(const LegalizeRule
&Rule
) {
366 assert(AliasOf
== 0 &&
367 "RuleSet is aliased, change the representative opcode instead");
368 Rules
.push_back(Rule
);
371 static bool always(const LegalityQuery
&) { return true; }
373 /// Use the given action when the predicate is true.
374 /// Action should not be an action that requires mutation.
375 LegalizeRuleSet
&actionIf(LegalizeAction Action
,
376 LegalityPredicate Predicate
) {
377 add({Predicate
, Action
});
380 /// Use the given action when the predicate is true.
381 /// Action should be an action that requires mutation.
382 LegalizeRuleSet
&actionIf(LegalizeAction Action
, LegalityPredicate Predicate
,
383 LegalizeMutation Mutation
) {
384 add({Predicate
, Action
, Mutation
});
387 /// Use the given action when type index 0 is any type in the given list.
388 /// Action should not be an action that requires mutation.
389 LegalizeRuleSet
&actionFor(LegalizeAction Action
,
390 std::initializer_list
<LLT
> Types
) {
391 using namespace LegalityPredicates
;
392 return actionIf(Action
, typeInSet(typeIdx(0), Types
));
394 /// Use the given action when type index 0 is any type in the given list.
395 /// Action should be an action that requires mutation.
396 LegalizeRuleSet
&actionFor(LegalizeAction Action
,
397 std::initializer_list
<LLT
> Types
,
398 LegalizeMutation Mutation
) {
399 using namespace LegalityPredicates
;
400 return actionIf(Action
, typeInSet(typeIdx(0), Types
), Mutation
);
402 /// Use the given action when type indexes 0 and 1 is any type pair in the
404 /// Action should not be an action that requires mutation.
405 LegalizeRuleSet
&actionFor(LegalizeAction Action
,
406 std::initializer_list
<std::pair
<LLT
, LLT
>> Types
) {
407 using namespace LegalityPredicates
;
408 return actionIf(Action
, typePairInSet(typeIdx(0), typeIdx(1), Types
));
410 /// Use the given action when type indexes 0 and 1 is any type pair in the
412 /// Action should be an action that requires mutation.
413 LegalizeRuleSet
&actionFor(LegalizeAction Action
,
414 std::initializer_list
<std::pair
<LLT
, LLT
>> Types
,
415 LegalizeMutation Mutation
) {
416 using namespace LegalityPredicates
;
417 return actionIf(Action
, typePairInSet(typeIdx(0), typeIdx(1), Types
),
420 /// Use the given action when type index 0 is any type in the given list and
421 /// imm index 0 is anything. Action should not be an action that requires
423 LegalizeRuleSet
&actionForTypeWithAnyImm(LegalizeAction Action
,
424 std::initializer_list
<LLT
> Types
) {
425 using namespace LegalityPredicates
;
426 immIdx(0); // Inform verifier imm idx 0 is handled.
427 return actionIf(Action
, typeInSet(typeIdx(0), Types
));
429 /// Use the given action when type indexes 0 and 1 are both in the given list.
430 /// That is, the type pair is in the cartesian product of the list.
431 /// Action should not be an action that requires mutation.
432 LegalizeRuleSet
&actionForCartesianProduct(LegalizeAction Action
,
433 std::initializer_list
<LLT
> Types
) {
434 using namespace LegalityPredicates
;
435 return actionIf(Action
, all(typeInSet(typeIdx(0), Types
),
436 typeInSet(typeIdx(1), Types
)));
438 /// Use the given action when type indexes 0 and 1 are both in their
439 /// respective lists.
440 /// That is, the type pair is in the cartesian product of the lists
441 /// Action should not be an action that requires mutation.
443 actionForCartesianProduct(LegalizeAction Action
,
444 std::initializer_list
<LLT
> Types0
,
445 std::initializer_list
<LLT
> Types1
) {
446 using namespace LegalityPredicates
;
447 return actionIf(Action
, all(typeInSet(typeIdx(0), Types0
),
448 typeInSet(typeIdx(1), Types1
)));
450 /// Use the given action when type indexes 0, 1, and 2 are all in their
451 /// respective lists.
452 /// That is, the type triple is in the cartesian product of the lists
453 /// Action should not be an action that requires mutation.
454 LegalizeRuleSet
&actionForCartesianProduct(
455 LegalizeAction Action
, std::initializer_list
<LLT
> Types0
,
456 std::initializer_list
<LLT
> Types1
, std::initializer_list
<LLT
> Types2
) {
457 using namespace LegalityPredicates
;
458 return actionIf(Action
, all(typeInSet(typeIdx(0), Types0
),
459 all(typeInSet(typeIdx(1), Types1
),
460 typeInSet(typeIdx(2), Types2
))));
464 LegalizeRuleSet() : AliasOf(0), IsAliasedByAnother(false), Rules() {}
466 bool isAliasedByAnother() { return IsAliasedByAnother
; }
467 void setIsAliasedByAnother() { IsAliasedByAnother
= true; }
468 void aliasTo(unsigned Opcode
) {
469 assert((AliasOf
== 0 || AliasOf
== Opcode
) &&
470 "Opcode is already aliased to another opcode");
471 assert(Rules
.empty() && "Aliasing will discard rules");
474 unsigned getAlias() const { return AliasOf
; }
476 /// The instruction is legal if predicate is true.
477 LegalizeRuleSet
&legalIf(LegalityPredicate Predicate
) {
478 // We have no choice but conservatively assume that the free-form
479 // user-provided Predicate properly handles all type indices:
480 markAllIdxsAsCovered();
481 return actionIf(LegalizeAction::Legal
, Predicate
);
483 /// The instruction is legal when type index 0 is any type in the given list.
484 LegalizeRuleSet
&legalFor(std::initializer_list
<LLT
> Types
) {
485 return actionFor(LegalizeAction::Legal
, Types
);
487 /// The instruction is legal when type indexes 0 and 1 is any type pair in the
489 LegalizeRuleSet
&legalFor(std::initializer_list
<std::pair
<LLT
, LLT
>> Types
) {
490 return actionFor(LegalizeAction::Legal
, Types
);
492 /// The instruction is legal when type index 0 is any type in the given list
493 /// and imm index 0 is anything.
494 LegalizeRuleSet
&legalForTypeWithAnyImm(std::initializer_list
<LLT
> Types
) {
495 markAllIdxsAsCovered();
496 return actionForTypeWithAnyImm(LegalizeAction::Legal
, Types
);
498 /// The instruction is legal when type indexes 0 and 1 along with the memory
499 /// size and minimum alignment is any type and size tuple in the given list.
500 LegalizeRuleSet
&legalForTypesWithMemDesc(
501 std::initializer_list
<LegalityPredicates::TypePairAndMemDesc
>
503 return actionIf(LegalizeAction::Legal
,
504 LegalityPredicates::typePairAndMemDescInSet(
505 typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemDesc
));
507 /// The instruction is legal when type indexes 0 and 1 are both in the given
508 /// list. That is, the type pair is in the cartesian product of the list.
509 LegalizeRuleSet
&legalForCartesianProduct(std::initializer_list
<LLT
> Types
) {
510 return actionForCartesianProduct(LegalizeAction::Legal
, Types
);
512 /// The instruction is legal when type indexes 0 and 1 are both their
513 /// respective lists.
514 LegalizeRuleSet
&legalForCartesianProduct(std::initializer_list
<LLT
> Types0
,
515 std::initializer_list
<LLT
> Types1
) {
516 return actionForCartesianProduct(LegalizeAction::Legal
, Types0
, Types1
);
518 /// The instruction is legal when type indexes 0, 1, and 2 are both their
519 /// respective lists.
520 LegalizeRuleSet
&legalForCartesianProduct(std::initializer_list
<LLT
> Types0
,
521 std::initializer_list
<LLT
> Types1
,
522 std::initializer_list
<LLT
> Types2
) {
523 return actionForCartesianProduct(LegalizeAction::Legal
, Types0
, Types1
,
527 LegalizeRuleSet
&alwaysLegal() {
528 using namespace LegalizeMutations
;
529 markAllIdxsAsCovered();
530 return actionIf(LegalizeAction::Legal
, always
);
533 /// The instruction is lowered.
534 LegalizeRuleSet
&lower() {
535 using namespace LegalizeMutations
;
536 // We have no choice but conservatively assume that predicate-less lowering
537 // properly handles all type indices by design:
538 markAllIdxsAsCovered();
539 return actionIf(LegalizeAction::Lower
, always
);
541 /// The instruction is lowered if predicate is true. Keep type index 0 as the
543 LegalizeRuleSet
&lowerIf(LegalityPredicate Predicate
) {
544 using namespace LegalizeMutations
;
545 // We have no choice but conservatively assume that lowering with a
546 // free-form user provided Predicate properly handles all type indices:
547 markAllIdxsAsCovered();
548 return actionIf(LegalizeAction::Lower
, Predicate
);
550 /// The instruction is lowered if predicate is true.
551 LegalizeRuleSet
&lowerIf(LegalityPredicate Predicate
,
552 LegalizeMutation Mutation
) {
553 // We have no choice but conservatively assume that lowering with a
554 // free-form user provided Predicate properly handles all type indices:
555 markAllIdxsAsCovered();
556 return actionIf(LegalizeAction::Lower
, Predicate
, Mutation
);
558 /// The instruction is lowered when type index 0 is any type in the given
559 /// list. Keep type index 0 as the same type.
560 LegalizeRuleSet
&lowerFor(std::initializer_list
<LLT
> Types
) {
561 return actionFor(LegalizeAction::Lower
, Types
,
562 LegalizeMutations::changeTo(0, 0));
564 /// The instruction is lowered when type index 0 is any type in the given
566 LegalizeRuleSet
&lowerFor(std::initializer_list
<LLT
> Types
,
567 LegalizeMutation Mutation
) {
568 return actionFor(LegalizeAction::Lower
, Types
, Mutation
);
570 /// The instruction is lowered when type indexes 0 and 1 is any type pair in
571 /// the given list. Keep type index 0 as the same type.
572 LegalizeRuleSet
&lowerFor(std::initializer_list
<std::pair
<LLT
, LLT
>> Types
) {
573 return actionFor(LegalizeAction::Lower
, Types
,
574 LegalizeMutations::changeTo(0, 0));
576 /// The instruction is lowered when type indexes 0 and 1 is any type pair in
578 LegalizeRuleSet
&lowerFor(std::initializer_list
<std::pair
<LLT
, LLT
>> Types
,
579 LegalizeMutation Mutation
) {
580 return actionFor(LegalizeAction::Lower
, Types
, Mutation
);
582 /// The instruction is lowered when type indexes 0 and 1 are both in their
583 /// respective lists.
584 LegalizeRuleSet
&lowerForCartesianProduct(std::initializer_list
<LLT
> Types0
,
585 std::initializer_list
<LLT
> Types1
) {
586 using namespace LegalityPredicates
;
587 return actionForCartesianProduct(LegalizeAction::Lower
, Types0
, Types1
);
589 /// The instruction is lowered when when type indexes 0, 1, and 2 are all in
590 /// their respective lists.
591 LegalizeRuleSet
&lowerForCartesianProduct(std::initializer_list
<LLT
> Types0
,
592 std::initializer_list
<LLT
> Types1
,
593 std::initializer_list
<LLT
> Types2
) {
594 using namespace LegalityPredicates
;
595 return actionForCartesianProduct(LegalizeAction::Lower
, Types0
, Types1
,
599 /// Like legalIf, but for the Libcall action.
600 LegalizeRuleSet
&libcallIf(LegalityPredicate Predicate
) {
601 // We have no choice but conservatively assume that a libcall with a
602 // free-form user provided Predicate properly handles all type indices:
603 markAllIdxsAsCovered();
604 return actionIf(LegalizeAction::Libcall
, Predicate
);
606 LegalizeRuleSet
&libcallFor(std::initializer_list
<LLT
> Types
) {
607 return actionFor(LegalizeAction::Libcall
, Types
);
610 libcallFor(std::initializer_list
<std::pair
<LLT
, LLT
>> Types
) {
611 return actionFor(LegalizeAction::Libcall
, Types
);
614 libcallForCartesianProduct(std::initializer_list
<LLT
> Types
) {
615 return actionForCartesianProduct(LegalizeAction::Libcall
, Types
);
618 libcallForCartesianProduct(std::initializer_list
<LLT
> Types0
,
619 std::initializer_list
<LLT
> Types1
) {
620 return actionForCartesianProduct(LegalizeAction::Libcall
, Types0
, Types1
);
623 /// Widen the scalar to the one selected by the mutation if the predicate is
625 LegalizeRuleSet
&widenScalarIf(LegalityPredicate Predicate
,
626 LegalizeMutation Mutation
) {
627 // We have no choice but conservatively assume that an action with a
628 // free-form user provided Predicate properly handles all type indices:
629 markAllIdxsAsCovered();
630 return actionIf(LegalizeAction::WidenScalar
, Predicate
, Mutation
);
632 /// Narrow the scalar to the one selected by the mutation if the predicate is
634 LegalizeRuleSet
&narrowScalarIf(LegalityPredicate Predicate
,
635 LegalizeMutation Mutation
) {
636 // We have no choice but conservatively assume that an action with a
637 // free-form user provided Predicate properly handles all type indices:
638 markAllIdxsAsCovered();
639 return actionIf(LegalizeAction::NarrowScalar
, Predicate
, Mutation
);
642 /// Add more elements to reach the type selected by the mutation if the
643 /// predicate is true.
644 LegalizeRuleSet
&moreElementsIf(LegalityPredicate Predicate
,
645 LegalizeMutation Mutation
) {
646 // We have no choice but conservatively assume that an action with a
647 // free-form user provided Predicate properly handles all type indices:
648 markAllIdxsAsCovered();
649 return actionIf(LegalizeAction::MoreElements
, Predicate
, Mutation
);
651 /// Remove elements to reach the type selected by the mutation if the
652 /// predicate is true.
653 LegalizeRuleSet
&fewerElementsIf(LegalityPredicate Predicate
,
654 LegalizeMutation Mutation
) {
655 // We have no choice but conservatively assume that an action with a
656 // free-form user provided Predicate properly handles all type indices:
657 markAllIdxsAsCovered();
658 return actionIf(LegalizeAction::FewerElements
, Predicate
, Mutation
);
661 /// The instruction is unsupported.
662 LegalizeRuleSet
&unsupported() {
663 return actionIf(LegalizeAction::Unsupported
, always
);
665 LegalizeRuleSet
&unsupportedIf(LegalityPredicate Predicate
) {
666 return actionIf(LegalizeAction::Unsupported
, Predicate
);
668 LegalizeRuleSet
&unsupportedIfMemSizeNotPow2() {
669 return actionIf(LegalizeAction::Unsupported
,
670 LegalityPredicates::memSizeInBytesNotPow2(0));
672 LegalizeRuleSet
&lowerIfMemSizeNotPow2() {
673 return actionIf(LegalizeAction::Lower
,
674 LegalityPredicates::memSizeInBytesNotPow2(0));
677 LegalizeRuleSet
&customIf(LegalityPredicate Predicate
) {
678 // We have no choice but conservatively assume that a custom action with a
679 // free-form user provided Predicate properly handles all type indices:
680 markAllIdxsAsCovered();
681 return actionIf(LegalizeAction::Custom
, Predicate
);
683 LegalizeRuleSet
&customFor(std::initializer_list
<LLT
> Types
) {
684 return actionFor(LegalizeAction::Custom
, Types
);
687 /// The instruction is custom when type indexes 0 and 1 is any type pair in the
689 LegalizeRuleSet
&customFor(std::initializer_list
<std::pair
<LLT
, LLT
>> Types
) {
690 return actionFor(LegalizeAction::Custom
, Types
);
693 LegalizeRuleSet
&customForCartesianProduct(std::initializer_list
<LLT
> Types
) {
694 return actionForCartesianProduct(LegalizeAction::Custom
, Types
);
697 customForCartesianProduct(std::initializer_list
<LLT
> Types0
,
698 std::initializer_list
<LLT
> Types1
) {
699 return actionForCartesianProduct(LegalizeAction::Custom
, Types0
, Types1
);
702 /// Unconditionally custom lower.
703 LegalizeRuleSet
&custom() {
704 return customIf(always
);
707 /// Widen the scalar to the next power of two that is at least MinSize.
708 /// No effect if the type is not a scalar or is a power of two.
709 LegalizeRuleSet
&widenScalarToNextPow2(unsigned TypeIdx
,
710 unsigned MinSize
= 0) {
711 using namespace LegalityPredicates
;
713 LegalizeAction::WidenScalar
, sizeNotPow2(typeIdx(TypeIdx
)),
714 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx
, MinSize
));
717 /// Widen the scalar or vector element type to the next power of two that is
718 /// at least MinSize. No effect if the scalar size is a power of two.
719 LegalizeRuleSet
&widenScalarOrEltToNextPow2(unsigned TypeIdx
,
720 unsigned MinSize
= 0) {
721 using namespace LegalityPredicates
;
723 LegalizeAction::WidenScalar
, scalarOrEltSizeNotPow2(typeIdx(TypeIdx
)),
724 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx
, MinSize
));
727 LegalizeRuleSet
&narrowScalar(unsigned TypeIdx
, LegalizeMutation Mutation
) {
728 using namespace LegalityPredicates
;
729 return actionIf(LegalizeAction::NarrowScalar
, isScalar(typeIdx(TypeIdx
)),
733 LegalizeRuleSet
&scalarize(unsigned TypeIdx
) {
734 using namespace LegalityPredicates
;
735 return actionIf(LegalizeAction::FewerElements
, isVector(typeIdx(TypeIdx
)),
736 LegalizeMutations::scalarize(TypeIdx
));
739 /// Ensure the scalar or element is at least as wide as Ty.
740 LegalizeRuleSet
&minScalarOrElt(unsigned TypeIdx
, const LLT
&Ty
) {
741 using namespace LegalityPredicates
;
742 using namespace LegalizeMutations
;
743 return actionIf(LegalizeAction::WidenScalar
,
744 scalarOrEltNarrowerThan(TypeIdx
, Ty
.getScalarSizeInBits()),
745 changeElementTo(typeIdx(TypeIdx
), Ty
));
748 /// Ensure the scalar or element is at least as wide as Ty.
749 LegalizeRuleSet
&minScalarOrEltIf(LegalityPredicate Predicate
,
750 unsigned TypeIdx
, const LLT
&Ty
) {
751 using namespace LegalityPredicates
;
752 using namespace LegalizeMutations
;
753 return actionIf(LegalizeAction::WidenScalar
,
754 all(Predicate
, scalarOrEltNarrowerThan(
755 TypeIdx
, Ty
.getScalarSizeInBits())),
756 changeElementTo(typeIdx(TypeIdx
), Ty
));
759 /// Ensure the scalar is at least as wide as Ty.
760 LegalizeRuleSet
&minScalar(unsigned TypeIdx
, const LLT
&Ty
) {
761 using namespace LegalityPredicates
;
762 using namespace LegalizeMutations
;
763 return actionIf(LegalizeAction::WidenScalar
,
764 narrowerThan(TypeIdx
, Ty
.getSizeInBits()),
765 changeTo(typeIdx(TypeIdx
), Ty
));
768 /// Ensure the scalar is at most as wide as Ty.
769 LegalizeRuleSet
&maxScalarOrElt(unsigned TypeIdx
, const LLT
&Ty
) {
770 using namespace LegalityPredicates
;
771 using namespace LegalizeMutations
;
772 return actionIf(LegalizeAction::NarrowScalar
,
773 scalarOrEltWiderThan(TypeIdx
, Ty
.getScalarSizeInBits()),
774 changeElementTo(typeIdx(TypeIdx
), Ty
));
777 /// Ensure the scalar is at most as wide as Ty.
778 LegalizeRuleSet
&maxScalar(unsigned TypeIdx
, const LLT
&Ty
) {
779 using namespace LegalityPredicates
;
780 using namespace LegalizeMutations
;
781 return actionIf(LegalizeAction::NarrowScalar
,
782 widerThan(TypeIdx
, Ty
.getSizeInBits()),
783 changeTo(typeIdx(TypeIdx
), Ty
));
786 /// Conditionally limit the maximum size of the scalar.
787 /// For example, when the maximum size of one type depends on the size of
788 /// another such as extracting N bits from an M bit container.
789 LegalizeRuleSet
&maxScalarIf(LegalityPredicate Predicate
, unsigned TypeIdx
,
791 using namespace LegalityPredicates
;
792 using namespace LegalizeMutations
;
794 LegalizeAction::NarrowScalar
,
795 [=](const LegalityQuery
&Query
) {
796 return widerThan(TypeIdx
, Ty
.getSizeInBits()) && Predicate(Query
);
798 changeElementTo(typeIdx(TypeIdx
), Ty
));
801 /// Limit the range of scalar sizes to MinTy and MaxTy.
802 LegalizeRuleSet
&clampScalar(unsigned TypeIdx
, const LLT
&MinTy
,
804 assert(MinTy
.isScalar() && MaxTy
.isScalar() && "Expected scalar types");
805 return minScalar(TypeIdx
, MinTy
).maxScalar(TypeIdx
, MaxTy
);
808 /// Limit the range of scalar sizes to MinTy and MaxTy.
809 LegalizeRuleSet
&clampScalarOrElt(unsigned TypeIdx
, const LLT
&MinTy
,
811 return minScalarOrElt(TypeIdx
, MinTy
).maxScalarOrElt(TypeIdx
, MaxTy
);
814 /// Widen the scalar to match the size of another.
815 LegalizeRuleSet
&minScalarSameAs(unsigned TypeIdx
, unsigned LargeTypeIdx
) {
817 return widenScalarIf(
818 [=](const LegalityQuery
&Query
) {
819 return Query
.Types
[LargeTypeIdx
].getScalarSizeInBits() >
820 Query
.Types
[TypeIdx
].getSizeInBits();
822 [=](const LegalityQuery
&Query
) {
823 LLT T
= Query
.Types
[LargeTypeIdx
];
824 return std::make_pair(TypeIdx
,
825 T
.isVector() ? T
.getElementType() : T
);
829 /// Conditionally widen the scalar or elt to match the size of another.
830 LegalizeRuleSet
&minScalarEltSameAsIf(LegalityPredicate Predicate
,
831 unsigned TypeIdx
, unsigned LargeTypeIdx
) {
833 return widenScalarIf(
834 [=](const LegalityQuery
&Query
) {
835 return Query
.Types
[LargeTypeIdx
].getScalarSizeInBits() >
836 Query
.Types
[TypeIdx
].getScalarSizeInBits() &&
839 [=](const LegalityQuery
&Query
) {
840 LLT T
= Query
.Types
[LargeTypeIdx
];
841 return std::make_pair(TypeIdx
, T
);
845 /// Add more elements to the vector to reach the next power of two.
846 /// No effect if the type is not a vector or the element count is a power of
848 LegalizeRuleSet
&moreElementsToNextPow2(unsigned TypeIdx
) {
849 using namespace LegalityPredicates
;
850 return actionIf(LegalizeAction::MoreElements
,
851 numElementsNotPow2(typeIdx(TypeIdx
)),
852 LegalizeMutations::moreElementsToNextPow2(TypeIdx
));
855 /// Limit the number of elements in EltTy vectors to at least MinElements.
856 LegalizeRuleSet
&clampMinNumElements(unsigned TypeIdx
, const LLT
&EltTy
,
857 unsigned MinElements
) {
858 // Mark the type index as covered:
861 LegalizeAction::MoreElements
,
862 [=](const LegalityQuery
&Query
) {
863 LLT VecTy
= Query
.Types
[TypeIdx
];
864 return VecTy
.isVector() && VecTy
.getElementType() == EltTy
&&
865 VecTy
.getNumElements() < MinElements
;
867 [=](const LegalityQuery
&Query
) {
868 LLT VecTy
= Query
.Types
[TypeIdx
];
869 return std::make_pair(
870 TypeIdx
, LLT::vector(MinElements
, VecTy
.getElementType()));
873 /// Limit the number of elements in EltTy vectors to at most MaxElements.
874 LegalizeRuleSet
&clampMaxNumElements(unsigned TypeIdx
, const LLT
&EltTy
,
875 unsigned MaxElements
) {
876 // Mark the type index as covered:
879 LegalizeAction::FewerElements
,
880 [=](const LegalityQuery
&Query
) {
881 LLT VecTy
= Query
.Types
[TypeIdx
];
882 return VecTy
.isVector() && VecTy
.getElementType() == EltTy
&&
883 VecTy
.getNumElements() > MaxElements
;
885 [=](const LegalityQuery
&Query
) {
886 LLT VecTy
= Query
.Types
[TypeIdx
];
887 LLT NewTy
= LLT::scalarOrVector(MaxElements
, VecTy
.getElementType());
888 return std::make_pair(TypeIdx
, NewTy
);
891 /// Limit the number of elements for the given vectors to at least MinTy's
892 /// number of elements and at most MaxTy's number of elements.
894 /// No effect if the type is not a vector or does not have the same element
895 /// type as the constraints.
896 /// The element type of MinTy and MaxTy must match.
897 LegalizeRuleSet
&clampNumElements(unsigned TypeIdx
, const LLT
&MinTy
,
899 assert(MinTy
.getElementType() == MaxTy
.getElementType() &&
900 "Expected element types to agree");
902 const LLT
&EltTy
= MinTy
.getElementType();
903 return clampMinNumElements(TypeIdx
, EltTy
, MinTy
.getNumElements())
904 .clampMaxNumElements(TypeIdx
, EltTy
, MaxTy
.getNumElements());
907 /// Fallback on the previous implementation. This should only be used while
909 LegalizeRuleSet
&fallback() {
910 add({always
, LegalizeAction::UseLegacyRules
});
914 /// Check if there is no type index which is obviously not handled by the
915 /// LegalizeRuleSet in any way at all.
916 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set.
917 bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs
) const;
918 /// Check if there is no imm index which is obviously not handled by the
919 /// LegalizeRuleSet in any way at all.
920 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set.
921 bool verifyImmIdxsCoverage(unsigned NumImmIdxs
) const;
923 /// Apply the ruleset to the given LegalityQuery.
924 LegalizeActionStep
apply(const LegalityQuery
&Query
) const;
927 class LegalizerInfo
{
930 virtual ~LegalizerInfo() = default;
932 unsigned getOpcodeIdxForOpcode(unsigned Opcode
) const;
933 unsigned getActionDefinitionsIdx(unsigned Opcode
) const;
935 /// Compute any ancillary tables needed to quickly decide how an operation
936 /// should be handled. This must be called after all "set*Action"methods but
937 /// before any query is made or incorrect results may be returned.
938 void computeTables();
940 /// Perform simple self-diagnostic and assert if there is anything obviously
941 /// wrong with the actions set up.
942 void verify(const MCInstrInfo
&MII
) const;
944 static bool needsLegalizingToDifferentSize(const LegalizeAction Action
) {
945 using namespace LegalizeActions
;
958 using SizeAndAction
= std::pair
<uint16_t, LegalizeAction
>;
959 using SizeAndActionsVec
= std::vector
<SizeAndAction
>;
960 using SizeChangeStrategy
=
961 std::function
<SizeAndActionsVec(const SizeAndActionsVec
&v
)>;
963 /// More friendly way to set an action for common types that have an LLT
965 /// The LegalizeAction must be one for which NeedsLegalizingToDifferentSize
967 void setAction(const InstrAspect
&Aspect
, LegalizeAction Action
) {
968 assert(!needsLegalizingToDifferentSize(Action
));
969 TablesInitialized
= false;
970 const unsigned OpcodeIdx
= Aspect
.Opcode
- FirstOp
;
971 if (SpecifiedActions
[OpcodeIdx
].size() <= Aspect
.Idx
)
972 SpecifiedActions
[OpcodeIdx
].resize(Aspect
.Idx
+ 1);
973 SpecifiedActions
[OpcodeIdx
][Aspect
.Idx
][Aspect
.Type
] = Action
;
976 /// The setAction calls record the non-size-changing legalization actions
977 /// to take on specificly-sized types. The SizeChangeStrategy defines what
978 /// to do when the size of the type needs to be changed to reach a legally
979 /// sized type (i.e., one that was defined through a setAction call).
981 /// setAction ({G_ADD, 0, LLT::scalar(32)}, Legal);
982 /// setLegalizeScalarToDifferentSizeStrategy(
983 /// G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
984 /// will end up defining getAction({G_ADD, 0, T}) to return the following
985 /// actions for different scalar types T:
986 /// LLT::scalar(1)..LLT::scalar(31): {WidenScalar, 0, LLT::scalar(32)}
987 /// LLT::scalar(32): {Legal, 0, LLT::scalar(32)}
988 /// LLT::scalar(33)..: {NarrowScalar, 0, LLT::scalar(32)}
990 /// If no SizeChangeAction gets defined, through this function,
991 /// the default is unsupportedForDifferentSizes.
992 void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode
,
993 const unsigned TypeIdx
,
994 SizeChangeStrategy S
) {
995 const unsigned OpcodeIdx
= Opcode
- FirstOp
;
996 if (ScalarSizeChangeStrategies
[OpcodeIdx
].size() <= TypeIdx
)
997 ScalarSizeChangeStrategies
[OpcodeIdx
].resize(TypeIdx
+ 1);
998 ScalarSizeChangeStrategies
[OpcodeIdx
][TypeIdx
] = S
;
1001 /// See also setLegalizeScalarToDifferentSizeStrategy.
1002 /// This function allows to set the SizeChangeStrategy for vector elements.
1003 void setLegalizeVectorElementToDifferentSizeStrategy(const unsigned Opcode
,
1004 const unsigned TypeIdx
,
1005 SizeChangeStrategy S
) {
1006 const unsigned OpcodeIdx
= Opcode
- FirstOp
;
1007 if (VectorElementSizeChangeStrategies
[OpcodeIdx
].size() <= TypeIdx
)
1008 VectorElementSizeChangeStrategies
[OpcodeIdx
].resize(TypeIdx
+ 1);
1009 VectorElementSizeChangeStrategies
[OpcodeIdx
][TypeIdx
] = S
;
1012 /// A SizeChangeStrategy for the common case where legalization for a
1013 /// particular operation consists of only supporting a specific set of type
1015 /// setAction ({G_DIV, 0, LLT::scalar(32)}, Legal);
1016 /// setAction ({G_DIV, 0, LLT::scalar(64)}, Legal);
1017 /// setLegalizeScalarToDifferentSizeStrategy(
1018 /// G_DIV, 0, unsupportedForDifferentSizes);
1019 /// will result in getAction({G_DIV, 0, T}) to return Legal for s32 and s64,
1020 /// and Unsupported for all other scalar types T.
1021 static SizeAndActionsVec
1022 unsupportedForDifferentSizes(const SizeAndActionsVec
&v
) {
1023 using namespace LegalizeActions
;
1024 return increaseToLargerTypesAndDecreaseToLargest(v
, Unsupported
,
1028 /// A SizeChangeStrategy for the common case where legalization for a
1029 /// particular operation consists of widening the type to a large legal type,
1030 /// unless there is no such type and then instead it should be narrowed to the
1031 /// largest legal type.
1032 static SizeAndActionsVec
1033 widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec
&v
) {
1034 using namespace LegalizeActions
;
1035 assert(v
.size() > 0 &&
1036 "At least one size that can be legalized towards is needed"
1037 " for this SizeChangeStrategy");
1038 return increaseToLargerTypesAndDecreaseToLargest(v
, WidenScalar
,
1042 static SizeAndActionsVec
1043 widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec
&v
) {
1044 using namespace LegalizeActions
;
1045 return increaseToLargerTypesAndDecreaseToLargest(v
, WidenScalar
,
1049 static SizeAndActionsVec
1050 narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec
&v
) {
1051 using namespace LegalizeActions
;
1052 return decreaseToSmallerTypesAndIncreaseToSmallest(v
, NarrowScalar
,
1056 static SizeAndActionsVec
1057 narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec
&v
) {
1058 using namespace LegalizeActions
;
1059 assert(v
.size() > 0 &&
1060 "At least one size that can be legalized towards is needed"
1061 " for this SizeChangeStrategy");
1062 return decreaseToSmallerTypesAndIncreaseToSmallest(v
, NarrowScalar
,
1066 /// A SizeChangeStrategy for the common case where legalization for a
1067 /// particular vector operation consists of having more elements in the
1068 /// vector, to a type that is legal. Unless there is no such type and then
1069 /// instead it should be legalized towards the widest vector that's still
1071 /// setAction({G_ADD, LLT::vector(8, 8)}, Legal);
1072 /// setAction({G_ADD, LLT::vector(16, 8)}, Legal);
1073 /// setAction({G_ADD, LLT::vector(2, 32)}, Legal);
1074 /// setAction({G_ADD, LLT::vector(4, 32)}, Legal);
1075 /// setLegalizeVectorElementToDifferentSizeStrategy(
1076 /// G_ADD, 0, moreToWiderTypesAndLessToWidest);
1077 /// will result in the following getAction results:
1078 /// * getAction({G_ADD, LLT::vector(8,8)}) returns
1079 /// (Legal, vector(8,8)).
1080 /// * getAction({G_ADD, LLT::vector(9,8)}) returns
1081 /// (MoreElements, vector(16,8)).
1082 /// * getAction({G_ADD, LLT::vector(8,32)}) returns
1083 /// (FewerElements, vector(4,32)).
1084 static SizeAndActionsVec
1085 moreToWiderTypesAndLessToWidest(const SizeAndActionsVec
&v
) {
1086 using namespace LegalizeActions
;
1087 return increaseToLargerTypesAndDecreaseToLargest(v
, MoreElements
,
1091 /// Helper function to implement many typical SizeChangeStrategy functions.
1092 static SizeAndActionsVec
1093 increaseToLargerTypesAndDecreaseToLargest(const SizeAndActionsVec
&v
,
1094 LegalizeAction IncreaseAction
,
1095 LegalizeAction DecreaseAction
);
1096 /// Helper function to implement many typical SizeChangeStrategy functions.
1097 static SizeAndActionsVec
1098 decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec
&v
,
1099 LegalizeAction DecreaseAction
,
1100 LegalizeAction IncreaseAction
);
1102 /// Get the action definitions for the given opcode. Use this to run a
1103 /// LegalityQuery through the definitions.
1104 const LegalizeRuleSet
&getActionDefinitions(unsigned Opcode
) const;
1106 /// Get the action definition builder for the given opcode. Use this to define
1107 /// the action definitions.
1109 /// It is an error to request an opcode that has already been requested by the
1110 /// multiple-opcode variant.
1111 LegalizeRuleSet
&getActionDefinitionsBuilder(unsigned Opcode
);
1113 /// Get the action definition builder for the given set of opcodes. Use this
1114 /// to define the action definitions for multiple opcodes at once. The first
1115 /// opcode given will be considered the representative opcode and will hold
1116 /// the definitions whereas the other opcodes will be configured to refer to
1117 /// the representative opcode. This lowers memory requirements and very
1118 /// slightly improves performance.
1120 /// It would be very easy to introduce unexpected side-effects as a result of
1121 /// this aliasing if it were permitted to request different but intersecting
1122 /// sets of opcodes but that is difficult to keep track of. It is therefore an
1123 /// error to request the same opcode twice using this API, to request an
1124 /// opcode that already has definitions, or to use the single-opcode API on an
1125 /// opcode that has already been requested by this API.
1127 getActionDefinitionsBuilder(std::initializer_list
<unsigned> Opcodes
);
1128 void aliasActionDefinitions(unsigned OpcodeTo
, unsigned OpcodeFrom
);
1130 /// Determine what action should be taken to legalize the described
1131 /// instruction. Requires computeTables to have been called.
1133 /// \returns a description of the next legalization step to perform.
1134 LegalizeActionStep
getAction(const LegalityQuery
&Query
) const;
1136 /// Determine what action should be taken to legalize the given generic
1139 /// \returns a description of the next legalization step to perform.
1140 LegalizeActionStep
getAction(const MachineInstr
&MI
,
1141 const MachineRegisterInfo
&MRI
) const;
1143 bool isLegal(const LegalityQuery
&Query
) const {
1144 return getAction(Query
).Action
== LegalizeAction::Legal
;
1146 bool isLegal(const MachineInstr
&MI
, const MachineRegisterInfo
&MRI
) const;
1147 bool isLegalOrCustom(const MachineInstr
&MI
,
1148 const MachineRegisterInfo
&MRI
) const;
1150 virtual bool legalizeCustom(MachineInstr
&MI
, MachineRegisterInfo
&MRI
,
1151 MachineIRBuilder
&MIRBuilder
,
1152 GISelChangeObserver
&Observer
) const;
1154 /// Return true if MI is either legal or has been legalized and false
1156 virtual bool legalizeIntrinsic(MachineInstr
&MI
, MachineRegisterInfo
&MRI
,
1157 MachineIRBuilder
&MIRBuilder
) const;
1160 /// Determine what action should be taken to legalize the given generic
1161 /// instruction opcode, type-index and type. Requires computeTables to have
1164 /// \returns a pair consisting of the kind of legalization that should be
1165 /// performed and the destination type.
1166 std::pair
<LegalizeAction
, LLT
>
1167 getAspectAction(const InstrAspect
&Aspect
) const;
1169 /// The SizeAndActionsVec is a representation mapping between all natural
1170 /// numbers and an Action. The natural number represents the bit size of
1171 /// the InstrAspect. For example, for a target with native support for 32-bit
1172 /// and 64-bit additions, you'd express that as:
1173 /// setScalarAction(G_ADD, 0,
1174 /// {{1, WidenScalar}, // bit sizes [ 1, 31[
1175 /// {32, Legal}, // bit sizes [32, 33[
1176 /// {33, WidenScalar}, // bit sizes [33, 64[
1177 /// {64, Legal}, // bit sizes [64, 65[
1178 /// {65, NarrowScalar} // bit sizes [65, +inf[
1180 /// It may be that only 64-bit pointers are supported on your target:
1181 /// setPointerAction(G_GEP, 0, LLT:pointer(1),
1182 /// {{1, Unsupported}, // bit sizes [ 1, 63[
1183 /// {64, Legal}, // bit sizes [64, 65[
1184 /// {65, Unsupported}, // bit sizes [65, +inf[
1186 void setScalarAction(const unsigned Opcode
, const unsigned TypeIndex
,
1187 const SizeAndActionsVec
&SizeAndActions
) {
1188 const unsigned OpcodeIdx
= Opcode
- FirstOp
;
1189 SmallVector
<SizeAndActionsVec
, 1> &Actions
= ScalarActions
[OpcodeIdx
];
1190 setActions(TypeIndex
, Actions
, SizeAndActions
);
1192 void setPointerAction(const unsigned Opcode
, const unsigned TypeIndex
,
1193 const unsigned AddressSpace
,
1194 const SizeAndActionsVec
&SizeAndActions
) {
1195 const unsigned OpcodeIdx
= Opcode
- FirstOp
;
1196 if (AddrSpace2PointerActions
[OpcodeIdx
].find(AddressSpace
) ==
1197 AddrSpace2PointerActions
[OpcodeIdx
].end())
1198 AddrSpace2PointerActions
[OpcodeIdx
][AddressSpace
] = {{}};
1199 SmallVector
<SizeAndActionsVec
, 1> &Actions
=
1200 AddrSpace2PointerActions
[OpcodeIdx
].find(AddressSpace
)->second
;
1201 setActions(TypeIndex
, Actions
, SizeAndActions
);
1204 /// If an operation on a given vector type (say <M x iN>) isn't explicitly
1205 /// specified, we proceed in 2 stages. First we legalize the underlying scalar
1206 /// (so that there's at least one legal vector with that scalar), then we
1207 /// adjust the number of elements in the vector so that it is legal. The
1208 /// desired action in the first step is controlled by this function.
1209 void setScalarInVectorAction(const unsigned Opcode
, const unsigned TypeIndex
,
1210 const SizeAndActionsVec
&SizeAndActions
) {
1211 unsigned OpcodeIdx
= Opcode
- FirstOp
;
1212 SmallVector
<SizeAndActionsVec
, 1> &Actions
=
1213 ScalarInVectorActions
[OpcodeIdx
];
1214 setActions(TypeIndex
, Actions
, SizeAndActions
);
1217 /// See also setScalarInVectorAction.
1218 /// This function let's you specify the number of elements in a vector that
1219 /// are legal for a legal element size.
1220 void setVectorNumElementAction(const unsigned Opcode
,
1221 const unsigned TypeIndex
,
1222 const unsigned ElementSize
,
1223 const SizeAndActionsVec
&SizeAndActions
) {
1224 const unsigned OpcodeIdx
= Opcode
- FirstOp
;
1225 if (NumElements2Actions
[OpcodeIdx
].find(ElementSize
) ==
1226 NumElements2Actions
[OpcodeIdx
].end())
1227 NumElements2Actions
[OpcodeIdx
][ElementSize
] = {{}};
1228 SmallVector
<SizeAndActionsVec
, 1> &Actions
=
1229 NumElements2Actions
[OpcodeIdx
].find(ElementSize
)->second
;
1230 setActions(TypeIndex
, Actions
, SizeAndActions
);
1233 /// A partial SizeAndActionsVec potentially doesn't cover all bit sizes,
1234 /// i.e. it's OK if it doesn't start from size 1.
1235 static void checkPartialSizeAndActionsVector(const SizeAndActionsVec
& v
) {
1236 using namespace LegalizeActions
;
1238 // The sizes should be in increasing order
1240 for(auto SizeAndAction
: v
) {
1241 assert(SizeAndAction
.first
> prev_size
);
1242 prev_size
= SizeAndAction
.first
;
1244 // - for every Widen action, there should be a larger bitsize that
1245 // can be legalized towards (e.g. Legal, Lower, Libcall or Custom
1247 // - for every Narrow action, there should be a smaller bitsize that
1248 // can be legalized towards.
1249 int SmallestNarrowIdx
= -1;
1250 int LargestWidenIdx
= -1;
1251 int SmallestLegalizableToSameSizeIdx
= -1;
1252 int LargestLegalizableToSameSizeIdx
= -1;
1253 for(size_t i
=0; i
<v
.size(); ++i
) {
1254 switch (v
[i
].second
) {
1257 if (SmallestNarrowIdx
== -1)
1258 SmallestNarrowIdx
= i
;
1262 LargestWidenIdx
= i
;
1267 if (SmallestLegalizableToSameSizeIdx
== -1)
1268 SmallestLegalizableToSameSizeIdx
= i
;
1269 LargestLegalizableToSameSizeIdx
= i
;
1272 if (SmallestNarrowIdx
!= -1) {
1273 assert(SmallestLegalizableToSameSizeIdx
!= -1);
1274 assert(SmallestNarrowIdx
> SmallestLegalizableToSameSizeIdx
);
1276 if (LargestWidenIdx
!= -1)
1277 assert(LargestWidenIdx
< LargestLegalizableToSameSizeIdx
);
1281 /// A full SizeAndActionsVec must cover all bit sizes, i.e. must start with
1283 static void checkFullSizeAndActionsVector(const SizeAndActionsVec
& v
) {
1285 // Data structure invariant: The first bit size must be size 1.
1286 assert(v
.size() >= 1);
1287 assert(v
[0].first
== 1);
1288 checkPartialSizeAndActionsVector(v
);
1292 /// Sets actions for all bit sizes on a particular generic opcode, type
1293 /// index and scalar or pointer type.
1294 void setActions(unsigned TypeIndex
,
1295 SmallVector
<SizeAndActionsVec
, 1> &Actions
,
1296 const SizeAndActionsVec
&SizeAndActions
) {
1297 checkFullSizeAndActionsVector(SizeAndActions
);
1298 if (Actions
.size() <= TypeIndex
)
1299 Actions
.resize(TypeIndex
+ 1);
1300 Actions
[TypeIndex
] = SizeAndActions
;
1303 static SizeAndAction
findAction(const SizeAndActionsVec
&Vec
,
1304 const uint32_t Size
);
1306 /// Returns the next action needed to get the scalar or pointer type closer
1308 /// E.g. findLegalAction({G_REM, 13}) should return
1309 /// (WidenScalar, 32). After that, findLegalAction({G_REM, 32}) will
1310 /// probably be called, which should return (Lower, 32).
1311 /// This is assuming the setScalarAction on G_REM was something like:
1312 /// setScalarAction(G_REM, 0,
1313 /// {{1, WidenScalar}, // bit sizes [ 1, 31[
1314 /// {32, Lower}, // bit sizes [32, 33[
1315 /// {33, NarrowScalar} // bit sizes [65, +inf[
1317 std::pair
<LegalizeAction
, LLT
>
1318 findScalarLegalAction(const InstrAspect
&Aspect
) const;
1320 /// Returns the next action needed towards legalizing the vector type.
1321 std::pair
<LegalizeAction
, LLT
>
1322 findVectorLegalAction(const InstrAspect
&Aspect
) const;
1324 static const int FirstOp
= TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START
;
1325 static const int LastOp
= TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END
;
1327 // Data structures used temporarily during construction of legality data:
1328 using TypeMap
= DenseMap
<LLT
, LegalizeAction
>;
1329 SmallVector
<TypeMap
, 1> SpecifiedActions
[LastOp
- FirstOp
+ 1];
1330 SmallVector
<SizeChangeStrategy
, 1>
1331 ScalarSizeChangeStrategies
[LastOp
- FirstOp
+ 1];
1332 SmallVector
<SizeChangeStrategy
, 1>
1333 VectorElementSizeChangeStrategies
[LastOp
- FirstOp
+ 1];
1334 bool TablesInitialized
;
1336 // Data structures used by getAction:
1337 SmallVector
<SizeAndActionsVec
, 1> ScalarActions
[LastOp
- FirstOp
+ 1];
1338 SmallVector
<SizeAndActionsVec
, 1> ScalarInVectorActions
[LastOp
- FirstOp
+ 1];
1339 std::unordered_map
<uint16_t, SmallVector
<SizeAndActionsVec
, 1>>
1340 AddrSpace2PointerActions
[LastOp
- FirstOp
+ 1];
1341 std::unordered_map
<uint16_t, SmallVector
<SizeAndActionsVec
, 1>>
1342 NumElements2Actions
[LastOp
- FirstOp
+ 1];
1344 LegalizeRuleSet RulesForOpcode
[LastOp
- FirstOp
+ 1];
1348 /// Checks that MIR is fully legal, returns an illegal instruction if it's not,
1349 /// nullptr otherwise
1350 const MachineInstr
*machineFunctionIsIllegal(const MachineFunction
&MF
);
1353 } // end namespace llvm.
1355 #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H