mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
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
This commit is contained in:
parent
5dad8000a9
commit
33d2c94345
@ -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) &&
|
||||
|
45
test/SafepointIRVerifier/unreachable-block-tolerant.ll
Normal file
45
test/SafepointIRVerifier/unreachable-block-tolerant.ll
Normal file
@ -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, ...)
|
Loading…
x
Reference in New Issue
Block a user