blob: 117c791d299f4a5829ce2f97b6e650a024483903 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- llvm/CodeGen/GlobalISel/LegalizerInfo.h ------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10/// Interface for Targets to specify which operations they can successfully
11/// select and how the others should be expanded most efficiently.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
16#define LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
17
18#include "llvm/ADT/DenseMap.h"
19#include "llvm/ADT/None.h"
20#include "llvm/ADT/Optional.h"
21#include "llvm/ADT/STLExtras.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"
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;
40
41namespace LegalizeActions {
42enum LegalizeAction : std::uint8_t {
43 /// The operation is expected to be selectable directly by the target, and
44 /// no transformation is necessary.
45 Legal,
46
47 /// The operation should be synthesized from multiple instructions acting on
48 /// a narrower scalar base-type. For example a 64-bit add might be
49 /// implemented in terms of 32-bit add-with-carry.
50 NarrowScalar,
51
52 /// The operation should be implemented in terms of a wider scalar
53 /// base-type. For example a <2 x s8> add could be implemented as a <2
54 /// x s32> add (ignoring the high bits).
55 WidenScalar,
56
57 /// The (vector) operation should be implemented by splitting it into
58 /// sub-vectors where the operation is legal. For example a <8 x s64> add
59 /// might be implemented as 4 separate <2 x s64> adds.
60 FewerElements,
61
62 /// The (vector) operation should be implemented by widening the input
63 /// vector and ignoring the lanes added by doing so. For example <2 x i8> is
64 /// rarely legal, but you might perform an <8 x i8> and then only look at
65 /// the first two results.
66 MoreElements,
67
68 /// The operation itself must be expressed in terms of simpler actions on
69 /// this target. E.g. a SREM replaced by an SDIV and subtraction.
70 Lower,
71
72 /// The operation should be implemented as a call to some kind of runtime
73 /// support library. For example this usually happens on machines that don't
74 /// support floating-point operations natively.
75 Libcall,
76
77 /// The target wants to do something special with this combination of
78 /// operand and type. A callback will be issued when it is needed.
79 Custom,
80
81 /// This operation is completely unsupported on the target. A programming
82 /// error has occurred.
83 Unsupported,
84
85 /// Sentinel value for when no action was found in the specified table.
86 NotFound,
87
88 /// Fall back onto the old rules.
89 /// TODO: Remove this once we've migrated
90 UseLegacyRules,
91};
92} // end namespace LegalizeActions
93
94using LegalizeActions::LegalizeAction;
95
96/// Legalization is decided based on an instruction's opcode, which type slot
97/// we're considering, and what the existing type is. These aspects are gathered
98/// together for convenience in the InstrAspect class.
99struct InstrAspect {
100 unsigned Opcode;
101 unsigned Idx = 0;
102 LLT Type;
103
104 InstrAspect(unsigned Opcode, LLT Type) : Opcode(Opcode), Type(Type) {}
105 InstrAspect(unsigned Opcode, unsigned Idx, LLT Type)
106 : Opcode(Opcode), Idx(Idx), Type(Type) {}
107
108 bool operator==(const InstrAspect &RHS) const {
109 return Opcode == RHS.Opcode && Idx == RHS.Idx && Type == RHS.Type;
110 }
111};
112
113/// The LegalityQuery object bundles together all the information that's needed
114/// to decide whether a given operation is legal or not.
115/// For efficiency, it doesn't make a copy of Types so care must be taken not
116/// to free it before using the query.
117struct LegalityQuery {
118 unsigned Opcode;
119 ArrayRef<LLT> Types;
120
121 raw_ostream &print(raw_ostream &OS) const;
122};
123
124/// The result of a query. It either indicates a final answer of Legal or
125/// Unsupported or describes an action that must be taken to make an operation
126/// more legal.
127struct LegalizeActionStep {
128 /// The action to take or the final answer.
129 LegalizeAction Action;
130 /// If describing an action, the type index to change. Otherwise zero.
131 unsigned TypeIdx;
132 /// If describing an action, the new type for TypeIdx. Otherwise LLT{}.
133 LLT NewType;
134
135 LegalizeActionStep(LegalizeAction Action, unsigned TypeIdx,
136 const LLT &NewType)
137 : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {}
138
139 bool operator==(const LegalizeActionStep &RHS) const {
140 return std::tie(Action, TypeIdx, NewType) ==
141 std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType);
142 }
143};
144
145using LegalityPredicate = std::function<bool (const LegalityQuery &)>;
146using LegalizeMutation =
147 std::function<std::pair<unsigned, LLT>(const LegalityQuery &)>;
148
149namespace LegalityPredicates {
150/// True iff P0 and P1 are true.
151LegalityPredicate all(LegalityPredicate P0, LegalityPredicate P1);
152/// True iff the given type index is one of the specified types.
153LegalityPredicate typeInSet(unsigned TypeIdx,
154 std::initializer_list<LLT> TypesInit);
155/// True iff the given types for the given pair of type indexes is one of the
156/// specified type pairs.
157LegalityPredicate
158typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1,
159 std::initializer_list<std::pair<LLT, LLT>> TypesInit);
160/// True iff the specified type index is a scalar.
161LegalityPredicate isScalar(unsigned TypeIdx);
162/// True iff the specified type index is a scalar that's narrower than the given
163/// size.
164LegalityPredicate narrowerThan(unsigned TypeIdx, unsigned Size);
165/// True iff the specified type index is a scalar that's wider than the given
166/// size.
167LegalityPredicate widerThan(unsigned TypeIdx, unsigned Size);
168/// True iff the specified type index is a scalar whose size is not a power of
169/// 2.
170LegalityPredicate sizeNotPow2(unsigned TypeIdx);
171/// True iff the specified type index is a vector whose element count is not a
172/// power of 2.
173LegalityPredicate numElementsNotPow2(unsigned TypeIdx);
174} // end namespace LegalityPredicates
175
176namespace LegalizeMutations {
177/// Select this specific type for the given type index.
178LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty);
179/// Widen the type for the given type index to the next power of 2.
180LegalizeMutation widenScalarToNextPow2(unsigned TypeIdx, unsigned Min = 0);
181/// Add more elements to the type for the given type index to the next power of
182/// 2.
183LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min = 0);
184} // end namespace LegalizeMutations
185
186/// A single rule in a legalizer info ruleset.
187/// The specified action is chosen when the predicate is true. Where appropriate
188/// for the action (e.g. for WidenScalar) the new type is selected using the
189/// given mutator.
190class LegalizeRule {
191 LegalityPredicate Predicate;
192 LegalizeAction Action;
193 LegalizeMutation Mutation;
194
195public:
196 LegalizeRule(LegalityPredicate Predicate, LegalizeAction Action,
197 LegalizeMutation Mutation = nullptr)
198 : Predicate(Predicate), Action(Action), Mutation(Mutation) {}
199
200 /// Test whether the LegalityQuery matches.
201 bool match(const LegalityQuery &Query) const {
202 return Predicate(Query);
203 }
204
205 LegalizeAction getAction() const { return Action; }
206
207 /// Determine the change to make.
208 std::pair<unsigned, LLT> determineMutation(const LegalityQuery &Query) const {
209 if (Mutation)
210 return Mutation(Query);
211 return std::make_pair(0, LLT{});
212 }
213};
214
215class LegalizeRuleSet {
216 /// When non-zero, the opcode we are an alias of
217 unsigned AliasOf;
218 /// If true, there is another opcode that aliases this one
219 bool IsAliasedByAnother;
220 SmallVector<LegalizeRule, 2> Rules;
221
222 void add(const LegalizeRule &Rule) {
223 assert(AliasOf == 0 &&
224 "RuleSet is aliased, change the representative opcode instead");
225 Rules.push_back(Rule);
226 }
227
228 static bool always(const LegalityQuery &) { return true; }
229
230 /// Use the given action when the predicate is true.
231 /// Action should not be an action that requires mutation.
232 LegalizeRuleSet &actionIf(LegalizeAction Action,
233 LegalityPredicate Predicate) {
234 add({Predicate, Action});
235 return *this;
236 }
237 /// Use the given action when the predicate is true.
238 /// Action should not be an action that requires mutation.
239 LegalizeRuleSet &actionIf(LegalizeAction Action, LegalityPredicate Predicate,
240 LegalizeMutation Mutation) {
241 add({Predicate, Action, Mutation});
242 return *this;
243 }
244 /// Use the given action when type index 0 is any type in the given list.
245 /// Action should not be an action that requires mutation.
246 LegalizeRuleSet &actionFor(LegalizeAction Action,
247 std::initializer_list<LLT> Types) {
248 using namespace LegalityPredicates;
249 return actionIf(Action, typeInSet(0, Types));
250 }
251 /// Use the given action when type indexes 0 and 1 is any type pair in the
252 /// given list.
253 /// Action should not be an action that requires mutation.
254 LegalizeRuleSet &
255 actionFor(LegalizeAction Action,
256 std::initializer_list<std::pair<LLT, LLT>> Types) {
257 using namespace LegalityPredicates;
258 return actionIf(Action, typePairInSet(0, 1, Types));
259 }
260 /// Use the given action when type indexes 0 and 1 are both in the given list.
261 /// That is, the type pair is in the cartesian product of the list.
262 /// Action should not be an action that requires mutation.
263 LegalizeRuleSet &actionForCartesianProduct(LegalizeAction Action,
264 std::initializer_list<LLT> Types) {
265 using namespace LegalityPredicates;
266 return actionIf(Action, all(typeInSet(0, Types), typeInSet(1, Types)));
267 }
268 /// Use the given action when type indexes 0 and 1 are both their respective
269 /// lists.
270 /// That is, the type pair is in the cartesian product of the lists
271 /// Action should not be an action that requires mutation.
272 LegalizeRuleSet &
273 actionForCartesianProduct(LegalizeAction Action,
274 std::initializer_list<LLT> Types0,
275 std::initializer_list<LLT> Types1) {
276 using namespace LegalityPredicates;
277 return actionIf(Action, all(typeInSet(0, Types0), typeInSet(1, Types1)));
278 }
279
280public:
281 LegalizeRuleSet() : AliasOf(0), IsAliasedByAnother(false), Rules() {}
282
283 bool isAliasedByAnother() { return IsAliasedByAnother; }
284 void setIsAliasedByAnother() { IsAliasedByAnother = true; }
285 void aliasTo(unsigned Opcode) {
286 assert((AliasOf == 0 || AliasOf == Opcode) &&
287 "Opcode is already aliased to another opcode");
288 assert(Rules.empty() && "Aliasing will discard rules");
289 AliasOf = Opcode;
290 }
291 unsigned getAlias() const { return AliasOf; }
292
293 /// The instruction is legal if predicate is true.
294 LegalizeRuleSet &legalIf(LegalityPredicate Predicate) {
295 return actionIf(LegalizeAction::Legal, Predicate);
296 }
297 /// The instruction is legal when type index 0 is any type in the given list.
298 LegalizeRuleSet &legalFor(std::initializer_list<LLT> Types) {
299 return actionFor(LegalizeAction::Legal, Types);
300 }
301 /// The instruction is legal when type indexes 0 and 1 is any type pair in the
302 /// given list.
303 LegalizeRuleSet &legalFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
304 return actionFor(LegalizeAction::Legal, Types);
305 }
306 /// The instruction is legal when type indexes 0 and 1 are both in the given
307 /// list. That is, the type pair is in the cartesian product of the list.
308 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types) {
309 return actionForCartesianProduct(LegalizeAction::Legal, Types);
310 }
311 /// The instruction is legal when type indexes 0 and 1 are both their
312 /// respective lists.
313 LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0,
314 std::initializer_list<LLT> Types1) {
315 return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1);
316 }
317
318 /// Like legalIf, but for the Libcall action.
319 LegalizeRuleSet &libcallIf(LegalityPredicate Predicate) {
320 return actionIf(LegalizeAction::Libcall, Predicate);
321 }
322 LegalizeRuleSet &libcallFor(std::initializer_list<LLT> Types) {
323 return actionFor(LegalizeAction::Libcall, Types);
324 }
325 LegalizeRuleSet &
326 libcallFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
327 return actionFor(LegalizeAction::Libcall, Types);
328 }
329 LegalizeRuleSet &
330 libcallForCartesianProduct(std::initializer_list<LLT> Types) {
331 return actionForCartesianProduct(LegalizeAction::Libcall, Types);
332 }
333 LegalizeRuleSet &
334 libcallForCartesianProduct(std::initializer_list<LLT> Types0,
335 std::initializer_list<LLT> Types1) {
336 return actionForCartesianProduct(LegalizeAction::Libcall, Types0, Types1);
337 }
338
339 /// Widen the scalar to the one selected by the mutation if the predicate is
340 /// true.
341 LegalizeRuleSet &widenScalarIf(LegalityPredicate Predicate,
342 LegalizeMutation Mutation) {
343 return actionIf(LegalizeAction::WidenScalar, Predicate, Mutation);
344 }
345 /// Narrow the scalar to the one selected by the mutation if the predicate is
346 /// true.
347 LegalizeRuleSet &narrowScalarIf(LegalityPredicate Predicate,
348 LegalizeMutation Mutation) {
349 return actionIf(LegalizeAction::NarrowScalar, Predicate, Mutation);
350 }
351
352 /// Add more elements to reach the type selected by the mutation if the
353 /// predicate is true.
354 LegalizeRuleSet &moreElementsIf(LegalityPredicate Predicate,
355 LegalizeMutation Mutation) {
356 return actionIf(LegalizeAction::MoreElements, Predicate, Mutation);
357 }
358 /// Remove elements to reach the type selected by the mutation if the
359 /// predicate is true.
360 LegalizeRuleSet &fewerElementsIf(LegalityPredicate Predicate,
361 LegalizeMutation Mutation) {
362 return actionIf(LegalizeAction::FewerElements, Predicate, Mutation);
363 }
364
365 /// The instruction is unsupported.
366 LegalizeRuleSet &unsupported() {
367 return actionIf(LegalizeAction::Unsupported, always);
368 }
369 LegalizeRuleSet &unsupportedIf(LegalityPredicate Predicate) {
370 return actionIf(LegalizeAction::Unsupported, Predicate);
371 }
372
373 LegalizeRuleSet &customIf(LegalityPredicate Predicate) {
374 return actionIf(LegalizeAction::Custom, Predicate);
375 }
376 LegalizeRuleSet &customFor(std::initializer_list<LLT> Types) {
377 return actionFor(LegalizeAction::Custom, Types);
378 }
379 LegalizeRuleSet &customForCartesianProduct(std::initializer_list<LLT> Types) {
380 return actionForCartesianProduct(LegalizeAction::Custom, Types);
381 }
382 LegalizeRuleSet &
383 customForCartesianProduct(std::initializer_list<LLT> Types0,
384 std::initializer_list<LLT> Types1) {
385 return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1);
386 }
387
388 /// Widen the scalar to the next power of two that is at least MinSize.
389 /// No effect if the type is not a scalar or is a power of two.
390 LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize = 0) {
391 using namespace LegalityPredicates;
392 return widenScalarIf(
393 sizeNotPow2(TypeIdx),
394 LegalizeMutations::widenScalarToNextPow2(TypeIdx, MinSize));
395 }
396
397 LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) {
398 using namespace LegalityPredicates;
399 return narrowScalarIf(isScalar(TypeIdx), Mutation);
400 }
401
402 /// Ensure the scalar is at least as wide as Ty.
403 LegalizeRuleSet &minScalar(unsigned TypeIdx, const LLT &Ty) {
404 using namespace LegalityPredicates;
405 using namespace LegalizeMutations;
406 return widenScalarIf(narrowerThan(TypeIdx, Ty.getSizeInBits()),
407 changeTo(TypeIdx, Ty));
408 }
409
410 /// Ensure the scalar is at most as wide as Ty.
411 LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT &Ty) {
412 using namespace LegalityPredicates;
413 using namespace LegalizeMutations;
414 return narrowScalarIf(widerThan(TypeIdx, Ty.getSizeInBits()),
415 changeTo(TypeIdx, Ty));
416 }
417
418 /// Conditionally limit the maximum size of the scalar.
419 /// For example, when the maximum size of one type depends on the size of
420 /// another such as extracting N bits from an M bit container.
421 LegalizeRuleSet &maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, const LLT &Ty) {
422 using namespace LegalityPredicates;
423 using namespace LegalizeMutations;
424 return narrowScalarIf(
425 [=](const LegalityQuery &Query) {
426 return widerThan(TypeIdx, Ty.getSizeInBits()) &&
427 Predicate(Query);
428 },
429 changeTo(TypeIdx, Ty));
430 }
431
432 /// Limit the range of scalar sizes to MinTy and MaxTy.
433 LegalizeRuleSet &clampScalar(unsigned TypeIdx, const LLT &MinTy, const LLT &MaxTy) {
434 assert(MinTy.isScalar() && MaxTy.isScalar() && "Expected scalar types");
435
436 return minScalar(TypeIdx, MinTy)
437 .maxScalar(TypeIdx, MaxTy);
438 }
439
440 /// Add more elements to the vector to reach the next power of two.
441 /// No effect if the type is not a vector or the element count is a power of
442 /// two.
443 LegalizeRuleSet &moreElementsToNextPow2(unsigned TypeIdx) {
444 using namespace LegalityPredicates;
445 return moreElementsIf(numElementsNotPow2(TypeIdx),
446 LegalizeMutations::moreElementsToNextPow2(TypeIdx));
447 }
448
449 /// Limit the number of elements in EltTy vectors to at least MinElements.
450 LegalizeRuleSet &clampMinNumElements(unsigned TypeIdx, const LLT &EltTy,
451 unsigned MinElements) {
452 return moreElementsIf(
453 [=](const LegalityQuery &Query) {
454 LLT VecTy = Query.Types[TypeIdx];
455 return VecTy.getElementType() == EltTy &&
456 VecTy.getNumElements() < MinElements;
457 },
458 [=](const LegalityQuery &Query) {
459 LLT VecTy = Query.Types[TypeIdx];
460 return std::make_pair(
461 TypeIdx, LLT::vector(MinElements, VecTy.getScalarSizeInBits()));
462 });
463 }
464 /// Limit the number of elements in EltTy vectors to at most MaxElements.
465 LegalizeRuleSet &clampMaxNumElements(unsigned TypeIdx, const LLT &EltTy,
466 unsigned MaxElements) {
467 return fewerElementsIf(
468 [=](const LegalityQuery &Query) {
469 LLT VecTy = Query.Types[TypeIdx];
470 return VecTy.getElementType() == EltTy &&
471 VecTy.getNumElements() > MaxElements;
472 },
473 [=](const LegalityQuery &Query) {
474 LLT VecTy = Query.Types[TypeIdx];
475 return std::make_pair(
476 TypeIdx, LLT::vector(MaxElements, VecTy.getScalarSizeInBits()));
477 });
478 }
479 /// Limit the number of elements for the given vectors to at least MinTy's
480 /// number of elements and at most MaxTy's number of elements.
481 ///
482 /// No effect if the type is not a vector or does not have the same element
483 /// type as the constraints.
484 /// The element type of MinTy and MaxTy must match.
485 LegalizeRuleSet &clampNumElements(unsigned TypeIdx, const LLT &MinTy,
486 const LLT &MaxTy) {
487 assert(MinTy.getElementType() == MaxTy.getElementType() &&
488 "Expected element types to agree");
489
490 const LLT &EltTy = MinTy.getElementType();
491 return clampMinNumElements(TypeIdx, EltTy, MinTy.getNumElements())
492 .clampMaxNumElements(TypeIdx, EltTy, MaxTy.getNumElements());
493 }
494
495 /// Fallback on the previous implementation. This should only be used while
496 /// porting a rule.
497 LegalizeRuleSet &fallback() {
498 add({always, LegalizeAction::UseLegacyRules});
499 return *this;
500 }
501
502 /// Apply the ruleset to the given LegalityQuery.
503 LegalizeActionStep apply(const LegalityQuery &Query) const;
504};
505
506class LegalizerInfo {
507public:
508 LegalizerInfo();
509 virtual ~LegalizerInfo() = default;
510
511 unsigned getOpcodeIdxForOpcode(unsigned Opcode) const;
512 unsigned getActionDefinitionsIdx(unsigned Opcode) const;
513
514 /// Compute any ancillary tables needed to quickly decide how an operation
515 /// should be handled. This must be called after all "set*Action"methods but
516 /// before any query is made or incorrect results may be returned.
517 void computeTables();
518
519 static bool needsLegalizingToDifferentSize(const LegalizeAction Action) {
520 using namespace LegalizeActions;
521 switch (Action) {
522 case NarrowScalar:
523 case WidenScalar:
524 case FewerElements:
525 case MoreElements:
526 case Unsupported:
527 return true;
528 default:
529 return false;
530 }
531 }
532
533 using SizeAndAction = std::pair<uint16_t, LegalizeAction>;
534 using SizeAndActionsVec = std::vector<SizeAndAction>;
535 using SizeChangeStrategy =
536 std::function<SizeAndActionsVec(const SizeAndActionsVec &v)>;
537
538 /// More friendly way to set an action for common types that have an LLT
539 /// representation.
540 /// The LegalizeAction must be one for which NeedsLegalizingToDifferentSize
541 /// returns false.
542 void setAction(const InstrAspect &Aspect, LegalizeAction Action) {
543 assert(!needsLegalizingToDifferentSize(Action));
544 TablesInitialized = false;
545 const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;
546 if (SpecifiedActions[OpcodeIdx].size() <= Aspect.Idx)
547 SpecifiedActions[OpcodeIdx].resize(Aspect.Idx + 1);
548 SpecifiedActions[OpcodeIdx][Aspect.Idx][Aspect.Type] = Action;
549 }
550
551 /// The setAction calls record the non-size-changing legalization actions
552 /// to take on specificly-sized types. The SizeChangeStrategy defines what
553 /// to do when the size of the type needs to be changed to reach a legally
554 /// sized type (i.e., one that was defined through a setAction call).
555 /// e.g.
556 /// setAction ({G_ADD, 0, LLT::scalar(32)}, Legal);
557 /// setLegalizeScalarToDifferentSizeStrategy(
558 /// G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
559 /// will end up defining getAction({G_ADD, 0, T}) to return the following
560 /// actions for different scalar types T:
561 /// LLT::scalar(1)..LLT::scalar(31): {WidenScalar, 0, LLT::scalar(32)}
562 /// LLT::scalar(32): {Legal, 0, LLT::scalar(32)}
563 /// LLT::scalar(33)..: {NarrowScalar, 0, LLT::scalar(32)}
564 ///
565 /// If no SizeChangeAction gets defined, through this function,
566 /// the default is unsupportedForDifferentSizes.
567 void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode,
568 const unsigned TypeIdx,
569 SizeChangeStrategy S) {
570 const unsigned OpcodeIdx = Opcode - FirstOp;
571 if (ScalarSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
572 ScalarSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
573 ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
574 }
575
576 /// See also setLegalizeScalarToDifferentSizeStrategy.
577 /// This function allows to set the SizeChangeStrategy for vector elements.
578 void setLegalizeVectorElementToDifferentSizeStrategy(const unsigned Opcode,
579 const unsigned TypeIdx,
580 SizeChangeStrategy S) {
581 const unsigned OpcodeIdx = Opcode - FirstOp;
582 if (VectorElementSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
583 VectorElementSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
584 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
585 }
586
587 /// A SizeChangeStrategy for the common case where legalization for a
588 /// particular operation consists of only supporting a specific set of type
589 /// sizes. E.g.
590 /// setAction ({G_DIV, 0, LLT::scalar(32)}, Legal);
591 /// setAction ({G_DIV, 0, LLT::scalar(64)}, Legal);
592 /// setLegalizeScalarToDifferentSizeStrategy(
593 /// G_DIV, 0, unsupportedForDifferentSizes);
594 /// will result in getAction({G_DIV, 0, T}) to return Legal for s32 and s64,
595 /// and Unsupported for all other scalar types T.
596 static SizeAndActionsVec
597 unsupportedForDifferentSizes(const SizeAndActionsVec &v) {
598 using namespace LegalizeActions;
599 return increaseToLargerTypesAndDecreaseToLargest(v, Unsupported,
600 Unsupported);
601 }
602
603 /// A SizeChangeStrategy for the common case where legalization for a
604 /// particular operation consists of widening the type to a large legal type,
605 /// unless there is no such type and then instead it should be narrowed to the
606 /// largest legal type.
607 static SizeAndActionsVec
608 widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v) {
609 using namespace LegalizeActions;
610 assert(v.size() > 0 &&
611 "At least one size that can be legalized towards is needed"
612 " for this SizeChangeStrategy");
613 return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
614 NarrowScalar);
615 }
616
617 static SizeAndActionsVec
618 widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v) {
619 using namespace LegalizeActions;
620 return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
621 Unsupported);
622 }
623
624 static SizeAndActionsVec
625 narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v) {
626 using namespace LegalizeActions;
627 return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
628 Unsupported);
629 }
630
631 static SizeAndActionsVec
632 narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec &v) {
633 using namespace LegalizeActions;
634 assert(v.size() > 0 &&
635 "At least one size that can be legalized towards is needed"
636 " for this SizeChangeStrategy");
637 return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
638 WidenScalar);
639 }
640
641 /// A SizeChangeStrategy for the common case where legalization for a
642 /// particular vector operation consists of having more elements in the
643 /// vector, to a type that is legal. Unless there is no such type and then
644 /// instead it should be legalized towards the widest vector that's still
645 /// legal. E.g.
646 /// setAction({G_ADD, LLT::vector(8, 8)}, Legal);
647 /// setAction({G_ADD, LLT::vector(16, 8)}, Legal);
648 /// setAction({G_ADD, LLT::vector(2, 32)}, Legal);
649 /// setAction({G_ADD, LLT::vector(4, 32)}, Legal);
650 /// setLegalizeVectorElementToDifferentSizeStrategy(
651 /// G_ADD, 0, moreToWiderTypesAndLessToWidest);
652 /// will result in the following getAction results:
653 /// * getAction({G_ADD, LLT::vector(8,8)}) returns
654 /// (Legal, vector(8,8)).
655 /// * getAction({G_ADD, LLT::vector(9,8)}) returns
656 /// (MoreElements, vector(16,8)).
657 /// * getAction({G_ADD, LLT::vector(8,32)}) returns
658 /// (FewerElements, vector(4,32)).
659 static SizeAndActionsVec
660 moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v) {
661 using namespace LegalizeActions;
662 return increaseToLargerTypesAndDecreaseToLargest(v, MoreElements,
663 FewerElements);
664 }
665
666 /// Helper function to implement many typical SizeChangeStrategy functions.
667 static SizeAndActionsVec
668 increaseToLargerTypesAndDecreaseToLargest(const SizeAndActionsVec &v,
669 LegalizeAction IncreaseAction,
670 LegalizeAction DecreaseAction);
671 /// Helper function to implement many typical SizeChangeStrategy functions.
672 static SizeAndActionsVec
673 decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec &v,
674 LegalizeAction DecreaseAction,
675 LegalizeAction IncreaseAction);
676
677 /// Get the action definitions for the given opcode. Use this to run a
678 /// LegalityQuery through the definitions.
679 const LegalizeRuleSet &getActionDefinitions(unsigned Opcode) const;
680
681 /// Get the action definition builder for the given opcode. Use this to define
682 /// the action definitions.
683 ///
684 /// It is an error to request an opcode that has already been requested by the
685 /// multiple-opcode variant.
686 LegalizeRuleSet &getActionDefinitionsBuilder(unsigned Opcode);
687
688 /// Get the action definition builder for the given set of opcodes. Use this
689 /// to define the action definitions for multiple opcodes at once. The first
690 /// opcode given will be considered the representative opcode and will hold
691 /// the definitions whereas the other opcodes will be configured to refer to
692 /// the representative opcode. This lowers memory requirements and very
693 /// slightly improves performance.
694 ///
695 /// It would be very easy to introduce unexpected side-effects as a result of
696 /// this aliasing if it were permitted to request different but intersecting
697 /// sets of opcodes but that is difficult to keep track of. It is therefore an
698 /// error to request the same opcode twice using this API, to request an
699 /// opcode that already has definitions, or to use the single-opcode API on an
700 /// opcode that has already been requested by this API.
701 LegalizeRuleSet &
702 getActionDefinitionsBuilder(std::initializer_list<unsigned> Opcodes);
703 void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom);
704
705 /// Determine what action should be taken to legalize the described
706 /// instruction. Requires computeTables to have been called.
707 ///
708 /// \returns a description of the next legalization step to perform.
709 LegalizeActionStep getAction(const LegalityQuery &Query) const;
710
711 /// Determine what action should be taken to legalize the given generic
712 /// instruction.
713 ///
714 /// \returns a description of the next legalization step to perform.
715 LegalizeActionStep getAction(const MachineInstr &MI,
716 const MachineRegisterInfo &MRI) const;
717
718 bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
719
720 virtual bool legalizeCustom(MachineInstr &MI,
721 MachineRegisterInfo &MRI,
722 MachineIRBuilder &MIRBuilder) const;
723
724private:
725 /// Determine what action should be taken to legalize the given generic
726 /// instruction opcode, type-index and type. Requires computeTables to have
727 /// been called.
728 ///
729 /// \returns a pair consisting of the kind of legalization that should be
730 /// performed and the destination type.
731 std::pair<LegalizeAction, LLT>
732 getAspectAction(const InstrAspect &Aspect) const;
733
734 /// The SizeAndActionsVec is a representation mapping between all natural
735 /// numbers and an Action. The natural number represents the bit size of
736 /// the InstrAspect. For example, for a target with native support for 32-bit
737 /// and 64-bit additions, you'd express that as:
738 /// setScalarAction(G_ADD, 0,
739 /// {{1, WidenScalar}, // bit sizes [ 1, 31[
740 /// {32, Legal}, // bit sizes [32, 33[
741 /// {33, WidenScalar}, // bit sizes [33, 64[
742 /// {64, Legal}, // bit sizes [64, 65[
743 /// {65, NarrowScalar} // bit sizes [65, +inf[
744 /// });
745 /// It may be that only 64-bit pointers are supported on your target:
746 /// setPointerAction(G_GEP, 0, LLT:pointer(1),
747 /// {{1, Unsupported}, // bit sizes [ 1, 63[
748 /// {64, Legal}, // bit sizes [64, 65[
749 /// {65, Unsupported}, // bit sizes [65, +inf[
750 /// });
751 void setScalarAction(const unsigned Opcode, const unsigned TypeIndex,
752 const SizeAndActionsVec &SizeAndActions) {
753 const unsigned OpcodeIdx = Opcode - FirstOp;
754 SmallVector<SizeAndActionsVec, 1> &Actions = ScalarActions[OpcodeIdx];
755 setActions(TypeIndex, Actions, SizeAndActions);
756 }
757 void setPointerAction(const unsigned Opcode, const unsigned TypeIndex,
758 const unsigned AddressSpace,
759 const SizeAndActionsVec &SizeAndActions) {
760 const unsigned OpcodeIdx = Opcode - FirstOp;
761 if (AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace) ==
762 AddrSpace2PointerActions[OpcodeIdx].end())
763 AddrSpace2PointerActions[OpcodeIdx][AddressSpace] = {{}};
764 SmallVector<SizeAndActionsVec, 1> &Actions =
765 AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace)->second;
766 setActions(TypeIndex, Actions, SizeAndActions);
767 }
768
769 /// If an operation on a given vector type (say <M x iN>) isn't explicitly
770 /// specified, we proceed in 2 stages. First we legalize the underlying scalar
771 /// (so that there's at least one legal vector with that scalar), then we
772 /// adjust the number of elements in the vector so that it is legal. The
773 /// desired action in the first step is controlled by this function.
774 void setScalarInVectorAction(const unsigned Opcode, const unsigned TypeIndex,
775 const SizeAndActionsVec &SizeAndActions) {
776 unsigned OpcodeIdx = Opcode - FirstOp;
777 SmallVector<SizeAndActionsVec, 1> &Actions =
778 ScalarInVectorActions[OpcodeIdx];
779 setActions(TypeIndex, Actions, SizeAndActions);
780 }
781
782 /// See also setScalarInVectorAction.
783 /// This function let's you specify the number of elements in a vector that
784 /// are legal for a legal element size.
785 void setVectorNumElementAction(const unsigned Opcode,
786 const unsigned TypeIndex,
787 const unsigned ElementSize,
788 const SizeAndActionsVec &SizeAndActions) {
789 const unsigned OpcodeIdx = Opcode - FirstOp;
790 if (NumElements2Actions[OpcodeIdx].find(ElementSize) ==
791 NumElements2Actions[OpcodeIdx].end())
792 NumElements2Actions[OpcodeIdx][ElementSize] = {{}};
793 SmallVector<SizeAndActionsVec, 1> &Actions =
794 NumElements2Actions[OpcodeIdx].find(ElementSize)->second;
795 setActions(TypeIndex, Actions, SizeAndActions);
796 }
797
798 /// A partial SizeAndActionsVec potentially doesn't cover all bit sizes,
799 /// i.e. it's OK if it doesn't start from size 1.
800 static void checkPartialSizeAndActionsVector(const SizeAndActionsVec& v) {
801 using namespace LegalizeActions;
802#ifndef NDEBUG
803 // The sizes should be in increasing order
804 int prev_size = -1;
805 for(auto SizeAndAction: v) {
806 assert(SizeAndAction.first > prev_size);
807 prev_size = SizeAndAction.first;
808 }
809 // - for every Widen action, there should be a larger bitsize that
810 // can be legalized towards (e.g. Legal, Lower, Libcall or Custom
811 // action).
812 // - for every Narrow action, there should be a smaller bitsize that
813 // can be legalized towards.
814 int SmallestNarrowIdx = -1;
815 int LargestWidenIdx = -1;
816 int SmallestLegalizableToSameSizeIdx = -1;
817 int LargestLegalizableToSameSizeIdx = -1;
818 for(size_t i=0; i<v.size(); ++i) {
819 switch (v[i].second) {
820 case FewerElements:
821 case NarrowScalar:
822 if (SmallestNarrowIdx == -1)
823 SmallestNarrowIdx = i;
824 break;
825 case WidenScalar:
826 case MoreElements:
827 LargestWidenIdx = i;
828 break;
829 case Unsupported:
830 break;
831 default:
832 if (SmallestLegalizableToSameSizeIdx == -1)
833 SmallestLegalizableToSameSizeIdx = i;
834 LargestLegalizableToSameSizeIdx = i;
835 }
836 }
837 if (SmallestNarrowIdx != -1) {
838 assert(SmallestLegalizableToSameSizeIdx != -1);
839 assert(SmallestNarrowIdx > SmallestLegalizableToSameSizeIdx);
840 }
841 if (LargestWidenIdx != -1)
842 assert(LargestWidenIdx < LargestLegalizableToSameSizeIdx);
843#endif
844 }
845
846 /// A full SizeAndActionsVec must cover all bit sizes, i.e. must start with
847 /// from size 1.
848 static void checkFullSizeAndActionsVector(const SizeAndActionsVec& v) {
849#ifndef NDEBUG
850 // Data structure invariant: The first bit size must be size 1.
851 assert(v.size() >= 1);
852 assert(v[0].first == 1);
853 checkPartialSizeAndActionsVector(v);
854#endif
855 }
856
857 /// Sets actions for all bit sizes on a particular generic opcode, type
858 /// index and scalar or pointer type.
859 void setActions(unsigned TypeIndex,
860 SmallVector<SizeAndActionsVec, 1> &Actions,
861 const SizeAndActionsVec &SizeAndActions) {
862 checkFullSizeAndActionsVector(SizeAndActions);
863 if (Actions.size() <= TypeIndex)
864 Actions.resize(TypeIndex + 1);
865 Actions[TypeIndex] = SizeAndActions;
866 }
867
868 static SizeAndAction findAction(const SizeAndActionsVec &Vec,
869 const uint32_t Size);
870
871 /// Returns the next action needed to get the scalar or pointer type closer
872 /// to being legal
873 /// E.g. findLegalAction({G_REM, 13}) should return
874 /// (WidenScalar, 32). After that, findLegalAction({G_REM, 32}) will
875 /// probably be called, which should return (Lower, 32).
876 /// This is assuming the setScalarAction on G_REM was something like:
877 /// setScalarAction(G_REM, 0,
878 /// {{1, WidenScalar}, // bit sizes [ 1, 31[
879 /// {32, Lower}, // bit sizes [32, 33[
880 /// {33, NarrowScalar} // bit sizes [65, +inf[
881 /// });
882 std::pair<LegalizeAction, LLT>
883 findScalarLegalAction(const InstrAspect &Aspect) const;
884
885 /// Returns the next action needed towards legalizing the vector type.
886 std::pair<LegalizeAction, LLT>
887 findVectorLegalAction(const InstrAspect &Aspect) const;
888
889 static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
890 static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
891
892 // Data structures used temporarily during construction of legality data:
893 using TypeMap = DenseMap<LLT, LegalizeAction>;
894 SmallVector<TypeMap, 1> SpecifiedActions[LastOp - FirstOp + 1];
895 SmallVector<SizeChangeStrategy, 1>
896 ScalarSizeChangeStrategies[LastOp - FirstOp + 1];
897 SmallVector<SizeChangeStrategy, 1>
898 VectorElementSizeChangeStrategies[LastOp - FirstOp + 1];
899 bool TablesInitialized;
900
901 // Data structures used by getAction:
902 SmallVector<SizeAndActionsVec, 1> ScalarActions[LastOp - FirstOp + 1];
903 SmallVector<SizeAndActionsVec, 1> ScalarInVectorActions[LastOp - FirstOp + 1];
904 std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
905 AddrSpace2PointerActions[LastOp - FirstOp + 1];
906 std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
907 NumElements2Actions[LastOp - FirstOp + 1];
908
909 LegalizeRuleSet RulesForOpcode[LastOp - FirstOp + 1];
910};
911
912#ifndef NDEBUG
913/// Checks that MIR is fully legal, returns an illegal instruction if it's not,
914/// nullptr otherwise
915const MachineInstr *machineFunctionIsIllegal(const MachineFunction &MF);
916#endif
917
918} // end namespace llvm.
919
920#endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H