[llvm] r333063 - SafepointIRVerifier is made unreachable block tolerant

Serguei Katkov via llvm-commits llvm-commits at lists.llvm.org
Tue May 22 22:54:55 PDT 2018


Author: skatkov
Date: Tue May 22 22:54:55 2018
New Revision: 333063

URL: http://llvm.org/viewvc/llvm-project?rev=333063&view=rev
Log:
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

Added:
    llvm/trunk/test/SafepointIRVerifier/unreachable-block-tolerant.ll
Modified:
    llvm/trunk/lib/IR/SafepointIRVerifier.cpp

Modified: llvm/trunk/lib/IR/SafepointIRVerifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/SafepointIRVerifier.cpp?rev=333063&r1=333062&r2=333063&view=diff
==============================================================================
--- llvm/trunk/lib/IR/SafepointIRVerifier.cpp (original)
+++ llvm/trunk/lib/IR/SafepointIRVerifier.cpp Tue May 22 22:54:55 2018
@@ -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::removeValidUnrelocate
         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 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::verifyInstruct
     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) &&

Added: llvm/trunk/test/SafepointIRVerifier/unreachable-block-tolerant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/SafepointIRVerifier/unreachable-block-tolerant.ll?rev=333063&view=auto
==============================================================================
--- llvm/trunk/test/SafepointIRVerifier/unreachable-block-tolerant.ll (added)
+++ llvm/trunk/test/SafepointIRVerifier/unreachable-block-tolerant.ll Tue May 22 22:54:55 2018
@@ -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, ...)




More information about the llvm-commits mailing list