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 @@ -8093,6 +8093,29 @@ return getZero(CI->getType()); } + // If we're exiting based on the overflow flag of an x.with.overflow intrinsic + // with a constant step, we can form an equivalent icmp predicate and figure + // out how many iterations will be taken before we exit. + const WithOverflowInst *WO; + const APInt *C; + if (match(ExitCond, m_ExtractValue<1>(m_WithOverflowInst(WO))) && + match(WO->getRHS(), m_APInt(C))) { + ConstantRange NWR = + ConstantRange::makeExactNoWrapRegion(WO->getBinaryOp(), *C, + WO->getNoWrapKind()); + CmpInst::Predicate Pred; + APInt NewRHSC, Offset; + NWR.getEquivalentICmp(Pred, NewRHSC, Offset); + if (!ExitIfTrue) + Pred = ICmpInst::getInversePredicate(Pred); + auto *LHS = getSCEV(WO->getLHS()); + if (Offset != 0) + LHS = getAddExpr(LHS, getConstant(Offset)); + auto EL = computeExitLimitFromICmp(L, Pred, LHS, getConstant(NewRHSC), + ControlsExit, AllowPredicates); + if (EL.hasAnyInfo()) return EL; + } + // If it's not an integer or pointer comparison then compute it the hard way. return computeExitCountExhaustively(L, ExitCond, ExitIfTrue); } diff --git a/llvm/test/Analysis/ScalarEvolution/overflow-intrinsics-trip-count.ll b/llvm/test/Analysis/ScalarEvolution/overflow-intrinsics-trip-count.ll --- a/llvm/test/Analysis/ScalarEvolution/overflow-intrinsics-trip-count.ll +++ b/llvm/test/Analysis/ScalarEvolution/overflow-intrinsics-trip-count.ll @@ -167,9 +167,11 @@ define void @uadd_symbolic_start(i16 %start) { ; CHECK-LABEL: 'uadd_symbolic_start' ; CHECK-NEXT: Determining loop execution counts for: @uadd_symbolic_start -; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count. -; CHECK-NEXT: Loop %for.body: Unpredictable max backedge-taken count. -; CHECK-NEXT: Loop %for.body: Unpredictable predicated backedge-taken count. +; CHECK-NEXT: Loop %for.body: backedge-taken count is (-1 + (-1 * %start)) +; CHECK-NEXT: Loop %for.body: max backedge-taken count is -1 +; CHECK-NEXT: Loop %for.body: Predicated backedge-taken count is (-1 + (-1 * %start)) +; CHECK-NEXT: Predicates: +; CHECK: Loop %for.body: Trip multiple is 1 ; entry: br i1 undef, label %for.end, label %for.body.preheader @@ -191,9 +193,11 @@ define void @sadd_symbolic_start(i16 %start) { ; CHECK-LABEL: 'sadd_symbolic_start' ; CHECK-NEXT: Determining loop execution counts for: @sadd_symbolic_start -; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count. -; CHECK-NEXT: Loop %for.body: Unpredictable max backedge-taken count. -; CHECK-NEXT: Loop %for.body: Unpredictable predicated backedge-taken count. +; CHECK-NEXT: Loop %for.body: backedge-taken count is (32767 + (-1 * %start)) +; CHECK-NEXT: Loop %for.body: max backedge-taken count is -1 +; CHECK-NEXT: Loop %for.body: Predicated backedge-taken count is (32767 + (-1 * %start)) +; CHECK-NEXT: Predicates: +; CHECK: Loop %for.body: Trip multiple is 1 ; entry: br i1 undef, label %for.end, label %for.body.preheader @@ -264,9 +268,11 @@ define void @usub_symbolic_start(i16 %start) { ; CHECK-LABEL: 'usub_symbolic_start' ; CHECK-NEXT: Determining loop execution counts for: @usub_symbolic_start -; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count. -; CHECK-NEXT: Loop %for.body: Unpredictable max backedge-taken count. -; CHECK-NEXT: Loop %for.body: Unpredictable predicated backedge-taken count. +; CHECK-NEXT: Loop %for.body: backedge-taken count is %start +; CHECK-NEXT: Loop %for.body: max backedge-taken count is -1 +; CHECK-NEXT: Loop %for.body: Predicated backedge-taken count is %start +; CHECK-NEXT: Predicates: +; CHECK: Loop %for.body: Trip multiple is 1 ; entry: br i1 undef, label %for.end, label %for.body.preheader @@ -288,9 +294,11 @@ define void @ssub_symbolic_start(i16 %start) { ; CHECK-LABEL: 'ssub_symbolic_start' ; CHECK-NEXT: Determining loop execution counts for: @ssub_symbolic_start -; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count. -; CHECK-NEXT: Loop %for.body: Unpredictable max backedge-taken count. -; CHECK-NEXT: Loop %for.body: Unpredictable predicated backedge-taken count. +; CHECK-NEXT: Loop %for.body: backedge-taken count is (-32768 + %start) +; CHECK-NEXT: Loop %for.body: max backedge-taken count is -1 +; CHECK-NEXT: Loop %for.body: Predicated backedge-taken count is (-32768 + %start) +; CHECK-NEXT: Predicates: +; CHECK: Loop %for.body: Trip multiple is 1 ; entry: br i1 undef, label %for.end, label %for.body.preheader @@ -360,11 +368,13 @@ define void @sadd_symbolic_non_latch(i16 %start) { ; CHECK-LABEL: 'sadd_symbolic_non_latch' ; CHECK-NEXT: Determining loop execution counts for: @sadd_symbolic_non_latch -; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count. -; CHECK-NEXT: exit count for for.body: ***COULDNOTCOMPUTE*** +; CHECK-NEXT: Loop %for.body: backedge-taken count is ((230 + (-1 * %start)) umin (32767 + (-1 * %start))) +; CHECK-NEXT: exit count for for.body: (32767 + (-1 * %start)) ; CHECK-NEXT: exit count for for.latch: (230 + (-1 * %start)) ; CHECK-NEXT: Loop %for.body: max backedge-taken count is -1 -; CHECK-NEXT: Loop %for.body: Unpredictable predicated backedge-taken count. +; CHECK-NEXT: Loop %for.body: Predicated backedge-taken count is ((230 + (-1 * %start)) umin (32767 + (-1 * %start))) +; CHECK-NEXT: Predicates: +; CHECK: Loop %for.body: Trip multiple is 1 ; entry: br i1 undef, label %for.end, label %for.body.preheader diff --git a/llvm/test/CodeGen/PowerPC/negctr.ll b/llvm/test/CodeGen/PowerPC/negctr.ll --- a/llvm/test/CodeGen/PowerPC/negctr.ll +++ b/llvm/test/CodeGen/PowerPC/negctr.ll @@ -34,14 +34,10 @@ %exitcond = icmp eq i64 %indvars.iv.next, 0 br i1 %exitcond, label %for.end, label %for.body -; FIXME: This should be a hardware loop. -; cmp is optimized to uadd intrinsic in CGP pass which can not be recognized in -; later HardwareLoops Pass. ; CHECK: @main1 -; CHECK: li [[REG:[0-9]+]], 1 -; CHECK: addi [[REG2:[0-9]+]], [[REG]], 1 -; CHECK: cmpld -; CHECK: bge +; CHECK: li [[REG:[0-9]+]], -1 +; CHECK: mtctr [[REG]] +; CHECK: bdnz for.end: ; preds = %for.body, %entry ret void