diff --git a/llvm/lib/Analysis/CGSCCPassManager.cpp b/llvm/lib/Analysis/CGSCCPassManager.cpp --- a/llvm/lib/Analysis/CGSCCPassManager.cpp +++ b/llvm/lib/Analysis/CGSCCPassManager.cpp @@ -432,8 +432,13 @@ break; } - // Check that we didn't miss any update scenario. - assert(!UR.InvalidatedSCCs.count(C) && "Processing an invalid SCC!"); + // If the CGSCC pass wasn't able to provide a valid updated SCC, the + // current SCC may simply need to be skipped if invalid. + if (UR.InvalidatedSCCs.count(C)) { + LLVM_DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n"); + break; + } + assert(C->begin() != C->end() && "Cannot have an empty SCC!"); // Check whether any of the handles were devirtualized. diff --git a/llvm/test/Other/devirt-invalidated.ll b/llvm/test/Other/devirt-invalidated.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Other/devirt-invalidated.ll @@ -0,0 +1,30 @@ +; RUN: opt -passes='devirt<0>(inline)' < %s -S | FileCheck %s + +; CHECK-NOT: internal +; CHECK: define void @e() +; CHECK-NOT: internal + +define void @e() { +entry: + call void @b() + ret void +} + +define internal void @b() { +entry: + call void @d() + call void @c() + ret void +} + +define internal void @d() { +entry: + unreachable +} + +define internal void @c() { +entry: + call void @b() + call void @e() + ret void +}