[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