Avoid precision emulation overhead on unused values
Avoid rounding intermediate values when the intermediate value is not
consumed. For example, this avoids rounding the return value of
assignment, so "b = a;" becomes "b = frm(a);" instead of "frm(b =
frm(a))".
BUG=angle:874
TEST=compiler_tests
Change-Id: Ifcdb53fb1d07a2cf24e429cc237c2d0262dc32f8
Reviewed-on: https://chromium-review.googlesource.com/241852
Reviewed-by: Olli Etuaho <oetuaho@nvidia.com>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/EmulatePrecision.cpp b/src/compiler/translator/EmulatePrecision.cpp
index 9f77261..3729b0e 100644
--- a/src/compiler/translator/EmulatePrecision.cpp
+++ b/src/compiler/translator/EmulatePrecision.cpp
@@ -228,6 +228,28 @@
return callNode;
}
+bool parentUsesResult(TIntermNode* parent, TIntermNode* node)
+{
+ if (!parent)
+ {
+ return false;
+ }
+
+ TIntermAggregate *aggParent = parent->getAsAggregate();
+ // If the parent's op is EOpSequence, the result is not assigned anywhere,
+ // so rounding it is not needed. In particular, this can avoid a lot of
+ // unnecessary rounding of unused return values of assignment.
+ if (aggParent && aggParent->getOp() == EOpSequence)
+ {
+ return false;
+ }
+ if (aggParent && aggParent->getOp() == EOpComma && (aggParent->getSequence()->back() != node))
+ {
+ return false;
+ }
+ return true;
+}
+
} // namespace anonymous
EmulatePrecision::EmulatePrecision()
@@ -293,6 +315,10 @@
case EOpMatrixTimesMatrix:
{
TIntermNode *parent = getParentNode();
+ if (!parentUsesResult(parent, node))
+ {
+ break;
+ }
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
break;
@@ -395,8 +421,11 @@
bool inFunctionMap = (mFunctionMap.find(node->getName()) != mFunctionMap.end());
if (visit == PreVisit)
{
- if (canRoundFloat(node->getType()) && !inFunctionMap) {
- TIntermNode *parent = getParentNode();
+ // User-defined function return values are not rounded, this relies on that
+ // calculations producing the value were rounded.
+ TIntermNode *parent = getParentNode();
+ if (canRoundFloat(node->getType()) && !inFunctionMap && parentUsesResult(parent, node))
+ {
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
}
@@ -437,9 +466,9 @@
break;
}
default:
- if (canRoundFloat(node->getType()) && visit == PreVisit)
+ TIntermNode *parent = getParentNode();
+ if (canRoundFloat(node->getType()) && visit == PreVisit && parentUsesResult(parent, node))
{
- TIntermNode *parent = getParentNode();
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
}