[llvm] r326748 - [RewriteStatepoints] Fix stale parse points

Daniel Neilson via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 5 14:27:31 PST 2018


Author: dneilson
Date: Mon Mar  5 14:27:30 2018
New Revision: 326748

URL: http://llvm.org/viewvc/llvm-project?rev=326748&view=rev
Log:
[RewriteStatepoints] Fix stale parse points

Summary:
RewriteStatepointsForGC collects parse points for further processing.
During the collection if a callsite is found in an unreachable block
(DominatorTree::isReachableFromEntry()) then all unreachable blocks are
removed by removeUnreachableBlocks(). Some of the removed blocks could
have been reachable according to DominatorTree::isReachableFromEntry().
In this case the collected parse points became stale and resulted in a
crash when accessed.

The fix is to unconditionally canonicalize the IR to
removeUnreachableBlocks and then collect the parse points.

The added test crashes with the old version and passes with this patch.

Patch by Yevgeny Rouban!

Reviewed by: Anna

Differential Revision: https://reviews.llvm.org/D43929

Added:
    llvm/trunk/test/Transforms/RewriteStatepointsForGC/unreachable-regression.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
    llvm/trunk/test/Transforms/RewriteStatepointsForGC/relocation.ll
    llvm/trunk/test/Transforms/RewriteStatepointsForGC/vector-bitcast.ll

Modified: llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp?rev=326748&r1=326747&r2=326748&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp Mon Mar  5 14:27:30 2018
@@ -2529,30 +2529,31 @@ bool RewriteStatepointsForGC::runOnFunct
     return false;
   };
 
+
+  // Delete any unreachable statepoints so that we don't have unrewritten
+  // statepoints surviving this pass.  This makes testing easier and the
+  // resulting IR less confusing to human readers.
+  DeferredDominance DD(DT);
+  bool MadeChange = removeUnreachableBlocks(F, nullptr, &DD);
+  DD.flush();
+
   // Gather all the statepoints which need rewritten.  Be careful to only
   // consider those in reachable code since we need to ask dominance queries
   // when rewriting.  We'll delete the unreachable ones in a moment.
   SmallVector<CallSite, 64> ParsePointNeeded;
-  bool HasUnreachableStatepoint = false;
   for (Instruction &I : instructions(F)) {
     // TODO: only the ones with the flag set!
     if (NeedsRewrite(I)) {
-      if (DT.isReachableFromEntry(I.getParent()))
-        ParsePointNeeded.push_back(CallSite(&I));
-      else
-        HasUnreachableStatepoint = true;
+      // NOTE removeUnreachableBlocks() is stronger than
+      // DominatorTree::isReachableFromEntry(). In other words
+      // removeUnreachableBlocks can remove some blocks for which
+      // isReachableFromEntry() returns true.
+      assert(DT.isReachableFromEntry(I.getParent()) &&
+            "no unreachable blocks expected");
+      ParsePointNeeded.push_back(CallSite(&I));
     }
   }
 
-  bool MadeChange = false;
-
-  // Delete any unreachable statepoints so that we don't have unrewritten
-  // statepoints surviving this pass.  This makes testing easier and the
-  // resulting IR less confusing to human readers.  Rather than be fancy, we
-  // just reuse a utility function which removes the unreachable blocks.
-  if (HasUnreachableStatepoint)
-    MadeChange |= removeUnreachableBlocks(F);
-
   // Return early if no work to do.
   if (ParsePointNeeded.empty())
     return MadeChange;

Modified: llvm/trunk/test/Transforms/RewriteStatepointsForGC/relocation.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/RewriteStatepointsForGC/relocation.ll?rev=326748&r1=326747&r2=326748&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/RewriteStatepointsForGC/relocation.ll (original)
+++ llvm/trunk/test/Transforms/RewriteStatepointsForGC/relocation.ll Mon Mar  5 14:27:30 2018
@@ -103,6 +103,10 @@ join:
   ret void
 }
 
+declare void @goo(i64)
+
+declare i32 @moo(i64 addrspace(1)*)
+
 ; Make sure a use in a statepoint gets properly relocated at a previous one.  
 ; This is basically just making sure that statepoints aren't accidentally 
 ; treated specially.
