//===- ReduceRegisterDefs.cpp - Specialized Delta Pass --------------------===// // // 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 // //===----------------------------------------------------------------------===// // // This file implements a function which calls the Generic Delta pass in order // to reduce uninteresting register uses from the MachineFunction. // //===----------------------------------------------------------------------===// #include "ReduceRegisterDefs.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetInstrInfo.h" using namespace llvm; static void removeDefsFromFunction(Oracle &O, MachineFunction &MF) { MachineRegisterInfo &MRI = MF.getRegInfo(); const TargetSubtargetInfo &STI = MF.getSubtarget(); const TargetInstrInfo *TII = STI.getInstrInfo(); DenseSet KeepDefs; DenseSet DeleteDefs; for (MachineBasicBlock &MBB : MF) { for (MachineBasicBlock::iterator It = MBB.begin(), E = MBB.getFirstTerminator(); It != E;) { MachineBasicBlock::iterator InsPt = It; MachineInstr &MI = *It; ++It; KeepDefs.clear(); DeleteDefs.clear(); int NumOperands = MI.getNumOperands(); int NumRequiredOps = MI.getNumExplicitOperands() + MI.getDesc().implicit_defs().size() + MI.getDesc().implicit_uses().size(); bool HaveDelete = false; // Do an initial scan in case the instruction defines the same register // multiple times. for (int I = NumOperands - 1; I >= 0; --I) { MachineOperand &MO = MI.getOperand(I); if (!MO.isReg() || !MO.isDef()) continue; TargetInstrInfo::RegSubRegPair RegPair(MO.getReg(), MO.getSubReg()); if (!RegPair.Reg.isVirtual()) continue; if (O.shouldKeep()) KeepDefs.insert(&MO); else HaveDelete = true; } if (!HaveDelete) continue; bool HaveKeptDef = !KeepDefs.empty(); for (int I = NumOperands - 1; I >= 0; --I) { MachineOperand &MO = MI.getOperand(I); if (!MO.isReg() || !MO.isDef()) continue; if (KeepDefs.count(&MO)) continue; TargetInstrInfo::RegSubRegPair RegPair(MO.getReg(), MO.getSubReg()); if (!RegPair.Reg.isVirtual()) continue; if (!DeleteDefs.insert(RegPair).second) continue; if (MRI.use_empty(RegPair.Reg)) { if (I >= NumRequiredOps) { // Delete implicit def operands that aren't part of the instruction // definition MI.removeOperand(I); } continue; } // If we aren't going to delete the instruction, replace it with a dead // def. if (HaveKeptDef) MO.setReg(MRI.cloneVirtualRegister(MO.getReg())); bool IsGeneric = MRI.getRegClassOrNull(RegPair.Reg) == nullptr; unsigned ImpDef = IsGeneric ? TargetOpcode::G_IMPLICIT_DEF : TargetOpcode::IMPLICIT_DEF; unsigned OpFlags = getRegState(MO) & ~RegState::Implicit; InsPt = BuildMI(MBB, InsPt, DebugLoc(), TII->get(ImpDef)) .addReg(RegPair.Reg, OpFlags, RegPair.SubReg); } if (!HaveKeptDef) MI.eraseFromParent(); } } } static void removeDefsFromModule(Oracle &O, ReducerWorkItem &WorkItem) { for (const Function &F : WorkItem.getModule()) { if (auto *MF = WorkItem.MMI->getMachineFunction(F)) removeDefsFromFunction(O, *MF); } } void llvm::reduceRegisterDefsMIRDeltaPass(TestRunner &Test) { runDeltaPass(Test, removeDefsFromModule, "Reducing register defs"); }