[llvm] [CodeGen][MachinePipeliner] Limit register pressure when scheduling (PR #74807)
Ryotaro Kasuga via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 18 18:52:30 PDT 2024
================
@@ -1102,6 +1156,375 @@ struct FuncUnitSorter {
}
};
+/// Calculate the maximum register pressure of the scheduled instructions stream
+class HighRegisterPressureDetector {
+ MachineBasicBlock *OrigMBB;
+ const MachineFunction &MF;
+ const MachineRegisterInfo &MRI;
+ const TargetRegisterInfo *TRI;
+
+ const unsigned PSetNum;
+
+ // Indexed by PSet ID
+ // InitSetPressure takes into account the register pressure of live-in
+ // registers. It's not depend on how the loop is scheduled, so it's enough to
+ // calculate them once at the beginning.
+ std::vector<unsigned> InitSetPressure;
+
+ // Indexed by PSet ID
+ // Upper limit for each register pressure set
+ std::vector<unsigned> PressureSetLimit;
+
+ DenseMap<MachineInstr *, RegisterOperands> ROMap;
+
+ using Instr2LastUsesTy = DenseMap<MachineInstr *, SmallDenseSet<Register, 4>>;
+
+public:
+ using OrderedInstsTy = std::vector<MachineInstr *>;
+ using Instr2StageTy = DenseMap<MachineInstr *, unsigned>;
+
+private:
+ static void dumpRegisterPressures(const std::vector<unsigned> &Pressures) {
+ if (Pressures.size() == 0) {
+ dbgs() << "[]";
+ } else {
+ char Prefix = '[';
+ for (unsigned P : Pressures) {
+ dbgs() << Prefix << P;
+ Prefix = ' ';
+ }
+ dbgs() << ']';
+ }
+ }
+
+ void dumpPSet(Register Reg) const {
+ dbgs() << "Reg=" << printReg(Reg, TRI, 0, &MRI) << " PSet=";
+ for (auto PSetIter = MRI.getPressureSets(Reg); PSetIter.isValid();
+ ++PSetIter) {
+ dbgs() << *PSetIter << ' ';
+ }
+ dbgs() << '\n';
+ }
+
+ void increaseRegisterPressure(std::vector<unsigned> &Pressure,
+ Register Reg) const {
+ auto PSetIter = MRI.getPressureSets(Reg);
+ unsigned Weight = PSetIter.getWeight();
+ for (; PSetIter.isValid(); ++PSetIter)
+ Pressure[*PSetIter] += Weight;
+ }
+
+ void decreaseRegisterPressure(std::vector<unsigned> &Pressure,
+ Register Reg) const {
+ auto PSetIter = MRI.getPressureSets(Reg);
+ unsigned Weight = PSetIter.getWeight();
+ for (; PSetIter.isValid(); ++PSetIter) {
+ auto &P = Pressure[*PSetIter];
+ assert(P >= Weight &&
+ "register pressure must be greater than or equal weight");
+ P -= Weight;
+ }
+ }
+
+ // Return true if Reg is fixed one, for example, stack pointer
+ bool isFixedRegister(Register Reg) const {
+ return Reg.isPhysical() && TRI->isFixedRegister(MF, Reg.asMCReg());
+ }
+
+ bool isDefinedInThisLoop(Register Reg) const {
+ return Reg.isVirtual() && MRI.getVRegDef(Reg)->getParent() == OrigMBB;
+ }
+
+ // Search for live-in variables. They are factored into the register pressure
+ // from the begining. Live-in variables used by every iteration should be
+ // considered as alive throughout the loop. For example, the variable `c` in
+ // following code. \code
+ // int c = ...;
+ // for (int i = 0; i < n; i++)
+ // a[i] += b[i] + c;
+ // \endcode
+ void computeLiveIn() {
+ DenseSet<Register> Used;
+ for (auto &MI : *OrigMBB) {
+ if (MI.isDebugInstr())
+ continue;
+ for (auto Use : ROMap[&MI].Uses) {
+ auto Reg = Use.RegUnit;
+ // Ignore the variable that appears only on one side of phi instruction
+ // because it's used only at the first iteration.
+ if (MI.isPHI() && Reg != getLoopPhiReg(MI, OrigMBB))
+ continue;
+ if (isFixedRegister(Reg))
+ continue;
+ if (isDefinedInThisLoop(Reg))
+ continue;
+ Used.insert(Reg);
+ }
+ }
+
+ for (auto LiveIn : Used)
+ increaseRegisterPressure(InitSetPressure, LiveIn);
+ }
+
+ // Calculate the upper limit of each pressure set
+ void computePressureSetLimit(const RegisterClassInfo &RCI) {
+ for (unsigned PSet = 0; PSet < PSetNum; PSet++)
+ PressureSetLimit[PSet] = RCI.getRegPressureSetLimit(PSet);
+
+ // We assume fixed registers, such as stack pointer, are already in use.
+ // Therefore subtracting the weight of the fixed registers from the limit of
+ // each pressure set in advance.
+ SmallDenseSet<Register, 8> FixedRegs;
+ for (const TargetRegisterClass *TRC : TRI->regclasses()) {
+ for (const MCPhysReg Reg : *TRC)
+ if (isFixedRegister(Reg))
+ FixedRegs.insert(Reg);
+ }
+
+ LLVM_DEBUG({
+ for (auto Reg : FixedRegs) {
+ dbgs() << printReg(Reg, TRI, 0, &MRI) << ": [";
+ const int *Sets = TRI->getRegUnitPressureSets(Reg);
----------------
kasuga-fj wrote:
Oh, I see, I didn't know that. Thanks for finding it.
https://github.com/llvm/llvm-project/pull/74807
More information about the llvm-commits
mailing list