Constant fold vector relational built-ins

This change adds constant folding support for vector relational
built-ins.

BUG=angleproject:913
TEST=dEQP Tests
dEQP-GLES3.functional.shaders.constant_expressions.builtin_functions.vector_relational*
(Fixes all 138 tests)

Change-Id: I291e332f2afb3ce3d6596e634f509995dbf35164
Reviewed-on: https://chromium-review.googlesource.com/272344
Reviewed-by: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 1bac12c..4f441ae 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -1163,10 +1163,66 @@
 
         return tempNode;
     }
+    else if (op == EOpAny || op == EOpAll)
+    {
+        // Do operations where the return type is different from the operand type.
+
+        TType returnType(EbtBool, EbpUndefined, EvqConst);
+        TConstantUnion *tempConstArray = nullptr;
+        if (op == EOpAny)
+        {
+            if (getType().getBasicType() == EbtBool)
+            {
+                tempConstArray = new TConstantUnion();
+                tempConstArray->setBConst(false);
+                for (size_t i = 0; i < objectSize; i++)
+                {
+                    if (unionArray[i].getBConst())
+                    {
+                        tempConstArray->setBConst(true);
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                infoSink.info.message(
+                    EPrefixInternalError, getLine(),
+                    "Unary operation not folded into constant");
+                return nullptr;
+            }
+        }
+        else if (op == EOpAll)
+        {
+            if (getType().getBasicType() == EbtBool)
+            {
+                tempConstArray = new TConstantUnion();
+                tempConstArray->setBConst(true);
+                for (size_t i = 0; i < objectSize; i++)
+                {
+                    if (!unionArray[i].getBConst())
+                    {
+                        tempConstArray->setBConst(false);
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                infoSink.info.message(
+                    EPrefixInternalError, getLine(),
+                    "Unary operation not folded into constant");
+                return nullptr;
+            }
+        }
+        TIntermConstantUnion *tempNode = new TIntermConstantUnion(tempConstArray, returnType);
+        tempNode->setLine(getLine());
+        return tempNode;
+    }
     else
     {
         //
-        // Do unary operations
+        // Do unary operations where the return type is the same as operand type.
         //
         TIntermConstantUnion *newNode = 0;
         TConstantUnion* tempConstArray = new TConstantUnion[objectSize];
@@ -1492,6 +1548,17 @@
                     tempConstArray[i].setFConst(1.0f / tempConstArray[i].getFConst());
                 break;
 
+              case EOpVectorLogicalNot:
+                if (getType().getBasicType() == EbtBool)
+                {
+                    tempConstArray[i].setBConst(!unionArray[i].getBConst());
+                    break;
+                }
+                infoSink.info.message(
+                    EPrefixInternalError, getLine(),
+                    "Unary operation not folded into constant");
+                return nullptr;
+
               default:
                 return nullptr;
             }
@@ -1685,6 +1752,156 @@
             }
             break;
 
+          case EOpLessThan:
+            {
+                tempConstArray = new TConstantUnion[maxObjectSize];
+                for (size_t i = 0; i < maxObjectSize; i++)
+                {
+                    switch (basicType)
+                    {
+                      case EbtFloat:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getFConst() < unionArrays[1][i].getFConst());
+                        break;
+                      case EbtInt:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getIConst() < unionArrays[1][i].getIConst());
+                        break;
+                      case EbtUInt:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getUConst() < unionArrays[1][i].getUConst());
+                        break;
+                      default:
+                        UNREACHABLE();
+                        break;
+                    }
+                }
+            }
+            break;
+
+          case EOpLessThanEqual:
+            {
+                tempConstArray = new TConstantUnion[maxObjectSize];
+                for (size_t i = 0; i < maxObjectSize; i++)
+                {
+                    switch (basicType)
+                    {
+                      case EbtFloat:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getFConst() <= unionArrays[1][i].getFConst());
+                        break;
+                      case EbtInt:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getIConst() <= unionArrays[1][i].getIConst());
+                        break;
+                      case EbtUInt:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getUConst() <= unionArrays[1][i].getUConst());
+                        break;
+                      default:
+                        UNREACHABLE();
+                        break;
+                    }
+                }
+            }
+            break;
+
+          case EOpGreaterThan:
+            {
+                tempConstArray = new TConstantUnion[maxObjectSize];
+                for (size_t i = 0; i < maxObjectSize; i++)
+                {
+                    switch (basicType)
+                    {
+                      case EbtFloat:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getFConst() > unionArrays[1][i].getFConst());
+                        break;
+                      case EbtInt:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getIConst() > unionArrays[1][i].getIConst());
+                        break;
+                      case EbtUInt:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getUConst() > unionArrays[1][i].getUConst());
+                        break;
+                      default:
+                        UNREACHABLE();
+                        break;
+                  }
+              }
+            }
+            break;
+
+          case EOpGreaterThanEqual:
+            {
+                tempConstArray = new TConstantUnion[maxObjectSize];
+                for (size_t i = 0; i < maxObjectSize; i++)
+                {
+                    switch (basicType)
+                    {
+                      case EbtFloat:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getFConst() >= unionArrays[1][i].getFConst());
+                        break;
+                      case EbtInt:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getIConst() >= unionArrays[1][i].getIConst());
+                        break;
+                      case EbtUInt:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getUConst() >= unionArrays[1][i].getUConst());
+                        break;
+                      default:
+                        UNREACHABLE();
+                        break;
+                    }
+                }
+            }
+            break;
+
+          case EOpVectorEqual:
+            {
+                tempConstArray = new TConstantUnion[maxObjectSize];
+                for (size_t i = 0; i < maxObjectSize; i++)
+                {
+                    switch (basicType)
+                    {
+                      case EbtFloat:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getFConst() == unionArrays[1][i].getFConst());
+                        break;
+                      case EbtInt:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getIConst() == unionArrays[1][i].getIConst());
+                        break;
+                      case EbtUInt:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getUConst() == unionArrays[1][i].getUConst());
+                        break;
+                      case EbtBool:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getBConst() == unionArrays[1][i].getBConst());
+                        break;
+                      default:
+                        UNREACHABLE();
+                        break;
+                    }
+                }
+            }
+            break;
+
+          case EOpVectorNotEqual:
+            {
+                tempConstArray = new TConstantUnion[maxObjectSize];
+                for (size_t i = 0; i < maxObjectSize; i++)
+                {
+                    switch (basicType)
+                    {
+                      case EbtFloat:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getFConst() != unionArrays[1][i].getFConst());
+                        break;
+                      case EbtInt:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getIConst() != unionArrays[1][i].getIConst());
+                        break;
+                      case EbtUInt:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getUConst() != unionArrays[1][i].getUConst());
+                        break;
+                      case EbtBool:
+                        tempConstArray[i].setBConst(unionArrays[0][i].getBConst() != unionArrays[1][i].getBConst());
+                        break;
+                      default:
+                        UNREACHABLE();
+                        break;
+                    }
+                }
+            }
+            break;
+
           default:
             UNREACHABLE();
             // TODO: Add constant folding support for other built-in operations that take 2 parameters and not handled above.
diff --git a/src/compiler/translator/Intermediate.cpp b/src/compiler/translator/Intermediate.cpp
index b48269e..a5f83a4 100644
--- a/src/compiler/translator/Intermediate.cpp
+++ b/src/compiler/translator/Intermediate.cpp
@@ -471,6 +471,12 @@
       case EOpMix:
       case EOpStep:
       case EOpSmoothStep:
+      case EOpLessThan:
+      case EOpLessThanEqual:
+      case EOpGreaterThan:
+      case EOpGreaterThanEqual:
+      case EOpVectorEqual:
+      case EOpVectorNotEqual:
         return TIntermConstantUnion::FoldAggregateBuiltIn(op, aggregate, mInfoSink);
       default:
         // Constant folding not supported for the built-in.