Skip to content

Commit 6410bdd

Browse files
authored
[InstCombine] Extend #125676 to handle variable power of 2 (#125855)
Alive2: https://alive2.llvm.org/ce/z/dJehZ8
1 parent e223485 commit 6410bdd

File tree

2 files changed

+41
-5
lines changed

2 files changed

+41
-5
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4200,14 +4200,14 @@ Value *InstCombinerImpl::foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS,
42004200

42014201
// Fold (icmp eq/ne (X & Pow2), 0) ^ (icmp eq/ne (Y & Pow2), 0) into
42024202
// (icmp eq/ne ((X ^ Y) & Pow2), 0)
4203-
Value *X, *Y;
4204-
const APInt *Mask;
4203+
Value *X, *Y, *Pow2;
42054204
if (ICmpInst::isEquality(PredL) && ICmpInst::isEquality(PredR) &&
42064205
LC->isZero() && RC->isZero() && LHS->hasOneUse() && RHS->hasOneUse() &&
4207-
match(LHS0, m_And(m_Value(X), m_Power2(Mask))) &&
4208-
match(RHS0, m_And(m_Value(Y), m_SpecificInt(*Mask)))) {
4206+
match(LHS0, m_And(m_Value(X), m_Value(Pow2))) &&
4207+
match(RHS0, m_And(m_Value(Y), m_Specific(Pow2))) &&
4208+
isKnownToBeAPowerOfTwo(Pow2, /*OrZero=*/true, /*Depth=*/0, &I)) {
42094209
Value *Xor = Builder.CreateXor(X, Y);
4210-
Value *And = Builder.CreateAnd(Xor, *Mask);
4210+
Value *And = Builder.CreateAnd(Xor, Pow2);
42114211
return Builder.CreateICmp(PredL == PredR ? ICmpInst::ICMP_NE
42124212
: ICmpInst::ICMP_EQ,
42134213
And, ConstantInt::getNullValue(Xor->getType()));

llvm/test/Transforms/InstCombine/xor-icmps.ll

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,42 @@ define i1 @test_xor_of_bittest_ne_ne(i8 %x, i8 %y) {
335335
ret i1 %xor
336336
}
337337

338+
define i1 @test_xor_of_bittest_ne_ne_var_pow2(i8 %x, i8 %y, i8 %shamt) {
339+
; CHECK-LABEL: @test_xor_of_bittest_ne_ne_var_pow2(
340+
; CHECK-NEXT: [[POW2:%.*]] = shl nuw i8 1, [[SHAMT:%.*]]
341+
; CHECK-NEXT: [[Y:%.*]] = xor i8 [[X:%.*]], [[Y1:%.*]]
342+
; CHECK-NEXT: [[MASK2:%.*]] = and i8 [[Y]], [[POW2]]
343+
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[MASK2]], 0
344+
; CHECK-NEXT: ret i1 [[CMP2]]
345+
;
346+
%pow2 = shl nuw i8 1, %shamt
347+
%mask1 = and i8 %x, %pow2
348+
%cmp1 = icmp ne i8 %mask1, 0
349+
%mask2 = and i8 %y, %pow2
350+
%cmp2 = icmp ne i8 %mask2, 0
351+
%xor = xor i1 %cmp1, %cmp2
352+
ret i1 %xor
353+
}
354+
355+
define i1 @test_xor_of_bittest_ne_ne_var_pow2_or_zero(i8 %x, i8 %y, i8 %z) {
356+
; CHECK-LABEL: @test_xor_of_bittest_ne_ne_var_pow2_or_zero(
357+
; CHECK-NEXT: [[NZ:%.*]] = sub i8 0, [[Z:%.*]]
358+
; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]]
359+
; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], [[NZ]]
360+
; CHECK-NEXT: [[MASK2:%.*]] = and i8 [[TMP2]], [[Z]]
361+
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[MASK2]], 0
362+
; CHECK-NEXT: ret i1 [[CMP2]]
363+
;
364+
%nz = sub i8 0, %z
365+
%pow2 = and i8 %z, %nz
366+
%mask1 = and i8 %x, %pow2
367+
%cmp1 = icmp ne i8 %mask1, 0
368+
%mask2 = and i8 %y, %pow2
369+
%cmp2 = icmp ne i8 %mask2, 0
370+
%xor = xor i1 %cmp1, %cmp2
371+
ret i1 %xor
372+
}
373+
338374
define i1 @test_xor_of_bittest_eq_eq(i8 %x, i8 %y) {
339375
; CHECK-LABEL: @test_xor_of_bittest_eq_eq(
340376
; CHECK-NEXT: [[Y:%.*]] = xor i8 [[X:%.*]], [[Y1:%.*]]

0 commit comments

Comments
 (0)