[PATCH] Move calls to llvm.gcroot() when inlining.

Ben Karel eschew at gmail.com
Mon Oct 14 21:03:43 PDT 2013


According to http://llvm.org/docs/GarbageCollection.html#gcroot , all calls to the gcroot intrinsic must occur in a function's entry block.

LLVM's inliner pass does not maintain this invariant; when a function containing a gcroot is inlined, the gcroot is not moved to the entry block for the call site's function. When using aggressive codegen optimizations, this violated invariant usually results in segfaults.

http://llvm-reviews.chandlerc.com/D1935

Files:
  b/lib/Transforms/Utils/InlineFunction.cpp

Index: b/lib/Transforms/Utils/InlineFunction.cpp
===================================================================
--- b/lib/Transforms/Utils/InlineFunction.cpp
+++ b/lib/Transforms/Utils/InlineFunction.cpp
@@ -14,6 +14,7 @@
 
 #include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Analysis/CallGraph.h"
 #include "llvm/Analysis/InstructionSimplify.h"
@@ -666,6 +667,33 @@
     }
   }
 
+  llvm::SmallSet<llvm::Value*, 8> AllocasWithGCRoots;
+
+  // Likewise, we must move calls to llvm.gcroot() to the caller's entry block.
+  {
+    BasicBlock::iterator InsertPoint = Caller->begin()->getTerminator();
+    for (BasicBlock::iterator I = FirstNewBlock->begin(),
+         E = FirstNewBlock->end(); I != E; ) {
+      IntrinsicInst *II = dyn_cast<IntrinsicInst>(I++);
+      if (!II || II->getIntrinsicID() != llvm::Intrinsic::gcroot) continue;
+
+      // Stick gc roots at the end of the caller's entry block.
+      II->removeFromParent();
+      II->insertBefore(InsertPoint);
+
+      Value* arg = II->getArgOperand(0);
+      Value* AI = arg->stripPointerCasts();
+      AllocasWithGCRoots.insert(AI);
+
+      // Usually the gcroot will mark a bitcast of an alloca;
+      // we must move the bitcast to maintain proper scoping.
+      if (BitCastInst* cast = dyn_cast<BitCastInst>(arg)) {
+        cast->removeFromParent();
+        cast->insertBefore(II);
+      }
+    }
+  }
+
   // Leave lifetime markers for the static alloca's, scoping them to the
   // function we just inlined.
   if (InsertLifetime && !IFI.StaticAllocas.empty()) {
@@ -675,7 +703,7 @@
 
       // If the alloca is already scoped to something smaller than the whole
       // function then there's no need to add redundant, less accurate markers.
-      if (hasLifetimeMarkers(AI))
+      if (hasLifetimeMarkers(AI) || AllocasWithGCRoots.count(AI))
         continue;
 
       // Try to determine the size of the allocation.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1935.1.patch
Type: text/x-patch
Size: 2018 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131014/2e8e0c1e/attachment.bin>


More information about the llvm-commits mailing list