Commit b5926e23 by Richard Biener Committed by Richard Biener

gimple-ssa-store-merging.c (struct store_immediate_info): Remove redundant val and dest members.

2016-11-02  Richard Biener  <rguenther@suse.de>

	* gimple-ssa-store-merging.c (struct store_immediate_info): Remove
	redundant val and dest members.
	(store_immediate_info::store_immediate_info): Adjust.
	(merged_store_group::merged_store_group): Adjust.
	(merged_store_group::apply_stores): Likewise.
	(struct imm_store_chain_info): Add base_addr field.
	(imm_store_chain_info::imm_store_chain_info): New constructor.
	(imm_store_chain_info::terminate_and_process_chain): Do not pass base.
	(imm_store_chain_info::output_merged_store): Likewise.  Use
	addr_base which is already the address.
	(imm_store_chain_info::output_merged_stores): Likewise.
	(pass_tree_store_merging::terminate_all_aliasing_chains): Take
	imm_store_chain_info instead of base.  Fix alias check.
	(pass_tree_store_merging::terminate_and_release_chain): Likewise.
	(imm_store_chain_info::coalesce_immediate_stores): Adjust.
	(pass_store_merging::execute): Refuse to operate on TARGET_MEM_REF.
	use the address of the base and adjust for other changes.

From-SVN: r241789
parent 4b69fb13
2016-11-02 Richard Biener <rguenther@suse.de>
* gimple-ssa-store-merging.c (struct store_immediate_info): Remove
redundant val and dest members.
(store_immediate_info::store_immediate_info): Adjust.
(merged_store_group::merged_store_group): Adjust.
(merged_store_group::apply_stores): Likewise.
(struct imm_store_chain_info): Add base_addr field.
(imm_store_chain_info::imm_store_chain_info): New constructor.
(imm_store_chain_info::terminate_and_process_chain): Do not pass base.
(imm_store_chain_info::output_merged_store): Likewise. Use
addr_base which is already the address.
(imm_store_chain_info::output_merged_stores): Likewise.
(pass_tree_store_merging::terminate_all_aliasing_chains): Take
imm_store_chain_info instead of base. Fix alias check.
(pass_tree_store_merging::terminate_and_release_chain): Likewise.
(imm_store_chain_info::coalesce_immediate_stores): Adjust.
(pass_store_merging::execute): Refuse to operate on TARGET_MEM_REF.
use the address of the base and adjust for other changes.
2016-11-02 Martin Liska <mliska@suse.cz> 2016-11-02 Martin Liska <mliska@suse.cz>
* fold-const-call.c (host_size_t_cst_p): Test whether * fold-const-call.c (host_size_t_cst_p): Test whether
...@@ -140,19 +140,17 @@ struct store_immediate_info ...@@ -140,19 +140,17 @@ struct store_immediate_info
{ {
unsigned HOST_WIDE_INT bitsize; unsigned HOST_WIDE_INT bitsize;
unsigned HOST_WIDE_INT bitpos; unsigned HOST_WIDE_INT bitpos;
tree val;
tree dest;
gimple *stmt; gimple *stmt;
unsigned int order; unsigned int order;
store_immediate_info (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, tree, store_immediate_info (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
tree, gimple *, unsigned int); gimple *, unsigned int);
}; };
store_immediate_info::store_immediate_info (unsigned HOST_WIDE_INT bs, store_immediate_info::store_immediate_info (unsigned HOST_WIDE_INT bs,
unsigned HOST_WIDE_INT bp, tree v, unsigned HOST_WIDE_INT bp,
tree d, gimple *st, gimple *st,
unsigned int ord) unsigned int ord)
: bitsize (bs), bitpos (bp), val (v), dest (d), stmt (st), order (ord) : bitsize (bs), bitpos (bp), stmt (st), order (ord)
{ {
} }
...@@ -557,7 +555,7 @@ merged_store_group::merged_store_group (store_immediate_info *info) ...@@ -557,7 +555,7 @@ merged_store_group::merged_store_group (store_immediate_info *info)
/* VAL has memory allocated for it in apply_stores once the group /* VAL has memory allocated for it in apply_stores once the group
width has been finalized. */ width has been finalized. */
val = NULL; val = NULL;
align = get_object_alignment (info->dest); align = get_object_alignment (gimple_assign_lhs (info->stmt));
stores.create (1); stores.create (1);
stores.safe_push (info); stores.safe_push (info);
last_stmt = info->stmt; last_stmt = info->stmt;
...@@ -654,14 +652,16 @@ merged_store_group::apply_stores () ...@@ -654,14 +652,16 @@ merged_store_group::apply_stores ()
FOR_EACH_VEC_ELT (stores, i, info) FOR_EACH_VEC_ELT (stores, i, info)
{ {
unsigned int pos_in_buffer = info->bitpos - start; unsigned int pos_in_buffer = info->bitpos - start;
bool ret = encode_tree_to_bitpos (info->val, val, info->bitsize, bool ret = encode_tree_to_bitpos (gimple_assign_rhs1 (info->stmt),
pos_in_buffer, buf_size); val, info->bitsize,
pos_in_buffer, buf_size);
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
if (ret) if (ret)
{ {
fprintf (dump_file, "After writing "); fprintf (dump_file, "After writing ");
print_generic_expr (dump_file, info->val, 0); print_generic_expr (dump_file,
gimple_assign_rhs1 (info->stmt), 0);
fprintf (dump_file, " of size " HOST_WIDE_INT_PRINT_DEC fprintf (dump_file, " of size " HOST_WIDE_INT_PRINT_DEC
" at position %d the merged region contains:\n", " at position %d the merged region contains:\n",
info->bitsize, pos_in_buffer); info->bitsize, pos_in_buffer);
...@@ -680,13 +680,15 @@ merged_store_group::apply_stores () ...@@ -680,13 +680,15 @@ merged_store_group::apply_stores ()
struct imm_store_chain_info struct imm_store_chain_info
{ {
tree base_addr;
auto_vec<struct store_immediate_info *> m_store_info; auto_vec<struct store_immediate_info *> m_store_info;
auto_vec<merged_store_group *> m_merged_store_groups; auto_vec<merged_store_group *> m_merged_store_groups;
bool terminate_and_process_chain (tree); imm_store_chain_info (tree b_a) : base_addr (b_a) {}
bool terminate_and_process_chain ();
bool coalesce_immediate_stores (); bool coalesce_immediate_stores ();
bool output_merged_store (tree, merged_store_group *); bool output_merged_store (merged_store_group *);
bool output_merged_stores (tree); bool output_merged_stores ();
}; };
const pass_data pass_data_tree_store_merging = { const pass_data pass_data_tree_store_merging = {
...@@ -722,8 +724,9 @@ private: ...@@ -722,8 +724,9 @@ private:
hash_map<tree_operand_hash, struct imm_store_chain_info *> m_stores; hash_map<tree_operand_hash, struct imm_store_chain_info *> m_stores;
bool terminate_and_process_all_chains (); bool terminate_and_process_all_chains ();
bool terminate_all_aliasing_chains (tree, tree, bool, gimple *); bool terminate_all_aliasing_chains (tree, imm_store_chain_info **,
bool terminate_and_release_chain (tree); bool, gimple *);
bool terminate_and_release_chain (imm_store_chain_info *);
}; // class pass_store_merging }; // class pass_store_merging
/* Terminate and process all recorded chains. Return true if any changes /* Terminate and process all recorded chains. Return true if any changes
...@@ -736,7 +739,7 @@ pass_store_merging::terminate_and_process_all_chains () ...@@ -736,7 +739,7 @@ pass_store_merging::terminate_and_process_all_chains ()
= m_stores.begin (); = m_stores.begin ();
bool ret = false; bool ret = false;
for (; iter != m_stores.end (); ++iter) for (; iter != m_stores.end (); ++iter)
ret |= terminate_and_release_chain ((*iter).first); ret |= terminate_and_release_chain ((*iter).second);
return ret; return ret;
} }
...@@ -750,7 +753,9 @@ pass_store_merging::terminate_and_process_all_chains () ...@@ -750,7 +753,9 @@ pass_store_merging::terminate_and_process_all_chains ()
If that is the case we have to terminate any chain anchored at BASE. */ If that is the case we have to terminate any chain anchored at BASE. */
bool bool
pass_store_merging::terminate_all_aliasing_chains (tree dest, tree base, pass_store_merging::terminate_all_aliasing_chains (tree dest,
imm_store_chain_info
**chain_info,
bool var_offset_p, bool var_offset_p,
gimple *stmt) gimple *stmt)
{ {
...@@ -760,44 +765,38 @@ pass_store_merging::terminate_all_aliasing_chains (tree dest, tree base, ...@@ -760,44 +765,38 @@ pass_store_merging::terminate_all_aliasing_chains (tree dest, tree base,
if (!gimple_vuse (stmt)) if (!gimple_vuse (stmt))
return false; return false;
struct imm_store_chain_info **chain_info = NULL;
/* Check if the assignment destination (BASE) is part of a store chain. /* Check if the assignment destination (BASE) is part of a store chain.
This is to catch non-constant stores to destinations that may be part This is to catch non-constant stores to destinations that may be part
of a chain. */ of a chain. */
if (base) if (chain_info)
{ {
chain_info = m_stores.get (base); /* We have a chain at BASE and we're writing to [BASE + <variable>].
if (chain_info) This can interfere with any of the stores so terminate
the chain. */
if (var_offset_p)
{ {
/* We have a chain at BASE and we're writing to [BASE + <variable>]. terminate_and_release_chain (*chain_info);
This can interfere with any of the stores so terminate ret = true;
the chain. */ }
if (var_offset_p) /* Otherwise go through every store in the chain to see if it
{ aliases with any of them. */
terminate_and_release_chain (base); else
ret = true; {
} struct store_immediate_info *info;
/* Otherwise go through every store in the chain to see if it unsigned int i;
aliases with any of them. */ FOR_EACH_VEC_ELT ((*chain_info)->m_store_info, i, info)
else
{ {
struct store_immediate_info *info; if (stmt_may_clobber_ref_p (info->stmt, dest))
unsigned int i;
FOR_EACH_VEC_ELT ((*chain_info)->m_store_info, i, info)
{ {
if (refs_may_alias_p (info->dest, dest)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file,
{ "stmt causes chain termination:\n");
fprintf (dump_file, print_gimple_stmt (dump_file, stmt, 0, 0);
"stmt causes chain termination:\n");
print_gimple_stmt (dump_file, stmt, 0, 0);
}
terminate_and_release_chain (base);
ret = true;
break;
} }
terminate_and_release_chain (*chain_info);
ret = true;
break;
} }
} }
} }
...@@ -814,11 +813,16 @@ pass_store_merging::terminate_all_aliasing_chains (tree dest, tree base, ...@@ -814,11 +813,16 @@ pass_store_merging::terminate_all_aliasing_chains (tree dest, tree base,
if (chain_info && (*chain_info) == (*iter).second) if (chain_info && (*chain_info) == (*iter).second)
continue; continue;
tree key = (*iter).first; /* We can't use the base object here as that does not reliably exist.
if (ref_maybe_used_by_stmt_p (stmt, key) Build a ao_ref from the base object address (if we know the
|| stmt_may_clobber_ref_p (stmt, key)) minimum and maximum offset and the maximum size we could improve
things here). */
ao_ref chain_ref;
ao_ref_init_from_ptr_and_size (&chain_ref, (*iter).first, NULL_TREE);
if (ref_maybe_used_by_stmt_p (stmt, &chain_ref)
|| stmt_may_clobber_ref_p_1 (stmt, &chain_ref))
{ {
terminate_and_release_chain (key); terminate_and_release_chain ((*iter).second);
ret = true; ret = true;
} }
} }
...@@ -831,19 +835,11 @@ pass_store_merging::terminate_all_aliasing_chains (tree dest, tree base, ...@@ -831,19 +835,11 @@ pass_store_merging::terminate_all_aliasing_chains (tree dest, tree base,
entry is removed after the processing in any case. */ entry is removed after the processing in any case. */
bool bool
pass_store_merging::terminate_and_release_chain (tree base) pass_store_merging::terminate_and_release_chain (imm_store_chain_info *chain_info)
{ {
struct imm_store_chain_info **chain_info = m_stores.get (base); bool ret = chain_info->terminate_and_process_chain ();
m_stores.remove (chain_info->base_addr);
if (!chain_info) delete chain_info;
return false;
gcc_assert (*chain_info);
bool ret = (*chain_info)->terminate_and_process_chain (base);
delete *chain_info;
m_stores.remove (base);
return ret; return ret;
} }
...@@ -880,7 +876,7 @@ imm_store_chain_info::coalesce_immediate_stores () ...@@ -880,7 +876,7 @@ imm_store_chain_info::coalesce_immediate_stores ()
fprintf (dump_file, "Store %u:\nbitsize:" HOST_WIDE_INT_PRINT_DEC fprintf (dump_file, "Store %u:\nbitsize:" HOST_WIDE_INT_PRINT_DEC
" bitpos:" HOST_WIDE_INT_PRINT_DEC " val:\n", " bitpos:" HOST_WIDE_INT_PRINT_DEC " val:\n",
i, info->bitsize, info->bitpos); i, info->bitsize, info->bitpos);
print_generic_expr (dump_file, info->val, 0); print_generic_expr (dump_file, gimple_assign_rhs1 (info->stmt), 0);
fprintf (dump_file, "\n------------\n"); fprintf (dump_file, "\n------------\n");
} }
...@@ -1103,7 +1099,7 @@ split_group (merged_store_group *group, ...@@ -1103,7 +1099,7 @@ split_group (merged_store_group *group,
return true. */ return true. */
bool bool
imm_store_chain_info::output_merged_store (tree base, merged_store_group *group) imm_store_chain_info::output_merged_store (merged_store_group *group)
{ {
unsigned HOST_WIDE_INT start_byte_pos = group->start / BITS_PER_UNIT; unsigned HOST_WIDE_INT start_byte_pos = group->start / BITS_PER_UNIT;
...@@ -1141,8 +1137,7 @@ imm_store_chain_info::output_merged_store (tree base, merged_store_group *group) ...@@ -1141,8 +1137,7 @@ imm_store_chain_info::output_merged_store (tree base, merged_store_group *group)
tree int_type = build_nonstandard_integer_type (try_size, UNSIGNED); tree int_type = build_nonstandard_integer_type (try_size, UNSIGNED);
int_type = build_aligned_type (int_type, align); int_type = build_aligned_type (int_type, align);
tree addr = build_fold_addr_expr (base); tree dest = fold_build2 (MEM_REF, int_type, base_addr,
tree dest = fold_build2 (MEM_REF, int_type, addr,
build_int_cst (offset_type, try_pos)); build_int_cst (offset_type, try_pos));
tree src = native_interpret_expr (int_type, tree src = native_interpret_expr (int_type,
...@@ -1213,14 +1208,14 @@ imm_store_chain_info::output_merged_store (tree base, merged_store_group *group) ...@@ -1213,14 +1208,14 @@ imm_store_chain_info::output_merged_store (tree base, merged_store_group *group)
successful. Return true iff any changes were made. */ successful. Return true iff any changes were made. */
bool bool
imm_store_chain_info::output_merged_stores (tree base) imm_store_chain_info::output_merged_stores ()
{ {
unsigned int i; unsigned int i;
merged_store_group *merged_store; merged_store_group *merged_store;
bool ret = false; bool ret = false;
FOR_EACH_VEC_ELT (m_merged_store_groups, i, merged_store) FOR_EACH_VEC_ELT (m_merged_store_groups, i, merged_store)
{ {
if (output_merged_store (base, merged_store)) if (output_merged_store (merged_store))
{ {
unsigned int j; unsigned int j;
store_immediate_info *store; store_immediate_info *store;
...@@ -1250,7 +1245,7 @@ imm_store_chain_info::output_merged_stores (tree base) ...@@ -1250,7 +1245,7 @@ imm_store_chain_info::output_merged_stores (tree base)
Return true if any changes were made. */ Return true if any changes were made. */
bool bool
imm_store_chain_info::terminate_and_process_chain (tree base) imm_store_chain_info::terminate_and_process_chain ()
{ {
/* Process store chain. */ /* Process store chain. */
bool ret = false; bool ret = false;
...@@ -1258,7 +1253,7 @@ imm_store_chain_info::terminate_and_process_chain (tree base) ...@@ -1258,7 +1253,7 @@ imm_store_chain_info::terminate_and_process_chain (tree base)
{ {
ret = coalesce_immediate_stores (); ret = coalesce_immediate_stores ();
if (ret) if (ret)
ret = output_merged_stores (base); ret = output_merged_stores ();
} }
/* Delete all the entries we allocated ourselves. */ /* Delete all the entries we allocated ourselves. */
...@@ -1381,28 +1376,29 @@ pass_store_merging::execute (function *fun) ...@@ -1381,28 +1376,29 @@ pass_store_merging::execute (function *fun)
other so we can't track chains on them. */ other so we can't track chains on them. */
|| TREE_THIS_VOLATILE (base_addr); || TREE_THIS_VOLATILE (base_addr);
/* We do not want to rewrite TARGET_MEM_REFs. */
if (TREE_CODE (base_addr) == TARGET_MEM_REF)
invalid = true;
/* In some cases get_inner_reference may return a /* In some cases get_inner_reference may return a
MEM_REF [ptr + byteoffset]. For the purposes of this pass MEM_REF [ptr + byteoffset]. For the purposes of this pass
canonicalize the base_addr to MEM_REF [ptr] and take canonicalize the base_addr to MEM_REF [ptr] and take
byteoffset into account in the bitpos. This occurs in byteoffset into account in the bitpos. This occurs in
PR 23684 and this way we can catch more chains. */ PR 23684 and this way we can catch more chains. */
if (TREE_CODE (base_addr) == MEM_REF else if (TREE_CODE (base_addr) == MEM_REF)
&& POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (base_addr, 0))))
{ {
offset_int bit_off, byte_off = mem_ref_offset (base_addr); offset_int bit_off, byte_off = mem_ref_offset (base_addr);
bit_off = byte_off << LOG2_BITS_PER_UNIT; bit_off = byte_off << LOG2_BITS_PER_UNIT;
bit_off += bitpos; bit_off += bitpos;
if (!wi::neg_p (bit_off) && wi::fits_shwi_p (bit_off)) if (!wi::neg_p (bit_off) && wi::fits_shwi_p (bit_off))
{ bitpos = bit_off.to_shwi ();
bitpos = bit_off.to_shwi ();
base_addr = build2 (MEM_REF, TREE_TYPE (base_addr),
TREE_OPERAND (base_addr, 0),
build_zero_cst (TREE_TYPE (
TREE_OPERAND (base_addr, 1))));
}
else else
invalid = true; invalid = true;
base_addr = TREE_OPERAND (base_addr, 0);
} }
/* get_inner_reference returns the base object, get at its
address now. */
else
base_addr = build_fold_addr_expr (base_addr);
struct imm_store_chain_info **chain_info struct imm_store_chain_info **chain_info
= m_stores.get (base_addr); = m_stores.get (base_addr);
...@@ -1413,7 +1409,7 @@ pass_store_merging::execute (function *fun) ...@@ -1413,7 +1409,7 @@ pass_store_merging::execute (function *fun)
if (chain_info) if (chain_info)
{ {
info = new store_immediate_info ( info = new store_immediate_info (
bitsize, bitpos, rhs, lhs, stmt, bitsize, bitpos, stmt,
(*chain_info)->m_store_info.length ()); (*chain_info)->m_store_info.length ());
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
...@@ -1432,17 +1428,17 @@ pass_store_merging::execute (function *fun) ...@@ -1432,17 +1428,17 @@ pass_store_merging::execute (function *fun)
fprintf (dump_file, fprintf (dump_file,
"Reached maximum number of statements" "Reached maximum number of statements"
" to merge:\n"); " to merge:\n");
terminate_and_release_chain (base_addr); terminate_and_release_chain (*chain_info);
} }
continue; continue;
} }
/* Store aliases any existing chain? */ /* Store aliases any existing chain? */
terminate_all_aliasing_chains (lhs, base_addr, false, stmt); terminate_all_aliasing_chains (lhs, chain_info, false, stmt);
/* Start a new chain. */ /* Start a new chain. */
struct imm_store_chain_info *new_chain struct imm_store_chain_info *new_chain
= new imm_store_chain_info; = new imm_store_chain_info (base_addr);
info = new store_immediate_info (bitsize, bitpos, rhs, lhs, info = new store_immediate_info (bitsize, bitpos,
stmt, 0); stmt, 0);
new_chain->m_store_info.safe_push (info); new_chain->m_store_info.safe_push (info);
m_stores.put (base_addr, new_chain); m_stores.put (base_addr, new_chain);
...@@ -1457,13 +1453,13 @@ pass_store_merging::execute (function *fun) ...@@ -1457,13 +1453,13 @@ pass_store_merging::execute (function *fun)
} }
} }
else else
terminate_all_aliasing_chains (lhs, base_addr, terminate_all_aliasing_chains (lhs, chain_info,
offset != NULL_TREE, stmt); offset != NULL_TREE, stmt);
continue; continue;
} }
terminate_all_aliasing_chains (NULL_TREE, NULL_TREE, false, stmt); terminate_all_aliasing_chains (NULL_TREE, NULL, false, stmt);
} }
terminate_and_process_all_chains (); terminate_and_process_all_chains ();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment