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

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 9 00:57:21 PDT 2026


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

fix #193178 

>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] [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
+}



More information about the llvm-commits mailing list