Implement distance intrinsic in RP codegen.

This is implemented in terms of the existing `length` intrinsic.

Change-Id: Ib2cfc0e5078e10e571551a9ee37f7911b62e2e66
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/657738
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp b/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp
index 670e408..a66178f 100644
--- a/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp
@@ -295,6 +295,7 @@
     [[nodiscard]] bool pushIntrinsic(BuilderOp builderOp,
                                      const Expression& arg0,
                                      const Expression& arg1);
+    [[nodiscard]] bool pushLengthIntrinsic(int slotCount);
     [[nodiscard]] bool pushVectorizedExpression(const Expression& expr, const Type& vectorType);
     [[nodiscard]] bool pushVariableReferencePartial(const VariableReference& v, SlotRange subset);
     [[nodiscard]] bool pushLValueOrExpression(LValue* lvalue, const Expression& expr);
@@ -2460,6 +2461,19 @@
     return unsupported();
 }
 
+bool Generator::pushLengthIntrinsic(int slotCount) {
+    if (slotCount > 1) {
+        // Implement `length(vec)` as `sqrt(dot(x, x))`.
+        fBuilder.push_clone(slotCount);
+        fBuilder.dot_floats(slotCount);
+        fBuilder.unary_op(BuilderOp::sqrt_float, 1);
+    } else {
+        // `length(scalar)` is `sqrt(x^2)`, which is equivalent to `abs(x)`.
+        fBuilder.unary_op(BuilderOp::abs_float, 1);
+    }
+    return true;
+}
+
 bool Generator::pushVectorizedExpression(const Expression& expr, const Type& vectorType) {
     if (!this->pushExpression(expr)) {
         return unsupported();
@@ -2547,19 +2561,8 @@
                    this->binaryOp(arg0.type(), kDivideOps);
         }
         case IntrinsicKind::k_length_IntrinsicKind:
-            if (!this->pushExpression(arg0)) {
-                return unsupported();
-            }
-            // Implement length as `sqrt(dot(x, x))`.
-            if (arg0.type().slotCount() > 1) {
-                fBuilder.push_clone(arg0.type().slotCount());
-                fBuilder.dot_floats(arg0.type().slotCount());
-                fBuilder.unary_op(BuilderOp::sqrt_float, 1);
-            } else {
-                // The length of a scalar is `sqrt(x^2)`, which is equivalent to `abs(x)`.
-                fBuilder.unary_op(BuilderOp::abs_float, 1);
-            }
-            return true;
+            return this->pushExpression(arg0) &&
+                   this->pushLengthIntrinsic(arg0.type().slotCount());
 
         case IntrinsicKind::k_not_IntrinsicKind:
             return this->pushPrefixExpression(OperatorKind::LOGICALNOT, arg0);
@@ -2734,8 +2737,13 @@
             subexpressionStack.exit();
             return true;
         }
+        case IntrinsicKind::k_distance_IntrinsicKind:
+            // Implement distance as `length(a - b)`.
+            SkASSERT(arg0.type().slotCount() == arg1.type().slotCount());
+            return this->pushBinaryExpression(arg0, OperatorKind::MINUS, arg1) &&
+                   this->pushLengthIntrinsic(arg0.type().slotCount());
+
         case IntrinsicKind::k_dot_IntrinsicKind:
