summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-ch.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-05-02 14:43:35 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-05-02 14:43:35 +0000
commit34efdaf078b01a7387007c4e6bde6db86384c4b7 (patch)
treed503eaf41d085669d1481bb46ec038bc866fece6 /gcc/tree-ssa-loop-ch.c
parentf733cf303bcdc952c92b81dd62199a40a1f555ec (diff)
downloadgcc-tarball-master.tar.gz
gcc-7.1.0gcc-7.1.0
Diffstat (limited to 'gcc/tree-ssa-loop-ch.c')
-rw-r--r--gcc/tree-ssa-loop-ch.c107
1 files changed, 84 insertions, 23 deletions
diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c
index 907525627d..86be34a1ac 100644
--- a/gcc/tree-ssa-loop-ch.c
+++ b/gcc/tree-ssa-loop-ch.c
@@ -1,5 +1,5 @@
/* Loop header copying on trees.
- Copyright (C) 2004-2016 Free Software Foundation, Inc.
+ Copyright (C) 2004-2017 Free Software Foundation, Inc.
This file is part of GCC.
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "tree-ssa-scopedtables.h"
#include "tree-ssa-threadedge.h"
+#include "params.h"
/* Duplicates headers of loops if they are small enough, so that the statements
in the loop body are always executed when the loop is entered. This
@@ -50,36 +51,63 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop,
gimple_stmt_iterator bsi;
gimple *last;
- /* Do not copy one block more than once (we do not really want to do
- loop peeling here). */
- if (header->aux)
- return false;
+ gcc_assert (!header->aux);
/* Loop header copying usually increases size of the code. This used not to
be true, since quite often it is possible to verify that the condition is
satisfied in the first iteration and therefore to eliminate it. Jump
threading handles these cases now. */
if (optimize_loop_for_size_p (loop))
- return false;
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ " Not duplicating bb %i: optimizing for size.\n",
+ header->index);
+ return false;
+ }
gcc_assert (EDGE_COUNT (header->succs) > 0);
if (single_succ_p (header))
- return false;
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ " Not duplicating bb %i: it is single succ.\n",
+ header->index);
+ return false;
+ }
+
if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest)
&& flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 1)->dest))
- return false;
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ " Not duplicating bb %i: both sucessors are in loop.\n",
+ loop->num);
+ return false;
+ }
/* If this is not the original loop header, we want it to have just
one predecessor in order to match the && pattern. */
if (header != loop->header && !single_pred_p (header))
- return false;
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ " Not duplicating bb %i: it has mutiple predecestors.\n",
+ header->index);
+ return false;
+ }
last = last_stmt (header);
if (gimple_code (last) != GIMPLE_COND)
- return false;
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ " Not duplicating bb %i: it does not end by conditional.\n",
+ header->index);
+ return false;
+ }
- /* Approximately copy the conditions that used to be used in jump.c --
- at most 20 insns and no calls. */
+ /* Count number of instructions and punt on calls. */
for (bsi = gsi_start_bb (header); !gsi_end_p (bsi); gsi_next (&bsi))
{
last = gsi_stmt (bsi);
@@ -90,14 +118,28 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop,
if (is_gimple_debug (last))
continue;
- if (is_gimple_call (last))
- return false;
+ if (gimple_code (last) == GIMPLE_CALL
+ && !gimple_inexpensive_call_p (as_a <gcall *> (last)))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ " Not duplicating bb %i: it contains call.\n",
+ header->index);
+ return false;
+ }
*limit -= estimate_num_insns (last, &eni_size_weights);
if (*limit < 0)
- return false;
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ " Not duplicating bb %i contains too many insns.\n",
+ header->index);
+ return false;
+ }
}
-
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " Will duplicate bb %i\n", header->index);
return true;
}
@@ -111,13 +153,27 @@ do_while_loop_p (struct loop *loop)
/* If the latch of the loop is not empty, it is not a do-while loop. */
if (stmt
&& gimple_code (stmt) != GIMPLE_LABEL)
- return false;
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Loop %i is not do-while loop: latch is not empty.\n",
+ loop->num);
+ 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)
- return false;
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Loop %i is not do-while loop: "
+ "header contains just condition.\n", loop->num);
+ return false;
+ }
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Loop %i is do-while loop\n", loop->num);
return true;
}
@@ -234,8 +290,11 @@ ch_base::copy_headers (function *fun)
FOR_EACH_LOOP (loop, 0)
{
- /* Copy at most 20 insns. */
- int limit = 20;
+ int initial_limit = PARAM_VALUE (PARAM_MAX_LOOP_HEADER_INSNS);
+ int remaining_limit = initial_limit;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Analyzing loop %i\n", loop->num);
header = loop->header;
@@ -254,7 +313,7 @@ ch_base::copy_headers (function *fun)
exit = NULL;
n_bbs = 0;
- while (should_duplicate_loop_header_p (header, loop, &limit))
+ while (should_duplicate_loop_header_p (header, loop, &remaining_limit))
{
/* Find a successor of header that is inside a loop; i.e. the new
header after the condition is copied. */
@@ -272,8 +331,10 @@ ch_base::copy_headers (function *fun)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
- "Duplicating header of the loop %d up to edge %d->%d.\n",
- loop->num, exit->src->index, exit->dest->index);
+ "Duplicating header of the loop %d up to edge %d->%d,"
+ " %i insns.\n",
+ loop->num, exit->src->index, exit->dest->index,
+ initial_limit - remaining_limit);
/* Ensure that the header will have just the latch as a predecessor
inside the loop. */