diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -15021,7 +15021,7 @@ const SCEV *URemRHS = nullptr; if (matchURem(LHS, URemLHS, URemRHS)) { if (const SCEVUnknown *LHSUnknown = dyn_cast(URemLHS)) { - auto Multiple = getMulExpr(getUDivExpr(URemLHS, URemRHS), URemRHS); + const auto *Multiple = getMulExpr(getUDivExpr(URemLHS, URemRHS), URemRHS); RewriteMap[LHSUnknown] = Multiple; ExprsToRewrite.push_back(LHSUnknown); return; @@ -15098,24 +15098,34 @@ } }; + BasicBlock *Header = L->getHeader(); SmallVector> Terms; // First, collect information from assumptions dominating the loop. for (auto &AssumeVH : AC.assumptions()) { if (!AssumeVH) continue; auto *AssumeI = cast(AssumeVH); - if (!DT.dominates(AssumeI, L->getHeader())) + if (!DT.dominates(AssumeI, Header)) continue; Terms.emplace_back(AssumeI->getOperand(0), true); } - // Second, collect conditions from dominating branches. Starting at the loop + // Second, collect information from llvm.experimental.guards dominating the loop. + auto *GuardDecl = F.getParent()->getFunction( + Intrinsic::getName(Intrinsic::experimental_guard)); + if (GuardDecl) + for (const auto *GU : GuardDecl->users()) + if (const auto *Guard = dyn_cast(GU)) + if (Guard->getFunction() == Header->getParent() && DT.dominates(Guard, Header)) + Terms.emplace_back(Guard->getArgOperand(0), true); + + // Third, collect conditions from dominating branches. Starting at the loop // predecessor, climb up the predecessor chain, as long as there are // predecessors that can be found that have unique successors leading to the // original header. // TODO: share this logic with isLoopEntryGuardedByCond. for (std::pair Pair( - L->getLoopPredecessor(), L->getHeader()); + L->getLoopPredecessor(), Header); Pair.first; Pair = getPredecessorWithUniqueSuccessorForBB(Pair.first)) { const BranchInst *LoopEntryPredicate = diff --git a/llvm/test/Analysis/ScalarEvolution/trip-multiple-guard-info.ll b/llvm/test/Analysis/ScalarEvolution/trip-multiple-guard-info.ll --- a/llvm/test/Analysis/ScalarEvolution/trip-multiple-guard-info.ll +++ b/llvm/test/Analysis/ScalarEvolution/trip-multiple-guard-info.ll @@ -38,6 +38,41 @@ ret void } +define void @test_trip_multiple_4_guard(i32 %num) { +; CHECK-LABEL: 'test_trip_multiple_4_guard' +; CHECK-NEXT: Classifying expressions for: @test_trip_multiple_4 +; CHECK-NEXT: %u = urem i32 %num, 4 +; CHECK-NEXT: --> (zext i2 (trunc i32 %num to i2) to i32) U: [0,4) S: [0,4) +; CHECK-NEXT: %i.010 = phi i32 [ 0, %entry ], [ %inc, %for.body ] +; CHECK-NEXT: --> {0,+,1}<%for.body> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %num) LoopDispositions: { %for.body: Computable } +; CHECK-NEXT: %inc = add nuw nsw i32 %i.010, 1 +; CHECK-NEXT: --> {1,+,1}<%for.body> U: [1,-2147483648) S: [1,-2147483648) Exits: %num LoopDispositions: { %for.body: Computable } +; CHECK-NEXT: Determining loop execution counts for: @test_trip_multiple_4 +; CHECK-NEXT: Loop %for.body: backedge-taken count is (-1 + %num) +; CHECK-NEXT: Loop %for.body: constant max backedge-taken count is -2 +; CHECK-NEXT: Loop %for.body: symbolic max backedge-taken count is (-1 + %num) +; CHECK-NEXT: Loop %for.body: Predicated backedge-taken count is (-1 + %num) +; CHECK-NEXT: Predicates: +; CHECK: Loop %for.body: Trip multiple is 4 +; +entry: + %u = urem i32 %num, 4 + %cmp = icmp eq i32 %u, 0 + call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ] + %cmp.1 = icmp uge i32 %num, 4 + call void(i1, ...) @llvm.experimental.guard(i1 %cmp.1) [ "deopt"() ] + br label %for.body + +for.body: + %i.010 = phi i32 [ 0, %entry ], [ %inc, %for.body ] + %inc = add nuw nsw i32 %i.010, 1 + %cmp2 = icmp ult i32 %inc, %num + br i1 %cmp2, label %for.body, label %exit + +exit: + ret void +} + define void @test_trip_multiple_4_ugt_5(i32 %num) { ; CHECK-LABEL: 'test_trip_multiple_4_ugt_5' @@ -430,3 +465,4 @@ } declare void @llvm.assume(i1) +declare void @llvm.experimental.guard(i1, ...)