[llvm] [X86] Remove redundant `cmp` before `adc` after `lzcnt` or `tzcnt` (PR #208392)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 13 23:50:57 PDT 2026


https://github.com/VachanVY updated https://github.com/llvm/llvm-project/pull/208392

>From e9766f66423c91c43b17b7bdfbad34904e8a8a08 Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Thu, 9 Jul 2026 13:25:06 +0530
Subject: [PATCH 1/9] [X86] pre commit tests

Remove redundant `cmp` before `adc` after `lzcnt` or `tzcnt`
---
 .../X86/remove-redundant-cmp-lzcnt-tzcnt.ll   | 160 ++++++++++++++++++
 1 file changed, 160 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll

diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
new file mode 100644
index 0000000000000..e0302cbd6ccc8
--- /dev/null
+++ b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
@@ -0,0 +1,160 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=znver5 | FileCheck %s
+
+declare i64 @llvm.ctlz.i64(i64, i1)
+declare i32 @llvm.ctlz.i32(i32, i1)
+declare i16 @llvm.ctlz.i16(i16, i1)
+declare i64 @llvm.cttz.i64(i64, i1)
+declare i32 @llvm.cttz.i32(i32, i1)
+declare i16 @llvm.cttz.i16(i16, i1)
+
+define i64 @remove_redundant_cmp_lzcnt_i64(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_lzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rax
+; CHECK-NEXT:    cmpq $1, %rdi
+; CHECK-NEXT:    adcq $0, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp eq i64 %0, 0
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i32 @remove_redundant_cmp_lzcnt_i32(i32 %0) {
+; CHECK-LABEL: remove_redundant_cmp_lzcnt_i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntl %edi, %eax
+; CHECK-NEXT:    cmpl $1, %edi
+; CHECK-NEXT:    adcl $0, %eax
+; CHECK-NEXT:    retq
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp eq i32 %0, 0
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i16 @remove_redundant_cmp_lzcnt_i16(i16 %0) {
+; CHECK-LABEL: remove_redundant_cmp_lzcnt_i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntw %di, %ax
+; CHECK-NEXT:    cmpw $1, %di
+; CHECK-NEXT:    adcw $0, %ax
+; CHECK-NEXT:    retq
+  %2 = tail call i16 @llvm.ctlz.i16(i16 %0, i1 false)
+  %3 = icmp eq i16 %0, 0
+  %4 = zext i1 %3 to i16
+  %5 = add nuw nsw i16 %2, %4
+  ret i16 %5
+}
+
+define i64 @remove_redundant_cmp_lzcnt_no_constant(i64 %0, i64 %1) {
+; CHECK-LABEL: remove_redundant_cmp_lzcnt_no_constant:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    cmpq %rsi, %rdi
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %3 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %4 = icmp eq i64 %0, %1
+  %5 = zext i1 %4 to i64
+  %6 = add nuw nsw i64 %3, %5
+  ret i64 %6
+}
+
+define i64 @remove_redundant_cmp_lzcnt_wrong_const(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_lzcnt_wrong_const:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp eq i64 %0, 2
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_tzcnt_i64(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_tzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rax
+; CHECK-NEXT:    cmpq $1, %rdi
+; CHECK-NEXT:    adcq $0, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp eq i64 %0, 0
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i32 @remove_redundant_cmp_tzcnt_i32(i32 %0) {
+; CHECK-LABEL: remove_redundant_cmp_tzcnt_i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntl %edi, %eax
+; CHECK-NEXT:    cmpl $1, %edi
+; CHECK-NEXT:    adcl $0, %eax
+; CHECK-NEXT:    retq
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp eq i32 %0, 0
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i16 @remove_redundant_cmp_tzcnt_i16(i16 %0) {
+; CHECK-LABEL: remove_redundant_cmp_tzcnt_i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    orl $65536, %eax # imm = 0x10000
+; CHECK-NEXT:    tzcntl %eax, %eax
+; CHECK-NEXT:    cmpw $1, %di
+; CHECK-NEXT:    adcw $0, %ax
+; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
+; CHECK-NEXT:    retq
+  %2 = tail call i16 @llvm.cttz.i16(i16 %0, i1 false)
+  %3 = icmp eq i16 %0, 0
+  %4 = zext i1 %3 to i16
+  %5 = add nuw nsw i16 %2, %4
+  ret i16 %5
+}
+
+define i64 @remove_redundant_cmp_tzcnt_no_constant(i64 %0, i64 %1) {
+; CHECK-LABEL: remove_redundant_cmp_tzcnt_no_constant:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    cmpq %rsi, %rdi
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %3 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %4 = icmp eq i64 %0, %1
+  %5 = zext i1 %4 to i64
+  %6 = add nuw nsw i64 %3, %5
+  ret i64 %6
+}
+
+define i64 @remove_redundant_cmp_tzcnt_wrong_const(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_tzcnt_wrong_const:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp eq i64 %0, 2
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}

>From fb9464a99b4bd2c821eb4c8bbed9db875bff7d9c Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Thu, 9 Jul 2026 13:47:19 +0530
Subject: [PATCH 2/9] [X86] optimization code with DIFF

---
 llvm/lib/Target/X86/X86InstrInfo.cpp                 | 12 ++++++++++++
 .../CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll  |  5 -----
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp
index 7ff2400d06d1d..db4ac9fc0a3e3 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -4993,6 +4993,18 @@ bool X86InstrInfo::isRedundantFlagInstr(const MachineInstr &FlagI,
     }
     return FlagI.isIdenticalTo(OI);
   }
+  case X86::LZCNT16rr:
+  case X86::LZCNT32rr:
+  case X86::LZCNT64rr:
+  case X86::TZCNT16rr:
+  case X86::TZCNT32rr:
+  case X86::TZCNT64rr: {
+    if (ImmMask != 0 && !SrcReg2.isValid() && ImmValue == 1 &&
+        OI.getOperand(1).isReg() && SrcReg == OI.getOperand(1).getReg()) {
+      return true;
+    }
+    return false;
+  }
   default:
     return false;
   }
diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
index e0302cbd6ccc8..d836fc51817f8 100644
--- a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
+++ b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
@@ -12,7 +12,6 @@ define i64 @remove_redundant_cmp_lzcnt_i64(i64 %0) {
 ; CHECK-LABEL: remove_redundant_cmp_lzcnt_i64:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    lzcntq %rdi, %rax
-; CHECK-NEXT:    cmpq $1, %rdi
 ; CHECK-NEXT:    adcq $0, %rax
 ; CHECK-NEXT:    retq
   %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
@@ -26,7 +25,6 @@ define i32 @remove_redundant_cmp_lzcnt_i32(i32 %0) {
 ; CHECK-LABEL: remove_redundant_cmp_lzcnt_i32:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    lzcntl %edi, %eax
-; CHECK-NEXT:    cmpl $1, %edi
 ; CHECK-NEXT:    adcl $0, %eax
 ; CHECK-NEXT:    retq
   %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
@@ -40,7 +38,6 @@ define i16 @remove_redundant_cmp_lzcnt_i16(i16 %0) {
 ; CHECK-LABEL: remove_redundant_cmp_lzcnt_i16:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    lzcntw %di, %ax
-; CHECK-NEXT:    cmpw $1, %di
 ; CHECK-NEXT:    adcw $0, %ax
 ; CHECK-NEXT:    retq
   %2 = tail call i16 @llvm.ctlz.i16(i16 %0, i1 false)
@@ -86,7 +83,6 @@ define i64 @remove_redundant_cmp_tzcnt_i64(i64 %0) {
 ; CHECK-LABEL: remove_redundant_cmp_tzcnt_i64:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    tzcntq %rdi, %rax
-; CHECK-NEXT:    cmpq $1, %rdi
 ; CHECK-NEXT:    adcq $0, %rax
 ; CHECK-NEXT:    retq
   %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
@@ -100,7 +96,6 @@ define i32 @remove_redundant_cmp_tzcnt_i32(i32 %0) {
 ; CHECK-LABEL: remove_redundant_cmp_tzcnt_i32:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    tzcntl %edi, %eax
-; CHECK-NEXT:    cmpl $1, %edi
 ; CHECK-NEXT:    adcl $0, %eax
 ; CHECK-NEXT:    retq
   %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)

>From 3f4151c4c0cfd8744adc86f6b51e54ffb1008244 Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Thu, 9 Jul 2026 16:11:41 +0530
Subject: [PATCH 3/9] [X86] address failing test in different file

---
 llvm/test/CodeGen/X86/bitcnt-load-with-cmov.ll | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/llvm/test/CodeGen/X86/bitcnt-load-with-cmov.ll b/llvm/test/CodeGen/X86/bitcnt-load-with-cmov.ll
index d3d6b25b60c16..0a159143efa74 100644
--- a/llvm/test/CodeGen/X86/bitcnt-load-with-cmov.ll
+++ b/llvm/test/CodeGen/X86/bitcnt-load-with-cmov.ll
@@ -101,9 +101,7 @@ define i64 @popcnt64_load_cmov(ptr %p0, i64 %a1) {
 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:    lzcntl (%rdi), %eax
 ; CHECK-NEXT:    cmovel %esi, %eax
 ; CHECK-NEXT:    retq
   %v = load i32, ptr %p0, align 4

>From 995fe2f834720e51e2571710df746267fd36d343 Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Thu, 9 Jul 2026 22:57:52 +0530
Subject: [PATCH 4/9] [X86] i686 test converage && `-mattr=+bmi,+lzcnt` instead
 of `-mcpu=znver5`

---
 .../X86/remove-redundant-cmp-lzcnt-tzcnt.ll   | 327 ++++++++++++++----
 1 file changed, 253 insertions(+), 74 deletions(-)

diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
index d836fc51817f8..6d7a5c18b6e9e 100644
--- a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
+++ b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
@@ -1,19 +1,38 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=znver5 | FileCheck %s
-
-declare i64 @llvm.ctlz.i64(i64, i1)
-declare i32 @llvm.ctlz.i32(i32, i1)
-declare i16 @llvm.ctlz.i16(i16, i1)
-declare i64 @llvm.cttz.i64(i64, i1)
-declare i32 @llvm.cttz.i32(i32, i1)
-declare i16 @llvm.cttz.i16(i16, i1)
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X64
+; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X86
 
 define i64 @remove_redundant_cmp_lzcnt_i64(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_lzcnt_i64:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntq %rdi, %rax
-; CHECK-NEXT:    adcq $0, %rax
-; CHECK-NEXT:    retq
+; X64-LABEL: remove_redundant_cmp_lzcnt_i64:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntq %rdi, %rax
+; X64-NEXT:    adcq $0, %rax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_lzcnt_i64:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 8
+; X86-NEXT:    .cfi_offset %esi, -8
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    testl %edx, %edx
+; X86-NEXT:    jne .LBB0_1
+; X86-NEXT:  # %bb.2:
+; X86-NEXT:    lzcntl %ecx, %esi
+; X86-NEXT:    addl $32, %esi
+; X86-NEXT:    jmp .LBB0_3
+; X86-NEXT:  .LBB0_1:
+; X86-NEXT:    lzcntl %edx, %esi
+; X86-NEXT:  .LBB0_3:
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    orl %edx, %ecx
+; X86-NEXT:    sete %al
+; X86-NEXT:    addl %esi, %eax
+; X86-NEXT:    xorl %edx, %edx
+; X86-NEXT:    popl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    retl
   %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
   %3 = icmp eq i64 %0, 0
   %4 = zext i1 %3 to i64
@@ -22,11 +41,17 @@ define i64 @remove_redundant_cmp_lzcnt_i64(i64 %0) {
 }
 
 define i32 @remove_redundant_cmp_lzcnt_i32(i32 %0) {
-; CHECK-LABEL: remove_redundant_cmp_lzcnt_i32:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntl %edi, %eax
-; CHECK-NEXT:    adcl $0, %eax
-; CHECK-NEXT:    retq
+; X64-LABEL: remove_redundant_cmp_lzcnt_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %eax
+; X64-NEXT:    adcl $0, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_lzcnt_i32:
+; X86:       # %bb.0:
+; X86-NEXT:    lzcntl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    adcl $0, %eax
+; X86-NEXT:    retl
   %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
   %3 = icmp eq i32 %0, 0
   %4 = zext i1 %3 to i32
@@ -35,11 +60,17 @@ define i32 @remove_redundant_cmp_lzcnt_i32(i32 %0) {
 }
 
 define i16 @remove_redundant_cmp_lzcnt_i16(i16 %0) {
-; CHECK-LABEL: remove_redundant_cmp_lzcnt_i16:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntw %di, %ax
-; CHECK-NEXT:    adcw $0, %ax
-; CHECK-NEXT:    retq
+; X64-LABEL: remove_redundant_cmp_lzcnt_i16:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntw %di, %ax
+; X64-NEXT:    adcw $0, %ax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_lzcnt_i16:
+; X86:       # %bb.0:
+; X86-NEXT:    lzcntw {{[0-9]+}}(%esp), %ax
+; X86-NEXT:    adcw $0, %ax
+; X86-NEXT:    retl
   %2 = tail call i16 @llvm.ctlz.i16(i16 %0, i1 false)
   %3 = icmp eq i16 %0, 0
   %4 = zext i1 %3 to i16
@@ -48,14 +79,41 @@ define i16 @remove_redundant_cmp_lzcnt_i16(i16 %0) {
 }
 
 define i64 @remove_redundant_cmp_lzcnt_no_constant(i64 %0, i64 %1) {
-; CHECK-LABEL: remove_redundant_cmp_lzcnt_no_constant:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntq %rdi, %rcx
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    cmpq %rsi, %rdi
-; CHECK-NEXT:    sete %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
+; X64-LABEL: remove_redundant_cmp_lzcnt_no_constant:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntq %rdi, %rcx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpq %rsi, %rdi
+; X64-NEXT:    sete %al
+; X64-NEXT:    addq %rcx, %rax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_lzcnt_no_constant:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 8
+; X86-NEXT:    .cfi_offset %esi, -8
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    testl %edx, %edx
+; X86-NEXT:    jne .LBB3_1
+; X86-NEXT:  # %bb.2:
+; X86-NEXT:    lzcntl %ecx, %esi
+; X86-NEXT:    addl $32, %esi
+; X86-NEXT:    jmp .LBB3_3
+; X86-NEXT:  .LBB3_1:
+; X86-NEXT:    lzcntl %edx, %esi
+; X86-NEXT:  .LBB3_3:
+; X86-NEXT:    xorl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    xorl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    orl %edx, %ecx
+; X86-NEXT:    sete %al
+; X86-NEXT:    addl %esi, %eax
+; X86-NEXT:    xorl %edx, %edx
+; X86-NEXT:    popl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    retl
   %3 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
   %4 = icmp eq i64 %0, %1
   %5 = zext i1 %4 to i64
@@ -64,14 +122,40 @@ define i64 @remove_redundant_cmp_lzcnt_no_constant(i64 %0, i64 %1) {
 }
 
 define i64 @remove_redundant_cmp_lzcnt_wrong_const(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_lzcnt_wrong_const:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntq %rdi, %rcx
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    cmpq $2, %rdi
-; CHECK-NEXT:    sete %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
+; X64-LABEL: remove_redundant_cmp_lzcnt_wrong_const:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntq %rdi, %rcx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpq $2, %rdi
+; X64-NEXT:    sete %al
+; X64-NEXT:    addq %rcx, %rax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_lzcnt_wrong_const:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 8
+; X86-NEXT:    .cfi_offset %esi, -8
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    testl %edx, %edx
+; X86-NEXT:    jne .LBB4_1
+; X86-NEXT:  # %bb.2:
+; X86-NEXT:    lzcntl %ecx, %esi
+; X86-NEXT:    addl $32, %esi
+; X86-NEXT:    jmp .LBB4_3
+; X86-NEXT:  .LBB4_1:
+; X86-NEXT:    lzcntl %edx, %esi
+; X86-NEXT:  .LBB4_3:
+; X86-NEXT:    xorl $2, %ecx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    orl %edx, %ecx
+; X86-NEXT:    sete %al
+; X86-NEXT:    addl %esi, %eax
+; X86-NEXT:    xorl %edx, %edx
+; X86-NEXT:    popl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    retl
   %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
   %3 = icmp eq i64 %0, 2
   %4 = zext i1 %3 to i64
@@ -80,11 +164,36 @@ define i64 @remove_redundant_cmp_lzcnt_wrong_const(i64 %0) {
 }
 
 define i64 @remove_redundant_cmp_tzcnt_i64(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_tzcnt_i64:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    tzcntq %rdi, %rax
-; CHECK-NEXT:    adcq $0, %rax
-; CHECK-NEXT:    retq
+; X64-LABEL: remove_redundant_cmp_tzcnt_i64:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntq %rdi, %rax
+; X64-NEXT:    adcq $0, %rax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_tzcnt_i64:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 8
+; X86-NEXT:    .cfi_offset %esi, -8
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    testl %ecx, %ecx
+; X86-NEXT:    jne .LBB5_1
+; X86-NEXT:  # %bb.2:
+; X86-NEXT:    tzcntl %edx, %esi
+; X86-NEXT:    addl $32, %esi
+; X86-NEXT:    jmp .LBB5_3
+; X86-NEXT:  .LBB5_1:
+; X86-NEXT:    tzcntl %ecx, %esi
+; X86-NEXT:  .LBB5_3:
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    orl %edx, %ecx
+; X86-NEXT:    sete %al
+; X86-NEXT:    addl %esi, %eax
+; X86-NEXT:    xorl %edx, %edx
+; X86-NEXT:    popl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    retl
   %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
   %3 = icmp eq i64 %0, 0
   %4 = zext i1 %3 to i64
@@ -93,11 +202,17 @@ define i64 @remove_redundant_cmp_tzcnt_i64(i64 %0) {
 }
 
 define i32 @remove_redundant_cmp_tzcnt_i32(i32 %0) {
-; CHECK-LABEL: remove_redundant_cmp_tzcnt_i32:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    tzcntl %edi, %eax
-; CHECK-NEXT:    adcl $0, %eax
-; CHECK-NEXT:    retq
+; X64-LABEL: remove_redundant_cmp_tzcnt_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %eax
+; X64-NEXT:    adcl $0, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_tzcnt_i32:
+; X86:       # %bb.0:
+; X86-NEXT:    tzcntl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    adcl $0, %eax
+; X86-NEXT:    retl
   %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
   %3 = icmp eq i32 %0, 0
   %4 = zext i1 %3 to i32
@@ -106,15 +221,26 @@ define i32 @remove_redundant_cmp_tzcnt_i32(i32 %0) {
 }
 
 define i16 @remove_redundant_cmp_tzcnt_i16(i16 %0) {
-; CHECK-LABEL: remove_redundant_cmp_tzcnt_i16:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl %edi, %eax
-; CHECK-NEXT:    orl $65536, %eax # imm = 0x10000
-; CHECK-NEXT:    tzcntl %eax, %eax
-; CHECK-NEXT:    cmpw $1, %di
-; CHECK-NEXT:    adcw $0, %ax
-; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
-; CHECK-NEXT:    retq
+; X64-LABEL: remove_redundant_cmp_tzcnt_i16:
+; X64:       # %bb.0:
+; X64-NEXT:    movl %edi, %eax
+; X64-NEXT:    orl $65536, %eax # imm = 0x10000
+; X64-NEXT:    tzcntl %eax, %eax
+; X64-NEXT:    cmpw $1, %di
+; X64-NEXT:    adcw $0, %ax
+; X64-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_tzcnt_i16:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl %ecx, %eax
+; X86-NEXT:    orl $65536, %eax # imm = 0x10000
+; X86-NEXT:    tzcntl %eax, %eax
+; X86-NEXT:    cmpw $1, %cx
+; X86-NEXT:    adcw $0, %ax
+; X86-NEXT:    # kill: def $ax killed $ax killed $eax
+; X86-NEXT:    retl
   %2 = tail call i16 @llvm.cttz.i16(i16 %0, i1 false)
   %3 = icmp eq i16 %0, 0
   %4 = zext i1 %3 to i16
@@ -123,14 +249,41 @@ define i16 @remove_redundant_cmp_tzcnt_i16(i16 %0) {
 }
 
 define i64 @remove_redundant_cmp_tzcnt_no_constant(i64 %0, i64 %1) {
-; CHECK-LABEL: remove_redundant_cmp_tzcnt_no_constant:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    tzcntq %rdi, %rcx
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    cmpq %rsi, %rdi
-; CHECK-NEXT:    sete %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
+; X64-LABEL: remove_redundant_cmp_tzcnt_no_constant:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntq %rdi, %rcx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpq %rsi, %rdi
+; X64-NEXT:    sete %al
+; X64-NEXT:    addq %rcx, %rax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_tzcnt_no_constant:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 8
+; X86-NEXT:    .cfi_offset %esi, -8
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    testl %ecx, %ecx
+; X86-NEXT:    jne .LBB8_1
+; X86-NEXT:  # %bb.2:
+; X86-NEXT:    tzcntl %edx, %esi
+; X86-NEXT:    addl $32, %esi
+; X86-NEXT:    jmp .LBB8_3
+; X86-NEXT:  .LBB8_1:
+; X86-NEXT:    tzcntl %ecx, %esi
+; X86-NEXT:  .LBB8_3:
+; X86-NEXT:    xorl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    xorl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    orl %edx, %ecx
+; X86-NEXT:    sete %al
+; X86-NEXT:    addl %esi, %eax
+; X86-NEXT:    xorl %edx, %edx
+; X86-NEXT:    popl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    retl
   %3 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
   %4 = icmp eq i64 %0, %1
   %5 = zext i1 %4 to i64
@@ -139,14 +292,40 @@ define i64 @remove_redundant_cmp_tzcnt_no_constant(i64 %0, i64 %1) {
 }
 
 define i64 @remove_redundant_cmp_tzcnt_wrong_const(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_tzcnt_wrong_const:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    tzcntq %rdi, %rcx
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    cmpq $2, %rdi
-; CHECK-NEXT:    sete %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
+; X64-LABEL: remove_redundant_cmp_tzcnt_wrong_const:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntq %rdi, %rcx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpq $2, %rdi
+; X64-NEXT:    sete %al
+; X64-NEXT:    addq %rcx, %rax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_tzcnt_wrong_const:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 8
+; X86-NEXT:    .cfi_offset %esi, -8
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    testl %ecx, %ecx
+; X86-NEXT:    jne .LBB9_1
+; X86-NEXT:  # %bb.2:
+; X86-NEXT:    tzcntl %edx, %esi
+; X86-NEXT:    addl $32, %esi
+; X86-NEXT:    jmp .LBB9_3
+; X86-NEXT:  .LBB9_1:
+; X86-NEXT:    tzcntl %ecx, %esi
+; X86-NEXT:  .LBB9_3:
+; X86-NEXT:    xorl $2, %ecx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    orl %edx, %ecx
+; X86-NEXT:    sete %al
+; X86-NEXT:    addl %esi, %eax
+; X86-NEXT:    xorl %edx, %edx
+; X86-NEXT:    popl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    retl
   %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
   %3 = icmp eq i64 %0, 2
   %4 = zext i1 %3 to i64

>From cc753f0e48daf0d0b32d73ab18ae0f7750def97d Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Fri, 10 Jul 2026 11:51:36 +0530
Subject: [PATCH 5/9] [X86] refactor tests -- phobewang

---
 .../remove-redundant-cmp-lzcnt-tzcnt-i64.ll   |  28 +++
 .../X86/remove-redundant-cmp-lzcnt-tzcnt.ll   | 238 ++++--------------
 2 files changed, 76 insertions(+), 190 deletions(-)
 create mode 100644 llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll

diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
new file mode 100644
index 0000000000000..6d36196997e17
--- /dev/null
+++ b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X64
+
+define i64 @remove_redundant_cmp_lzcnt_i64(i64 %0) {
+; X64-LABEL: remove_redundant_cmp_lzcnt_i64:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntq %rdi, %rax
+; X64-NEXT:    adcq $0, %rax
+; X64-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp eq i64 %0, 0
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_tzcnt_i64(i64 %0) {
+; X64-LABEL: remove_redundant_cmp_tzcnt_i64:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntq %rdi, %rax
+; X64-NEXT:    adcq $0, %rax
+; X64-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp eq i64 %0, 0
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
index 6d7a5c18b6e9e..57ac1d5e2f4c8 100644
--- a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
+++ b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
@@ -2,44 +2,6 @@
 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X64
 ; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X86
 
-define i64 @remove_redundant_cmp_lzcnt_i64(i64 %0) {
-; X64-LABEL: remove_redundant_cmp_lzcnt_i64:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntq %rdi, %rax
-; X64-NEXT:    adcq $0, %rax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_lzcnt_i64:
-; X86:       # %bb.0:
-; X86-NEXT:    pushl %esi
-; X86-NEXT:    .cfi_def_cfa_offset 8
-; X86-NEXT:    .cfi_offset %esi, -8
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    testl %edx, %edx
-; X86-NEXT:    jne .LBB0_1
-; X86-NEXT:  # %bb.2:
-; X86-NEXT:    lzcntl %ecx, %esi
-; X86-NEXT:    addl $32, %esi
-; X86-NEXT:    jmp .LBB0_3
-; X86-NEXT:  .LBB0_1:
-; X86-NEXT:    lzcntl %edx, %esi
-; X86-NEXT:  .LBB0_3:
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    orl %edx, %ecx
-; X86-NEXT:    sete %al
-; X86-NEXT:    addl %esi, %eax
-; X86-NEXT:    xorl %edx, %edx
-; X86-NEXT:    popl %esi
-; X86-NEXT:    .cfi_def_cfa_offset 4
-; X86-NEXT:    retl
-  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
-  %3 = icmp eq i64 %0, 0
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
 define i32 @remove_redundant_cmp_lzcnt_i32(i32 %0) {
 ; X64-LABEL: remove_redundant_cmp_lzcnt_i32:
 ; X64:       # %bb.0:
@@ -78,127 +40,56 @@ define i16 @remove_redundant_cmp_lzcnt_i16(i16 %0) {
   ret i16 %5
 }
 
-define i64 @remove_redundant_cmp_lzcnt_no_constant(i64 %0, i64 %1) {
+define i32 @remove_redundant_cmp_lzcnt_no_constant(i32 %0, i32 %1) {
 ; X64-LABEL: remove_redundant_cmp_lzcnt_no_constant:
 ; X64:       # %bb.0:
-; X64-NEXT:    lzcntq %rdi, %rcx
+; X64-NEXT:    lzcntl %edi, %ecx
 ; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpq %rsi, %rdi
+; X64-NEXT:    cmpl %esi, %edi
 ; X64-NEXT:    sete %al
-; X64-NEXT:    addq %rcx, %rax
+; X64-NEXT:    addl %ecx, %eax
 ; X64-NEXT:    retq
 ;
 ; X86-LABEL: remove_redundant_cmp_lzcnt_no_constant:
 ; X86:       # %bb.0:
-; X86-NEXT:    pushl %esi
-; X86-NEXT:    .cfi_def_cfa_offset 8
-; X86-NEXT:    .cfi_offset %esi, -8
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    testl %edx, %edx
-; X86-NEXT:    jne .LBB3_1
-; X86-NEXT:  # %bb.2:
-; X86-NEXT:    lzcntl %ecx, %esi
-; X86-NEXT:    addl $32, %esi
-; X86-NEXT:    jmp .LBB3_3
-; X86-NEXT:  .LBB3_1:
-; X86-NEXT:    lzcntl %edx, %esi
-; X86-NEXT:  .LBB3_3:
-; X86-NEXT:    xorl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    xorl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    lzcntl %ecx, %edx
 ; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    orl %edx, %ecx
+; X86-NEXT:    cmpl {{[0-9]+}}(%esp), %ecx
 ; X86-NEXT:    sete %al
-; X86-NEXT:    addl %esi, %eax
-; X86-NEXT:    xorl %edx, %edx
-; X86-NEXT:    popl %esi
-; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    addl %edx, %eax
 ; X86-NEXT:    retl
-  %3 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
-  %4 = icmp eq i64 %0, %1
-  %5 = zext i1 %4 to i64
-  %6 = add nuw nsw i64 %3, %5
-  ret i64 %6
+  %3 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %4 = icmp eq i32 %0, %1
+  %5 = zext i1 %4 to i32
+  %6 = add nuw nsw i32 %3, %5
+  ret i32 %6
 }
 
-define i64 @remove_redundant_cmp_lzcnt_wrong_const(i64 %0) {
+define i32 @remove_redundant_cmp_lzcnt_wrong_const(i32 %0) {
 ; X64-LABEL: remove_redundant_cmp_lzcnt_wrong_const:
 ; X64:       # %bb.0:
-; X64-NEXT:    lzcntq %rdi, %rcx
+; X64-NEXT:    lzcntl %edi, %ecx
 ; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpq $2, %rdi
+; X64-NEXT:    cmpl $2, %edi
 ; X64-NEXT:    sete %al
-; X64-NEXT:    addq %rcx, %rax
+; X64-NEXT:    addl %ecx, %eax
 ; X64-NEXT:    retq
 ;
 ; X86-LABEL: remove_redundant_cmp_lzcnt_wrong_const:
 ; X86:       # %bb.0:
-; X86-NEXT:    pushl %esi
-; X86-NEXT:    .cfi_def_cfa_offset 8
-; X86-NEXT:    .cfi_offset %esi, -8
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    testl %edx, %edx
-; X86-NEXT:    jne .LBB4_1
-; X86-NEXT:  # %bb.2:
-; X86-NEXT:    lzcntl %ecx, %esi
-; X86-NEXT:    addl $32, %esi
-; X86-NEXT:    jmp .LBB4_3
-; X86-NEXT:  .LBB4_1:
-; X86-NEXT:    lzcntl %edx, %esi
-; X86-NEXT:  .LBB4_3:
-; X86-NEXT:    xorl $2, %ecx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    orl %edx, %ecx
-; X86-NEXT:    sete %al
-; X86-NEXT:    addl %esi, %eax
-; X86-NEXT:    xorl %edx, %edx
-; X86-NEXT:    popl %esi
-; X86-NEXT:    .cfi_def_cfa_offset 4
-; X86-NEXT:    retl
-  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
-  %3 = icmp eq i64 %0, 2
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_tzcnt_i64(i64 %0) {
-; X64-LABEL: remove_redundant_cmp_tzcnt_i64:
-; X64:       # %bb.0:
-; X64-NEXT:    tzcntq %rdi, %rax
-; X64-NEXT:    adcq $0, %rax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_tzcnt_i64:
-; X86:       # %bb.0:
-; X86-NEXT:    pushl %esi
-; X86-NEXT:    .cfi_def_cfa_offset 8
-; X86-NEXT:    .cfi_offset %esi, -8
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    testl %ecx, %ecx
-; X86-NEXT:    jne .LBB5_1
-; X86-NEXT:  # %bb.2:
-; X86-NEXT:    tzcntl %edx, %esi
-; X86-NEXT:    addl $32, %esi
-; X86-NEXT:    jmp .LBB5_3
-; X86-NEXT:  .LBB5_1:
-; X86-NEXT:    tzcntl %ecx, %esi
-; X86-NEXT:  .LBB5_3:
+; X86-NEXT:    lzcntl %ecx, %edx
 ; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    orl %edx, %ecx
+; X86-NEXT:    cmpl $2, %ecx
 ; X86-NEXT:    sete %al
-; X86-NEXT:    addl %esi, %eax
-; X86-NEXT:    xorl %edx, %edx
-; X86-NEXT:    popl %esi
-; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    addl %edx, %eax
 ; X86-NEXT:    retl
-  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
-  %3 = icmp eq i64 %0, 0
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp eq i32 %0, 2
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
 }
 
 define i32 @remove_redundant_cmp_tzcnt_i32(i32 %0) {
@@ -248,87 +139,54 @@ define i16 @remove_redundant_cmp_tzcnt_i16(i16 %0) {
   ret i16 %5
 }
 
-define i64 @remove_redundant_cmp_tzcnt_no_constant(i64 %0, i64 %1) {
+define i32 @remove_redundant_cmp_tzcnt_no_constant(i32 %0, i32 %1) {
 ; X64-LABEL: remove_redundant_cmp_tzcnt_no_constant:
 ; X64:       # %bb.0:
-; X64-NEXT:    tzcntq %rdi, %rcx
+; X64-NEXT:    tzcntl %edi, %ecx
 ; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpq %rsi, %rdi
+; X64-NEXT:    cmpl %esi, %edi
 ; X64-NEXT:    sete %al
-; X64-NEXT:    addq %rcx, %rax
+; X64-NEXT:    addl %ecx, %eax
 ; X64-NEXT:    retq
 ;
 ; X86-LABEL: remove_redundant_cmp_tzcnt_no_constant:
 ; X86:       # %bb.0:
-; X86-NEXT:    pushl %esi
-; X86-NEXT:    .cfi_def_cfa_offset 8
-; X86-NEXT:    .cfi_offset %esi, -8
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    testl %ecx, %ecx
-; X86-NEXT:    jne .LBB8_1
-; X86-NEXT:  # %bb.2:
-; X86-NEXT:    tzcntl %edx, %esi
-; X86-NEXT:    addl $32, %esi
-; X86-NEXT:    jmp .LBB8_3
-; X86-NEXT:  .LBB8_1:
-; X86-NEXT:    tzcntl %ecx, %esi
-; X86-NEXT:  .LBB8_3:
-; X86-NEXT:    xorl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    xorl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    tzcntl %ecx, %edx
 ; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    orl %edx, %ecx
+; X86-NEXT:    cmpl {{[0-9]+}}(%esp), %ecx
 ; X86-NEXT:    sete %al
-; X86-NEXT:    addl %esi, %eax
-; X86-NEXT:    xorl %edx, %edx
-; X86-NEXT:    popl %esi
-; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    addl %edx, %eax
 ; X86-NEXT:    retl
-  %3 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
-  %4 = icmp eq i64 %0, %1
-  %5 = zext i1 %4 to i64
-  %6 = add nuw nsw i64 %3, %5
-  ret i64 %6
+  %3 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %4 = icmp eq i32 %0, %1
+  %5 = zext i1 %4 to i32
+  %6 = add nuw nsw i32 %3, %5
+  ret i32 %6
 }
 
-define i64 @remove_redundant_cmp_tzcnt_wrong_const(i64 %0) {
+define i32 @remove_redundant_cmp_tzcnt_wrong_const(i32 %0) {
 ; X64-LABEL: remove_redundant_cmp_tzcnt_wrong_const:
 ; X64:       # %bb.0:
-; X64-NEXT:    tzcntq %rdi, %rcx
+; X64-NEXT:    tzcntl %edi, %ecx
 ; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpq $2, %rdi
+; X64-NEXT:    cmpl $2, %edi
 ; X64-NEXT:    sete %al
-; X64-NEXT:    addq %rcx, %rax
+; X64-NEXT:    addl %ecx, %eax
 ; X64-NEXT:    retq
 ;
 ; X86-LABEL: remove_redundant_cmp_tzcnt_wrong_const:
 ; X86:       # %bb.0:
-; X86-NEXT:    pushl %esi
-; X86-NEXT:    .cfi_def_cfa_offset 8
-; X86-NEXT:    .cfi_offset %esi, -8
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    testl %ecx, %ecx
-; X86-NEXT:    jne .LBB9_1
-; X86-NEXT:  # %bb.2:
-; X86-NEXT:    tzcntl %edx, %esi
-; X86-NEXT:    addl $32, %esi
-; X86-NEXT:    jmp .LBB9_3
-; X86-NEXT:  .LBB9_1:
-; X86-NEXT:    tzcntl %ecx, %esi
-; X86-NEXT:  .LBB9_3:
-; X86-NEXT:    xorl $2, %ecx
+; X86-NEXT:    tzcntl %ecx, %edx
 ; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    orl %edx, %ecx
+; X86-NEXT:    cmpl $2, %ecx
 ; X86-NEXT:    sete %al
-; X86-NEXT:    addl %esi, %eax
-; X86-NEXT:    xorl %edx, %edx
-; X86-NEXT:    popl %esi
-; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    addl %edx, %eax
 ; X86-NEXT:    retl
-  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
-  %3 = icmp eq i64 %0, 2
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp eq i32 %0, 2
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
 }

>From cddabda627f37f0bb98b881e40bd0fff5bacdddf Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Fri, 10 Jul 2026 12:08:25 +0530
Subject: [PATCH 6/9] [X86] remove check prefix

---
 llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
index 6d36196997e17..51b1faec788d7 100644
--- a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
+++ b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X64
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s
 
 define i64 @remove_redundant_cmp_lzcnt_i64(i64 %0) {
 ; X64-LABEL: remove_redundant_cmp_lzcnt_i64:

>From 86895bbd105c6d89f133d1c118da356763d6902e Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Fri, 10 Jul 2026 12:12:25 +0530
Subject: [PATCH 7/9] [X86] update the stale checks

---
 .../remove-redundant-cmp-lzcnt-tzcnt-i64.ll   | 20 +++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
index 51b1faec788d7..e0cd38db4a277 100644
--- a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
+++ b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
@@ -2,11 +2,11 @@
 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s
 
 define i64 @remove_redundant_cmp_lzcnt_i64(i64 %0) {
-; X64-LABEL: remove_redundant_cmp_lzcnt_i64:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntq %rdi, %rax
-; X64-NEXT:    adcq $0, %rax
-; X64-NEXT:    retq
+; CHECK-LABEL: remove_redundant_cmp_lzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rax
+; CHECK-NEXT:    adcq $0, %rax
+; CHECK-NEXT:    retq
   %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
   %3 = icmp eq i64 %0, 0
   %4 = zext i1 %3 to i64
@@ -15,11 +15,11 @@ define i64 @remove_redundant_cmp_lzcnt_i64(i64 %0) {
 }
 
 define i64 @remove_redundant_cmp_tzcnt_i64(i64 %0) {
-; X64-LABEL: remove_redundant_cmp_tzcnt_i64:
-; X64:       # %bb.0:
-; X64-NEXT:    tzcntq %rdi, %rax
-; X64-NEXT:    adcq $0, %rax
-; X64-NEXT:    retq
+; CHECK-LABEL: remove_redundant_cmp_tzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rax
+; CHECK-NEXT:    adcq $0, %rax
+; CHECK-NEXT:    retq
   %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
   %3 = icmp eq i64 %0, 0
   %4 = zext i1 %3 to i64

>From d1890c55713dd8d44840b2866e1c2b53317bbdc4 Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Sun, 12 Jul 2026 01:56:09 +0530
Subject: [PATCH 8/9] [X86] test coverage with other cmpcodes

---
 .../remove-redundant-cmp-lzcnt-tzcnt-i64.ll   | 277 ++++++++++-
 .../X86/remove-redundant-cmp-lzcnt-tzcnt.ll   | 430 +++++++++++++++++-
 2 files changed, 697 insertions(+), 10 deletions(-)

diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
index e0cd38db4a277..9a2473d7734af 100644
--- a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
+++ b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
@@ -1,8 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s
 
-define i64 @remove_redundant_cmp_lzcnt_i64(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_lzcnt_i64:
+define i64 @remove_redundant_cmp_eq_lzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_eq_lzcnt:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    lzcntq %rdi, %rax
 ; CHECK-NEXT:    adcq $0, %rax
@@ -14,8 +14,143 @@ define i64 @remove_redundant_cmp_lzcnt_i64(i64 %0) {
   ret i64 %5
 }
 
-define i64 @remove_redundant_cmp_tzcnt_i64(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_tzcnt_i64:
+define i64 @remove_redundant_cmp_ult_lzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_ult_lzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rax
+; CHECK-NEXT:    adcq $0, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp ult i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_uge_lzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_uge_lzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rax
+; CHECK-NEXT:    sbbq $-1, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp uge i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_ugt_lzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_ugt_lzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    sbbq $-1, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp ugt i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_ule_lzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_ule_lzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    adcq $0, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp ule i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+
+
+define i64 @remove_redundant_cmp_ne_lzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_ne_lzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    lzcntq %rdi, %rcx
+; CHECK-NEXT:    setne %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp ne i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_slt_lzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_slt_lzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    testq %rdi, %rdi
+; CHECK-NEXT:    setle %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp slt i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_sge_lzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_sge_lzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    testq %rdi, %rdi
+; CHECK-NEXT:    setg %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp sge i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_sgt_lzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_sgt_lzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    setge %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp sgt i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_sle_lzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_sle_lzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    setl %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp sle i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_eq_tzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_eq_tzcnt:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    tzcntq %rdi, %rax
 ; CHECK-NEXT:    adcq $0, %rax
@@ -26,3 +161,137 @@ define i64 @remove_redundant_cmp_tzcnt_i64(i64 %0) {
   %5 = add nuw nsw i64 %2, %4
   ret i64 %5
 }
+
+
+define i64 @remove_redundant_cmp_ult_tzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_ult_tzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rax
+; CHECK-NEXT:    adcq $0, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp ult i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_uge_tzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_uge_tzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rax
+; CHECK-NEXT:    sbbq $-1, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp uge i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_ugt_tzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_ugt_tzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    sbbq $-1, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp ugt i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_ule_tzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_ule_tzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    adcq $0, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp ule i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_ne_tzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_ne_tzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    tzcntq %rdi, %rcx
+; CHECK-NEXT:    setne %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp ne i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_slt_tzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_slt_tzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    testq %rdi, %rdi
+; CHECK-NEXT:    setle %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp slt i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_sge_tzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_sge_tzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    testq %rdi, %rdi
+; CHECK-NEXT:    setg %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp sge i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_sgt_tzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_sgt_tzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    setge %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp sgt i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_sle_tzcnt(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_sle_tzcnt:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    setl %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp sle i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
index 57ac1d5e2f4c8..e0bf88cda1f90 100644
--- a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
+++ b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
@@ -2,14 +2,14 @@
 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X64
 ; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X86
 
-define i32 @remove_redundant_cmp_lzcnt_i32(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_lzcnt_i32:
+define i32 @remove_redundant_cmp_eq_lzcnt_i32(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_eq_lzcnt_i32:
 ; X64:       # %bb.0:
 ; X64-NEXT:    lzcntl %edi, %eax
 ; X64-NEXT:    adcl $0, %eax
 ; X64-NEXT:    retq
 ;
-; X86-LABEL: remove_redundant_cmp_lzcnt_i32:
+; X86-LABEL: remove_redundant_cmp_eq_lzcnt_i32:
 ; X86:       # %bb.0:
 ; X86-NEXT:    lzcntl {{[0-9]+}}(%esp), %eax
 ; X86-NEXT:    adcl $0, %eax
@@ -40,6 +40,215 @@ define i16 @remove_redundant_cmp_lzcnt_i16(i16 %0) {
   ret i16 %5
 }
 
+define i32 @remove_redundant_cmp_ult_lzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_ult_lzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %eax
+; X64-NEXT:    adcl $0, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_ult_lzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    lzcntl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    adcl $0, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp ult i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_uge_lzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_uge_lzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %eax
+; X64-NEXT:    sbbl $-1, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_uge_lzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    lzcntl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    sbbl $-1, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp uge i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_ugt_lzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_ugt_lzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    sbbl $-1, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_ugt_lzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    lzcntl %ecx, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    sbbl $-1, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp ugt i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_ule_lzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_ule_lzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    adcl $0, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_ule_lzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    lzcntl %ecx, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    adcl $0, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp ule i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_ne_lzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_ne_lzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    lzcntl %edi, %ecx
+; X64-NEXT:    setne %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_ne_lzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    lzcntl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    setne %al
+; X86-NEXT:    addl %ecx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp ne i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_slt_lzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_slt_lzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    testl %edi, %edi
+; X64-NEXT:    setle %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_slt_lzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    lzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    testl %ecx, %ecx
+; X86-NEXT:    setle %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp slt i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_sge_lzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_sge_lzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    testl %edi, %edi
+; X64-NEXT:    setg %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_sge_lzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    lzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    testl %ecx, %ecx
+; X86-NEXT:    setg %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp sge i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_sgt_lzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_sgt_lzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    setge %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_sgt_lzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    lzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    setge %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp sgt i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_sle_lzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_sle_lzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    setl %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_sle_lzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    lzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    setl %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp sle i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
 define i32 @remove_redundant_cmp_lzcnt_no_constant(i32 %0, i32 %1) {
 ; X64-LABEL: remove_redundant_cmp_lzcnt_no_constant:
 ; X64:       # %bb.0:
@@ -92,14 +301,14 @@ define i32 @remove_redundant_cmp_lzcnt_wrong_const(i32 %0) {
   ret i32 %5
 }
 
-define i32 @remove_redundant_cmp_tzcnt_i32(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_tzcnt_i32:
+define i32 @remove_redundant_cmp_eq_tzcnt_i32(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_eq_tzcnt_i32:
 ; X64:       # %bb.0:
 ; X64-NEXT:    tzcntl %edi, %eax
 ; X64-NEXT:    adcl $0, %eax
 ; X64-NEXT:    retq
 ;
-; X86-LABEL: remove_redundant_cmp_tzcnt_i32:
+; X86-LABEL: remove_redundant_cmp_eq_tzcnt_i32:
 ; X86:       # %bb.0:
 ; X86-NEXT:    tzcntl {{[0-9]+}}(%esp), %eax
 ; X86-NEXT:    adcl $0, %eax
@@ -190,3 +399,212 @@ define i32 @remove_redundant_cmp_tzcnt_wrong_const(i32 %0) {
   %5 = add nuw nsw i32 %2, %4
   ret i32 %5
 }
+
+define i32 @remove_redundant_cmp_ult_tzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_ult_tzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %eax
+; X64-NEXT:    adcl $0, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_ult_tzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    tzcntl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    adcl $0, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp ult i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_uge_tzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_uge_tzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %eax
+; X64-NEXT:    sbbl $-1, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_uge_tzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    tzcntl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    sbbl $-1, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp uge i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_ugt_tzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_ugt_tzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    sbbl $-1, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_ugt_tzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    tzcntl %ecx, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    sbbl $-1, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp ugt i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_ule_tzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_ule_tzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    adcl $0, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_ule_tzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    tzcntl %ecx, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    adcl $0, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp ule i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_ne_tzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_ne_tzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    tzcntl %edi, %ecx
+; X64-NEXT:    setne %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_ne_tzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    tzcntl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    setne %al
+; X86-NEXT:    addl %ecx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp ne i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_slt_tzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_slt_tzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    testl %edi, %edi
+; X64-NEXT:    setle %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_slt_tzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    tzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    testl %ecx, %ecx
+; X86-NEXT:    setle %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp slt i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_sge_tzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_sge_tzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    testl %edi, %edi
+; X64-NEXT:    setg %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_sge_tzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    tzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    testl %ecx, %ecx
+; X86-NEXT:    setg %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp sge i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_sgt_tzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_sgt_tzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    setge %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_sgt_tzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    tzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    setge %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp sgt i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_sle_tzcnt(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_sle_tzcnt:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    setl %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_sle_tzcnt:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    tzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    setl %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp sle i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}

>From 9ed8a02fcc166383e908f22823ca0b555ad3d3a6 Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Tue, 14 Jul 2026 12:20:34 +0530
Subject: [PATCH 9/9] [X86] refactor tests -- RKSimon

---
 .../X86/remove-redundant-cmp-lzcnt-i64.ll     |  76 +++
 .../remove-redundant-cmp-lzcnt-tzcnt-i64.ll   | 297 ---------
 .../X86/remove-redundant-cmp-lzcnt-tzcnt.ll   | 610 ------------------
 .../CodeGen/X86/remove-redundant-cmp-lzcnt.ll | 186 ++++++
 .../X86/remove-redundant-cmp-tzcnt-i64.ll     |  74 +++
 .../CodeGen/X86/remove-redundant-cmp-tzcnt.ll | 199 ++++++
 6 files changed, 535 insertions(+), 907 deletions(-)
 create mode 100644 llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-i64.ll
 delete mode 100644 llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
 delete mode 100644 llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
 create mode 100644 llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt.ll
 create mode 100644 llvm/test/CodeGen/X86/remove-redundant-cmp-tzcnt-i64.ll
 create mode 100644 llvm/test/CodeGen/X86/remove-redundant-cmp-tzcnt.ll

diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-i64.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-i64.ll
new file mode 100644
index 0000000000000..82d10a5688cfa
--- /dev/null
+++ b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-i64.ll
@@ -0,0 +1,76 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s
+
+define i64 @remove_redundant_cmp_ult_lzcnt_i64(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_ult_lzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rax
+; CHECK-NEXT:    adcq $0, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp ult i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_ugt_lzcnt_i64(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_ugt_lzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    sbbq $-1, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp ugt i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_ne_lzcnt_i64(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_ne_lzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    lzcntq %rdi, %rcx
+; CHECK-NEXT:    setne %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp ne i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_sge_lzcnt_i64(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_sge_lzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    testq %rdi, %rdi
+; CHECK-NEXT:    setg %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp sge i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_sle_lzcnt_i64(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_sle_lzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    setl %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
+  %3 = icmp sle i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
deleted file mode 100644
index 9a2473d7734af..0000000000000
--- a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt-i64.ll
+++ /dev/null
@@ -1,297 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s
-
-define i64 @remove_redundant_cmp_eq_lzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_eq_lzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntq %rdi, %rax
-; CHECK-NEXT:    adcq $0, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
-  %3 = icmp eq i64 %0, 0
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_ult_lzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_ult_lzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntq %rdi, %rax
-; CHECK-NEXT:    adcq $0, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
-  %3 = icmp ult i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_uge_lzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_uge_lzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntq %rdi, %rax
-; CHECK-NEXT:    sbbq $-1, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
-  %3 = icmp uge i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_ugt_lzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_ugt_lzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntq %rdi, %rax
-; CHECK-NEXT:    cmpq $2, %rdi
-; CHECK-NEXT:    sbbq $-1, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
-  %3 = icmp ugt i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_ule_lzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_ule_lzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntq %rdi, %rax
-; CHECK-NEXT:    cmpq $2, %rdi
-; CHECK-NEXT:    adcq $0, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
-  %3 = icmp ule i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-
-
-define i64 @remove_redundant_cmp_ne_lzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_ne_lzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    lzcntq %rdi, %rcx
-; CHECK-NEXT:    setne %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
-  %3 = icmp ne i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_slt_lzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_slt_lzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntq %rdi, %rcx
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    testq %rdi, %rdi
-; CHECK-NEXT:    setle %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
-  %3 = icmp slt i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_sge_lzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_sge_lzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntq %rdi, %rcx
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    testq %rdi, %rdi
-; CHECK-NEXT:    setg %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
-  %3 = icmp sge i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_sgt_lzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_sgt_lzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntq %rdi, %rcx
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    cmpq $2, %rdi
-; CHECK-NEXT:    setge %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
-  %3 = icmp sgt i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_sle_lzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_sle_lzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lzcntq %rdi, %rcx
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    cmpq $2, %rdi
-; CHECK-NEXT:    setl %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.ctlz.i64(i64 %0, i1 false)
-  %3 = icmp sle i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_eq_tzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_eq_tzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    tzcntq %rdi, %rax
-; CHECK-NEXT:    adcq $0, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
-  %3 = icmp eq i64 %0, 0
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-
-define i64 @remove_redundant_cmp_ult_tzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_ult_tzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    tzcntq %rdi, %rax
-; CHECK-NEXT:    adcq $0, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
-  %3 = icmp ult i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_uge_tzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_uge_tzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    tzcntq %rdi, %rax
-; CHECK-NEXT:    sbbq $-1, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
-  %3 = icmp uge i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_ugt_tzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_ugt_tzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    tzcntq %rdi, %rax
-; CHECK-NEXT:    cmpq $2, %rdi
-; CHECK-NEXT:    sbbq $-1, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
-  %3 = icmp ugt i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_ule_tzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_ule_tzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    tzcntq %rdi, %rax
-; CHECK-NEXT:    cmpq $2, %rdi
-; CHECK-NEXT:    adcq $0, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
-  %3 = icmp ule i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_ne_tzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_ne_tzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    tzcntq %rdi, %rcx
-; CHECK-NEXT:    setne %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
-  %3 = icmp ne i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_slt_tzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_slt_tzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    tzcntq %rdi, %rcx
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    testq %rdi, %rdi
-; CHECK-NEXT:    setle %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
-  %3 = icmp slt i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_sge_tzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_sge_tzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    tzcntq %rdi, %rcx
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    testq %rdi, %rdi
-; CHECK-NEXT:    setg %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
-  %3 = icmp sge i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_sgt_tzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_sgt_tzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    tzcntq %rdi, %rcx
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    cmpq $2, %rdi
-; CHECK-NEXT:    setge %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
-  %3 = icmp sgt i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
-
-define i64 @remove_redundant_cmp_sle_tzcnt(i64 %0) {
-; CHECK-LABEL: remove_redundant_cmp_sle_tzcnt:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    tzcntq %rdi, %rcx
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    cmpq $2, %rdi
-; CHECK-NEXT:    setl %al
-; CHECK-NEXT:    addq %rcx, %rax
-; CHECK-NEXT:    retq
-  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
-  %3 = icmp sle i64 %0, 1
-  %4 = zext i1 %3 to i64
-  %5 = add nuw nsw i64 %2, %4
-  ret i64 %5
-}
diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
deleted file mode 100644
index e0bf88cda1f90..0000000000000
--- a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt-tzcnt.ll
+++ /dev/null
@@ -1,610 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X64
-; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X86
-
-define i32 @remove_redundant_cmp_eq_lzcnt_i32(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_eq_lzcnt_i32:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntl %edi, %eax
-; X64-NEXT:    adcl $0, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_eq_lzcnt_i32:
-; X86:       # %bb.0:
-; X86-NEXT:    lzcntl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    adcl $0, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
-  %3 = icmp eq i32 %0, 0
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i16 @remove_redundant_cmp_lzcnt_i16(i16 %0) {
-; X64-LABEL: remove_redundant_cmp_lzcnt_i16:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntw %di, %ax
-; X64-NEXT:    adcw $0, %ax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_lzcnt_i16:
-; X86:       # %bb.0:
-; X86-NEXT:    lzcntw {{[0-9]+}}(%esp), %ax
-; X86-NEXT:    adcw $0, %ax
-; X86-NEXT:    retl
-  %2 = tail call i16 @llvm.ctlz.i16(i16 %0, i1 false)
-  %3 = icmp eq i16 %0, 0
-  %4 = zext i1 %3 to i16
-  %5 = add nuw nsw i16 %2, %4
-  ret i16 %5
-}
-
-define i32 @remove_redundant_cmp_ult_lzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_ult_lzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntl %edi, %eax
-; X64-NEXT:    adcl $0, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_ult_lzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    lzcntl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    adcl $0, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
-  %3 = icmp ult i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_uge_lzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_uge_lzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntl %edi, %eax
-; X64-NEXT:    sbbl $-1, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_uge_lzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    lzcntl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    sbbl $-1, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
-  %3 = icmp uge i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_ugt_lzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_ugt_lzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntl %edi, %eax
-; X64-NEXT:    cmpl $2, %edi
-; X64-NEXT:    sbbl $-1, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_ugt_lzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    lzcntl %ecx, %eax
-; X86-NEXT:    cmpl $2, %ecx
-; X86-NEXT:    sbbl $-1, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
-  %3 = icmp ugt i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_ule_lzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_ule_lzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntl %edi, %eax
-; X64-NEXT:    cmpl $2, %edi
-; X64-NEXT:    adcl $0, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_ule_lzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    lzcntl %ecx, %eax
-; X86-NEXT:    cmpl $2, %ecx
-; X86-NEXT:    adcl $0, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
-  %3 = icmp ule i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_ne_lzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_ne_lzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    lzcntl %edi, %ecx
-; X64-NEXT:    setne %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_ne_lzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    lzcntl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    setne %al
-; X86-NEXT:    addl %ecx, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
-  %3 = icmp ne i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_slt_lzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_slt_lzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntl %edi, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    testl %edi, %edi
-; X64-NEXT:    setle %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_slt_lzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    lzcntl %ecx, %edx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    testl %ecx, %ecx
-; X86-NEXT:    setle %al
-; X86-NEXT:    addl %edx, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
-  %3 = icmp slt i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_sge_lzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_sge_lzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntl %edi, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    testl %edi, %edi
-; X64-NEXT:    setg %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_sge_lzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    lzcntl %ecx, %edx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    testl %ecx, %ecx
-; X86-NEXT:    setg %al
-; X86-NEXT:    addl %edx, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
-  %3 = icmp sge i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_sgt_lzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_sgt_lzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntl %edi, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpl $2, %edi
-; X64-NEXT:    setge %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_sgt_lzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    lzcntl %ecx, %edx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    cmpl $2, %ecx
-; X86-NEXT:    setge %al
-; X86-NEXT:    addl %edx, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
-  %3 = icmp sgt i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_sle_lzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_sle_lzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntl %edi, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpl $2, %edi
-; X64-NEXT:    setl %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_sle_lzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    lzcntl %ecx, %edx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    cmpl $2, %ecx
-; X86-NEXT:    setl %al
-; X86-NEXT:    addl %edx, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
-  %3 = icmp sle i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_lzcnt_no_constant(i32 %0, i32 %1) {
-; X64-LABEL: remove_redundant_cmp_lzcnt_no_constant:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntl %edi, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpl %esi, %edi
-; X64-NEXT:    sete %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_lzcnt_no_constant:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    lzcntl %ecx, %edx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    cmpl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    sete %al
-; X86-NEXT:    addl %edx, %eax
-; X86-NEXT:    retl
-  %3 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
-  %4 = icmp eq i32 %0, %1
-  %5 = zext i1 %4 to i32
-  %6 = add nuw nsw i32 %3, %5
-  ret i32 %6
-}
-
-define i32 @remove_redundant_cmp_lzcnt_wrong_const(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_lzcnt_wrong_const:
-; X64:       # %bb.0:
-; X64-NEXT:    lzcntl %edi, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpl $2, %edi
-; X64-NEXT:    sete %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_lzcnt_wrong_const:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    lzcntl %ecx, %edx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    cmpl $2, %ecx
-; X86-NEXT:    sete %al
-; X86-NEXT:    addl %edx, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
-  %3 = icmp eq i32 %0, 2
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_eq_tzcnt_i32(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_eq_tzcnt_i32:
-; X64:       # %bb.0:
-; X64-NEXT:    tzcntl %edi, %eax
-; X64-NEXT:    adcl $0, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_eq_tzcnt_i32:
-; X86:       # %bb.0:
-; X86-NEXT:    tzcntl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    adcl $0, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
-  %3 = icmp eq i32 %0, 0
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i16 @remove_redundant_cmp_tzcnt_i16(i16 %0) {
-; X64-LABEL: remove_redundant_cmp_tzcnt_i16:
-; X64:       # %bb.0:
-; X64-NEXT:    movl %edi, %eax
-; X64-NEXT:    orl $65536, %eax # imm = 0x10000
-; X64-NEXT:    tzcntl %eax, %eax
-; X64-NEXT:    cmpw $1, %di
-; X64-NEXT:    adcw $0, %ax
-; X64-NEXT:    # kill: def $ax killed $ax killed $eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_tzcnt_i16:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl %ecx, %eax
-; X86-NEXT:    orl $65536, %eax # imm = 0x10000
-; X86-NEXT:    tzcntl %eax, %eax
-; X86-NEXT:    cmpw $1, %cx
-; X86-NEXT:    adcw $0, %ax
-; X86-NEXT:    # kill: def $ax killed $ax killed $eax
-; X86-NEXT:    retl
-  %2 = tail call i16 @llvm.cttz.i16(i16 %0, i1 false)
-  %3 = icmp eq i16 %0, 0
-  %4 = zext i1 %3 to i16
-  %5 = add nuw nsw i16 %2, %4
-  ret i16 %5
-}
-
-define i32 @remove_redundant_cmp_tzcnt_no_constant(i32 %0, i32 %1) {
-; X64-LABEL: remove_redundant_cmp_tzcnt_no_constant:
-; X64:       # %bb.0:
-; X64-NEXT:    tzcntl %edi, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpl %esi, %edi
-; X64-NEXT:    sete %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_tzcnt_no_constant:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    tzcntl %ecx, %edx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    cmpl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    sete %al
-; X86-NEXT:    addl %edx, %eax
-; X86-NEXT:    retl
-  %3 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
-  %4 = icmp eq i32 %0, %1
-  %5 = zext i1 %4 to i32
-  %6 = add nuw nsw i32 %3, %5
-  ret i32 %6
-}
-
-define i32 @remove_redundant_cmp_tzcnt_wrong_const(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_tzcnt_wrong_const:
-; X64:       # %bb.0:
-; X64-NEXT:    tzcntl %edi, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpl $2, %edi
-; X64-NEXT:    sete %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_tzcnt_wrong_const:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    tzcntl %ecx, %edx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    cmpl $2, %ecx
-; X86-NEXT:    sete %al
-; X86-NEXT:    addl %edx, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
-  %3 = icmp eq i32 %0, 2
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_ult_tzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_ult_tzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    tzcntl %edi, %eax
-; X64-NEXT:    adcl $0, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_ult_tzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    tzcntl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    adcl $0, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
-  %3 = icmp ult i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_uge_tzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_uge_tzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    tzcntl %edi, %eax
-; X64-NEXT:    sbbl $-1, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_uge_tzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    tzcntl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    sbbl $-1, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
-  %3 = icmp uge i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_ugt_tzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_ugt_tzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    tzcntl %edi, %eax
-; X64-NEXT:    cmpl $2, %edi
-; X64-NEXT:    sbbl $-1, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_ugt_tzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    tzcntl %ecx, %eax
-; X86-NEXT:    cmpl $2, %ecx
-; X86-NEXT:    sbbl $-1, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
-  %3 = icmp ugt i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_ule_tzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_ule_tzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    tzcntl %edi, %eax
-; X64-NEXT:    cmpl $2, %edi
-; X64-NEXT:    adcl $0, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_ule_tzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    tzcntl %ecx, %eax
-; X86-NEXT:    cmpl $2, %ecx
-; X86-NEXT:    adcl $0, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
-  %3 = icmp ule i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_ne_tzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_ne_tzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    tzcntl %edi, %ecx
-; X64-NEXT:    setne %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_ne_tzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    tzcntl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    setne %al
-; X86-NEXT:    addl %ecx, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
-  %3 = icmp ne i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_slt_tzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_slt_tzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    tzcntl %edi, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    testl %edi, %edi
-; X64-NEXT:    setle %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_slt_tzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    tzcntl %ecx, %edx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    testl %ecx, %ecx
-; X86-NEXT:    setle %al
-; X86-NEXT:    addl %edx, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
-  %3 = icmp slt i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_sge_tzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_sge_tzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    tzcntl %edi, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    testl %edi, %edi
-; X64-NEXT:    setg %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_sge_tzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    tzcntl %ecx, %edx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    testl %ecx, %ecx
-; X86-NEXT:    setg %al
-; X86-NEXT:    addl %edx, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
-  %3 = icmp sge i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_sgt_tzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_sgt_tzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    tzcntl %edi, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpl $2, %edi
-; X64-NEXT:    setge %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_sgt_tzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    tzcntl %ecx, %edx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    cmpl $2, %ecx
-; X86-NEXT:    setge %al
-; X86-NEXT:    addl %edx, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
-  %3 = icmp sgt i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
-
-define i32 @remove_redundant_cmp_sle_tzcnt(i32 %0) {
-; X64-LABEL: remove_redundant_cmp_sle_tzcnt:
-; X64:       # %bb.0:
-; X64-NEXT:    tzcntl %edi, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpl $2, %edi
-; X64-NEXT:    setl %al
-; X64-NEXT:    addl %ecx, %eax
-; X64-NEXT:    retq
-;
-; X86-LABEL: remove_redundant_cmp_sle_tzcnt:
-; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    tzcntl %ecx, %edx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    cmpl $2, %ecx
-; X86-NEXT:    setl %al
-; X86-NEXT:    addl %edx, %eax
-; X86-NEXT:    retl
-  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
-  %3 = icmp sle i32 %0, 1
-  %4 = zext i1 %3 to i32
-  %5 = add nuw nsw i32 %2, %4
-  ret i32 %5
-}
diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt.ll
new file mode 100644
index 0000000000000..7658e7e96c93c
--- /dev/null
+++ b/llvm/test/CodeGen/X86/remove-redundant-cmp-lzcnt.ll
@@ -0,0 +1,186 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X64
+; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X86
+
+define i32 @remove_redundant_cmp_eq_lzcnt_i32(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_eq_lzcnt_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %eax
+; X64-NEXT:    adcl $0, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_eq_lzcnt_i32:
+; X86:       # %bb.0:
+; X86-NEXT:    lzcntl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    adcl $0, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp eq i32 %0, 0
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_uge_lzcnt_i32(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_uge_lzcnt_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %eax
+; X64-NEXT:    sbbl $-1, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_uge_lzcnt_i32:
+; X86:       # %bb.0:
+; X86-NEXT:    lzcntl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    sbbl $-1, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp uge i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_ule_lzcnt_i32(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_ule_lzcnt_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    adcl $0, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_ule_lzcnt_i32:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    lzcntl %ecx, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    adcl $0, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp ule i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_slt_lzcnt_i32(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_slt_lzcnt_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    testl %edi, %edi
+; X64-NEXT:    setle %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_slt_lzcnt_i32:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    lzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    testl %ecx, %ecx
+; X86-NEXT:    setle %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp slt i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_sgt_lzcnt_i32(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_sgt_lzcnt_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    setge %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_sgt_lzcnt_i32:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    lzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    setge %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp sgt i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i16 @remove_redundant_cmp_lzcnt_i16(i16 %0) {
+; X64-LABEL: remove_redundant_cmp_lzcnt_i16:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntw %di, %ax
+; X64-NEXT:    adcw $0, %ax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_lzcnt_i16:
+; X86:       # %bb.0:
+; X86-NEXT:    lzcntw {{[0-9]+}}(%esp), %ax
+; X86-NEXT:    adcw $0, %ax
+; X86-NEXT:    retl
+  %2 = tail call i16 @llvm.ctlz.i16(i16 %0, i1 false)
+  %3 = icmp eq i16 %0, 0
+  %4 = zext i1 %3 to i16
+  %5 = add nuw nsw i16 %2, %4
+  ret i16 %5
+}
+
+define i32 @remove_redundant_cmp_lzcnt_no_constant(i32 %0, i32 %1) {
+; X64-LABEL: remove_redundant_cmp_lzcnt_no_constant:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpl %esi, %edi
+; X64-NEXT:    sete %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_lzcnt_no_constant:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    lzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    cmpl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    sete %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %3 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %4 = icmp eq i32 %0, %1
+  %5 = zext i1 %4 to i32
+  %6 = add nuw nsw i32 %3, %5
+  ret i32 %6
+}
+
+define i32 @remove_redundant_cmp_lzcnt_wrong_const(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_lzcnt_wrong_const:
+; X64:       # %bb.0:
+; X64-NEXT:    lzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    sete %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_lzcnt_wrong_const:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    lzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    sete %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.ctlz.i32(i32 %0, i1 false)
+  %3 = icmp eq i32 %0, 2
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-tzcnt-i64.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-tzcnt-i64.ll
new file mode 100644
index 0000000000000..a378156c639ef
--- /dev/null
+++ b/llvm/test/CodeGen/X86/remove-redundant-cmp-tzcnt-i64.ll
@@ -0,0 +1,74 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s
+
+define i64 @remove_redundant_cmp_eq_tzcnt_i64(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_eq_tzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rax
+; CHECK-NEXT:    adcq $0, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp eq i64 %0, 0
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_uge_tzcnt_i64(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_uge_tzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rax
+; CHECK-NEXT:    sbbq $-1, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp uge i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_ule_tzcnt_i64(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_ule_tzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    adcq $0, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp ule i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_slt_tzcnt_i64(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_slt_tzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    testq %rdi, %rdi
+; CHECK-NEXT:    setle %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp slt i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
+
+define i64 @remove_redundant_cmp_sgt_tzcnt_i64(i64 %0) {
+; CHECK-LABEL: remove_redundant_cmp_sgt_tzcnt_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    tzcntq %rdi, %rcx
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    cmpq $2, %rdi
+; CHECK-NEXT:    setge %al
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    retq
+  %2 = tail call i64 @llvm.cttz.i64(i64 %0, i1 false)
+  %3 = icmp sgt i64 %0, 1
+  %4 = zext i1 %3 to i64
+  %5 = add nuw nsw i64 %2, %4
+  ret i64 %5
+}
diff --git a/llvm/test/CodeGen/X86/remove-redundant-cmp-tzcnt.ll b/llvm/test/CodeGen/X86/remove-redundant-cmp-tzcnt.ll
new file mode 100644
index 0000000000000..0dee74e413066
--- /dev/null
+++ b/llvm/test/CodeGen/X86/remove-redundant-cmp-tzcnt.ll
@@ -0,0 +1,199 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X64
+; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X86
+
+define i32 @remove_redundant_cmp_ult_tzcnt_i32(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_ult_tzcnt_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %eax
+; X64-NEXT:    adcl $0, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_ult_tzcnt_i32:
+; X86:       # %bb.0:
+; X86-NEXT:    tzcntl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    adcl $0, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp ult i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_ugt_tzcnt_i32(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_ugt_tzcnt_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    sbbl $-1, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_ugt_tzcnt_i32:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    tzcntl %ecx, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    sbbl $-1, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp ugt i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_ne_tzcnt_i32(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_ne_tzcnt_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    tzcntl %edi, %ecx
+; X64-NEXT:    setne %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_ne_tzcnt_i32:
+; X86:       # %bb.0:
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    tzcntl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    setne %al
+; X86-NEXT:    addl %ecx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp ne i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_sge_tzcnt_i32(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_sge_tzcnt_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    testl %edi, %edi
+; X64-NEXT:    setg %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_sge_tzcnt_i32:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    tzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    testl %ecx, %ecx
+; X86-NEXT:    setg %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp sge i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i32 @remove_redundant_cmp_sle_tzcnt_i32(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_sle_tzcnt_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    setl %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_sle_tzcnt_i32:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    tzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    setl %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp sle i32 %0, 1
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}
+
+define i16 @remove_redundant_cmp_tzcnt_i16(i16 %0) {
+; X64-LABEL: remove_redundant_cmp_tzcnt_i16:
+; X64:       # %bb.0:
+; X64-NEXT:    movl %edi, %eax
+; X64-NEXT:    orl $65536, %eax # imm = 0x10000
+; X64-NEXT:    tzcntl %eax, %eax
+; X64-NEXT:    cmpw $1, %di
+; X64-NEXT:    adcw $0, %ax
+; X64-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_tzcnt_i16:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl %ecx, %eax
+; X86-NEXT:    orl $65536, %eax # imm = 0x10000
+; X86-NEXT:    tzcntl %eax, %eax
+; X86-NEXT:    cmpw $1, %cx
+; X86-NEXT:    adcw $0, %ax
+; X86-NEXT:    # kill: def $ax killed $ax killed $eax
+; X86-NEXT:    retl
+  %2 = tail call i16 @llvm.cttz.i16(i16 %0, i1 false)
+  %3 = icmp eq i16 %0, 0
+  %4 = zext i1 %3 to i16
+  %5 = add nuw nsw i16 %2, %4
+  ret i16 %5
+}
+
+define i32 @remove_redundant_cmp_tzcnt_no_constant(i32 %0, i32 %1) {
+; X64-LABEL: remove_redundant_cmp_tzcnt_no_constant:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpl %esi, %edi
+; X64-NEXT:    sete %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_tzcnt_no_constant:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    tzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    cmpl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    sete %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %3 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %4 = icmp eq i32 %0, %1
+  %5 = zext i1 %4 to i32
+  %6 = add nuw nsw i32 %3, %5
+  ret i32 %6
+}
+
+define i32 @remove_redundant_cmp_tzcnt_wrong_const(i32 %0) {
+; X64-LABEL: remove_redundant_cmp_tzcnt_wrong_const:
+; X64:       # %bb.0:
+; X64-NEXT:    tzcntl %edi, %ecx
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    cmpl $2, %edi
+; X64-NEXT:    sete %al
+; X64-NEXT:    addl %ecx, %eax
+; X64-NEXT:    retq
+;
+; X86-LABEL: remove_redundant_cmp_tzcnt_wrong_const:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    tzcntl %ecx, %edx
+; X86-NEXT:    xorl %eax, %eax
+; X86-NEXT:    cmpl $2, %ecx
+; X86-NEXT:    sete %al
+; X86-NEXT:    addl %edx, %eax
+; X86-NEXT:    retl
+  %2 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false)
+  %3 = icmp eq i32 %0, 2
+  %4 = zext i1 %3 to i32
+  %5 = add nuw nsw i32 %2, %4
+  ret i32 %5
+}



More information about the llvm-commits mailing list