diff options
author | Richard Biener <rguenther@suse.de> | 2016-09-21 07:38:33 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2016-09-21 07:38:33 +0000 |
commit | 6811ea797651caab6df9cf6ce4237ca4eaf1399e (patch) | |
tree | 36c2c41787ff92e38461f73aa58c90f4c18f8a37 /gcc/tree-ssa-structalias.c | |
parent | f955c4c4837a491a8e8c3962867f276a94125dde (diff) | |
download | gcc-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.c | 58 |
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)); |