Add non-square MatrixCompMult support to public SkSL in ES3 mode.

We already had a test case here, but it wasn't actually in operation.
The test has been split into ES2 (square) and ES3 (non-square) halves,
returns the color like a proper runtime effect, and it's now running in
dm.

Also, Metal doesn't natively support matrixCompMult, so it injects a
helper function; I tweaked the helper so it no longer requires an extra
result variable.

Change-Id: Ie79242768966fcbe879ad73461d17b4fb8e55670
Bug: skia:12202
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/448117
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/gn/sksl_tests.gni b/gn/sksl_tests.gni
index 68cde03..df773342 100644
--- a/gn/sksl_tests.gni
+++ b/gn/sksl_tests.gni
@@ -250,7 +250,8 @@
   "/sksl/intrinsics/LessThanEqual.sksl",
   "/sksl/intrinsics/Log.sksl",
   "/sksl/intrinsics/Log2.sksl",
-  "/sksl/intrinsics/MatrixCompMult.sksl",
+  "/sksl/intrinsics/MatrixCompMultES2.sksl",
+  "/sksl/intrinsics/MatrixCompMultES3.sksl",
   "/sksl/intrinsics/MaxFloat.sksl",
   "/sksl/intrinsics/MaxInt.sksl",
   "/sksl/intrinsics/MinFloat.sksl",
diff --git a/resources/sksl/intrinsics/MatrixCompMult.sksl b/resources/sksl/intrinsics/MatrixCompMult.sksl
deleted file mode 100644
index da89f68..0000000
--- a/resources/sksl/intrinsics/MatrixCompMult.sksl
+++ /dev/null
@@ -1,19 +0,0 @@
-uniform half4 colorGreen, colorRed;
-half3x3 a, b;
-float4x4 c, d;
-
-void main() {
-    half2x2 h22 = matrixCompMult(half2x2(5, 5, 5, 5), half2x2(0, 1, 2, 3));
-    half4x4 h44 = matrixCompMult(half4x4(0.5), half4x4(1, 2, 3, 4,
-                                                       5, 6, 7, 8,
-                                                       9, 10,11,12,
-                                                       13,14,15,16));
-    float4x3 f43 = matrixCompMult(float4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
-                                  float4x3(12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
-    sk_FragColor.xyz = matrixCompMult(a, b)[0];
-    sk_FragColor = half4(matrixCompMult(c, d)[0]);
-    sk_FragColor = (h22 == half2x2(0, 5, 10, 15) &&
-                    h44 == half4x4(0.5, 0, 0, 0, 0, 3, 0, 0, 0, 0, 5.5, 0, 0, 0, 0, 8) &&
-                    f43 == float4x3(12, 22, 30, 36, 40, 42, 42, 40, 36, 30, 22, 12)) ? colorGreen
-                                                                                     : colorRed;
-}
diff --git a/resources/sksl/intrinsics/MatrixCompMultES2.sksl b/resources/sksl/intrinsics/MatrixCompMultES2.sksl
new file mode 100644
index 0000000..adae9e9
--- /dev/null
+++ b/resources/sksl/intrinsics/MatrixCompMultES2.sksl
@@ -0,0 +1,18 @@
+uniform half4 colorGreen, colorRed;
+uniform float2x2 testMatrix2x2;
+uniform half3x3 testMatrix3x3;
+
+half4 main(float2 coords) {
+    half2x2 h22 = matrixCompMult(half2x2(5, 5, 5, 5), half2x2(0, 1, 2, 3));
+    const half4x4 h44 = matrixCompMult(half4x4(0.5), half4x4(1, 2, 3, 4,
+                                                             5, 6, 7, 8,
+                                                             9, 10,11,12,
+                                                             13,14,15,16));
+    float2x2 f22 = matrixCompMult(testMatrix2x2, float2x2(1));
+    half3x3 h33 = matrixCompMult(testMatrix3x3, half3x3(2,2,2,2,2,2,2,2,2));
+    return (h22 == half2x2(0, 5, 10, 15) &&
+            f22 == float2x2(1, 0, 0, 4) &&
+            h33 == half3x3(2, 4, 6, 8, 10, 12, 14, 16, 18) &&
+            h44 == half4x4(0.5, 0, 0, 0, 0, 3, 0, 0, 0, 0, 5.5, 0, 0, 0, 0, 8))
+                ? colorGreen : colorRed;
+}
diff --git a/resources/sksl/intrinsics/MatrixCompMultES3.sksl b/resources/sksl/intrinsics/MatrixCompMultES3.sksl
new file mode 100644
index 0000000..edea42a
--- /dev/null
+++ b/resources/sksl/intrinsics/MatrixCompMultES3.sksl
@@ -0,0 +1,21 @@
+uniform half4 colorGreen, colorRed;
+
+half4 main(float2 coords) {
+    const float2x3 f23 = matrixCompMult(float2x3(4), float2x3(5));
+    const half3x2 h32 = matrixCompMult(half3x2(5), half3x2(3));
+    half2x4 h24 = matrixCompMult(half2x4(9, 9, 9, 9, 9, 9, 9, 9),
+                                 half2x4(colorRed, colorGreen));
+    half4x2 h42 = matrixCompMult(half4x2(1, 2, 3, 4, 5, 6, 7, 8),
+                                 half4x2(colorRed, colorGreen));
+    const float3x4 f34 = matrixCompMult(float3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
+                                        float3x4(12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
+    float4x3 f43 = matrixCompMult(float4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
+                                  float4x3(12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
+    return (f23 == float2x3(20) &&
+            h32 == half3x2(15) &&
+            h24 == half2x4(9, 0, 0, 9, 0, 9, 0, 9) &&
+            h42 == half4x2(1, 0, 0, 4, 0, 6, 0, 8) &&
+            f34 == float3x4(12, 22, 30, 36, 40, 42, 42, 40, 36, 30, 22, 12) &&
+            f43 == float4x3(12, 22, 30, 36, 40, 42, 42, 40, 36, 30, 22, 12)) ? colorGreen
+                                                                             : colorRed;
+}
diff --git a/src/sksl/codegen/SkSLMetalCodeGenerator.cpp b/src/sksl/codegen/SkSLMetalCodeGenerator.cpp
index 3e5daae..bb34f30 100644
--- a/src/sksl/codegen/SkSLMetalCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLMetalCodeGenerator.cpp
@@ -464,12 +464,11 @@
 void MetalCodeGenerator::writeMatrixCompMult() {
     static constexpr char kMatrixCompMult[] = R"(
 template <int C, int R>
-matrix<float, C, R> matrixCompMult(matrix<float, C, R> a, matrix<float, C, R> b) {
-    matrix<float, C, R> result;
+matrix<float, C, R> matrixCompMult(matrix<float, C, R> a, const matrix<float, C, R> b) {
     for (int c = 0; c < C; ++c) {
-        result[c] = a[c] * b[c];
+        a[c] *= b[c];
     }
-    return result;
+    return a;
 }
 )";
 
diff --git a/src/sksl/generated/sksl_public.dehydrated.sksl b/src/sksl/generated/sksl_public.dehydrated.sksl
index 268bec1..0441b45 100644
--- a/src/sksl/generated/sksl_public.dehydrated.sksl
+++ b/src/sksl/generated/sksl_public.dehydrated.sksl
@@ -1,4 +1,4 @@
-static uint8_t SKSL_INCLUDE_sksl_public[] = {181,3,
+static uint8_t SKSL_INCLUDE_sksl_public[] = {192,3,
 7,100,101,103,114,101,101,115,
 8,36,103,101,110,84,121,112,101,
 7,114,97,100,105,97,110,115,
@@ -88,6 +88,8 @@
 10,36,115,113,117,97,114,101,77,97,116,
 14,109,97,116,114,105,120,67,111,109,112,77,117,108,116,
 11,36,115,113,117,97,114,101,72,77,97,116,
+4,36,109,97,116,
+5,36,104,109,97,116,
 1,109,
 7,105,110,118,101,114,115,101,
 11,100,101,116,101,114,109,105,110,97,110,116,
@@ -138,7 +140,7 @@
 3,100,115,116,
 1,98,
 7,98,108,101,110,100,101,114,
-48,106,2,
+48,114,2,
 52,1,0,
 17,2,0,
 49,2,0,10,0,3,
@@ -1447,851 +1449,880 @@
 46,160,1,
 46,163,1,
 52,164,1,
-17,83,2,
-46,156,1,3,
-29,165,1,
-17,85,2,1,164,1,
-46,156,1,
+17,55,0,
+49,165,1,83,2,3,
 52,166,1,
-17,83,2,
-46,160,1,3,
-51,167,1,2,
-46,165,1,
+17,67,0,
+46,165,1,3,
+51,167,1,3,
+46,158,1,
+46,163,1,
 29,168,1,
-17,85,2,1,166,1,
-46,160,1,
+37,
+16,0,16,0,0,56,2,2,164,1,166,1,
+46,165,1,
 46,168,1,
 52,169,1,
-17,83,2,
-46,156,1,3,
-29,170,1,
-37,
-16,0,16,0,0,93,2,1,169,1,
-46,145,0,
+17,55,0,
+49,170,1,88,2,3,
 52,171,1,
-17,83,2,
-46,160,1,3,
-51,172,1,2,
-46,170,1,
+17,67,0,
+46,170,1,3,
+51,172,1,4,
+46,158,1,
+46,163,1,
+46,168,1,
 29,173,1,
 37,
-16,0,16,0,0,93,2,1,171,1,
-46,153,0,
+16,0,16,0,0,56,2,2,169,1,171,1,
+46,170,1,
 46,173,1,
 52,174,1,
-17,83,2,
+17,94,2,
 46,156,1,3,
 29,175,1,
-37,
-16,0,16,0,0,105,2,1,174,1,
+17,96,2,1,174,1,
 46,156,1,
 52,176,1,
-17,83,2,
+17,94,2,
 46,160,1,3,
 51,177,1,2,
 46,175,1,
 29,178,1,
-37,
-16,0,16,0,0,105,2,1,176,1,
+17,96,2,1,176,1,
 46,160,1,
 46,178,1,
 52,179,1,
-17,83,2,
-49,180,1,115,2,3,
-51,181,1,3,
-46,175,1,
-46,178,1,
-29,182,1,
+17,94,2,
+46,156,1,3,
+29,180,1,
 37,
-16,0,16,0,0,105,2,1,179,1,
-49,183,1,124,2,
-46,182,1,
+16,0,16,0,0,104,2,1,179,1,
+46,145,0,
+52,181,1,
+17,94,2,
+46,160,1,3,
+51,182,1,2,
+46,180,1,
+29,183,1,
+37,
+16,0,16,0,0,104,2,1,181,1,
+46,153,0,
+46,183,1,
 52,184,1,
-17,83,2,
-49,185,1,133,2,3,
-51,186,1,4,
-46,175,1,
-46,178,1,
-46,182,1,
-29,187,1,
+17,94,2,
+46,156,1,3,
+29,185,1,
 37,
-16,0,16,0,0,105,2,1,184,1,
-49,188,1,141,2,
-46,187,1,
+16,0,16,0,0,116,2,1,184,1,
+46,156,1,
+52,186,1,
+17,94,2,
+46,160,1,3,
+51,187,1,2,
+46,185,1,
+29,188,1,
+37,
+16,0,16,0,0,116,2,1,186,1,
+46,160,1,
+46,188,1,
 52,189,1,
-17,83,2,
-49,190,1,149,2,3,
-51,191,1,5,
-46,175,1,
-46,178,1,
-46,182,1,
-46,187,1,
+17,94,2,
+49,190,1,126,2,3,
+51,191,1,3,
+46,185,1,
+46,188,1,
 29,192,1,
 37,
-16,0,16,0,0,105,2,1,189,1,
-49,193,1,158,2,
+16,0,16,0,0,116,2,1,189,1,
+49,193,1,135,2,
 46,192,1,
 52,194,1,
-17,83,2,
-49,195,1,167,2,3,
-51,196,1,6,
-46,175,1,
-46,178,1,
-46,182,1,
-46,187,1,
+17,94,2,
+49,195,1,144,2,3,
+51,196,1,4,
+46,185,1,
+46,188,1,
 46,192,1,
 29,197,1,
 37,
-16,0,16,0,0,105,2,1,194,1,
-49,198,1,175,2,
+16,0,16,0,0,116,2,1,194,1,
+49,198,1,152,2,
 46,197,1,
 52,199,1,
-17,83,2,
-46,183,1,3,
-51,200,1,7,
-46,175,1,
-46,178,1,
-46,182,1,
-46,187,1,
-46,192,1,
-46,197,1,
-29,201,1,
-37,
-16,0,16,0,0,105,2,1,199,1,
-46,180,1,
-46,201,1,
-52,202,1,
-17,83,2,
-46,188,1,3,
-51,203,1,8,
-46,175,1,
-46,178,1,
-46,182,1,
-46,187,1,
-46,192,1,
-46,197,1,
-46,201,1,
-29,204,1,
-37,
-16,0,16,0,0,105,2,1,202,1,
+17,94,2,
+49,200,1,160,2,3,
+51,201,1,5,
 46,185,1,
-46,204,1,
-52,205,1,
-17,83,2,
-49,206,1,183,2,3,
-51,207,1,9,
-46,175,1,
-46,178,1,
-46,182,1,
-46,187,1,
+46,188,1,
 46,192,1,
 46,197,1,
-46,201,1,
-46,204,1,
-29,208,1,
+29,202,1,
 37,
-16,0,16,0,0,105,2,1,205,1,
-49,209,1,192,2,
-46,208,1,
-52,210,1,
-17,83,2,
-49,211,1,201,2,3,
-51,212,1,10,
-46,175,1,
-46,178,1,
-46,182,1,
-46,187,1,
+16,0,16,0,0,116,2,1,199,1,
+49,203,1,169,2,
+46,202,1,
+52,204,1,
+17,94,2,
+49,205,1,178,2,3,
+51,206,1,6,
+46,185,1,
+46,188,1,
 46,192,1,
 46,197,1,
-46,201,1,
-46,204,1,
-46,208,1,
-29,213,1,
+46,202,1,
+29,207,1,
 37,
-16,0,16,0,0,105,2,1,210,1,
-49,214,1,209,2,
-46,213,1,
-52,215,1,
-17,83,2,
+16,0,16,0,0,116,2,1,204,1,
+49,208,1,186,2,
+46,207,1,
+52,209,1,
+17,94,2,
 46,193,1,3,
-51,216,1,11,
-46,175,1,
-46,178,1,
-46,182,1,
-46,187,1,
+51,210,1,7,
+46,185,1,
+46,188,1,
 46,192,1,
 46,197,1,
-46,201,1,
-46,204,1,
-46,208,1,
-46,213,1,
-29,217,1,
+46,202,1,
+46,207,1,
+29,211,1,
 37,
-16,0,16,0,0,105,2,1,215,1,
+16,0,16,0,0,116,2,1,209,1,
 46,190,1,
-46,217,1,
-52,218,1,
-17,83,2,
+46,211,1,
+52,212,1,
+17,94,2,
 46,198,1,3,
-51,219,1,12,
-46,175,1,
-46,178,1,
-46,182,1,
-46,187,1,
+51,213,1,8,
+46,185,1,
+46,188,1,
 46,192,1,
 46,197,1,
-46,201,1,
-46,204,1,
-46,208,1,
-46,213,1,
-46,217,1,
-29,220,1,
+46,202,1,
+46,207,1,
+46,211,1,
+29,214,1,
 37,
-16,0,16,0,0,105,2,1,218,1,
+16,0,16,0,0,116,2,1,212,1,
 46,195,1,
-46,220,1,
-52,221,1,
-17,83,2,
-46,209,1,3,
-51,222,1,13,
-46,175,1,
-46,178,1,
-46,182,1,
-46,187,1,
+46,214,1,
+52,215,1,
+17,94,2,
+49,216,1,194,2,3,
+51,217,1,9,
+46,185,1,
+46,188,1,
 46,192,1,
 46,197,1,
-46,201,1,
-46,204,1,
-46,208,1,
-46,213,1,
-46,217,1,
-46,220,1,
+46,202,1,
+46,207,1,
+46,211,1,
+46,214,1,
+29,218,1,
+37,
+16,0,16,0,0,116,2,1,215,1,
+49,219,1,203,2,
+46,218,1,
+52,220,1,
+17,94,2,
+49,221,1,212,2,3,
+51,222,1,10,
+46,185,1,
+46,188,1,
+46,192,1,
+46,197,1,
+46,202,1,
+46,207,1,
+46,211,1,
+46,214,1,
+46,218,1,
 29,223,1,
 37,
-16,0,16,0,0,105,2,1,221,1,
-46,206,1,
+16,0,16,0,0,116,2,1,220,1,
+49,224,1,220,2,
 46,223,1,
-52,224,1,
-17,83,2,
-46,214,1,3,
-51,225,1,14,
-46,175,1,
-46,178,1,
-46,182,1,
-46,187,1,
+52,225,1,
+17,94,2,
+46,203,1,3,
+51,226,1,11,
+46,185,1,
+46,188,1,
 46,192,1,
 46,197,1,
-46,201,1,
-46,204,1,
-46,208,1,
-46,213,1,
-46,217,1,
-46,220,1,
-46,223,1,
-29,226,1,
-37,
-16,0,16,0,0,105,2,1,224,1,
+46,202,1,
+46,207,1,
 46,211,1,
-46,226,1,
-52,227,1,
-17,217,2,
-49,228,1,219,2,3,
-52,229,1,
-17,224,2,
-46,228,1,3,
+46,214,1,
+46,218,1,
+46,223,1,
+29,227,1,
+37,
+16,0,16,0,0,116,2,1,225,1,
+46,200,1,
+46,227,1,
+52,228,1,
+17,94,2,
+46,208,1,3,
+51,229,1,12,
+46,185,1,
+46,188,1,
+46,192,1,
+46,197,1,
+46,202,1,
+46,207,1,
+46,211,1,
+46,214,1,
+46,218,1,
+46,223,1,
+46,227,1,
 29,230,1,
 37,
-16,0,16,0,0,226,2,2,227,1,229,1,
-46,156,1,
+16,0,16,0,0,116,2,1,228,1,
+46,205,1,
+46,230,1,
 52,231,1,
-17,217,2,
-49,232,1,239,2,3,
-52,233,1,
-17,224,2,
-46,232,1,3,
-51,234,1,2,
-46,230,1,
-29,235,1,
-37,
-16,0,16,0,0,226,2,2,231,1,233,1,
-46,160,1,
-46,235,1,
-52,236,1,
-17,217,2,
-46,117,1,3,
-52,237,1,
-17,224,2,
-46,92,1,3,
-51,238,1,3,
-46,230,1,
-46,235,1,
-29,239,1,
-37,
-16,0,16,0,0,226,2,2,236,1,237,1,
-46,183,1,
-46,239,1,
-52,240,1,
-17,217,2,
-46,121,1,3,
-52,241,1,
-17,224,2,
-49,242,1,245,2,3,
-51,243,1,4,
-46,230,1,
-46,235,1,
-46,239,1,
-29,244,1,
-37,
-16,0,16,0,0,226,2,2,240,1,241,1,
-46,188,1,
-46,244,1,
-52,245,1,
-17,217,2,
-46,92,1,3,
-52,246,1,
-17,224,2,
-46,117,1,3,
-51,247,1,5,
-46,230,1,
-46,235,1,
-46,239,1,
-46,244,1,
-29,248,1,
-37,
-16,0,16,0,0,226,2,2,245,1,246,1,
-46,180,1,
-46,248,1,
-52,249,1,
-17,217,2,
-46,242,1,3,
-52,250,1,
-17,224,2,
-46,121,1,3,
-51,251,1,6,
-46,230,1,
-46,235,1,
-46,239,1,
-46,244,1,
-46,248,1,
-29,252,1,
-37,
-16,0,16,0,0,226,2,2,249,1,250,1,
+17,94,2,
+46,219,1,3,
+51,232,1,13,
 46,185,1,
-46,252,1,
-52,253,1,
-17,217,2,
-49,254,1,251,2,3,
-52,255,1,
-17,224,2,
-46,92,1,3,
-51,0,2,7,
+46,188,1,
+46,192,1,
+46,197,1,
+46,202,1,
+46,207,1,
+46,211,1,
+46,214,1,
+46,218,1,
+46,223,1,
+46,227,1,
 46,230,1,
-46,235,1,
-46,239,1,
-46,244,1,
-46,248,1,
-46,252,1,
-29,1,2,
+29,233,1,
 37,
-16,0,16,0,0,226,2,2,253,1,255,1,
-46,193,1,
-46,1,2,
-52,2,2,
-17,217,2,
-49,3,2,2,3,3,
-52,4,2,
-17,224,2,
-46,242,1,3,
-51,5,2,8,
+16,0,16,0,0,116,2,1,231,1,
+46,216,1,
+46,233,1,
+52,234,1,
+17,94,2,
+46,224,1,3,
+51,235,1,14,
+46,185,1,
+46,188,1,
+46,192,1,
+46,197,1,
+46,202,1,
+46,207,1,
+46,211,1,
+46,214,1,
+46,218,1,
+46,223,1,
+46,227,1,
 46,230,1,
-46,235,1,
-46,239,1,
-46,244,1,
-46,248,1,
-46,252,1,
-46,1,2,
+46,233,1,
+29,236,1,
+37,
+16,0,16,0,0,116,2,1,234,1,
+46,221,1,
+46,236,1,
+52,237,1,
+17,228,2,
+49,238,1,230,2,3,
+52,239,1,
+17,235,2,
+46,238,1,3,
+29,240,1,
+37,
+16,0,16,0,0,237,2,2,237,1,239,1,
+46,156,1,
+52,241,1,
+17,228,2,
+49,242,1,250,2,3,
+52,243,1,
+17,235,2,
+46,242,1,3,
+51,244,1,2,
+46,240,1,
+29,245,1,
+37,
+16,0,16,0,0,237,2,2,241,1,243,1,
+46,160,1,
+46,245,1,
+52,246,1,
+17,228,2,
+46,117,1,3,
+52,247,1,
+17,235,2,
+46,92,1,3,
+51,248,1,3,
+46,240,1,
+46,245,1,
+29,249,1,
+37,
+16,0,16,0,0,237,2,2,246,1,247,1,
+46,193,1,
+46,249,1,
+52,250,1,
+17,228,2,
+46,121,1,3,
+52,251,1,
+17,235,2,
+49,252,1,0,3,3,
+51,253,1,4,
+46,240,1,
+46,245,1,
+46,249,1,
+29,254,1,
+37,
+16,0,16,0,0,237,2,2,250,1,251,1,
+46,198,1,
+46,254,1,
+52,255,1,
+17,228,2,
+46,92,1,3,
+52,0,2,
+17,235,2,
+46,117,1,3,
+51,1,2,5,
+46,240,1,
+46,245,1,
+46,249,1,
+46,254,1,
+29,2,2,
+37,
+16,0,16,0,0,237,2,2,255,1,0,2,
+46,190,1,
+46,2,2,
+52,3,2,
+17,228,2,
+46,252,1,3,
+52,4,2,
+17,235,2,
+46,121,1,3,
+51,5,2,6,
+46,240,1,
+46,245,1,
+46,249,1,
+46,254,1,
+46,2,2,
 29,6,2,
 37,
-16,0,16,0,0,226,2,2,2,2,4,2,
-46,198,1,
+16,0,16,0,0,237,2,2,3,2,4,2,
+46,195,1,
 46,6,2,
 52,7,2,
-17,217,2,
+17,228,2,
+49,8,2,6,3,3,
+52,9,2,
+17,235,2,
 46,92,1,3,
-52,8,2,
-17,224,2,
-46,254,1,3,
-51,9,2,9,
-46,230,1,
-46,235,1,
-46,239,1,
-46,244,1,
-46,248,1,
-46,252,1,
-46,1,2,
-46,6,2,
-29,10,2,
-37,
-16,0,16,0,0,226,2,2,7,2,8,2,
-46,190,1,
-46,10,2,
-52,11,2,
-17,217,2,
-46,242,1,3,
-52,12,2,
-17,224,2,
-46,3,2,3,
-51,13,2,10,
-46,230,1,
-46,235,1,
-46,239,1,
-46,244,1,
-46,248,1,
-46,252,1,
-46,1,2,
-46,6,2,
-46,10,2,
-29,14,2,
-37,
-16,0,16,0,0,226,2,2,11,2,12,2,
-46,195,1,
-46,14,2,
-52,15,2,
-17,217,2,
-46,254,1,3,
-52,16,2,
-17,224,2,
-46,117,1,3,
-51,17,2,11,
-46,230,1,
-46,235,1,
-46,239,1,
-46,244,1,
-46,248,1,
-46,252,1,
-46,1,2,
-46,6,2,
-46,10,2,
-46,14,2,
-29,18,2,
-37,
-16,0,16,0,0,226,2,2,15,2,16,2,
-46,209,1,
-46,18,2,
-52,19,2,
-17,217,2,
-46,3,2,3,
-52,20,2,
-17,224,2,
-46,121,1,3,
-51,21,2,12,
-46,230,1,
-46,235,1,
-46,239,1,
-46,244,1,
-46,248,1,
-46,252,1,
-46,1,2,
-46,6,2,
-46,10,2,
-46,14,2,
-46,18,2,
-29,22,2,
-37,
-16,0,16,0,0,226,2,2,19,2,20,2,
-46,214,1,
-46,22,2,
-52,23,2,
-17,217,2,
-46,117,1,3,
-52,24,2,
-17,224,2,
-46,254,1,3,
-51,25,2,13,
-46,230,1,
-46,235,1,
-46,239,1,
-46,244,1,
-46,248,1,
-46,252,1,
-46,1,2,
-46,6,2,
-46,10,2,
-46,14,2,
-46,18,2,
-46,22,2,
-29,26,2,
-37,
-16,0,16,0,0,226,2,2,23,2,24,2,
-46,206,1,
-46,26,2,
-52,27,2,
-17,217,2,
-46,121,1,3,
-52,28,2,
-17,224,2,
-46,3,2,3,
-51,29,2,14,
-46,230,1,
-46,235,1,
-46,239,1,
-46,244,1,
-46,248,1,
-46,252,1,
-46,1,2,
-46,6,2,
-46,10,2,
-46,14,2,
-46,18,2,
-46,22,2,
-46,26,2,
-29,30,2,
-37,
-16,0,16,0,0,226,2,2,27,2,28,2,
-46,211,1,
-46,30,2,
-52,31,2,
-17,55,0,
-46,228,1,3,
-52,32,2,
-17,67,0,
-46,228,1,3,
-29,33,2,
-17,8,3,2,31,2,32,2,
-49,34,2,17,3,
-52,35,2,
-17,55,0,
-46,232,1,3,
-52,36,2,
-17,67,0,
-46,232,1,3,
-51,37,2,2,
-46,33,2,
-29,38,2,
-17,8,3,2,35,2,36,2,
-46,34,2,
-46,38,2,
-52,39,2,
-17,55,0,
-49,40,2,23,3,3,
-52,41,2,
-17,67,0,
-46,40,2,3,
-51,42,2,3,
-46,33,2,
-46,38,2,
-29,43,2,
-17,8,3,2,39,2,41,2,
-46,34,2,
-46,43,2,
-52,44,2,
-17,55,0,
-46,228,1,3,
-52,45,2,
-17,67,0,
-46,228,1,3,
-29,46,2,
-17,29,3,2,44,2,45,2,
-46,34,2,
-52,47,2,
-17,55,0,
-46,232,1,3,
-52,48,2,
-17,67,0,
-46,232,1,3,
-51,49,2,2,
-46,46,2,
-29,50,2,
-17,29,3,2,47,2,48,2,
-46,34,2,
-46,50,2,
-52,51,2,
-17,55,0,
-46,40,2,3,
-52,52,2,
-17,67,0,
-46,40,2,3,
-51,53,2,3,
-46,46,2,
-46,50,2,
-29,54,2,
-17,29,3,2,51,2,52,2,
-46,34,2,
-46,54,2,
-52,55,2,
-17,55,0,
-46,228,1,3,
-52,56,2,
-17,67,0,
-46,228,1,3,
-29,57,2,
-17,43,3,2,55,2,56,2,
-46,34,2,
-52,58,2,
-17,55,0,
-46,232,1,3,
-52,59,2,
-17,67,0,
-46,232,1,3,
-51,60,2,2,
-46,57,2,
-29,61,2,
-17,43,3,2,58,2,59,2,
-46,34,2,
-46,61,2,
-52,62,2,
-17,55,0,
-46,40,2,3,
-52,63,2,
-17,67,0,
-46,40,2,3,
-51,64,2,3,
-46,57,2,
-46,61,2,
-29,65,2,
-17,43,3,2,62,2,63,2,
-46,34,2,
-46,65,2,
-52,66,2,
-17,55,0,
-46,228,1,3,
-52,67,2,
-17,67,0,
-46,228,1,3,
-29,68,2,
-17,55,3,2,66,2,67,2,
-46,34,2,
-52,69,2,
-17,55,0,
-46,232,1,3,
-52,70,2,
-17,67,0,
-46,232,1,3,
-51,71,2,2,
-46,68,2,
-29,72,2,
-17,55,3,2,69,2,70,2,
-46,34,2,
-46,72,2,
-52,73,2,
-17,55,0,
-46,40,2,3,
-52,74,2,
-17,67,0,
-46,40,2,3,
-51,75,2,3,
-46,68,2,
-46,72,2,
-29,76,2,
-17,55,3,2,73,2,74,2,
-46,34,2,
-46,76,2,
-52,77,2,
-17,55,0,
-46,228,1,3,
-52,78,2,
-17,67,0,
-46,228,1,3,
-29,79,2,
-17,72,3,2,77,2,78,2,
-46,34,2,
-52,80,2,
-17,55,0,
-46,232,1,3,
-52,81,2,
-17,67,0,
-46,232,1,3,
-51,82,2,2,
-46,79,2,
-29,83,2,
-17,72,3,2,80,2,81,2,
-46,34,2,
-46,83,2,
-52,84,2,
-17,55,0,
-46,40,2,3,
-52,85,2,
-17,67,0,
-46,40,2,3,
-51,86,2,3,
-46,79,2,
-46,83,2,
-29,87,2,
-17,72,3,2,84,2,85,2,
-46,34,2,
-46,87,2,
-52,88,2,
-17,55,0,
-46,34,2,3,
-52,89,2,
-17,67,0,
-46,34,2,3,
-51,90,2,4,
-46,79,2,
-46,83,2,
-46,87,2,
-29,91,2,
-17,72,3,2,88,2,89,2,
-46,34,2,
-46,91,2,
-52,92,2,
-17,55,0,
-46,228,1,3,
-52,93,2,
-17,67,0,
-46,228,1,3,
-29,94,2,
-17,78,3,2,92,2,93,2,
-46,34,2,
-52,95,2,
-17,55,0,
-46,232,1,3,
-52,96,2,
-17,67,0,
-46,232,1,3,
-51,97,2,2,
-46,94,2,
-29,98,2,
-17,78,3,2,95,2,96,2,
-46,34,2,
-46,98,2,
-52,99,2,
-17,55,0,
-46,40,2,3,
-52,100,2,
-17,67,0,
-46,40,2,3,
-51,101,2,3,
-46,94,2,
-46,98,2,
-29,102,2,
-17,78,3,2,99,2,100,2,
-46,34,2,
-46,102,2,
-52,103,2,
-17,55,0,
-46,34,2,3,
-52,104,2,
-17,67,0,
-46,34,2,3,
-51,105,2,4,
-46,94,2,
-46,98,2,
-46,102,2,
-29,106,2,
-17,78,3,2,103,2,104,2,
-46,34,2,
-46,106,2,
-52,107,2,
-17,55,0,
-46,34,2,3,
-29,108,2,
-17,87,3,1,107,2,
-49,109,2,91,3,
-52,110,2,
-17,55,0,
-46,34,2,3,
-29,111,2,
-17,96,3,1,110,2,
-46,109,2,
-52,112,2,
-17,55,0,
-46,34,2,3,
-29,113,2,
-17,100,3,1,112,2,
-46,34,2,
-52,114,2,
-17,187,1,
-46,2,0,3,
-29,115,2,
-37,
-16,0,16,0,0,104,3,1,114,2,
-46,2,0,
-52,116,2,
-17,187,1,
-46,2,0,3,
-29,117,2,
-37,
-16,0,16,0,0,109,3,1,116,2,
-46,2,0,
-52,118,2,
-17,187,1,
-46,5,0,3,
-51,119,2,2,
-46,115,2,
-29,120,2,
-37,
-16,0,16,0,0,104,3,1,118,2,
-46,5,0,
-46,120,2,
-52,121,2,
-17,187,1,
-46,5,0,3,
-51,122,2,2,
-46,117,2,
-29,123,2,
-37,
-16,0,16,0,0,109,3,1,121,2,
-46,5,0,
-46,123,2,
-52,124,2,
-17,114,3,
-46,3,2,3,
-29,125,2,
-17,120,3,1,124,2,
-46,3,2,
-52,126,2,
-17,114,3,
-46,254,1,3,
-51,127,2,2,
-46,125,2,
-29,128,2,
-17,120,3,1,126,2,
+51,10,2,7,
+46,240,1,
+46,245,1,
+46,249,1,
 46,254,1,
-46,128,2,
-52,129,2,
-17,129,3,
+46,2,2,
+46,6,2,
+29,11,2,
+37,
+16,0,16,0,0,237,2,2,7,2,9,2,
+46,203,1,
+46,11,2,
+52,12,2,
+17,228,2,
+49,13,2,13,3,3,
+52,14,2,
+17,235,2,
+46,252,1,3,
+51,15,2,8,
+46,240,1,
+46,245,1,
+46,249,1,
+46,254,1,
+46,2,2,
+46,6,2,
+46,11,2,
+29,16,2,
+37,
+16,0,16,0,0,237,2,2,12,2,14,2,
+46,208,1,
+46,16,2,
+52,17,2,
+17,228,2,
 46,92,1,3,
-52,130,2,
-17,136,3,
-49,131,2,138,3,3,
-29,132,2,
-17,145,3,2,129,2,130,2,
-46,3,2,
-52,133,2,
-17,114,3,
-46,3,2,3,
+52,18,2,
+17,235,2,
+46,8,2,3,
+51,19,2,9,
+46,240,1,
+46,245,1,
+46,249,1,
+46,254,1,
+46,2,2,
+46,6,2,
+46,11,2,
+46,16,2,
+29,20,2,
+37,
+16,0,16,0,0,237,2,2,17,2,18,2,
+46,200,1,
+46,20,2,
+52,21,2,
+17,228,2,
+46,252,1,3,
+52,22,2,
+17,235,2,
+46,13,2,3,
+51,23,2,10,
+46,240,1,
+46,245,1,
+46,249,1,
+46,254,1,
+46,2,2,
+46,6,2,
+46,11,2,
+46,16,2,
+46,20,2,
+29,24,2,
+37,
+16,0,16,0,0,237,2,2,21,2,22,2,
+46,205,1,
+46,24,2,
+52,25,2,
+17,228,2,
+46,8,2,3,
+52,26,2,
+17,235,2,
+46,117,1,3,
+51,27,2,11,
+46,240,1,
+46,245,1,
+46,249,1,
+46,254,1,
+46,2,2,
+46,6,2,
+46,11,2,
+46,16,2,
+46,20,2,
+46,24,2,
+29,28,2,
+37,
+16,0,16,0,0,237,2,2,25,2,26,2,
+46,219,1,
+46,28,2,
+52,29,2,
+17,228,2,
+46,13,2,3,
+52,30,2,
+17,235,2,
+46,121,1,3,
+51,31,2,12,
+46,240,1,
+46,245,1,
+46,249,1,
+46,254,1,
+46,2,2,
+46,6,2,
+46,11,2,
+46,16,2,
+46,20,2,
+46,24,2,
+46,28,2,
+29,32,2,
+37,
+16,0,16,0,0,237,2,2,29,2,30,2,
+46,224,1,
+46,32,2,
+52,33,2,
+17,228,2,
+46,117,1,3,
+52,34,2,
+17,235,2,
+46,8,2,3,
+51,35,2,13,
+46,240,1,
+46,245,1,
+46,249,1,
+46,254,1,
+46,2,2,
+46,6,2,
+46,11,2,
+46,16,2,
+46,20,2,
+46,24,2,
+46,28,2,
+46,32,2,
+29,36,2,
+37,
+16,0,16,0,0,237,2,2,33,2,34,2,
+46,216,1,
+46,36,2,
+52,37,2,
+17,228,2,
+46,121,1,3,
+52,38,2,
+17,235,2,
+46,13,2,3,
+51,39,2,14,
+46,240,1,
+46,245,1,
+46,249,1,
+46,254,1,
+46,2,2,
+46,6,2,
+46,11,2,
+46,16,2,
+46,20,2,
+46,24,2,
+46,28,2,
+46,32,2,
+46,36,2,
+29,40,2,
+37,
+16,0,16,0,0,237,2,2,37,2,38,2,
+46,221,1,
+46,40,2,
+52,41,2,
+17,55,0,
+46,238,1,3,
+52,42,2,
+17,67,0,
+46,238,1,3,
+29,43,2,
+17,19,3,2,41,2,42,2,
+49,44,2,28,3,
+52,45,2,
+17,55,0,
+46,242,1,3,
+52,46,2,
+17,67,0,
+46,242,1,3,
+51,47,2,2,
+46,43,2,
+29,48,2,
+17,19,3,2,45,2,46,2,
+46,44,2,
+46,48,2,
+52,49,2,
+17,55,0,
+49,50,2,34,3,3,
+52,51,2,
+17,67,0,
+46,50,2,3,
+51,52,2,3,
+46,43,2,
+46,48,2,
+29,53,2,
+17,19,3,2,49,2,51,2,
+46,44,2,
+46,53,2,
+52,54,2,
+17,55,0,
+46,238,1,3,
+52,55,2,
+17,67,0,
+46,238,1,3,
+29,56,2,
+17,40,3,2,54,2,55,2,
+46,44,2,
+52,57,2,
+17,55,0,
+46,242,1,3,
+52,58,2,
+17,67,0,
+46,242,1,3,
+51,59,2,2,
+46,56,2,
+29,60,2,
+17,40,3,2,57,2,58,2,
+46,44,2,
+46,60,2,
+52,61,2,
+17,55,0,
+46,50,2,3,
+52,62,2,
+17,67,0,
+46,50,2,3,
+51,63,2,3,
+46,56,2,
+46,60,2,
+29,64,2,
+17,40,3,2,61,2,62,2,
+46,44,2,
+46,64,2,
+52,65,2,
+17,55,0,
+46,238,1,3,
+52,66,2,
+17,67,0,
+46,238,1,3,
+29,67,2,
+17,54,3,2,65,2,66,2,
+46,44,2,
+52,68,2,
+17,55,0,
+46,242,1,3,
+52,69,2,
+17,67,0,
+46,242,1,3,
+51,70,2,2,
+46,67,2,
+29,71,2,
+17,54,3,2,68,2,69,2,
+46,44,2,
+46,71,2,
+52,72,2,
+17,55,0,
+46,50,2,3,
+52,73,2,
+17,67,0,
+46,50,2,3,
+51,74,2,3,
+46,67,2,
+46,71,2,
+29,75,2,
+17,54,3,2,72,2,73,2,
+46,44,2,
+46,75,2,
+52,76,2,
+17,55,0,
+46,238,1,3,
+52,77,2,
+17,67,0,
+46,238,1,3,
+29,78,2,
+17,66,3,2,76,2,77,2,
+46,44,2,
+52,79,2,
+17,55,0,
+46,242,1,3,
+52,80,2,
+17,67,0,
+46,242,1,3,
+51,81,2,2,
+46,78,2,
+29,82,2,
+17,66,3,2,79,2,80,2,
+46,44,2,
+46,82,2,
+52,83,2,
+17,55,0,
+46,50,2,3,
+52,84,2,
+17,67,0,
+46,50,2,3,
+51,85,2,3,
+46,78,2,
+46,82,2,
+29,86,2,
+17,66,3,2,83,2,84,2,
+46,44,2,
+46,86,2,
+52,87,2,
+17,55,0,
+46,238,1,3,
+52,88,2,
+17,67,0,
+46,238,1,3,
+29,89,2,
+17,83,3,2,87,2,88,2,
+46,44,2,
+52,90,2,
+17,55,0,
+46,242,1,3,
+52,91,2,
+17,67,0,
+46,242,1,3,
+51,92,2,2,
+46,89,2,
+29,93,2,
+17,83,3,2,90,2,91,2,
+46,44,2,
+46,93,2,
+52,94,2,
+17,55,0,
+46,50,2,3,
+52,95,2,
+17,67,0,
+46,50,2,3,
+51,96,2,3,
+46,89,2,
+46,93,2,
+29,97,2,
+17,83,3,2,94,2,95,2,
+46,44,2,
+46,97,2,
+52,98,2,
+17,55,0,
+46,44,2,3,
+52,99,2,
+17,67,0,
+46,44,2,3,
+51,100,2,4,
+46,89,2,
+46,93,2,
+46,97,2,
+29,101,2,
+17,83,3,2,98,2,99,2,
+46,44,2,
+46,101,2,
+52,102,2,
+17,55,0,
+46,238,1,3,
+52,103,2,
+17,67,0,
+46,238,1,3,
+29,104,2,
+17,89,3,2,102,2,103,2,
+46,44,2,
+52,105,2,
+17,55,0,
+46,242,1,3,
+52,106,2,
+17,67,0,
+46,242,1,3,
+51,107,2,2,
+46,104,2,
+29,108,2,
+17,89,3,2,105,2,106,2,
+46,44,2,
+46,108,2,
+52,109,2,
+17,55,0,
+46,50,2,3,
+52,110,2,
+17,67,0,
+46,50,2,3,
+51,111,2,3,
+46,104,2,
+46,108,2,
+29,112,2,
+17,89,3,2,109,2,110,2,
+46,44,2,
+46,112,2,
+52,113,2,
+17,55,0,
+46,44,2,3,
+52,114,2,
+17,67,0,
+46,44,2,3,
+51,115,2,4,
+46,104,2,
+46,108,2,
+46,112,2,
+29,116,2,
+17,89,3,2,113,2,114,2,
+46,44,2,
+46,116,2,
+52,117,2,
+17,55,0,
+46,44,2,3,
+29,118,2,
+17,98,3,1,117,2,
+49,119,2,102,3,
+52,120,2,
+17,55,0,
+46,44,2,3,
+29,121,2,
+17,107,3,1,120,2,
+46,119,2,
+52,122,2,
+17,55,0,
+46,44,2,3,
+29,123,2,
+17,111,3,1,122,2,
+46,44,2,
+52,124,2,
+17,187,1,
+46,2,0,3,
+29,125,2,
+37,
+16,0,16,0,0,115,3,1,124,2,
+46,2,0,
+52,126,2,
+17,187,1,
+46,2,0,3,
+29,127,2,
+37,
+16,0,16,0,0,120,3,1,126,2,
+46,2,0,
+52,128,2,
+17,187,1,
+46,5,0,3,
+51,129,2,2,
+46,125,2,
+29,130,2,
+37,
+16,0,16,0,0,115,3,1,128,2,
+46,5,0,
+46,130,2,
+52,131,2,
+17,187,1,
+46,5,0,3,
+51,132,2,2,
+46,127,2,
+29,133,2,
+37,
+16,0,16,0,0,120,3,1,131,2,
+46,5,0,
+46,133,2,
 52,134,2,
-17,151,3,
-49,135,2,153,3,3,
-51,136,2,2,
-46,132,2,
-29,137,2,
-17,145,3,2,133,2,134,2,
-46,3,2,
-46,137,2,
-52,138,2,
-17,165,3,
-46,3,2,3,
+17,125,3,
+46,13,2,3,
+29,135,2,
+17,131,3,1,134,2,
+46,13,2,
+52,136,2,
+17,125,3,
+46,8,2,3,
+51,137,2,2,
+46,135,2,
+29,138,2,
+17,131,3,1,136,2,
+46,8,2,
+46,138,2,
 52,139,2,
-17,169,3,
-46,3,2,3,
+17,140,3,
+46,92,1,3,
 52,140,2,
-17,173,3,
-49,141,2,175,3,3,
-51,142,2,3,
-46,132,2,
-46,137,2,
-29,143,2,
-17,145,3,3,138,2,139,2,140,2,
-46,3,2,
-46,143,2,72,0,
-104,2,
+17,147,3,
+49,141,2,149,3,3,
+29,142,2,
+17,156,3,2,139,2,140,2,
+46,13,2,
+52,143,2,
+17,125,3,
+46,13,2,3,
+52,144,2,
+17,162,3,
+49,145,2,164,3,3,
+51,146,2,2,
+46,142,2,
+29,147,2,
+17,156,3,2,143,2,144,2,
+46,13,2,
+46,147,2,
+52,148,2,
+17,176,3,
+46,13,2,3,
+52,149,2,
+17,180,3,
+46,13,2,3,
+52,150,2,
+17,184,3,
+49,151,2,186,3,3,
+51,152,2,3,
+46,142,2,
+46,147,2,
+29,153,2,
+17,156,3,3,148,2,149,2,150,2,
+46,13,2,
+46,153,2,72,0,
+112,2,
 118,0,
 33,0,
 71,0,
-76,2,
-74,2,
+84,2,
+82,2,
 28,0,
 66,0,
 46,0,
@@ -2301,13 +2332,13 @@
 18,0,
 56,0,
 110,1,
-84,2,
-87,2,
+92,2,
+95,2,
 8,0,
-157,1,
+165,1,
 96,1,
 103,1,
-56,2,
+64,2,
 88,0,
 98,0,
 124,1,
@@ -2315,28 +2346,28 @@
 9,1,
 128,0,
 138,0,
-30,2,
-41,2,
+38,2,
+49,2,
 11,1,
-152,1,
+160,1,
 113,0,
 73,1,
 68,1,
 89,1,
-8,2,
-19,2,
+16,2,
+27,2,
 93,0,
 103,0,
-147,1,
+155,1,
 43,1,
 35,1,
 63,1,
 153,0,
 80,1,
 115,1,
-78,2,
-71,2,
-253,1,
+86,2,
+79,2,
+5,2,
 83,1,
 83,0,
 3,0,
@@ -2353,45 +2384,45 @@
 241,0,
 23,0,
 61,0,
-198,1,
+206,1,
 17,1,
 13,1,
 85,1,
-92,2,
+100,2,
 20,
-28,125,2,
+28,135,2,
 2,
 48,0,0,0,0,1,
 40,
 8,
-46,3,2,2,
+46,13,2,2,
 1,
 45,
-55,124,2,0,3,0,1,2,50,
+55,134,2,0,3,0,1,2,50,
 27,
 46,153,0,185,0,2,
 45,
-55,124,2,0,1,3,
+55,134,2,0,1,3,
 25,
 46,153,0,23,183,209,56,
 45,
-55,124,2,0,1,3,1,
-28,128,2,
+55,134,2,0,1,3,1,
+28,138,2,
 2,
 48,0,0,0,0,1,
 40,
 8,
-46,254,1,2,
+46,8,2,2,
 1,
 45,
-55,126,2,0,3,0,1,2,50,
+55,136,2,0,3,0,1,2,50,
 27,
 46,145,0,177,0,2,
 45,
-55,126,2,0,1,3,
+55,136,2,0,1,3,
 25,
 46,145,0,23,183,209,56,
 45,
-55,126,2,0,1,3,1,
+55,136,2,0,1,3,1,
 21,};
 static constexpr size_t SKSL_INCLUDE_sksl_public_LENGTH = sizeof(SKSL_INCLUDE_sksl_public);
diff --git a/src/sksl/sksl_public.sksl b/src/sksl/sksl_public.sksl
index ab7bdd7..f193961 100644
--- a/src/sksl/sksl_public.sksl
+++ b/src/sksl/sksl_public.sksl
@@ -151,6 +151,8 @@
 // 8.6 : Matrix Functions
 $squareMat  matrixCompMult($squareMat  x, $squareMat  y);
 $squareHMat matrixCompMult($squareHMat x, $squareHMat y);
+$es3 $mat   matrixCompMult($mat x, $mat y);
+$es3 $hmat  matrixCompMult($hmat x, $hmat y);
 
 // 8.6 : Matrix Functions (GLSL 1.4, poly-filled by SkSL as needed)
 $squareMat  inverse($squareMat  m);
diff --git a/tests/SkSLTest.cpp b/tests/SkSLTest.cpp
index 344d89a..b2fdb1f 100644
--- a/tests/SkSLTest.cpp
+++ b/tests/SkSLTest.cpp
@@ -217,6 +217,8 @@
 SKSL_TEST_ES3(SkSLIntrinsicIsInf,              "intrinsics/IsInf.sksl")
 // Fails on Adreno 6xx + Vulkan
 SKSL_TEST_CPU(SkSLIntrinsicClampFloat,         "intrinsics/ClampFloat.sksl")
+SKSL_TEST(SkSLIntrinsicMatrixCompMultES2,      "intrinsics/MatrixCompMultES2.sksl")
+SKSL_TEST_ES3(SkSLIntrinsicMatrixCompMultES3,  "intrinsics/MatrixCompMultES3.sksl")
 SKSL_TEST(SkSLIntrinsicMaxFloat,               "intrinsics/MaxFloat.sksl")
 SKSL_TEST(SkSLIntrinsicMinFloat,               "intrinsics/MinFloat.sksl")
 // Fails on Adreno + Vulkan (skia:11919)
diff --git a/tests/sksl/intrinsics/MatrixCompMult.asm.frag b/tests/sksl/intrinsics/MatrixCompMult.asm.frag
deleted file mode 100644
index 14964ec..0000000
--- a/tests/sksl/intrinsics/MatrixCompMult.asm.frag
+++ /dev/null
@@ -1,274 +0,0 @@
-OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %sk_FragColor %sk_Clockwise
-OpExecutionMode %main OriginUpperLeft
-OpName %sk_FragColor "sk_FragColor"
-OpName %sk_Clockwise "sk_Clockwise"
-OpName %a "a"
-OpName %b "b"
-OpName %c "c"
-OpName %d "d"
-OpName %_UniformBuffer "_UniformBuffer"
-OpMemberName %_UniformBuffer 0 "colorGreen"
-OpMemberName %_UniformBuffer 1 "colorRed"
-OpName %main "main"
-OpName %h22 "h22"
-OpName %h44 "h44"
-OpName %f43 "f43"
-OpDecorate %sk_FragColor RelaxedPrecision
-OpDecorate %sk_FragColor Location 0
-OpDecorate %sk_FragColor Index 0
-OpDecorate %sk_Clockwise BuiltIn FrontFacing
-OpDecorate %a RelaxedPrecision
-OpDecorate %b RelaxedPrecision
-OpMemberDecorate %_UniformBuffer 0 Offset 0
-OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision
-OpMemberDecorate %_UniformBuffer 1 Offset 16
-OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
-OpDecorate %_UniformBuffer Block
-OpDecorate %19 Binding 0
-OpDecorate %19 DescriptorSet 0
-OpDecorate %h22 RelaxedPrecision
-OpDecorate %33 RelaxedPrecision
-OpDecorate %34 RelaxedPrecision
-OpDecorate %35 RelaxedPrecision
-OpDecorate %h44 RelaxedPrecision
-OpDecorate %42 RelaxedPrecision
-OpDecorate %43 RelaxedPrecision
-OpDecorate %44 RelaxedPrecision
-OpDecorate %45 RelaxedPrecision
-OpDecorate %46 RelaxedPrecision
-OpDecorate %64 RelaxedPrecision
-OpDecorate %65 RelaxedPrecision
-OpDecorate %66 RelaxedPrecision
-OpDecorate %67 RelaxedPrecision
-OpDecorate %68 RelaxedPrecision
-OpDecorate %69 RelaxedPrecision
-OpDecorate %70 RelaxedPrecision
-OpDecorate %71 RelaxedPrecision
-OpDecorate %72 RelaxedPrecision
-OpDecorate %73 RelaxedPrecision
-OpDecorate %74 RelaxedPrecision
-OpDecorate %75 RelaxedPrecision
-OpDecorate %80 RelaxedPrecision
-OpDecorate %81 RelaxedPrecision
-OpDecorate %82 RelaxedPrecision
-OpDecorate %104 RelaxedPrecision
-OpDecorate %105 RelaxedPrecision
-OpDecorate %106 RelaxedPrecision
-OpDecorate %107 RelaxedPrecision
-OpDecorate %120 RelaxedPrecision
-OpDecorate %121 RelaxedPrecision
-OpDecorate %122 RelaxedPrecision
-OpDecorate %123 RelaxedPrecision
-OpDecorate %124 RelaxedPrecision
-OpDecorate %125 RelaxedPrecision
-OpDecorate %182 RelaxedPrecision
-OpDecorate %185 RelaxedPrecision
-OpDecorate %186 RelaxedPrecision
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%sk_FragColor = OpVariable %_ptr_Output_v4float Output
-%bool = OpTypeBool
-%_ptr_Input_bool = OpTypePointer Input %bool
-%sk_Clockwise = OpVariable %_ptr_Input_bool Input
-%v3float = OpTypeVector %float 3
-%mat3v3float = OpTypeMatrix %v3float 3
-%_ptr_Private_mat3v3float = OpTypePointer Private %mat3v3float
-%a = OpVariable %_ptr_Private_mat3v3float Private
-%b = OpVariable %_ptr_Private_mat3v3float Private
-%mat4v4float = OpTypeMatrix %v4float 4
-%_ptr_Private_mat4v4float = OpTypePointer Private %mat4v4float
-%c = OpVariable %_ptr_Private_mat4v4float Private
-%d = OpVariable %_ptr_Private_mat4v4float Private
-%_UniformBuffer = OpTypeStruct %v4float %v4float
-%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer
-%19 = OpVariable %_ptr_Uniform__UniformBuffer Uniform
-%void = OpTypeVoid
-%23 = OpTypeFunction %void
-%v2float = OpTypeVector %float 2
-%mat2v2float = OpTypeMatrix %v2float 2
-%_ptr_Function_mat2v2float = OpTypePointer Function %mat2v2float
-%float_0 = OpConstant %float 0
-%float_5 = OpConstant %float 5
-%float_10 = OpConstant %float 10
-%float_15 = OpConstant %float 15
-%_ptr_Function_mat4v4float = OpTypePointer Function %mat4v4float
-%float_0_5 = OpConstant %float 0.5
-%float_3 = OpConstant %float 3
-%float_5_5 = OpConstant %float 5.5
-%float_8 = OpConstant %float 8
-%mat4v3float = OpTypeMatrix %v3float 4
-%_ptr_Function_mat4v3float = OpTypePointer Function %mat4v3float
-%float_12 = OpConstant %float 12
-%float_22 = OpConstant %float 22
-%float_30 = OpConstant %float 30
-%float_36 = OpConstant %float 36
-%float_40 = OpConstant %float 40
-%float_42 = OpConstant %float 42
-%_ptr_Function_mat3v3float = OpTypePointer Function %mat3v3float
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Function_v3float = OpTypePointer Function %v3float
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%false = OpConstantFalse %bool
-%v2bool = OpTypeVector %bool 2
-%v4bool = OpTypeVector %bool 4
-%v3bool = OpTypeVector %bool 3
-%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
-%int_1 = OpConstant %int 1
-%main = OpFunction %void None %23
-%24 = OpLabel
-%h22 = OpVariable %_ptr_Function_mat2v2float Function
-%h44 = OpVariable %_ptr_Function_mat4v4float Function
-%f43 = OpVariable %_ptr_Function_mat4v3float Function
-%61 = OpVariable %_ptr_Function_mat3v3float Function
-%83 = OpVariable %_ptr_Function_mat4v4float Function
-%176 = OpVariable %_ptr_Function_v4float Function
-%33 = OpCompositeConstruct %v2float %float_0 %float_5
-%34 = OpCompositeConstruct %v2float %float_10 %float_15
-%35 = OpCompositeConstruct %mat2v2float %33 %34
-OpStore %h22 %35
-%42 = OpCompositeConstruct %v4float %float_0_5 %float_0 %float_0 %float_0
-%43 = OpCompositeConstruct %v4float %float_0 %float_3 %float_0 %float_0
-%44 = OpCompositeConstruct %v4float %float_0 %float_0 %float_5_5 %float_0
-%45 = OpCompositeConstruct %v4float %float_0 %float_0 %float_0 %float_8
-%46 = OpCompositeConstruct %mat4v4float %42 %43 %44 %45
-OpStore %h44 %46
-%56 = OpCompositeConstruct %v3float %float_12 %float_22 %float_30
-%57 = OpCompositeConstruct %v3float %float_36 %float_40 %float_42
-%58 = OpCompositeConstruct %v3float %float_42 %float_40 %float_36
-%59 = OpCompositeConstruct %v3float %float_30 %float_22 %float_12
-%60 = OpCompositeConstruct %mat4v3float %56 %57 %58 %59
-OpStore %f43 %60
-%64 = OpLoad %mat3v3float %a
-%65 = OpLoad %mat3v3float %b
-%66 = OpCompositeExtract %v3float %64 0
-%67 = OpCompositeExtract %v3float %65 0
-%68 = OpFMul %v3float %66 %67
-%69 = OpCompositeExtract %v3float %64 1
-%70 = OpCompositeExtract %v3float %65 1
-%71 = OpFMul %v3float %69 %70
-%72 = OpCompositeExtract %v3float %64 2
-%73 = OpCompositeExtract %v3float %65 2
-%74 = OpFMul %v3float %72 %73
-%75 = OpCompositeConstruct %mat3v3float %68 %71 %74
-OpStore %61 %75
-%78 = OpAccessChain %_ptr_Function_v3float %61 %int_0
-%80 = OpLoad %v3float %78
-%81 = OpLoad %v4float %sk_FragColor
-%82 = OpVectorShuffle %v4float %81 %80 4 5 6 3
-OpStore %sk_FragColor %82
-%85 = OpLoad %mat4v4float %c
-%86 = OpLoad %mat4v4float %d
-%87 = OpCompositeExtract %v4float %85 0
-%88 = OpCompositeExtract %v4float %86 0
-%89 = OpFMul %v4float %87 %88
-%90 = OpCompositeExtract %v4float %85 1
-%91 = OpCompositeExtract %v4float %86 1
-%92 = OpFMul %v4float %90 %91
-%93 = OpCompositeExtract %v4float %85 2
-%94 = OpCompositeExtract %v4float %86 2
-%95 = OpFMul %v4float %93 %94
-%96 = OpCompositeExtract %v4float %85 3
-%97 = OpCompositeExtract %v4float %86 3
-%98 = OpFMul %v4float %96 %97
-%99 = OpCompositeConstruct %mat4v4float %89 %92 %95 %98
-OpStore %83 %99
-%100 = OpAccessChain %_ptr_Function_v4float %83 %int_0
-%102 = OpLoad %v4float %100
-OpStore %sk_FragColor %102
-%104 = OpLoad %mat2v2float %h22
-%105 = OpCompositeConstruct %v2float %float_0 %float_5
-%106 = OpCompositeConstruct %v2float %float_10 %float_15
-%107 = OpCompositeConstruct %mat2v2float %105 %106
-%109 = OpCompositeExtract %v2float %104 0
-%110 = OpCompositeExtract %v2float %107 0
-%111 = OpFOrdEqual %v2bool %109 %110
-%112 = OpAll %bool %111
-%113 = OpCompositeExtract %v2float %104 1
-%114 = OpCompositeExtract %v2float %107 1
-%115 = OpFOrdEqual %v2bool %113 %114
-%116 = OpAll %bool %115
-%117 = OpLogicalAnd %bool %112 %116
-OpSelectionMerge %119 None
-OpBranchConditional %117 %118 %119
-%118 = OpLabel
-%120 = OpLoad %mat4v4float %h44
-%121 = OpCompositeConstruct %v4float %float_0_5 %float_0 %float_0 %float_0
-%122 = OpCompositeConstruct %v4float %float_0 %float_3 %float_0 %float_0
-%123 = OpCompositeConstruct %v4float %float_0 %float_0 %float_5_5 %float_0
-%124 = OpCompositeConstruct %v4float %float_0 %float_0 %float_0 %float_8
-%125 = OpCompositeConstruct %mat4v4float %121 %122 %123 %124
-%127 = OpCompositeExtract %v4float %120 0
-%128 = OpCompositeExtract %v4float %125 0
-%129 = OpFOrdEqual %v4bool %127 %128
-%130 = OpAll %bool %129
-%131 = OpCompositeExtract %v4float %120 1
-%132 = OpCompositeExtract %v4float %125 1
-%133 = OpFOrdEqual %v4bool %131 %132
-%134 = OpAll %bool %133
-%135 = OpLogicalAnd %bool %130 %134
-%136 = OpCompositeExtract %v4float %120 2
-%137 = OpCompositeExtract %v4float %125 2
-%138 = OpFOrdEqual %v4bool %136 %137
-%139 = OpAll %bool %138
-%140 = OpLogicalAnd %bool %135 %139
-%141 = OpCompositeExtract %v4float %120 3
-%142 = OpCompositeExtract %v4float %125 3
-%143 = OpFOrdEqual %v4bool %141 %142
-%144 = OpAll %bool %143
-%145 = OpLogicalAnd %bool %140 %144
-OpBranch %119
-%119 = OpLabel
-%146 = OpPhi %bool %false %24 %145 %118
-OpSelectionMerge %148 None
-OpBranchConditional %146 %147 %148
-%147 = OpLabel
-%149 = OpLoad %mat4v3float %f43
-%150 = OpCompositeConstruct %v3float %float_12 %float_22 %float_30
-%151 = OpCompositeConstruct %v3float %float_36 %float_40 %float_42
-%152 = OpCompositeConstruct %v3float %float_42 %float_40 %float_36
-%153 = OpCompositeConstruct %v3float %float_30 %float_22 %float_12
-%154 = OpCompositeConstruct %mat4v3float %150 %151 %152 %153
-%156 = OpCompositeExtract %v3float %149 0
-%157 = OpCompositeExtract %v3float %154 0
-%158 = OpFOrdEqual %v3bool %156 %157
-%159 = OpAll %bool %158
-%160 = OpCompositeExtract %v3float %149 1
-%161 = OpCompositeExtract %v3float %154 1
-%162 = OpFOrdEqual %v3bool %160 %161
-%163 = OpAll %bool %162
-%164 = OpLogicalAnd %bool %159 %163
-%165 = OpCompositeExtract %v3float %149 2
-%166 = OpCompositeExtract %v3float %154 2
-%167 = OpFOrdEqual %v3bool %165 %166
-%168 = OpAll %bool %167
-%169 = OpLogicalAnd %bool %164 %168
-%170 = OpCompositeExtract %v3float %149 3
-%171 = OpCompositeExtract %v3float %154 3
-%172 = OpFOrdEqual %v3bool %170 %171
-%173 = OpAll %bool %172
-%174 = OpLogicalAnd %bool %169 %173
-OpBranch %148
-%148 = OpLabel
-%175 = OpPhi %bool %false %119 %174 %147
-OpSelectionMerge %179 None
-OpBranchConditional %175 %177 %178
-%177 = OpLabel
-%180 = OpAccessChain %_ptr_Uniform_v4float %19 %int_0
-%182 = OpLoad %v4float %180
-OpStore %176 %182
-OpBranch %179
-%178 = OpLabel
-%183 = OpAccessChain %_ptr_Uniform_v4float %19 %int_1
-%185 = OpLoad %v4float %183
-OpStore %176 %185
-OpBranch %179
-%179 = OpLabel
-%186 = OpLoad %v4float %176
-OpStore %sk_FragColor %186
-OpReturn
-OpFunctionEnd
diff --git a/tests/sksl/intrinsics/MatrixCompMult.glsl b/tests/sksl/intrinsics/MatrixCompMult.glsl
deleted file mode 100644
index 1432306..0000000
--- a/tests/sksl/intrinsics/MatrixCompMult.glsl
+++ /dev/null
@@ -1,16 +0,0 @@
-
-out vec4 sk_FragColor;
-uniform vec4 colorGreen;
-uniform vec4 colorRed;
-mat3 a;
-mat3 b;
-mat4 c;
-mat4 d;
-void main() {
-    mat2 h22 = mat2(0.0, 5.0, 10.0, 15.0);
-    mat4 h44 = mat4(0.5, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 5.5, 0.0, 0.0, 0.0, 0.0, 8.0);
-    mat4x3 f43 = mat4x3(12.0, 22.0, 30.0, 36.0, 40.0, 42.0, 42.0, 40.0, 36.0, 30.0, 22.0, 12.0);
-    sk_FragColor.xyz = matrixCompMult(a, b)[0];
-    sk_FragColor = matrixCompMult(c, d)[0];
-    sk_FragColor = (h22 == mat2(0.0, 5.0, 10.0, 15.0) && h44 == mat4(0.5, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 5.5, 0.0, 0.0, 0.0, 0.0, 8.0)) && f43 == mat4x3(12.0, 22.0, 30.0, 36.0, 40.0, 42.0, 42.0, 40.0, 36.0, 30.0, 22.0, 12.0) ? colorGreen : colorRed;
-}
diff --git a/tests/sksl/intrinsics/MatrixCompMult.metal b/tests/sksl/intrinsics/MatrixCompMult.metal
deleted file mode 100644
index 940a78c..0000000
--- a/tests/sksl/intrinsics/MatrixCompMult.metal
+++ /dev/null
@@ -1,74 +0,0 @@
-#include <metal_stdlib>
-#include <simd/simd.h>
-using namespace metal;
-struct Uniforms {
-    float4 colorGreen;
-    float4 colorRed;
-};
-struct Inputs {
-};
-struct Outputs {
-    float4 sk_FragColor [[color(0)]];
-};
-struct Globals {
-    float3x3 a;
-    float3x3 b;
-    float4x4 c;
-    float4x4 d;
-};
-
-thread bool operator==(const float2x2 left, const float2x2 right);
-thread bool operator!=(const float2x2 left, const float2x2 right);
-
-thread bool operator==(const float4x4 left, const float4x4 right);
-thread bool operator!=(const float4x4 left, const float4x4 right);
-
-thread bool operator==(const float4x3 left, const float4x3 right);
-thread bool operator!=(const float4x3 left, const float4x3 right);
-
-template <int C, int R>
-matrix<float, C, R> matrixCompMult(matrix<float, C, R> a, matrix<float, C, R> b) {
-    matrix<float, C, R> result;
-    for (int c = 0; c < C; ++c) {
-        result[c] = a[c] * b[c];
-    }
-    return result;
-}
-thread bool operator==(const float2x2 left, const float2x2 right) {
-    return all(left[0] == right[0]) &&
-           all(left[1] == right[1]);
-}
-thread bool operator!=(const float2x2 left, const float2x2 right) {
-    return !(left == right);
-}
-thread bool operator==(const float4x4 left, const float4x4 right) {
-    return all(left[0] == right[0]) &&
-           all(left[1] == right[1]) &&
-           all(left[2] == right[2]) &&
-           all(left[3] == right[3]);
-}
-thread bool operator!=(const float4x4 left, const float4x4 right) {
-    return !(left == right);
-}
-thread bool operator==(const float4x3 left, const float4x3 right) {
-    return all(left[0] == right[0]) &&
-           all(left[1] == right[1]) &&
-           all(left[2] == right[2]) &&
-           all(left[3] == right[3]);
-}
-thread bool operator!=(const float4x3 left, const float4x3 right) {
-    return !(left == right);
-}
-fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
-    Globals _globals{{}, {}, {}, {}};
-    (void)_globals;
-    Outputs _out;
-    (void)_out;
-    float2x2 h22 = float2x2(float2(0.0, 5.0), float2(10.0, 15.0));
-    float4x4 h44 = float4x4(float4(0.5, 0.0, 0.0, 0.0), float4(0.0, 3.0, 0.0, 0.0), float4(0.0, 0.0, 5.5, 0.0), float4(0.0, 0.0, 0.0, 8.0));
-    float4x3 f43 = float4x3(float3(12.0, 22.0, 30.0), float3(36.0, 40.0, 42.0), float3(42.0, 40.0, 36.0), float3(30.0, 22.0, 12.0));
-    _out.sk_FragColor.xyz = matrixCompMult(_globals.a, _globals.b)[0];
-    _out.sk_FragColor = matrixCompMult(_globals.c, _globals.d)[0];
-    _out.sk_FragColor = (h22 == float2x2(float2(0.0, 5.0), float2(10.0, 15.0)) && h44 == float4x4(float4(0.5, 0.0, 0.0, 0.0), float4(0.0, 3.0, 0.0, 0.0), float4(0.0, 0.0, 5.5, 0.0), float4(0.0, 0.0, 0.0, 8.0))) && f43 == float4x3(float3(12.0, 22.0, 30.0), float3(36.0, 40.0, 42.0), float3(42.0, 40.0, 36.0), float3(30.0, 22.0, 12.0)) ? _uniforms.colorGreen : _uniforms.colorRed;
-    return _out;
-}
diff --git a/tests/sksl/intrinsics/MatrixCompMultES2.asm.frag b/tests/sksl/intrinsics/MatrixCompMultES2.asm.frag
new file mode 100644
index 0000000..51cdc4f
--- /dev/null
+++ b/tests/sksl/intrinsics/MatrixCompMultES2.asm.frag
@@ -0,0 +1,235 @@
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise
+OpExecutionMode %_entrypoint_v OriginUpperLeft
+OpName %sk_FragColor "sk_FragColor"
+OpName %sk_Clockwise "sk_Clockwise"
+OpName %_UniformBuffer "_UniformBuffer"
+OpMemberName %_UniformBuffer 0 "colorGreen"
+OpMemberName %_UniformBuffer 1 "colorRed"
+OpMemberName %_UniformBuffer 2 "testMatrix2x2"
+OpMemberName %_UniformBuffer 3 "testMatrix3x3"
+OpName %_entrypoint_v "_entrypoint_v"
+OpName %main "main"
+OpName %h22 "h22"
+OpName %f22 "f22"
+OpName %h33 "h33"
+OpDecorate %sk_FragColor RelaxedPrecision
+OpDecorate %sk_FragColor Location 0
+OpDecorate %sk_FragColor Index 0
+OpDecorate %sk_Clockwise BuiltIn FrontFacing
+OpMemberDecorate %_UniformBuffer 0 Offset 0
+OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 1 Offset 16
+OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 2 Offset 32
+OpMemberDecorate %_UniformBuffer 2 ColMajor
+OpMemberDecorate %_UniformBuffer 2 MatrixStride 16
+OpMemberDecorate %_UniformBuffer 3 Offset 64
+OpMemberDecorate %_UniformBuffer 3 ColMajor
+OpMemberDecorate %_UniformBuffer 3 MatrixStride 16
+OpMemberDecorate %_UniformBuffer 3 RelaxedPrecision
+OpDecorate %_UniformBuffer Block
+OpDecorate %10 Binding 0
+OpDecorate %10 DescriptorSet 0
+OpDecorate %h22 RelaxedPrecision
+OpDecorate %34 RelaxedPrecision
+OpDecorate %35 RelaxedPrecision
+OpDecorate %36 RelaxedPrecision
+OpDecorate %h33 RelaxedPrecision
+OpDecorate %61 RelaxedPrecision
+OpDecorate %63 RelaxedPrecision
+OpDecorate %64 RelaxedPrecision
+OpDecorate %65 RelaxedPrecision
+OpDecorate %66 RelaxedPrecision
+OpDecorate %67 RelaxedPrecision
+OpDecorate %68 RelaxedPrecision
+OpDecorate %69 RelaxedPrecision
+OpDecorate %70 RelaxedPrecision
+OpDecorate %71 RelaxedPrecision
+OpDecorate %72 RelaxedPrecision
+OpDecorate %73 RelaxedPrecision
+OpDecorate %74 RelaxedPrecision
+OpDecorate %75 RelaxedPrecision
+OpDecorate %76 RelaxedPrecision
+OpDecorate %78 RelaxedPrecision
+OpDecorate %79 RelaxedPrecision
+OpDecorate %80 RelaxedPrecision
+OpDecorate %81 RelaxedPrecision
+OpDecorate %111 RelaxedPrecision
+OpDecorate %118 RelaxedPrecision
+OpDecorate %119 RelaxedPrecision
+OpDecorate %120 RelaxedPrecision
+OpDecorate %121 RelaxedPrecision
+OpDecorate %146 RelaxedPrecision
+OpDecorate %149 RelaxedPrecision
+OpDecorate %150 RelaxedPrecision
+%float = OpTypeFloat 32
+%v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%sk_FragColor = OpVariable %_ptr_Output_v4float Output
+%bool = OpTypeBool
+%_ptr_Input_bool = OpTypePointer Input %bool
+%sk_Clockwise = OpVariable %_ptr_Input_bool Input
+%v2float = OpTypeVector %float 2
+%mat2v2float = OpTypeMatrix %v2float 2
+%v3float = OpTypeVector %float 3
+%mat3v3float = OpTypeMatrix %v3float 3
+%_UniformBuffer = OpTypeStruct %v4float %v4float %mat2v2float %mat3v3float
+%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer
+%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform
+%void = OpTypeVoid
+%19 = OpTypeFunction %void
+%float_0 = OpConstant %float 0
+%22 = OpConstantComposite %v2float %float_0 %float_0
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+%26 = OpTypeFunction %v4float %_ptr_Function_v2float
+%_ptr_Function_mat2v2float = OpTypePointer Function %mat2v2float
+%float_5 = OpConstant %float 5
+%float_10 = OpConstant %float 10
+%float_15 = OpConstant %float 15
+%_ptr_Uniform_mat2v2float = OpTypePointer Uniform %mat2v2float
+%int = OpTypeInt 32 1
+%int_2 = OpConstant %int 2
+%float_1 = OpConstant %float 1
+%_ptr_Function_mat3v3float = OpTypePointer Function %mat3v3float
+%_ptr_Uniform_mat3v3float = OpTypePointer Uniform %mat3v3float
+%int_3 = OpConstant %int 3
+%float_2 = OpConstant %float 2
+%false = OpConstantFalse %bool
+%v2bool = OpTypeVector %bool 2
+%float_4 = OpConstant %float 4
+%float_6 = OpConstant %float 6
+%float_8 = OpConstant %float 8
+%float_12 = OpConstant %float 12
+%float_14 = OpConstant %float 14
+%float_16 = OpConstant %float 16
+%float_18 = OpConstant %float 18
+%v3bool = OpTypeVector %bool 3
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%_entrypoint_v = OpFunction %void None %19
+%20 = OpLabel
+%23 = OpVariable %_ptr_Function_v2float Function
+OpStore %23 %22
+%25 = OpFunctionCall %v4float %main %23
+OpStore %sk_FragColor %25
+OpReturn
+OpFunctionEnd
+%main = OpFunction %v4float None %26
+%27 = OpFunctionParameter %_ptr_Function_v2float
+%28 = OpLabel
+%h22 = OpVariable %_ptr_Function_mat2v2float Function
+%f22 = OpVariable %_ptr_Function_mat2v2float Function
+%h33 = OpVariable %_ptr_Function_mat3v3float Function
+%138 = OpVariable %_ptr_Function_v4float Function
+%34 = OpCompositeConstruct %v2float %float_0 %float_5
+%35 = OpCompositeConstruct %v2float %float_10 %float_15
+%36 = OpCompositeConstruct %mat2v2float %34 %35
+OpStore %h22 %36
+%39 = OpAccessChain %_ptr_Uniform_mat2v2float %10 %int_2
+%43 = OpLoad %mat2v2float %39
+%46 = OpCompositeConstruct %v2float %float_1 %float_0
+%47 = OpCompositeConstruct %v2float %float_0 %float_1
+%45 = OpCompositeConstruct %mat2v2float %46 %47
+%48 = OpCompositeExtract %v2float %43 0
+%49 = OpCompositeExtract %v2float %45 0
+%50 = OpFMul %v2float %48 %49
+%51 = OpCompositeExtract %v2float %43 1
+%52 = OpCompositeExtract %v2float %45 1
+%53 = OpFMul %v2float %51 %52
+%54 = OpCompositeConstruct %mat2v2float %50 %53
+OpStore %f22 %54
+%58 = OpAccessChain %_ptr_Uniform_mat3v3float %10 %int_3
+%61 = OpLoad %mat3v3float %58
+%63 = OpCompositeConstruct %v3float %float_2 %float_2 %float_2
+%64 = OpCompositeConstruct %v3float %float_2 %float_2 %float_2
+%65 = OpCompositeConstruct %v3float %float_2 %float_2 %float_2
+%66 = OpCompositeConstruct %mat3v3float %63 %64 %65
+%67 = OpCompositeExtract %v3float %61 0
+%68 = OpCompositeExtract %v3float %66 0
+%69 = OpFMul %v3float %67 %68
+%70 = OpCompositeExtract %v3float %61 1
+%71 = OpCompositeExtract %v3float %66 1
+%72 = OpFMul %v3float %70 %71
+%73 = OpCompositeExtract %v3float %61 2
+%74 = OpCompositeExtract %v3float %66 2
+%75 = OpFMul %v3float %73 %74
+%76 = OpCompositeConstruct %mat3v3float %69 %72 %75
+OpStore %h33 %76
+%78 = OpLoad %mat2v2float %h22
+%79 = OpCompositeConstruct %v2float %float_0 %float_5
+%80 = OpCompositeConstruct %v2float %float_10 %float_15
+%81 = OpCompositeConstruct %mat2v2float %79 %80
+%83 = OpCompositeExtract %v2float %78 0
+%84 = OpCompositeExtract %v2float %81 0
+%85 = OpFOrdEqual %v2bool %83 %84
+%86 = OpAll %bool %85
+%87 = OpCompositeExtract %v2float %78 1
+%88 = OpCompositeExtract %v2float %81 1
+%89 = OpFOrdEqual %v2bool %87 %88
+%90 = OpAll %bool %89
+%91 = OpLogicalAnd %bool %86 %90
+OpSelectionMerge %93 None
+OpBranchConditional %91 %92 %93
+%92 = OpLabel
+%94 = OpLoad %mat2v2float %f22
+%96 = OpCompositeConstruct %v2float %float_1 %float_0
+%97 = OpCompositeConstruct %v2float %float_0 %float_4
+%98 = OpCompositeConstruct %mat2v2float %96 %97
+%99 = OpCompositeExtract %v2float %94 0
+%100 = OpCompositeExtract %v2float %98 0
+%101 = OpFOrdEqual %v2bool %99 %100
+%102 = OpAll %bool %101
+%103 = OpCompositeExtract %v2float %94 1
+%104 = OpCompositeExtract %v2float %98 1
+%105 = OpFOrdEqual %v2bool %103 %104
+%106 = OpAll %bool %105
+%107 = OpLogicalAnd %bool %102 %106
+OpBranch %93
+%93 = OpLabel
+%108 = OpPhi %bool %false %28 %107 %92
+OpSelectionMerge %110 None
+OpBranchConditional %108 %109 %110
+%109 = OpLabel
+%111 = OpLoad %mat3v3float %h33
+%118 = OpCompositeConstruct %v3float %float_2 %float_4 %float_6
+%119 = OpCompositeConstruct %v3float %float_8 %float_10 %float_12
+%120 = OpCompositeConstruct %v3float %float_14 %float_16 %float_18
+%121 = OpCompositeConstruct %mat3v3float %118 %119 %120
+%123 = OpCompositeExtract %v3float %111 0
+%124 = OpCompositeExtract %v3float %121 0
+%125 = OpFOrdEqual %v3bool %123 %124
+%126 = OpAll %bool %125
+%127 = OpCompositeExtract %v3float %111 1
+%128 = OpCompositeExtract %v3float %121 1
+%129 = OpFOrdEqual %v3bool %127 %128
+%130 = OpAll %bool %129
+%131 = OpLogicalAnd %bool %126 %130
+%132 = OpCompositeExtract %v3float %111 2
+%133 = OpCompositeExtract %v3float %121 2
+%134 = OpFOrdEqual %v3bool %132 %133
+%135 = OpAll %bool %134
+%136 = OpLogicalAnd %bool %131 %135
+OpBranch %110
+%110 = OpLabel
+%137 = OpPhi %bool %false %93 %136 %109
+OpSelectionMerge %142 None
+OpBranchConditional %137 %140 %141
+%140 = OpLabel
+%143 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%146 = OpLoad %v4float %143
+OpStore %138 %146
+OpBranch %142
+%141 = OpLabel
+%147 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%149 = OpLoad %v4float %147
+OpStore %138 %149
+OpBranch %142
+%142 = OpLabel
+%150 = OpLoad %v4float %138
+OpReturnValue %150
+OpFunctionEnd
diff --git a/tests/sksl/intrinsics/MatrixCompMultES2.glsl b/tests/sksl/intrinsics/MatrixCompMultES2.glsl
new file mode 100644
index 0000000..f561042
--- /dev/null
+++ b/tests/sksl/intrinsics/MatrixCompMultES2.glsl
@@ -0,0 +1,12 @@
+
+out vec4 sk_FragColor;
+uniform vec4 colorGreen;
+uniform vec4 colorRed;
+uniform mat2 testMatrix2x2;
+uniform mat3 testMatrix3x3;
+vec4 main() {
+    mat2 h22 = mat2(0.0, 5.0, 10.0, 15.0);
+    mat2 f22 = matrixCompMult(testMatrix2x2, mat2(1.0));
+    mat3 h33 = matrixCompMult(testMatrix3x3, mat3(2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0));
+    return (h22 == mat2(0.0, 5.0, 10.0, 15.0) && f22 == mat2(1.0, 0.0, 0.0, 4.0)) && h33 == mat3(2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0) ? colorGreen : colorRed;
+}
diff --git a/tests/sksl/intrinsics/MatrixCompMultES2.metal b/tests/sksl/intrinsics/MatrixCompMultES2.metal
new file mode 100644
index 0000000..f01179a
--- /dev/null
+++ b/tests/sksl/intrinsics/MatrixCompMultES2.metal
@@ -0,0 +1,52 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+using namespace metal;
+struct Uniforms {
+    float4 colorGreen;
+    float4 colorRed;
+    float2x2 testMatrix2x2;
+    float3x3 testMatrix3x3;
+};
+struct Inputs {
+};
+struct Outputs {
+    float4 sk_FragColor [[color(0)]];
+};
+
+thread bool operator==(const float2x2 left, const float2x2 right);
+thread bool operator!=(const float2x2 left, const float2x2 right);
+
+thread bool operator==(const float3x3 left, const float3x3 right);
+thread bool operator!=(const float3x3 left, const float3x3 right);
+
+template <int C, int R>
+matrix<float, C, R> matrixCompMult(matrix<float, C, R> a, const matrix<float, C, R> b) {
+    for (int c = 0; c < C; ++c) {
+        a[c] *= b[c];
+    }
+    return a;
+}
+thread bool operator==(const float2x2 left, const float2x2 right) {
+    return all(left[0] == right[0]) &&
+           all(left[1] == right[1]);
+}
+thread bool operator!=(const float2x2 left, const float2x2 right) {
+    return !(left == right);
+}
+thread bool operator==(const float3x3 left, const float3x3 right) {
+    return all(left[0] == right[0]) &&
+           all(left[1] == right[1]) &&
+           all(left[2] == right[2]);
+}
+thread bool operator!=(const float3x3 left, const float3x3 right) {
+    return !(left == right);
+}
+fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
+    Outputs _out;
+    (void)_out;
+    float2x2 h22 = float2x2(float2(0.0, 5.0), float2(10.0, 15.0));
+    float2x2 f22 = matrixCompMult(_uniforms.testMatrix2x2, float2x2(1.0));
+    float3x3 h33 = matrixCompMult(_uniforms.testMatrix3x3, float3x3(float3(2.0, 2.0, 2.0), float3(2.0, 2.0, 2.0), float3(2.0, 2.0, 2.0)));
+    _out.sk_FragColor = (h22 == float2x2(float2(0.0, 5.0), float2(10.0, 15.0)) && f22 == float2x2(float2(1.0, 0.0), float2(0.0, 4.0))) && h33 == float3x3(float3(2.0, 4.0, 6.0), float3(8.0, 10.0, 12.0), float3(14.0, 16.0, 18.0)) ? _uniforms.colorGreen : _uniforms.colorRed;
+    return _out;
+}
diff --git a/tests/sksl/intrinsics/MatrixCompMultES3.asm.frag b/tests/sksl/intrinsics/MatrixCompMultES3.asm.frag
new file mode 100644
index 0000000..9d6c417
--- /dev/null
+++ b/tests/sksl/intrinsics/MatrixCompMultES3.asm.frag
@@ -0,0 +1,299 @@
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise
+OpExecutionMode %_entrypoint_v OriginUpperLeft
+OpName %sk_FragColor "sk_FragColor"
+OpName %sk_Clockwise "sk_Clockwise"
+OpName %_UniformBuffer "_UniformBuffer"
+OpMemberName %_UniformBuffer 0 "colorGreen"
+OpMemberName %_UniformBuffer 1 "colorRed"
+OpName %_entrypoint_v "_entrypoint_v"
+OpName %main "main"
+OpName %h24 "h24"
+OpName %h42 "h42"
+OpName %f43 "f43"
+OpDecorate %sk_FragColor RelaxedPrecision
+OpDecorate %sk_FragColor Location 0
+OpDecorate %sk_FragColor Index 0
+OpDecorate %sk_Clockwise BuiltIn FrontFacing
+OpMemberDecorate %_UniformBuffer 0 Offset 0
+OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 1 Offset 16
+OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
+OpDecorate %_UniformBuffer Block
+OpDecorate %10 Binding 0
+OpDecorate %10 DescriptorSet 0
+OpDecorate %h24 RelaxedPrecision
+OpDecorate %31 RelaxedPrecision
+OpDecorate %32 RelaxedPrecision
+OpDecorate %33 RelaxedPrecision
+OpDecorate %38 RelaxedPrecision
+OpDecorate %41 RelaxedPrecision
+OpDecorate %42 RelaxedPrecision
+OpDecorate %43 RelaxedPrecision
+OpDecorate %44 RelaxedPrecision
+OpDecorate %45 RelaxedPrecision
+OpDecorate %46 RelaxedPrecision
+OpDecorate %47 RelaxedPrecision
+OpDecorate %48 RelaxedPrecision
+OpDecorate %49 RelaxedPrecision
+OpDecorate %h42 RelaxedPrecision
+OpDecorate %62 RelaxedPrecision
+OpDecorate %63 RelaxedPrecision
+OpDecorate %64 RelaxedPrecision
+OpDecorate %65 RelaxedPrecision
+OpDecorate %66 RelaxedPrecision
+OpDecorate %68 RelaxedPrecision
+OpDecorate %70 RelaxedPrecision
+OpDecorate %71 RelaxedPrecision
+OpDecorate %72 RelaxedPrecision
+OpDecorate %73 RelaxedPrecision
+OpDecorate %74 RelaxedPrecision
+OpDecorate %75 RelaxedPrecision
+OpDecorate %76 RelaxedPrecision
+OpDecorate %77 RelaxedPrecision
+OpDecorate %78 RelaxedPrecision
+OpDecorate %79 RelaxedPrecision
+OpDecorate %80 RelaxedPrecision
+OpDecorate %81 RelaxedPrecision
+OpDecorate %82 RelaxedPrecision
+OpDecorate %83 RelaxedPrecision
+OpDecorate %84 RelaxedPrecision
+OpDecorate %85 RelaxedPrecision
+OpDecorate %86 RelaxedPrecision
+OpDecorate %87 RelaxedPrecision
+OpDecorate %88 RelaxedPrecision
+OpDecorate %89 RelaxedPrecision
+OpDecorate %90 RelaxedPrecision
+OpDecorate %91 RelaxedPrecision
+OpDecorate %92 RelaxedPrecision
+OpDecorate %93 RelaxedPrecision
+OpDecorate %94 RelaxedPrecision
+OpDecorate %95 RelaxedPrecision
+OpDecorate %96 RelaxedPrecision
+OpDecorate %113 RelaxedPrecision
+OpDecorate %114 RelaxedPrecision
+OpDecorate %115 RelaxedPrecision
+OpDecorate %116 RelaxedPrecision
+OpDecorate %129 RelaxedPrecision
+OpDecorate %130 RelaxedPrecision
+OpDecorate %131 RelaxedPrecision
+OpDecorate %132 RelaxedPrecision
+OpDecorate %133 RelaxedPrecision
+OpDecorate %134 RelaxedPrecision
+OpDecorate %191 RelaxedPrecision
+OpDecorate %193 RelaxedPrecision
+OpDecorate %194 RelaxedPrecision
+%float = OpTypeFloat 32
+%v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%sk_FragColor = OpVariable %_ptr_Output_v4float Output
+%bool = OpTypeBool
+%_ptr_Input_bool = OpTypePointer Input %bool
+%sk_Clockwise = OpVariable %_ptr_Input_bool Input
+%_UniformBuffer = OpTypeStruct %v4float %v4float
+%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer
+%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform
+%void = OpTypeVoid
+%15 = OpTypeFunction %void
+%v2float = OpTypeVector %float 2
+%float_0 = OpConstant %float 0
+%19 = OpConstantComposite %v2float %float_0 %float_0
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+%23 = OpTypeFunction %v4float %_ptr_Function_v2float
+%mat2v4float = OpTypeMatrix %v4float 2
+%_ptr_Function_mat2v4float = OpTypePointer Function %mat2v4float
+%float_9 = OpConstant %float 9
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%int = OpTypeInt 32 1
+%int_1 = OpConstant %int 1
+%int_0 = OpConstant %int 0
+%mat4v2float = OpTypeMatrix %v2float 4
+%_ptr_Function_mat4v2float = OpTypePointer Function %mat4v2float
+%float_1 = OpConstant %float 1
+%float_2 = OpConstant %float 2
+%float_3 = OpConstant %float 3
+%float_4 = OpConstant %float 4
+%float_5 = OpConstant %float 5
+%float_6 = OpConstant %float 6
+%float_7 = OpConstant %float 7
+%float_8 = OpConstant %float 8
+%v3float = OpTypeVector %float 3
+%mat4v3float = OpTypeMatrix %v3float 4
+%_ptr_Function_mat4v3float = OpTypePointer Function %mat4v3float
+%float_12 = OpConstant %float 12
+%float_22 = OpConstant %float 22
+%float_30 = OpConstant %float 30
+%float_36 = OpConstant %float 36
+%float_40 = OpConstant %float 40
+%float_42 = OpConstant %float 42
+%false = OpConstantFalse %bool
+%v4bool = OpTypeVector %bool 4
+%v2bool = OpTypeVector %bool 2
+%v3bool = OpTypeVector %bool 3
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%_entrypoint_v = OpFunction %void None %15
+%16 = OpLabel
+%20 = OpVariable %_ptr_Function_v2float Function
+OpStore %20 %19
+%22 = OpFunctionCall %v4float %main %20
+OpStore %sk_FragColor %22
+OpReturn
+OpFunctionEnd
+%main = OpFunction %v4float None %23
+%24 = OpFunctionParameter %_ptr_Function_v2float
+%25 = OpLabel
+%h24 = OpVariable %_ptr_Function_mat2v4float Function
+%h42 = OpVariable %_ptr_Function_mat4v2float Function
+%f43 = OpVariable %_ptr_Function_mat4v3float Function
+%185 = OpVariable %_ptr_Function_v4float Function
+%31 = OpCompositeConstruct %v4float %float_9 %float_9 %float_9 %float_9
+%32 = OpCompositeConstruct %v4float %float_9 %float_9 %float_9 %float_9
+%33 = OpCompositeConstruct %mat2v4float %31 %32
+%34 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%38 = OpLoad %v4float %34
+%39 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%41 = OpLoad %v4float %39
+%42 = OpCompositeConstruct %mat2v4float %38 %41
+%43 = OpCompositeExtract %v4float %33 0
+%44 = OpCompositeExtract %v4float %42 0
+%45 = OpFMul %v4float %43 %44
+%46 = OpCompositeExtract %v4float %33 1
+%47 = OpCompositeExtract %v4float %42 1
+%48 = OpFMul %v4float %46 %47
+%49 = OpCompositeConstruct %mat2v4float %45 %48
+OpStore %h24 %49
+%62 = OpCompositeConstruct %v2float %float_1 %float_2
+%63 = OpCompositeConstruct %v2float %float_3 %float_4
+%64 = OpCompositeConstruct %v2float %float_5 %float_6
+%65 = OpCompositeConstruct %v2float %float_7 %float_8
+%66 = OpCompositeConstruct %mat4v2float %62 %63 %64 %65
+%67 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%68 = OpLoad %v4float %67
+%69 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%70 = OpLoad %v4float %69
+%71 = OpCompositeExtract %float %68 0
+%72 = OpCompositeExtract %float %68 1
+%73 = OpCompositeConstruct %v2float %71 %72
+%74 = OpCompositeExtract %float %68 2
+%75 = OpCompositeExtract %float %68 3
+%76 = OpCompositeConstruct %v2float %74 %75
+%77 = OpCompositeExtract %float %70 0
+%78 = OpCompositeExtract %float %70 1
+%79 = OpCompositeConstruct %v2float %77 %78
+%80 = OpCompositeExtract %float %70 2
+%81 = OpCompositeExtract %float %70 3
+%82 = OpCompositeConstruct %v2float %80 %81
+%83 = OpCompositeConstruct %mat4v2float %73 %76 %79 %82
+%84 = OpCompositeExtract %v2float %66 0
+%85 = OpCompositeExtract %v2float %83 0
+%86 = OpFMul %v2float %84 %85
+%87 = OpCompositeExtract %v2float %66 1
+%88 = OpCompositeExtract %v2float %83 1
+%89 = OpFMul %v2float %87 %88
+%90 = OpCompositeExtract %v2float %66 2
+%91 = OpCompositeExtract %v2float %83 2
+%92 = OpFMul %v2float %90 %91
+%93 = OpCompositeExtract %v2float %66 3
+%94 = OpCompositeExtract %v2float %83 3
+%95 = OpFMul %v2float %93 %94
+%96 = OpCompositeConstruct %mat4v2float %86 %89 %92 %95
+OpStore %h42 %96
+%107 = OpCompositeConstruct %v3float %float_12 %float_22 %float_30
+%108 = OpCompositeConstruct %v3float %float_36 %float_40 %float_42
+%109 = OpCompositeConstruct %v3float %float_42 %float_40 %float_36
+%110 = OpCompositeConstruct %v3float %float_30 %float_22 %float_12
+%111 = OpCompositeConstruct %mat4v3float %107 %108 %109 %110
+OpStore %f43 %111
+%113 = OpLoad %mat2v4float %h24
+%114 = OpCompositeConstruct %v4float %float_9 %float_0 %float_0 %float_9
+%115 = OpCompositeConstruct %v4float %float_0 %float_9 %float_0 %float_9
+%116 = OpCompositeConstruct %mat2v4float %114 %115
+%118 = OpCompositeExtract %v4float %113 0
+%119 = OpCompositeExtract %v4float %116 0
+%120 = OpFOrdEqual %v4bool %118 %119
+%121 = OpAll %bool %120
+%122 = OpCompositeExtract %v4float %113 1
+%123 = OpCompositeExtract %v4float %116 1
+%124 = OpFOrdEqual %v4bool %122 %123
+%125 = OpAll %bool %124
+%126 = OpLogicalAnd %bool %121 %125
+OpSelectionMerge %128 None
+OpBranchConditional %126 %127 %128
+%127 = OpLabel
+%129 = OpLoad %mat4v2float %h42
+%130 = OpCompositeConstruct %v2float %float_1 %float_0
+%131 = OpCompositeConstruct %v2float %float_0 %float_4
+%132 = OpCompositeConstruct %v2float %float_0 %float_6
+%133 = OpCompositeConstruct %v2float %float_0 %float_8
+%134 = OpCompositeConstruct %mat4v2float %130 %131 %132 %133
+%136 = OpCompositeExtract %v2float %129 0
+%137 = OpCompositeExtract %v2float %134 0
+%138 = OpFOrdEqual %v2bool %136 %137
+%139 = OpAll %bool %138
+%140 = OpCompositeExtract %v2float %129 1
+%141 = OpCompositeExtract %v2float %134 1
+%142 = OpFOrdEqual %v2bool %140 %141
+%143 = OpAll %bool %142
+%144 = OpLogicalAnd %bool %139 %143
+%145 = OpCompositeExtract %v2float %129 2
+%146 = OpCompositeExtract %v2float %134 2
+%147 = OpFOrdEqual %v2bool %145 %146
+%148 = OpAll %bool %147
+%149 = OpLogicalAnd %bool %144 %148
+%150 = OpCompositeExtract %v2float %129 3
+%151 = OpCompositeExtract %v2float %134 3
+%152 = OpFOrdEqual %v2bool %150 %151
+%153 = OpAll %bool %152
+%154 = OpLogicalAnd %bool %149 %153
+OpBranch %128
+%128 = OpLabel
+%155 = OpPhi %bool %false %25 %154 %127
+OpSelectionMerge %157 None
+OpBranchConditional %155 %156 %157
+%156 = OpLabel
+%158 = OpLoad %mat4v3float %f43
+%159 = OpCompositeConstruct %v3float %float_12 %float_22 %float_30
+%160 = OpCompositeConstruct %v3float %float_36 %float_40 %float_42
+%161 = OpCompositeConstruct %v3float %float_42 %float_40 %float_36
+%162 = OpCompositeConstruct %v3float %float_30 %float_22 %float_12
+%163 = OpCompositeConstruct %mat4v3float %159 %160 %161 %162
+%165 = OpCompositeExtract %v3float %158 0
+%166 = OpCompositeExtract %v3float %163 0
+%167 = OpFOrdEqual %v3bool %165 %166
+%168 = OpAll %bool %167
+%169 = OpCompositeExtract %v3float %158 1
+%170 = OpCompositeExtract %v3float %163 1
+%171 = OpFOrdEqual %v3bool %169 %170
+%172 = OpAll %bool %171
+%173 = OpLogicalAnd %bool %168 %172
+%174 = OpCompositeExtract %v3float %158 2
+%175 = OpCompositeExtract %v3float %163 2
+%176 = OpFOrdEqual %v3bool %174 %175
+%177 = OpAll %bool %176
+%178 = OpLogicalAnd %bool %173 %177
+%179 = OpCompositeExtract %v3float %158 3
+%180 = OpCompositeExtract %v3float %163 3
+%181 = OpFOrdEqual %v3bool %179 %180
+%182 = OpAll %bool %181
+%183 = OpLogicalAnd %bool %178 %182
+OpBranch %157
+%157 = OpLabel
+%184 = OpPhi %bool %false %128 %183 %156
+OpSelectionMerge %189 None
+OpBranchConditional %184 %187 %188
+%187 = OpLabel
+%190 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%191 = OpLoad %v4float %190
+OpStore %185 %191
+OpBranch %189
+%188 = OpLabel
+%192 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%193 = OpLoad %v4float %192
+OpStore %185 %193
+OpBranch %189
+%189 = OpLabel
+%194 = OpLoad %v4float %185
+OpReturnValue %194
+OpFunctionEnd
diff --git a/tests/sksl/intrinsics/MatrixCompMultES3.glsl b/tests/sksl/intrinsics/MatrixCompMultES3.glsl
new file mode 100644
index 0000000..0e25874
--- /dev/null
+++ b/tests/sksl/intrinsics/MatrixCompMultES3.glsl
@@ -0,0 +1,10 @@
+
+out vec4 sk_FragColor;
+uniform vec4 colorGreen;
+uniform vec4 colorRed;
+vec4 main() {
+    mat2x4 h24 = matrixCompMult(mat2x4(9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0), mat2x4(colorRed, colorGreen));
+    mat4x2 h42 = matrixCompMult(mat4x2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0), mat4x2(colorRed, colorGreen));
+    mat4x3 f43 = mat4x3(12.0, 22.0, 30.0, 36.0, 40.0, 42.0, 42.0, 40.0, 36.0, 30.0, 22.0, 12.0);
+    return (h24 == mat2x4(9.0, 0.0, 0.0, 9.0, 0.0, 9.0, 0.0, 9.0) && h42 == mat4x2(1.0, 0.0, 0.0, 4.0, 0.0, 6.0, 0.0, 8.0)) && f43 == mat4x3(12.0, 22.0, 30.0, 36.0, 40.0, 42.0, 42.0, 40.0, 36.0, 30.0, 22.0, 12.0) ? colorGreen : colorRed;
+}
diff --git a/tests/sksl/intrinsics/MatrixCompMultES3.metal b/tests/sksl/intrinsics/MatrixCompMultES3.metal
new file mode 100644
index 0000000..41c42ea
--- /dev/null
+++ b/tests/sksl/intrinsics/MatrixCompMultES3.metal
@@ -0,0 +1,66 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+using namespace metal;
+struct Uniforms {
+    float4 colorGreen;
+    float4 colorRed;
+};
+struct Inputs {
+};
+struct Outputs {
+    float4 sk_FragColor [[color(0)]];
+};
+
+thread bool operator==(const float2x4 left, const float2x4 right);
+thread bool operator!=(const float2x4 left, const float2x4 right);
+
+thread bool operator==(const float4x2 left, const float4x2 right);
+thread bool operator!=(const float4x2 left, const float4x2 right);
+
+thread bool operator==(const float4x3 left, const float4x3 right);
+thread bool operator!=(const float4x3 left, const float4x3 right);
+
+template <int C, int R>
+matrix<float, C, R> matrixCompMult(matrix<float, C, R> a, const matrix<float, C, R> b) {
+    for (int c = 0; c < C; ++c) {
+        a[c] *= b[c];
+    }
+    return a;
+}
+float4x2 float4x2_from_float4_float4(float4 x0, float4 x1) {
+    return float4x2(float2(x0[0], x0[1]), float2(x0[2], x0[3]), float2(x1[0], x1[1]), float2(x1[2], x1[3]));
+}
+thread bool operator==(const float2x4 left, const float2x4 right) {
+    return all(left[0] == right[0]) &&
+           all(left[1] == right[1]);
+}
+thread bool operator!=(const float2x4 left, const float2x4 right) {
+    return !(left == right);
+}
+thread bool operator==(const float4x2 left, const float4x2 right) {
+    return all(left[0] == right[0]) &&
+           all(left[1] == right[1]) &&
+           all(left[2] == right[2]) &&
+           all(left[3] == right[3]);
+}
+thread bool operator!=(const float4x2 left, const float4x2 right) {
+    return !(left == right);
+}
+thread bool operator==(const float4x3 left, const float4x3 right) {
+    return all(left[0] == right[0]) &&
+           all(left[1] == right[1]) &&
+           all(left[2] == right[2]) &&
+           all(left[3] == right[3]);
+}
+thread bool operator!=(const float4x3 left, const float4x3 right) {
+    return !(left == right);
+}
+fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
+    Outputs _out;
+    (void)_out;
+    float2x4 h24 = matrixCompMult(float2x4(float4(9.0, 9.0, 9.0, 9.0), float4(9.0, 9.0, 9.0, 9.0)), float2x4(_uniforms.colorRed, _uniforms.colorGreen));
+    float4x2 h42 = matrixCompMult(float4x2(float2(1.0, 2.0), float2(3.0, 4.0), float2(5.0, 6.0), float2(7.0, 8.0)), float4x2_from_float4_float4(_uniforms.colorRed, _uniforms.colorGreen));
+    float4x3 f43 = float4x3(float3(12.0, 22.0, 30.0), float3(36.0, 40.0, 42.0), float3(42.0, 40.0, 36.0), float3(30.0, 22.0, 12.0));
+    _out.sk_FragColor = (h24 == float2x4(float4(9.0, 0.0, 0.0, 9.0), float4(0.0, 9.0, 0.0, 9.0)) && h42 == float4x2(float2(1.0, 0.0), float2(0.0, 4.0), float2(0.0, 6.0), float2(0.0, 8.0))) && f43 == float4x3(float3(12.0, 22.0, 30.0), float3(36.0, 40.0, 42.0), float3(42.0, 40.0, 36.0), float3(30.0, 22.0, 12.0)) ? _uniforms.colorGreen : _uniforms.colorRed;
+    return _out;
+}