aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-structalias.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2016-09-21 07:38:33 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2016-09-21 07:38:33 +0000
commit6811ea797651caab6df9cf6ce4237ca4eaf1399e (patch)
tree36c2c41787ff92e38461f73aa58c90f4c18f8a37 /gcc/tree-ssa-structalias.c
parentf955c4c4837a491a8e8c3962867f276a94125dde (diff)
downloadgcc-6811ea797651caab6df9cf6ce4237ca4eaf1399e.zip
gcc-6811ea797651caab6df9cf6ce4237ca4eaf1399e.tar.gz
gcc-6811ea797651caab6df9cf6ce4237ca4eaf1399e.tar.bz2
re PR tree-optimization/77648 (Setting conversion to a integer to double to 0 3/4 through a loop)
2016-09-21 Richard Biener <rguenther@suse.de> PR tree-optimization/77648 * tree-ssa-structalias.c (process_constraint): Handle all DEREF with complex RHS. (make_transitive_closure_constraints): Adjust comment. (make_any_offset_constraints): New function. (handle_rhs_call): Make sure to first expand a pointer to all subfields before transitively closing it. (handle_const_call): Likewise. Properly expand returned pointers as well. (handle_pure_call): Likewise. * gcc.dg/torture/pr77648-1.c: New testcase. * gcc.dg/torture/pr77648-2.c: Likewise. From-SVN: r240303
Diffstat (limited to 'gcc/tree-ssa-structalias.c')
-rw-r--r--gcc/tree-ssa-structalias.c58
1 files changed, 42 insertions, 16 deletions
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index cbf509b..be892fd 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -3010,7 +3010,7 @@ process_constraint (constraint_t t)
process_constraint (new_constraint (tmplhs, rhs));
process_constraint (new_constraint (lhs, tmplhs));
}
- else if (rhs.type == ADDRESSOF && lhs.type == DEREF)
+ else if ((rhs.type != SCALAR || rhs.offset != 0) && lhs.type == DEREF)
{
/* Split into tmp = &rhs, *lhs = tmp */
struct constraint_expr tmplhs;
@@ -3747,7 +3747,7 @@ make_transitive_closure_constraints (varinfo_t vi)
{
struct constraint_expr lhs, rhs;
- /* VAR = *VAR; */
+ /* VAR = *(VAR + UNKNOWN); */
lhs.type = SCALAR;
lhs.var = vi->id;
lhs.offset = 0;
@@ -3757,6 +3757,23 @@ make_transitive_closure_constraints (varinfo_t vi)
process_constraint (new_constraint (lhs, rhs));
}
+/* Add constraints to that the solution of VI has all subvariables added. */
+
+static void
+make_any_offset_constraints (varinfo_t vi)
+{
+ struct constraint_expr lhs, rhs;
+
+ /* VAR = VAR + UNKNOWN; */
+ lhs.type = SCALAR;
+ lhs.var = vi->id;
+ lhs.offset = 0;
+ rhs.type = SCALAR;
+ rhs.var = vi->id;
+ rhs.offset = UNKNOWN_OFFSET;
+ process_constraint (new_constraint (lhs, rhs));
+}
+
/* Temporary storage for fake var decls. */
struct obstack fake_var_decl_obstack;
@@ -3902,15 +3919,12 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
&& (flags & EAF_NOESCAPE))
{
varinfo_t uses = get_call_use_vi (stmt);
+ varinfo_t tem = new_var_info (NULL_TREE, "callarg", true);
+ make_constraint_to (tem->id, arg);
+ make_any_offset_constraints (tem);
if (!(flags & EAF_DIRECT))
- {
- varinfo_t tem = new_var_info (NULL_TREE, "callarg", true);
- make_constraint_to (tem->id, arg);
- make_transitive_closure_constraints (tem);
- make_copy_constraint (uses, tem->id);
- }
- else
- make_constraint_to (uses->id, arg);
+ make_transitive_closure_constraints (tem);
+ make_copy_constraint (uses, tem->id);
returns_uses = true;
}
else if (flags & EAF_NOESCAPE)
@@ -3920,6 +3934,7 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
varinfo_t clobbers = get_call_clobber_vi (stmt);
varinfo_t tem = new_var_info (NULL_TREE, "callarg", true);
make_constraint_to (tem->id, arg);
+ make_any_offset_constraints (tem);
if (!(flags & EAF_DIRECT))
make_transitive_closure_constraints (tem);
make_copy_constraint (uses, tem->id);
@@ -3945,7 +3960,7 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results)
if (returns_uses)
{
rhsc.var = get_call_use_vi (stmt)->id;
- rhsc.offset = 0;
+ rhsc.offset = UNKNOWN_OFFSET;
rhsc.type = SCALAR;
results->safe_push (rhsc);
}
@@ -4054,6 +4069,7 @@ handle_const_call (gcall *stmt, vec<ce_s> *results)
if (gimple_call_chain (stmt))
{
varinfo_t uses = get_call_use_vi (stmt);
+ make_any_offset_constraints (uses);
make_transitive_closure_constraints (uses);
make_constraint_to (uses->id, gimple_call_chain (stmt));
rhsc.var = uses->id;
@@ -4062,16 +4078,24 @@ handle_const_call (gcall *stmt, vec<ce_s> *results)
results->safe_push (rhsc);
}
- /* May return arguments. */
+ /* May return offsetted arguments. */
+ varinfo_t tem = NULL;
+ if (gimple_call_num_args (stmt) != 0)
+ tem = new_var_info (NULL_TREE, "callarg", true);
for (k = 0; k < gimple_call_num_args (stmt); ++k)
{
tree arg = gimple_call_arg (stmt, k);
auto_vec<ce_s> argc;
- unsigned i;
- struct constraint_expr *argp;
get_constraint_for_rhs (arg, &argc);
- FOR_EACH_VEC_ELT (argc, i, argp)
- results->safe_push (*argp);
+ make_constraints_to (tem->id, argc);
+ }
+ if (tem)
+ {
+ ce_s ce;
+ ce.type = SCALAR;
+ ce.var = tem->id;
+ ce.offset = UNKNOWN_OFFSET;
+ results->safe_push (ce);
}
/* May return addresses of globals. */
@@ -4098,6 +4122,7 @@ handle_pure_call (gcall *stmt, vec<ce_s> *results)
if (!uses)
{
uses = get_call_use_vi (stmt);
+ make_any_offset_constraints (uses);
make_transitive_closure_constraints (uses);
}
make_constraint_to (uses->id, arg);
@@ -4109,6 +4134,7 @@ handle_pure_call (gcall *stmt, vec<ce_s> *results)
if (!uses)
{
uses = get_call_use_vi (stmt);
+ make_any_offset_constraints (uses);
make_transitive_closure_constraints (uses);
}
make_constraint_to (uses->id, gimple_call_chain (stmt));