mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 20:29:53 +00:00
[PlaceSafepoints] Make the width of a counted loop settable.
Summary: This change lets a `PlaceSafepoints` client change how wide the trip count of a loop has to be for the loop to be considerd "counted", via `CountedLoopTripWidth`. It also removes the boolean `SkipCounted` flag and the `upperTripBound` constant -- we can get the old behavior of `SkipCounted` == `false` by setting `CountedLoopTripWidth` to `13` (2 ^ 13 == 8192). Reviewers: reames Subscribers: llvm-commits, sanjoy Differential Revision: http://reviews.llvm.org/D12789 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@247656 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
270e6f8a27
commit
d7e1379fc2
@ -96,8 +96,10 @@ using namespace llvm;
|
||||
static cl::opt<bool> AllBackedges("spp-all-backedges", cl::Hidden,
|
||||
cl::init(false));
|
||||
|
||||
/// If true, do not place backedge safepoints in counted loops.
|
||||
static cl::opt<bool> 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<int> 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 @@ static bool containsUnconditionalCallSafepoint(Loop *L, BasicBlock *Header,
|
||||
/// 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 @@ static bool mustBeFiniteCountedLoop(Loop *L, ScalarEvolution *SE,
|
||||
// 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))
|
||||
if (MaxExec != SE->getCouldNotCompute() &&
|
||||
SE->getUnsignedRange(MaxExec).getUnsignedMax().isIntN(
|
||||
CountedLoopTripWidth))
|
||||
return true;
|
||||
if (SkipCounted &&
|
||||
SE->getUnsignedRange(MaxExec).getUnsignedMax().isIntN(32))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return /* not finite */ false;
|
||||
|
@ -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 @@ exit:
|
||||
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()
|
||||
|
Loading…
Reference in New Issue
Block a user