[InstCombine] Fold X!=Y ? ctz(X^Y, true) : BW -> ctz(X^Y, false) (#128483)

Proof: https://alive2.llvm.org/ce/z/mzL6W2
Closes https://github.com/llvm/llvm-project/issues/128441.
This commit is contained in:
Yingwei Zheng
2025-02-24 17:35:46 +08:00
committed by GitHub
parent 6c2d418027
commit c5f40bf024
2 changed files with 64 additions and 1 deletions

View File

@@ -1227,8 +1227,10 @@ static Value *foldSelectCttzCtlz(ICmpInst *ICI, Value *TrueVal, Value *FalseVal,
// (X == 0) ? BitWidth : ctz(X)
// (X == -1) ? BitWidth : ctz(~X)
// (X == Y) ? BitWidth : ctz(X ^ Y)
if ((X != CmpLHS || !match(CmpRHS, m_Zero())) &&
(!match(X, m_Not(m_Specific(CmpLHS))) || !match(CmpRHS, m_AllOnes())))
(!match(X, m_Not(m_Specific(CmpLHS))) || !match(CmpRHS, m_AllOnes())) &&
!match(X, m_c_Xor(m_Specific(CmpLHS), m_Specific(CmpRHS))))
return nullptr;
IntrinsicInst *II = cast<IntrinsicInst>(Count);

View File

@@ -657,6 +657,67 @@ define i16 @test_multiuse_trunc_undef(i64 %x, ptr %p) {
ret i16 %cond
}
define i64 @test_pr128441(i64 %x, i64 %y) {
; CHECK-LABEL: @test_pr128441(
; CHECK-NEXT: [[XOR:%.*]] = xor i64 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[SEL:%.*]] = call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[XOR]], i1 false)
; CHECK-NEXT: ret i64 [[SEL]]
;
%iszero = icmp ne i64 %x, %y
%xor = xor i64 %x, %y
%cttz = call i64 @llvm.cttz.i64(i64 %xor, i1 true)
%sel = select i1 %iszero, i64 %cttz, i64 64
ret i64 %sel
}
define i64 @test_pr128441_commuted1(i64 %x, i64 %y) {
; CHECK-LABEL: @test_pr128441_commuted1(
; CHECK-NEXT: [[XOR:%.*]] = xor i64 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[SEL:%.*]] = call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[XOR]], i1 false)
; CHECK-NEXT: ret i64 [[SEL]]
;
%iszero = icmp ne i64 %x, %y
%xor = xor i64 %y, %x
%cttz = call i64 @llvm.cttz.i64(i64 %xor, i1 true)
%sel = select i1 %iszero, i64 %cttz, i64 64
ret i64 %sel
}
define i64 @test_pr128441_commuted2(i64 %x, i64 %y) {
; CHECK-LABEL: @test_pr128441_commuted2(
; CHECK-NEXT: [[XOR:%.*]] = xor i64 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[SEL:%.*]] = call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[XOR]], i1 false)
; CHECK-NEXT: ret i64 [[SEL]]
;
%iszero = icmp eq i64 %x, %y
%xor = xor i64 %x, %y
%cttz = call i64 @llvm.cttz.i64(i64 %xor, i1 true)
%sel = select i1 %iszero, i64 64, i64 %cttz
ret i64 %sel
}
define i64 @test_pr128441_commuted3_negative(i64 %x, i64 %y) {
; CHECK-LABEL: @test_pr128441_commuted3_negative(
; CHECK-NEXT: ret i64 64
;
%iszero = icmp eq i64 %x, %y
%xor = xor i64 %y, %x
%cttz = call i64 @llvm.cttz.i64(i64 %xor, i1 true)
%sel = select i1 %iszero, i64 %cttz, i64 64
ret i64 %sel
}
define i64 @test_pr128441_commuted4_negative(i64 %x, i64 %y) {
; CHECK-LABEL: @test_pr128441_commuted4_negative(
; CHECK-NEXT: ret i64 64
;
%iszero = icmp ne i64 %x, %y
%xor = xor i64 %x, %y
%cttz = call i64 @llvm.cttz.i64(i64 %xor, i1 true)
%sel = select i1 %iszero, i64 64, i64 %cttz
ret i64 %sel
}
declare i16 @llvm.ctlz.i16(i16, i1)
declare i32 @llvm.ctlz.i32(i32, i1)
declare i64 @llvm.ctlz.i64(i64, i1)