diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/CodeGenPrepare.cpp | 44 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp | 17 |
4 files changed, 66 insertions, 14 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; diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 374f8f210be..a5d5829b071 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -3384,10 +3384,8 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { "'gc parameters' section of the statepoint call", &CI); - // Assert that the result type matches the type of the relocated pointer - GCRelocateOperands Operands(&CI); - Assert(Operands.getDerivedPtr()->getType() == CI.getType(), - "gc.relocate: relocating a pointer shouldn't change its type", &CI); + // gc_relocate does not need to be the same type as the relocated pointer. + // It can casted to the correct type later if it's desired break; } }; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index cae611f21b2..3b925eda16b 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1202,6 +1202,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { // preserve relocation semantics. GCRelocateOperands Operands(II); Value *DerivedPtr = Operands.getDerivedPtr(); + auto *GCRelocateType = cast<PointerType>(II->getType()); // Remove the relocation if unused, note that this check is required // to prevent the cases below from looping forever. @@ -1212,14 +1213,18 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { // TODO: provide a hook for this in GCStrategy. This is clearly legal for // most practical collectors, but there was discussion in the review thread // about whether it was legal for all possible collectors. - if (isa<UndefValue>(DerivedPtr)) - return ReplaceInstUsesWith(*II, DerivedPtr); + if (isa<UndefValue>(DerivedPtr)) { + // gc_relocate is uncasted. Use undef of gc_relocate's type to replace it. + return ReplaceInstUsesWith(*II, UndefValue::get(GCRelocateType)); + } // The relocation of null will be null for most any collector. // TODO: provide a hook for this in GCStrategy. There might be some weird // collector this property does not hold for. - if (isa<ConstantPointerNull>(DerivedPtr)) - return ReplaceInstUsesWith(*II, DerivedPtr); + if (isa<ConstantPointerNull>(DerivedPtr)) { + // gc_relocate is uncasted. Use null-pointer of gc_relocate's type to replace it. + return ReplaceInstUsesWith(*II, ConstantPointerNull::get(GCRelocateType)); + } // isKnownNonNull -> nonnull attribute if (isKnownNonNull(DerivedPtr)) diff --git a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp index 9cb0748c515..7f33295f828 100644 --- a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -1075,7 +1075,10 @@ static void CreateGCRelocates(ArrayRef<llvm::Value *> liveVariables, // the IR, but removes the need for argument bitcasts which shrinks the IR // greatly and makes it much more readable. SmallVector<Type *, 1> types; // one per 'any' type - types.push_back(liveVariables[i]->getType()); // result type + // All gc_relocate are set to i8 addrspace(1)* type. This could help avoid + // cases where the actual value's type mangling is not supported by llvm. A + // bitcast is added later to convert gc_relocate to the actual value's type. + types.push_back(Type::getInt8PtrTy(M->getContext(), 1)); Value *gc_relocate_decl = Intrinsic::getDeclaration( M, Intrinsic::experimental_gc_relocate, types); @@ -1342,8 +1345,16 @@ insertRelocationStores(iterator_range<Value::user_iterator> gcRelocs, Value *alloca = allocaMap[originalValue]; // Emit store into the related alloca - StoreInst *store = new StoreInst(relocatedValue, alloca); - store->insertAfter(relocatedValue); + // All gc_relocate are i8 addrspace(1)* typed, and it must be bitcasted to + // the correct type according to alloca. + assert(relocatedValue->getNextNode() && "Should always have one since it's not a terminator"); + IRBuilder<> Builder(relocatedValue->getNextNode()); + Value *CastedRelocatedValue = + Builder.CreateBitCast(relocatedValue, cast<AllocaInst>(alloca)->getAllocatedType(), + relocatedValue->hasName() ? relocatedValue->getName() + ".casted" : ""); + + StoreInst *store = new StoreInst(CastedRelocatedValue, alloca); + store->insertAfter(cast<Instruction>(CastedRelocatedValue)); #ifndef NDEBUG visitedLiveValues.insert(originalValue); |