2 // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
3 // Copyright (C) 2012-2013 LunarG, Inc.
4 // Copyright (C) 2017 ARM Limited.
6 // All rights reserved.
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
12 // Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
15 // Redistributions in binary form must reproduce the above
16 // copyright notice, this list of conditions and the following
17 // disclaimer in the documentation and/or other materials provided
18 // with the distribution.
20 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
21 // contributors may be used to endorse or promote products derived
22 // from this software without specific prior written permission.
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 // POSSIBILITY OF SUCH DAMAGE.
38 #include "localintermediate.h"
46 using namespace glslang;
53 // Some helper functions
58 // tough to find a platform independent library function, do it directly
60 int bitPatternL = u.i[0];
61 int bitPatternH = u.i[1];
62 return (bitPatternH & 0x7ff80000) == 0x7ff80000 &&
63 ((bitPatternH & 0xFFFFF) != 0 || bitPatternL != 0);
69 // tough to find a platform independent library function, do it directly
71 int bitPatternL = u.i[0];
72 int bitPatternH = u.i[1];
73 return (bitPatternH & 0x7ff00000) == 0x7ff00000 &&
74 (bitPatternH & 0xFFFFF) == 0 && bitPatternL == 0;
77 const double pi = 3.1415926535897932384626433832795;
79 } // end anonymous namespace
85 // The fold functions see if an operation on a constant can be done in place,
86 // without generating run-time code.
88 // Returns the node to keep using, which may or may not be the node passed in.
90 // Note: As of version 1.2, all constant operations must be folded. It is
91 // not opportunistic, but rather a semantic requirement.
95 // Do folding between a pair of nodes.
96 // 'this' is the left-hand operand and 'rightConstantNode' is the right-hand operand.
98 // Returns a new node representing the result.
100 TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* rightConstantNode) const
102 // For most cases, the return type matches the argument type, so set that
103 // up and just code to exceptions below.
105 returnType.shallowCopy(getType());
108 // A pair of nodes is to be folded together
111 const TIntermConstantUnion *rightNode = rightConstantNode->getAsConstantUnion();
112 TConstUnionArray leftUnionArray = getConstArray();
113 TConstUnionArray rightUnionArray = rightNode->getConstArray();
115 // Figure out the size of the result
119 case EOpMatrixTimesMatrix:
120 newComps = rightNode->getMatrixCols() * getMatrixRows();
122 case EOpMatrixTimesVector:
123 newComps = getMatrixRows();
125 case EOpVectorTimesMatrix:
126 newComps = rightNode->getMatrixCols();
129 newComps = getType().computeNumComponents();
130 constComps = rightConstantNode->getType().computeNumComponents();
131 if (constComps == 1 && newComps > 1) {
132 // for a case like vec4 f = vec4(2,3,4,5) + 1.2;
133 TConstUnionArray smearedArray(newComps, rightNode->getConstArray()[0]);
134 rightUnionArray = smearedArray;
135 } else if (constComps > 1 && newComps == 1) {
136 // for a case like vec4 f = 1.2 + vec4(2,3,4,5);
137 newComps = constComps;
138 rightUnionArray = rightNode->getConstArray();
139 TConstUnionArray smearedArray(newComps, getConstArray()[0]);
140 leftUnionArray = smearedArray;
141 returnType.shallowCopy(rightNode->getType());
146 TConstUnionArray newConstArray(newComps);
147 TType constBool(EbtBool, EvqConst);
151 for (int i = 0; i < newComps; i++)
152 newConstArray[i] = leftUnionArray[i] + rightUnionArray[i];
155 for (int i = 0; i < newComps; i++)
156 newConstArray[i] = leftUnionArray[i] - rightUnionArray[i];
160 case EOpVectorTimesScalar:
161 case EOpMatrixTimesScalar:
162 for (int i = 0; i < newComps; i++)
163 newConstArray[i] = leftUnionArray[i] * rightUnionArray[i];
165 case EOpMatrixTimesMatrix:
166 for (int row = 0; row < getMatrixRows(); row++) {
167 for (int column = 0; column < rightNode->getMatrixCols(); column++) {
169 for (int i = 0; i < rightNode->getMatrixRows(); i++)
170 sum += leftUnionArray[i * getMatrixRows() + row].getDConst() * rightUnionArray[column * rightNode->getMatrixRows() + i].getDConst();
171 newConstArray[column * getMatrixRows() + row].setDConst(sum);
174 returnType.shallowCopy(TType(getType().getBasicType(), EvqConst, 0, rightNode->getMatrixCols(), getMatrixRows()));
177 for (int i = 0; i < newComps; i++) {
178 switch (getType().getBasicType()) {
182 if (rightUnionArray[i].getDConst() != 0.0)
183 newConstArray[i].setDConst(leftUnionArray[i].getDConst() / rightUnionArray[i].getDConst());
184 else if (leftUnionArray[i].getDConst() > 0.0)
185 newConstArray[i].setDConst((double)INFINITY);
186 else if (leftUnionArray[i].getDConst() < 0.0)
187 newConstArray[i].setDConst(-(double)INFINITY);
189 newConstArray[i].setDConst((double)NAN);
192 if (rightUnionArray[i] == (signed char)0)
193 newConstArray[i].setI8Const((signed char)0x7F);
194 else if (rightUnionArray[i].getI8Const() == (signed char)-1 && leftUnionArray[i].getI8Const() == (signed char)-0x80)
195 newConstArray[i].setI8Const((signed char)-0x80);
197 newConstArray[i].setI8Const(leftUnionArray[i].getI8Const() / rightUnionArray[i].getI8Const());
201 if (rightUnionArray[i] == (unsigned char)0u)
202 newConstArray[i].setU8Const((unsigned char)0xFFu);
204 newConstArray[i].setU8Const(leftUnionArray[i].getU8Const() / rightUnionArray[i].getU8Const());
208 if (rightUnionArray[i] == (signed short)0)
209 newConstArray[i].setI16Const((signed short)0x7FFF);
210 else if (rightUnionArray[i].getI16Const() == (signed short)-1 && leftUnionArray[i].getI16Const() == (signed short)-0x8000)
211 newConstArray[i].setI16Const((signed short)-0x8000);
213 newConstArray[i].setI16Const(leftUnionArray[i].getI16Const() / rightUnionArray[i].getI16Const());
217 if (rightUnionArray[i] == (unsigned short)0u)
218 newConstArray[i].setU16Const((unsigned short)0xFFFFu);
220 newConstArray[i].setU16Const(leftUnionArray[i].getU16Const() / rightUnionArray[i].getU16Const());
224 if (rightUnionArray[i] == 0)
225 newConstArray[i].setIConst(0x7FFFFFFF);
226 else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)-0x80000000ll)
227 newConstArray[i].setIConst((int)-0x80000000ll);
229 newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
233 if (rightUnionArray[i] == 0u)
234 newConstArray[i].setUConst(0xFFFFFFFFu);
236 newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
240 if (rightUnionArray[i] == 0ll)
241 newConstArray[i].setI64Const(0x7FFFFFFFFFFFFFFFll);
242 else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == (long long)-0x8000000000000000ll)
243 newConstArray[i].setI64Const((long long)-0x8000000000000000ll);
245 newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const());
249 if (rightUnionArray[i] == 0ull)
250 newConstArray[i].setU64Const(0xFFFFFFFFFFFFFFFFull);
252 newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const());
260 case EOpMatrixTimesVector:
261 for (int i = 0; i < getMatrixRows(); i++) {
263 for (int j = 0; j < rightNode->getVectorSize(); j++) {
264 sum += leftUnionArray[j*getMatrixRows() + i].getDConst() * rightUnionArray[j].getDConst();
266 newConstArray[i].setDConst(sum);
269 returnType.shallowCopy(TType(getBasicType(), EvqConst, getMatrixRows()));
272 case EOpVectorTimesMatrix:
273 for (int i = 0; i < rightNode->getMatrixCols(); i++) {
275 for (int j = 0; j < getVectorSize(); j++)
276 sum += leftUnionArray[j].getDConst() * rightUnionArray[i*rightNode->getMatrixRows() + j].getDConst();
277 newConstArray[i].setDConst(sum);
280 returnType.shallowCopy(TType(getBasicType(), EvqConst, rightNode->getMatrixCols()));
284 for (int i = 0; i < newComps; i++) {
285 if (rightUnionArray[i] == 0)
286 newConstArray[i] = leftUnionArray[i];
288 switch (getType().getBasicType()) {
290 if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == INT_MIN) {
291 newConstArray[i].setIConst(0);
293 } else goto modulo_default;
296 if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == LLONG_MIN) {
297 newConstArray[i].setI64Const(0);
299 } else goto modulo_default;
300 #ifdef AMD_EXTENSIONS
302 if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == SHRT_MIN) {
303 newConstArray[i].setIConst(0);
305 } else goto modulo_default;
309 newConstArray[i] = leftUnionArray[i] % rightUnionArray[i];
316 for (int i = 0; i < newComps; i++)
317 newConstArray[i] = leftUnionArray[i] >> rightUnionArray[i];
321 for (int i = 0; i < newComps; i++)
322 newConstArray[i] = leftUnionArray[i] << rightUnionArray[i];
326 for (int i = 0; i < newComps; i++)
327 newConstArray[i] = leftUnionArray[i] & rightUnionArray[i];
330 for (int i = 0; i < newComps; i++)
331 newConstArray[i] = leftUnionArray[i] | rightUnionArray[i];
334 for (int i = 0; i < newComps; i++)
335 newConstArray[i] = leftUnionArray[i] ^ rightUnionArray[i];
338 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
339 for (int i = 0; i < newComps; i++)
340 newConstArray[i] = leftUnionArray[i] && rightUnionArray[i];
343 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
344 for (int i = 0; i < newComps; i++)
345 newConstArray[i] = leftUnionArray[i] || rightUnionArray[i];
349 for (int i = 0; i < newComps; i++) {
350 switch (getType().getBasicType()) {
351 case EbtBool: newConstArray[i].setBConst((leftUnionArray[i] == rightUnionArray[i]) ? false : true); break;
352 default: assert(false && "Default missing");
358 newConstArray[0].setBConst(leftUnionArray[0] < rightUnionArray[0]);
359 returnType.shallowCopy(constBool);
362 newConstArray[0].setBConst(leftUnionArray[0] > rightUnionArray[0]);
363 returnType.shallowCopy(constBool);
365 case EOpLessThanEqual:
366 newConstArray[0].setBConst(! (leftUnionArray[0] > rightUnionArray[0]));
367 returnType.shallowCopy(constBool);
369 case EOpGreaterThanEqual:
370 newConstArray[0].setBConst(! (leftUnionArray[0] < rightUnionArray[0]));
371 returnType.shallowCopy(constBool);
374 newConstArray[0].setBConst(rightNode->getConstArray() == leftUnionArray);
375 returnType.shallowCopy(constBool);
378 newConstArray[0].setBConst(rightNode->getConstArray() != leftUnionArray);
379 returnType.shallowCopy(constBool);
386 TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
387 newNode->setLoc(getLoc());
393 // Do single unary node folding
395 // Returns a new node representing the result.
397 TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) const
399 // First, size the result, which is mostly the same as the argument's size,
400 // but not always, and classify what is componentwise.
401 // Also, eliminate cases that can't be compile-time constant.
403 bool componentWise = true;
405 int objectSize = getType().computeNumComponents();
411 componentWise = false;
415 case EOpEmitStreamVertex:
416 case EOpEndStreamPrimitive:
417 // These don't actually fold
420 case EOpPackSnorm2x16:
421 case EOpPackUnorm2x16:
422 case EOpPackHalf2x16:
423 componentWise = false;
427 case EOpUnpackSnorm2x16:
428 case EOpUnpackUnorm2x16:
429 case EOpUnpackHalf2x16:
430 componentWise = false;
441 componentWise = false;
442 resultSize = objectSize;
446 resultSize = objectSize;
450 // Set up for processing
451 TConstUnionArray newConstArray(resultSize);
452 const TConstUnionArray& unionArray = getConstArray();
454 // Process non-component-wise operations
460 for (int i = 0; i < objectSize; i++)
461 sum += unionArray[i].getDConst() * unionArray[i].getDConst();
462 double length = sqrt(sum);
464 newConstArray[0].setDConst(length);
466 for (int i = 0; i < objectSize; i++)
467 newConstArray[i].setDConst(unionArray[i].getDConst() / length);
475 for (int i = 0; i < objectSize; i++) {
476 if (unionArray[i].getBConst())
479 newConstArray[0].setBConst(result);
485 for (int i = 0; i < objectSize; i++) {
486 if (! unionArray[i].getBConst())
489 newConstArray[0].setBConst(result);
493 // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
495 case EOpPackSnorm2x16:
496 case EOpPackUnorm2x16:
497 case EOpPackHalf2x16:
505 case EOpUnpackSnorm2x16:
506 case EOpUnpackUnorm2x16:
507 case EOpUnpackHalf2x16:
510 case EOpMatrixInverse:
515 assert(componentWise);
519 // Turn off the componentwise loop
523 // Process component-wise operations
524 for (int i = 0; i < objectSize; i++) {
527 switch (getType().getBasicType()) {
530 case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
531 case EbtInt8: newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break;
532 case EbtUint8: newConstArray[i].setU8Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU8Const()))); break;
533 case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break;
534 case EbtUint16:newConstArray[i].setU16Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU16Const()))); break;
535 case EbtInt: newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
536 case EbtUint: newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
537 case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
538 case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const()))); break;
544 case EOpVectorLogicalNot:
545 switch (getType().getBasicType()) {
546 case EbtBool: newConstArray[i].setBConst(!unionArray[i].getBConst()); break;
552 newConstArray[i] = ~unionArray[i];
555 newConstArray[i].setDConst(unionArray[i].getDConst() * pi / 180.0);
558 newConstArray[i].setDConst(unionArray[i].getDConst() * 180.0 / pi);
561 newConstArray[i].setDConst(sin(unionArray[i].getDConst()));
564 newConstArray[i].setDConst(cos(unionArray[i].getDConst()));
567 newConstArray[i].setDConst(tan(unionArray[i].getDConst()));
570 newConstArray[i].setDConst(asin(unionArray[i].getDConst()));
573 newConstArray[i].setDConst(acos(unionArray[i].getDConst()));
576 newConstArray[i].setDConst(atan(unionArray[i].getDConst()));
587 case EOpFwidthCoarse:
588 // The derivatives are all mandated to create a constant 0.
589 newConstArray[i].setDConst(0.0);
593 newConstArray[i].setDConst(exp(unionArray[i].getDConst()));
596 newConstArray[i].setDConst(log(unionArray[i].getDConst()));
600 const double inv_log2_e = 0.69314718055994530941723212145818;
601 newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e));
606 const double log2_e = 1.4426950408889634073599246810019;
607 newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst()));
611 newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
614 newConstArray[i].setDConst(1.0 / sqrt(unionArray[i].getDConst()));
618 if (unionArray[i].getType() == EbtDouble)
619 newConstArray[i].setDConst(fabs(unionArray[i].getDConst()));
620 else if (unionArray[i].getType() == EbtInt)
621 newConstArray[i].setIConst(abs(unionArray[i].getIConst()));
623 newConstArray[i] = unionArray[i];
626 #define SIGN(X) (X == 0 ? 0 : (X < 0 ? -1 : 1))
627 if (unionArray[i].getType() == EbtDouble)
628 newConstArray[i].setDConst(SIGN(unionArray[i].getDConst()));
630 newConstArray[i].setIConst(SIGN(unionArray[i].getIConst()));
633 newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
636 if (unionArray[i].getDConst() > 0)
637 newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
639 newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
642 newConstArray[i].setDConst(floor(0.5 + unionArray[i].getDConst()));
646 double flr = floor(unionArray[i].getDConst());
647 bool even = flr / 2.0 == floor(flr / 2.0);
648 double rounded = even ? ceil(unionArray[i].getDConst() - 0.5) : floor(unionArray[i].getDConst() + 0.5);
649 newConstArray[i].setDConst(rounded);
653 newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
657 double x = unionArray[i].getDConst();
658 newConstArray[i].setDConst(x - floor(x));
664 newConstArray[i].setBConst(isNan(unionArray[i].getDConst()));
669 newConstArray[i].setBConst(isInf(unionArray[i].getDConst()));
673 // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
682 case EOpFloatBitsToInt:
683 case EOpFloatBitsToUint:
684 case EOpIntBitsToFloat:
685 case EOpUintBitsToFloat:
686 case EOpDoubleBitsToInt64:
687 case EOpDoubleBitsToUint64:
688 case EOpInt64BitsToDouble:
689 case EOpUint64BitsToDouble:
690 case EOpFloat16BitsToInt16:
691 case EOpFloat16BitsToUint16:
692 case EOpInt16BitsToFloat16:
693 case EOpUint16BitsToFloat16:
699 TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
700 newNode->getWritableType().getQualifier().storage = EvqConst;
701 newNode->setLoc(getLoc());
707 // Do constant folding for an aggregate node that has all its children
708 // as constants and an operator that requires constant folding.
710 TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
712 if (aggrNode == nullptr)
715 if (! areAllChildConst(aggrNode))
718 if (aggrNode->isConstructor())
719 return foldConstructor(aggrNode);
721 TIntermSequence& children = aggrNode->getSequence();
723 // First, see if this is an operation to constant fold, kick out if not,
724 // see what size the result is if so.
726 bool componentwise = false; // will also say componentwise if a scalar argument gets repeated to make per-component results
728 switch (aggrNode->getOp()) {
737 case EOpLessThanEqual:
738 case EOpGreaterThanEqual:
740 case EOpVectorNotEqual:
741 componentwise = true;
742 objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
748 objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
754 case EOpOuterProduct:
755 objectSize = children[0]->getAsTyped()->getType().getVectorSize() *
756 children[1]->getAsTyped()->getType().getVectorSize();
759 componentwise = true;
760 objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
761 children[1]->getAsTyped()->getType().getVectorSize());
764 componentwise = true;
765 objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
766 children[2]->getAsTyped()->getType().getVectorSize());
771 TConstUnionArray newConstArray(objectSize);
773 TVector<TConstUnionArray> childConstUnions;
774 for (unsigned int arg = 0; arg < children.size(); ++arg)
775 childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray());
778 for (int comp = 0; comp < objectSize; comp++) {
780 // some arguments are scalars instead of matching vectors; simulate a smear
781 int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1);
783 if (children.size() > 1)
784 arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1);
786 if (children.size() > 2)
787 arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1);
789 switch (aggrNode->getOp()) {
791 newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
794 newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
797 switch(children[0]->getAsTyped()->getBasicType()) {
801 newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
804 newConstArray[comp].setI8Const(std::min(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
807 newConstArray[comp].setU8Const(std::min(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
810 newConstArray[comp].setI16Const(std::min(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
813 newConstArray[comp].setU16Const(std::min(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
816 newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
819 newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
822 newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
825 newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
827 default: assert(false && "Default missing");
831 switch(children[0]->getAsTyped()->getBasicType()) {
835 newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
838 newConstArray[comp].setI8Const(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
841 newConstArray[comp].setU8Const(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
844 newConstArray[comp].setI16Const(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
847 newConstArray[comp].setU16Const(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
850 newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
853 newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
856 newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
859 newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
861 default: assert(false && "Default missing");
865 switch(children[0]->getAsTyped()->getBasicType()) {
869 newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()),
870 childConstUnions[2][arg2comp].getDConst()));
873 newConstArray[comp].setI8Const(std::min(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()),
874 childConstUnions[2][arg2comp].getI8Const()));
877 newConstArray[comp].setU8Const(std::min(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()),
878 childConstUnions[2][arg2comp].getU8Const()));
881 newConstArray[comp].setI16Const(std::min(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()),
882 childConstUnions[2][arg2comp].getI16Const()));
885 newConstArray[comp].setU16Const(std::min(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()),
886 childConstUnions[2][arg2comp].getU16Const()));
889 newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()),
890 childConstUnions[2][arg2comp].getIConst()));
893 newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()),
894 childConstUnions[2][arg2comp].getUConst()));
897 newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()),
898 childConstUnions[2][arg2comp].getI64Const()));
901 newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()),
902 childConstUnions[2][arg2comp].getU64Const()));
904 default: assert(false && "Default missing");
908 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]);
911 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]);
913 case EOpLessThanEqual:
914 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]));
916 case EOpGreaterThanEqual:
917 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]));
920 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] == childConstUnions[1][arg1comp]);
922 case EOpVectorNotEqual:
923 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] != childConstUnions[1][arg1comp]);
926 if (children[2]->getAsTyped()->getBasicType() == EbtBool)
927 newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst() ? childConstUnions[1][arg1comp].getDConst() :
928 childConstUnions[0][arg0comp].getDConst());
930 newConstArray[comp].setDConst(childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) +
931 childConstUnions[1][arg1comp].getDConst() * childConstUnions[2][arg2comp].getDConst());
934 newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0);
938 double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) /
939 (childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst());
944 newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t));
952 // Non-componentwise...
954 int numComps = children[0]->getAsConstantUnion()->getType().computeNumComponents();
957 switch (aggrNode->getOp()) {
961 for (int comp = 0; comp < numComps; ++comp) {
962 double diff = childConstUnions[1][comp].getDConst() - childConstUnions[0][comp].getDConst();
965 newConstArray[0].setDConst(sqrt(sum));
969 newConstArray[0].setDConst(childConstUnions[0].dot(childConstUnions[1]));
972 newConstArray[0] = childConstUnions[0][1] * childConstUnions[1][2] - childConstUnions[0][2] * childConstUnions[1][1];
973 newConstArray[1] = childConstUnions[0][2] * childConstUnions[1][0] - childConstUnions[0][0] * childConstUnions[1][2];
974 newConstArray[2] = childConstUnions[0][0] * childConstUnions[1][1] - childConstUnions[0][1] * childConstUnions[1][0];
977 // If dot(Nref, I) < 0 return N, otherwise return -N: Arguments are (N, I, Nref).
978 dot = childConstUnions[1].dot(childConstUnions[2]);
979 for (int comp = 0; comp < numComps; ++comp) {
981 newConstArray[comp] = childConstUnions[0][comp];
983 newConstArray[comp].setDConst(-childConstUnions[0][comp].getDConst());
987 // I - 2 * dot(N, I) * N: Arguments are (I, N).
988 dot = childConstUnions[0].dot(childConstUnions[1]);
990 for (int comp = 0; comp < numComps; ++comp)
991 newConstArray[comp].setDConst(childConstUnions[0][comp].getDConst() - dot * childConstUnions[1][comp].getDConst());
995 // Arguments are (I, N, eta).
996 // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
1000 // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
1001 dot = childConstUnions[0].dot(childConstUnions[1]);
1002 double eta = childConstUnions[2][0].getDConst();
1003 double k = 1.0 - eta * eta * (1.0 - dot * dot);
1005 for (int comp = 0; comp < numComps; ++comp)
1006 newConstArray[comp].setDConst(0.0);
1008 for (int comp = 0; comp < numComps; ++comp)
1009 newConstArray[comp].setDConst(eta * childConstUnions[0][comp].getDConst() - (eta * dot + sqrt(k)) * childConstUnions[1][comp].getDConst());
1013 case EOpOuterProduct:
1015 int numRows = numComps;
1016 int numCols = children[1]->getAsConstantUnion()->getType().computeNumComponents();
1017 for (int row = 0; row < numRows; ++row)
1018 for (int col = 0; col < numCols; ++col)
1019 newConstArray[col * numRows + row] = childConstUnions[0][row] * childConstUnions[1][col];
1027 TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType());
1028 newNode->getWritableType().getQualifier().storage = EvqConst;
1029 newNode->setLoc(aggrNode->getLoc());
1034 bool TIntermediate::areAllChildConst(TIntermAggregate* aggrNode)
1036 bool allConstant = true;
1038 // check if all the child nodes are constants so that they can be inserted into
1041 TIntermSequence& childSequenceVector = aggrNode->getSequence();
1042 for (TIntermSequence::iterator p = childSequenceVector.begin();
1043 p != childSequenceVector.end(); p++) {
1044 if (!(*p)->getAsTyped()->getAsConstantUnion())
1052 TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode)
1056 TConstUnionArray unionArray(aggrNode->getType().computeNumComponents());
1057 if (aggrNode->getSequence().size() == 1)
1058 error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true);
1060 error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType());
1065 return addConstantUnion(unionArray, aggrNode->getType(), aggrNode->getLoc());
1069 // Constant folding of a bracket (array-style) dereference or struct-like dot
1070 // dereference. Can handle anything except a multi-character swizzle, though
1071 // all swizzles may go to foldSwizzle().
1073 TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, const TSourceLoc& loc)
1075 TType dereferencedType(node->getType(), index);
1076 dereferencedType.getQualifier().storage = EvqConst;
1077 TIntermTyped* result = 0;
1078 int size = dereferencedType.computeNumComponents();
1080 // arrays, vectors, matrices, all use simple multiplicative math
1081 // while structures need to add up heterogeneous members
1083 if (node->isArray() || ! node->isStruct())
1084 start = size * index;
1086 // it is a structure
1087 assert(node->isStruct());
1089 for (int i = 0; i < index; ++i)
1090 start += (*node->getType().getStruct())[i].type->computeNumComponents();
1093 result = addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), start, size), node->getType(), loc);
1098 result->setType(dereferencedType);
1104 // Make a constant vector node or constant scalar node, representing a given
1105 // constant vector and constant swizzle into it.
1107 TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& selectors, const TSourceLoc& loc)
1109 const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray();
1110 TConstUnionArray constArray(selectors.size());
1112 for (int i = 0; i < selectors.size(); i++)
1113 constArray[i] = unionArray[selectors[i]];
1115 TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc);
1120 result->setType(TType(node->getBasicType(), EvqConst, selectors.size()));
1125 } // end namespace glslang