//===-- RISCVMoveMerger.cpp - RISC-V move merge 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 contains a pass that performs move related peephole optimizations
// as Zcmp has specified. This pass should be run after register allocation.
//
// This pass also supports Xqccmp, which has identical instructions.
//
//===----------------------------------------------------------------------===//

#include "RISCVInstrInfo.h"
#include "RISCVSubtarget.h"

using namespace llvm;

#define RISCV_MOVE_MERGE_NAME "RISC-V Zcmp move merging pass"

namespace {
struct RISCVMoveMerge : public MachineFunctionPass {
  static char ID;

  RISCVMoveMerge() : MachineFunctionPass(ID) {}

  const RISCVSubtarget *ST;
  const RISCVInstrInfo *TII;
  const TargetRegisterInfo *TRI;

  // Track which register units have been modified and used.
  LiveRegUnits ModifiedRegUnits, UsedRegUnits;

  bool isGPRPairCopyCandidate(const DestSourcePair &RegPair, bool EvenRegPair);

  bool isCandidateToMergeMVA01S(const DestSourcePair &RegPair);
  bool isCandidateToMergeMVSA01(const DestSourcePair &RegPair);

  bool isPLIPairCandidate(const MachineInstr &MI, bool EvenRegPair);

  // Merge the two instructions indicated into a single pair instruction.
  MachineBasicBlock::iterator
  mergeGPRPairInsns(MachineBasicBlock::iterator I,
                    MachineBasicBlock::iterator Paired, bool RegPairIsEven);
  MachineBasicBlock::iterator
  mergePairedInsns(MachineBasicBlock::iterator I,
                   MachineBasicBlock::iterator Paired, bool MoveFromSToA);
  MachineBasicBlock::iterator mergePLIPair(MachineBasicBlock::iterator I,
                                           MachineBasicBlock::iterator Paired,
                                           bool RegPairIsEven);

  MachineBasicBlock::iterator
  findMatchingGPRPairCopy(MachineBasicBlock::iterator &MBBI, bool EvenRegPair,
                          const DestSourcePair &RegPair);
  // Look for C.MV instruction that can be combined with
  // the given instruction into CM.MVA01S or CM.MVSA01. Return the matching
  // instruction if one exists.
  MachineBasicBlock::iterator
  findMatchingSACopy(MachineBasicBlock::iterator &MBBI, bool MoveFromSToA,
                     const DestSourcePair &RegPair);
  MachineBasicBlock::iterator findMatchingPLI(MachineBasicBlock::iterator &MBBI,
                                              bool EvenRegPair);
  bool mergeMovePairs(MachineBasicBlock &MBB);
  bool runOnMachineFunction(MachineFunction &Fn) override;

  StringRef getPassName() const override { return RISCV_MOVE_MERGE_NAME; }
};

char RISCVMoveMerge::ID = 0;

} // end of anonymous namespace

INITIALIZE_PASS(RISCVMoveMerge, "riscv-move-merge", RISCV_MOVE_MERGE_NAME,
                false, false)

static unsigned getCM_MVOpcode(const RISCVSubtarget &ST, bool MoveFromSToA) {
  if (ST.hasStdExtZcmp())
    return MoveFromSToA ? RISCV::CM_MVA01S : RISCV::CM_MVSA01;

  if (ST.hasVendorXqccmp())
    return MoveFromSToA ? RISCV::QC_CM_MVA01S : RISCV::QC_CM_MVSA01;

  llvm_unreachable("Unhandled subtarget with paired move.");
}

// Returns 0 if Opc has no paired form.
static unsigned getPairedPLIOpcode(unsigned Opc) {
  switch (Opc) {
  case RISCV::PLI_B:
    return RISCV::PLI_DB;
  case RISCV::PLI_H:
    return RISCV::PLI_DH;
  case RISCV::PLUI_H:
    return RISCV::PLUI_DH;
  default:
    return 0;
  }
}

