[AArch64] Rearrange SVE conversion patterns
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 14 Aug 2019 08:39:48 +0000 (08:39 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 14 Aug 2019 08:39:48 +0000 (08:39 +0000)
The SVE int<->float conversion patterns need to handle various
combinations of modes, making sure that the predicate mode is based
on the widest element size.  We did this using separate patterns for
conversions involving:

- HF (converting to/from [HSD]I, predicated based on the int operand)
- SF (converting to/from [SD]I, predicated based on the int operand)
- DF (converting to/from [SD]I, predicated based on the float operand)

This worked, and meant that there were no redundant patterns.  However,
the ACLE needs various new predicated patterns too, and having three
versions of each one seemed excessive.

This patch instead splits the patterns into two groups rather than three.
For conversions to integers:

- truncating (predicated based on the source type, DF->SI only)
- non-truncating (predicated based on the destination type)

For conversions from integers:

- extending (predicated based on the destination type, SI->DF only)
- non-extending (predicated based on the source type)

This means that we still don't create pattern names for the invalid
combinations DF<->HI and SF<->HI.  The downside is that we need to
use C conditions to exclude the SI<->DF case from the non-truncating/
non-extending patterns.  We therefore have two pattern names for SI<->DF,
but genconditions ensures that the invalid one always has the value
CODE_FOR_nothing.

2019-08-14  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
* config/aarch64/iterators.md (VNx4SI_ONLY, VNx2DF_ONLY): New mode
iterators.
(SVE_BHSI, SVE_SDI): Tweak comment.
(SVE_HSDI): Likewise.  Fix definition.
(SVE_SDF): New mode iterator.
(elem_bits): New mode attribute.
(SVE_COND_FCVT): New int iterator.
* config/aarch64/aarch64-sve.md
(*<SVE_COND_ICVTF:optab>v16hsf<SVE_HSDI:mode>2)
(*<SVE_COND_ICVTF:optab>vnx4sf<SVE_SDI:mode>2)
(*<SVE_COND_ICVTF:optab>vnx2df<SVE_SDI:mode>2): Merge into...
(*aarch64_sve_<SVE_COND_ICVTF:optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>)
(*aarch64_sve_<SVE_COND_ICVTF:optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>):
...these new patterns.
(*<SVE_COND_FCVTI:optab><SVE_HSDI:mode>vnx8hf2)
(*<SVE_COND_FCVTI:optab><SVE_SDI:mode>vnx4sf2)
(aarch64_sve_<SVE_COND_FCVTI:optab><SVE_SDI:mode>vnx2df2):
Merge into...
(*aarch64_sve_<SVE_COND_FCVTI:optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>)
(aarch64_sve_<SVE_COND_FCVTI:optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>):
...these new patterns.
(vec_unpack<su_optab>_float_<perm_hilo>_vnx4si): Update accordingly.
(*trunc<Vwide><SVE_SDF:mode>2): Replace with...
(*aarch64_sve_<SVE_COND_FCVT:optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>):
...this new pattern.
(aarch64_sve_extend<SVE_HSDF:mode><Vwide>2): Replace with...
(aarch64_sve_<SVE_COND_FCVT:optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>):
...this new pattern.
(vec_unpacks_<perm_hilo>_<mode>): Update accordingly.

From-SVN: r274424

gcc/ChangeLog
gcc/config/aarch64/aarch64-sve.md
gcc/config/aarch64/iterators.md

index 2f2a8a4..ddf6763 100644 (file)
@@ -1,5 +1,37 @@
 2019-08-14  Richard Sandiford  <richard.sandiford@arm.com>
 
+       * config/aarch64/iterators.md (VNx4SI_ONLY, VNx2DF_ONLY): New mode
+       iterators.
+       (SVE_BHSI, SVE_SDI): Tweak comment.
+       (SVE_HSDI): Likewise.  Fix definition.
+       (SVE_SDF): New mode iterator.
+       (elem_bits): New mode attribute.
+       (SVE_COND_FCVT): New int iterator.
+       * config/aarch64/aarch64-sve.md
+       (*<SVE_COND_ICVTF:optab>v16hsf<SVE_HSDI:mode>2)
+       (*<SVE_COND_ICVTF:optab>vnx4sf<SVE_SDI:mode>2)
+       (*<SVE_COND_ICVTF:optab>vnx2df<SVE_SDI:mode>2): Merge into...
+       (*aarch64_sve_<SVE_COND_ICVTF:optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>)
+       (*aarch64_sve_<SVE_COND_ICVTF:optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>):
+       ...these new patterns.
+       (*<SVE_COND_FCVTI:optab><SVE_HSDI:mode>vnx8hf2)
+       (*<SVE_COND_FCVTI:optab><SVE_SDI:mode>vnx4sf2)
+       (aarch64_sve_<SVE_COND_FCVTI:optab><SVE_SDI:mode>vnx2df2):
+       Merge into...
+       (*aarch64_sve_<SVE_COND_FCVTI:optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>)
+       (aarch64_sve_<SVE_COND_FCVTI:optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>):
+       ...these new patterns.
+       (vec_unpack<su_optab>_float_<perm_hilo>_vnx4si): Update accordingly.
+       (*trunc<Vwide><SVE_SDF:mode>2): Replace with...
+       (*aarch64_sve_<SVE_COND_FCVT:optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>):
+       ...this new pattern.
+       (aarch64_sve_extend<SVE_HSDF:mode><Vwide>2): Replace with...
+       (aarch64_sve_<SVE_COND_FCVT:optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>):
+       ...this new pattern.
+       (vec_unpacks_<perm_hilo>_<mode>): Update accordingly.
+
+2019-08-14  Richard Sandiford  <richard.sandiford@arm.com>
+
        * config/aarch64/aarch64.md (UNSPEC_FLOAT_CONVERT): Delete.
        * config/aarch64/iterators.md (UNSPEC_COND_FCVT, UNSPEC_COND_FCVTZS)
        (UNSPEC_COND_FCVTZU, UNSPEC_COND_SCVTF, UNSPEC_COND_UCVTF): New
index 0c9d4c5..64992c4 100644 (file)
   }
 )
 
