From: jamborm Date: Thu, 9 Sep 2010 23:38:23 +0000 (+0000) Subject: 2010-09-10 Martin Jambor X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c52cb4395f97f94cb92b62840af21ce7b158118d;p=thirdparty%2Fgcc.git 2010-09-10 Martin Jambor PR tree-optimization/44972 * tree-sra.c: Include toplev.h. (build_ref_for_offset): Entirely reimplemented. (build_ref_for_model): New function. (build_user_friendly_ref_for_offset): New function. (analyze_access_subtree): Removed build_ref_for_offset check. (propagate_subaccesses_across_link): Likewise. (create_artificial_child_access): Use build_user_friendly_ref_for_offset. (propagate_subaccesses_across_link): Likewise. (ref_expr_for_all_replacements_p): Removed. (generate_subtree_copies): Updated comment. Use build_ref_for_model. (sra_modify_expr): Use build_ref_for_model. (load_assign_lhs_subreplacements): Likewise. (sra_modify_assign): Removed ref_expr_for_all_replacements_p checks, checks for return values of build_ref_for_offset. * ipa-cp.c (ipcp_lattice_from_jfunc): No need to check return value of build_ref_for_offset. * ipa-prop.h: Include gimple.h * ipa-prop.c (ipa_compute_jump_functions): Update to look for MEM_REFs. (ipa_analyze_indirect_call_uses): Update comment. * Makefile.in (tree-sra.o): Add $(GIMPLE_H) to dependencies. (IPA_PROP_H): Likewise. * testsuite/gcc.dg/ipa/ipa-sra-1.c: Adjust scanning expressions. * testsuite/gcc.dg/tree-ssa/pr45144.c: Likewise. * testsuite/gcc.dg/tree-ssa/forwprop-5.c: Likewise and scan optimzed dump instead. * testsuite/g++.dg/torture/pr44972.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@164136 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1128ae9f302f..22c53c069f0d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2010-09-10 Martin Jambor + + PR tree-optimization/44972 + * tree-sra.c: Include toplev.h. + (build_ref_for_offset): Entirely reimplemented. + (build_ref_for_model): New function. + (build_user_friendly_ref_for_offset): New function. + (analyze_access_subtree): Removed build_ref_for_offset check. + (propagate_subaccesses_across_link): Likewise. + (create_artificial_child_access): Use + build_user_friendly_ref_for_offset. + (propagate_subaccesses_across_link): Likewise. + (ref_expr_for_all_replacements_p): Removed. + (generate_subtree_copies): Updated comment. Use build_ref_for_model. + (sra_modify_expr): Use build_ref_for_model. + (load_assign_lhs_subreplacements): Likewise. + (sra_modify_assign): Removed ref_expr_for_all_replacements_p checks, + checks for return values of build_ref_for_offset. + * ipa-cp.c (ipcp_lattice_from_jfunc): No need to check return value of + build_ref_for_offset. + * ipa-prop.h: Include gimple.h + * ipa-prop.c (ipa_compute_jump_functions): Update to look for MEM_REFs. + (ipa_analyze_indirect_call_uses): Update comment. + * Makefile.in (tree-sra.o): Add $(GIMPLE_H) to dependencies. + (IPA_PROP_H): Likewise. + 2010-09-10 Martin Jambor PR tree-optimization/44972 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 736963c5fa1d..1bf35f1e9f56 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -968,7 +968,7 @@ EBITMAP_H = ebitmap.h sbitmap.h LTO_STREAMER_H = lto-streamer.h $(LINKER_PLUGIN_API_H) $(TARGET_H) \ $(CGRAPH_H) $(VEC_H) vecprim.h $(TREE_H) $(GIMPLE_H) TREE_VECTORIZER_H = tree-vectorizer.h $(TREE_DATA_REF_H) -IPA_PROP_H = ipa-prop.h $(TREE_H) $(VEC_H) $(CGRAPH_H) +IPA_PROP_H = ipa-prop.h $(TREE_H) $(VEC_H) $(CGRAPH_H) $(GIMPLE_H) GSTAB_H = gstab.h stab.def BITMAP_H = bitmap.h $(HASHTAB_H) statistics.h GCC_PLUGIN_H = gcc-plugin.h highlev-plugin-common.h $(CONFIG_H) $(SYSTEM_H) \ @@ -3143,10 +3143,10 @@ tree-ssa-ccp.o : tree-ssa-ccp.c $(TREE_FLOW_H) $(CONFIG_H) \ tree-ssa-propagate.h value-prof.h $(FLAGS_H) $(TARGET_H) $(TOPLEV_H) $(DIAGNOSTIC_CORE_H) \ $(DBGCNT_H) tree-pretty-print.h gimple-pretty-print.h tree-sra.o : tree-sra.c $(CONFIG_H) $(SYSTEM_H) coretypes.h alloc-pool.h \ - $(TM_H) $(TREE_H) $(GIMPLE_H) $(CGRAPH_H) $(TREE_FLOW_H) $(IPA_PROP_H) \ - $(DIAGNOSTIC_H) statistics.h $(TREE_DUMP_H) $(TIMEVAR_H) $(PARAMS_H) \ - $(TARGET_H) $(FLAGS_H) $(EXPR_H) tree-pretty-print.h $(DBGCNT_H) \ - $(TREE_INLINE_H) gimple-pretty-print.h + $(TM_H) $(TOPLEV_H) $(TREE_H) $(GIMPLE_H) $(CGRAPH_H) $(TREE_FLOW_H) \ + $(IPA_PROP_H) $(DIAGNOSTIC_H) statistics.h $(TREE_DUMP_H) $(TIMEVAR_H) \ + $(PARAMS_H) $(TARGET_H) $(FLAGS_H) $(EXPR_H) tree-pretty-print.h \ + $(DBGCNT_H) $(TREE_INLINE_H) gimple-pretty-print.h tree-switch-conversion.o : tree-switch-conversion.c $(CONFIG_H) $(SYSTEM_H) \ $(TREE_H) $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) $(TREE_INLINE_H) \ $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(GIMPLE_H) \ diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index e94fdca9d3b9..0680e3254d68 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -327,7 +327,6 @@ ipcp_lattice_from_jfunc (struct ipa_node_params *info, struct ipcp_lattice *lat, { struct ipcp_lattice *caller_lat; tree t; - bool ok; caller_lat = ipcp_get_lattice (info, jfunc->value.ancestor.formal_id); lat->type = caller_lat->type; @@ -340,16 +339,9 @@ ipcp_lattice_from_jfunc (struct ipa_node_params *info, struct ipcp_lattice *lat, return; } t = TREE_OPERAND (caller_lat->constant, 0); - ok = build_ref_for_offset (&t, TREE_TYPE (t), - jfunc->value.ancestor.offset, - jfunc->value.ancestor.type, false); - if (!ok) - { - lat->type = IPA_BOTTOM; - lat->constant = NULL_TREE; - } - else - lat->constant = build_fold_addr_expr (t); + t = build_ref_for_offset (t, jfunc->value.ancestor.offset, + jfunc->value.ancestor.type, NULL, false); + lat->constant = build_fold_addr_expr (t); } else lat->type = IPA_BOTTOM; diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 0ad732456e9f..ec45d7c52710 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -916,23 +916,27 @@ ipa_compute_jump_functions (struct cgraph_node *node, static tree ipa_get_member_ptr_load_param (tree rhs, bool use_delta) { - tree rec, fld; + tree rec, ref_offset, fld_offset; tree ptr_field; tree delta_field; - if (TREE_CODE (rhs) != COMPONENT_REF) + if (TREE_CODE (rhs) != MEM_REF) return NULL_TREE; - rec = TREE_OPERAND (rhs, 0); + if (TREE_CODE (rec) != ADDR_EXPR) + return NULL_TREE; + rec = TREE_OPERAND (rec, 0); if (TREE_CODE (rec) != PARM_DECL || !type_like_member_ptr_p (TREE_TYPE (rec), &ptr_field, &delta_field)) return NULL_TREE; - fld = TREE_OPERAND (rhs, 1); - if (use_delta ? (fld == delta_field) : (fld == ptr_field)) - return rec; + ref_offset = TREE_OPERAND (rhs, 1); + if (use_delta) + fld_offset = byte_position (delta_field); else - return NULL_TREE; + fld_offset = byte_position (ptr_field); + + return tree_int_cst_equal (ref_offset, fld_offset) ? rec : NULL_TREE; } /* If STMT looks like a statement loading a value from a member pointer formal @@ -999,8 +1003,8 @@ ipa_note_param_call (struct cgraph_node *node, int param_index, gimple stmt, below, the call is on the last line: : - f$__delta_5 = f.__delta; - f$__pfn_24 = f.__pfn; + f$__delta_5 = MEM[(struct *)&f]; + f$__pfn_24 = MEM[(struct *)&f + 4B]; ... diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 8244a7f79e32..210a8638a40e 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "vec.h" #include "cgraph.h" +#include "gimple.h" /* The following definitions and interfaces are used by interprocedural analyses or parameters. */ @@ -511,6 +512,7 @@ void ipa_prop_read_jump_functions (void); void ipa_update_after_lto_read (void); /* From tree-sra.c: */ -bool build_ref_for_offset (tree *, tree, HOST_WIDE_INT, tree, bool); +tree build_ref_for_offset (tree, HOST_WIDE_INT, tree, gimple_stmt_iterator *, + bool); #endif /* IPA_PROP_H */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0478d9a4d854..e4c2c9aba02b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2010-09-10 Martin Jambor + + PR tree-optimization/44972 + * gcc.dg/ipa/ipa-sra-1.c: Adjust scanning expressions. + * gcc.dg/tree-ssa/pr45144.c: Likewise. + * gcc.dg/tree-ssa/forwprop-5.c: Likewise and scan optimzed dump + instead. + * g++.dg/torture/pr44972.C: New test. + 2010-09-10 Martin Jambor PR tree-optimization/44972 diff --git a/gcc/testsuite/g++.dg/torture/pr44972.C b/gcc/testsuite/g++.dg/torture/pr44972.C new file mode 100644 index 000000000000..81806076c58c --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr44972.C @@ -0,0 +1,142 @@ +/* { dg-do compile } */ + +#include +#include +#include + +namespace boost { + +template +class optional; + +class aligned_storage +{ + char data[ 1000 ]; + public: + void const* address() const { return &data[0]; } + void * address() { return &data[0]; } +} ; + + +template +class optional_base +{ + protected : + optional_base(){} + optional_base ( T const& val ) + { + construct(val); + } + + template + void assign ( optional const& rhs ) + { + if (!is_initialized()) + if ( rhs.is_initialized() ) + construct(T()); + } + + public : + + bool is_initialized() const { return m_initialized ; } + + protected : + + void construct ( T const& val ) + { + new (m_storage.address()) T(val) ; + } + + T const* get_ptr_impl() const + { return static_cast(m_storage.address()); } + + private : + + bool m_initialized ; + aligned_storage m_storage ; +} ; + + +template +class optional : public optional_base +{ + typedef optional_base base ; + + public : + + optional() : base() {} + optional ( T const& val ) : base(val) {} + optional& operator= ( optional const& rhs ) + { + this->assign( rhs ) ; + return *this ; + } + + T const& get() const ; + + T const* operator->() const { ((this->is_initialized()) ? static_cast (0) : __assert_fail ("this->is_initialized()", "pr44972.C", 78, __PRETTY_FUNCTION__)) ; return this->get_ptr_impl() ; } + +} ; + + +} // namespace boost + + +namespace std +{ + + template + struct array + { + typedef _Tp value_type; + typedef const value_type* const_iterator; + + value_type _M_instance[_Nm]; + + }; +} + + +class NT +{ + double _inf, _sup; +}; + + +template < typename T > inline +std::array +make_array(const T& b1) +{ + std::array a = { { b1 } }; + return a; +} + +class V +{ + typedef std::array Base; + Base base; + +public: + V() {} + V(const NT &x) + : base(make_array(x)) {} + +}; + +using boost::optional ; + +optional< std::pair< NT, NT > > + linsolve_pointC2() ; + +optional< V > construct_normal_offset_lines_isecC2 ( ) +{ + optional< std::pair > ip; + + ip = linsolve_pointC2(); + + V a(ip->first) ; + return a; +} + + + diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-1.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-1.c index d53338135d17..2c05347c641d 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipa-sra-1.c +++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-1.c @@ -36,6 +36,5 @@ main (int argc, char *argv[]) return 0; } -/* { dg-final { scan-tree-dump "About to replace expr cow.green with ISRA" "eipa_sra" } } */ -/* { dg-final { scan-tree-dump "About to replace expr cow.blue with ISRA" "eipa_sra" } } */ +/* { dg-final { scan-tree-dump-times "About to replace expr" 2 "eipa_sra" } } */ /* { dg-final { cleanup-tree-dump "eipa_sra" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-5.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-5.c index 1b68d5a35f02..f2ddab2535b9 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-5.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-5.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O1 -fdump-tree-esra -w" } */ +/* { dg-options "-O1 -fdump-tree-optimized -w" } */ #define vector __attribute__((vector_size(16) )) struct VecClass @@ -11,12 +11,9 @@ vector float foo( vector float v ) { vector float x = v; x = x + x; - struct VecClass y = *(struct VecClass*)&x; - return y.v; + struct VecClass disappear = *(struct VecClass*)&x; + return disappear.v; } -/* We should be able to remove the intermediate struct and directly - return x. As we do not fold VIEW_CONVERT_EXPR(x).v - that doesn't happen right now. */ -/* { dg-final { scan-tree-dump-times "VIEW_CONVERT_EXPR" 1 "esra"} } */ -/* { dg-final { cleanup-tree-dump "esra" } } */ +/* { dg-final { scan-tree-dump-times "disappear" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr45144.c b/gcc/testsuite/gcc.dg/tree-ssa/pr45144.c index 47530ced46e4..1e0dabdee8b1 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr45144.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr45144.c @@ -42,5 +42,5 @@ bar (unsigned orig, unsigned *new) *new = foo (&a); } -/* { dg-final { scan-tree-dump "x = a;" "optimized"} } */ +/* { dg-final { scan-tree-dump " = VIEW_CONVERT_EXPR\\(a\\);" "optimized"} } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 75e7682fcacf..83a515515dfc 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -76,6 +76,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "alloc-pool.h" #include "tm.h" +#include "toplev.h" #include "tree.h" #include "gimple.h" #include "cgraph.h" @@ -1320,15 +1321,106 @@ make_fancy_name (tree expr) return XOBFINISH (&name_obstack, char *); } -/* Helper function for build_ref_for_offset. +/* Construct a MEM_REF that would reference a part of aggregate BASE of type + EXP_TYPE at the given OFFSET. If BASE is something for which + get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used + to insert new statements either before or below the current one as specified + by INSERT_AFTER. This function is not capable of handling bitfields. */ - FIXME: Eventually this should be rewritten to either re-use the - original access expression unshared (which is good for alias - analysis) or to build a MEM_REF expression. */ +tree +build_ref_for_offset (tree base, HOST_WIDE_INT offset, + tree exp_type, gimple_stmt_iterator *gsi, + bool insert_after) +{ + tree prev_base = base; + tree off; + location_t loc = EXPR_LOCATION (base); + HOST_WIDE_INT base_offset; + + gcc_checking_assert (offset % BITS_PER_UNIT == 0); + + base = get_addr_base_and_unit_offset (base, &base_offset); + + /* get_addr_base_and_unit_offset returns NULL for references with a variable + offset such as array[var_index]. */ + if (!base) + { + gimple stmt; + tree tmp, addr; + + gcc_checking_assert (gsi); + tmp = create_tmp_reg (build_pointer_type (TREE_TYPE (prev_base)), NULL); + add_referenced_var (tmp); + tmp = make_ssa_name (tmp, NULL); + addr = build_fold_addr_expr (unshare_expr (prev_base)); + stmt = gimple_build_assign (tmp, addr); + SSA_NAME_DEF_STMT (tmp) = stmt; + if (insert_after) + gsi_insert_after (gsi, stmt, GSI_NEW_STMT); + else + gsi_insert_before (gsi, stmt, GSI_SAME_STMT); + update_stmt (stmt); + + off = build_int_cst (reference_alias_ptr_type (prev_base), + offset / BITS_PER_UNIT); + base = tmp; + } + else if (TREE_CODE (base) == MEM_REF) + { + off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)), + base_offset + offset / BITS_PER_UNIT); + off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off, 0); + base = unshare_expr (TREE_OPERAND (base, 0)); + } + else + { + off = build_int_cst (reference_alias_ptr_type (base), + base_offset + offset / BITS_PER_UNIT); + base = build_fold_addr_expr (unshare_expr (base)); + } + + return fold_build2_loc (loc, MEM_REF, exp_type, base, off); +} + +/* Construct a memory reference to a part of an aggregate BASE at the given + OFFSET and of the same type as MODEL. In case this is a reference to a + bit-field, the function will replicate the last component_ref of model's + expr to access it. GSI and INSERT_AFTER have the same meaning as in + build_ref_for_offset. */ + +static tree +build_ref_for_model (tree base, HOST_WIDE_INT offset, + struct access *model, gimple_stmt_iterator *gsi, + bool insert_after) +{ + if (TREE_CODE (model->expr) == COMPONENT_REF + && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1))) + { + /* This access represents a bit-field. */ + tree t, exp_type; + + offset -= int_bit_position (TREE_OPERAND (model->expr, 1)); + exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0)); + t = build_ref_for_offset (base, offset, exp_type, gsi, insert_after); + return fold_build3_loc (EXPR_LOCATION (base), COMPONENT_REF, + model->type, t, TREE_OPERAND (model->expr, 1), + NULL_TREE); + } + else + return build_ref_for_offset (base, offset, model->type, gsi, insert_after); +} + +/* Construct a memory reference consisting of component_refs and array_refs to + a part of an aggregate *RES (which is of type TYPE). The requested part + should have type EXP_TYPE at be the given OFFSET. This function might not + succeed, it returns true when it does and only then *RES points to something + meaningful. This function should be used only to build expressions that we + might need to present to user (e.g. in warnings). In all other situations, + build_ref_for_model or build_ref_for_offset should be used instead. */ static bool -build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset, - tree exp_type) +build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset, + tree exp_type) { while (1) { @@ -1367,19 +1459,13 @@ build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset, else if (pos > offset || (pos + size) <= offset) continue; - if (res) + expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld, + NULL_TREE); + expr_ptr = &expr; + if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld), + offset - pos, exp_type)) { - expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld, - NULL_TREE); - expr_ptr = &expr; - } - else - expr_ptr = NULL; - if (build_ref_for_offset_1 (expr_ptr, TREE_TYPE (fld), - offset - pos, exp_type)) - { - if (res) - *res = expr; + *res = expr; return true; } } @@ -1394,14 +1480,11 @@ build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset, minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type)); if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0) return false; - if (res) - { - index = build_int_cst (TYPE_DOMAIN (type), offset / el_size); - if (!integer_zerop (minidx)) - index = int_const_binop (PLUS_EXPR, index, minidx, 0); - *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index, - NULL_TREE, NULL_TREE); - } + index = build_int_cst (TYPE_DOMAIN (type), offset / el_size); + if (!integer_zerop (minidx)) + index = int_const_binop (PLUS_EXPR, index, minidx, 0); + *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index, + NULL_TREE, NULL_TREE); offset = offset % el_size; type = TREE_TYPE (type); break; @@ -1418,31 +1501,6 @@ build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset, } } -/* Construct an expression that would reference a part of aggregate *EXPR of - type TYPE at the given OFFSET of the type EXP_TYPE. If EXPR is NULL, the - function only determines whether it can build such a reference without - actually doing it, otherwise, the tree it points to is unshared first and - then used as a base for furhter sub-references. */ - -bool -build_ref_for_offset (tree *expr, tree type, HOST_WIDE_INT offset, - tree exp_type, bool allow_ptr) -{ - location_t loc = expr ? EXPR_LOCATION (*expr) : UNKNOWN_LOCATION; - - if (expr) - *expr = unshare_expr (*expr); - - if (allow_ptr && POINTER_TYPE_P (type)) - { - type = TREE_TYPE (type); - if (expr) - *expr = build_simple_mem_ref_loc (loc, *expr); - } - - return build_ref_for_offset_1 (expr, type, offset, exp_type); -} - /* Return true iff TYPE is stdarg va_list type. */ static inline bool @@ -1823,13 +1881,7 @@ analyze_access_subtree (struct access *root, bool allow_replacements, if (allow_replacements && scalar && !root->first_child && (root->grp_hint - || (root->grp_write && (direct_read || root->grp_assignment_read))) - /* We must not ICE later on when trying to build an access to the - original data within the aggregate even when it is impossible to do in - a defined way like in the PR 42703 testcase. Therefore we check - pre-emptively here that we will be able to do that. */ - && build_ref_for_offset (NULL, TREE_TYPE (root->base), root->offset, - root->type, false)) + || (root->grp_write && (direct_read || root->grp_assignment_read)))) { if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -1914,12 +1966,11 @@ create_artificial_child_access (struct access *parent, struct access *model, { struct access *access; struct access **child; - tree expr = parent->base;; + tree expr = parent->base; gcc_assert (!model->grp_unscalarizable_region); - - if (!build_ref_for_offset (&expr, TREE_TYPE (expr), new_offset, - model->type, false)) + if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset, + model->type)) return NULL; access = (struct access *) pool_alloc (access_pool); @@ -1964,8 +2015,8 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc) { tree t = lacc->base; - if (build_ref_for_offset (&t, TREE_TYPE (t), lacc->offset, racc->type, - false)) + if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t), lacc->offset, + racc->type)) { lacc->expr = t; lacc->type = racc->type; @@ -1994,13 +2045,6 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc) continue; } - /* If a (part of) a union field is on the RHS of an assignment, it can - have sub-accesses which do not make sense on the LHS (PR 40351). - Check that this is not the case. */ - if (!build_ref_for_offset (NULL, TREE_TYPE (lacc->base), norm_offset, - rchild->type, false)) - continue; - rchild->grp_hint = 1; new_acc = create_artificial_child_access (lacc, rchild, norm_offset); if (new_acc) @@ -2124,48 +2168,19 @@ analyze_all_variable_accesses (void) return false; } -/* Return true iff a reference statement into aggregate AGG can be built for - every single to-be-replaced accesses that is a child of ACCESS, its sibling - or a child of its sibling. TOP_OFFSET is the offset from the processed - access subtree that has to be subtracted from offset of each access. */ - -static bool -ref_expr_for_all_replacements_p (struct access *access, tree agg, - HOST_WIDE_INT top_offset) -{ - do - { - if (access->grp_to_be_replaced - && !build_ref_for_offset (NULL, TREE_TYPE (agg), - access->offset - top_offset, - access->type, false)) - return false; - - if (access->first_child - && !ref_expr_for_all_replacements_p (access->first_child, agg, - top_offset)) - return false; - - access = access->next_sibling; - } - while (access); - - return true; -} - /* Generate statements copying scalar replacements of accesses within a subtree into or out of AGG. ACCESS is the first child of the root of the subtree to be processed. AGG is an aggregate type expression (can be a declaration but - does not have to be, it can for example also be an indirect_ref). - TOP_OFFSET is the offset of the processed subtree which has to be subtracted - from offsets of individual accesses to get corresponding offsets for AGG. - If CHUNK_SIZE is non-null, copy only replacements in the interval - , otherwise copy all. GSI is a - statement iterator used to place the new statements. WRITE should be true - when the statements should write from AGG to the replacement and false if - vice versa. if INSERT_AFTER is true, new statements will be added after the - current statement in GSI, they will be added before the statement - otherwise. */ + does not have to be, it can for example also be a mem_ref or a series of + handled components). TOP_OFFSET is the offset of the processed subtree + which has to be subtracted from offsets of individual accesses to get + corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only + replacements in the interval , + otherwise copy all. GSI is a statement iterator used to place the new + statements. WRITE should be true when the statements should write from AGG + to the replacement and false if vice versa. if INSERT_AFTER is true, new + statements will be added after the current statement in GSI, they will be + added before the statement otherwise. */ static void generate_subtree_copies (struct access *access, tree agg, @@ -2176,8 +2191,6 @@ generate_subtree_copies (struct access *access, tree agg, { do { - tree expr = agg; - if (chunk_size && access->offset >= start_offset + chunk_size) return; @@ -2185,14 +2198,11 @@ generate_subtree_copies (struct access *access, tree agg, && (chunk_size == 0 || access->offset + access->size > start_offset)) { - tree repl = get_access_replacement (access); - bool ref_found; + tree expr, repl = get_access_replacement (access); gimple stmt; - ref_found = build_ref_for_offset (&expr, TREE_TYPE (agg), - access->offset - top_offset, - access->type, false); - gcc_assert (ref_found); + expr = build_ref_for_model (agg, access->offset - top_offset, + access, gsi, insert_after); if (write) { @@ -2329,12 +2339,10 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) in assembler statements (see PR42398). */ if (!useless_type_conversion_p (type, access->type)) { - tree ref = access->base; - bool ok; + tree ref; - ok = build_ref_for_offset (&ref, TREE_TYPE (ref), - access->offset, access->type, false); - gcc_assert (ok); + ref = build_ref_for_model (access->base, access->offset, access, + NULL, false); if (write) { @@ -2458,25 +2466,11 @@ load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc, lhs, old_gsi); if (*refreshed == SRA_UDH_LEFT) - { - bool repl_found; - - rhs = lacc->base; - repl_found = build_ref_for_offset (&rhs, TREE_TYPE (rhs), - lacc->offset, lacc->type, - false); - gcc_assert (repl_found); - } + rhs = build_ref_for_model (lacc->base, lacc->offset, lacc, + new_gsi, true); else - { - bool repl_found; - - rhs = top_racc->base; - repl_found = build_ref_for_offset (&rhs, - TREE_TYPE (top_racc->base), - offset, lacc->type, false); - gcc_assert (repl_found); - } + rhs = build_ref_for_model (top_racc->base, offset, lacc, + new_gsi, true); } stmt = gimple_build_assign (get_access_replacement (lacc), rhs); @@ -2633,25 +2627,18 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi) if (AGGREGATE_TYPE_P (TREE_TYPE (lhs)) && !access_has_children_p (lacc)) { - tree expr = lhs; - if (build_ref_for_offset (&expr, TREE_TYPE (lhs), 0, - TREE_TYPE (rhs), false)) - { - lhs = expr; - gimple_assign_set_lhs (*stmt, expr); - } + lhs = build_ref_for_offset (lhs, 0, TREE_TYPE (rhs), gsi, false); + gimple_assign_set_lhs (*stmt, lhs); } else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs)) + && !contains_view_convert_expr_p (rhs) && !access_has_children_p (racc)) - { - tree expr = rhs; - if (build_ref_for_offset (&expr, TREE_TYPE (rhs), 0, - TREE_TYPE (lhs), false)) - rhs = expr; - } + rhs = build_ref_for_offset (rhs, 0, TREE_TYPE (lhs), gsi, false); + if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs))) { - rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs); + rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), + rhs); if (is_gimple_reg_type (TREE_TYPE (lhs)) && TREE_CODE (lhs) != SSA_NAME) force_gimple_rhs = true; @@ -2694,11 +2681,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi) if (gimple_has_volatile_ops (*stmt) || contains_view_convert_expr_p (rhs) - || contains_view_convert_expr_p (lhs) - || (access_has_children_p (racc) - && !ref_expr_for_all_replacements_p (racc, lhs, racc->offset)) - || (access_has_children_p (lacc) - && !ref_expr_for_all_replacements_p (lacc, rhs, lacc->offset))) + || contains_view_convert_expr_p (lhs)) { if (access_has_children_p (racc)) generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,