Support constant folding of common built-ins
This change adds constant folding support for unary common built-ins:
abs, sign, floor, trunc, round, roundEven, ceil and fract.
BUG=angleproject:913
TEST= dEQP tests
dEQP-GLES3.functional.shaders.constant_expressions.builtin_functions.common*
(80 out of 210 tests started passing with this change)
Change-Id: I46312fec43084601d4fca8195ddaaa5292f1c02a
Reviewed-on: https://chromium-review.googlesource.com/265967
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 49f688d..4a60dc5 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -11,6 +11,7 @@
#include <float.h>
#include <limits.h>
#include <math.h>
+#include <stdlib.h>
#include <algorithm>
#include "compiler/translator/HashNames.h"
@@ -1284,6 +1285,106 @@
return nullptr;
break;
+ case EOpAbs:
+ switch (getType().getBasicType())
+ {
+ case EbtFloat:
+ tempConstArray[i].setFConst(fabsf(unionArray[i].getFConst()));
+ break;
+ case EbtInt:
+ tempConstArray[i].setIConst(abs(unionArray[i].getIConst()));
+ break;
+ default:
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return nullptr;
+ }
+ break;
+
+ case EOpSign:
+ switch (getType().getBasicType())
+ {
+ case EbtFloat:
+ {
+ float fConst = unionArray[i].getFConst();
+ float fResult = 0.0f;
+ if (fConst > 0.0f)
+ fResult = 1.0f;
+ else if (fConst < 0.0f)
+ fResult = -1.0f;
+ tempConstArray[i].setFConst(fResult);
+ }
+ break;
+ case EbtInt:
+ {
+ int iConst = unionArray[i].getIConst();
+ int iResult = 0;
+ if (iConst > 0)
+ iResult = 1;
+ else if (iConst < 0)
+ iResult = -1;
+ tempConstArray[i].setIConst(iResult);
+ }
+ break;
+ default:
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return nullptr;
+ }
+ break;
+
+ case EOpFloor:
+ if (!foldFloatTypeUnary(unionArray[i], &floorf, infoSink, &tempConstArray[i]))
+ return nullptr;
+ break;
+
+ case EOpTrunc:
+ if (!foldFloatTypeUnary(unionArray[i], &truncf, infoSink, &tempConstArray[i]))
+ return nullptr;
+ break;
+
+ case EOpRound:
+ if (!foldFloatTypeUnary(unionArray[i], &roundf, infoSink, &tempConstArray[i]))
+ return nullptr;
+ break;
+
+ case EOpRoundEven:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ float x = unionArray[i].getFConst();
+ float result;
+ float fractPart = modff(x, &result);
+ if (fabsf(fractPart) == 0.5f)
+ result = 2.0f * roundf(x / 2.0f);
+ else
+ result = roundf(x);
+ tempConstArray[i].setFConst(result);
+ break;
+ }
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return nullptr;
+
+ case EOpCeil:
+ if (!foldFloatTypeUnary(unionArray[i], &ceilf, infoSink, &tempConstArray[i]))
+ return nullptr;
+ break;
+
+ case EOpFract:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ float x = unionArray[i].getFConst();
+ tempConstArray[i].setFConst(x - floorf(x));
+ break;
+ }
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return nullptr;
+
default:
return NULL;
}