-;; Conversion of SF to DI, SI or HI, predicated with a PTRUE.
-(define_insn "*<optab>v16hsf<mode>2"
+;; Predicated float-to-integer conversion, either to the same width or wider.
+(define_insn "*aarch64_sve_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>"
   [(set (match_operand:SVE_HSDI 0 "register_operand" "=w")
        (unspec:SVE_HSDI
-         [(match_operand:<VPRED> 1 "register_operand" "Upl")
+         [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand" "Upl")
           (match_operand:SI 3 "aarch64_sve_gp_strictness")
-          (match_operand:VNx8HF 2 "register_operand" "w")]
-         SVE_COND_FCVTI))]
-  "TARGET_SVE"
-  "fcvtz<su>\t%0.<Vetype>, %1/m, %2.h"
-)
-
-;; Conversion of SF to DI or SI, predicated with a PTRUE.
-(define_insn "*<optab>vnx4sf<mode>2"
-  [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
-       (unspec:SVE_SDI
-         [(match_operand:<VPRED> 1 "register_operand" "Upl")
-          (match_operand:SI 3 "aarch64_sve_gp_strictness")
-          (match_operand:VNx4SF 2 "register_operand" "w")]
+          (match_operand:SVE_F 2 "register_operand" "w")]
          SVE_COND_FCVTI))]
-  "TARGET_SVE"
-  "fcvtz<su>\t%0.<Vetype>, %1/m, %2.s"
+  "TARGET_SVE && <SVE_HSDI:elem_bits> >= <SVE_F:elem_bits>"
+  "fcvtz<su>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_F:Vetype>"
 )
 
-;; Conversion of DF to DI or SI, predicated with a PTRUE.
-(define_insn "*<optab>vnx2df<mode>2"
-  [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
-       (unspec:SVE_SDI
+;; Predicated narrowing float-to-integer conversion.
+(define_insn "*aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>"
+  [(set (match_operand:VNx4SI_ONLY 0 "register_operand" "=w")
+       (unspec:VNx4SI_ONLY
          [(match_operand:VNx2BI 1 "register_operand" "Upl")
           (match_operand:SI 3 "aarch64_sve_gp_strictness")
-          (match_operand:VNx2DF 2 "register_operand" "w")]
+          (match_operand:VNx2DF_ONLY 2 "register_operand" "w")]
          SVE_COND_FCVTI))]
   "TARGET_SVE"
-  "fcvtz<su>\t%0.<Vetype>, %1/m, %2.d"
+  "fcvtz<su>\t%0.<VNx4SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>"
 )
 
 ;; -------------------------------------------------------------------------
   }
 )
 
