Skip to content

Commit

Permalink
Print indices of assertions instead of raw bitsets (#54928)
Browse files Browse the repository at this point in the history
* Add JITDUMPEXEC macro

For use in contexts where some printing method
should only be executed when "verbose" is true.

* Add helpers for printing assertion indexes

* Print assertion indices instead of raw bitsets

To aid in understanding what assertions are being
propagated and merged when reading the dumps.

* Don't print VNs for the same assertion twice

* Also correctly print VNs in CopyProp

* Align "in"s with "out"s for final assertions

* Don't print the assertion dataflow in usual dumps

It can still be enabled if needed.
  • Loading branch information
SingleAccretion authored Jul 8, 2021
1 parent 2432926 commit f3b7775
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 54 deletions.
184 changes: 139 additions & 45 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ void Compiler::optAssertionInit(bool isLocalProp)
}

#ifdef DEBUG
void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex assertionIndex /* =0 */)
void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex assertionIndex /* = 0 */)
{
if (curAssertion->op1.kind == O1K_EXACT_TYPE)
{
Expand Down Expand Up @@ -590,10 +590,6 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse
printf("?assertion classification? ");
}
printf("Assertion: ");
if (!optLocalAssertionProp)
{
printf("(%d, %d) ", curAssertion->op1.vn, curAssertion->op2.vn);
}

if (!optLocalAssertionProp)
{
Expand Down Expand Up @@ -778,12 +774,67 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse

if (assertionIndex > 0)
{
printf(" index=#%02u, mask=", assertionIndex);
printf("%s", BitVecOps::ToString(apTraits, BitVecOps::MakeSingleton(apTraits, assertionIndex - 1)));
printf(", index = ");
optPrintAssertionIndex(assertionIndex);
}
printf("\n");
}

void Compiler::optPrintAssertionIndex(AssertionIndex index)
{
if (index == NO_ASSERTION_INDEX)
{
printf("#NA");
return;
}

printf("#%02u", index);
}

void Compiler::optPrintAssertionIndices(ASSERT_TP assertions)
{
if (BitVecOps::IsEmpty(apTraits, assertions))
{
optPrintAssertionIndex(NO_ASSERTION_INDEX);
return;
}

BitVecOps::Iter iter(apTraits, assertions);
unsigned bitIndex = 0;
if (iter.NextElem(&bitIndex))
{
optPrintAssertionIndex(static_cast<AssertionIndex>(bitIndex + 1));
while (iter.NextElem(&bitIndex))
{
printf(" ");
optPrintAssertionIndex(static_cast<AssertionIndex>(bitIndex + 1));
}
}
}
#endif // DEBUG

/* static */
void Compiler::optDumpAssertionIndices(const char* header, ASSERT_TP assertions, const char* footer /* = nullptr */)
{
#ifdef DEBUG
Compiler* compiler = JitTls::GetCompiler();
if (compiler->verbose)
{
printf(header);
compiler->optPrintAssertionIndices(assertions);
if (footer != nullptr)
{
printf(footer);
}
}
#endif // DEBUG
}

/* static */
void Compiler::optDumpAssertionIndices(ASSERT_TP assertions, const char* footer /* = nullptr */)
{
optDumpAssertionIndices("", assertions, footer);
}

/******************************************************************************
*
Expand Down Expand Up @@ -4511,7 +4562,7 @@ void Compiler::optImpliedByConstAssertion(AssertionDsc* constAssertion, ASSERT_T
if (verbose)
{
AssertionDsc* firstAssertion = optGetAssertion(1);
printf("\nCompiler::optImpliedByConstAssertion: constAssertion #%02d , implies assertion #%02d",
printf("Compiler::optImpliedByConstAssertion: const assertion #%02d implies assertion #%02d\n",
(constAssertion - firstAssertion) + 1, (impAssertion - firstAssertion) + 1);
}
#endif
Expand Down Expand Up @@ -4721,8 +4772,12 @@ class AssertionPropFlowCallback
// At the start of the merge function of the dataflow equations, initialize premerge state (to detect change.)
void StartMerge(BasicBlock* block)
{
JITDUMP("AssertionPropCallback::StartMerge: " FMT_BB " in -> %s\n", block->bbNum,
BitVecOps::ToString(apTraits, block->bbAssertionIn));
if (VerboseDataflow())
{
JITDUMP("StartMerge: " FMT_BB " ", block->bbNum);
Compiler::optDumpAssertionIndices("in -> ", block->bbAssertionIn, "\n");
}

BitVecOps::Assign(apTraits, preMergeOut, block->bbAssertionOut);
BitVecOps::Assign(apTraits, preMergeJumpDestOut, mJumpDestOut[block->bbNum]);
}
Expand All @@ -4743,21 +4798,29 @@ class AssertionPropFlowCallback
assert(predBlock->bbNext == block);
BitVecOps::IntersectionD(apTraits, pAssertionOut, predBlock->bbAssertionOut);

JITDUMP("AssertionPropCallback::Merge : Duplicate flow, " FMT_BB " in -> %s, predBlock " FMT_BB
" out1 -> %s, out2 -> %s\n",
block->bbNum, BitVecOps::ToString(apTraits, block->bbAssertionIn), predBlock->bbNum,
BitVecOps::ToString(apTraits, mJumpDestOut[predBlock->bbNum]),
BitVecOps::ToString(apTraits, predBlock->bbAssertionOut));
if (VerboseDataflow())
{
JITDUMP("Merge : Duplicate flow, " FMT_BB " ", block->bbNum);
Compiler::optDumpAssertionIndices("in -> ", block->bbAssertionIn, "; ");
JITDUMP("pred " FMT_BB " ", predBlock->bbNum);
Compiler::optDumpAssertionIndices("out1 -> ", mJumpDestOut[predBlock->bbNum], "; ");
Compiler::optDumpAssertionIndices("out2 -> ", predBlock->bbAssertionOut, "\n");
}
}
}
else
{
pAssertionOut = predBlock->bbAssertionOut;
}

JITDUMP("AssertionPropCallback::Merge : " FMT_BB " in -> %s, predBlock " FMT_BB " out -> %s\n",
block->bbNum, BitVecOps::ToString(apTraits, block->bbAssertionIn), predBlock->bbNum,
BitVecOps::ToString(apTraits, pAssertionOut));
if (VerboseDataflow())
{
JITDUMP("Merge : " FMT_BB " ", block->bbNum);
Compiler::optDumpAssertionIndices("in -> ", block->bbAssertionIn, "; ");
JITDUMP("pred " FMT_BB " ", predBlock->bbNum);
Compiler::optDumpAssertionIndices("out -> ", pAssertionOut, "\n");
}

BitVecOps::IntersectionD(apTraits, block->bbAssertionIn, pAssertionOut);
}

Expand All @@ -4781,33 +4844,47 @@ class AssertionPropFlowCallback
// At the end of the merge store results of the dataflow equations, in a postmerge state.
bool EndMerge(BasicBlock* block)
{
JITDUMP("AssertionPropCallback::EndMerge : " FMT_BB " in -> %s\n\n", block->bbNum,
BitVecOps::ToString(apTraits, block->bbAssertionIn));
if (VerboseDataflow())
{
JITDUMP("EndMerge : " FMT_BB " ", block->bbNum);
Compiler::optDumpAssertionIndices("in -> ", block->bbAssertionIn, "\n\n");
}

BitVecOps::DataFlowD(apTraits, block->bbAssertionOut, block->bbAssertionGen, block->bbAssertionIn);
BitVecOps::DataFlowD(apTraits, mJumpDestOut[block->bbNum], mJumpDestGen[block->bbNum], block->bbAssertionIn);

bool changed = (!BitVecOps::Equal(apTraits, preMergeOut, block->bbAssertionOut) ||
!BitVecOps::Equal(apTraits, preMergeJumpDestOut, mJumpDestOut[block->bbNum]));

if (changed)
{
JITDUMP("AssertionPropCallback::Changed : " FMT_BB " before out -> %s; after out -> %s;\n"
"\t\tjumpDest before out -> %s; jumpDest after out -> %s;\n\n",
block->bbNum, BitVecOps::ToString(apTraits, preMergeOut),
BitVecOps::ToString(apTraits, block->bbAssertionOut),
BitVecOps::ToString(apTraits, preMergeJumpDestOut),
BitVecOps::ToString(apTraits, mJumpDestOut[block->bbNum]));
}
else
if (VerboseDataflow())
{
JITDUMP("AssertionPropCallback::Unchanged : " FMT_BB " out -> %s; \t\tjumpDest out -> %s\n\n",
block->bbNum, BitVecOps::ToString(apTraits, block->bbAssertionOut),
BitVecOps::ToString(apTraits, mJumpDestOut[block->bbNum]));
if (changed)
{
JITDUMP("Changed : " FMT_BB " ", block->bbNum);
Compiler::optDumpAssertionIndices("before out -> ", preMergeOut, "; ");
Compiler::optDumpAssertionIndices("after out -> ", block->bbAssertionOut, ";\n ");
Compiler::optDumpAssertionIndices("jumpDest before out -> ", preMergeJumpDestOut, "; ");
Compiler::optDumpAssertionIndices("jumpDest after out -> ", mJumpDestOut[block->bbNum], ";\n\n");
}
else
{
JITDUMP("Unchanged : " FMT_BB " ", block->bbNum);
Compiler::optDumpAssertionIndices("out -> ", block->bbAssertionOut, "; ");
Compiler::optDumpAssertionIndices("jumpDest out -> ", mJumpDestOut[block->bbNum], "\n\n");
}
}

return changed;
}

// Can be enabled to get detailed debug output about dataflow for assertions.
bool VerboseDataflow()
{
#if 0
return VERBOSE;
#endif
return false;
}
};

/*****************************************************************************
Expand Down Expand Up @@ -4894,16 +4971,28 @@ ASSERT_TP* Compiler::optComputeAssertionGen()
#ifdef DEBUG
if (verbose)
{
printf(FMT_BB " valueGen = %s", block->bbNum, BitVecOps::ToString(apTraits, block->bbAssertionGen));
if (block == fgFirstBB)
{
printf("\n");
}

printf(FMT_BB " valueGen = ", block->bbNum);
optPrintAssertionIndices(block->bbAssertionGen);
if (block->bbJumpKind == BBJ_COND)
{
printf(" => " FMT_BB " valueGen = %s,", block->bbJumpDest->bbNum,
BitVecOps::ToString(apTraits, jumpDestGen[block->bbNum]));
printf(" => " FMT_BB " valueGen = ", block->bbJumpDest->bbNum);
optPrintAssertionIndices(jumpDestGen[block->bbNum]);
}
printf("\n");

if (block == fgLastBB)
{
printf("\n");
}
}
#endif
}

return jumpDestGen;
}

Expand Down Expand Up @@ -5408,6 +5497,10 @@ void Compiler::optAssertionPropMain()
// Modified dataflow algorithm for available expressions.
DataFlow flow(this);
AssertionPropFlowCallback ap(this, bbJtrueAssertionOut, jumpDestGen);
if (ap.VerboseDataflow())
{
JITDUMP("AssertionPropFlowCallback:\n\n")
}
flow.ForwardAnalysis(ap);

for (BasicBlock* const block : Blocks())
Expand All @@ -5419,16 +5512,15 @@ void Compiler::optAssertionPropMain()
#ifdef DEBUG
if (verbose)
{
printf("\n");
for (BasicBlock* const block : Blocks())
{
printf("\n" FMT_BB, block->bbNum);
printf(" valueIn = %s", BitVecOps::ToString(apTraits, block->bbAssertionIn));
printf(" valueOut = %s", BitVecOps::ToString(apTraits, block->bbAssertionOut));
printf(FMT_BB ":\n", block->bbNum);
optDumpAssertionIndices(" in = ", block->bbAssertionIn, "\n");
optDumpAssertionIndices(" out = ", block->bbAssertionOut, "\n");
if (block->bbJumpKind == BBJ_COND)
{
printf(" => " FMT_BB, block->bbJumpDest->bbNum);
printf(" valueOut= %s", BitVecOps::ToString(apTraits, bbJtrueAssertionOut[block->bbNum]));
printf(" " FMT_BB " = ", block->bbJumpDest->bbNum);
optDumpAssertionIndices(bbJtrueAssertionOut[block->bbNum], "\n");
}
}
printf("\n");
Expand Down Expand Up @@ -5473,9 +5565,11 @@ void Compiler::optAssertionPropMain()
// and thus we must morph, set order, re-link
for (GenTree* tree = stmt->GetTreeList(); tree != nullptr; tree = tree->gtNext)
{
JITDUMP("Propagating %s assertions for " FMT_BB ", stmt " FMT_STMT ", tree [%06d], tree -> %d\n",
BitVecOps::ToString(apTraits, assertions), block->bbNum, stmt->GetID(), dspTreeID(tree),
tree->GetAssertionInfo().GetAssertionIndex());
optDumpAssertionIndices("Propagating ", assertions, " ");
JITDUMP("for " FMT_BB ", stmt " FMT_STMT ", tree [%06d]", block->bbNum, stmt->GetID(), dspTreeID(tree));
JITDUMP(", tree -> ");
JITDUMPEXEC(optPrintAssertionIndex(tree->GetAssertionInfo().GetAssertionIndex()));
JITDUMP("\n");

GenTree* newTree = optAssertionProp(assertions, tree, stmt, block);
if (newTree)
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -7491,9 +7491,14 @@ class Compiler

#ifdef DEBUG
void optPrintAssertion(AssertionDsc* newAssertion, AssertionIndex assertionIndex = 0);
void optPrintAssertionIndex(AssertionIndex index);
void optPrintAssertionIndices(ASSERT_TP assertions);
void optDebugCheckAssertion(AssertionDsc* assertion);
void optDebugCheckAssertions(AssertionIndex AssertionIndex);
#endif
static void optDumpAssertionIndices(const char* header, ASSERT_TP assertions, const char* footer = nullptr);
static void optDumpAssertionIndices(ASSERT_TP assertions, const char* footer = nullptr);

void optAddCopies();
#endif // ASSERTION_PROP

Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/jit/copyprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,9 @@ void Compiler::optCopyProp(BasicBlock* block, Statement* stmt, GenTree* tree, Lc
{
JITDUMP("VN based copy assertion for ");
printTreeID(tree);
printf(" V%02d @%08X by ", lclNum, tree->GetVN(VNK_Conservative));
printf(" V%02d " FMT_VN " by ", lclNum, tree->GetVN(VNK_Conservative));
printTreeID(op);
printf(" V%02d @%08X.\n", newLclNum, op->GetVN(VNK_Conservative));
printf(" V%02d " FMT_VN ".\n", newLclNum, op->GetVN(VNK_Conservative));
gtDispTree(tree, nullptr, nullptr, true);
}
#endif
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/jit/jit.h
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,11 @@ const bool dspGCtbls = true;
if (JitTls::GetCompiler()->verbose) \
logf(__VA_ARGS__); \
}
#define JITDUMPEXEC(x) \
{ \
if (JitTls::GetCompiler()->verbose) \
x; \
}
#define JITLOG(x) \
{ \
JitLogEE x; \
Expand Down Expand Up @@ -521,6 +526,7 @@ const bool dspGCtbls = true;
#define VERBOSE JitTls::GetCompiler()->verbose
#else // !DEBUG
#define JITDUMP(...)
#define JITDUMPEXEC(x)
#define JITLOG(x)
#define JITLOG_THIS(t, x)
#define DBEXEC(flg, expr)
Expand Down
15 changes: 8 additions & 7 deletions src/coreclr/jit/rangecheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -865,16 +865,16 @@ void RangeCheck::MergeAssertion(BasicBlock* block, GenTree* op, Range* pRange DE
if (pred->bbFallsThrough() && pred->bbNext == block)
{
assertions = pred->bbAssertionOut;
JITDUMP("Merge assertions from pred " FMT_BB " edge: %s\n", pred->bbNum,
BitVecOps::ToString(m_pCompiler->apTraits, assertions));
JITDUMP("Merge assertions from pred " FMT_BB " edge: ", pred->bbNum);
Compiler::optDumpAssertionIndices(assertions, "\n");
}
else if ((pred->bbJumpKind == BBJ_COND || pred->bbJumpKind == BBJ_ALWAYS) && pred->bbJumpDest == block)
{
if (m_pCompiler->bbJtrueAssertionOut != nullptr)
{
assertions = m_pCompiler->bbJtrueAssertionOut[pred->bbNum];
JITDUMP("Merge assertions from pred " FMT_BB " JTrue edge: %s\n", pred->bbNum,
BitVecOps::ToString(m_pCompiler->apTraits, assertions));
JITDUMP("Merge assertions from pred " FMT_BB " JTrue edge: ", pred->bbNum);
Compiler::optDumpAssertionIndices(assertions, "\n");
}
}
}
Expand Down Expand Up @@ -1012,9 +1012,10 @@ Range RangeCheck::ComputeRangeForLocalDef(BasicBlock* block,
Range range = GetRange(ssaDef->GetBlock(), ssaDef->GetAssignment()->gtGetOp2(), monIncreasing DEBUGARG(indent));
if (!BitVecOps::MayBeUninit(block->bbAssertionIn) && (m_pCompiler->GetAssertionCount() > 0))
{
JITDUMP("Merge assertions from " FMT_BB ":%s for assignment about [%06d]\n", block->bbNum,
BitVecOps::ToString(m_pCompiler->apTraits, block->bbAssertionIn),
Compiler::dspTreeID(ssaDef->GetAssignment()->gtGetOp1()));
JITDUMP("Merge assertions from " FMT_BB ": ", block->bbNum);
Compiler::optDumpAssertionIndices(block->bbAssertionIn, " ");
JITDUMP("for assignment about [%06d]\n", Compiler::dspTreeID(ssaDef->GetAssignment()->gtGetOp1()))

MergeEdgeAssertions(ssaDef->GetAssignment()->gtGetOp1()->AsLclVarCommon(), block->bbAssertionIn, &range);
JITDUMP("done merging\n");
}
Expand Down

0 comments on commit f3b7775

Please sign in to comment.