[PATCH][PR tree-optimization/pr67755] Fix profile insanity adjustments

PR tree-optimization/pr67755
	* tree-ssa-threadupdate.c (struct ssa_local_info_t): Add new field
	"need_profile_correction".
	(thread_block_1): Initialize new field to false by default.  If we
	have multiple thread paths through a common joiner to different
	final targets, then set new field to true.
	(compute_path_counts): Only do count adjustment when it's really
	needed.

	PR tree-optimization/67755
	* gcc.dg/tree-ssa/pr67755.c: New test.

From-SVN: r232313
This commit is contained in:
Jeff Law 2016-01-12 21:17:36 -07:00
parent 5ee4820a1f
commit c6f72a4614
4 changed files with 62 additions and 2 deletions

View File

@ -1,3 +1,14 @@
2016-01-12 Jeff Law <law@redhat.com>
PR tree-optimization/pr67755
* tree-ssa-threadupdate.c (struct ssa_local_info_t): Add new field
"need_profile_correction".
(thread_block_1): Initialize new field to false by default. If we
have multiple thread paths through a common joiner to different
final targets, then set new field to true.
(compute_path_counts): Only do count adjustment when it's really
needed.
2016-01-12 Sandra Loosemore <sandra@codesourcery.com>
* doc/invoke.texi (Spec Files): Move section down in file, past

View File

@ -1,4 +1,9 @@
2015-01-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
2016-01-13 Jeff Law <law@redhat.com>
PR tree-optimization/67755
* gcc.dg/tree-ssa/pr67755.c: New test.
2016-01-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
* gcc.c-torture/unsorted/dump-noaddr.x (dump_compare): Replace static
pass number in output by a star.

View File

@ -0,0 +1,25 @@
/* { dg-do compile } */
/* { dg-options "-O1 -fdump-tree-dom2-details-blocks" } */
/* We want to verify no outgoing edge from a conditional
has a probability of 100%. */
/* { dg-final { scan-tree-dump-not "succ:\[ \]+. .100.0%. .\(TRUE|FALSE\)_VALUE" "dom2"} } */
void (*zend_block_interruptions) (void);
int * _zend_mm_alloc_int (int * heap, long int size)
{
int *best_fit;
long int true_size = (size < 15 ? 32 : size);
if (zend_block_interruptions)
zend_block_interruptions ();
if (__builtin_expect ((true_size < 543), 1))
best_fit = heap + 2;
else
best_fit = heap;
return best_fit;
}

View File

@ -239,6 +239,11 @@ struct ssa_local_info_t
/* Blocks duplicated for the thread. */
bitmap duplicate_blocks;
/* When we have multiple paths through a joiner which reach different
final destinations, then we may need to correct for potential
profile insanities. */
bool need_profile_correction;
};
/* Passes which use the jump threading code register jump threading
@ -826,7 +831,8 @@ compute_path_counts (struct redirection_data *rd,
So ensure that this path's path_out_count is at least the
difference between elast->count and nonpath_count. Otherwise the edge
counts after threading will not be sane. */
if (has_joiner && path_out_count < elast->count - nonpath_count)
if (local_info->need_profile_correction
&& has_joiner && path_out_count < elast->count - nonpath_count)
{
path_out_count = elast->count - nonpath_count;
/* But neither can we go above the minimum count along the path
@ -1492,6 +1498,7 @@ thread_block_1 (basic_block bb, bool noloop_only, bool joiners)
ssa_local_info_t local_info;
local_info.duplicate_blocks = BITMAP_ALLOC (NULL);
local_info.need_profile_correction = false;
/* To avoid scanning a linear array for the element we need we instead
use a hash table. For normal code there should be no noticeable
@ -1502,6 +1509,7 @@ thread_block_1 (basic_block bb, bool noloop_only, bool joiners)
/* Record each unique threaded destination into a hash table for
efficient lookups. */
edge last = NULL;
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (e->aux == NULL)
@ -1555,6 +1563,17 @@ thread_block_1 (basic_block bb, bool noloop_only, bool joiners)
/* Insert the outgoing edge into the hash table if it is not
already in the hash table. */
lookup_redirection_data (e, INSERT);
/* When we have thread paths through a common joiner with different
final destinations, then we may need corrections to deal with
profile insanities. See the big comment before compute_path_counts. */
if ((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK)
{
if (!last)
last = e2;
else if (e2 != last)
local_info.need_profile_correction = true;
}
}
/* We do not update dominance info. */