//===- SIInsertWaitcnts.cpp - Insert Wait Instructions --------------------===//
//
// 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
/// Insert wait instructions for memory reads and writes.
///
/// Memory reads and writes are issued asynchronously, so we need to insert
/// S_WAITCNT instructions when we want to access any of their results or
/// overwrite any register that's used asynchronously.
///
/// TODO: This pass currently keeps one timeline per hardware counter. A more
/// finely-grained approach that keeps one timeline per event type could
/// sometimes get away with generating weaker s_waitcnt instructions. For
/// example, when both SMEM and LDS are in flight and we need to wait for
/// the i-th-last LDS instruction, then an lgkmcnt(i) is actually sufficient,
/// but the pass will currently generate a conservative lgkmcnt(0) because
/// multiple event types are in flight.
//
//===----------------------------------------------------------------------===//

#include "AMDGPU.h"
#include "AMDGPUWaitcntUtils.h"
#include "GCNSubtarget.h"
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
#include "SIMachineFunctionInfo.h"
#include "Utils/AMDGPUBaseInfo.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachinePassManager.h"
#include "llvm/CodeGen/MachinePostDominators.h"
#include "llvm/IR/Dominators.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/DebugCounter.h"
#include "llvm/TargetParser/TargetParser.h"

using namespace llvm;

#define DEBUG_TYPE "si-insert-waitcnts"

DEBUG_COUNTER(ForceExpCounter, DEBUG_TYPE "-forceexp",
              "Force emit s_waitcnt expcnt(0) instrs");
DEBUG_COUNTER(ForceLgkmCounter, DEBUG_TYPE "-forcelgkm",
              "Force emit s_waitcnt lgkmcnt(0) instrs");
DEBUG_COUNTER(ForceVMCounter, DEBUG_TYPE "-forcevm",
              "Force emit s_waitcnt vmcnt(0) instrs");

static cl::opt<bool>
    ForceEmitZeroFlag("amdgpu-waitcnt-forcezero",
                      cl::desc("Force all waitcnt instrs to be emitted as "
                               "s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)"),
                      cl::init(false), cl::Hidden);

static cl::opt<bool> ForceEmitZeroLoadFlag(
    "amdgpu-waitcnt-load-forcezero",
    cl::desc("Force all waitcnt load counters to wait until 0"),
    cl::init(false), cl::Hidden);

static cl::opt<bool> ExpertSchedulingModeFlag(
    "amdgpu-expert-scheduling-mode",
    cl::desc("Enable expert scheduling mode 2 for all functions (GFX12+ only)"),
    cl::init(false), cl::Hidden);

namespace {
// Get the maximum wait count value for a given counter type.
static unsigned getWaitCountMax(const AMDGPU::HardwareLimits &Limits,
                                AMDGPU::InstCounterType T) {
  switch (T) {
  case AMDGPU::LOAD_CNT:
    return Limits.LoadcntMax;
  case AMDGPU::DS_CNT:
    return Limits.DscntMax;
  case AMDGPU::EXP_CNT:
    return Limits.ExpcntMax;
  case AMDGPU::STORE_CNT:
    return Limits.StorecntMax;
  case AMDGPU::SAMPLE_CNT:
    return Limits.SamplecntMax;
  case AMDGPU::BVH_CNT:
    return Limits.BvhcntMax;
  case AMDGPU::KM_CNT:
    return Limits.KmcntMax;
  case AMDGPU::X_CNT:
    return Limits.XcntMax;
  case AMDGPU::VA_VDST:
    return Limits.VaVdstMax;
  case AMDGPU::VM_VSRC:
    return Limits.VmVsrcMax;
  default:
    return 0;
  }
}

/// Integer IDs used to track vector memory locations we may have to wait on.
/// Encoded as u16 chunks:
///
///   [0,               REGUNITS_END ): MCRegUnit
///   [LDSDMA_BEGIN,    LDSDMA_END  ) : LDS DMA IDs
///
/// NOTE: The choice of encoding these as "u16 chunks" is arbitrary.
/// It gives (2 << 16) - 1 entries per category which is more than enough
/// for all register units. MCPhysReg is u16 so we don't even support >u16
/// physical register numbers at this time, let alone >u16 register units.
/// In any case, an assertion in "WaitcntBrackets" ensures REGUNITS_END
/// is enough for all register units.
using VMEMID = uint32_t;

enum : VMEMID {
  TRACKINGID_RANGE_LEN = (1 << 16),

  // Important: MCRegUnits must always be tracked starting from 0, as we
  // need to be able to convert between a MCRegUnit and a VMEMID freely.
  REGUNITS_BEGIN = 0,
  REGUNITS_END = REGUNITS_BEGIN + TRACKINGID_RANGE_LEN,

  // Note for LDSDMA: LDSDMA_BEGIN corresponds to the "common"
  // entry, which is updated for all LDS DMA operations encountered.
  // Specific LDS DMA IDs start at LDSDMA_BEGIN + 1.
  NUM_LDSDMA = TRACKINGID_RANGE_LEN,
  LDSDMA_BEGIN = REGUNITS_END,
  LDSDMA_END = LDSDMA_BEGIN + NUM_LDSDMA,
};

/// Convert a MCRegUnit to a VMEMID.
static constexpr VMEMID toVMEMID(MCRegUnit RU) {
  return static_cast<unsigned>(RU);
}

#define AMDGPU_DECLARE_WAIT_EVENTS(DECL)                                       \
  DECL(VMEM_ACCESS) /* vmem read & write (pre-gfx10), vmem read (gfx10+) */    \
  DECL(VMEM_SAMPLER_READ_ACCESS) /* vmem SAMPLER read (gfx12+ only) */         \
  DECL(VMEM_BVH_READ_ACCESS)     /* vmem BVH read (gfx12+ only) */             \
  DECL(GLOBAL_INV_ACCESS)        /* GLOBAL_INV (gfx12+ only) */                \
  DECL(VMEM_WRITE_ACCESS)        /* vmem write that is not scratch */          \
  DECL(SCRATCH_WRITE_ACCESS)     /* vmem write that may be scratch */          \
  DECL(VMEM_GROUP)               /* vmem group */                              \
  DECL(LDS_ACCESS)               /* lds read & write */                        \
  DECL(GDS_ACCESS)               /* gds read & write */                        \
  DECL(SQ_MESSAGE)               /* send message */                            \
  DECL(SCC_WRITE)                /* write to SCC from barrier */               \
  DECL(SMEM_ACCESS)              /* scalar-memory read & write */              \
  DECL(SMEM_GROUP)               /* scalar-memory group */                     \
  DECL(EXP_GPR_LOCK)             /* export holding on its data src */          \
  DECL(GDS_GPR_LOCK)             /* GDS holding on its data and addr src */    \
  DECL(EXP_POS_ACCESS)           /* write to export position */                \
  DECL(EXP_PARAM_ACCESS)         /* write to export parameter */               \
  DECL(VMW_GPR_LOCK)             /* vmem write holding on its data src */      \
  DECL(EXP_LDS_ACCESS)           /* read by ldsdir counting as export */       \
  DECL(VGPR_CSMACC_WRITE)        /* write VGPR dest in Core/Side-MACC VALU */  \
  DECL(VGPR_DPMACC_WRITE)        /* write VGPR dest in DPMACC VALU */          \
  DECL(VGPR_TRANS_WRITE)         /* write VGPR dest in TRANS VALU */           \
  DECL(VGPR_XDL_WRITE)           /* write VGPR dest in XDL VALU */             \
  DECL(VGPR_LDS_READ)            /* read VGPR source in LDS */                 \
  DECL(VGPR_FLAT_READ)           /* read VGPR source in FLAT */                \
  DECL(VGPR_VMEM_READ)           /* read VGPR source in other VMEM */          \
  DECL(ASYNC_ACCESS)             /* access that uses ASYNC_CNT */

// clang-format off
#define AMDGPU_EVENT_ENUM(Name) Name,
enum WaitEventType {
  AMDGPU_DECLARE_WAIT_EVENTS(AMDGPU_EVENT_ENUM)
  NUM_WAIT_EVENTS
};
#undef AMDGPU_EVENT_ENUM
} // namespace

namespace llvm {
template <> struct enum_iteration_traits<WaitEventType> {
  static constexpr bool is_iterable = true;
};
} // namespace llvm

namespace {

/// Return an iterator over all events between VMEM_ACCESS (the first event)
/// and \c MaxEvent (exclusive, default value yields an enumeration over
/// all counters).
auto wait_events(WaitEventType MaxEvent = NUM_WAIT_EVENTS) {
  return enum_seq(VMEM_ACCESS, MaxEvent);
}

#define AMDGPU_EVENT_NAME(Name) #Name,
static constexpr StringLiteral WaitEventTypeName[] = {
  AMDGPU_DECLARE_WAIT_EVENTS(AMDGPU_EVENT_NAME)
};
#undef AMDGPU_EVENT_NAME
static constexpr StringLiteral getWaitEventTypeName(WaitEventType Event) {
  return WaitEventTypeName[Event];
}
// clang-format on

// Enumerate different types of result-returning VMEM operations. Although
// s_waitcnt orders them all with a single vmcnt counter, in the absence of
// s_waitcnt only instructions of the same VmemType are guaranteed to write
// their results in order -- so there is no need to insert an s_waitcnt between
// two instructions of the same type that write the same vgpr.
enum VmemType {
  // BUF instructions and MIMG instructions without a sampler.
  VMEM_NOSAMPLER,
  // MIMG instructions with a sampler.
  VMEM_SAMPLER,
  // BVH instructions
  VMEM_BVH,
  NUM_VMEM_TYPES
};

// Maps values of InstCounterType to the instruction that waits on that
// counter. Only used if GCNSubtarget::hasExtendedWaitCounts()
// returns true, and does not cover VA_VDST or VM_VSRC.
static const unsigned
    instrsForExtendedCounterTypes[AMDGPU::NUM_EXTENDED_INST_CNTS] = {
        AMDGPU::S_WAIT_LOADCNT,   AMDGPU::S_WAIT_DSCNT,
        AMDGPU::S_WAIT_EXPCNT,    AMDGPU::S_WAIT_STORECNT,
        AMDGPU::S_WAIT_SAMPLECNT, AMDGPU::S_WAIT_BVHCNT,
        AMDGPU::S_WAIT_KMCNT,     AMDGPU::S_WAIT_XCNT,
        AMDGPU::S_WAIT_ASYNCCNT};

// ASYNCMARK and WAIT_ASYNCMARK are meta instructions that emit no hardware
// code but still need to be processed by this pass for async vmcnt tracking.
static bool isNonWaitcntMetaInst(const MachineInstr &MI) {
  switch (MI.getOpcode()) {
  case AMDGPU::ASYNCMARK:
  case AMDGPU::WAIT_ASYNCMARK:
    return false;
  default:
    return MI.isMetaInstruction();
  }
}

static bool updateVMCntOnly(const MachineInstr &Inst) {
  return (SIInstrInfo::isVMEM(Inst) && !SIInstrInfo::isFLAT(Inst)) ||
         SIInstrInfo::isFLATGlobal(Inst) || SIInstrInfo::isFLATScratch(Inst);
}

#ifndef NDEBUG
static bool isNormalMode(AMDGPU::InstCounterType MaxCounter) {
  return MaxCounter == AMDGPU::NUM_NORMAL_INST_CNTS;
}
#endif // NDEBUG

VmemType getVmemType(const MachineInstr &Inst) {
  assert(updateVMCntOnly(Inst));
  if (!SIInstrInfo::isImage(Inst))
    return VMEM_NOSAMPLER;
  const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Inst.getOpcode());
  const AMDGPU::MIMGBaseOpcodeInfo *BaseInfo =
      AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);

  if (BaseInfo->BVH)
    return VMEM_BVH;

  // We have to make an additional check for isVSAMPLE here since some
  // instructions don't have a sampler, but are still classified as sampler
  // instructions for the purposes of e.g. waitcnt.
  if (BaseInfo->Sampler || BaseInfo->MSAA || SIInstrInfo::isVSAMPLE(Inst))
    return VMEM_SAMPLER;

  return VMEM_NOSAMPLER;
}

void addWait(AMDGPU::Waitcnt &Wait, AMDGPU::InstCounterType T, unsigned Count) {
  Wait.set(T, std::min(Wait.get(T), Count));
}

void setNoWait(AMDGPU::Waitcnt &Wait, AMDGPU::InstCounterType T) {
  Wait.set(T, ~0u);
}

/// A small set of events.
class WaitEventSet {
  unsigned Mask = 0;

public:
  WaitEventSet() = default;
  explicit constexpr WaitEventSet(WaitEventType Event) {
    static_assert(NUM_WAIT_EVENTS <= sizeof(Mask) * 8,
                  "Not enough bits in Mask for all the events");
    Mask |= 1 << Event;
  }
  constexpr WaitEventSet(std::initializer_list<WaitEventType> Events) {
    for (auto &E : Events) {
      Mask |= 1 << E;
    }
  }
  void insert(const WaitEventType &Event) { Mask |= 1 << Event; }
  void remove(const WaitEventType &Event) { Mask &= ~(1 << Event); }
  void remove(const WaitEventSet &Other) { Mask &= ~Other.Mask; }
  bool contains(const WaitEventType &Event) const {
    return Mask & (1 << Event);
  }
  /// \Returns true if this set contains all elements of \p Other.
  bool contains(const WaitEventSet &Other) const {
    return (~Mask & Other.Mask) == 0;
  }
  /// \Returns the intersection of this and \p Other.
  WaitEventSet operator&(const WaitEventSet &Other) const {
    auto Copy = *this;
    Copy.Mask &= Other.Mask;
    return Copy;
  }
  /// \Returns the union of this and \p Other.
  WaitEventSet operator|(const WaitEventSet &Other) const {
    auto Copy = *this;
    Copy.Mask |= Other.Mask;
    return Copy;
  }
  /// This set becomes the union of this and \p Other.
  WaitEventSet &operator|=(const WaitEventSet &Other) {
    Mask |= Other.Mask;
    return *this;
  }
  /// This set becomes the intersection of this and \p Other.
  WaitEventSet &operator&=(const WaitEventSet &Other) {
    Mask &= Other.Mask;
    return *this;
  }
  bool operator==(const WaitEventSet &Other) const {
    return Mask == Other.Mask;
  }
  bool operator!=(const WaitEventSet &Other) const { return !(*this == Other); }
  bool empty() const { return Mask == 0; }
  /// \Returns true if the set contains more than one element.
  bool twoOrMore() const { return Mask & (Mask - 1); }
  operator bool() const { return !empty(); }
  void print(raw_ostream &OS) const {
    ListSeparator LS(", ");
    for (WaitEventType Event : wait_events()) {
      if (contains(Event))
        OS << LS << getWaitEventTypeName(Event);
    }
  }
  LLVM_DUMP_METHOD void dump() const;
};

void WaitEventSet::dump() const {
  print(dbgs());
  dbgs() << "\n";
}

class WaitcntBrackets;

// This abstracts the logic for generating and updating S_WAIT* instructions
// away from the analysis that determines where they are needed. This was
// done because the set of counters and instructions for waiting on them
// underwent a major shift with gfx12, sufficiently so that having this
// abstraction allows the main analysis logic to be simpler than it would
// otherwise have had to become.
class WaitcntGenerator {
protected:
  const GCNSubtarget &ST;
  const SIInstrInfo &TII;
  AMDGPU::IsaVersion IV;
  AMDGPU::InstCounterType MaxCounter;
  bool OptNone;
  bool ExpandWaitcntProfiling = false;
  const AMDGPU::HardwareLimits &Limits;

public:
  WaitcntGenerator() = delete;
  WaitcntGenerator(const WaitcntGenerator &) = delete;
  WaitcntGenerator(const MachineFunction &MF,
                   AMDGPU::InstCounterType MaxCounter,
                   const AMDGPU::HardwareLimits &Limits)
      : ST(MF.getSubtarget<GCNSubtarget>()), TII(*ST.getInstrInfo()),
        IV(AMDGPU::getIsaVersion(ST.getCPU())), MaxCounter(MaxCounter),
        OptNone(MF.getFunction().hasOptNone() ||
                MF.getTarget().getOptLevel() == CodeGenOptLevel::None),
        ExpandWaitcntProfiling(
            MF.getFunction().hasFnAttribute("amdgpu-expand-waitcnt-profiling")),
        Limits(Limits) {}

  // Return true if the current function should be compiled with no
  // optimization.
  bool isOptNone() const { return OptNone; }

  const AMDGPU::HardwareLimits &getLimits() const { return Limits; }

  // Edits an existing sequence of wait count instructions according
  // to an incoming Waitcnt value, which is itself updated to reflect
  // any new wait count instructions which may need to be generated by
  // WaitcntGenerator::createNewWaitcnt(). It will return true if any edits
  // were made.
  //
  // This editing will usually be merely updated operands, but it may also
  // delete instructions if the incoming Wait value indicates they are not
  // needed. It may also remove existing instructions for which a wait
  // is needed if it can be determined that it is better to generate new
  // instructions later, as can happen on gfx12.
  virtual bool
  applyPreexistingWaitcnt(WaitcntBrackets &ScoreBrackets,
                          MachineInstr &OldWaitcntInstr, AMDGPU::Waitcnt &Wait,
                          MachineBasicBlock::instr_iterator It) const = 0;

  // Transform a soft waitcnt into a normal one.
  bool promoteSoftWaitCnt(MachineInstr *Waitcnt) const;

  // Generates new wait count instructions according to the value of
  // Wait, returning true if any new instructions were created.
  // ScoreBrackets is used for profiling expansion.
  virtual bool createNewWaitcnt(MachineBasicBlock &Block,
                                MachineBasicBlock::instr_iterator It,
                                AMDGPU::Waitcnt Wait,
                                const WaitcntBrackets &ScoreBrackets) = 0;

  // Returns the WaitEventSet that corresponds to counter \p T.
  virtual const WaitEventSet &
  getWaitEvents(AMDGPU::InstCounterType T) const = 0;

  /// \returns the counter that corresponds to event \p E.
  AMDGPU::InstCounterType getCounterFromEvent(WaitEventType E) const {
    for (auto T : AMDGPU::inst_counter_types()) {
      if (getWaitEvents(T).contains(E))
        return T;
    }
    llvm_unreachable("event type has no associated counter");
  }

  // Returns a new waitcnt with all counters except VScnt set to 0. If
  // IncludeVSCnt is true, VScnt is set to 0, otherwise it is set to ~0u.
  // AsyncCnt always defaults to ~0u (don't wait for it). It is only updated
  // when a call to @llvm.amdgcn.wait.asyncmark() is processed.
  virtual AMDGPU::Waitcnt getAllZeroWaitcnt(bool IncludeVSCnt) const = 0;

  virtual ~WaitcntGenerator() = default;
};

class WaitcntGeneratorPreGFX12 final : public WaitcntGenerator {
  static constexpr const WaitEventSet
      WaitEventMaskForInstPreGFX12[AMDGPU::NUM_INST_CNTS] = {
          WaitEventSet(
              {VMEM_ACCESS, VMEM_SAMPLER_READ_ACCESS, VMEM_BVH_READ_ACCESS}),
          WaitEventSet({SMEM_ACCESS, LDS_ACCESS, GDS_ACCESS, SQ_MESSAGE}),
          WaitEventSet({EXP_GPR_LOCK, GDS_GPR_LOCK, VMW_GPR_LOCK,
                        EXP_PARAM_ACCESS, EXP_POS_ACCESS, EXP_LDS_ACCESS}),
          WaitEventSet({VMEM_WRITE_ACCESS, SCRATCH_WRITE_ACCESS}),
          WaitEventSet(),
          WaitEventSet(),
          WaitEventSet(),
          WaitEventSet(),
          WaitEventSet(),
          WaitEventSet()};

public:
  using WaitcntGenerator::WaitcntGenerator;
  bool
  applyPreexistingWaitcnt(WaitcntBrackets &ScoreBrackets,
                          MachineInstr &OldWaitcntInstr, AMDGPU::Waitcnt &Wait,
                          MachineBasicBlock::instr_iterator It) const override;

  bool createNewWaitcnt(MachineBasicBlock &Block,
                        MachineBasicBlock::instr_iterator It,
                        AMDGPU::Waitcnt Wait,
                        const WaitcntBrackets &ScoreBrackets) override;

  const WaitEventSet &getWaitEvents(AMDGPU::InstCounterType T) const override {
    return WaitEventMaskForInstPreGFX12[T];
  }

  AMDGPU::Waitcnt getAllZeroWaitcnt(bool IncludeVSCnt) const override;
};

class WaitcntGeneratorGFX12Plus final : public WaitcntGenerator {
protected:
  bool IsExpertMode;
  static constexpr const WaitEventSet
      WaitEventMaskForInstGFX12Plus[AMDGPU::NUM_INST_CNTS] = {
          WaitEventSet({VMEM_ACCESS, GLOBAL_INV_ACCESS}),
          WaitEventSet({LDS_ACCESS, GDS_ACCESS}),
          WaitEventSet({EXP_GPR_LOCK, GDS_GPR_LOCK, VMW_GPR_LOCK,
                        EXP_PARAM_ACCESS, EXP_POS_ACCESS, EXP_LDS_ACCESS}),
          WaitEventSet({VMEM_WRITE_ACCESS, SCRATCH_WRITE_ACCESS}),
          WaitEventSet({VMEM_SAMPLER_READ_ACCESS}),
          WaitEventSet({VMEM_BVH_READ_ACCESS}),
          WaitEventSet({SMEM_ACCESS, SQ_MESSAGE, SCC_WRITE}),
          WaitEventSet({VMEM_GROUP, SMEM_GROUP}),
          WaitEventSet({ASYNC_ACCESS}),
          WaitEventSet({VGPR_CSMACC_WRITE, VGPR_DPMACC_WRITE, VGPR_TRANS_WRITE,
                        VGPR_XDL_WRITE}),
          WaitEventSet({VGPR_LDS_READ, VGPR_FLAT_READ, VGPR_VMEM_READ})};

public:
  WaitcntGeneratorGFX12Plus() = delete;
  WaitcntGeneratorGFX12Plus(const MachineFunction &MF,
                            AMDGPU::InstCounterType MaxCounter,
                            const AMDGPU::HardwareLimits &Limits,
                            bool IsExpertMode)
      : WaitcntGenerator(MF, MaxCounter, Limits), IsExpertMode(IsExpertMode) {}

