Commit ab2b9a23 by Arun Patole Committed by Jamie Madill

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/283464Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent cdfa8f50
...@@ -810,7 +810,28 @@ TIntermTyped *TIntermUnary::fold(TInfoSink &infoSink) ...@@ -810,7 +810,28 @@ TIntermTyped *TIntermUnary::fold(TInfoSink &infoSink)
{ {
return nullptr; 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); return CreateFoldedNode(constArray, this);
} }
...@@ -1178,582 +1199,586 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, TIntermConstantUn ...@@ -1178,582 +1199,586 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, TIntermConstantUn
// //
// Returns the constant value to keep using or nullptr. // 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) if (!operandArray)
return nullptr; return nullptr;
size_t objectSize = getType().getObjectSize(); size_t objectSize = getType().getObjectSize();
TConstantUnion *resultArray = nullptr;
if (op == EOpAny || op == EOpAll || op == EOpLength || op == EOpTranspose || op == EOpDeterminant || switch (op)
op == EOpInverse || op == EOpPackSnorm2x16 || op == EOpUnpackSnorm2x16 || op == EOpPackUnorm2x16 ||
op == EOpUnpackUnorm2x16 || op == EOpPackHalf2x16 || op == EOpUnpackHalf2x16)
{ {
// Do operations where the return type has a different number of components compared to the operand type. case EOpAny:
TConstantUnion *resultArray = nullptr; if (getType().getBasicType() == EbtBool)
switch (op)
{ {
case EOpAny: resultArray = new TConstantUnion();
if (getType().getBasicType() == EbtBool) resultArray->setBConst(false);
for (size_t i = 0; i < objectSize; i++)
{ {
resultArray = new TConstantUnion(); if (operandArray[i].getBConst())
resultArray->setBConst(false);
for (size_t i = 0; i < objectSize; i++)
{ {
if (operandArray[i].getBConst()) resultArray->setBConst(true);
{ break;
resultArray->setBConst(true);
break;
}
} }
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
} }
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpAll: case EOpAll:
if (getType().getBasicType() == EbtBool) if (getType().getBasicType() == EbtBool)
{
resultArray = new TConstantUnion();
resultArray->setBConst(true);
for (size_t i = 0; i < objectSize; i++)
{ {
resultArray = new TConstantUnion(); if (!operandArray[i].getBConst())
resultArray->setBConst(true);
for (size_t i = 0; i < objectSize; i++)
{ {
if (!operandArray[i].getBConst()) resultArray->setBConst(false);
{ break;
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;
} }
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpTranspose: case EOpLength:
if (getType().getBasicType() == EbtFloat) if (getType().getBasicType() == EbtFloat)
{ {
resultArray = new TConstantUnion[objectSize]; resultArray = new TConstantUnion();
angle::Matrix<float> result = resultArray->setFConst(VectorLength(operandArray, objectSize));
GetMatrix(operandArray, getType().getNominalSize(), getType().getSecondarySize()).transpose(); break;
SetUnionArrayFromMatrix(result, resultArray); }
break; else
} {
else infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
{ return nullptr;
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); }
return nullptr;
}
case EOpDeterminant: case EOpTranspose:
if (getType().getBasicType() == EbtFloat) if (getType().getBasicType() == EbtFloat)
{ {
unsigned int size = getType().getNominalSize(); resultArray = new TConstantUnion[objectSize];
ASSERT(size >= 2 && size <= 4); angle::Matrix<float> result =
resultArray = new TConstantUnion(); GetMatrix(operandArray, getType().getNominalSize(), getType().getSecondarySize()).transpose();
resultArray->setFConst(GetMatrix(operandArray, size).determinant()); SetUnionArrayFromMatrix(result, resultArray);
break; break;
} }
else else
{ {
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr; return nullptr;
} }
case EOpInverse: case EOpDeterminant:
if (getType().getBasicType() == EbtFloat) if (getType().getBasicType() == EbtFloat)
{ {
unsigned int size = getType().getNominalSize(); unsigned int size = getType().getNominalSize();
ASSERT(size >= 2 && size <= 4); ASSERT(size >= 2 && size <= 4);
resultArray = new TConstantUnion[objectSize]; resultArray = new TConstantUnion();
angle::Matrix<float> result = GetMatrix(operandArray, size).inverse(); resultArray->setFConst(GetMatrix(operandArray, size).determinant());
SetUnionArrayFromMatrix(result, resultArray); break;
break; }
} else
else {
{ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); return nullptr;
return nullptr; }
}
case EOpPackSnorm2x16: case EOpInverse:
if (getType().getBasicType() == EbtFloat) if (getType().getBasicType() == EbtFloat)
{ {
ASSERT(getType().getNominalSize() == 2); unsigned int size = getType().getNominalSize();
resultArray = new TConstantUnion(); ASSERT(size >= 2 && size <= 4);
resultArray->setUConst(gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); resultArray = new TConstantUnion[objectSize];
break; angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
} SetUnionArrayFromMatrix(result, resultArray);
else break;
{ }
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); else
return nullptr; {
} infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpUnpackSnorm2x16: case EOpPackSnorm2x16:
if (getType().getBasicType() == EbtUInt) if (getType().getBasicType() == EbtFloat)
{ {
resultArray = new TConstantUnion[2]; ASSERT(getType().getNominalSize() == 2);
float f1, f2; resultArray = new TConstantUnion();
gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2); resultArray->setUConst(gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
resultArray[0].setFConst(f1); break;
resultArray[1].setFConst(f2); }
break; else
} {
else infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
{ return nullptr;
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); }
return nullptr;
}
case EOpPackUnorm2x16: case EOpUnpackSnorm2x16:
if (getType().getBasicType() == EbtFloat) if (getType().getBasicType() == EbtUInt)
{ {
ASSERT(getType().getNominalSize() == 2); resultArray = new TConstantUnion[2];
resultArray = new TConstantUnion(); float f1, f2;
resultArray->setUConst(gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
break; resultArray[0].setFConst(f1);
} resultArray[1].setFConst(f2);
else break;
{ }
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); else
return nullptr; {
} infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpUnpackUnorm2x16: case EOpPackUnorm2x16:
if (getType().getBasicType() == EbtUInt) if (getType().getBasicType() == EbtFloat)
{ {
resultArray = new TConstantUnion[2]; ASSERT(getType().getNominalSize() == 2);
float f1, f2; resultArray = new TConstantUnion();
gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2); resultArray->setUConst(gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
resultArray[0].setFConst(f1); break;
resultArray[1].setFConst(f2); }
break; else
} {
else infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
{ return nullptr;
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); }
return nullptr;
}
case EOpPackHalf2x16: case EOpUnpackUnorm2x16:
if (getType().getBasicType() == EbtFloat) if (getType().getBasicType() == EbtUInt)
{ {
ASSERT(getType().getNominalSize() == 2); resultArray = new TConstantUnion[2];
resultArray = new TConstantUnion(); float f1, f2;
resultArray->setUConst(gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst())); gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
break; resultArray[0].setFConst(f1);
} resultArray[1].setFConst(f2);
else break;
{ }
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); else
return nullptr; {
} infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpUnpackHalf2x16: case EOpPackHalf2x16:
if (getType().getBasicType() == EbtUInt) if (getType().getBasicType() == EbtFloat)
{ {
resultArray = new TConstantUnion[2]; ASSERT(getType().getNominalSize() == 2);
float f1, f2; resultArray = new TConstantUnion();
gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2); resultArray->setUConst(gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
resultArray[0].setFConst(f1);
resultArray[1].setFConst(f2);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
break; break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
default: 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; break;
} }
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
break;
return resultArray; default:
break;
} }
else
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();
TConstantUnion *resultArray = new TConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
{ {
// switch(op)
// 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 EOpNegative: case EbtFloat:
switch (getType().getBasicType()) resultArray[i].setFConst(-operandArray[i].getFConst());
{
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; break;
case EbtInt:
case EOpPositive: resultArray[i].setIConst(-operandArray[i].getIConst());
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; break;
case EbtUInt:
case EOpLogicalNot: resultArray[i].setUConst(static_cast<unsigned int>(
// this code is written for possible future use, -static_cast<int>(operandArray[i].getUConst())));
// 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; break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpBitwiseNot: case EOpPositive:
switch (getType().getBasicType()) switch (getType().getBasicType())
{ {
case EbtInt: case EbtFloat:
resultArray[i].setIConst(~operandArray[i].getIConst()); resultArray[i].setFConst(operandArray[i].getFConst());
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; break;
case EbtInt:
case EOpRadians: resultArray[i].setIConst(operandArray[i].getIConst());
if (getType().getBasicType() == EbtFloat) break;
{ case EbtUInt:
resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst()); resultArray[i].setUConst(static_cast<unsigned int>(
break; static_cast<int>(operandArray[i].getUConst())));
} break;
default:
infoSink.info.message( infoSink.info.message(
EPrefixInternalError, getLine(), EPrefixInternalError, getLine(),
"Unary operation not folded into constant"); "Unary operation not folded into constant");
return nullptr; return nullptr;
}
break;
case EOpDegrees: case EOpLogicalNot:
if (getType().getBasicType() == EbtFloat) // this code is written for possible future use,
{ // will not get executed currently
resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst()); switch (getType().getBasicType())
break; {
} case EbtBool:
resultArray[i].setBConst(!operandArray[i].getBConst());
break;
default:
infoSink.info.message( infoSink.info.message(
EPrefixInternalError, getLine(), EPrefixInternalError, getLine(),
"Unary operation not folded into constant"); "Unary operation not folded into constant");
return nullptr; return nullptr;
}
break;
case EOpSin: case EOpBitwiseNot:
if (!foldFloatTypeUnary(operandArray[i], &sinf, infoSink, &resultArray[i])) switch (getType().getBasicType())
return nullptr; {
case EbtInt:
resultArray[i].setIConst(~operandArray[i].getIConst());
break; break;
case EbtUInt:
case EOpCos: resultArray[i].setUConst(~operandArray[i].getUConst());
if (!foldFloatTypeUnary(operandArray[i], &cosf, infoSink, &resultArray[i]))
return nullptr;
break; break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpTan: case EOpRadians:
if (!foldFloatTypeUnary(operandArray[i], &tanf, infoSink, &resultArray[i])) if (getType().getBasicType() == EbtFloat)
return nullptr; {
resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
break; break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpAsin: case EOpDegrees:
// For asin(x), results are undefined if |x| > 1, we are choosing to set result to 0. if (getType().getBasicType() == EbtFloat)
if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f) {
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
else if (!foldFloatTypeUnary(operandArray[i], &asinf, infoSink, &resultArray[i]))
return nullptr;
break; break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpAcos: case EOpSin:
// For acos(x), results are undefined if |x| > 1, we are choosing to set result to 0. if (!foldFloatTypeUnary(operandArray[i], &sinf, infoSink, &resultArray[i]))
if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f) return nullptr;
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); break;
else if (!foldFloatTypeUnary(operandArray[i], &acosf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAtan: case EOpCos:
if (!foldFloatTypeUnary(operandArray[i], &atanf, infoSink, &resultArray[i])) if (!foldFloatTypeUnary(operandArray[i], &cosf, infoSink, &resultArray[i]))
return nullptr; return nullptr;
break; break;
case EOpSinh: case EOpTan:
if (!foldFloatTypeUnary(operandArray[i], &sinhf, infoSink, &resultArray[i])) if (!foldFloatTypeUnary(operandArray[i], &tanf, infoSink, &resultArray[i]))
return nullptr; return nullptr;
break; break;
case EOpCosh: case EOpAsin:
if (!foldFloatTypeUnary(operandArray[i], &coshf, infoSink, &resultArray[i])) // For asin(x), results are undefined if |x| > 1, we are choosing to set result to 0.
return nullptr; if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
break; UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &asinf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpTanh: case EOpAcos:
if (!foldFloatTypeUnary(operandArray[i], &tanhf, infoSink, &resultArray[i])) // For acos(x), results are undefined if |x| > 1, we are choosing to set result to 0.
return nullptr; if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
break; UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &acosf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAsinh: case EOpAtan:
if (!foldFloatTypeUnary(operandArray[i], &asinhf, infoSink, &resultArray[i])) if (!foldFloatTypeUnary(operandArray[i], &atanf, infoSink, &resultArray[i]))
return nullptr; return nullptr;
break; break;
case EOpAcosh: case EOpSinh:
// For acosh(x), results are undefined if x < 1, we are choosing to set result to 0. if (!foldFloatTypeUnary(operandArray[i], &sinhf, infoSink, &resultArray[i]))
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 1.0f) return nullptr;
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); break;
else if (!foldFloatTypeUnary(operandArray[i], &acoshf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAtanh: case EOpCosh:
// For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to 0. if (!foldFloatTypeUnary(operandArray[i], &coshf, infoSink, &resultArray[i]))
if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) >= 1.0f) return nullptr;
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); break;
else if (!foldFloatTypeUnary(operandArray[i], &atanhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAbs: case EOpTanh:
switch (getType().getBasicType()) if (!foldFloatTypeUnary(operandArray[i], &tanhf, infoSink, &resultArray[i]))
{ return nullptr;
case EbtFloat: break;
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: case EOpAsinh:
switch (getType().getBasicType()) if (!foldFloatTypeUnary(operandArray[i], &asinhf, infoSink, &resultArray[i]))
{ return nullptr;
case EbtFloat: break;
{
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: case EOpAcosh:
if (!foldFloatTypeUnary(operandArray[i], &floorf, infoSink, &resultArray[i])) // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
return nullptr; if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 1.0f)
break; UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &acoshf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpTrunc: case EOpAtanh:
if (!foldFloatTypeUnary(operandArray[i], &truncf, infoSink, &resultArray[i])) // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to 0.
return nullptr; if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) >= 1.0f)
break; UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &atanhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpRound: case EOpAbs:
if (!foldFloatTypeUnary(operandArray[i], &roundf, infoSink, &resultArray[i])) switch (getType().getBasicType())
return nullptr; {
case EbtFloat:
resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
break; break;
case EbtInt:
case EOpRoundEven: resultArray[i].setIConst(abs(operandArray[i].getIConst()));
if (getType().getBasicType() == EbtFloat) break;
{ default:
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( infoSink.info.message(
EPrefixInternalError, getLine(), EPrefixInternalError, getLine(),
"Unary operation not folded into constant"); "Unary operation not folded into constant");
return nullptr; return nullptr;
}
break;
case EOpCeil: case EOpSign:
if (!foldFloatTypeUnary(operandArray[i], &ceilf, infoSink, &resultArray[i])) switch (getType().getBasicType())
return nullptr; {
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; break;
case EbtInt:
case EOpFract:
if (getType().getBasicType() == EbtFloat)
{ {
float x = operandArray[i].getFConst(); int iConst = operandArray[i].getIConst();
resultArray[i].setFConst(x - floorf(x)); int iResult = 0;
break; if (iConst > 0)
iResult = 1;
else if (iConst < 0)
iResult = -1;
resultArray[i].setIConst(iResult);
} }
break;
default:
infoSink.info.message( infoSink.info.message(
EPrefixInternalError, getLine(), EPrefixInternalError, getLine(),
"Unary operation not folded into constant"); "Unary operation not folded into constant");
return nullptr; return nullptr;
}
break;
case EOpExp: case EOpFloor:
if (!foldFloatTypeUnary(operandArray[i], &expf, infoSink, &resultArray[i])) if (!foldFloatTypeUnary(operandArray[i], &floorf, infoSink, &resultArray[i]))
return nullptr; return nullptr;
break; break;
case EOpLog: case EOpTrunc:
// For log(x), results are undefined if x <= 0, we are choosing to set result to 0. if (!foldFloatTypeUnary(operandArray[i], &truncf, infoSink, &resultArray[i]))
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f) return nullptr;
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); break;
else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpExp2: case EOpRound:
if (!foldFloatTypeUnary(operandArray[i], &exp2f, infoSink, &resultArray[i])) if (!foldFloatTypeUnary(operandArray[i], &roundf, infoSink, &resultArray[i]))
return nullptr; return nullptr;
break; break;
case EOpLog2: case EOpRoundEven:
// For log2(x), results are undefined if x <= 0, we are choosing to set result to 0. if (getType().getBasicType() == EbtFloat)
// 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) float x = operandArray[i].getFConst();
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); float result;
else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i])) float fractPart = modff(x, &result);
return nullptr; if (fabsf(fractPart) == 0.5f)
result = 2.0f * roundf(x / 2.0f);
else else
resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f)); result = roundf(x);
resultArray[i].setFConst(result);
break; break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpSqrt: case EOpCeil:
// For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0. if (!foldFloatTypeUnary(operandArray[i], &ceilf, infoSink, &resultArray[i]))
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 0.0f) return nullptr;
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]); break;
else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpInverseSqrt: case EOpFract:
// There is no stdlib built-in function equavalent for GLES built-in inversesqrt(), if (getType().getBasicType() == EbtFloat)
// 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. float x = operandArray[i].getFConst();
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f) resultArray[i].setFConst(x - floorf(x));
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; break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpVectorLogicalNot: case EOpExp:
if (getType().getBasicType() == EbtBool) if (!foldFloatTypeUnary(operandArray[i], &expf, infoSink, &resultArray[i]))
{ return nullptr;
resultArray[i].setBConst(!operandArray[i].getBConst()); break;
break;
} case EOpLog:
infoSink.info.message( // For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
EPrefixInternalError, getLine(), if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
"Unary operation not folded into constant"); UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
return nullptr; return nullptr;
break;
case EOpNormalize: case EOpExp2:
if (getType().getBasicType() == EbtFloat) if (!foldFloatTypeUnary(operandArray[i], &exp2f, infoSink, &resultArray[i]))
{
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; return nullptr;
break;
default: 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; 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 &parameter, FloatTypeUnaryFunc builtinFunc, bool TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter, FloatTypeUnaryFunc builtinFunc,
......
...@@ -300,7 +300,8 @@ class TIntermConstantUnion : public TIntermTyped ...@@ -300,7 +300,8 @@ class TIntermConstantUnion : public TIntermTyped
virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
TConstantUnion *foldBinary(TOperator op, TIntermConstantUnion *rightNode, TInfoSink &infoSink); TConstantUnion *foldBinary(TOperator op, TIntermConstantUnion *rightNode, TInfoSink &infoSink);
TConstantUnion *foldUnary(TOperator op, TInfoSink &infoSink); TConstantUnion *foldUnaryWithDifferentReturnType(TOperator op, TInfoSink &infoSink);
TConstantUnion *foldUnaryWithSameReturnType(TOperator op, TInfoSink &infoSink);
static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate, TInfoSink &infoSink); static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate, TInfoSink &infoSink);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment