blob: 59791738fdf6c3699673f4379c7219fb3c90a5e9 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- llvm/CodeGen/GlobalISel/LegalizerInfo.h ------------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
7//===----------------------------------------------------------------------===//
8//
9/// Interface for Targets to specify which operations they can successfully
10/// select and how the others should be expanded most efficiently.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
15#define LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
16
17#include "llvm/ADT/DenseMap.h"
18#include "llvm/ADT/None.h"
19#include "llvm/ADT/Optional.h"
20#include "llvm/ADT/STLExtras.h"
Andrew Scullcdfcccc2018-10-05 20:58:37 +010021#include "llvm/ADT/SmallBitVector.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010022#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"
27#include <cassert>
28#include <cstdint>
29#include <tuple>
30#include <unordered_map>
31#include <utility>
32
33namespace llvm {
34
35extern cl::opt<bool> DisableGISelLegalityCheck;
36
37class MachineInstr;
38class MachineIRBuilder;
39class MachineRegisterInfo;
Andrew Scullcdfcccc2018-10-05 20:58:37 +010040class MCInstrInfo;
Andrew Walbran16937d02019-10-22 13:54:20 +010041class GISelChangeObserver;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010042
43namespace LegalizeActions {
44enum LegalizeAction : std::uint8_t {
45 /// The operation is expected to be selectable directly by the target, and
46 /// no transformation is necessary.
47 Legal,
48
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.
52 NarrowScalar,
53
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).
57 WidenScalar,
58
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.
62 FewerElements,
63
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.
68 MoreElements,
69
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.
72 Lower,
73
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.
77 Libcall,
78
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.
81 Custom,
82
83 /// This operation is completely unsupported on the target. A programming
84 /// error has occurred.
85 Unsupported,
86
87 /// Sentinel value for when no action was found in the specified table.
88 NotFound,
89
90 /// Fall back onto the old rules.
91 /// TODO: Remove this once we've migrated
92 UseLegacyRules,
93};
94} // end namespace LegalizeActions
95
96using LegalizeActions::LegalizeAction;
97
98/// Legalization is decided based on an instruction's opcode, which type slot
99/// we're considering, and what the existing type is. These aspects are gathered
100/// together for convenience in the InstrAspect class.
101struct InstrAspect {
102 unsigned Opcode;
103 unsigned Idx = 0;
104 LLT Type;
105
106 InstrAspect(unsigned Opcode, LLT Type) : Opcode(Opcode), Type(Type) {}
107 InstrAspect(unsigned Opcode, unsigned Idx, LLT Type)
108 : Opcode(Opcode), Idx(Idx), Type(Type) {}
109
110 bool operator==(const InstrAspect &RHS) const {
111 return Opcode == RHS.Opcode && Idx == RHS.Idx && Type == RHS.Type;
112 }
113};
114
115/// The LegalityQuery object bundles together all the information that's needed
116/// to decide whether a given operation is legal or not.
117/// For efficiency, it doesn't make a copy of Types so care must be taken not
118/// to free it before using the query.
119struct LegalityQuery {
120 unsigned Opcode;
121 ArrayRef<LLT> Types;
122
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100123 struct MemDesc {
Andrew Walbran16937d02019-10-22 13:54:20 +0100124 uint64_t SizeInBits;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100125 AtomicOrdering Ordering;
126 };
127
128 /// Operations which require memory can use this to place requirements on the
129 /// memory type for each MMO.
130 ArrayRef<MemDesc> MMODescrs;
131
132 constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types,
133 const ArrayRef<MemDesc> MMODescrs)
134 : Opcode(Opcode), Types(Types), MMODescrs(MMODescrs) {}
135 constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types)
136 : LegalityQuery(Opcode, Types, {}) {}
137
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100138 raw_ostream &print(raw_ostream &OS) const;
139};
140
141/// The result of a query. It either indicates a final answer of Legal or
142/// Unsupported or describes an action that must be taken to make an operation
143/// more legal.
144struct LegalizeActionStep {
145 /// The action to take or the final answer.
146 LegalizeAction Action;
147 /// If describing an action, the type index to change. Otherwise zero.
148 unsigned TypeIdx;
149 /// If describing an action, the new type for TypeIdx. Otherwise LLT{}.
150 LLT NewType;
151
152 LegalizeActionStep(LegalizeAction Action, unsigned TypeIdx,
153 const LLT &NewType)
154 : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {}
155
156 bool operator==(const LegalizeActionStep &RHS) const {
157 return std::tie(Action, TypeIdx, NewType) ==
158 std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType);
159 }
160};
161
162using LegalityPredicate = std::function<bool (const LegalityQuery &)>;
163using LegalizeMutation =
164 std::function<std::pair<unsigned, LLT>(const LegalityQuery &)>;
165
166namespace LegalityPredicates {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100167struct TypePairAndMemSize {
168 LLT Type0;
169 LLT Type1;
170 uint64_t MemSize;
171
172 bool operator==(const TypePairAndMemSize &Other) const {
173 return Type0 == Other.Type0 && Type1 == Other.Type1 &&
174 MemSize == Other.MemSize;
175 }
176};
177
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100178/// True iff P0 and P1 are true.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100179template<typename Predicate>
180Predicate all(Predicate P0, Predicate P1) {
181 return [=](const LegalityQuery &Query) {
182 return P0(Query) && P1(Query);
183 };
184}
185/// True iff all given predicates are true.
186template<typename Predicate, typename... Args>
187Predicate all(Predicate P0, Predicate P1, Args... args) {
188 return all(all(P0, P1), args...);
189}
190/// True iff the given type index is the specified types.
191LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100192/// True iff the given type index is one of the specified types.
193LegalityPredicate typeInSet(unsigned TypeIdx,
194 std::initializer_list<LLT> TypesInit);
195/// True iff the given types for the given pair of type indexes is one of the
196/// specified type pairs.
197LegalityPredicate
198typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1,
199 std::initializer_list<std::pair<LLT, LLT>> TypesInit);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100200/// True iff the given types for the given pair of type indexes is one of the
201/// specified type pairs.
202LegalityPredicate typePairAndMemSizeInSet(
203 unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx,
204 std::initializer_list<TypePairAndMemSize> TypesAndMemSizeInit);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100205/// True iff the specified type index is a scalar.
206LegalityPredicate isScalar(unsigned TypeIdx);
Andrew Walbran16937d02019-10-22 13:54:20 +0100207/// True iff the specified type index is a vector.
208LegalityPredicate isVector(unsigned TypeIdx);
209/// True iff the specified type index is a pointer (with any address space).
210LegalityPredicate isPointer(unsigned TypeIdx);
211/// True iff the specified type index is a pointer with the specified address
212/// space.
213LegalityPredicate isPointer(unsigned TypeIdx, unsigned AddrSpace);
214
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100215/// True iff the specified type index is a scalar that's narrower than the given
216/// size.
217LegalityPredicate narrowerThan(unsigned TypeIdx, unsigned Size);
Andrew Walbran16937d02019-10-22 13:54:20 +0100218
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100219/// True iff the specified type index is a scalar that's wider than the given
220/// size.
221LegalityPredicate widerThan(unsigned TypeIdx, unsigned Size);
Andrew Walbran16937d02019-10-22 13:54:20 +0100222
223/// True iff the specified type index is a scalar or vector with an element type
224/// that's narrower than the given size.
225LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size);
226
227/// True iff the specified type index is a scalar or a vector with an element
228/// type that's wider than the given size.
229LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size);
230
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100231/// True iff the specified type index is a scalar whose size is not a power of
232/// 2.
233LegalityPredicate sizeNotPow2(unsigned TypeIdx);
Andrew Walbran16937d02019-10-22 13:54:20 +0100234
235/// True iff the specified type index is a scalar or vector whose element size
236/// is not a power of 2.
237LegalityPredicate scalarOrEltSizeNotPow2(unsigned TypeIdx);
238
239/// True iff the specified type indices are both the same bit size.
240LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100241/// True iff the specified MMO index has a size that is not a power of 2
242LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100243/// True iff the specified type index is a vector whose element count is not a
244/// power of 2.
245LegalityPredicate numElementsNotPow2(unsigned TypeIdx);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100246/// True iff the specified MMO index has at an atomic ordering of at Ordering or
247/// stronger.
248LegalityPredicate atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx,
249 AtomicOrdering Ordering);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100250} // end namespace LegalityPredicates
251
252namespace LegalizeMutations {
253/// Select this specific type for the given type index.
254LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty);
Andrew Walbran16937d02019-10-22 13:54:20 +0100255
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100256/// Keep the same type as the given type index.
257LegalizeMutation changeTo(unsigned TypeIdx, unsigned FromTypeIdx);
Andrew Walbran16937d02019-10-22 13:54:20 +0100258
259/// Keep the same scalar or element type as the given type index.
260LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx);
261
262/// Keep the same scalar or element type as the given type.
263LegalizeMutation changeElementTo(unsigned TypeIdx, LLT Ty);
264
265/// Widen the scalar type or vector element type for the given type index to the
266/// next power of 2.
267LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min = 0);
268
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100269/// Add more elements to the type for the given type index to the next power of
270/// 2.
271LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min = 0);
Andrew Walbran16937d02019-10-22 13:54:20 +0100272/// Break up the vector type for the given type index into the element type.
273LegalizeMutation scalarize(unsigned TypeIdx);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100274} // end namespace LegalizeMutations
275
276/// A single rule in a legalizer info ruleset.
277/// The specified action is chosen when the predicate is true. Where appropriate
278/// for the action (e.g. for WidenScalar) the new type is selected using the
279/// given mutator.
280class LegalizeRule {
281 LegalityPredicate Predicate;
282 LegalizeAction Action;
283 LegalizeMutation Mutation;
284
285public:
286 LegalizeRule(LegalityPredicate Predicate, LegalizeAction Action,
287 LegalizeMutation Mutation = nullptr)
288 : Predicate(Predicate), Action(Action), Mutation(Mutation) {}
289
290 /// Test whether the LegalityQuery matches.
291 bool match(const LegalityQuery &Query) const {
292 return Predicate(Query);
293 }
294
295 LegalizeAction getAction() const { return Action; }
296
297 /// Determine the change to make.
298 std::pair<unsigned, LLT> determineMutation(const LegalityQuery &Query) const {
299 if (Mutation)
300 return Mutation(Query);
301 return std::make_pair(0, LLT{});
302 }
303};
304
305class LegalizeRuleSet {
306 /// When non-zero, the opcode we are an alias of
307 unsigned AliasOf;
308 /// If true, there is another opcode that aliases this one
309 bool IsAliasedByAnother;
310 SmallVector<LegalizeRule, 2> Rules;
311
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100312#ifndef NDEBUG
313 /// If bit I is set, this rule set contains a rule that may handle (predicate
314 /// or perform an action upon (or both)) the type index I. The uncertainty
315 /// comes from free-form rules executing user-provided lambda functions. We
316 /// conservatively assume such rules do the right thing and cover all type
317 /// indices. The bitset is intentionally 1 bit wider than it absolutely needs
318 /// to be to distinguish such cases from the cases where all type indices are
319 /// individually handled.
320 SmallBitVector TypeIdxsCovered{MCOI::OPERAND_LAST_GENERIC -
321 MCOI::OPERAND_FIRST_GENERIC + 2};
322#endif
323
324 unsigned typeIdx(unsigned TypeIdx) {
325 assert(TypeIdx <=
326 (MCOI::OPERAND_LAST_GENERIC - MCOI::OPERAND_FIRST_GENERIC) &&
327 "Type Index is out of bounds");
328#ifndef NDEBUG
329 TypeIdxsCovered.set(TypeIdx);
330#endif
331 return TypeIdx;
332 }
333 void markAllTypeIdxsAsCovered() {
334#ifndef NDEBUG
335 TypeIdxsCovered.set();
336#endif
337 }
338
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100339 void add(const LegalizeRule &Rule) {
340 assert(AliasOf == 0 &&
341 "RuleSet is aliased, change the representative opcode instead");
342 Rules.push_back(Rule);
343 }
344
345 static bool always(const LegalityQuery &) { return true; }
346
347 /// Use the given action when the predicate is true.
348 /// Action should not be an action that requires mutation.
349 LegalizeRuleSet &actionIf(LegalizeAction Action,
350 LegalityPredicate Predicate) {
351 add({Predicate, Action});
352 return *this;
353 }
354 /// Use the given action when the predicate is true.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100355 /// Action should be an action that requires mutation.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100356 LegalizeRuleSet &actionIf(LegalizeAction Action, LegalityPredicate Predicate,
357 LegalizeMutation Mutation) {
358 add({Predicate, Action, Mutation});
359 return *this;
360 }
361 /// Use the given action when type index 0 is any type in the given list.
362 /// Action should not be an action that requires mutation.
363 LegalizeRuleSet &actionFor(LegalizeAction Action,
364 std::initializer_list<LLT> Types) {
365 using namespace LegalityPredicates;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100366 return actionIf(Action, typeInSet(typeIdx(0), Types));
367 }
368 /// Use the given action when type index 0 is any type in the given list.
369 /// Action should be an action that requires mutation.
370 LegalizeRuleSet &actionFor(LegalizeAction Action,
371 std::initializer_list<LLT> Types,
372 LegalizeMutation Mutation) {
373 using namespace LegalityPredicates;
374 return actionIf(Action, typeInSet(typeIdx(0), Types), Mutation);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100375 }
376 /// Use the given action when type indexes 0 and 1 is any type pair in the
377 /// given list.
378 /// Action should not be an action that requires mutation.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100379 LegalizeRuleSet &actionFor(LegalizeAction Action,
380 std::initializer_list<std::pair<LLT, LLT>> Types) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100381 using namespace LegalityPredicates;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100382 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types));
383 }
384 /// Use the given action when type indexes 0 and 1 is any type pair in the
385 /// given list.
386 /// Action should be an action that requires mutation.
387 LegalizeRuleSet &actionFor(LegalizeAction Action,
388 std::initializer_list<std::pair<LLT, LLT>> Types,
389 LegalizeMutation Mutation) {
390 using namespace LegalityPredicates;
391 return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types),
392 Mutation);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100393 }
394 /// Use the given action when type indexes 0 and 1 are both in the given list.
395 /// That is, the type pair is in the cartesian product of the list.
396 /// Action should not be an action that requires mutation.
397 LegalizeRuleSet &actionForCartesianProduct(LegalizeAction Action,
398 std::initializer_list<LLT> Types) {
399 using namespace LegalityPredicates;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100400 return actionIf(Action, all(typeInSet(typeIdx(0), Types),
401 typeInSet(typeIdx(1), Types)));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100402 }
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100403 /// Use the given action when type indexes 0 and 1 are both in their
404 /// respective lists.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100405 /// That is, the type pair is in the cartesian product of the lists
406 /// Action should not be an action that requires mutation.
407 LegalizeRuleSet &
408 actionForCartesianProduct(LegalizeAction Action,
409 std::initializer_list<LLT> Types0,
410 std::initializer_list<LLT> Types1) {
411 using namespace LegalityPredicates;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100412 return actionIf(Action, all(typeInSet(typeIdx(0), Types0),
413 typeInSet(typeIdx(1), Types1)));
414 }
415 /// Use the given action when type indexes 0, 1, and 2 are all in their
416 /// respective lists.
417 /// That is, the type triple is in the cartesian product of the lists
418 /// Action should not be an action that requires mutation.
419 LegalizeRuleSet &actionForCartesianProduct(
420 LegalizeAction Action, std::initializer_list<LLT> Types0,
421 std::initializer_list<LLT> Types1, std::initializer_list<LLT> Types2) {
422 using namespace LegalityPredicates;
423 return actionIf(Action, all(typeInSet(typeIdx(0), Types0),
424 all(typeInSet(typeIdx(1), Types1),
425 typeInSet(typeIdx(2), Types2))));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100426 }
427
428public:
429 LegalizeRuleSet() : AliasOf(0), IsAliasedByAnother(false), Rules() {}
430
431 bool isAliasedByAnother() { return IsAliasedByAnother; }
432 void setIsAliasedByAnother() { IsAliasedByAnother = true; }
433 void aliasTo(unsigned Opcode) {
434 assert((AliasOf == 0 || AliasOf == Opcode) &&
435 "Opcode is already aliased to another opcode");
436 assert(Rules.empty() && "Aliasing will discard rules");
437 AliasOf = Opcode;
438 }
439 unsigned getAlias() const { return AliasOf; }
440
441 /// The instruction is legal if predicate is true.
442 LegalizeRuleSet &legalIf(LegalityPredicate Predicate) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100443 // We have no choice but conservatively assume that the free-form
444 // user-provided Predicate properly handles all type indices:
445 markAllTypeIdxsAsCovered();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100446 return actionIf(LegalizeAction::Legal, Predicate);
447 }
448 /// The instruction is legal when type index 0 is any type in the given list.
449 LegalizeRuleSet &legalFor(std::initializer_list<LLT> Types) {
450 return actionFor(LegalizeAction::Legal, Types);
451 }
452 /// The instruction is legal when type indexes 0 and 1 is any type pair in the
453 /// given list.
454 LegalizeRuleSet &legalFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
455 return actionFor(LegalizeAction::Legal, Types);
456 }
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100457 /// The instruction is legal when type indexes 0 and 1 along with the memory
458 /// size is any type and size tuple in the given list.
459 LegalizeRuleSet &legalForTypesWithMemSize(
460 std::initializer_list<LegalityPredicates::TypePairAndMemSize>
461 TypesAndMemSize) {
462 return actionIf(LegalizeAction::Legal,
463 LegalityPredicates::typePairAndMemSizeInSet(
464 typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemSize));
465 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100466 /// The instruction is legal when type indexes 0 and 1 are both in the given
467 /// list. That is, the type pair is in the cartesian product of the list.
468 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types) {
469 return actionForCartesianProduct(LegalizeAction::Legal, Types);
470 }
471 /// The instruction is legal when type indexes 0 and 1 are both their
472 /// respective lists.
473 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0,
474 std::initializer_list<LLT> Types1) {
475 return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1);
476 }
477
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100478 /// The instruction is lowered.
479 LegalizeRuleSet &lower() {
480 using namespace LegalizeMutations;
481 // We have no choice but conservatively assume that predicate-less lowering
482 // properly handles all type indices by design:
483 markAllTypeIdxsAsCovered();
484 return actionIf(LegalizeAction::Lower, always);
485 }
486 /// The instruction is lowered if predicate is true. Keep type index 0 as the
487 /// same type.
488 LegalizeRuleSet &lowerIf(LegalityPredicate Predicate) {
489 using namespace LegalizeMutations;
490 // We have no choice but conservatively assume that lowering with a
491 // free-form user provided Predicate properly handles all type indices:
492 markAllTypeIdxsAsCovered();
493 return actionIf(LegalizeAction::Lower, Predicate);
494 }
495 /// The instruction is lowered if predicate is true.
496 LegalizeRuleSet &lowerIf(LegalityPredicate Predicate,
497 LegalizeMutation Mutation) {
498 // We have no choice but conservatively assume that lowering with a
499 // free-form user provided Predicate properly handles all type indices:
500 markAllTypeIdxsAsCovered();
501 return actionIf(LegalizeAction::Lower, Predicate, Mutation);
502 }
503 /// The instruction is lowered when type index 0 is any type in the given
504 /// list. Keep type index 0 as the same type.
505 LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types) {
506 return actionFor(LegalizeAction::Lower, Types,
507 LegalizeMutations::changeTo(0, 0));
508 }
509 /// The instruction is lowered when type index 0 is any type in the given
510 /// list.
511 LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types,
512 LegalizeMutation Mutation) {
513 return actionFor(LegalizeAction::Lower, Types, Mutation);
514 }
515 /// The instruction is lowered when type indexes 0 and 1 is any type pair in
516 /// the given list. Keep type index 0 as the same type.
517 LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
518 return actionFor(LegalizeAction::Lower, Types,
519 LegalizeMutations::changeTo(0, 0));
520 }
521 /// The instruction is lowered when type indexes 0 and 1 is any type pair in
522 /// the given list.
523 LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types,
524 LegalizeMutation Mutation) {
525 return actionFor(LegalizeAction::Lower, Types, Mutation);
526 }
527 /// The instruction is lowered when type indexes 0 and 1 are both in their
528 /// respective lists.
529 LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0,
530 std::initializer_list<LLT> Types1) {
531 using namespace LegalityPredicates;
532 return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1);
533 }
534 /// The instruction is lowered when when type indexes 0, 1, and 2 are all in
535 /// their respective lists.
536 LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0,
537 std::initializer_list<LLT> Types1,
538 std::initializer_list<LLT> Types2) {
539 using namespace LegalityPredicates;
540 return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1,
541 Types2);
542 }
543
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100544 /// Like legalIf, but for the Libcall action.
545 LegalizeRuleSet &libcallIf(LegalityPredicate Predicate) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100546 // We have no choice but conservatively assume that a libcall with a
547 // free-form user provided Predicate properly handles all type indices:
548 markAllTypeIdxsAsCovered();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100549 return actionIf(LegalizeAction::Libcall, Predicate);
550 }
551 LegalizeRuleSet &libcallFor(std::initializer_list<LLT> Types) {
552 return actionFor(LegalizeAction::Libcall, Types);
553 }
554 LegalizeRuleSet &
555 libcallFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
556 return actionFor(LegalizeAction::Libcall, Types);
557 }
558 LegalizeRuleSet &
559 libcallForCartesianProduct(std::initializer_list<LLT> Types) {
560 return actionForCartesianProduct(LegalizeAction::Libcall, Types);
561 }
562 LegalizeRuleSet &
563 libcallForCartesianProduct(std::initializer_list<LLT> Types0,
564 std::initializer_list<LLT> Types1) {
565 return actionForCartesianProduct(LegalizeAction::Libcall, Types0, Types1);
566 }
567
568 /// Widen the scalar to the one selected by the mutation if the predicate is
569 /// true.
570 LegalizeRuleSet &widenScalarIf(LegalityPredicate Predicate,
571 LegalizeMutation Mutation) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100572 // We have no choice but conservatively assume that an action with a
573 // free-form user provided Predicate properly handles all type indices:
574 markAllTypeIdxsAsCovered();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100575 return actionIf(LegalizeAction::WidenScalar, Predicate, Mutation);
576 }
577 /// Narrow the scalar to the one selected by the mutation if the predicate is
578 /// true.
579 LegalizeRuleSet &narrowScalarIf(LegalityPredicate Predicate,
580 LegalizeMutation Mutation) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100581 // We have no choice but conservatively assume that an action with a
582 // free-form user provided Predicate properly handles all type indices:
583 markAllTypeIdxsAsCovered();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100584 return actionIf(LegalizeAction::NarrowScalar, Predicate, Mutation);
585 }
586
587 /// Add more elements to reach the type selected by the mutation if the
588 /// predicate is true.
589 LegalizeRuleSet &moreElementsIf(LegalityPredicate Predicate,
590 LegalizeMutation Mutation) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100591 // We have no choice but conservatively assume that an action with a
592 // free-form user provided Predicate properly handles all type indices:
593 markAllTypeIdxsAsCovered();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100594 return actionIf(LegalizeAction::MoreElements, Predicate, Mutation);
595 }
596 /// Remove elements to reach the type selected by the mutation if the
597 /// predicate is true.
598 LegalizeRuleSet &fewerElementsIf(LegalityPredicate Predicate,
599 LegalizeMutation Mutation) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100600 // We have no choice but conservatively assume that an action with a
601 // free-form user provided Predicate properly handles all type indices:
602 markAllTypeIdxsAsCovered();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100603 return actionIf(LegalizeAction::FewerElements, Predicate, Mutation);
604 }
605
606 /// The instruction is unsupported.
607 LegalizeRuleSet &unsupported() {
608 return actionIf(LegalizeAction::Unsupported, always);
609 }
610 LegalizeRuleSet &unsupportedIf(LegalityPredicate Predicate) {
611 return actionIf(LegalizeAction::Unsupported, Predicate);
612 }
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100613 LegalizeRuleSet &unsupportedIfMemSizeNotPow2() {
614 return actionIf(LegalizeAction::Unsupported,
615 LegalityPredicates::memSizeInBytesNotPow2(0));
616 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100617
618 LegalizeRuleSet &customIf(LegalityPredicate Predicate) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100619 // We have no choice but conservatively assume that a custom action with a
620 // free-form user provided Predicate properly handles all type indices:
621 markAllTypeIdxsAsCovered();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100622 return actionIf(LegalizeAction::Custom, Predicate);
623 }
624 LegalizeRuleSet &customFor(std::initializer_list<LLT> Types) {
625 return actionFor(LegalizeAction::Custom, Types);
626 }
627 LegalizeRuleSet &customForCartesianProduct(std::initializer_list<LLT> Types) {
628 return actionForCartesianProduct(LegalizeAction::Custom, Types);
629 }
630 LegalizeRuleSet &
631 customForCartesianProduct(std::initializer_list<LLT> Types0,
632 std::initializer_list<LLT> Types1) {
633 return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1);
634 }
635
Andrew Walbran16937d02019-10-22 13:54:20 +0100636 /// Unconditionally custom lower.
637 LegalizeRuleSet &custom() {
638 return customIf(always);
639 }
640
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100641 /// Widen the scalar to the next power of two that is at least MinSize.
642 /// No effect if the type is not a scalar or is a power of two.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100643 LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx,
644 unsigned MinSize = 0) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100645 using namespace LegalityPredicates;
Andrew Walbran16937d02019-10-22 13:54:20 +0100646 return actionIf(
647 LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)),
648 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize));
649 }
650
651 /// Widen the scalar or vector element type to the next power of two that is
652 /// at least MinSize. No effect if the scalar size is a power of two.
653 LegalizeRuleSet &widenScalarOrEltToNextPow2(unsigned TypeIdx,
654 unsigned MinSize = 0) {
655 using namespace LegalityPredicates;
656 return actionIf(
657 LegalizeAction::WidenScalar, scalarOrEltSizeNotPow2(typeIdx(TypeIdx)),
658 LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100659 }
660
661 LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) {
662 using namespace LegalityPredicates;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100663 return actionIf(LegalizeAction::NarrowScalar, isScalar(typeIdx(TypeIdx)),
664 Mutation);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100665 }
666
Andrew Walbran16937d02019-10-22 13:54:20 +0100667 LegalizeRuleSet &scalarize(unsigned TypeIdx) {
668 using namespace LegalityPredicates;
669 return actionIf(LegalizeAction::FewerElements, isVector(typeIdx(TypeIdx)),
670 LegalizeMutations::scalarize(TypeIdx));
671 }
672
673 /// Ensure the scalar is at least as wide as Ty.
674 LegalizeRuleSet &minScalarOrElt(unsigned TypeIdx, const LLT &Ty) {
675 using namespace LegalityPredicates;
676 using namespace LegalizeMutations;
677 return actionIf(LegalizeAction::WidenScalar,
678 scalarOrEltNarrowerThan(TypeIdx, Ty.getScalarSizeInBits()),
679 changeElementTo(typeIdx(TypeIdx), Ty));
680 }
681
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100682 /// Ensure the scalar is at least as wide as Ty.
683 LegalizeRuleSet &minScalar(unsigned TypeIdx, const LLT &Ty) {
684 using namespace LegalityPredicates;
685 using namespace LegalizeMutations;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100686 return actionIf(LegalizeAction::WidenScalar,
687 narrowerThan(TypeIdx, Ty.getSizeInBits()),
688 changeTo(typeIdx(TypeIdx), Ty));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100689 }
690
691 /// Ensure the scalar is at most as wide as Ty.
Andrew Walbran16937d02019-10-22 13:54:20 +0100692 LegalizeRuleSet &maxScalarOrElt(unsigned TypeIdx, const LLT &Ty) {
693 using namespace LegalityPredicates;
694 using namespace LegalizeMutations;
695 return actionIf(LegalizeAction::NarrowScalar,
696 scalarOrEltWiderThan(TypeIdx, Ty.getScalarSizeInBits()),
697 changeElementTo(typeIdx(TypeIdx), Ty));
698 }
699
700 /// Ensure the scalar is at most as wide as Ty.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100701 LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT &Ty) {
702 using namespace LegalityPredicates;
703 using namespace LegalizeMutations;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100704 return actionIf(LegalizeAction::NarrowScalar,
705 widerThan(TypeIdx, Ty.getSizeInBits()),
706 changeTo(typeIdx(TypeIdx), Ty));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100707 }
708
709 /// Conditionally limit the maximum size of the scalar.
710 /// For example, when the maximum size of one type depends on the size of
711 /// another such as extracting N bits from an M bit container.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100712 LegalizeRuleSet &maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx,
713 const LLT &Ty) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100714 using namespace LegalityPredicates;
715 using namespace LegalizeMutations;
Andrew Walbran16937d02019-10-22 13:54:20 +0100716 return actionIf(
717 LegalizeAction::NarrowScalar,
718 [=](const LegalityQuery &Query) {
719 return widerThan(TypeIdx, Ty.getSizeInBits()) && Predicate(Query);
720 },
721 changeElementTo(typeIdx(TypeIdx), Ty));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100722 }
723
724 /// Limit the range of scalar sizes to MinTy and MaxTy.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100725 LegalizeRuleSet &clampScalar(unsigned TypeIdx, const LLT &MinTy,
726 const LLT &MaxTy) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100727 assert(MinTy.isScalar() && MaxTy.isScalar() && "Expected scalar types");
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100728 return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100729 }
730
Andrew Walbran16937d02019-10-22 13:54:20 +0100731 /// Limit the range of scalar sizes to MinTy and MaxTy.
732 LegalizeRuleSet &clampScalarOrElt(unsigned TypeIdx, const LLT &MinTy,
733 const LLT &MaxTy) {
734 return minScalarOrElt(TypeIdx, MinTy).maxScalarOrElt(TypeIdx, MaxTy);
735 }
736
737 /// Widen the scalar to match the size of another.
738 LegalizeRuleSet &minScalarSameAs(unsigned TypeIdx, unsigned LargeTypeIdx) {
739 typeIdx(TypeIdx);
740 return widenScalarIf(
741 [=](const LegalityQuery &Query) {
742 return Query.Types[LargeTypeIdx].getScalarSizeInBits() >
743 Query.Types[TypeIdx].getSizeInBits();
744 },
745 [=](const LegalityQuery &Query) {
746 LLT T = Query.Types[LargeTypeIdx];
747 return std::make_pair(TypeIdx,
748 T.isVector() ? T.getElementType() : T);
749 });
750 }
751
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100752 /// Add more elements to the vector to reach the next power of two.
753 /// No effect if the type is not a vector or the element count is a power of
754 /// two.
755 LegalizeRuleSet &moreElementsToNextPow2(unsigned TypeIdx) {
756 using namespace LegalityPredicates;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100757 return actionIf(LegalizeAction::MoreElements,
758 numElementsNotPow2(typeIdx(TypeIdx)),
759 LegalizeMutations::moreElementsToNextPow2(TypeIdx));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100760 }
761
762 /// Limit the number of elements in EltTy vectors to at least MinElements.
763 LegalizeRuleSet &clampMinNumElements(unsigned TypeIdx, const LLT &EltTy,
764 unsigned MinElements) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100765 // Mark the type index as covered:
766 typeIdx(TypeIdx);
767 return actionIf(
768 LegalizeAction::MoreElements,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100769 [=](const LegalityQuery &Query) {
770 LLT VecTy = Query.Types[TypeIdx];
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100771 return VecTy.isVector() && VecTy.getElementType() == EltTy &&
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100772 VecTy.getNumElements() < MinElements;
773 },
774 [=](const LegalityQuery &Query) {
775 LLT VecTy = Query.Types[TypeIdx];
776 return std::make_pair(
Andrew Walbran16937d02019-10-22 13:54:20 +0100777 TypeIdx, LLT::vector(MinElements, VecTy.getElementType()));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100778 });
779 }
780 /// Limit the number of elements in EltTy vectors to at most MaxElements.
781 LegalizeRuleSet &clampMaxNumElements(unsigned TypeIdx, const LLT &EltTy,
782 unsigned MaxElements) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100783 // Mark the type index as covered:
784 typeIdx(TypeIdx);
785 return actionIf(
786 LegalizeAction::FewerElements,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100787 [=](const LegalityQuery &Query) {
788 LLT VecTy = Query.Types[TypeIdx];
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100789 return VecTy.isVector() && VecTy.getElementType() == EltTy &&
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100790 VecTy.getNumElements() > MaxElements;
791 },
792 [=](const LegalityQuery &Query) {
793 LLT VecTy = Query.Types[TypeIdx];
Andrew Walbran16937d02019-10-22 13:54:20 +0100794 LLT NewTy = LLT::scalarOrVector(MaxElements, VecTy.getElementType());
795 return std::make_pair(TypeIdx, NewTy);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100796 });
797 }
798 /// Limit the number of elements for the given vectors to at least MinTy's
799 /// number of elements and at most MaxTy's number of elements.
800 ///
801 /// No effect if the type is not a vector or does not have the same element
802 /// type as the constraints.
803 /// The element type of MinTy and MaxTy must match.
804 LegalizeRuleSet &clampNumElements(unsigned TypeIdx, const LLT &MinTy,
805 const LLT &MaxTy) {
806 assert(MinTy.getElementType() == MaxTy.getElementType() &&
807 "Expected element types to agree");
808
809 const LLT &EltTy = MinTy.getElementType();
810 return clampMinNumElements(TypeIdx, EltTy, MinTy.getNumElements())
811 .clampMaxNumElements(TypeIdx, EltTy, MaxTy.getNumElements());
812 }
813
814 /// Fallback on the previous implementation. This should only be used while
815 /// porting a rule.
816 LegalizeRuleSet &fallback() {
817 add({always, LegalizeAction::UseLegacyRules});
818 return *this;
819 }
820
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100821 /// Check if there is no type index which is obviously not handled by the
822 /// LegalizeRuleSet in any way at all.
823 /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set.
824 bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const;
825
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100826 /// Apply the ruleset to the given LegalityQuery.
827 LegalizeActionStep apply(const LegalityQuery &Query) const;
828};
829
830class LegalizerInfo {
831public:
832 LegalizerInfo();
833 virtual ~LegalizerInfo() = default;
834
835 unsigned getOpcodeIdxForOpcode(unsigned Opcode) const;
836 unsigned getActionDefinitionsIdx(unsigned Opcode) const;
837
838 /// Compute any ancillary tables needed to quickly decide how an operation
839 /// should be handled. This must be called after all "set*Action"methods but
840 /// before any query is made or incorrect results may be returned.
841 void computeTables();
842
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100843 /// Perform simple self-diagnostic and assert if there is anything obviously
844 /// wrong with the actions set up.
845 void verify(const MCInstrInfo &MII) const;
846
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100847 static bool needsLegalizingToDifferentSize(const LegalizeAction Action) {
848 using namespace LegalizeActions;
849 switch (Action) {
850 case NarrowScalar:
851 case WidenScalar:
852 case FewerElements:
853 case MoreElements:
854 case Unsupported:
855 return true;
856 default:
857 return false;
858 }
859 }
860
861 using SizeAndAction = std::pair<uint16_t, LegalizeAction>;
862 using SizeAndActionsVec = std::vector<SizeAndAction>;
863 using SizeChangeStrategy =
864 std::function<SizeAndActionsVec(const SizeAndActionsVec &v)>;
865
866 /// More friendly way to set an action for common types that have an LLT
867 /// representation.
868 /// The LegalizeAction must be one for which NeedsLegalizingToDifferentSize
869 /// returns false.
870 void setAction(const InstrAspect &Aspect, LegalizeAction Action) {
871 assert(!needsLegalizingToDifferentSize(Action));
872 TablesInitialized = false;
873 const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;
874 if (SpecifiedActions[OpcodeIdx].size() <= Aspect.Idx)
875 SpecifiedActions[OpcodeIdx].resize(Aspect.Idx + 1);
876 SpecifiedActions[OpcodeIdx][Aspect.Idx][Aspect.Type] = Action;
877 }
878
879 /// The setAction calls record the non-size-changing legalization actions
880 /// to take on specificly-sized types. The SizeChangeStrategy defines what
881 /// to do when the size of the type needs to be changed to reach a legally
882 /// sized type (i.e., one that was defined through a setAction call).
883 /// e.g.
884 /// setAction ({G_ADD, 0, LLT::scalar(32)}, Legal);
885 /// setLegalizeScalarToDifferentSizeStrategy(
886 /// G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100887 /// will end up defining getAction({G_ADD, 0, T}) to return the following
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100888 /// actions for different scalar types T:
889 /// LLT::scalar(1)..LLT::scalar(31): {WidenScalar, 0, LLT::scalar(32)}
890 /// LLT::scalar(32): {Legal, 0, LLT::scalar(32)}
891 /// LLT::scalar(33)..: {NarrowScalar, 0, LLT::scalar(32)}
892 ///
893 /// If no SizeChangeAction gets defined, through this function,
894 /// the default is unsupportedForDifferentSizes.
895 void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode,
896 const unsigned TypeIdx,
897 SizeChangeStrategy S) {
898 const unsigned OpcodeIdx = Opcode - FirstOp;
899 if (ScalarSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
900 ScalarSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
901 ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
902 }
903
904 /// See also setLegalizeScalarToDifferentSizeStrategy.
905 /// This function allows to set the SizeChangeStrategy for vector elements.
906 void setLegalizeVectorElementToDifferentSizeStrategy(const unsigned Opcode,
907 const unsigned TypeIdx,
908 SizeChangeStrategy S) {
909 const unsigned OpcodeIdx = Opcode - FirstOp;
910 if (VectorElementSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
911 VectorElementSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
912 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
913 }
914
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100915 /// A SizeChangeStrategy for the common case where legalization for a
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100916 /// particular operation consists of only supporting a specific set of type
917 /// sizes. E.g.
918 /// setAction ({G_DIV, 0, LLT::scalar(32)}, Legal);
919 /// setAction ({G_DIV, 0, LLT::scalar(64)}, Legal);
920 /// setLegalizeScalarToDifferentSizeStrategy(
921 /// G_DIV, 0, unsupportedForDifferentSizes);
922 /// will result in getAction({G_DIV, 0, T}) to return Legal for s32 and s64,
923 /// and Unsupported for all other scalar types T.
924 static SizeAndActionsVec
925 unsupportedForDifferentSizes(const SizeAndActionsVec &v) {
926 using namespace LegalizeActions;
927 return increaseToLargerTypesAndDecreaseToLargest(v, Unsupported,
928 Unsupported);
929 }
930
931 /// A SizeChangeStrategy for the common case where legalization for a
932 /// particular operation consists of widening the type to a large legal type,
933 /// unless there is no such type and then instead it should be narrowed to the
934 /// largest legal type.
935 static SizeAndActionsVec
936 widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v) {
937 using namespace LegalizeActions;
938 assert(v.size() > 0 &&
939 "At least one size that can be legalized towards is needed"
940 " for this SizeChangeStrategy");
941 return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
942 NarrowScalar);
943 }
944
945 static SizeAndActionsVec
946 widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v) {
947 using namespace LegalizeActions;
948 return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
949 Unsupported);
950 }
951
952 static SizeAndActionsVec
953 narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v) {
954 using namespace LegalizeActions;
955 return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
956 Unsupported);
957 }
958
959 static SizeAndActionsVec
960 narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec &v) {
961 using namespace LegalizeActions;
962 assert(v.size() > 0 &&
963 "At least one size that can be legalized towards is needed"
964 " for this SizeChangeStrategy");
965 return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
966 WidenScalar);
967 }
968
969 /// A SizeChangeStrategy for the common case where legalization for a
970 /// particular vector operation consists of having more elements in the
971 /// vector, to a type that is legal. Unless there is no such type and then
972 /// instead it should be legalized towards the widest vector that's still
973 /// legal. E.g.
974 /// setAction({G_ADD, LLT::vector(8, 8)}, Legal);
975 /// setAction({G_ADD, LLT::vector(16, 8)}, Legal);
976 /// setAction({G_ADD, LLT::vector(2, 32)}, Legal);
977 /// setAction({G_ADD, LLT::vector(4, 32)}, Legal);
978 /// setLegalizeVectorElementToDifferentSizeStrategy(
979 /// G_ADD, 0, moreToWiderTypesAndLessToWidest);
980 /// will result in the following getAction results:
981 /// * getAction({G_ADD, LLT::vector(8,8)}) returns
982 /// (Legal, vector(8,8)).
983 /// * getAction({G_ADD, LLT::vector(9,8)}) returns
984 /// (MoreElements, vector(16,8)).
985 /// * getAction({G_ADD, LLT::vector(8,32)}) returns
986 /// (FewerElements, vector(4,32)).
987 static SizeAndActionsVec
988 moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v) {
989 using namespace LegalizeActions;
990 return increaseToLargerTypesAndDecreaseToLargest(v, MoreElements,
991 FewerElements);
992 }
993
994 /// Helper function to implement many typical SizeChangeStrategy functions.
995 static SizeAndActionsVec
996 increaseToLargerTypesAndDecreaseToLargest(const SizeAndActionsVec &v,
997 LegalizeAction IncreaseAction,
998 LegalizeAction DecreaseAction);
999 /// Helper function to implement many typical SizeChangeStrategy functions.
1000 static SizeAndActionsVec
1001 decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec &v,
1002 LegalizeAction DecreaseAction,
1003 LegalizeAction IncreaseAction);
1004
1005 /// Get the action definitions for the given opcode. Use this to run a
1006 /// LegalityQuery through the definitions.
1007 const LegalizeRuleSet &getActionDefinitions(unsigned Opcode) const;
1008
1009 /// Get the action definition builder for the given opcode. Use this to define
1010 /// the action definitions.
1011 ///
1012 /// It is an error to request an opcode that has already been requested by the
1013 /// multiple-opcode variant.
1014 LegalizeRuleSet &getActionDefinitionsBuilder(unsigned Opcode);
1015
1016 /// Get the action definition builder for the given set of opcodes. Use this
1017 /// to define the action definitions for multiple opcodes at once. The first
1018 /// opcode given will be considered the representative opcode and will hold
1019 /// the definitions whereas the other opcodes will be configured to refer to
1020 /// the representative opcode. This lowers memory requirements and very
1021 /// slightly improves performance.
1022 ///
1023 /// It would be very easy to introduce unexpected side-effects as a result of
1024 /// this aliasing if it were permitted to request different but intersecting
1025 /// sets of opcodes but that is difficult to keep track of. It is therefore an
1026 /// error to request the same opcode twice using this API, to request an
1027 /// opcode that already has definitions, or to use the single-opcode API on an
1028 /// opcode that has already been requested by this API.
1029 LegalizeRuleSet &
1030 getActionDefinitionsBuilder(std::initializer_list<unsigned> Opcodes);
1031 void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom);
1032
1033 /// Determine what action should be taken to legalize the described
1034 /// instruction. Requires computeTables to have been called.
1035 ///
1036 /// \returns a description of the next legalization step to perform.
1037 LegalizeActionStep getAction(const LegalityQuery &Query) const;
1038
1039 /// Determine what action should be taken to legalize the given generic
1040 /// instruction.
1041 ///
1042 /// \returns a description of the next legalization step to perform.
1043 LegalizeActionStep getAction(const MachineInstr &MI,
1044 const MachineRegisterInfo &MRI) const;
1045
1046 bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
1047
Andrew Walbran16937d02019-10-22 13:54:20 +01001048 virtual bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI,
1049 MachineIRBuilder &MIRBuilder,
1050 GISelChangeObserver &Observer) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001051
1052private:
1053 /// Determine what action should be taken to legalize the given generic
1054 /// instruction opcode, type-index and type. Requires computeTables to have
1055 /// been called.
1056 ///
1057 /// \returns a pair consisting of the kind of legalization that should be
1058 /// performed and the destination type.
1059 std::pair<LegalizeAction, LLT>
1060 getAspectAction(const InstrAspect &Aspect) const;
1061
1062 /// The SizeAndActionsVec is a representation mapping between all natural
1063 /// numbers and an Action. The natural number represents the bit size of
1064 /// the InstrAspect. For example, for a target with native support for 32-bit
1065 /// and 64-bit additions, you'd express that as:
1066 /// setScalarAction(G_ADD, 0,
1067 /// {{1, WidenScalar}, // bit sizes [ 1, 31[
1068 /// {32, Legal}, // bit sizes [32, 33[
1069 /// {33, WidenScalar}, // bit sizes [33, 64[
1070 /// {64, Legal}, // bit sizes [64, 65[
1071 /// {65, NarrowScalar} // bit sizes [65, +inf[
1072 /// });
1073 /// It may be that only 64-bit pointers are supported on your target:
1074 /// setPointerAction(G_GEP, 0, LLT:pointer(1),
1075 /// {{1, Unsupported}, // bit sizes [ 1, 63[
1076 /// {64, Legal}, // bit sizes [64, 65[
1077 /// {65, Unsupported}, // bit sizes [65, +inf[
1078 /// });
1079 void setScalarAction(const unsigned Opcode, const unsigned TypeIndex,
1080 const SizeAndActionsVec &SizeAndActions) {
1081 const unsigned OpcodeIdx = Opcode - FirstOp;
1082 SmallVector<SizeAndActionsVec, 1> &Actions = ScalarActions[OpcodeIdx];
1083 setActions(TypeIndex, Actions, SizeAndActions);
1084 }
1085 void setPointerAction(const unsigned Opcode, const unsigned TypeIndex,
1086 const unsigned AddressSpace,
1087 const SizeAndActionsVec &SizeAndActions) {
1088 const unsigned OpcodeIdx = Opcode - FirstOp;
1089 if (AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace) ==
1090 AddrSpace2PointerActions[OpcodeIdx].end())
1091 AddrSpace2PointerActions[OpcodeIdx][AddressSpace] = {{}};
1092 SmallVector<SizeAndActionsVec, 1> &Actions =
1093 AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace)->second;
1094 setActions(TypeIndex, Actions, SizeAndActions);
1095 }
1096
1097 /// If an operation on a given vector type (say <M x iN>) isn't explicitly
1098 /// specified, we proceed in 2 stages. First we legalize the underlying scalar
1099 /// (so that there's at least one legal vector with that scalar), then we
1100 /// adjust the number of elements in the vector so that it is legal. The
1101 /// desired action in the first step is controlled by this function.
1102 void setScalarInVectorAction(const unsigned Opcode, const unsigned TypeIndex,
1103 const SizeAndActionsVec &SizeAndActions) {
1104 unsigned OpcodeIdx = Opcode - FirstOp;
1105 SmallVector<SizeAndActionsVec, 1> &Actions =
1106 ScalarInVectorActions[OpcodeIdx];
1107 setActions(TypeIndex, Actions, SizeAndActions);
1108 }
1109
1110 /// See also setScalarInVectorAction.
1111 /// This function let's you specify the number of elements in a vector that
1112 /// are legal for a legal element size.
1113 void setVectorNumElementAction(const unsigned Opcode,
1114 const unsigned TypeIndex,
1115 const unsigned ElementSize,
1116 const SizeAndActionsVec &SizeAndActions) {
1117 const unsigned OpcodeIdx = Opcode - FirstOp;
1118 if (NumElements2Actions[OpcodeIdx].find(ElementSize) ==
1119 NumElements2Actions[OpcodeIdx].end())
1120 NumElements2Actions[OpcodeIdx][ElementSize] = {{}};
1121 SmallVector<SizeAndActionsVec, 1> &Actions =
1122 NumElements2Actions[OpcodeIdx].find(ElementSize)->second;
1123 setActions(TypeIndex, Actions, SizeAndActions);
1124 }
1125
1126 /// A partial SizeAndActionsVec potentially doesn't cover all bit sizes,
1127 /// i.e. it's OK if it doesn't start from size 1.
1128 static void checkPartialSizeAndActionsVector(const SizeAndActionsVec& v) {
1129 using namespace LegalizeActions;
1130#ifndef NDEBUG
1131 // The sizes should be in increasing order
1132 int prev_size = -1;
1133 for(auto SizeAndAction: v) {
1134 assert(SizeAndAction.first > prev_size);
1135 prev_size = SizeAndAction.first;
1136 }
1137 // - for every Widen action, there should be a larger bitsize that
1138 // can be legalized towards (e.g. Legal, Lower, Libcall or Custom
1139 // action).
1140 // - for every Narrow action, there should be a smaller bitsize that
1141 // can be legalized towards.
1142 int SmallestNarrowIdx = -1;
1143 int LargestWidenIdx = -1;
1144 int SmallestLegalizableToSameSizeIdx = -1;
1145 int LargestLegalizableToSameSizeIdx = -1;
1146 for(size_t i=0; i<v.size(); ++i) {
1147 switch (v[i].second) {
1148 case FewerElements:
1149 case NarrowScalar:
1150 if (SmallestNarrowIdx == -1)
1151 SmallestNarrowIdx = i;
1152 break;
1153 case WidenScalar:
1154 case MoreElements:
1155 LargestWidenIdx = i;
1156 break;
1157 case Unsupported:
1158 break;
1159 default:
1160 if (SmallestLegalizableToSameSizeIdx == -1)
1161 SmallestLegalizableToSameSizeIdx = i;
1162 LargestLegalizableToSameSizeIdx = i;
1163 }
1164 }
1165 if (SmallestNarrowIdx != -1) {
1166 assert(SmallestLegalizableToSameSizeIdx != -1);
1167 assert(SmallestNarrowIdx > SmallestLegalizableToSameSizeIdx);
1168 }
1169 if (LargestWidenIdx != -1)
1170 assert(LargestWidenIdx < LargestLegalizableToSameSizeIdx);
1171#endif
1172 }
1173
1174 /// A full SizeAndActionsVec must cover all bit sizes, i.e. must start with
1175 /// from size 1.
1176 static void checkFullSizeAndActionsVector(const SizeAndActionsVec& v) {
1177#ifndef NDEBUG
1178 // Data structure invariant: The first bit size must be size 1.
1179 assert(v.size() >= 1);
1180 assert(v[0].first == 1);
1181 checkPartialSizeAndActionsVector(v);
1182#endif
1183 }
1184
1185 /// Sets actions for all bit sizes on a particular generic opcode, type
1186 /// index and scalar or pointer type.
1187 void setActions(unsigned TypeIndex,
1188 SmallVector<SizeAndActionsVec, 1> &Actions,
1189 const SizeAndActionsVec &SizeAndActions) {
1190 checkFullSizeAndActionsVector(SizeAndActions);
1191 if (Actions.size() <= TypeIndex)
1192 Actions.resize(TypeIndex + 1);
1193 Actions[TypeIndex] = SizeAndActions;
1194 }
1195
1196 static SizeAndAction findAction(const SizeAndActionsVec &Vec,
1197 const uint32_t Size);
1198
1199 /// Returns the next action needed to get the scalar or pointer type closer
1200 /// to being legal
1201 /// E.g. findLegalAction({G_REM, 13}) should return
1202 /// (WidenScalar, 32). After that, findLegalAction({G_REM, 32}) will
1203 /// probably be called, which should return (Lower, 32).
1204 /// This is assuming the setScalarAction on G_REM was something like:
1205 /// setScalarAction(G_REM, 0,
1206 /// {{1, WidenScalar}, // bit sizes [ 1, 31[
1207 /// {32, Lower}, // bit sizes [32, 33[
1208 /// {33, NarrowScalar} // bit sizes [65, +inf[
1209 /// });
1210 std::pair<LegalizeAction, LLT>
1211 findScalarLegalAction(const InstrAspect &Aspect) const;
1212
1213 /// Returns the next action needed towards legalizing the vector type.
1214 std::pair<LegalizeAction, LLT>
1215 findVectorLegalAction(const InstrAspect &Aspect) const;
1216
1217 static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
1218 static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
1219
1220 // Data structures used temporarily during construction of legality data:
1221 using TypeMap = DenseMap<LLT, LegalizeAction>;
1222 SmallVector<TypeMap, 1> SpecifiedActions[LastOp - FirstOp + 1];
1223 SmallVector<SizeChangeStrategy, 1>
1224 ScalarSizeChangeStrategies[LastOp - FirstOp + 1];
1225 SmallVector<SizeChangeStrategy, 1>
1226 VectorElementSizeChangeStrategies[LastOp - FirstOp + 1];
1227 bool TablesInitialized;
1228
1229 // Data structures used by getAction:
1230 SmallVector<SizeAndActionsVec, 1> ScalarActions[LastOp - FirstOp + 1];
1231 SmallVector<SizeAndActionsVec, 1> ScalarInVectorActions[LastOp - FirstOp + 1];
1232 std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
1233 AddrSpace2PointerActions[LastOp - FirstOp + 1];
1234 std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
1235 NumElements2Actions[LastOp - FirstOp + 1];
1236
1237 LegalizeRuleSet RulesForOpcode[LastOp - FirstOp + 1];
1238};
1239
1240#ifndef NDEBUG
1241/// Checks that MIR is fully legal, returns an illegal instruction if it's not,
1242/// nullptr otherwise
1243const MachineInstr *machineFunctionIsIllegal(const MachineFunction &MF);
1244#endif
1245
1246} // end namespace llvm.
1247
1248#endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H