From: Kyrylo Tkachov <[email protected]>

Arm exposes V4UQQ, V2UHQ, and V2UHA as SIMD32 vector modes, but the
non-saturating add and subtract patterns only accept their signed forms.
Generic unsigned vector arithmetic therefore produces unresolved libgcc
calls even though Armv6 has exact UADD8, UADD16, USUB8, and USUB16
instructions.

At

  -O2 -mcpu=unset -march=armv6+fp -marm

the six test functions call __addv4uqq3, __addv2uhq3, __addv2uha3,
__subv4uqq3, __subv2uhq3, and __subv2uha3 before the change.  After the
change, the assembly has one UADD8, two UADD16, one USUB8, and two USUB16
instructions.  It has no libgcc helper calls.

Add the three unsigned modes to the existing add and subtract iterator.
Select the signed or unsigned instruction prefix from the mode.  Keep the
existing condition that protects live GE bits.

Tested on arm-linux-gnueabihf with QEMU.
Ok for trunk?
Thanks,
Kyrill

gcc/ChangeLog:

        * config/arm/arm-fixed.md (*arm_add<mode>3, *arm_sub<mode>3): Use the
        mode instruction prefix.
        * config/arm/iterators.md (ADDSUB): Add V4UQQ, V2UHQ, and V2UHA.
        (addsub_prefix): New mode attribute.

gcc/testsuite/ChangeLog:

        * gcc.target/arm/fixed-point-vector-unsigned-1.c: New test.

Signed-off-by: Kyrylo Tkachov <[email protected]>
---
 gcc/config/arm/arm-fixed.md                   |  4 ++--
 gcc/config/arm/iterators.md                   |  5 +++-
 .../arm/fixed-point-vector-unsigned-1.c       | 24 +++++++++++++++++++
 3 files changed, 30 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arm/fixed-point-vector-unsigned-1.c

diff --git a/gcc/config/arm/arm-fixed.md b/gcc/config/arm/arm-fixed.md
index 5d2849b9730..5b24470c7f6 100644
--- a/gcc/config/arm/arm-fixed.md
+++ b/gcc/config/arm/arm-fixed.md
@@ -44,7 +44,7 @@
        (plus:ADDSUB (match_operand:ADDSUB 1 "s_register_operand" "r")
                     (match_operand:ADDSUB 2 "s_register_operand" "r")))]
   "TARGET_INT_SIMD && !ARM_GE_BITS_READ"
-  "sadd<qaddsub_suf>%?\\t%0, %1, %2"
+  "<addsub_prefix>add<qaddsub_suf>%?\\t%0, %1, %2"
   [(set_attr "predicable" "yes")
    (set_attr "type" "alu_dsp_reg")])
 
@@ -103,7 +103,7 @@
        (minus:ADDSUB (match_operand:ADDSUB 1 "s_register_operand" "r")
                      (match_operand:ADDSUB 2 "s_register_operand" "r")))]
   "TARGET_INT_SIMD && !ARM_GE_BITS_READ"
-  "ssub<qaddsub_suf>%?\\t%0, %1, %2"
+  "<addsub_prefix>sub<qaddsub_suf>%?\\t%0, %1, %2"
   [(set_attr "predicable" "yes")
    (set_attr "type" "alu_dsp_reg")])
 
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index c8fd31b52c5..f355be2df1e 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -278,7 +278,7 @@
 ;; Iterators used for fixed-point support.
 (define_mode_iterator FIXED [QQ HQ SQ UQQ UHQ USQ HA SA UHA USA])
 
-(define_mode_iterator ADDSUB [V4QQ V2HQ V2HA])
+(define_mode_iterator ADDSUB [V4QQ V2HQ V2HA V4UQQ V2UHQ V2UHA])
 
 (define_mode_iterator UQADDSUB [V4UQQ V2UHQ UQQ UHQ V2UHA UHA])
 
@@ -1988,6 +1988,9 @@
                               (V4QQ "8") (V2HQ "16") (QQ "8") (HQ "16")
                               (V2HA "16") (HA "16") (SQ "") (SA "")])
 
+(define_mode_attr addsub_prefix [(V4QQ "s") (V2HQ "s") (V2HA "s")
+                                (V4UQQ "u") (V2UHQ "u") (V2UHA "u")])
+
 (define_mode_attr qaddsub_clob_q [(V4UQQ "0") (V2UHQ "0") (UQQ "0") (UHQ "0")
                               (V2UHA "0") (UHA "0")
                               (V4QQ "0") (V2HQ "0") (QQ "0") (HQ "0")
diff --git a/gcc/testsuite/gcc.target/arm/fixed-point-vector-unsigned-1.c 
b/gcc/testsuite/gcc.target/arm/fixed-point-vector-unsigned-1.c
new file mode 100644
index 00000000000..a9530084581
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/fixed-point-vector-unsigned-1.c
@@ -0,0 +1,24 @@
+/* { dg-do compile { target fixed_point } } */
+/* { dg-require-effective-target arm_arch_v6_arm_ok } */
+/* { dg-options "-O2 -std=gnu99" } */
+/* { dg-add-options arm_arch_v6_arm } */
+
+#define DEF(NAME, TYPE, OP)                                          \
+  typedef TYPE NAME##_type __attribute__ ((vector_size (4)));        \
+  void                                                              \
+  NAME (NAME##_type *out, const NAME##_type *x, const NAME##_type *y) \
+  {                                                                 \
+    *out = *x OP *y;                                                 \
+  }
+
+DEF (add_v4uqq, unsigned short _Fract, +)
+DEF (add_v2uhq, unsigned _Fract, +)
+DEF (add_v2uha, unsigned short _Accum, +)
+DEF (sub_v4uqq, unsigned short _Fract, -)
+DEF (sub_v2uhq, unsigned _Fract, -)
+DEF (sub_v2uha, unsigned short _Accum, -)
+
+/* { dg-final { scan-assembler-times "\tuadd8\t...?, ...?, ...?" 1 } } */
+/* { dg-final { scan-assembler-times "\tuadd16\t...?, ...?, ...?" 2 } } */
+/* { dg-final { scan-assembler-times "\tusub8\t...?, ...?, ...?" 1 } } */
+/* { dg-final { scan-assembler-times "\tusub16\t...?, ...?, ...?" 2 } } */
-- 
2.50.1 (Apple Git-155)

Reply via email to