Home | History | Annotate | Download | only in MachineIndependent
      1 //
      2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
      3 // Copyright (C) 2012-2013 LunarG, Inc.
      4 // Copyright (C) 2017 ARM Limited.
      5 // Copyright (C) 2018 Google, Inc.
      6 //
      7 // All rights reserved.
      8 //
      9 // Redistribution and use in source and binary forms, with or without
     10 // modification, are permitted provided that the following conditions
     11 // are met:
     12 //
     13 //    Redistributions of source code must retain the above copyright
     14 //    notice, this list of conditions and the following disclaimer.
     15 //
     16 //    Redistributions in binary form must reproduce the above
     17 //    copyright notice, this list of conditions and the following
     18 //    disclaimer in the documentation and/or other materials provided
     19 //    with the distribution.
     20 //
     21 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
     22 //    contributors may be used to endorse or promote products derived
     23 //    from this software without specific prior written permission.
     24 //
     25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     26 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     27 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     28 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     29 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     30 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     31 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     32 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     33 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     34 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     35 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36 // POSSIBILITY OF SUCH DAMAGE.
     37 //
     38 
     39 #include "localintermediate.h"
     40 #include <cmath>
     41 #include <cfloat>
     42 #include <cstdlib>
     43 #include <climits>
     44 
     45 namespace {
     46 
     47 using namespace glslang;
     48 
     49 typedef union {
     50     double d;
     51     int i[2];
     52 } DoubleIntUnion;
     53 
     54 // Some helper functions
     55 
     56 bool isNan(double x)
     57 {
     58     DoubleIntUnion u;
     59     // tough to find a platform independent library function, do it directly
     60     u.d = x;
     61     int bitPatternL = u.i[0];
     62     int bitPatternH = u.i[1];
     63     return (bitPatternH & 0x7ff80000) == 0x7ff80000 &&
     64            ((bitPatternH & 0xFFFFF) != 0 || bitPatternL != 0);
     65 }
     66 
     67 bool isInf(double x)
     68 {
     69     DoubleIntUnion u;
     70     // tough to find a platform independent library function, do it directly
     71     u.d = x;
     72     int bitPatternL = u.i[0];
     73     int bitPatternH = u.i[1];
     74     return (bitPatternH & 0x7ff00000) == 0x7ff00000 &&
     75            (bitPatternH & 0xFFFFF) == 0 && bitPatternL == 0;
     76 }
     77 
     78 const double pi = 3.1415926535897932384626433832795;
     79 
     80 } // end anonymous namespace
     81 
     82 
     83 namespace glslang {
     84 
     85 //
     86 // The fold functions see if an operation on a constant can be done in place,
     87 // without generating run-time code.
     88 //
     89 // Returns the node to keep using, which may or may not be the node passed in.
     90 //
     91 // Note: As of version 1.2, all constant operations must be folded.  It is
     92 // not opportunistic, but rather a semantic requirement.
     93 //
     94 
     95 //
     96 // Do folding between a pair of nodes.
     97 // 'this' is the left-hand operand and 'rightConstantNode' is the right-hand operand.
     98 //
     99 // Returns a new node representing the result.
    100 //
    101 TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* rightConstantNode) const
    102 {
    103     // For most cases, the return type matches the argument type, so set that
    104     // up and just code to exceptions below.
    105     TType returnType;
    106     returnType.shallowCopy(getType());
    107 
    108     //
    109     // A pair of nodes is to be folded together
    110     //
    111 
    112     const TIntermConstantUnion *rightNode = rightConstantNode->getAsConstantUnion();
    113     TConstUnionArray leftUnionArray = getConstArray();
    114     TConstUnionArray rightUnionArray = rightNode->getConstArray();
    115 
    116     // Figure out the size of the result
    117     int newComps;
    118     int constComps;
    119     switch(op) {
    120     case EOpMatrixTimesMatrix:
    121         newComps = rightNode->getMatrixCols() * getMatrixRows();
    122         break;
    123     case EOpMatrixTimesVector:
    124         newComps = getMatrixRows();
    125         break;
    126     case EOpVectorTimesMatrix:
    127         newComps = rightNode->getMatrixCols();
    128         break;
    129     default:
    130         newComps = getType().computeNumComponents();
    131         constComps = rightConstantNode->getType().computeNumComponents();
    132         if (constComps == 1 && newComps > 1) {
    133             // for a case like vec4 f = vec4(2,3,4,5) + 1.2;
    134             TConstUnionArray smearedArray(newComps, rightNode->getConstArray()[0]);
    135             rightUnionArray = smearedArray;
    136         } else if (constComps > 1 && newComps == 1) {
    137             // for a case like vec4 f = 1.2 + vec4(2,3,4,5);
    138             newComps = constComps;
    139             rightUnionArray = rightNode->getConstArray();
    140             TConstUnionArray smearedArray(newComps, getConstArray()[0]);
    141             leftUnionArray = smearedArray;
    142             returnType.shallowCopy(rightNode->getType());
    143         }
    144         break;
    145     }
    146 
    147     TConstUnionArray newConstArray(newComps);
    148     TType constBool(EbtBool, EvqConst);
    149 
    150     switch(op) {
    151     case EOpAdd:
    152         for (int i = 0; i < newComps; i++)
    153             newConstArray[i] = leftUnionArray[i] + rightUnionArray[i];
    154         break;
    155     case EOpSub:
    156         for (int i = 0; i < newComps; i++)
    157             newConstArray[i] = leftUnionArray[i] - rightUnionArray[i];
    158         break;
    159 
    160     case EOpMul:
    161     case EOpVectorTimesScalar:
    162     case EOpMatrixTimesScalar:
    163         for (int i = 0; i < newComps; i++)
    164             newConstArray[i] = leftUnionArray[i] * rightUnionArray[i];
    165         break;
    166     case EOpMatrixTimesMatrix:
    167         for (int row = 0; row < getMatrixRows(); row++) {
    168             for (int column = 0; column < rightNode->getMatrixCols(); column++) {
    169                 double sum = 0.0f;
    170                 for (int i = 0; i < rightNode->getMatrixRows(); i++)
    171                     sum += leftUnionArray[i * getMatrixRows() + row].getDConst() * rightUnionArray[column * rightNode->getMatrixRows() + i].getDConst();
    172                 newConstArray[column * getMatrixRows() + row].setDConst(sum);
    173             }
    174         }
    175         returnType.shallowCopy(TType(getType().getBasicType(), EvqConst, 0, rightNode->getMatrixCols(), getMatrixRows()));
    176         break;
    177     case EOpDiv:
    178         for (int i = 0; i < newComps; i++) {
    179             switch (getType().getBasicType()) {
    180             case EbtDouble:
    181             case EbtFloat:
    182             case EbtFloat16:
    183                 if (rightUnionArray[i].getDConst() != 0.0)
    184                     newConstArray[i].setDConst(leftUnionArray[i].getDConst() / rightUnionArray[i].getDConst());
    185                 else if (leftUnionArray[i].getDConst() > 0.0)
    186                     newConstArray[i].setDConst((double)INFINITY);
    187                 else if (leftUnionArray[i].getDConst() < 0.0)
    188                     newConstArray[i].setDConst(-(double)INFINITY);
    189                 else
    190                     newConstArray[i].setDConst((double)NAN);
    191                 break;
    192             case EbtInt8:
    193                 if (rightUnionArray[i] == (signed char)0)
    194                     newConstArray[i].setI8Const((signed char)0x7F);
    195                 else if (rightUnionArray[i].getI8Const() == (signed char)-1 && leftUnionArray[i].getI8Const() == (signed char)-0x80)
    196                     newConstArray[i].setI8Const((signed char)-0x80);
    197                 else
    198                     newConstArray[i].setI8Const(leftUnionArray[i].getI8Const() / rightUnionArray[i].getI8Const());
    199                 break;
    200 
    201             case EbtUint8:
    202                 if (rightUnionArray[i] == (unsigned char)0u)
    203                     newConstArray[i].setU8Const((unsigned char)0xFFu);
    204                 else
    205                     newConstArray[i].setU8Const(leftUnionArray[i].getU8Const() / rightUnionArray[i].getU8Const());
    206                 break;
    207 
    208            case EbtInt16:
    209                 if (rightUnionArray[i] == (signed short)0)
    210                     newConstArray[i].setI16Const((signed short)0x7FFF);
    211                 else if (rightUnionArray[i].getI16Const() == (signed short)-1 && leftUnionArray[i].getI16Const() == (signed short)-0x8000)
    212                     newConstArray[i].setI16Const((signed short)-0x8000);
    213                 else
    214                     newConstArray[i].setI16Const(leftUnionArray[i].getI16Const() / rightUnionArray[i].getI16Const());
    215                 break;
    216 
    217             case EbtUint16:
    218                 if (rightUnionArray[i] == (unsigned short)0u)
    219                     newConstArray[i].setU16Const((unsigned short)0xFFFFu);
    220                 else
    221                     newConstArray[i].setU16Const(leftUnionArray[i].getU16Const() / rightUnionArray[i].getU16Const());
    222                 break;
    223 
    224             case EbtInt:
    225                 if (rightUnionArray[i] == 0)
    226                     newConstArray[i].setIConst(0x7FFFFFFF);
    227                 else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)-0x80000000ll)
    228                     newConstArray[i].setIConst((int)-0x80000000ll);
    229                 else
    230                     newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
    231                 break;
    232 
    233             case EbtUint:
    234                 if (rightUnionArray[i] == 0u)
    235                     newConstArray[i].setUConst(0xFFFFFFFFu);
    236                 else
    237                     newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
    238                 break;
    239 
    240             case EbtInt64:
    241                 if (rightUnionArray[i] == 0ll)
    242                     newConstArray[i].setI64Const(0x7FFFFFFFFFFFFFFFll);
    243                 else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == (long long)-0x8000000000000000ll)
    244                     newConstArray[i].setI64Const((long long)-0x8000000000000000ll);
    245                 else
    246                     newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const());
    247                 break;
    248 
    249             case EbtUint64:
    250                 if (rightUnionArray[i] == 0ull)
    251                     newConstArray[i].setU64Const(0xFFFFFFFFFFFFFFFFull);
    252                 else
    253                     newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const());
    254                 break;
    255             default:
    256                 return 0;
    257             }
    258         }
    259         break;
    260 
    261     case EOpMatrixTimesVector:
    262         for (int i = 0; i < getMatrixRows(); i++) {
    263             double sum = 0.0f;
    264             for (int j = 0; j < rightNode->getVectorSize(); j++) {
    265                 sum += leftUnionArray[j*getMatrixRows() + i].getDConst() * rightUnionArray[j].getDConst();
    266             }
    267             newConstArray[i].setDConst(sum);
    268         }
    269 
    270         returnType.shallowCopy(TType(getBasicType(), EvqConst, getMatrixRows()));
    271         break;
    272 
    273     case EOpVectorTimesMatrix:
    274         for (int i = 0; i < rightNode->getMatrixCols(); i++) {
    275             double sum = 0.0f;
    276             for (int j = 0; j < getVectorSize(); j++)
    277                 sum += leftUnionArray[j].getDConst() * rightUnionArray[i*rightNode->getMatrixRows() + j].getDConst();
    278             newConstArray[i].setDConst(sum);
    279         }
    280 
    281         returnType.shallowCopy(TType(getBasicType(), EvqConst, rightNode->getMatrixCols()));
    282         break;
    283 
    284     case EOpMod:
    285         for (int i = 0; i < newComps; i++) {
    286             if (rightUnionArray[i] == 0)
    287                 newConstArray[i] = leftUnionArray[i];
    288             else {
    289                 switch (getType().getBasicType()) {
    290                 case EbtInt:
    291                     if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == INT_MIN) {
    292                         newConstArray[i].setIConst(0);
    293                         break;
    294                     } else goto modulo_default;
    295 
    296                 case EbtInt64:
    297                     if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == LLONG_MIN) {
    298                         newConstArray[i].setI64Const(0);
    299                         break;
    300                     } else goto modulo_default;
    301 #ifdef AMD_EXTENSIONS
    302                 case EbtInt16:
    303                     if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == SHRT_MIN) {
    304                         newConstArray[i].setIConst(0);
    305                         break;
    306                     } else goto modulo_default;
    307 #endif
    308                 default:
    309                 modulo_default:
    310                     newConstArray[i] = leftUnionArray[i] % rightUnionArray[i];
    311                 }
    312             }
    313         }
    314         break;
    315 
    316     case EOpRightShift:
    317         for (int i = 0; i < newComps; i++)
    318             newConstArray[i] = leftUnionArray[i] >> rightUnionArray[i];
    319         break;
    320 
    321     case EOpLeftShift:
    322         for (int i = 0; i < newComps; i++)
    323             newConstArray[i] = leftUnionArray[i] << rightUnionArray[i];
    324         break;
    325 
    326     case EOpAnd:
    327         for (int i = 0; i < newComps; i++)
    328             newConstArray[i] = leftUnionArray[i] & rightUnionArray[i];
    329         break;
    330     case EOpInclusiveOr:
    331         for (int i = 0; i < newComps; i++)
    332             newConstArray[i] = leftUnionArray[i] | rightUnionArray[i];
    333         break;
    334     case EOpExclusiveOr:
    335         for (int i = 0; i < newComps; i++)
    336             newConstArray[i] = leftUnionArray[i] ^ rightUnionArray[i];
    337         break;
    338 
    339     case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
    340         for (int i = 0; i < newComps; i++)
    341             newConstArray[i] = leftUnionArray[i] && rightUnionArray[i];
    342         break;
    343 
    344     case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
    345         for (int i = 0; i < newComps; i++)
    346             newConstArray[i] = leftUnionArray[i] || rightUnionArray[i];
    347         break;
    348 
    349     case EOpLogicalXor:
    350         for (int i = 0; i < newComps; i++) {
    351             switch (getType().getBasicType()) {
    352             case EbtBool: newConstArray[i].setBConst((leftUnionArray[i] == rightUnionArray[i]) ? false : true); break;
    353             default: assert(false && "Default missing");
    354             }
    355         }
    356         break;
    357 
    358     case EOpLessThan:
    359         newConstArray[0].setBConst(leftUnionArray[0] < rightUnionArray[0]);
    360         returnType.shallowCopy(constBool);
    361         break;
    362     case EOpGreaterThan:
    363         newConstArray[0].setBConst(leftUnionArray[0] > rightUnionArray[0]);
    364         returnType.shallowCopy(constBool);
    365         break;
    366     case EOpLessThanEqual:
    367         newConstArray[0].setBConst(! (leftUnionArray[0] > rightUnionArray[0]));
    368         returnType.shallowCopy(constBool);
    369         break;
    370     case EOpGreaterThanEqual:
    371         newConstArray[0].setBConst(! (leftUnionArray[0] < rightUnionArray[0]));
    372         returnType.shallowCopy(constBool);
    373         break;
    374     case EOpEqual:
    375         newConstArray[0].setBConst(rightNode->getConstArray() == leftUnionArray);
    376         returnType.shallowCopy(constBool);
    377         break;
    378     case EOpNotEqual:
    379         newConstArray[0].setBConst(rightNode->getConstArray() != leftUnionArray);
    380         returnType.shallowCopy(constBool);
    381         break;
    382 
    383     default:
    384         return 0;
    385     }
    386 
    387     TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
    388     newNode->setLoc(getLoc());
    389 
    390     return newNode;
    391 }
    392 
    393 //
    394 // Do single unary node folding
    395 //
    396 // Returns a new node representing the result.
    397 //
    398 TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) const
    399 {
    400     // First, size the result, which is mostly the same as the argument's size,
    401     // but not always, and classify what is componentwise.
    402     // Also, eliminate cases that can't be compile-time constant.
    403     int resultSize;
    404     bool componentWise = true;
    405 
    406     int objectSize = getType().computeNumComponents();
    407     switch (op) {
    408     case EOpDeterminant:
    409     case EOpAny:
    410     case EOpAll:
    411     case EOpLength:
    412         componentWise = false;
    413         resultSize = 1;
    414         break;
    415 
    416     case EOpEmitStreamVertex:
    417     case EOpEndStreamPrimitive:
    418         // These don't actually fold
    419         return 0;
    420 
    421     case EOpPackSnorm2x16:
    422     case EOpPackUnorm2x16:
    423     case EOpPackHalf2x16:
    424         componentWise = false;
    425         resultSize = 1;
    426         break;
    427 
    428     case EOpUnpackSnorm2x16:
    429     case EOpUnpackUnorm2x16:
    430     case EOpUnpackHalf2x16:
    431         componentWise = false;
    432         resultSize = 2;
    433         break;
    434 
    435     case EOpPack16:
    436     case EOpPack32:
    437     case EOpPack64:
    438     case EOpUnpack32:
    439     case EOpUnpack16:
    440     case EOpUnpack8:
    441     case EOpNormalize:
    442         componentWise = false;
    443         resultSize = objectSize;
    444         break;
    445 
    446     default:
    447         resultSize = objectSize;
    448         break;
    449     }
    450 
    451     // Set up for processing
    452     TConstUnionArray newConstArray(resultSize);
    453     const TConstUnionArray& unionArray = getConstArray();
    454 
    455     // Process non-component-wise operations
    456     switch (op) {
    457     case EOpLength:
    458     case EOpNormalize:
    459     {
    460         double sum = 0;
    461         for (int i = 0; i < objectSize; i++)
    462             sum += unionArray[i].getDConst() * unionArray[i].getDConst();
    463         double length = sqrt(sum);
    464         if (op == EOpLength)
    465             newConstArray[0].setDConst(length);
    466         else {
    467             for (int i = 0; i < objectSize; i++)
    468                 newConstArray[i].setDConst(unionArray[i].getDConst() / length);
    469         }
    470         break;
    471     }
    472 
    473     case EOpAny:
    474     {
    475         bool result = false;
    476         for (int i = 0; i < objectSize; i++) {
    477             if (unionArray[i].getBConst())
    478                 result = true;
    479         }
    480         newConstArray[0].setBConst(result);
    481         break;
    482     }
    483     case EOpAll:
    484     {
    485         bool result = true;
    486         for (int i = 0; i < objectSize; i++) {
    487             if (! unionArray[i].getBConst())
    488                 result = false;
    489         }
    490         newConstArray[0].setBConst(result);
    491         break;
    492     }
    493 
    494     // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
    495 
    496     case EOpPackSnorm2x16:
    497     case EOpPackUnorm2x16:
    498     case EOpPackHalf2x16:
    499     case EOpPack16:
    500     case EOpPack32:
    501     case EOpPack64:
    502     case EOpUnpack32:
    503     case EOpUnpack16:
    504     case EOpUnpack8:
    505 
    506     case EOpUnpackSnorm2x16:
    507     case EOpUnpackUnorm2x16:
    508     case EOpUnpackHalf2x16:
    509 
    510     case EOpDeterminant:
    511     case EOpMatrixInverse:
    512     case EOpTranspose:
    513         return 0;
    514 
    515     default:
    516         assert(componentWise);
    517         break;
    518     }
    519 
    520     // Turn off the componentwise loop
    521     if (! componentWise)
    522         objectSize = 0;
    523 
    524     // Process component-wise operations
    525     for (int i = 0; i < objectSize; i++) {
    526         switch (op) {
    527         case EOpNegative:
    528             switch (getType().getBasicType()) {
    529             case EbtDouble:
    530             case EbtFloat16:
    531             case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
    532             case EbtInt8:  newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break;
    533             case EbtUint8: newConstArray[i].setU8Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU8Const())));  break;
    534             case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break;
    535             case EbtUint16:newConstArray[i].setU16Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU16Const())));  break;
    536             case EbtInt:   newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
    537             case EbtUint:  newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst())));  break;
    538             case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
    539             case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const())));  break;
    540             default:
    541                 return 0;
    542             }
    543             break;
    544         case EOpLogicalNot:
    545         case EOpVectorLogicalNot:
    546             switch (getType().getBasicType()) {
    547             case EbtBool:  newConstArray[i].setBConst(!unionArray[i].getBConst()); break;
    548             default:
    549                 return 0;
    550             }
    551             break;
    552         case EOpBitwiseNot:
    553             newConstArray[i] = ~unionArray[i];
    554             break;
    555         case EOpRadians:
    556             newConstArray[i].setDConst(unionArray[i].getDConst() * pi / 180.0);
    557             break;
    558         case EOpDegrees:
    559             newConstArray[i].setDConst(unionArray[i].getDConst() * 180.0 / pi);
    560             break;
    561         case EOpSin:
    562             newConstArray[i].setDConst(sin(unionArray[i].getDConst()));
    563             break;
    564         case EOpCos:
    565             newConstArray[i].setDConst(cos(unionArray[i].getDConst()));
    566             break;
    567         case EOpTan:
    568             newConstArray[i].setDConst(tan(unionArray[i].getDConst()));
    569             break;
    570         case EOpAsin:
    571             newConstArray[i].setDConst(asin(unionArray[i].getDConst()));
    572             break;
    573         case EOpAcos:
    574             newConstArray[i].setDConst(acos(unionArray[i].getDConst()));
    575             break;
    576         case EOpAtan:
    577             newConstArray[i].setDConst(atan(unionArray[i].getDConst()));
    578             break;
    579 
    580         case EOpDPdx:
    581         case EOpDPdy:
    582         case EOpFwidth:
    583         case EOpDPdxFine:
    584         case EOpDPdyFine:
    585         case EOpFwidthFine:
    586         case EOpDPdxCoarse:
    587         case EOpDPdyCoarse:
    588         case EOpFwidthCoarse:
    589             // The derivatives are all mandated to create a constant 0.
    590             newConstArray[i].setDConst(0.0);
    591             break;
    592 
    593         case EOpExp:
    594             newConstArray[i].setDConst(exp(unionArray[i].getDConst()));
    595             break;
    596         case EOpLog:
    597             newConstArray[i].setDConst(log(unionArray[i].getDConst()));
    598             break;
    599         case EOpExp2:
    600             {
    601                 const double inv_log2_e = 0.69314718055994530941723212145818;
    602                 newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e));
    603                 break;
    604             }
    605         case EOpLog2:
    606             {
    607                 const double log2_e = 1.4426950408889634073599246810019;
    608                 newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst()));
    609                 break;
    610             }
    611         case EOpSqrt:
    612             newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
    613             break;
    614         case EOpInverseSqrt:
    615             newConstArray[i].setDConst(1.0 / sqrt(unionArray[i].getDConst()));
    616             break;
    617 
    618         case EOpAbs:
    619             if (unionArray[i].getType() == EbtDouble)
    620                 newConstArray[i].setDConst(fabs(unionArray[i].getDConst()));
    621             else if (unionArray[i].getType() == EbtInt)
    622                 newConstArray[i].setIConst(abs(unionArray[i].getIConst()));
    623             else
    624                 newConstArray[i] = unionArray[i];
    625             break;
    626         case EOpSign:
    627             #define SIGN(X) (X == 0 ? 0 : (X < 0 ? -1 : 1))
    628             if (unionArray[i].getType() == EbtDouble)
    629                 newConstArray[i].setDConst(SIGN(unionArray[i].getDConst()));
    630             else
    631                 newConstArray[i].setIConst(SIGN(unionArray[i].getIConst()));
    632             break;
    633         case EOpFloor:
    634             newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
    635             break;
    636         case EOpTrunc:
    637             if (unionArray[i].getDConst() > 0)
    638                 newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
    639             else
    640                 newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
    641             break;
    642         case EOpRound:
    643             newConstArray[i].setDConst(floor(0.5 + unionArray[i].getDConst()));
    644             break;
    645         case EOpRoundEven:
    646         {
    647             double flr = floor(unionArray[i].getDConst());
    648             bool even = flr / 2.0 == floor(flr / 2.0);
    649             double rounded = even ? ceil(unionArray[i].getDConst() - 0.5) : floor(unionArray[i].getDConst() + 0.5);
    650             newConstArray[i].setDConst(rounded);
    651             break;
    652         }
    653         case EOpCeil:
    654             newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
    655             break;
    656         case EOpFract:
    657         {
    658             double x = unionArray[i].getDConst();
    659             newConstArray[i].setDConst(x - floor(x));
    660             break;
    661         }
    662 
    663         case EOpIsNan:
    664         {
    665             newConstArray[i].setBConst(isNan(unionArray[i].getDConst()));
    666             break;
    667         }
    668         case EOpIsInf:
    669         {
    670             newConstArray[i].setBConst(isInf(unionArray[i].getDConst()));
    671             break;
    672         }
    673 
    674         case EOpConvInt8ToBool:
    675             newConstArray[i].setBConst(unionArray[i].getI8Const() != 0); break;
    676         case EOpConvUint8ToBool:
    677             newConstArray[i].setBConst(unionArray[i].getU8Const() != 0); break;
    678         case EOpConvInt16ToBool:
    679             newConstArray[i].setBConst(unionArray[i].getI16Const() != 0); break;
    680         case EOpConvUint16ToBool:
    681             newConstArray[i].setBConst(unionArray[i].getU16Const() != 0); break;
    682         case EOpConvIntToBool:
    683             newConstArray[i].setBConst(unionArray[i].getIConst() != 0); break;
    684         case EOpConvUintToBool:
    685             newConstArray[i].setBConst(unionArray[i].getUConst() != 0); break;
    686         case EOpConvInt64ToBool:
    687             newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
    688         case EOpConvUint64ToBool:
    689             newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
    690         case EOpConvFloat16ToBool:
    691             newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
    692         case EOpConvFloatToBool:
    693             newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
    694         case EOpConvDoubleToBool:
    695             newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
    696 
    697         case EOpConvBoolToInt8:
    698             newConstArray[i].setI8Const(unionArray[i].getBConst()); break;
    699         case EOpConvBoolToUint8:
    700             newConstArray[i].setU8Const(unionArray[i].getBConst()); break;
    701         case EOpConvBoolToInt16:
    702             newConstArray[i].setI16Const(unionArray[i].getBConst()); break;
    703         case EOpConvBoolToUint16:
    704             newConstArray[i].setU16Const(unionArray[i].getBConst()); break;
    705         case EOpConvBoolToInt:
    706             newConstArray[i].setIConst(unionArray[i].getBConst()); break;
    707         case EOpConvBoolToUint:
    708             newConstArray[i].setUConst(unionArray[i].getBConst()); break;
    709         case EOpConvBoolToInt64:
    710             newConstArray[i].setI64Const(unionArray[i].getBConst()); break;
    711         case EOpConvBoolToUint64:
    712             newConstArray[i].setU64Const(unionArray[i].getBConst()); break;
    713         case EOpConvBoolToFloat16:
    714             newConstArray[i].setDConst(unionArray[i].getBConst()); break;
    715         case EOpConvBoolToFloat:
    716             newConstArray[i].setDConst(unionArray[i].getBConst()); break;
    717         case EOpConvBoolToDouble:
    718             newConstArray[i].setDConst(unionArray[i].getBConst()); break;
    719 
    720         case EOpConvInt8ToInt16:
    721             newConstArray[i].setI16Const(unionArray[i].getI8Const()); break;
    722         case EOpConvInt8ToInt:
    723             newConstArray[i].setIConst(unionArray[i].getI8Const()); break;
    724         case EOpConvInt8ToInt64:
    725             newConstArray[i].setI64Const(unionArray[i].getI8Const()); break;
    726         case EOpConvInt8ToUint8:
    727             newConstArray[i].setU8Const(unionArray[i].getI8Const()); break;
    728         case EOpConvInt8ToUint16:
    729             newConstArray[i].setU16Const(unionArray[i].getI8Const()); break;
    730         case EOpConvInt8ToUint:
    731             newConstArray[i].setUConst(unionArray[i].getI8Const()); break;
    732         case EOpConvInt8ToUint64:
    733             newConstArray[i].setU64Const(unionArray[i].getI8Const()); break;
    734         case EOpConvUint8ToInt8:
    735             newConstArray[i].setI8Const(unionArray[i].getU8Const()); break;
    736         case EOpConvUint8ToInt16:
    737             newConstArray[i].setI16Const(unionArray[i].getU8Const()); break;
    738         case EOpConvUint8ToInt:
    739             newConstArray[i].setIConst(unionArray[i].getU8Const()); break;
    740         case EOpConvUint8ToInt64:
    741             newConstArray[i].setI64Const(unionArray[i].getU8Const()); break;
    742         case EOpConvUint8ToUint16:
    743             newConstArray[i].setU16Const(unionArray[i].getU8Const()); break;
    744         case EOpConvUint8ToUint:
    745             newConstArray[i].setUConst(unionArray[i].getU8Const()); break;
    746         case EOpConvUint8ToUint64:
    747             newConstArray[i].setU64Const(unionArray[i].getU8Const()); break;
    748         case EOpConvInt8ToFloat16:
    749             newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
    750         case EOpConvInt8ToFloat:
    751             newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
    752         case EOpConvInt8ToDouble:
    753             newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
    754         case EOpConvUint8ToFloat16:
    755             newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
    756         case EOpConvUint8ToFloat:
    757             newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
    758         case EOpConvUint8ToDouble:
    759             newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
    760 
    761         case EOpConvInt16ToInt8:
    762             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI16Const())); break;
    763         case EOpConvInt16ToInt:
    764             newConstArray[i].setIConst(unionArray[i].getI16Const()); break;
    765         case EOpConvInt16ToInt64:
    766             newConstArray[i].setI64Const(unionArray[i].getI16Const()); break;
    767         case EOpConvInt16ToUint8:
    768             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI16Const())); break;
    769         case EOpConvInt16ToUint16:
    770             newConstArray[i].setU16Const(unionArray[i].getI16Const()); break;
    771         case EOpConvInt16ToUint:
    772             newConstArray[i].setUConst(unionArray[i].getI16Const()); break;
    773         case EOpConvInt16ToUint64:
    774             newConstArray[i].setU64Const(unionArray[i].getI16Const()); break;
    775         case EOpConvUint16ToInt8:
    776             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU16Const())); break;
    777         case EOpConvUint16ToInt16:
    778             newConstArray[i].setI16Const(unionArray[i].getU16Const()); break;
    779         case EOpConvUint16ToInt:
    780             newConstArray[i].setIConst(unionArray[i].getU16Const()); break;
    781         case EOpConvUint16ToInt64:
    782             newConstArray[i].setI64Const(unionArray[i].getU16Const()); break;
    783         case EOpConvUint16ToUint8:
    784             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU16Const())); break;
    785 
    786         case EOpConvUint16ToUint:
    787             newConstArray[i].setUConst(unionArray[i].getU16Const()); break;
    788         case EOpConvUint16ToUint64:
    789             newConstArray[i].setU64Const(unionArray[i].getU16Const()); break;
    790         case EOpConvInt16ToFloat16:
    791             newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
    792         case EOpConvInt16ToFloat:
    793             newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
    794         case EOpConvInt16ToDouble:
    795             newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
    796         case EOpConvUint16ToFloat16:
    797             newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
    798         case EOpConvUint16ToFloat:
    799             newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
    800         case EOpConvUint16ToDouble:
    801             newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
    802 
    803         case EOpConvIntToInt8:
    804             newConstArray[i].setI8Const((signed char)unionArray[i].getIConst()); break;
    805         case EOpConvIntToInt16:
    806             newConstArray[i].setI16Const((signed short)unionArray[i].getIConst()); break;
    807         case EOpConvIntToInt64:
    808             newConstArray[i].setI64Const(unionArray[i].getIConst()); break;
    809         case EOpConvIntToUint8:
    810             newConstArray[i].setU8Const((unsigned char)unionArray[i].getIConst()); break;
    811         case EOpConvIntToUint16:
    812             newConstArray[i].setU16Const((unsigned char)unionArray[i].getIConst()); break;
    813         case EOpConvIntToUint:
    814             newConstArray[i].setUConst(unionArray[i].getIConst()); break;
    815         case EOpConvIntToUint64:
    816             newConstArray[i].setU64Const(unionArray[i].getIConst()); break;
    817 
    818         case EOpConvUintToInt8:
    819             newConstArray[i].setI8Const((signed char)unionArray[i].getUConst()); break;
    820         case EOpConvUintToInt16:
    821             newConstArray[i].setI16Const((signed short)unionArray[i].getUConst()); break;
    822         case EOpConvUintToInt:
    823             newConstArray[i].setIConst(unionArray[i].getUConst()); break;
    824         case EOpConvUintToInt64:
    825             newConstArray[i].setI64Const(unionArray[i].getUConst()); break;
    826         case EOpConvUintToUint8:
    827             newConstArray[i].setU8Const((unsigned char)unionArray[i].getUConst()); break;
    828         case EOpConvUintToUint16:
    829             newConstArray[i].setU16Const((unsigned short)unionArray[i].getUConst()); break;
    830         case EOpConvUintToUint64:
    831             newConstArray[i].setU64Const(unionArray[i].getUConst()); break;
    832         case EOpConvIntToFloat16:
    833             newConstArray[i].setDConst(unionArray[i].getIConst()); break;
    834         case EOpConvIntToFloat:
    835             newConstArray[i].setDConst(unionArray[i].getIConst()); break;
    836         case EOpConvIntToDouble:
    837             newConstArray[i].setDConst(unionArray[i].getIConst()); break;
    838         case EOpConvUintToFloat16:
    839             newConstArray[i].setDConst(unionArray[i].getUConst()); break;
    840         case EOpConvUintToFloat:
    841             newConstArray[i].setDConst(unionArray[i].getUConst()); break;
    842         case EOpConvUintToDouble:
    843             newConstArray[i].setDConst(unionArray[i].getUConst()); break;
    844         case EOpConvInt64ToInt8:
    845             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI64Const())); break;
    846         case EOpConvInt64ToInt16:
    847             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getI64Const())); break;
    848         case EOpConvInt64ToInt:
    849             newConstArray[i].setIConst(static_cast<int>(unionArray[i].getI64Const())); break;
    850         case EOpConvInt64ToUint8:
    851             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI64Const())); break;
    852         case EOpConvInt64ToUint16:
    853             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getI64Const())); break;
    854         case EOpConvInt64ToUint:
    855             newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getI64Const())); break;
    856         case EOpConvInt64ToUint64:
    857             newConstArray[i].setU64Const(unionArray[i].getI64Const()); break;
    858         case EOpConvUint64ToInt8:
    859             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU64Const())); break;
    860         case EOpConvUint64ToInt16:
    861             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getU64Const())); break;
    862         case EOpConvUint64ToInt:
    863             newConstArray[i].setIConst(static_cast<int>(unionArray[i].getU64Const())); break;
    864         case EOpConvUint64ToInt64:
    865             newConstArray[i].setI64Const(unionArray[i].getU64Const()); break;
    866         case EOpConvUint64ToUint8:
    867             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU64Const())); break;
    868         case EOpConvUint64ToUint16:
    869             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getU64Const())); break;
    870         case EOpConvUint64ToUint:
    871             newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getU64Const())); break;
    872         case EOpConvInt64ToFloat16:
    873             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
    874         case EOpConvInt64ToFloat:
    875             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
    876         case EOpConvInt64ToDouble:
    877             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
    878         case EOpConvUint64ToFloat16:
    879             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
    880         case EOpConvUint64ToFloat:
    881             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
    882         case EOpConvUint64ToDouble:
    883             newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
    884         case EOpConvFloat16ToInt8:
    885             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
    886         case EOpConvFloat16ToInt16:
    887             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
    888         case EOpConvFloat16ToInt:
    889             newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
    890         case EOpConvFloat16ToInt64:
    891             newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
    892         case EOpConvFloat16ToUint8:
    893             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
    894         case EOpConvFloat16ToUint16:
    895             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
    896         case EOpConvFloat16ToUint:
    897             newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
    898         case EOpConvFloat16ToUint64:
    899             newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
    900         case EOpConvFloat16ToFloat:
    901             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
    902         case EOpConvFloat16ToDouble:
    903             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
    904         case EOpConvFloatToInt8:
    905             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
    906         case EOpConvFloatToInt16:
    907             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
    908         case EOpConvFloatToInt:
    909             newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
    910         case EOpConvFloatToInt64:
    911             newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
    912         case EOpConvFloatToUint8:
    913             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
    914         case EOpConvFloatToUint16:
    915             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
    916         case EOpConvFloatToUint:
    917             newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
    918         case EOpConvFloatToUint64:
    919             newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
    920         case EOpConvFloatToFloat16:
    921             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
    922         case EOpConvFloatToDouble:
    923             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
    924         case EOpConvDoubleToInt8:
    925             newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
    926         case EOpConvDoubleToInt16:
    927             newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
    928         case EOpConvDoubleToInt:
    929             newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
    930         case EOpConvDoubleToInt64:
    931             newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
    932         case EOpConvDoubleToUint8:
    933             newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
    934         case EOpConvDoubleToUint16:
    935             newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
    936         case EOpConvDoubleToUint:
    937             newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
    938         case EOpConvDoubleToUint64:
    939             newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
    940         case EOpConvDoubleToFloat16:
    941             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
    942         case EOpConvDoubleToFloat:
    943             newConstArray[i].setDConst(unionArray[i].getDConst()); break;
    944 
    945 
    946 
    947         // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
    948 
    949         case EOpSinh:
    950         case EOpCosh:
    951         case EOpTanh:
    952         case EOpAsinh:
    953         case EOpAcosh:
    954         case EOpAtanh:
    955 
    956         case EOpFloatBitsToInt:
    957         case EOpFloatBitsToUint:
    958         case EOpIntBitsToFloat:
    959         case EOpUintBitsToFloat:
    960         case EOpDoubleBitsToInt64:
    961         case EOpDoubleBitsToUint64:
    962         case EOpInt64BitsToDouble:
    963         case EOpUint64BitsToDouble:
    964         case EOpFloat16BitsToInt16:
    965         case EOpFloat16BitsToUint16:
    966         case EOpInt16BitsToFloat16:
    967         case EOpUint16BitsToFloat16:
    968         default:
    969             return 0;
    970         }
    971     }
    972 
    973     TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
    974     newNode->getWritableType().getQualifier().storage = EvqConst;
    975     newNode->setLoc(getLoc());
    976 
    977     return newNode;
    978 }
    979 
    980 //
    981 // Do constant folding for an aggregate node that has all its children
    982 // as constants and an operator that requires constant folding.
    983 //
    984 TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
    985 {
    986     if (aggrNode == nullptr)
    987         return aggrNode;
    988 
    989     if (! areAllChildConst(aggrNode))
    990         return aggrNode;
    991 
    992     if (aggrNode->isConstructor())
    993         return foldConstructor(aggrNode);
    994 
    995     TIntermSequence& children = aggrNode->getSequence();
    996 
    997     // First, see if this is an operation to constant fold, kick out if not,
    998     // see what size the result is if so.
    999 
   1000     bool componentwise = false;  // will also say componentwise if a scalar argument gets repeated to make per-component results
   1001     int objectSize;
   1002     switch (aggrNode->getOp()) {
   1003     case EOpAtan:
   1004     case EOpPow:
   1005     case EOpMin:
   1006     case EOpMax:
   1007     case EOpMix:
   1008     case EOpClamp:
   1009     case EOpLessThan:
   1010     case EOpGreaterThan:
   1011     case EOpLessThanEqual:
   1012     case EOpGreaterThanEqual:
   1013     case EOpVectorEqual:
   1014     case EOpVectorNotEqual:
   1015         componentwise = true;
   1016         objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
   1017         break;
   1018     case EOpCross:
   1019     case EOpReflect:
   1020     case EOpRefract:
   1021     case EOpFaceForward:
   1022         objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
   1023         break;
   1024     case EOpDistance:
   1025     case EOpDot:
   1026         objectSize = 1;
   1027         break;
   1028     case EOpOuterProduct:
   1029         objectSize = children[0]->getAsTyped()->getType().getVectorSize() *
   1030                      children[1]->getAsTyped()->getType().getVectorSize();
   1031         break;
   1032     case EOpStep:
   1033         componentwise = true;
   1034         objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
   1035                               children[1]->getAsTyped()->getType().getVectorSize());
   1036         break;
   1037     case EOpSmoothStep:
   1038         componentwise = true;
   1039         objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
   1040                               children[2]->getAsTyped()->getType().getVectorSize());
   1041         break;
   1042     default:
   1043         return aggrNode;
   1044     }
   1045     TConstUnionArray newConstArray(objectSize);
   1046 
   1047     TVector<TConstUnionArray> childConstUnions;
   1048     for (unsigned int arg = 0; arg < children.size(); ++arg)
   1049         childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray());
   1050 
   1051     if (componentwise) {
   1052         for (int comp = 0; comp < objectSize; comp++) {
   1053 
   1054             // some arguments are scalars instead of matching vectors; simulate a smear
   1055             int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1);
   1056             int arg1comp = 0;
   1057             if (children.size() > 1)
   1058                 arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1);
   1059             int arg2comp = 0;
   1060             if (children.size() > 2)
   1061                 arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1);
   1062 
   1063             switch (aggrNode->getOp()) {
   1064             case EOpAtan:
   1065                 newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
   1066                 break;
   1067             case EOpPow:
   1068                 newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
   1069                 break;
   1070             case EOpMin:
   1071                 switch(children[0]->getAsTyped()->getBasicType()) {
   1072                 case EbtFloat16:
   1073                 case EbtFloat:
   1074                 case EbtDouble:
   1075                     newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
   1076                     break;
   1077                 case EbtInt8:
   1078                     newConstArray[comp].setI8Const(std::min(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
   1079                     break;
   1080                 case EbtUint8:
   1081                     newConstArray[comp].setU8Const(std::min(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
   1082                     break;
   1083                 case EbtInt16:
   1084                     newConstArray[comp].setI16Const(std::min(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
   1085                     break;
   1086                 case EbtUint16:
   1087                     newConstArray[comp].setU16Const(std::min(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
   1088                     break;
   1089                 case EbtInt:
   1090                     newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
   1091                     break;
   1092                 case EbtUint:
   1093                     newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
   1094                     break;
   1095                 case EbtInt64:
   1096                     newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
   1097                     break;
   1098                 case EbtUint64:
   1099                     newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
   1100                     break;
   1101                 default: assert(false && "Default missing");
   1102                 }
   1103                 break;
   1104             case EOpMax:
   1105                 switch(children[0]->getAsTyped()->getBasicType()) {
   1106                 case EbtFloat16:
   1107                 case EbtFloat:
   1108                 case EbtDouble:
   1109                     newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
   1110                     break;
   1111                 case EbtInt8:
   1112                     newConstArray[comp].setI8Const(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
   1113                     break;
   1114                 case EbtUint8:
   1115                     newConstArray[comp].setU8Const(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
   1116                     break;
   1117                 case EbtInt16:
   1118                     newConstArray[comp].setI16Const(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
   1119                     break;
   1120                 case EbtUint16:
   1121                     newConstArray[comp].setU16Const(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
   1122                     break;
   1123                 case EbtInt:
   1124                     newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
   1125                     break;
   1126                 case EbtUint:
   1127                     newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
   1128                     break;
   1129                 case EbtInt64:
   1130                     newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
   1131                     break;
   1132                 case EbtUint64:
   1133                     newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
   1134                     break;
   1135                 default: assert(false && "Default missing");
   1136                 }
   1137                 break;
   1138             case EOpClamp:
   1139                 switch(children[0]->getAsTyped()->getBasicType()) {
   1140                 case EbtFloat16:
   1141                 case EbtFloat:
   1142                 case EbtDouble:
   1143                     newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()),
   1144                                                                                                                childConstUnions[2][arg2comp].getDConst()));
   1145                     break;
   1146                 case EbtInt8:
   1147                     newConstArray[comp].setI8Const(std::min(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()),
   1148                                                                                                                    childConstUnions[2][arg2comp].getI8Const()));
   1149                     break;
   1150                 case EbtUint8:
   1151                      newConstArray[comp].setU8Const(std::min(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()),
   1152                                                                                                                    childConstUnions[2][arg2comp].getU8Const()));
   1153                     break;
   1154                 case EbtInt16:
   1155                     newConstArray[comp].setI16Const(std::min(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()),
   1156                                                                                                                    childConstUnions[2][arg2comp].getI16Const()));
   1157                     break;
   1158                 case EbtUint16:
   1159                     newConstArray[comp].setU16Const(std::min(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()),
   1160                                                                                                                    childConstUnions[2][arg2comp].getU16Const()));
   1161                     break;
   1162                 case EbtInt:
   1163                     newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()),
   1164                                                                                                                    childConstUnions[2][arg2comp].getIConst()));
   1165                     break;
   1166                 case EbtUint:
   1167                     newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()),
   1168                                                                                                                    childConstUnions[2][arg2comp].getUConst()));
   1169                     break;
   1170                 case EbtInt64:
   1171                     newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()),
   1172                                                                                                                        childConstUnions[2][arg2comp].getI64Const()));
   1173                     break;
   1174                 case EbtUint64:
   1175                     newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()),
   1176                                                                                                                        childConstUnions[2][arg2comp].getU64Const()));
   1177                     break;
   1178                 default: assert(false && "Default missing");
   1179                 }
   1180                 break;
   1181             case EOpLessThan:
   1182                 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]);
   1183                 break;
   1184             case EOpGreaterThan:
   1185                 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]);
   1186                 break;
   1187             case EOpLessThanEqual:
   1188                 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]));
   1189                 break;
   1190             case EOpGreaterThanEqual:
   1191                 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]));
   1192                 break;
   1193             case EOpVectorEqual:
   1194                 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] == childConstUnions[1][arg1comp]);
   1195                 break;
   1196             case EOpVectorNotEqual:
   1197                 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] != childConstUnions[1][arg1comp]);
   1198                 break;
   1199             case EOpMix:
   1200                 if (children[2]->getAsTyped()->getBasicType() == EbtBool)
   1201                     newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst() ? childConstUnions[1][arg1comp].getDConst() :
   1202                                                                                               childConstUnions[0][arg0comp].getDConst());
   1203                 else
   1204                     newConstArray[comp].setDConst(childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) +
   1205                                                   childConstUnions[1][arg1comp].getDConst() *        childConstUnions[2][arg2comp].getDConst());
   1206                 break;
   1207             case EOpStep:
   1208                 newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0);
   1209                 break;
   1210             case EOpSmoothStep:
   1211             {
   1212                 double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) /
   1213                            (childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst());
   1214                 if (t < 0.0)
   1215                     t = 0.0;
   1216                 if (t > 1.0)
   1217                     t = 1.0;
   1218                 newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t));
   1219                 break;
   1220             }
   1221             default:
   1222                 return aggrNode;
   1223             }
   1224         }
   1225     } else {
   1226         // Non-componentwise...
   1227 
   1228         int numComps = children[0]->getAsConstantUnion()->getType().computeNumComponents();
   1229         double dot;
   1230 
   1231         switch (aggrNode->getOp()) {
   1232         case EOpDistance:
   1233         {
   1234             double sum = 0.0;
   1235             for (int comp = 0; comp < numComps; ++comp) {
   1236                 double diff = childConstUnions[1][comp].getDConst() - childConstUnions[0][comp].getDConst();
   1237                 sum += diff * diff;
   1238             }
   1239             newConstArray[0].setDConst(sqrt(sum));
   1240             break;
   1241         }
   1242         case EOpDot:
   1243             newConstArray[0].setDConst(childConstUnions[0].dot(childConstUnions[1]));
   1244             break;
   1245         case EOpCross:
   1246             newConstArray[0] = childConstUnions[0][1] * childConstUnions[1][2] - childConstUnions[0][2] * childConstUnions[1][1];
   1247             newConstArray[1] = childConstUnions[0][2] * childConstUnions[1][0] - childConstUnions[0][0] * childConstUnions[1][2];
   1248             newConstArray[2] = childConstUnions[0][0] * childConstUnions[1][1] - childConstUnions[0][1] * childConstUnions[1][0];
   1249             break;
   1250         case EOpFaceForward:
   1251             // If dot(Nref, I) < 0 return N, otherwise return -N:  Arguments are (N, I, Nref).
   1252             dot = childConstUnions[1].dot(childConstUnions[2]);
   1253             for (int comp = 0; comp < numComps; ++comp) {
   1254                 if (dot < 0.0)
   1255                     newConstArray[comp] = childConstUnions[0][comp];
   1256                 else
   1257                     newConstArray[comp].setDConst(-childConstUnions[0][comp].getDConst());
   1258             }
   1259             break;
   1260         case EOpReflect:
   1261             // I - 2 * dot(N, I) * N:  Arguments are (I, N).
   1262             dot = childConstUnions[0].dot(childConstUnions[1]);
   1263             dot *= 2.0;
   1264             for (int comp = 0; comp < numComps; ++comp)
   1265                 newConstArray[comp].setDConst(childConstUnions[0][comp].getDConst() - dot * childConstUnions[1][comp].getDConst());
   1266             break;
   1267         case EOpRefract:
   1268         {
   1269             // Arguments are (I, N, eta).
   1270             // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
   1271             // if (k < 0.0)
   1272             //     return dvec(0.0)
   1273             // else
   1274             //     return eta * I - (eta * dot(N, I) + sqrt(k)) * N
   1275             dot = childConstUnions[0].dot(childConstUnions[1]);
   1276             double eta = childConstUnions[2][0].getDConst();
   1277             double k = 1.0 - eta * eta * (1.0 - dot * dot);
   1278             if (k < 0.0) {
   1279                 for (int comp = 0; comp < numComps; ++comp)
   1280                     newConstArray[comp].setDConst(0.0);
   1281             } else {
   1282                 for (int comp = 0; comp < numComps; ++comp)
   1283                     newConstArray[comp].setDConst(eta * childConstUnions[0][comp].getDConst() - (eta * dot + sqrt(k)) * childConstUnions[1][comp].getDConst());
   1284             }
   1285             break;
   1286         }
   1287         case EOpOuterProduct:
   1288         {
   1289             int numRows = numComps;
   1290             int numCols = children[1]->getAsConstantUnion()->getType().computeNumComponents();
   1291             for (int row = 0; row < numRows; ++row)
   1292                 for (int col = 0; col < numCols; ++col)
   1293                     newConstArray[col * numRows + row] = childConstUnions[0][row] * childConstUnions[1][col];
   1294             break;
   1295         }
   1296         default:
   1297             return aggrNode;
   1298         }
   1299     }
   1300 
   1301     TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType());
   1302     newNode->getWritableType().getQualifier().storage = EvqConst;
   1303     newNode->setLoc(aggrNode->getLoc());
   1304 
   1305     return newNode;
   1306 }
   1307 
   1308 bool TIntermediate::areAllChildConst(TIntermAggregate* aggrNode)
   1309 {
   1310     bool allConstant = true;
   1311 
   1312     // check if all the child nodes are constants so that they can be inserted into
   1313     // the parent node
   1314     if (aggrNode) {
   1315         TIntermSequence& childSequenceVector = aggrNode->getSequence();
   1316         for (TIntermSequence::iterator p  = childSequenceVector.begin();
   1317                                        p != childSequenceVector.end(); p++) {
   1318             if (!(*p)->getAsTyped()->getAsConstantUnion())
   1319                 return false;
   1320         }
   1321     }
   1322 
   1323     return allConstant;
   1324 }
   1325 
   1326 TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode)
   1327 {
   1328     bool error = false;
   1329 
   1330     TConstUnionArray unionArray(aggrNode->getType().computeNumComponents());
   1331     if (aggrNode->getSequence().size() == 1)
   1332         error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true);
   1333     else
   1334         error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType());
   1335 
   1336     if (error)
   1337         return aggrNode;
   1338 
   1339     return addConstantUnion(unionArray, aggrNode->getType(), aggrNode->getLoc());
   1340 }
   1341 
   1342 //
   1343 // Constant folding of a bracket (array-style) dereference or struct-like dot
   1344 // dereference.  Can handle anything except a multi-character swizzle, though
   1345 // all swizzles may go to foldSwizzle().
   1346 //
   1347 TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, const TSourceLoc& loc)
   1348 {
   1349     TType dereferencedType(node->getType(), index);
   1350     dereferencedType.getQualifier().storage = EvqConst;
   1351     TIntermTyped* result = 0;
   1352     int size = dereferencedType.computeNumComponents();
   1353 
   1354     // arrays, vectors, matrices, all use simple multiplicative math
   1355     // while structures need to add up heterogeneous members
   1356     int start;
   1357     if (node->isArray() || ! node->isStruct())
   1358         start = size * index;
   1359     else {
   1360         // it is a structure
   1361         assert(node->isStruct());
   1362         start = 0;
   1363         for (int i = 0; i < index; ++i)
   1364             start += (*node->getType().getStruct())[i].type->computeNumComponents();
   1365     }
   1366 
   1367     result = addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), start, size), node->getType(), loc);
   1368 
   1369     if (result == 0)
   1370         result = node;
   1371     else
   1372         result->setType(dereferencedType);
   1373 
   1374     return result;
   1375 }
   1376 
   1377 //
   1378 // Make a constant vector node or constant scalar node, representing a given
   1379 // constant vector and constant swizzle into it.
   1380 //
   1381 TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& selectors, const TSourceLoc& loc)
   1382 {
   1383     const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray();
   1384     TConstUnionArray constArray(selectors.size());
   1385 
   1386     for (int i = 0; i < selectors.size(); i++)
   1387         constArray[i] = unionArray[selectors[i]];
   1388 
   1389     TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc);
   1390 
   1391     if (result == 0)
   1392         result = node;
   1393     else
   1394         result->setType(TType(node->getBasicType(), EvqConst, selectors.size()));
   1395 
   1396     return result;
   1397 }
   1398 
   1399 } // end namespace glslang
   1400