[llvm] 2a27c05 - [X86] Use BSR passthrough behaviour to fold (CMOV (BSR ?, X), Y, (X == 0)) -> (BSR Y, X) (#143662)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 12 02:46:12 PDT 2025
Author: Simon Pilgrim
Date: 2025-06-12T10:46:08+01:00
New Revision: 2a27c059eccd96b6e46464dbdf69fd2f6237a56c
URL: https://github.com/llvm/llvm-project/commit/2a27c059eccd96b6e46464dbdf69fd2f6237a56c
DIFF: https://github.com/llvm/llvm-project/commit/2a27c059eccd96b6e46464dbdf69fd2f6237a56c.diff
LOG: [X86] Use BSR passthrough behaviour to fold (CMOV (BSR ?, X), Y, (X == 0)) -> (BSR Y, X) (#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
Added:
Modified:
llvm/lib/Target/X86/X86ISelLowering.cpp
llvm/test/CodeGen/X86/bsr.ll
llvm/test/CodeGen/X86/pr40090.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index b0553aa4b8197..f0fbf55e97be9 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -49398,6 +49398,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;
@@ -49406,6 +49408,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