//===---------------------- ProcessImplicitDefs.cpp -----------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/ProcessImplicitDefs.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

#define DEBUG_TYPE "process-implicit-defs"

namespace {
/// Process IMPLICIT_DEF instructions and make sure there is one implicit_def
/// for each use. Add isUndef marker to implicit_def defs and their uses.
class ProcessImplicitDefsLegacy : public MachineFunctionPass {
public:
  static char ID;

  ProcessImplicitDefsLegacy() : MachineFunctionPass(ID) {}

  void getAnalysisUsage(AnalysisUsage &AU) const override;

  bool runOnMachineFunction(MachineFunction &MF) override;

  MachineFunctionProperties getRequiredProperties() const override {
    return MachineFunctionProperties().setIsSSA();
  }
};

class ProcessImplicitDefs {
  const TargetInstrInfo *TII = nullptr;
  const TargetRegisterInfo *TRI = nullptr;
  MachineRegisterInfo *MRI = nullptr;

  SmallSetVector<MachineInstr *, 16> WorkList;

  void processImplicitDef(MachineInstr *MI);
  bool canTurnIntoImplicitDef(MachineInstr *MI);

public:
  bool run(MachineFunction &MF);
};
} // end anonymous namespace

char ProcessImplicitDefsLegacy::ID = 0;
char &llvm::ProcessImplicitDefsID = ProcessImplicitDefsLegacy::ID;

INITIALIZE_PASS(ProcessImplicitDefsLegacy, DEBUG_TYPE,
                "Process Implicit Definitions", false, false)

void ProcessImplicitDefsLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesCFG();
  AU.addPreserved<AAResultsWrapperPass>();
  MachineFunctionPass::getAnalysisUsage(AU);
}

bool ProcessImplicitDefs::canTurnIntoImplicitDef(MachineInstr *MI) {
  if (!MI->isCopyLike() &&
      !MI->isInsertSubreg() &&
      !MI->isRegSequence() &&
      !MI->isPHI())
    return false;
  for (const MachineOperand &MO : MI->all_uses())
    if (MO.readsReg())
      return false;
  return true;
}

