diff options
author | Kyrylo Tkachov <kyrylo.tkachov@arm.com> | 2019-11-07 10:49:06 +0000 |
---|---|---|
committer | Kyrylo Tkachov <ktkachov@gcc.gnu.org> | 2019-11-07 10:49:06 +0000 |
commit | 65dd610dcbcf5e1a952f341d0a441593bebe200f (patch) | |
tree | f9325cafb9706e72c4560efda43a4fcabb90a689 | |
parent | 16155ccf588a403c033ccd7743329671bcfb27d5 (diff) | |
download | gcc-65dd610dcbcf5e1a952f341d0a441593bebe200f.zip gcc-65dd610dcbcf5e1a952f341d0a441593bebe200f.tar.gz gcc-65dd610dcbcf5e1a952f341d0a441593bebe200f.tar.bz2 |
[arm][5/X] Implement Q-bit-setting SIMD32 intrinsics
This patch implements some more Q-setting intrinsics of the
multiply-accumulate
variety, but these are in the SIMD32 family in that they treat their
operands as packed SIMD values, but that's not important at the RTL level.
* config/arm/arm.md (arm_<simd32_op><add_clobber_q_name>_insn):
New define_insns.
(arm_<simd32_op>): New define_expands.
* config/arm/arm_acle.h (__smlad, __smladx, __smlsd, __smlsdx,
__smuad, __smuadx): Define.
* config/arm/arm_acle_builtins.def: Define builtins for the above.
* config/arm/iterators.md (SIMD32_TERNOP_Q): New int_iterator.
(SIMD32_BINOP_Q): Likewise.
(simd32_op): Handle the above.
* config/arm/unspecs.md: Define unspecs for the above.
* gcc.target/arm/acle/simd32.c: Update test.
From-SVN: r277918
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 56 | ||||
-rw-r--r-- | gcc/config/arm/arm_acle.h | 42 | ||||
-rw-r--r-- | gcc/config/arm/arm_acle_builtins.def | 7 | ||||
-rw-r--r-- | gcc/config/arm/iterators.md | 10 | ||||
-rw-r--r-- | gcc/config/arm/unspecs.md | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arm/acle/simd32.c | 48 |
8 files changed, 185 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 82cc2ca..d875026 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><add_clobber_q_name>_insn): + New define_insns. + (arm_<simd32_op>): New define_expands. + * config/arm/arm_acle.h (__smlad, __smladx, __smlsd, __smlsdx, + __smuad, __smuadx): Define. + * config/arm/arm_acle_builtins.def: Define builtins for the above. + * config/arm/iterators.md (SIMD32_TERNOP_Q): New int_iterator. + (SIMD32_BINOP_Q): Likewise. + (simd32_op): Handle the above. + * config/arm/unspecs.md: Define unspecs for the above. + +2019-11-07 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + * config/arm/aout.h (REGISTER_NAMES): Add apsrge. * config/arm/arm.md (APSRGE_REGNUM): Define. (arm_<simd32_op>): New define_insn. diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index a74c93c..e0e528d 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -5865,6 +5865,62 @@ [(set_attr "predicable" "yes") (set_attr "type" "alu_sreg")]) +(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 "s_register_operand" "r") + (match_operand:SI 3 "s_register_operand" "r")] SIMD32_TERNOP_Q))] + "TARGET_INT_SIMD && <add_clobber_q_pred>" + "<simd32_op>%?\\t%0, %1, %2, %3" + [(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 "s_register_operand") + (match_operand:SI 3 "s_register_operand")] SIMD32_TERNOP_Q))] + "TARGET_INT_SIMD" + { + if (ARM_Q_BIT_READ) + emit_insn (gen_arm_<simd32_op>_setq_insn (operands[0], operands[1], + operands[2], operands[3])); + else + emit_insn (gen_arm_<simd32_op>_insn (operands[0], operands[1], + operands[2], operands[3])); + DONE; + } +) + +(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 "s_register_operand" "r")] SIMD32_BINOP_Q))] + "TARGET_INT_SIMD && <add_clobber_q_pred>" + "<simd32_op>%?\\t%0, %1, %2" + [(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 "s_register_operand")] SIMD32_BINOP_Q))] + "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 b8d02a5..c30645e 100644 --- a/gcc/config/arm/arm_acle.h +++ b/gcc/config/arm/arm_acle.h @@ -522,6 +522,48 @@ __usub16 (uint16x2_t __a, uint16x2_t __b) return __builtin_arm_usub16 (__a, __b); } +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__smlad (int16x2_t __a, int16x2_t __b, int32_t __c) +{ + return __builtin_arm_smlad (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__smladx (int16x2_t __a, int16x2_t __b, int32_t __c) +{ + return __builtin_arm_smladx (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__smlsd (int16x2_t __a, int16x2_t __b, int32_t __c) +{ + return __builtin_arm_smlsd (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__smlsdx (int16x2_t __a, int16x2_t __b, int32_t __c) +{ + return __builtin_arm_smlsdx (__a, __b, __c); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__smuad (int16x2_t __a, int16x2_t __b) +{ + return __builtin_arm_smuad (__a, __b); +} + +__extension__ extern __inline int32_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +__smuadx (int16x2_t __a, int16x2_t __b) +{ + return __builtin_arm_smuadx (__a, __b); +} + #endif #ifdef __ARM_FEATURE_SAT diff --git a/gcc/config/arm/arm_acle_builtins.def b/gcc/config/arm/arm_acle_builtins.def index 715c3c9..018d896 100644 --- a/gcc/config/arm/arm_acle_builtins.def +++ b/gcc/config/arm/arm_acle_builtins.def @@ -107,3 +107,10 @@ VAR1 (UBINOP, usax, si) VAR1 (UBINOP, usub16, si) VAR1 (UBINOP, sel, si) + +VAR1 (TERNOP, smlad, si) +VAR1 (TERNOP, smladx, si) +VAR1 (TERNOP, smlsd, si) +VAR1 (TERNOP, smlsdx, si) +VAR1 (BINOP, smuad, si) +VAR1 (BINOP, smuadx, si) diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index 2394a95..72aba5e 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -453,6 +453,11 @@ UNSPEC_SSAX UNSPEC_SSUB16 UNSPEC_UADD16 UNSPEC_UASX UNSPEC_USAX UNSPEC_USUB16]) +(define_int_iterator SIMD32_TERNOP_Q [UNSPEC_SMLAD UNSPEC_SMLADX UNSPEC_SMLSD + UNSPEC_SMLSDX]) + +(define_int_iterator SIMD32_BINOP_Q [UNSPEC_SMUAD UNSPEC_SMUADX]) + (define_int_iterator VQRDMLH_AS [UNSPEC_VQRDMLAH UNSPEC_VQRDMLSH]) (define_int_iterator VFM_LANE_AS [UNSPEC_VFMA_LANE UNSPEC_VFMS_LANE]) @@ -1075,7 +1080,10 @@ (UNSPEC_SASX "sasx") (UNSPEC_SSAX "ssax") (UNSPEC_SSUB16 "ssub16") (UNSPEC_UADD16 "uadd16") (UNSPEC_UASX "uasx") (UNSPEC_USAX "usax") - (UNSPEC_USUB16 "usub16")]) + (UNSPEC_USUB16 "usub16") (UNSPEC_SMLAD "smlad") + (UNSPEC_SMLADX "smladx") (UNSPEC_SMLSD "smlsd") + (UNSPEC_SMLSDX "smlsdx") (UNSPEC_SMUAD "smuad") + (UNSPEC_SMUADX "smuadx")]) ;; Both kinds of return insn. (define_code_iterator RETURNS [return simple_return]) diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md index dfd6dea..8bf6d97 100644 --- a/gcc/config/arm/unspecs.md +++ b/gcc/config/arm/unspecs.md @@ -146,6 +146,12 @@ UNSPEC_UASX ; Represent the UASX operation. UNSPEC_USAX ; Represent the USAX operation. UNSPEC_USUB16 ; Represent the USUB16 operation. + UNSPEC_SMLAD ; Represent the SMLAD operation. + UNSPEC_SMLADX ; Represent the SMLADX operation. + UNSPEC_SMLSD ; Represent the SMLSD operation. + UNSPEC_SMLSDX ; Represent the SMLSDX operation. + UNSPEC_SMUAD ; Represent the SMUAD operation. + UNSPEC_SMUADX ; Represent the SMUADX operation. ]) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index de6d58a..1a65f6b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,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 d4304d8..0db560c 100644 --- a/gcc/testsuite/gcc.target/arm/acle/simd32.c +++ b/gcc/testsuite/gcc.target/arm/acle/simd32.c @@ -372,3 +372,51 @@ test_usub16 (uint16x2_t a, uint16x2_t b) } /* { dg-final { scan-assembler-times "\tusub16\t...?, ...?, ...?" 1 } } */ + +int32_t +test_smlad (int16x2_t a, int16x2_t b, int32_t c) +{ + return __smlad (a, b, c); +} + +/* { dg-final { scan-assembler-times "\tsmlad\t...?, ...?, ...?, ...?" 1 } } */ + +int32_t +test_smladx (int16x2_t a, int16x2_t b, int32_t c) +{ + return __smladx (a, b, c); +} + +/* { dg-final { scan-assembler-times "\tsmladx\t...?, ...?, ...?, ...?" 1 } } */ + +int32_t +test_smlsd (int16x2_t a, int16x2_t b, int32_t c) +{ + return __smlsd (a, b, c); +} + +/* { dg-final { scan-assembler-times "\tsmlsd\t...?, ...?, ...?, ...?" 1 } } */ + +int32_t +test_smlsdx (int16x2_t a, int16x2_t b, int32_t c) +{ + return __smlsdx (a, b, c); +} + +/* { dg-final { scan-assembler-times "\tsmlsdx\t...?, ...?, ...?, ...?" 1 } } */ + +int32_t +test_smuad (int16x2_t a, int16x2_t b) +{ + return __smuad (a, b); +} + +/* { dg-final { scan-assembler-times "\tsmuad\t...?, ...?, ...?" 1 } } */ + +int32_t +test_smuadx (int16x2_t a, int16x2_t b) +{ + return __smuadx (a, b); +} + +/* { dg-final { scan-assembler-times "\tsmuadx\t...?, ...?, ...?" 1 } } */ |