[llvm] [X86] Use BSR passthrough behaviour to fold (CMOV (BSR ?, X), Y, (X == 0)) -> (BSR Y, X) (PR #143662)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 11 00:43:43 PDT 2025
https://github.com/RKSimon created https://github.com/llvm/llvm-project/pull/143662
Make use of targets that support BSR "pass through behaviour" on a zero input to remove a CMOV thats performing the same function
BSF will be a trickier patch as we need to make sure it works with the "REP BSF" hack in X86MCInstLower
>From 319bc9517920c3ef9b5b2731762c8a099d8a8357 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Wed, 11 Jun 2025 08:42:29 +0100
Subject: [PATCH] [X86] Use BSR passthrough behaviour to fold (CMOV (BSR ?, X),
Y, (X == 0)) -> (BSR Y, X)
Make use of targets that support BSR "pass through behaviour" on a zero input to remove a CMOV thats performing the same function
BSF will be a trickier patch as we need to make sure it works with the "REP BSF" hack in X86MCInstLower
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 10 ++++++++++
llvm/test/CodeGen/X86/bsr.ll | 10 ++++------
llvm/test/CodeGen/X86/pr40090.ll | 11 ++++-------
3 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 8bcd8670879a9..91636dce814e8 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -49392,6 +49392,8 @@ static SDValue combineCMov(SDNode *N, SelectionDAG &DAG,
// (ADD (CMOV C1-C2, (CTTZ X), (X != 0)), C2)
// Or (CMOV (ADD (CTTZ X), C2), C1, (X == 0)) ->
// (ADD (CMOV (CTTZ X), C1-C2, (X == 0)), C2)
+ // Or (CMOV (BSR ?, X), Y, (X == 0)) -> (BSR Y, X)
+ // TODO: Or (CMOV (BSF ?, X), Y, (X == 0)) -> (BSF Y, X)
if ((CC == X86::COND_NE || CC == X86::COND_E) &&
Cond.getOpcode() == X86ISD::CMP && isNullConstant(Cond.getOperand(1))) {
SDValue Add = TrueOp;
@@ -49400,6 +49402,14 @@ static SDValue combineCMov(SDNode *N, SelectionDAG &DAG,
if (CC == X86::COND_E)
std::swap(Add, Const);
+ // TODO: ADD BSF support, but requires changes to the "REP BSF" CTTZ hack.
+ if (Subtarget.hasBitScanPassThrough() && Add.getOpcode() == X86ISD::BSR &&
+ Add.getResNo() == 0 && Add.hasOneUse() &&
+ Add.getOperand(1) == Cond.getOperand(0)) {
+ return DAG.getNode(Add.getOpcode(), DL, Add->getVTList(), Const,
+ Add.getOperand(1));
+ }
+
// We might have replaced the constant in the cmov with the LHS of the
// compare. If so change it to the RHS of the compare.
if (Const == Cond.getOperand(0))
diff --git a/llvm/test/CodeGen/X86/bsr.ll b/llvm/test/CodeGen/X86/bsr.ll
index 1247b3ec59324..fbca4af425eac 100644
--- a/llvm/test/CodeGen/X86/bsr.ll
+++ b/llvm/test/CodeGen/X86/bsr.ll
@@ -162,9 +162,8 @@ define i32 @cmov_bsr32(i32 %x, i32 %y) nounwind {
;
; X64-LABEL: cmov_bsr32:
; X64: # %bb.0:
-; X64-NEXT: movl $63, %eax
+; X64-NEXT: movl %esi, %eax
; X64-NEXT: bsrl %edi, %eax
-; X64-NEXT: cmovel %esi, %eax
; X64-NEXT: retq
%1 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
%2 = xor i32 %1, 31
@@ -188,8 +187,8 @@ define i32 @cmov_bsr32_undef(i32 %x, i32 %y) nounwind {
;
; X64-LABEL: cmov_bsr32_undef:
; X64: # %bb.0:
+; X64-NEXT: movl %esi, %eax
; X64-NEXT: bsrl %edi, %eax
-; X64-NEXT: cmovel %esi, %eax
; X64-NEXT: retq
%1 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
%2 = xor i32 %1, 31
@@ -239,9 +238,8 @@ define i64 @cmov_bsr64(i64 %x, i64 %y) nounwind {
;
; X64-LABEL: cmov_bsr64:
; X64: # %bb.0:
-; X64-NEXT: movl $127, %eax
+; X64-NEXT: movq %rsi, %rax
; X64-NEXT: bsrq %rdi, %rax
-; X64-NEXT: cmoveq %rsi, %rax
; X64-NEXT: retq
%1 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
%2 = xor i64 %1, 63
@@ -279,8 +277,8 @@ define i64 @cmov_bsr64_undef(i64 %x, i64 %y) nounwind {
;
; X64-LABEL: cmov_bsr64_undef:
; X64: # %bb.0:
+; X64-NEXT: movq %rsi, %rax
; X64-NEXT: bsrq %rdi, %rax
-; X64-NEXT: cmoveq %rsi, %rax
; X64-NEXT: retq
%1 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
%2 = xor i64 %1, 63
diff --git a/llvm/test/CodeGen/X86/pr40090.ll b/llvm/test/CodeGen/X86/pr40090.ll
index 24e957ac59f52..af933c950e111 100644
--- a/llvm/test/CodeGen/X86/pr40090.ll
+++ b/llvm/test/CodeGen/X86/pr40090.ll
@@ -4,10 +4,9 @@
define i64 @foo(i64 %x, i64 %y) {
; CHECK-LABEL: foo:
; CHECK: # %bb.0:
-; CHECK-NEXT: bsrq %rdi, %rax
-; CHECK-NEXT: orq $64, %rax
+; CHECK-NEXT: bsrq %rdi, %rcx
+; CHECK-NEXT: orq $64, %rcx
; CHECK-NEXT: bsrq %rsi, %rcx
-; CHECK-NEXT: cmoveq %rax, %rcx
; CHECK-NEXT: movl $63, %eax
; CHECK-NEXT: subq %rcx, %rax
; CHECK-NEXT: retq
@@ -25,11 +24,9 @@ define i64 @bar(i64 %x, i64 %y) {
; CHECK-LABEL: bar:
; CHECK: # %bb.0:
; CHECK-NEXT: movl $127, %ecx
-; CHECK-NEXT: movl $127, %eax
-; CHECK-NEXT: bsrq %rdi, %rax
-; CHECK-NEXT: xorq $64, %rax
+; CHECK-NEXT: bsrq %rdi, %rcx
+; CHECK-NEXT: xorq $64, %rcx
; CHECK-NEXT: bsrq %rsi, %rcx
-; CHECK-NEXT: cmoveq %rax, %rcx
; CHECK-NEXT: movl $63, %eax
; CHECK-NEXT: subq %rcx, %rax
; CHECK-NEXT: retq
More information about the llvm-commits
mailing list