diff options
author | Simon Pilgrim <llvm-dev@redking.me.uk> | 2025-06-12 10:46:08 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-12 10:46:08 +0100 |
commit | 2a27c059eccd96b6e46464dbdf69fd2f6237a56c (patch) | |
tree | 6a3c38152121f8ac5fe10d32844fb70fedfc9c12 | |
parent | db8d34db26e9ea92c08d6e813eca9cce40c48478 (diff) | |
download | llvm-2a27c059eccd96b6e46464dbdf69fd2f6237a56c.zip llvm-2a27c059eccd96b6e46464dbdf69fd2f6237a56c.tar.gz llvm-2a27c059eccd96b6e46464dbdf69fd2f6237a56c.tar.bz2 |
[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
-rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 10 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/bsr.ll | 10 | ||||
-rw-r--r-- | 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 b0553aa..f0fbf55 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 1247b3e..fbca4af 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 24e957a..af933c9 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 |