Skip to content

Commit

Permalink
Implement a helper to evaluate a node to a condition register
Browse files Browse the repository at this point in the history
In certain evaluators (e.g. *select), a selector value needs to be used
as a condition in ICF. Previously, compare nodes would need to be
evaluated to a GPR, then the GPR would be compared against 0. This was
obviously inefficient, since it's possible to evaluate most comparisons
directly to a condition register in 1-2 instructions. Some evaluators
had special handling for this, but this handling was not uniform and
would frequently miss corner cases.

To address this and allow for better optimization opportunities, a new
helper has been added which evaluates a node to a condition register and
returns the condition which is true if the node was non-zero. For
compare nodes, the comparison will be performed directly into a
condition register. For other types of nodes, the old behaviour of
evaluating the node to a GPR and comparing that against 0 will be used.

Signed-off-by: Ben Thomas <ben@benthomas.ca>
  • Loading branch information
aviansie-ben committed Sep 2, 2020
1 parent f0d0291 commit 5ed32ed
Showing 1 changed file with 138 additions and 0 deletions.
138 changes: 138 additions & 0 deletions compiler/p/codegen/ControlFlowEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,144 @@ CompareCondition evaluateCompareToConditionRegister(
}
}

CompareInfo getCompareInfo(TR::ILOpCode op)
{
TR::DataTypes type = op.expectedChildType(0);

switch (op.getOpCodeValue())
{
case TR::bcmpeq:
case TR::scmpeq:
case TR::icmpeq:
case TR::lcmpeq:
case TR::acmpeq:
case TR::fcmpeq:
case TR::dcmpeq:
return CompareInfo(CompareCondition::eq, type, false, false);

case TR::fcmpequ:
case TR::dcmpequ:
return CompareInfo(CompareCondition::eq, type, false, true);

case TR::bcmpne:
case TR::scmpne:
case TR::icmpne:
case TR::lcmpne:
case TR::acmpne:
case TR::fcmpne:
case TR::dcmpne:
return CompareInfo(CompareCondition::ne, type, false, false);

case TR::fcmpneu:
case TR::dcmpneu:
return CompareInfo(CompareCondition::ne, type, false, true);

case TR::bcmplt:
case TR::scmplt:
case TR::icmplt:
case TR::lcmplt:
case TR::fcmplt:
case TR::dcmplt:
return CompareInfo(CompareCondition::lt, type, false, false);

case TR::bucmplt:
case TR::sucmplt:
case TR::iucmplt:
case TR::lucmplt:
case TR::acmplt:
return CompareInfo(CompareCondition::lt, type, true, false);

case TR::fcmpltu:
case TR::dcmpltu:
return CompareInfo(CompareCondition::lt, type, false, true);

case TR::bcmpge:
case TR::scmpge:
case TR::icmpge:
case TR::lcmpge:
case TR::fcmpge:
case TR::dcmpge:
return CompareInfo(CompareCondition::ge, type, false, false);

case TR::bucmpge:
case TR::sucmpge:
case TR::iucmpge:
case TR::lucmpge:
case TR::acmpge:
return CompareInfo(CompareCondition::ge, type, true, false);

case TR::fcmpgeu:
case TR::dcmpgeu:
return CompareInfo(CompareCondition::ge, type, false, true);

case TR::bcmpgt:
case TR::scmpgt:
case TR::icmpgt:
case TR::lcmpgt:
case TR::fcmpgt:
case TR::dcmpgt:
return CompareInfo(CompareCondition::gt, type, false, false);

case TR::bucmpgt:
case TR::sucmpgt:
case TR::iucmpgt:
case TR::lucmpgt:
case TR::acmpgt:
return CompareInfo(CompareCondition::gt, type, true, false);

case TR::fcmpgtu:
case TR::dcmpgtu:
return CompareInfo(CompareCondition::gt, type, false, true);

case TR::bcmple:
case TR::scmple:
case TR::icmple:
case TR::lcmple:
case TR::fcmple:
case TR::dcmple:
return CompareInfo(CompareCondition::le, type, false, false);

case TR::bucmple:
case TR::sucmple:
case TR::iucmple:
case TR::lucmple:
case TR::acmple:
return CompareInfo(CompareCondition::le, type, true, false);

case TR::fcmpleu:
case TR::dcmpleu:
return CompareInfo(CompareCondition::le, type, false, true);

default:
return CompareInfo(CompareCondition::eq, TR::DataTypes::NoType, false, false);
}
}

CompareCondition evaluateToConditionRegister(TR::Register *condReg, TR::Node *node, TR::Node *condNode, TR::CodeGenerator *cg)
{
static bool disableCondRegEval = feGetEnv("TR_DisableCondRegEval") != NULL;

if (!disableCondRegEval && !condNode->getRegister() && condNode->getReferenceCount() == 1)
{
auto compareInfo = getCompareInfo(condNode->getOpCode());

if (compareInfo.type != TR::DataTypes::NoType &&
performTransformation(cg->comp(), "O^O evaluateToConditionRegister: evaluating n%dn directly to a condition register\n", condNode->getGlobalIndex()))
{
auto cond = evaluateCompareToConditionRegister(condReg, condNode, condNode->getFirstChild(), condNode->getSecondChild(), compareInfo, cg);

cg->decReferenceCount(condNode->getFirstChild());
cg->decReferenceCount(condNode->getSecondChild());
return cond;
}
}

TR::Register *condIntReg = cg->evaluate(condNode);

generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::cmpi4, node, condReg, condIntReg, 0);
return CompareCondition::ne;
}

TR::Register *OMR::Power::TreeEvaluator::ifacmpltEvaluator(TR::Node *node, TR::CodeGenerator *cg)
{
if (cg->comp()->target().is64Bit())
Expand Down

0 comments on commit 5ed32ed

Please sign in to comment.