re PR libstdc++/85116 (std::min_element does not optimize well with inlined predicate)

2018-04-26  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/85116
	* tree-ssa-loop-ch.c (do_while_loop_p): A do-while loop should
	have a loop exit from the single latch predecessor.  Remove
	case of header with just condition.
	(ch_base::copy_headers): Exclude infinite loops from any
	processing.
	(pass_ch::execute): Record exits.

	* gcc.dg/tree-ssa/copy-headers-2.c: New testcase.
	* gcc.dg/tree-ssa/copy-headers-3.c: Likewise.
	* gcc.dg/tree-ssa/copy-headers-4.c: Likewise.
	* gcc.dg/tree-ssa/loadpre6.c: Adjust.

From-SVN: r259672
This commit is contained in:
Richard Biener 2018-04-26 12:18:58 +00:00 committed by Richard Biener
parent ae05281f4a
commit 1c53fa8ca9
7 changed files with 104 additions and 10 deletions

View File

@ -1,3 +1,13 @@
2018-04-26 Richard Biener <rguenther@suse.de>
PR tree-optimization/85116
* tree-ssa-loop-ch.c (do_while_loop_p): A do-while loop should
have a loop exit from the single latch predecessor. Remove
case of header with just condition.
(ch_base::copy_headers): Exclude infinite loops from any
processing.
(pass_ch::execute): Record exits.
2018-04-26 Richard Biener <rguenther@suse.de> 2018-04-26 Richard Biener <rguenther@suse.de>
* tree-vect-data-refs.c (vect_get_data_access_cost): Get * tree-vect-data-refs.c (vect_get_data_access_cost): Get

View File

@ -1,3 +1,11 @@
2018-04-26 Richard Biener <rguenther@suse.de>
PR tree-optimization/85116
* gcc.dg/tree-ssa/copy-headers-2.c: New testcase.
* gcc.dg/tree-ssa/copy-headers-3.c: Likewise.
* gcc.dg/tree-ssa/copy-headers-4.c: Likewise.
* gcc.dg/tree-ssa/loadpre6.c: Adjust.
2018-04-25 Sebastian Peryt <sebastian.peryt@intel.com> 2018-04-25 Sebastian Peryt <sebastian.peryt@intel.com>
PR target/85473 PR target/85473

View File

@ -0,0 +1,17 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-ch2-details" } */
int *a, *b;
int test(int n, int k)
{
int it = 0;
while (++it < n)
{
if (it % k == 1)
a[it] = 0;
else
b[it] = 1;
}
}
/* { dg-final { scan-tree-dump "is now do-while loop" "ch2" } } */

View File

@ -0,0 +1,19 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fgimple -fdump-tree-ch2-details" } */
int __GIMPLE (startwith("ch"))
test2 (int n)
{
bb_3:
if (n_1(D) > 0)
goto bb_3;
else
goto bb_4;
bb_4:
return;
}
/* { dg-final { scan-tree-dump "is do-while loop" "ch2" } } */
/* { dg-final { scan-tree-dump-not "is not do-while loop" "ch2" } } */

View File

@ -0,0 +1,18 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-ch2-details" } */
int *a, *b;
int test(int n, int k)
{
int it = 0;
do
{
if (it % k == 1)
a[it] = 0;
else
b[it] = 1;
}
while (++it < n);
}
/* { dg-final { scan-tree-dump-not "is not do-while loop" "ch2" } } */

View File

@ -75,4 +75,4 @@ main (void)
/* { dg-final { scan-tree-dump-not "= unexpanded_var_list;" "fre1" } } */ /* { dg-final { scan-tree-dump-not "= unexpanded_var_list;" "fre1" } } */
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ /* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */
/* { dg-final { scan-tree-dump-times "Insertions: 2" 1 "pre" } } */ /* { dg-final { scan-tree-dump-times "Insertions: 1" 1 "pre" } } */

View File

@ -165,17 +165,28 @@ do_while_loop_p (struct loop *loop)
return false; return false;
} }
/* If the header contains just a condition, it is not a do-while loop. */ /* If the latch does not have a single predecessor, it is not a
stmt = last_and_only_stmt (loop->header); do-while loop. */
if (stmt if (!single_pred_p (loop->latch))
&& gimple_code (stmt) == GIMPLE_COND)
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, fprintf (dump_file,
"Loop %i is not do-while loop: " "Loop %i is not do-while loop: latch has multiple "
"header contains just condition.\n", loop->num); "predecessors.\n", loop->num);
return false; return false;
} }
/* If the latch predecessor doesn't exit the loop, it is not a
do-while loop. */
if (!loop_exits_from_bb_p (loop, single_pred (loop->latch)))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
"Loop %i is not do-while loop: latch predecessor "
"does not exit loop.\n", loop->num);
return false;
}
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Loop %i is do-while loop\n", loop->num); fprintf (dump_file, "Loop %i is do-while loop\n", loop->num);
@ -305,8 +316,9 @@ ch_base::copy_headers (function *fun)
/* If the loop is already a do-while style one (either because it was /* If the loop is already a do-while style one (either because it was
written as such, or because jump threading transformed it into one), written as such, or because jump threading transformed it into one),
we might be in fact peeling the first iteration of the loop. This we might be in fact peeling the first iteration of the loop. This
in general is not a good idea. */ in general is not a good idea. Also avoid touching infinite loops. */
if (!process_loop_p (loop)) if (!loop_has_exit_edges (loop)
|| !process_loop_p (loop))
continue; continue;
/* Iterate the header copying up to limit; this takes care of the cases /* Iterate the header copying up to limit; this takes care of the cases
@ -392,6 +404,15 @@ ch_base::copy_headers (function *fun)
split_edge (loop_preheader_edge (loop)); split_edge (loop_preheader_edge (loop));
split_edge (loop_latch_edge (loop)); split_edge (loop_latch_edge (loop));
if (dump_file && (dump_flags & TDF_DETAILS))
{
if (do_while_loop_p (loop))
fprintf (dump_file, "Loop %d is now do-while loop.\n", loop->num);
else
fprintf (dump_file, "Loop %d is still not do-while loop.\n",
loop->num);
}
changed = true; changed = true;
} }
@ -409,7 +430,8 @@ unsigned int
pass_ch::execute (function *fun) pass_ch::execute (function *fun)
{ {
loop_optimizer_init (LOOPS_HAVE_PREHEADERS loop_optimizer_init (LOOPS_HAVE_PREHEADERS
| LOOPS_HAVE_SIMPLE_LATCHES); | LOOPS_HAVE_SIMPLE_LATCHES
| LOOPS_HAVE_RECORDED_EXITS);
unsigned int res = copy_headers (fun); unsigned int res = copy_headers (fun);