re PR middle-end/58956 (wrong code at -O1 and above (affecting gcc 4.6 to trunk))

PR middle-end/58956
	PR middle-end/59470
	* gimple-walk.h (walk_stmt_load_store_addr_fn): New typedef.
	(walk_stmt_load_store_addr_ops, walk_stmt_load_store_ops): Use it
	for callback params.
	* gimple-walk.c (walk_stmt_load_store_ops): Likewise.
	(walk_stmt_load_store_addr_ops): Likewise.  Adjust all callback
	calls to supply the gimple operand containing the base tree
	as an extra argument.
	* tree-ssa-ter.c: Include gimple-walk.h.
	(find_ssaname, find_ssaname_in_store): New helper functions.
	(find_replaceable_in_bb): For calls or GIMPLE_ASM, only set
	same_root_var if USE is used somewhere in the stores of the stmt.
	* ipa-prop.c (visit_ref_for_mod_analysis): Remove name of the stmt
	argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
	* ipa-pure-const.c (check_load, check_store, check_ipa_load,
	check_ipa_store): Likewise.
	* gimple.c (gimple_ior_addresses_taken_1, check_loadstore): Likewise.
	* ipa-split.c (test_nonssa_use, mark_nonssa_use): Likewise.
	(verify_non_ssa_vars, visit_bb): Adjust their callers.
	* cfgexpand.c (add_scope_conflicts_1): Use
	walk_stmt_load_store_addr_fn type for visit variable.
	(visit_op, visit_conflict): Remove name of the stmt
	argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
	* tree-sra.c (asm_visit_addr): Likewise.  Remove name of the data
	argument and ATTRIBUTE_UNUSED.
	* cgraphbuild.c (mark_address, mark_load, mark_store): Add another
	unnamed tree argument.
	* gimple-ssa-isolate-paths.c (check_loadstore): Likewise.  Remove
	ATTRIBUTE_UNUSED from stmt parameter.

	* gcc.target/i386/pr59470.c: New test.

From-SVN: r206009
This commit is contained in:
Jakub Jelinek 2013-12-16 09:09:05 +01:00 committed by Jakub Jelinek
parent 317c184928
commit 9f1363cd0d
14 changed files with 178 additions and 73 deletions

View File

@ -1,3 +1,36 @@
2013-12-16 Jakub Jelinek <jakub@redhat.com>
PR middle-end/58956
PR middle-end/59470
* gimple-walk.h (walk_stmt_load_store_addr_fn): New typedef.
(walk_stmt_load_store_addr_ops, walk_stmt_load_store_ops): Use it
for callback params.
* gimple-walk.c (walk_stmt_load_store_ops): Likewise.
(walk_stmt_load_store_addr_ops): Likewise. Adjust all callback
calls to supply the gimple operand containing the base tree
as an extra argument.
* tree-ssa-ter.c: Include gimple-walk.h.
(find_ssaname, find_ssaname_in_store): New helper functions.
(find_replaceable_in_bb): For calls or GIMPLE_ASM, only set
same_root_var if USE is used somewhere in the stores of the stmt.
* ipa-prop.c (visit_ref_for_mod_analysis): Remove name of the stmt
argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
* ipa-pure-const.c (check_load, check_store, check_ipa_load,
check_ipa_store): Likewise.
* gimple.c (gimple_ior_addresses_taken_1, check_loadstore): Likewise.
* ipa-split.c (test_nonssa_use, mark_nonssa_use): Likewise.
(verify_non_ssa_vars, visit_bb): Adjust their callers.
* cfgexpand.c (add_scope_conflicts_1): Use
walk_stmt_load_store_addr_fn type for visit variable.
(visit_op, visit_conflict): Remove name of the stmt
argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
* tree-sra.c (asm_visit_addr): Likewise. Remove name of the data
argument and ATTRIBUTE_UNUSED.
* cgraphbuild.c (mark_address, mark_load, mark_store): Add another
unnamed tree argument.
* gimple-ssa-isolate-paths.c (check_loadstore): Likewise. Remove
ATTRIBUTE_UNUSED from stmt parameter.
2013-12-16 Chung-Lin Tang <cltang@codesourcery.com>
* opts-common.c (integral_argument): Add support for

View File

