diff --git a/llvm/include/llvm/IR/PassInstrumentation.h b/llvm/include/llvm/IR/PassInstrumentation.h --- a/llvm/include/llvm/IR/PassInstrumentation.h +++ b/llvm/include/llvm/IR/PassInstrumentation.h @@ -243,6 +243,16 @@ ExtraArgsT...) { return false; } + + template + void pushBeforeNonSkippedPassCallback(CallableT C) { + if (Callbacks) + Callbacks->BeforeNonSkippedPassCallbacks.emplace_back(std::move(C)); + } + void popBeforeNonSkippedPassCallback() { + if (Callbacks) + Callbacks->BeforeNonSkippedPassCallbacks.pop_back(); + } }; bool isSpecialPass(StringRef PassID, const std::vector &Specials); diff --git a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h --- a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h +++ b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h @@ -50,6 +50,7 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Dominators.h" +#include "llvm/IR/PassInstrumentation.h" #include "llvm/IR/PassManager.h" #include "llvm/Transforms/Utils/LCSSA.h" #include "llvm/Transforms/Utils/LoopSimplify.h" @@ -296,6 +297,21 @@ // declaration. appendLoopsToWorklist(LI, Worklist); +#ifndef NDEBUG + PI.pushBeforeNonSkippedPassCallback([&LAR, &LI](StringRef PassID, Any IR) { + if (isSpecialPass(PassID, {"PassManager"})) + return; + assert(any_isa(IR)); + const Loop *L = any_cast(IR); + assert(L && "Loop should be valid for printing"); + + // Verify the loop structure and LCSSA form before visiting the loop. + L->verifyLoop(); + assert(L->isRecursivelyLCSSAForm(LAR.DT, LI) && + "Loops must remain in LCSSA form!"); + }); +#endif + do { Loop *L = Worklist.pop_back_val(); @@ -306,11 +322,6 @@ #ifndef NDEBUG // Save a parent loop pointer for asserts. Updater.ParentL = L->getParentLoop(); - - // Verify the loop structure and LCSSA form before visiting the loop. - L->verifyLoop(); - assert(L->isRecursivelyLCSSAForm(LAR.DT, LI) && - "Loops must remain in LCSSA form!"); #endif // Check the PassInstrumentation's BeforePass callbacks before running the // pass, skip its execution completely if asked to (callback returns @@ -345,6 +356,10 @@ PA.intersect(std::move(PassPA)); } while (!Worklist.empty()); +#ifndef NDEBUG + PI.popBeforeNonSkippedPassCallback(); +#endif + // By definition we preserve the proxy. We also preserve all analyses on // Loops. This precludes *any* invalidation of loop analyses by the proxy, // but that's OK because we've taken care to invalidate analyses in the diff --git a/llvm/lib/Transforms/Scalar/LoopPassManager.cpp b/llvm/lib/Transforms/Scalar/LoopPassManager.cpp --- a/llvm/lib/Transforms/Scalar/LoopPassManager.cpp +++ b/llvm/lib/Transforms/Scalar/LoopPassManager.cpp @@ -57,13 +57,6 @@ break; } -#ifndef NDEBUG - // Verify the loop structure and LCSSA form before visiting the loop. - L.verifyLoop(); - assert(L.isRecursivelyLCSSAForm(AR.DT, AR.LI) && - "Loops must remain in LCSSA form!"); -#endif - // Update the analysis manager as each pass runs and potentially // invalidates analyses. AM.invalidate(L, PassPA); diff --git a/llvm/test/Feature/optnone-opt.ll b/llvm/test/Feature/optnone-opt.ll --- a/llvm/test/Feature/optnone-opt.ll +++ b/llvm/test/Feature/optnone-opt.ll @@ -34,7 +34,7 @@ br label %while.cond while.end: ; preds = %while.cond - ret i32 0 + ret i32 %dec } attributes #0 = { optnone noinline }