Commit 33a002b0 by Kyrylo Tkachov Committed by Kyrylo Tkachov

[TER] PR target/48863 : Don't replace expressions across local register variable definitions

	PR target/48863
	PR inline-asm/70184
	* tree-ssa-ter.c (temp_expr_table): Add reg_vars_cnt field.
	(new_temp_expr_table): Initialise reg_vars_cnt.
	(free_temp_expr_table): Release reg_vars_cnt.
	(process_replaceable): Add reg_vars_cnt argument, set reg_vars_cnt
	field of TAB.
	(find_replaceable_in_bb): Use the above to record register variable
	write occurrences and cancel replacement across them.

	* gcc.target/arm/pr48863.c: New test.

From-SVN: r242840
parent 4da41abf
2016-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR target/48863
PR inline-asm/70184
* tree-ssa-ter.c (temp_expr_table): Add reg_vars_cnt field.
(new_temp_expr_table): Initialise reg_vars_cnt.
(free_temp_expr_table): Release reg_vars_cnt.
(process_replaceable): Add reg_vars_cnt argument, set reg_vars_cnt
field of TAB.
(find_replaceable_in_bb): Use the above to record register variable
write occurrences and cancel replacement across them.
2016-11-24 Eric Botcazou <ebotcazou@adacore.com> 2016-11-24 Eric Botcazou <ebotcazou@adacore.com>
PR rtl-optimization/78437 PR rtl-optimization/78437
2016-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR target/48863
PR inline-asm/70184
* gcc.target/arm/pr48863.c: New test.
2016-11-24 Martin Liska <mliska@suse.cz> 2016-11-24 Martin Liska <mliska@suse.cz>
* gcc.dg/builtin-unreachable-6.c: Update test to not to scan * gcc.dg/builtin-unreachable-6.c: Update test to not to scan
......
/* PR target/48863. */
/* { dg-do run } */
/* { dg-options "-O2" } */
/* Check that Temporary Expression Replacement does not move a
libcall-producing expression across a statement initialising a local
register variable. */
static inline int
dosvc (int fd, unsigned long high, unsigned low)
{
register int r0 asm("r0") = fd;
register int r2 asm("r2") = high;
register int r3 asm("r3") = low;
asm volatile("" : "=r"(r0) : "0"(r0), "r"(r2), "r"(r3));
return r0;
}
struct s
{
int fd;
long long length;
} s = { 2, 0 }, *p = &s;
int
main (void)
{
unsigned low = p->length & 0xffffffff;
unsigned high = p->length / 23;
if (dosvc (p->fd, high, low) != 2)
__builtin_abort ();
return 0;
}
...@@ -169,6 +169,8 @@ struct temp_expr_table ...@@ -169,6 +169,8 @@ struct temp_expr_table
bitmap new_replaceable_dependencies; /* Holding place for pending dep's. */ bitmap new_replaceable_dependencies; /* Holding place for pending dep's. */
int *num_in_part; /* # of ssa_names in a partition. */ int *num_in_part; /* # of ssa_names in a partition. */
int *call_cnt; /* Call count at definition. */ int *call_cnt; /* Call count at definition. */
int *reg_vars_cnt; /* Number of register variable
definitions encountered. */
}; };
/* Used to indicate a dependency on VDEFs. */ /* Used to indicate a dependency on VDEFs. */
...@@ -211,6 +213,7 @@ new_temp_expr_table (var_map map) ...@@ -211,6 +213,7 @@ new_temp_expr_table (var_map map)
t->num_in_part[p]++; t->num_in_part[p]++;
} }
t->call_cnt = XCNEWVEC (int, num_ssa_names + 1); t->call_cnt = XCNEWVEC (int, num_ssa_names + 1);
t->reg_vars_cnt = XCNEWVEC (int, num_ssa_names + 1);
return t; return t;
} }
...@@ -243,6 +246,7 @@ free_temp_expr_table (temp_expr_table *t) ...@@ -243,6 +246,7 @@ free_temp_expr_table (temp_expr_table *t)
free (t->partition_dependencies); free (t->partition_dependencies);
free (t->num_in_part); free (t->num_in_part);
free (t->call_cnt); free (t->call_cnt);
free (t->reg_vars_cnt);
if (t->replaceable_expressions) if (t->replaceable_expressions)
ret = t->replaceable_expressions; ret = t->replaceable_expressions;
...@@ -435,7 +439,8 @@ ter_is_replaceable_p (gimple *stmt) ...@@ -435,7 +439,8 @@ ter_is_replaceable_p (gimple *stmt)
/* Create an expression entry for a replaceable expression. */ /* Create an expression entry for a replaceable expression. */
static void static void
process_replaceable (temp_expr_table *tab, gimple *stmt, int call_cnt) process_replaceable (temp_expr_table *tab, gimple *stmt, int call_cnt,
int reg_vars_cnt)
{ {
tree var, def, basevar; tree var, def, basevar;
int version; int version;
...@@ -477,6 +482,7 @@ process_replaceable (temp_expr_table *tab, gimple *stmt, int call_cnt) ...@@ -477,6 +482,7 @@ process_replaceable (temp_expr_table *tab, gimple *stmt, int call_cnt)
} }
tab->call_cnt[version] = call_cnt; tab->call_cnt[version] = call_cnt;
tab->reg_vars_cnt[version] = reg_vars_cnt;
} }
...@@ -573,6 +579,7 @@ find_replaceable_in_bb (temp_expr_table *tab, basic_block bb) ...@@ -573,6 +579,7 @@ find_replaceable_in_bb (temp_expr_table *tab, basic_block bb)
ssa_op_iter iter; ssa_op_iter iter;
bool stmt_replaceable; bool stmt_replaceable;
int cur_call_cnt = 0; int cur_call_cnt = 0;
int cur_reg_vars_cnt = 0;
for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
{ {
...@@ -649,11 +656,14 @@ find_replaceable_in_bb (temp_expr_table *tab, basic_block bb) ...@@ -649,11 +656,14 @@ find_replaceable_in_bb (temp_expr_table *tab, basic_block bb)
/* Mark expression as replaceable unless stmt is volatile, or the /* Mark expression as replaceable unless stmt is volatile, or the
def variable has the same root variable as something in the def variable has the same root variable as something in the
substitution list, or the def and use span a call such that substitution list, or the def and use span a call such that
we'll expand lifetimes across a call. */ we'll expand lifetimes across a call. We also don't want to
replace across these expressions that may call libcalls that
clobber the register involved. See PR 70184. */
if (gimple_has_volatile_ops (stmt) || same_root_var if (gimple_has_volatile_ops (stmt) || same_root_var
|| (tab->call_cnt[ver] != cur_call_cnt || (tab->call_cnt[ver] != cur_call_cnt
&& SINGLE_SSA_USE_OPERAND (SSA_NAME_DEF_STMT (use), SSA_OP_USE) && SINGLE_SSA_USE_OPERAND (SSA_NAME_DEF_STMT (use), SSA_OP_USE)
== NULL_USE_OPERAND_P)) == NULL_USE_OPERAND_P)
|| tab->reg_vars_cnt[ver] != cur_reg_vars_cnt)
finished_with_expr (tab, ver, true); finished_with_expr (tab, ver, true);
else else
mark_replaceable (tab, use, stmt_replaceable); mark_replaceable (tab, use, stmt_replaceable);
...@@ -676,9 +686,16 @@ find_replaceable_in_bb (temp_expr_table *tab, basic_block bb) ...@@ -676,9 +686,16 @@ find_replaceable_in_bb (temp_expr_table *tab, basic_block bb)
&& DECL_BUILT_IN (fndecl))) && DECL_BUILT_IN (fndecl)))
cur_call_cnt++; cur_call_cnt++;
/* Increment counter if this statement sets a local
register variable. */
if (gimple_assign_single_p (stmt)
&& (TREE_CODE (gimple_assign_lhs (stmt)) == VAR_DECL
&& DECL_HARD_REGISTER (gimple_assign_lhs (stmt))))
cur_reg_vars_cnt++;
/* Now see if we are creating a new expression or not. */ /* Now see if we are creating a new expression or not. */
if (stmt_replaceable) if (stmt_replaceable)
process_replaceable (tab, stmt, cur_call_cnt); process_replaceable (tab, stmt, cur_call_cnt, cur_reg_vars_cnt);
/* Free any unused dependency lists. */ /* Free any unused dependency lists. */
bitmap_clear (tab->new_replaceable_dependencies); bitmap_clear (tab->new_replaceable_dependencies);
......
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