Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[rs4gc] Optionally directly relocated vector of pointers
This patch teaches rewrite-statepoints-for-gc to relocate vector-of-pointers directly rather than trying to split them. This builds on the recent lowering/IR changes to allow vector typed gc.relocates. The motivation for this is that we recently found a bug in the vector splitting code where depending on visit order, a vector might not be relocated at some safepoint. Specifically, the bug is that the splitting code wasn't updating the side tables (live vector) of other safepoints. As a result, a vector which was live at two safepoints might not be updated at one of them. However, if you happened to visit safepoints in post order over the dominator tree, everything worked correctly. Weirdly, it turns out that post order is actually an incredibly common order to visit instructions in in practice. Frustratingly, I have not managed to write a test case which actually hits this. I can only reproduce it in large IR files produced by actual applications. Rather than continue to make this code more complicated, we can remove all of the complexity by just representing the relocation of the entire vector natively in the IR. At the moment, the new functionality is hidden behind a flag. To use this code, you need to pass "-rs4gc-split-vector-values=0". Once I have a chance to stress test with this option and get feedback from other users, my plan is to flip the default and remove the original splitting code. I would just remove it now, but given the rareness of the bug, I figured it was better to leave it in place until the new approach has been stress tested. Differential Revision: http://reviews.llvm.org/D15982 llvm-svn: 257244
- Loading branch information
Showing
4 changed files
with
143 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
llvm/test/Transforms/RewriteStatepointsForGC/deopt-bundles/live-vector-nosplit.ll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
; Test that we can correctly handle vectors of pointers in statepoint | ||
; rewriting. | ||
; RUN: opt %s -rewrite-statepoints-for-gc -rs4gc-use-deopt-bundles -rs4gc-split-vector-values=0 -S | FileCheck %s | ||
|
||
; A non-vector relocation for comparison | ||
define i64 addrspace(1)* @test(i64 addrspace(1)* %obj) gc "statepoint-example" { | ||
; CHECK-LABEL: test | ||
; CHECK: gc.statepoint | ||
; CHECK-NEXT: gc.relocate | ||
; CHECK-NEXT: bitcast | ||
; CHECK-NEXT: ret i64 addrspace(1)* | ||
; A base vector from a argument | ||
entry: | ||
call void @do_safepoint() [ "deopt"() ] | ||
ret i64 addrspace(1)* %obj | ||
} | ||
|
||
; A vector argument | ||
define <2 x i64 addrspace(1)*> @test2(<2 x i64 addrspace(1)*> %obj) gc "statepoint-example" { | ||
; CHECK-LABEL: test2 | ||
; CHECK-NEXT: gc.statepoint | ||
; CHECK-NEXT: gc.relocate | ||
; CHECK-NEXT: bitcast | ||
; CHECK-NEXT: ret <2 x i64 addrspace(1)*> | ||
call void @do_safepoint() [ "deopt"() ] | ||
ret <2 x i64 addrspace(1)*> %obj | ||
} | ||
|
||
; A load | ||
define <2 x i64 addrspace(1)*> @test3(<2 x i64 addrspace(1)*>* %ptr) gc "statepoint-example" { | ||
; CHECK-LABEL: test3 | ||
; CHECK: load | ||
; CHECK-NEXT: gc.statepoint | ||
; CHECK-NEXT: gc.relocate | ||
; CHECK-NEXT: bitcast | ||
; CHECK-NEXT: ret <2 x i64 addrspace(1)*> | ||
entry: | ||
%obj = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr | ||
call void @do_safepoint() [ "deopt"() ] | ||
ret <2 x i64 addrspace(1)*> %obj | ||
} | ||
|
||
declare i32 @fake_personality_function() | ||
|
||
; When a statepoint is an invoke rather than a call | ||
define <2 x i64 addrspace(1)*> @test4(<2 x i64 addrspace(1)*>* %ptr) gc "statepoint-example" personality i32 ()* @fake_personality_function { | ||
; CHECK-LABEL: test4 | ||
; CHECK: load | ||
; CHECK-NEXT: gc.statepoint | ||
entry: | ||
%obj = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr | ||
invoke void @do_safepoint() [ "deopt"() ] | ||
to label %normal_return unwind label %exceptional_return | ||
|
||
normal_return: ; preds = %entry | ||
; CHECK-LABEL: normal_return: | ||
; CHECK: gc.relocate | ||
; CHECK-NEXT: bitcast | ||
; CHECK-NEXT: ret <2 x i64 addrspace(1)*> | ||
ret <2 x i64 addrspace(1)*> %obj | ||
|
||
exceptional_return: ; preds = %entry | ||
; CHECK-LABEL: exceptional_return: | ||
; CHECK: gc.relocate | ||
; CHECK-NEXT: bitcast | ||
; CHECK-NEXT: ret <2 x i64 addrspace(1)*> | ||
%landing_pad4 = landingpad token | ||
cleanup | ||
ret <2 x i64 addrspace(1)*> %obj | ||
} | ||
|
||
; A newly created vector | ||
define <2 x i64 addrspace(1)*> @test5(i64 addrspace(1)* %p) gc "statepoint-example" { | ||
; CHECK-LABEL: test5 | ||
; CHECK: insertelement | ||
; CHECK-NEXT: gc.statepoint | ||
; CHECK-NEXT: gc.relocate | ||
; CHECK-NEXT: bitcast | ||
; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %vec.relocated.casted | ||
entry: | ||
%vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %p, i32 0 | ||
call void @do_safepoint() [ "deopt"() ] | ||
ret <2 x i64 addrspace(1)*> %vec | ||
} | ||
|
||
; A merge point | ||
define <2 x i64 addrspace(1)*> @test6(i1 %cnd, <2 x i64 addrspace(1)*>* %ptr) gc "statepoint-example" { | ||
; CHECK-LABEL: test6 | ||
entry: | ||
br i1 %cnd, label %taken, label %untaken | ||
|
||
taken: ; preds = %entry | ||
%obja = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr | ||
br label %merge | ||
|
||
untaken: ; preds = %entry | ||
%objb = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr | ||
br label %merge | ||
|
||
merge: ; preds = %untaken, %taken | ||
; CHECK-LABEL: merge: | ||
; CHECK-NEXT: = phi | ||
; CHECK-NEXT: gc.statepoint | ||
; CHECK-NEXT: gc.relocate | ||
; CHECK-NEXT: bitcast | ||
; CHECK-NEXT: ret <2 x i64 addrspace(1)*> | ||
%obj = phi <2 x i64 addrspace(1)*> [ %obja, %taken ], [ %objb, %untaken ] | ||
call void @do_safepoint() [ "deopt"() ] | ||
ret <2 x i64 addrspace(1)*> %obj | ||
} | ||
|
||
declare void @do_safepoint() |
2 changes: 1 addition & 1 deletion
2
llvm/test/Transforms/RewriteStatepointsForGC/deopt-bundles/live-vector.ll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters