Improved skslc optimizer, particularly around vectors.

BUG=skia:

Change-Id: Idb364d9198f2ff84aad1eb68e236fb45ec1c86b7
Reviewed-on: https://skia-review.googlesource.com/8000
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ben Wagner <benjaminwagner@google.com>
diff --git a/src/sksl/ir/SkSLConstructor.h b/src/sksl/ir/SkSLConstructor.h
index 5c647c7..208031a 100644
--- a/src/sksl/ir/SkSLConstructor.h
+++ b/src/sksl/ir/SkSLConstructor.h
@@ -30,20 +30,36 @@
     : INHERITED(position, kConstructor_Kind, type)
     , fArguments(std::move(arguments)) {}
 
-    virtual std::unique_ptr<Expression> constantPropagate(
-                                                        const IRGenerator& irGenerator,
-                                                        const DefinitionMap& definitions) override {
-        if (fArguments.size() == 1 && fArguments[0]->fKind == Expression::kIntLiteral_Kind &&
-            // promote float(1) to 1.0
-            fType == *irGenerator.fContext.fFloat_Type) {
-            int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
-            return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext,
-                                                                fPosition,
-                                                                intValue));
+    std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
+                                                  const DefinitionMap& definitions) override {
+        if (fArguments.size() == 1 && fArguments[0]->fKind == Expression::kIntLiteral_Kind) {
+            if (fType == *irGenerator.fContext.fFloat_Type) {
+                // promote float(1) to 1.0
+                int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
+                return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext,
+                                                                    fPosition,
+                                                                    intValue));
+            } else if (fType == *irGenerator.fContext.fUInt_Type) {
+                // promote uint(1) to 1u
+                int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
+                return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
+                                                                  fPosition,
+                                                                  intValue,
+                                                                  &fType));
+            }
         }
         return nullptr;
     }
 
+    bool hasSideEffects() const override {
+        for (const auto& arg : fArguments) {
+            if (arg->hasSideEffects()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     String description() const override {
         String result = fType.description() + "(";
         String separator;
@@ -65,6 +81,43 @@
         return true;
     }
 
+    const Expression& getVecComponent(int index) const {
+        ASSERT(fType.kind() == Type::kVector_Kind);
+        if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) {
+            return *fArguments[0];
+        }
+        int current = 0;
+        for (const auto& arg : fArguments) {
+            ASSERT(current <= index);
+            if (arg->fType.kind() == Type::kScalar_Kind) {
+                if (index == current) {
+                    return *arg;
+                }
+                current++;
+            } else {
+                ASSERT(arg->fType.kind() == Type::kVector_Kind);
+                ASSERT(arg->fKind == Expression::kConstructor_Kind);
+                if (current + arg->fType.columns() > index) {
+                    return ((const Constructor&) *arg).getVecComponent(index - current);
+                }
+                current += arg->fType.columns();
+            }
+        }
+        ABORT("failed to find vector component %d in %s\n", index, description().c_str());
+    }
+
+    double getFVecComponent(int index) const {
+        const Expression& c = this->getVecComponent(index);
+        ASSERT(c.fKind == Expression::kFloatLiteral_Kind);
+        return ((FloatLiteral&) c).fValue;
+    }
+
+    int64_t getIVecComponent(int index) const {
+        const Expression& c = this->getVecComponent(index);
+        ASSERT(c.fKind == Expression::kIntLiteral_Kind);
+        return ((IntLiteral&) c).fValue;
+    }
+
     std::vector<std::unique_ptr<Expression>> fArguments;
 
     typedef Expression INHERITED;