Commit e46dd6fb authored by Nikita Popov's avatar Nikita Popov
Browse files

Revert "[InstCombine] Simplify and/or of icmp eq with op replacement (#70335)"

This reverts commit 1770a2e3.

Stage 2 llvm-tblgen crashes when generating X86GenAsmWriter.inc and
other files.
parent 9a7c26a3
Loading
Loading
Loading
Loading
+0 −60
Original line number Diff line number Diff line
@@ -2025,52 +2025,6 @@ static Value *simplifyAndOrOfCmps(const SimplifyQuery &Q, Value *Op0,
  return nullptr;
}

static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
                                     const SimplifyQuery &Q,
                                     bool AllowRefinement,
                                     SmallVectorImpl<Instruction *> *DropFlags,
                                     unsigned MaxRecurse);

static Value *simplifyAndOrWithICmpEq(unsigned Opcode, Value *Op0, Value *Op1,
                                      const SimplifyQuery &Q,
                                      unsigned MaxRecurse) {
  assert((Opcode == Instruction::And || Opcode == Instruction::Or) &&
         "Must be and/or");
  ICmpInst::Predicate Pred;
  Value *A, *B;
  if (!match(Op0, m_ICmp(Pred, m_Value(A), m_Value(B))) ||
      !ICmpInst::isEquality(Pred) || !MaxRecurse--)
    return nullptr;

  auto Simplify = [&](Value *Res) -> Value * {
    // and (icmp eq a, b), x implies (a==b) inside x.
    // or (icmp ne a, b), x implies (a==b) inside x.
    // If x simplifies to true/false, we can simplify the and/or.
    if (Pred ==
        (Opcode == Instruction::And ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE))
      return simplifyBinOp(Opcode, Op0, Res, Q, MaxRecurse);
    // If we have and (icmp ne a, b), x and for a==b we can simplify x to false,
    // then we can drop the icmp, as x will already be false in the case where
    // the icmp is false. Similar for or and true.
    if (Res == ConstantExpr::getBinOpAbsorber(Opcode, Res->getType()))
      return Op1;
    return nullptr;
  };

  // Increment MaxRecurse again, because simplifyWithOpReplaced() does its own
  // decrement.
  if (Value *Res =
          simplifyWithOpReplaced(Op1, A, B, Q, /* AllowRefinement */ true,
                                 /* DropFlags */ nullptr, MaxRecurse + 1))
    return Simplify(Res);
  if (Value *Res =
          simplifyWithOpReplaced(Op1, B, A, Q, /* AllowRefinement */ true,
                                 /* DropFlags */ nullptr, MaxRecurse + 1))
    return Simplify(Res);

  return nullptr;
}

/// Given a bitwise logic op, check if the operands are add/sub with a common
/// source value and inverted constant (identity: C - X -> ~(X + ~C)).
static Value *simplifyLogicOfAddSub(Value *Op0, Value *Op1,
@@ -2205,13 +2159,6 @@ static Value *simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
      isKnownToBeAPowerOfTwo(Op0, Q.DL, /*OrZero*/ true, 0, Q.AC, Q.CxtI, Q.DT))
    return Constant::getNullValue(Op0->getType());

  if (Value *V =
          simplifyAndOrWithICmpEq(Instruction::And, Op0, Op1, Q, MaxRecurse))
    return V;
  if (Value *V =
          simplifyAndOrWithICmpEq(Instruction::And, Op1, Op0, Q, MaxRecurse))
    return V;

  if (Value *V = simplifyAndOrOfCmps(Q, Op0, Op1, true))
    return V;

@@ -2488,13 +2435,6 @@ static Value *simplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
      match(Op0, m_LShr(m_Specific(X), m_Specific(Y))))
    return Op1;

  if (Value *V =
          simplifyAndOrWithICmpEq(Instruction::Or, Op0, Op1, Q, MaxRecurse))
    return V;
  if (Value *V =
          simplifyAndOrWithICmpEq(Instruction::Or, Op1, Op0, Q, MaxRecurse))
    return V;

  if (Value *V = simplifyAndOrOfCmps(Q, Op0, Op1, false))
    return V;

