[llvm] [X86] Add post-RA redundant copy elimination for TEST/CMP branch paths (PR #203733)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 13 17:23:51 PDT 2026


github-actions[bot] wrote:

<!--LLVM CODE FORMAT COMMENT: {clang-format}-->


:warning: C/C++ code formatter, clang-format found issues in your code. :warning:

<details>
<summary>
You can test this locally with the following command:
</summary>

``````````bash
git-clang-format --diff origin/main HEAD --extensions h,cpp -- llvm/lib/Target/X86/X86RedundantCopyElimination.cpp llvm/lib/Target/X86/X86.h llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp llvm/lib/Target/X86/X86TargetMachine.cpp --diff_from_common_commit
``````````

:warning:
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing `origin/main` to the base branch/commit you want to compare against.
:warning:

</details>

<details>
<summary>
View the diff from clang-format here.
</summary>

``````````diff
diff --git a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
index f240e1069..bd484ea62 100644
--- a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
@@ -163,8 +163,7 @@ void X86CodeGenPassBuilder::addPreRegAlloc(PassManagerWrapper &PMW) const {
 }
 
 void X86CodeGenPassBuilder::addPostRegAlloc(PassManagerWrapper &PMW) const {
-  if (getOptLevel() != CodeGenOptLevel::None &&
-      EnableRedundantCopyElimination)
+  if (getOptLevel() != CodeGenOptLevel::None && EnableRedundantCopyElimination)
     addMachineFunctionPass(X86RedundantCopyEliminationPass(), PMW);
   addMachineFunctionPass(X86LowerTileCopyPass(), PMW);
   addMachineFunctionPass(X86FPStackifierPass(), PMW);
diff --git a/llvm/lib/Target/X86/X86RedundantCopyElimination.cpp b/llvm/lib/Target/X86/X86RedundantCopyElimination.cpp
index 46bb7577d..3086d1e3f 100644
--- a/llvm/lib/Target/X86/X86RedundantCopyElimination.cpp
+++ b/llvm/lib/Target/X86/X86RedundantCopyElimination.cpp
@@ -66,7 +66,6 @@ public:
   bool run(MachineFunction &MF);
 
 private:
-
   const TargetRegisterInfo *TRI;
   const TargetInstrInfo *TII;
 
@@ -111,7 +110,7 @@ bool X86RedundantCopyEliminationImpl::optimizeBlock(MachineBasicBlock &MBB) {
     return false;
 
   X86::CondCode CC = static_cast<X86::CondCode>(Cond[0].getImm());
-  
+
   MachineBasicBlock *NextOnPath = Path.empty() ? &MBB : Path.back();
   bool IsTruePath = (NextOnPath == TBB);
   if (!IsTruePath) {
@@ -148,8 +147,8 @@ bool X86RedundantCopyEliminationImpl::optimizeBlock(MachineBasicBlock &MBB) {
   SmallVector<std::pair<MCPhysReg, KnownValue>, 4> KnownRegs;
 
   // Helper: is the equality/zero path taken?
-  bool IsEqualPath = (CC == X86::COND_E && IsTruePath) ||
-                     (CC == X86::COND_NE && !IsTruePath);
+  bool IsEqualPath =
+      (CC == X86::COND_E && IsTruePath) || (CC == X86::COND_NE && !IsTruePath);
 
   // Analyze the flag setter.
   switch (FlagSetter->getOpcode()) {
@@ -158,8 +157,10 @@ bool X86RedundantCopyEliminationImpl::optimizeBlock(MachineBasicBlock &MBB) {
 
   // TEST is BinOpRR_F: (outs), (ins $src1, $src2) — no destination register.
   // Operand 0 = $src1, Operand 1 = $src2.
-  case X86::TEST8rr: case X86::TEST16rr:
-  case X86::TEST32rr: case X86::TEST64rr:
+  case X86::TEST8rr:
+  case X86::TEST16rr:
+  case X86::TEST32rr:
+  case X86::TEST64rr:
     if (FlagSetter->getOperand(0).getReg() ==
         FlagSetter->getOperand(1).getReg()) {
       if (IsEqualPath)
@@ -171,10 +172,14 @@ bool X86RedundantCopyEliminationImpl::optimizeBlock(MachineBasicBlock &MBB) {
   // AND/OR are BinOpRR_RF: (outs $dst), (ins $src1, $src2).
   // Operand 0 = $dst (tied to $src1), Operand 1 = $src1, Operand 2 = $src2.
   // Self-AND/OR (src1 == src2) sets ZF iff the value is zero.
-  case X86::AND8rr: case X86::AND16rr:
-  case X86::AND32rr: case X86::AND64rr:
-  case X86::OR8rr: case X86::OR16rr:
-  case X86::OR32rr: case X86::OR64rr:
+  case X86::AND8rr:
+  case X86::AND16rr:
+  case X86::AND32rr:
+  case X86::AND64rr:
+  case X86::OR8rr:
+  case X86::OR16rr:
+  case X86::OR32rr:
+  case X86::OR64rr:
     if (FlagSetter->getOperand(1).getReg() ==
         FlagSetter->getOperand(2).getReg()) {
       if (IsEqualPath)
@@ -185,21 +190,29 @@ bool X86RedundantCopyEliminationImpl::optimizeBlock(MachineBasicBlock &MBB) {
 
   // CMP reg, reg is BinOpRR_F: (outs), (ins $src1, $src2).
   // If equal, $src1 == $src2.
-  case X86::CMP8rr: case X86::CMP16rr:
-  case X86::CMP32rr: case X86::CMP64rr:
+  case X86::CMP8rr:
+  case X86::CMP16rr:
+  case X86::CMP32rr:
+  case X86::CMP64rr:
     if (IsEqualPath) {
-      KnownRegs.push_back({FlagSetter->getOperand(0).getReg(),
-                        KnownValue((MCPhysReg)FlagSetter->getOperand(1).getReg())});
-      KnownRegs.push_back({FlagSetter->getOperand(1).getReg(),
-                        KnownValue((MCPhysReg)FlagSetter->getOperand(0).getReg())});
+      KnownRegs.push_back(
+          {FlagSetter->getOperand(0).getReg(),
+           KnownValue((MCPhysReg)FlagSetter->getOperand(1).getReg())});
+      KnownRegs.push_back(
+          {FlagSetter->getOperand(1).getReg(),
+           KnownValue((MCPhysReg)FlagSetter->getOperand(0).getReg())});
     }
     break;
 
   // CMP reg, imm: (outs), (ins $src1, $imm).
   // If equal, $src1 == $imm.
-  case X86::CMP8ri: case X86::CMP16ri: case X86::CMP16ri8:
-  case X86::CMP32ri: case X86::CMP32ri8:
-  case X86::CMP64ri8: case X86::CMP64ri32:
+  case X86::CMP8ri:
+  case X86::CMP16ri:
+  case X86::CMP16ri8:
+  case X86::CMP32ri:
+  case X86::CMP32ri8:
+  case X86::CMP64ri8:
+  case X86::CMP64ri32:
     if (IsEqualPath && FlagSetter->getOperand(1).isImm()) {
       int64_t Imm = FlagSetter->getOperand(1).getImm();
       KnownRegs.push_back(
@@ -208,10 +221,13 @@ bool X86RedundantCopyEliminationImpl::optimizeBlock(MachineBasicBlock &MBB) {
     break;
 
   // SUB reg, reg is BinOpRR_RF: (outs $dst), (ins $src1, $src2).
-  // If ZF set, $dst is zero. (Note: src1 and src2 were equal before the instruction,
-  // but $dst is tied to $src1, so $src1 is overwritten with zero and no longer equals $src2).
-  case X86::SUB8rr: case X86::SUB16rr:
-  case X86::SUB32rr: case X86::SUB64rr:
+  // If ZF set, $dst is zero. (Note: src1 and src2 were equal before the
+  // instruction, but $dst is tied to $src1, so $src1 is overwritten with zero
+  // and no longer equals $src2).
+  case X86::SUB8rr:
+  case X86::SUB16rr:
+  case X86::SUB32rr:
+  case X86::SUB64rr:
     if (IsEqualPath) {
       KnownRegs.push_back(
           {FlagSetter->getOperand(0).getReg(), KnownValue((int64_t)0)});
@@ -225,13 +241,17 @@ bool X86RedundantCopyEliminationImpl::optimizeBlock(MachineBasicBlock &MBB) {
   // Check if any known register was clobbered in the path.
   auto isClobbered = [&](MCPhysReg Reg) {
     // Check BranchMBB from FlagSetter to end
-    for (MachineInstr &MI : make_range(std::next(MachineBasicBlock::iterator(FlagSetter)), BranchMBB->end())) {
-      if (MI.modifiesRegister(Reg, TRI)) return true;
+    for (MachineInstr &MI :
+         make_range(std::next(MachineBasicBlock::iterator(FlagSetter)),
+                    BranchMBB->end())) {
+      if (MI.modifiesRegister(Reg, TRI))
+        return true;
     }
     // Check Path blocks
     for (auto *PMBB : llvm::reverse(Path)) {
       for (MachineInstr &MI : *PMBB) {
-        if (MI.modifiesRegister(Reg, TRI)) return true;
+        if (MI.modifiesRegister(Reg, TRI))
+          return true;
       }
     }
     return false;
@@ -252,7 +272,7 @@ bool X86RedundantCopyEliminationImpl::optimizeBlock(MachineBasicBlock &MBB) {
 
   bool Changed = false;
   MachineBasicBlock::iterator LastChange = MBB.begin();
-  
+
   SmallVector<MCPhysReg, 4> OptimizedRegs;
 
   for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E;) {
@@ -264,9 +284,10 @@ bool X86RedundantCopyEliminationImpl::optimizeBlock(MachineBasicBlock &MBB) {
     // move-immediates matching a known constant from CMP reg, imm.
     if (isRedundantZeroDefinition(*MI)) {
       Register DefReg = MI->getOperand(0).getReg();
-      auto It = llvm::find_if(KnownRegs, [&](const std::pair<MCPhysReg, KnownValue> &K) {
-        return K.first == DefReg;
-      });
+      auto It = llvm::find_if(KnownRegs,
+                              [&](const std::pair<MCPhysReg, KnownValue> &K) {
+                                return K.first == DefReg;
+                              });
       if (It != KnownRegs.end() && !It->second.IsReg && It->second.U.Imm == 0) {
         LLVM_DEBUG(dbgs() << "Remove redundant zero definition: " << *MI);
         MI->eraseFromParent();
@@ -279,9 +300,10 @@ bool X86RedundantCopyEliminationImpl::optimizeBlock(MachineBasicBlock &MBB) {
     } else if (MI->isMoveImmediate() && MI->getOperand(1).isImm()) {
       Register DefReg = MI->getOperand(0).getReg();
       int64_t MIImm = MI->getOperand(1).getImm();
-      auto It = llvm::find_if(KnownRegs, [&](const std::pair<MCPhysReg, KnownValue> &K) {
-        return K.first == DefReg;
-      });
+      auto It = llvm::find_if(KnownRegs,
+                              [&](const std::pair<MCPhysReg, KnownValue> &K) {
+                                return K.first == DefReg;
+                              });
       if (It != KnownRegs.end() && !It->second.IsReg &&
           It->second.U.Imm == MIImm) {
         LLVM_DEBUG(dbgs() << "Remove redundant immediate definition: " << *MI);
@@ -298,10 +320,12 @@ bool X86RedundantCopyEliminationImpl::optimizeBlock(MachineBasicBlock &MBB) {
     if (MI->isCopy() || MI->isMoveReg()) {
       Register DefReg = MI->getOperand(0).getReg();
       Register SrcReg = MI->getOperand(1).getReg();
-      auto It = llvm::find_if(KnownRegs, [&](const std::pair<MCPhysReg, KnownValue> &K) {
-        return K.first == DefReg;
-      });
-      if (It != KnownRegs.end() && It->second.IsReg && It->second.U.Reg == SrcReg) {
+      auto It = llvm::find_if(KnownRegs,
+                              [&](const std::pair<MCPhysReg, KnownValue> &K) {
+                                return K.first == DefReg;
+                              });
+      if (It != KnownRegs.end() && It->second.IsReg &&
+          It->second.U.Reg == SrcReg) {
         LLVM_DEBUG(dbgs() << "Remove redundant register copy: " << *MI);
         MI->eraseFromParent();
         Changed = true;
@@ -315,7 +339,8 @@ bool X86RedundantCopyEliminationImpl::optimizeBlock(MachineBasicBlock &MBB) {
     // Remove clobbered registers from KnownRegs.
     for (unsigned i = 0; i < KnownRegs.size();) {
       if (MI->modifiesRegister(KnownRegs[i].first, TRI) ||
-          (KnownRegs[i].second.IsReg && MI->modifiesRegister(KnownRegs[i].second.U.Reg, TRI))) {
+          (KnownRegs[i].second.IsReg &&
+           MI->modifiesRegister(KnownRegs[i].second.U.Reg, TRI))) {
         KnownRegs[i] = KnownRegs.back();
         KnownRegs.pop_back();
       } else {
diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp
index d12133358..4fc4c3bf4 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -540,8 +540,7 @@ void X86PassConfig::addMachineSSAOptimization() {
 }
 
 void X86PassConfig::addPostRegAlloc() {
-  if (getOptLevel() != CodeGenOptLevel::None &&
-      EnableRedundantCopyElimination)
+  if (getOptLevel() != CodeGenOptLevel::None && EnableRedundantCopyElimination)
     addPass(createX86RedundantCopyEliminationLegacyPass());
   addPass(createX86LowerTileCopyLegacyPass());
   addPass(createX86FPStackifierLegacyPass());

``````````

</details>


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


More information about the llvm-commits mailing list