Skip to content

Commit

Permalink
Improve selection criteria for IndVarEliminination
Browse files Browse the repository at this point in the history
Add post dominance check for primary induction variable(PIV) and derived
induction variable(DIV) to improve selection criteria for
`redundantInductionVarElimination` optimization.

Previously when checking whether or not to replace a DIV with PIV one
of the things we did was count the number of increments. We replaced DIV
with PIV only if both had equal number of increments. However, when
counting the increments we did not check if those increments were in the
same block. Because of this we would sometimes replace a DIV even if it
was in a different block than the PIV it was being replaced with. This
resulted in addition of extra add and load instructions to compensate
for the  different block locations. Addition of those extra add and load
instructions resulted in a performance regression.

To combat this regression, we have added domination relationship check
for PIV and DIV. DIV will be replaced only if every increment of the DIV
being replaced is post dominated by at least one PIV increment. This
helps ensure we don't replace a DIV which needs extra instructions to
load PIV.

This change is not enabled on x platform as the complex addressing modes
mitigate the complexity of the expression used to eliminate the derived
induction variable.

The post dominate check can be disabled by setting
`TR_DisableIVEPostDominatorsCheck` environment variable

Signed-off-by: Shubham Verma <shubhamv.sv@gmail.com>
  • Loading branch information
VermaSh committed Nov 10, 2020
1 parent e5f5e20 commit ce53d62
Showing 1 changed file with 48 additions and 5 deletions.
53 changes: 48 additions & 5 deletions compiler/optimizer/LoopCanonicalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1964,7 +1964,17 @@ void TR_LoopCanonicalizer::eliminateRedundantInductionVariablesFromLoop(TR_Regio
//else
primaryIncr = (int64_t) primaryInductionVariable->getIncrement();

static bool disableIVEPostDominatorsCheck = (comp()->cg()->hasComplexAddressingMode()
|| NULL != feGetEnv("TR_DisableIVEPostDominatorsCheck"));
TR_PostDominators *postDominators;
if (!disableIVEPostDominatorsCheck)
{
TR_PostDominators computedPostDominators(comp());
postDominators = &computedPostDominators;
}

//ListIterator<TR_InductionVariable> derivedIt(&derivedInductionVariables);
// Iterate over all derived induction variables and check if they can be replaced
TR_BasicInductionVariable *nextIndVar;
for (nextIndVar = bivIterator.getFirst(); nextIndVar != NULL;)
{
Expand Down Expand Up @@ -2011,13 +2021,11 @@ void TR_LoopCanonicalizer::eliminateRedundantInductionVariablesFromLoop(TR_Regio
TR_ScratchList<TR::Block> derivedInductionVarIncrementBlocks(trMemory());
TR_ScratchList<TR::Block> primaryInductionVarIncrementBlocks(trMemory());
//comp()->incVisitCount();
bool incrementsInLockStep = incrementedInLockStep(naturalLoop, derivedInductionVar, symRefInCompare, nextIndVarIncr, primaryIncr, &derivedInductionVarIncrementBlocks, &primaryInductionVarIncrementBlocks);
if (incrementsInLockStep &&
bool performElimination = incrementedInLockStep(naturalLoop, derivedInductionVar, symRefInCompare, nextIndVarIncr, primaryIncr, &derivedInductionVarIncrementBlocks, &primaryInductionVarIncrementBlocks);
if (performElimination &&
(!derivedInductionVarIncrementBlocks.isEmpty() ||
!primaryInductionVarIncrementBlocks.isEmpty()))
{
incrementsInLockStep = checkIfOrderOfBlocksIsKnown(naturalLoop, entryBlock, loopTestBlock, &derivedInductionVarIncrementBlocks, &primaryInductionVarIncrementBlocks, _primaryIncrementedFirst);
//if (_primaryIncrementedFirst == 1)
// {
// _primaryInductionIncrementBlock = entryBlock;
// _derivedInductionIncrementBlock = loopTestBlock;
Expand All @@ -2027,9 +2035,42 @@ void TR_LoopCanonicalizer::eliminateRedundantInductionVariablesFromLoop(TR_Regio
// _primaryInductionIncrementBlock = loopTestBlock;
// _derivedInductionIncrementBlock = entryBlock;
// }
if (!disableIVEPostDominatorsCheck)
{
if (trace())
traceMsg(comp(), "Checking post dominator relationship between primary and derived induction variable increments");

bool existsAtLeastOnePostDom = false;
ListIterator<TR::Block> primaryIndVarIncrIt(&primaryInductionVarIncrementBlocks);
ListIterator<TR::Block> derivedIndVarIncrIt(&derivedInductionVarIncrementBlocks);
for (TR::Block *primaryIndVarIncr = primaryIndVarIncrIt.getFirst();
performElimination && NULL != primaryIndVarIncr;
primaryIndVarIncr = primaryIndVarIncrIt.getNext())
{
/* Check if all increments of derived induction variable are
* post-dominated by an increment of the primary variable.
* We go ahead with the elimination only if they are.
*/
existsAtLeastOnePostDom = false;

for (TR::Block *derivedIndVarIncr = derivedIndVarIncrIt.getFirst();
!existsAtLeastOnePostDom && NULL != derivedIndVarIncr;
derivedIndVarIncr = derivedIndVarIncrIt.getNext())
{
if (postDominators->dominates(primaryIndVarIncr, derivedIndVarIncr))
existsAtLeastOnePostDom = true;
}

if (!existsAtLeastOnePostDom)
performElimination = false;
}
}

if (performElimination)
performElimination = checkIfOrderOfBlocksIsKnown(naturalLoop, entryBlock, loopTestBlock, &derivedInductionVarIncrementBlocks, &primaryInductionVarIncrementBlocks, _primaryIncrementedFirst);
}

if (incrementsInLockStep)
if (performElimination)
{
_symRefBeingReplaced = derivedInductionVar;
alteredCode = true;
Expand All @@ -2053,6 +2094,8 @@ void TR_LoopCanonicalizer::eliminateRedundantInductionVariablesFromLoop(TR_Regio

_symRefBeingReplaced = NULL;
}
else
performTransformation(comp(), "%sSkipping induction variable elimination for %d.\n", OPT_DETAILS, derivedInductionVar->getReferenceNumber());
//else
// derivedInductionVariables.remove(nextIndVar);
}
Expand Down

0 comments on commit ce53d62

Please sign in to comment.