forked from OSchip/llvm-project
[InstCombine] fold icmp equality with 'or' mask ops
This could go either direction since the instruction count is the same either way, but there are a few reasons to prefer this: 1. We already do the related transform with 'and' (see just above the new code). 2. We try (too hard) to compensate for not having this and possibly other folds in transformZExtICmp(), and that leads to bugs like https://llvm.org/PR51762 . 3. Codegen looks better across a variety of targets. https://alive2.llvm.org/ce/z/uEgn4P
This commit is contained in:
parent
9565457aad
commit
a3c1669b17
|
@ -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<<X)-1) --> A == (trunc B)
|
||||
// and (B & (1<<X)-1) == (zext A) --> A == (trunc B)
|
||||
ConstantInt *Cst1;
|
||||
|
|
|
@ -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:%.*]], <i8 -106, i8 5>
|
||||
; CHECK-NEXT: [[B1:%.*]] = or <2 x i8> [[Y:%.*]], <i8 -106, i8 5>
|
||||
; 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]], <i8 105, i8 -6>
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[TMP2]], zeroinitializer
|
||||
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
||||
;
|
||||
%b0 = or <2 x i8> %x, <i8 150, i8 5>
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue