aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr67755.c25
-rw-r--r--gcc/tree-ssa-threadupdate.c21
4 files changed, 62 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6423a37..f8f818b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 11f3b0c..240fae7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr67755.c b/gcc/testsuite/gcc.dg/tree-ssa/pr67755.c
new file mode 100644
index 0000000..64ffd0b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr67755.c
@@ -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;
+}
+
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index 1bf9ae6..4783c4b 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -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. */