Add abs support to RP codegen.

This causes four additional tests to pass:
38/113: PASS intrinsics/MinUint.sksl
41/116: PASS intrinsics/MaxUint.sksl
47/133: PASS intrinsics/AbsInt.sksl
48/134: PASS intrinsics/AbsFloat.sksl

Change-Id: I7870b6f78a48141e9b9229a313c5038d988b6e28
Bug: skia:13676
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/626276
Reviewed-by: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
diff --git a/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp b/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp
index 8b53f53..7ffae12 100644
--- a/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLRasterPipelineCodeGenerator.cpp
@@ -221,6 +221,7 @@
     static BuilderOp GetTypedOp(const SkSL::Type& type, const TypedOps& ops);
 
     [[nodiscard]] bool assign(const Expression& e);
+    [[nodiscard]] bool unaryOp(const SkSL::Type& type, const TypedOps& ops);
     [[nodiscard]] bool binaryOp(const SkSL::Type& type, const TypedOps& ops);
     [[nodiscard]] bool ternaryOp(const SkSL::Type& type, const TypedOps& ops);
     [[nodiscard]] bool pushVectorizedExpression(const Expression& expr, const Type& vectorType);
@@ -250,6 +251,10 @@
     SlotRange fCurrentContinueMask;
     int fCurrentTempStack = 0;
 
+    static constexpr auto kAbsOps = TypedOps{BuilderOp::abs_float,
+                                             BuilderOp::abs_int,
+                                             BuilderOp::unsupported,
+                                             BuilderOp::unsupported};
     static constexpr auto kAddOps = TypedOps{BuilderOp::add_n_floats,
                                              BuilderOp::add_n_ints,
                                              BuilderOp::add_n_ints,
@@ -826,6 +831,14 @@
     }
 }
 
+bool Generator::unaryOp(const SkSL::Type& type, const TypedOps& ops) {
+    BuilderOp op = GetTypedOp(type, ops);
+    if (op == BuilderOp::unsupported) {
+        return unsupported();
+    }
+    fBuilder.unary_op(op, type.slotCount());
+    return true;
+}
 bool Generator::binaryOp(const SkSL::Type& type, const TypedOps& ops) {
     BuilderOp op = GetTypedOp(type, ops);
     if (op == BuilderOp::unsupported) {
@@ -1195,6 +1208,12 @@
 
 bool Generator::pushIntrinsic(IntrinsicKind intrinsic, const Expression& arg0) {
     switch (intrinsic) {
+        case IntrinsicKind::k_abs_IntrinsicKind:
+            if (!this->pushExpression(arg0)) {
+                return unsupported();
+            }
+            return this->unaryOp(arg0.type(), kAbsOps);
+
         case IntrinsicKind::k_not_IntrinsicKind:
             return this->pushPrefixExpression(OperatorKind::LOGICALNOT, arg0);
 
@@ -1229,80 +1248,56 @@
             if (!this->pushExpression(arg0) || !this->pushExpression(arg1)) {
                 return unsupported();
             }
-            if (!this->binaryOp(arg0.type(), kEqualOps)) {
-                return unsupported();
-            }
-            return true;
+            return this->binaryOp(arg0.type(), kEqualOps);
 
         case IntrinsicKind::k_notEqual_IntrinsicKind:
             SkASSERT(arg0.type().matches(arg1.type()));
             if (!this->pushExpression(arg0) || !this->pushExpression(arg1)) {
                 return unsupported();
             }
-            if (!this->binaryOp(arg0.type(), kNotEqualOps)) {
-                return unsupported();
-            }
-            return true;
+            return this->binaryOp(arg0.type(), kNotEqualOps);
 
         case IntrinsicKind::k_lessThan_IntrinsicKind:
             SkASSERT(arg0.type().matches(arg1.type()));
             if (!this->pushExpression(arg0) || !this->pushExpression(arg1)) {
                 return unsupported();
             }
-            if (!this->binaryOp(arg0.type(), kLessThanOps)) {
-                return unsupported();
-            }
-            return true;
+            return this->binaryOp(arg0.type(), kLessThanOps);
 
         case IntrinsicKind::k_greaterThan_IntrinsicKind:
             SkASSERT(arg0.type().matches(arg1.type()));
             if (!this->pushExpression(arg1) || !this->pushExpression(arg0)) {
                 return unsupported();
             }
-            if (!this->binaryOp(arg0.type(), kLessThanOps)) {
-                return unsupported();
-            }
-            return true;
+            return this->binaryOp(arg0.type(), kLessThanOps);
 
         case IntrinsicKind::k_lessThanEqual_IntrinsicKind:
             SkASSERT(arg0.type().matches(arg1.type()));
             if (!this->pushExpression(arg0) || !this->pushExpression(arg1)) {
                 return unsupported();
             }
-            if (!this->binaryOp(arg0.type(), kLessThanEqualOps)) {
-                return unsupported();
-            }
-            return true;
+            return this->binaryOp(arg0.type(), kLessThanEqualOps);
 
         case IntrinsicKind::k_greaterThanEqual_IntrinsicKind:
             SkASSERT(arg0.type().matches(arg1.type()));
             if (!this->pushExpression(arg1) || !this->pushExpression(arg0)) {
                 return unsupported();
             }
-            if (!this->binaryOp(arg0.type(), kLessThanEqualOps)) {
-                return unsupported();
-            }
-            return true;
+            return this->binaryOp(arg0.type(), kLessThanEqualOps);
 
         case IntrinsicKind::k_min_IntrinsicKind:
             SkASSERT(arg0.type().componentType().matches(arg1.type().componentType()));
             if (!this->pushExpression(arg0) || !this->pushVectorizedExpression(arg1, arg0.type())) {
                 return unsupported();
             }
-            if (!this->binaryOp(arg0.type(), kMinOps)) {
-                return unsupported();
-            }
-            return true;
+            return this->binaryOp(arg0.type(), kMinOps);
 
         case IntrinsicKind::k_max_IntrinsicKind:
             SkASSERT(arg0.type().componentType().matches(arg1.type().componentType()));
             if (!this->pushExpression(arg0) || !this->pushVectorizedExpression(arg1, arg0.type())) {
                 return unsupported();
             }
-            if (!this->binaryOp(arg0.type(), kMaxOps)) {
-                return unsupported();
-            }
-            return true;
+            return this->binaryOp(arg0.type(), kMaxOps);
 
         default:
             break;