Commit 4af3b0ea by Martin Liska Committed by Martin Liska

Test for not existence of a negative loop (PR gcov-profile/90380).

2019-05-13  Martin Liska  <mliska@suse.cz>

	PR gcov-profile/90380
	* gcov.c (enum loop_type): Remove the enum and
	the operator.
	(handle_cycle): Assert that we should not reach
	a negative count.
	(circuit): Use loop_found instead of a tri-state loop_type.
	(get_cycles_count): Do not handle NEGATIVE_LOOP as it can't
	happen.

From-SVN: r271116
parent 15f3429d
2019-05-13 Martin Liska <mliska@suse.cz>
PR gcov-profile/90380
* gcov.c (enum loop_type): Remove the enum and
the operator.
(handle_cycle): Assert that we should not reach
a negative count.
(circuit): Use loop_found instead of a tri-state loop_type.
(get_cycles_count): Do not handle NEGATIVE_LOOP as it can't
happen.
2019-05-12 Iain Sandoe <iain@sandoe.co.uk> 2019-05-12 Iain Sandoe <iain@sandoe.co.uk>
PR target/82920 PR target/82920
......
...@@ -676,27 +676,11 @@ bool function_info::group_line_p (unsigned n, unsigned src_idx) ...@@ -676,27 +676,11 @@ bool function_info::group_line_p (unsigned n, unsigned src_idx)
typedef vector<arc_info *> arc_vector_t; typedef vector<arc_info *> arc_vector_t;
typedef vector<const block_info *> block_vector_t; typedef vector<const block_info *> block_vector_t;
/* Enum with types of loop in CFG. */
enum loop_type
{
NO_LOOP = 0,
LOOP = 1,
NEGATIVE_LOOP = 3
};
/* Loop_type operator that merges two values: A and B. */
inline loop_type& operator |= (loop_type& a, loop_type b)
{
return a = static_cast<loop_type> (a | b);
}
/* Handle cycle identified by EDGES, where the function finds minimum cs_count /* Handle cycle identified by EDGES, where the function finds minimum cs_count
and subtract the value from all counts. The subtracted value is added and subtract the value from all counts. The subtracted value is added
to COUNT. Returns type of loop. */ to COUNT. Returns type of loop. */
static loop_type static void
handle_cycle (const arc_vector_t &edges, int64_t &count) handle_cycle (const arc_vector_t &edges, int64_t &count)
{ {
/* Find the minimum edge of the cycle, and reduce all nodes in the cycle by /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
...@@ -712,7 +696,7 @@ handle_cycle (const arc_vector_t &edges, int64_t &count) ...@@ -712,7 +696,7 @@ handle_cycle (const arc_vector_t &edges, int64_t &count)
for (unsigned i = 0; i < edges.size (); i++) for (unsigned i = 0; i < edges.size (); i++)
edges[i]->cs_count -= cycle_count; edges[i]->cs_count -= cycle_count;
return cycle_count < 0 ? NEGATIVE_LOOP : LOOP; gcc_assert (cycle_count >= 0);
} }
/* Unblock a block U from BLOCKED. Apart from that, iterate all blocks /* Unblock a block U from BLOCKED. Apart from that, iterate all blocks
...@@ -743,12 +727,12 @@ unblock (const block_info *u, block_vector_t &blocked, ...@@ -743,12 +727,12 @@ unblock (const block_info *u, block_vector_t &blocked,
blocked by a block. COUNT is accumulated count of the current LINE. blocked by a block. COUNT is accumulated count of the current LINE.
Returns what type of loop it contains. */ Returns what type of loop it contains. */
static loop_type static bool
circuit (block_info *v, arc_vector_t &path, block_info *start, circuit (block_info *v, arc_vector_t &path, block_info *start,
block_vector_t &blocked, vector<block_vector_t> &block_lists, block_vector_t &blocked, vector<block_vector_t> &block_lists,
line_info &linfo, int64_t &count) line_info &linfo, int64_t &count)
{ {
loop_type result = NO_LOOP; bool loop_found = false;
/* Add v to the block list. */ /* Add v to the block list. */
gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ()); gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ());
...@@ -763,15 +747,19 @@ circuit (block_info *v, arc_vector_t &path, block_info *start, ...@@ -763,15 +747,19 @@ circuit (block_info *v, arc_vector_t &path, block_info *start,
path.push_back (arc); path.push_back (arc);
if (w == start) if (w == start)
/* Cycle has been found. */ {
result |= handle_cycle (path, count); /* Cycle has been found. */
handle_cycle (path, count);
loop_found = true;
}
else if (find (blocked.begin (), blocked.end (), w) == blocked.end ()) else if (find (blocked.begin (), blocked.end (), w) == blocked.end ())
result |= circuit (w, path, start, blocked, block_lists, linfo, count); loop_found |= circuit (w, path, start, blocked, block_lists, linfo,
count);
path.pop_back (); path.pop_back ();
} }
if (result != NO_LOOP) if (loop_found)
unblock (v, blocked, block_lists); unblock (v, blocked, block_lists);
else else
for (arc_info *arc = v->succ; arc; arc = arc->succ_next) for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
...@@ -788,14 +776,13 @@ circuit (block_info *v, arc_vector_t &path, block_info *start, ...@@ -788,14 +776,13 @@ circuit (block_info *v, arc_vector_t &path, block_info *start,
list.push_back (v); list.push_back (v);
} }
return result; return loop_found;
} }
/* Find cycles for a LINFO. If HANDLE_NEGATIVE_CYCLES is set and the line /* Find cycles for a LINFO. */
contains a negative loop, then perform the same function once again. */
static gcov_type static gcov_type
get_cycles_count (line_info &linfo, bool handle_negative_cycles = true) get_cycles_count (line_info &linfo)
{ {
/* Note that this algorithm works even if blocks aren't in sorted order. /* Note that this algorithm works even if blocks aren't in sorted order.
Each iteration of the circuit detection is completely independent Each iteration of the circuit detection is completely independent
...@@ -803,7 +790,7 @@ get_cycles_count (line_info &linfo, bool handle_negative_cycles = true) ...@@ -803,7 +790,7 @@ get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
Therefore, operating on a permuted order (i.e., non-sorted) only Therefore, operating on a permuted order (i.e., non-sorted) only
has the effect of permuting the output cycles. */ has the effect of permuting the output cycles. */
loop_type result = NO_LOOP; bool loop_found = false;
gcov_type count = 0; gcov_type count = 0;
for (vector<block_info *>::iterator it = linfo.blocks.begin (); for (vector<block_info *>::iterator it = linfo.blocks.begin ();
it != linfo.blocks.end (); it++) it != linfo.blocks.end (); it++)
...@@ -811,14 +798,10 @@ get_cycles_count (line_info &linfo, bool handle_negative_cycles = true) ...@@ -811,14 +798,10 @@ get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
arc_vector_t path; arc_vector_t path;
block_vector_t blocked; block_vector_t blocked;
vector<block_vector_t > block_lists; vector<block_vector_t > block_lists;
result |= circuit (*it, path, *it, blocked, block_lists, linfo, loop_found |= circuit (*it, path, *it, blocked, block_lists, linfo,
count); count);
} }
/* If we have a negative cycle, repeat the find_cycles routine. */
if (result == NEGATIVE_LOOP && handle_negative_cycles)
count += get_cycles_count (linfo, false);
return count; return count;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment