aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8/gcc/cfgloopanal.c
diff options
context:
space:
mode:
authorDan Albert <danalbert@google.com>2015-10-13 16:28:19 -0700
committerDan Albert <danalbert@google.com>2015-10-13 16:28:19 -0700
commita8c075f72b231c37823661ba0d7d082a21cd39d9 (patch)
tree395aa3b848d56037292e50466643453485073018 /gcc-4.8/gcc/cfgloopanal.c
parent5aff2e0142aca13849b4e51de503e71d5010efa6 (diff)
downloadtoolchain_gcc-a8c075f72b231c37823661ba0d7d082a21cd39d9.tar.gz
toolchain_gcc-a8c075f72b231c37823661ba0d7d082a21cd39d9.tar.bz2
toolchain_gcc-a8c075f72b231c37823661ba0d7d082a21cd39d9.zip
Remove gcc-4.8.
Change-Id: Iee9c6985c613f58c82e33a91722d371579eb290f
Diffstat (limited to 'gcc-4.8/gcc/cfgloopanal.c')
-rw-r--r--gcc-4.8/gcc/cfgloopanal.c517
1 files changed, 0 insertions, 517 deletions
diff --git a/gcc-4.8/gcc/cfgloopanal.c b/gcc-4.8/gcc/cfgloopanal.c
deleted file mode 100644
index b41701b82..000000000
--- a/gcc-4.8/gcc/cfgloopanal.c
+++ /dev/null
@@ -1,517 +0,0 @@
-/* Natural loop analysis code for GNU compiler.
- Copyright (C) 2002-2013 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "hard-reg-set.h"
-#include "obstack.h"
-#include "basic-block.h"
-#include "cfgloop.h"
-#include "expr.h"
-#include "graphds.h"
-#include "params.h"
-
-struct target_cfgloop default_target_cfgloop;
-#if SWITCHABLE_TARGET
-struct target_cfgloop *this_target_cfgloop = &default_target_cfgloop;
-#endif
-
-/* Checks whether BB is executed exactly once in each LOOP iteration. */
-
-bool
-just_once_each_iteration_p (const struct loop *loop, const_basic_block bb)
-{
- /* It must be executed at least once each iteration. */
- if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
- return false;
-
- /* And just once. */
- if (bb->loop_father != loop)
- return false;
-
- /* But this was not enough. We might have some irreducible loop here. */
- if (bb->flags & BB_IRREDUCIBLE_LOOP)
- return false;
-
- return true;
-}
-
-/* Marks blocks and edges that are part of non-recognized loops; i.e. we
- throw away all latch edges and mark blocks inside any remaining cycle.
- Everything is a bit complicated due to fact we do not want to do this
- for parts of cycles that only "pass" through some loop -- i.e. for
- each cycle, we want to mark blocks that belong directly to innermost
- loop containing the whole cycle.
-
- LOOPS is the loop tree. */
-
-#define LOOP_REPR(LOOP) ((LOOP)->num + last_basic_block)
-#define BB_REPR(BB) ((BB)->index + 1)
-
-bool
-mark_irreducible_loops (void)
-{
- basic_block act;
- struct graph_edge *ge;
- edge e;
- edge_iterator ei;
- int src, dest;
- unsigned depth;
- struct graph *g;
- int num = number_of_loops ();
- struct loop *cloop;
- bool irred_loop_found = false;
- int i;
-
- gcc_assert (current_loops != NULL);
-
- /* Reset the flags. */
- FOR_BB_BETWEEN (act, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
- {
- act->flags &= ~BB_IRREDUCIBLE_LOOP;
- FOR_EACH_EDGE (e, ei, act->succs)
- e->flags &= ~EDGE_IRREDUCIBLE_LOOP;
- }
-
- /* Create the edge lists. */
- g = new_graph (last_basic_block + num);
-
- FOR_BB_BETWEEN (act, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
- FOR_EACH_EDGE (e, ei, act->succs)
- {
- /* Ignore edges to exit. */
- if (e->dest == EXIT_BLOCK_PTR)
- continue;
-
- src = BB_REPR (act);
- dest = BB_REPR (e->dest);
-
- /* Ignore latch edges. */
- if (e->dest->loop_father->header == e->dest
- && e->dest->loop_father->latch == act)
- continue;
-
- /* Edges inside a single loop should be left where they are. Edges
- to subloop headers should lead to representative of the subloop,
- but from the same place.
-
- Edges exiting loops should lead from representative
- of the son of nearest common ancestor of the loops in that
- act lays. */
-
- if (e->dest->loop_father->header == e->dest)
- dest = LOOP_REPR (e->dest->loop_father);
-
- if (!flow_bb_inside_loop_p (act->loop_father, e->dest))
- {
- depth = 1 + loop_depth (find_common_loop (act->loop_father,
- e->dest->loop_father));
- if (depth == loop_depth (act->loop_father))
- cloop = act->loop_father;
- else
- cloop = (*act->loop_father->superloops)[depth];
-
- src = LOOP_REPR (cloop);
- }
-
- add_edge (g, src, dest)->data = e;
- }
-
- /* Find the strongly connected components. */
- graphds_scc (g, NULL);
-
- /* Mark the irreducible loops. */
- for (i = 0; i < g->n_vertices; i++)
- for (ge = g->vertices[i].succ; ge; ge = ge->succ_next)
- {
- edge real = (edge) ge->data;
- /* edge E in graph G is irreducible if it connects two vertices in the
- same scc. */
-
- /* All edges should lead from a component with higher number to the
- one with lower one. */
- gcc_assert (g->vertices[ge->src].component >= g->vertices[ge->dest].component);
-
- if (g->vertices[ge->src].component != g->vertices[ge->dest].component)
- continue;
-
- real->flags |= EDGE_IRREDUCIBLE_LOOP;
- irred_loop_found = true;
- if (flow_bb_inside_loop_p (real->src->loop_father, real->dest))
- real->src->flags |= BB_IRREDUCIBLE_LOOP;
- }
-
- free_graph (g);
-
- loops_state_set (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS);
- return irred_loop_found;
-}
-
-/* Counts number of insns inside LOOP. */
-int
-num_loop_insns (const struct loop *loop)
-{
- basic_block *bbs, bb;
- unsigned i, ninsns = 0;
- rtx insn;
-
- bbs = get_loop_body (loop);
- for (i = 0; i < loop->num_nodes; i++)
- {
- bb = bbs[i];
- FOR_BB_INSNS (bb, insn)
- if (NONDEBUG_INSN_P (insn))
- ninsns++;
- }
- free (bbs);
-
- if (!ninsns)
- ninsns = 1; /* To avoid division by zero. */
-
- return ninsns;
-}
-
-/* Counts number of insns executed on average per iteration LOOP. */
-int
-average_num_loop_insns (const struct loop *loop)
-{
- basic_block *bbs, bb;
- unsigned i, binsns, ninsns, ratio;
- rtx insn;
-
- ninsns = 0;
- bbs = get_loop_body (loop);
- for (i = 0; i < loop->num_nodes; i++)
- {
- bb = bbs[i];
-
- binsns = 0;
- FOR_BB_INSNS (bb, insn)
- if (NONDEBUG_INSN_P (insn))
- binsns++;
-
- ratio = loop->header->frequency == 0
- ? BB_FREQ_MAX
- : (bb->frequency * BB_FREQ_MAX) / loop->header->frequency;
- ninsns += binsns * ratio;
- }
- free (bbs);
-
- ninsns /= BB_FREQ_MAX;
- if (!ninsns)
- ninsns = 1; /* To avoid division by zero. */
-
- return ninsns;
-}
-
-/* Returns expected number of iterations of LOOP, according to
- measured or guessed profile. No bounding is done on the
- value. */
-
-gcov_type
-expected_loop_iterations_unbounded (const struct loop *loop)
-{
- edge e;
- edge_iterator ei;
-
- if (loop->latch->count || loop->header->count)
- {
- gcov_type count_in, count_latch, expected;
-
- count_in = 0;
- count_latch = 0;
-
- FOR_EACH_EDGE (e, ei, loop->header->preds)
- if (e->src == loop->latch)
- count_latch = e->count;
- else
- count_in += e->count;
-
- if (count_in == 0)
- expected = count_latch * 2;
- else
- expected = (count_latch + count_in - 1) / count_in;
-
- return expected;
- }
- else
- {
- int freq_in, freq_latch;
-
- freq_in = 0;
- freq_latch = 0;
-
- FOR_EACH_EDGE (e, ei, loop->header->preds)
- if (e->src == loop->latch)
- freq_latch = EDGE_FREQUENCY (e);
- else
- freq_in += EDGE_FREQUENCY (e);
-
- if (freq_in == 0)
- return freq_latch * 2;
-
- return (freq_latch + freq_in - 1) / freq_in;
- }
-}
-
-/* Returns expected number of LOOP iterations. The returned value is bounded
- by REG_BR_PROB_BASE. */
-
-unsigned
-expected_loop_iterations (const struct loop *loop)
-{
- gcov_type expected = expected_loop_iterations_unbounded (loop);
- return (expected > REG_BR_PROB_BASE ? REG_BR_PROB_BASE : expected);
-}
-
-/* Returns the maximum level of nesting of subloops of LOOP. */
-
-unsigned
-get_loop_level (const struct loop *loop)
-{
- const struct loop *ploop;
- unsigned mx = 0, l;
-
- for (ploop = loop->inner; ploop; ploop = ploop->next)
- {
- l = get_loop_level (ploop);
- if (l >= mx)
- mx = l + 1;
- }
- return mx;
-}
-
-/* Returns estimate on cost of computing SEQ. */
-
-static unsigned
-seq_cost (const_rtx seq, bool speed)
-{
- unsigned cost = 0;
- rtx set;
-
- for (; seq; seq = NEXT_INSN (seq))
- {
- set = single_set (seq);
- if (set)
- cost += set_rtx_cost (set, speed);
- else
- cost++;
- }
-
- return cost;
-}
-
-/* Initialize the constants for computing set costs. */
-
-void
-init_set_costs (void)
-{
- int speed;
- rtx seq;
- rtx reg1 = gen_raw_REG (SImode, FIRST_PSEUDO_REGISTER);
- rtx reg2 = gen_raw_REG (SImode, FIRST_PSEUDO_REGISTER + 1);
- rtx addr = gen_raw_REG (Pmode, FIRST_PSEUDO_REGISTER + 2);
- rtx mem = validize_mem (gen_rtx_MEM (SImode, addr));
- unsigned i;
-
- target_avail_regs = 0;
- target_clobbered_regs = 0;
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], i)
- && !fixed_regs[i])
- {
- target_avail_regs++;
- if (call_used_regs[i])
- target_clobbered_regs++;
- }
-
- target_res_regs = 3;
-
- for (speed = 0; speed < 2; speed++)
- {
- crtl->maybe_hot_insn_p = speed;
- /* Set up the costs for using extra registers:
-
- 1) If not many free registers remain, we should prefer having an
- additional move to decreasing the number of available registers.
- (TARGET_REG_COST).
- 2) If no registers are available, we need to spill, which may require
- storing the old value to memory and loading it back
- (TARGET_SPILL_COST). */
-
- start_sequence ();
- emit_move_insn (reg1, reg2);
- seq = get_insns ();
- end_sequence ();
- target_reg_cost [speed] = seq_cost (seq, speed);
-
- start_sequence ();
- emit_move_insn (mem, reg1);
- emit_move_insn (reg2, mem);
- seq = get_insns ();
- end_sequence ();
- target_spill_cost [speed] = seq_cost (seq, speed);
- }
- default_rtl_profile ();
-}
-
-/* Estimates cost of increased register pressure caused by making N_NEW new
- registers live around the loop. N_OLD is the number of registers live
- around the loop. If CALL_P is true, also take into account that
- call-used registers may be clobbered in the loop body, reducing the
- number of available registers before we spill. */
-
-unsigned
-estimate_reg_pressure_cost (unsigned n_new, unsigned n_old, bool speed,
- bool call_p)
-{
- unsigned cost;
- unsigned regs_needed = n_new + n_old;
- unsigned available_regs = target_avail_regs;
-
- /* If there is a call in the loop body, the call-clobbered registers
- are not available for loop invariants. */
- if (call_p)
- available_regs = available_regs - target_clobbered_regs;
-
- /* If we have enough registers, we should use them and not restrict
- the transformations unnecessarily. */
- if (regs_needed + target_res_regs <= available_regs)
- return 0;
-
- if (regs_needed <= available_regs)
- /* If we are close to running out of registers, try to preserve
- them. */
- cost = target_reg_cost [speed] * n_new;
- else
- /* If we run out of registers, it is very expensive to add another
- one. */
- cost = target_spill_cost [speed] * n_new;
-
- if (optimize && (flag_ira_region == IRA_REGION_ALL
- || flag_ira_region == IRA_REGION_MIXED)
- && number_of_loops () <= (unsigned) IRA_MAX_LOOPS_NUM)
- /* IRA regional allocation deals with high register pressure
- better. So decrease the cost (to do more accurate the cost
- calculation for IRA, we need to know how many registers lives
- through the loop transparently). */
- cost /= 2;
-
- return cost;
-}
-
-/* Sets EDGE_LOOP_EXIT flag for all loop exits. */
-
-void
-mark_loop_exit_edges (void)
-{
- basic_block bb;
- edge e;
-
- if (number_of_loops () <= 1)
- return;
-
- FOR_EACH_BB (bb)
- {
- edge_iterator ei;
-
- FOR_EACH_EDGE (e, ei, bb->succs)
- {
- if (loop_outer (bb->loop_father)
- && loop_exit_edge_p (bb->loop_father, e))
- e->flags |= EDGE_LOOP_EXIT;
- else
- e->flags &= ~EDGE_LOOP_EXIT;
- }
- }
-}
-
-/* Return exit edge if loop has only one exit that is likely
- to be executed on runtime (i.e. it is not EH or leading
- to noreturn call. */
-
-edge
-single_likely_exit (struct loop *loop)
-{
- edge found = single_exit (loop);
- vec<edge> exits;
- unsigned i;
- edge ex;
-
- if (found)
- return found;
- exits = get_loop_exit_edges (loop);
- FOR_EACH_VEC_ELT (exits, i, ex)
- {
- if (ex->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
- continue;
- /* The constant of 5 is set in a way so noreturn calls are
- ruled out by this test. The static branch prediction algorithm
- will not assign such a low probability to conditionals for usual
- reasons. */
- if (profile_status != PROFILE_ABSENT
- && ex->probability < 5 && !ex->count)
- continue;
- if (!found)
- found = ex;
- else
- {
- exits.release ();
- return NULL;
- }
- }
- exits.release ();
- return found;
-}
-
-
-/* Gets basic blocks of a LOOP. Header is the 0-th block, rest is in dfs
- order against direction of edges from latch. Specially, if
- header != latch, latch is the 1-st block. */
-
-vec<basic_block>
-get_loop_hot_path (const struct loop *loop)
-{
- basic_block bb = loop->header;
- vec<basic_block> path = vNULL;
- bitmap visited = BITMAP_ALLOC (NULL);
-
- while (true)
- {
- edge_iterator ei;
- edge e;
- edge best = NULL;
-
- path.safe_push (bb);
- bitmap_set_bit (visited, bb->index);
- FOR_EACH_EDGE (e, ei, bb->succs)
- if ((!best || e->probability > best->probability)
- && !loop_exit_edge_p (loop, e)
- && !bitmap_bit_p (visited, e->dest->index))
- best = e;
- if (!best || best->dest == loop->header)
- break;
- bb = best->dest;
- }
- BITMAP_FREE (visited);
- return path;
-}