Implement normalize intrinsic in RP codegen.

We implement normalize as `x / length(x)`, which matches the SkVM
implementation.

A zero-length vector will return nan; the GLSL docs don't specify
what should happen in this case: http://screen/3TsNoijNDxN5xQZ

Change-Id: I4c57e54fdbc0d986bb8d1adb52ec0889f9d9846b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/657816
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
diff --git a/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp b/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp
index fcc5d93..45cdacd 100644
--- a/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp
+++ b/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp
@@ -397,7 +397,7 @@
     switch (count) {
         case 3:  this->swizzle(/*consumedSlots=*/1, {0, 0, 0, 0}); break;
         case 2:  this->swizzle(/*consumedSlots=*/1, {0, 0, 0});    break;
-        case 1:  this->push_clone(/*numSlots=*/1);              break;
+        case 1:  this->push_clone(/*numSlots=*/1);                 break;
         default: break;
     }
 }
diff --git a/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp b/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp
index 6df0eb4..b1dc894 100644
--- a/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp
@@ -2564,6 +2564,20 @@
             return this->pushExpression(arg0) &&
                    this->pushLengthIntrinsic(arg0.type().slotCount());
 
+        case IntrinsicKind::k_normalize_IntrinsicKind:
+            // Implement normalize as `x / length(x)`. First, push the expression.
+            if (!this->pushExpression(arg0)) {
+                return unsupported();
+            }
+            // Clone the expression and calculate its length.
+            fBuilder.push_clone(arg0.type().slotCount());
+            if (!this->pushLengthIntrinsic(arg0.type().slotCount())) {
+                return unsupported();
+            }
+            // Finally, vectorize the length and divide.
+            fBuilder.push_duplicates(arg0.type().slotCount() - 1);
+            return this->binaryOp(arg0.type(), kDivideOps);
+
         case IntrinsicKind::k_not_IntrinsicKind:
             return this->pushPrefixExpression(OperatorKind::LOGICALNOT, arg0);
 
diff --git a/tests/SkSLTest.cpp b/tests/SkSLTest.cpp
index a98b1d5..e14bff1 100644
--- a/tests/SkSLTest.cpp
+++ b/tests/SkSLTest.cpp
@@ -641,7 +641,7 @@
 SKSL_TEST(RP + VM + GPU,     kApiLevel_T, FunctionReturnTypeMatch,         "shared/FunctionReturnTypeMatch.sksl")
 SKSL_TEST(RP + VM + GPU,     kApiLevel_T, Functions,                       "shared/Functions.sksl")
 SKSL_TEST(RP + VM + GPU,     kApiLevel_T, FunctionPrototype,               "shared/FunctionPrototype.sksl")
-SKSL_TEST(VM + GPU,          kApiLevel_T, GeometricIntrinsics,             "shared/GeometricIntrinsics.sksl")
+SKSL_TEST(RP + VM + GPU,     kApiLevel_T, GeometricIntrinsics,             "shared/GeometricIntrinsics.sksl")
 SKSL_TEST(RP + VM + GPU,     kApiLevel_T, HelloWorld,                      "shared/HelloWorld.sksl")
 SKSL_TEST(RP + VM + GPU,     kApiLevel_T, Hex,                             "shared/Hex.sksl")
 SKSL_TEST(RP + GPU_ES3,      kNever,      HexUnsigned,                     "shared/HexUnsigned.sksl")
diff --git a/tests/sksl/intrinsics/Normalize.skrp b/tests/sksl/intrinsics/Normalize.skrp
index 3ef3d71..1f2faa9 100644
--- a/tests/sksl/intrinsics/Normalize.skrp
+++ b/tests/sksl/intrinsics/Normalize.skrp
@@ -1,4 +1,77 @@
-### 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                  expectedVec(0) = 0x3F800000 (1.0)
+    4. zero_3_slots_unmasked          expectedVec(1..3) = 0
+    5. copy_constant                  $0 = inputVal(0)
+    6. copy_slot_unmasked             $1 = $0
+    7. abs_float                      $1 = abs($1)
+    8. div_float                      $0 /= $1
+    9. copy_slot_unmasked             $1 = expectedVec(0)
+   10. cmpeq_float                    $0 = equal($0, $1)
+   11. copy_2_constants               $1..2 = inputVal(0..1)
+   12. copy_2_slots_unmasked          $3..4 = $1..2
+   13. copy_2_slots_unmasked          $5..6 = $3..4
+   14. dot_2_floats                   $3 = dot($3..4, $5..6)
+   15. sqrt_float                     $3 = sqrt($3)
+   16. copy_slot_unmasked             $4 = $3
+   17. div_2_floats                   $1..2 /= $3..4
+   18. copy_2_slots_unmasked          $3..4 = expectedVec(0..1)
+   19. cmpeq_2_floats                 $1..2 = equal($1..2, $3..4)
+   20. bitwise_and_int                $1 &= $2
+   21. bitwise_and_int                $0 &= $1
+   22. copy_3_constants               $1..3 = inputVal(0..2)
+   23. copy_3_slots_unmasked          $4..6 = $1..3
+   24. copy_3_slots_unmasked          $7..9 = $4..6
+   25. dot_3_floats                   $4 = dot($4..6, $7..9)
+   26. sqrt_float                     $4 = sqrt($4)
+   27. swizzle_3                      $4..6 = ($4..6).xxx
+   28. div_3_floats                   $1..3 /= $4..6
+   29. copy_3_slots_unmasked          $4..6 = expectedVec(0..2)
+   30. cmpeq_3_floats                 $1..3 = equal($1..3, $4..6)
+   31. bitwise_and_int                $2 &= $3
+   32. bitwise_and_int                $1 &= $2
+   33. bitwise_and_int                $0 &= $1
+   34. copy_4_constants               $1..4 = inputVal
+   35. copy_4_slots_unmasked          $5..8 = $1..4
+   36. copy_4_slots_unmasked          $9..12 = $5..8
+   37. dot_4_floats                   $5 = dot($5..8, $9..12)
+   38. sqrt_float                     $5 = sqrt($5)
+   39. swizzle_4                      $5..8 = ($5..8).xxxx
+   40. div_4_floats                   $1..4 /= $5..8
+   41. copy_4_slots_unmasked          $5..8 = expectedVec
+   42. cmpeq_4_floats                 $1..4 = equal($1..4, $5..8)
+   43. bitwise_and_2_ints             $1..2 &= $3..4
+   44. bitwise_and_int                $1 &= $2
+   45. bitwise_and_int                $0 &= $1
+   46. copy_constant                  $1 = 0x3F800000 (1.0)
+   47. copy_slot_unmasked             $2 = expectedVec(0)
+   48. cmpeq_float                    $1 = equal($1, $2)
+   49. bitwise_and_int                $0 &= $1
+   50. zero_slot_unmasked             $1 = 0
+   51. copy_constant                  $2 = 0x3F800000 (1.0)
+   52. copy_4_slots_unmasked          $3..6 = expectedVec
+   53. swizzle_2                      $3..4 = ($3..4).yx
+   54. cmpeq_2_floats                 $1..2 = equal($1..2, $3..4)
+   55. bitwise_and_int                $1 &= $2
+   56. bitwise_and_int                $0 &= $1
+   57. zero_slot_unmasked             $1 = 0
+   58. copy_constant                  $2 = 0x3F800000 (1.0)
+   59. zero_slot_unmasked             $3 = 0
+   60. copy_4_slots_unmasked          $4..7 = expectedVec
+   61. swizzle_3                      $4..6 = ($4..6).zxy
+   62. cmpeq_3_floats                 $1..3 = equal($1..3, $4..6)
+   63. bitwise_and_int                $2 &= $3
+   64. bitwise_and_int                $1 &= $2
+   65. bitwise_and_int                $0 &= $1
+   66. copy_constant                  $1 = 0x3F800000 (1.0)
+   67. zero_3_slots_unmasked          $2..4 = 0
+   68. copy_4_slots_unmasked          $5..8 = expectedVec
+   69. cmpeq_4_floats                 $1..4 = equal($1..4, $5..8)
+   70. bitwise_and_2_ints             $1..2 &= $3..4
+   71. bitwise_and_int                $1 &= $2
+   72. bitwise_and_int                $0 &= $1
+   73. swizzle_4                      $0..3 = ($0..3).xxxx
+   74. copy_4_constants               $4..7 = colorRed
+   75. copy_4_constants               $8..11 = colorGreen
+   76. mix_4_ints                     $0..3 = mix($4..7, $8..11, $0..3)
+   77. load_src                       src.rgba = $0..3
diff --git a/tests/sksl/shared/GeometricIntrinsics.skrp b/tests/sksl/shared/GeometricIntrinsics.skrp
index 3ef3d71..9b52364 100644
--- a/tests/sksl/shared/GeometricIntrinsics.skrp
+++ b/tests/sksl/shared/GeometricIntrinsics.skrp
@@ -1,4 +1,47 @@
-### 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                  _0_x = 0x3F800000 (1.0)
+    4. copy_slot_unmasked             $0 = _0_x
+    5. abs_float                      $0 = abs($0)
+    6. copy_slot_unmasked             _0_x = $0
+    7. copy_constant                  $1 = 0x40000000 (2.0)
+    8. sub_float                      $0 -= $1
+    9. abs_float                      $0 = abs($0)
+   10. copy_slot_unmasked             _0_x = $0
+   11. copy_constant                  $1 = 0x40000000 (2.0)
+   12. mul_float                      $0 *= $1
+   13. copy_slot_unmasked             _0_x = $0
+   14. copy_slot_unmasked             $1 = $0
+   15. abs_float                      $1 = abs($1)
+   16. div_float                      $0 /= $1
+   17. copy_slot_unmasked             _0_x = $0
+   18. copy_constant                  _1_x(0) = 0x3F800000 (1.0)
+   19. copy_constant                  _1_x(1) = 0x40000000 (2.0)
+   20. copy_2_slots_unmasked          $0..1 = _1_x
+   21. copy_2_slots_unmasked          $2..3 = $0..1
+   22. dot_2_floats                   $0 = dot($0..1, $2..3)
+   23. sqrt_float                     $0 = sqrt($0)
+   24. copy_slot_unmasked             $1 = $0
+   25. copy_2_slots_unmasked          _1_x = $0..1
+   26. copy_constant                  $2 = 0x40400000 (3.0)
+   27. copy_constant                  $3 = 0x40800000 (4.0)
+   28. sub_2_floats                   $0..1 -= $2..3
+   29. copy_2_slots_unmasked          $2..3 = $0..1
+   30. dot_2_floats                   $0 = dot($0..1, $2..3)
+   31. sqrt_float                     $0 = sqrt($0)
+   32. copy_slot_unmasked             $1 = $0
+   33. copy_2_slots_unmasked          _1_x = $0..1
+   34. copy_constant                  $2 = 0x40400000 (3.0)
+   35. copy_constant                  $3 = 0x40800000 (4.0)
+   36. dot_2_floats                   $0 = dot($0..1, $2..3)
+   37. copy_slot_unmasked             $1 = $0
+   38. copy_2_slots_unmasked          _1_x = $0..1
+   39. copy_2_slots_unmasked          $2..3 = $0..1
+   40. copy_2_slots_unmasked          $4..5 = $2..3
+   41. dot_2_floats                   $2 = dot($2..3, $4..5)
+   42. sqrt_float                     $2 = sqrt($2)
+   43. copy_slot_unmasked             $3 = $2
+   44. div_2_floats                   $0..1 /= $2..3
+   45. copy_2_slots_unmasked          _1_x = $0..1
+   46. copy_4_constants               $0..3 = colorGreen
+   47. load_src                       src.rgba = $0..3