@ -365,7 +365,7 @@ stack_var_conflict_p (size_t x, size_t y)
enter its partition number into bitmap DATA. */
static bool
visit_op (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
visit_op (gimple, tree op, tree, void *data)
{
bitmap active = (bitmap)data;
op = get_base_address (op);
@ -385,7 +385,7 @@ visit_op (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
from bitmap DATA. */
static bool
visit_conflict (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
visit_conflict (gimple, tree op, tree, void *data)
{
bitmap active = (bitmap)data;
op = get_base_address (op);
@ -419,7 +419,7 @@ add_scope_conflicts_1 (basic_block bb, bitmap work, bool for_conflict)
edge e;
edge_iterator ei;
gimple_stmt_iterator gsi;
bool (*visit)(gimple, tree, void *);
walk_stmt_load_store_addr_fn visit;
bitmap_clear (work);
FOR_EACH_EDGE (e, ei, bb->preds)

View File

@ -224,7 +224,7 @@ compute_call_stmt_bb_frequency (tree decl, basic_block bb)
/* Mark address taken in STMT. */
static bool
mark_address (gimple stmt, tree addr, void *data)
mark_address (gimple stmt, tree addr, tree, void *data)
{
addr = get_base_address (addr);
if (TREE_CODE (addr) == FUNCTION_DECL)
@ -251,7 +251,7 @@ mark_address (gimple stmt, tree addr, void *data)
/* Mark load of T. */
static bool
mark_load (gimple stmt, tree t, void *data)
mark_load (gimple stmt, tree t, tree, void *data)
{
t = get_base_address (t);
if (t && TREE_CODE (t) == FUNCTION_DECL)
@ -279,7 +279,7 @@ mark_load (gimple stmt, tree t, void *data)
/* Mark store of T. */
static bool
mark_store (gimple stmt, tree t, void *data)
mark_store (gimple stmt, tree t, tree, void *data)
{
t = get_base_address (t);
if (t && TREE_CODE (t) == VAR_DECL

View File

@ -55,7 +55,7 @@ static bool cfg_altered;
This routine only makes a superficial check for a dereference. Thus,
it must only be used if it is safe to return a false negative. */
static bool
check_loadstore (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
check_loadstore (gimple stmt, tree op, tree, void *data)
{
if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
&& operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0))

View File

@ -649,42 +649,46 @@ get_base_loadstore (tree op)
/* For the statement STMT call the callbacks VISIT_LOAD, VISIT_STORE and
VISIT_ADDR if non-NULL on loads, store and address-taken operands
passing the STMT, the base of the operand and DATA to it. The base
will be either a decl, an indirect reference (including TARGET_MEM_REF)
or the argument of an address expression.
passing the STMT, the base of the operand, the operand itself containing
the base and DATA to it. The base will be either a decl, an indirect
reference (including TARGET_MEM_REF) or the argument of an address
expression.
Returns the results of these callbacks or'ed. */
bool
walk_stmt_load_store_addr_ops (gimple stmt, void *data,
bool (*visit_load)(gimple, tree, void *),
bool (*visit_store)(gimple, tree, void *),
bool (*visit_addr)(gimple, tree, void *))
walk_stmt_load_store_addr_fn visit_load,
walk_stmt_load_store_addr_fn visit_store,
walk_stmt_load_store_addr_fn visit_addr)
{
bool ret = false;
unsigned i;
if (gimple_assign_single_p (stmt))
{
tree lhs, rhs;
tree lhs, rhs, arg;
if (visit_store)
{
lhs = get_base_loadstore (gimple_assign_lhs (stmt));
arg = gimple_assign_lhs (stmt);
lhs = get_base_loadstore (arg);
if (lhs)
ret |= visit_store (stmt, lhs, data);
ret |= visit_store (stmt, lhs, arg, data);
}
rhs = gimple_assign_rhs1 (stmt);
arg = gimple_assign_rhs1 (stmt);
rhs = arg;
while (handled_component_p (rhs))
rhs = TREE_OPERAND (rhs, 0);
if (visit_addr)
{
if (TREE_CODE (rhs) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), arg, data);
else if (TREE_CODE (rhs) == TARGET_MEM_REF
&& TREE_CODE (TMR_BASE (rhs)) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), data);
ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), arg,
data);
else if (TREE_CODE (rhs) == OBJ_TYPE_REF
&& TREE_CODE (OBJ_TYPE_REF_OBJECT (rhs)) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (OBJ_TYPE_REF_OBJECT (rhs),
0), data);
0), arg, data);
else if (TREE_CODE (rhs) == CONSTRUCTOR)
{
unsigned int ix;
@ -692,23 +696,23 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), ix, val)
if (TREE_CODE (val) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (val, 0), data);
ret |= visit_addr (stmt, TREE_OPERAND (val, 0), arg, data);
else if (TREE_CODE (val) == OBJ_TYPE_REF
&& TREE_CODE (OBJ_TYPE_REF_OBJECT (val)) == ADDR_EXPR)
ret |= visit_addr (stmt,
TREE_OPERAND (OBJ_TYPE_REF_OBJECT (val),
0), data);
0), arg, data);
}
lhs = gimple_assign_lhs (stmt);
if (TREE_CODE (lhs) == TARGET_MEM_REF
&& TREE_CODE (TMR_BASE (lhs)) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 0), data);
ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 0), lhs, data);
}
if (visit_load)
{
rhs = get_base_loadstore (rhs);
if (rhs)
ret |= visit_load (stmt, rhs, data);
ret |= visit_load (stmt, rhs, arg, data);
}
}
else if (visit_addr
@ -721,17 +725,17 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
if (op == NULL_TREE)
;
else if (TREE_CODE (op) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
/* COND_EXPR and VCOND_EXPR rhs1 argument is a comparison
tree with two operands. */
else if (i == 1 && COMPARISON_CLASS_P (op))
{
if (TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 0),
0), data);
0), op, data);
if (TREE_CODE (TREE_OPERAND (op, 1)) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 1),
0), data);
0), op, data);
}
}
}
@ -739,38 +743,39 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
{
if (visit_store)
{
tree lhs = gimple_call_lhs (stmt);
if (lhs)
tree arg = gimple_call_lhs (stmt);
if (arg)
{
lhs = get_base_loadstore (lhs);
tree lhs = get_base_loadstore (arg);
if (lhs)
ret |= visit_store (stmt, lhs, data);
ret |= visit_store (stmt, lhs, arg, data);
}
}
if (visit_load || visit_addr)
for (i = 0; i < gimple_call_num_args (stmt); ++i)
{
tree rhs = gimple_call_arg (stmt, i);
tree arg = gimple_call_arg (stmt, i);
if (visit_addr
&& TREE_CODE (rhs) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
&& TREE_CODE (arg) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (arg, 0), arg, data);
else if (visit_load)
{
rhs = get_base_loadstore (rhs);
tree rhs = get_base_loadstore (arg);
if (rhs)
ret |= visit_load (stmt, rhs, data);
ret |= visit_load (stmt, rhs, arg, data);
}
}
if (visit_addr
&& gimple_call_chain (stmt)
&& TREE_CODE (gimple_call_chain (stmt)) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (stmt), 0),
data);
gimple_call_chain (stmt), data);
if (visit_addr
&& gimple_call_return_slot_opt_p (stmt)
&& gimple_call_lhs (stmt) != NULL_TREE
&& TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt))))
ret |= visit_addr (stmt, gimple_call_lhs (stmt), data);
ret |= visit_addr (stmt, gimple_call_lhs (stmt),
gimple_call_lhs (stmt), data);
}
else if (gimple_code (stmt) == GIMPLE_ASM)
{
@ -786,7 +791,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
tree link = gimple_asm_output_op (stmt, i);
tree op = get_base_loadstore (TREE_VALUE (link));
if (op && visit_store)
ret |= visit_store (stmt, op, data);
ret |= visit_store (stmt, op, TREE_VALUE (link), data);
if (visit_addr)
{
constraint = TREE_STRING_POINTER
@ -795,7 +800,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
&allows_reg, &is_inout);
if (op && !allows_reg && allows_mem)
ret |= visit_addr (stmt, op, data);
ret |= visit_addr (stmt, op, TREE_VALUE (link), data);
}
}
if (visit_load || visit_addr)
@ -805,14 +810,14 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
tree op = TREE_VALUE (link);
if (visit_addr
&& TREE_CODE (op) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
else if (visit_load || visit_addr)
{
op = get_base_loadstore (op);
if (op)
{
if (visit_load)
ret |= visit_load (stmt, op, data);
ret |= visit_load (stmt, op, TREE_VALUE (link), data);
if (visit_addr)
{
constraint = TREE_STRING_POINTER
@ -821,7 +826,8 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
0, oconstraints,
&allows_mem, &allows_reg);
if (!allows_reg && allows_mem)
ret |= visit_addr (stmt, op, data);
ret |= visit_addr (stmt, op, TREE_VALUE (link),
data);
}
}
}
@ -834,12 +840,12 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
{
if (visit_addr
&& TREE_CODE (op) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
else if (visit_load)
{
op = get_base_loadstore (op);
if (op)
ret |= visit_load (stmt, op, data);
tree base = get_base_loadstore (op);
if (base)
ret |= visit_load (stmt, base, op, data);
}
}
}
@ -850,7 +856,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
{
tree op = gimple_phi_arg_def (stmt, i);
if (TREE_CODE (op) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
}
}
else if (visit_addr
@ -858,7 +864,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
{
tree op = gimple_goto_dest (stmt);
if (TREE_CODE (op) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
}
return ret;
@ -869,8 +875,8 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
bool
walk_stmt_load_store_ops (gimple stmt, void *data,
bool (*visit_load)(gimple, tree, void *),
bool (*visit_store)(gimple, tree, void *))
walk_stmt_load_store_addr_fn visit_load,
walk_stmt_load_store_addr_fn visit_store)
{
return walk_stmt_load_store_addr_ops (stmt, data,
visit_load, visit_store, NULL);

View File

@ -89,11 +89,12 @@ extern gimple walk_gimple_seq (gimple_seq, walk_stmt_fn, walk_tree_fn,
extern tree walk_gimple_op (gimple, walk_tree_fn, struct walk_stmt_info *);
extern tree walk_gimple_stmt (gimple_stmt_iterator *, walk_stmt_fn,
walk_tree_fn, struct walk_stmt_info *);
typedef bool (*walk_stmt_load_store_addr_fn) (gimple, tree, tree, void *);
extern bool walk_stmt_load_store_addr_ops (gimple, void *,
bool (*)(gimple, tree, void *),
bool (*)(gimple, tree, void *),
bool (*)(gimple, tree, void *));
walk_stmt_load_store_addr_fn,
walk_stmt_load_store_addr_fn,
walk_stmt_load_store_addr_fn);
extern bool walk_stmt_load_store_ops (gimple, void *,
bool (*)(gimple, tree, void *),
bool (*)(gimple, tree, void *));
walk_stmt_load_store_addr_fn,
walk_stmt_load_store_addr_fn);
#endif /* GCC_GIMPLE_WALK_H */

View File

@ -2326,8 +2326,7 @@ gimple_get_alias_set (tree t)
/* Helper for gimple_ior_addresses_taken_1. */
static bool
gimple_ior_addresses_taken_1 (gimple stmt ATTRIBUTE_UNUSED,
tree addr, void *data)
gimple_ior_addresses_taken_1 (gimple, tree addr, tree, void *data)
{
bitmap addresses_taken = (bitmap)data;
addr = get_base_address (addr);
@ -2496,7 +2495,7 @@ nonfreeing_call_p (gimple call)
This routine only makes a superficial check for a dereference. Thus
it must only be used if it is safe to return a false negative. */
static bool
check_loadstore (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
check_loadstore (gimple, tree op, tree, void *data)
{
if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
&& operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0))

View File

@ -2061,8 +2061,7 @@ ipa_analyze_stmt_uses (struct cgraph_node *node, struct ipa_node_params *info,
passed in DATA. */
static bool
visit_ref_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED,
tree op, void *data)
visit_ref_for_mod_analysis (gimple, tree op, tree, void *data)
{
struct ipa_node_params *info = (struct ipa_node_params *) data;

View File

@ -589,7 +589,7 @@ check_call (funct_state local, gimple call, bool ipa)
/* Wrapper around check_decl for loads in local more. */
static bool
check_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
check_load (gimple, tree op, tree, void *data)
{
if (DECL_P (op))
check_decl ((funct_state)data, op, false, false);
@ -601,7 +601,7 @@ check_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
/* Wrapper around check_decl for stores in local more. */
static bool
check_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
check_store (gimple, tree op, tree, void *data)
{
if (DECL_P (op))
check_decl ((funct_state)data, op, true, false);
@ -613,7 +613,7 @@ check_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
/* Wrapper around check_decl for loads in ipa mode. */
static bool
check_ipa_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
check_ipa_load (gimple, tree op, tree, void *data)
{
if (DECL_P (op))
check_decl ((funct_state)data, op, false, true);
@ -625,7 +625,7 @@ check_ipa_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
/* Wrapper around check_decl for stores in ipa mode. */
static bool
check_ipa_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
check_ipa_store (gimple, tree op, tree, void *data)
{
if (DECL_P (op))
check_decl ((funct_state)data, op, true, true);

View File

@ -156,7 +156,7 @@ static tree find_retval (basic_block return_bb);
variable, check it if it is present in bitmap passed via DATA. */
static bool
test_nonssa_use (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
test_nonssa_use (gimple, tree t, tree, void *data)
{
t = get_base_address (t);
@ -249,7 +249,7 @@ verify_non_ssa_vars (struct split_point *current, bitmap non_ssa_vars,
}
if (gimple_code (stmt) == GIMPLE_LABEL
&& test_nonssa_use (stmt, gimple_label_label (stmt),
non_ssa_vars))
NULL_TREE, non_ssa_vars))
{
ok = false;
goto done;
@ -278,7 +278,7 @@ verify_non_ssa_vars (struct split_point *current, bitmap non_ssa_vars,
if (virtual_operand_p (gimple_phi_result (stmt)))
continue;
if (TREE_CODE (op) != SSA_NAME
&& test_nonssa_use (stmt, op, non_ssa_vars))
&& test_nonssa_use (stmt, op, op, non_ssa_vars))
{
ok = false;
goto done;
@ -714,7 +714,7 @@ find_retval (basic_block return_bb)
Return true when access to T prevents splitting the function. */
static bool
mark_nonssa_use (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
mark_nonssa_use (gimple, tree t, tree, void *data)
{
t = get_base_address (t);
@ -874,7 +874,7 @@ visit_bb (basic_block bb, basic_block return_bb,
if (TREE_CODE (op) == SSA_NAME)
bitmap_set_bit (used_ssa_names, SSA_NAME_VERSION (op));
else
can_split &= !mark_nonssa_use (stmt, op, non_ssa_vars);
can_split &= !mark_nonssa_use (stmt, op, op, non_ssa_vars);
}
}
return can_split;

View File

@ -1,3 +1,9 @@
2013-12-16 Jakub Jelinek <jakub@redhat.com>
PR middle-end/58956
PR middle-end/59470
* gcc.target/i386/pr59470.c: New test.
2013-12-14 Jan Hubicka <jh@suse.cz>
PR ipa/59265

View File

@ -0,0 +1,17 @@
/* PR middle-end/58956 */
/* PR middle-end/59470 */
/* { dg-do run } */
/* { dg-options "-O2" } */
int a, b, d[1024];
int
main ()
{
int c = a;
asm ("{movl $6, (%2); movl $1, %0|mov dword ptr [%2], 6; mov %0, 1}"
: "=r" (d[c]) : "rm" (b), "r" (&a) : "memory");
if (d[0] != 1 || d[6] != 0)
__builtin_abort ();
return 0;
}

View File

@ -1223,8 +1223,7 @@ build_accesses_from_assign (gimple stmt)
GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
static bool
asm_visit_addr (gimple stmt ATTRIBUTE_UNUSED, tree op,
void *data ATTRIBUTE_UNUSED)
asm_visit_addr (gimple, tree op, tree, void *)
{
op = get_base_address (op);
if (op

View File

@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-ter.h"
#include "tree-outof-ssa.h"
#include "flags.h"
#include "gimple-walk.h"
/* Temporary Expression Replacement (TER)
@ -554,6 +555,30 @@ mark_replaceable (temp_expr_table_p tab, tree var, bool more_replacing)
}
/* Helper function for find_ssaname_in_stores. Called via walk_tree to
find a SSA_NAME DATA somewhere in *TP. */
static tree
find_ssaname (tree *tp, int *walk_subtrees, void *data)
{
tree var = (tree) data;
if (*tp == var)
return var;
else if (IS_TYPE_OR_DECL_P (*tp))
*walk_subtrees = 0;
return NULL_TREE;
}
/* Helper function for find_replaceable_in_bb. Return true if SSA_NAME DATA
is used somewhere in T, which is a store in the statement. Called via
walk_stmt_load_store_addr_ops. */
static bool
find_ssaname_in_store (gimple, tree, tree t, void *data)
{
return walk_tree (&t, find_ssaname, data, NULL) != NULL_TREE;
}
/* This function processes basic block BB, and looks for variables which can
be replaced by their expressions. Results are stored in the table TAB. */
@ -618,7 +643,27 @@ find_replaceable_in_bb (temp_expr_table_p tab, basic_block bb)
&& gimple_assign_single_p (def_stmt)
&& stmt_may_clobber_ref_p (stmt,
gimple_assign_rhs1 (def_stmt)))
same_root_var = true;
{
/* For calls, it is not a problem if USE is among
call's arguments or say OBJ_TYPE_REF argument,
all those necessarily need to be evaluated before
the call that may clobber the memory. But if
LHS of the call refers to USE, expansion might
evaluate it after the call, prevent TER in that
case.
For inline asm, allow TER of loads into input
arguments, but disallow TER for USEs that occur
somewhere in outputs. */
if (is_gimple_call (stmt)
|| gimple_code (stmt) == GIMPLE_ASM)
{
if (walk_stmt_load_store_ops (stmt, use, NULL,
find_ssaname_in_store))
same_root_var = true;
}
else
same_root_var = true;
}
}
/* Mark expression as replaceable unless stmt is volatile, or the