bool RISCVMoveMerge::isGPRPairCopyCandidate(const DestSourcePair &RegPair,
                                            bool EvenRegPair) {
  Register Destination = RegPair.Destination->getReg();
  Register Source = RegPair.Source->getReg();

  if (Source == Destination)
    return false;

  if ((!ST->hasStdExtZdinx() && !ST->hasStdExtP()) || ST->is64Bit())
    return false;

  unsigned SubIdx = EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;

  Register SrcPair =
      TRI->getMatchingSuperReg(Source, SubIdx, &RISCV::GPRPairRegClass);
  Register DestPair =
      TRI->getMatchingSuperReg(Destination, SubIdx, &RISCV::GPRPairRegClass);

  return SrcPair.isValid() && DestPair.isValid();
}

// Check if registers meet CM.MVA01S constraints.
bool RISCVMoveMerge::isCandidateToMergeMVA01S(const DestSourcePair &RegPair) {
  Register Destination = RegPair.Destination->getReg();
  Register Source = RegPair.Source->getReg();
  // If destination is not a0 or a1.
  if ((ST->hasStdExtZcmp() || ST->hasVendorXqccmp()) &&
      (Destination == RISCV::X10 || Destination == RISCV::X11) &&
      RISCV::GPRS07RegClass.contains(Source))
    return true;
  return false;
}

// Check if registers meet CM.MVSA01 constraints.
bool RISCVMoveMerge::isCandidateToMergeMVSA01(const DestSourcePair &RegPair) {
  Register Destination = RegPair.Destination->getReg();
  Register Source = RegPair.Source->getReg();
  // If Source is s0 - s7.
  if ((ST->hasStdExtZcmp() || ST->hasVendorXqccmp()) &&
      (Source == RISCV::X10 || Source == RISCV::X11) &&
      RISCV::GPRS07RegClass.contains(Destination))
    return true;
  return false;
}

// Check if MI is a single-reg pli/plui whose destination is a half of a
// GPRPair.
bool RISCVMoveMerge::isPLIPairCandidate(const MachineInstr &MI,
                                        bool EvenRegPair) {
  if (!ST->hasStdExtP() || ST->is64Bit())
    return false;
  if (!getPairedPLIOpcode(MI.getOpcode()))
    return false;
  unsigned SubIdx = EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
  return TRI
      ->getMatchingSuperReg(MI.getOperand(0).getReg(), SubIdx,
                            &RISCV::GPRPairRegClass)
      .isValid();
}

MachineBasicBlock::iterator
RISCVMoveMerge::mergeGPRPairInsns(MachineBasicBlock::iterator I,
                                  MachineBasicBlock::iterator Paired,
                                  bool RegPairIsEven) {
  MachineBasicBlock::iterator E = I->getParent()->end();
  MachineBasicBlock::iterator NextI = next_nodbg(I, E);
  DestSourcePair FirstPair = *TII->isCopyInstrImpl(*I);
  DestSourcePair SecondPair = *TII->isCopyInstrImpl(*Paired);

  if (NextI == Paired)
    NextI = next_nodbg(NextI, E);
  DebugLoc DL = I->getDebugLoc();

  // Make a copy of the second instruction to update the kill
  // flag.
  MachineOperand PairedSource = *SecondPair.Source;

  for (auto It = std::next(I); It != Paired && PairedSource.isKill(); ++It)
    if (It->readsRegister(PairedSource.getReg(), TRI))
      PairedSource.setIsKill(false);

  unsigned GPRPairIdx =
      RegPairIsEven ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
  MCRegister SrcReg = TRI->getMatchingSuperReg(
      FirstPair.Source->getReg(), GPRPairIdx, &RISCV::GPRPairRegClass);
  MCRegister DestReg = TRI->getMatchingSuperReg(
      FirstPair.Destination->getReg(), GPRPairIdx, &RISCV::GPRPairRegClass);
  bool KillSrc = PairedSource.isKill() && FirstPair.Source->isKill();

  TII->copyPhysReg(*I->getParent(), I, DL, DestReg, SrcReg, KillSrc);

  I->eraseFromParent();
  Paired->eraseFromParent();
  return NextI;
}