-;; Conversion of DI, SI or HI to the same number of HFs, predicated
-;; with a PTRUE.
-(define_insn "*<optab><mode>vnx8hf2"
-  [(set (match_operand:VNx8HF 0 "register_operand" "=w")
-       (unspec:VNx8HF
-         [(match_operand:<VPRED> 1 "register_operand" "Upl")
+;; Predicated integer-to-float conversion, either to the same width or
+;; narrower.
+(define_insn "*aarch64_sve_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w")
+       (unspec:SVE_F
+         [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand" "Upl")
           (match_operand:SI 3 "aarch64_sve_gp_strictness")
           (match_operand:SVE_HSDI 2 "register_operand" "w")]
          SVE_COND_ICVTF))]
-  "TARGET_SVE"
-  "<su>cvtf\t%0.h, %1/m, %2.<Vetype>"
-)
-
-;; Conversion of DI or SI to the same number of SFs, predicated with a PTRUE.
-(define_insn "*<optab><mode>vnx4sf2"
-  [(set (match_operand:VNx4SF 0 "register_operand" "=w")
-       (unspec:VNx4SF
-         [(match_operand:<VPRED> 1 "register_operand" "Upl")
-          (match_operand:SI 3 "aarch64_sve_gp_strictness")
-          (match_operand:SVE_SDI 2 "register_operand" "w")]
-         SVE_COND_ICVTF))]
-  "TARGET_SVE"
-  "<su>cvtf\t%0.s, %1/m, %2.<Vetype>"
+  "TARGET_SVE && <SVE_HSDI:elem_bits> >= <SVE_F:elem_bits>"
+  "<su>cvtf\t%0.<SVE_F:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>"
 )
 
-;; Conversion of DI or SI to DF, predicated with a PTRUE.
-(define_insn "aarch64_sve_<optab><mode>vnx2df2"
-  [(set (match_operand:VNx2DF 0 "register_operand" "=w")
-       (unspec:VNx2DF
+;; Predicated widening integer-to-float conversion.
+(define_insn "aarch64_sve_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>"
+  [(set (match_operand:VNx2DF_ONLY 0 "register_operand" "=w")
+       (unspec:VNx2DF_ONLY
          [(match_operand:VNx2BI 1 "register_operand" "Upl")
           (match_operand:SI 3 "aarch64_sve_gp_strictness")
-          (match_operand:SVE_SDI 2 "register_operand" "w")]
+          (match_operand:VNx4SI_ONLY 2 "register_operand" "w")]
          SVE_COND_ICVTF))]
   "TARGET_SVE"
-  "<su>cvtf\t%0.d, %1/m, %2.<Vetype>"
+  "<su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>"
 )
 
 ;; -------------------------------------------------------------------------
               (temp, operands[1], operands[1]));
     rtx ptrue = aarch64_ptrue_reg (VNx2BImode);
     rtx strictness = gen_int_mode (SVE_RELAXED_GP, SImode);
-    emit_insn (gen_aarch64_sve_<FLOATUORS:optab>vnx4sivnx2df2
+    emit_insn (gen_aarch64_sve_<FLOATUORS:optab>_extendvnx4sivnx2df
               (operands[0], ptrue, temp, strictness));
     DONE;
   }
   }
 )
 
-;; Conversion of DFs to the same number of SFs, or SFs to the same number
-;; of HFs.
-(define_insn "*trunc<Vwide><mode>2"
+;; Predicated float-to-float truncation.
+(define_insn "*aarch64_sve_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>"
   [(set (match_operand:SVE_HSF 0 "register_operand" "=w")
        (unspec:SVE_HSF
-         [(match_operand:<VWIDE_PRED> 1 "register_operand" "Upl")
+         [(match_operand:<SVE_SDF:VPRED> 1 "register_operand" "Upl")
           (match_operand:SI 3 "aarch64_sve_gp_strictness")
-          (match_operand:<VWIDE> 2 "register_operand" "w")]
-         UNSPEC_COND_FCVT))]
-  "TARGET_SVE"
-  "fcvt\t%0.<Vetype>, %1/m, %2.<Vewtype>"
+          (match_operand:SVE_SDF 2 "register_operand" "w")]
+         SVE_COND_FCVT))]
+  "TARGET_SVE && <SVE_SDF:elem_bits> > <SVE_HSF:elem_bits>"
+  "fcvt\t%0.<SVE_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>"
 )
 
 ;; -------------------------------------------------------------------------
                (temp, operands[1], operands[1]));
     rtx ptrue = aarch64_ptrue_reg (<VWIDE_PRED>mode);
     rtx strictness = gen_int_mode (SVE_RELAXED_GP, SImode);
-    emit_insn (gen_aarch64_sve_extend<mode><Vwide>2
+    emit_insn (gen_aarch64_sve_fcvt_nontrunc<mode><Vwide>
               (operands[0], ptrue, temp, strictness));
     DONE;
   }
 )
 
