Refactor unary operation constant folding code
This change splits TIntermConstantUnion::foldUnary into two
functions:
- foldUnaryWithDifferentReturnType:
- Handles constant folding of operations where the return
type has a different number of components compared to the
operand type.
- foldUnaryWithSameReturnType:
- Handles constant folding of unary operations where the
return type is the same as operand type.
BUG=angleproject:913
TEST=angle_unittests, dEQP Tests
(dEQP-GLES3.functional.shaders.constant_expressions.builtin_functions.*)
Change-Id: I675891138d4e17fd2390c03e9f710e0be0b7c7b6
Reviewed-on: https://chromium-review.googlesource.com/283464
Reviewed-by: Olli Etuaho <oetuaho@nvidia.com>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 4a84b24..6c0e907 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -810,7 +810,28 @@
{
return nullptr;
}
- TConstantUnion *constArray = operandConstant->foldUnary(mOp, infoSink);
+
+ TConstantUnion *constArray = nullptr;
+ switch (mOp)
+ {
+ case EOpAny:
+ case EOpAll:
+ case EOpLength:
+ case EOpTranspose:
+ case EOpDeterminant:
+ case EOpInverse:
+ case EOpPackSnorm2x16:
+ case EOpUnpackSnorm2x16:
+ case EOpPackUnorm2x16:
+ case EOpUnpackUnorm2x16:
+ case EOpPackHalf2x16:
+ case EOpUnpackHalf2x16:
+ constArray = operandConstant->foldUnaryWithDifferentReturnType(mOp, infoSink);
+ break;
+ default:
+ constArray = operandConstant->foldUnaryWithSameReturnType(mOp, infoSink);
+ break;
+ }
return CreateFoldedNode(constArray, this);
}
@@ -1178,582 +1199,586 @@
//
// Returns the constant value to keep using or nullptr.
//
-TConstantUnion *TIntermConstantUnion::foldUnary(TOperator op, TInfoSink &infoSink)
+TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator op, TInfoSink &infoSink)
{
- TConstantUnion *operandArray = getUnionArrayPointer();
+ //
+ // Do operations where the return type has a different number of components compared to the operand type.
+ //
+ TConstantUnion *operandArray = getUnionArrayPointer();
+ if (!operandArray)
+ return nullptr;
+
+ size_t objectSize = getType().getObjectSize();
+ TConstantUnion *resultArray = nullptr;
+ switch (op)
+ {
+ case EOpAny:
+ if (getType().getBasicType() == EbtBool)
+ {
+ resultArray = new TConstantUnion();
+ resultArray->setBConst(false);
+ for (size_t i = 0; i < objectSize; i++)
+ {
+ if (operandArray[i].getBConst())
+ {
+ resultArray->setBConst(true);
+ break;
+ }
+ }
+ break;
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return nullptr;
+ }
+
+ case EOpAll:
+ if (getType().getBasicType() == EbtBool)
+ {
+ resultArray = new TConstantUnion();
+ resultArray->setBConst(true);
+ for (size_t i = 0; i < objectSize; i++)
+ {
+ if (!operandArray[i].getBConst())
+ {
+ resultArray->setBConst(false);
+ break;
+ }
+ }
+ break;
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return nullptr;
+ }
+
+ case EOpLength:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ resultArray = new TConstantUnion();
+ resultArray->setFConst(VectorLength(operandArray, objectSize));
+ break;
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return nullptr;
+ }
+
+ case EOpTranspose:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ resultArray = new TConstantUnion[objectSize];
+ angle::Matrix<float> result =
+ GetMatrix(operandArray, getType().getNominalSize(), getType().getSecondarySize()).transpose();
+ SetUnionArrayFromMatrix(result, resultArray);
+ break;
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return nullptr;
+ }
+
+ case EOpDeterminant:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ unsigned int size = getType().getNominalSize();
+ ASSERT(size >= 2 && size <= 4);
+ resultArray = new TConstantUnion();
+ resultArray->setFConst(GetMatrix(operandArray, size).determinant());
+ break;
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return nullptr;
+ }
+
+ case EOpInverse:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ unsigned int size = getType().getNominalSize();
+ ASSERT(size >= 2 && size <= 4);
+ resultArray = new TConstantUnion[objectSize];
+ angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
+ SetUnionArrayFromMatrix(result, resultArray);
+ break;
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return nullptr;
+ }
+
+ case EOpPackSnorm2x16:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ ASSERT(getType().getNominalSize() == 2);
+ resultArray = new TConstantUnion();
+ resultArray->setUConst(gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
+ break;
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return nullptr;
+ }
+
+ case EOpUnpackSnorm2x16:
+ if (getType().getBasicType() == EbtUInt)
+ {
+ resultArray = new TConstantUnion[2];
+ float f1, f2;
+ gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
+ resultArray[0].setFConst(f1);
+ resultArray[1].setFConst(f2);
+ break;
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return nullptr;
+ }
+
+ case EOpPackUnorm2x16:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ ASSERT(getType().getNominalSize() == 2);
+ resultArray = new TConstantUnion();
+ resultArray->setUConst(gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
+ break;
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return nullptr;
+ }
+
+ case EOpUnpackUnorm2x16:
+ if (getType().getBasicType() == EbtUInt)
+ {
+ resultArray = new TConstantUnion[2];
+ float f1, f2;
+ gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
+ resultArray[0].setFConst(f1);
+ resultArray[1].setFConst(f2);
+ break;
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return nullptr;
+ }
+
+ case EOpPackHalf2x16:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ ASSERT(getType().getNominalSize() == 2);
+ resultArray = new TConstantUnion();
+ resultArray->setUConst(gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
+ break;
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return nullptr;
+ }
+
+ case EOpUnpackHalf2x16:
+ if (getType().getBasicType() == EbtUInt)
+ {
+ resultArray = new TConstantUnion[2];
+ float f1, f2;
+ gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
+ resultArray[0].setFConst(f1);
+ resultArray[1].setFConst(f2);
+ break;
+ }
+ else
+ {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return nullptr;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return resultArray;
+}
+
+TConstantUnion *TIntermConstantUnion::foldUnaryWithSameReturnType(TOperator op, TInfoSink &infoSink)
+{
+ //
+ // Do unary operations where the return type is the same as operand type.
+ //
+
+ TConstantUnion *operandArray = getUnionArrayPointer();
if (!operandArray)
return nullptr;
size_t objectSize = getType().getObjectSize();
- if (op == EOpAny || op == EOpAll || op == EOpLength || op == EOpTranspose || op == EOpDeterminant ||
- op == EOpInverse || op == EOpPackSnorm2x16 || op == EOpUnpackSnorm2x16 || op == EOpPackUnorm2x16 ||
- op == EOpUnpackUnorm2x16 || op == EOpPackHalf2x16 || op == EOpUnpackHalf2x16)
+ TConstantUnion *resultArray = new TConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
{
- // Do operations where the return type has a different number of components compared to the operand type.
- TConstantUnion *resultArray = nullptr;
-
- switch (op)
+ switch(op)
{
- case EOpAny:
- if (getType().getBasicType() == EbtBool)
+ case EOpNegative:
+ switch (getType().getBasicType())
{
- resultArray = new TConstantUnion();
- resultArray->setBConst(false);
- for (size_t i = 0; i < objectSize; i++)
- {
- if (operandArray[i].getBConst())
- {
- resultArray->setBConst(true);
- break;
- }
- }
+ case EbtFloat:
+ resultArray[i].setFConst(-operandArray[i].getFConst());
break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
-
- case EOpAll:
- if (getType().getBasicType() == EbtBool)
- {
- resultArray = new TConstantUnion();
- resultArray->setBConst(true);
- for (size_t i = 0; i < objectSize; i++)
- {
- if (!operandArray[i].getBConst())
- {
- resultArray->setBConst(false);
- break;
- }
- }
+ case EbtInt:
+ resultArray[i].setIConst(-operandArray[i].getIConst());
break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
-
- case EOpLength:
- if (getType().getBasicType() == EbtFloat)
- {
- resultArray = new TConstantUnion();
- resultArray->setFConst(VectorLength(operandArray, objectSize));
+ case EbtUInt:
+ resultArray[i].setUConst(static_cast<unsigned int>(
+ -static_cast<int>(operandArray[i].getUConst())));
break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
-
- case EOpTranspose:
- if (getType().getBasicType() == EbtFloat)
- {
- resultArray = new TConstantUnion[objectSize];
- angle::Matrix<float> result =
- GetMatrix(operandArray, getType().getNominalSize(), getType().getSecondarySize()).transpose();
- SetUnionArrayFromMatrix(result, resultArray);
- break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
-
- case EOpDeterminant:
- if (getType().getBasicType() == EbtFloat)
- {
- unsigned int size = getType().getNominalSize();
- ASSERT(size >= 2 && size <= 4);
- resultArray = new TConstantUnion();
- resultArray->setFConst(GetMatrix(operandArray, size).determinant());
- break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
-
- case EOpInverse:
- if (getType().getBasicType() == EbtFloat)
- {
- unsigned int size = getType().getNominalSize();
- ASSERT(size >= 2 && size <= 4);
- resultArray = new TConstantUnion[objectSize];
- angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
- SetUnionArrayFromMatrix(result, resultArray);
- break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
-
- case EOpPackSnorm2x16:
- if (getType().getBasicType() == EbtFloat)
- {
- ASSERT(getType().getNominalSize() == 2);
- resultArray = new TConstantUnion();
- resultArray->setUConst(gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
- break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
-
- case EOpUnpackSnorm2x16:
- if (getType().getBasicType() == EbtUInt)
- {
- resultArray = new TConstantUnion[2];
- float f1, f2;
- gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
- resultArray[0].setFConst(f1);
- resultArray[1].setFConst(f2);
- break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
-
- case EOpPackUnorm2x16:
- if (getType().getBasicType() == EbtFloat)
- {
- ASSERT(getType().getNominalSize() == 2);
- resultArray = new TConstantUnion();
- resultArray->setUConst(gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
- break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
-
- case EOpUnpackUnorm2x16:
- if (getType().getBasicType() == EbtUInt)
- {
- resultArray = new TConstantUnion[2];
- float f1, f2;
- gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
- resultArray[0].setFConst(f1);
- resultArray[1].setFConst(f2);
- break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
-
- case EOpPackHalf2x16:
- if (getType().getBasicType() == EbtFloat)
- {
- ASSERT(getType().getNominalSize() == 2);
- resultArray = new TConstantUnion();
- resultArray->setUConst(gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
- break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
-
- case EOpUnpackHalf2x16:
- if (getType().getBasicType() == EbtUInt)
- {
- resultArray = new TConstantUnion[2];
- float f1, f2;
- gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
- resultArray[0].setFConst(f1);
- resultArray[1].setFConst(f2);
- break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ default:
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
return nullptr;
}
break;
+ case EOpPositive:
+ switch (getType().getBasicType())
+ {
+ case EbtFloat:
+ resultArray[i].setFConst(operandArray[i].getFConst());
+ break;
+ case EbtInt:
+ resultArray[i].setIConst(operandArray[i].getIConst());
+ break;
+ case EbtUInt:
+ resultArray[i].setUConst(static_cast<unsigned int>(
+ static_cast<int>(operandArray[i].getUConst())));
+ break;
+ default:
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return nullptr;
+ }
+ break;
+
+ case EOpLogicalNot:
+ // this code is written for possible future use,
+ // will not get executed currently
+ switch (getType().getBasicType())
+ {
+ case EbtBool:
+ resultArray[i].setBConst(!operandArray[i].getBConst());
+ break;
+ default:
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return nullptr;
+ }
+ break;
+
+ case EOpBitwiseNot:
+ switch (getType().getBasicType())
+ {
+ case EbtInt:
+ resultArray[i].setIConst(~operandArray[i].getIConst());
+ break;
+ case EbtUInt:
+ resultArray[i].setUConst(~operandArray[i].getUConst());
+ break;
+ default:
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return nullptr;
+ }
+ break;
+
+ case EOpRadians:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
+ break;
+ }
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return nullptr;
+
+ case EOpDegrees:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
+ break;
+ }
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return nullptr;
+
+ case EOpSin:
+ if (!foldFloatTypeUnary(operandArray[i], &sinf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpCos:
+ if (!foldFloatTypeUnary(operandArray[i], &cosf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpTan:
+ if (!foldFloatTypeUnary(operandArray[i], &tanf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpAsin:
+ // For asin(x), results are undefined if |x| > 1, we are choosing to set result to 0.
+ if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
+ else if (!foldFloatTypeUnary(operandArray[i], &asinf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpAcos:
+ // For acos(x), results are undefined if |x| > 1, we are choosing to set result to 0.
+ if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
+ else if (!foldFloatTypeUnary(operandArray[i], &acosf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpAtan:
+ if (!foldFloatTypeUnary(operandArray[i], &atanf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpSinh:
+ if (!foldFloatTypeUnary(operandArray[i], &sinhf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpCosh:
+ if (!foldFloatTypeUnary(operandArray[i], &coshf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpTanh:
+ if (!foldFloatTypeUnary(operandArray[i], &tanhf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpAsinh:
+ if (!foldFloatTypeUnary(operandArray[i], &asinhf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpAcosh:
+ // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
+ if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 1.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
+ else if (!foldFloatTypeUnary(operandArray[i], &acoshf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpAtanh:
+ // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to 0.
+ if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) >= 1.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
+ else if (!foldFloatTypeUnary(operandArray[i], &atanhf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpAbs:
+ switch (getType().getBasicType())
+ {
+ case EbtFloat:
+ resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
+ break;
+ case EbtInt:
+ resultArray[i].setIConst(abs(operandArray[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 = operandArray[i].getFConst();
+ float fResult = 0.0f;
+ if (fConst > 0.0f)
+ fResult = 1.0f;
+ else if (fConst < 0.0f)
+ fResult = -1.0f;
+ resultArray[i].setFConst(fResult);
+ }
+ break;
+ case EbtInt:
+ {
+ int iConst = operandArray[i].getIConst();
+ int iResult = 0;
+ if (iConst > 0)
+ iResult = 1;
+ else if (iConst < 0)
+ iResult = -1;
+ resultArray[i].setIConst(iResult);
+ }
+ break;
+ default:
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return nullptr;
+ }
+ break;
+
+ case EOpFloor:
+ if (!foldFloatTypeUnary(operandArray[i], &floorf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpTrunc:
+ if (!foldFloatTypeUnary(operandArray[i], &truncf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpRound:
+ if (!foldFloatTypeUnary(operandArray[i], &roundf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpRoundEven:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ float x = operandArray[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);
+ resultArray[i].setFConst(result);
+ break;
+ }
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return nullptr;
+
+ case EOpCeil:
+ if (!foldFloatTypeUnary(operandArray[i], &ceilf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpFract:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ float x = operandArray[i].getFConst();
+ resultArray[i].setFConst(x - floorf(x));
+ break;
+ }
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return nullptr;
+
+ case EOpExp:
+ if (!foldFloatTypeUnary(operandArray[i], &expf, infoSink, &resultArray[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 && operandArray[i].getFConst() <= 0.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
+ else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpExp2:
+ if (!foldFloatTypeUnary(operandArray[i], &exp2f, infoSink, &resultArray[i]))
+ return nullptr;
+ break;
+
+ case EOpLog2:
+ // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
+ // And log2f is not available on some plarforms like old android, so just using log(x)/log(2) here.
+ if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
+ else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
+ return nullptr;
+ else
+ resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
+ break;
+
+ case EOpSqrt:
+ // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
+ if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 0.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
+ else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[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 && operandArray[i].getFConst() <= 0.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
+ else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[i]))
+ return nullptr;
+ else
+ resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
+ break;
+
+ case EOpVectorLogicalNot:
+ if (getType().getBasicType() == EbtBool)
+ {
+ resultArray[i].setBConst(!operandArray[i].getBConst());
+ break;
+ }
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return nullptr;
+
+ case EOpNormalize:
+ if (getType().getBasicType() == EbtFloat)
+ {
+ float x = operandArray[i].getFConst();
+ float length = VectorLength(operandArray, objectSize);
+ if (length)
+ resultArray[i].setFConst(x / length);
+ else
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink,
+ &resultArray[i]);
+ break;
+ }
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return nullptr;
+
default:
- break;
+ return nullptr;
}
-
- return resultArray;
}
- else
- {
- //
- // Do unary operations where the return type is the same as operand type.
- //
- TConstantUnion *resultArray = new TConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- {
- switch(op)
- {
- case EOpNegative:
- switch (getType().getBasicType())
- {
- case EbtFloat:
- resultArray[i].setFConst(-operandArray[i].getFConst());
- break;
- case EbtInt:
- resultArray[i].setIConst(-operandArray[i].getIConst());
- break;
- case EbtUInt:
- resultArray[i].setUConst(static_cast<unsigned int>(
- -static_cast<int>(operandArray[i].getUConst())));
- break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- }
- break;
- case EOpPositive:
- switch (getType().getBasicType())
- {
- case EbtFloat:
- resultArray[i].setFConst(operandArray[i].getFConst());
- break;
- case EbtInt:
- resultArray[i].setIConst(operandArray[i].getIConst());
- break;
- case EbtUInt:
- resultArray[i].setUConst(static_cast<unsigned int>(
- static_cast<int>(operandArray[i].getUConst())));
- break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- }
- break;
-
- case EOpLogicalNot:
- // this code is written for possible future use,
- // will not get executed currently
- switch (getType().getBasicType())
- {
- case EbtBool:
- resultArray[i].setBConst(!operandArray[i].getBConst());
- break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- }
- break;
-
- case EOpBitwiseNot:
- switch (getType().getBasicType())
- {
- case EbtInt:
- resultArray[i].setIConst(~operandArray[i].getIConst());
- break;
- case EbtUInt:
- resultArray[i].setUConst(~operandArray[i].getUConst());
- break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- }
- break;
-
- case EOpRadians:
- if (getType().getBasicType() == EbtFloat)
- {
- resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
- break;
- }
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
-
- case EOpDegrees:
- if (getType().getBasicType() == EbtFloat)
- {
- resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
- break;
- }
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
-
- case EOpSin:
- if (!foldFloatTypeUnary(operandArray[i], &sinf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpCos:
- if (!foldFloatTypeUnary(operandArray[i], &cosf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpTan:
- if (!foldFloatTypeUnary(operandArray[i], &tanf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpAsin:
- // For asin(x), results are undefined if |x| > 1, we are choosing to set result to 0.
- if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &asinf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpAcos:
- // For acos(x), results are undefined if |x| > 1, we are choosing to set result to 0.
- if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &acosf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpAtan:
- if (!foldFloatTypeUnary(operandArray[i], &atanf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpSinh:
- if (!foldFloatTypeUnary(operandArray[i], &sinhf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpCosh:
- if (!foldFloatTypeUnary(operandArray[i], &coshf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpTanh:
- if (!foldFloatTypeUnary(operandArray[i], &tanhf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpAsinh:
- if (!foldFloatTypeUnary(operandArray[i], &asinhf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpAcosh:
- // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
- if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 1.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &acoshf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpAtanh:
- // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to 0.
- if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) >= 1.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &atanhf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpAbs:
- switch (getType().getBasicType())
- {
- case EbtFloat:
- resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
- break;
- case EbtInt:
- resultArray[i].setIConst(abs(operandArray[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 = operandArray[i].getFConst();
- float fResult = 0.0f;
- if (fConst > 0.0f)
- fResult = 1.0f;
- else if (fConst < 0.0f)
- fResult = -1.0f;
- resultArray[i].setFConst(fResult);
- }
- break;
- case EbtInt:
- {
- int iConst = operandArray[i].getIConst();
- int iResult = 0;
- if (iConst > 0)
- iResult = 1;
- else if (iConst < 0)
- iResult = -1;
- resultArray[i].setIConst(iResult);
- }
- break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- }
- break;
-
- case EOpFloor:
- if (!foldFloatTypeUnary(operandArray[i], &floorf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpTrunc:
- if (!foldFloatTypeUnary(operandArray[i], &truncf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpRound:
- if (!foldFloatTypeUnary(operandArray[i], &roundf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpRoundEven:
- if (getType().getBasicType() == EbtFloat)
- {
- float x = operandArray[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);
- resultArray[i].setFConst(result);
- break;
- }
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
-
- case EOpCeil:
- if (!foldFloatTypeUnary(operandArray[i], &ceilf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpFract:
- if (getType().getBasicType() == EbtFloat)
- {
- float x = operandArray[i].getFConst();
- resultArray[i].setFConst(x - floorf(x));
- break;
- }
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
-
- case EOpExp:
- if (!foldFloatTypeUnary(operandArray[i], &expf, infoSink, &resultArray[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 && operandArray[i].getFConst() <= 0.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpExp2:
- if (!foldFloatTypeUnary(operandArray[i], &exp2f, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpLog2:
- // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
- // And log2f is not available on some plarforms like old android, so just using log(x)/log(2) here.
- if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
- return nullptr;
- else
- resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
- break;
-
- case EOpSqrt:
- // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
- if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 0.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[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 && operandArray[i].getFConst() <= 0.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[i]))
- return nullptr;
- else
- resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
- break;
-
- case EOpVectorLogicalNot:
- if (getType().getBasicType() == EbtBool)
- {
- resultArray[i].setBConst(!operandArray[i].getBConst());
- break;
- }
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
-
- case EOpNormalize:
- if (getType().getBasicType() == EbtFloat)
- {
- float x = operandArray[i].getFConst();
- float length = VectorLength(operandArray, objectSize);
- if (length)
- resultArray[i].setFConst(x / length);
- else
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink,
- &resultArray[i]);
- break;
- }
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
-
- default:
- return nullptr;
- }
- }
- return resultArray;
- }
+ return resultArray;
}
bool TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion ¶meter, FloatTypeUnaryFunc builtinFunc,