[llvm] [X86] Use BSR passthrough behaviour to fold (CMOV (BSR ?, X), Y, (X == 0)) -> (BSR Y, X) (PR #143662)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 11 00:44:12 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: Simon Pilgrim (RKSimon)
<details>
<summary>Changes</summary>
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
---
Full diff: https://github.com/llvm/llvm-project/pull/143662.diff
3 Files Affected:
- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+10)
- (modified) llvm/test/CodeGen/X86/bsr.ll (+4-6)
- (modified) llvm/test/CodeGen/X86/pr40090.ll (+4-7)
``````````diff
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
``````````
</details>
https://github.com/llvm/llvm-project/pull/143662
More information about the llvm-commits
mailing list