+7 −3
Original line number Diff line number Diff line
@@ -20,16 +20,20 @@ define hidden void @julia_tryparse_internal_45896() #0 {
; CHECK-NEXT:  .LBB0_6: # %fail194
; CHECK-NEXT:  .LBB0_7: # %L670
; CHECK-NEXT:    li r5, -3
; CHECK-NEXT:    cmpdi r3, 0
; CHECK-NEXT:    sradi r4, r3, 63
; CHECK-NEXT:    rldic r5, r5, 4, 32
; CHECK-NEXT:    crnot 4*cr5+lt, eq
; CHECK-NEXT:    mulhdu r3, r3, r5
; CHECK-NEXT:    maddld r6, r4, r5, r3
; CHECK-NEXT:    cmpld cr1, r6, r3
; CHECK-NEXT:    mulhdu. r3, r4, r5
; CHECK-NEXT:    bc 4, 4*cr5+lt, .LBB0_10
; CHECK-NEXT:  # %bb.8: # %L670
; CHECK-NEXT:    crorc 4*cr5+lt, 4*cr1+lt, eq
; CHECK-NEXT:    bc 4, 4*cr5+lt, .LBB0_9
; CHECK-NEXT:  # %bb.8: # %L917
; CHECK-NEXT:  .LBB0_9: # %L994
; CHECK-NEXT:    bc 4, 4*cr5+lt, .LBB0_10
; CHECK-NEXT:  # %bb.9: # %L917
; CHECK-NEXT:  .LBB0_10: # %L994
top:
  %0 = load i64, ptr undef, align 8
  %1 = icmp ne i64 %0, 0
