diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -992,15 +992,23 @@ computeKnownBits(I->getOperand(0), DemandedElts, Known2, Depth + 1, Q); computeKnownBits(I->getOperand(1), DemandedElts, Known, Depth + 1, Q); - if (Known.isConstant()) { - Known = KF(Known2, Known); + // Note: We cannot use Known.Zero.getLimitedValue() here, because if + // BitWidth > 64 and any upper bits are known, we'll end up returning the + // limit value (which implies all bits are known). + uint64_t ShiftAmtKZ = Known.Zero.zextOrTrunc(64).getZExtValue(); + uint64_t ShiftAmtKO = Known.One.zextOrTrunc(64).getZExtValue(); + bool ShiftAmtIsConstant = Known.isConstant(); + bool MaxShiftAmtIsOutOfRange = Known.getMaxValue().uge(BitWidth); + + // Use the KF callback to get an initial knownbits approximation. + Known = KF(Known2, Known); + if (ShiftAmtIsConstant) { // If the known bits conflict, this must be an overflowing left shift, so // the shift result is poison. We can return anything we want. Choose 0 for // the best folding opportunity. if (Known.hasConflict()) Known.setAllZero(); - return; } @@ -1008,21 +1016,10 @@ // LHS, the value could be poison, but bail out because the check below is // expensive. // TODO: Should we just carry on? - if (Known.getMaxValue().uge(BitWidth)) { - Known.resetAll(); + if (MaxShiftAmtIsOutOfRange) { return; } - // Note: We cannot use Known.Zero.getLimitedValue() here, because if - // BitWidth > 64 and any upper bits are known, we'll end up returning the - // limit value (which implies all bits are known). - uint64_t ShiftAmtKZ = Known.Zero.zextOrTrunc(64).getZExtValue(); - uint64_t ShiftAmtKO = Known.One.zextOrTrunc(64).getZExtValue(); - - // It would be more-clearly correct to use the two temporaries for this - // calculation. Reusing the APInts here to prevent unnecessary allocations. - Known.resetAll(); - // If we know the shifter operand is nonzero, we can sometimes infer more // known bits. However this is expensive to compute, so be lazy about it and // only compute it when absolutely necessary. diff --git a/llvm/test/Transforms/InstCombine/and2.ll b/llvm/test/Transforms/InstCombine/and2.ll --- a/llvm/test/Transforms/InstCombine/and2.ll +++ b/llvm/test/Transforms/InstCombine/and2.ll @@ -150,9 +150,8 @@ define i8 @and1_lshr1_is_cmp_eq_0(i8 %x) { ; CHECK-LABEL: @and1_lshr1_is_cmp_eq_0( -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 -; CHECK-NEXT: [[AND:%.*]] = zext i1 [[TMP1]] to i8 -; CHECK-NEXT: ret i8 [[AND]] +; CHECK-NEXT: [[SH:%.*]] = lshr i8 1, [[X:%.*]] +; CHECK-NEXT: ret i8 [[SH]] ; %sh = lshr i8 1, %x %and = and i8 %sh, 1 @@ -164,8 +163,7 @@ define i8 @and1_lshr1_is_cmp_eq_0_multiuse(i8 %x) { ; CHECK-LABEL: @and1_lshr1_is_cmp_eq_0_multiuse( ; CHECK-NEXT: [[SH:%.*]] = lshr i8 1, [[X:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[SH]], 1 -; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i8 [[SH]], [[AND]] +; CHECK-NEXT: [[ADD:%.*]] = shl nuw nsw i8 [[SH]], 1 ; CHECK-NEXT: ret i8 [[ADD]] ; %sh = lshr i8 1, %x @@ -178,9 +176,8 @@ define <2 x i8> @and1_lshr1_is_cmp_eq_0_vec(<2 x i8> %x) { ; CHECK-LABEL: @and1_lshr1_is_cmp_eq_0_vec( -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer -; CHECK-NEXT: [[AND:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8> -; CHECK-NEXT: ret <2 x i8> [[AND]] +; CHECK-NEXT: [[SH:%.*]] = lshr <2 x i8> , [[X:%.*]] +; CHECK-NEXT: ret <2 x i8> [[SH]] ; %sh = lshr <2 x i8> , %x %and = and <2 x i8> %sh, diff --git a/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll b/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll --- a/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll +++ b/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll @@ -184,7 +184,8 @@ define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant1(i32 %y) { ; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant1( ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 12345, [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[LSHR]], 8 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], 16376 +; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %lshr = lshr i32 12345, %y @@ -196,7 +197,8 @@ define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant2(i32 %y) { ; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant2( ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 268435456, [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[LSHR]], 8 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], 536870904 +; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %lshr = lshr i32 268435456, %y diff --git a/llvm/test/Transforms/InstCombine/signbit-shl-and-icmpeq-zero.ll b/llvm/test/Transforms/InstCombine/signbit-shl-and-icmpeq-zero.ll --- a/llvm/test/Transforms/InstCombine/signbit-shl-and-icmpeq-zero.ll +++ b/llvm/test/Transforms/InstCombine/signbit-shl-and-icmpeq-zero.ll @@ -187,10 +187,7 @@ define i1 @scalar_i32_signbit_shl_and_eq_X_is_constant1(i32 %y) { ; CHECK-LABEL: @scalar_i32_signbit_shl_and_eq_X_is_constant1( -; CHECK-NEXT: [[SHL:%.*]] = shl i32 -2147483648, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], 12345 -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %shl = shl i32 2147483648, %y %and = and i32 %shl, 12345 @@ -200,10 +197,7 @@ define i1 @scalar_i32_signbit_shl_and_eq_X_is_constant2(i32 %y) { ; CHECK-LABEL: @scalar_i32_signbit_shl_and_eq_X_is_constant2( -; CHECK-NEXT: [[SHL:%.*]] = shl i32 -2147483648, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], 1 -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %shl = shl i32 2147483648, %y %and = and i32 %shl, 1 @@ -219,7 +213,7 @@ ; CHECK-LABEL: @scalar_i32_signbit_shl_and_slt( ; CHECK-NEXT: [[SHL:%.*]] = shl i32 -2147483648, [[Y:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[AND]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[AND]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %shl = shl i32 2147483648, %y @@ -232,10 +226,7 @@ define i1 @scalar_i32_signbit_shl_and_eq_nonzero(i32 %x, i32 %y) { ; CHECK-LABEL: @scalar_i32_signbit_shl_and_eq_nonzero( -; CHECK-NEXT: [[SHL:%.*]] = shl i32 -2147483648, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 1 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %shl = shl i32 2147483648, %y %and = and i32 %shl, %x diff --git a/llvm/test/Transforms/InstCombine/zext-or-icmp.ll b/llvm/test/Transforms/InstCombine/zext-or-icmp.ll --- a/llvm/test/Transforms/InstCombine/zext-or-icmp.ll +++ b/llvm/test/Transforms/InstCombine/zext-or-icmp.ll @@ -32,10 +32,7 @@ ; CHECK-NEXT: br label [[BLOCK2]] ; CHECK: block2: ; CHECK-NEXT: [[CMP_I:%.*]] = phi i1 [ false, [[BLOCK1:%.*]] ], [ true, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[M_011:%.*]] = phi i32 [ 0, [[BLOCK1]] ], [ 33, [[ENTRY]] ] -; CHECK-NEXT: [[M_1_OP:%.*]] = lshr i32 1, [[M_011]] -; CHECK-NEXT: [[SEXT_MASK:%.*]] = and i32 [[M_1_OP]], 65535 -; CHECK-NEXT: [[CMP115:%.*]] = icmp ne i32 [[SEXT_MASK]], 0 +; CHECK-NEXT: [[CMP115:%.*]] = phi i1 [ true, [[BLOCK1]] ], [ false, [[ENTRY]] ] ; CHECK-NEXT: [[CMP1:%.*]] = or i1 [[CMP_I]], [[CMP115]] ; CHECK-NEXT: [[CONV2:%.*]] = zext i1 [[CMP1]] to i32 ; CHECK-NEXT: ret i32 [[CONV2]]