Don't install unnecessary ARRAY_REF element sizes
authorRichard Sandiford <richard.sandiford@arm.com>
Tue, 3 Dec 2019 18:06:40 +0000 (18:06 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 3 Dec 2019 18:06:40 +0000 (18:06 +0000)
Even EXACT_DIV_EXPR doesn't distribute across addition for wrapping
types, so in general we can't fold EXACT_DIV_EXPRs of POLY_INT_CSTs
at compile time.  This was causing an ICE when trying to gimplify the
element size field in an ARRAY_REF.

If the result of that EXACT_DIV_EXPR is an invariant, we don't bother
recording it in the ARRAY_REF and simply read the element size from the
element type.  This avoids the overhead of doing:

      /* ??? tree_ssa_useless_type_conversion will eliminate casts to
 sizetype from another type of the same width and signedness.  */
      if (TREE_TYPE (aligned_size) != sizetype)
aligned_size = fold_convert_loc (loc, sizetype, aligned_size);
      return size_binop_loc (loc, MULT_EXPR, aligned_size,
     size_int (TYPE_ALIGN_UNIT (elmt_type)));

each time array_ref_element_size is called.

So rather than read array_ref_element_size, do some arithmetic on it,
and only then check whether the result is an invariant, we might as
well check whether the element size is an invariant to start with.
We're then directly testing whether array_ref_element_size gives
a reusable value.

For consistency, the patch makes the same change for the offset field
in a COMPONENT_REF, although I don't think that can trigger yet.

2019-12-03  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
* gimplify.c (gimplify_compound_lval): Don't gimplify and install
an array element size if array_element_size is already an invariant.
Similarly don't gimplify and install a field offset if
component_ref_field_offset is already an invariant.

gcc/testsuite/
* gcc.target/aarch64/sve/acle/general-c/struct_1.c: New test.

From-SVN: r278942

gcc/ChangeLog
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/struct_1.c [new file with mode: 0644]

index 1b246171d46825af89a8e22e0cdbc3e8202bf716..430aedbcb0527b1d3446774011f97dd6d00d570d 100644 (file)
@@ -1,3 +1,10 @@
+2019-12-03  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * gimplify.c (gimplify_compound_lval): Don't gimplify and install
+       an array element size if array_element_size is already an invariant.
+       Similarly don't gimplify and install a field offset if
+       component_ref_field_offset is already an invariant.
+
 2019-12-03  Richard Sandiford  <richard.sandiford@arm.com>
 
        * cfgexpand.c (discover_nonconstant_array_refs_r): If an access
index da6566903e07b57ddba12384542b6a2c720caa74..9073680cb3179f196979a0ea10b8db0188462eb8 100644 (file)
@@ -2987,17 +2987,18 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
          if (TREE_OPERAND (t, 3) == NULL_TREE)
            {
-             tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
-             tree elmt_size = unshare_expr (array_ref_element_size (t));
-             tree factor = size_int (TYPE_ALIGN_UNIT (elmt_type));
-
-             /* Divide the element size by the alignment of the element
-                type (above).  */
-             elmt_size
-               = size_binop_loc (loc, EXACT_DIV_EXPR, elmt_size, factor);
-
+             tree elmt_size = array_ref_element_size (t);
              if (!is_gimple_min_invariant (elmt_size))
                {
+                 elmt_size = unshare_expr (elmt_size);
+                 tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
+                 tree factor = size_int (TYPE_ALIGN_UNIT (elmt_type));
+
+                 /* Divide the element size by the alignment of the element
+                    type (above).  */
+                 elmt_size = size_binop_loc (loc, EXACT_DIV_EXPR,
+                                             elmt_size, factor);
+
                  TREE_OPERAND (t, 3) = elmt_size;
                  tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p,
                                        post_p, is_gimple_reg,
@@ -3017,16 +3018,18 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          /* Set the field offset into T and gimplify it.  */
          if (TREE_OPERAND (t, 2) == NULL_TREE)
            {
-             tree offset = unshare_expr (component_ref_field_offset (t));
-             tree field = TREE_OPERAND (t, 1);
-             tree factor
-               = size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT);
-
-             /* Divide the offset by its alignment.  */
-             offset = size_binop_loc (loc, EXACT_DIV_EXPR, offset, factor);
-
+             tree offset = component_ref_field_offset (t);
              if (!is_gimple_min_invariant (offset))
                {
+                 offset = unshare_expr (offset);
+                 tree field = TREE_OPERAND (t, 1);
+                 tree factor
+                   = size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT);
+
+                 /* Divide the offset by its alignment.  */
+                 offset = size_binop_loc (loc, EXACT_DIV_EXPR,
+                                          offset, factor);
+
                  TREE_OPERAND (t, 2) = offset;
                  tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
                                        post_p, is_gimple_reg,
index 028755bb51a864efad8dbb5ea6cdf1f0d9301f52..39e8ace59f7981f19ac3e9fdae3a835b13452cb3 100644 (file)
@@ -1,3 +1,7 @@
+2019-12-03  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * gcc.target/aarch64/sve/acle/general-c/struct_1.c: New test.
+
 2019-12-03  Richard Sandiford  <richard.sandiford@arm.com>
 
        * gcc.target/aarch64/sve/acle/general/deref_1.c: New test.
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/struct_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/struct_1.c
new file mode 100644 (file)
index 0000000..1ebc229
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f (svint8_t a, svint8_t b)
+{
+  /* Not supported, but mustn't ICE.  */
+  (svint8x2_t) { a, b };
+}