mirror of git://gcc.gnu.org/git/gcc.git
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:
parent
ae05281f4a
commit
1c53fa8ca9
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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" } } */
|
||||||
|
|
@ -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" } } */
|
||||||
|
|
@ -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" } } */
|
||||||
|
|
@ -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" } } */
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue