add SkSLInterpreter vector instructions

Change-Id: I93c8754d55b9d462b056a77e95b852fc61f1fd66
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/266560
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp
index 75b3d22..90a9dbb 100644
--- a/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/src/sksl/SkSLByteCodeGenerator.cpp
@@ -271,38 +271,34 @@
     return ByteCode::Instruction::kNop;
 }
 
+#define VEC(inst) ((ByteCode::Instruction) ((uint16_t) inst + 1))
+
 class ByteCodeSimpleLValue : public ByteCodeGenerator::LValue {
 public:
     ByteCodeSimpleLValue(ByteCodeGenerator* generator, ByteCodeGenerator::Location location,
                          int count, ByteCode::Instruction load, ByteCode::Instruction store)
         : INHERITED(*generator)
         , fLocation(location)
-        , fCount(count)
+        , fCount((uint8_t) count)
         , fLoad(load)
         , fStore(store) {}
 
     void load(ByteCode::Register result) override {
-        for (int i = 0; i < fCount; ++i) {
-            ByteCodeGenerator::Location final = fLocation.offset(fGenerator, i);
-            fGenerator.write(fLoad);
-            fGenerator.write(result + i);
-            fGenerator.write(final);
-        }
+        fGenerator.write(fLoad, fCount);
+        fGenerator.write(result);
+        fGenerator.write(fLocation);
     }
 
     void store(ByteCode::Register src) override {
-        for (int i = 0; i < fCount; ++i) {
-            ByteCodeGenerator::Location final = fLocation.offset(fGenerator, i);
-            fGenerator.write(fStore);
-            fGenerator.write(final);
-            fGenerator.write(src + i);
-        }
+        fGenerator.write(fStore, fCount);
+        fGenerator.write(fLocation);
+        fGenerator.write(src);
     }
 
 private:
     ByteCodeGenerator::Location fLocation;
 
-    int fCount;
+    uint8_t fCount;
 
     ByteCode::Instruction fLoad;
 
@@ -425,6 +421,17 @@
     }
 }
 
+void ByteCodeGenerator::write(ByteCode::Instruction inst, int count) {
+    SkASSERT(count <= 255);
+    if (count > 1) {
+        this->write(VEC(inst));
+        this->write((uint8_t) count);
+    }
+    else {
+        this->write(inst);
+    }
+}
+
 void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCode::Instruction s,
                                               ByteCode::Instruction u, ByteCode::Instruction f) {
     switch (type_category(type)) {
@@ -443,6 +450,26 @@
     }
 }
 
+void ByteCodeGenerator::writeVectorBinaryInstruction(const Type& operandType,
+                                                     ByteCode::Register left,
+                                                     ByteCode::Register right,
+                                                     ByteCode::Instruction s,
+                                                     ByteCode::Instruction u,
+                                                     ByteCode::Instruction f,
+                                                     ByteCode::Register result) {
+    uint8_t count = (uint8_t) SlotCount(operandType);
+    if (count == 1) {
+        this->writeTypedInstruction(operandType, s, u, f);
+    }
+    else {
+        this->writeTypedInstruction(operandType, VEC(s), VEC(u), VEC(f));
+        this->write(count);
+    }
+    this->write(result);
+    this->write(left);
+    this->write(right);
+}
+
 void ByteCodeGenerator::writeBinaryInstruction(const Type& operandType,
                                                ByteCode::Register left,
                                                ByteCode::Register right,
@@ -497,11 +524,10 @@
         this->writeExpression(*b.fLeft, left);
         op = b.fOperator;
         if (!lVecOrMtx && rVecOrMtx) {
-            for (int i = 1; i < SlotCount(rType); ++i) {
-                this->write(ByteCode::Instruction::kCopy);
-                this->write(left + i);
-                this->write(left);
-            }
+            this->write(ByteCode::Instruction::kSplat);
+            this->write((uint8_t) (SlotCount(rType) - 1));
+            this->write(left + 1);
+            this->write(left);
         }
     }
     SkDEBUGCODE(TypeCategory tc = type_category(lType));
@@ -607,11 +633,10 @@
     ByteCode::Register right = this->next(SlotCount(*operandType));
     this->writeExpression(*b.fRight, right);
     if (lVecOrMtx && !rVecOrMtx) {
-        for (int i = 1; i < SlotCount(*operandType); ++i) {
-            this->write(ByteCode::Instruction::kCopy);
-            this->write(right + i);
-            this->write(right);
-        }
+        this->write(ByteCode::Instruction::kSplat);
+        this->write((uint8_t) (SlotCount(*operandType) - 1));
+        this->write(right + 1);
+        this->write(right);
     }
     switch (op) {
         case Token::Kind::EQEQ:
@@ -657,11 +682,11 @@
                                          result);
             break;
         case Token::Kind::MINUS:
-            this->writeBinaryInstruction(*operandType, left, right,
-                                         ByteCode::Instruction::kSubtractI,
-                                         ByteCode::Instruction::kSubtractI,
-                                         ByteCode::Instruction::kSubtractF,
-                                         result);
+            this->writeVectorBinaryInstruction(*operandType, left, right,
+                                               ByteCode::Instruction::kSubtractI,
+                                               ByteCode::Instruction::kSubtractI,
+                                               ByteCode::Instruction::kSubtractF,
+                                               result);
             break;
         case Token::Kind::NEQ:
             this->writeBinaryInstruction(*operandType, left, right,
@@ -678,32 +703,32 @@
             }
             break;
         case Token::Kind::PERCENT:
-            this->writeBinaryInstruction(*operandType, left, right,
-                                         ByteCode::Instruction::kRemainderS,
-                                         ByteCode::Instruction::kRemainderU,
-                                         ByteCode::Instruction::kRemainderF,
-                                         result);
+            this->writeVectorBinaryInstruction(*operandType, left, right,
+                                               ByteCode::Instruction::kRemainderS,
+                                               ByteCode::Instruction::kRemainderU,
+                                               ByteCode::Instruction::kRemainderF,
+                                               result);
             break;
         case Token::Kind::PLUS:
-            this->writeBinaryInstruction(*operandType, left, right,
-                                         ByteCode::Instruction::kAddI,
-                                         ByteCode::Instruction::kAddI,
-                                         ByteCode::Instruction::kAddF,
-                                         result);
+            this->writeVectorBinaryInstruction(*operandType, left, right,
+                                               ByteCode::Instruction::kAddI,
+                                               ByteCode::Instruction::kAddI,
+                                               ByteCode::Instruction::kAddF,
+                                               result);
             break;
         case Token::Kind::SLASH:
-            this->writeBinaryInstruction(*operandType, left, right,
-                                         ByteCode::Instruction::kDivideS,
-                                         ByteCode::Instruction::kDivideU,
-                                         ByteCode::Instruction::kDivideF,
-                                         result);
+            this->writeVectorBinaryInstruction(*operandType, left, right,
+                                               ByteCode::Instruction::kDivideS,
+                                               ByteCode::Instruction::kDivideU,
+                                               ByteCode::Instruction::kDivideF,
+                                               result);
             break;
         case Token::Kind::STAR:
-            this->writeBinaryInstruction(*operandType, left, right,
-                                         ByteCode::Instruction::kMultiplyI,
-                                         ByteCode::Instruction::kMultiplyI,
-                                         ByteCode::Instruction::kMultiplyF,
-                                         result);
+            this->writeVectorBinaryInstruction(*operandType, left, right,
+                                               ByteCode::Instruction::kMultiplyI,
+                                               ByteCode::Instruction::kMultiplyI,
+                                               ByteCode::Instruction::kMultiplyF,
+                                               result);
             break;
         case Token::Kind::LOGICALXOR: {
             SkASSERT(tc == SkSL::TypeCategory::kBool);
@@ -784,11 +809,10 @@
         SkASSERT(SlotCount(c.fArguments[0]->fType) == 1);
         ByteCode::Register v = result;
         this->writeExpression(*c.fArguments[0], v);
-        for (int i = 1; i < c.fType.columns(); ++i) {
-            this->write(ByteCode::Instruction::kCopy);
-            this->write(v + i);
-            this->write(v);
-        }
+        this->write(ByteCode::Instruction::kSplat);
+        this->write((uint8_t) (c.fType.columns() - 1));
+        this->write(v + 1);
+        this->write(v);
         return;
     }
     ByteCode::Instruction inst;
@@ -894,15 +918,14 @@
                 ByteCode::Register right = this->next(count);
                 this->writeExpression(*c.fArguments[1], right);
                 ByteCode::Register product = this->next(count);
-                for (int i = 0; i < count; ++i) {
-                    this->writeTypedInstruction(c.fType,
-                                                ByteCode::Instruction::kMultiplyI,
-                                                ByteCode::Instruction::kMultiplyI,
-                                                ByteCode::Instruction::kMultiplyF);
-                    this->write(product + i);
-                    this->write(left + i);
-                    this->write(right + i);
-                }
+                this->writeTypedInstruction(c.fType,
+                                            ByteCode::Instruction::kMultiplyIN,
+                                            ByteCode::Instruction::kMultiplyIN,
+                                            ByteCode::Instruction::kMultiplyFN);
+                this->write((uint8_t) count);
+                this->write(product);
+                this->write(left);
+                this->write(right);
                 ByteCode::Register total = product;
                 for (int i = 1; i < count; ++i) {
                     this->writeTypedInstruction(c.fType,
@@ -1132,12 +1155,10 @@
                                                 ByteCode::Register result) {
     ByteCodeGenerator::Location location = this->getLocation(expr);
     int count = SlotCount(expr.fType);
-    for (int i = 0; i < count; ++i) {
-        ByteCodeGenerator::Location final = location.offset(*this, i);
-        this->write(this->getLoadInstruction(location, this->getStorage(expr)));
-        this->write(result + i);
-        this->write(final);
-    }
+    ByteCode::Instruction load = this->getLoadInstruction(location, this->getStorage(expr));
+    this->write(load, count);
+    this->write(result);
+    this->write(location);
 }
 
 void ByteCodeGenerator::writeExpression(const Expression& expr, ByteCode::Register result) {
@@ -1303,12 +1324,10 @@
         ByteCodeGenerator::Location location = this->getLocation(*decl.fVar);
         if (decl.fValue) {
             ByteCode::Register src = this->writeExpression(*decl.fValue);
-            for (int i = 0; i < SlotCount(decl.fVar->fType); ++i) {
-                ByteCodeGenerator::Location final = location.offset(*this, i);
-                this->write(ByteCode::Instruction::kStoreStackDirect);
-                this->write(final);
-                this->write(src + i);
-            }
+            uint8_t count = (uint8_t) SlotCount(decl.fVar->fType);
+            this->write(ByteCode::Instruction::kStoreStackDirect, count);
+            this->write(location);
+            this->write(src);
         }
     }
 }