Skip to content

Commit

Permalink
Add debug checking of the loop table (dotnet#48060)
Browse files Browse the repository at this point in the history
* Add fgDebugCheckLoopTable()

* Minify some logging

* Add checking of the loop table to some phases

* Ignore removed loops in fgDebugCheckLoopTable
  • Loading branch information
SingleAccretion authored Feb 18, 2021
1 parent 0c5dbbb commit aa138f7
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5445,6 +5445,7 @@ class Compiler
void fgDebugCheckStmtsList(BasicBlock* block, bool morphTrees);
void fgDebugCheckNodeLinks(BasicBlock* block, Statement* stmt);
void fgDebugCheckNodesUniqueness();
void fgDebugCheckLoopTable();

void fgDebugCheckFlags(GenTree* tree);
void fgDebugCheckDispFlags(GenTree* tree, unsigned dispFlags, unsigned debugFlags);
Expand Down
80 changes: 66 additions & 14 deletions src/coreclr/jit/fgdiagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1617,13 +1617,8 @@ Compiler::fgWalkResult Compiler::fgStress64RsltMulCB(GenTree** pTree, fgWalkData
return WALK_CONTINUE;
}

#ifdef DEBUG
if (pComp->verbose)
{
printf("STRESS_64RSLT_MUL before:\n");
pComp->gtDispTree(tree);
}
#endif // DEBUG
JITDUMP("STRESS_64RSLT_MUL before:\n");
DISPTREE(tree);

// To ensure optNarrowTree() doesn't fold back to the original tree.
tree->AsOp()->gtOp1 = pComp->gtNewCastNode(TYP_LONG, tree->AsOp()->gtOp1, false, TYP_LONG);
Expand All @@ -1633,13 +1628,8 @@ Compiler::fgWalkResult Compiler::fgStress64RsltMulCB(GenTree** pTree, fgWalkData
tree->gtType = TYP_LONG;
*pTree = pComp->gtNewCastNode(TYP_INT, tree, false, TYP_INT);

#ifdef DEBUG
if (pComp->verbose)
{
printf("STRESS_64RSLT_MUL after:\n");
pComp->gtDispTree(*pTree);
}
#endif // DEBUG
JITDUMP("STRESS_64RSLT_MUL after:\n");
DISPTREE(*pTree);

return WALK_SKIP_SUBTREES;
}
Expand Down Expand Up @@ -3031,5 +3021,67 @@ void Compiler::fgDebugCheckNodesUniqueness()
}
}

//------------------------------------------------------------------------------
// fgDebugCheckLoopTable: checks that the loop table is valid.
// - If the method has natural loops, the loop table is not null
// - All basic blocks with loop numbers set have a corresponding loop in the table
// - All basic blocks without a loop number are not in a loop
// - All parents of the loop with the block contain that block
//
void Compiler::fgDebugCheckLoopTable()
{
if (optLoopCount > 0)
{
assert(optLoopTable != nullptr);
}

for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
{
if (optLoopCount == 0)
{
assert(block->bbNatLoopNum == BasicBlock::NOT_IN_LOOP);
continue;
}

// Walk the loop table and find the first loop that contains our block.
// It should be the innermost one.
int loopNum = BasicBlock::NOT_IN_LOOP;
for (int i = optLoopCount - 1; i >= 0; i--)
{
// Ignore removed loops
if (optLoopTable[i].lpFlags & LPFLG_REMOVED)
{
continue;
}
// Does this loop contain our block?
if (optLoopTable[i].lpContains(block))
{
loopNum = i;
break;
}
}

// If there is at least one loop that contains this block...
if (loopNum != BasicBlock::NOT_IN_LOOP)
{
// ...it must be the one pointed to by bbNatLoopNum.
assert(block->bbNatLoopNum == loopNum);
}
else
{
// Otherwise, this block should not point to a loop.
assert(block->bbNatLoopNum == BasicBlock::NOT_IN_LOOP);
}

// All loops that contain the innermost loop with this block must also contain this block.
while (loopNum != BasicBlock::NOT_IN_LOOP)
{
assert(optLoopTable[loopNum].lpContains(block));

loopNum = optLoopTable[loopNum].lpParent;
}
}
}

/*****************************************************************************/
#endif // DEBUG
2 changes: 1 addition & 1 deletion src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12543,7 +12543,7 @@ GenTree* Compiler::gtFoldExpr(GenTree* tree)
fgWalkTreePre(&colon_op2, gtClearColonCond);
}

JITDUMP("\nIdentical GT_COLON trees! ");
JITDUMP("\nIdentical GT_COLON trees!\n");
DISPTREE(op2);

GenTree* op;
Expand Down
6 changes: 5 additions & 1 deletion src/coreclr/jit/optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3949,7 +3949,7 @@ void Compiler::optUnrollLoops()
/* Make sure to update loop table */

/* Use the LPFLG_REMOVED flag and update the bbLoopMask accordingly
* (also make head and bottom NULL - to hit an assert or GPF) */
* (also make head and bottom NULL - to hit an assert or an access violation) */

optLoopTable[lnum].lpFlags |= LPFLG_REMOVED;
optLoopTable[lnum].lpHead = optLoopTable[lnum].lpBottom = nullptr;
Expand Down Expand Up @@ -4576,6 +4576,8 @@ void Compiler::optOptimizeLoops()
printf("\n");
}
}

fgDebugCheckLoopTable();
#endif
optLoopsMarked = true;
}
Expand Down Expand Up @@ -5194,6 +5196,8 @@ void Compiler::optCloneLoops()
printf("\nAfter loop cloning:\n");
fgDispBasicBlocks(/*dumpTrees*/ true);
}

fgDebugCheckLoopTable();
#endif
}

Expand Down

0 comments on commit aa138f7

Please sign in to comment.