1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 12:12:47 +01:00
llvm-mirror/include/llvm/CodeGen/CalcSpillWeights.h
Serguei Katkov c9a1c9ca92 [RegAlloc] Fix "ran out of regs" with uses in statepoint
Statepoint instruction is known to have a variable and big number of operands.
It is possible that Register Allocator will split live intervals in the way that all
physical registers are occupied by "zero-length" live intervals which are marked
as not-spillable.
While intervals are marked as not-spillable in the moment of creation when they are
really zero-length it is possible that in future as part of re-materialization there will
need for physical register between def and use of such tiny interval (the use is not
related to this interval at all).
As all physical registers are assigned to not-spillable intervals there is not avaialbe
registers and RA reports an error.

The idea of the fix is avoid marking tiny live intervals where there is a use in statepoint
instruction in var args section. Such interval may be perfectly spilled and folded to
operand of statepoint.

Reviewers: reames, dantrushin, qcolombet, dsanders, dmgreen
Reviewed By: reames
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D98766
2021-03-24 10:25:34 +07:00

108 lines
4.6 KiB
C++

//===- lib/CodeGen/CalcSpillWeights.h ---------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_CALCSPILLWEIGHTS_H
#define LLVM_CODEGEN_CALCSPILLWEIGHTS_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/CodeGen/SlotIndexes.h"
namespace llvm {
class LiveInterval;
class LiveIntervals;
class MachineBlockFrequencyInfo;
class MachineFunction;
class MachineLoopInfo;
class VirtRegMap;
/// Normalize the spill weight of a live interval
///
/// The spill weight of a live interval is computed as:
///
/// (sum(use freq) + sum(def freq)) / (K + size)
///
/// @param UseDefFreq Expected number of executed use and def instructions
/// per function call. Derived from block frequencies.
/// @param Size Size of live interval as returnexd by getSize()
/// @param NumInstr Number of instructions using this live interval
static inline float normalizeSpillWeight(float UseDefFreq, unsigned Size,
unsigned NumInstr) {
// The constant 25 instructions is added to avoid depending too much on
// accidental SlotIndex gaps for small intervals. The effect is that small
// intervals have a spill weight that is mostly proportional to the number
// of uses, while large intervals get a spill weight that is closer to a use
// density.
return UseDefFreq / (Size + 25*SlotIndex::InstrDist);
}
/// Calculate auxiliary information for a virtual register such as its
/// spill weight and allocation hint.
class VirtRegAuxInfo {
MachineFunction &MF;
LiveIntervals &LIS;
const VirtRegMap &VRM;
const MachineLoopInfo &Loops;
const MachineBlockFrequencyInfo &MBFI;
/// Returns true if Reg of live interval LI is used in instruction with many
/// operands like STATEPOINT.
bool isLiveAtStatepointVarArg(LiveInterval &LI);
public:
VirtRegAuxInfo(MachineFunction &MF, LiveIntervals &LIS,
const VirtRegMap &VRM, const MachineLoopInfo &Loops,
const MachineBlockFrequencyInfo &MBFI)
: MF(MF), LIS(LIS), VRM(VRM), Loops(Loops), MBFI(MBFI) {}
virtual ~VirtRegAuxInfo() = default;
/// (re)compute li's spill weight and allocation hint.
void calculateSpillWeightAndHint(LiveInterval &LI);
/// Compute future expected spill weight of a split artifact of LI
/// that will span between start and end slot indexes.
/// \param LI The live interval to be split.
/// \param Start The expected beginning of the split artifact. Instructions
/// before start will not affect the weight.
/// \param End The expected end of the split artifact. Instructions
/// after end will not affect the weight.
/// \return The expected spill weight of the split artifact. Returns
/// negative weight for unspillable LI.
float futureWeight(LiveInterval &LI, SlotIndex Start, SlotIndex End);
/// Compute spill weights and allocation hints for all virtual register
/// live intervals.
void calculateSpillWeightsAndHints();
protected:
/// Helper function for weight calculations.
/// (Re)compute LI's spill weight and allocation hint, or, for non null
/// start and end - compute future expected spill weight of a split
/// artifact of LI that will span between start and end slot indexes.
/// \param LI The live interval for which to compute the weight.
/// \param Start The expected beginning of the split artifact. Instructions
/// before start will not affect the weight. Relevant for
/// weight calculation of future split artifact.
/// \param End The expected end of the split artifact. Instructions
/// after end will not affect the weight. Relevant for
/// weight calculation of future split artifact.
/// \return The spill weight. Returns negative weight for unspillable LI.
float weightCalcHelper(LiveInterval &LI, SlotIndex *Start = nullptr,
SlotIndex *End = nullptr);
/// Weight normalization function.
virtual float normalize(float UseDefFreq, unsigned Size,
unsigned NumInstr) {
return normalizeSpillWeight(UseDefFreq, Size, NumInstr);
}
};
} // end namespace llvm
#endif // LLVM_CODEGEN_CALCSPILLWEIGHTS_H