-;; Conversion of SFs to the same number of DFs, or HFs to the same number
-;; of SFs.
-(define_insn "aarch64_sve_extend<mode><Vwide>2"
-  [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
-       (unspec:<VWIDE>
-         [(match_operand:<VWIDE_PRED> 1 "register_operand" "Upl")
+;; Predicated float-to-float extension.
+(define_insn "aarch64_sve_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>"
+  [(set (match_operand:SVE_SDF 0 "register_operand" "=w")
+       (unspec:SVE_SDF
+         [(match_operand:<SVE_SDF:VPRED> 1 "register_operand" "Upl")
           (match_operand:SI 3 "aarch64_sve_gp_strictness")
           (match_operand:SVE_HSF 2 "register_operand" "w")]
-         UNSPEC_COND_FCVT))]
-  "TARGET_SVE"
-  "fcvt\t%0.<Vewtype>, %1/m, %2.<Vetype>"
+         SVE_COND_FCVT))]
+  "TARGET_SVE && <SVE_SDF:elem_bits> > <SVE_HSF:elem_bits>"
+  "fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_HSF:Vetype>"
 )
 
 ;; -------------------------------------------------------------------------
index 05adbba..75e672b 100644 (file)
 (define_mode_iterator SVE_ALL [VNx16QI VNx8HI VNx4SI VNx2DI
                               VNx8HF VNx4SF VNx2DF])
 
+;; Iterators for single modes, for "@" patterns.
+(define_mode_iterator VNx4SI_ONLY [VNx4SI])
+(define_mode_iterator VNx2DF_ONLY [VNx2DF])
+
 ;; All SVE vector structure modes.
 (define_mode_iterator SVE_STRUCT [VNx32QI VNx16HI VNx8SI VNx4DI
                                  VNx16HF VNx8SF VNx4DF
 ;; All SVE vector modes that have 8-bit, 16-bit or 32-bit elements.
 (define_mode_iterator SVE_BHS [VNx16QI VNx8HI VNx4SI VNx8HF VNx4SF])
 
-;; All SVE integer vector modes that have 8-bit, 16-bit or 32-bit elements.
+;; SVE integer vector modes that have 8-bit, 16-bit or 32-bit elements.
 (define_mode_iterator SVE_BHSI [VNx16QI VNx8HI VNx4SI])
 
-;; All SVE integer vector modes that have 16-bit, 32-bit or 64-bit elements.
-(define_mode_iterator SVE_HSDI [VNx16QI VNx8HI VNx4SI])
+;; SVE integer vector modes that have 16-bit, 32-bit or 64-bit elements.
+(define_mode_iterator SVE_HSDI [VNx8HI VNx4SI VNx2DI])
 
-;; All SVE floating-point vector modes that have 16-bit or 32-bit elements.
+;; SVE floating-point vector modes that have 16-bit or 32-bit elements.
 (define_mode_iterator SVE_HSF [VNx8HF VNx4SF])
 
+;; SVE integer vector modes that have 32-bit or 64-bit elements.
+(define_mode_iterator SVE_SDI [VNx4SI VNx2DI])
+
+;; SVE floating-point vector modes that have 32-bit or 64-bit elements.
+(define_mode_iterator SVE_SDF [VNx4SF VNx2DF])
+
 ;; All SVE vector modes that have 16-bit, 32-bit or 64-bit elements.
 (define_mode_iterator SVE_HSD [VNx8HI VNx4SI VNx2DI VNx8HF VNx4SF VNx2DF])
 
 ;; All SVE vector modes that have 64-bit elements.
 (define_mode_iterator SVE_D [VNx2DI VNx2DF])
 
-;; All SVE integer vector modes that have 32-bit or 64-bit elements.
-(define_mode_iterator SVE_SDI [VNx4SI VNx2DI])
-
 ;; All SVE integer vector modes.
 (define_mode_iterator SVE_I [VNx16QI VNx8HI VNx4SI VNx2DI])
 
 (define_mode_attr sizem1 [(QI "#7") (HI "#15") (SI "#31") (DI "#63")
                          (HF "#15") (SF "#31") (DF "#63")])
 
+;; The number of bits in a vector element, or controlled by a predicate
+;; element.
+(define_mode_attr elem_bits [(VNx8HI "16") (VNx4SI "32") (VNx2DI "64")
+                            (VNx8HF "16") (VNx4SF "32") (VNx2DF "64")])
+
 ;; Attribute to describe constants acceptable in logical operations
 (define_mode_attr lconst [(SI "K") (DI "L")])
 
                                        UNSPEC_COND_FRINTZ
                                        UNSPEC_COND_FSQRT])
 
+(define_int_iterator SVE_COND_FCVT [UNSPEC_COND_FCVT])
 (define_int_iterator SVE_COND_FCVTI [UNSPEC_COND_FCVTZS UNSPEC_COND_FCVTZU])
 (define_int_iterator SVE_COND_ICVTF [UNSPEC_COND_SCVTF UNSPEC_COND_UCVTF])