xref: /llvm-project/llvm/lib/CodeGen/RemoveLoadsIntoFakeUses.cpp (revision 22687aa97bdae2f0ea0be9baf208247c18d69c06)
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