[llvm] [CodeGen] Fold load into LZCNT/TZCNT/POPCNT after compare elimination in peephole optimizer (PR #194662)
via llvm-commits
llvm-commits at lists.llvm.org
Tue May 12 20:12:59 PDT 2026
https://github.com/Michael-Chen-NJU updated https://github.com/llvm/llvm-project/pull/194662
>From c44c37f7e51c9d3c6d0a429449417e42341781fe Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <221250121 at smail.nju.edu.cn>
Date: Tue, 28 Apr 2026 23:38:53 +0800
Subject: [PATCH 1/4] [CodeGen] Fold load into LZCNT/TZCNT/POPCNT after compare
elimination in peephole optimizer
---
llvm/lib/CodeGen/PeepholeOptimizer.cpp | 42 +++++++
llvm/test/CodeGen/X86/cttz.ll | 13 +--
llvm/test/CodeGen/X86/freeze-unary.ll | 3 +-
.../lzcnt-tzcnt-popcnt-load-fold-with-cmov.ll | 104 ++++++++++++++++++
4 files changed, 153 insertions(+), 9 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/lzcnt-tzcnt-popcnt-load-fold-with-cmov.ll
diff --git a/llvm/lib/CodeGen/PeepholeOptimizer.cpp b/llvm/lib/CodeGen/PeepholeOptimizer.cpp
index d10cf18b1c5e2..5c4daadb305c3 100644
--- a/llvm/lib/CodeGen/PeepholeOptimizer.cpp
+++ b/llvm/lib/CodeGen/PeepholeOptimizer.cpp
@@ -1825,6 +1825,16 @@ bool PeepholeOptimizer::run(MachineFunction &MF) {
NAPhysToVirtMIs.clear();
}
+ // SrcReg must be captured before MI is erased inside optimizeCmpInstr.
+ Register CmpSrcReg;
+ if (MI->isCompare()) {
+ Register SrcReg2;
+ int64_t CmpMask, CmpValue;
+ if (!TII->analyzeCompare(*MI, CmpSrcReg, SrcReg2, CmpMask, CmpValue) ||
+ CmpSrcReg.isPhysical() || SrcReg2.isPhysical())
+ CmpSrcReg = Register();
+ }
+
if ((isUncoalescableCopy(*MI) &&
optimizeUncoalescableCopy(*MI, LocalMIs)) ||
(MI->isCompare() && optimizeCmpInstr(*MI)) ||
@@ -1832,6 +1842,38 @@ bool PeepholeOptimizer::run(MachineFunction &MF) {
// MI is deleted.
LocalMIs.erase(MI);
Changed = true;
+
+ // The eliminated compare may have been the extra use blocking load
+ // folding into the EFLAGS producer;
+ if (CmpSrcReg.isVirtual() && MRI->hasOneNonDBGUser(CmpSrcReg)) {
+ MachineInstr *FlagProducer =
+ MRI->use_nodbg_begin(CmpSrcReg)->getParent();
+ MachineInstr *LoadMI = MRI->getVRegDef(CmpSrcReg);
+ if (LocalMIs.count(FlagProducer) && LoadMI &&
+ LoadMI->canFoldAsLoad() && LoadMI->mayLoad() &&
+ LocalMIs.count(LoadMI)) {
+ Register FoldReg = CmpSrcReg;
+ MachineInstr *DefMI = nullptr;
+ MachineInstr *CopyMI = nullptr;
+ if (MachineInstr *FoldMI = TII->optimizeLoadInstr(
+ *FlagProducer, MRI, FoldReg, DefMI, CopyMI)) {
+ LLVM_DEBUG(dbgs() << "Replacing: " << *FlagProducer);
+ LLVM_DEBUG(dbgs() << " With: " << *FoldMI);
+ LocalMIs.erase(FlagProducer);
+ LocalMIs.erase(LoadMI);
+ LocalMIs.insert(FoldMI);
+ if (CopyMI)
+ LocalMIs.insert(CopyMI);
+ if (FlagProducer->shouldUpdateAdditionalCallInfo())
+ FlagProducer->getMF()->moveAdditionalCallInfo(FlagProducer,
+ FoldMI);
+ FlagProducer->eraseFromParent();
+ DefMI->eraseFromParent();
+ MRI->markUsesInDebugValueAsUndef(CmpSrcReg);
+ ++NumLoadFold;
+ }
+ }
+ }
continue;
}
diff --git a/llvm/test/CodeGen/X86/cttz.ll b/llvm/test/CodeGen/X86/cttz.ll
index a88fb96dd7c8c..9890450a1c195 100644
--- a/llvm/test/CodeGen/X86/cttz.ll
+++ b/llvm/test/CodeGen/X86/cttz.ll
@@ -379,13 +379,12 @@ define i64 @cttz_i64_zero_test(i64 %n) nounwind {
;
; X86-CMOV-LABEL: cttz_i64_zero_test:
; X86-CMOV: # %bb.0:
-; X86-CMOV-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-CMOV-NEXT: bsfl {{[0-9]+}}(%esp), %ecx
-; X86-CMOV-NEXT: movl $32, %edx
-; X86-CMOV-NEXT: cmovnel %ecx, %edx
-; X86-CMOV-NEXT: addl $32, %edx
-; X86-CMOV-NEXT: bsfl %eax, %eax
-; X86-CMOV-NEXT: cmovel %edx, %eax
+; X86-CMOV-NEXT: bsfl {{[0-9]+}}(%esp), %eax
+; X86-CMOV-NEXT: movl $32, %ecx
+; X86-CMOV-NEXT: cmovnel %eax, %ecx
+; X86-CMOV-NEXT: addl $32, %ecx
+; X86-CMOV-NEXT: bsfl {{[0-9]+}}(%esp), %eax
+; X86-CMOV-NEXT: cmovel %ecx, %eax
; X86-CMOV-NEXT: xorl %edx, %edx
; X86-CMOV-NEXT: retl
;
diff --git a/llvm/test/CodeGen/X86/freeze-unary.ll b/llvm/test/CodeGen/X86/freeze-unary.ll
index 56b0ceb34fe18..222ec1eb3b9de 100644
--- a/llvm/test/CodeGen/X86/freeze-unary.ll
+++ b/llvm/test/CodeGen/X86/freeze-unary.ll
@@ -300,8 +300,7 @@ define i32 @freeze_cttz(i32 %a0) nounwind {
define i32 @freeze_cttz_poison(i32 %a0) nounwind {
; X86-LABEL: freeze_cttz_poison:
; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: bsfl %eax, %ecx
+; X86-NEXT: bsfl {{[0-9]+}}(%esp), %ecx
; X86-NEXT: movl $32, %eax
; X86-NEXT: cmovnel %ecx, %eax
; X86-NEXT: retl
diff --git a/llvm/test/CodeGen/X86/lzcnt-tzcnt-popcnt-load-fold-with-cmov.ll b/llvm/test/CodeGen/X86/lzcnt-tzcnt-popcnt-load-fold-with-cmov.ll
new file mode 100644
index 0000000000000..8a171859387a5
--- /dev/null
+++ b/llvm/test/CodeGen/X86/lzcnt-tzcnt-popcnt-load-fold-with-cmov.ll
@@ -0,0 +1,104 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+lzcnt,+bmi,+popcnt | FileCheck %s
+
+; Test that loads are folded into the memory form of LZCNT/TZCNT/POPCNT when
+; the loaded value is also used in an icmp-eq-zero/select sequence whose
+; condition is satisfied by the EFLAGS already produced by the bit-count
+; instruction (LZCNT/TZCNT set CF=1, POPCNT sets ZF=1 when input is zero).
+;
+; Before the fix, ISel chose the register form (rr) because the loaded value
+; had two uses: the bit-count instruction and the compare. The peephole
+; optimizer later removed the redundant TEST but missed folding the load into
+; the now single-use bit-count instruction.
+; See https://github.com/llvm/llvm-project/issues/164782
+
+; --- lzcnt: CF=1 when input is zero, cmovb takes the fallback ---
+
+define i32 @lzcnt32_load_cmov(ptr %p0, i32 %a1) {
+; CHECK-LABEL: lzcnt32_load_cmov:
+; CHECK: # %bb.0:
+; CHECK-NEXT: lzcntl (%rdi), %eax
+; CHECK-NEXT: cmovbl %esi, %eax
+; CHECK-NEXT: retq
+ %v = load i32, ptr %p0, align 4
+ %cnt = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %v, i1 true)
+ %iszero = icmp eq i32 %v, 0
+ %res = select i1 %iszero, i32 %a1, i32 %cnt
+ ret i32 %res
+}
+
+define i64 @lzcnt64_load_cmov(ptr %p0, i64 %a1) {
+; CHECK-LABEL: lzcnt64_load_cmov:
+; CHECK: # %bb.0:
+; CHECK-NEXT: lzcntq (%rdi), %rax
+; CHECK-NEXT: cmovbq %rsi, %rax
+; CHECK-NEXT: retq
+ %v = load i64, ptr %p0, align 8
+ %cnt = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 %v, i1 true)
+ %iszero = icmp eq i64 %v, 0
+ %res = select i1 %iszero, i64 %a1, i64 %cnt
+ ret i64 %res
+}
+
+; --- tzcnt: CF=1 when input is zero, cmovb takes the fallback ---
+
+define i32 @tzcnt32_load_cmov(ptr %p0, i32 %a1) {
+; CHECK-LABEL: tzcnt32_load_cmov:
+; CHECK: # %bb.0:
+; CHECK-NEXT: tzcntl (%rdi), %eax
+; CHECK-NEXT: cmovbl %esi, %eax
+; CHECK-NEXT: retq
+ %v = load i32, ptr %p0, align 4
+ %cnt = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 %v, i1 true)
+ %iszero = icmp eq i32 %v, 0
+ %res = select i1 %iszero, i32 %a1, i32 %cnt
+ ret i32 %res
+}
+
+define i64 @tzcnt64_load_cmov(ptr %p0, i64 %a1) {
+; CHECK-LABEL: tzcnt64_load_cmov:
+; CHECK: # %bb.0:
+; CHECK-NEXT: tzcntq (%rdi), %rax
+; CHECK-NEXT: cmovbq %rsi, %rax
+; CHECK-NEXT: retq
+ %v = load i64, ptr %p0, align 8
+ %cnt = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 %v, i1 true)
+ %iszero = icmp eq i64 %v, 0
+ %res = select i1 %iszero, i64 %a1, i64 %cnt
+ ret i64 %res
+}
+
+; --- popcnt: ZF=1 when input is zero, cmove takes the fallback ---
+
+define i32 @popcnt32_load_cmov(ptr %p0, i32 %a1) {
+; CHECK-LABEL: popcnt32_load_cmov:
+; CHECK: # %bb.0:
+; CHECK-NEXT: popcntl (%rdi), %eax
+; CHECK-NEXT: cmovel %esi, %eax
+; CHECK-NEXT: retq
+ %v = load i32, ptr %p0, align 4
+ %cnt = tail call i32 @llvm.ctpop.i32(i32 %v)
+ %iszero = icmp eq i32 %v, 0
+ %res = select i1 %iszero, i32 %a1, i32 %cnt
+ ret i32 %res
+}
+
+define i64 @popcnt64_load_cmov(ptr %p0, i64 %a1) {
+; CHECK-LABEL: popcnt64_load_cmov:
+; CHECK: # %bb.0:
+; CHECK-NEXT: popcntq (%rdi), %rax
+; CHECK-NEXT: cmoveq %rsi, %rax
+; CHECK-NEXT: retq
+ %v = load i64, ptr %p0, align 8
+ %cnt = tail call i64 @llvm.ctpop.i64(i64 %v)
+ %iszero = icmp eq i64 %v, 0
+ %res = select i1 %iszero, i64 %a1, i64 %cnt
+ ret i64 %res
+}
+
+declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone
+declare i64 @llvm.ctlz.i64(i64, i1) nounwind readnone
+declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone
+declare i64 @llvm.cttz.i64(i64, i1) nounwind readnone
+declare i32 @llvm.ctpop.i32(i32) nounwind readnone
+declare i64 @llvm.ctpop.i64(i64) nounwind readnone
>From 3384fcd4314981b40fce9d5ccb992d82e22ae47a Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <221250121 at smail.nju.edu.cn>
Date: Thu, 7 May 2026 09:48:36 +0800
Subject: [PATCH 2/4] [CodeGen][test] Drop redundant declares and add negative
tests for lzcnt/tzcnt/popcnt load-fold
---
.../lzcnt-tzcnt-popcnt-load-fold-with-cmov.ll | 37 ++++++++++++++++---
1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/llvm/test/CodeGen/X86/lzcnt-tzcnt-popcnt-load-fold-with-cmov.ll b/llvm/test/CodeGen/X86/lzcnt-tzcnt-popcnt-load-fold-with-cmov.ll
index 8a171859387a5..41d87a75be7e0 100644
--- a/llvm/test/CodeGen/X86/lzcnt-tzcnt-popcnt-load-fold-with-cmov.ll
+++ b/llvm/test/CodeGen/X86/lzcnt-tzcnt-popcnt-load-fold-with-cmov.ll
@@ -96,9 +96,34 @@ define i64 @popcnt64_load_cmov(ptr %p0, i64 %a1) {
ret i64 %res
}
-declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone
-declare i64 @llvm.ctlz.i64(i64, i1) nounwind readnone
-declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone
-declare i64 @llvm.cttz.i64(i64, i1) nounwind readnone
-declare i32 @llvm.ctpop.i32(i32) nounwind readnone
-declare i64 @llvm.ctpop.i64(i64) nounwind readnone
+; --- negative: icmp against non-zero constant; load must NOT be folded ---
+
+define i32 @lzcnt32_no_fold_nonzero_cmp(ptr %p0, i32 %a1) {
+; CHECK-LABEL: lzcnt32_no_fold_nonzero_cmp:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movl (%rdi), %ecx
+; CHECK-NEXT: lzcntl %ecx, %eax
+; CHECK-NEXT: cmpl $1, %ecx
+; CHECK-NEXT: cmovel %esi, %eax
+; CHECK-NEXT: retq
+ %v = load i32, ptr %p0, align 4
+ %cnt = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %v, i1 true)
+ %isone = icmp eq i32 %v, 1
+ %res = select i1 %isone, i32 %a1, i32 %cnt
+ ret i32 %res
+}
+
+define i32 @lzcnt32_no_fold_var_cmp(ptr %p0, i32 %a1, i32 %a2) {
+; CHECK-LABEL: lzcnt32_no_fold_var_cmp:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movl (%rdi), %ecx
+; CHECK-NEXT: lzcntl %ecx, %eax
+; CHECK-NEXT: cmpl %edx, %ecx
+; CHECK-NEXT: cmovel %esi, %eax
+; CHECK-NEXT: retq
+ %v = load i32, ptr %p0, align 4
+ %cnt = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %v, i1 true)
+ %eq = icmp eq i32 %v, %a2
+ %res = select i1 %eq, i32 %a1, i32 %cnt
+ ret i32 %res
+}
>From cf56438d9189e67d11b5d9c938ab80b05a22a8b3 Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <221250121 at smail.nju.edu.cn>
Date: Mon, 11 May 2026 15:53:07 +0800
Subject: [PATCH 3/4] [CodeGen] Split compare handling out of compound if, fix
generic comment, rename test
---
llvm/lib/CodeGen/PeepholeOptimizer.cpp | 60 +++++++------------
...-with-cmov.ll => bitcnt-load-with-cmov.ll} | 0
2 files changed, 21 insertions(+), 39 deletions(-)
rename llvm/test/CodeGen/X86/{lzcnt-tzcnt-popcnt-load-fold-with-cmov.ll => bitcnt-load-with-cmov.ll} (100%)
diff --git a/llvm/lib/CodeGen/PeepholeOptimizer.cpp b/llvm/lib/CodeGen/PeepholeOptimizer.cpp
index 5c4daadb305c3..d3bb21c662b3d 100644
--- a/llvm/lib/CodeGen/PeepholeOptimizer.cpp
+++ b/llvm/lib/CodeGen/PeepholeOptimizer.cpp
@@ -1825,55 +1825,37 @@ bool PeepholeOptimizer::run(MachineFunction &MF) {
NAPhysToVirtMIs.clear();
}
- // SrcReg must be captured before MI is erased inside optimizeCmpInstr.
- Register CmpSrcReg;
if (MI->isCompare()) {
- Register SrcReg2;
+ Register CmpSrcReg, SrcReg2;
int64_t CmpMask, CmpValue;
- if (!TII->analyzeCompare(*MI, CmpSrcReg, SrcReg2, CmpMask, CmpValue) ||
- CmpSrcReg.isPhysical() || SrcReg2.isPhysical())
- CmpSrcReg = Register();
+ // Capture CmpSrcReg before MI is erased inside optimizeCmpInstr.
+ bool HaveVirtSrc =
+ TII->analyzeCompare(*MI, CmpSrcReg, SrcReg2, CmpMask, CmpValue) &&
+ CmpSrcReg.isVirtual() && !SrcReg2.isPhysical();
+ if (optimizeCmpInstr(*MI)) {
+ LocalMIs.erase(MI);
+ Changed = true;
+ // The eliminated compare may have been the extra use preventing a
+ // load from being folded into the flag-setting instruction.
+ if (HaveVirtSrc && MRI->hasOneNonDBGUser(CmpSrcReg)) {
+ MachineInstr *FlagProducer =
+ MRI->use_nodbg_begin(CmpSrcReg)->getParent();
+ MachineInstr *LoadMI = MRI->getVRegDef(CmpSrcReg);
+ if (LocalMIs.count(FlagProducer) && LoadMI &&
+ LoadMI->canFoldAsLoad() && LoadMI->mayLoad() &&
+ LocalMIs.count(LoadMI))
+ foldLoadInto(MF, *FlagProducer, CmpSrcReg, LocalMIs);
+ }
+ continue;
+ }
}
if ((isUncoalescableCopy(*MI) &&
optimizeUncoalescableCopy(*MI, LocalMIs)) ||
- (MI->isCompare() && optimizeCmpInstr(*MI)) ||
(MI->isSelect() && optimizeSelect(*MI, LocalMIs))) {
// MI is deleted.
LocalMIs.erase(MI);
Changed = true;
-
- // The eliminated compare may have been the extra use blocking load
- // folding into the EFLAGS producer;
- if (CmpSrcReg.isVirtual() && MRI->hasOneNonDBGUser(CmpSrcReg)) {
- MachineInstr *FlagProducer =
- MRI->use_nodbg_begin(CmpSrcReg)->getParent();
- MachineInstr *LoadMI = MRI->getVRegDef(CmpSrcReg);
- if (LocalMIs.count(FlagProducer) && LoadMI &&
- LoadMI->canFoldAsLoad() && LoadMI->mayLoad() &&
- LocalMIs.count(LoadMI)) {
- Register FoldReg = CmpSrcReg;
- MachineInstr *DefMI = nullptr;
- MachineInstr *CopyMI = nullptr;
- if (MachineInstr *FoldMI = TII->optimizeLoadInstr(
- *FlagProducer, MRI, FoldReg, DefMI, CopyMI)) {
- LLVM_DEBUG(dbgs() << "Replacing: " << *FlagProducer);
- LLVM_DEBUG(dbgs() << " With: " << *FoldMI);
- LocalMIs.erase(FlagProducer);
- LocalMIs.erase(LoadMI);
- LocalMIs.insert(FoldMI);
- if (CopyMI)
- LocalMIs.insert(CopyMI);
- if (FlagProducer->shouldUpdateAdditionalCallInfo())
- FlagProducer->getMF()->moveAdditionalCallInfo(FlagProducer,
- FoldMI);
- FlagProducer->eraseFromParent();
- DefMI->eraseFromParent();
- MRI->markUsesInDebugValueAsUndef(CmpSrcReg);
- ++NumLoadFold;
- }
- }
- }
continue;
}
diff --git a/llvm/test/CodeGen/X86/lzcnt-tzcnt-popcnt-load-fold-with-cmov.ll b/llvm/test/CodeGen/X86/bitcnt-load-with-cmov.ll
similarity index 100%
rename from llvm/test/CodeGen/X86/lzcnt-tzcnt-popcnt-load-fold-with-cmov.ll
rename to llvm/test/CodeGen/X86/bitcnt-load-with-cmov.ll
>From 79926641609ba6b6b0448d7f38c384043a78363f Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <221250121 at smail.nju.edu.cn>
Date: Wed, 13 May 2026 11:07:49 +0800
Subject: [PATCH 4/4] [CodeGen] Move load-fold logic into optimizeCmpInstr to
avoid double analyzeCompare
---
llvm/lib/CodeGen/PeepholeOptimizer.cpp | 54 ++++++++++++--------------
1 file changed, 24 insertions(+), 30 deletions(-)
diff --git a/llvm/lib/CodeGen/PeepholeOptimizer.cpp b/llvm/lib/CodeGen/PeepholeOptimizer.cpp
index d3bb21c662b3d..cfbffb920ef36 100644
--- a/llvm/lib/CodeGen/PeepholeOptimizer.cpp
+++ b/llvm/lib/CodeGen/PeepholeOptimizer.cpp
@@ -444,7 +444,8 @@ class PeepholeOptimizer : private MachineFunction::Delegate {
using RecurrenceCycle = SmallVector<RecurrenceInstr, 4>;
private:
- bool optimizeCmpInstr(MachineInstr &MI);
+ bool optimizeCmpInstr(MachineInstr &MI, MachineFunction &MF,
+ SmallPtrSet<MachineInstr *, 16> &LocalMIs);
bool optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB,
SmallPtrSetImpl<MachineInstr *> &LocalMIs);
bool optimizeSelect(MachineInstr &MI,
@@ -943,7 +944,9 @@ bool PeepholeOptimizer::optimizeExtInstr(
/// against already sets (or could be modified to set) the same flag as the
/// compare, then we can remove the comparison and use the flag from the
/// previous instruction.
-bool PeepholeOptimizer::optimizeCmpInstr(MachineInstr &MI) {
+bool PeepholeOptimizer::optimizeCmpInstr(
+ MachineInstr &MI, MachineFunction &MF,
+ SmallPtrSet<MachineInstr *, 16> &LocalMIs) {
// If this instruction is a comparison against zero and isn't comparing a
// physical register, we can try to optimize it.
Register SrcReg, SrcReg2;
@@ -954,13 +957,23 @@ bool PeepholeOptimizer::optimizeCmpInstr(MachineInstr &MI) {
// Attempt to optimize the comparison instruction.
LLVM_DEBUG(dbgs() << "Attempting to optimize compare: " << MI);
- if (TII->optimizeCompareInstr(MI, SrcReg, SrcReg2, CmpMask, CmpValue, MRI)) {
- LLVM_DEBUG(dbgs() << " -> Successfully optimized compare!\n");
- ++NumCmps;
- return true;
+ if (!TII->optimizeCompareInstr(MI, SrcReg, SrcReg2, CmpMask, CmpValue, MRI))
+ return false;
+
+ LLVM_DEBUG(dbgs() << " -> Successfully optimized compare!\n");
+ ++NumCmps;
+
+ // The eliminated compare may have been the extra use preventing a
+ // load from being folded into the flag-setting instruction.
+ if (SrcReg.isVirtual() && MRI->hasOneNonDBGUser(SrcReg)) {
+ MachineInstr *FlagProducer = MRI->use_nodbg_begin(SrcReg)->getParent();
+ MachineInstr *LoadMI = MRI->getVRegDef(SrcReg);
+ if (LocalMIs.count(FlagProducer) && LoadMI && LoadMI->canFoldAsLoad() &&
+ LoadMI->mayLoad() && LocalMIs.count(LoadMI))
+ foldLoadInto(MF, *FlagProducer, SrcReg, LocalMIs);
}
- return false;
+ return true;
}
/// Optimize a select instruction.
@@ -1825,29 +1838,10 @@ bool PeepholeOptimizer::run(MachineFunction &MF) {
NAPhysToVirtMIs.clear();
}
- if (MI->isCompare()) {
- Register CmpSrcReg, SrcReg2;
- int64_t CmpMask, CmpValue;
- // Capture CmpSrcReg before MI is erased inside optimizeCmpInstr.
- bool HaveVirtSrc =
- TII->analyzeCompare(*MI, CmpSrcReg, SrcReg2, CmpMask, CmpValue) &&
- CmpSrcReg.isVirtual() && !SrcReg2.isPhysical();
- if (optimizeCmpInstr(*MI)) {
- LocalMIs.erase(MI);
- Changed = true;
- // The eliminated compare may have been the extra use preventing a
- // load from being folded into the flag-setting instruction.
- if (HaveVirtSrc && MRI->hasOneNonDBGUser(CmpSrcReg)) {
- MachineInstr *FlagProducer =
- MRI->use_nodbg_begin(CmpSrcReg)->getParent();
- MachineInstr *LoadMI = MRI->getVRegDef(CmpSrcReg);
- if (LocalMIs.count(FlagProducer) && LoadMI &&
- LoadMI->canFoldAsLoad() && LoadMI->mayLoad() &&
- LocalMIs.count(LoadMI))
- foldLoadInto(MF, *FlagProducer, CmpSrcReg, LocalMIs);
- }
- continue;
- }
+ if (MI->isCompare() && optimizeCmpInstr(*MI, MF, LocalMIs)) {
+ LocalMIs.erase(MI);
+ Changed = true;
+ continue;
}
if ((isUncoalescableCopy(*MI) &&
More information about the llvm-commits
mailing list