brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.9 KiB · 37a9e62 Raw
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