33#define DEBUG_TYPE "amdgpu-regbanklegalize"
36using namespace AMDGPU;
50 return "AMDGPU Register Bank Legalize";
70 "AMDGPU Register Bank Legalize",
false,
false)
77char AMDGPURegBankLegalize::
ID = 0;
82 return new AMDGPURegBankLegalize();
87 static std::mutex GlobalMutex;
90 std::lock_guard<std::mutex> Lock(GlobalMutex);
91 auto [It, Inserted] = CacheForRuleSet.
try_emplace(ST.getGeneration());
93 It->second = std::make_unique<RegBankLegalizeRules>(ST,
MRI);
95 It->second->refreshRefs(ST,
MRI);
116 SgprRB(&RBI.getRegBank(AMDGPU::SGPRRegBankID)),
117 VgprRB(&RBI.getRegBank(AMDGPU::VGPRRegBankID)),
118 VccRB(&RBI.getRegBank(AMDGPU::VCCRegBankID)) {};
121 std::pair<MachineInstr *, Register>
tryMatch(
Register Src,
unsigned Opcode);
133 if (RB && RB->
getID() == AMDGPU::VCCRegBankID)
140std::pair<MachineInstr *, Register>
148std::pair<GUnmerge *, int>
151 if (ReadAnyLane->
getOpcode() != AMDGPU::G_AMDGPU_READANYLANE)
152 return {
nullptr, -1};
155 if (
auto *UnMerge = getOpcodeDef<GUnmerge>(RALSrc, MRI))
156 return {UnMerge, UnMerge->findRegisterDefOperandIdx(RALSrc,
nullptr)};
158 return {
nullptr, -1};
163 auto [RAL, RALSrc] =
tryMatch(Src, AMDGPU::G_AMDGPU_READANYLANE);
171 auto *
Merge = getOpcodeDef<GMergeLikeInstr>(Src, MRI);
173 unsigned NumElts =
Merge->getNumSources();
175 if (!Unmerge || Unmerge->getNumDefs() != NumElts ||
Idx != 0)
179 for (
unsigned i = 1; i < NumElts; ++i) {
181 if (UnmergeI != Unmerge || (
unsigned)IdxI != i)
184 return Unmerge->getSourceReg();
190 auto *UnMerge = getOpcodeDef<GUnmerge>(Src, MRI);
194 int Idx = UnMerge->findRegisterDefOperandIdx(Src,
nullptr);
195 Merge = getOpcodeDef<GMergeLikeInstr>(UnMerge->getSourceReg(), MRI);
196 if (!
Merge || UnMerge->getNumDefs() !=
Merge->getNumSources())
203 auto [RALEl, RALElSrc] =
tryMatch(SrcRegIdx, AMDGPU::G_AMDGPU_READANYLANE);
220 Register Dst = Copy.getOperand(0).getReg();
221 Register Src = Copy.getOperand(1).getReg();
234 if (SrcMI.
getOpcode() == AMDGPU::G_BITCAST)
242 if (SrcMI.
getOpcode() != AMDGPU::G_BITCAST) {
270 if (!Dst.isVirtual() || !Src.isVirtual())
281 auto [Trunc, TruncS32Src] =
tryMatch(Src, AMDGPU::G_TRUNC);
283 "sgpr S1 must be result of G_TRUNC of sgpr S32");
288 auto BoolSrc = B.
buildAnd({SgprRB, S32}, TruncS32Src, One);
289 B.
buildInstr(AMDGPU::G_AMDGPU_COPY_VCC_SCC, {Dst}, {BoolSrc});
304 auto [Trunc, TruncSrc] =
tryMatch(Src, AMDGPU::G_TRUNC);
311 if (DstTy == TruncSrcTy) {
319 if (DstTy == S32 && TruncSrcTy == S64) {
326 if (DstTy == S64 && TruncSrcTy == S32) {
328 {TruncSrc, B.buildUndef({SgprRB, S32})});
333 if (DstTy ==
S32 && TruncSrcTy ==
S16) {
334 B.buildAnyExt(Dst, TruncSrc);
339 if (DstTy ==
S16 && TruncSrcTy ==
S32) {
340 B.buildTrunc(Dst, TruncSrc);
351 for (
unsigned i = 0; i <
MRI.getNumVirtRegs(); ++i) {
353 if (
MRI.def_empty(Reg) ||
MRI.getType(Reg) !=
S1)
357 if (RB && RB->
getID() == AMDGPU::SGPRRegBankID) {
374 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
380 B.setCSEInfo(&CSEInfo);
381 B.setChangeObserver(Observer);
390 getAnalysis<MachineUniformityAnalysisPass>().getUniformityInfo();
407 if (!
MI->isPreISelOpcode())
410 unsigned Opc =
MI->getOpcode();
412 if (
Opc == AMDGPU::G_PHI) {
413 RBLHelper.applyMappingPHI(*
MI);
419 if (
Opc == AMDGPU::G_BUILD_VECTOR ||
Opc == AMDGPU::G_UNMERGE_VALUES ||
420 Opc == AMDGPU::G_MERGE_VALUES ||
Opc == AMDGPU::G_BITCAST) {
421 RBLHelper.applyMappingTrivial(*
MI);
426 if (
Opc == G_FREEZE &&
428 RBLHelper.applyMappingTrivial(*
MI);
432 if ((
Opc == AMDGPU::G_CONSTANT ||
Opc == AMDGPU::G_FCONSTANT ||
433 Opc == AMDGPU::G_IMPLICIT_DEF)) {
437 assert(
MRI.getRegBank(Dst)->getID() == AMDGPU::SGPRRegBankID);
444 RBLHelper.findRuleAndApplyMapping(*
MI);
474 if (
MI.getOpcode() == AMDGPU::COPY) {
478 if (
MI.getOpcode() == AMDGPU::G_ANYEXT) {
486 "Registers with sgpr reg bank and S1 LLT are not legal after "
487 "AMDGPURegBankLegalize. Should lower to sgpr S32");
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
AMDGPU Register Bank Legalize
static Register getAnySgprS1(const MachineRegisterInfo &MRI)
const RegBankLegalizeRules & getRules(const GCNSubtarget &ST, MachineRegisterInfo &MRI)
#define DEBUG_TYPE
Lower G_ instructions that can't be inst-selected with register bank assignment from AMDGPURegBankSel...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Provides analysis for continuously CSEing during GISel passes.
This file implements a version of MachineIRBuilder which CSEs insts within a MachineBasicBlock.
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
AMD GCN specific subclass of TargetSubtarget.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
Target-Independent Code Generator Pass Configuration Options pass.
std::pair< GUnmerge *, int > tryMatchRALFromUnmerge(Register Src)
void replaceRegWithOrBuildCopy(Register Dst, Register Src)
AMDGPURegBankLegalizeCombiner(MachineIRBuilder &B, const SIRegisterInfo &TRI, const RegisterBankInfo &RBI)
bool isLaneMask(Register Reg)
void tryCombineS1AnyExt(MachineInstr &MI)
std::pair< MachineInstr *, Register > tryMatch(Register Src, unsigned Opcode)
Register getReadAnyLaneSrc(Register Src)
void tryCombineCopy(MachineInstr &MI)
bool tryEliminateReadAnyLane(MachineInstr &Copy)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
Defines a builder that does CSE of MachineInstructions using GISelCSEInfo.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
FunctionPass class - This class is used to implement most global optimizations.
The actual analysis pass wrapper.
Simple wrapper that does the following.
Simple wrapper observer that takes several observers, and calls each one for each event.
void addObserver(GISelChangeObserver *O)
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual MachineFunctionProperties getClearedProperties() const
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Properties which a MachineFunction may have at a given point in time.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Helper class to build MachineInstr.
MachineInstrBuilder buildUnmerge(ArrayRef< LLT > Res, const SrcOp &Op)
Build and insert Res0, ... = G_UNMERGE_VALUES Op.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
void setInstr(MachineInstr &MI)
Set the insertion point to before MI.
MachineInstrBuilder buildMergeLikeInstr(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ... or Res = G_BUILD_VECTOR Op0, ... or Res = G_CONCAT_VEC...
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
const RegisterBank * getRegBankOrNull(Register Reg) const
Return the register bank of Reg, or null if Reg has not been assigned a register bank or has been ass...
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
A simple RAII based Delegate installer.
A simple RAII based Observer installer.
Holds all the information related to register banks.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
bool isVGPR(const MachineRegisterInfo &MRI, Register Reg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Target-Independent Code Generator Pass Configuration Options.
virtual std::unique_ptr< CSEConfigBase > getCSEConfig() const
Returns the CSEConfig object to use for the current optimization level.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createAMDGPURegBankLegalizePass()
LLVM_ABI void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, LostDebugLocObserver *LocObserver=nullptr)
char & AMDGPURegBankLegalizeID