]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
More .DEFERRED_INIT expansion rework
authorRichard Biener <rguenther@suse.de>
Tue, 5 Oct 2021 07:28:20 +0000 (09:28 +0200)
committerRichard Biener <rguenther@suse.de>
Tue, 5 Oct 2021 08:36:11 +0000 (10:36 +0200)
This avoids looking at the type size and instead uses the size
as passed to .DEFERRED_INIT to determine the size of the non-MEM
to be initialized.  It also arranges for possibly poly-int
inits to always use zero-initialization rather than not initializing
and when we need to pun puns the LHS instead of the constant value.

That correctly initializes the variable-size typed array in the
testcase for PR102285 and the SVE vector in PR102587 where for
the testcase I needed to add a SVE capable -march as to not
ICE later.

2021-10-05  Richard Biener  <rguenther@suse.de>

PR middle-end/102587
PR middle-end/102285
* internal-fn.c (expand_DEFERRED_INIT): Fall back to
zero-initialization as last resort, use the constant
size as given by the DEFERRED_INIT argument to build
the initializer.

* gcc.target/aarch64/sve/pr102587-1.c: Add -march=armv8.3-a+sve.
* gcc.target/aarch64/sve/pr102587-2.c: Likewise.

gcc/internal-fn.c
gcc/testsuite/gcc.target/aarch64/sve/pr102587-1.c
gcc/testsuite/gcc.target/aarch64/sve/pr102587-2.c

index 110145218b94ba00e8bf2641eb0159568c5ba0ad..78db25bbac4287cda3e5cee3344d0e1ff10d6e85 100644 (file)
@@ -3038,19 +3038,18 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
       /* Expand this memset call.  */
       expand_builtin_memset (m_call, NULL_RTX, TYPE_MODE (var_type));
     }
-  /* ???  Deal with poly-int sized registers.  */
-  else if (tree_fits_uhwi_p (TYPE_SIZE_UNIT (var_type)))
+  else
     {
-      /* If this variable is in a register, use expand_assignment might
-        generate better code.  */
-      tree init = build_zero_cst (var_type);
-      unsigned HOST_WIDE_INT total_bytes
-       = tree_to_uhwi (TYPE_SIZE_UNIT (var_type));
-
-      if (init_type == AUTO_INIT_PATTERN)
+      /* If this variable is in a register use expand_assignment.  */
+      tree init;
+      if (tree_fits_uhwi_p (var_size)
+         && (init_type == AUTO_INIT_PATTERN
+             || !is_gimple_reg_type (var_type)))
        {
+         unsigned HOST_WIDE_INT total_bytes = tree_to_uhwi (var_size);
          unsigned char *buf = (unsigned char *) xmalloc (total_bytes);
-         memset (buf, INIT_PATTERN_VALUE, total_bytes);
+         memset (buf, (init_type == AUTO_INIT_PATTERN
+                       ? INIT_PATTERN_VALUE : 0), total_bytes);
          if (can_native_interpret_type_p (var_type))
            init = native_interpret_expr (var_type, buf, total_bytes);
          else
@@ -3058,10 +3057,14 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
              tree itype = build_nonstandard_integer_type
                             (total_bytes * BITS_PER_UNIT, 1);
              wide_int w = wi::from_buffer (buf, total_bytes);
-             init = build1 (VIEW_CONVERT_EXPR, var_type,
-                            wide_int_to_tree (itype, w));
+             init = wide_int_to_tree (itype, w);
+             /* Pun the LHS to make sure its type has constant size.  */
+             lhs = build1 (VIEW_CONVERT_EXPR, itype, lhs);
            }
        }
+      else
+       /* Use zero-init also for variable-length sizes.  */
+       init = build_zero_cst (var_type);
 
       expand_assignment (lhs, init, false);
     }
index 2b9a68b0b59c3b15b6576288e12c7bf3ffc14f6f..af2ae59e5d482dcd689e3058927758dadf120559 100644 (file)
@@ -1,4 +1,4 @@
 /* { dg-do compile } */
-/* { dg-options "-ftrivial-auto-var-init=zero" } */
+/* { dg-options "-march=armv8.3-a+sve -ftrivial-auto-var-init=zero" } */
 
 void foo() { __SVFloat64_t f64; }
index 4cdb9056002905daf9b25e69ca79a1467aa50d99..8c9d9908bac696a442ea3b07e6ead6e36a047507 100644 (file)
@@ -1,4 +1,4 @@
 /* { dg-do compile } */
-/* { dg-options "-ftrivial-auto-var-init=pattern" } */
+/* { dg-options "-march=armv8.3-a+sve -ftrivial-auto-var-init=pattern" } */
 
 void foo() { __SVFloat64_t f64; }