//===-- SIFormMemoryClauses.cpp -------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // /// \file This pass extends the live ranges of registers used as pointers in /// sequences of adjacent SMEM and VMEM instructions if XNACK is enabled. A /// load that would overwrite a pointer would require breaking the soft clause. /// Artificially extend the live ranges of the pointer operands by adding /// implicit-def early-clobber operands throughout the soft clause. /// //===----------------------------------------------------------------------===// #include "AMDGPU.h" #include "GCNRegPressure.h" #include "SIMachineFunctionInfo.h" #include "llvm/InitializePasses.h" usingnamespacellvm; #define DEBUG_TYPE … // Clauses longer then 15 instructions would overflow one of the counters // and stall. They can stall even earlier if there are outstanding counters. static cl::opt<unsigned> MaxClause("amdgpu-max-memory-clause", cl::Hidden, cl::init(15), cl::desc("Maximum length of a memory clause, instructions")); namespace { class SIFormMemoryClauses : public MachineFunctionPass { … }; } // End anonymous namespace. INITIALIZE_PASS_BEGIN(SIFormMemoryClauses, DEBUG_TYPE, "SI Form memory clauses", false, false) INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass) INITIALIZE_PASS_END(SIFormMemoryClauses, DEBUG_TYPE, "SI Form memory clauses", false, false) char SIFormMemoryClauses::ID = …; char &llvm::SIFormMemoryClausesID = …; FunctionPass *llvm::createSIFormMemoryClausesPass() { … } static bool isVMEMClauseInst(const MachineInstr &MI) { … } static bool isSMEMClauseInst(const MachineInstr &MI) { … } // There no sense to create store clauses, they do not define anything, // thus there is nothing to set early-clobber. static bool isValidClauseInst(const MachineInstr &MI, bool IsVMEMClause) { … } static unsigned getMopState(const MachineOperand &MO) { … } // Returns false if there is a use of a def already in the map. // In this case we must break the clause. bool SIFormMemoryClauses::canBundle(const MachineInstr &MI, const RegUse &Defs, const RegUse &Uses) const { … } // Since all defs in the clause are early clobber we can run out of registers. // Function returns false if pressure would hit the limit if instruction is // bundled into a memory clause. bool SIFormMemoryClauses::checkPressure(const MachineInstr &MI, GCNDownwardRPTracker &RPT) { … } // Collect register defs and uses along with their lane masks and states. void SIFormMemoryClauses::collectRegUses(const MachineInstr &MI, RegUse &Defs, RegUse &Uses) const { … } // Check register def/use conflicts, occupancy limits and collect def/use maps. // Return true if instruction can be bundled with previous. If it cannot // def/use maps are not updated. bool SIFormMemoryClauses::processRegUses(const MachineInstr &MI, RegUse &Defs, RegUse &Uses, GCNDownwardRPTracker &RPT) { … } bool SIFormMemoryClauses::runOnMachineFunction(MachineFunction &MF) { … }