  bool
  applyPreexistingWaitcnt(WaitcntBrackets &ScoreBrackets,
                          MachineInstr &OldWaitcntInstr, AMDGPU::Waitcnt &Wait,
                          MachineBasicBlock::instr_iterator It) const override;

  bool createNewWaitcnt(MachineBasicBlock &Block,
                        MachineBasicBlock::instr_iterator It,
                        AMDGPU::Waitcnt Wait,
                        const WaitcntBrackets &ScoreBrackets) override;

  const WaitEventSet &getWaitEvents(AMDGPU::InstCounterType T) const override {
    return WaitEventMaskForInstGFX12Plus[T];
  }

  AMDGPU::Waitcnt getAllZeroWaitcnt(bool IncludeVSCnt) const override;
};

// Flags indicating which counters should be flushed in a loop preheader.
struct PreheaderFlushFlags {
  bool FlushVmCnt = false;
  bool FlushDsCnt = false;
};

class SIInsertWaitcnts {
  DenseMap<const Value *, MachineBasicBlock *> SLoadAddresses;
  DenseMap<MachineBasicBlock *, PreheaderFlushFlags> PreheadersToFlush;
  MachineLoopInfo &MLI;
  MachinePostDominatorTree &PDT;
  AliasAnalysis *AA = nullptr;
  MachineFunction &MF;

  struct BlockInfo {
    std::unique_ptr<WaitcntBrackets> Incoming;
    bool Dirty = true;
  };

  MapVector<MachineBasicBlock *, BlockInfo> BlockInfos;

  bool ForceEmitWaitcnt[AMDGPU::NUM_INST_CNTS] = {};

  std::unique_ptr<WaitcntGenerator> WCG;

  // Remember call and return instructions in the function.
  DenseSet<MachineInstr *> CallInsts;
  DenseSet<MachineInstr *> ReturnInsts;

  // Remember all S_ENDPGM instructions. The boolean flag is true if there might
  // be outstanding stores but definitely no outstanding scratch stores, to help
  // with insertion of DEALLOC_VGPRS messages.
  DenseMap<MachineInstr *, bool> EndPgmInsts;

  AMDGPU::HardwareLimits Limits;

public:
  const GCNSubtarget &ST;
  const SIInstrInfo &TII;
  const SIRegisterInfo &TRI;
  const MachineRegisterInfo &MRI;
  AMDGPU::InstCounterType SmemAccessCounter;
  AMDGPU::InstCounterType MaxCounter;
  bool IsExpertMode = false;

  SIInsertWaitcnts(MachineLoopInfo &MLI, MachinePostDominatorTree &PDT,
                   AliasAnalysis *AA, MachineFunction &MF)
      : MLI(MLI), PDT(PDT), AA(AA), MF(MF), ST(MF.getSubtarget<GCNSubtarget>()),
        TII(*ST.getInstrInfo()), TRI(TII.getRegisterInfo()),
        MRI(MF.getRegInfo()) {
    (void)ForceExpCounter;
    (void)ForceLgkmCounter;
    (void)ForceVMCounter;
  }

  const AMDGPU::HardwareLimits &getLimits() const { return Limits; }

  PreheaderFlushFlags getPreheaderFlushFlags(MachineLoop *ML,
                                             const WaitcntBrackets &Brackets);
  PreheaderFlushFlags isPreheaderToFlush(MachineBasicBlock &MBB,
                                         const WaitcntBrackets &ScoreBrackets);
  bool isVMEMOrFlatVMEM(const MachineInstr &MI) const;
  bool isDSRead(const MachineInstr &MI) const;
  bool mayStoreIncrementingDSCNT(const MachineInstr &MI) const;
  bool run();

  void setForceEmitWaitcnt() {
// For non-debug builds, ForceEmitWaitcnt has been initialized to false;
// For debug builds, get the debug counter info and adjust if need be
#ifndef NDEBUG
    if (DebugCounter::isCounterSet(ForceExpCounter) &&
        DebugCounter::shouldExecute(ForceExpCounter)) {
      ForceEmitWaitcnt[AMDGPU::EXP_CNT] = true;
    } else {
      ForceEmitWaitcnt[AMDGPU::EXP_CNT] = false;
    }

    if (DebugCounter::isCounterSet(ForceLgkmCounter) &&
        DebugCounter::shouldExecute(ForceLgkmCounter)) {
      ForceEmitWaitcnt[AMDGPU::DS_CNT] = true;
      ForceEmitWaitcnt[AMDGPU::KM_CNT] = true;
    } else {
      ForceEmitWaitcnt[AMDGPU::DS_CNT] = false;
      ForceEmitWaitcnt[AMDGPU::KM_CNT] = false;
    }

    if (DebugCounter::isCounterSet(ForceVMCounter) &&
        DebugCounter::shouldExecute(ForceVMCounter)) {
      ForceEmitWaitcnt[AMDGPU::LOAD_CNT] = true;
      ForceEmitWaitcnt[AMDGPU::SAMPLE_CNT] = true;
      ForceEmitWaitcnt[AMDGPU::BVH_CNT] = true;
    } else {
      ForceEmitWaitcnt[AMDGPU::LOAD_CNT] = false;
      ForceEmitWaitcnt[AMDGPU::SAMPLE_CNT] = false;
      ForceEmitWaitcnt[AMDGPU::BVH_CNT] = false;
    }

    ForceEmitWaitcnt[AMDGPU::VA_VDST] = false;
    ForceEmitWaitcnt[AMDGPU::VM_VSRC] = false;
#endif // NDEBUG
  }

  // Return the appropriate VMEM_*_ACCESS type for Inst, which must be a VMEM
  // instruction.
  WaitEventType getVmemWaitEventType(const MachineInstr &Inst) const {
    switch (Inst.getOpcode()) {
    // FIXME: GLOBAL_INV needs to be tracked with xcnt too.
    case AMDGPU::GLOBAL_INV:
      return GLOBAL_INV_ACCESS; // tracked using loadcnt, but doesn't write
                                // VGPRs
    case AMDGPU::GLOBAL_WB:
    case AMDGPU::GLOBAL_WBINV:
      return VMEM_WRITE_ACCESS; // tracked using storecnt
    default:
      break;
    }

    // Maps VMEM access types to their corresponding WaitEventType.
    static const WaitEventType VmemReadMapping[NUM_VMEM_TYPES] = {
        VMEM_ACCESS, VMEM_SAMPLER_READ_ACCESS, VMEM_BVH_READ_ACCESS};

    assert(SIInstrInfo::isVMEM(Inst));
    // LDS DMA loads are also stores, but on the LDS side. On the VMEM side
    // these should use VM_CNT.
    if (!ST.hasVscnt() || SIInstrInfo::mayWriteLDSThroughDMA(Inst))
      return VMEM_ACCESS;
    if (Inst.mayStore() &&
        (!Inst.mayLoad() || SIInstrInfo::isAtomicNoRet(Inst))) {
      if (TII.mayAccessScratch(Inst))
        return SCRATCH_WRITE_ACCESS;
      return VMEM_WRITE_ACCESS;
    }
    if (!ST.hasExtendedWaitCounts() || SIInstrInfo::isFLAT(Inst))
      return VMEM_ACCESS;
    return VmemReadMapping[getVmemType(Inst)];
  }

  std::optional<WaitEventType>
  getExpertSchedulingEventType(const MachineInstr &Inst) const;

  bool isAsync(const MachineInstr &MI) const {
    if (!SIInstrInfo::isLDSDMA(MI))
      return false;
    if (SIInstrInfo::usesASYNC_CNT(MI))
      return true;
    const MachineOperand *Async =
        TII.getNamedOperand(MI, AMDGPU::OpName::IsAsync);
    return Async && (Async->getImm());
  }

  bool isNonAsyncLdsDmaWrite(const MachineInstr &MI) const {
    return SIInstrInfo::mayWriteLDSThroughDMA(MI) && !isAsync(MI);
  }

  bool isAsyncLdsDmaWrite(const MachineInstr &MI) const {
    return SIInstrInfo::mayWriteLDSThroughDMA(MI) && isAsync(MI);
  }

  bool shouldUpdateAsyncMark(const MachineInstr &MI,
                             AMDGPU::InstCounterType T) const {
    if (!isAsyncLdsDmaWrite(MI))
      return false;
    if (SIInstrInfo::usesASYNC_CNT(MI))
      return T == AMDGPU::ASYNC_CNT;
    return T == AMDGPU::LOAD_CNT;
  }

  bool isVmemAccess(const MachineInstr &MI) const;
  bool generateWaitcntInstBefore(MachineInstr &MI,
                                 WaitcntBrackets &ScoreBrackets,
                                 MachineInstr *OldWaitcntInstr,
                                 PreheaderFlushFlags FlushFlags);
  bool generateWaitcnt(AMDGPU::Waitcnt Wait,
                       MachineBasicBlock::instr_iterator It,
                       MachineBasicBlock &Block, WaitcntBrackets &ScoreBrackets,
                       MachineInstr *OldWaitcntInstr);
  /// \returns all events that correspond to \p Inst.
  WaitEventSet getEventsFor(const MachineInstr &Inst) const;
  void updateEventWaitcntAfter(MachineInstr &Inst,
                               WaitcntBrackets *ScoreBrackets);
  bool isNextENDPGM(MachineBasicBlock::instr_iterator It,
                    MachineBasicBlock *Block) const;
  bool insertForcedWaitAfter(MachineInstr &Inst, MachineBasicBlock &Block,
                             WaitcntBrackets &ScoreBrackets);
  bool insertWaitcntInBlock(MachineFunction &MF, MachineBasicBlock &Block,
                            WaitcntBrackets &ScoreBrackets);
  /// Removes redundant Soft Xcnt Waitcnts in \p Block emitted by the Memory
  /// Legalizer. Returns true if block was modified.
  bool removeRedundantSoftXcnts(MachineBasicBlock &Block);
  void setSchedulingMode(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
                         bool ExpertMode) const;
  const WaitEventSet &getWaitEvents(AMDGPU::InstCounterType T) const {
    return WCG->getWaitEvents(T);
  }
  AMDGPU::InstCounterType getCounterFromEvent(WaitEventType E) const {
    return WCG->getCounterFromEvent(E);
  }
};

// This objects maintains the current score brackets of each wait counter, and
// a per-register scoreboard for each wait counter.
//
// We also maintain the latest score for every event type that can change the
// waitcnt in order to know if there are multiple types of events within
// the brackets. When multiple types of event happen in the bracket,
// wait count may get decreased out of order, therefore we need to put in
// "s_waitcnt 0" before use.
class WaitcntBrackets {
public:
  WaitcntBrackets(const SIInsertWaitcnts *Context) : Context(Context) {
    assert(Context->TRI.getNumRegUnits() < REGUNITS_END);
  }

#ifndef NDEBUG
  ~WaitcntBrackets() {
    unsigned NumUnusedVmem = 0, NumUnusedSGPRs = 0;
    for (auto &[ID, Val] : VMem) {
      if (Val.empty())
        ++NumUnusedVmem;
    }
    for (auto &[ID, Val] : SGPRs) {
      if (Val.empty())
        ++NumUnusedSGPRs;
    }

    if (NumUnusedVmem || NumUnusedSGPRs) {
      errs() << "WaitcntBracket had unused entries at destruction time: "
             << NumUnusedVmem << " VMem and " << NumUnusedSGPRs
             << " SGPR unused entries\n";
      std::abort();
    }
  }
#endif

  bool isSmemCounter(AMDGPU::InstCounterType T) const {
    return T == Context->SmemAccessCounter || T == AMDGPU::X_CNT;
  }

  unsigned getOutstanding(AMDGPU::InstCounterType T) const {
    return ScoreUBs[T] - ScoreLBs[T];
  }

  bool hasPendingVMEM(VMEMID ID, AMDGPU::InstCounterType T) const {
    return getVMemScore(ID, T) > getScoreLB(T);
  }

  /// \Return true if we have no score entries for counter \p T.
  bool empty(AMDGPU::InstCounterType T) const { return getScoreRange(T) == 0; }

private:
  unsigned getScoreLB(AMDGPU::InstCounterType T) const {
    assert(T < AMDGPU::NUM_INST_CNTS);
    return ScoreLBs[T];
  }

  unsigned getScoreUB(AMDGPU::InstCounterType T) const {
    assert(T < AMDGPU::NUM_INST_CNTS);
    return ScoreUBs[T];
  }

  unsigned getScoreRange(AMDGPU::InstCounterType T) const {
    return getScoreUB(T) - getScoreLB(T);
  }

  unsigned getSGPRScore(MCRegUnit RU, AMDGPU::InstCounterType T) const {
    auto It = SGPRs.find(RU);
    return It != SGPRs.end() ? It->second.get(T) : 0;
  }

  unsigned getVMemScore(VMEMID TID, AMDGPU::InstCounterType T) const {
    auto It = VMem.find(TID);
    return It != VMem.end() ? It->second.Scores[T] : 0;
  }

public:
  bool merge(const WaitcntBrackets &Other);

  bool counterOutOfOrder(AMDGPU::InstCounterType T) const;
  void simplifyWaitcnt(AMDGPU::Waitcnt &Wait) const {
    simplifyWaitcnt(Wait, Wait);
  }
  void simplifyWaitcnt(const AMDGPU::Waitcnt &CheckWait,
                       AMDGPU::Waitcnt &UpdateWait) const;
  void simplifyWaitcnt(AMDGPU::InstCounterType T, unsigned &Count) const;
  void simplifyWaitcnt(AMDGPU::Waitcnt &Wait, AMDGPU::InstCounterType T) const;
  void simplifyXcnt(const AMDGPU::Waitcnt &CheckWait,
                    AMDGPU::Waitcnt &UpdateWait) const;
  void simplifyVmVsrc(const AMDGPU::Waitcnt &CheckWait,
                      AMDGPU::Waitcnt &UpdateWait) const;

  void determineWaitForPhysReg(AMDGPU::InstCounterType T, MCPhysReg Reg,
                               AMDGPU::Waitcnt &Wait) const;
  void determineWaitForLDSDMA(AMDGPU::InstCounterType T, VMEMID TID,
                              AMDGPU::Waitcnt &Wait) const;
  AMDGPU::Waitcnt determineAsyncWait(unsigned N);
  void tryClearSCCWriteEvent(MachineInstr *Inst);

  void applyWaitcnt(const AMDGPU::Waitcnt &Wait);
  void applyWaitcnt(AMDGPU::InstCounterType T, unsigned Count);
  void applyWaitcnt(const AMDGPU::Waitcnt &Wait, AMDGPU::InstCounterType T);
  void updateByEvent(WaitEventType E, MachineInstr &MI);
  void recordAsyncMark(MachineInstr &MI);

  bool hasPendingEvent() const { return !PendingEvents.empty(); }
  bool hasPendingEvent(WaitEventType E) const {
    return PendingEvents.contains(E);
  }
  bool hasPendingEvent(AMDGPU::InstCounterType T) const {
    bool HasPending = PendingEvents & Context->getWaitEvents(T);
    assert(HasPending == !empty(T) &&
           "Expected pending events iff scoreboard is not empty");
    return HasPending;
  }

  bool hasMixedPendingEvents(AMDGPU::InstCounterType T) const {
    WaitEventSet Events = PendingEvents & Context->getWaitEvents(T);
    // Return true if more than one bit is set in Events.
    return Events.twoOrMore();
  }

  bool hasPendingFlat() const {
    return ((LastFlatDsCnt > ScoreLBs[AMDGPU::DS_CNT] &&
             LastFlatDsCnt <= ScoreUBs[AMDGPU::DS_CNT]) ||
            (LastFlatLoadCnt > ScoreLBs[AMDGPU::LOAD_CNT] &&
             LastFlatLoadCnt <= ScoreUBs[AMDGPU::LOAD_CNT]));
  }

  void setPendingFlat() {
    LastFlatLoadCnt = ScoreUBs[AMDGPU::LOAD_CNT];
    LastFlatDsCnt = ScoreUBs[AMDGPU::DS_CNT];
  }

  bool hasPendingGDS() const {
    return LastGDS > ScoreLBs[AMDGPU::DS_CNT] &&
           LastGDS <= ScoreUBs[AMDGPU::DS_CNT];
  }

  unsigned getPendingGDSWait() const {
    return std::min(getScoreUB(AMDGPU::DS_CNT) - LastGDS,
                    getWaitCountMax(Context->getLimits(), AMDGPU::DS_CNT) - 1);
  }

  void setPendingGDS() { LastGDS = ScoreUBs[AMDGPU::DS_CNT]; }

  // Return true if there might be pending writes to the vgpr-interval by VMEM
  // instructions with types different from V.
  bool hasOtherPendingVmemTypes(MCPhysReg Reg, VmemType V) const {
    for (MCRegUnit RU : regunits(Reg)) {
      auto It = VMem.find(toVMEMID(RU));
      if (It != VMem.end() && (It->second.VMEMTypes & ~(1 << V)))
        return true;
    }
    return false;
  }

  void clearVgprVmemTypes(MCPhysReg Reg) {
    for (MCRegUnit RU : regunits(Reg)) {
      if (auto It = VMem.find(toVMEMID(RU)); It != VMem.end()) {
        It->second.VMEMTypes = 0;
        if (It->second.empty())
          VMem.erase(It);
      }
    }
  }

  void setStateOnFunctionEntryOrReturn() {
    setScoreUB(AMDGPU::STORE_CNT,
               getScoreUB(AMDGPU::STORE_CNT) +
                   getWaitCountMax(Context->getLimits(), AMDGPU::STORE_CNT));
    PendingEvents |= Context->getWaitEvents(AMDGPU::STORE_CNT);
  }

  ArrayRef<const MachineInstr *> getLDSDMAStores() const {
    return LDSDMAStores;
  }

  bool hasPointSampleAccel(const MachineInstr &MI) const;
  bool hasPointSamplePendingVmemTypes(const MachineInstr &MI,
                                      MCPhysReg RU) const;

  void print(raw_ostream &) const;
  void dump() const { print(dbgs()); }

  // Free up memory by removing empty entries from the DenseMap that track event
  // scores.
  void purgeEmptyTrackingData();

private:
  struct MergeInfo {
    unsigned OldLB;
    unsigned OtherLB;
    unsigned MyShift;
    unsigned OtherShift;
  };

  using CounterValueArray = std::array<unsigned, AMDGPU::NUM_INST_CNTS>;

  void determineWaitForScore(AMDGPU::InstCounterType T, unsigned Score,
                             AMDGPU::Waitcnt &Wait) const;

  static bool mergeScore(const MergeInfo &M, unsigned &Score,
                         unsigned OtherScore);
  bool mergeAsyncMarks(ArrayRef<MergeInfo> MergeInfos,
                       ArrayRef<CounterValueArray> OtherMarks);

  iterator_range<MCRegUnitIterator> regunits(MCPhysReg Reg) const {
    assert(Reg != AMDGPU::SCC && "Shouldn't be used on SCC");
    if (!Context->TRI.isInAllocatableClass(Reg))
      return {{}, {}};
    const TargetRegisterClass *RC = Context->TRI.getPhysRegBaseClass(Reg);
    unsigned Size = Context->TRI.getRegSizeInBits(*RC);
    if (Size == 16 && Context->ST.hasD16Writes32BitVgpr())
      Reg = Context->TRI.get32BitRegister(Reg);
    return Context->TRI.regunits(Reg);
  }

  void setScoreLB(AMDGPU::InstCounterType T, unsigned Val) {
    assert(T < AMDGPU::NUM_INST_CNTS);
    ScoreLBs[T] = Val;
  }

  void setScoreUB(AMDGPU::InstCounterType T, unsigned Val) {
    assert(T < AMDGPU::NUM_INST_CNTS);
    ScoreUBs[T] = Val;

    if (T != AMDGPU::EXP_CNT)
      return;

    if (getScoreRange(AMDGPU::EXP_CNT) >
        getWaitCountMax(Context->getLimits(), AMDGPU::EXP_CNT))
      ScoreLBs[AMDGPU::EXP_CNT] =
          ScoreUBs[AMDGPU::EXP_CNT] -
          getWaitCountMax(Context->getLimits(), AMDGPU::EXP_CNT);
  }

  void setRegScore(MCPhysReg Reg, AMDGPU::InstCounterType T, unsigned Val) {
    const SIRegisterInfo &TRI = Context->TRI;
    if (Reg == AMDGPU::SCC) {
      SCCScore = Val;
    } else if (TRI.isVectorRegister(Context->MRI, Reg)) {
      for (MCRegUnit RU : regunits(Reg))
        VMem[toVMEMID(RU)].Scores[T] = Val;
    } else if (TRI.isSGPRReg(Context->MRI, Reg)) {
      for (MCRegUnit RU : regunits(Reg))
        SGPRs[RU].get(T) = Val;
    } else {
      llvm_unreachable("Register cannot be tracked/unknown register!");
    }
  }

  void setVMemScore(VMEMID TID, AMDGPU::InstCounterType T, unsigned Val) {
    VMem[TID].Scores[T] = Val;
  }

  void setScoreByOperand(const MachineOperand &Op,
                         AMDGPU::InstCounterType CntTy, unsigned Val);

  const SIInsertWaitcnts *Context;

  unsigned ScoreLBs[AMDGPU::NUM_INST_CNTS] = {0};
  unsigned ScoreUBs[AMDGPU::NUM_INST_CNTS] = {0};
  WaitEventSet PendingEvents;
  // Remember the last flat memory operation.
  unsigned LastFlatDsCnt = 0;
  unsigned LastFlatLoadCnt = 0;
  // Remember the last GDS operation.
  unsigned LastGDS = 0;

  // The score tracking logic is fragmented as follows:
  // - VMem: VGPR RegUnits and LDS DMA IDs, see the VMEMID encoding.
  // - SGPRs: SGPR RegUnits
  // - SCC: Non-allocatable and not general purpose: not a SGPR.
  //
  // For the VMem case, if the key is within the range of LDS DMA IDs,
  // then the corresponding index into the `LDSDMAStores` vector below is:
  //   Key - LDSDMA_BEGIN - 1
  // This is because LDSDMA_BEGIN is a generic entry and does not have an
  // associated MachineInstr.
  //
  // TODO: Could we track SCC alongside SGPRs so it's not longer a special case?

  struct VMEMInfo {
    // Scores for all instruction counters. Zero-initialized.
    CounterValueArray Scores{};
    // Bitmask of the VmemTypes of VMEM instructions for this VGPR.
    unsigned VMEMTypes = 0;

    bool empty() const { return all_of(Scores, equal_to(0)) && !VMEMTypes; }
  };

