mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-02 16:23:56 +08:00
tree-scalar-evolution.h (final_value_replacement_loop): Update prototype.
2018-11-05 Richard Biener <rguenther@suse.de> * tree-scalar-evolution.h (final_value_replacement_loop): Update prototype. * tree-scalar-evolution.c (final_value_replacement_loop): Return whether anything was done. (scev_const_prop): Remove constant propagation part, fold remains into ... * tree-ssa-loop.c (pass_scev_cprop::execute): ... here. (pass_data_scev_cprop): TODO_cleanup_cfg is now done conditionally. * gcc.dg/pr41488.c: Scan ivcanon dump instead of sccp one. * gcc.dg/tree-ssa/scev-7.c: Likewise. From-SVN: r265795
This commit is contained in:
parent
18e0c3d171
commit
4cc31a3c4e
@ -1,3 +1,15 @@
|
|||||||
|
2018-11-05 Richard Biener <rguenther@suse.de>
|
||||||
|
|
||||||
|
* tree-scalar-evolution.h (final_value_replacement_loop): Update
|
||||||
|
prototype.
|
||||||
|
* tree-scalar-evolution.c (final_value_replacement_loop): Return
|
||||||
|
whether anything was done.
|
||||||
|
(scev_const_prop): Remove constant propagation part, fold
|
||||||
|
remains into ...
|
||||||
|
* tree-ssa-loop.c (pass_scev_cprop::execute): ... here.
|
||||||
|
(pass_data_scev_cprop): TODO_cleanup_cfg is now done
|
||||||
|
conditionally.
|
||||||
|
|
||||||
2018-11-05 Jakub Jelinek <jakub@redhat.com>
|
2018-11-05 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR tree-optimization/87859
|
PR tree-optimization/87859
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2018-11-05 Richard Biener <rguenther@suse.de>
|
||||||
|
|
||||||
|
* gcc.dg/pr41488.c: Scan ivcanon dump instead of sccp one.
|
||||||
|
* gcc.dg/tree-ssa/scev-7.c: Likewise.
|
||||||
|
|
||||||
2018-11-05 Jakub Jelinek <jakub@redhat.com>
|
2018-11-05 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR tree-optimization/87859
|
PR tree-optimization/87859
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* { dg-do compile } */
|
/* { dg-do compile } */
|
||||||
/* { dg-options "-O2 -fdump-tree-sccp-scev" } */
|
/* { dg-options "-O2 -fdump-tree-ivcanon-scev" } */
|
||||||
|
|
||||||
struct struct_t
|
struct struct_t
|
||||||
{
|
{
|
||||||
@ -14,4 +14,4 @@ void foo (struct struct_t* sp, int start, int end)
|
|||||||
sp->data[i+start] = 0;
|
sp->data[i+start] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* { dg-final { scan-tree-dump-times "Simplify PEELED_CHREC into POLYNOMIAL_CHREC" 1 "sccp" } } */
|
/* { dg-final { scan-tree-dump-times "Simplify PEELED_CHREC into POLYNOMIAL_CHREC" 1 "ivcanon" } } */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* { dg-do compile } */
|
/* { dg-do compile } */
|
||||||
/* { dg-options "-O2 -fdump-tree-sccp-scev" } */
|
/* { dg-options "-O2 -fdump-tree-ivcanon-scev" } */
|
||||||
|
|
||||||
struct struct_t
|
struct struct_t
|
||||||
{
|
{
|
||||||
@ -14,4 +14,4 @@ void foo (struct struct_t* sp, int start, int end)
|
|||||||
sp->data[i+start] = 0;
|
sp->data[i+start] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* { dg-final { scan-tree-dump-times "Simplify PEELED_CHREC into POLYNOMIAL_CHREC" 1 "sccp" } } */
|
/* { dg-final { scan-tree-dump-times "Simplify PEELED_CHREC into POLYNOMIAL_CHREC" 1 "ivcanon" } } */
|
||||||
|
@ -3537,20 +3537,20 @@ expression_expensive_p (tree expr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do final value replacement for LOOP. */
|
/* Do final value replacement for LOOP, return true if we did anything. */
|
||||||
|
|
||||||
void
|
bool
|
||||||
final_value_replacement_loop (struct loop *loop)
|
final_value_replacement_loop (struct loop *loop)
|
||||||
{
|
{
|
||||||
/* If we do not know exact number of iterations of the loop, we cannot
|
/* If we do not know exact number of iterations of the loop, we cannot
|
||||||
replace the final value. */
|
replace the final value. */
|
||||||
edge exit = single_exit (loop);
|
edge exit = single_exit (loop);
|
||||||
if (!exit)
|
if (!exit)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
tree niter = number_of_latch_executions (loop);
|
tree niter = number_of_latch_executions (loop);
|
||||||
if (niter == chrec_dont_know)
|
if (niter == chrec_dont_know)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
/* Ensure that it is possible to insert new statements somewhere. */
|
/* Ensure that it is possible to insert new statements somewhere. */
|
||||||
if (!single_pred_p (exit->dest))
|
if (!single_pred_p (exit->dest))
|
||||||
@ -3563,6 +3563,7 @@ final_value_replacement_loop (struct loop *loop)
|
|||||||
= superloop_at_depth (loop,
|
= superloop_at_depth (loop,
|
||||||
loop_depth (exit->dest->loop_father) + 1);
|
loop_depth (exit->dest->loop_father) + 1);
|
||||||
|
|
||||||
|
bool any = false;
|
||||||
gphi_iterator psi;
|
gphi_iterator psi;
|
||||||
for (psi = gsi_start_phis (exit->dest); !gsi_end_p (psi); )
|
for (psi = gsi_start_phis (exit->dest); !gsi_end_p (psi); )
|
||||||
{
|
{
|
||||||
@ -3620,6 +3621,7 @@ final_value_replacement_loop (struct loop *loop)
|
|||||||
fprintf (dump_file, " with expr: ");
|
fprintf (dump_file, " with expr: ");
|
||||||
print_generic_expr (dump_file, def);
|
print_generic_expr (dump_file, def);
|
||||||
}
|
}
|
||||||
|
any = true;
|
||||||
def = unshare_expr (def);
|
def = unshare_expr (def);
|
||||||
remove_phi_node (&psi, false);
|
remove_phi_node (&psi, false);
|
||||||
|
|
||||||
@ -3662,100 +3664,8 @@ final_value_replacement_loop (struct loop *loop)
|
|||||||
fprintf (dump_file, "\n");
|
fprintf (dump_file, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Replace ssa names for that scev can prove they are constant by the
|
return any;
|
||||||
appropriate constants. Also perform final value replacement in loops,
|
|
||||||
in case the replacement expressions are cheap.
|
|
||||||
|
|
||||||
We only consider SSA names defined by phi nodes; rest is left to the
|
|
||||||
ordinary constant propagation pass. */
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
scev_const_prop (void)
|
|
||||||
{
|
|
||||||
basic_block bb;
|
|
||||||
tree name, type, ev;
|
|
||||||
gphi *phi;
|
|
||||||
struct loop *loop;
|
|
||||||
bitmap ssa_names_to_remove = NULL;
|
|
||||||
unsigned i;
|
|
||||||
gphi_iterator psi;
|
|
||||||
|
|
||||||
if (number_of_loops (cfun) <= 1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
FOR_EACH_BB_FN (bb, cfun)
|
|
||||||
{
|
|
||||||
loop = bb->loop_father;
|
|
||||||
|
|
||||||
for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
|
|
||||||
{
|
|
||||||
phi = psi.phi ();
|
|
||||||
name = PHI_RESULT (phi);
|
|
||||||
|
|
||||||
if (virtual_operand_p (name))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
type = TREE_TYPE (name);
|
|
||||||
|
|
||||||
if (!POINTER_TYPE_P (type)
|
|
||||||
&& !INTEGRAL_TYPE_P (type))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ev = resolve_mixers (loop, analyze_scalar_evolution (loop, name),
|
|
||||||
NULL);
|
|
||||||
if (!is_gimple_min_invariant (ev)
|
|
||||||
|| !may_propagate_copy (name, ev))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Replace the uses of the name. */
|
|
||||||
if (name != ev)
|
|
||||||
{
|
|
||||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
|
||||||
{
|
|
||||||
fprintf (dump_file, "Replacing uses of: ");
|
|
||||||
print_generic_expr (dump_file, name);
|
|
||||||
fprintf (dump_file, " with: ");
|
|
||||||
print_generic_expr (dump_file, ev);
|
|
||||||
fprintf (dump_file, "\n");
|
|
||||||
}
|
|
||||||
replace_uses_by (name, ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ssa_names_to_remove)
|
|
||||||
ssa_names_to_remove = BITMAP_ALLOC (NULL);
|
|
||||||
bitmap_set_bit (ssa_names_to_remove, SSA_NAME_VERSION (name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the ssa names that were replaced by constants. We do not
|
|
||||||
remove them directly in the previous cycle, since this
|
|
||||||
invalidates scev cache. */
|
|
||||||
if (ssa_names_to_remove)
|
|
||||||
{
|
|
||||||
bitmap_iterator bi;
|
|
||||||
|
|
||||||
EXECUTE_IF_SET_IN_BITMAP (ssa_names_to_remove, 0, i, bi)
|
|
||||||
{
|
|
||||||
gimple_stmt_iterator psi;
|
|
||||||
name = ssa_name (i);
|
|
||||||
phi = as_a <gphi *> (SSA_NAME_DEF_STMT (name));
|
|
||||||
|
|
||||||
gcc_assert (gimple_code (phi) == GIMPLE_PHI);
|
|
||||||
psi = gsi_for_stmt (phi);
|
|
||||||
remove_phi_node (&psi, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
BITMAP_FREE (ssa_names_to_remove);
|
|
||||||
scev_reset ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now the regular final value replacement. */
|
|
||||||
FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
|
|
||||||
final_value_replacement_loop (loop);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "gt-tree-scalar-evolution.h"
|
#include "gt-tree-scalar-evolution.h"
|
||||||
|
@ -33,7 +33,7 @@ extern tree analyze_scalar_evolution (struct loop *, tree);
|
|||||||
extern tree instantiate_scev (edge, struct loop *, tree);
|
extern tree instantiate_scev (edge, struct loop *, tree);
|
||||||
extern tree resolve_mixers (struct loop *, tree, bool *);
|
extern tree resolve_mixers (struct loop *, tree, bool *);
|
||||||
extern void gather_stats_on_scev_database (void);
|
extern void gather_stats_on_scev_database (void);
|
||||||
extern void final_value_replacement_loop (struct loop *);
|
extern bool final_value_replacement_loop (struct loop *);
|
||||||
extern unsigned int scev_const_prop (void);
|
extern unsigned int scev_const_prop (void);
|
||||||
extern bool expression_expensive_p (tree);
|
extern bool expression_expensive_p (tree);
|
||||||
extern bool simple_iv_with_niters (struct loop *, struct loop *, tree,
|
extern bool simple_iv_with_niters (struct loop *, struct loop *, tree,
|
||||||
|
@ -436,8 +436,7 @@ const pass_data pass_data_scev_cprop =
|
|||||||
0, /* properties_provided */
|
0, /* properties_provided */
|
||||||
0, /* properties_destroyed */
|
0, /* properties_destroyed */
|
||||||
0, /* todo_flags_start */
|
0, /* todo_flags_start */
|
||||||
( TODO_cleanup_cfg
|
0, /* todo_flags_finish */
|
||||||
| TODO_update_ssa_only_virtuals ), /* todo_flags_finish */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class pass_scev_cprop : public gimple_opt_pass
|
class pass_scev_cprop : public gimple_opt_pass
|
||||||
@ -449,10 +448,24 @@ public:
|
|||||||
|
|
||||||
/* opt_pass methods: */
|
/* opt_pass methods: */
|
||||||
virtual bool gate (function *) { return flag_tree_scev_cprop; }
|
virtual bool gate (function *) { return flag_tree_scev_cprop; }
|
||||||
virtual unsigned int execute (function *) { return scev_const_prop (); }
|
virtual unsigned int execute (function *);
|
||||||
|
|
||||||
}; // class pass_scev_cprop
|
}; // class pass_scev_cprop
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
pass_scev_cprop::execute (function *)
|
||||||
|
{
|
||||||
|
struct loop *loop;
|
||||||
|
bool any = false;
|
||||||
|
|
||||||
|
/* Perform final value replacement in loops, in case the replacement
|
||||||
|
expressions are cheap. */
|
||||||
|
FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
|
||||||
|
any |= final_value_replacement_loop (loop);
|
||||||
|
|
||||||
|
return any ? TODO_cleanup_cfg | TODO_update_ssa_only_virtuals : 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // anon namespace
|
} // anon namespace
|
||||||
|
|
||||||
gimple_opt_pass *
|
gimple_opt_pass *
|
||||||
|
Loading…
Reference in New Issue
Block a user