Support constant folding of exponential built-ins

This change adds constant folding support for unary exponential
built-ins - exp, log, exp2, log2, sqrt and inversesqrt.

BUG=angleproject:913
TEST= dEQP tests
dEQP-GLES3.functional.shaders.constant_expressions.builtin_functions.exponential*
(48 out of 56 tests started passing with this change)

Change-Id: Ie7808cd57d6ed7598c642a9a0940b8f5bd293741
Reviewed-on: https://chromium-review.googlesource.com/265393
Reviewed-by: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index c7fea1c..896bb02 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -1284,6 +1284,52 @@
                     return nullptr;
                 break;
 
+              case EOpExp:
+                if (!foldFloatTypeUnary(unionArray[i], static_cast<FloatTypeUnaryFunc>(&std::exp), infoSink, &tempConstArray[i]))
+                  return nullptr;
+                break;
+
+              case EOpLog:
+                // For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
+                if (getType().getBasicType() == EbtFloat && unionArray[i].getFConst() <= 0.0f)
+                    tempConstArray[i].setFConst(0.0f);
+                else if (!foldFloatTypeUnary(unionArray[i], static_cast<FloatTypeUnaryFunc>(&std::log), infoSink, &tempConstArray[i]))
+                    return nullptr;
+                break;
+
+              case EOpExp2:
+                if (!foldFloatTypeUnary(unionArray[i], static_cast<FloatTypeUnaryFunc>(&std::exp2), infoSink, &tempConstArray[i]))
+                    return nullptr;
+                break;
+
+              case EOpLog2:
+                // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
+                if (getType().getBasicType() == EbtFloat && unionArray[i].getFConst() <= 0.0f)
+                    tempConstArray[i].setFConst(0.0f);
+                else if (!foldFloatTypeUnary(unionArray[i], static_cast<FloatTypeUnaryFunc>(&std::log2), infoSink, &tempConstArray[i]))
+                    return nullptr;
+                break;
+
+              case EOpSqrt:
+                // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
+                if (getType().getBasicType() == EbtFloat && unionArray[i].getFConst() < 0.0f)
+                    tempConstArray[i].setFConst(0.0f);
+                else if (!foldFloatTypeUnary(unionArray[i], static_cast<FloatTypeUnaryFunc>(&std::sqrt), infoSink, &tempConstArray[i]))
+                    return nullptr;
+                break;
+
+              case EOpInverseSqrt:
+                // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
+                // so getting the square root first using builtin function sqrt() and then taking its inverse.
+                // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set result to 0.
+                if (getType().getBasicType() == EbtFloat && unionArray[i].getFConst() <= 0.0f)
+                    tempConstArray[i].setFConst(0.0f);
+                else if (!foldFloatTypeUnary(unionArray[i], static_cast<FloatTypeUnaryFunc>(&std::sqrt), infoSink, &tempConstArray[i]))
+                    return nullptr;
+                else
+                    tempConstArray[i].setFConst(1.0f / tempConstArray[i].getFConst());
+                break;
+
               default:
                 return NULL;
             }