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? Thanks, Martin 2019-02-15 Martin Jambor <mjam...@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); -- 2.20.1