@@ -113,11 +117,13 @@ define void @test3(i64 addrspace(1)* %ob
 ; CHECK-NEXT: bitcast
 ; CHECK-NEXT: gc.statepoint
 entry:
-  call void undef(i64 undef) [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
-  %0 = call i32 undef(i64 addrspace(1)* %obj) [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
+  call void @goo(i64 undef) [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
+  %0 = call i32 @moo(i64 addrspace(1)* %obj) [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
   ret void
 }
 
+declare i8 addrspace(1)* @boo()
+
 ; Check specifically for the case where the result of a statepoint needs to 
 ; be relocated itself
 define void @test4() gc "statepoint-example" {
@@ -127,17 +133,17 @@ define void @test4() gc "statepoint-exam
 ; CHECK: gc.statepoint
 ; CHECK: [[RELOCATED:%[^ ]+]] = call {{.*}}gc.relocate
 ; CHECK: @use(i8 addrspace(1)* [[RELOCATED]])
-  %1 = call i8 addrspace(1)* undef() [ "deopt"() ]
-  %2 = call i8 addrspace(1)* undef() [ "deopt"() ]
+  %1 = call i8 addrspace(1)* @boo() [ "deopt"() ]
+  %2 = call i8 addrspace(1)* @boo() [ "deopt"() ]
   call void (...) @use(i8 addrspace(1)* %1)
-  unreachable
+  ret void
 }
 
 ; Test updating a phi where not all inputs are live to begin with
 define void @test5(i8 addrspace(1)* %arg) gc "statepoint-example" {
 ; CHECK-LABEL: test5
 entry:
-  %0 = call i8 addrspace(1)* undef() [ "deopt"() ]
+  %0 = call i8 addrspace(1)* @boo() [ "deopt"() ]
   switch i32 undef, label %kill [
     i32 10, label %merge
     i32 13, label %merge
@@ -154,7 +160,7 @@ merge:
 ; CHECK-DAG: [ %arg.relocated, %entry ]
   %test = phi i8 addrspace(1)* [ null, %kill ], [ %arg, %entry ], [ %arg, %entry ]
   call void (...) @use(i8 addrspace(1)* %test)
-  unreachable
+  ret void
 }
 
 ; Check to make sure we handle values live over an entry statepoint

Added: llvm/trunk/test/Transforms/RewriteStatepointsForGC/unreachable-regression.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/RewriteStatepointsForGC/unreachable-regression.ll?rev=326748&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/RewriteStatepointsForGC/unreachable-regression.ll (added)
+++ llvm/trunk/test/Transforms/RewriteStatepointsForGC/unreachable-regression.ll Mon Mar  5 14:27:30 2018
@@ -0,0 +1,34 @@
+; RUN: opt -S -rewrite-statepoints-for-gc < %s | FileCheck %s
+; RUN: opt -S -passes=rewrite-statepoints-for-gc < %s | FileCheck %s
+;
+; Regression test:
+;   After the rewritable callsite collection if any callsite was found
+;   in a block that was reported unreachable by DominanceTree then
+;   removeUnreachableBlocks() was called. But it is stronger than
+;   DominatorTree::isReachableFromEntry(), i.e. removeUnreachableBlocks
+;   can remove some blocks for which isReachableFromEntry() returns true.
+;   This resulted in stale pointers to the collected but removed
+;   callsites. Such stale pointers caused crash when accessed.
+declare void @f(i8 addrspace(1)* %obj)
+
+define void @test(i8 addrspace(1)* %arg) gc "statepoint-example" {
+; CHECK-LABEL: test(
+; CHECK-NEXT: @f
+ call void @f(i8 addrspace(1)* %arg) #1
+ br i1 true, label %not_zero, label %zero
+
+not_zero:
+ ret void
+
+; This block is reachable but removed by removeUnreachableBlocks()
+zero:
+; CHECK-NOT: @f
+ call void @f(i8 addrspace(1)* %arg) #1
+ ret void
+
+unreach:
+ call void @f(i8 addrspace(1)* %arg) #1
+ ret void
+}
+
+attributes #1 = { norecurse noimplicitfloat }

Modified: llvm/trunk/test/Transforms/RewriteStatepointsForGC/vector-bitcast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/RewriteStatepointsForGC/vector-bitcast.ll?rev=326748&r1=326747&r2=326748&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/RewriteStatepointsForGC/vector-bitcast.ll (original)
+++ llvm/trunk/test/Transforms/RewriteStatepointsForGC/vector-bitcast.ll Mon Mar  5 14:27:30 2018
@@ -7,8 +7,10 @@
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:1"
 target triple = "x86_64-unknown-linux-gnu"
 
+declare i8 addrspace(1)* @foo()
+
 ; Function Attrs: uwtable
-define void @test() gc "statepoint-example" {
+define i32 @test() gc "statepoint-example" {
 ; CHECK-LABEL: @test
 entry:
 ; CHECK-LABEL: entry
@@ -21,7 +23,7 @@ entry:
 ; CHECK: load atomic
   %bc = bitcast <8 x i8 addrspace(1)*> undef to <8 x i32 addrspace(1)*>
   %ptr= extractelement <8 x i32 addrspace(1)*> %bc, i32 7
-  %0 = call i8 addrspace(1)* undef() [ "deopt"() ]
+  %0 = call i8 addrspace(1)* @foo() [ "deopt"() ]
   %1 = load atomic i32, i32 addrspace(1)* %ptr unordered, align 4
-  unreachable
+  ret i32 %1
 }




More information about the llvm-commits mailing list