From 8a9e059e5c593107cc007f04865b54131fe14545 Mon Sep 17 00:00:00 2001 From: Max Kazantsev Date: Thu, 6 Sep 2018 08:33:02 +0000 Subject: [PATCH] Return "[NFC] Add severe validation of InstructionPrecedenceTracking" This validation patch has been reverted as rL341147 because of conserns raised by @reames. This revision returns it as is to raise a discussion and address the concerns. Differential Revision: https://reviews.llvm.org/D51523 Reviewed By: reames llvm-svn: 341526 --- .../llvm/Analysis/InstructionPrecedenceTracking.h | 12 +++++ .../lib/Analysis/InstructionPrecedenceTracking.cpp | 60 ++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/llvm/include/llvm/Analysis/InstructionPrecedenceTracking.h b/llvm/include/llvm/Analysis/InstructionPrecedenceTracking.h index 0a82eec..b421138 100644 --- a/llvm/include/llvm/Analysis/InstructionPrecedenceTracking.h +++ b/llvm/include/llvm/Analysis/InstructionPrecedenceTracking.h @@ -37,6 +37,18 @@ class InstructionPrecedenceTracking { // Fills information about the given block's special instructions. void fill(const BasicBlock *BB); +#ifndef NDEBUG + /// Asserts that the cached info for \p BB is up-to-date. This helps to catch + /// the usage error of accessing a block without properly invalidating after a + /// previous transform. + void validate(const BasicBlock *BB) const; + + /// Asserts whether or not the contents of this tracking is up-to-date. This + /// helps to catch the usage error of accessing a block without properly + /// invalidating after a previous transform. + void validateAll() const; +#endif + protected: InstructionPrecedenceTracking(DominatorTree *DT) : OI(OrderedInstructions(DT)) {} diff --git a/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp b/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp index d045771..c020c32 100644 --- a/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp +++ b/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp @@ -23,8 +23,25 @@ using namespace llvm; +#ifndef NDEBUG +static cl::opt ExpensiveAsserts( + "ipt-expensive-asserts", + cl::desc("Perform expensive assert validation on every query to Instruction" + " Precedence Tracking"), + cl::init(false), cl::Hidden); +#endif + const Instruction *InstructionPrecedenceTracking::getFirstSpecialInstruction( const BasicBlock *BB) { +#ifndef NDEBUG + // If there is a bug connected to invalid cache, turn on ExpensiveAsserts to + // catch this situation as early as possible. + if (ExpensiveAsserts) + validateAll(); + else + validate(BB); +#endif + if (!KnownBlocks.count(BB)) fill(BB); auto *FirstICF = FirstSpecialInsts.lookup(BB); @@ -56,6 +73,45 @@ void InstructionPrecedenceTracking::fill(const BasicBlock *BB) { KnownBlocks.insert(BB); } +#ifndef NDEBUG +void InstructionPrecedenceTracking::validate(const BasicBlock *BB) const { + // If we don't know anything about this block, make sure we don't store + // a bucket for it in FirstSpecialInsts map. + if (!KnownBlocks.count(BB)) { + assert(FirstSpecialInsts.find(BB) == FirstSpecialInsts.end() && "Must be!"); + return; + } + + auto It = FirstSpecialInsts.find(BB); + bool BlockHasSpecialInsns = false; + for (const Instruction &Insn : *BB) { + if (isSpecialInstruction(&Insn)) { + assert(It != FirstSpecialInsts.end() && + "Blocked marked as known but we have no cached value for it!"); + assert(It->second == &Insn && + "Cached first special instruction is wrong!"); + BlockHasSpecialInsns = true; + break; + } + } + if (!BlockHasSpecialInsns) + assert(It == FirstSpecialInsts.end() && + "Block is marked as having special instructions but in fact it " + "has none!"); +} + +void InstructionPrecedenceTracking::validateAll() const { + // Check that for every known block the cached value is correct. + for (auto *BB : KnownBlocks) + validate(BB); + + // Check that all blocks with cached values are marked as known. + for (auto &It : FirstSpecialInsts) + assert(KnownBlocks.count(It.first) && + "We have a cached value but the block is not marked as known?"); +} +#endif + void InstructionPrecedenceTracking::invalidateBlock(const BasicBlock *BB) { OI.invalidateBlock(BB); FirstSpecialInsts.erase(BB); @@ -67,6 +123,10 @@ void InstructionPrecedenceTracking::clear() { OI.invalidateBlock(It.first); FirstSpecialInsts.clear(); KnownBlocks.clear(); +#ifndef NDEBUG + // The map should be valid after clearing (at least empty). + validateAll(); +#endif } bool ImplicitControlFlowTracking::isSpecialInstruction( -- 2.7.4