37#define DEBUG_TYPE "amdgpu-reg-bank-legalize"
46template <
typename SrcTy>
48m_GAMDGPUReadAnyLane(
const SrcTy &Src) {
62 return "AMDGPU Register Bank Legalize";
83 "AMDGPU Register Bank Legalize",
false,
false)
91char AMDGPURegBankLegalizeLegacy::ID = 0;
96 return new AMDGPURegBankLegalizeLegacy();
101 static std::mutex GlobalMutex;
104 std::lock_guard<std::mutex> Lock(GlobalMutex);
105 auto [It, Inserted] = CacheForRuleSet.
try_emplace(ST.getGeneration());
107 It->second = std::make_unique<RegBankLegalizeRules>(ST, MRI);
109 It->second->refreshRefs(ST, MRI);
129 : B(B), MRI(*B.getMRI()), TRI(TRI),
130 SgprRB(&RBI.getRegBank(
AMDGPU::SGPRRegBankID)),
131 VgprRB(&RBI.getRegBank(
AMDGPU::VGPRRegBankID)),
132 VccRB(&RBI.getRegBank(
AMDGPU::VCCRegBankID)) {};
135 std::pair<MachineInstr *, Register>
tryMatch(
Register Src,
unsigned Opcode);
148 if (RB && RB->
getID() == AMDGPU::VCCRegBankID)
152 return RC && TRI.isSGPRClass(RC) && MRI.getType(Reg) ==
LLT::scalar(1);
155std::pair<MachineInstr *, Register>
168 if (!UnMerge || UnMerge->getNumDefs() != DefRegs.
size())
170 for (
unsigned I = 1;
I < DefRegs.
size(); ++
I) {
171 if (UnMerge->getReg(
I) != DefRegs[
I])
174 return UnMerge->getSourceReg();
182 for (
unsigned i = 0; i <
Merge->getNumSources(); ++i) {
185 m_GAMDGPUReadAnyLane(
m_Reg(Src))))
189 return ReadAnyLaneSrcs;
222 if (ReadAnyLaneSrcs.
empty())
230 return ReadAnyLaneSrcs;
240 int Idx = UnMerge->findRegisterDefOperandIdx(Src,
nullptr);
242 if (!
Merge || UnMerge->getNumDefs() !=
Merge->getNumSources())
246 if (MRI.getType(Src) != MRI.getType(SrcRegIdx))
249 auto [RALEl, RALElSrc] =
tryMatch(SrcRegIdx, AMDGPU::G_AMDGPU_READANYLANE);
259 MRI.replaceRegWith(Dst, Src);
261 B.buildCopy(Dst, Src);
266 Register Dst = Copy.getOperand(0).getReg();
267 Register Src = Copy.getOperand(1).getReg();
270 if (Dst.isVirtual() ? (MRI.getRegBankOrNull(Dst) != VgprRB)
271 : !TRI.isVGPR(MRI, Dst))
275 if (!Src.isVirtual() || MRI.getRegClassOrNull(Src))
281 B.setInstrAndDebugLoc(Copy);
283 if (ReadAnyLaneSrcRegs.
empty())
287 if (ReadAnyLaneSrcRegs.
size() == 1) {
288 ReadAnyLaneSrc = ReadAnyLaneSrcRegs[0];
291 auto Merge = B.buildMergeLikeInstr({VgprRB, MRI.getType(RALDst)},
293 ReadAnyLaneSrc =
Merge.getReg(0);
309 auto Bitcast = B.buildBitcast({VgprRB, MRI.getType(Src)}, ReadAnyLaneSrc);
324 if (!Dst.isVirtual() || !Src.isVirtual())
334 if (
isLaneMask(Dst) && MRI.getRegBankOrNull(Src) == SgprRB) {
335 auto [Trunc, TruncS32Src] =
tryMatch(Src, AMDGPU::G_TRUNC);
336 assert(Trunc && MRI.getType(TruncS32Src) == S32 &&
337 "sgpr S1 must be result of G_TRUNC of sgpr S32");
341 auto One = B.buildConstant({SgprRB, S32}, 1);
342 auto BoolSrc = B.buildAnd({SgprRB, S32}, TruncS32Src, One);
343 B.buildInstr(AMDGPU::G_AMDGPU_COPY_VCC_SCC, {Dst}, {BoolSrc});
355 if (MRI.getType(Src) != S1)
358 auto [Trunc, TruncSrc] =
tryMatch(Src, AMDGPU::G_TRUNC);
362 LLT DstTy = MRI.getType(Dst);
363 LLT TruncSrcTy = MRI.getType(TruncSrc);
365 if (DstTy == TruncSrcTy) {
366 MRI.replaceRegWith(Dst, TruncSrc);
373 if (DstTy == S32 && TruncSrcTy == S64) {
374 auto Unmerge = B.buildUnmerge({SgprRB, S32}, TruncSrc);
375 MRI.replaceRegWith(Dst, Unmerge.getReg(0));
380 if (DstTy == S64 && TruncSrcTy == S32) {
381 B.buildMergeLikeInstr(
MI.getOperand(0).getReg(),
382 {TruncSrc, B.buildUndef({SgprRB, S32})});
387 if (DstTy ==
S32 && TruncSrcTy ==
S16) {
388 B.buildAnyExt(Dst, TruncSrc);
393 if (DstTy ==
S16 && TruncSrcTy ==
S32) {
394 B.buildTrunc(Dst, TruncSrc);
411 if (RB && RB->
getID() == AMDGPU::SGPRRegBankID) {
438 B.setCSEInfo(&CSEInfo);
439 B.setChangeObserver(Observer);
463 if (!
MI->isPreISelOpcode())
497 if (
MI.getOpcode() == AMDGPU::COPY) {
501 if (
MI.getOpcode() == AMDGPU::G_ANYEXT) {
509 "Registers with sgpr reg bank and S1 LLT are not legal after "
510 "AMDGPURegBankLegalize. Should lower to sgpr S32");
515bool AMDGPURegBankLegalizeLegacy::runOnMachineFunction(
MachineFunction &MF) {
519 GISelCSEAnalysisWrapper &
Wrapper =
520 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
521 return &
Wrapper.get(getAnalysis<TargetPassConfig>().getCSEConfig());
524 return &getAnalysis<MachineUniformityAnalysisPass>()
525 .getUniformityInfo();
528 return &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static Register getAnySgprS1(const MachineRegisterInfo &MRI)
static bool runRegBankLegalize(MachineFunction &MF, function_ref< GISelCSEInfo *()> GetCSEInfo, function_ref< const MachineUniformityInfo *()> GetMUI, function_ref< GISelValueTracking *()> GetVT)
const RegBankLegalizeRules & getRules(const GCNSubtarget &ST, MachineRegisterInfo &MRI)
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.
AMD GCN specific subclass of TargetSubtarget.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
Contains matchers for matching SSA Machine Instructions.
Promote Memory to Register
#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.
Register tryMatchUnmergeDefs(SmallVectorImpl< Register > &DefRegs)
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)
SmallVector< Register > tryMatchMergeReadAnyLane(GMergeLikeInstr *Merge)
void tryCombineCopy(MachineInstr &MI)
bool tryEliminateReadAnyLane(MachineInstr &Copy)
SmallVector< Register > getReadAnyLaneSrcs(Register Src)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
bool findRuleAndApplyMapping(MachineInstr &MI)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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 observer that takes several observers, and calls each one for each event.
void addObserver(GISelChangeObserver *O)
To use KnownBitsInfo analysis in a pass, KnownBitsInfo &Info = getAnalysis<GISelValueTrackingInfoAnal...
Represents G_BUILD_VECTOR, G_CONCAT_VECTORS or G_MERGE_VALUES.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
An RAII based helper class to modify MachineFunctionProperties when running pass.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
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.
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 LLVM_READONLY 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.
bool def_empty(Register RegNo) const
def_empty - Return true if there are no instructions defining the specified register (it may be live-...
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...
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Target-Independent Code Generator Pass Configuration Options.
An efficient, type-erasing, non-owning reference to a callable.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
operand_type_match m_Reg()
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
UnaryOp_match< SrcTy, TargetOpcode::G_BITCAST > m_GBitcast(const SrcTy &Src)
UnaryOp_match< SrcTy, TargetOpcode::G_ANYEXT > m_GAnyExt(const SrcTy &Src)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< MachineSSAContext > MachineUniformityInfo
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
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...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
char & AMDGPURegBankLegalizeLegacyID
LLVM_ABI void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI, LostDebugLocObserver *LocObserver=nullptr)
FunctionPass * createAMDGPURegBankLegalizeLegacyPass()
MCRegisterClass TargetRegisterClass