diff options
| author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-05-11 18:49:34 +0000 |
|---|---|---|
| committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-05-11 18:49:34 +0000 |
| commit | 89c5491a72d2eda952f8314e6700e8657e13ffb6 (patch) | |
| tree | 1ce36270d68aca3464a611392fb1247731002b0b /llvm/lib/CodeGen | |
| parent | 539175428883f84c4c8c8e6cc051a5d5b02fde88 (diff) | |
| download | bcm5719-llvm-89c5491a72d2eda952f8314e6700e8657e13ffb6.tar.gz bcm5719-llvm-89c5491a72d2eda952f8314e6700e8657e13ffb6.zip | |
[RewriteStatepointsForGC] Fix a bug on creating gc_relocate for pointer to vector of pointers
Summary:
In RewriteStatepointsForGC pass, we create a gc_relocate intrinsic for
each relocated pointer, and the gc_relocate has the same type with the
pointer. During the creation of gc_relocate intrinsic, llvm requires to
mangle its type. However, llvm does not support mangling of all possible
types. RewriteStatepointsForGC will hit an assertion failure when it
tries to create a gc_relocate for pointer to vector of pointers because
mangling for vector of pointers is not supported.
This patch changes the way RewriteStatepointsForGC pass creates
gc_relocate. For each relocated pointer, we erase the type of pointers
and create an unified gc_relocate of type i8 addrspace(1)*. Then a
bitcast is inserted to convert the gc_relocate to the correct type. In
this way, gc_relocate does not need to deal with different types of
pointers and the unsupported type mangling is no longer a problem. This
change would also ease further merge when LLVM erases types of pointers
and introduces an unified pointer type.
Some minor changes are also introduced to gc_relocate related part in
InstCombineCalls, CodeGenPrepare, and Verifier accordingly.
Patch by Chen Li!
Reviewers: reames, AndyAyers, sanjoy
Reviewed By: sanjoy
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D9592
llvm-svn: 237009
Diffstat (limited to 'llvm/lib/CodeGen')
| -rw-r--r-- | llvm/lib/CodeGen/CodeGenPrepare.cpp | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 49836254356..641316105c0 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -600,13 +600,51 @@ simplifyRelocatesOffABase(IntrinsicInst *RelocatedBase, // Create a Builder and replace the target callsite with a gep IRBuilder<> Builder(ToReplace); Builder.SetCurrentDebugLocation(ToReplace->getDebugLoc()); + + // If gc_relocate does not match the actual type, cast it to the right type. + // In theory, there must be a bitcast after gc_relocate if the type does not + // match, and we should reuse it to get the derived pointer. But it could be + // cases like this: + // bb1: + // ... + // %g1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(...) + // br label %merge + // + // bb2: + // ... + // %g2 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(...) + // br label %merge + // + // merge: + // %p1 = phi i8 addrspace(1)* [ %g1, %bb1 ], [ %g2, %bb2 ] + // %cast = bitcast i8 addrspace(1)* %p1 in to i32 addrspace(1)* + // + // In this case, we can not find the bitcast any more. So we insert a new bitcast + // no matter there is already one or not. In this way, we can handle all cases, and + // the extra bitcast should be optimized away in later passes. + Instruction *ActualRelocatedBase = RelocatedBase; + if (RelocatedBase->getType() != Base->getType()) { + ActualRelocatedBase = + cast<Instruction>(Builder.CreateBitCast(RelocatedBase, Base->getType())); + ActualRelocatedBase->removeFromParent(); + ActualRelocatedBase->insertAfter(cast<Instruction>(RelocatedBase)); + } Value *Replacement = Builder.CreateGEP( - Derived->getSourceElementType(), RelocatedBase, makeArrayRef(OffsetV)); + Derived->getSourceElementType(), ActualRelocatedBase, makeArrayRef(OffsetV)); Instruction *ReplacementInst = cast<Instruction>(Replacement); ReplacementInst->removeFromParent(); - ReplacementInst->insertAfter(RelocatedBase); + ReplacementInst->insertAfter(ActualRelocatedBase); Replacement->takeName(ToReplace); - ToReplace->replaceAllUsesWith(Replacement); + // If the newly generated derived pointer's type does not match the original derived + // pointer's type, cast the new derived pointer to match it. Same reasoning as above. + Instruction *ActualReplacement = ReplacementInst; + if (ReplacementInst->getType() != ToReplace->getType()) { + ActualReplacement = + cast<Instruction>(Builder.CreateBitCast(ReplacementInst, ToReplace->getType())); + ActualReplacement->removeFromParent(); + ActualReplacement->insertAfter(ReplacementInst); + } + ToReplace->replaceAllUsesWith(ActualReplacement); ToReplace->eraseFromParent(); MadeChange = true; |

