struct PlaceSafepoints : public ModulePass {
static char ID; // Pass identification, replacement for typeid
- bool EnableEntrySafepoints;
- bool EnableBackedgeSafepoints;
- bool EnableCallSafepoints;
-
PlaceSafepoints() : ModulePass(ID) {
initializePlaceSafepointsPass(*PassRegistry::getPassRegistry());
- EnableEntrySafepoints = !NoEntry;
- EnableBackedgeSafepoints = !NoBackedge;
- EnableCallSafepoints = !NoCall;
}
bool runOnModule(Module &M) override {
bool modified = false;
return F.getName().equals(GCSafepointPollName);
}
+/// Returns true if this function should be rewritten to include safepoint
+/// polls and parseable call sites. The main point of this function is to be
+/// an extension point for custom logic.
+static bool shouldRewriteFunction(Function &F) {
+ // TODO: This should check the GCStrategy
+ if (F.hasGC()) {
+ const std::string StatepointExampleName("statepoint-example");
+ return StatepointExampleName == F.getGC();
+ } else
+ return false;
+}
+
+// TODO: These should become properties of the GCStrategy, possibly with
+// command line overrides.
+static bool enableEntrySafepoints(Function &F) { return !NoEntry; }
+static bool enableBackedgeSafepoints(Function &F) { return !NoBackedge; }
+static bool enableCallSafepoints(Function &F) { return !NoCall; }
+
+
bool PlaceSafepoints::runOnFunction(Function &F) {
if (F.isDeclaration() || F.empty()) {
// This is a declaration, nothing to do. Must exit early to avoid crash in
return false;
}
+ if (!shouldRewriteFunction(F))
+ return false;
+
bool modified = false;
// In various bits below, we rely on the fact that uses are reachable from
std::vector<CallSite> ParsePointNeeded;
- if (EnableBackedgeSafepoints) {
+ if (enableBackedgeSafepoints(F)) {
// Construct a pass manager to run the LoopPass backedge logic. We
// need the pass manager to handle scheduling all the loop passes
// appropriately. Doing this by hand is painful and just not worth messing
// with for the moment.
legacy::FunctionPassManager FPM(F.getParent());
- bool CanAssumeCallSafepoints = EnableCallSafepoints;
+ bool CanAssumeCallSafepoints = enableCallSafepoints(F);
PlaceBackedgeSafepointsImpl *PBS =
new PlaceBackedgeSafepointsImpl(CanAssumeCallSafepoints);
FPM.add(PBS);
}
}
- if (EnableEntrySafepoints) {
+ if (enableEntrySafepoints(F)) {
DT.recalculate(F);
Instruction *term = findLocationForEntrySafepoint(F, DT);
if (!term) {
}
}
- if (EnableCallSafepoints) {
+ if (enableCallSafepoints(F)) {
DT.recalculate(F);
std::vector<CallSite> Calls;
findCallSafepoints(F, Calls);
declare i64 addrspace(1)* @"some_call"(i64 addrspace(1)*)
declare i32 @"personality_function"()
-define i64 addrspace(1)* @test_basic(i64 addrspace(1)* %obj, i64 addrspace(1)* %obj1) {
+define i64 addrspace(1)* @test_basic(i64 addrspace(1)* %obj, i64 addrspace(1)* %obj1) gc "statepoint-example" {
; CHECK-LABEL: entry:
entry:
; CHECK: invoke
ret i64 addrspace(1)* %obj1
}
-define i64 addrspace(1)* @test_two_invokes(i64 addrspace(1)* %obj, i64 addrspace(1)* %obj1) {
+define i64 addrspace(1)* @test_two_invokes(i64 addrspace(1)* %obj, i64 addrspace(1)* %obj1) gc "statepoint-example" {
; CHECK-LABEL: entry:
entry:
; CHECK: invoke
ret i64 addrspace(1)* %obj1
}
-define i64 addrspace(1)* @test_phi_node(i1 %cond, i64 addrspace(1)* %obj) {
+define i64 addrspace(1)* @test_phi_node(i1 %cond, i64 addrspace(1)* %obj) gc "statepoint-example" {
; CHECK-LABEL: entry:
entry:
br i1 %cond, label %left, label %right
;; A very basic test to make sure that splitting the backedge keeps working
;; RUN: opt -place-safepoints -spp-split-backedge=1 -S %s | FileCheck %s
-define void @test(i32, i1 %cond) {
+define void @test(i32, i1 %cond) gc "statepoint-example" {
; CHECK-LABEL: @test
; CHECK-LABEL: loop.loop_crit_edge
; CHECK: gc.statepoint
; different loop header blocks. Since we're currently using LoopSimplfy
; this doesn't hit the interesting case, but once we remove that, we need
; to be sure this keeps working.
-define void @test2(i32, i1 %cond) {
+define void @test2(i32, i1 %cond) gc "statepoint-example" {
; CHECK-LABEL: @test2
; CHECK-LABE: loop.loopexit.split
; CHECK: gc.statepoint