diff options
author | Serguei Katkov <serguei.katkov@azul.com> | 2018-05-23 05:54:55 +0000 |
---|---|---|
committer | Serguei Katkov <serguei.katkov@azul.com> | 2018-05-23 05:54:55 +0000 |
commit | 46ef8fffdf6409fb520ce614146b18fd98c0010e (patch) | |
tree | a83bdc8846d24bab88696989d795fd7cd10d48e6 | |
parent | 39e0347e6a0a3c2f29f427e755de75358b2d7bbb (diff) | |
download | bcm5719-llvm-46ef8fffdf6409fb520ce614146b18fd98c0010e.tar.gz bcm5719-llvm-46ef8fffdf6409fb520ce614146b18fd98c0010e.zip |
SafepointIRVerifier is made unreachable block tolerant
SafepointIRVerifier crashed while traversing blocks without a DomTreeNode.
This could happen with a custom pipeline or when some optional passes were skipped by OptBisect.
SafepointIRVerifier is fixed to traverse basic blocks that are reachable from entry. Test are added.
Patch Author: Yevgeny Rouban!
Reviewers: anna, reames, dneilson, DaniilSuchkov, skatkov
Reviewed By: reames
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D47011
llvm-svn: 333063
-rw-r--r-- | llvm/lib/IR/SafepointIRVerifier.cpp | 27 | ||||
-rw-r--r-- | llvm/test/SafepointIRVerifier/unreachable-block-tolerant.ll | 45 |
2 files changed, 65 insertions, 7 deletions
diff --git a/llvm/lib/IR/SafepointIRVerifier.cpp b/llvm/lib/IR/SafepointIRVerifier.cpp index 25a7f8d6d51..8de18c0fb34 100644 --- a/llvm/lib/IR/SafepointIRVerifier.cpp +++ b/llvm/lib/IR/SafepointIRVerifier.cpp @@ -318,6 +318,12 @@ public: static void verifyFunction(GCPtrTracker &&Tracker, InstructionVerifier &Verifier); + /// Returns true for reachable blocks that are verified, the other blocks are + /// ignored. + bool isMapped(const BasicBlock *BB) const { + return BlockMap.find(BB) != BlockMap.end(); + } + private: /// Returns true if the instruction may be safely skipped during verification. bool instructionMayBeSkipped(const Instruction *I) const; @@ -374,12 +380,13 @@ private: GCPtrTracker::GCPtrTracker(const Function &F, const DominatorTree &DT) : F(F) { // First, calculate Contribution of each BB. - for (const BasicBlock &BB : F) { - BasicBlockState *BBS = new (BSAllocator.Allocate()) BasicBlockState; - for (const auto &I : BB) - transferInstruction(I, BBS->Cleared, BBS->Contribution); - BlockMap[&BB] = BBS; - } + for (const BasicBlock &BB : F) + if (DT.isReachableFromEntry(&BB)) { + BasicBlockState *BBS = new (BSAllocator.Allocate()) BasicBlockState; + for (const auto &I : BB) + transferInstruction(I, BBS->Cleared, BBS->Contribution); + BlockMap[&BB] = BBS; + } // Initialize AvailableIn/Out sets of each BB using only information about // dominating BBs. @@ -452,7 +459,8 @@ void GCPtrTracker::recalculateBBsStates() { size_t OldInCount = BBS->AvailableIn.size(); for (const BasicBlock *PBB : predecessors(BB)) - set_intersect(BBS->AvailableIn, BlockMap[PBB]->AvailableOut); + if (isMapped(PBB)) + set_intersect(BBS->AvailableIn, BlockMap[PBB]->AvailableOut); assert(OldInCount >= BBS->AvailableIn.size() && "invariant!"); @@ -491,6 +499,8 @@ bool GCPtrTracker::removeValidUnrelocatedDefs(const BasicBlock *BB, bool HasUnrelocatedInputs = false; for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { const BasicBlock *InBB = PN->getIncomingBlock(i); + if (!isMapped(InBB)) + continue; const Value *InValue = PN->getIncomingValue(i); if (isNotExclusivelyConstantDerived(InValue)) { @@ -560,6 +570,7 @@ void GCPtrTracker::gatherDominatingDefs(const BasicBlock *BB, const DominatorTree &DT) { DomTreeNode *DTN = DT[const_cast<BasicBlock *>(BB)]; + assert(DTN && "Unreachable blocks are ignored"); while (DTN->getIDom()) { DTN = DTN->getIDom(); const auto &Defs = BlockMap[DTN->getBlock()]->Contribution; @@ -617,6 +628,8 @@ void InstructionVerifier::verifyInstruction( if (containsGCPtrType(PN->getType())) for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { const BasicBlock *InBB = PN->getIncomingBlock(i); + if (!Tracker->isMapped(InBB)) + continue; const Value *InValue = PN->getIncomingValue(i); if (isNotExclusivelyConstantDerived(InValue) && diff --git a/llvm/test/SafepointIRVerifier/unreachable-block-tolerant.ll b/llvm/test/SafepointIRVerifier/unreachable-block-tolerant.ll new file mode 100644 index 00000000000..724794b458f --- /dev/null +++ b/llvm/test/SafepointIRVerifier/unreachable-block-tolerant.ll @@ -0,0 +1,45 @@ +; RUN: opt -safepoint-ir-verifier-print-only -verify-safepoint-ir -S %s 2>&1 | FileCheck %s + +; This test checks that StatepointIRVerifier does not crash on +; a CFG with unreachable blocks. + +%jObject = type { [8 x i8] } + +define %jObject addrspace(1)* @test(%jObject addrspace(1)* %arg) gc "statepoint-example" { +; CHECK-LABEL: Verifying gc pointers in function: test +; CHECK-NEXT: No illegal uses found by SafepointIRVerifier in: test + %safepoint_token3 = tail call token (i64, i32, double (double)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_f64f64f(i64 0, i32 0, double (double)* undef, i32 1, i32 0, double undef, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, %jObject addrspace(1)* %arg) + %arg2.relocated4 = call coldcc %jObject addrspace(1)* @llvm.experimental.gc.relocate.p1jObject(token %safepoint_token3, i32 13, i32 13) + ret %jObject addrspace(1)* %arg2.relocated4 + +unreachable: + ret %jObject addrspace(1)* null +} + +; Function Attrs: nounwind +declare %jObject addrspace(1)* @llvm.experimental.gc.relocate.p1jObject(token, i32, i32) #3 + +declare token @llvm.experimental.gc.statepoint.p0f_f64f64f(i64, i32, double (double)*, i32, i32, ...) + +; In %merge %val.unrelocated, %ptr and %arg should be unrelocated. +define void @test2(i8 addrspace(1)* %arg) gc "statepoint-example" { +; CHECK-LABEL: Verifying gc pointers in function: test2 +; CHECK: No illegal uses found by SafepointIRVerifier in: test2 + bci_0: + %ptr = getelementptr i8, i8 addrspace(1)* %arg, i64 4 + br label %right + + left: + %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + br label %merge + + right: + br label %merge + + merge: + %val.unrelocated = phi i8 addrspace(1)* [ %arg, %left ], [ %ptr, %right ] + %c = icmp eq i8 addrspace(1)* %val.unrelocated, %arg + ret void +} + +declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) |