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

Philip Reames listmail at philipreames.com
Tue Mar 3 16:13:53 PST 2015


Author: reames
Date: Tue Mar  3 18:13:52 2015
New Revision: 231183

URL: http://llvm.org/viewvc/llvm-project?rev=231183&view=rev
Log:
[RewriteStatepointsForGC] Fix a relocation bug w.r.t values defined by invoke instructions

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.

Patch by: Chen Li
Differential Revision: http://reviews.llvm.org/D7923



Added:
    llvm/trunk/test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp?rev=231183&r1=231182&r2=231183&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp Tue Mar  3 18:13:52 2015
@@ -1593,8 +1593,18 @@ static void relocationViaAlloca(
     // store must be inserted after load, otherwise store will be in alloca's
     // 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 (Instruction *inst = dyn_cast<Instruction>(def)) {
+      if (InvokeInst *invoke = dyn_cast<InvokeInst>(inst)) {
+        // 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(!inst->isTerminator() &&
+               "The only TerminatorInst that can produce a value is "
+               "InvokeInst which is handled above.");
+         store->insertAfter(inst);
+      }
     } else {
       assert((isa<Argument>(def) || isa<GlobalVariable>(def) ||
               (isa<Constant>(def) && cast<Constant>(def)->isNullValue())) &&

Added: llvm/trunk/test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll?rev=231183&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll (added)
+++ llvm/trunk/test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll Tue Mar  3 18:13:52 2015
@@ -0,0 +1,33 @@
+;; RUN: opt -rewrite-statepoints-for-gc -verify -S < %s | FileCheck %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: 
+  %lpad = landingpad { i8*, i32 } personality i32* ()* @fake_personality_function
+          cleanup
+  resume { i8*, i32 } undef
+
+normal_dest:
+;; CHECK-LABEL: normal_dest:
+;; CHECK-NEXT: gc.statepoint
+;; CHECK-NEXT: %obj.relocated = call coldcc i64* addrspace(1)*                                      
+  %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, ...)
+
+





More information about the llvm-commits mailing list