forked from OSchip/llvm-project
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
This commit is contained in:
parent
d518c5fc87
commit
8a9e059e5c
|
@ -37,6 +37,18 @@ class InstructionPrecedenceTracking {
|
||||||
// Fills information about the given block's special instructions.
|
// Fills information about the given block's special instructions.
|
||||||
void fill(const BasicBlock *BB);
|
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:
|
protected:
|
||||||
InstructionPrecedenceTracking(DominatorTree *DT)
|
InstructionPrecedenceTracking(DominatorTree *DT)
|
||||||
: OI(OrderedInstructions(DT)) {}
|
: OI(OrderedInstructions(DT)) {}
|
||||||
|
|
|
@ -23,8 +23,25 @@
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
static cl::opt<bool> 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 Instruction *InstructionPrecedenceTracking::getFirstSpecialInstruction(
|
||||||
const BasicBlock *BB) {
|
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))
|
if (!KnownBlocks.count(BB))
|
||||||
fill(BB);
|
fill(BB);
|
||||||
auto *FirstICF = FirstSpecialInsts.lookup(BB);
|
auto *FirstICF = FirstSpecialInsts.lookup(BB);
|
||||||
|
@ -56,6 +73,45 @@ void InstructionPrecedenceTracking::fill(const BasicBlock *BB) {
|
||||||
KnownBlocks.insert(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) {
|
void InstructionPrecedenceTracking::invalidateBlock(const BasicBlock *BB) {
|
||||||
OI.invalidateBlock(BB);
|
OI.invalidateBlock(BB);
|
||||||
FirstSpecialInsts.erase(BB);
|
FirstSpecialInsts.erase(BB);
|
||||||
|
@ -67,6 +123,10 @@ void InstructionPrecedenceTracking::clear() {
|
||||||
OI.invalidateBlock(It.first);
|
OI.invalidateBlock(It.first);
|
||||||
FirstSpecialInsts.clear();
|
FirstSpecialInsts.clear();
|
||||||
KnownBlocks.clear();
|
KnownBlocks.clear();
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// The map should be valid after clearing (at least empty).
|
||||||
|
validateAll();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImplicitControlFlowTracking::isSpecialInstruction(
|
bool ImplicitControlFlowTracking::isSpecialInstruction(
|
||||||
|
|
Loading…
Reference in New Issue