MachineBasicBlock::iterator
RISCVMoveMerge::mergePairedInsns(MachineBasicBlock::iterator I,
                                 MachineBasicBlock::iterator Paired,
                                 bool MoveFromSToA) {
  const MachineOperand *Sreg1, *Sreg2;
  MachineBasicBlock::iterator E = I->getParent()->end();
  MachineBasicBlock::iterator NextI = next_nodbg(I, E);
  DestSourcePair FirstPair = *TII->isCopyInstrImpl(*I);
  DestSourcePair PairedRegs = *TII->isCopyInstrImpl(*Paired);

  if (NextI == Paired)
    NextI = next_nodbg(NextI, E);
  DebugLoc DL = I->getDebugLoc();

  // Make a copy so we can update the kill flag in the MoveFromSToA case. The
  // copied operand needs to be scoped outside the if since we make a pointer
  // to it.
  MachineOperand PairedSource = *PairedRegs.Source;

  // The order of S-reg depends on which instruction holds A0, instead of
  // the order of register pair.
  // e,g.
  //   mv a1, s1
  //   mv a0, s2    =>  cm.mva01s s2,s1
  //
  //   mv a0, s2
  //   mv a1, s1    =>  cm.mva01s s2,s1
  unsigned Opcode = getCM_MVOpcode(*ST, MoveFromSToA);
  if (MoveFromSToA) {
    // We are moving one of the copies earlier so its kill flag may become
    // invalid. Clear the copied kill flag if there are any reads of the
    // register between the new location and the old location.
    for (auto It = std::next(I); It != Paired && PairedSource.isKill(); ++It)
      if (It->readsRegister(PairedSource.getReg(), TRI))
        PairedSource.setIsKill(false);

    Sreg1 = FirstPair.Source;
    Sreg2 = &PairedSource;
    if (FirstPair.Destination->getReg() != RISCV::X10)
      std::swap(Sreg1, Sreg2);
  } else {
    Sreg1 = FirstPair.Destination;
    Sreg2 = PairedRegs.Destination;
    if (FirstPair.Source->getReg() != RISCV::X10)
      std::swap(Sreg1, Sreg2);
  }

  BuildMI(*I->getParent(), I, DL, TII->get(Opcode)).add(*Sreg1).add(*Sreg2);

  I->eraseFromParent();
  Paired->eraseFromParent();
  return NextI;
}

MachineBasicBlock::iterator
RISCVMoveMerge::mergePLIPair(MachineBasicBlock::iterator I,
                             MachineBasicBlock::iterator Paired,
                             bool RegPairIsEven) {
  MachineBasicBlock::iterator E = I->getParent()->end();
  MachineBasicBlock::iterator NextI = next_nodbg(I, E);

  if (NextI == Paired)
    NextI = next_nodbg(NextI, E);
  DebugLoc DL = I->getDebugLoc();

  unsigned Opcode = getPairedPLIOpcode(I->getOpcode());
  unsigned GPRPairIdx =
      RegPairIsEven ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
  Register DestReg = TRI->getMatchingSuperReg(
      I->getOperand(0).getReg(), GPRPairIdx, &RISCV::GPRPairRegClass);

  BuildMI(*I->getParent(), I, DL, TII->get(Opcode), DestReg)
      .addImm(I->getOperand(1).getImm());

  I->eraseFromParent();
  Paired->eraseFromParent();
  return NextI;
}

MachineBasicBlock::iterator
RISCVMoveMerge::findMatchingGPRPairCopy(MachineBasicBlock::iterator &MBBI,
                                        bool EvenRegPair,
                                        const DestSourcePair &RegPair) {
  MachineBasicBlock::iterator E = MBBI->getParent()->end();
  ModifiedRegUnits.clear();
  UsedRegUnits.clear();
  unsigned RegPairIdx = EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
  unsigned SecondPairIdx =
      !EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;

  // Get the expected source/destination registers of the matching lane.
  Register SrcGPRPair = TRI->getMatchingSuperReg(
      RegPair.Source->getReg(), RegPairIdx, &RISCV::GPRPairRegClass);
  Register DestGPRPair = TRI->getMatchingSuperReg(
      RegPair.Destination->getReg(), RegPairIdx, &RISCV::GPRPairRegClass);
  Register ExpectedSourceReg = TRI->getSubReg(SrcGPRPair, SecondPairIdx);
  Register ExpectedDestReg = TRI->getSubReg(DestGPRPair, SecondPairIdx);

  for (MachineBasicBlock::iterator I = next_nodbg(MBBI, E); I != E;
       I = next_nodbg(I, E)) {

    MachineInstr &MI = *I;

    if (auto SecondPair = TII->isCopyInstrImpl(MI)) {
      Register SourceReg = SecondPair->Source->getReg();
      Register DestReg = SecondPair->Destination->getReg();

      if (RegPair.Destination->getReg() == DestReg ||
          RegPair.Source->getReg() == SourceReg)
        return E;

      // Check if the second pair's registers match the other lane of the
      // GPRPairs.
      if (SourceReg == ExpectedSourceReg && DestReg == ExpectedDestReg)
        return I;
    }
    // Update modified / used register units.
    LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
    // Once expected lane registers are clobbered/read in-between, we can stop
    // scanning since the pair cannot be legally merged anymore.
    if (!ModifiedRegUnits.available(ExpectedDestReg) ||
        !UsedRegUnits.available(ExpectedDestReg) ||
        !ModifiedRegUnits.available(ExpectedSourceReg))
      return E;
  }
  return E;
}

MachineBasicBlock::iterator
RISCVMoveMerge::findMatchingSACopy(MachineBasicBlock::iterator &MBBI,
                                   bool MoveFromSToA,
                                   const DestSourcePair &RegPair) {
  MachineBasicBlock::iterator E = MBBI->getParent()->end();

  // Track which register units have been modified and used between the first
  // insn and the second insn.
  ModifiedRegUnits.clear();
  UsedRegUnits.clear();

  for (MachineBasicBlock::iterator I = next_nodbg(MBBI, E); I != E;
       I = next_nodbg(I, E)) {

    MachineInstr &MI = *I;

    if (auto SecondPair = TII->isCopyInstrImpl(MI)) {
      Register SourceReg = SecondPair->Source->getReg();
      Register DestReg = SecondPair->Destination->getReg();

      bool IsCandidate = MoveFromSToA ? isCandidateToMergeMVA01S(*SecondPair)
                                      : isCandidateToMergeMVSA01(*SecondPair);
      if (IsCandidate) {
        // Second destination must be different.
        if (RegPair.Destination->getReg() == DestReg)
          return E;

        // For AtoS the source must also be different.
        if (!MoveFromSToA && RegPair.Source->getReg() == SourceReg)
          return E;

        // If paired destination register was modified or used, the source reg
        // was modified, there is no possibility of finding matching
        // instruction so exit early.
        if (!ModifiedRegUnits.available(DestReg) ||
            !UsedRegUnits.available(DestReg) ||
            !ModifiedRegUnits.available(SourceReg))
          return E;

        return I;
      }
    }
    // Update modified / used register units.
    LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
  }
  return E;
}

// Look for a same-opcode pli/plui writing the other lane of the same GPRPair
// with the same immediate. Return the matching instruction if one exists.
MachineBasicBlock::iterator
RISCVMoveMerge::findMatchingPLI(MachineBasicBlock::iterator &MBBI,
                                bool EvenRegPair) {
  MachineBasicBlock::iterator E = MBBI->getParent()->end();
  ModifiedRegUnits.clear();
  UsedRegUnits.clear();
  unsigned Opc = MBBI->getOpcode();
  Register FirstDestReg = MBBI->getOperand(0).getReg();
  int64_t FirstImm = MBBI->getOperand(1).getImm();
  unsigned RegPairIdx = EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;
  unsigned SecondPairIdx =
      !EvenRegPair ? RISCV::sub_gpr_even : RISCV::sub_gpr_odd;

  // Get the expected destination register of the matching lane.
  Register DestGPRPair = TRI->getMatchingSuperReg(FirstDestReg, RegPairIdx,
                                                  &RISCV::GPRPairRegClass);
  Register ExpectedDestReg = TRI->getSubReg(DestGPRPair, SecondPairIdx);

  for (MachineBasicBlock::iterator I = next_nodbg(MBBI, E); I != E;
       I = next_nodbg(I, E)) {

    MachineInstr &MI = *I;

    if (MI.getOpcode() == Opc) {
      Register DestReg = MI.getOperand(0).getReg();
      int64_t Imm = MI.getOperand(1).getImm();

      if (FirstDestReg == DestReg)
        return E;

      // Check if the second PLI matches the other lane and immediate.
      if (DestReg == ExpectedDestReg && Imm == FirstImm)
        return I;
    }
    // Update modified / used register units.
    LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
    // Once the expected lane register is clobbered/read in-between, we can
    // stop scanning since the pair cannot be legally merged anymore.
    if (!ModifiedRegUnits.available(ExpectedDestReg) ||
        !UsedRegUnits.available(ExpectedDestReg))
      return E;
  }
  return E;
}

