aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>2019-11-07 10:50:23 +0000
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>2019-11-07 10:50:23 +0000
commit0775830a79bad1cdaa8fe279da7cbed123f696b6 (patch)
treed82b5a3fa03a2395ea8df222f06ab956fcfab98f
parent65dd610dcbcf5e1a952f341d0a441593bebe200f (diff)
downloadgcc-0775830a79bad1cdaa8fe279da7cbed123f696b6.zip
gcc-0775830a79bad1cdaa8fe279da7cbed123f696b6.tar.gz
gcc-0775830a79bad1cdaa8fe279da7cbed123f696b6.tar.bz2
[arm][6/X] Add support for __[us]sat16 intrinsics
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
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/arm/arm.md27
-rw-r--r--gcc/config/arm/arm_acle.h18
-rw-r--r--gcc/config/arm/arm_acle_builtins.def3
-rw-r--r--gcc/config/arm/iterators.md6
-rw-r--r--gcc/config/arm/predicates.md8
-rw-r--r--gcc/config/arm/unspecs.md2
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/arm/acle/simd32.c16
9 files changed, 96 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d875026..3b9bae7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,18 @@
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):
New define_insns.
(arm_<simd32_op>): New define_expands.
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index e0e528d..f1d27ff 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -5921,6 +5921,33 @@
}
)
+(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
diff --git a/gcc/config/arm/arm_acle.h b/gcc/config/arm/arm_acle.h
index c30645e..9ea922f 100644
--- a/gcc/config/arm/arm_acle.h
+++ b/gcc/config/arm/arm_acle.h
@@ -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
diff --git a/gcc/config/arm/arm_acle_builtins.def b/gcc/config/arm/arm_acle_builtins.def
index 018d896..8a21ff7 100644
--- a/gcc/config/arm/arm_acle_builtins.def
+++ b/gcc/config/arm/arm_acle_builtins.def
@@ -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)
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index 72aba5e..c412851 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -458,6 +458,8 @@
(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])
@@ -918,6 +920,7 @@
(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
@@ -1083,7 +1086,8 @@
(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])
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index 267c446..c1f655c 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -193,6 +193,14 @@
(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))")))
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 8bf6d97..b4196b0 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -152,6 +152,8 @@
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.
])
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1a65f6b..05b12a8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -5,6 +5,10 @@
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.
* gcc.target/arm/acle/simd32_sel.c: New test.
2019-11-07 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
diff --git a/gcc/testsuite/gcc.target/arm/acle/simd32.c b/gcc/testsuite/gcc.target/arm/acle/simd32.c
index 0db560c..d9b337d 100644
--- a/gcc/testsuite/gcc.target/arm/acle/simd32.c
+++ b/gcc/testsuite/gcc.target/arm/acle/simd32.c
@@ -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 } } */