Skip to content

Commit c5f40bf

Browse files
authored
[InstCombine] Fold X!=Y ? ctz(X^Y, true) : BW -> ctz(X^Y, false) (#128483)
Proof: https://alive2.llvm.org/ce/z/mzL6W2 Closes #128441.
1 parent 6c2d418 commit c5f40bf

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1227,8 +1227,10 @@ static Value *foldSelectCttzCtlz(ICmpInst *ICI, Value *TrueVal, Value *FalseVal,
12271227

12281228
// (X == 0) ? BitWidth : ctz(X)
12291229
// (X == -1) ? BitWidth : ctz(~X)
1230+
// (X == Y) ? BitWidth : ctz(X ^ Y)
12301231
if ((X != CmpLHS || !match(CmpRHS, m_Zero())) &&
1231-
(!match(X, m_Not(m_Specific(CmpLHS))) || !match(CmpRHS, m_AllOnes())))
1232+
(!match(X, m_Not(m_Specific(CmpLHS))) || !match(CmpRHS, m_AllOnes())) &&
1233+
!match(X, m_c_Xor(m_Specific(CmpLHS), m_Specific(CmpRHS))))
12321234
return nullptr;
12331235

12341236
IntrinsicInst *II = cast<IntrinsicInst>(Count);

llvm/test/Transforms/InstCombine/select-cmp-cttz-ctlz.ll

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,67 @@ define i16 @test_multiuse_trunc_undef(i64 %x, ptr %p) {
657657
ret i16 %cond
658658
}
659659

660+
define i64 @test_pr128441(i64 %x, i64 %y) {
661+
; CHECK-LABEL: @test_pr128441(
662+
; CHECK-NEXT: [[XOR:%.*]] = xor i64 [[X:%.*]], [[Y:%.*]]
663+
; CHECK-NEXT: [[SEL:%.*]] = call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[XOR]], i1 false)
664+
; CHECK-NEXT: ret i64 [[SEL]]
665+
;
666+
%iszero = icmp ne i64 %x, %y
667+
%xor = xor i64 %x, %y
668+
%cttz = call i64 @llvm.cttz.i64(i64 %xor, i1 true)
669+
%sel = select i1 %iszero, i64 %cttz, i64 64
670+
ret i64 %sel
671+
}
672+
673+
define i64 @test_pr128441_commuted1(i64 %x, i64 %y) {
674+
; CHECK-LABEL: @test_pr128441_commuted1(
675+
; CHECK-NEXT: [[XOR:%.*]] = xor i64 [[Y:%.*]], [[X:%.*]]
676+
; CHECK-NEXT: [[SEL:%.*]] = call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[XOR]], i1 false)
677+
; CHECK-NEXT: ret i64 [[SEL]]
678+
;
679+
%iszero = icmp ne i64 %x, %y
680+
%xor = xor i64 %y, %x
681+
%cttz = call i64 @llvm.cttz.i64(i64 %xor, i1 true)
682+
%sel = select i1 %iszero, i64 %cttz, i64 64
683+
ret i64 %sel
684+
}
685+
686+
define i64 @test_pr128441_commuted2(i64 %x, i64 %y) {
687+
; CHECK-LABEL: @test_pr128441_commuted2(
688+
; CHECK-NEXT: [[XOR:%.*]] = xor i64 [[X:%.*]], [[Y:%.*]]
689+
; CHECK-NEXT: [[SEL:%.*]] = call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[XOR]], i1 false)
690+
; CHECK-NEXT: ret i64 [[SEL]]
691+
;
692+
%iszero = icmp eq i64 %x, %y
693+
%xor = xor i64 %x, %y
694+
%cttz = call i64 @llvm.cttz.i64(i64 %xor, i1 true)
695+
%sel = select i1 %iszero, i64 64, i64 %cttz
696+
ret i64 %sel
697+
}
698+
699+
define i64 @test_pr128441_commuted3_negative(i64 %x, i64 %y) {
700+
; CHECK-LABEL: @test_pr128441_commuted3_negative(
701+
; CHECK-NEXT: ret i64 64
702+
;
703+
%iszero = icmp eq i64 %x, %y
704+
%xor = xor i64 %y, %x
705+
%cttz = call i64 @llvm.cttz.i64(i64 %xor, i1 true)
706+
%sel = select i1 %iszero, i64 %cttz, i64 64
707+
ret i64 %sel
708+
}
709+
710+
define i64 @test_pr128441_commuted4_negative(i64 %x, i64 %y) {
711+
; CHECK-LABEL: @test_pr128441_commuted4_negative(
712+
; CHECK-NEXT: ret i64 64
713+
;
714+
%iszero = icmp ne i64 %x, %y
715+
%xor = xor i64 %x, %y
716+
%cttz = call i64 @llvm.cttz.i64(i64 %xor, i1 true)
717+
%sel = select i1 %iszero, i64 64, i64 %cttz
718+
ret i64 %sel
719+
}
720+
660721
declare i16 @llvm.ctlz.i16(i16, i1)
661722
declare i32 @llvm.ctlz.i32(i32, i1)
662723
declare i64 @llvm.ctlz.i64(i64, i1)

0 commit comments

Comments
 (0)