tree-optimization/98213 - cache PHI walking result in SM

This avoids exponential work when walking PHIs in loop store motion.
Fails are quickly propagated and thus need no caching.

2020-12-09  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/98213
	* tree-ssa-loop-im.c (sm_seq_valid_bb): Cache successfully
	processed PHIs.
	(hoist_memory_references): Adjust.

	* g++.dg/pr98213.C: New testcase.
This commit is contained in:
Richard Biener 2020-12-09 15:48:36 +01:00
parent 0b37233152
commit 84d08255f9
2 changed files with 38 additions and 6 deletions

View file

@ -0,0 +1,24 @@
/* { dg-do compile } */
/* { dg-options "-O3" } */
#include <algorithm>
long var_23;
int var_24, test_var_8;
extern bool arr_20[][13];
char arr_21_0_0_0_0_0;
int *test_arr_0;
void test(unsigned long long var_1)
{
int arr_16;
for (int i_0 = 0;;)
for (int i_5; i_5;) {
for (int i_6 = 0; i_6 < 19; i_6 += 4)
for (long i_7(test_var_8); i_7; i_7 += 2) {
arr_20[0][i_7] = arr_21_0_0_0_0_0 = 0;
var_23 = test_arr_0[0];
}
var_24 = std::max((unsigned long long)arr_16,
std::min((unsigned long long)5, var_1));
}
}

View file

@ -2254,7 +2254,8 @@ sm_seq_push_down (vec<seq_entry> &seq, unsigned ptr, unsigned *at)
static int static int
sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef, sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
vec<seq_entry> &seq, bitmap refs_not_in_seq, vec<seq_entry> &seq, bitmap refs_not_in_seq,
bitmap refs_not_supported, bool forked) bitmap refs_not_supported, bool forked,
bitmap fully_visited)
{ {
if (!vdef) if (!vdef)
for (gimple_stmt_iterator gsi = gsi_last_bb (bb); !gsi_end_p (gsi); for (gimple_stmt_iterator gsi = gsi_last_bb (bb); !gsi_end_p (gsi);
@ -2276,7 +2277,7 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
/* This handles the perfect nest case. */ /* This handles the perfect nest case. */
return sm_seq_valid_bb (loop, single_pred (bb), vdef, return sm_seq_valid_bb (loop, single_pred (bb), vdef,
seq, refs_not_in_seq, refs_not_supported, seq, refs_not_in_seq, refs_not_supported,
forked); forked, fully_visited);
return 0; return 0;
} }
do do
@ -2314,7 +2315,10 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
return sm_seq_valid_bb (loop, gimple_phi_arg_edge (phi, 0)->src, return sm_seq_valid_bb (loop, gimple_phi_arg_edge (phi, 0)->src,
gimple_phi_arg_def (phi, 0), seq, gimple_phi_arg_def (phi, 0), seq,
refs_not_in_seq, refs_not_supported, refs_not_in_seq, refs_not_supported,
false); false, fully_visited);
if (bitmap_bit_p (fully_visited,
SSA_NAME_VERSION (gimple_phi_result (phi))))
return 1;
auto_vec<seq_entry> first_edge_seq; auto_vec<seq_entry> first_edge_seq;
auto_bitmap tem_refs_not_in_seq (&lim_bitmap_obstack); auto_bitmap tem_refs_not_in_seq (&lim_bitmap_obstack);
int eret; int eret;
@ -2323,7 +2327,7 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
gimple_phi_arg_def (phi, 0), gimple_phi_arg_def (phi, 0),
first_edge_seq, first_edge_seq,
tem_refs_not_in_seq, refs_not_supported, tem_refs_not_in_seq, refs_not_supported,
true); true, fully_visited);
if (eret != 1) if (eret != 1)
return -1; return -1;
/* Simplify our lives by pruning the sequence of !sm_ord. */ /* Simplify our lives by pruning the sequence of !sm_ord. */
@ -2338,7 +2342,7 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
bitmap_copy (tem_refs_not_in_seq, refs_not_in_seq); bitmap_copy (tem_refs_not_in_seq, refs_not_in_seq);
eret = sm_seq_valid_bb (loop, e->src, vuse, edge_seq, eret = sm_seq_valid_bb (loop, e->src, vuse, edge_seq,
tem_refs_not_in_seq, refs_not_supported, tem_refs_not_in_seq, refs_not_supported,
true); true, fully_visited);
if (eret != 1) if (eret != 1)
return -1; return -1;
/* Simplify our lives by pruning the sequence of !sm_ord. */ /* Simplify our lives by pruning the sequence of !sm_ord. */
@ -2419,6 +2423,8 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree vdef,
seq[new_idx].from = NULL_TREE; seq[new_idx].from = NULL_TREE;
} }
} }
bitmap_set_bit (fully_visited,
SSA_NAME_VERSION (gimple_phi_result (phi)));
return 1; return 1;
} }
lim_aux_data *data = get_lim_data (def); lim_aux_data *data = get_lim_data (def);
@ -2494,9 +2500,11 @@ hoist_memory_references (class loop *loop, bitmap mem_refs,
seq.create (4); seq.create (4);
auto_bitmap refs_not_in_seq (&lim_bitmap_obstack); auto_bitmap refs_not_in_seq (&lim_bitmap_obstack);
bitmap_copy (refs_not_in_seq, mem_refs); bitmap_copy (refs_not_in_seq, mem_refs);
auto_bitmap fully_visited;
int res = sm_seq_valid_bb (loop, e->src, NULL_TREE, int res = sm_seq_valid_bb (loop, e->src, NULL_TREE,
seq, refs_not_in_seq, seq, refs_not_in_seq,
refs_not_supported, false); refs_not_supported, false,
fully_visited);
if (res != 1) if (res != 1)
{ {
bitmap_copy (refs_not_supported, mem_refs); bitmap_copy (refs_not_supported, mem_refs);