+9 −2
Original line number Diff line number Diff line
@@ -47,7 +47,11 @@ define i1 @n2_wrong_size(i4 %size0, i4 %size1, i4 %nmemb) {

define i1 @n3_wrong_pred(i4 %size, i4 %nmemb) {
; CHECK-LABEL: @n3_wrong_pred(
; CHECK-NEXT:    ret i1 false
; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i4 [[SIZE:%.*]], 0
; CHECK-NEXT:    [[SMUL:%.*]] = tail call { i4, i1 } @llvm.smul.with.overflow.i4(i4 [[SIZE]], i4 [[NMEMB:%.*]])
; CHECK-NEXT:    [[SMUL_OV:%.*]] = extractvalue { i4, i1 } [[SMUL]], 1
; CHECK-NEXT:    [[AND:%.*]] = and i1 [[SMUL_OV]], [[CMP]]
; CHECK-NEXT:    ret i1 [[AND]]
;
  %cmp = icmp eq i4 %size, 0 ; not 'ne'
  %smul = tail call { i4, i1 } @llvm.smul.with.overflow.i4(i4 %size, i4 %nmemb)
@@ -59,7 +63,10 @@ define i1 @n3_wrong_pred(i4 %size, i4 %nmemb) {
define i1 @n4_not_and(i4 %size, i4 %nmemb) {
; CHECK-LABEL: @n4_not_and(
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i4 [[SIZE:%.*]], 0
; CHECK-NEXT:    ret i1 [[CMP]]
; CHECK-NEXT:    [[SMUL:%.*]] = tail call { i4, i1 } @llvm.smul.with.overflow.i4(i4 [[SIZE]], i4 [[NMEMB:%.*]])
; CHECK-NEXT:    [[SMUL_OV:%.*]] = extractvalue { i4, i1 } [[SMUL]], 1
; CHECK-NEXT:    [[AND:%.*]] = or i1 [[SMUL_OV]], [[CMP]]
; CHECK-NEXT:    ret i1 [[AND]]
;
  %cmp = icmp ne i4 %size, 0
  %smul = tail call { i4, i1 } @llvm.smul.with.overflow.i4(i4 %size, i4 %nmemb)
+9 −2
Original line number Diff line number Diff line
@@ -47,7 +47,11 @@ define i1 @n2_wrong_size(i4 %size0, i4 %size1, i4 %nmemb) {

define i1 @n3_wrong_pred(i4 %size, i4 %nmemb) {
; CHECK-LABEL: @n3_wrong_pred(
; CHECK-NEXT:    ret i1 false
; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i4 [[SIZE:%.*]], 0
; CHECK-NEXT:    [[UMUL:%.*]] = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 [[SIZE]], i4 [[NMEMB:%.*]])
; CHECK-NEXT:    [[UMUL_OV:%.*]] = extractvalue { i4, i1 } [[UMUL]], 1
; CHECK-NEXT:    [[AND:%.*]] = and i1 [[UMUL_OV]], [[CMP]]
; CHECK-NEXT:    ret i1 [[AND]]
;
  %cmp = icmp eq i4 %size, 0 ; not 'ne'
  %umul = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 %size, i4 %nmemb)
@@ -59,7 +63,10 @@ define i1 @n3_wrong_pred(i4 %size, i4 %nmemb) {
define i1 @n4_not_and(i4 %size, i4 %nmemb) {
; CHECK-LABEL: @n4_not_and(
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i4 [[SIZE:%.*]], 0
; CHECK-NEXT:    ret i1 [[CMP]]
; CHECK-NEXT:    [[UMUL:%.*]] = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 [[SIZE]], i4 [[NMEMB:%.*]])
; CHECK-NEXT:    [[UMUL_OV:%.*]] = extractvalue { i4, i1 } [[UMUL]], 1
; CHECK-NEXT:    [[AND:%.*]] = or i1 [[UMUL_OV]], [[CMP]]
; CHECK-NEXT:    ret i1 [[AND]]
;
  %cmp = icmp ne i4 %size, 0
  %umul = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 %size, i4 %nmemb)
+19 −5
Original line number Diff line number Diff line
@@ -392,7 +392,9 @@ define i1 @is_pow2_ctpop_wrong_pred1(i32 %x) {
; CHECK-LABEL: @is_pow2_ctpop_wrong_pred1(
; CHECK-NEXT:    [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[T0]], 2
; CHECK-NEXT:    ret i1 [[CMP]]
; CHECK-NEXT:    [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
; CHECK-NEXT:    [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
; CHECK-NEXT:    ret i1 [[R]]
;
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ugt i32 %t0, 2
@@ -944,7 +946,9 @@ define i1 @is_pow2or0_ctpop_wrong_pred1(i32 %x) {
; CHECK-LABEL: @is_pow2or0_ctpop_wrong_pred1(
; CHECK-NEXT:    [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[T0]], 1
; CHECK-NEXT:    ret i1 [[CMP]]
; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
; CHECK-NEXT:    [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
; CHECK-NEXT:    ret i1 [[R]]
;
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
@@ -955,7 +959,11 @@ define i1 @is_pow2or0_ctpop_wrong_pred1(i32 %x) {

define i1 @is_pow2or0_ctpop_wrong_pred2(i32 %x) {
; CHECK-LABEL: @is_pow2or0_ctpop_wrong_pred2(
; CHECK-NEXT:    ret i1 true
; CHECK-NEXT:    [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[T0]], 1
; CHECK-NEXT:    [[ISZERO:%.*]] = icmp ne i32 [[X]], 0
; CHECK-NEXT:    [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
; CHECK-NEXT:    ret i1 [[R]]
;
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp ne i32 %t0, 1
@@ -1141,7 +1149,9 @@ define i1 @isnot_pow2nor0_ctpop_wrong_pred1(i32 %x) {
; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_pred1(
; CHECK-NEXT:    [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[T0]], 1
; CHECK-NEXT:    ret i1 [[CMP]]
; CHECK-NEXT:    [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
; CHECK-NEXT:    [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
; CHECK-NEXT:    ret i1 [[R]]
;
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
@@ -1152,7 +1162,11 @@ define i1 @isnot_pow2nor0_ctpop_wrong_pred1(i32 %x) {

define i1 @isnot_pow2nor0_ctpop_wrong_pred2(i32 %x) {
; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_pred2(
; CHECK-NEXT:    ret i1 false
; CHECK-NEXT:    [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[T0]], 1
; CHECK-NEXT:    [[NOTZERO:%.*]] = icmp eq i32 [[X]], 0
; CHECK-NEXT:    [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
; CHECK-NEXT:    ret i1 [[R]]
;
  %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
  %cmp = icmp eq i32 %t0, 1
Loading