[llvm] [RISCV] Eliminate redundant materializations after register comparison (PR #227673)

via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 1 01:03:42 PDT 2026


https://github.com/tinfengyu updated https://github.com/llvm/llvm-project/pull/227673

>From a00bf0cd9539a43f9d31bc2ad50c3b178bde2312 Mon Sep 17 00:00:00 2001
From: tinfeng <1768309929 at qq.com>
Date: Thu, 1 Oct 2026 10:30:33 +0800
Subject: [PATCH 1/3] [RISCV] Add tests for redundant materializations after
 register comparisons

---
 .../RISCV/redundant-copy-elim-reg-imm.mir     | 337 ++++++++++++++++++
 1 file changed, 337 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/redundant-copy-elim-reg-imm.mir

diff --git a/llvm/test/CodeGen/RISCV/redundant-copy-elim-reg-imm.mir b/llvm/test/CodeGen/RISCV/redundant-copy-elim-reg-imm.mir
new file mode 100644
index 0000000000000..16d8aca98fa25
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/redundant-copy-elim-reg-imm.mir
@@ -0,0 +1,337 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=riscv32 -mattr=+xqcili -run-pass=riscv-copyelim -verify-machineinstrs %s -o - | FileCheck %s
+
+--- |
+  define void @beq_reg_imm() { ret void }
+  define void @bne_reg_imm() { ret void }
+  define void @clobber_const() { ret void }
+  define void @clobber_target() { ret void }
+  define void @inequality_edge() { ret void }
+  define void @beq_x0_is_zero() { ret void }
+  define void @bne_x0_is_zero() { ret void }
+  define void @beq_reg_imm_swapped() { ret void }
+  define void @bne_reg_imm_swapped() { ret void }
+  declare void @callee()
+...
+---
+name:            beq_reg_imm
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: beq_reg_imm
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $x11 = ADDI $x0, 7
+  ; CHECK-NEXT:   BEQ $x11, killed $x10, %bb.1
+  ; CHECK-NEXT:   PseudoBR %bb.2
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.2(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $x10 = ADDI $x0, 7
+  ; CHECK-NEXT:   PseudoRET implicit $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   PseudoRET
+  bb.0:
+    successors: %bb.1, %bb.2
+    liveins: $x10
+    $x11 = ADDI $x0, 7
+    BEQ $x11, killed $x10, %bb.1
+    PseudoBR %bb.2
+  bb.1:
+    successors: %bb.2
+    $x10 = ADDI $x0, 7
+    PseudoRET implicit $x10
+  bb.2:
+    PseudoRET
+...
+
+
+---
+name:            bne_reg_imm
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: bne_reg_imm
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.2(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $x11 = QC_LI 9
+  ; CHECK-NEXT:   BNE killed $x10, $x11, %bb.2
+  ; CHECK-NEXT:   PseudoBR %bb.1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   $x10 = ADDI $x0, 9
+  ; CHECK-NEXT:   PseudoRET implicit $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   PseudoRET
+  bb.0:
+    successors: %bb.2, %bb.1
+    liveins: $x10
+    $x11 = QC_LI 9
+    BNE killed $x10, $x11, %bb.2
+    PseudoBR %bb.1
+  bb.1:
+    $x10 = ADDI $x0, 9
+    PseudoRET implicit $x10
+  bb.2:
+    PseudoRET
+...
+
+
+---
+name:            clobber_const
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: clobber_const
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT:   liveins: $x8
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $x11 = ADDI $x0, 7
+  ; CHECK-NEXT:   PseudoCALL target-flags(riscv-call) @callee, csr_ilp32_lp64, implicit-def dead $x1, implicit-def $x11
+  ; CHECK-NEXT:   BEQ $x8, $x11, %bb.1
+  ; CHECK-NEXT:   PseudoBR %bb.2
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   $x8 = ADDI $x0, 7
+  ; CHECK-NEXT:   PseudoRET implicit $x8
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   liveins: $x8
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   PseudoRET implicit $x8
+  bb.0:
+    successors: %bb.1, %bb.2
+    liveins: $x8
+    $x11 = ADDI $x0, 7
+    PseudoCALL target-flags(riscv-call) @callee, csr_ilp32_lp64, implicit-def dead $x1, implicit-def $x11
+    BEQ $x8, $x11, %bb.1
+    PseudoBR %bb.2
+  bb.1:
+    $x8 = ADDI $x0, 7
+    PseudoRET implicit $x8
+  bb.2:
+    liveins: $x8
+    PseudoRET implicit $x8
+...
+
+
+---
+name:            clobber_target
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: clobber_target
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $x11 = ADDI $x0, 7
+  ; CHECK-NEXT:   BEQ $x10, $x11, %bb.1
+  ; CHECK-NEXT:   PseudoBR %bb.2
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $x10 = ADDI $x10, 1
+  ; CHECK-NEXT:   $x10 = ADDI $x0, 7
+  ; CHECK-NEXT:   PseudoRET implicit $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   PseudoRET implicit $x10
+  bb.0:
+    successors: %bb.1, %bb.2
+    liveins: $x10
+    $x11 = ADDI $x0, 7
+    BEQ $x10, $x11, %bb.1
+    PseudoBR %bb.2
+  bb.1:
+    liveins: $x10
+    $x10 = ADDI $x10, 1
+    $x10 = ADDI $x0, 7
+    PseudoRET implicit $x10
+  bb.2:
+    liveins: $x10
+    PseudoRET implicit $x10
+...
+
+
+---
+name:            inequality_edge
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: inequality_edge
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.2(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $x11 = ADDI $x0, 7
+  ; CHECK-NEXT:   BEQ $x10, $x11, %bb.2
+  ; CHECK-NEXT:   PseudoBR %bb.1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   $x10 = ADDI $x0, 7
+  ; CHECK-NEXT:   PseudoRET implicit $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   PseudoRET implicit $x10
+  bb.0:
+    successors: %bb.2, %bb.1
+    liveins: $x10
+    $x11 = ADDI $x0, 7
+    BEQ $x10, $x11, %bb.2
+    PseudoBR %bb.1
+  bb.1:
+    $x10 = ADDI $x0, 7
+    PseudoRET implicit $x10
+  bb.2:
+    liveins: $x10
+    PseudoRET implicit $x10
+...
+
+
+---
+name:            beq_x0_is_zero
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: beq_x0_is_zero
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $x0 = ADDI $x0, 7
+  ; CHECK-NEXT:   BEQ $x0, $x10, %bb.1
+  ; CHECK-NEXT:   PseudoBR %bb.2
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   $x10 = ADDI $x0, 7
+  ; CHECK-NEXT:   PseudoRET implicit $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   PseudoRET
+  bb.0:
+    successors: %bb.1, %bb.2
+    liveins: $x10
+    $x0 = ADDI $x0, 7
+    BEQ $x0, $x10, %bb.1
+    PseudoBR %bb.2
+  bb.1:
+    $x10 = ADDI $x0, 7
+    PseudoRET implicit $x10
+  bb.2:
+    PseudoRET
+...
+
+# The formal ADDI definition cannot change x0's architectural zero value.
+
+---
+name:            bne_x0_is_zero
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: bne_x0_is_zero
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.2(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $x0 = ADDI $x0, 9
+  ; CHECK-NEXT:   BNE $x0, $x10, %bb.2
+  ; CHECK-NEXT:   PseudoBR %bb.1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   $x10 = ADDI $x0, 9
+  ; CHECK-NEXT:   PseudoRET implicit $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   PseudoRET
+  bb.0:
+    successors: %bb.2, %bb.1
+    liveins: $x10
+    $x0 = ADDI $x0, 9
+    BNE $x0, $x10, %bb.2
+    PseudoBR %bb.1
+  bb.1:
+    $x10 = ADDI $x0, 9
+    PseudoRET implicit $x10
+  bb.2:
+    PseudoRET
+...
+
+
+---
+name:            beq_reg_imm_swapped
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: beq_reg_imm_swapped
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $x11 = ADDI $x0, 7
+  ; CHECK-NEXT:   BEQ killed $x10, $x11, %bb.1
+  ; CHECK-NEXT:   PseudoBR %bb.2
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $x12 = ADDI killed $x10, 1
+  ; CHECK-NEXT:   $x10 = ADDI $x0, 7
+  ; CHECK-NEXT:   PseudoRET implicit $x10, implicit $x12
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   PseudoRET
+  bb.0:
+    successors: %bb.1, %bb.2
+    liveins: $x10
+    $x11 = ADDI $x0, 7
+    BEQ killed $x10, $x11, %bb.1
+    PseudoBR %bb.2
+  bb.1:
+    liveins: $x10
+    $x12 = ADDI killed $x10, 1
+    $x10 = ADDI $x0, 7
+    PseudoRET implicit $x10, implicit $x12
+  bb.2:
+    PseudoRET
+...
+
+# The compared value is the first branch operand. Its kill in the successor
+# must be cleared when the later materialization is removed.
+
+---
+name:            bne_reg_imm_swapped
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: bne_reg_imm_swapped
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.2(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $x11 = ADDI $x0, 9
+  ; CHECK-NEXT:   BNE $x11, killed $x10, %bb.2
+  ; CHECK-NEXT:   PseudoBR %bb.1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   $x10 = ADDI $x0, 9
+  ; CHECK-NEXT:   PseudoRET implicit $x10
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   PseudoRET
+  bb.0:
+    successors: %bb.2, %bb.1
+    liveins: $x10
+    $x11 = ADDI $x0, 9
+    BNE $x11, killed $x10, %bb.2
+    PseudoBR %bb.1
+  bb.1:
+    $x10 = ADDI $x0, 9
+    PseudoRET implicit $x10
+  bb.2:
+    PseudoRET
+...

>From 8069c49727011931c0449c0d278006bd267ca2a0 Mon Sep 17 00:00:00 2001
From: tinfeng <1768309929 at qq.com>
Date: Thu, 1 Oct 2026 12:08:31 +0800
Subject: [PATCH 2/3] [RISCV] Eliminate redundant materializations after
 register comparisons

---
 .../RISCV/RISCVRedundantCopyElimination.cpp   | 68 +++++++++++++++++--
 .../RISCV/redundant-copy-elim-reg-imm.mir     | 19 +++---
 .../test/CodeGen/RISCV/redundant-copy-elim.ll |  9 +--
 .../RISCV/xandesperf-redundant-copy-elim.ll   |  9 +--
 .../RISCV/xqcibi-redundant-copy-elim.ll       | 16 ++---
 5 files changed, 84 insertions(+), 37 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVRedundantCopyElimination.cpp b/llvm/lib/Target/RISCV/RISCVRedundantCopyElimination.cpp
index 2e0e6ab2408d7..327c2104b7958 100644
--- a/llvm/lib/Target/RISCV/RISCVRedundantCopyElimination.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRedundantCopyElimination.cpp
@@ -20,8 +20,8 @@
 // This pass should be run after register allocation and is based on the
 // earliest versions of AArch64RedundantCopyElimination.
 //
-// FIXME: Support compare with non-zero immediates where the immediate is stored
-// in a register.
+// The pass also handles register-register branches when one operand is
+// materialized as a non-zero immediate in the predecessor block.
 //
 //===----------------------------------------------------------------------===//
 
@@ -32,6 +32,7 @@
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/RegisterClassInfo.h"
 #include "llvm/Support/Debug.h"
+#include <optional>
 
 using namespace llvm;
 
@@ -108,6 +109,32 @@ guaranteesRegEqualsImmInBlock(MachineBasicBlock &MBB,
   return false;
 }
 
+static std::optional<int64_t>
+getRegImmediateBeforeTerminator(MachineBasicBlock &MBB, Register Reg,
+                                const TargetRegisterInfo *TRI) {
+  // A write to X0 is discarded, so it cannot establish a nonzero value.
+  if (Reg == RISCV::X0)
+    return std::nullopt;
+
+  for (auto I = MBB.getFirstTerminator(); I != MBB.begin();) {
+    MachineInstr &MI = *--I;
+    if (!MI.modifiesRegister(Reg, TRI))
+      continue;
+    // The last modification must define Reg itself to a known immediate.
+    if (MI.getOpcode() == RISCV::ADDI && MI.getOperand(0).isReg() &&
+        MI.getOperand(0).getReg() == Reg &&
+        MI.getOperand(1).isReg() && MI.getOperand(1).getReg() == RISCV::X0 &&
+        MI.getOperand(2).isImm())
+      return MI.getOperand(2).getImm();
+    if (MI.getOpcode() == RISCV::QC_LI && MI.getOperand(0).isReg() &&
+        MI.getOperand(0).getReg() == Reg &&
+        MI.getOperand(1).isImm())
+      return MI.getOperand(1).getImm();
+    return std::nullopt;
+  }
+  return std::nullopt;
+}
+
 bool RISCVRedundantCopyElimination::optimizeBlock(MachineBasicBlock &MBB) {
   // Check if the current basic block has a single predecessor.
   if (MBB.pred_size() != 1)
@@ -131,8 +158,35 @@ bool RISCVRedundantCopyElimination::optimizeBlock(MachineBasicBlock &MBB) {
     return false;
 
   bool IsZeroCopy = guaranteesZeroRegInBlock(MBB, Cond, TBB);
+  bool IsImmCopy =
+      !IsZeroCopy && guaranteesRegEqualsImmInBlock(MBB, Cond, TBB);
+  int64_t CompareImm = IsImmCopy ? Cond[2].getImm() : 0;
+  if (!IsZeroCopy && !IsImmCopy && Cond.size() == 3 &&
+      (Cond[0].getImm() == RISCV::BEQ || Cond[0].getImm() == RISCV::BNE) &&
+      Cond[2].isReg()) {
+    // One branch operand may have been materialized with ADDI or QC_LI.
+    // The other operand is known to have the same value on the equality edge,
+    // irrespective of the operand order.
+    std::optional<int64_t> Imm =
+        getRegImmediateBeforeTerminator(*PredMBB, Cond[2].getReg(), TRI);
+    if (Imm && *Imm != 0) {
+      TargetReg = Cond[1].getReg();
+      CompareImm = *Imm;
+      IsImmCopy = true;
+    } else {
+      Imm = getRegImmediateBeforeTerminator(*PredMBB, Cond[1].getReg(), TRI);
+      if (Imm && *Imm != 0) {
+        TargetReg = Cond[2].getReg();
+        CompareImm = *Imm;
+        IsImmCopy = true;
+      }
+    }
+    // For BEQ, equality is guaranteed on the taken edge. For BNE, it is
+    // guaranteed on the fallthrough edge.
+    IsImmCopy &= (Cond[0].getImm() == RISCV::BEQ) == (TBB == &MBB);
+  }
 
-  if (!IsZeroCopy && !guaranteesRegEqualsImmInBlock(MBB, Cond, TBB))
+  if (!IsZeroCopy && !IsImmCopy)
     return false;
 
   bool Changed = false;
@@ -161,14 +215,14 @@ bool RISCVRedundantCopyElimination::optimizeBlock(MachineBasicBlock &MBB) {
         Register SrcReg = MI->getOperand(1).getReg();
         int64_t Imm = MI->getOperand(2).getImm();
         if (SrcReg == RISCV::X0 && !MRI->isReserved(DefReg) &&
-            TargetReg == DefReg && Imm == Cond[2].getImm())
+            TargetReg == DefReg && Imm == CompareImm)
           RemoveMI = true;
       } else if (MI->getOpcode() == RISCV::QC_LI && MI->getOperand(0).isReg() &&
                  MI->getOperand(1).isImm()) {
         Register DefReg = MI->getOperand(0).getReg();
         int64_t Imm = MI->getOperand(1).getImm();
         if (!MRI->isReserved(DefReg) && TargetReg == DefReg &&
-            Imm == Cond[2].getImm())
+            Imm == CompareImm)
           RemoveMI = true;
       }
     }
@@ -203,7 +257,9 @@ bool RISCVRedundantCopyElimination::optimizeBlock(MachineBasicBlock &MBB) {
           CondBr->getOpcode() == RISCV::NDS_BEQC ||
           CondBr->getOpcode() == RISCV::NDS_BNEC) &&
          "Unexpected opcode");
-  assert(CondBr->getOperand(0).getReg() == TargetReg && "Unexpected register");
+  assert((CondBr->getOperand(0).getReg() == TargetReg ||
+          CondBr->getOperand(1).getReg() == TargetReg) &&
+         "Unexpected register");
 
   // Otherwise, we have to fixup the use-def chain, starting with the
   // BEQ(I)/BNE(I). Conservatively mark as much as we can live.
diff --git a/llvm/test/CodeGen/RISCV/redundant-copy-elim-reg-imm.mir b/llvm/test/CodeGen/RISCV/redundant-copy-elim-reg-imm.mir
index 16d8aca98fa25..162f118b1b583 100644
--- a/llvm/test/CodeGen/RISCV/redundant-copy-elim-reg-imm.mir
+++ b/llvm/test/CodeGen/RISCV/redundant-copy-elim-reg-imm.mir
@@ -23,13 +23,13 @@ body:             |
   ; CHECK-NEXT:   liveins: $x10
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT:   $x11 = ADDI $x0, 7
-  ; CHECK-NEXT:   BEQ $x11, killed $x10, %bb.1
+  ; CHECK-NEXT:   BEQ $x11, $x10, %bb.1
   ; CHECK-NEXT:   PseudoBR %bb.2
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.1:
   ; CHECK-NEXT:   successors: %bb.2(0x80000000)
+  ; CHECK-NEXT:   liveins: $x10
   ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   $x10 = ADDI $x0, 7
   ; CHECK-NEXT:   PseudoRET implicit $x10
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.2:
@@ -59,11 +59,12 @@ body:             |
   ; CHECK-NEXT:   liveins: $x10
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT:   $x11 = QC_LI 9
-  ; CHECK-NEXT:   BNE killed $x10, $x11, %bb.2
+  ; CHECK-NEXT:   BNE $x10, $x11, %bb.2
   ; CHECK-NEXT:   PseudoBR %bb.1
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.1:
-  ; CHECK-NEXT:   $x10 = ADDI $x0, 9
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT:   PseudoRET implicit $x10
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.2:
@@ -274,14 +275,13 @@ body:             |
   ; CHECK-NEXT:   liveins: $x10
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT:   $x11 = ADDI $x0, 7
-  ; CHECK-NEXT:   BEQ killed $x10, $x11, %bb.1
+  ; CHECK-NEXT:   BEQ $x10, $x11, %bb.1
   ; CHECK-NEXT:   PseudoBR %bb.2
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.1:
   ; CHECK-NEXT:   liveins: $x10
   ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   $x12 = ADDI killed $x10, 1
-  ; CHECK-NEXT:   $x10 = ADDI $x0, 7
+  ; CHECK-NEXT:   $x12 = ADDI $x10, 1
   ; CHECK-NEXT:   PseudoRET implicit $x10, implicit $x12
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.2:
@@ -314,11 +314,12 @@ body:             |
   ; CHECK-NEXT:   liveins: $x10
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT:   $x11 = ADDI $x0, 9
-  ; CHECK-NEXT:   BNE $x11, killed $x10, %bb.2
+  ; CHECK-NEXT:   BNE $x11, $x10, %bb.2
   ; CHECK-NEXT:   PseudoBR %bb.1
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.1:
-  ; CHECK-NEXT:   $x10 = ADDI $x0, 9
+  ; CHECK-NEXT:   liveins: $x10
+  ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT:   PseudoRET implicit $x10
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.2:
diff --git a/llvm/test/CodeGen/RISCV/redundant-copy-elim.ll b/llvm/test/CodeGen/RISCV/redundant-copy-elim.ll
index a93514dfaedc6..cc72d46c0de85 100644
--- a/llvm/test/CodeGen/RISCV/redundant-copy-elim.ll
+++ b/llvm/test/CodeGen/RISCV/redundant-copy-elim.ll
@@ -8,12 +8,10 @@ define i32 @test_beqi(i32 %a) nounwind {
 ; RV32I-LABEL: test_beqi:
 ; RV32I:       # %bb.0: # %entry
 ; RV32I-NEXT:    li a1, 7
-; RV32I-NEXT:    bne a0, a1, .LBB0_2
-; RV32I-NEXT:  # %bb.1: # %if.end
-; RV32I-NEXT:    li a0, 7
-; RV32I-NEXT:    ret
-; RV32I-NEXT:  .LBB0_2: # %if.then
+; RV32I-NEXT:    beq a0, a1, .LBB0_2
+; RV32I-NEXT:  # %bb.1: # %if.then
 ; RV32I-NEXT:    li a0, 1
+; RV32I-NEXT:  .LBB0_2: # %if.end
 ; RV32I-NEXT:    ret
 ;
 ; RV32IZIBI-LABEL: test_beqi:
@@ -41,7 +39,6 @@ define i32 @test_bnei(i32 %a) nounwind {
 ; RV32I-NEXT:    li a0, 1
 ; RV32I-NEXT:    ret
 ; RV32I-NEXT:  .LBB1_2: # %if.then
-; RV32I-NEXT:    li a0, 7
 ; RV32I-NEXT:    ret
 ;
 ; RV32IZIBI-LABEL: test_bnei:
diff --git a/llvm/test/CodeGen/RISCV/xandesperf-redundant-copy-elim.ll b/llvm/test/CodeGen/RISCV/xandesperf-redundant-copy-elim.ll
index d01eb2082a6fc..12497baa67556 100644
--- a/llvm/test/CodeGen/RISCV/xandesperf-redundant-copy-elim.ll
+++ b/llvm/test/CodeGen/RISCV/xandesperf-redundant-copy-elim.ll
@@ -8,12 +8,10 @@ define i32 @test_beqc(i32 %a) nounwind {
 ; RV32I-LABEL: test_beqc:
 ; RV32I:       # %bb.0: # %entry
 ; RV32I-NEXT:    li a1, 7
-; RV32I-NEXT:    bne a0, a1, .LBB0_2
-; RV32I-NEXT:  # %bb.1: # %if.end
-; RV32I-NEXT:    li a0, 7
-; RV32I-NEXT:    ret
-; RV32I-NEXT:  .LBB0_2: # %if.then
+; RV32I-NEXT:    beq a0, a1, .LBB0_2
+; RV32I-NEXT:  # %bb.1: # %if.then
 ; RV32I-NEXT:    li a0, 1
+; RV32I-NEXT:  .LBB0_2: # %if.end
 ; RV32I-NEXT:    ret
 ;
 ; RV32IXANDESPERF-LABEL: test_beqc:
@@ -41,7 +39,6 @@ define i32 @test_bnec(i32 %a) nounwind {
 ; RV32I-NEXT:    li a0, 1
 ; RV32I-NEXT:    ret
 ; RV32I-NEXT:  .LBB1_2: # %if.then
-; RV32I-NEXT:    li a0, 7
 ; RV32I-NEXT:    ret
 ;
 ; RV32IXANDESPERF-LABEL: test_bnec:
diff --git a/llvm/test/CodeGen/RISCV/xqcibi-redundant-copy-elim.ll b/llvm/test/CodeGen/RISCV/xqcibi-redundant-copy-elim.ll
index df5c6a21b0868..8bd370c48947f 100644
--- a/llvm/test/CodeGen/RISCV/xqcibi-redundant-copy-elim.ll
+++ b/llvm/test/CodeGen/RISCV/xqcibi-redundant-copy-elim.ll
@@ -10,12 +10,10 @@ define dso_local i32 @test_beqi(i32 %a) nounwind {
 ; RV32I-LABEL: test_beqi:
 ; RV32I:       # %bb.0: # %entry
 ; RV32I-NEXT:    li a1, 7
-; RV32I-NEXT:    bne a0, a1, .LBB0_2
-; RV32I-NEXT:  # %bb.1: # %if.end
-; RV32I-NEXT:    li a0, 7
-; RV32I-NEXT:    ret
-; RV32I-NEXT:  .LBB0_2: # %if.then
+; RV32I-NEXT:    beq a0, a1, .LBB0_2
+; RV32I-NEXT:  # %bb.1: # %if.then
 ; RV32I-NEXT:    li a0, 1
+; RV32I-NEXT:  .LBB0_2: # %if.end
 ; RV32I-NEXT:    ret
 ;
 ; RV32IXQCIBI-LABEL: test_beqi:
@@ -54,12 +52,10 @@ define dso_local i32 @test_e_beqi(i32 %a) nounwind {
 ; RV32I-LABEL: test_e_beqi:
 ; RV32I:       # %bb.0: # %entry
 ; RV32I-NEXT:    li a1, 40
-; RV32I-NEXT:    bne a0, a1, .LBB1_2
-; RV32I-NEXT:  # %bb.1: # %if.end
-; RV32I-NEXT:    li a0, 40
-; RV32I-NEXT:    ret
-; RV32I-NEXT:  .LBB1_2: # %if.then
+; RV32I-NEXT:    beq a0, a1, .LBB1_2
+; RV32I-NEXT:  # %bb.1: # %if.then
 ; RV32I-NEXT:    li a0, 1
+; RV32I-NEXT:  .LBB1_2: # %if.end
 ; RV32I-NEXT:    ret
 ;
 ; RV32IXQCIBI-LABEL: test_e_beqi:

>From d0bf60559666614fe219f7d22c2f9b43a29c5f29 Mon Sep 17 00:00:00 2001
From: tinfeng <1768309929 at qq.com>
Date: Thu, 1 Oct 2026 16:02:47 +0800
Subject: [PATCH 3/3] [RISCV] Fix formatting

---
 .../Target/RISCV/RISCVRedundantCopyElimination.cpp    | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVRedundantCopyElimination.cpp b/llvm/lib/Target/RISCV/RISCVRedundantCopyElimination.cpp
index 327c2104b7958..ccf9fc2b040f6 100644
--- a/llvm/lib/Target/RISCV/RISCVRedundantCopyElimination.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRedundantCopyElimination.cpp
@@ -122,13 +122,11 @@ getRegImmediateBeforeTerminator(MachineBasicBlock &MBB, Register Reg,
       continue;
     // The last modification must define Reg itself to a known immediate.
     if (MI.getOpcode() == RISCV::ADDI && MI.getOperand(0).isReg() &&
-        MI.getOperand(0).getReg() == Reg &&
-        MI.getOperand(1).isReg() && MI.getOperand(1).getReg() == RISCV::X0 &&
-        MI.getOperand(2).isImm())
+        MI.getOperand(0).getReg() == Reg && MI.getOperand(1).isReg() &&
+        MI.getOperand(1).getReg() == RISCV::X0 && MI.getOperand(2).isImm())
       return MI.getOperand(2).getImm();
     if (MI.getOpcode() == RISCV::QC_LI && MI.getOperand(0).isReg() &&
-        MI.getOperand(0).getReg() == Reg &&
-        MI.getOperand(1).isImm())
+        MI.getOperand(0).getReg() == Reg && MI.getOperand(1).isImm())
       return MI.getOperand(1).getImm();
     return std::nullopt;
   }
@@ -158,8 +156,7 @@ bool RISCVRedundantCopyElimination::optimizeBlock(MachineBasicBlock &MBB) {
     return false;
 
   bool IsZeroCopy = guaranteesZeroRegInBlock(MBB, Cond, TBB);
-  bool IsImmCopy =
-      !IsZeroCopy && guaranteesRegEqualsImmInBlock(MBB, Cond, TBB);
+  bool IsImmCopy = !IsZeroCopy && guaranteesRegEqualsImmInBlock(MBB, Cond, TBB);
   int64_t CompareImm = IsImmCopy ? Cond[2].getImm() : 0;
   if (!IsZeroCopy && !IsImmCopy && Cond.size() == 3 &&
       (Cond[0].getImm() == RISCV::BEQ || Cond[0].getImm() == RISCV::BNE) &&



More information about the llvm-commits mailing list