test premul/unpremul are no-ops when a==1.0f

Constant propagation means we can always notionally
unpremul and premul at the right points, and if alpha
was already opaque, they'll just drop away.

This has been true, but it's nice to put a test on it.

Change-Id: Iacd2002d9e1a10b73e800a452f377001d5ba3777
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268336
Auto-Submit: Mike Klein <mtklein@google.com>
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
diff --git a/tests/SkVMTest.cpp b/tests/SkVMTest.cpp
index cc250d4..2f69e16 100644
--- a/tests/SkVMTest.cpp
+++ b/tests/SkVMTest.cpp
@@ -816,6 +816,75 @@
     });
 }
 
+DEF_TEST(SkVM_premul, reporter) {
+    // Test that premul is short-circuited when alpha is known opaque.
+    {
+        skvm::Builder p;
+        auto rptr = p.varying<int>(),
+             aptr = p.varying<int>();
+
+        skvm::F32 r = p.bit_cast(p.load32(rptr)),
+                  g = p.splat(0.0f),
+                  b = p.splat(0.0f),
+                  a = p.bit_cast(p.load32(aptr));
+
+        p.premul(&r, &g, &b, a);
+        p.store32(rptr, p.bit_cast(r));
+
+        // load red, load alpha, red *= alpha, store red
+        REPORTER_ASSERT(reporter, p.done().instructions().size() == 4);
+    }
+
+    {
+        skvm::Builder p;
+        auto rptr = p.varying<int>();
+
+        skvm::F32 r = p.bit_cast(p.load32(rptr)),
+                  g = p.splat(0.0f),
+                  b = p.splat(0.0f),
+                  a = p.splat(1.0f);
+
+        p.premul(&r, &g, &b, a);
+        p.store32(rptr, p.bit_cast(r));
+
+        // load red, store red
+        REPORTER_ASSERT(reporter, p.done().instructions().size() == 2);
+    }
+
+    // Same deal for unpremul.
+    {
+        skvm::Builder p;
+        auto rptr = p.varying<int>(),
+             aptr = p.varying<int>();
+
+        skvm::F32 r = p.bit_cast(p.load32(rptr)),
+                  g = p.splat(0.0f),
+                  b = p.splat(0.0f),
+                  a = p.bit_cast(p.load32(aptr));
+
+        p.unpremul(&r, &g, &b, a);
+        p.store32(rptr, p.bit_cast(r));
+
+        // load red, load alpha, a bunch of unpremul instructions, store red
+        REPORTER_ASSERT(reporter, p.done().instructions().size() >= 4);
+    }
+
+    {
+        skvm::Builder p;
+        auto rptr = p.varying<int>();
+
+        skvm::F32 r = p.bit_cast(p.load32(rptr)),
+                  g = p.splat(0.0f),
+                  b = p.splat(0.0f),
+                  a = p.splat(1.0f);
+
+        p.unpremul(&r, &g, &b, a);
+        p.store32(rptr, p.bit_cast(r));
+
+        // load red, store red
+        REPORTER_ASSERT(reporter, p.done().instructions().size() == 2);
+    }
+}
 
 template <typename Fn>
 static void test_asm(skiatest::Reporter* r, Fn&& fn, std::initializer_list<uint8_t> expected) {