diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index fb744d61aad63..28d7e1ce401e4 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -797,10 +797,28 @@ static void computeKnownBitsFromCond(const Value *V, Value *Cond, else Known2 = Known2.intersectWith(Known3); Known = Known.unionWith(Known2); + return; } - if (auto *Cmp = dyn_cast(Cond)) + if (auto *Cmp = dyn_cast(Cond)) { computeKnownBitsFromICmpCond(V, Cmp, Known, SQ, Invert); + return; + } + + if (match(Cond, m_Trunc(m_Specific(V)))) { + KnownBits DstKnown(1); + if (Invert) { + DstKnown.setAllZero(); + } else { + DstKnown.setAllOnes(); + } + if (cast(Cond)->hasNoUnsignedWrap()) { + Known = Known.unionWith(DstKnown.zext(Known.getBitWidth())); + return; + } + Known = Known.unionWith(DstKnown.anyext(Known.getBitWidth())); + return; + } if (Depth < MaxAnalysisRecursionDepth && match(Cond, m_Not(m_Value(A)))) computeKnownBitsFromCond(V, A, Known, Depth + 1, SQ, !Invert); @@ -10280,6 +10298,10 @@ void llvm::findValuesAffectedByCondition( m_Value()))) { // Handle patterns that computeKnownFPClass() support. AddAffected(A); + } else if (!IsAssume && match(V, m_Trunc(m_Value(X)))) { + // Assume is checked here as X is already added above for assumes in + // addValueAffectedByCondition + AddAffected(X); } else if (!IsAssume && match(V, m_Not(m_Value(X)))) { // Assume is checked here to avoid issues with ephemeral values Worklist.push_back(X); diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index b729cbd971acc..9a9fec694ff0e 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -2167,11 +2167,9 @@ define i8 @test_trunc_and_1(i8 %a) { ; CHECK-NEXT: [[CAST:%.*]] = trunc i8 [[A:%.*]] to i1 ; CHECK-NEXT: br i1 [[CAST]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[B:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[B]] +; CHECK-NEXT: ret i8 1 ; CHECK: if.else: -; CHECK-NEXT: [[C:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[C]] +; CHECK-NEXT: ret i8 0 ; entry: %cast = trunc i8 %a to i1 @@ -2192,11 +2190,9 @@ define i8 @test_not_trunc_and_1(i8 %a) { ; CHECK-NEXT: [[CAST:%.*]] = trunc i8 [[A:%.*]] to i1 ; CHECK-NEXT: br i1 [[CAST]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[B:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[B]] +; CHECK-NEXT: ret i8 0 ; CHECK: if.else: -; CHECK-NEXT: [[C:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[C]] +; CHECK-NEXT: ret i8 1 ; entry: %cast = trunc i8 %a to i1 @@ -2243,11 +2239,9 @@ define i8 @test_trunc_nuw_and_1(i8 %a) { ; CHECK-NEXT: [[CAST:%.*]] = trunc nuw i8 [[A:%.*]] to i1 ; CHECK-NEXT: br i1 [[CAST]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[B:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[B]] +; CHECK-NEXT: ret i8 0 ; CHECK: if.else: -; CHECK-NEXT: [[C:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[C]] +; CHECK-NEXT: ret i8 1 ; entry: %cast = trunc nuw i8 %a to i1 @@ -2268,11 +2262,9 @@ define i8 @test_trunc_nuw_or_2(i8 %a) { ; CHECK-NEXT: [[CAST:%.*]] = trunc nuw i8 [[A:%.*]] to i1 ; CHECK-NEXT: br i1 [[CAST]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[B:%.*]] = or i8 [[A]], 2 -; CHECK-NEXT: ret i8 [[B]] +; CHECK-NEXT: ret i8 2 ; CHECK: if.else: -; CHECK-NEXT: [[C:%.*]] = or i8 [[A]], 2 -; CHECK-NEXT: ret i8 [[C]] +; CHECK-NEXT: ret i8 3 ; entry: %cast = trunc nuw i8 %a to i1 @@ -2293,11 +2285,9 @@ define i8 @test_not_trunc_nuw_and_1(i8 %a) { ; CHECK-NEXT: [[CAST:%.*]] = trunc nuw i8 [[A:%.*]] to i1 ; CHECK-NEXT: br i1 [[CAST]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[B:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[B]] +; CHECK-NEXT: ret i8 0 ; CHECK: if.else: -; CHECK-NEXT: [[C:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[C]] +; CHECK-NEXT: ret i8 1 ; entry: %cast = trunc nuw i8 %a to i1 @@ -2319,8 +2309,7 @@ define i8 @test_trunc_cond_and(i8 %x, i1 %c) { ; CHECK-NEXT: [[COND:%.*]] = and i1 [[C:%.*]], [[CMP]] ; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[EXIT:%.*]] ; CHECK: if: -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[X]], -2 -; CHECK-NEXT: ret i8 [[OR1]] +; CHECK-NEXT: ret i8 -1 ; CHECK: exit: ; CHECK-NEXT: [[OR2:%.*]] = or i8 [[X]], -2 ; CHECK-NEXT: ret i8 [[OR2]] @@ -2345,8 +2334,7 @@ define i8 @test_not_trunc_cond_and(i8 %x, i1 %c) { ; CHECK-NEXT: [[COND:%.*]] = and i1 [[C:%.*]], [[NOT]] ; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[EXIT:%.*]] ; CHECK: if: -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[X]], -2 -; CHECK-NEXT: ret i8 [[OR1]] +; CHECK-NEXT: ret i8 -2 ; CHECK: exit: ; CHECK-NEXT: [[OR2:%.*]] = or i8 [[X]], -2 ; CHECK-NEXT: ret i8 [[OR2]]