brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.7 KiB · a77da01 Raw
425 lines · cpp
1//===- CalcSpillWeights.cpp -----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/CodeGen/CalcSpillWeights.h"10#include "llvm/ADT/SmallPtrSet.h"11#include "llvm/CodeGen/LiveInterval.h"12#include "llvm/CodeGen/LiveIntervals.h"13#include "llvm/CodeGen/MachineFunction.h"14#include "llvm/CodeGen/MachineInstr.h"15#include "llvm/CodeGen/MachineLoopInfo.h"16#include "llvm/CodeGen/MachineOperand.h"17#include "llvm/CodeGen/MachineRegisterInfo.h"18#include "llvm/CodeGen/StackMaps.h"19#include "llvm/CodeGen/TargetInstrInfo.h"20#include "llvm/CodeGen/TargetRegisterInfo.h"21#include "llvm/CodeGen/TargetSubtargetInfo.h"22#include "llvm/CodeGen/VirtRegMap.h"23#include "llvm/Support/Debug.h"24#include "llvm/Support/MathExtras.h"25#include "llvm/Support/raw_ostream.h"26#include <cassert>27#include <tuple>28 29using namespace llvm;30 31#define DEBUG_TYPE "calcspillweights"32 33void VirtRegAuxInfo::calculateSpillWeightsAndHints() {34  LLVM_DEBUG(dbgs() << "********** Compute Spill Weights **********\n"35                    << "********** Function: " << MF.getName() << '\n');36 37  MachineRegisterInfo &MRI = MF.getRegInfo();38  for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {39    Register Reg = Register::index2VirtReg(I);40    if (MRI.reg_nodbg_empty(Reg))41      continue;42    calculateSpillWeightAndHint(LIS.getInterval(Reg));43  }44}45 46// Return the preferred allocation register for reg, given a COPY instruction.47Register VirtRegAuxInfo::copyHint(const MachineInstr *MI, Register Reg,48                                  const TargetRegisterInfo &TRI,49                                  const MachineRegisterInfo &MRI) {50  unsigned Sub, HSub;51  Register HReg;52  if (MI->getOperand(0).getReg() == Reg) {53    Sub = MI->getOperand(0).getSubReg();54    HReg = MI->getOperand(1).getReg();55    HSub = MI->getOperand(1).getSubReg();56  } else {57    Sub = MI->getOperand(1).getSubReg();58    HReg = MI->getOperand(0).getReg();59    HSub = MI->getOperand(0).getSubReg();60  }61 62  if (!HReg)63    return 0;64 65  if (HReg.isVirtual())66    return Sub == HSub ? HReg : Register();67 68  const TargetRegisterClass *RC = MRI.getRegClass(Reg);69  MCRegister CopiedPReg = HSub ? TRI.getSubReg(HReg, HSub) : HReg.asMCReg();70  if (RC->contains(CopiedPReg))71    return CopiedPReg;72 73  // Check if reg:sub matches so that a super register could be hinted.74  if (Sub)75    return TRI.getMatchingSuperReg(CopiedPReg, Sub, RC);76 77  return Register();78}79 80// Check if all values in LI are rematerializable81bool VirtRegAuxInfo::isRematerializable(const LiveInterval &LI,82                                        const LiveIntervals &LIS,83                                        const VirtRegMap &VRM,84                                        const MachineRegisterInfo &MRI,85                                        const TargetInstrInfo &TII) {86  Register Reg = LI.reg();87  Register Original = VRM.getOriginal(Reg);88  SmallDenseMap<unsigned, MachineInstr *> VNIDefs;89  for (LiveInterval::const_vni_iterator I = LI.vni_begin(), E = LI.vni_end();90       I != E; ++I) {91    const VNInfo *VNI = *I;92    const VNInfo *OrigVNI = VNI;93    if (VNI->isUnused())94      continue;95    if (VNI->isPHIDef())96      return false;97 98    MachineInstr *MI = LIS.getInstructionFromIndex(VNI->def);99    assert(MI && "Dead valno in interval");100 101    // Trace copies introduced by live range splitting.  The inline102    // spiller can rematerialize through these copies, so the spill103    // weight must reflect this.104    while (TII.isFullCopyInstr(*MI)) {105      // The copy destination must match the interval register.106      if (MI->getOperand(0).getReg() != Reg)107        return false;108 109      // Get the source register.110      Reg = MI->getOperand(1).getReg();111 112      // If the original (pre-splitting) registers match this113      // copy came from a split.114      if (!Reg.isVirtual() || VRM.getOriginal(Reg) != Original)115        return false;116 117      // Follow the copy live-in value.118      const LiveInterval &SrcLI = LIS.getInterval(Reg);119      LiveQueryResult SrcQ = SrcLI.Query(VNI->def);120      VNI = SrcQ.valueIn();121      assert(VNI && "Copy from non-existing value");122      if (VNI->isPHIDef())123        return false;124      MI = LIS.getInstructionFromIndex(VNI->def);125      assert(MI && "Dead valno in interval");126    }127 128    if (!TII.isReMaterializable(*MI))129      return false;130 131    VNIDefs[OrigVNI->id] = MI;132  }133 134  // If MI has register uses, it will only be rematerializable if its uses are135  // also live at the indices it will be rematerialized at.136  for (MachineOperand &MO : MRI.reg_nodbg_operands(LI.reg())) {137    if (!MO.readsReg())138      continue;139    SlotIndex UseIdx = LIS.getInstructionIndex(*MO.getParent());140    MachineInstr *Def = VNIDefs[LI.getVNInfoAt(UseIdx)->id];141    assert(Def && "Use with no def");142    if (!allUsesAvailableAt(Def, UseIdx, LIS, MRI, TII))143      return false;144  }145 146  return true;147}148 149bool VirtRegAuxInfo::allUsesAvailableAt(const MachineInstr *MI,150                                        SlotIndex UseIdx,151                                        const LiveIntervals &LIS,152                                        const MachineRegisterInfo &MRI,153                                        const TargetInstrInfo &TII) {154  SlotIndex OrigIdx = LIS.getInstructionIndex(*MI).getRegSlot(true);155  UseIdx = std::max(UseIdx, UseIdx.getRegSlot(true));156  for (const MachineOperand &MO : MI->operands()) {157    if (!MO.isReg() || !MO.getReg() || !MO.readsReg())158      continue;159 160    // We can't remat physreg uses, unless it is a constant or target wants161    // to ignore this use.162    if (MO.getReg().isPhysical()) {163      if (MRI.isConstantPhysReg(MO.getReg()) || TII.isIgnorableUse(MO))164        continue;165      return false;166    }167 168    const LiveInterval &li = LIS.getInterval(MO.getReg());169    const VNInfo *OVNI = li.getVNInfoAt(OrigIdx);170    if (!OVNI)171      continue;172 173    // Don't allow rematerialization immediately after the original def.174    // It would be incorrect if OrigMI redefines the register.175    // See PR14098.176    if (SlotIndex::isSameInstr(OrigIdx, UseIdx))177      return false;178 179    if (OVNI != li.getVNInfoAt(UseIdx))180      return false;181 182    // Check that subrange is live at UseIdx.183    if (li.hasSubRanges()) {184      const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();185      unsigned SubReg = MO.getSubReg();186      LaneBitmask LM = SubReg ? TRI->getSubRegIndexLaneMask(SubReg)187                              : MRI.getMaxLaneMaskForVReg(MO.getReg());188      for (const LiveInterval::SubRange &SR : li.subranges()) {189        if ((SR.LaneMask & LM).none())190          continue;191        if (!SR.liveAt(UseIdx))192          return false;193        // Early exit if all used lanes are checked. No need to continue.194        LM &= ~SR.LaneMask;195        if (LM.none())196          break;197      }198    }199  }200  return true;201}202 203bool VirtRegAuxInfo::isLiveAtStatepointVarArg(LiveInterval &LI) {204  return any_of(VRM.getRegInfo().reg_operands(LI.reg()),205                [](MachineOperand &MO) {206    MachineInstr *MI = MO.getParent();207    if (MI->getOpcode() != TargetOpcode::STATEPOINT)208      return false;209    return StatepointOpers(MI).getVarIdx() <= MO.getOperandNo();210  });211}212 213void VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &LI) {214  float Weight = weightCalcHelper(LI);215  // Check if unspillable.216  if (Weight < 0)217    return;218  LI.setWeight(Weight);219}220 221static bool canMemFoldInlineAsm(LiveInterval &LI,222                                const MachineRegisterInfo &MRI) {223  for (const MachineOperand &MO : MRI.reg_operands(LI.reg())) {224    const MachineInstr *MI = MO.getParent();225    if (MI->isInlineAsm() && MI->mayFoldInlineAsmRegOp(MI->getOperandNo(&MO)))226      return true;227  }228 229  return false;230}231 232float VirtRegAuxInfo::weightCalcHelper(LiveInterval &LI, SlotIndex *Start,233                                       SlotIndex *End) {234  MachineRegisterInfo &MRI = MF.getRegInfo();235  const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();236  const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();237  MachineBasicBlock *MBB = nullptr;238  float TotalWeight = 0;239  unsigned NumInstr = 0; // Number of instructions using LI240  SmallPtrSet<MachineInstr *, 8> Visited;241 242  std::pair<unsigned, Register> TargetHint = MRI.getRegAllocationHint(LI.reg());243 244  if (LI.isSpillable()) {245    Register Reg = LI.reg();246    Register Original = VRM.getOriginal(Reg);247    const LiveInterval &OrigInt = LIS.getInterval(Original);248    // li comes from a split of OrigInt. If OrigInt was marked249    // as not spillable, make sure the new interval is marked250    // as not spillable as well.251    if (!OrigInt.isSpillable())252      LI.markNotSpillable();253  }254 255  // Don't recompute spill weight for an unspillable register.256  bool IsSpillable = LI.isSpillable();257 258  bool IsLocalSplitArtifact = Start && End;259 260  // Do not update future local split artifacts.261  bool ShouldUpdateLI = !IsLocalSplitArtifact;262 263  if (IsLocalSplitArtifact) {264    MachineBasicBlock *LocalMBB = LIS.getMBBFromIndex(*End);265    assert(LocalMBB == LIS.getMBBFromIndex(*Start) &&266           "start and end are expected to be in the same basic block");267 268    // Local split artifact will have 2 additional copy instructions and they269    // will be in the same BB.270    // localLI = COPY other271    // ...272    // other   = COPY localLI273    TotalWeight +=274        LiveIntervals::getSpillWeight(true, false, &MBFI, LocalMBB, PSI);275    TotalWeight +=276        LiveIntervals::getSpillWeight(false, true, &MBFI, LocalMBB, PSI);277 278    NumInstr += 2;279  }280 281  // CopyHint is a sortable hint derived from a COPY instruction.282  struct CopyHint {283    Register Reg;284    float Weight;285    bool IsCSR;286    CopyHint(Register R, float W, bool IsCSR)287        : Reg(R), Weight(W), IsCSR(IsCSR) {}288    bool operator<(const CopyHint &Rhs) const {289      // Always prefer any physreg hint.290      if (Reg.isPhysical() != Rhs.Reg.isPhysical())291        return Reg.isPhysical();292      if (Weight != Rhs.Weight)293        return (Weight > Rhs.Weight);294      // Prefer non-CSR to CSR.295      if (Reg.isPhysical() && IsCSR != Rhs.IsCSR)296        return !IsCSR;297      return Reg.id() < Rhs.Reg.id(); // Tie-breaker.298    }299  };300 301  bool IsExiting = false;302  SmallDenseMap<Register, float, 8> Hint;303  for (MachineRegisterInfo::reg_instr_nodbg_iterator304           I = MRI.reg_instr_nodbg_begin(LI.reg()),305           E = MRI.reg_instr_nodbg_end();306       I != E;) {307    MachineInstr *MI = &*(I++);308 309    // For local split artifacts, we are interested only in instructions between310    // the expected start and end of the range.311    SlotIndex SI = LIS.getInstructionIndex(*MI);312    if (IsLocalSplitArtifact && ((SI < *Start) || (SI > *End)))313      continue;314 315    NumInstr++;316    bool identityCopy = false;317    auto DestSrc = TII.isCopyInstr(*MI);318    if (DestSrc) {319      const MachineOperand *DestRegOp = DestSrc->Destination;320      const MachineOperand *SrcRegOp = DestSrc->Source;321      identityCopy = DestRegOp->getReg() == SrcRegOp->getReg() &&322                     DestRegOp->getSubReg() == SrcRegOp->getSubReg();323    }324 325    if (identityCopy || MI->isImplicitDef())326      continue;327    if (!Visited.insert(MI).second)328      continue;329 330    // For terminators that produce values, ask the backend if the register is331    // not spillable.332    if (TII.isUnspillableTerminator(MI) &&333        MI->definesRegister(LI.reg(), /*TRI=*/nullptr)) {334      LI.markNotSpillable();335      return -1.0f;336    }337 338    // Force Weight onto the stack so that x86 doesn't add hidden precision.339    stack_float_t Weight = 1.0f;340    if (IsSpillable) {341      // Get loop info for mi.342      if (MI->getParent() != MBB) {343        MBB = MI->getParent();344        const MachineLoop *Loop = Loops.getLoopFor(MBB);345        IsExiting = Loop ? Loop->isLoopExiting(MBB) : false;346      }347 348      // Calculate instr weight.349      bool Reads, Writes;350      std::tie(Reads, Writes) = MI->readsWritesVirtualRegister(LI.reg());351      Weight = LiveIntervals::getSpillWeight(Writes, Reads, &MBFI, *MI, PSI);352 353      // Give extra weight to what looks like a loop induction variable update.354      if (Writes && IsExiting && LIS.isLiveOutOfMBB(LI, MBB))355        Weight *= 3;356 357      TotalWeight += Weight;358    }359 360    // Get allocation hints from copies.361    if (!TII.isCopyInstr(*MI))362      continue;363    Register HintReg = copyHint(MI, LI.reg(), TRI, MRI);364    if (HintReg && (HintReg.isVirtual() || MRI.isAllocatable(HintReg)))365      Hint[HintReg] += Weight;366  }367 368  // Pass all the sorted copy hints to mri.369  if (ShouldUpdateLI && Hint.size()) {370    // Remove a generic hint if previously added by target.371    if (TargetHint.first == 0 && TargetHint.second)372      MRI.clearSimpleHint(LI.reg());373 374    // Don't add the target-type hint again.375    Register SkipReg = TargetHint.first != 0 ? TargetHint.second : Register();376    SmallVector<CopyHint, 8> RegHints;377    for (const auto &[Reg, Weight] : Hint) {378      if (Reg != SkipReg)379        RegHints.emplace_back(380            Reg, Weight,381            Reg.isPhysical() ? TRI.isCalleeSavedPhysReg(Reg, MF) : false);382    }383    sort(RegHints);384    for (const auto &[Reg, _, __] : RegHints)385      MRI.addRegAllocationHint(LI.reg(), Reg);386 387    // Weakly boost the spill weight of hinted registers.388    TotalWeight *= 1.01F;389  }390 391  // If the live interval was already unspillable, leave it that way.392  if (!IsSpillable)393    return -1.0;394 395  // Mark li as unspillable if all live ranges are tiny and the interval396  // is not live at any reg mask.  If the interval is live at a reg mask397  // spilling may be required. If li is live as use in statepoint instruction398  // spilling may be required due to if we mark interval with use in statepoint399  // as not spillable we are risky to end up with no register to allocate.400  // At the same time STATEPOINT instruction is perfectly fine to have this401  // operand on stack, so spilling such interval and folding its load from stack402  // into instruction itself makes perfect sense.403  if (ShouldUpdateLI && LI.isZeroLength(LIS.getSlotIndexes()) &&404      !LI.isLiveAtIndexes(LIS.getRegMaskSlots()) &&405      !isLiveAtStatepointVarArg(LI) && !canMemFoldInlineAsm(LI, MRI)) {406    LI.markNotSpillable();407    return -1.0;408  }409 410  // If all of the definitions of the interval are re-materializable,411  // it is a preferred candidate for spilling.412  // FIXME: this gets much more complicated once we support non-trivial413  // re-materialization.414  if (isRematerializable(LI, LIS, VRM, MRI, *MF.getSubtarget().getInstrInfo()))415    TotalWeight *= 0.5F;416 417  // Finally, we scale the weight by the scale factor of register class.418  const TargetRegisterClass *RC = MRI.getRegClass(LI.reg());419  TotalWeight *= TRI.getSpillWeightScaleFactor(RC);420 421  if (IsLocalSplitArtifact)422    return normalize(TotalWeight, Start->distance(*End), NumInstr);423  return normalize(TotalWeight, LI.getSize(), NumInstr);424}425