[arm][6/X] Add support for __[us]sat16 intrinsics
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>
Thu, 7 Nov 2019 10:50:23 +0000 (10:50 +0000)
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>
Thu, 7 Nov 2019 10:50:23 +0000 (10:50 +0000)
This last patch adds the the __ssat16 and __usat16 intrinsics that perform
"clipping" to a particular bitwidth on packed SIMD values, setting the Q bit
as appropriate.

* config/arm/arm.md (arm_<simd32_op>): New define_expand.
(arm_<simd32_op><add_clobber_q_name>_insn): New define_insn.
* config/arm/arm_acle.h (__ssat16, __usat16): Define.
* config/arm/arm_acle_builtins.def: Define builtins for the above.
* config/arm/iterators.md (USSAT16): New int_iterator.
(simd32_op): Handle UNSPEC_SSAT16, UNSPEC_USAT16.
(sup): Likewise.
* config/arm/predicates.md (ssat16_imm): New predicate.
(usat16_imm): Likewise.
* config/arm/unspecs.md (UNSPEC_SSAT16, UNSPEC_USAT16): Define.

* gcc.target/arm/acle/simd32.c: Update test.

From-SVN: r277919

gcc/ChangeLog
gcc/config/arm/arm.md
gcc/config/arm/arm_acle.h
gcc/config/arm/arm_acle_builtins.def
gcc/config/arm/iterators.md
gcc/config/arm/predicates.md
gcc/config/arm/unspecs.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/acle/simd32.c

index d875026161280269d3a174c238172fb89f2334ab..3b9bae709ddd07e0df4dab191fea1e6ab78d4b58 100644 (file)
@@ -1,3 +1,16 @@
+2019-11-07  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * config/arm/arm.md (arm_<simd32_op>): New define_expand.
+       (arm_<simd32_op><add_clobber_q_name>_insn): New define_insn.
+       * config/arm/arm_acle.h (__ssat16, __usat16): Define.
+       * config/arm/arm_acle_builtins.def: Define builtins for the above.
+       * config/arm/iterators.md (USSAT16): New int_iterator.
+       (simd32_op): Handle UNSPEC_SSAT16, UNSPEC_USAT16.
+       (sup): Likewise.
+       * config/arm/predicates.md (ssat16_imm): New predicate.
+       (usat16_imm): Likewise.
+       * config/arm/unspecs.md (UNSPEC_SSAT16, UNSPEC_USAT16): Define.
+
 2019-11-07  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * config/arm/arm.md (arm_<simd32_op><add_clobber_q_name>_insn):
index e0e528dd677480fe33bb4f9cbd58fff4696f654d..f1d27ffbb4aa8190959cbf7d9c9ac1b7bcd97b33 100644 (file)
   }
 )
 
+(define_insn "arm_<simd32_op><add_clobber_q_name>_insn"
+  [(set (match_operand:SI 0 "s_register_operand" "=r")
+       (unspec:SI
+         [(match_operand:SI 1 "s_register_operand" "r")
+          (match_operand:SI 2 "<sup>sat16_imm" "i")] USSAT16))]
+  "TARGET_INT_SIMD && <add_clobber_q_pred>"
+  "<simd32_op>%?\\t%0, %2, %1"
+  [(set_attr "predicable" "yes")
+   (set_attr "type" "alu_sreg")])
+
+(define_expand "arm_<simd32_op>"
+  [(set (match_operand:SI 0 "s_register_operand")
+       (unspec:SI
+         [(match_operand:SI 1 "s_register_operand")
+          (match_operand:SI 2 "<sup>sat16_imm")] USSAT16))]
+  "TARGET_INT_SIMD"
+  {
+    if (ARM_Q_BIT_READ)
+      emit_insn (gen_arm_<simd32_op>_setq_insn (operands[0], operands[1],
+                                               operands[2]));
+    else
+      emit_insn (gen_arm_<simd32_op>_insn (operands[0], operands[1],
+                                          operands[2]));
+    DONE;
+  }
+)
+
 (define_insn "arm_sel"
   [(set (match_operand:SI 0 "s_register_operand" "=r")
        (unspec:SI
index c30645e3949f84321fb1dfe3afd06167ef859d62..9ea922f2d096870d2c2d34ac43f03e3bc9dc4741 100644 (file)
@@ -564,6 +564,24 @@ __smuadx (int16x2_t __a, int16x2_t __b)
   return __builtin_arm_smuadx (__a, __b);
 }
 
+#define __ssat16(__a, __sat)                                   \
+  __extension__                                                        \
+  ({                                                           \
+    int16x2_t __arg = (__a);                                   \
+    __builtin_sat_imm_check (__sat, 1, 16);                    \
+    int16x2_t __res = __builtin_arm_ssat16 (__arg, __sat);     \
+    __res;                                                     \
+  })
+
+#define __usat16(__a, __sat)                                   \
+  __extension__                                                        \
+  ({                                                           \
+    int16x2_t __arg = (__a);                                   \
+    __builtin_sat_imm_check (__sat, 0, 15);                    \
+    int16x2_t __res = __builtin_arm_usat16 (__arg, __sat);     \
+    __res;                                                     \
+  })
+
 #endif
 
 #ifdef __ARM_FEATURE_SAT
index 018d89682c61a963961515823420f1b986cd40db..8a21ff74f41840dd793221e079627055d379c474 100644 (file)
@@ -114,3 +114,6 @@ VAR1 (TERNOP, smlsd, si)
 VAR1 (TERNOP, smlsdx, si)
 VAR1 (BINOP, smuad, si)
 VAR1 (BINOP, smuadx, si)
+
+VAR1 (SAT_BINOP_UNSIGNED_IMM, ssat16, si)
+VAR1 (SAT_BINOP_UNSIGNED_IMM, usat16, si)
index 72aba5e86fc20216bcba74f5cfa5b9f744497a6e..c412851843f4468c2c18bce264288705e076ac50 100644 (file)
 
 (define_int_iterator SIMD32_BINOP_Q [UNSPEC_SMUAD UNSPEC_SMUADX])
 
+(define_int_iterator USSAT16 [UNSPEC_SSAT16 UNSPEC_USAT16])
+
 (define_int_iterator VQRDMLH_AS [UNSPEC_VQRDMLAH UNSPEC_VQRDMLSH])
 
 (define_int_iterator VFM_LANE_AS [UNSPEC_VFMA_LANE UNSPEC_VFMS_LANE])
   (UNSPEC_VRSRA_S_N "s") (UNSPEC_VRSRA_U_N "u")
   (UNSPEC_VCVTH_S "s") (UNSPEC_VCVTH_U "u")
   (UNSPEC_DOT_S "s") (UNSPEC_DOT_U "u")
+  (UNSPEC_SSAT16 "s") (UNSPEC_USAT16 "u")
 ])
 
 (define_int_attr vfml_half
                            (UNSPEC_USUB16 "usub16") (UNSPEC_SMLAD "smlad")
                            (UNSPEC_SMLADX "smladx") (UNSPEC_SMLSD "smlsd")
                            (UNSPEC_SMLSDX "smlsdx") (UNSPEC_SMUAD "smuad")
-                           (UNSPEC_SMUADX "smuadx")])
+                           (UNSPEC_SMUADX "smuadx") (UNSPEC_SSAT16 "ssat16")
+                           (UNSPEC_USAT16 "usat16")])
 
 ;; Both kinds of return insn.
 (define_code_iterator RETURNS [return simple_return])
index 267c446c03e8903c21a0d74e43ae589ffcf689f4..c1f655c704011bbe8bac82c24a3234a23bf6b242 100644 (file)
   (and (match_code "const_int")
        (match_test "IN_RANGE (UINTVAL (op), 1, GET_MODE_BITSIZE (mode))")))
 
+(define_predicate "ssat16_imm"
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (INTVAL (op), 1, 16)")))
+
+(define_predicate "usat16_imm"
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (INTVAL (op), 0, 15)")))
+
 (define_predicate "ldrd_strd_offset_operand"
   (and (match_operand 0 "const_int_operand")
        (match_test "TARGET_LDRD && offset_ok_for_ldrd_strd (INTVAL (op))")))
index 8bf6d9712054808143d308726c5c0f1d613c6ed4..b4196b0e5cd939c3ee5e3f9bd19622fcc963adae 100644 (file)
   UNSPEC_SMLSDX                ; Represent the SMLSDX operation.
   UNSPEC_SMUAD         ; Represent the SMUAD operation.
   UNSPEC_SMUADX                ; Represent the SMUADX operation.
+  UNSPEC_SSAT16                ; Represent the SSAT16 operation.
+  UNSPEC_USAT16                ; Represent the USAT16 operation.
 ])
 
 
index 1a65f6b928b616846999cf616853b5967647d5b1..05b12a8ebaf772a77847db574c3795f9dd51ba0a 100644 (file)
@@ -2,6 +2,10 @@
 
        * gcc.target/arm/acle/simd32.c: Update test.
 
+2019-11-07  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * gcc.target/arm/acle/simd32.c: Update test.
+
 2019-11-07  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * gcc.target/arm/acle/simd32.c: Update test.
index 0db560c690e98cbf1c9e642a7a626a1a2ff8ece4..d9b337da35bae5a7eedf17bcd05c8fc065557425 100644 (file)
@@ -420,3 +420,19 @@ test_smuadx (int16x2_t a, int16x2_t b)
 }
 
 /* { dg-final { scan-assembler-times "\tsmuadx\t...?, ...?, ...?" 1 } } */
+
+int16x2_t
+test_ssat16 (int16x2_t a)
+{
+  return __ssat16 (a, 13);
+}
+
+/* { dg-final { scan-assembler-times "\tssat16\t...?, #13, ...?" 1 } } */
+
+int16x2_t
+test_usat16 (int16x2_t a)
+{
+  return __usat16 (a, 15);
+}
+
+/* { dg-final { scan-assembler-times "\tusat16\t...?, #15, ...?" 1 } } */