From 1c53fa8ca9912f6acf8c3c8cec31d647bd8ba691 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 26 Apr 2018 12:18:58 +0000 Subject: [PATCH] re PR libstdc++/85116 (std::min_element does not optimize well with inlined predicate) 2018-04-26 Richard Biener 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 --- gcc/ChangeLog | 10 +++++++ gcc/testsuite/ChangeLog | 8 ++++++ gcc/testsuite/gcc.dg/tree-ssa/copy-headers-2.c | 17 +++++++++++ gcc/testsuite/gcc.dg/tree-ssa/copy-headers-3.c | 19 ++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/copy-headers-4.c | 18 ++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/loadpre6.c | 2 +- gcc/tree-ssa-loop-ch.c | 40 ++++++++++++++++++++------ 7 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/copy-headers-2.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/copy-headers-3.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/copy-headers-4.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6132444..2fed948 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,15 @@ 2018-04-26 Richard Biener + 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 + * tree-vect-data-refs.c (vect_get_data_access_cost): Get prologue cost vector and pass it to vect_get_load_cost. (vect_get_peeling_costs_all_drs): Likewise. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a62a9cb..a4d32ec 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2018-04-26 Richard Biener + + 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 PR target/85473 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-2.c b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-2.c new file mode 100644 index 0000000..7f1bfe1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-2.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-3.c b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-3.c new file mode 100644 index 0000000..6b63cdf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-3.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-4.c b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-4.c new file mode 100644 index 0000000..88466c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-4.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre6.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre6.c index 2224891..028becd 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/loadpre6.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre6.c @@ -75,4 +75,4 @@ main (void) /* { 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 "Insertions: 2" 1 "pre" } } */ +/* { dg-final { scan-tree-dump-times "Insertions: 1" 1 "pre" } } */ diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c index 488999d..6b5c82c 100644 --- a/gcc/tree-ssa-loop-ch.c +++ b/gcc/tree-ssa-loop-ch.c @@ -165,17 +165,28 @@ do_while_loop_p (struct loop *loop) return false; } - /* If the header contains just a condition, it is not a do-while loop. */ - stmt = last_and_only_stmt (loop->header); - if (stmt - && gimple_code (stmt) == GIMPLE_COND) + /* If the latch does not have a single predecessor, it is not a + do-while loop. */ + if (!single_pred_p (loop->latch)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, + "Loop %i is not do-while loop: latch has multiple " + "predecessors.\n", loop->num); + 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: " - "header contains just condition.\n", loop->num); + "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)) 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 written as such, or because jump threading transformed it into one), we might be in fact peeling the first iteration of the loop. This - in general is not a good idea. */ - if (!process_loop_p (loop)) + in general is not a good idea. Also avoid touching infinite loops. */ + if (!loop_has_exit_edges (loop) + || !process_loop_p (loop)) continue; /* 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_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; } @@ -409,7 +430,8 @@ unsigned int pass_ch::execute (function *fun) { loop_optimizer_init (LOOPS_HAVE_PREHEADERS - | LOOPS_HAVE_SIMPLE_LATCHES); + | LOOPS_HAVE_SIMPLE_LATCHES + | LOOPS_HAVE_RECORDED_EXITS); unsigned int res = copy_headers (fun); -- 2.7.4