[committed,AArch64] Rearrange SVE conversion patterns
diff mbox series

Message ID mptzhkcnnq2.fsf@arm.com
State New
Headers show
Series
  • [committed,AArch64] Rearrange SVE conversion patterns
Related show

Commit Message

Richard Sandiford Aug. 14, 2019, 8:41 a.m. UTC
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.

Tested on aarch64-linux-gnu (with and without SVE) and aarch64_be-elf.
Applied as r274424.

Richard


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.

Patch
diff mbox series

Index: gcc/config/aarch64/iterators.md
===================================================================
--- gcc/config/aarch64/iterators.md	2019-08-14 09:34:05.509786440 +0100
+++ gcc/config/aarch64/iterators.md	2019-08-14 09:38:47.027705882 +0100
@@ -278,6 +278,10 @@  (define_mode_iterator VMUL_CHANGE_NLANES
 (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
@@ -292,15 +296,21 @@  (define_mode_iterator SVE_BH [VNx16QI VN
 ;; 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])
 
@@ -313,9 +323,6 @@  (define_mode_iterator SVE_S [VNx4SI VNx4
 ;; 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])
 
@@ -629,6 +636,11 @@  (define_mode_attr sizen [(QI "8") (HI "1
 (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")])
 
@@ -1647,6 +1659,7 @@  (define_int_iterator SVE_COND_FP_UNARY [
 					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])
 
Index: gcc/config/aarch64/aarch64-sve.md
===================================================================
--- gcc/config/aarch64/aarch64-sve.md	2019-08-14 09:34:05.505786467 +0100
+++ gcc/config/aarch64/aarch64-sve.md	2019-08-14 09:38:47.027705882 +0100
@@ -3656,40 +3656,28 @@  (define_expand "<optab><mode><v_int_equi
   }
 )
 
-;; 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")]
+	   (match_operand:SVE_F 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")]
-	  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>"
 )
 
 ;; -------------------------------------------------------------------------
@@ -3751,41 +3739,29 @@  (define_expand "<optab><v_int_equiv><mod
   }
 )
 
-;; 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>"
+  "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 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>"
-)
-
-;; 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>"
 )
 
 ;; -------------------------------------------------------------------------
@@ -3821,7 +3797,7 @@  (define_expand "vec_unpack<su_optab>_flo
 	       (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;
   }
@@ -3859,17 +3835,16 @@  (define_expand "vec_pack_trunc_<Vwide>"
   }
 )
 
-;; 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>"
 )
 
 ;; -------------------------------------------------------------------------
@@ -3899,23 +3874,22 @@  (define_expand "vec_unpacks_<perm_hilo>_
 		(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>"
 )
 
 ;; -------------------------------------------------------------------------