aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2019-12-03 18:06:40 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2019-12-03 18:06:40 +0000
commitbd8a2482569900a114d631f9c38353d3a96a1d85 (patch)
tree0f1dac36e3df9cab6b3e4a4ff088a07ec4b2e2fa
parent2c98350fcb269a653b11f73ca0175679aa29977a (diff)
downloadgcc-bd8a2482569900a114d631f9c38353d3a96a1d85.zip
gcc-bd8a2482569900a114d631f9c38353d3a96a1d85.tar.gz
gcc-bd8a2482569900a114d631f9c38353d3a96a1d85.tar.bz2
Don't install unnecessary ARRAY_REF element sizes
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
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/gimplify.c37
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/struct_1.c10
4 files changed, 41 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1b24617..430aedb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
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
with POLY_INT_CST size is made to a fixed-size object, force the
object to live in memory.
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index da65669..9073680 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 028755b..39e8ace 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
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.
2019-12-03 Marek Polacek <polacek@redhat.com>
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
index 0000000..1ebc229
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/struct_1.c
@@ -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 };
+}