[llvm-branch-commits] [llvm] release/22.x: [RISCV] Add missing COPY elimination when folding vmerge into mask (#176077) (PR #176432)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jan 16 09:19:28 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-risc-v

Author: None (llvmbot)

<details>
<summary>Changes</summary>

Backport 6f69d68a9ef4a4e3fae634a80f24ea5d77e1fd45

Requested by: @<!-- -->mshockwave

---
Full diff: https://github.com/llvm/llvm-project/pull/176432.diff


3 Files Affected:

- (modified) llvm/lib/Target/RISCV/RISCVVectorPeephole.cpp (+20-7) 
- (modified) llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll (+1-2) 
- (modified) llvm/test/CodeGen/RISCV/rvv/vmerge-peephole.mir (+31-1) 


``````````diff
diff --git a/llvm/lib/Target/RISCV/RISCVVectorPeephole.cpp b/llvm/lib/Target/RISCV/RISCVVectorPeephole.cpp
index a5385be0c011c..b00244af1a875 100644
--- a/llvm/lib/Target/RISCV/RISCVVectorPeephole.cpp
+++ b/llvm/lib/Target/RISCV/RISCVVectorPeephole.cpp
@@ -73,7 +73,9 @@ class RISCVVectorPeephole : public MachineFunctionPass {
   bool isAllOnesMask(const MachineInstr *MaskDef) const;
   std::optional<unsigned> getConstant(const MachineOperand &VL) const;
   bool ensureDominates(const MachineOperand &Use, MachineInstr &Src) const;
-  Register lookThruCopies(Register Reg, bool OneUseOnly = false) const;
+  Register
+  lookThruCopies(Register Reg, bool OneUseOnly = false,
+                 SmallVectorImpl<MachineInstr *> *Copies = nullptr) const;
 };
 
 } // namespace
@@ -389,8 +391,9 @@ bool RISCVVectorPeephole::convertAllOnesVMergeToVMv(MachineInstr &MI) const {
 
 // If \p Reg is defined by one or more COPYs of virtual registers, traverses
 // the chain and returns the root non-COPY source.
-Register RISCVVectorPeephole::lookThruCopies(Register Reg,
-                                             bool OneUseOnly) const {
+Register RISCVVectorPeephole::lookThruCopies(
+    Register Reg, bool OneUseOnly,
+    SmallVectorImpl<MachineInstr *> *Copies) const {
   while (MachineInstr *Def = MRI->getUniqueVRegDef(Reg)) {
     if (!Def->isFullCopy())
       break;
@@ -399,6 +402,8 @@ Register RISCVVectorPeephole::lookThruCopies(Register Reg,
       break;
     if (OneUseOnly && !MRI->hasOneNonDBGUse(Reg))
       break;
+    if (Copies)
+      Copies->push_back(Def);
     Reg = Src;
   }
   return Reg;
@@ -735,10 +740,12 @@ bool RISCVVectorPeephole::foldVMergeToMask(MachineInstr &MI) const {
   if (RISCV::getRVVMCOpcode(MI.getOpcode()) != RISCV::VMERGE_VVM)
     return false;
 
+  // Collect chain of COPYs on True's result for later cleanup.
+  SmallVector<MachineInstr *, 4> TrueCopies;
   Register PassthruReg = lookThruCopies(MI.getOperand(1).getReg());
   Register FalseReg = lookThruCopies(MI.getOperand(2).getReg());
-  Register TrueReg =
-      lookThruCopies(MI.getOperand(3).getReg(), /*OneUseOnly=*/true);
+  Register TrueReg = lookThruCopies(MI.getOperand(3).getReg(),
+                                    /*OneUseOnly=*/true, &TrueCopies);
   if (!TrueReg.isVirtual() || !MRI->hasOneUse(TrueReg))
     return false;
   MachineInstr &True = *MRI->getUniqueVRegDef(TrueReg);
@@ -821,8 +828,9 @@ bool RISCVVectorPeephole::foldVMergeToMask(MachineInstr &MI) const {
   assert(RISCVII::hasVecPolicyOp(True.getDesc().TSFlags) &&
          "Foldable unmasked pseudo should have a policy op already");
 
-  // Make sure the mask dominates True, otherwise move down True so it does.
-  // VL will always dominate since if it's a register they need to be the same.
+  // Make sure the mask dominates True and its copies, otherwise move down True
+  // so it does. VL will always dominate since if it's a register they need to
+  // be the same.
   if (!ensureDominates(MaskOp, True))
     return false;
 
@@ -861,6 +869,11 @@ bool RISCVVectorPeephole::foldVMergeToMask(MachineInstr &MI) const {
   MRI->clearKillFlags(FalseReg);
   MI.eraseFromParent();
 
+  // Cleanup all the COPYs on True's value. We have to manually do this because
+  // sometimes sinking True causes these COPY to be invalid (use before define).
+  for (MachineInstr *TrueCopy : TrueCopies)
+    TrueCopy->eraseFromParent();
+
   return true;
 }
 
diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll
index 5be32cc35fe37..acd9519bb5a8e 100644
--- a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll
@@ -867,9 +867,8 @@ define void @test_dag_loop() {
 ; CHECK-NEXT:    vmseq.vv v0, v12, v8
 ; CHECK-NEXT:    vsetvli zero, zero, e16, m8, ta, ma
 ; CHECK-NEXT:    vmv.v.i v8, 0
-; CHECK-NEXT:    vsetivli zero, 1, e16, m8, tu, mu
+; CHECK-NEXT:    vsetvli zero, zero, e16, m8, tu, mu
 ; CHECK-NEXT:    vle16.v v8, (zero), v0.t
-; CHECK-NEXT:    vsetivli zero, 0, e16, m8, ta, ma
 ; CHECK-NEXT:    vse16.v v8, (zero)
 ; CHECK-NEXT:    ret
 entry:
diff --git a/llvm/test/CodeGen/RISCV/rvv/vmerge-peephole.mir b/llvm/test/CodeGen/RISCV/rvv/vmerge-peephole.mir
index bc78a7732c15a..98b193f24d7c8 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vmerge-peephole.mir
+++ b/llvm/test/CodeGen/RISCV/rvv/vmerge-peephole.mir
@@ -128,7 +128,6 @@ body: |
     ; CHECK-NEXT: %passthru:vrnov0 = COPY $v8
     ; CHECK-NEXT: %mask:vmv0 = COPY $v0
     ; CHECK-NEXT: %z:vrnov0 = PseudoVLE32_V_M1_MASK %passthru, $noreg, %mask, %avl, 5 /* e32 */, 0 /* tu, mu */ :: (load unknown-size, align 1)
-    ; CHECK-NEXT: %y:vrnov0 = COPY %z
     %avl:gprnox0 = COPY $x8
     %passthru:vrnov0 = COPY $v8
     %x:vr = PseudoVLE32_V_M1 $noreg, $noreg, %avl, 5 /* e32 */, 2 /* tu, ma */ :: (load unknown-size)
@@ -181,3 +180,34 @@ body: |
     %mask:vmv0 = COPY $v0
     PseudoVSE8_V_M1 %copy, $noreg, %avl, 5 /* e8 */
     %y:vrnov0 = PseudoVMERGE_VVM_M1 %passthru, %passthru, %copy, %mask, %avl, 5 /* e32 */
+...
+---
+name: true_copy_elimination
+body:             |
+  ; CHECK-LABEL: name: true_copy_elimination
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   PseudoBR %bb.1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   [[DEF:%[0-9]+]]:vmv0 = IMPLICIT_DEF
+  ; CHECK-NEXT:   early-clobber %5:vrm8nov0 = PseudoVZEXT_VF8_M8_MASK $noreg, $noreg, [[DEF]], 16, 6 /* e64 */, 1 /* ta, mu */
+  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:vrm8 = COPY %5
+  ; CHECK-NEXT:   PseudoRET
+  bb.0:
+    successors: %bb.1
+
+    PseudoBR %bb.1
+
+  bb.1:
+
+    %102:vrm8 = PseudoVZEXT_VF8_M8 $noreg, $noreg, 16, 6 /* e64 */, 3 /* ta, ma */
+    %123:vrm8nov0 = COPY %102
+    %a123:vrm8 = COPY %123
+    %b123:vrm8nov0 = COPY %a123
+    %124:vmv0 = IMPLICIT_DEF
+    %121:vrm8nov0 = PseudoVMERGE_VVM_M8 $noreg, $noreg, %b123, undef %124, 16, 6 /* e64 */
+    %125:vrm8 = COPY %121
+    PseudoRET
+...

``````````

</details>


https://github.com/llvm/llvm-project/pull/176432


More information about the llvm-branch-commits mailing list