[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:
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user