// Finds instructions, which could be represented as C.MV instructions and
// merged into CM.MVA01S or CM.MVSA01.
bool RISCVMoveMerge::mergeMovePairs(MachineBasicBlock &MBB) {
  bool Modified = false;

  for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
       MBBI != E;) {
    // Try merging a pair of single-reg PLI/PLUI into a paired form.
    bool IsPLIEven = isPLIPairCandidate(*MBBI, /*EvenRegPair=*/true);
    bool IsPLIOdd = isPLIPairCandidate(*MBBI, /*EvenRegPair=*/false);
    if (IsPLIEven != IsPLIOdd) {
      MachineBasicBlock::iterator Paired = findMatchingPLI(MBBI, IsPLIEven);
      if (Paired != E) {
        MBBI = mergePLIPair(MBBI, Paired, IsPLIEven);
        Modified = true;
        continue;
      }
    }

    // Check if the instruction can be compressed to C.MV instruction. If it
    // can, return Dest/Src register pair.
    auto RegPair = TII->isCopyInstrImpl(*MBBI);
    if (RegPair.has_value()) {
      bool MoveFromSToA = isCandidateToMergeMVA01S(*RegPair);
      bool MoveFromAToS = isCandidateToMergeMVSA01(*RegPair);
      bool IsEven = isGPRPairCopyCandidate(*RegPair, /*EvenRegPair=*/true);
      bool IsOdd = isGPRPairCopyCandidate(*RegPair, /*EvenRegPair=*/false);
      if (!MoveFromSToA && !MoveFromAToS && !IsEven && !IsOdd) {
        ++MBBI;
        continue;
      }

      MachineBasicBlock::iterator Paired = E;
      if (MoveFromSToA || MoveFromAToS) {
        Paired = findMatchingSACopy(MBBI, MoveFromSToA, *RegPair);
        if (Paired != E) {
          MBBI = mergePairedInsns(MBBI, Paired, MoveFromSToA);
          Modified = true;
          continue;
        }
      }
      if (IsEven != IsOdd) {
        Paired = findMatchingGPRPairCopy(MBBI, IsEven, *RegPair);
        if (Paired != E) {
          MBBI = mergeGPRPairInsns(MBBI, Paired, IsEven);
          Modified = true;
          continue;
        }
      }
    }
    ++MBBI;
  }
  return Modified;
}

bool RISCVMoveMerge::runOnMachineFunction(MachineFunction &Fn) {
  if (skipFunction(Fn.getFunction()))
    return false;

  ST = &Fn.getSubtarget<RISCVSubtarget>();
  bool HasGPRPairCopy =
      !ST->is64Bit() && (ST->hasStdExtZdinx() || ST->hasStdExtP());
  if (!ST->hasStdExtZcmp() && !ST->hasVendorXqccmp() && !HasGPRPairCopy)
    return false;

  TII = ST->getInstrInfo();
  TRI = ST->getRegisterInfo();
  // Resize the modified and used register unit trackers.  We do this once
  // per function and then clear the register units each time we optimize a
  // move.
  ModifiedRegUnits.init(*TRI);
  UsedRegUnits.init(*TRI);
  bool Modified = false;
  for (auto &MBB : Fn)
    Modified |= mergeMovePairs(MBB);
  return Modified;
}

/// createRISCVMoveMergePass - returns an instance of the
/// move merge pass.
FunctionPass *llvm::createRISCVMoveMergePass() { return new RISCVMoveMerge(); }
