189 lines · cpp
1//===---------------------- ProcessImplicitDefs.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/ProcessImplicitDefs.h"10#include "llvm/ADT/SetVector.h"11#include "llvm/Analysis/AliasAnalysis.h"12#include "llvm/CodeGen/MachineFunctionPass.h"13#include "llvm/CodeGen/MachineInstr.h"14#include "llvm/CodeGen/MachineRegisterInfo.h"15#include "llvm/CodeGen/TargetInstrInfo.h"16#include "llvm/CodeGen/TargetSubtargetInfo.h"17#include "llvm/InitializePasses.h"18#include "llvm/Pass.h"19#include "llvm/PassRegistry.h"20#include "llvm/Support/Debug.h"21#include "llvm/Support/raw_ostream.h"22 23using namespace llvm;24 25#define DEBUG_TYPE "processimpdefs"26 27namespace {28/// Process IMPLICIT_DEF instructions and make sure there is one implicit_def29/// for each use. Add isUndef marker to implicit_def defs and their uses.30class ProcessImplicitDefsLegacy : public MachineFunctionPass {31public:32 static char ID;33 34 ProcessImplicitDefsLegacy() : MachineFunctionPass(ID) {35 initializeProcessImplicitDefsLegacyPass(*PassRegistry::getPassRegistry());36 }37 38 void getAnalysisUsage(AnalysisUsage &AU) const override;39 40 bool runOnMachineFunction(MachineFunction &MF) override;41 42 MachineFunctionProperties getRequiredProperties() const override {43 return MachineFunctionProperties().setIsSSA();44 }45};46 47class ProcessImplicitDefs {48 const TargetInstrInfo *TII = nullptr;49 const TargetRegisterInfo *TRI = nullptr;50 MachineRegisterInfo *MRI = nullptr;51 52 SmallSetVector<MachineInstr *, 16> WorkList;53 54 void processImplicitDef(MachineInstr *MI);55 bool canTurnIntoImplicitDef(MachineInstr *MI);56 57public:58 bool run(MachineFunction &MF);59};60} // end anonymous namespace61 62char ProcessImplicitDefsLegacy::ID = 0;63char &llvm::ProcessImplicitDefsID = ProcessImplicitDefsLegacy::ID;64 65INITIALIZE_PASS(ProcessImplicitDefsLegacy, DEBUG_TYPE,66 "Process Implicit Definitions", false, false)67 68void ProcessImplicitDefsLegacy::getAnalysisUsage(AnalysisUsage &AU) const {69 AU.setPreservesCFG();70 AU.addPreserved<AAResultsWrapperPass>();71 MachineFunctionPass::getAnalysisUsage(AU);72}73 74bool ProcessImplicitDefs::canTurnIntoImplicitDef(MachineInstr *MI) {75 if (!MI->isCopyLike() &&76 !MI->isInsertSubreg() &&77 !MI->isRegSequence() &&78 !MI->isPHI())79 return false;80 for (const MachineOperand &MO : MI->all_uses())81 if (MO.readsReg())82 return false;83 return true;84}85 86void ProcessImplicitDefs::processImplicitDef(MachineInstr *MI) {87 LLVM_DEBUG(dbgs() << "Processing " << *MI);88 Register Reg = MI->getOperand(0).getReg();89 90 if (Reg.isVirtual()) {91 // For virtual registers, mark all uses as <undef>, and convert users to92 // implicit-def when possible.93 for (MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {94 MO.setIsUndef();95 MachineInstr *UserMI = MO.getParent();96 if (!canTurnIntoImplicitDef(UserMI))97 continue;98 LLVM_DEBUG(dbgs() << "Converting to IMPLICIT_DEF: " << *UserMI);99 UserMI->setDesc(TII->get(TargetOpcode::IMPLICIT_DEF));100 WorkList.insert(UserMI);101 }102 MI->eraseFromParent();103 return;104 }105 106 // This is a physreg implicit-def.107 // Look for the first instruction to use or define an alias.108 MachineBasicBlock::instr_iterator UserMI = MI->getIterator();109 MachineBasicBlock::instr_iterator UserE = MI->getParent()->instr_end();110 bool Found = false;111 for (++UserMI; UserMI != UserE; ++UserMI) {112 for (MachineOperand &MO : UserMI->operands()) {113 if (!MO.isReg())114 continue;115 Register UserReg = MO.getReg();116 if (!UserReg.isPhysical() || !TRI->regsOverlap(Reg, UserReg))117 continue;118 // UserMI uses or redefines Reg. Set <undef> flags on all uses.119 Found = true;120 if (MO.isUse())121 MO.setIsUndef();122 }123 if (Found)124 break;125 }126 127 // If we found the using MI, we can erase the IMPLICIT_DEF.128 if (Found) {129 LLVM_DEBUG(dbgs() << "Physreg user: " << *UserMI);130 MI->eraseFromParent();131 return;132 }133 134 // Using instr wasn't found, it could be in another block.135 // Leave the physreg IMPLICIT_DEF, but trim any extra operands.136 for (unsigned i = MI->getNumOperands() - 1; i; --i)137 MI->removeOperand(i);138 LLVM_DEBUG(dbgs() << "Keeping physreg: " << *MI);139}140 141bool ProcessImplicitDefsLegacy::runOnMachineFunction(MachineFunction &MF) {142 return ProcessImplicitDefs().run(MF);143}144 145PreservedAnalyses146ProcessImplicitDefsPass::run(MachineFunction &MF,147 MachineFunctionAnalysisManager &MFAM) {148 if (!ProcessImplicitDefs().run(MF))149 return PreservedAnalyses::all();150 151 return getMachineFunctionPassPreservedAnalyses()152 .preserveSet<CFGAnalyses>()153 .preserve<AAManager>();154}155 156/// processImplicitDefs - Process IMPLICIT_DEF instructions and turn them into157/// <undef> operands.158bool ProcessImplicitDefs::run(MachineFunction &MF) {159 160 LLVM_DEBUG(dbgs() << "********** PROCESS IMPLICIT DEFS **********\n"161 << "********** Function: " << MF.getName() << '\n');162 163 bool Changed = false;164 165 TII = MF.getSubtarget().getInstrInfo();166 TRI = MF.getSubtarget().getRegisterInfo();167 MRI = &MF.getRegInfo();168 assert(WorkList.empty() && "Inconsistent worklist state");169 170 for (MachineBasicBlock &MBB : MF) {171 // Scan the basic block for implicit defs.172 for (MachineInstr &MI : MBB)173 if (MI.isImplicitDef())174 WorkList.insert(&MI);175 176 if (WorkList.empty())177 continue;178 179 LLVM_DEBUG(dbgs() << printMBBReference(MBB) << " has " << WorkList.size()180 << " implicit defs.\n");181 Changed = true;182 183 // Drain the WorkList to recursively process any new implicit defs.184 do processImplicitDef(WorkList.pop_back_val());185 while (!WorkList.empty());186 }187 return Changed;188}189