Commit d8403914 authored by Noah Goldstein's avatar Noah Goldstein
Browse files

[ValueTracking] Add logic for `isKnownNonZero(smin/smax X, Y)`

For `smin` if either `X` or `Y` is negative, the result is non-zero.
For `smax` if either `X` or `Y` is strictly positive, the result is
non-zero.

For both if `X != 0` and `Y != 0` the result is non-zero.

Alive2 Link:
    https://alive2.llvm.org/ce/z/7yvbgN
    https://alive2.llvm.org/ce/z/zizbvq

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149417
parent e78c30a1
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -2942,6 +2942,26 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
            isKnownNonZero(II->getArgOperand(1), DemandedElts, Depth, Q))
          return true;
        break;
      case Intrinsic::smin:
      case Intrinsic::smax: {
        auto KnownOpImpliesNonZero = [&](const KnownBits &K) {
          return II->getIntrinsicID() == Intrinsic::smin
                     ? K.isNegative()
                     : K.isStrictlyPositive();
        };
        KnownBits XKnown =
            computeKnownBits(II->getArgOperand(0), DemandedElts, Depth, Q);
        if (KnownOpImpliesNonZero(XKnown))
          return true;
        KnownBits YKnown =
            computeKnownBits(II->getArgOperand(1), DemandedElts, Depth, Q);
        if (KnownOpImpliesNonZero(YKnown))
          return true;

        if (XKnown.isNonZero() && YKnown.isNonZero())
          return true;
      }
        [[fallthrough]];
      case Intrinsic::umin:
        return isKnownNonZero(II->getArgOperand(0), DemandedElts, Depth, Q) &&
               isKnownNonZero(II->getArgOperand(1), DemandedElts, Depth, Q);
+1 −6
Original line number Diff line number Diff line
@@ -1074,12 +1074,7 @@ define i1 @smin_nonzero_fail_y_maybe_z(i8 %xx, i8 %yy, i8 %ind) {

define i1 @smax_nonzero_pos_arg(i8 %xx, i8 %yy, i8 %ind) {
; CHECK-LABEL: @smax_nonzero_pos_arg(
; CHECK-NEXT:    [[YA:%.*]] = and i8 [[YY:%.*]], 127
; CHECK-NEXT:    [[YO:%.*]] = or i8 [[YA]], 1
; CHECK-NEXT:    [[X:%.*]] = call i8 @llvm.smax.i8(i8 [[XX:%.*]], i8 [[YO]])
; CHECK-NEXT:    [[Z:%.*]] = or i8 [[X]], [[IND:%.*]]
; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[Z]], 0
; CHECK-NEXT:    ret i1 [[R]]
; CHECK-NEXT:    ret i1 false
;
  %ya = and i8 %yy, 127
  %yo = or i8 %ya, 1
+2 −3
Original line number Diff line number Diff line
@@ -263,10 +263,9 @@ define double @external_use_without_fast_math(ptr %a, i64 %n) {
; AUTO_VEC-LABEL: @external_use_without_fast_math(
; AUTO_VEC-NEXT:  entry:
; AUTO_VEC-NEXT:    [[SMAX:%.*]] = tail call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1)
; AUTO_VEC-NEXT:    [[TMP0:%.*]] = add nsw i64 [[SMAX]], -1
; AUTO_VEC-NEXT:    [[XTRAITER:%.*]] = and i64 [[SMAX]], 7
; AUTO_VEC-NEXT:    [[TMP1:%.*]] = icmp ult i64 [[TMP0]], 7
; AUTO_VEC-NEXT:    br i1 [[TMP1]], label [[FOR_END_UNR_LCSSA:%.*]], label [[ENTRY_NEW:%.*]]
; AUTO_VEC-NEXT:    [[TMP0:%.*]] = icmp ult i64 [[SMAX]], 8
; AUTO_VEC-NEXT:    br i1 [[TMP0]], label [[FOR_END_UNR_LCSSA:%.*]], label [[ENTRY_NEW:%.*]]
; AUTO_VEC:       entry.new:
; AUTO_VEC-NEXT:    [[UNROLL_ITER:%.*]] = and i64 [[SMAX]], 9223372036854775800
; AUTO_VEC-NEXT:    br label [[FOR_BODY:%.*]]
+4 −4
Original line number Diff line number Diff line
@@ -943,7 +943,7 @@ define float @scalarize_induction_variable_02(ptr %a, ptr %b, i64 %n) {
; IND-NEXT:    [[TMP0:%.*]] = add nsw i64 [[SMAX]], -1
; IND-NEXT:    [[TMP1:%.*]] = lshr i64 [[TMP0]], 3
; IND-NEXT:    [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1
; IND-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 8
; IND-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[SMAX]], 9
; IND-NEXT:    br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
; IND:       vector.ph:
; IND-NEXT:    [[N_VEC:%.*]] = and i64 [[TMP2]], -2
@@ -1003,7 +1003,7 @@ define float @scalarize_induction_variable_02(ptr %a, ptr %b, i64 %n) {
; UNROLL-NEXT:    [[TMP0:%.*]] = add nsw i64 [[SMAX]], -1
; UNROLL-NEXT:    [[TMP1:%.*]] = lshr i64 [[TMP0]], 3
; UNROLL-NEXT:    [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1
; UNROLL-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 24
; UNROLL-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[SMAX]], 25
; UNROLL-NEXT:    br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
; UNROLL:       vector.ph:
; UNROLL-NEXT:    [[N_VEC:%.*]] = and i64 [[TMP2]], -4
@@ -1160,10 +1160,10 @@ define float @scalarize_induction_variable_02(ptr %a, ptr %b, i64 %n) {
; INTERLEAVE-LABEL: @scalarize_induction_variable_02(
; INTERLEAVE-NEXT:  entry:
; INTERLEAVE-NEXT:    [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 8)
; INTERLEAVE-NEXT:    [[TMP0:%.*]] = add nsw i64 [[SMAX]], -1
; INTERLEAVE-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 64
; INTERLEAVE-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[SMAX]], 65
; INTERLEAVE-NEXT:    br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
; INTERLEAVE:       vector.ph:
; INTERLEAVE-NEXT:    [[TMP0:%.*]] = add nsw i64 [[SMAX]], -1
; INTERLEAVE-NEXT:    [[TMP1:%.*]] = lshr i64 [[TMP0]], 3
; INTERLEAVE-NEXT:    [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1
; INTERLEAVE-NEXT:    [[N_MOD_VF:%.*]] = and i64 [[TMP2]], 7
+1 −1
Original line number Diff line number Diff line
@@ -1278,7 +1278,7 @@ define void @PR27626_4(ptr %a, i32 %x, i32 %y, i32 %z, i64 %n) {
; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i64 [[SMAX]], -1
; CHECK-NEXT:    [[TMP1:%.*]] = lshr i64 [[TMP0]], 1
; CHECK-NEXT:    [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1
; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 6
; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[SMAX]], 7
; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
; CHECK:       vector.ph:
; CHECK-NEXT:    [[N_VEC:%.*]] = and i64 [[TMP2]], -4
Loading