[PlaceSafepoints] Adjust enablement logic to default to off and be GC configurable...
authorPhilip Reames <listmail@philipreames.com>
Sat, 21 Feb 2015 00:09:09 +0000 (00:09 +0000)
committerPhilip Reames <listmail@philipreames.com>
Sat, 21 Feb 2015 00:09:09 +0000 (00:09 +0000)
Previously, this pass ran over every function in the Module if added to the pass order.  With this change, it runs only over those with a GC attribute where the GC explicitly opts in.  A GC can also choose which of entry safepoint polls, backedge safepoint polls, and call safepoints it wants.  I hope to get these exposed as checks on the GCStrategy at some point, but for now, the checks are manual string comparisons.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230097 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/PlaceSafepoints.cpp
test/Transforms/PlaceSafepoints/basic.ll
test/Transforms/PlaceSafepoints/call-in-loop.ll
test/Transforms/PlaceSafepoints/finite-loops.ll
test/Transforms/PlaceSafepoints/invokes.ll
test/Transforms/PlaceSafepoints/split-backedge.ll

index a3e759f0f3b17d03570f66f40d0d75d42b4f10d5..376be88fe8a456a8995ceff687593119c4dedd2e 100644 (file)
@@ -150,15 +150,8 @@ namespace {
 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;
@@ -504,6 +497,25 @@ static bool isGCSafepointPoll(Function &F) {
   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
@@ -518,6 +530,9 @@ bool PlaceSafepoints::runOnFunction(Function &F) {
     return false;
   }
 
+  if (!shouldRewriteFunction(F))
+    return false;
+
   bool modified = false;
 
   // In various bits below, we rely on the fact that uses are reachable from
@@ -536,13 +551,13 @@ bool PlaceSafepoints::runOnFunction(Function &F) {
 
   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);
@@ -609,7 +624,7 @@ bool PlaceSafepoints::runOnFunction(Function &F) {
     }
   }
 
-  if (EnableEntrySafepoints) {
+  if (enableEntrySafepoints(F)) {
     DT.recalculate(F);
     Instruction *term = findLocationForEntrySafepoint(F, DT);
     if (!term) {
@@ -624,7 +639,7 @@ bool PlaceSafepoints::runOnFunction(Function &F) {
     }
   }
 
-  if (EnableCallSafepoints) {
+  if (enableCallSafepoints(F)) {
     DT.recalculate(F);
     std::vector<CallSite> Calls;
     findCallSafepoints(F, Calls);
index e9f24a5c86fef56dbd1b686de0e9154b2347bccf..0e3ed3d773d0846a0c8c0bcee39f634fce6df264 100644 (file)
@@ -10,6 +10,14 @@ entry:
   ret void
 }
 
+; On a non-gc function, we should NOT get an entry safepoint
+define void @test_negative() {
+; CHECK-LABEL: @test_negative
+entry:
+; CHECK-NOT: statepoint
+  ret void
+}
+
 ; Do we insert a backedge safepoint in a statically
 ; infinite loop?
 define void @test_backedge() gc "statepoint-example" {
index 5e961f73fa73bf9df5adc360aab4359673658848..a220fc96c109c00515685b65365625d7177825cf 100644 (file)
@@ -5,7 +5,7 @@
 
 declare void @foo()
 
-define void @test1() {
+define void @test1() gc "statepoint-example" {
 ; CHECK-LABEL: test1
 
 entry:
index a66aa28fc4a603e47cb4acd1c324830e76c90449..8b64d240603b5d391f5923552af4fd62a63b826f 100644 (file)
@@ -4,7 +4,7 @@
 
 
 ; A simple counted loop with trivially known range
-define void @test1(i32) {
+define void @test1(i32) gc "statepoint-example" {
 ; CHECK-LABEL: test1
 ; CHECK-LABEL: entry
 ; CHECK: statepoint
@@ -25,7 +25,7 @@ exit:
 }
 
 ; The same counted loop, but with an unknown early exit
-define void @test2(i32) {
+define void @test2(i32) gc "statepoint-example" {
 ; CHECK-LABEL: test2
 ; CHECK-LABEL: entry
 ; CHECK: statepoint
@@ -49,7 +49,7 @@ exit:
 }
 
 ; The range is a 8 bit value and we can't overflow
-define void @test3(i8 %upper) {
+define void @test3(i8 %upper) gc "statepoint-example" {
 ; CHECK-LABEL: test3
 ; CHECK-LABEL: entry
 ; CHECK: statepoint
index fcac3451bc8a91e5697cc8a740a0f9a3e2ff9861..5fd5bea7e5faae373babb9499129ba321a6c86a6 100644 (file)
@@ -3,7 +3,7 @@
 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
@@ -29,7 +29,7 @@ exceptional_return:
   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 
@@ -61,7 +61,7 @@ exceptional_return:
   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
index 00243ae3c031393c659666b9c44e2be343b986fd..176b54f558e8cd2f3a357ca215c8572cfa499c82 100644 (file)
@@ -1,7 +1,7 @@
 ;; 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
@@ -20,7 +20,7 @@ exit:
 ; 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