-            // Implement dot as `a*b`, followed by folding via addition.
             SkASSERT(arg0.type().matches(arg1.type()));
             if (!this->pushExpression(arg0) || !this->pushExpression(arg1)) {
                 return unsupported();
diff --git a/tests/sksl/intrinsics/Distance.skrp b/tests/sksl/intrinsics/Distance.skrp
index 3ef3d71..8ca4c0d 100644
--- a/tests/sksl/intrinsics/Distance.skrp
+++ b/tests/sksl/intrinsics/Distance.skrp
@@ -1,4 +1,60 @@
-### Compilation failed:
-
-error: code is not supported
-1 error
+    1. store_src_rg                   coords = src.rg
+    2. init_lane_masks                CondMask = LoopMask = RetMask = true
+    3. copy_constant                  expected(0) = 0x40400000 (3.0)
+    4. copy_constant                  expected(1) = 0x40400000 (3.0)
+    5. copy_constant                  expected(2) = 0x40A00000 (5.0)
+    6. copy_constant                  expected(3) = 0x41500000 (13.0)
+    7. copy_constant                  $0 = pos1(0)
+    8. copy_constant                  $1 = pos2(0)
+    9. sub_float                      $0 -= $1
+   10. abs_float                      $0 = abs($0)
+   11. copy_slot_unmasked             $1 = expected(0)
+   12. cmpeq_float                    $0 = equal($0, $1)
+   13. copy_2_constants               $1..2 = pos1(0..1)
+   14. copy_2_constants               $3..4 = pos2(0..1)
+   15. sub_2_floats                   $1..2 -= $3..4
+   16. copy_2_slots_unmasked          $3..4 = $1..2
+   17. dot_2_floats                   $1 = dot($1..2, $3..4)
+   18. sqrt_float                     $1 = sqrt($1)
+   19. copy_slot_unmasked             $2 = expected(1)
+   20. cmpeq_float                    $1 = equal($1, $2)
+   21. bitwise_and_int                $0 &= $1
+   22. copy_3_constants               $1..3 = pos1(0..2)
+   23. copy_3_constants               $4..6 = pos2(0..2)
+   24. sub_3_floats                   $1..3 -= $4..6
+   25. copy_3_slots_unmasked          $4..6 = $1..3
+   26. dot_3_floats                   $1 = dot($1..3, $4..6)
+   27. sqrt_float                     $1 = sqrt($1)
+   28. copy_slot_unmasked             $2 = expected(2)
+   29. cmpeq_float                    $1 = equal($1, $2)
+   30. bitwise_and_int                $0 &= $1
+   31. copy_4_constants               $1..4 = pos1
+   32. copy_4_constants               $5..8 = pos2
+   33. sub_4_floats                   $1..4 -= $5..8
+   34. copy_4_slots_unmasked          $5..8 = $1..4
+   35. dot_4_floats                   $1 = dot($1..4, $5..8)
+   36. sqrt_float                     $1 = sqrt($1)
+   37. copy_slot_unmasked             $2 = expected(3)
+   38. cmpeq_float                    $1 = equal($1, $2)
+   39. bitwise_and_int                $0 &= $1
+   40. copy_constant                  $1 = 0x40400000 (3.0)
+   41. copy_slot_unmasked             $2 = expected(0)
+   42. cmpeq_float                    $1 = equal($1, $2)
+   43. bitwise_and_int                $0 &= $1
+   44. copy_constant                  $1 = 0x40400000 (3.0)
+   45. copy_slot_unmasked             $2 = expected(1)
+   46. cmpeq_float                    $1 = equal($1, $2)
+   47. bitwise_and_int                $0 &= $1
+   48. copy_constant                  $1 = 0x40A00000 (5.0)
+   49. copy_slot_unmasked             $2 = expected(2)
+   50. cmpeq_float                    $1 = equal($1, $2)
+   51. bitwise_and_int                $0 &= $1
+   52. copy_constant                  $1 = 0x41500000 (13.0)
+   53. copy_slot_unmasked             $2 = expected(3)
+   54. cmpeq_float                    $1 = equal($1, $2)
+   55. bitwise_and_int                $0 &= $1
+   56. swizzle_4                      $0..3 = ($0..3).xxxx
+   57. copy_4_constants               $4..7 = colorRed
+   58. copy_4_constants               $8..11 = colorGreen
+   59. mix_4_ints                     $0..3 = mix($4..7, $8..11, $0..3)
+   60. load_src                       src.rgba = $0..3