Allow compile-time intrinsic evaluation to read const variables.

Previously, the code neglected to resolve constant variables into
values. This meant that expressions like `lessThan(zero, one)` could not
be compile-time evaluated even when `zero` and `one` have known values.

Change-Id: I2f5ce303e3dcc682be14e4d2485e24dd7c59212e
Bug: skia:10835
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/405536
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/resources/sksl/folding/BoolFolding.sksl b/resources/sksl/folding/BoolFolding.sksl
index f9eb3e0..2b253d1 100644
--- a/resources/sksl/folding/BoolFolding.sksl
+++ b/resources/sksl/folding/BoolFolding.sksl
@@ -11,10 +11,13 @@
     bool h = false == true;
     bool i = true == !false;
     bool j = false == !false;
-    bool k = all(bool3(1 == 1, !false, 123 > 12));  // all are true
-    bool l = all(bool4(true, 1 == 2, true, true));  // three out of four are true
-    bool m = any(bool4(true, 1 == 2, true, true));  // three out of four are true
-    bool n = any(bool2(0 == 1, false));             // none are true
+
+    const bool TRUE = true;
+    const bool FALSE = false;
+    bool k = all(bool4(1 == 1, !false, 123 > 12, TRUE));  // all are true
+    bool l = all(bool3(TRUE, 1 == 2, true));              // three out of four are true
+    bool m = any(bool4(true, 1 == 2, true, TRUE));        // three out of four are true
+    bool n = any(bool2(0 == 1, FALSE));                   // none are true
 
     return a && !b && c && !d && e && !f && g && !h && i && !j && k && !l && m && !n;
 }
