brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.5 KiB · ea0ea02 Raw
199 lines · cpp
1//===---- RemoveLoadsIntoFakeUses.cpp - Remove loads with no real uses ----===//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/// \file10/// The FAKE_USE instruction is used to preserve certain values through11/// optimizations for the sake of debugging. This may result in spilled values12/// being loaded into registers that are only used by FAKE_USEs; this is not13/// necessary for debugging purposes, because at that point the value must be on14/// the stack and hence available for debugging. Therefore, this pass removes15/// loads that are only used by FAKE_USEs.16///17/// This pass should run very late, to ensure that we don't inadvertently18/// shorten stack lifetimes by removing these loads, since the FAKE_USEs will19/// also no longer be in effect. Running immediately before LiveDebugValues20/// ensures that LDV will have accurate information of the machine location of21/// debug values.22///23//===----------------------------------------------------------------------===//24 25#include "llvm/CodeGen/RemoveLoadsIntoFakeUses.h"26#include "llvm/ADT/PostOrderIterator.h"27#include "llvm/ADT/Statistic.h"28#include "llvm/CodeGen/LiveRegUnits.h"29#include "llvm/CodeGen/MachineFunction.h"30#include "llvm/CodeGen/MachineFunctionPass.h"31#include "llvm/CodeGen/MachinePassManager.h"32#include "llvm/CodeGen/MachineRegisterInfo.h"33#include "llvm/CodeGen/TargetSubtargetInfo.h"34#include "llvm/IR/Function.h"35#include "llvm/InitializePasses.h"36#include "llvm/Support/Debug.h"37#include "llvm/Target/TargetMachine.h"38 39using namespace llvm;40 41#define DEBUG_TYPE "remove-loads-into-fake-uses"42 43STATISTIC(NumLoadsDeleted, "Number of dead load instructions deleted");44STATISTIC(NumFakeUsesDeleted, "Number of FAKE_USE instructions deleted");45 46class RemoveLoadsIntoFakeUsesLegacy : public MachineFunctionPass {47public:48  static char ID;49 50  RemoveLoadsIntoFakeUsesLegacy() : MachineFunctionPass(ID) {51    initializeRemoveLoadsIntoFakeUsesLegacyPass(52        *PassRegistry::getPassRegistry());53  }54 55  void getAnalysisUsage(AnalysisUsage &AU) const override {56    AU.setPreservesCFG();57    MachineFunctionPass::getAnalysisUsage(AU);58  }59 60  MachineFunctionProperties getRequiredProperties() const override {61    return MachineFunctionProperties().setNoVRegs();62  }63 64  StringRef getPassName() const override {65    return "Remove Loads Into Fake Uses";66  }67 68  bool runOnMachineFunction(MachineFunction &MF) override;69};70 71struct RemoveLoadsIntoFakeUses {72  bool run(MachineFunction &MF);73};74 75char RemoveLoadsIntoFakeUsesLegacy::ID = 0;76char &llvm::RemoveLoadsIntoFakeUsesID = RemoveLoadsIntoFakeUsesLegacy::ID;77 78INITIALIZE_PASS_BEGIN(RemoveLoadsIntoFakeUsesLegacy, DEBUG_TYPE,79                      "Remove Loads Into Fake Uses", false, false)80INITIALIZE_PASS_END(RemoveLoadsIntoFakeUsesLegacy, DEBUG_TYPE,81                    "Remove Loads Into Fake Uses", false, false)82 83bool RemoveLoadsIntoFakeUsesLegacy::runOnMachineFunction(MachineFunction &MF) {84  if (skipFunction(MF.getFunction()))85    return false;86 87  return RemoveLoadsIntoFakeUses().run(MF);88}89 90PreservedAnalyses91RemoveLoadsIntoFakeUsesPass::run(MachineFunction &MF,92                                 MachineFunctionAnalysisManager &MFAM) {93  MFPropsModifier _(*this, MF);94 95  if (!RemoveLoadsIntoFakeUses().run(MF))96    return PreservedAnalyses::all();97 98  auto PA = getMachineFunctionPassPreservedAnalyses();99  PA.preserveSet<CFGAnalyses>();100  return PA;101}102 103bool RemoveLoadsIntoFakeUses::run(MachineFunction &MF) {104  // Skip this pass if we would use VarLoc-based LDV, as there may be DBG_VALUE105  // instructions of the restored values that would become invalid.106  if (!MF.useDebugInstrRef())107    return false;108  // Only run this for functions that have fake uses.109  if (!MF.hasFakeUses())110    return false;111 112  bool AnyChanges = false;113 114  LiveRegUnits LivePhysRegs;115  const MachineRegisterInfo *MRI = &MF.getRegInfo();116  const TargetSubtargetInfo &ST = MF.getSubtarget();117  const TargetInstrInfo *TII = ST.getInstrInfo();118  const TargetRegisterInfo *TRI = ST.getRegisterInfo();119 120  SmallVector<MachineInstr *> RegFakeUses;121  LivePhysRegs.init(*TRI);122  for (MachineBasicBlock *MBB : post_order(&MF)) {123    RegFakeUses.clear();124    LivePhysRegs.addLiveOuts(*MBB);125 126    for (MachineInstr &MI : make_early_inc_range(reverse(*MBB))) {127      if (MI.isFakeUse()) {128        if (MI.getNumOperands() == 0 || !MI.getOperand(0).isReg())129          continue;130        // Track the Fake Uses that use these register units so that we can131        // delete them if we delete the corresponding load.132        RegFakeUses.push_back(&MI);133        // Do not record FAKE_USE uses in LivePhysRegs so that we can recognize134        // otherwise-unused loads.135        continue;136      }137 138      // If the restore size is not std::nullopt then we are dealing with a139      // reload of a spilled register.140      if (MI.getRestoreSize(TII)) {141        Register Reg = MI.getOperand(0).getReg();142        // Don't delete live physreg defs, or any reserved register defs.143        if (!LivePhysRegs.available(Reg) || MRI->isReserved(Reg))144          continue;145        // There should typically be an exact match between the loaded register146        // and the FAKE_USE, but sometimes regalloc will choose to load a larger147        // value than is needed. Therefore, as long as the load isn't used by148        // anything except at least one FAKE_USE, we will delete it. If it isn't149        // used by any fake uses, it should still be safe to delete but we150        // choose to ignore it so that this pass has no side effects unrelated151        // to fake uses.152        SmallDenseSet<MachineInstr *> FakeUsesToDelete;153        for (MachineInstr *&FakeUse : reverse(RegFakeUses)) {154          if (FakeUse->readsRegister(Reg, TRI)) {155            FakeUsesToDelete.insert(FakeUse);156            RegFakeUses.erase(&FakeUse);157          }158        }159        if (!FakeUsesToDelete.empty()) {160          LLVM_DEBUG(dbgs() << "RemoveLoadsIntoFakeUses: DELETING: " << MI);161          // Since this load only exists to restore a spilled register and we162          // haven't, run LiveDebugValues yet, there shouldn't be any DBG_VALUEs163          // for this load; otherwise, deleting this would be incorrect.164          MI.eraseFromParent();165          AnyChanges = true;166          ++NumLoadsDeleted;167          for (MachineInstr *FakeUse : FakeUsesToDelete) {168            LLVM_DEBUG(dbgs()169                       << "RemoveLoadsIntoFakeUses: DELETING: " << *FakeUse);170            FakeUse->eraseFromParent();171          }172          NumFakeUsesDeleted += FakeUsesToDelete.size();173        }174        continue;175      }176 177      // In addition to tracking LivePhysRegs, we need to clear RegFakeUses each178      // time a register is defined, as existing FAKE_USEs no longer apply to179      // that register.180      if (!RegFakeUses.empty()) {181        for (const MachineOperand &MO : MI.operands()) {182          if (!MO.isReg())183            continue;184          Register Reg = MO.getReg();185          // We clear RegFakeUses for this register and all subregisters,186          // because any such FAKE_USE encountered prior is no longer relevant187          // for later encountered loads.188          for (MachineInstr *&FakeUse : reverse(RegFakeUses))189            if (FakeUse->readsRegister(Reg, TRI))190              RegFakeUses.erase(&FakeUse);191        }192      }193      LivePhysRegs.stepBackward(MI);194    }195  }196 197  return AnyChanges;198}199