void ProcessImplicitDefs::processImplicitDef(MachineInstr *MI) {
  LLVM_DEBUG(dbgs() << "Processing " << *MI);
  Register Reg = MI->getOperand(0).getReg();
  // Trim any extra operands.
  for (unsigned i = MI->getNumOperands() - 1; i; --i)
    MI->removeOperand(i);

  MachineBasicBlock *MBB = MI->getParent();

  if (Reg.isVirtual()) {
    // For virtual registers, mark all uses as <undef>, and convert users to
    // implicit-def when possible.
    bool AllUsesUndef = true;
    for (MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
      MachineInstr *UserMI = MO.getParent();
      if (UserMI->hasTiedAndOtherReadOf(Reg, MO.getSubReg())) {
        AllUsesUndef = false;
        continue;
      }
      MO.setIsUndef();
      if (!canTurnIntoImplicitDef(UserMI))
        continue;
      LLVM_DEBUG(dbgs() << "Converting to IMPLICIT_DEF: " << *UserMI);
      UserMI->setDesc(TII->get(TargetOpcode::IMPLICIT_DEF));
      WorkList.insert(UserMI);
    }
    if (AllUsesUndef) {
      MI->eraseFromParent();
      return;
    }
    // A kept PHI, now an IMPLICIT_DEF, leaves the PHI block.
    MachineBasicBlock::iterator Next = std::next(MI->getIterator());
    if (Next != MBB->end() && Next->isPHI())
      MBB->splice(MBB->SkipPHIsAndLabels(Next), MBB, MI);
    return;
  }

  // This is a physreg implicit-def.
  // Try to add undef flag to all uses.  If all uses are updated remove
  // implicit-def.
  MachineBasicBlock::instr_iterator SearchMI = MI->getIterator();
  MachineBasicBlock::instr_iterator SearchE = MBB->instr_end();
  bool ImplicitDefIsDead = false;
  bool SearchedWholeBlock = true;
  constexpr unsigned SearchLimit = 35;
  unsigned Count = 0;
  for (++SearchMI; SearchMI != SearchE; ++SearchMI) {
    if (SearchMI->isDebugInstr())
      continue;
    if (++Count > SearchLimit) {
      SearchedWholeBlock = false;
      break;
    }
    for (MachineOperand &MO : SearchMI->operands()) {
      if (!MO.isReg())
        continue;
      Register SearchReg = MO.getReg();
      if (!SearchReg.isPhysical() || !TRI->regsOverlap(Reg, SearchReg))
        continue;
      // SearchMI uses or redefines Reg. Set <undef> flags on all uses.
      if (MO.isUse()) {
        if (TRI->isSubRegisterEq(Reg, SearchReg)) {
          MO.setIsUndef();
        } else {
          // Use is larger than Reg.  It is not safe to add undef to this use.
          return;
        }
      }
      if (MO.isDef()) {
        if (TRI->isSubRegisterEq(SearchReg, Reg)) {
          ImplicitDefIsDead = true;
        } else {
          // Reg is larger than definition.  It is not safe to add undef to any
          // subsequent uses of Reg.
          return;
        }
      }
    }
    if (ImplicitDefIsDead) {
      LLVM_DEBUG(dbgs() << "Physreg redefine: " << *SearchMI);
      break;
    }
  }

  // If we have added an undef flag to all uses (i.e. we have found a redefining
  // MI or there are no successors), we can erase the IMPLICIT_DEF.
  if (ImplicitDefIsDead || (SearchedWholeBlock && MBB->succ_empty())) {
    LLVM_DEBUG(dbgs() << "Deleting implicit-def: " << *MI);
    MI->eraseFromParent();
    return;
  }

  if (SearchedWholeBlock && MRI->tracksLiveness() && !MRI->isReserved(Reg) &&
      none_of(MBB->successors(), [&](MachineBasicBlock *Succ) {
        return Succ->isLiveInOverlappedWith(Reg, *TRI);
      }))
    MI->eraseFromParent();
}

bool ProcessImplicitDefsLegacy::runOnMachineFunction(MachineFunction &MF) {
  return ProcessImplicitDefs().run(MF);
}

PreservedAnalyses
ProcessImplicitDefsPass::run(MachineFunction &MF,
                             MachineFunctionAnalysisManager &MFAM) {
  if (!ProcessImplicitDefs().run(MF))
    return PreservedAnalyses::all();

  return getMachineFunctionPassPreservedAnalyses()
      .preserveSet<CFGAnalyses>()
      .preserve<AAManager>();
}

/// processImplicitDefs - Process IMPLICIT_DEF instructions and turn them into
/// <undef> operands.
bool ProcessImplicitDefs::run(MachineFunction &MF) {

  LLVM_DEBUG(dbgs() << "********** PROCESS IMPLICIT DEFS **********\n"
                    << "********** Function: " << MF.getName() << '\n');

  bool Changed = false;

  TII = MF.getSubtarget().getInstrInfo();
  TRI = MF.getSubtarget().getRegisterInfo();
  MRI = &MF.getRegInfo();
  assert(WorkList.empty() && "Inconsistent worklist state");

  for (MachineBasicBlock &MBB : MF) {
    // Scan the basic block for implicit defs.
    for (MachineInstr &MI : MBB)
      if (MI.isImplicitDef())
        WorkList.insert(&MI);

    if (WorkList.empty())
      continue;

    LLVM_DEBUG(dbgs() << printMBBReference(MBB) << " has " << WorkList.size()
                      << " implicit defs.\n");
    Changed = true;

    // Drain the WorkList to recursively process any new implicit defs.
    do processImplicitDef(WorkList.pop_back_val());
    while (!WorkList.empty());
  }
  return Changed;
}
