Index: lib/Transforms/Scalar/PlaceSafepoints.cpp =================================================================== --- lib/Transforms/Scalar/PlaceSafepoints.cpp +++ lib/Transforms/Scalar/PlaceSafepoints.cpp @@ -96,8 +96,10 @@ static cl::opt AllBackedges("spp-all-backedges", cl::Hidden, cl::init(false)); -/// If true, do not place backedge safepoints in counted loops. -static cl::opt SkipCounted("spp-counted", cl::Hidden, cl::init(true)); +/// How narrow does the trip count of a loop have to be to have to be considered +/// "counted"? Counted loops do not get safepoints at backedges. +static cl::opt CountedLoopTripWidth("spp-counted-loop-trip-width", + cl::Hidden, cl::init(32)); // If true, split the backedge of a loop when placing the safepoint, otherwise // split the latch block itself. Both are useful to support for @@ -255,18 +257,12 @@ /// conservatism in the analysis. static bool mustBeFiniteCountedLoop(Loop *L, ScalarEvolution *SE, BasicBlock *Pred) { - // Only used when SkipCounted is off - const unsigned upperTripBound = 8192; - // A conservative bound on the loop as a whole. const SCEV *MaxTrips = SE->getMaxBackedgeTakenCount(L); - if (MaxTrips != SE->getCouldNotCompute()) { - if (SE->getUnsignedRange(MaxTrips).getUnsignedMax().ult(upperTripBound)) - return true; - if (SkipCounted && - SE->getUnsignedRange(MaxTrips).getUnsignedMax().isIntN(32)) - return true; - } + if (MaxTrips != SE->getCouldNotCompute() && + SE->getUnsignedRange(MaxTrips).getUnsignedMax().isIntN( + CountedLoopTripWidth)) + return true; // If this is a conditional branch to the header with the alternate path // being outside the loop, we can ask questions about the execution frequency @@ -275,13 +271,10 @@ // This returns an exact expression only. TODO: We really only need an // upper bound here, but SE doesn't expose that. const SCEV *MaxExec = SE->getExitCount(L, Pred); - if (MaxExec != SE->getCouldNotCompute()) { - if (SE->getUnsignedRange(MaxExec).getUnsignedMax().ult(upperTripBound)) - return true; - if (SkipCounted && - SE->getUnsignedRange(MaxExec).getUnsignedMax().isIntN(32)) + if (MaxExec != SE->getCouldNotCompute() && + SE->getUnsignedRange(MaxExec).getUnsignedMax().isIntN( + CountedLoopTripWidth)) return true; - } } return /* not finite */ false; Index: test/Transforms/PlaceSafepoints/finite-loops.ll =================================================================== --- test/Transforms/PlaceSafepoints/finite-loops.ll +++ test/Transforms/PlaceSafepoints/finite-loops.ll @@ -1,6 +1,7 @@ ; Tests to ensure that we are not placing backedge safepoints in ; loops which are clearly finite. -;; RUN: opt %s -place-safepoints -S | FileCheck %s +;; RUN: opt %s -place-safepoints -spp-counted-loop-trip-width=32 -S | FileCheck %s +;; RUN: opt %s -place-safepoints -spp-counted-loop-trip-width=64 -S | FileCheck %s -check-prefix=COUNTED-64 ; A simple counted loop with trivially known range @@ -69,6 +70,61 @@ ret void } +; The range is a 64 bit value +define void @test4(i64 %upper) gc "statepoint-example" { +; CHECK-LABEL: test4 +; CHECK-LABEL: entry +; CHECK: statepoint +; CHECK-LABEL: loop +; CHECK: statepoint + +; COUNTED-64-LABEL: test4 +; COUNTED-64-LABEL: entry +; COUNTED-64: statepoint +; COUNTED-64-LABEL: loop +; COUNTED-64-NOT: statepoint + +entry: + br label %loop + +loop: + %counter = phi i64 [ 0 , %entry ], [ %counter.inc , %loop ] + %counter.inc = add i64 %counter, 1 + %counter.cmp = icmp slt i64 %counter.inc, %upper + br i1 %counter.cmp, label %loop, label %exit + +exit: + ret void +} + +; This loop can run infinitely (for %upper == INT64_MAX) so it needs a +; safepoint. +define void @test5(i64 %upper) gc "statepoint-example" { +; CHECK-LABEL: test5 +; CHECK-LABEL: entry +; CHECK: statepoint +; CHECK-LABEL: loop +; CHECK: statepoint + +; COUNTED-64-LABEL: test5 +; COUNTED-64-LABEL: entry +; COUNTED-64: statepoint +; COUNTED-64-LABEL: loop +; COUNTED-64: statepoint + +entry: + br label %loop + +loop: + %counter = phi i64 [ 0 , %entry ], [ %counter.inc , %loop ] + %counter.inc = add i64 %counter, 1 + %counter.cmp = icmp sle i64 %counter.inc, %upper + br i1 %counter.cmp, label %loop, label %exit + +exit: + ret void +} + ; This function is inlined when inserting a poll. declare void @do_safepoint()