Repository: llvm/llvm-project
File: llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp (C++)

Code before:
      return false;

    if (MRI->getRegClass(SrcMI->getOperand(1).getReg()) ==
        &AArch64::FPR128RegClass) {
      break;
    }
    SrcMI = MRI->getUniqueVRegDef(SrcMI->getOperand(1).getReg());
  }

  Register DstReg = MI.getOperand(0).getReg();
  Register SrcReg = SrcMI->getOperand(1).getReg();
  MachineInstr *INSvilaneMI =
      BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(Opc), DstReg)
          .add(MI.getOperand(1))
          .add(MI.getOperand(2))
          .addUse(SrcReg, getRegState(SrcMI->getOperand(1)))
          .addImm(0);

  LLVM_DEBUG(dbgs() << MI << "  replace by:\n: " << *INSvilaneMI << "\n");
  (void)INSvilaneMI;
  MI.eraseFromParent();
  return true;
}

// All instructions that set a FPR64 will implicitly zero the top bits of the
// register. When the def is expressed as a COPY from a GPR, turn it into an
// explicit FMOV so it cannot be elided later in further passes.
static bool is64bitDefwithZeroHigh64bit(MachineInstr *MI,
                                        MachineRegisterInfo *MRI,
                                        const AArch64InstrInfo *TII) {
  if (!MI->getOperand(0).isReg() || !MI->getOperand(0).isDef())
    return false;
  const TargetRegisterClass *RC = MRI->getRegClass(MI->getOperand(0).getReg());
  if (RC != &AArch64::FPR64RegClass)
    return false;
  if (MI->getOpcode() == TargetOpcode::COPY) {
    MachineOperand &SrcOp = MI->getOperand(1);
    if (!SrcOp.isReg())
      return false;
    if (SrcOp.getSubReg())
      return false;
    Register SrcReg = SrcOp.getReg();
    auto IsGPR64Like = [&]() -> bool {
      if (SrcReg.isVirtual())
        return AArch64::GPR64allRegClass.hasSubClassEq(
            MRI->getRegClass(SrcReg));
      return AArch64::GPR64allRegClass.contains(SrcReg);
    };
    if (!IsGPR64Like())
      return false;
    assert(TII && "Expected InstrInfo when materializing COPYs");

Review comment (refactor):
If you wanted to pull this part out into a separate PR, that might help get that bit done and simplify what remains.

Code after:

    if (MRI->getRegClass(SrcMI->getOperand(1).getReg()) ==
        &AArch64::FPR128RegClass) {
      break;
    }
    SrcMI = MRI->getUniqueVRegDef(SrcMI->getOperand(1).getReg());
  }

  Register DstReg = MI.getOperand(0).getReg();
  Register SrcReg = SrcMI->getOperand(1).getReg();
  MachineInstr *INSvilaneMI =
      BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(Opc), DstReg)
          .add(MI.getOperand(1))
          .add(MI.getOperand(2))
          .addUse(SrcReg, getRegState(SrcMI->getOperand(1)))
          .addImm(0);

  LLVM_DEBUG(dbgs() << MI << "  replace by:\n: " << *INSvilaneMI << "\n");
  (void)INSvilaneMI;
  MI.eraseFromParent();
  return true;
}

// All instructions that set a FPR64 will implicitly zero the top bits of the
// register.
static bool is64bitDefwithZeroHigh64bit(MachineInstr *MI,
                                        MachineRegisterInfo *MRI) {
  if (!MI->getOperand(0).isReg() || !MI->getOperand(0).isDef())
    return false;
  const TargetRegisterClass *RC = MRI->getRegClass(MI->getOperand(0).getReg());
  if (RC != &AArch64::FPR64RegClass)
    return false;
  return MI->getOpcode() > TargetOpcode::GENERIC_OP_END;
}

bool AArch64MIPeepholeOpt::visitINSvi64lane(MachineInstr &MI) {
  // Check the MI for low 64-bits sets zero for high 64-bits implicitly.
  // We are expecting below case.
  //
  //  %1:fpr64 = nofpexcept FCVTNv4i16 %0:fpr128, implicit $fpcr
  //  %6:fpr128 = IMPLICIT_DEF
  //  %5:fpr128 = INSERT_SUBREG %6:fpr128(tied-def 0), killed %1:fpr64, %subreg.dsub
  //  %7:fpr128 = INSvi64lane %5:fpr128(tied-def 0), 1, killed %3:fpr128, 0
  MachineInstr *Low64MI = MRI->getUniqueVRegDef(MI.getOperand(1).getReg());
  if (Low64MI->getOpcode() != AArch64::INSERT_SUBREG)
    return false;
  Low64MI = MRI->getUniqueVRegDef(Low64MI->getOperand(2).getReg());
  if (!Low64MI || !is64bitDefwithZeroHigh64bit(Low64MI, MRI))
    return false;

  // Check there is `mov 0` MI for high 64-bits.