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 @@ -1001,15 +1001,15 @@ bool ShiftAmtIsConstant = Known.isConstant(); bool MaxShiftAmtIsOutOfRange = Known.getMaxValue().uge(BitWidth); - if (ShiftAmtIsConstant) { - Known = KF(Known2, Known); + // 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; } @@ -1018,14 +1018,9 @@ // expensive. // TODO: Should we just carry on? if (MaxShiftAmtIsOutOfRange) { - Known.resetAll(); return; } - // 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/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1702,6 +1702,17 @@ if (Instruction *X = foldVectorBinop(I)) return X; + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + + Value *X, *Y; + if (match(Op0, m_OneUse(m_LogicalShift(m_One(), m_Value(X)))) && + match(Op1, m_One())) { + // (1 << X) & 1 --> zext(X == 0) + // (1 >> X) & 1 --> zext(X == 0) + Value *IsZero = Builder.CreateICmpEQ(X, ConstantInt::get(Ty, 0)); + return new ZExtInst(IsZero, Ty); + } + // See if we can simplify any instructions used by the instruction whose sole // purpose is to compute bits we don't care about. if (SimplifyDemandedInstructionBits(I)) @@ -1718,17 +1729,6 @@ if (Value *V = SimplifyBSwap(I, Builder)) return replaceInstUsesWith(I, V); - Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); - - Value *X, *Y; - if (match(Op0, m_OneUse(m_LogicalShift(m_One(), m_Value(X)))) && - match(Op1, m_One())) { - // (1 << X) & 1 --> zext(X == 0) - // (1 >> X) & 1 --> zext(X == 0) - Value *IsZero = Builder.CreateICmpEQ(X, ConstantInt::get(Ty, 0)); - return new ZExtInst(IsZero, Ty); - } - const APInt *C; if (match(Op1, m_APInt(C))) { const APInt *XorC; 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 @@ -164,8 +164,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 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 @@ -211,15 +205,13 @@ ret i1 %r } -; Negative tests - ; Check 'slt' predicate define i1 @scalar_i32_signbit_shl_and_slt(i32 %x, i32 %y) { ; 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 +224,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]]