diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 8e66b81abcfe2..04657360afe37 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4465,6 +4465,19 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) { } } + { + // Similar to above, but specialized for constant because invert is needed: + // (X | C) == (Y | C) --> (X ^ Y) & ~C == 0 + Value *X, *Y; + Constant *C; + if (match(Op0, m_OneUse(m_Or(m_Value(X), m_Constant(C)))) && + match(Op1, m_OneUse(m_Or(m_Value(Y), m_Specific(C))))) { + Value *Xor = Builder.CreateXor(X, Y); + Value *And = Builder.CreateAnd(Xor, ConstantExpr::getNot(C)); + return new ICmpInst(Pred, And, Constant::getNullValue(And->getType())); + } + } + // Transform (zext A) == (B & (1< A == (trunc B) // and (B & (1< A == (trunc B) ConstantInt *Cst1; diff --git a/llvm/test/Transforms/InstCombine/icmp-or.ll b/llvm/test/Transforms/InstCombine/icmp-or.ll index f7c03feb3eeaf..7c821aa2a3209 100644 --- a/llvm/test/Transforms/InstCombine/icmp-or.ll +++ b/llvm/test/Transforms/InstCombine/icmp-or.ll @@ -113,9 +113,9 @@ define i1 @set_low_bit_mask_sle(i8 %x) { define i1 @eq_const_mask(i8 %x, i8 %y) { ; CHECK-LABEL: @eq_const_mask( -; CHECK-NEXT: [[B0:%.*]] = or i8 [[X:%.*]], 42 -; CHECK-NEXT: [[B1:%.*]] = or i8 [[Y:%.*]], 42 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[B0]], [[B1]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], -43 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP2]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %b0 = or i8 %x, 42 @@ -126,9 +126,9 @@ define i1 @eq_const_mask(i8 %x, i8 %y) { define <2 x i1> @ne_const_mask(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @ne_const_mask( -; CHECK-NEXT: [[B0:%.*]] = or <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[B1:%.*]] = or <2 x i8> [[Y:%.*]], -; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[B0]], [[B1]] +; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i8> [[TMP1]], +; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[TMP2]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %b0 = or <2 x i8> %x, @@ -137,6 +137,8 @@ define <2 x i1> @ne_const_mask(<2 x i8> %x, <2 x i8> %y) { ret <2 x i1> %cmp } +; negative test - predicate + define i1 @eq_const_mask_not_equality(i8 %x, i8 %y) { ; CHECK-LABEL: @eq_const_mask_not_equality( ; CHECK-NEXT: [[B0:%.*]] = or i8 [[X:%.*]], 5 @@ -150,6 +152,8 @@ define i1 @eq_const_mask_not_equality(i8 %x, i8 %y) { ret i1 %cmp } +; negative test - mismatched constants + define i1 @eq_const_mask_not_same(i8 %x, i8 %y) { ; CHECK-LABEL: @eq_const_mask_not_same( ; CHECK-NEXT: [[B0:%.*]] = or i8 [[X:%.*]], 5 @@ -163,6 +167,8 @@ define i1 @eq_const_mask_not_same(i8 %x, i8 %y) { ret i1 %cmp } +; negative test - mismatched logic + define i1 @eq_const_mask_wrong_opcode(i8 %x, i8 %y) { ; CHECK-LABEL: @eq_const_mask_wrong_opcode( ; CHECK-NEXT: [[B0:%.*]] = or i8 [[X:%.*]], 5 @@ -176,6 +182,8 @@ define i1 @eq_const_mask_wrong_opcode(i8 %x, i8 %y) { ret i1 %cmp } +; negative test - no extra uses + define i1 @eq_const_mask_use1(i8 %x, i8 %y) { ; CHECK-LABEL: @eq_const_mask_use1( ; CHECK-NEXT: [[B0:%.*]] = or i8 [[X:%.*]], 5 @@ -191,6 +199,8 @@ define i1 @eq_const_mask_use1(i8 %x, i8 %y) { ret i1 %cmp } +; negative test - no extra uses + define i1 @eq_const_mask_use2(i8 %x, i8 %y) { ; CHECK-LABEL: @eq_const_mask_use2( ; CHECK-NEXT: [[B0:%.*]] = or i8 [[X:%.*]], 5