[PR 89209] Avoid segfault in a peculiar corner case in SRA

Richard Biener rguenther@suse.de
Sat Feb 16 11:14:00 GMT 2019


On February 16, 2019 11:56:13 AM GMT+01:00, Martin Jambor <mjambor@suse.cz> wrote:
>Hi,
>
>PR 89209 takes place because SRA on trunk encounters an assignment into
>an SSA_NAME from a V_C_E of a structure load which however cannot
>contain any useful data because (it is not addressable and) there is no
>store to that portion of the aggregate in the entire function.  In such
>circumstances, SRA conjures up a default-definition SSA name and
>replaces the RHS of the load with it so that an uninitialized warning
>is
>generated.  Unfortunately, the code digging through V_C_Es badly
>interacts with this and what happens is that first we create an
>aggregate type SSA name which the code avoiding creation of additional
>V_C_Es then tries to store "into" the SSA name on the LHS, which of
>course fails.  BTW, I was surprised no verifier caught the aggregate
>SSA
>name if I just avoided the segfaulting path.
>
>Fixed with the patch below which gives the code creating the
>default-definition SSA_NAME an alternative type which is used if the
>access type is not a gimple_register_typoe.  I have also added an
>additional test that lacc is not NULL to sra_modify_assign because the
>code path could trigger if the created default-def SSA_NAME happens to
>be loaded as two different types.  However, I have not managed to
>quickly create a testcase that would lead to it..
>
>Bootstrapped and tested on x86_64-linux.  OK for trunk?

OK. 

Richard. 

>Thanks,
>
>Martin
>
>
>2019-02-15  Martin Jambor  <mjambor@suse.cz>
>
>	PR tree-optimization/89209
>	* tree-sra.c (create_access_replacement): New optional parameter
>	reg_tree.  Use it as a type if non-NULL and access type is not of
>	a register type.
>	(get_repl_default_def_ssa_name): New parameter REG_TYPE, pass it
>	to create_access_replacement.
>	(sra_modify_assign): Pass LHS type to get_repl_default_def_ssa_name.
>	Check lacc is non-NULL before attempting to re-create it on the RHS.
>
>	testsuite/
>	* gcc.dg/tree-ssa/pr89209.c: New test.
>---
> gcc/testsuite/gcc.dg/tree-ssa/pr89209.c | 16 ++++++++++++
> gcc/tree-sra.c                          | 34 +++++++++++++++----------
> 2 files changed, 37 insertions(+), 13 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr89209.c
>
>diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89209.c
>b/gcc/testsuite/gcc.dg/tree-ssa/pr89209.c
>new file mode 100644
>index 00000000000..f01bda9ae5c
>--- /dev/null
>+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89209.c
>@@ -0,0 +1,16 @@
>+/* { dg-do compile } */
>+/* { dg-options "-O2" } */
>+
>+struct S {
>+  short a, b;
>+};
>+struct T {
>+  int c;
>+  struct S s;
>+};
>+int f ()
>+{
>+  struct T t;
>+  t.c = t.s.a || t.s.b;
>+  return t.c;
>+}
>diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
>index e4851daaa3f..eeef31ba496 100644
>--- a/gcc/tree-sra.c
>+++ b/gcc/tree-sra.c
>@@ -2195,13 +2195,20 @@ sort_and_splice_var_accesses (tree var)
> 
>/* Create a variable for the given ACCESS which determines the type,
>name and a
>few other properties.  Return the variable declaration and store it
>also to
>-   ACCESS->replacement.  */
>+   ACCESS->replacement.  REG_TREE is used when creating a declaration
>to base a
>+   default-definition SSA name on on in order to facilitate an
>uninitialized
>+   warning.  It is used instead of the actual ACCESS type if that is
>not of a
>+   gimple register type.  */
> 
> static tree
>-create_access_replacement (struct access *access)
>+create_access_replacement (struct access *access, tree reg_type =
>NULL_TREE)
> {
>   tree repl;
> 
>+  tree type = access->type;
>+  if (reg_type && !is_gimple_reg_type (type))
>+    type = reg_type;
>+
>   if (access->grp_to_be_debug_replaced)
>     {
>       repl = create_tmp_var_raw (access->type);
>@@ -2210,17 +2217,16 @@ create_access_replacement (struct access
>*access)
>   else
>     /* Drop any special alignment on the type if it's not on the main
>        variant.  This avoids issues with weirdo ABIs like AAPCS.  */
>-    repl = create_tmp_var (build_qualified_type
>-			     (TYPE_MAIN_VARIANT (access->type),
>-			      TYPE_QUALS (access->type)), "SR");
>-  if (TREE_CODE (access->type) == COMPLEX_TYPE
>-      || TREE_CODE (access->type) == VECTOR_TYPE)
>+    repl = create_tmp_var (build_qualified_type (TYPE_MAIN_VARIANT
>(type),
>+						 TYPE_QUALS (type)), "SR");
>+  if (TREE_CODE (type) == COMPLEX_TYPE
>+      || TREE_CODE (type) == VECTOR_TYPE)
>     {
>       if (!access->grp_partial_lhs)
> 	DECL_GIMPLE_REG_P (repl) = 1;
>     }
>   else if (access->grp_partial_lhs
>-	   && is_gimple_reg_type (access->type))
>+	   && is_gimple_reg_type (type))
>     TREE_ADDRESSABLE (repl) = 1;
> 
>   DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
>@@ -3450,15 +3456,16 @@ sra_modify_constructor_assign (gimple *stmt,
>gimple_stmt_iterator *gsi)
> 
>/* Create and return a new suitable default definition SSA_NAME for
>RACC which
>is an access describing an uninitialized part of an aggregate that is
>being
>-   loaded.  */
>+   loaded.  REG_TREE is used instead of the actual RACC type if that
>is not of
>+   a gimple register type.  */
> 
> static tree
>-get_repl_default_def_ssa_name (struct access *racc)
>+get_repl_default_def_ssa_name (struct access *racc, tree reg_type)
> {
>   gcc_checking_assert (!racc->grp_to_be_replaced
> 		       && !racc->grp_to_be_debug_replaced);
>   if (!racc->replacement_decl)
>-    racc->replacement_decl = create_access_replacement (racc);
>+    racc->replacement_decl = create_access_replacement (racc,
>reg_type);
>   return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
> }
> 
>@@ -3530,7 +3537,7 @@ sra_modify_assign (gimple *stmt,
>gimple_stmt_iterator *gsi)
> 	   && TREE_CODE (lhs) == SSA_NAME
> 	   && !access_has_replacements_p (racc))
>     {
>-      rhs = get_repl_default_def_ssa_name (racc);
>+      rhs = get_repl_default_def_ssa_name (racc, TREE_TYPE (lhs));
>       modify_this_stmt = true;
>       sra_stats.exprs++;
>     }
>@@ -3548,7 +3555,8 @@ sra_modify_assign (gimple *stmt,
>gimple_stmt_iterator *gsi)
> 	      lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
> 	      gimple_assign_set_lhs (stmt, lhs);
> 	    }
>-	  else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
>+	  else if (lacc
>+		   && AGGREGATE_TYPE_P (TREE_TYPE (rhs))
> 		   && !contains_vce_or_bfcref_p (rhs))
> 	    rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
> 



More information about the Gcc-patches mailing list