From 5da301cbd81c41b2e9629f55dd1b1889f7dae75e Mon Sep 17 00:00:00 2001
From: Richard Sandiford <richard.sandiford@arm.com>
Date: Mon, 20 Apr 2020 15:43:32 +0100
Subject: [PATCH] aarch64: Fix vector builds used by SVE vec_init [PR94668]

This testcase triggered an ICE in rtx_vector_builder::step because
we were trying to use a stepped representation for floating-point
constants.  The underlying problem was that the arguments to
rtx_vector_builder were the wrong way around, meaning that some
variations were likely to be incorrectly encoded for integers
(but probably as a silent failure).

Also, aarch64_sve_expand_vector_init_handle_trailing_constants
tries to extend the trailing constant elements to a full vector
by following the "natural" pattern of the original vector, which
should generally lead to nicer constants.  However, for the testcase,
we'd then end up picking a variable for some elements.  Fixed by
stubbing out all variable elements with zeros.

That fix involved testing valid_for_const_vector_p.  For consistency,
the patch uses the same test when finding trailing constants, instead
of the previous aarch64_legitimate_constant_p.

2020-04-20  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	PR target/94668
	* config/aarch64/aarch64.c (aarch64_sve_expand_vector_init): Fix
	order of arguments to rtx_vector_builder.
	(aarch64_sve_expand_vector_init_handle_trailing_constants): Likewise.
	When extending the trailing constants to a full vector, replace any
	variables with zeros.

gcc/testsuite/
	PR target/94668
	* gcc.target/aarch64/sve/pr94668.c: New test.
---
 gcc/ChangeLog                                 |  9 +++++++
 gcc/config/aarch64/aarch64.c                  | 26 ++++++++++++++-----
 gcc/testsuite/ChangeLog                       |  5 ++++
 .../gcc.target/aarch64/sve/pr94668.c          |  8 ++++++
 4 files changed, 41 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pr94668.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index cc6c6389b902..4c9de79c1fd5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2020-04-20  Richard Sandiford  <richard.sandiford@arm.com>
+
+	PR target/94668
+	* config/aarch64/aarch64.c (aarch64_sve_expand_vector_init): Fix
+	order of arguments to rtx_vector_builder.
+	(aarch64_sve_expand_vector_init_handle_trailing_constants): Likewise.
+	When extending the trailing constants to a full vector, replace any
+	variables with zeros.
+
 2020-04-20  Jan Hubicka  <hubicka@ucw.cz>
 
 	PR ipa/94582
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 24c055df0dcb..ee6a2de77a59 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -18382,15 +18382,27 @@ aarch64_sve_expand_vector_init_handle_trailing_constants
   int n_trailing_constants = 0;
 
   for (int i = nelts_reqd - 1;
-       i >= 0 && aarch64_legitimate_constant_p (elem_mode, builder.elt (i));
+       i >= 0 && valid_for_const_vector_p (elem_mode, builder.elt (i));
        i--)
     n_trailing_constants++;
 
   if (n_trailing_constants >= nelts_reqd / 2)
     {
-      rtx_vector_builder v (mode, 1, nelts);
+      /* Try to use the natural pattern of BUILDER to extend the trailing
+	 constant elements to a full vector.  Replace any variables in the
+	 extra elements with zeros.
+
+	 ??? It would be better if the builders supported "don't care"
+	     elements, with the builder filling in whichever elements
+	     give the most compact encoding.  */
+      rtx_vector_builder v (mode, nelts, 1);
       for (int i = 0; i < nelts; i++)
-	v.quick_push (builder.elt (i + nelts_reqd - n_trailing_constants));
+	{
+	  rtx x = builder.elt (i + nelts_reqd - n_trailing_constants);
+	  if (!valid_for_const_vector_p (elem_mode, x))
+	    x = const0_rtx;
+	  v.quick_push (x);
+	}
       rtx const_vec = v.build ();
       emit_move_insn (target, const_vec);
 
@@ -18508,7 +18520,7 @@ aarch64_sve_expand_vector_init (rtx target, const rtx_vector_builder &builder,
 
   /* Case 2: Vector contains leading constants.  */
 
-  rtx_vector_builder rev_builder (mode, 1, nelts_reqd);
+  rtx_vector_builder rev_builder (mode, nelts_reqd, 1);
   for (int i = 0; i < nelts_reqd; i++)
     rev_builder.quick_push (builder.elt (nelts_reqd - i - 1));
   rev_builder.finalize ();
@@ -18541,8 +18553,8 @@ aarch64_sve_expand_vector_init (rtx target, const rtx_vector_builder &builder,
   if (nelts_reqd <= 4)
     return false;
 
-  rtx_vector_builder v_even (mode, 1, nelts);
-  rtx_vector_builder v_odd (mode, 1, nelts);
+  rtx_vector_builder v_even (mode, nelts, 1);
+  rtx_vector_builder v_odd (mode, nelts, 1);
 
   for (int i = 0; i < nelts * 2; i += 2)
     {
@@ -18586,7 +18598,7 @@ aarch64_sve_expand_vector_init (rtx target, rtx vals)
   machine_mode mode = GET_MODE (target);
   int nelts = XVECLEN (vals, 0);
 
-  rtx_vector_builder v (mode, 1, nelts);
+  rtx_vector_builder v (mode, nelts, 1);
   for (int i = 0; i < nelts; i++)
     v.quick_push (XVECEXP (vals, 0, i));
   v.finalize ();
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9ba21a0b7f83..9bf3581b7700 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2020-04-20  Richard Sandiford  <richard.sandiford@arm.com>
+
+	PR target/94668
+	* gcc.target/aarch64/sve/pr94668.c: New test.
+
 2020-04-20  Jan Hubicka  <hubicka@ucw.cz>
 
 	PR ipa/94582
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr94668.c b/gcc/testsuite/gcc.target/aarch64/sve/pr94668.c
new file mode 100644
index 000000000000..9ff01e825c94
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr94668.c
@@ -0,0 +1,8 @@
+/* { dg-options "-O -msve-vector-bits=512" } */
+
+typedef float v16sf __attribute__ ((vector_size(64)));
+v16sf
+foo (float a)
+{
+  return (v16sf) { 0, 0, 0, a, 0, 0, 0, 0, 0, a, 0, 0, 0, 0, 0, 0 };
+}
-- 
GitLab