13d08ade7SStephen Tozer //===---- RemoveLoadsIntoFakeUses.cpp - Remove loads with no real uses ----===// 23d08ade7SStephen Tozer // 33d08ade7SStephen Tozer // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43d08ade7SStephen Tozer // See https://llvm.org/LICENSE.txt for license information. 53d08ade7SStephen Tozer // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63d08ade7SStephen Tozer // 73d08ade7SStephen Tozer //===----------------------------------------------------------------------===// 83d08ade7SStephen Tozer /// 93d08ade7SStephen Tozer /// \file 103d08ade7SStephen Tozer /// The FAKE_USE instruction is used to preserve certain values through 113d08ade7SStephen Tozer /// optimizations for the sake of debugging. This may result in spilled values 123d08ade7SStephen Tozer /// being loaded into registers that are only used by FAKE_USEs; this is not 133d08ade7SStephen Tozer /// necessary for debugging purposes, because at that point the value must be on 143d08ade7SStephen Tozer /// the stack and hence available for debugging. Therefore, this pass removes 153d08ade7SStephen Tozer /// loads that are only used by FAKE_USEs. 163d08ade7SStephen Tozer /// 173d08ade7SStephen Tozer /// This pass should run very late, to ensure that we don't inadvertently 183d08ade7SStephen Tozer /// shorten stack lifetimes by removing these loads, since the FAKE_USEs will 193d08ade7SStephen Tozer /// also no longer be in effect. Running immediately before LiveDebugValues 203d08ade7SStephen Tozer /// ensures that LDV will have accurate information of the machine location of 213d08ade7SStephen Tozer /// debug values. 223d08ade7SStephen Tozer /// 233d08ade7SStephen Tozer //===----------------------------------------------------------------------===// 243d08ade7SStephen Tozer 253d08ade7SStephen Tozer #include "llvm/ADT/PostOrderIterator.h" 263d08ade7SStephen Tozer #include "llvm/ADT/Statistic.h" 273d08ade7SStephen Tozer #include "llvm/CodeGen/LiveRegUnits.h" 283d08ade7SStephen Tozer #include "llvm/CodeGen/MachineFunction.h" 293d08ade7SStephen Tozer #include "llvm/CodeGen/MachineFunctionPass.h" 303d08ade7SStephen Tozer #include "llvm/CodeGen/MachineRegisterInfo.h" 313d08ade7SStephen Tozer #include "llvm/CodeGen/TargetSubtargetInfo.h" 323d08ade7SStephen Tozer #include "llvm/IR/Function.h" 333d08ade7SStephen Tozer #include "llvm/InitializePasses.h" 343d08ade7SStephen Tozer #include "llvm/Support/Debug.h" 35*22687aa9SStephen Tozer #include "llvm/Target/TargetMachine.h" 363d08ade7SStephen Tozer 373d08ade7SStephen Tozer using namespace llvm; 383d08ade7SStephen Tozer 393d08ade7SStephen Tozer #define DEBUG_TYPE "remove-loads-into-fake-uses" 403d08ade7SStephen Tozer 413d08ade7SStephen Tozer STATISTIC(NumLoadsDeleted, "Number of dead load instructions deleted"); 423d08ade7SStephen Tozer STATISTIC(NumFakeUsesDeleted, "Number of FAKE_USE instructions deleted"); 433d08ade7SStephen Tozer 443d08ade7SStephen Tozer class RemoveLoadsIntoFakeUses : public MachineFunctionPass { 453d08ade7SStephen Tozer public: 463d08ade7SStephen Tozer static char ID; 473d08ade7SStephen Tozer 483d08ade7SStephen Tozer RemoveLoadsIntoFakeUses() : MachineFunctionPass(ID) { 493d08ade7SStephen Tozer initializeRemoveLoadsIntoFakeUsesPass(*PassRegistry::getPassRegistry()); 503d08ade7SStephen Tozer } 513d08ade7SStephen Tozer 523d08ade7SStephen Tozer void getAnalysisUsage(AnalysisUsage &AU) const override { 533d08ade7SStephen Tozer AU.setPreservesCFG(); 543d08ade7SStephen Tozer MachineFunctionPass::getAnalysisUsage(AU); 553d08ade7SStephen Tozer } 563d08ade7SStephen Tozer 573d08ade7SStephen Tozer MachineFunctionProperties getRequiredProperties() const override { 583d08ade7SStephen Tozer return MachineFunctionProperties().set( 593d08ade7SStephen Tozer MachineFunctionProperties::Property::NoVRegs); 603d08ade7SStephen Tozer } 613d08ade7SStephen Tozer 623d08ade7SStephen Tozer StringRef getPassName() const override { 633d08ade7SStephen Tozer return "Remove Loads Into Fake Uses"; 643d08ade7SStephen Tozer } 653d08ade7SStephen Tozer 663d08ade7SStephen Tozer bool runOnMachineFunction(MachineFunction &MF) override; 673d08ade7SStephen Tozer }; 683d08ade7SStephen Tozer 693d08ade7SStephen Tozer char RemoveLoadsIntoFakeUses::ID = 0; 703d08ade7SStephen Tozer char &llvm::RemoveLoadsIntoFakeUsesID = RemoveLoadsIntoFakeUses::ID; 713d08ade7SStephen Tozer 723d08ade7SStephen Tozer INITIALIZE_PASS_BEGIN(RemoveLoadsIntoFakeUses, DEBUG_TYPE, 733d08ade7SStephen Tozer "Remove Loads Into Fake Uses", false, false) 743d08ade7SStephen Tozer INITIALIZE_PASS_END(RemoveLoadsIntoFakeUses, DEBUG_TYPE, 753d08ade7SStephen Tozer "Remove Loads Into Fake Uses", false, false) 763d08ade7SStephen Tozer 773d08ade7SStephen Tozer bool RemoveLoadsIntoFakeUses::runOnMachineFunction(MachineFunction &MF) { 78*22687aa9SStephen Tozer // Skip this pass if we would use VarLoc-based LDV, as there may be DBG_VALUE 79*22687aa9SStephen Tozer // instructions of the restored values that would become invalid. 80*22687aa9SStephen Tozer if (!MF.useDebugInstrRef()) 81*22687aa9SStephen Tozer return false; 82d826b0c9SStephen Tozer // Only run this for functions that have fake uses. 83d826b0c9SStephen Tozer if (!MF.hasFakeUses() || skipFunction(MF.getFunction())) 843d08ade7SStephen Tozer return false; 853d08ade7SStephen Tozer 863d08ade7SStephen Tozer bool AnyChanges = false; 873d08ade7SStephen Tozer 883d08ade7SStephen Tozer LiveRegUnits LivePhysRegs; 893d08ade7SStephen Tozer const MachineRegisterInfo *MRI = &MF.getRegInfo(); 903d08ade7SStephen Tozer const TargetSubtargetInfo &ST = MF.getSubtarget(); 913d08ade7SStephen Tozer const TargetInstrInfo *TII = ST.getInstrInfo(); 923d08ade7SStephen Tozer const TargetRegisterInfo *TRI = ST.getRegisterInfo(); 933d08ade7SStephen Tozer 94*22687aa9SStephen Tozer SmallVector<MachineInstr *> RegFakeUses; 953d08ade7SStephen Tozer LivePhysRegs.init(*TRI); 963d08ade7SStephen Tozer SmallVector<MachineInstr *, 16> Statepoints; 973d08ade7SStephen Tozer for (MachineBasicBlock *MBB : post_order(&MF)) { 98*22687aa9SStephen Tozer RegFakeUses.clear(); 993d08ade7SStephen Tozer LivePhysRegs.addLiveOuts(*MBB); 1003d08ade7SStephen Tozer 1013d08ade7SStephen Tozer for (MachineInstr &MI : make_early_inc_range(reverse(*MBB))) { 1023d08ade7SStephen Tozer if (MI.isFakeUse()) { 103*22687aa9SStephen Tozer if (MI.getNumOperands() == 0 || !MI.getOperand(0).isReg()) 104*22687aa9SStephen Tozer continue; 105*22687aa9SStephen Tozer // Track the Fake Uses that use these register units so that we can 106*22687aa9SStephen Tozer // delete them if we delete the corresponding load. 107*22687aa9SStephen Tozer RegFakeUses.push_back(&MI); 1083d08ade7SStephen Tozer // Do not record FAKE_USE uses in LivePhysRegs so that we can recognize 1093d08ade7SStephen Tozer // otherwise-unused loads. 1103d08ade7SStephen Tozer continue; 1113d08ade7SStephen Tozer } 1123d08ade7SStephen Tozer 1133d08ade7SStephen Tozer // If the restore size is not std::nullopt then we are dealing with a 1143d08ade7SStephen Tozer // reload of a spilled register. 1153d08ade7SStephen Tozer if (MI.getRestoreSize(TII)) { 1163d08ade7SStephen Tozer Register Reg = MI.getOperand(0).getReg(); 1173d08ade7SStephen Tozer // Don't delete live physreg defs, or any reserved register defs. 1183d08ade7SStephen Tozer if (!LivePhysRegs.available(Reg) || MRI->isReserved(Reg)) 1193d08ade7SStephen Tozer continue; 120*22687aa9SStephen Tozer // There should typically be an exact match between the loaded register 121*22687aa9SStephen Tozer // and the FAKE_USE, but sometimes regalloc will choose to load a larger 122*22687aa9SStephen Tozer // value than is needed. Therefore, as long as the load isn't used by 123*22687aa9SStephen Tozer // anything except at least one FAKE_USE, we will delete it. If it isn't 124*22687aa9SStephen Tozer // used by any fake uses, it should still be safe to delete but we 125*22687aa9SStephen Tozer // choose to ignore it so that this pass has no side effects unrelated 126*22687aa9SStephen Tozer // to fake uses. 127*22687aa9SStephen Tozer SmallDenseSet<MachineInstr *> FakeUsesToDelete; 128*22687aa9SStephen Tozer SmallVector<MachineInstr *> RemainingFakeUses; 129*22687aa9SStephen Tozer for (MachineInstr *&FakeUse : reverse(RegFakeUses)) { 130*22687aa9SStephen Tozer if (FakeUse->readsRegister(Reg, TRI)) { 131*22687aa9SStephen Tozer FakeUsesToDelete.insert(FakeUse); 132*22687aa9SStephen Tozer RegFakeUses.erase(&FakeUse); 133*22687aa9SStephen Tozer } 134*22687aa9SStephen Tozer } 135*22687aa9SStephen Tozer if (!FakeUsesToDelete.empty()) { 1363d08ade7SStephen Tozer LLVM_DEBUG(dbgs() << "RemoveLoadsIntoFakeUses: DELETING: " << MI); 137*22687aa9SStephen Tozer // Since this load only exists to restore a spilled register and we 138*22687aa9SStephen Tozer // haven't, run LiveDebugValues yet, there shouldn't be any DBG_VALUEs 139*22687aa9SStephen Tozer // for this load; otherwise, deleting this would be incorrect. 1403d08ade7SStephen Tozer MI.eraseFromParent(); 1413d08ade7SStephen Tozer AnyChanges = true; 1423d08ade7SStephen Tozer ++NumLoadsDeleted; 143*22687aa9SStephen Tozer for (MachineInstr *FakeUse : FakeUsesToDelete) { 1443d08ade7SStephen Tozer LLVM_DEBUG(dbgs() 1453d08ade7SStephen Tozer << "RemoveLoadsIntoFakeUses: DELETING: " << *FakeUse); 1463d08ade7SStephen Tozer FakeUse->eraseFromParent(); 1473d08ade7SStephen Tozer } 148*22687aa9SStephen Tozer NumFakeUsesDeleted += FakeUsesToDelete.size(); 1493d08ade7SStephen Tozer } 1503d08ade7SStephen Tozer continue; 1513d08ade7SStephen Tozer } 1523d08ade7SStephen Tozer 1533d08ade7SStephen Tozer // In addition to tracking LivePhysRegs, we need to clear RegFakeUses each 1543d08ade7SStephen Tozer // time a register is defined, as existing FAKE_USEs no longer apply to 1553d08ade7SStephen Tozer // that register. 1563d08ade7SStephen Tozer if (!RegFakeUses.empty()) { 1573d08ade7SStephen Tozer for (const MachineOperand &MO : MI.operands()) { 158*22687aa9SStephen Tozer if (!MO.isReg()) 159*22687aa9SStephen Tozer continue; 1603d08ade7SStephen Tozer Register Reg = MO.getReg(); 161*22687aa9SStephen Tozer // We clear RegFakeUses for this register and all subregisters, 162*22687aa9SStephen Tozer // because any such FAKE_USE encountered prior is no longer relevant 163*22687aa9SStephen Tozer // for later encountered loads. 164*22687aa9SStephen Tozer for (MachineInstr *&FakeUse : reverse(RegFakeUses)) 165*22687aa9SStephen Tozer if (FakeUse->readsRegister(Reg, TRI)) 166*22687aa9SStephen Tozer RegFakeUses.erase(&FakeUse); 1673d08ade7SStephen Tozer } 1683d08ade7SStephen Tozer } 1693d08ade7SStephen Tozer LivePhysRegs.stepBackward(MI); 1703d08ade7SStephen Tozer } 1713d08ade7SStephen Tozer } 1723d08ade7SStephen Tozer 1733d08ade7SStephen Tozer return AnyChanges; 1743d08ade7SStephen Tozer } 175