[llvm] [RISCV] Move vmerge same mask peephole to RISCVVectorPeephole (PR #106108)
Luke Lau via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 9 02:12:19 PDT 2024
================
@@ -361,14 +358,68 @@ bool RISCVVectorPeephole::convertVMergeToVMv(MachineInstr &MI) const {
CASE_VMERGE_TO_VMV(M4)
CASE_VMERGE_TO_VMV(M8)
}
+}
+/// Convert a PseudoVMERGE_VVM with an all ones mask to a PseudoVMV_V_V.
+///
+/// %x = PseudoVMERGE_VVM %passthru, %false, %true, %allones, sew, vl
+/// ->
+/// %x = PseudoVMV_V_V %passthru, %true, vl, sew, tu_mu
+bool RISCVVectorPeephole::convertAllOnesVMergeToVMv(MachineInstr &MI) const {
+ unsigned NewOpc = getVMV_V_VOpcodeForVMERGE_VVM(MI);
+ if (!NewOpc)
+ return false;
assert(MI.getOperand(4).isReg() && MI.getOperand(4).getReg() == RISCV::V0);
if (!isAllOnesMask(V0Defs.lookup(&MI)))
return false;
MI.setDesc(TII->get(NewOpc));
- MI.removeOperand(2); // False operand
- MI.removeOperand(3); // Mask operand
+ MI.removeOperand(2); // False operand
+ MI.removeOperand(3); // Mask operand
+ MI.addOperand(
+ MachineOperand::CreateImm(RISCVII::TAIL_UNDISTURBED_MASK_UNDISTURBED));
+
+ // vmv.v.v doesn't have a mask operand, so we may be able to inflate the
+ // register class for the destination and passthru operands e.g. VRNoV0 -> VR
+ MRI->recomputeRegClass(MI.getOperand(0).getReg());
+ if (MI.getOperand(1).getReg() != RISCV::NoRegister)
+ MRI->recomputeRegClass(MI.getOperand(1).getReg());
+ return true;
+}
+
+/// If a PseudoVMERGE_VVM's true operand is a masked pseudo and both have the
+/// same mask, and the masked pseudo's passthru is the same as the false
+/// operand, we can convert the PseudoVMERGE_VVM to a PseudoVMV_V_V.
+///
+/// %true = PseudoVADD_VV_M1_MASK %false, %x, %y, %mask, vl1, sew, policy
+/// %x = PseudoVMERGE_VVM %passthru, %false, %true, %mask, vl2, sew
+/// ->
+/// %true = PseudoVADD_VV_M1_MASK %false, %x, %y, %mask, vl1, sew, policy
+/// %x = PseudoVMV_V_V %passthru, %true, vl2, sew, tu_mu
+bool RISCVVectorPeephole::convertSameMaskVMergeToVMv(MachineInstr &MI) const {
+ unsigned NewOpc = getVMV_V_VOpcodeForVMERGE_VVM(MI);
+ if (!NewOpc)
+ return false;
+ MachineInstr *True = MRI->getVRegDef(MI.getOperand(3).getReg());
+ if (!True || !RISCV::getMaskedPseudoInfo(True->getOpcode()) ||
+ !hasSameEEW(MI, *True))
+ return false;
+
+ // True's passthru needs to be equivalent to False
+ Register TruePassthruReg = True->getOperand(1).getReg();
+ Register FalseReg = MI.getOperand(2).getReg();
+ if (TruePassthruReg != RISCV::NoRegister && TruePassthruReg != FalseReg)
+ return false;
+
+ const MachineInstr *TrueV0Def = V0Defs.lookup(True);
+ const MachineInstr *MIV0Def = V0Defs.lookup(&MI);
+ assert(TrueV0Def && TrueV0Def->isCopy() && MIV0Def && MIV0Def->isCopy());
+ if (TrueV0Def->getOperand(1).getReg() != MIV0Def->getOperand(1).getReg())
+ return false;
+
----------------
lukel97 wrote:
I've opened #107827 to fix it, I believe the underlying issue was that we were discarding the false operand when the true operand's passthru was undef.
In your example above, in theory I think we can still replace the VMERGE_VVM with VMV_V_V as long as the VRSUB_VI's passthru becomes the false operand. In practice though we would need to move the VRSUB_VI past a copy to $v0, so the peephole should just bail instead after the patch.
https://github.com/llvm/llvm-project/pull/106108
More information about the llvm-commits
mailing list