Repository: llvm/llvm-project
File: llvm/lib/Target/RISCV/RISCVMoveMerger.cpp (C++)

Code before:
  MachineBasicBlock::iterator
  findMatchingInst(MachineBasicBlock::iterator &MBBI, bool MoveFromSToA,
                   const DestSourcePair &RegPair);
  bool mergeMoveSARegPair(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 getMoveFromOpcode(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;

  if (ST.hasStdExtZdinx()) {
    if (ST.is64Bit())
      return RISCV::FSGNJ_D;
    return RISCV::FSGNJ_D_IN32X;
  }

  if (ST.hasStdExtP())
    return RISCV::ADDD;

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

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

  if (Source == Destination)
    return false;

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

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

// Check if registers meet CM.MVA01S constraints.

Review comment (suggestion):
I think you meant to use `RISCV::FSGNJ_D_INX`, but that wouldn't be right either - it only moves one 64-bit value from one GPR to another, but on rv64 a pair is 128 bits.

We should skip the move pair optimisation on rv64 for the moment, as I don't think we have any move pair instructions and we don't have pair load/stores either (zilsd is 32-bit only).

Code after:
  MachineBasicBlock::iterator
  findMatchingInst(MachineBasicBlock::iterator &MBBI, bool MoveFromSToA,
                   const DestSourcePair &RegPair);
  bool mergeMoveSARegPair(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 getMoveFromOpcode(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;

  if (ST.hasStdExtZdinx())
    return RISCV::FSGNJ_D_IN32X;

  if (ST.hasStdExtP())
    return RISCV::PADD_DW;

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

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

  if (Source == Destination)
    return false;

  Register SrcPair = TRI->getMatchingSuperReg(Source, RISCV::sub_gpr_even,
                                              &RISCV::GPRPairRegClass);
  Register DestPair = TRI->getMatchingSuperReg(Destination, RISCV::sub_gpr_even,
                                               &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();