Path: blob/main_old/src/tests/compiler_tests/ConstantFolding_test.cpp
1693 views
//1// Copyright 2015 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//5// ConstantFolding_test.cpp:6// Tests for constant folding7//89#include "tests/test_utils/ConstantFoldingTest.h"1011using namespace sh;1213// Test that zero, true or false are not found in AST when they are not expected. This is to make14// sure that the subsequent tests run correctly.15TEST_F(ConstantFoldingExpressionTest, FoldFloatTestCheck)16{17const std::string &floatString = "1.0";18evaluateFloat(floatString);19ASSERT_FALSE(constantFoundInAST(0.0f));20ASSERT_FALSE(constantFoundInAST(true));21ASSERT_FALSE(constantFoundInAST(false));22}2324TEST_F(ConstantFoldingTest, FoldIntegerAdd)25{26const std::string &shaderString =27"#version 300 es\n"28"precision mediump float;\n"29"out int my_Int;\n"30"void main() {\n"31" const int i = 1124 + 5;\n"32" my_Int = i;\n"33"}\n";34compileAssumeSuccess(shaderString);35ASSERT_FALSE(constantFoundInAST(1124));36ASSERT_FALSE(constantFoundInAST(5));37ASSERT_TRUE(constantFoundInAST(1129));38}3940TEST_F(ConstantFoldingTest, FoldIntegerSub)41{42const std::string &shaderString =43"#version 300 es\n"44"precision mediump float;\n"45"out int my_Int;\n"46"void main() {\n"47" const int i = 1124 - 5;\n"48" my_Int = i;\n"49"}\n";50compileAssumeSuccess(shaderString);51ASSERT_FALSE(constantFoundInAST(1124));52ASSERT_FALSE(constantFoundInAST(5));53ASSERT_TRUE(constantFoundInAST(1119));54}5556TEST_F(ConstantFoldingTest, FoldIntegerMul)57{58const std::string &shaderString =59"#version 300 es\n"60"precision mediump float;\n"61"out int my_Int;\n"62"void main() {\n"63" const int i = 1124 * 5;\n"64" my_Int = i;\n"65"}\n";66compileAssumeSuccess(shaderString);67ASSERT_FALSE(constantFoundInAST(1124));68ASSERT_FALSE(constantFoundInAST(5));69ASSERT_TRUE(constantFoundInAST(5620));70}7172TEST_F(ConstantFoldingTest, FoldIntegerDiv)73{74const std::string &shaderString =75"#version 300 es\n"76"precision mediump float;\n"77"out int my_Int;\n"78"void main() {\n"79" const int i = 1124 / 5;\n"80" my_Int = i;\n"81"}\n";82compileAssumeSuccess(shaderString);83ASSERT_FALSE(constantFoundInAST(1124));84ASSERT_FALSE(constantFoundInAST(5));85// Rounding mode of division is undefined in the spec but ANGLE can be expected to round down.86ASSERT_TRUE(constantFoundInAST(224));87}8889TEST_F(ConstantFoldingTest, FoldIntegerModulus)90{91const std::string &shaderString =92"#version 300 es\n"93"precision mediump float;\n"94"out int my_Int;\n"95"void main() {\n"96" const int i = 1124 % 5;\n"97" my_Int = i;\n"98"}\n";99compileAssumeSuccess(shaderString);100ASSERT_FALSE(constantFoundInAST(1124));101ASSERT_FALSE(constantFoundInAST(5));102ASSERT_TRUE(constantFoundInAST(4));103}104105TEST_F(ConstantFoldingTest, FoldVectorCrossProduct)106{107const std::string &shaderString =108"#version 300 es\n"109"precision mediump float;\n"110"out vec3 my_Vec3;"111"void main() {\n"112" const vec3 v3 = cross(vec3(1.0f, 1.0f, 1.0f), vec3(1.0f, -1.0f, 1.0f));\n"113" my_Vec3 = v3;\n"114"}\n";115compileAssumeSuccess(shaderString);116std::vector<float> input1(3, 1.0f);117ASSERT_FALSE(constantVectorFoundInAST(input1));118std::vector<float> input2;119input2.push_back(1.0f);120input2.push_back(-1.0f);121input2.push_back(1.0f);122ASSERT_FALSE(constantVectorFoundInAST(input2));123std::vector<float> result;124result.push_back(2.0f);125result.push_back(0.0f);126result.push_back(-2.0f);127ASSERT_TRUE(constantVectorFoundInAST(result));128}129130// FoldMxNMatrixInverse tests check if the matrix 'inverse' operation131// on MxN matrix is constant folded when argument is constant expression and also132// checks the correctness of the result returned by the constant folding operation.133// All the matrices including matrices in the shader code are in column-major order.134TEST_F(ConstantFoldingTest, Fold2x2MatrixInverse)135{136const std::string &shaderString =137"#version 300 es\n"138"precision mediump float;\n"139"in float i;\n"140"out vec2 my_Vec;\n"141"void main() {\n"142" const mat2 m2 = inverse(mat2(2.0f, 3.0f,\n"143" 5.0f, 7.0f));\n"144" mat2 m = m2 * mat2(i);\n"145" my_Vec = m[0];\n"146"}\n";147compileAssumeSuccess(shaderString);148float inputElements[] = {2.0f, 3.0f, 5.0f, 7.0f};149std::vector<float> input(inputElements, inputElements + 4);150ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));151float outputElements[] = {-7.0f, 3.0f, 5.0f, -2.0f};152std::vector<float> result(outputElements, outputElements + 4);153ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));154}155156// Check if the matrix 'inverse' operation on 3x3 matrix is constant folded.157TEST_F(ConstantFoldingTest, Fold3x3MatrixInverse)158{159const std::string &shaderString =160"#version 300 es\n"161"precision mediump float;\n"162"in float i;\n"163"out vec3 my_Vec;\n"164"void main() {\n"165" const mat3 m3 = inverse(mat3(11.0f, 13.0f, 19.0f,\n"166" 23.0f, 29.0f, 31.0f,\n"167" 37.0f, 41.0f, 43.0f));\n"168" mat3 m = m3 * mat3(i);\n"169" my_Vec = m[0];\n"170"}\n";171compileAssumeSuccess(shaderString);172float inputElements[] = {11.0f, 13.0f, 19.0f, 23.0f, 29.0f, 31.0f, 37.0f, 41.0f, 43.0f};173std::vector<float> input(inputElements, inputElements + 9);174ASSERT_FALSE(constantVectorFoundInAST(input));175float outputElements[] = {3.0f / 85.0f, -11.0f / 34.0f, 37.0f / 170.0f,176-79.0f / 340.0f, 23.0f / 68.0f, -12.0f / 85.0f,17713.0f / 68.0f, -3.0f / 68.0f, -1.0f / 34.0f};178std::vector<float> result(outputElements, outputElements + 9);179const float floatFaultTolerance = 0.000001f;180ASSERT_TRUE(constantVectorNearFoundInAST(result, floatFaultTolerance));181}182183// Check if the matrix 'inverse' operation on 4x4 matrix is constant folded.184TEST_F(ConstantFoldingTest, Fold4x4MatrixInverse)185{186const std::string &shaderString =187"#version 300 es\n"188"precision mediump float;\n"189"in float i;\n"190"out vec4 my_Vec;\n"191"void main() {\n"192" const mat4 m4 = inverse(mat4(29.0f, 31.0f, 37.0f, 41.0f,\n"193" 43.0f, 47.0f, 53.0f, 59.0f,\n"194" 61.0f, 67.0f, 71.0f, 73.0f,\n"195" 79.0f, 83.0f, 89.0f, 97.0f));\n"196" mat4 m = m4 * mat4(i);\n"197" my_Vec = m[0];\n"198"}\n";199compileAssumeSuccess(shaderString);200float inputElements[] = {29.0f, 31.0f, 37.0f, 41.0f, 43.0f, 47.0f, 53.0f, 59.0f,20161.0f, 67.0f, 71.0f, 73.0f, 79.0f, 83.0f, 89.0f, 97.0f};202std::vector<float> input(inputElements, inputElements + 16);203ASSERT_FALSE(constantVectorFoundInAST(input));204float outputElements[] = {43.0f / 126.0f, -11.0f / 21.0f, -2.0f / 21.0f, 31.0f / 126.0f,205-5.0f / 7.0f, 9.0f / 14.0f, 1.0f / 14.0f, -1.0f / 7.0f,20685.0f / 126.0f, -11.0f / 21.0f, 43.0f / 210.0f, -38.0f / 315.0f,207-2.0f / 7.0f, 5.0f / 14.0f, -6.0f / 35.0f, 3.0f / 70.0f};208std::vector<float> result(outputElements, outputElements + 16);209const float floatFaultTolerance = 0.00001f;210ASSERT_TRUE(constantVectorNearFoundInAST(result, floatFaultTolerance));211}212213// FoldMxNMatrixDeterminant tests check if the matrix 'determinant' operation214// on MxN matrix is constant folded when argument is constant expression and also215// checks the correctness of the result returned by the constant folding operation.216// All the matrices including matrices in the shader code are in column-major order.217TEST_F(ConstantFoldingTest, Fold2x2MatrixDeterminant)218{219const std::string &shaderString =220"#version 300 es\n"221"precision mediump float;\n"222"out float my_Float;"223"void main() {\n"224" const float f = determinant(mat2(2.0f, 3.0f,\n"225" 5.0f, 7.0f));\n"226" my_Float = f;\n"227"}\n";228compileAssumeSuccess(shaderString);229float inputElements[] = {2.0f, 3.0f, 5.0f, 7.0f};230std::vector<float> input(inputElements, inputElements + 4);231ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));232ASSERT_TRUE(constantFoundInAST(-1.0f));233}234235// Check if the matrix 'determinant' operation on 3x3 matrix is constant folded.236TEST_F(ConstantFoldingTest, Fold3x3MatrixDeterminant)237{238const std::string &shaderString =239"#version 300 es\n"240"precision mediump float;\n"241"out float my_Float;"242"void main() {\n"243" const float f = determinant(mat3(11.0f, 13.0f, 19.0f,\n"244" 23.0f, 29.0f, 31.0f,\n"245" 37.0f, 41.0f, 43.0f));\n"246" my_Float = f;\n"247"}\n";248compileAssumeSuccess(shaderString);249float inputElements[] = {11.0f, 13.0f, 19.0f, 23.0f, 29.0f, 31.0f, 37.0f, 41.0f, 43.0f};250std::vector<float> input(inputElements, inputElements + 9);251ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));252ASSERT_TRUE(constantFoundInAST(-680.0f));253}254255// Check if the matrix 'determinant' operation on 4x4 matrix is constant folded.256TEST_F(ConstantFoldingTest, Fold4x4MatrixDeterminant)257{258const std::string &shaderString =259"#version 300 es\n"260"precision mediump float;\n"261"out float my_Float;"262"void main() {\n"263" const float f = determinant(mat4(29.0f, 31.0f, 37.0f, 41.0f,\n"264" 43.0f, 47.0f, 53.0f, 59.0f,\n"265" 61.0f, 67.0f, 71.0f, 73.0f,\n"266" 79.0f, 83.0f, 89.0f, 97.0f));\n"267" my_Float = f;\n"268"}\n";269compileAssumeSuccess(shaderString);270float inputElements[] = {29.0f, 31.0f, 37.0f, 41.0f, 43.0f, 47.0f, 53.0f, 59.0f,27161.0f, 67.0f, 71.0f, 73.0f, 79.0f, 83.0f, 89.0f, 97.0f};272std::vector<float> input(inputElements, inputElements + 16);273ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));274ASSERT_TRUE(constantFoundInAST(-2520.0f));275}276277// Check if the matrix 'transpose' operation on 3x3 matrix is constant folded.278// All the matrices including matrices in the shader code are in column-major order.279TEST_F(ConstantFoldingTest, Fold3x3MatrixTranspose)280{281const std::string &shaderString =282"#version 300 es\n"283"precision mediump float;\n"284"in float i;\n"285"out vec3 my_Vec;\n"286"void main() {\n"287" const mat3 m3 = transpose(mat3(11.0f, 13.0f, 19.0f,\n"288" 23.0f, 29.0f, 31.0f,\n"289" 37.0f, 41.0f, 43.0f));\n"290" mat3 m = m3 * mat3(i);\n"291" my_Vec = m[0];\n"292"}\n";293compileAssumeSuccess(shaderString);294float inputElements[] = {11.0f, 13.0f, 19.0f, 23.0f, 29.0f, 31.0f, 37.0f, 41.0f, 43.0f};295std::vector<float> input(inputElements, inputElements + 9);296ASSERT_FALSE(constantColumnMajorMatrixFoundInAST(input));297float outputElements[] = {11.0f, 23.0f, 37.0f, 13.0f, 29.0f, 41.0f, 19.0f, 31.0f, 43.0f};298std::vector<float> result(outputElements, outputElements + 9);299ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));300}301302// Test that 0xFFFFFFFF wraps to -1 when parsed as integer.303// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42304// means that any 32-bit unsigned integer value is a valid literal.305TEST_F(ConstantFoldingTest, ParseWrappedHexIntLiteral)306{307const std::string &shaderString =308"#version 300 es\n"309"precision mediump float;\n"310"precision highp int;\n"311"uniform int inInt;\n"312"out vec4 my_Vec;\n"313"void main() {\n"314" const int i = 0xFFFFFFFF;\n"315" my_Vec = vec4(i * inInt);\n"316"}\n";317compileAssumeSuccess(shaderString);318ASSERT_TRUE(constantFoundInAST(-1));319}320321// Test that 3000000000 wraps to -1294967296 when parsed as integer.322// This is featured in the examples of GLSL 4.5, and ESSL behavior should match323// desktop GLSL when it comes to integer parsing.324TEST_F(ConstantFoldingTest, ParseWrappedDecimalIntLiteral)325{326const std::string &shaderString =327"#version 300 es\n"328"precision mediump float;\n"329"precision highp int;\n"330"uniform int inInt;\n"331"out vec4 my_Vec;\n"332"void main() {\n"333" const int i = 3000000000;\n"334" my_Vec = vec4(i * inInt);\n"335"}\n";336compileAssumeSuccess(shaderString);337ASSERT_TRUE(constantFoundInAST(-1294967296));338}339340// Test that 0xFFFFFFFFu is parsed correctly as an unsigned integer literal.341// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42342// means that any 32-bit unsigned integer value is a valid literal.343TEST_F(ConstantFoldingTest, ParseMaxUintLiteral)344{345const std::string &shaderString =346"#version 300 es\n"347"precision mediump float;\n"348"precision highp int;\n"349"uniform uint inInt;\n"350"out vec4 my_Vec;\n"351"void main() {\n"352" const uint i = 0xFFFFFFFFu;\n"353" my_Vec = vec4(i * inInt);\n"354"}\n";355compileAssumeSuccess(shaderString);356ASSERT_TRUE(constantFoundInAST(0xFFFFFFFFu));357}358359// Test that unary minus applied to unsigned int is constant folded correctly.360// This is featured in the examples of ESSL3 section 4.1.3. ESSL3 section 12.42361// means that any 32-bit unsigned integer value is a valid literal.362TEST_F(ConstantFoldingTest, FoldUnaryMinusOnUintLiteral)363{364const std::string &shaderString =365"#version 300 es\n"366"precision mediump float;\n"367"precision highp int;\n"368"uniform uint inInt;\n"369"out vec4 my_Vec;\n"370"void main() {\n"371" const uint i = -1u;\n"372" my_Vec = vec4(i * inInt);\n"373"}\n";374compileAssumeSuccess(shaderString);375ASSERT_TRUE(constantFoundInAST(0xFFFFFFFFu));376}377378// Test that constant mat2 initialization with a mat2 parameter works correctly.379TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingMat2)380{381const std::string &shaderString =382"precision mediump float;\n"383"uniform float mult;\n"384"void main() {\n"385" const mat2 cm = mat2(mat2(0.0, 1.0, 2.0, 3.0));\n"386" mat2 m = cm * mult;\n"387" gl_FragColor = vec4(m[0], m[1]);\n"388"}\n";389compileAssumeSuccess(shaderString);390float outputElements[] = {0.0f, 1.0f, 2.0f, 3.0f};391std::vector<float> result(outputElements, outputElements + 4);392ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));393}394395// Test that constant mat2 initialization with an int parameter works correctly.396TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingScalar)397{398const std::string &shaderString =399"precision mediump float;\n"400"uniform float mult;\n"401"void main() {\n"402" const mat2 cm = mat2(3);\n"403" mat2 m = cm * mult;\n"404" gl_FragColor = vec4(m[0], m[1]);\n"405"}\n";406compileAssumeSuccess(shaderString);407float outputElements[] = {3.0f, 0.0f, 0.0f, 3.0f};408std::vector<float> result(outputElements, outputElements + 4);409ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));410}411412// Test that constant mat2 initialization with a mix of parameters works correctly.413TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingMix)414{415const std::string &shaderString =416"precision mediump float;\n"417"uniform float mult;\n"418"void main() {\n"419" const mat2 cm = mat2(-1, vec2(0.0, 1.0), vec4(2.0));\n"420" mat2 m = cm * mult;\n"421" gl_FragColor = vec4(m[0], m[1]);\n"422"}\n";423compileAssumeSuccess(shaderString);424float outputElements[] = {-1.0, 0.0f, 1.0f, 2.0f};425std::vector<float> result(outputElements, outputElements + 4);426ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));427}428429// Test that constant mat2 initialization with a mat3 parameter works correctly.430TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingMat3)431{432const std::string &shaderString =433"precision mediump float;\n"434"uniform float mult;\n"435"void main() {\n"436" const mat2 cm = mat2(mat3(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0));\n"437" mat2 m = cm * mult;\n"438" gl_FragColor = vec4(m[0], m[1]);\n"439"}\n";440compileAssumeSuccess(shaderString);441float outputElements[] = {0.0f, 1.0f, 3.0f, 4.0f};442std::vector<float> result(outputElements, outputElements + 4);443ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));444}445446// Test that constant mat4x3 initialization with a mat3x2 parameter works correctly.447TEST_F(ConstantFoldingTest, FoldMat4x3ConstructorTakingMat3x2)448{449const std::string &shaderString =450"#version 300 es\n"451"precision mediump float;\n"452"uniform float mult;\n"453"out vec4 my_FragColor;\n"454"void main() {\n"455" const mat4x3 cm = mat4x3(mat3x2(1.0, 2.0,\n"456" 3.0, 4.0,\n"457" 5.0, 6.0));\n"458" mat4x3 m = cm * mult;\n"459" my_FragColor = vec4(m[0], m[1][0]);\n"460"}\n";461compileAssumeSuccess(shaderString);462float outputElements[] = {1.0f, 2.0f, 0.0f, 3.0f, 4.0f, 0.0f,4635.0f, 6.0f, 1.0f, 0.0f, 0.0f, 0.0f};464std::vector<float> result(outputElements, outputElements + 12);465ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));466}467468// Test that constant mat2 initialization with a vec4 parameter works correctly.469TEST_F(ConstantFoldingTest, FoldMat2ConstructorTakingVec4)470{471const std::string &shaderString =472"precision mediump float;\n"473"uniform float mult;\n"474"void main() {\n"475" const mat2 cm = mat2(vec4(0.0, 1.0, 2.0, 3.0));\n"476" mat2 m = cm * mult;\n"477" gl_FragColor = vec4(m[0], m[1]);\n"478"}\n";479compileAssumeSuccess(shaderString);480float outputElements[] = {0.0f, 1.0f, 2.0f, 3.0f};481std::vector<float> result(outputElements, outputElements + 4);482ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));483}484485// Test that equality comparison of two different structs with a nested struct inside returns false.486TEST_F(ConstantFoldingTest, FoldNestedDifferentStructEqualityComparison)487{488const std::string &shaderString =489"precision mediump float;\n"490"struct nested {\n"491" float f\n;"492"};\n"493"struct S {\n"494" nested a;\n"495" float f;\n"496"};\n"497"uniform vec4 mult;\n"498"void main()\n"499"{\n"500" const S s1 = S(nested(0.0), 2.0);\n"501" const S s2 = S(nested(0.0), 3.0);\n"502" gl_FragColor = (s1 == s2 ? 1.0 : 0.5) * mult;\n"503"}\n";504compileAssumeSuccess(shaderString);505ASSERT_TRUE(constantFoundInAST(0.5f));506}507508// Test that equality comparison of two identical structs with a nested struct inside returns true.509TEST_F(ConstantFoldingTest, FoldNestedIdenticalStructEqualityComparison)510{511const std::string &shaderString =512"precision mediump float;\n"513"struct nested {\n"514" float f\n;"515"};\n"516"struct S {\n"517" nested a;\n"518" float f;\n"519" int i;\n"520"};\n"521"uniform vec4 mult;\n"522"void main()\n"523"{\n"524" const S s1 = S(nested(0.0), 2.0, 3);\n"525" const S s2 = S(nested(0.0), 2.0, 3);\n"526" gl_FragColor = (s1 == s2 ? 1.0 : 0.5) * mult;\n"527"}\n";528compileAssumeSuccess(shaderString);529ASSERT_TRUE(constantFoundInAST(1.0f));530}531532// Test that right elements are chosen from non-square matrix533TEST_F(ConstantFoldingTest, FoldNonSquareMatrixIndexing)534{535const std::string &shaderString =536"#version 300 es\n"537"precision mediump float;\n"538"out vec4 my_FragColor;\n"539"void main()\n"540"{\n"541" my_FragColor = mat3x4(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)[1];\n"542"}\n";543compileAssumeSuccess(shaderString);544float outputElements[] = {4.0f, 5.0f, 6.0f, 7.0f};545std::vector<float> result(outputElements, outputElements + 4);546ASSERT_TRUE(constantVectorFoundInAST(result));547}548549// Test that folding outer product of vectors with non-matching lengths works.550TEST_F(ConstantFoldingTest, FoldNonSquareOuterProduct)551{552const std::string &shaderString =553"#version 300 es\n"554"precision mediump float;\n"555"out vec4 my_FragColor;\n"556"void main()\n"557"{\n"558" mat3x2 prod = outerProduct(vec2(2.0, 3.0), vec3(5.0, 7.0, 11.0));\n"559" my_FragColor = vec4(prod[0].x);\n"560"}\n";561compileAssumeSuccess(shaderString);562// clang-format off563float outputElements[] =564{56510.0f, 15.0f,56614.0f, 21.0f,56722.0f, 33.0f568};569// clang-format on570std::vector<float> result(outputElements, outputElements + 6);571ASSERT_TRUE(constantColumnMajorMatrixFoundInAST(result));572}573574// Test that folding bit shift left with non-matching signedness works.575TEST_F(ConstantFoldingTest, FoldBitShiftLeftDifferentSignedness)576{577const std::string &shaderString =578"#version 300 es\n"579"precision mediump float;\n"580"out vec4 my_FragColor;\n"581"void main()\n"582"{\n"583" uint u = 0xffffffffu << 31;\n"584" my_FragColor = vec4(u);\n"585"}\n";586compileAssumeSuccess(shaderString);587ASSERT_TRUE(constantFoundInAST(0x80000000u));588}589590// Test that folding bit shift right with non-matching signedness works.591TEST_F(ConstantFoldingTest, FoldBitShiftRightDifferentSignedness)592{593const std::string &shaderString =594"#version 300 es\n"595"precision mediump float;\n"596"out vec4 my_FragColor;\n"597"void main()\n"598"{\n"599" uint u = 0xffffffffu >> 30;\n"600" my_FragColor = vec4(u);\n"601"}\n";602compileAssumeSuccess(shaderString);603ASSERT_TRUE(constantFoundInAST(0x3u));604}605606// Test that folding signed bit shift right extends the sign bit.607// ESSL 3.00.6 section 5.9 Expressions.608TEST_F(ConstantFoldingTest, FoldBitShiftRightExtendSignBit)609{610const std::string &shaderString =611"#version 300 es\n"612"precision mediump float;\n"613"out vec4 my_FragColor;\n"614"void main()\n"615"{\n"616" const int i = 0x8fffe000 >> 6;\n"617" uint u = uint(i);"618" my_FragColor = vec4(u);\n"619"}\n";620compileAssumeSuccess(shaderString);621// The bits of the operand are 0x8fffe000 = 1000 1111 1111 1111 1110 0000 0000 0000622// After shifting, they become 1111 1110 0011 1111 1111 1111 1000 0000 = 0xfe3fff80623ASSERT_TRUE(constantFoundInAST(0xfe3fff80u));624}625626// Signed bit shift left should interpret its operand as a bit pattern. As a consequence a number627// may turn from positive to negative when shifted left.628// ESSL 3.00.6 section 5.9 Expressions.629TEST_F(ConstantFoldingTest, FoldBitShiftLeftInterpretedAsBitPattern)630{631const std::string &shaderString =632"#version 300 es\n"633"precision mediump float;\n"634"out vec4 my_FragColor;\n"635"void main()\n"636"{\n"637" const int i = 0x1fffffff << 3;\n"638" uint u = uint(i);"639" my_FragColor = vec4(u);\n"640"}\n";641compileAssumeSuccess(shaderString);642ASSERT_TRUE(constantFoundInAST(0xfffffff8u));643}644645// Test that dividing the minimum signed integer by -1 works.646// ESSL 3.00.6 section 4.1.3 Integers:647// "However, for the case where the minimum representable value is divided by -1, it is allowed to648// return either the minimum representable value or the maximum representable value."649TEST_F(ConstantFoldingTest, FoldDivideMinimumIntegerByMinusOne)650{651const std::string &shaderString =652"#version 300 es\n"653"precision mediump float;\n"654"out vec4 my_FragColor;\n"655"void main()\n"656"{\n"657" int i = 0x80000000 / (-1);\n"658" my_FragColor = vec4(i);\n"659"}\n";660compileAssumeSuccess(shaderString);661ASSERT_TRUE(constantFoundInAST(0x7fffffff) || constantFoundInAST(-0x7fffffff - 1));662}663664// Test that folding an unsigned integer addition that overflows works.665// ESSL 3.00.6 section 4.1.3 Integers:666// "For all precisions, operations resulting in overflow or underflow will not cause any exception,667// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where668// n is the size in bits of the integer."669TEST_F(ConstantFoldingTest, FoldUnsignedIntegerAddOverflow)670{671const std::string &shaderString =672"#version 300 es\n"673"precision mediump float;\n"674"out vec4 my_FragColor;\n"675"void main()\n"676"{\n"677" uint u = 0xffffffffu + 43u;\n"678" my_FragColor = vec4(u);\n"679"}\n";680compileAssumeSuccess(shaderString);681ASSERT_TRUE(constantFoundInAST(42u));682}683684// Test that folding a signed integer addition that overflows works.685// ESSL 3.00.6 section 4.1.3 Integers:686// "For all precisions, operations resulting in overflow or underflow will not cause any exception,687// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where688// n is the size in bits of the integer."689TEST_F(ConstantFoldingTest, FoldSignedIntegerAddOverflow)690{691const std::string &shaderString =692"#version 300 es\n"693"precision mediump float;\n"694"out vec4 my_FragColor;\n"695"void main()\n"696"{\n"697" int i = 0x7fffffff + 4;\n"698" my_FragColor = vec4(i);\n"699"}\n";700compileAssumeSuccess(shaderString);701ASSERT_TRUE(constantFoundInAST(-0x7ffffffd));702}703704// Test that folding an unsigned integer subtraction that overflows works.705// ESSL 3.00.6 section 4.1.3 Integers:706// "For all precisions, operations resulting in overflow or underflow will not cause any exception,707// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where708// n is the size in bits of the integer."709TEST_F(ConstantFoldingTest, FoldUnsignedIntegerDiffOverflow)710{711const std::string &shaderString =712"#version 300 es\n"713"precision mediump float;\n"714"out vec4 my_FragColor;\n"715"void main()\n"716"{\n"717" uint u = 0u - 5u;\n"718" my_FragColor = vec4(u);\n"719"}\n";720compileAssumeSuccess(shaderString);721ASSERT_TRUE(constantFoundInAST(0xfffffffbu));722}723724// Test that folding a signed integer subtraction that overflows works.725// ESSL 3.00.6 section 4.1.3 Integers:726// "For all precisions, operations resulting in overflow or underflow will not cause any exception,727// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where728// n is the size in bits of the integer."729TEST_F(ConstantFoldingTest, FoldSignedIntegerDiffOverflow)730{731const std::string &shaderString =732"#version 300 es\n"733"precision mediump float;\n"734"out vec4 my_FragColor;\n"735"void main()\n"736"{\n"737" int i = -0x7fffffff - 7;\n"738" my_FragColor = vec4(i);\n"739"}\n";740compileAssumeSuccess(shaderString);741ASSERT_TRUE(constantFoundInAST(0x7ffffffa));742}743744// Test that folding an unsigned integer multiplication that overflows works.745// ESSL 3.00.6 section 4.1.3 Integers:746// "For all precisions, operations resulting in overflow or underflow will not cause any exception,747// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where748// n is the size in bits of the integer."749TEST_F(ConstantFoldingTest, FoldUnsignedIntegerMultiplyOverflow)750{751const std::string &shaderString =752"#version 300 es\n"753"precision mediump float;\n"754"out vec4 my_FragColor;\n"755"void main()\n"756"{\n"757" uint u = 0xffffffffu * 10u;\n"758" my_FragColor = vec4(u);\n"759"}\n";760compileAssumeSuccess(shaderString);761ASSERT_TRUE(constantFoundInAST(0xfffffff6u));762}763764// Test that folding a signed integer multiplication that overflows works.765// ESSL 3.00.6 section 4.1.3 Integers:766// "For all precisions, operations resulting in overflow or underflow will not cause any exception,767// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where768// n is the size in bits of the integer."769TEST_F(ConstantFoldingTest, FoldSignedIntegerMultiplyOverflow)770{771const std::string &shaderString =772"#version 300 es\n"773"precision mediump float;\n"774"out vec4 my_FragColor;\n"775"void main()\n"776"{\n"777" int i = 0x7fffffff * 42;\n"778" my_FragColor = vec4(i);\n"779"}\n";780compileAssumeSuccess(shaderString);781ASSERT_TRUE(constantFoundInAST(-42));782}783784// Test that folding of negating the minimum representable integer works. Note that in the test785// "0x80000000" is a negative literal, and the minus sign before it is the negation operator.786// ESSL 3.00.6 section 4.1.3 Integers:787// "For all precisions, operations resulting in overflow or underflow will not cause any exception,788// nor will they saturate, rather they will 'wrap' to yield the low-order n bits of the result where789// n is the size in bits of the integer."790TEST_F(ConstantFoldingTest, FoldMinimumSignedIntegerNegation)791{792const std::string &shaderString =793"#version 300 es\n"794"precision mediump float;\n"795"out vec4 my_FragColor;\n"796"void main()\n"797"{\n"798" int i = -0x80000000;\n"799" my_FragColor = vec4(i);\n"800"}\n";801compileAssumeSuccess(shaderString);802// Negating the minimum signed integer overflows the positive range, so it wraps back to itself.803ASSERT_TRUE(constantFoundInAST(-0x7fffffff - 1));804}805806// Test that folding of shifting the minimum representable integer works.807TEST_F(ConstantFoldingTest, FoldMinimumSignedIntegerRightShift)808{809const std::string &shaderString =810"#version 300 es\n"811"precision mediump float;\n"812"out vec4 my_FragColor;\n"813"void main()\n"814"{\n"815" int i = (0x80000000 >> 1);\n"816" int j = (0x80000000 >> 7);\n"817" my_FragColor = vec4(i, j, i, j);\n"818"}\n";819compileAssumeSuccess(shaderString);820ASSERT_TRUE(constantFoundInAST(-0x40000000));821ASSERT_TRUE(constantFoundInAST(-0x01000000));822}823824// Test that folding of shifting by 0 works.825TEST_F(ConstantFoldingTest, FoldShiftByZero)826{827const std::string &shaderString =828"#version 300 es\n"829"precision mediump float;\n"830"out vec4 my_FragColor;\n"831"void main()\n"832"{\n"833" int i = (3 >> 0);\n"834" int j = (73 << 0);\n"835" my_FragColor = vec4(i, j, i, j);\n"836"}\n";837compileAssumeSuccess(shaderString);838ASSERT_TRUE(constantFoundInAST(3));839ASSERT_TRUE(constantFoundInAST(73));840}841842// Test that folding IsInf results in true when the parameter is an out-of-range float literal.843// ESSL 3.00.6 section 4.1.4 Floats:844// "If the value of the floating point number is too large (small) to be stored as a single845// precision value, it is converted to positive (negative) infinity."846// ESSL 3.00.6 section 12.4:847// "Mandate support for signed infinities."848TEST_F(ConstantFoldingTest, FoldIsInfOutOfRangeFloatLiteral)849{850const std::string &shaderString =851"#version 300 es\n"852"precision mediump float;\n"853"out vec4 my_FragColor;\n"854"void main()\n"855"{\n"856" bool b = isinf(1.0e2048);\n"857" my_FragColor = vec4(b);\n"858"}\n";859compileAssumeSuccess(shaderString);860ASSERT_TRUE(constantFoundInAST(true));861}862863// Regression test case of unary + constant folding of a void struct member.864TEST_F(ConstantFoldingTest, VoidStructMember)865{866constexpr const char *kShaderString = "struct U{void t;}n(){+U().t";867ASSERT_FALSE(compile(kShaderString));868}869870// Test that floats that are too small to be represented get flushed to zero.871// ESSL 3.00.6 section 4.1.4 Floats:872// "A value with a magnitude too small to be represented as a mantissa and exponent is converted to873// zero."874TEST_F(ConstantFoldingExpressionTest, FoldTooSmallFloat)875{876const std::string &floatString = "1.0e-2048";877evaluateFloat(floatString);878ASSERT_TRUE(constantFoundInAST(0.0f));879}880881// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.882// lim radians(x) x -> inf = inf883// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".884TEST_F(ConstantFoldingExpressionTest, FoldRadiansInfinity)885{886const std::string &floatString = "radians(1.0e2048)";887evaluateFloat(floatString);888ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));889}890891// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.892// lim degrees(x) x -> inf = inf893// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".894TEST_F(ConstantFoldingExpressionTest, FoldDegreesInfinity)895{896const std::string &floatString = "degrees(1.0e2048)";897evaluateFloat(floatString);898ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));899}900901// IEEE 754 dictates that sinh(inf) = inf.902// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".903TEST_F(ConstantFoldingExpressionTest, FoldSinhInfinity)904{905const std::string &floatString = "sinh(1.0e2048)";906evaluateFloat(floatString);907ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));908}909910// IEEE 754 dictates that sinh(-inf) = -inf.911// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".912TEST_F(ConstantFoldingExpressionTest, FoldSinhNegativeInfinity)913{914const std::string &floatString = "sinh(-1.0e2048)";915evaluateFloat(floatString);916ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));917}918919// IEEE 754 dictates that cosh(inf) = inf.920// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".921TEST_F(ConstantFoldingExpressionTest, FoldCoshInfinity)922{923const std::string &floatString = "cosh(1.0e2048)";924evaluateFloat(floatString);925ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));926}927928// IEEE 754 dictates that cosh(-inf) = inf.929// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".930TEST_F(ConstantFoldingExpressionTest, FoldCoshNegativeInfinity)931{932const std::string &floatString = "cosh(-1.0e2048)";933evaluateFloat(floatString);934ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));935}936937// IEEE 754 dictates that asinh(inf) = inf.938// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".939TEST_F(ConstantFoldingExpressionTest, FoldAsinhInfinity)940{941const std::string &floatString = "asinh(1.0e2048)";942evaluateFloat(floatString);943ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));944}945946// IEEE 754 dictates that asinh(-inf) = -inf.947// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".948TEST_F(ConstantFoldingExpressionTest, FoldAsinhNegativeInfinity)949{950const std::string &floatString = "asinh(-1.0e2048)";951evaluateFloat(floatString);952ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));953}954955// IEEE 754 dictates that acosh(inf) = inf.956// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".957TEST_F(ConstantFoldingExpressionTest, FoldAcoshInfinity)958{959const std::string &floatString = "acosh(1.0e2048)";960evaluateFloat(floatString);961ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));962}963964// IEEE 754 dictates that pow or powr(0, inf) = 0.965// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".966TEST_F(ConstantFoldingExpressionTest, FoldPowInfinity)967{968const std::string &floatString = "pow(0.0, 1.0e2048)";969evaluateFloat(floatString);970ASSERT_TRUE(constantFoundInAST(0.0f));971}972973// IEEE 754 dictates that exp(inf) = inf.974// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".975TEST_F(ConstantFoldingExpressionTest, FoldExpInfinity)976{977const std::string &floatString = "exp(1.0e2048)";978evaluateFloat(floatString);979ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));980}981982// IEEE 754 dictates that exp(-inf) = 0.983// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".984TEST_F(ConstantFoldingExpressionTest, FoldExpNegativeInfinity)985{986const std::string &floatString = "exp(-1.0e2048)";987evaluateFloat(floatString);988ASSERT_TRUE(constantFoundInAST(0.0f));989}990991// IEEE 754 dictates that log(inf) = inf.992// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".993TEST_F(ConstantFoldingExpressionTest, FoldLogInfinity)994{995const std::string &floatString = "log(1.0e2048)";996evaluateFloat(floatString);997ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));998}9991000// IEEE 754 dictates that exp2(inf) = inf.1001// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1002TEST_F(ConstantFoldingExpressionTest, FoldExp2Infinity)1003{1004const std::string &floatString = "exp2(1.0e2048)";1005evaluateFloat(floatString);1006ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));1007}10081009// IEEE 754 dictates that exp2(-inf) = 0.1010// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1011TEST_F(ConstantFoldingExpressionTest, FoldExp2NegativeInfinity)1012{1013const std::string &floatString = "exp2(-1.0e2048)";1014evaluateFloat(floatString);1015ASSERT_TRUE(constantFoundInAST(0.0f));1016}10171018// IEEE 754 dictates that log2(inf) = inf.1019// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1020TEST_F(ConstantFoldingExpressionTest, FoldLog2Infinity)1021{1022const std::string &floatString = "log2(1.0e2048)";1023evaluateFloat(floatString);1024ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));1025}10261027// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.1028// lim sqrt(x) x -> inf = inf1029// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1030TEST_F(ConstantFoldingExpressionTest, FoldSqrtInfinity)1031{1032const std::string &floatString = "sqrt(1.0e2048)";1033evaluateFloat(floatString);1034ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));1035}10361037// IEEE 754 dictates that rSqrt(inf) = 01038// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1039TEST_F(ConstantFoldingExpressionTest, FoldInversesqrtInfinity)1040{1041const std::string &floatString = "inversesqrt(1.0e2048)";1042evaluateFloat(floatString);1043ASSERT_TRUE(constantFoundInAST(0.0f));1044}10451046// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.1047// lim length(x) x -> inf = inf1048// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1049TEST_F(ConstantFoldingExpressionTest, FoldLengthInfinity)1050{1051const std::string &floatString = "length(1.0e2048)";1052evaluateFloat(floatString);1053ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));1054}10551056// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.1057// lim dot(x, y) x -> inf, y > 0 = inf1058// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1059TEST_F(ConstantFoldingExpressionTest, FoldDotInfinity)1060{1061const std::string &floatString = "dot(1.0e2048, 1.0)";1062evaluateFloat(floatString);1063ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));1064}10651066// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.1067// lim dot(vec2(x, y), vec2(z)) x -> inf, finite y, z > 0 = inf1068// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1069TEST_F(ConstantFoldingExpressionTest, FoldDotInfinity2)1070{1071const std::string &floatString = "dot(vec2(1.0e2048, -1.0), vec2(1.0))";1072evaluateFloat(floatString);1073ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));1074}10751076// Faceforward behavior with infinity as a parameter can be derived from dot().1077// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1078TEST_F(ConstantFoldingExpressionTest, FoldFaceForwardInfinity)1079{1080const std::string &floatString = "faceforward(4.0, 1.0e2048, 1.0)";1081evaluateFloat(floatString);1082ASSERT_TRUE(constantFoundInAST(-4.0f));1083}10841085// Faceforward behavior with infinity as a parameter can be derived from dot().1086// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1087TEST_F(ConstantFoldingExpressionTest, FoldFaceForwardInfinity2)1088{1089const std::string &floatString = "faceforward(vec2(4.0), vec2(1.0e2048, -1.0), vec2(1.0)).x";1090evaluateFloat(floatString);1091ASSERT_TRUE(constantFoundInAST(-4.0f));1092}10931094// Test that infinity - finite value evaluates to infinity.1095// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1096TEST_F(ConstantFoldingExpressionTest, FoldInfinityMinusFinite)1097{1098const std::string &floatString = "1.0e2048 - 1.0e20";1099evaluateFloat(floatString);1100ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));1101}11021103// Test that -infinity + finite value evaluates to -infinity.1104// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1105TEST_F(ConstantFoldingExpressionTest, FoldMinusInfinityPlusFinite)1106{1107const std::string &floatString = "(-1.0e2048) + 1.0e20";1108evaluateFloat(floatString);1109ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));1110}11111112// Test that infinity * finite value evaluates to infinity.1113// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1114TEST_F(ConstantFoldingExpressionTest, FoldInfinityMultipliedByFinite)1115{1116const std::string &floatString = "1.0e2048 * 1.0e-20";1117evaluateFloat(floatString);1118ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));1119}11201121// Test that infinity * infinity evaluates to infinity.1122// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1123TEST_F(ConstantFoldingExpressionTest, FoldInfinityMultipliedByInfinity)1124{1125const std::string &floatString = "1.0e2048 * 1.0e2048";1126evaluateFloat(floatString);1127ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));1128}11291130// Test that infinity * negative infinity evaluates to negative infinity.1131// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1132TEST_F(ConstantFoldingExpressionTest, FoldInfinityMultipliedByNegativeInfinity)1133{1134const std::string &floatString = "1.0e2048 * (-1.0e2048)";1135evaluateFloat(floatString);1136ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));1137}11381139// Test that dividing by minus zero results in the appropriately signed infinity.1140// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1141// "If both positive and negative zeros are implemented, the correctly signed Inf will be1142// generated".1143TEST_F(ConstantFoldingExpressionTest, FoldDivideByNegativeZero)1144{1145const std::string &floatString = "1.0 / (-0.0)";1146evaluateFloat(floatString);1147ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));1148ASSERT_TRUE(hasWarning());1149}11501151// Test that infinity divided by zero evaluates to infinity.1152// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1153TEST_F(ConstantFoldingExpressionTest, FoldInfinityDividedByZero)1154{1155const std::string &floatString = "1.0e2048 / 0.0";1156evaluateFloat(floatString);1157ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));1158ASSERT_TRUE(hasWarning());1159}11601161// Test that negative infinity divided by zero evaluates to negative infinity.1162// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1163TEST_F(ConstantFoldingExpressionTest, FoldMinusInfinityDividedByZero)1164{1165const std::string &floatString = "(-1.0e2048) / 0.0";1166evaluateFloat(floatString);1167ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));1168ASSERT_TRUE(hasWarning());1169}11701171// Test that dividing a finite number by infinity results in zero.1172// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".1173TEST_F(ConstantFoldingExpressionTest, FoldDivideByInfinity)1174{1175const std::string &floatString = "1.0e30 / 1.0e2048";1176evaluateFloat(floatString);1177ASSERT_TRUE(constantFoundInAST(0.0f));1178}11791180// Test that unsigned bitfieldExtract is folded correctly.1181TEST_F(ConstantFoldingExpressionTest, FoldUnsignedBitfieldExtract)1182{1183const std::string &uintString = "bitfieldExtract(0x00110000u, 16, 5)";1184evaluateUint(uintString);1185ASSERT_TRUE(constantFoundInAST(0x11u));1186}11871188// Test that unsigned bitfieldExtract to extract 32 bits is folded correctly.1189TEST_F(ConstantFoldingExpressionTest, FoldUnsignedBitfieldExtract32Bits)1190{1191const std::string &uintString = "bitfieldExtract(0xff0000ffu, 0, 32)";1192evaluateUint(uintString);1193ASSERT_TRUE(constantFoundInAST(0xff0000ffu));1194}11951196// Test that signed bitfieldExtract is folded correctly. The higher bits should be set to 1 if the1197// most significant bit of the extracted value is 1.1198TEST_F(ConstantFoldingExpressionTest, FoldSignedBitfieldExtract)1199{1200const std::string &intString = "bitfieldExtract(0x00110000, 16, 5)";1201evaluateInt(intString);1202// 0xfffffff1 == -151203ASSERT_TRUE(constantFoundInAST(-15));1204}12051206// Test that bitfieldInsert is folded correctly.1207TEST_F(ConstantFoldingExpressionTest, FoldBitfieldInsert)1208{1209const std::string &uintString = "bitfieldInsert(0x04501701u, 0x11u, 8, 5)";1210evaluateUint(uintString);1211ASSERT_TRUE(constantFoundInAST(0x04501101u));1212}12131214// Test that bitfieldInsert to insert 32 bits is folded correctly.1215TEST_F(ConstantFoldingExpressionTest, FoldBitfieldInsert32Bits)1216{1217const std::string &uintString = "bitfieldInsert(0xff0000ffu, 0x11u, 0, 32)";1218evaluateUint(uintString);1219ASSERT_TRUE(constantFoundInAST(0x11u));1220}12211222// Test that bitfieldReverse is folded correctly.1223TEST_F(ConstantFoldingExpressionTest, FoldBitfieldReverse)1224{1225const std::string &uintString = "bitfieldReverse((1u << 4u) | (1u << 7u))";1226evaluateUint(uintString);1227uint32_t flag1 = 1u << (31u - 4u);1228uint32_t flag2 = 1u << (31u - 7u);1229ASSERT_TRUE(constantFoundInAST(flag1 | flag2));1230}12311232// Test that bitCount is folded correctly.1233TEST_F(ConstantFoldingExpressionTest, FoldBitCount)1234{1235const std::string &intString = "bitCount(0x17103121u)";1236evaluateInt(intString);1237ASSERT_TRUE(constantFoundInAST(10));1238}12391240// Test that findLSB is folded correctly.1241TEST_F(ConstantFoldingExpressionTest, FoldFindLSB)1242{1243const std::string &intString = "findLSB(0x80010000u)";1244evaluateInt(intString);1245ASSERT_TRUE(constantFoundInAST(16));1246}12471248// Test that findLSB is folded correctly when the operand is zero.1249TEST_F(ConstantFoldingExpressionTest, FoldFindLSBZero)1250{1251const std::string &intString = "findLSB(0u)";1252evaluateInt(intString);1253ASSERT_TRUE(constantFoundInAST(-1));1254}12551256// Test that findMSB is folded correctly.1257TEST_F(ConstantFoldingExpressionTest, FoldFindMSB)1258{1259const std::string &intString = "findMSB(0x01000008u)";1260evaluateInt(intString);1261ASSERT_TRUE(constantFoundInAST(24));1262}12631264// Test that findMSB is folded correctly when the operand is zero.1265TEST_F(ConstantFoldingExpressionTest, FoldFindMSBZero)1266{1267const std::string &intString = "findMSB(0u)";1268evaluateInt(intString);1269ASSERT_TRUE(constantFoundInAST(-1));1270}12711272// Test that findMSB is folded correctly for a negative integer.1273// It is supposed to return the index of the most significant bit set to 0.1274TEST_F(ConstantFoldingExpressionTest, FoldFindMSBNegativeInt)1275{1276const std::string &intString = "findMSB(-8)";1277evaluateInt(intString);1278ASSERT_TRUE(constantFoundInAST(2));1279}12801281// Test that findMSB is folded correctly for -1.1282TEST_F(ConstantFoldingExpressionTest, FoldFindMSBMinusOne)1283{1284const std::string &intString = "findMSB(-1)";1285evaluateInt(intString);1286ASSERT_TRUE(constantFoundInAST(-1));1287}12881289// Test that packUnorm4x8 is folded correctly for a vector of zeroes.1290TEST_F(ConstantFoldingExpressionTest, FoldPackUnorm4x8Zero)1291{1292const std::string &intString = "packUnorm4x8(vec4(0.0))";1293evaluateUint(intString);1294ASSERT_TRUE(constantFoundInAST(0u));1295}12961297// Test that packUnorm4x8 is folded correctly for a vector of ones.1298TEST_F(ConstantFoldingExpressionTest, FoldPackUnorm4x8One)1299{1300const std::string &intString = "packUnorm4x8(vec4(1.0))";1301evaluateUint(intString);1302ASSERT_TRUE(constantFoundInAST(0xffffffffu));1303}13041305// Test that packSnorm4x8 is folded correctly for a vector of zeroes.1306TEST_F(ConstantFoldingExpressionTest, FoldPackSnorm4x8Zero)1307{1308const std::string &intString = "packSnorm4x8(vec4(0.0))";1309evaluateUint(intString);1310ASSERT_TRUE(constantFoundInAST(0u));1311}13121313// Test that packSnorm4x8 is folded correctly for a vector of ones.1314TEST_F(ConstantFoldingExpressionTest, FoldPackSnorm4x8One)1315{1316const std::string &intString = "packSnorm4x8(vec4(1.0))";1317evaluateUint(intString);1318ASSERT_TRUE(constantFoundInAST(0x7f7f7f7fu));1319}13201321// Test that packSnorm4x8 is folded correctly for a vector of minus ones.1322TEST_F(ConstantFoldingExpressionTest, FoldPackSnorm4x8MinusOne)1323{1324const std::string &intString = "packSnorm4x8(vec4(-1.0))";1325evaluateUint(intString);1326ASSERT_TRUE(constantFoundInAST(0x81818181u));1327}13281329// Test that unpackSnorm4x8 is folded correctly when it needs to clamp the result.1330TEST_F(ConstantFoldingExpressionTest, FoldUnpackSnorm4x8Clamp)1331{1332const std::string &floatString = "unpackSnorm4x8(0x00000080u).x";1333evaluateFloat(floatString);1334ASSERT_TRUE(constantFoundInAST(-1.0f));1335}13361337// Test that unpackUnorm4x8 is folded correctly.1338TEST_F(ConstantFoldingExpressionTest, FoldUnpackUnorm4x8)1339{1340const std::string &floatString = "unpackUnorm4x8(0x007bbeefu).z";1341evaluateFloat(floatString);1342ASSERT_TRUE(constantFoundInAST(123.0f / 255.0f));1343}13441345// Test that ldexp is folded correctly.1346TEST_F(ConstantFoldingExpressionTest, FoldLdexp)1347{1348const std::string &floatString = "ldexp(0.625, 1)";1349evaluateFloat(floatString);1350ASSERT_TRUE(constantFoundInAST(1.25f));1351}13521353// Fold a ternary operator.1354TEST_F(ConstantFoldingTest, FoldTernary)1355{1356const std::string &shaderString =1357R"(#version 300 es1358precision highp int;1359uniform int u;1360out int my_FragColor;1361void main()1362{1363my_FragColor = (true ? 1 : u);1364})";1365compileAssumeSuccess(shaderString);1366ASSERT_TRUE(constantFoundInAST(1));1367ASSERT_FALSE(symbolFoundInMain("u"));1368}13691370// Fold a ternary operator inside a consuming expression.1371TEST_F(ConstantFoldingTest, FoldTernaryInsideExpression)1372{1373const std::string &shaderString =1374R"(#version 300 es1375precision highp int;1376uniform int u;1377out int my_FragColor;1378void main()1379{1380my_FragColor = ivec2((true ? 1 : u) + 2, 4).x;1381})";1382compileAssumeSuccess(shaderString);1383ASSERT_TRUE(constantFoundInAST(3));1384ASSERT_FALSE(symbolFoundInMain("u"));1385}13861387// Fold indexing into an array constructor.1388TEST_F(ConstantFoldingExpressionTest, FoldArrayConstructorIndexing)1389{1390const std::string &floatString = "(float[3](-1.0, 1.0, 2.0))[2]";1391evaluateFloat(floatString);1392ASSERT_FALSE(constantFoundInAST(-1.0f));1393ASSERT_FALSE(constantFoundInAST(1.0f));1394ASSERT_TRUE(constantFoundInAST(2.0f));1395}13961397// Fold indexing into an array of arrays constructor.1398TEST_F(ConstantFoldingExpressionTest, FoldArrayOfArraysConstructorIndexing)1399{1400const std::string &floatString = "(float[2][2](float[2](-1.0, 1.0), float[2](2.0, 3.0)))[1][0]";1401evaluateFloat(floatString);1402ASSERT_FALSE(constantFoundInAST(-1.0f));1403ASSERT_FALSE(constantFoundInAST(1.0f));1404ASSERT_FALSE(constantFoundInAST(3.0f));1405ASSERT_TRUE(constantFoundInAST(2.0f));1406}14071408// Fold indexing into a named constant array.1409TEST_F(ConstantFoldingTest, FoldNamedArrayIndexing)1410{1411const std::string &shaderString =1412R"(#version 300 es1413precision highp float;1414const float[3] arr = float[3](-1.0, 1.0, 2.0);1415out float my_FragColor;1416void main()1417{1418my_FragColor = arr[1];1419})";1420compileAssumeSuccess(shaderString);1421ASSERT_FALSE(constantFoundInAST(-1.0f));1422ASSERT_FALSE(constantFoundInAST(2.0f));1423ASSERT_TRUE(constantFoundInAST(1.0f));1424// The variable should be pruned out since after folding the indexing, there are no more1425// references to it.1426ASSERT_FALSE(symbolFoundInAST("arr"));1427}14281429// Fold indexing into a named constant array of arrays.1430TEST_F(ConstantFoldingTest, FoldNamedArrayOfArraysIndexing)1431{1432const std::string &shaderString =1433R"(#version 310 es1434precision highp float;1435const float[2][2] arr = float[2][2](float[2](-1.0, 1.0), float[2](2.0, 3.0));1436out float my_FragColor;1437void main()1438{1439my_FragColor = arr[0][1];1440})";1441compileAssumeSuccess(shaderString);1442ASSERT_FALSE(constantFoundInAST(-1.0f));1443ASSERT_FALSE(constantFoundInAST(2.0f));1444ASSERT_FALSE(constantFoundInAST(3.0f));1445ASSERT_TRUE(constantFoundInAST(1.0f));1446// The variable should be pruned out since after folding the indexing, there are no more1447// references to it.1448ASSERT_FALSE(symbolFoundInAST("arr"));1449}14501451// Fold indexing into an array constructor where some of the arguments are constant and others are1452// non-constant but without side effects.1453TEST_F(ConstantFoldingTest, FoldArrayConstructorIndexingWithMixedArguments)1454{1455const std::string &shaderString =1456R"(#version 300 es1457precision highp float;1458uniform float u;1459out float my_FragColor;1460void main()1461{1462my_FragColor = float[2](u, 1.0)[1];1463})";1464compileAssumeSuccess(shaderString);1465ASSERT_TRUE(constantFoundInAST(1.0f));1466ASSERT_FALSE(constantFoundInAST(1));1467ASSERT_FALSE(symbolFoundInMain("u"));1468}14691470// Indexing into an array constructor where some of the arguments have side effects can't be folded.1471TEST_F(ConstantFoldingTest, CantFoldArrayConstructorIndexingWithSideEffects)1472{1473const std::string &shaderString =1474R"(#version 300 es1475precision highp float;1476out float my_FragColor;1477void main()1478{1479float sideEffectTarget = 0.0;1480float f = float[3](sideEffectTarget = 1.0, 1.0, 2.0)[1];1481my_FragColor = f + sideEffectTarget;1482})";1483compileAssumeSuccess(shaderString);1484// All of the array constructor arguments should be present in the final AST.1485ASSERT_TRUE(constantFoundInAST(1.0f));1486ASSERT_TRUE(constantFoundInAST(2.0f));1487}14881489// Fold comparing two array constructors.1490TEST_F(ConstantFoldingTest, FoldArrayConstructorEquality)1491{1492const std::string &shaderString =1493R"(#version 300 es1494precision highp float;1495out float my_FragColor;1496void main()1497{1498const bool b = (float[3](2.0, 1.0, -1.0) == float[3](2.0, 1.0, -1.0));1499my_FragColor = b ? 3.0 : 4.0;1500})";1501compileAssumeSuccess(shaderString);1502ASSERT_TRUE(constantFoundInAST(3.0f));1503ASSERT_FALSE(constantFoundInAST(4.0f));1504}15051506// Fold comparing two named constant arrays.1507TEST_F(ConstantFoldingExpressionTest, FoldNamedArrayEquality)1508{1509const std::string &shaderString =1510R"(#version 300 es1511precision highp float;1512const float[3] arrA = float[3](-1.0, 1.0, 2.0);1513const float[3] arrB = float[3](-1.0, 1.0, 2.0);1514out float my_FragColor;1515void main()1516{1517const bool b = (arrA == arrB);1518my_FragColor = b ? 3.0 : 4.0;1519})";1520compileAssumeSuccess(shaderString);1521ASSERT_TRUE(constantFoundInAST(3.0f));1522ASSERT_FALSE(constantFoundInAST(4.0f));1523}15241525// Fold comparing two array of arrays constructors.1526TEST_F(ConstantFoldingTest, FoldArrayOfArraysConstructorEquality)1527{1528const std::string &shaderString =1529R"(#version 310 es1530precision highp float;1531out float my_FragColor;1532void main()1533{1534const bool b = (float[2][2](float[2](-1.0, 1.0), float[2](2.0, 3.0)) ==1535float[2][2](float[2](-1.0, 1.0), float[2](2.0, 1000.0)));1536my_FragColor = b ? 4.0 : 5.0;1537})";1538compileAssumeSuccess(shaderString);1539ASSERT_TRUE(constantFoundInAST(5.0f));1540ASSERT_FALSE(constantFoundInAST(4.0f));1541}15421543// Test that casting a negative float to uint results in a warning. ESSL 3.00.6 section 5.4.11544// specifies this as an undefined conversion.1545TEST_F(ConstantFoldingExpressionTest, FoldNegativeFloatToUint)1546{1547const std::string &uintString = "uint(-1.0)";1548evaluateUint(uintString);1549ASSERT_TRUE(constantFoundInAST(std::numeric_limits<unsigned int>::max()));1550ASSERT_TRUE(hasWarning());1551}15521553// Test that casting a negative float to uint inside a uvec constructor results in a warning. ESSL1554// 3.00.6 section 5.4.1 specifies this as an undefined conversion.1555TEST_F(ConstantFoldingExpressionTest, FoldNegativeFloatToUvec)1556{1557const std::string &uintString = "uvec4(2.0, 1.0, vec2(0.0, -1.0)).w";1558evaluateUint(uintString);1559ASSERT_TRUE(constantFoundInAST(std::numeric_limits<unsigned int>::max()));1560ASSERT_TRUE(hasWarning());1561}15621563// Test that a negative float doesn't result in a warning when it is inside a constructor but isn't1564// actually converted.1565TEST_F(ConstantFoldingExpressionTest, NegativeFloatInsideUvecConstructorButOutOfRange)1566{1567const std::string &uintString = "uvec2(1.0, vec2(0.0, -1.0)).x";1568evaluateUint(uintString);1569ASSERT_FALSE(hasWarning());1570}15711572// Test that a large float (above max int32_t) is converted to unsigned integer correctly.1573TEST_F(ConstantFoldingExpressionTest, LargeFloatToUint)1574{1575const std::string &uintString = "uint(3221225472.0)";1576evaluateUint(uintString);1577ASSERT_TRUE(constantFoundInAST(3221225472u));1578ASSERT_FALSE(hasWarning());1579}15801581// Test that folding % with a negative dividend generates a warning.1582TEST_F(ConstantFoldingExpressionTest, IntegerModulusNegativeDividend)1583{1584const std::string &intString = "(-5) % 3";1585evaluateInt(intString);1586ASSERT_TRUE(hasWarning());1587}15881589// Test that folding % with a negative divisor generates a warning.1590TEST_F(ConstantFoldingExpressionTest, IntegerModulusNegativeDivisor)1591{1592const std::string &intString = "5 % (-3)";1593evaluateInt(intString);1594ASSERT_TRUE(hasWarning());1595}159615971598