diff --git a/resources/sksl/intrinsics/Equal.sksl b/resources/sksl/intrinsics/Equal.sksl
index 07a73c8..0453493 100644
--- a/resources/sksl/intrinsics/Equal.sksl
+++ b/resources/sksl/intrinsics/Equal.sksl
@@ -2,8 +2,9 @@
 uniform uint2 c, d;
 uniform int3 e, f;
 void main() {
+    const int4 int4_zero = int4(0);
     bool4 expectTTFF = equal(half4(3, 3, 3.25, 100), half4(3));
-    bool4 expectFFTT = equal(int4(0), int4(-100, -50, 0, 0));
+    bool4 expectFFTT = equal(int4_zero, int4(-100, -50, 0, 0));
 
     sk_FragColor.x = equal(a, b).x ? 1 : 0;
     sk_FragColor.y = equal(c, d).y ? 1 : 0;
diff --git a/resources/sksl/intrinsics/GreaterThan.sksl b/resources/sksl/intrinsics/GreaterThan.sksl
index f5f1cbc..cf88597 100644
--- a/resources/sksl/intrinsics/GreaterThan.sksl
+++ b/resources/sksl/intrinsics/GreaterThan.sksl
@@ -2,8 +2,9 @@
 uniform uint2 c, d;
 uniform int3 e, f;
 void main() {
+    const int4 int4_zero = int4(0);
     bool4 expectFFTT = greaterThan(half4(1, 2, 2.5, 2.75), half4(2.25));
-    bool4 expectTTFF = greaterThan(int4(0), int4(-100, -50, 0, 50));
+    bool4 expectTTFF = greaterThan(int4_zero, int4(-100, -50, 0, 50));
 
     sk_FragColor.x = greaterThan(a, b).x ? 1 : 0;
     sk_FragColor.y = greaterThan(c, d).y ? 1 : 0;
diff --git a/resources/sksl/intrinsics/GreaterThanEqual.sksl b/resources/sksl/intrinsics/GreaterThanEqual.sksl
index 0c7f297..706528a 100644
--- a/resources/sksl/intrinsics/GreaterThanEqual.sksl
+++ b/resources/sksl/intrinsics/GreaterThanEqual.sksl
@@ -2,8 +2,9 @@
 uniform uint2 c, d;
 uniform int3 e, f;
 void main() {
+    const int4 int4_zero = int4(0);
     bool4 expectFFTT = greaterThanEqual(half4(1, 2, 2.25, 2.5), half4(2.25));
-    bool4 expectTTFF = greaterThanEqual(int4(0), int4(-50, 0, 50, 100));
+    bool4 expectTTFF = greaterThanEqual(int4_zero, int4(-50, 0, 50, 100));
 
     sk_FragColor.x = greaterThanEqual(a, b).x ? 1 : 0;
     sk_FragColor.y = greaterThanEqual(c, d).y ? 1 : 0;
diff --git a/resources/sksl/intrinsics/LessThan.sksl b/resources/sksl/intrinsics/LessThan.sksl
index 4b353f3..723e3d7 100644
--- a/resources/sksl/intrinsics/LessThan.sksl
+++ b/resources/sksl/intrinsics/LessThan.sksl
@@ -2,8 +2,9 @@
 uniform uint2 c, d;
 uniform int3 e, f;
 void main() {
+    const int4 int4_zero = int4(0);
     bool4 expectTTFF = lessThan(half4(1, 2, 2.5, 2.75), half4(2.25));
-    bool4 expectFFTT = lessThan(int4(0), int4(-50, 0, 50, 100));
+    bool4 expectFFTT = lessThan(int4_zero, int4(-50, 0, 50, 100));
 
     sk_FragColor.x = lessThan(a, b).x ? 1 : 0;
     sk_FragColor.y = lessThan(c, d).y ? 1 : 0;
diff --git a/resources/sksl/intrinsics/LessThanEqual.sksl b/resources/sksl/intrinsics/LessThanEqual.sksl
index 550cb3e..5dea289 100644
--- a/resources/sksl/intrinsics/LessThanEqual.sksl
+++ b/resources/sksl/intrinsics/LessThanEqual.sksl
@@ -2,8 +2,9 @@
 uniform uint2 c, d;
 uniform int3 e, f;
 void main() {
+    const int4 int4_zero = int4(0);
     bool4 expectTTFF = lessThanEqual(half4(2, 2.25, 2.5, 2.75), half4(2.25));
-    bool4 expectFFTT = lessThanEqual(int4(0), int4(-100, -50, 0, 50));
+    bool4 expectFFTT = lessThanEqual(int4_zero, int4(-100, -50, 0, 50));
 
     sk_FragColor.x = lessThanEqual(a, b).x ? 1 : 0;
     sk_FragColor.y = lessThanEqual(c, d).y ? 1 : 0;
diff --git a/resources/sksl/intrinsics/NotEqual.sksl b/resources/sksl/intrinsics/NotEqual.sksl
index 9eaf13f..b8d9bd8 100644
--- a/resources/sksl/intrinsics/NotEqual.sksl
+++ b/resources/sksl/intrinsics/NotEqual.sksl
@@ -2,8 +2,9 @@
 uniform uint2 c, d;
 uniform int3 e, f;
 void main() {
+    const int4 int4_zero = int4(0);
     bool4 expectFFTT = notEqual(half4(3, 3, 3.25, 100), half4(3));
-    bool4 expectTTFF = notEqual(int4(0), int4(-100, -50, 0, 0));
+    bool4 expectTTFF = notEqual(int4_zero, int4(-100, -50, 0, 0));
 
     sk_FragColor.x = notEqual(a, b).x ? 1 : 0;
     sk_FragColor.y = notEqual(c, d).y ? 1 : 0;
diff --git a/src/sksl/ir/SkSLFunctionCall.cpp b/src/sksl/ir/SkSLFunctionCall.cpp
index c4fe6b8..65be785 100644
--- a/src/sksl/ir/SkSLFunctionCall.cpp
+++ b/src/sksl/ir/SkSLFunctionCall.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "src/sksl/SkSLAnalysis.h"
+#include "src/sksl/SkSLConstantFolder.h"
 #include "src/sksl/SkSLContext.h"
 #include "src/sksl/SkSLProgramSettings.h"
 #include "src/sksl/ir/SkSLBoolLiteral.h"
@@ -18,7 +19,8 @@
 
 static bool has_compile_time_constant_arguments(const ExpressionArray& arguments) {
     for (const std::unique_ptr<Expression>& arg : arguments) {
-        if (!arg->isCompileTimeConstant()) {
+        const Expression* expr = ConstantFolder::GetConstantValueForVariable(*arg);
+        if (!expr->isCompileTimeConstant()) {
             return false;
         }
     }
@@ -30,19 +32,19 @@
         bool startingState,
         const std::function<bool(bool, bool)>& coalesce) {
     SkASSERT(arguments.size() == 1);
-    const Expression& arg = *arguments.front();
-    const Type& type = arg.type();
+    const Expression* arg = ConstantFolder::GetConstantValueForVariable(*arguments.front());
+    const Type& type = arg->type();
     SkASSERT(type.isVector());
     SkASSERT(type.componentType().isBoolean());
 
     bool value = startingState;
     for (int index = 0; index < type.columns(); ++index) {
-        const Expression* subexpression = arg.getConstantSubexpression(index);
+        const Expression* subexpression = arg->getConstantSubexpression(index);
         SkASSERT(subexpression);
         value = coalesce(value, subexpression->as<BoolLiteral>().value());
     }
 
-    return BoolLiteral::Make(arg.fOffset, value, &type.componentType());
+    return BoolLiteral::Make(arg->fOffset, value, &type.componentType());
 }
 
 template <typename LITERAL, typename FN>
@@ -77,16 +79,16 @@
                                                        const ExpressionArray& arguments,
                                                        const FN& compare) {
     SkASSERT(arguments.size() == 2);
-    const Expression& left = *arguments[0];
-    const Expression& right = *arguments[1];
+    const Expression* left = ConstantFolder::GetConstantValueForVariable(*arguments[0]);
+    const Expression* right = ConstantFolder::GetConstantValueForVariable(*arguments[1]);
 
-    if (left.type().componentType().isFloat()) {
-        return optimize_comparison_of_type<FloatLiteral>(context, left, right, compare);
+    if (left->type().componentType().isFloat()) {
+        return optimize_comparison_of_type<FloatLiteral>(context, *left, *right, compare);
     }
-    if (left.type().componentType().isInteger()) {
-        return optimize_comparison_of_type<IntLiteral>(context, left, right, compare);
+    if (left->type().componentType().isInteger()) {
+        return optimize_comparison_of_type<IntLiteral>(context, *left, *right, compare);
     }
-    SkDEBUGFAILF("unsupported type %s", left.type().description().c_str());
+    SkDEBUGFAILF("unsupported type %s", left->type().description().c_str());
     return nullptr;
 }
 
diff --git a/tests/sksl/folding/BoolFolding.glsl b/tests/sksl/folding/BoolFolding.glsl
index 733c025..a598aec 100644
--- a/tests/sksl/folding/BoolFolding.glsl
+++ b/tests/sksl/folding/BoolFolding.glsl
@@ -13,9 +13,9 @@
     bool _7_h = false;
     bool _8_i = true;
     bool _9_j = false;
-    bool _10_k = true;
-    bool _11_l = false;
-    bool _12_m = true;
-    bool _13_n = false;
-    return ((((((((((((_0_a && !_1_b) && _2_c) && !_3_d) && _4_e) && !_5_f) && _6_g) && !_7_h) && _8_i) && !_9_j) && _10_k) && !_11_l) && _12_m) && !_13_n ? colorGreen : colorRed;
+    bool _12_k = true;
+    bool _13_l = false;
+    bool _14_m = true;
+    bool _15_n = false;
+    return ((((((((((((_0_a && !_1_b) && _2_c) && !_3_d) && _4_e) && !_5_f) && _6_g) && !_7_h) && _8_i) && !_9_j) && _12_k) && !_13_l) && _14_m) && !_15_n ? colorGreen : colorRed;
 }