LLVM 23.0.0git
AMDGPURegBankLegalizeRules.h
Go to the documentation of this file.
1//===- AMDGPURegBankLegalizeRules --------------------------------*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUREGBANKLEGALIZERULES_H
10#define LLVM_LIB_TARGET_AMDGPU_AMDGPUREGBANKLEGALIZERULES_H
11
12#include "llvm/ADT/DenseMap.h"
14#include <functional>
15
16namespace llvm {
17
18class LLT;
20class MachineInstr;
21class GCNSubtarget;
22class MachineFunction;
23template <typename T> class GenericUniformityInfo;
24template <typename T> class GenericSSAContext;
27
28namespace AMDGPU {
29
30/// \returns true if \p Ty is a pointer type with size \p Width.
31bool isAnyPtr(LLT Ty, unsigned Width);
32
33// IDs used to build predicate for RegBankLegalizeRule. Predicate can have one
34// or more IDs and each represents a check for 'uniform or divergent' + LLT or
35// just LLT on register operand.
36// Most often checking one operand is enough to decide which RegBankLLTMapping
37// to apply (see Fast Rules), IDs are useful when two or more operands need to
38// be checked.
161
162// How to apply register bank on register operand.
163// In most cases, this serves as a LLT and register bank assert.
164// Can change operands and insert copies, extends, truncs, and read-any-lanes.
165// Anything more complicated requires LoweringMethod.
172
173 // any LLT, bank-only apply IDs
177
178 // sgpr scalars, pointers, vectors and B-types
204
205 // vgpr scalars, pointers, vectors and B-types
236
237 // Dst only modifiers: read-any-lane and truncs
261
263
264 // Dst only modifiers: dst was assigned VGPR by RegBankSelect but the
265 // instruction result must be in SGPR. Replace dst with SGPR, then copy the
266 // result back to the original VGPR.
269
270 // Src only modifiers: execute in waterfall loop if divergent
273
274 // Src only modifiers: execute in waterfall loop for calls
277
278 // Src only modifiers: for operands that must end up in M0. If divergent,
279 // readfirstlane to SGPR. The result can then be copied to M0 in ISel.
281
282 // Src only modifiers: operand must be SGPR, if in VGPR, insert readfirstlane
283 // to move to SGPR.
288
289 // Src only modifiers: extends
297
302};
303
304// Instruction needs to be replaced with sequence of instructions. Lowering was
305// not done by legalizer since instructions is available in either sgpr or vgpr.
306// For example S64 AND is available on sgpr, for that reason S64 AND is legal in
307// context of Legalizer that only checks LLT. But S64 AND is not available on
308// vgpr. Lower it to two S32 vgpr ANDs.
354
357 Standard, // S16, S32, S64, V2S16
358 StandardB, // B32, B64, B96, B128
359 Vector, // S32, V2S32, V3S32, V4S32
360};
361
367 std::initializer_list<RegBankLLTMappingApplyID> DstOpMappingList,
368 std::initializer_list<RegBankLLTMappingApplyID> SrcOpMappingList,
370};
371
374 std::function<bool(const MachineInstr &)> TestFunc;
376 std::initializer_list<UniformityLLTOpPredicateID> OpList,
377 std::function<bool(const MachineInstr &)> TestFunc = nullptr);
378
379 bool match(const MachineInstr &MI, const MachineUniformityInfo &MUI,
380 const MachineRegisterInfo &MRI) const;
381};
382
387
389 // "Slow Rules". More complex 'Rules[i].Predicate', check them one by one.
391
392 // "Fast Rules"
393 // Instead of testing each 'Rules[i].Predicate' we do direct access to
394 // RegBankLLTMapping using getFastPredicateSlot. For example if:
395 // - FastTypes == Standard Uni[0] holds Mapping in case Op 0 is uniform S32
396 // - FastTypes == Vector Div[3] holds Mapping in case Op 0 is divergent V4S32
397 FastRulesTypes FastTypes = NoFastRules;
398#define InvMapping RegBankLLTMapping({InvalidMapping}, {InvalidMapping})
399 RegBankLLTMapping Uni[4] = {InvMapping, InvMapping, InvMapping, InvMapping};
400 RegBankLLTMapping Div[4] = {InvMapping, InvMapping, InvMapping, InvMapping};
401
402public:
405
406 const RegBankLLTMapping *
408 const MachineUniformityInfo &MUI) const;
409
410 void addRule(RegBankLegalizeRule Rule);
411
413 RegBankLLTMapping RuleApplyIDs);
415 RegBankLLTMapping RuleApplyIDs);
416
417private:
418 int getFastPredicateSlot(UniformityLLTOpPredicateID Ty) const;
419};
420
421// Essentially 'map<Opcode(or intrinsic_opcode), SetOfRulesForOpcode>' but a
422// little more efficient.
424 const GCNSubtarget *ST;
426 // Separate maps for G-opcodes and intrinsics since they are in different
427 // enums. Multiple opcodes can share same set of rules.
428 // RulesAlias = map<Opcode, KeyOpcode>
429 // Rules = map<KeyOpcode, SetOfRulesForOpcode>
434 class RuleSetInitializer {
435 SetOfRulesForOpcode *RuleSet;
436
437 public:
438 // Used for clang-format line breaks and to force writing all rules for
439 // opcode in same place.
440 template <class AliasMap, class RulesMap>
441 RuleSetInitializer(std::initializer_list<unsigned> OpcList,
442 AliasMap &RulesAlias, RulesMap &Rules,
443 FastRulesTypes FastTypes = NoFastRules) {
444 unsigned KeyOpcode = *OpcList.begin();
445 for (unsigned Opc : OpcList) {
446 [[maybe_unused]] auto [_, NewInput] =
447 RulesAlias.try_emplace(Opc, KeyOpcode);
448 assert(NewInput && "Can't redefine existing Rules");
449 }
450
451 auto [DenseMapIter, NewInput] = Rules.try_emplace(KeyOpcode, FastTypes);
452 assert(NewInput && "Can't redefine existing Rules");
453
454 RuleSet = &DenseMapIter->second;
455 }
456
457 RuleSetInitializer(const RuleSetInitializer &) = delete;
458 RuleSetInitializer &operator=(const RuleSetInitializer &) = delete;
459 RuleSetInitializer(RuleSetInitializer &&) = delete;
460 RuleSetInitializer &operator=(RuleSetInitializer &&) = delete;
461 ~RuleSetInitializer() = default;
462
463 RuleSetInitializer &Div(UniformityLLTOpPredicateID Ty,
464 RegBankLLTMapping RuleApplyIDs,
465 bool STPred = true) {
466 if (STPred)
467 RuleSet->addFastRuleDivergent(Ty, RuleApplyIDs);
468 return *this;
469 }
470
471 RuleSetInitializer &Uni(UniformityLLTOpPredicateID Ty,
472 RegBankLLTMapping RuleApplyIDs,
473 bool STPred = true) {
474 if (STPred)
475 RuleSet->addFastRuleUniform(Ty, RuleApplyIDs);
476 return *this;
477 }
478
479 RuleSetInitializer &Any(RegBankLegalizeRule Init, bool STPred = true) {
480 if (STPred)
481 RuleSet->addRule(Init);
482 return *this;
483 }
484 };
485
486 RuleSetInitializer addRulesForGOpcs(std::initializer_list<unsigned> OpcList,
487 FastRulesTypes FastTypes = NoFastRules);
488
489 RuleSetInitializer addRulesForIOpcs(std::initializer_list<unsigned> OpcList,
490 FastRulesTypes FastTypes = NoFastRules);
491
492public:
493 // Initialize rules for all opcodes.
495
496 // In case we don't want to regenerate same rules, we can use already
497 // generated rules but need to refresh references to objects that are
498 // created for this run.
500 ST = &_ST;
501 MRI = &_MRI;
502 };
503
505};
506
507} // end namespace AMDGPU
508} // end namespace llvm
509
510#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define InvMapping
This file defines the DenseMap class.
IRTranslator LLVM IR MI
This file defines the SmallVector class.
RegBankLegalizeRules(const GCNSubtarget &ST, MachineRegisterInfo &MRI)
const SetOfRulesForOpcode * getRulesForOpc(MachineInstr &MI) const
void refreshRefs(const GCNSubtarget &_ST, MachineRegisterInfo &_MRI)
const RegBankLLTMapping * findMappingForMI(const MachineInstr &MI, const MachineRegisterInfo &MRI, const MachineUniformityInfo &MUI) const
void addFastRuleDivergent(UniformityLLTOpPredicateID Ty, RegBankLLTMapping RuleApplyIDs)
void addFastRuleUniform(UniformityLLTOpPredicateID Ty, RegBankLLTMapping RuleApplyIDs)
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool isAnyPtr(LLT Ty, unsigned Width)
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< MachineSSAContext > MachineUniformityInfo
GenericSSAContext< MachineFunction > MachineSSAContext
SmallVector< UniformityLLTOpPredicateID, 4 > OpUniformityAndTypes
PredicateMapping(std::initializer_list< UniformityLLTOpPredicateID > OpList, std::function< bool(const MachineInstr &)> TestFunc=nullptr)
bool match(const MachineInstr &MI, const MachineUniformityInfo &MUI, const MachineRegisterInfo &MRI) const
std::function< bool(const MachineInstr &)> TestFunc
RegBankLLTMapping(std::initializer_list< RegBankLLTMappingApplyID > DstOpMappingList, std::initializer_list< RegBankLLTMappingApplyID > SrcOpMappingList, LoweringMethodID LoweringMethod=DoNotLower)
SmallVector< RegBankLLTMappingApplyID, 2 > DstOpMapping
SmallVector< RegBankLLTMappingApplyID, 4 > SrcOpMapping