  /// Wait cnt scores for every sgpr, the DS_CNT (corresponding to LGKMcnt
  /// pre-gfx12) or KM_CNT (gfx12+ only), and X_CNT (gfx1250) are relevant.
  class SGPRInfo {
    /// Either DS_CNT or KM_CNT score.
    unsigned ScoreDsKmCnt = 0;
    unsigned ScoreXCnt = 0;

  public:
    unsigned get(AMDGPU::InstCounterType T) const {
      assert(
          (T == AMDGPU::DS_CNT || T == AMDGPU::KM_CNT || T == AMDGPU::X_CNT) &&
          "Invalid counter");
      return T == AMDGPU::X_CNT ? ScoreXCnt : ScoreDsKmCnt;
    }
    unsigned &get(AMDGPU::InstCounterType T) {
      assert(
          (T == AMDGPU::DS_CNT || T == AMDGPU::KM_CNT || T == AMDGPU::X_CNT) &&
          "Invalid counter");
      return T == AMDGPU::X_CNT ? ScoreXCnt : ScoreDsKmCnt;
    }

    bool empty() const { return !ScoreDsKmCnt && !ScoreXCnt; }
  };

  DenseMap<VMEMID, VMEMInfo> VMem; // VGPR + LDS DMA
  DenseMap<MCRegUnit, SGPRInfo> SGPRs;

  // Reg score for SCC.
  unsigned SCCScore = 0;
  // The unique instruction that has an SCC write pending, if there is one.
  const MachineInstr *PendingSCCWrite = nullptr;

  // Store representative LDS DMA operations. The only useful info here is
  // alias info. One store is kept per unique AAInfo.
  SmallVector<const MachineInstr *> LDSDMAStores;

  // State of all counters at each async mark encountered so far.
  SmallVector<CounterValueArray> AsyncMarks;

  // But in the rare pathological case, a nest of loops that pushes marks
  // without waiting on any mark can cause AsyncMarks to grow very large. We cap
  // it to a reasonable limit. We can tune this later or potentially introduce a
  // user option to control the value.
  static constexpr unsigned MaxAsyncMarks = 16;

  // Track the upper bound score for async operations that are not part of a
  // mark yet. Initialized to all zeros.
  CounterValueArray AsyncScore{};
};

class SIInsertWaitcntsLegacy : public MachineFunctionPass {
public:
  static char ID;
  SIInsertWaitcntsLegacy() : MachineFunctionPass(ID) {}

  bool runOnMachineFunction(MachineFunction &MF) override;

  StringRef getPassName() const override {
    return "SI insert wait instructions";
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesCFG();
    AU.addRequired<MachineLoopInfoWrapperPass>();
    AU.addRequired<MachinePostDominatorTreeWrapperPass>();
    AU.addUsedIfAvailable<AAResultsWrapperPass>();
    AU.addPreserved<AAResultsWrapperPass>();
    MachineFunctionPass::getAnalysisUsage(AU);
  }
};

} // end anonymous namespace

void WaitcntBrackets::setScoreByOperand(const MachineOperand &Op,
                                        AMDGPU::InstCounterType CntTy,
                                        unsigned Score) {
  setRegScore(Op.getReg().asMCReg(), CntTy, Score);
}

// Return true if the subtarget is one that enables Point Sample Acceleration
// and the MachineInstr passed in is one to which it might be applied (the
// hardware makes this decision based on several factors, but we can't determine
// this at compile time, so we have to assume it might be applied if the
// instruction supports it).
bool WaitcntBrackets::hasPointSampleAccel(const MachineInstr &MI) const {
  if (!Context->ST.hasPointSampleAccel() || !SIInstrInfo::isMIMG(MI))
    return false;

  const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(MI.getOpcode());
  const AMDGPU::MIMGBaseOpcodeInfo *BaseInfo =
      AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
  return BaseInfo->PointSampleAccel;
}

// Return true if the subtarget enables Point Sample Acceleration, the supplied
// MachineInstr is one to which it might be applied and the supplied interval is
// one that has outstanding writes to vmem-types different than VMEM_NOSAMPLER
// (this is the type that a point sample accelerated instruction effectively
// becomes)
bool WaitcntBrackets::hasPointSamplePendingVmemTypes(const MachineInstr &MI,
                                                     MCPhysReg Reg) const {
  if (!hasPointSampleAccel(MI))
    return false;

  return hasOtherPendingVmemTypes(Reg, VMEM_NOSAMPLER);
}

void WaitcntBrackets::updateByEvent(WaitEventType E, MachineInstr &Inst) {
  AMDGPU::InstCounterType T = Context->getCounterFromEvent(E);
  assert(T < Context->MaxCounter);

  unsigned UB = getScoreUB(T);
  unsigned CurrScore = UB + 1;
  if (CurrScore == 0)
    report_fatal_error("InsertWaitcnt score wraparound");
  // PendingEvents and ScoreUB need to be update regardless if this event
  // changes the score of a register or not.
  // Examples including vm_cnt when buffer-store or lgkm_cnt when send-message.
  PendingEvents.insert(E);
  setScoreUB(T, CurrScore);

  const SIRegisterInfo &TRI = Context->TRI;
  const MachineRegisterInfo &MRI = Context->MRI;
  const SIInstrInfo &TII = Context->TII;

  if (T == AMDGPU::EXP_CNT) {
    // Put score on the source vgprs. If this is a store, just use those
    // specific register(s).
    if (TII.isDS(Inst) && Inst.mayLoadOrStore()) {
      // All GDS operations must protect their address register (same as
      // export.)
      if (const auto *AddrOp = TII.getNamedOperand(Inst, AMDGPU::OpName::addr))
        setScoreByOperand(*AddrOp, AMDGPU::EXP_CNT, CurrScore);

      if (Inst.mayStore()) {
        if (const auto *Data0 =
                TII.getNamedOperand(Inst, AMDGPU::OpName::data0))
          setScoreByOperand(*Data0, AMDGPU::EXP_CNT, CurrScore);
        if (const auto *Data1 =
                TII.getNamedOperand(Inst, AMDGPU::OpName::data1))
          setScoreByOperand(*Data1, AMDGPU::EXP_CNT, CurrScore);
      } else if (SIInstrInfo::isAtomicRet(Inst) && !SIInstrInfo::isGWS(Inst) &&
                 Inst.getOpcode() != AMDGPU::DS_APPEND &&
                 Inst.getOpcode() != AMDGPU::DS_CONSUME &&
                 Inst.getOpcode() != AMDGPU::DS_ORDERED_COUNT) {
        for (const MachineOperand &Op : Inst.all_uses()) {
          if (TRI.isVectorRegister(MRI, Op.getReg()))
            setScoreByOperand(Op, AMDGPU::EXP_CNT, CurrScore);
        }
      }
    } else if (TII.isFLAT(Inst)) {
      if (Inst.mayStore()) {
        setScoreByOperand(*TII.getNamedOperand(Inst, AMDGPU::OpName::data),
                          AMDGPU::EXP_CNT, CurrScore);
      } else if (SIInstrInfo::isAtomicRet(Inst)) {
        setScoreByOperand(*TII.getNamedOperand(Inst, AMDGPU::OpName::data),
                          AMDGPU::EXP_CNT, CurrScore);
      }
    } else if (TII.isMIMG(Inst)) {
      if (Inst.mayStore()) {
        setScoreByOperand(Inst.getOperand(0), AMDGPU::EXP_CNT, CurrScore);
      } else if (SIInstrInfo::isAtomicRet(Inst)) {
        setScoreByOperand(*TII.getNamedOperand(Inst, AMDGPU::OpName::data),
                          AMDGPU::EXP_CNT, CurrScore);
      }
    } else if (TII.isMTBUF(Inst)) {
      if (Inst.mayStore())
        setScoreByOperand(Inst.getOperand(0), AMDGPU::EXP_CNT, CurrScore);
    } else if (TII.isMUBUF(Inst)) {
      if (Inst.mayStore()) {
        setScoreByOperand(Inst.getOperand(0), AMDGPU::EXP_CNT, CurrScore);
      } else if (SIInstrInfo::isAtomicRet(Inst)) {
        setScoreByOperand(*TII.getNamedOperand(Inst, AMDGPU::OpName::data),
                          AMDGPU::EXP_CNT, CurrScore);
      }
    } else if (TII.isLDSDIR(Inst)) {
      // LDSDIR instructions attach the score to the destination.
      setScoreByOperand(*TII.getNamedOperand(Inst, AMDGPU::OpName::vdst),
                        AMDGPU::EXP_CNT, CurrScore);
    } else {
      if (TII.isEXP(Inst)) {
        // For export the destination registers are really temps that
        // can be used as the actual source after export patching, so
        // we need to treat them like sources and set the EXP_CNT
        // score.
        for (MachineOperand &DefMO : Inst.all_defs()) {
          if (TRI.isVGPR(MRI, DefMO.getReg())) {
            setScoreByOperand(DefMO, AMDGPU::EXP_CNT, CurrScore);
          }
        }
      }
      for (const MachineOperand &Op : Inst.all_uses()) {
        if (TRI.isVectorRegister(MRI, Op.getReg()))
          setScoreByOperand(Op, AMDGPU::EXP_CNT, CurrScore);
      }
    }
  } else if (T == AMDGPU::X_CNT) {
    WaitEventType OtherEvent = E == SMEM_GROUP ? VMEM_GROUP : SMEM_GROUP;
    if (PendingEvents.contains(OtherEvent)) {
      // Hardware inserts an implicit xcnt between interleaved
      // SMEM and VMEM operations. So there will never be
      // outstanding address translations for both SMEM and
      // VMEM at the same time.
      setScoreLB(T, getScoreUB(T) - 1);
      PendingEvents.remove(OtherEvent);
    }
    for (const MachineOperand &Op : Inst.all_uses())
      setScoreByOperand(Op, T, CurrScore);
  } else if (T == AMDGPU::VA_VDST || T == AMDGPU::VM_VSRC) {
    // Match the score to the VGPR destination or source registers as
    // appropriate
    for (const MachineOperand &Op : Inst.operands()) {
      if (!Op.isReg() || (T == AMDGPU::VA_VDST && Op.isUse()) ||
          (T == AMDGPU::VM_VSRC && Op.isDef()))
        continue;
      if (TRI.isVectorRegister(Context->MRI, Op.getReg()))
        setScoreByOperand(Op, T, CurrScore);
    }
  } else /* LGKM_CNT || EXP_CNT || VS_CNT || NUM_INST_CNTS */ {
    // Match the score to the destination registers.
    //
    // Check only explicit operands. Stores, especially spill stores, include
    // implicit uses and defs of their super registers which would create an
    // artificial dependency, while these are there only for register liveness
    // accounting purposes.
    //
    // Special cases where implicit register defs exists, such as M0 or VCC,
    // but none with memory instructions.
    for (const MachineOperand &Op : Inst.defs()) {
      if (T == AMDGPU::LOAD_CNT || T == AMDGPU::SAMPLE_CNT ||
          T == AMDGPU::BVH_CNT) {
        if (!TRI.isVectorRegister(MRI, Op.getReg())) // TODO: add wrapper
          continue;
        if (updateVMCntOnly(Inst)) {
          // updateVMCntOnly should only leave us with VGPRs
          // MUBUF, MTBUF, MIMG, FlatGlobal, and FlatScratch only have VGPR/AGPR
          // defs. That's required for a sane index into `VgprMemTypes` below
          assert(TRI.isVectorRegister(MRI, Op.getReg()));
          VmemType V = getVmemType(Inst);
          unsigned char TypesMask = 1 << V;
          // If instruction can have Point Sample Accel applied, we have to flag
          // this with another potential dependency
          if (hasPointSampleAccel(Inst))
            TypesMask |= 1 << VMEM_NOSAMPLER;
          for (MCRegUnit RU : regunits(Op.getReg().asMCReg()))
            VMem[toVMEMID(RU)].VMEMTypes |= TypesMask;
        }
      }
      setScoreByOperand(Op, T, CurrScore);
    }
    if (Inst.mayStore() &&
        (TII.isDS(Inst) || Context->isNonAsyncLdsDmaWrite(Inst))) {
      // MUBUF and FLAT LDS DMA operations need a wait on vmcnt before LDS
      // written can be accessed. A load from LDS to VMEM does not need a wait.
      //
      // The "Slot" is the offset from LDSDMA_BEGIN. If it's non-zero, then
      // there is a MachineInstr in LDSDMAStores used to track this LDSDMA
      // store. The "Slot" is the index into LDSDMAStores + 1.
      unsigned Slot = 0;
      for (const auto *MemOp : Inst.memoperands()) {
        if (!MemOp->isStore() ||
            MemOp->getAddrSpace() != AMDGPUAS::LOCAL_ADDRESS)
          continue;
        // Comparing just AA info does not guarantee memoperands are equal
        // in general, but this is so for LDS DMA in practice.
        auto AAI = MemOp->getAAInfo();
        // Alias scope information gives a way to definitely identify an
        // original memory object and practically produced in the module LDS
        // lowering pass. If there is no scope available we will not be able
        // to disambiguate LDS aliasing as after the module lowering all LDS
        // is squashed into a single big object.
        if (!AAI || !AAI.Scope)
          break;
        for (unsigned I = 0, E = LDSDMAStores.size(); I != E && !Slot; ++I) {
          for (const auto *MemOp : LDSDMAStores[I]->memoperands()) {
            if (MemOp->isStore() && AAI == MemOp->getAAInfo()) {
              Slot = I + 1;
              break;
            }
          }
        }
        if (Slot)
          break;
        // The slot may not be valid because it can be >= NUM_LDSDMA which
        // means the scoreboard cannot track it. We still want to preserve the
        // MI in order to check alias information, though.
        LDSDMAStores.push_back(&Inst);
        Slot = LDSDMAStores.size();
        break;
      }
      setVMemScore(LDSDMA_BEGIN, T, CurrScore);
      if (Slot && Slot < NUM_LDSDMA)
        setVMemScore(LDSDMA_BEGIN + Slot, T, CurrScore);
    }

    if (Context->shouldUpdateAsyncMark(Inst, T)) {
      AsyncScore[T] = CurrScore;
    }

    if (SIInstrInfo::isSBarrierSCCWrite(Inst.getOpcode())) {
      setRegScore(AMDGPU::SCC, T, CurrScore);
      PendingSCCWrite = &Inst;
    }
  }
}

void WaitcntBrackets::recordAsyncMark(MachineInstr &Inst) {
  // In the absence of loops, AsyncMarks can grow linearly with the program
  // until we encounter an ASYNCMARK_WAIT. We could drop the oldest mark above a
  // limit every time we push a new mark, but that seems like unnecessary work
  // in practical cases. We do separately truncate the array when processing a
  // loop, which should be sufficient.
  AsyncMarks.push_back(AsyncScore);
  AsyncScore = {};
  LLVM_DEBUG({
    dbgs() << "recordAsyncMark:\n" << Inst;
    for (const auto &Mark : AsyncMarks) {
      llvm::interleaveComma(Mark, dbgs());
      dbgs() << '\n';
    }
  });
}

void WaitcntBrackets::print(raw_ostream &OS) const {
  const GCNSubtarget &ST = Context->ST;

  for (auto T : inst_counter_types(Context->MaxCounter)) {
    unsigned SR = getScoreRange(T);
    switch (T) {
    case AMDGPU::LOAD_CNT:
      OS << "    " << (ST.hasExtendedWaitCounts() ? "LOAD" : "VM") << "_CNT("
         << SR << "):";
      break;
    case AMDGPU::DS_CNT:
      OS << "    " << (ST.hasExtendedWaitCounts() ? "DS" : "LGKM") << "_CNT("
         << SR << "):";
      break;
    case AMDGPU::EXP_CNT:
      OS << "    EXP_CNT(" << SR << "):";
      break;
    case AMDGPU::STORE_CNT:
      OS << "    " << (ST.hasExtendedWaitCounts() ? "STORE" : "VS") << "_CNT("
         << SR << "):";
      break;
    case AMDGPU::SAMPLE_CNT:
      OS << "    SAMPLE_CNT(" << SR << "):";
      break;
    case AMDGPU::BVH_CNT:
      OS << "    BVH_CNT(" << SR << "):";
      break;
    case AMDGPU::KM_CNT:
      OS << "    KM_CNT(" << SR << "):";
      break;
    case AMDGPU::X_CNT:
      OS << "    X_CNT(" << SR << "):";
      break;
    case AMDGPU::ASYNC_CNT:
      OS << "    ASYNC_CNT(" << SR << "):";
      break;
    case AMDGPU::VA_VDST:
      OS << "    VA_VDST(" << SR << "): ";
      break;
    case AMDGPU::VM_VSRC:
      OS << "    VM_VSRC(" << SR << "): ";
      break;
    default:
      OS << "    UNKNOWN(" << SR << "):";
      break;
    }

    if (SR != 0) {
      // Print vgpr scores.
      unsigned LB = getScoreLB(T);

      SmallVector<VMEMID> SortedVMEMIDs(VMem.keys());
      sort(SortedVMEMIDs);

      for (auto ID : SortedVMEMIDs) {
        unsigned RegScore = VMem.at(ID).Scores[T];
        if (RegScore <= LB)
          continue;
        unsigned RelScore = RegScore - LB - 1;
        if (ID < REGUNITS_END) {
          OS << ' ' << RelScore << ":vRU" << ID;
        } else {
          assert(ID >= LDSDMA_BEGIN && ID < LDSDMA_END &&
                 "Unhandled/unexpected ID value!");
          OS << ' ' << RelScore << ":LDSDMA" << ID;
        }
      }

      // Also need to print sgpr scores for lgkm_cnt or xcnt.
      if (isSmemCounter(T)) {
        SmallVector<MCRegUnit> SortedSMEMIDs(SGPRs.keys());
        sort(SortedSMEMIDs);
        for (auto ID : SortedSMEMIDs) {
          unsigned RegScore = SGPRs.at(ID).get(T);
          if (RegScore <= LB)
            continue;
          unsigned RelScore = RegScore - LB - 1;
          OS << ' ' << RelScore << ":sRU" << static_cast<unsigned>(ID);
        }
      }

      if (T == AMDGPU::KM_CNT && SCCScore > 0)
        OS << ' ' << SCCScore << ":scc";
    }
    OS << '\n';
  }

  OS << "Pending Events: ";
  if (hasPendingEvent()) {
    ListSeparator LS;
    for (unsigned I = 0; I != NUM_WAIT_EVENTS; ++I) {
      if (hasPendingEvent((WaitEventType)I)) {
        OS << LS << WaitEventTypeName[I];
      }
    }
  } else {
    OS << "none";
  }
  OS << '\n';

  OS << "Async score: ";
  if (AsyncScore.empty())
    OS << "none";
  else
    llvm::interleaveComma(AsyncScore, OS);
  OS << '\n';

  OS << "Async marks: " << AsyncMarks.size() << '\n';

  for (const auto &Mark : AsyncMarks) {
    for (auto T : AMDGPU::inst_counter_types()) {
      unsigned MarkedScore = Mark[T];
      switch (T) {
      case AMDGPU::LOAD_CNT:
        OS << "  " << (ST.hasExtendedWaitCounts() ? "LOAD" : "VM")
           << "_CNT: " << MarkedScore;
        break;
      case AMDGPU::DS_CNT:
        OS << "  " << (ST.hasExtendedWaitCounts() ? "DS" : "LGKM")
           << "_CNT: " << MarkedScore;
        break;
      case AMDGPU::EXP_CNT:
        OS << "  EXP_CNT: " << MarkedScore;
        break;
      case AMDGPU::STORE_CNT:
        OS << "  " << (ST.hasExtendedWaitCounts() ? "STORE" : "VS")
           << "_CNT: " << MarkedScore;
        break;
      case AMDGPU::SAMPLE_CNT:
        OS << "  SAMPLE_CNT: " << MarkedScore;
        break;
      case AMDGPU::BVH_CNT:
        OS << "  BVH_CNT: " << MarkedScore;
        break;
      case AMDGPU::KM_CNT:
        OS << "  KM_CNT: " << MarkedScore;
        break;
      case AMDGPU::X_CNT:
        OS << "  X_CNT: " << MarkedScore;
        break;
      case AMDGPU::ASYNC_CNT:
        OS << "  ASYNC_CNT: " << MarkedScore;
        break;
      default:
        OS << "  UNKNOWN: " << MarkedScore;
        break;
      }
    }
    OS << '\n';
  }
  OS << '\n';
}

/// Simplify \p UpdateWait by removing waits that are redundant based on the
/// current WaitcntBrackets and any other waits specified in \p CheckWait.
void WaitcntBrackets::simplifyWaitcnt(const AMDGPU::Waitcnt &CheckWait,
                                      AMDGPU::Waitcnt &UpdateWait) const {
  simplifyWaitcnt(UpdateWait, AMDGPU::LOAD_CNT);
  simplifyWaitcnt(UpdateWait, AMDGPU::EXP_CNT);
  simplifyWaitcnt(UpdateWait, AMDGPU::DS_CNT);
  simplifyWaitcnt(UpdateWait, AMDGPU::STORE_CNT);
  simplifyWaitcnt(UpdateWait, AMDGPU::SAMPLE_CNT);
  simplifyWaitcnt(UpdateWait, AMDGPU::BVH_CNT);
  simplifyWaitcnt(UpdateWait, AMDGPU::KM_CNT);
  simplifyXcnt(CheckWait, UpdateWait);
  simplifyWaitcnt(UpdateWait, AMDGPU::VA_VDST);
  simplifyVmVsrc(CheckWait, UpdateWait);
  simplifyWaitcnt(UpdateWait, AMDGPU::ASYNC_CNT);
}

void WaitcntBrackets::simplifyWaitcnt(AMDGPU::InstCounterType T,
                                      unsigned &Count) const {
  // The number of outstanding events for this type, T, can be calculated
  // as (UB - LB). If the current Count is greater than or equal to the number
  // of outstanding events, then the wait for this counter is redundant.
  if (Count >= getScoreRange(T))
    Count = ~0u;
}

void WaitcntBrackets::simplifyWaitcnt(AMDGPU::Waitcnt &Wait,
                                      AMDGPU::InstCounterType T) const {
  unsigned Cnt = Wait.get(T);
  simplifyWaitcnt(T, Cnt);
  Wait.set(T, Cnt);
}

void WaitcntBrackets::simplifyXcnt(const AMDGPU::Waitcnt &CheckWait,
                                   AMDGPU::Waitcnt &UpdateWait) const {
  // Try to simplify xcnt further by checking for joint kmcnt and loadcnt
  // optimizations. On entry to a block with multiple predescessors, there may
  // be pending SMEM and VMEM events active at the same time.
  // In such cases, only clear one active event at a time.
  // TODO: Revisit xcnt optimizations for gfx1250.
  // Wait on XCNT is redundant if we are already waiting for a load to complete.
  // SMEM can return out of order, so only omit XCNT wait if we are waiting till
  // zero.
  if (CheckWait.get(AMDGPU::KM_CNT) == 0 && hasPendingEvent(SMEM_GROUP))
    UpdateWait.set(AMDGPU::X_CNT, ~0u);
  // If we have pending store we cannot optimize XCnt because we do not wait for
  // stores. VMEM loads retun in order, so if we only have loads XCnt is
  // decremented to the same number as LOADCnt.
  if (CheckWait.get(AMDGPU::LOAD_CNT) != ~0u && hasPendingEvent(VMEM_GROUP) &&
      !hasPendingEvent(AMDGPU::STORE_CNT) &&
      CheckWait.get(AMDGPU::X_CNT) >= CheckWait.get(AMDGPU::LOAD_CNT))
    UpdateWait.set(AMDGPU::X_CNT, ~0u);
  simplifyWaitcnt(UpdateWait, AMDGPU::X_CNT);
}

void WaitcntBrackets::simplifyVmVsrc(const AMDGPU::Waitcnt &CheckWait,
                                     AMDGPU::Waitcnt &UpdateWait) const {
  // Waiting for some counters implies waiting for VM_VSRC, since an
  // instruction that decrements a counter on completion would have
  // decremented VM_VSRC once its VGPR operands had been read.
  if (CheckWait.get(AMDGPU::VM_VSRC) >=
      std::min({CheckWait.get(AMDGPU::LOAD_CNT),
                CheckWait.get(AMDGPU::STORE_CNT),
                CheckWait.get(AMDGPU::SAMPLE_CNT),
                CheckWait.get(AMDGPU::BVH_CNT), CheckWait.get(AMDGPU::DS_CNT)}))
    UpdateWait.set(AMDGPU::VM_VSRC, ~0u);
  simplifyWaitcnt(UpdateWait, AMDGPU::VM_VSRC);
}

void WaitcntBrackets::purgeEmptyTrackingData() {
  for (auto &[K, V] : make_early_inc_range(VMem)) {
    if (V.empty())
      VMem.erase(K);
  }
  for (auto &[K, V] : make_early_inc_range(SGPRs)) {
    if (V.empty())
      SGPRs.erase(K);
  }
}

void WaitcntBrackets::determineWaitForScore(AMDGPU::InstCounterType T,
                                            unsigned ScoreToWait,
                                            AMDGPU::Waitcnt &Wait) const {
  const unsigned LB = getScoreLB(T);
  const unsigned UB = getScoreUB(T);

  // If the score falls within the bracket, we need a waitcnt.
  if ((UB >= ScoreToWait) && (ScoreToWait > LB)) {
    if ((T == AMDGPU::LOAD_CNT || T == AMDGPU::DS_CNT) && hasPendingFlat() &&
        !Context->ST.hasFlatLgkmVMemCountInOrder()) {
      // If there is a pending FLAT operation, and this is a VMem or LGKM
      // waitcnt and the target can report early completion, then we need
      // to force a waitcnt 0.
      addWait(Wait, T, 0);
    } else if (counterOutOfOrder(T)) {
      // Counter can get decremented out-of-order when there
      // are multiple types event in the bracket. Also emit an s_wait counter
      // with a conservative value of 0 for the counter.
      addWait(Wait, T, 0);
    } else {
      // If a counter has been maxed out avoid overflow by waiting for
      // MAX(CounterType) - 1 instead.
      unsigned NeededWait = std::min(
          UB - ScoreToWait, getWaitCountMax(Context->getLimits(), T) - 1);
      addWait(Wait, T, NeededWait);
    }
  }
}

AMDGPU::Waitcnt WaitcntBrackets::determineAsyncWait(unsigned N) {
  LLVM_DEBUG({
    dbgs() << "Need " << N << " async marks. Found " << AsyncMarks.size()
           << ":\n";
    for (const auto &Mark : AsyncMarks) {
      llvm::interleaveComma(Mark, dbgs());
      dbgs() << '\n';
    }
  });

  if (AsyncMarks.size() == MaxAsyncMarks) {
    // Enforcing MaxAsyncMarks here is unnecessary work because the size of
    // MaxAsyncMarks is linear when traversing straightline code. But we do
    // need to check if truncation may have occured at a merge, and adjust N
    // to ensure that a wait is generated.
    LLVM_DEBUG(dbgs() << "Possible truncation. Ensuring a non-trivial wait.\n");
    N = std::min(N, (unsigned)MaxAsyncMarks - 1);
  }

  AMDGPU::Waitcnt Wait;
  if (AsyncMarks.size() <= N) {
    LLVM_DEBUG(dbgs() << "No additional wait for async mark.\n");
    return Wait;
  }

  size_t MarkIndex = AsyncMarks.size() - N - 1;
  const auto &RequiredMark = AsyncMarks[MarkIndex];
  for (AMDGPU::InstCounterType T : AMDGPU::inst_counter_types())
    determineWaitForScore(T, RequiredMark[T], Wait);

  // Immediately remove the waited mark and all older ones
  // This happens BEFORE the wait is actually inserted, which is fine
  // because we've already extracted the wait requirements
  LLVM_DEBUG({
    dbgs() << "Removing " << (MarkIndex + 1)
           << " async marks after determining wait\n";
  });
  AsyncMarks.erase(AsyncMarks.begin(), AsyncMarks.begin() + MarkIndex + 1);

  LLVM_DEBUG(dbgs() << "Waits to add: " << Wait);
  return Wait;
}

void WaitcntBrackets::determineWaitForPhysReg(AMDGPU::InstCounterType T,
                                              MCPhysReg Reg,
                                              AMDGPU::Waitcnt &Wait) const {
  if (Reg == AMDGPU::SCC) {
    determineWaitForScore(T, SCCScore, Wait);
  } else {
    bool IsVGPR = Context->TRI.isVectorRegister(Context->MRI, Reg);
    for (MCRegUnit RU : regunits(Reg))
      determineWaitForScore(
          T, IsVGPR ? getVMemScore(toVMEMID(RU), T) : getSGPRScore(RU, T),
          Wait);
  }
}

void WaitcntBrackets::determineWaitForLDSDMA(AMDGPU::InstCounterType T,
                                             VMEMID TID,
                                             AMDGPU::Waitcnt &Wait) const {
  assert(TID >= LDSDMA_BEGIN && TID < LDSDMA_END);
  determineWaitForScore(T, getVMemScore(TID, T), Wait);
}

void WaitcntBrackets::tryClearSCCWriteEvent(MachineInstr *Inst) {
  // S_BARRIER_WAIT on the same barrier guarantees that the pending write to
  // SCC has landed
  if (PendingSCCWrite &&
      PendingSCCWrite->getOpcode() == AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM &&
      PendingSCCWrite->getOperand(0).getImm() == Inst->getOperand(0).getImm()) {
    WaitEventSet SCC_WRITE_PendingEvent(SCC_WRITE);
    // If this SCC_WRITE is the only pending KM_CNT event, clear counter.
    if ((PendingEvents & Context->getWaitEvents(AMDGPU::KM_CNT)) ==
        SCC_WRITE_PendingEvent) {
      setScoreLB(AMDGPU::KM_CNT, getScoreUB(AMDGPU::KM_CNT));
    }

    PendingEvents.remove(SCC_WRITE_PendingEvent);
    PendingSCCWrite = nullptr;
  }
}

void WaitcntBrackets::applyWaitcnt(const AMDGPU::Waitcnt &Wait) {
  for (AMDGPU::InstCounterType T : AMDGPU::inst_counter_types())
    applyWaitcnt(Wait, T);
}

void WaitcntBrackets::applyWaitcnt(AMDGPU::InstCounterType T, unsigned Count) {
  const unsigned UB = getScoreUB(T);
  if (Count >= UB)
    return;
  if (Count != 0) {
    if (counterOutOfOrder(T))
      return;
    setScoreLB(T, std::max(getScoreLB(T), UB - Count));
  } else {
    setScoreLB(T, UB);
    PendingEvents.remove(Context->getWaitEvents(T));
  }

  if (T == AMDGPU::KM_CNT && Count == 0 && hasPendingEvent(SMEM_GROUP)) {
    if (!hasMixedPendingEvents(AMDGPU::X_CNT))
      applyWaitcnt(AMDGPU::X_CNT, 0);
    else
      PendingEvents.remove(SMEM_GROUP);
  }
  if (T == AMDGPU::LOAD_CNT && hasPendingEvent(VMEM_GROUP) &&
      !hasPendingEvent(AMDGPU::STORE_CNT)) {
    if (!hasMixedPendingEvents(AMDGPU::X_CNT))
      applyWaitcnt(AMDGPU::X_CNT, Count);
    else if (Count == 0)
      PendingEvents.remove(VMEM_GROUP);
  }
}

void WaitcntBrackets::applyWaitcnt(const AMDGPU::Waitcnt &Wait,
                                   AMDGPU::InstCounterType T) {
  unsigned Cnt = Wait.get(T);
  applyWaitcnt(T, Cnt);
}

// Where there are multiple types of event in the bracket of a counter,
// the decrement may go out of order.
bool WaitcntBrackets::counterOutOfOrder(AMDGPU::InstCounterType T) const {
  // Scalar memory read always can go out of order.
  if ((T == Context->SmemAccessCounter && hasPendingEvent(SMEM_ACCESS)) ||
      (T == AMDGPU::X_CNT && hasPendingEvent(SMEM_GROUP)))
    return true;

  // GLOBAL_INV completes in-order with other LOAD_CNT events (VMEM_ACCESS),
  // so having GLOBAL_INV_ACCESS mixed with other LOAD_CNT events doesn't cause
  // out-of-order completion.
  if (T == AMDGPU::LOAD_CNT) {
    WaitEventSet Events = PendingEvents & Context->getWaitEvents(T);
    // Remove GLOBAL_INV_ACCESS from the event mask before checking for mixed
    // events
    Events.remove(GLOBAL_INV_ACCESS);
    // Return true only if there are still multiple event types after removing
    // GLOBAL_INV
    return Events.twoOrMore();
  }

  return hasMixedPendingEvents(T);
}

INITIALIZE_PASS_BEGIN(SIInsertWaitcntsLegacy, DEBUG_TYPE, "SI Insert Waitcnts",
                      false, false)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTreeWrapperPass)
INITIALIZE_PASS_END(SIInsertWaitcntsLegacy, DEBUG_TYPE, "SI Insert Waitcnts",
                    false, false)

char SIInsertWaitcntsLegacy::ID = 0;

char &llvm::SIInsertWaitcntsID = SIInsertWaitcntsLegacy::ID;

FunctionPass *llvm::createSIInsertWaitcntsPass() {
  return new SIInsertWaitcntsLegacy();
}

static bool updateOperandIfDifferent(MachineInstr &MI, AMDGPU::OpName OpName,
                                     unsigned NewEnc) {
  int OpIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
  assert(OpIdx >= 0);

  MachineOperand &MO = MI.getOperand(OpIdx);

  if (NewEnc == MO.getImm())
    return false;

  MO.setImm(NewEnc);
  return true;
}

/// Determine if \p MI is a gfx12+ single-counter S_WAIT_*CNT instruction,
/// and if so, which counter it is waiting on.
static std::optional<AMDGPU::InstCounterType>
counterTypeForInstr(unsigned Opcode) {
  switch (Opcode) {
  case AMDGPU::S_WAIT_LOADCNT:
    return AMDGPU::LOAD_CNT;
  case AMDGPU::S_WAIT_EXPCNT:
    return AMDGPU::EXP_CNT;
  case AMDGPU::S_WAIT_STORECNT:
    return AMDGPU::STORE_CNT;
  case AMDGPU::S_WAIT_SAMPLECNT:
    return AMDGPU::SAMPLE_CNT;
  case AMDGPU::S_WAIT_BVHCNT:
    return AMDGPU::BVH_CNT;
  case AMDGPU::S_WAIT_DSCNT:
    return AMDGPU::DS_CNT;
  case AMDGPU::S_WAIT_KMCNT:
    return AMDGPU::KM_CNT;
  case AMDGPU::S_WAIT_XCNT:
    return AMDGPU::X_CNT;
  case AMDGPU::S_WAIT_ASYNCCNT:
    return AMDGPU::ASYNC_CNT;
  default:
    return {};
  }
}

bool WaitcntGenerator::promoteSoftWaitCnt(MachineInstr *Waitcnt) const {
  unsigned Opcode = SIInstrInfo::getNonSoftWaitcntOpcode(Waitcnt->getOpcode());
  if (Opcode == Waitcnt->getOpcode())
    return false;

  Waitcnt->setDesc(TII.get(Opcode));
  return true;
}

/// Combine consecutive S_WAITCNT and S_WAITCNT_VSCNT instructions that
/// precede \p It and follow \p OldWaitcntInstr and apply any extra waits
/// from \p Wait that were added by previous passes. Currently this pass
/// conservatively assumes that these preexisting waits are required for
/// correctness.
bool WaitcntGeneratorPreGFX12::applyPreexistingWaitcnt(
    WaitcntBrackets &ScoreBrackets, MachineInstr &OldWaitcntInstr,
    AMDGPU::Waitcnt &Wait, MachineBasicBlock::instr_iterator It) const {
  assert(isNormalMode(MaxCounter));

  bool Modified = false;
  MachineInstr *WaitcntInstr = nullptr;
  MachineInstr *WaitcntVsCntInstr = nullptr;

  LLVM_DEBUG({
    dbgs() << "PreGFX12::applyPreexistingWaitcnt at: ";
    if (It.isEnd())
      dbgs() << "end of block\n";
    else
      dbgs() << *It;
  });

  for (auto &II :
       make_early_inc_range(make_range(OldWaitcntInstr.getIterator(), It))) {
    LLVM_DEBUG(dbgs() << "pre-existing iter: " << II);
    if (isNonWaitcntMetaInst(II)) {
      LLVM_DEBUG(dbgs() << "skipped meta instruction\n");
      continue;
    }

    unsigned Opcode = SIInstrInfo::getNonSoftWaitcntOpcode(II.getOpcode());
    bool TrySimplify = Opcode != II.getOpcode() && !OptNone;

    // Update required wait count. If this is a soft waitcnt (= it was added
    // by an earlier pass), it may be entirely removed.
    if (Opcode == AMDGPU::S_WAITCNT) {
      unsigned IEnc = II.getOperand(0).getImm();
      AMDGPU::Waitcnt OldWait = AMDGPU::decodeWaitcnt(IV, IEnc);
      if (TrySimplify)
        ScoreBrackets.simplifyWaitcnt(OldWait);
      Wait = Wait.combined(OldWait);

      // Merge consecutive waitcnt of the same type by erasing multiples.
      if (WaitcntInstr || (!Wait.hasWaitExceptStoreCnt() && TrySimplify)) {
        II.eraseFromParent();
        Modified = true;
      } else
        WaitcntInstr = &II;
    } else if (Opcode == AMDGPU::S_WAITCNT_lds_direct) {
      assert(ST.hasVMemToLDSLoad());
      LLVM_DEBUG(dbgs() << "Processing S_WAITCNT_lds_direct: " << II
                        << "Before: " << Wait << '\n';);
      ScoreBrackets.determineWaitForLDSDMA(AMDGPU::LOAD_CNT, LDSDMA_BEGIN,
                                           Wait);
      LLVM_DEBUG(dbgs() << "After: " << Wait << '\n';);

      // It is possible (but unlikely) that this is the only wait instruction,
      // in which case, we exit this loop without a WaitcntInstr to consume
      // `Wait`. But that works because `Wait` was passed in by reference, and
      // the callee eventually calls createNewWaitcnt on it. We test this
      // possibility in an articial MIR test since such a situation cannot be
      // recreated by running the memory legalizer.
      II.eraseFromParent();
    } else if (Opcode == AMDGPU::WAIT_ASYNCMARK) {
      unsigned N = II.getOperand(0).getImm();
      LLVM_DEBUG(dbgs() << "Processing WAIT_ASYNCMARK: " << II << '\n';);
      AMDGPU::Waitcnt OldWait = ScoreBrackets.determineAsyncWait(N);
      Wait = Wait.combined(OldWait);
    } else {
      assert(Opcode == AMDGPU::S_WAITCNT_VSCNT);
      assert(II.getOperand(0).getReg() == AMDGPU::SGPR_NULL);

      unsigned OldVSCnt =
          TII.getNamedOperand(II, AMDGPU::OpName::simm16)->getImm();
      if (TrySimplify)
        ScoreBrackets.simplifyWaitcnt(AMDGPU::STORE_CNT, OldVSCnt);
      Wait.set(AMDGPU::STORE_CNT,
               std::min(Wait.get(AMDGPU::STORE_CNT), OldVSCnt));

      if (WaitcntVsCntInstr || (!Wait.hasWaitStoreCnt() && TrySimplify)) {
        II.eraseFromParent();
        Modified = true;
      } else
        WaitcntVsCntInstr = &II;
    }
  }

  if (WaitcntInstr) {
    Modified |= updateOperandIfDifferent(*WaitcntInstr, AMDGPU::OpName::simm16,
                                         AMDGPU::encodeWaitcnt(IV, Wait));
    Modified |= promoteSoftWaitCnt(WaitcntInstr);

    ScoreBrackets.applyWaitcnt(Wait, AMDGPU::LOAD_CNT);
    ScoreBrackets.applyWaitcnt(Wait, AMDGPU::EXP_CNT);
    ScoreBrackets.applyWaitcnt(Wait, AMDGPU::DS_CNT);
    Wait.set(AMDGPU::LOAD_CNT, ~0u);
    Wait.set(AMDGPU::EXP_CNT, ~0u);
    Wait.set(AMDGPU::DS_CNT, ~0u);

    LLVM_DEBUG(It.isEnd() ? dbgs() << "applied pre-existing waitcnt\n"
                                   << "New Instr at block end: "
                                   << *WaitcntInstr << '\n'
                          : dbgs() << "applied pre-existing waitcnt\n"
                                   << "Old Instr: " << *It
                                   << "New Instr: " << *WaitcntInstr << '\n');
  }

  if (WaitcntVsCntInstr) {
    Modified |=
        updateOperandIfDifferent(*WaitcntVsCntInstr, AMDGPU::OpName::simm16,
                                 Wait.get(AMDGPU::STORE_CNT));
    Modified |= promoteSoftWaitCnt(WaitcntVsCntInstr);

    ScoreBrackets.applyWaitcnt(AMDGPU::STORE_CNT, Wait.get(AMDGPU::STORE_CNT));
    Wait.set(AMDGPU::STORE_CNT, ~0u);

    LLVM_DEBUG(It.isEnd()
                   ? dbgs() << "applied pre-existing waitcnt\n"
                            << "New Instr at block end: " << *WaitcntVsCntInstr
                            << '\n'
                   : dbgs() << "applied pre-existing waitcnt\n"
                            << "Old Instr: " << *It
                            << "New Instr: " << *WaitcntVsCntInstr << '\n');
  }

  return Modified;
}

/// Generate S_WAITCNT and/or S_WAITCNT_VSCNT instructions for any
/// required counters in \p Wait
bool WaitcntGeneratorPreGFX12::createNewWaitcnt(
    MachineBasicBlock &Block, MachineBasicBlock::instr_iterator It,
    AMDGPU::Waitcnt Wait, const WaitcntBrackets &ScoreBrackets) {
  assert(isNormalMode(MaxCounter));

  bool Modified = false;
  const DebugLoc &DL = Block.findDebugLoc(It);

  // Helper to emit expanded waitcnt sequence for profiling.
  // Emits waitcnts from (Outstanding-1) down to Target.
  // The EmitWaitcnt callback emits a single waitcnt.
  auto EmitExpandedWaitcnt = [&](unsigned Outstanding, unsigned Target,
                                 auto EmitWaitcnt) {
    do {
      EmitWaitcnt(--Outstanding);
    } while (Outstanding > Target);
    Modified = true;
  };

  // Waits for VMcnt, LKGMcnt and/or EXPcnt are encoded together into a
  // single instruction while VScnt has its own instruction.
  if (Wait.hasWaitExceptStoreCnt()) {
    // If profiling expansion is enabled, emit an expanded sequence
    if (ExpandWaitcntProfiling) {
      // Check if any of the counters to be waited on are out-of-order.
      // If so, fall back to normal (non-expanded) behavior since expansion
      // would provide misleading profiling information.
      bool AnyOutOfOrder = false;
      for (auto CT : {AMDGPU::LOAD_CNT, AMDGPU::DS_CNT, AMDGPU::EXP_CNT}) {
        unsigned WaitCnt = Wait.get(CT);
        if (WaitCnt != ~0u && ScoreBrackets.counterOutOfOrder(CT)) {
          AnyOutOfOrder = true;
          break;
        }
      }

      if (AnyOutOfOrder) {
        // Fall back to non-expanded wait
        unsigned Enc = AMDGPU::encodeWaitcnt(IV, Wait);
        BuildMI(Block, It, DL, TII.get(AMDGPU::S_WAITCNT)).addImm(Enc);
        Modified = true;
      } else {
        // All counters are in-order, safe to expand
        for (auto CT : {AMDGPU::LOAD_CNT, AMDGPU::DS_CNT, AMDGPU::EXP_CNT}) {
          unsigned WaitCnt = Wait.get(CT);
          if (WaitCnt == ~0u)
            continue;

          unsigned Outstanding = std::min(ScoreBrackets.getOutstanding(CT),
                                          getWaitCountMax(getLimits(), CT) - 1);
          EmitExpandedWaitcnt(Outstanding, WaitCnt, [&](unsigned Count) {
            AMDGPU::Waitcnt W;
            W.set(CT, Count);
            BuildMI(Block, It, DL, TII.get(AMDGPU::S_WAITCNT))
                .addImm(AMDGPU::encodeWaitcnt(IV, W));
          });
        }
      }
    } else {
      // Normal behavior: emit single combined waitcnt
      unsigned Enc = AMDGPU::encodeWaitcnt(IV, Wait);
      [[maybe_unused]] auto SWaitInst =
          BuildMI(Block, It, DL, TII.get(AMDGPU::S_WAITCNT)).addImm(Enc);
      Modified = true;

      LLVM_DEBUG(dbgs() << "PreGFX12::createNewWaitcnt\n";
                 if (It != Block.instr_end()) dbgs() << "Old Instr: " << *It;
                 dbgs() << "New Instr: " << *SWaitInst << '\n');
    }
  }

  if (Wait.hasWaitStoreCnt()) {
    assert(ST.hasVscnt());

    if (ExpandWaitcntProfiling && Wait.get(AMDGPU::STORE_CNT) != ~0u &&
        !ScoreBrackets.counterOutOfOrder(AMDGPU::STORE_CNT)) {
      // Only expand if counter is not out-of-order
      unsigned Outstanding =
          std::min(ScoreBrackets.getOutstanding(AMDGPU::STORE_CNT),
                   getWaitCountMax(getLimits(), AMDGPU::STORE_CNT) - 1);
      EmitExpandedWaitcnt(
          Outstanding, Wait.get(AMDGPU::STORE_CNT), [&](unsigned Count) {
            BuildMI(Block, It, DL, TII.get(AMDGPU::S_WAITCNT_VSCNT))
                .addReg(AMDGPU::SGPR_NULL, RegState::Undef)
                .addImm(Count);
          });
    } else {
      [[maybe_unused]] auto SWaitInst =
          BuildMI(Block, It, DL, TII.get(AMDGPU::S_WAITCNT_VSCNT))
              .addReg(AMDGPU::SGPR_NULL, RegState::Undef)
              .addImm(Wait.get(AMDGPU::STORE_CNT));
      Modified = true;

      LLVM_DEBUG(dbgs() << "PreGFX12::createNewWaitcnt\n";
                 if (It != Block.instr_end()) dbgs() << "Old Instr: " << *It;
                 dbgs() << "New Instr: " << *SWaitInst << '\n');
    }
  }

  return Modified;
}

AMDGPU::Waitcnt
WaitcntGeneratorPreGFX12::getAllZeroWaitcnt(bool IncludeVSCnt) const {
  return AMDGPU::Waitcnt(0, 0, 0, IncludeVSCnt && ST.hasVscnt() ? 0 : ~0u);
}

AMDGPU::Waitcnt
WaitcntGeneratorGFX12Plus::getAllZeroWaitcnt(bool IncludeVSCnt) const {
  unsigned ExpertVal = IsExpertMode ? 0 : ~0u;
  return AMDGPU::Waitcnt(0, 0, 0, IncludeVSCnt ? 0 : ~0u, 0, 0, 0,
                         ~0u /* XCNT */, ~0u /* ASYNC_CNT */, ExpertVal,
                         ExpertVal);
}

/// Combine consecutive S_WAIT_*CNT instructions that precede \p It and
/// follow \p OldWaitcntInstr and apply any extra waits from \p Wait that
/// were added by previous passes. Currently this pass conservatively
/// assumes that these preexisting waits are required for correctness.
bool WaitcntGeneratorGFX12Plus::applyPreexistingWaitcnt(
    WaitcntBrackets &ScoreBrackets, MachineInstr &OldWaitcntInstr,
    AMDGPU::Waitcnt &Wait, MachineBasicBlock::instr_iterator It) const {
  assert(!isNormalMode(MaxCounter));

  bool Modified = false;
  MachineInstr *CombinedLoadDsCntInstr = nullptr;
  MachineInstr *CombinedStoreDsCntInstr = nullptr;
  MachineInstr *WaitcntDepctrInstr = nullptr;
  MachineInstr *WaitInstrs[AMDGPU::NUM_EXTENDED_INST_CNTS] = {};

  LLVM_DEBUG({
    dbgs() << "GFX12Plus::applyPreexistingWaitcnt at: ";
    if (It.isEnd())
      dbgs() << "end of block\n";
    else
      dbgs() << *It;
  });

  // Accumulate waits that should not be simplified.
  AMDGPU::Waitcnt RequiredWait;

  for (auto &II :
       make_early_inc_range(make_range(OldWaitcntInstr.getIterator(), It))) {
    LLVM_DEBUG(dbgs() << "pre-existing iter: " << II);
    if (isNonWaitcntMetaInst(II)) {
      LLVM_DEBUG(dbgs() << "skipped meta instruction\n");
      continue;
    }

    // Update required wait count. If this is a soft waitcnt (= it was added
    // by an earlier pass), it may be entirely removed.

    unsigned Opcode = SIInstrInfo::getNonSoftWaitcntOpcode(II.getOpcode());
    bool TrySimplify = Opcode != II.getOpcode() && !OptNone;

    // Don't crash if the programmer used legacy waitcnt intrinsics, but don't
    // attempt to do more than that either.
    if (Opcode == AMDGPU::S_WAITCNT)
      continue;

    if (Opcode == AMDGPU::S_WAIT_LOADCNT_DSCNT) {
      unsigned OldEnc =
          TII.getNamedOperand(II, AMDGPU::OpName::simm16)->getImm();
      AMDGPU::Waitcnt OldWait = AMDGPU::decodeLoadcntDscnt(IV, OldEnc);
      if (TrySimplify)
        Wait = Wait.combined(OldWait);
      else
        RequiredWait = RequiredWait.combined(OldWait);
      // Keep the first wait_loadcnt, erase the rest.
      if (CombinedLoadDsCntInstr == nullptr) {
        CombinedLoadDsCntInstr = &II;
      } else {
        II.eraseFromParent();
        Modified = true;
      }
    } else if (Opcode == AMDGPU::S_WAIT_STORECNT_DSCNT) {
      unsigned OldEnc =
          TII.getNamedOperand(II, AMDGPU::OpName::simm16)->getImm();
      AMDGPU::Waitcnt OldWait = AMDGPU::decodeStorecntDscnt(IV, OldEnc);
      if (TrySimplify)
        Wait = Wait.combined(OldWait);
      else
        RequiredWait = RequiredWait.combined(OldWait);
      // Keep the first wait_storecnt, erase the rest.
      if (CombinedStoreDsCntInstr == nullptr) {
        CombinedStoreDsCntInstr = &II;
      } else {
        II.eraseFromParent();
        Modified = true;
      }
    } else if (Opcode == AMDGPU::S_WAITCNT_DEPCTR) {
      unsigned OldEnc =
          TII.getNamedOperand(II, AMDGPU::OpName::simm16)->getImm();
      AMDGPU::Waitcnt OldWait;
      OldWait.set(AMDGPU::VA_VDST, AMDGPU::DepCtr::decodeFieldVaVdst(OldEnc));
      OldWait.set(AMDGPU::VM_VSRC, AMDGPU::DepCtr::decodeFieldVmVsrc(OldEnc));
      if (TrySimplify)
        ScoreBrackets.simplifyWaitcnt(OldWait);
      Wait = Wait.combined(OldWait);
      if (WaitcntDepctrInstr == nullptr) {
        WaitcntDepctrInstr = &II;
      } else {
        // S_WAITCNT_DEPCTR requires special care. Don't remove a
        // duplicate if it is waiting on things other than VA_VDST or
        // VM_VSRC. If that is the case, just make sure the VA_VDST and
        // VM_VSRC subfields of the operand are set to the "no wait"
        // values.

        unsigned Enc =
            TII.getNamedOperand(II, AMDGPU::OpName::simm16)->getImm();
        Enc = AMDGPU::DepCtr::encodeFieldVmVsrc(Enc, ~0u);
        Enc = AMDGPU::DepCtr::encodeFieldVaVdst(Enc, ~0u);

        if (Enc != (unsigned)AMDGPU::DepCtr::getDefaultDepCtrEncoding(ST)) {
          Modified |= updateOperandIfDifferent(II, AMDGPU::OpName::simm16, Enc);
          Modified |= promoteSoftWaitCnt(&II);
        } else {
          II.eraseFromParent();
          Modified = true;
        }
      }
    } else if (Opcode == AMDGPU::S_WAITCNT_lds_direct) {
      // Architectures higher than GFX10 do not have direct loads to
      // LDS, so no work required here yet.
      II.eraseFromParent();
      Modified = true;
    } else if (Opcode == AMDGPU::WAIT_ASYNCMARK) {
      // Update the Waitcnt, but don't erase the wait.asyncmark() itself. It
      // shows up in the assembly as a comment with the original parameter N.
      unsigned N = II.getOperand(0).getImm();
      AMDGPU::Waitcnt OldWait = ScoreBrackets.determineAsyncWait(N);
      Wait = Wait.combined(OldWait);
    } else {
      std::optional<AMDGPU::InstCounterType> CT = counterTypeForInstr(Opcode);
      assert(CT.has_value());
      unsigned OldCnt =
          TII.getNamedOperand(II, AMDGPU::OpName::simm16)->getImm();
      if (TrySimplify)
        addWait(Wait, CT.value(), OldCnt);
      else
        addWait(RequiredWait, CT.value(), OldCnt);
      // Keep the first wait of its kind, erase the rest.
      if (WaitInstrs[CT.value()] == nullptr) {
        WaitInstrs[CT.value()] = &II;
      } else {
        II.eraseFromParent();
        Modified = true;
      }
    }
  }

  ScoreBrackets.simplifyWaitcnt(Wait.combined(RequiredWait), Wait);
  Wait = Wait.combined(RequiredWait);

  if (CombinedLoadDsCntInstr) {
    // Only keep an S_WAIT_LOADCNT_DSCNT if both counters actually need
    // to be waited for. Otherwise, let the instruction be deleted so
    // the appropriate single counter wait instruction can be inserted
    // instead, when new S_WAIT_*CNT instructions are inserted by
    // createNewWaitcnt(). As a side effect, resetting the wait counts will
    // cause any redundant S_WAIT_LOADCNT or S_WAIT_DSCNT to be removed by
    // the loop below that deals with single counter instructions.
    //
    // A wait for LOAD_CNT or DS_CNT implies a wait for VM_VSRC, since
    // instructions that have decremented LOAD_CNT or DS_CNT on completion
    // will have needed to wait for their register sources to be available
    // first.
    if (Wait.get(AMDGPU::LOAD_CNT) != ~0u && Wait.get(AMDGPU::DS_CNT) != ~0u) {
      unsigned NewEnc = AMDGPU::encodeLoadcntDscnt(IV, Wait);
      Modified |= updateOperandIfDifferent(*CombinedLoadDsCntInstr,
                                           AMDGPU::OpName::simm16, NewEnc);
      Modified |= promoteSoftWaitCnt(CombinedLoadDsCntInstr);
      ScoreBrackets.applyWaitcnt(AMDGPU::LOAD_CNT, Wait.get(AMDGPU::LOAD_CNT));
      ScoreBrackets.applyWaitcnt(AMDGPU::DS_CNT, Wait.get(AMDGPU::DS_CNT));
      Wait.set(AMDGPU::LOAD_CNT, ~0u);
      Wait.set(AMDGPU::DS_CNT, ~0u);

      LLVM_DEBUG(It.isEnd() ? dbgs() << "applied pre-existing waitcnt\n"
                                     << "New Instr at block end: "
                                     << *CombinedLoadDsCntInstr << '\n'
                            : dbgs() << "applied pre-existing waitcnt\n"
                                     << "Old Instr: " << *It << "New Instr: "
                                     << *CombinedLoadDsCntInstr << '\n');
    } else {
      CombinedLoadDsCntInstr->eraseFromParent();
      Modified = true;
    }
  }

  if (CombinedStoreDsCntInstr) {
    // Similarly for S_WAIT_STORECNT_DSCNT.
    if (Wait.get(AMDGPU::STORE_CNT) != ~0u && Wait.get(AMDGPU::DS_CNT) != ~0u) {
      unsigned NewEnc = AMDGPU::encodeStorecntDscnt(IV, Wait);
      Modified |= updateOperandIfDifferent(*CombinedStoreDsCntInstr,
                                           AMDGPU::OpName::simm16, NewEnc);
      Modified |= promoteSoftWaitCnt(CombinedStoreDsCntInstr);
      ScoreBrackets.applyWaitcnt(Wait, AMDGPU::STORE_CNT);
      ScoreBrackets.applyWaitcnt(Wait, AMDGPU::DS_CNT);
      Wait.set(AMDGPU::STORE_CNT, ~0u);
      Wait.set(AMDGPU::DS_CNT, ~0u);

      LLVM_DEBUG(It.isEnd() ? dbgs() << "applied pre-existing waitcnt\n"
                                     << "New Instr at block end: "
                                     << *CombinedStoreDsCntInstr << '\n'
                            : dbgs() << "applied pre-existing waitcnt\n"
                                     << "Old Instr: " << *It << "New Instr: "
                                     << *CombinedStoreDsCntInstr << '\n');
    } else {
      CombinedStoreDsCntInstr->eraseFromParent();
      Modified = true;
    }
  }

  // Look for an opportunity to convert existing S_WAIT_LOADCNT,
  // S_WAIT_STORECNT and S_WAIT_DSCNT into new S_WAIT_LOADCNT_DSCNT
  // or S_WAIT_STORECNT_DSCNT. This is achieved by selectively removing
  // instructions so that createNewWaitcnt() will create new combined
  // instructions to replace them.

  if (Wait.get(AMDGPU::DS_CNT) != ~0u) {
    // This is a vector of addresses in WaitInstrs pointing to instructions
    // that should be removed if they are present.
    SmallVector<MachineInstr **, 2> WaitsToErase;

    // If it's known that both DScnt and either LOADcnt or STOREcnt (but not
    // both) need to be waited for, ensure that there are no existing
    // individual wait count instructions for these.

    if (Wait.get(AMDGPU::LOAD_CNT) != ~0u) {
      WaitsToErase.push_back(&WaitInstrs[AMDGPU::LOAD_CNT]);
      WaitsToErase.push_back(&WaitInstrs[AMDGPU::DS_CNT]);
    } else if (Wait.get(AMDGPU::STORE_CNT) != ~0u) {
      WaitsToErase.push_back(&WaitInstrs[AMDGPU::STORE_CNT]);
      WaitsToErase.push_back(&WaitInstrs[AMDGPU::DS_CNT]);
    }

    for (MachineInstr **WI : WaitsToErase) {
      if (!*WI)
        continue;

      (*WI)->eraseFromParent();
      *WI = nullptr;
      Modified = true;
    }
  }

  for (auto CT : inst_counter_types(AMDGPU::NUM_EXTENDED_INST_CNTS)) {
    if (!WaitInstrs[CT])
      continue;

    unsigned NewCnt = Wait.get(CT);
    if (NewCnt != ~0u) {
      Modified |= updateOperandIfDifferent(*WaitInstrs[CT],
                                           AMDGPU::OpName::simm16, NewCnt);
      Modified |= promoteSoftWaitCnt(WaitInstrs[CT]);

      ScoreBrackets.applyWaitcnt(CT, NewCnt);
      setNoWait(Wait, CT);

      LLVM_DEBUG(It.isEnd()
                     ? dbgs() << "applied pre-existing waitcnt\n"
                              << "New Instr at block end: " << *WaitInstrs[CT]
                              << '\n'
                     : dbgs() << "applied pre-existing waitcnt\n"
                              << "Old Instr: " << *It
                              << "New Instr: " << *WaitInstrs[CT] << '\n');
    } else {
      WaitInstrs[CT]->eraseFromParent();
      Modified = true;
    }
  }

  if (WaitcntDepctrInstr) {
    // Get the encoded Depctr immediate and override the VA_VDST and VM_VSRC
    // subfields with the new required values.
    unsigned Enc =
        TII.getNamedOperand(*WaitcntDepctrInstr, AMDGPU::OpName::simm16)
            ->getImm();
    Enc = AMDGPU::DepCtr::encodeFieldVmVsrc(Enc, Wait.get(AMDGPU::VM_VSRC));
    Enc = AMDGPU::DepCtr::encodeFieldVaVdst(Enc, Wait.get(AMDGPU::VA_VDST));

    ScoreBrackets.applyWaitcnt(AMDGPU::VA_VDST, Wait.get(AMDGPU::VA_VDST));
    ScoreBrackets.applyWaitcnt(AMDGPU::VM_VSRC, Wait.get(AMDGPU::VM_VSRC));
    Wait.set(AMDGPU::VA_VDST, ~0u);
    Wait.set(AMDGPU::VM_VSRC, ~0u);

    // If that new encoded Depctr immediate would actually still wait
    // for anything, update the instruction's operand. Otherwise it can
    // just be deleted.
    if (Enc != (unsigned)AMDGPU::DepCtr::getDefaultDepCtrEncoding(ST)) {
      Modified |= updateOperandIfDifferent(*WaitcntDepctrInstr,
                                           AMDGPU::OpName::simm16, Enc);
      LLVM_DEBUG(It.isEnd() ? dbgs() << "applyPreexistingWaitcnt\n"
                                     << "New Instr at block end: "
                                     << *WaitcntDepctrInstr << '\n'
                            : dbgs() << "applyPreexistingWaitcnt\n"
                                     << "Old Instr: " << *It << "New Instr: "
                                     << *WaitcntDepctrInstr << '\n');
    } else {
      WaitcntDepctrInstr->eraseFromParent();
      Modified = true;
    }
  }

  return Modified;
}

/// Generate S_WAIT_*CNT instructions for any required counters in \p Wait
bool WaitcntGeneratorGFX12Plus::createNewWaitcnt(
    MachineBasicBlock &Block, MachineBasicBlock::instr_iterator It,
    AMDGPU::Waitcnt Wait, const WaitcntBrackets &ScoreBrackets) {
  assert(!isNormalMode(MaxCounter));

  bool Modified = false;
  const DebugLoc &DL = Block.findDebugLoc(It);

  // Helper to emit expanded waitcnt sequence for profiling.
  auto EmitExpandedWaitcnt = [&](unsigned Outstanding, unsigned Target,
                                 auto EmitWaitcnt) {
    for (unsigned I = Outstanding - 1; I > Target && I != ~0u; --I)
      EmitWaitcnt(I);
    EmitWaitcnt(Target);
    Modified = true;
  };

  // For GFX12+, we use separate wait instructions, which makes expansion
  // simpler
  if (ExpandWaitcntProfiling) {
    for (auto CT : inst_counter_types(AMDGPU::NUM_EXTENDED_INST_CNTS)) {
      unsigned Count = Wait.get(CT);
      if (Count == ~0u)
        continue;

      // Skip expansion for out-of-order counters - emit normal wait instead
      if (ScoreBrackets.counterOutOfOrder(CT)) {
        BuildMI(Block, It, DL, TII.get(instrsForExtendedCounterTypes[CT]))
            .addImm(Count);
        Modified = true;
        continue;
      }

      unsigned Outstanding = std::min(ScoreBrackets.getOutstanding(CT),
                                      getWaitCountMax(getLimits(), CT) - 1);
      EmitExpandedWaitcnt(Outstanding, Count, [&](unsigned Val) {
        BuildMI(Block, It, DL, TII.get(instrsForExtendedCounterTypes[CT]))
            .addImm(Val);
      });
    }
    return Modified;
  }

  // Normal behavior (no expansion)
  // Check for opportunities to use combined wait instructions.
  if (Wait.get(AMDGPU::DS_CNT) != ~0u) {
    MachineInstr *SWaitInst = nullptr;

    if (Wait.get(AMDGPU::LOAD_CNT) != ~0u) {
      unsigned Enc = AMDGPU::encodeLoadcntDscnt(IV, Wait);

      SWaitInst = BuildMI(Block, It, DL, TII.get(AMDGPU::S_WAIT_LOADCNT_DSCNT))
                      .addImm(Enc);

      Wait.set(AMDGPU::LOAD_CNT, ~0u);
      Wait.set(AMDGPU::DS_CNT, ~0u);
    } else if (Wait.get(AMDGPU::STORE_CNT) != ~0u) {
      unsigned Enc = AMDGPU::encodeStorecntDscnt(IV, Wait);

      SWaitInst = BuildMI(Block, It, DL, TII.get(AMDGPU::S_WAIT_STORECNT_DSCNT))
                      .addImm(Enc);

      Wait.set(AMDGPU::STORE_CNT, ~0u);
      Wait.set(AMDGPU::DS_CNT, ~0u);
    }

    if (SWaitInst) {
      Modified = true;

      LLVM_DEBUG(dbgs() << "GFX12Plus::createNewWaitcnt\n";
                 if (It != Block.instr_end()) dbgs() << "Old Instr: " << *It;
                 dbgs() << "New Instr: " << *SWaitInst << '\n');
    }
  }

  // Generate an instruction for any remaining counter that needs
  // waiting for.

  for (auto CT : inst_counter_types(AMDGPU::NUM_EXTENDED_INST_CNTS)) {
    unsigned Count = Wait.get(CT);
    if (Count == ~0u)
      continue;

    [[maybe_unused]] auto SWaitInst =
        BuildMI(Block, It, DL, TII.get(instrsForExtendedCounterTypes[CT]))
            .addImm(Count);

    Modified = true;

    LLVM_DEBUG(dbgs() << "GFX12Plus::createNewWaitcnt\n";
               if (It != Block.instr_end()) dbgs() << "Old Instr: " << *It;
               dbgs() << "New Instr: " << *SWaitInst << '\n');
  }

  if (Wait.hasWaitDepctr()) {
    assert(IsExpertMode);
    unsigned Enc =
        AMDGPU::DepCtr::encodeFieldVmVsrc(Wait.get(AMDGPU::VM_VSRC), ST);
    Enc = AMDGPU::DepCtr::encodeFieldVaVdst(Enc, Wait.get(AMDGPU::VA_VDST));

    [[maybe_unused]] auto SWaitInst =
        BuildMI(Block, It, DL, TII.get(AMDGPU::S_WAITCNT_DEPCTR)).addImm(Enc);

    Modified = true;

    LLVM_DEBUG(dbgs() << "generateWaitcnt\n";
               if (It != Block.instr_end()) dbgs() << "Old Instr: " << *It;
               dbgs() << "New Instr: " << *SWaitInst << '\n');
  }

  return Modified;
}

///  Generate s_waitcnt instruction to be placed before cur_Inst.
///  Instructions of a given type are returned in order,
///  but instructions of different types can complete out of order.
///  We rely on this in-order completion
///  and simply assign a score to the memory access instructions.
///  We keep track of the active "score bracket" to determine
///  if an access of a memory read requires an s_waitcnt
///  and if so what the value of each counter is.
///  The "score bracket" is bound by the lower bound and upper bound
///  scores (*_score_LB and *_score_ub respectively).
///  If FlushFlags.FlushVmCnt is true, we want to flush the vmcnt counter here.
///  If FlushFlags.FlushDsCnt is true, we want to flush the dscnt counter here
///  (GFX12+ only, where DS_CNT is a separate counter).
bool SIInsertWaitcnts::generateWaitcntInstBefore(
    MachineInstr &MI, WaitcntBrackets &ScoreBrackets,
    MachineInstr *OldWaitcntInstr, PreheaderFlushFlags FlushFlags) {
  LLVM_DEBUG(dbgs() << "\n*** GenerateWaitcntInstBefore: "; MI.print(dbgs()););
  setForceEmitWaitcnt();

  assert(!isNonWaitcntMetaInst(MI));

  AMDGPU::Waitcnt Wait;
  const unsigned Opc = MI.getOpcode();

  switch (Opc) {
  case AMDGPU::BUFFER_WBINVL1:
  case AMDGPU::BUFFER_WBINVL1_SC:
  case AMDGPU::BUFFER_WBINVL1_VOL:
  case AMDGPU::BUFFER_GL0_INV:
  case AMDGPU::BUFFER_GL1_INV: {
    // FIXME: This should have already been handled by the memory legalizer.
    // Removing this currently doesn't affect any lit tests, but we need to
    // verify that nothing was relying on this. The number of buffer invalidates
    // being handled here should not be expanded.
    Wait.set(AMDGPU::LOAD_CNT, 0);
    break;
  }
  case AMDGPU::SI_RETURN_TO_EPILOG:
  case AMDGPU::SI_RETURN:
  case AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN:
  case AMDGPU::S_SETPC_B64_return: {
    // All waits must be resolved at call return.
    // NOTE: this could be improved with knowledge of all call sites or
    //   with knowledge of the called routines.
    ReturnInsts.insert(&MI);
    AMDGPU::Waitcnt AllZeroWait =
        WCG->getAllZeroWaitcnt(/*IncludeVSCnt=*/false);
    // On GFX12+, if LOAD_CNT is pending but no VGPRs are waiting for loads
    // (e.g., only GLOBAL_INV is pending), we can skip waiting on loadcnt.
    // GLOBAL_INV increments loadcnt but doesn't write to VGPRs, so there's
    // no need to wait for it at function boundaries.
    if (ST.hasExtendedWaitCounts() &&
        !ScoreBrackets.hasPendingEvent(VMEM_ACCESS))
      AllZeroWait.set(AMDGPU::LOAD_CNT, ~0u);
    Wait = AllZeroWait;
    break;
  }
  case AMDGPU::S_ENDPGM:
  case AMDGPU::S_ENDPGM_SAVED: {
    // In dynamic VGPR mode, we want to release the VGPRs before the wave exits.
    // Technically the hardware will do this on its own if we don't, but that
    // might cost extra cycles compared to doing it explicitly.
    // When not in dynamic VGPR mode, identify S_ENDPGM instructions which may
    // have to wait for outstanding VMEM stores. In this case it can be useful
    // to send a message to explicitly release all VGPRs before the stores have
    // completed, but it is only safe to do this if there are no outstanding
    // scratch stores.
    EndPgmInsts[&MI] = !ScoreBrackets.empty(AMDGPU::STORE_CNT) &&
                       !ScoreBrackets.hasPendingEvent(SCRATCH_WRITE_ACCESS);
    break;
  }
  case AMDGPU::S_SENDMSG:
  case AMDGPU::S_SENDMSGHALT: {
    if (ST.hasLegacyGeometry() &&
        ((MI.getOperand(0).getImm() & AMDGPU::SendMsg::ID_MASK_PreGFX11_) ==
         AMDGPU::SendMsg::ID_GS_DONE_PreGFX11)) {
      // Resolve vm waits before gs-done.
      Wait.set(AMDGPU::LOAD_CNT, 0);
      break;
    }
    [[fallthrough]];
  }
  default: {

    // Export & GDS instructions do not read the EXEC mask until after the
    // export is granted (which can occur well after the instruction is issued).
    // The shader program must flush all EXP operations on the export-count
    // before overwriting the EXEC mask.
    if (MI.modifiesRegister(AMDGPU::EXEC, &TRI)) {
      // Export and GDS are tracked individually, either may trigger a waitcnt
      // for EXEC.
      if (ScoreBrackets.hasPendingEvent(EXP_GPR_LOCK) ||
          ScoreBrackets.hasPendingEvent(EXP_PARAM_ACCESS) ||
          ScoreBrackets.hasPendingEvent(EXP_POS_ACCESS) ||
          ScoreBrackets.hasPendingEvent(GDS_GPR_LOCK)) {
        Wait.set(AMDGPU::EXP_CNT, 0);
      }
    }

    // Wait for any pending GDS instruction to complete before any
    // "Always GDS" instruction.
    if (TII.isAlwaysGDS(Opc) && ScoreBrackets.hasPendingGDS())
      addWait(Wait, AMDGPU::DS_CNT, ScoreBrackets.getPendingGDSWait());

    if (MI.isCall()) {
      // The function is going to insert a wait on everything in its prolog.
      // This still needs to be careful if the call target is a load (e.g. a GOT
      // load). We also need to check WAW dependency with saved PC.
      CallInsts.insert(&MI);
      Wait = AMDGPU::Waitcnt();

      const MachineOperand &CallAddrOp = TII.getCalleeOperand(MI);
      if (CallAddrOp.isReg()) {
        ScoreBrackets.determineWaitForPhysReg(
            SmemAccessCounter, CallAddrOp.getReg().asMCReg(), Wait);

        if (const auto *RtnAddrOp =
                TII.getNamedOperand(MI, AMDGPU::OpName::dst)) {
          ScoreBrackets.determineWaitForPhysReg(
              SmemAccessCounter, RtnAddrOp->getReg().asMCReg(), Wait);
        }
      }
    } else if (Opc == AMDGPU::S_BARRIER_WAIT) {
      ScoreBrackets.tryClearSCCWriteEvent(&MI);
    } else {
      // FIXME: Should not be relying on memoperands.
      // Look at the source operands of every instruction to see if
      // any of them results from a previous memory operation that affects
      // its current usage. If so, an s_waitcnt instruction needs to be
      // emitted.
      // If the source operand was defined by a load, add the s_waitcnt
      // instruction.
      //
      // Two cases are handled for destination operands:
      // 1) If the destination operand was defined by a load, add the s_waitcnt
      // instruction to guarantee the right WAW order.
      // 2) If a destination operand that was used by a recent export/store ins,
      // add s_waitcnt on exp_cnt to guarantee the WAR order.

      for (const MachineMemOperand *Memop : MI.memoperands()) {
        const Value *Ptr = Memop->getValue();
        if (Memop->isStore()) {
          if (auto It = SLoadAddresses.find(Ptr); It != SLoadAddresses.end()) {
            addWait(Wait, SmemAccessCounter, 0);
            if (PDT.dominates(MI.getParent(), It->second))
              SLoadAddresses.erase(It);
          }
        }
        unsigned AS = Memop->getAddrSpace();
        if (AS != AMDGPUAS::LOCAL_ADDRESS && AS != AMDGPUAS::FLAT_ADDRESS)
          continue;
        // No need to wait before load from VMEM to LDS.
        if (TII.mayWriteLDSThroughDMA(MI))
          continue;

        // LOAD_CNT is only relevant to vgpr or LDS.
        unsigned TID = LDSDMA_BEGIN;
        if (Ptr && Memop->getAAInfo()) {
          const auto &LDSDMAStores = ScoreBrackets.getLDSDMAStores();
          for (unsigned I = 0, E = LDSDMAStores.size(); I != E; ++I) {
            if (MI.mayAlias(AA, *LDSDMAStores[I], true)) {
              if ((I + 1) >= NUM_LDSDMA) {
                // We didn't have enough slot to track this LDS DMA store, it
                // has been tracked using the common RegNo (FIRST_LDS_VGPR).
                ScoreBrackets.determineWaitForLDSDMA(AMDGPU::LOAD_CNT, TID,
                                                     Wait);
                break;
              }

              ScoreBrackets.determineWaitForLDSDMA(AMDGPU::LOAD_CNT,
                                                   TID + I + 1, Wait);
            }
          }
        } else {
          ScoreBrackets.determineWaitForLDSDMA(AMDGPU::LOAD_CNT, TID, Wait);
        }
        if (Memop->isStore()) {
          ScoreBrackets.determineWaitForLDSDMA(AMDGPU::EXP_CNT, TID, Wait);
        }
      }

      // Loop over use and def operands.
      for (const MachineOperand &Op : MI.operands()) {
        if (!Op.isReg())
          continue;

        // If the instruction does not read tied source, skip the operand.
        if (Op.isTied() && Op.isUse() && TII.doesNotReadTiedSource(MI))
          continue;

        MCPhysReg Reg = Op.getReg().asMCReg();

        const bool IsVGPR = TRI.isVectorRegister(MRI, Op.getReg());
        if (IsVGPR) {
          // Implicit VGPR defs and uses are never a part of the memory
          // instructions description and usually present to account for
          // super-register liveness.
          // TODO: Most of the other instructions also have implicit uses
          // for the liveness accounting only.
          if (Op.isImplicit() && MI.mayLoadOrStore())
            continue;

          ScoreBrackets.determineWaitForPhysReg(AMDGPU::VA_VDST, Reg, Wait);
          if (Op.isDef())
            ScoreBrackets.determineWaitForPhysReg(AMDGPU::VM_VSRC, Reg, Wait);
          // RAW always needs an s_waitcnt. WAW needs an s_waitcnt unless the
          // previous write and this write are the same type of VMEM
          // instruction, in which case they are (in some architectures)
          // guaranteed to write their results in order anyway.
          // Additionally check instructions where Point Sample Acceleration
          // might be applied.
          if (Op.isUse() || !updateVMCntOnly(MI) ||
              ScoreBrackets.hasOtherPendingVmemTypes(Reg, getVmemType(MI)) ||
              ScoreBrackets.hasPointSamplePendingVmemTypes(MI, Reg) ||
              !ST.hasVmemWriteVgprInOrder()) {
            ScoreBrackets.determineWaitForPhysReg(AMDGPU::LOAD_CNT, Reg, Wait);
            ScoreBrackets.determineWaitForPhysReg(AMDGPU::SAMPLE_CNT, Reg,
                                                  Wait);
            ScoreBrackets.determineWaitForPhysReg(AMDGPU::BVH_CNT, Reg, Wait);
            ScoreBrackets.clearVgprVmemTypes(Reg);
          }

          if (Op.isDef() || ScoreBrackets.hasPendingEvent(EXP_LDS_ACCESS)) {
            ScoreBrackets.determineWaitForPhysReg(AMDGPU::EXP_CNT, Reg, Wait);
          }
          ScoreBrackets.determineWaitForPhysReg(AMDGPU::DS_CNT, Reg, Wait);
        } else if (Op.getReg() == AMDGPU::SCC) {
          ScoreBrackets.determineWaitForPhysReg(AMDGPU::KM_CNT, Reg, Wait);
        } else {
          ScoreBrackets.determineWaitForPhysReg(SmemAccessCounter, Reg, Wait);
        }

        if (ST.hasWaitXcnt() && Op.isDef())
          ScoreBrackets.determineWaitForPhysReg(AMDGPU::X_CNT, Reg, Wait);
      }
    }
  }
  }

  // Ensure safety against exceptions from outstanding memory operations while
  // waiting for a barrier:
  //
  //  * Some subtargets safely handle backing off the barrier in hardware
  //    when an exception occurs.
  //  * Some subtargets have an implicit S_WAITCNT 0 before barriers, so that
  //    there can be no outstanding memory operations during the wait.
  //  * Subtargets with split barriers don't need to back off the barrier; it
  //    is up to the trap handler to preserve the user barrier state correctly.
  //
  // In all other cases, ensure safety by ensuring that there are no outstanding
  // memory operations.
  if (Opc == AMDGPU::S_BARRIER && !ST.hasAutoWaitcntBeforeBarrier() &&
      !ST.hasBackOffBarrier()) {
    Wait = Wait.combined(WCG->getAllZeroWaitcnt(/*IncludeVSCnt=*/true));
  }

  // TODO: Remove this work-around, enable the assert for Bug 457939
  //       after fixing the scheduler. Also, the Shader Compiler code is
  //       independent of target.
  if (SIInstrInfo::isCBranchVCCZRead(MI) && ST.hasReadVCCZBug() &&
      ScoreBrackets.hasPendingEvent(SMEM_ACCESS)) {
    Wait.set(AMDGPU::DS_CNT, 0);
  }

  // Verify that the wait is actually needed.
  ScoreBrackets.simplifyWaitcnt(Wait);

  // It is only necessary to insert an S_WAITCNT_DEPCTR instruction that
  // waits on VA_VDST if the instruction it would precede is not a VALU
  // instruction, since hardware handles VALU->VGPR->VALU hazards in
  // expert scheduling mode.
  if (TII.isVALU(MI))
    Wait.set(AMDGPU::VA_VDST, ~0u);

  // Since the translation for VMEM addresses occur in-order, we can apply the
  // XCnt if the current instruction is of VMEM type and has a memory
  // dependency with another VMEM instruction in flight.
  if (Wait.get(AMDGPU::X_CNT) != ~0u && isVmemAccess(MI)) {
    ScoreBrackets.applyWaitcnt(Wait, AMDGPU::X_CNT);
    Wait.set(AMDGPU::X_CNT, ~0u);
  }

  // When forcing emit, we need to skip terminators because that would break the
  // terminators of the MBB if we emit a waitcnt between terminators.
  if (ForceEmitZeroFlag && !MI.isTerminator())
    Wait = WCG->getAllZeroWaitcnt(/*IncludeVSCnt=*/false);

  // If we force waitcnt then update Wait accordingly.
  for (AMDGPU::InstCounterType T : AMDGPU::inst_counter_types()) {
    if (!ForceEmitWaitcnt[T])
      continue;
    Wait.set(T, 0);
  }

  if (FlushFlags.FlushVmCnt) {
    for (AMDGPU::InstCounterType T :
         {AMDGPU::LOAD_CNT, AMDGPU::SAMPLE_CNT, AMDGPU::BVH_CNT})
      Wait.set(T, 0);
  }

  if (FlushFlags.FlushDsCnt && ScoreBrackets.hasPendingEvent(AMDGPU::DS_CNT))
    Wait.set(AMDGPU::DS_CNT, 0);

  if (ForceEmitZeroLoadFlag && Wait.get(AMDGPU::LOAD_CNT) != ~0u)
    Wait.set(AMDGPU::LOAD_CNT, 0);

  return generateWaitcnt(Wait, MI.getIterator(), *MI.getParent(), ScoreBrackets,
                         OldWaitcntInstr);
}

bool SIInsertWaitcnts::generateWaitcnt(AMDGPU::Waitcnt Wait,
                                       MachineBasicBlock::instr_iterator It,
                                       MachineBasicBlock &Block,
                                       WaitcntBrackets &ScoreBrackets,
                                       MachineInstr *OldWaitcntInstr) {
  bool Modified = false;

  if (OldWaitcntInstr)
    // Try to merge the required wait with preexisting waitcnt instructions.
    // Also erase redundant waitcnt.
    Modified =
        WCG->applyPreexistingWaitcnt(ScoreBrackets, *OldWaitcntInstr, Wait, It);

  // ExpCnt can be merged into VINTERP.
  if (Wait.get(AMDGPU::EXP_CNT) != ~0u && It != Block.instr_end() &&
      SIInstrInfo::isVINTERP(*It)) {
    MachineOperand *WaitExp = TII.getNamedOperand(*It, AMDGPU::OpName::waitexp);
    if (Wait.get(AMDGPU::EXP_CNT) < WaitExp->getImm()) {
      WaitExp->setImm(Wait.get(AMDGPU::EXP_CNT));
      Modified = true;
    }
    // Apply ExpCnt before resetting it, so applyWaitcnt below sees all counts.
    ScoreBrackets.applyWaitcnt(Wait, AMDGPU::EXP_CNT);
    Wait.set(AMDGPU::EXP_CNT, ~0u);

    LLVM_DEBUG(dbgs() << "generateWaitcnt\n"
                      << "Update Instr: " << *It);
  }

  if (WCG->createNewWaitcnt(Block, It, Wait, ScoreBrackets))
    Modified = true;

  // Any counts that could have been applied to any existing waitcnt
  // instructions will have been done so, now deal with any remaining.
  ScoreBrackets.applyWaitcnt(Wait);

  return Modified;
}

std::optional<WaitEventType>
SIInsertWaitcnts::getExpertSchedulingEventType(const MachineInstr &Inst) const {
  if (TII.isVALU(Inst)) {
    // Core/Side-, DP-, XDL- and TRANS-MACC VALU instructions complete
    // out-of-order with respect to each other, so each of these classes
    // has its own event.

    if (TII.isXDL(Inst))
      return VGPR_XDL_WRITE;

    if (TII.isTRANS(Inst))
      return VGPR_TRANS_WRITE;

    if (AMDGPU::isDPMACCInstruction(Inst.getOpcode()))
      return VGPR_DPMACC_WRITE;

    return VGPR_CSMACC_WRITE;
  }

  // FLAT and LDS instructions may read their VGPR sources out-of-order
  // with respect to each other and all other VMEM instructions, so
  // each of these also has a separate event.

  if (TII.isFLAT(Inst))
    return VGPR_FLAT_READ;

  if (TII.isDS(Inst))
    return VGPR_LDS_READ;

  if (TII.isVMEM(Inst) || TII.isVIMAGE(Inst) || TII.isVSAMPLE(Inst))
    return VGPR_VMEM_READ;

  // Otherwise, no hazard.

  return {};
}

bool SIInsertWaitcnts::isVmemAccess(const MachineInstr &MI) const {
  return (TII.isFLAT(MI) && TII.mayAccessVMEMThroughFlat(MI)) ||
         (TII.isVMEM(MI) && !AMDGPU::getMUBUFIsBufferInv(MI.getOpcode()));
}

// Return true if the next instruction is S_ENDPGM, following fallthrough
// blocks if necessary.
bool SIInsertWaitcnts::isNextENDPGM(MachineBasicBlock::instr_iterator It,
                                    MachineBasicBlock *Block) const {
  auto BlockEnd = Block->getParent()->end();
  auto BlockIter = Block->getIterator();

  while (true) {
    if (It.isEnd()) {
      if (++BlockIter != BlockEnd) {
        It = BlockIter->instr_begin();
        continue;
      }

      return false;
    }

    if (!It->isMetaInstruction())
      break;

    It++;
  }

  assert(!It.isEnd());

  return It->getOpcode() == AMDGPU::S_ENDPGM;
}

// Add a wait after an instruction if architecture requirements mandate one.
bool SIInsertWaitcnts::insertForcedWaitAfter(MachineInstr &Inst,
                                             MachineBasicBlock &Block,
                                             WaitcntBrackets &ScoreBrackets) {
  AMDGPU::Waitcnt Wait;
  bool NeedsEndPGMCheck = false;

  if (ST.isPreciseMemoryEnabled() && Inst.mayLoadOrStore())
    Wait = WCG->getAllZeroWaitcnt(Inst.mayStore() &&
                                  !SIInstrInfo::isAtomicRet(Inst));

  if (TII.isAlwaysGDS(Inst.getOpcode())) {
    Wait.set(AMDGPU::DS_CNT, 0);
    NeedsEndPGMCheck = true;
  }

  ScoreBrackets.simplifyWaitcnt(Wait);

  auto SuccessorIt = std::next(Inst.getIterator());
  bool Result = generateWaitcnt(Wait, SuccessorIt, Block, ScoreBrackets,
                                /*OldWaitcntInstr=*/nullptr);

  if (Result && NeedsEndPGMCheck && isNextENDPGM(SuccessorIt, &Block)) {
    BuildMI(Block, SuccessorIt, Inst.getDebugLoc(), TII.get(AMDGPU::S_NOP))
        .addImm(0);
  }

  return Result;
}

WaitEventSet SIInsertWaitcnts::getEventsFor(const MachineInstr &Inst) const {
  WaitEventSet Events;
  if (IsExpertMode) {
    if (const auto ET = getExpertSchedulingEventType(Inst))
      Events.insert(*ET);
  }

  if (TII.isDS(Inst) && TII.usesLGKM_CNT(Inst)) {
    if (TII.isAlwaysGDS(Inst.getOpcode()) ||
        TII.hasModifiersSet(Inst, AMDGPU::OpName::gds)) {
      Events.insert(GDS_ACCESS);
      Events.insert(GDS_GPR_LOCK);
    } else {
      Events.insert(LDS_ACCESS);
    }
  } else if (TII.isFLAT(Inst)) {
    if (SIInstrInfo::isGFX12CacheInvOrWBInst(Inst.getOpcode())) {
      Events.insert(getVmemWaitEventType(Inst));
    } else {
      assert(Inst.mayLoadOrStore());
      if (TII.mayAccessVMEMThroughFlat(Inst)) {
        if (ST.hasWaitXcnt())
          Events.insert(VMEM_GROUP);
        Events.insert(getVmemWaitEventType(Inst));
      }
      if (TII.mayAccessLDSThroughFlat(Inst))
        Events.insert(LDS_ACCESS);
    }
  } else if (SIInstrInfo::isVMEM(Inst) &&
             (!AMDGPU::getMUBUFIsBufferInv(Inst.getOpcode()) ||
              Inst.getOpcode() == AMDGPU::BUFFER_WBL2)) {
    // BUFFER_WBL2 is included here because unlike invalidates, has to be
    // followed "S_WAITCNT vmcnt(0)" is needed after to ensure the writeback has
    // completed.
    if (ST.hasWaitXcnt())
      Events.insert(VMEM_GROUP);
    Events.insert(getVmemWaitEventType(Inst));
    if (ST.vmemWriteNeedsExpWaitcnt() &&
        (Inst.mayStore() || SIInstrInfo::isAtomicRet(Inst))) {
      Events.insert(VMW_GPR_LOCK);
    }
  } else if (TII.isSMRD(Inst)) {
    if (ST.hasWaitXcnt())
      Events.insert(SMEM_GROUP);
    Events.insert(SMEM_ACCESS);
  } else if (SIInstrInfo::isLDSDIR(Inst)) {
    Events.insert(EXP_LDS_ACCESS);
  } else if (SIInstrInfo::isEXP(Inst)) {
    unsigned Imm = TII.getNamedOperand(Inst, AMDGPU::OpName::tgt)->getImm();
    if (Imm >= AMDGPU::Exp::ET_PARAM0 && Imm <= AMDGPU::Exp::ET_PARAM31)
      Events.insert(EXP_PARAM_ACCESS);
    else if (Imm >= AMDGPU::Exp::ET_POS0 && Imm <= AMDGPU::Exp::ET_POS_LAST)
      Events.insert(EXP_POS_ACCESS);
    else
      Events.insert(EXP_GPR_LOCK);
  } else if (SIInstrInfo::isSBarrierSCCWrite(Inst.getOpcode())) {
    Events.insert(SCC_WRITE);
  } else {
    switch (Inst.getOpcode()) {
    case AMDGPU::S_SENDMSG:
    case AMDGPU::S_SENDMSG_RTN_B32:
    case AMDGPU::S_SENDMSG_RTN_B64:
    case AMDGPU::S_SENDMSGHALT:
      Events.insert(SQ_MESSAGE);
      break;
    case AMDGPU::S_MEMTIME:
    case AMDGPU::S_MEMREALTIME:
    case AMDGPU::S_GET_BARRIER_STATE_M0:
    case AMDGPU::S_GET_BARRIER_STATE_IMM:
      Events.insert(SMEM_ACCESS);
      break;
    }
  }
  return Events;
}

void SIInsertWaitcnts::updateEventWaitcntAfter(MachineInstr &Inst,
                                               WaitcntBrackets *ScoreBrackets) {

  WaitEventSet InstEvents = getEventsFor(Inst);
  for (WaitEventType E : wait_events()) {
    if (InstEvents.contains(E))
      ScoreBrackets->updateByEvent(E, Inst);
  }

  if (TII.isDS(Inst) && TII.usesLGKM_CNT(Inst)) {
    if (TII.isAlwaysGDS(Inst.getOpcode()) ||
        TII.hasModifiersSet(Inst, AMDGPU::OpName::gds)) {
      ScoreBrackets->setPendingGDS();
    }
  } else if (TII.isFLAT(Inst)) {
    if (Inst.mayLoadOrStore() && TII.mayAccessVMEMThroughFlat(Inst) &&
        TII.mayAccessLDSThroughFlat(Inst) && !SIInstrInfo::isLDSDMA(Inst)) {
      // Async/LDSDMA operations have FLAT encoding but do not actually use flat
      // pointers. They do have two operands that each access global and LDS,
      // thus making it appear at this point that they are using a flat pointer.
      // Filter them out, and for the rest, generate a dependency on flat
      // pointers so that both VM and LGKM counters are flushed.
      ScoreBrackets->setPendingFlat();
    }
    if (SIInstrInfo::usesASYNC_CNT(Inst)) {
      ScoreBrackets->updateByEvent(ASYNC_ACCESS, Inst);
    }
  } else if (Inst.isCall()) {
    // Act as a wait on everything, but AsyncCnt is never included in such
    // blanket waits.
    ScoreBrackets->applyWaitcnt(WCG->getAllZeroWaitcnt(/*IncludeVSCnt=*/false));
    ScoreBrackets->setStateOnFunctionEntryOrReturn();
  } else if (TII.isVINTERP(Inst)) {
    int64_t Imm = TII.getNamedOperand(Inst, AMDGPU::OpName::waitexp)->getImm();
    ScoreBrackets->applyWaitcnt(AMDGPU::EXP_CNT, Imm);
  }
}

bool WaitcntBrackets::mergeScore(const MergeInfo &M, unsigned &Score,
                                 unsigned OtherScore) {
  unsigned MyShifted = Score <= M.OldLB ? 0 : Score + M.MyShift;
  unsigned OtherShifted =
      OtherScore <= M.OtherLB ? 0 : OtherScore + M.OtherShift;
  Score = std::max(MyShifted, OtherShifted);
  return OtherShifted > MyShifted;
}

bool WaitcntBrackets::mergeAsyncMarks(ArrayRef<MergeInfo> MergeInfos,
                                      ArrayRef<CounterValueArray> OtherMarks) {
  bool StrictDom = false;

  LLVM_DEBUG(dbgs() << "Merging async marks ...");
  // Early exit: nothing to merge when both sides are empty.
  if (AsyncMarks.empty() && OtherMarks.empty()) {
    LLVM_DEBUG(dbgs() << " nothing to merge\n");
    return false;
  }
  LLVM_DEBUG(dbgs() << '\n');

  // Determine maximum length needed after merging
  auto MaxSize = (unsigned)std::max(AsyncMarks.size(), OtherMarks.size());
  MaxSize = std::min(MaxSize, MaxAsyncMarks);

  // Keep only the most recent marks within our limit.
  if (AsyncMarks.size() > MaxSize)
    AsyncMarks.erase(AsyncMarks.begin(),
                     AsyncMarks.begin() + (AsyncMarks.size() - MaxSize));

  // Pad with zero-filled marks if our list is shorter. Zero represents "no
  // pending async operations at this checkpoint" and acts as the identity
  // element for max() during merging. We pad at the beginning since the marks
  // need to be aligned in most-recent order.
  constexpr CounterValueArray ZeroMark{};
  AsyncMarks.insert(AsyncMarks.begin(), MaxSize - AsyncMarks.size(), ZeroMark);

  LLVM_DEBUG({
    dbgs() << "Before merge:\n";
    for (const auto &Mark : AsyncMarks) {
      llvm::interleaveComma(Mark, dbgs());
      dbgs() << '\n';
    }
    dbgs() << "Other marks:\n";
    for (const auto &Mark : OtherMarks) {
      llvm::interleaveComma(Mark, dbgs());
      dbgs() << '\n';
    }
  });

  // Merge element-wise using the existing mergeScore function and the
  // appropriate MergeInfo for each counter type. Iterate only while we have
  // elements in both vectors.
  unsigned OtherSize = OtherMarks.size();
  unsigned OurSize = AsyncMarks.size();
  unsigned MergeCount = std::min(OtherSize, OurSize);
  // OtherMarks is empty -> OtherSize == 0 -> MergeCount == 0.
  // Our existing marks are the conservative result; return early to avoid
  // passing MergeCount == 0 to seq_inclusive which asserts Begin <= End.
  if (MergeCount == 0)
    return StrictDom;
  for (auto Idx : seq_inclusive<unsigned>(1, MergeCount)) {
    for (auto T : inst_counter_types(Context->MaxCounter)) {
      StrictDom |= mergeScore(MergeInfos[T], AsyncMarks[OurSize - Idx][T],
                              OtherMarks[OtherSize - Idx][T]);
    }
  }

  LLVM_DEBUG({
    dbgs() << "After merge:\n";
    for (const auto &Mark : AsyncMarks) {
      llvm::interleaveComma(Mark, dbgs());
      dbgs() << '\n';
    }
  });

  return StrictDom;
}

/// Merge the pending events and associater score brackets of \p Other into
/// this brackets status.
///
/// Returns whether the merge resulted in a change that requires tighter waits
/// (i.e. the merged brackets strictly dominate the original brackets).
bool WaitcntBrackets::merge(const WaitcntBrackets &Other) {
  bool StrictDom = false;

  // Check if "other" has keys we don't have, and create default entries for
  // those. If they remain empty after merging, we will clean it up after.
  for (auto K : Other.VMem.keys())
    VMem.try_emplace(K);
  for (auto K : Other.SGPRs.keys())
    SGPRs.try_emplace(K);

  // Array to store MergeInfo for each counter type
  MergeInfo MergeInfos[AMDGPU::NUM_INST_CNTS];

  for (auto T : inst_counter_types(Context->MaxCounter)) {
    // Merge event flags for this counter
    const WaitEventSet &EventsForT = Context->getWaitEvents(T);
    const WaitEventSet OldEvents = PendingEvents & EventsForT;
    const WaitEventSet OtherEvents = Other.PendingEvents & EventsForT;
    if (!OldEvents.contains(OtherEvents))
      StrictDom = true;
    PendingEvents |= OtherEvents;

    // Merge scores for this counter
    const unsigned MyPending = ScoreUBs[T] - ScoreLBs[T];
    const unsigned OtherPending = Other.ScoreUBs[T] - Other.ScoreLBs[T];
    const unsigned NewUB = ScoreLBs[T] + std::max(MyPending, OtherPending);
    if (NewUB < ScoreLBs[T])
      report_fatal_error("waitcnt score overflow");

    MergeInfo &M = MergeInfos[T];
    M.OldLB = ScoreLBs[T];
    M.OtherLB = Other.ScoreLBs[T];
    M.MyShift = NewUB - ScoreUBs[T];
    M.OtherShift = NewUB - Other.ScoreUBs[T];

    ScoreUBs[T] = NewUB;

    if (T == AMDGPU::LOAD_CNT)
      StrictDom |= mergeScore(M, LastFlatLoadCnt, Other.LastFlatLoadCnt);

    if (T == AMDGPU::DS_CNT) {
      StrictDom |= mergeScore(M, LastFlatDsCnt, Other.LastFlatDsCnt);
      StrictDom |= mergeScore(M, LastGDS, Other.LastGDS);
    }

    if (T == AMDGPU::KM_CNT) {
      StrictDom |= mergeScore(M, SCCScore, Other.SCCScore);
      if (Other.hasPendingEvent(SCC_WRITE)) {
        if (!OldEvents.contains(SCC_WRITE)) {
          PendingSCCWrite = Other.PendingSCCWrite;
        } else if (PendingSCCWrite != Other.PendingSCCWrite) {
          PendingSCCWrite = nullptr;
        }
      }
    }

    for (auto &[RegID, Info] : VMem)
      StrictDom |= mergeScore(M, Info.Scores[T], Other.getVMemScore(RegID, T));

    if (isSmemCounter(T)) {
      for (auto &[RegID, Info] : SGPRs) {
        auto It = Other.SGPRs.find(RegID);
        unsigned OtherScore = (It != Other.SGPRs.end()) ? It->second.get(T) : 0;
        StrictDom |= mergeScore(M, Info.get(T), OtherScore);
      }
    }
  }

  for (auto &[TID, Info] : VMem) {
    if (auto It = Other.VMem.find(TID); It != Other.VMem.end()) {
      unsigned char NewVmemTypes = Info.VMEMTypes | It->second.VMEMTypes;
      StrictDom |= NewVmemTypes != Info.VMEMTypes;
      Info.VMEMTypes = NewVmemTypes;
    }
  }

  StrictDom |= mergeAsyncMarks(MergeInfos, Other.AsyncMarks);
  for (auto T : inst_counter_types(Context->MaxCounter))
    StrictDom |= mergeScore(MergeInfos[T], AsyncScore[T], Other.AsyncScore[T]);

  purgeEmptyTrackingData();
  return StrictDom;
}

static bool isWaitInstr(MachineInstr &Inst) {
  unsigned Opcode = SIInstrInfo::getNonSoftWaitcntOpcode(Inst.getOpcode());
  return Opcode == AMDGPU::S_WAITCNT ||
         (Opcode == AMDGPU::S_WAITCNT_VSCNT && Inst.getOperand(0).isReg() &&
          Inst.getOperand(0).getReg() == AMDGPU::SGPR_NULL) ||
         Opcode == AMDGPU::S_WAIT_LOADCNT_DSCNT ||
         Opcode == AMDGPU::S_WAIT_STORECNT_DSCNT ||
         Opcode == AMDGPU::S_WAITCNT_lds_direct ||
         Opcode == AMDGPU::WAIT_ASYNCMARK ||
         counterTypeForInstr(Opcode).has_value();
}

void SIInsertWaitcnts::setSchedulingMode(MachineBasicBlock &MBB,
                                         MachineBasicBlock::iterator I,
                                         bool ExpertMode) const {
  const unsigned EncodedReg = AMDGPU::Hwreg::HwregEncoding::encode(
      AMDGPU::Hwreg::ID_SCHED_MODE, AMDGPU::Hwreg::HwregOffset::Default, 2);
  BuildMI(MBB, I, DebugLoc(), TII.get(AMDGPU::S_SETREG_IMM32_B32))
      .addImm(ExpertMode ? 2 : 0)
      .addImm(EncodedReg);
}

namespace {
// TODO: Remove this work-around after fixing the scheduler.
// There are two reasons why vccz might be incorrect; see ST.hasReadVCCZBug()
// and ST.partialVCCWritesUpdateVCCZ().
// i. VCCZBug: There is a hardware bug on CI/SI where SMRD instruction may
//    corrupt vccz bit, so when we detect that an instruction may read from
//    a corrupt vccz bit, we need to:
//   1. Insert s_waitcnt lgkm(0) to wait for all outstanding SMRD
//      operations to complete.
//   2. Recompute the correct value of vccz by writing the current value
//      of vcc back to vcc.
// ii. Partial writes to vcc don't update vccz, so we need to recompute the
//     correct value of vccz by reading vcc and writing it back to vcc.
//     No waitcnt is needed in this case.
class VCCZWorkaround {
  const WaitcntBrackets &ScoreBrackets;
  const GCNSubtarget &ST;
  const SIInstrInfo &TII;
  const SIRegisterInfo &TRI;
  bool VCCZCorruptionBug = false;
  bool VCCZNotUpdatedByPartialWrites = false;
  /// vccz could be incorrect at a basic block boundary if a predecessor wrote
  /// to vcc and then issued an smem load, so initialize to true.
  bool MustRecomputeVCCZ = true;

public:
  VCCZWorkaround(const WaitcntBrackets &ScoreBrackets, const GCNSubtarget &ST,
                 const SIInstrInfo &TII, const SIRegisterInfo &TRI)
      : ScoreBrackets(ScoreBrackets), ST(ST), TII(TII), TRI(TRI) {
    VCCZCorruptionBug = ST.hasReadVCCZBug();
    VCCZNotUpdatedByPartialWrites = !ST.partialVCCWritesUpdateVCCZ();
  }
  /// If \p MI reads vccz and we must recompute it based on MustRecomputeVCCZ,
  /// then emit a vccz recompute instruction before \p MI. This needs to be
  /// called on every instruction in the basic block because it also tracks the
  /// state and updates MustRecomputeVCCZ accordingly. Returns true if it
  /// modified the IR.
  bool tryRecomputeVCCZ(MachineInstr &MI) {
    // No need to run this if neither bug is present.
    if (!VCCZCorruptionBug && !VCCZNotUpdatedByPartialWrites)
      return false;

    // If MI is an SMEM and it can corrupt vccz on this target, then we need
    // both to emit a waitcnt and to recompute vccz.
    // But we don't actually emit a waitcnt here. This is done in
    // generateWaitcntInstBefore() because it tracks all the necessary waitcnt
    // state, and can either skip emitting a waitcnt if there is already one in
    // the IR, or emit an "optimized" combined waitcnt.
    // If this is an smem read, it could complete and clobber vccz at any time.
    MustRecomputeVCCZ |= VCCZCorruptionBug && TII.isSMRD(MI);

    // If the target partial vcc writes don't update vccz, and MI is such an
    // instruction then we must recompute vccz.
    // Note: We are using PartiallyWritesToVCCOpt optional to avoid calling
    // `definesRegister()` more than needed, because it's not very cheap.
    std::optional<bool> PartiallyWritesToVCCOpt;
    auto PartiallyWritesToVCC = [](MachineInstr &MI) {
      return MI.definesRegister(AMDGPU::VCC_LO, /*TRI=*/nullptr) ||
             MI.definesRegister(AMDGPU::VCC_HI, /*TRI=*/nullptr);
    };
    if (VCCZNotUpdatedByPartialWrites) {
      PartiallyWritesToVCCOpt = PartiallyWritesToVCC(MI);
      // If this is a partial VCC write but won't update vccz, then we must
      // recompute vccz.
      MustRecomputeVCCZ |= *PartiallyWritesToVCCOpt;
    }

    // If MI is a vcc write with no pending smem, or there is a pending smem
    // but the target does not suffer from the vccz corruption bug, then we
    // don't need to recompute vccz as this write will recompute it anyway.
    if (!ScoreBrackets.hasPendingEvent(SMEM_ACCESS) || !VCCZCorruptionBug) {
      // Compute PartiallyWritesToVCCOpt if we haven't done so already.
      if (!PartiallyWritesToVCCOpt)
        PartiallyWritesToVCCOpt = PartiallyWritesToVCC(MI);
      bool FullyWritesToVCC = !*PartiallyWritesToVCCOpt &&
                              MI.definesRegister(AMDGPU::VCC, /*TRI=*/nullptr);
      // If we write to the full vcc or we write partially and the target
      // updates vccz on partial writes, then vccz will be updated correctly.
      bool UpdatesVCCZ = FullyWritesToVCC || (!VCCZNotUpdatedByPartialWrites &&
                                              *PartiallyWritesToVCCOpt);
      if (UpdatesVCCZ)
        MustRecomputeVCCZ = false;
    }

    // If MI is a branch that reads VCCZ then emit a waitcnt and a vccz
    // restore instruction if either is needed.
    if (SIInstrInfo::isCBranchVCCZRead(MI) && MustRecomputeVCCZ) {
      // Recompute the vccz bit. Any time a value is written to vcc, the vccz
      // bit is updated, so we can restore the bit by reading the value of vcc
      // and then writing it back to the register.
      BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
              TII.get(ST.isWave32() ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64),
              TRI.getVCC())
          .addReg(TRI.getVCC());
      MustRecomputeVCCZ = false;
      return true;
    }
    return false;
  }
};

} // namespace

// Generate s_waitcnt instructions where needed.
bool SIInsertWaitcnts::insertWaitcntInBlock(MachineFunction &MF,
                                            MachineBasicBlock &Block,
                                            WaitcntBrackets &ScoreBrackets) {
  bool Modified = false;

  LLVM_DEBUG({
    dbgs() << "*** Begin Block: ";
    Block.printName(dbgs());
    ScoreBrackets.dump();
  });
  VCCZWorkaround VCCZW(ScoreBrackets, ST, TII, TRI);

  // Walk over the instructions.
  MachineInstr *OldWaitcntInstr = nullptr;

  // NOTE: We may append instrs after Inst while iterating.
  for (MachineBasicBlock::instr_iterator Iter = Block.instr_begin(),
                                         E = Block.instr_end();
       Iter != E; ++Iter) {
    MachineInstr &Inst = *Iter;
    if (isNonWaitcntMetaInst(Inst))
      continue;
    // Track pre-existing waitcnts that were added in earlier iterations or by
    // the memory legalizer.
    if (isWaitInstr(Inst) ||
        (IsExpertMode && Inst.getOpcode() == AMDGPU::S_WAITCNT_DEPCTR)) {
      if (!OldWaitcntInstr)
        OldWaitcntInstr = &Inst;
      continue;
    }

    PreheaderFlushFlags FlushFlags;
    if (Block.getFirstTerminator() == Inst)
      FlushFlags = isPreheaderToFlush(Block, ScoreBrackets);

    // Generate an s_waitcnt instruction to be placed before Inst, if needed.
    Modified |= generateWaitcntInstBefore(Inst, ScoreBrackets, OldWaitcntInstr,
                                          FlushFlags);
    OldWaitcntInstr = nullptr;

    if (Inst.getOpcode() == AMDGPU::ASYNCMARK) {
      // Asyncmarks record the current wait state and so should not allow
      // waitcnts that occur after them to be merged into waitcnts that occur
      // before.
      ScoreBrackets.recordAsyncMark(Inst);
      continue;
    }

    if (TII.isSMRD(Inst)) {
      for (const MachineMemOperand *Memop : Inst.memoperands()) {
        // No need to handle invariant loads when avoiding WAR conflicts, as
        // there cannot be a vector store to the same memory location.
        if (!Memop->isInvariant()) {
          const Value *Ptr = Memop->getValue();
          SLoadAddresses.insert(std::pair(Ptr, Inst.getParent()));
        }
      }
    }

    updateEventWaitcntAfter(Inst, &ScoreBrackets);

    // Note: insertForcedWaitAfter() may add instrs after Iter that need to be
    // visited by the loop.
    Modified |= insertForcedWaitAfter(Inst, Block, ScoreBrackets);

    LLVM_DEBUG({
      Inst.print(dbgs());
      ScoreBrackets.dump();
    });

    // If the target suffers from the vccz bugs, this may emit the necessary
    // vccz recompute instruction before \p Inst if needed.
    Modified |= VCCZW.tryRecomputeVCCZ(Inst);
  }

  // Flush counters at the end of the block if needed (for preheaders with no
  // terminator).
  AMDGPU::Waitcnt Wait;
  if (Block.getFirstTerminator() == Block.end()) {
    PreheaderFlushFlags FlushFlags = isPreheaderToFlush(Block, ScoreBrackets);
    if (FlushFlags.FlushVmCnt) {
      if (ScoreBrackets.hasPendingEvent(AMDGPU::LOAD_CNT))
        Wait.set(AMDGPU::LOAD_CNT, 0);
      if (ScoreBrackets.hasPendingEvent(AMDGPU::SAMPLE_CNT))
        Wait.set(AMDGPU::SAMPLE_CNT, 0);
      if (ScoreBrackets.hasPendingEvent(AMDGPU::BVH_CNT))
        Wait.set(AMDGPU::BVH_CNT, 0);
    }
    if (FlushFlags.FlushDsCnt && ScoreBrackets.hasPendingEvent(AMDGPU::DS_CNT))
      Wait.set(AMDGPU::DS_CNT, 0);
  }

  // Combine or remove any redundant waitcnts at the end of the block.
  Modified |= generateWaitcnt(Wait, Block.instr_end(), Block, ScoreBrackets,
                              OldWaitcntInstr);

  LLVM_DEBUG({
    dbgs() << "*** End Block: ";
    Block.printName(dbgs());
    ScoreBrackets.dump();
  });

  return Modified;
}

bool SIInsertWaitcnts::removeRedundantSoftXcnts(MachineBasicBlock &Block) {
  if (Block.size() <= 1)
    return false;
  // The Memory Legalizer conservatively inserts a soft xcnt before each
  // atomic RMW operation. However, for sequences of back-to-back atomic
  // RMWs, only the first s_wait_xcnt insertion is necessary. Optimize away
  // the redundant soft xcnts.
  bool Modified = false;
  // Remember the last atomic with a soft xcnt right before it.
  MachineInstr *LastAtomicWithSoftXcnt = nullptr;

  for (MachineInstr &MI : drop_begin(Block)) {
    // Ignore last atomic if non-LDS VMEM and SMEM.
    bool IsLDS =
        TII.isDS(MI) || (TII.isFLAT(MI) && TII.mayAccessLDSThroughFlat(MI));
    if (!IsLDS && (MI.mayLoad() ^ MI.mayStore()))
      LastAtomicWithSoftXcnt = nullptr;

    bool IsAtomicRMW = (MI.getDesc().TSFlags & SIInstrFlags::maybeAtomic) &&
                       MI.mayLoad() && MI.mayStore();
    MachineInstr &PrevMI = *MI.getPrevNode();
    // This is an atomic with a soft xcnt.
    if (PrevMI.getOpcode() == AMDGPU::S_WAIT_XCNT_soft && IsAtomicRMW) {
      // If we have already found an atomic with a soft xcnt, remove this soft
      // xcnt as it's redundant.
      if (LastAtomicWithSoftXcnt) {
        PrevMI.eraseFromParent();
        Modified = true;
      }
      LastAtomicWithSoftXcnt = &MI;
    }
  }
  return Modified;
}

// Return flags indicating which counters should be flushed in the preheader.
PreheaderFlushFlags
SIInsertWaitcnts::isPreheaderToFlush(MachineBasicBlock &MBB,
                                     const WaitcntBrackets &ScoreBrackets) {
  auto [Iterator, IsInserted] =
      PreheadersToFlush.try_emplace(&MBB, PreheaderFlushFlags());
  if (!IsInserted)
    return Iterator->second;

  MachineBasicBlock *Succ = MBB.getSingleSuccessor();
  if (!Succ)
    return PreheaderFlushFlags();

  MachineLoop *Loop = MLI.getLoopFor(Succ);
  if (!Loop)
    return PreheaderFlushFlags();

  if (Loop->getLoopPreheader() == &MBB) {
    Iterator->second = getPreheaderFlushFlags(Loop, ScoreBrackets);
    return Iterator->second;
  }

  return PreheaderFlushFlags();
}

bool SIInsertWaitcnts::isVMEMOrFlatVMEM(const MachineInstr &MI) const {
  if (SIInstrInfo::isFLAT(MI))
    return TII.mayAccessVMEMThroughFlat(MI);
  return SIInstrInfo::isVMEM(MI);
}

bool SIInsertWaitcnts::isDSRead(const MachineInstr &MI) const {
  return SIInstrInfo::isDS(MI) && MI.mayLoad() && !MI.mayStore();
}

// Check if instruction is a store to LDS that is counted via DSCNT
// (where that counter exists).
bool SIInsertWaitcnts::mayStoreIncrementingDSCNT(const MachineInstr &MI) const {
  return MI.mayStore() && SIInstrInfo::isDS(MI);
}

// Return flags indicating which counters should be flushed in the preheader of
// the given loop. We currently decide to flush in the following situations:
// For VMEM (FlushVmCnt):
// 1. The loop contains vmem store(s), no vmem load and at least one use of a
//    vgpr containing a value that is loaded outside of the loop. (Only on
//    targets with no vscnt counter).
// 2. The loop contains vmem load(s), but the loaded values are not used in the
//    loop, and at least one use of a vgpr containing a value that is loaded
//    outside of the loop.
// For DS (FlushDsCnt, GFX12+ only):
// 3. The loop contains no DS reads, and at least one use of a vgpr containing
//    a value that is DS read outside of the loop.
// 4. The loop contains DS read(s), loaded values are not used in the same
//    iteration but in the next iteration (prefetch pattern), and at least one
//    use of a vgpr containing a value that is DS read outside of the loop.
//    Flushing in preheader reduces wait overhead if the wait requirement in
//    iteration 1 would otherwise be more strict (but unfortunately preheader
//    flush decision is taken before knowing that).
// 5. (Single-block loops only) The loop has DS prefetch reads with flush point
//    tracking. Some DS reads may be used in the same iteration (creating
//    "flush points"), but others remain unflushed at the backedge. When a DS
//    read is consumed in the same iteration, it and all prior reads are
//    "flushed" (FIFO order). No DS writes are allowed in the loop.
//    TODO: Find a way to extend to multi-block loops.
PreheaderFlushFlags
SIInsertWaitcnts::getPreheaderFlushFlags(MachineLoop *ML,
                                         const WaitcntBrackets &Brackets) {
  PreheaderFlushFlags Flags;
  bool HasVMemLoad = false;
  bool HasVMemStore = false;
  bool UsesVgprVMEMLoadedOutside = false;
  bool UsesVgprDSReadOutside = false;
  bool VMemInvalidated = false;
  // DS optimization only applies to GFX12+ where DS_CNT is separate.
  // Tracking status for "no DS read in loop" or "pure DS prefetch
  // (use only in next iteration)".
  bool TrackSimpleDSOpt = ST.hasExtendedWaitCounts();
  DenseSet<MCRegUnit> VgprUse;
  DenseSet<MCRegUnit> VgprDefVMEM;
  DenseSet<MCRegUnit> VgprDefDS;

  // Track DS reads for prefetch pattern with flush points (single-block only).
  // Keeps track of the last DS read (position counted from the top of the loop)
  // to each VGPR. Read is considered consumed (and thus needs flushing) if
  // the dest register has a use or is overwritten (by any later opertions).
  DenseMap<MCRegUnit, unsigned> LastDSReadPositionMap;
  unsigned DSReadPosition = 0;
  bool IsSingleBlock = ML->getNumBlocks() == 1;
  bool TrackDSFlushPoint = ST.hasExtendedWaitCounts() && IsSingleBlock;
  unsigned LastDSFlushPosition = 0;

  for (MachineBasicBlock *MBB : ML->blocks()) {
    for (MachineInstr &MI : *MBB) {
      if (isVMEMOrFlatVMEM(MI)) {
        HasVMemLoad |= MI.mayLoad();
        HasVMemStore |= MI.mayStore();
      }
      // TODO: Can we relax DSStore check? There may be cases where
      // these DS stores are drained prior to the end of MBB (or loop).
      if (mayStoreIncrementingDSCNT(MI)) {
        // Early exit if none of the optimizations are feasible.
        // Otherwise, set tracking status appropriately and continue.
        if (VMemInvalidated)
          return Flags;
        TrackSimpleDSOpt = false;
        TrackDSFlushPoint = false;
      }
      bool IsDSRead = isDSRead(MI);
      if (IsDSRead)
        ++DSReadPosition;

      // Helper: if RU has a pending DS read, update LastDSFlushPosition
      auto updateDSReadFlushTracking = [&](MCRegUnit RU) {
        if (!TrackDSFlushPoint)
          return;
        if (auto It = LastDSReadPositionMap.find(RU);
            It != LastDSReadPositionMap.end()) {
          // RU defined by DSRead is used or overwritten. Need to complete
          // the read, if not already implied by a later DSRead (to any RU)
          // needing to complete in FIFO order.
          LastDSFlushPosition = std::max(LastDSFlushPosition, It->second);
        }
      };

      for (const MachineOperand &Op : MI.all_uses()) {
        if (Op.isDebug() || !TRI.isVectorRegister(MRI, Op.getReg()))
          continue;
        // Vgpr use
        for (MCRegUnit RU : TRI.regunits(Op.getReg().asMCReg())) {
          // If we find a register that is loaded inside the loop, 1. and 2.
          // are invalidated.
          if (VgprDefVMEM.contains(RU))
            VMemInvalidated = true;

          // Check for DS reads used inside the loop
          if (VgprDefDS.contains(RU))
            TrackSimpleDSOpt = false;

          // Early exit if all optimizations are invalidated
          if (VMemInvalidated && !TrackSimpleDSOpt && !TrackDSFlushPoint)
            return Flags;

          // Check for flush points (DS read used in same iteration)
          updateDSReadFlushTracking(RU);

          VgprUse.insert(RU);
          // Check if this register has a pending VMEM load from outside the
          // loop (value loaded outside and used inside).
          VMEMID ID = toVMEMID(RU);
          if (Brackets.hasPendingVMEM(ID, AMDGPU::LOAD_CNT) ||
              Brackets.hasPendingVMEM(ID, AMDGPU::SAMPLE_CNT) ||
              Brackets.hasPendingVMEM(ID, AMDGPU::BVH_CNT))
            UsesVgprVMEMLoadedOutside = true;
          // Check if loaded outside the loop via DS (not VMEM/FLAT).
          // Only consider it a DS read if there's no pending VMEM load for
          // this register, since FLAT can set both counters.
          else if (Brackets.hasPendingVMEM(ID, AMDGPU::DS_CNT))
            UsesVgprDSReadOutside = true;
        }
      }

      // VMem load vgpr def
      if (isVMEMOrFlatVMEM(MI) && MI.mayLoad()) {
        for (const MachineOperand &Op : MI.all_defs()) {
          for (MCRegUnit RU : TRI.regunits(Op.getReg().asMCReg())) {
            // If we find a register that is loaded inside the loop, 1. and 2.
            // are invalidated.
            if (VgprUse.contains(RU))
              VMemInvalidated = true;
            VgprDefVMEM.insert(RU);
          }
        }
        // Early exit if all optimizations are invalidated
        if (VMemInvalidated && !TrackSimpleDSOpt && !TrackDSFlushPoint)
          return Flags;
      }

      // DS read vgpr def
      // Note: Unlike VMEM, we DON'T invalidate when VgprUse.contains(RegNo).
      // If USE comes before DEF, it's the prefetch pattern (use value from
      // previous iteration, read for next iteration). We should still flush
      // in preheader so iteration 1 doesn't need to wait inside the loop.
      // Only invalidate when DEF comes before USE (same-iteration consumption,
      // checked above when processing uses).
      if (IsDSRead || TrackDSFlushPoint) {
        for (const MachineOperand &Op : MI.all_defs()) {
          if (!TRI.isVectorRegister(MRI, Op.getReg()))
            continue;
          for (MCRegUnit RU : TRI.regunits(Op.getReg().asMCReg())) {
            // Check for overwrite of pending DS read (flush point) by any
            // instruction
            updateDSReadFlushTracking(RU);
            if (IsDSRead) {
              VgprDefDS.insert(RU);
              if (TrackDSFlushPoint)
                LastDSReadPositionMap[RU] = DSReadPosition;
            }
          }
        }
      }
    }
  }

  // VMEM flush decision
  if (!VMemInvalidated && UsesVgprVMEMLoadedOutside &&
      ((!ST.hasVscnt() && HasVMemStore && !HasVMemLoad) ||
       (HasVMemLoad && ST.hasVmemWriteVgprInOrder())))
    Flags.FlushVmCnt = true;

  // DS flush decision:
  // Simple DS Opt: flush if loop uses DS read values from outside
  // and either has no DS reads in the loop, or DS reads whose results
  // are not used in the loop.
  bool SimpleDSOpt = TrackSimpleDSOpt && UsesVgprDSReadOutside;
  // Prefetch with flush points: some DS reads used in same iteration,
  // but unflushed reads remain at backedge
  bool HasUnflushedDSReads = DSReadPosition > LastDSFlushPosition;
  bool DSFlushPointPrefetch =
      TrackDSFlushPoint && UsesVgprDSReadOutside && HasUnflushedDSReads;

  if (SimpleDSOpt || DSFlushPointPrefetch)
    Flags.FlushDsCnt = true;

  return Flags;
}

bool SIInsertWaitcntsLegacy::runOnMachineFunction(MachineFunction &MF) {
  auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
  auto &PDT =
      getAnalysis<MachinePostDominatorTreeWrapperPass>().getPostDomTree();
  AliasAnalysis *AA = nullptr;
  if (auto *AAR = getAnalysisIfAvailable<AAResultsWrapperPass>())
    AA = &AAR->getAAResults();

  return SIInsertWaitcnts(MLI, PDT, AA, MF).run();
}

PreservedAnalyses
SIInsertWaitcntsPass::run(MachineFunction &MF,
                          MachineFunctionAnalysisManager &MFAM) {
  auto &MLI = MFAM.getResult<MachineLoopAnalysis>(MF);
  auto &PDT = MFAM.getResult<MachinePostDominatorTreeAnalysis>(MF);
  auto *AA = MFAM.getResult<FunctionAnalysisManagerMachineFunctionProxy>(MF)
                 .getManager()
                 .getCachedResult<AAManager>(MF.getFunction());

  if (!SIInsertWaitcnts(MLI, PDT, AA, MF).run())
    return PreservedAnalyses::all();

  return getMachineFunctionPassPreservedAnalyses()
      .preserveSet<CFGAnalyses>()
      .preserve<AAManager>();
}

bool SIInsertWaitcnts::run() {
  const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();

  AMDGPU::IsaVersion IV = AMDGPU::getIsaVersion(ST.getCPU());

  // Initialize hardware limits first, as they're needed by the generators.
  Limits = AMDGPU::HardwareLimits(IV);

  if (ST.hasExtendedWaitCounts()) {
    IsExpertMode = ST.hasExpertSchedulingMode() &&
                   (ExpertSchedulingModeFlag.getNumOccurrences()
                        ? ExpertSchedulingModeFlag
                        : MF.getFunction()
                              .getFnAttribute("amdgpu-expert-scheduling-mode")
                              .getValueAsBool());
    MaxCounter = IsExpertMode ? AMDGPU::NUM_EXPERT_INST_CNTS
                              : AMDGPU::NUM_EXTENDED_INST_CNTS;
    // Initialize WCG per MF. It contains state that depends on MF attributes.
    WCG = std::make_unique<WaitcntGeneratorGFX12Plus>(MF, MaxCounter, Limits,
                                                      IsExpertMode);
  } else {
    MaxCounter = AMDGPU::NUM_NORMAL_INST_CNTS;
    // Initialize WCG per MF. It contains state that depends on MF attributes.
    WCG = std::make_unique<WaitcntGeneratorPreGFX12>(
        MF, AMDGPU::NUM_NORMAL_INST_CNTS, Limits);
  }

  SmemAccessCounter = getCounterFromEvent(SMEM_ACCESS);

  bool Modified = false;

  MachineBasicBlock &EntryBB = MF.front();

  if (!MFI->isEntryFunction() &&
      !MF.getFunction().hasFnAttribute(Attribute::Naked)) {
    // Wait for any outstanding memory operations that the input registers may
    // depend on. We can't track them and it's better to do the wait after the
    // costly call sequence.

    // TODO: Could insert earlier and schedule more liberally with operations
    // that only use caller preserved registers.
    MachineBasicBlock::iterator I = EntryBB.begin();
    while (I != EntryBB.end() && I->isMetaInstruction())
      ++I;

    if (ST.hasExtendedWaitCounts()) {
      BuildMI(EntryBB, I, DebugLoc(), TII.get(AMDGPU::S_WAIT_LOADCNT_DSCNT))
          .addImm(0);
      for (auto CT : inst_counter_types(AMDGPU::NUM_EXTENDED_INST_CNTS)) {
        if (CT == AMDGPU::LOAD_CNT || CT == AMDGPU::DS_CNT ||
            CT == AMDGPU::STORE_CNT || CT == AMDGPU::X_CNT ||
            CT == AMDGPU::ASYNC_CNT)
          continue;

        if (!ST.hasImageInsts() &&
            (CT == AMDGPU::EXP_CNT || CT == AMDGPU::SAMPLE_CNT ||
             CT == AMDGPU::BVH_CNT))
          continue;

        BuildMI(EntryBB, I, DebugLoc(),
                TII.get(instrsForExtendedCounterTypes[CT]))
            .addImm(0);
      }
      if (IsExpertMode) {
        unsigned Enc = AMDGPU::DepCtr::encodeFieldVaVdst(0, ST);
        Enc = AMDGPU::DepCtr::encodeFieldVmVsrc(Enc, 0);
        BuildMI(EntryBB, I, DebugLoc(), TII.get(AMDGPU::S_WAITCNT_DEPCTR))
            .addImm(Enc);
      }
    } else {
      BuildMI(EntryBB, I, DebugLoc(), TII.get(AMDGPU::S_WAITCNT)).addImm(0);
    }

    auto NonKernelInitialState = std::make_unique<WaitcntBrackets>(this);
    NonKernelInitialState->setStateOnFunctionEntryOrReturn();
    BlockInfos[&EntryBB].Incoming = std::move(NonKernelInitialState);

    Modified = true;
  }

  // Keep iterating over the blocks in reverse post order, inserting and
  // updating s_waitcnt where needed, until a fix point is reached.
  for (auto *MBB : ReversePostOrderTraversal<MachineFunction *>(&MF))
    BlockInfos.try_emplace(MBB);

  std::unique_ptr<WaitcntBrackets> Brackets;
  bool Repeat;
  do {
    Repeat = false;

    for (auto BII = BlockInfos.begin(), BIE = BlockInfos.end(); BII != BIE;
         ++BII) {
      MachineBasicBlock *MBB = BII->first;
      BlockInfo &BI = BII->second;
      if (!BI.Dirty)
        continue;

      if (BI.Incoming) {
        if (!Brackets)
          Brackets = std::make_unique<WaitcntBrackets>(*BI.Incoming);
        else
          *Brackets = *BI.Incoming;
      } else {
        if (!Brackets) {
          Brackets = std::make_unique<WaitcntBrackets>(this);
        } else {
          // Reinitialize in-place. N.B. do not do this by assigning from a
          // temporary because the WaitcntBrackets class is large and it could
          // cause this function to use an unreasonable amount of stack space.
          Brackets->~WaitcntBrackets();
          new (Brackets.get()) WaitcntBrackets(this);
        }
      }

      if (ST.hasWaitXcnt())
        Modified |= removeRedundantSoftXcnts(*MBB);
      Modified |= insertWaitcntInBlock(MF, *MBB, *Brackets);
      BI.Dirty = false;

      if (Brackets->hasPendingEvent()) {
        BlockInfo *MoveBracketsToSucc = nullptr;
        for (MachineBasicBlock *Succ : MBB->successors()) {
          auto *SuccBII = BlockInfos.find(Succ);
          BlockInfo &SuccBI = SuccBII->second;
          if (!SuccBI.Incoming) {
            SuccBI.Dirty = true;
            if (SuccBII <= BII) {
              LLVM_DEBUG(dbgs() << "Repeat on backedge without merge\n");
              Repeat = true;
            }
            if (!MoveBracketsToSucc) {
              MoveBracketsToSucc = &SuccBI;
            } else {
              SuccBI.Incoming = std::make_unique<WaitcntBrackets>(*Brackets);
            }
          } else {
            LLVM_DEBUG({
              dbgs() << "Try to merge ";
              MBB->printName(dbgs());
              dbgs() << " into ";
              Succ->printName(dbgs());
              dbgs() << '\n';
            });
            if (SuccBI.Incoming->merge(*Brackets)) {
              SuccBI.Dirty = true;
              if (SuccBII <= BII) {
                LLVM_DEBUG(dbgs() << "Repeat on backedge with merge\n");
                Repeat = true;
              }
            }
          }
        }
        if (MoveBracketsToSucc)
          MoveBracketsToSucc->Incoming = std::move(Brackets);
      }
    }
  } while (Repeat);

  if (ST.hasScalarStores()) {
    SmallVector<MachineBasicBlock *, 4> EndPgmBlocks;
    bool HaveScalarStores = false;

    for (MachineBasicBlock &MBB : MF) {
      for (MachineInstr &MI : MBB) {
        if (!HaveScalarStores && TII.isScalarStore(MI))
          HaveScalarStores = true;

        if (MI.getOpcode() == AMDGPU::S_ENDPGM ||
            MI.getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG)
          EndPgmBlocks.push_back(&MBB);
      }
    }

    if (HaveScalarStores) {
      // If scalar writes are used, the cache must be flushed or else the next
      // wave to reuse the same scratch memory can be clobbered.
      //
      // Insert s_dcache_wb at wave termination points if there were any scalar
      // stores, and only if the cache hasn't already been flushed. This could
      // be improved by looking across blocks for flushes in postdominating
      // blocks from the stores but an explicitly requested flush is probably
      // very rare.
      for (MachineBasicBlock *MBB : EndPgmBlocks) {
        bool SeenDCacheWB = false;

        for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end();
             I != E; ++I) {
          if (I->getOpcode() == AMDGPU::S_DCACHE_WB)
            SeenDCacheWB = true;
          else if (TII.isScalarStore(*I))
            SeenDCacheWB = false;

          // FIXME: It would be better to insert this before a waitcnt if any.
          if ((I->getOpcode() == AMDGPU::S_ENDPGM ||
               I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG) &&
              !SeenDCacheWB) {
            Modified = true;
            BuildMI(*MBB, I, I->getDebugLoc(), TII.get(AMDGPU::S_DCACHE_WB));
          }
        }
      }
    }
  }

  if (IsExpertMode) {
    // Enable expert scheduling on function entry. To satisfy ABI requirements
    // and to allow calls between function with different expert scheduling
    // settings, disable it around calls and before returns.

    MachineBasicBlock::iterator I = EntryBB.begin();
    while (I != EntryBB.end() && I->isMetaInstruction())
      ++I;
    setSchedulingMode(EntryBB, I, true);

    for (MachineInstr *MI : CallInsts) {
      MachineBasicBlock &MBB = *MI->getParent();
      setSchedulingMode(MBB, MI, false);
      setSchedulingMode(MBB, std::next(MI->getIterator()), true);
    }

    for (MachineInstr *MI : ReturnInsts)
      setSchedulingMode(*MI->getParent(), MI, false);

    Modified = true;
  }

  // Deallocate the VGPRs before previously identified S_ENDPGM instructions.
  // This is done in different ways depending on how the VGPRs were allocated
  // (i.e. whether we're in dynamic VGPR mode or not).
  // Skip deallocation if kernel is waveslot limited vs VGPR limited. A short
  // waveslot limited kernel runs slower with the deallocation.
  if (!WCG->isOptNone() && MFI->isDynamicVGPREnabled()) {
    for (auto [MI, _] : EndPgmInsts) {
      BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
              TII.get(AMDGPU::S_ALLOC_VGPR))
          .addImm(0);
      Modified = true;
    }
  } else if (!WCG->isOptNone() &&
             ST.getGeneration() >= AMDGPUSubtarget::GFX11 &&
             (MF.getFrameInfo().hasCalls() ||
              ST.getOccupancyWithNumVGPRs(
                  TRI.getNumUsedPhysRegs(MRI, AMDGPU::VGPR_32RegClass),
                  /*IsDynamicVGPR=*/false) <
                  AMDGPU::IsaInfo::getMaxWavesPerEU(&ST))) {
    for (auto [MI, Flag] : EndPgmInsts) {
      if (Flag) {
        if (ST.requiresNopBeforeDeallocVGPRs()) {
          BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
                  TII.get(AMDGPU::S_NOP))
              .addImm(0);
        }
        BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
                TII.get(AMDGPU::S_SENDMSG))
            .addImm(AMDGPU::SendMsg::ID_DEALLOC_VGPRS_GFX11Plus);
        Modified = true;
      }
    }
  }

  return Modified;
}
