[PATCH] [RewriteStatepointsForGC] Fix a relocation bug w.r.t values defined by invoke instructions

Chen Li meloli87 at gmail.com
Thu Feb 26 16:48:01 PST 2015


Hi reames,

RewriteStatepointsForGC pass emits an alloca for each GC pointer which will be relocated. It then inserts stores after def and all relocations, and inserts loads before each use as well. In the end, mem2reg is used to update IR with relocations in SSA form.

However, there is a problem with inserting stores for values defined by invoke instructions. The code didn't expect a def was a terminator instruction, and inserting instructions after these terminators resulted in malformed IR. 

This patch fixes this problem by handling invoke instructions as a special case. If the def is an invoke instruction, the store will be inserted at the beginning of the normal destination block. Since return value from invoke instruction does not dominate the unwind destination block, no action is needed there.

http://reviews.llvm.org/D7923

Files:
  lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
  test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll

Index: lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
===================================================================
--- lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
+++ lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
@@ -1560,7 +1560,17 @@
     // use list and an extra load will be inserted before it
     StoreInst *store = new StoreInst(def, alloca);
     if (isa<Instruction>(def)) {
-      store->insertAfter(cast<Instruction>(def));
+      if (InvokeInst *invoke = dyn_cast<InvokeInst>(def)) {
+        // InvokeInst is a TerminatorInst so the store need to be inserted
+        // into its normal destination block.
+        BasicBlock *normalDest = invoke->getNormalDest();
+        store->insertBefore(normalDest->getFirstNonPHI());
+      } else {
+        assert(!cast<Instruction>(def)->isTerminator() &&
+               "The only TerminatorInst that can produce a value is\
+               InvokeInst which is handled above.");
+         store->insertAfter(cast<Instruction>(def));
+      }
     } else {
       assert((isa<Argument>(def) || isa<GlobalVariable>(def) ||
               (isa<Constant>(def) && cast<Constant>(def)->isNullValue())) &&
Index: test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll
===================================================================
--- test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll
+++ test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll
@@ -0,0 +1,30 @@
+;; RUN: opt %s -rewrite-statepoints-for-gc -verify -S 
+
+;; This test is to verify that RewriteStatepointsForGC correctly relocates values
+;; defined by invoke instruction results. 
+
+declare i64* addrspace(1)* @non_gc_call()
+
+declare void @gc_call()
+
+declare i32* @fake_personality_function()
+
+; Function Attrs: nounwind
+define i64* addrspace(1)* @test() gc "statepoint-example" {
+entry:
+  %obj = invoke i64* addrspace(1)* @non_gc_call()
+          to label %normal_dest unwind label %unwind_dest
+
+unwind_dest:                                      ; preds = %entry
+  %lpad = landingpad { i8*, i32 } personality i32* ()* @fake_personality_function
+          cleanup
+  resume { i8*, i32 } undef
+
+normal_dest:                                      ; preds = %entry
+  %safepoint_token = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @gc_call, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
+  ret i64* addrspace(1)* %obj
+}
+
+declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()*, i32, i32, ...)
+
+

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D7923.20805.patch
Type: text/x-patch
Size: 2559 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150227/796e505b/attachment.bin>


More information about the llvm-commits mailing list