public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Deduplicate edge predictors
@ 2016-06-02 11:57 marxin
  2016-06-02 11:57 ` [PATCH 1/2] Introduce filtering for edge_predictions marxin
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: marxin @ 2016-06-02 11:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: hubicka

Hi.

Following small series makes deduplication of predictors in following 2 ways:
   1) remove duplicate prediction that is guessed with the same probability
      (different than 1/2) to both edges
   2) remove duplicates for a prediction that belongs with the same probability
      to a single edge

Patch also changes dump output format a bit, thus analyze_brprob.py script
has been also modified to understand the format.

Bootstrapped and regtested on x86_64-linux

Ready for trunk?
Martin

marxin (2):
  Introduce filtering for edge_predictions.
  Add edge predictions pruning

 contrib/analyze_brprob.py                  |  10 +-
 gcc/predict.c                              | 209 +++++++++++++++++++++++++----
 gcc/testsuite/g++.dg/predict-loop-exit-1.C |   4 +-
 gcc/testsuite/g++.dg/predict-loop-exit-2.C |   4 +-
 gcc/testsuite/g++.dg/predict-loop-exit-3.C |   4 +-
 gcc/testsuite/gcc.dg/predict-1.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-3.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-4.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-5.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-6.c           |   2 +-
 10 files changed, 201 insertions(+), 40 deletions(-)

-- 
2.8.3

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/2] Introduce filtering for edge_predictions.
  2016-06-02 11:57 [PATCH 0/2] Deduplicate edge predictors marxin
@ 2016-06-02 11:57 ` marxin
  2016-06-02 11:57 ` [PATCH 2/2] Add edge predictions pruning marxin
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 14+ messages in thread
From: marxin @ 2016-06-02 11:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: hubicka

gcc/ChangeLog:

2016-05-31  Martin Liska  <mliska@suse.cz>

	* predict.c (filter_predictions): New function.
	(remove_predictions_associated_with_edge): Use the filter
	function.
	(equal_edge_p): New function.
---
 gcc/predict.c | 38 ++++++++++++++++++++++++++++++--------
 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/gcc/predict.c b/gcc/predict.c
index e9dda20..51a9993 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -609,16 +609,16 @@ gimple_predict_edge (edge e, enum br_predictor predictor, int probability)
     }
 }
 
-/* Remove all predictions on given basic block that are attached
-   to edge E.  */
+/* Filter edge predictions PREDS by a function FILTER.  DATA are passed
+   to the filter function.  */
+
 void
-remove_predictions_associated_with_edge (edge e)
+filter_predictions (edge_prediction **preds,
+		    bool (*filter) (edge_prediction *, void *), void *data)
 {
   if (!bb_predictions)
     return;
 
-  edge_prediction **preds = bb_predictions->get (e->src);
-
   if (preds)
     {
       struct edge_prediction **prediction = preds;
@@ -626,18 +626,40 @@ remove_predictions_associated_with_edge (edge e)
 
       while (*prediction)
 	{
-	  if ((*prediction)->ep_edge == e)
+	  if ((*filter) (*prediction, data))
+	    prediction = &((*prediction)->ep_next);
+	  else
 	    {
 	      next = (*prediction)->ep_next;
 	      free (*prediction);
 	      *prediction = next;
 	    }
-	  else
-	    prediction = &((*prediction)->ep_next);
 	}
     }
 }
 
+/* Filter function predicate that returns true for a edge predicate P
+   if its edge is equal to DATA.  */
+
+bool
+equal_edge_p (edge_prediction *p, void *data)
+{
+  return p->ep_edge == (edge)data;
+}
+
+/* Remove all predictions on given basic block that are attached
+   to edge E.  */
+
+void
+remove_predictions_associated_with_edge (edge e)
+{
+  if (!bb_predictions)
+    return;
+
+  edge_prediction **preds = bb_predictions->get (e->src);
+  filter_predictions (preds, equal_edge_p, e);
+}
+
 /* Clears the list of predictions stored for BB.  */
 
 static void
-- 
2.8.3


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 2/2] Add edge predictions pruning
  2016-06-02 11:57 [PATCH 0/2] Deduplicate edge predictors marxin
  2016-06-02 11:57 ` [PATCH 1/2] Introduce filtering for edge_predictions marxin
@ 2016-06-02 11:57 ` marxin
  2016-06-08 12:25   ` Martin Liška
  2016-06-08 12:26 ` [PATCH 3/N] Add sorting support to analyze_brprob script Martin Liška
  2016-06-08 12:29 ` [PATCH 4/N] Add new analyze_brprob_spec.py script Martin Liška
  3 siblings, 1 reply; 14+ messages in thread
From: marxin @ 2016-06-02 11:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: hubicka

contrib/ChangeLog:

2016-06-01  Martin Liska  <mliska@suse.cz>

	* analyze_brprob.py: Cover new dump output format.

gcc/ChangeLog:

2016-06-01  Martin Liska  <mliska@suse.cz>

	* predict.c (dump_prediction): Add new argument.
	(enum predictor_reason): New enum.
	(struct predictor_hash): New struct.
	(predictor_hash::hash): New function.
	(predictor_hash::equal): Likewise.
	(not_removed_prediction_p): New function.
	(prune_predictions_for_bb): Likewise.
	(combine_predictions_for_bb): Prune predictions.

gcc/testsuite/ChangeLog:

2016-06-02  Martin Liska  <mliska@suse.cz>

	* g++.dg/predict-loop-exit-1.C: Cover new dump format.
	* g++.dg/predict-loop-exit-2.C: Likewise.
	* g++.dg/predict-loop-exit-3.C: Likewise.
	* gcc.dg/predict-1.c: Likewise.
	* gcc.dg/predict-3.c: Likewise.
	* gcc.dg/predict-4.c: Likewise.
	* gcc.dg/predict-5.c: Likewise.
	* gcc.dg/predict-6.c: Likewise.
---
 contrib/analyze_brprob.py                  |  10 +-
 gcc/predict.c                              | 171 ++++++++++++++++++++++++++---
 gcc/testsuite/g++.dg/predict-loop-exit-1.C |   4 +-
 gcc/testsuite/g++.dg/predict-loop-exit-2.C |   4 +-
 gcc/testsuite/g++.dg/predict-loop-exit-3.C |   4 +-
 gcc/testsuite/gcc.dg/predict-1.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-3.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-4.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-5.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-6.c           |   2 +-
 10 files changed, 171 insertions(+), 32 deletions(-)

diff --git a/contrib/analyze_brprob.py b/contrib/analyze_brprob.py
index 36371ff..9416eed 100755
--- a/contrib/analyze_brprob.py
+++ b/contrib/analyze_brprob.py
@@ -122,14 +122,14 @@ if len(sys.argv) != 2:
     exit(1)
 
 profile = Profile(sys.argv[1])
-r = re.compile('  (.*) heuristics: (.*)%.*exec ([0-9]*) hit ([0-9]*)')
+r = re.compile('  (.*) heuristics( of edge [0-9]*->[0-9]*)?( \\(.*\\))?: (.*)%.*exec ([0-9]*) hit ([0-9]*)')
 for l in open(profile.filename).readlines():
     m = r.match(l)
-    if m != None:
+    if m != None and m.group(3) == None:
         name = m.group(1)
-        prediction = float(m.group(2))
-        count = int(m.group(3))
-        hits = int(m.group(4))
+        prediction = float(m.group(4))
+        count = int(m.group(5))
+        hits = int(m.group(6))
 
         profile.add(name, prediction, count, hits)
 
diff --git a/gcc/predict.c b/gcc/predict.c
index 51a9993..dab97ad 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -55,13 +55,25 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-loop.h"
 #include "tree-scalar-evolution.h"
 
+enum predictor_reason
+{
+  NONE,
+  IGNORED,
+  SINGLE_EDGE_DUPLICATE,
+  EDGE_PAIR_DUPLICATE
+};
+
+static const char *reason_messages[] = {"", " (ignored)",
+    " (single edge duplicate)", " (edge pair duplicate)"};
+
 /* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE,
 		   1/REG_BR_PROB_BASE, 0.5, BB_FREQ_MAX.  */
 static sreal real_almost_one, real_br_prob_base,
 	     real_inv_br_prob_base, real_one_half, real_bb_freq_max;
 
 static void combine_predictions_for_insn (rtx_insn *, basic_block);
-static void dump_prediction (FILE *, enum br_predictor, int, basic_block, int);
+static void dump_prediction (FILE *, enum br_predictor, int, basic_block,
+			     enum predictor_reason, edge);
 static void predict_paths_leading_to (basic_block, enum br_predictor, enum prediction);
 static void predict_paths_leading_to_edge (edge, enum br_predictor, enum prediction);
 static bool can_predict_insn_p (const rtx_insn *);
@@ -724,7 +736,8 @@ invert_br_probabilities (rtx insn)
 
 static void
 dump_prediction (FILE *file, enum br_predictor predictor, int probability,
-		 basic_block bb, int used)
+		 basic_block bb, enum predictor_reason reason = NONE,
+		 edge ep_edge = NULL)
 {
   edge e;
   edge_iterator ei;
@@ -736,9 +749,17 @@ dump_prediction (FILE *file, enum br_predictor predictor, int probability,
     if (! (e->flags & EDGE_FALLTHRU))
       break;
 
-  fprintf (file, "  %s heuristics%s: %.1f%%",
+  char edge_info_str[128];
+  if (ep_edge)
+    sprintf (edge_info_str, " of edge %d->%d", ep_edge->src->index,
+	     ep_edge->dest->index);
+  else
+    edge_info_str[0] = '\0';
+
+  fprintf (file, "  %s heuristics%s%s: %.1f%%",
 	   predictor_info[predictor].name,
-	   used ? "" : " (ignored)", probability * 100.0 / REG_BR_PROB_BASE);
+	   edge_info_str, reason_messages[reason],
+	   probability * 100.0 / REG_BR_PROB_BASE);
 
   if (bb->count)
     {
@@ -835,18 +856,18 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
 
   if (!found)
     dump_prediction (dump_file, PRED_NO_PREDICTION,
-		     combined_probability, bb, true);
+		     combined_probability, bb);
   else
     {
       dump_prediction (dump_file, PRED_DS_THEORY, combined_probability,
-		       bb, !first_match);
+		       bb, !first_match ? NONE : IGNORED);
       dump_prediction (dump_file, PRED_FIRST_MATCH, best_probability,
-		       bb, first_match);
+		       bb, first_match ? NONE: IGNORED);
     }
 
   if (first_match)
     combined_probability = best_probability;
-  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb, true);
+  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb);
 
   while (*pnote)
     {
@@ -857,7 +878,8 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
 	  int probability = INTVAL (XEXP (XEXP (*pnote, 0), 1));
 
 	  dump_prediction (dump_file, predictor, probability, bb,
-			   !first_match || best_predictor == predictor);
+			   (!first_match || best_predictor == predictor)
+			   ? NONE : IGNORED);
 	  *pnote = XEXP (*pnote, 1);
 	}
       else
@@ -888,6 +910,121 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
     single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
 }
 
+/* Edge prediction hash traits.  */
+
+struct predictor_hash: pointer_hash <edge_prediction>
+{
+
+  static inline hashval_t hash (const edge_prediction *);
+  static inline bool equal (const edge_prediction *, const edge_prediction *);
+};
+
+/* Calculate hash value of an edge prediction P based on predictor and
+   normalized probability.  */
+
+inline hashval_t
+predictor_hash::hash (const edge_prediction *p)
+{
+  inchash::hash hstate;
+  hstate.add_int (p->ep_predictor);
+
+  int prob = p->ep_probability;
+  if (prob > REG_BR_PROB_BASE / 2)
+    prob = REG_BR_PROB_BASE - prob;
+
+  hstate.add_int (prob);
+
+  return hstate.end ();
+}
+
+/* Return true whether edge predictions P1 and P2 use the same predictor and
+   have equal (or opposed probability).  */
+
+inline bool
+predictor_hash::equal (const edge_prediction *p1, const edge_prediction *p2)
+{
+  return (p1->ep_predictor == p2->ep_predictor
+	  && (p1->ep_probability == p2->ep_probability
+	      || p1->ep_probability == REG_BR_PROB_BASE - p2->ep_probability));
+}
+
+struct predictor_hash_traits: predictor_hash,
+  typed_noop_remove <edge_prediction *> {};
+
+/* Return true if edge prediction P is not in DATA hash set.  */
+
+static bool
+not_removed_prediction_p (edge_prediction *p, void *data)
+{
+  hash_set<edge_prediction *> *remove = (hash_set<edge_prediction *> *) data;
+  return !remove->contains (p);
+}
+
+/* Prune predictions for a basic block BB.  Currently we do following
+   clean-up steps:
+
+   1) remove duplicate prediction that is guessed with the same probability
+      (different than 1/2) to both edge
+   2) remove duplicates for a prediction that belongs with the same probability
+      to a single edge
+
+  */
+
+static void
+prune_predictions_for_bb (basic_block bb)
+{
+  edge_prediction **preds = bb_predictions->get (bb);
+
+  if (preds)
+    {
+      hash_table <predictor_hash_traits> s (13);
+      hash_set <edge_prediction *> remove;
+
+      /* Step 1: identify predictors that should be removed.  */
+      for (edge_prediction *pred = *preds; pred; pred = pred->ep_next)
+	{
+	  edge_prediction *existing = s.find (pred);
+	  if (existing)
+	    {
+	      if (pred->ep_edge == existing->ep_edge
+		  && pred->ep_probability == existing->ep_probability)
+		{
+		  /* Remove a duplicate predictor.  */
+		  dump_prediction (dump_file, pred->ep_predictor,
+				   pred->ep_probability, bb,
+				   SINGLE_EDGE_DUPLICATE, pred->ep_edge);
+
+		  remove.add (pred);
+		}
+	      else if (pred->ep_edge != existing->ep_edge
+		       && pred->ep_probability == existing->ep_probability
+		       && pred->ep_probability != REG_BR_PROB_BASE / 2)
+		{
+		  /* Remove both predictors as they predict the same
+		     for both edges.  */
+		  dump_prediction (dump_file, existing->ep_predictor,
+				   pred->ep_probability, bb,
+				   EDGE_PAIR_DUPLICATE,
+				   existing->ep_edge);
+		  dump_prediction (dump_file, pred->ep_predictor,
+				   pred->ep_probability, bb,
+				   EDGE_PAIR_DUPLICATE,
+				   pred->ep_edge);
+
+		  remove.add (existing);
+		  remove.add (pred);
+		}
+	    }
+
+	  edge_prediction **slot2 = s.find_slot (pred, INSERT);
+	  *slot2 = pred;
+	}
+
+      /* Step 2: Remove predictors.  */
+      filter_predictions (preds, not_removed_prediction_p, &remove);
+    }
+}
+
 /* Combine predictions into single probability and store them into CFG.
    Remove now useless prediction entries.
    If DRY_RUN is set, only produce dumps and do not modify profile.  */
@@ -936,7 +1073,10 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
   if (dump_file)
     fprintf (dump_file, "Predictions for bb %i\n", bb->index);
 
+  prune_predictions_for_bb (bb);
+
   edge_prediction **preds = bb_predictions->get (bb);
+
   if (preds)
     {
       /* We implement "first match" heuristics and use probability guessed
@@ -1002,18 +1142,18 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
     first_match = true;
 
   if (!found)
-    dump_prediction (dump_file, PRED_NO_PREDICTION, combined_probability, bb, true);
+    dump_prediction (dump_file, PRED_NO_PREDICTION, combined_probability, bb);
   else
     {
       dump_prediction (dump_file, PRED_DS_THEORY, combined_probability, bb,
-		       !first_match);
+		       !first_match ? NONE : IGNORED);
       dump_prediction (dump_file, PRED_FIRST_MATCH, best_probability, bb,
-		       first_match);
+		       first_match ? NONE : IGNORED);
     }
 
   if (first_match)
     combined_probability = best_probability;
-  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb, true);
+  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb);
 
   if (preds)
     {
@@ -1022,10 +1162,9 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
 	  enum br_predictor predictor = pred->ep_predictor;
 	  int probability = pred->ep_probability;
 
-	  if (pred->ep_edge != EDGE_SUCC (bb, 0))
-	    probability = REG_BR_PROB_BASE - probability;
 	  dump_prediction (dump_file, predictor, probability, bb,
-			   !first_match || best_predictor == predictor);
+			   (!first_match || best_predictor == predictor)
+			   ? NONE : IGNORED, pred->ep_edge);
 	}
     }
   clear_bb_predictions (bb);
diff --git a/gcc/testsuite/g++.dg/predict-loop-exit-1.C b/gcc/testsuite/g++.dg/predict-loop-exit-1.C
index 357397f..88262eb 100644
--- a/gcc/testsuite/g++.dg/predict-loop-exit-1.C
+++ b/gcc/testsuite/g++.dg/predict-loop-exit-1.C
@@ -9,5 +9,5 @@ void test() {
   return;
 }
 
-/* { dg-final { scan-tree-dump-times "extra loop exit heuristics:" 2 "profile_estimate"} } */
-/* { dg-final { scan-tree-dump-times "loop exit heuristics:" 3 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "extra loop exit heuristics of edge\[^:\]*:" 2 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop exit heuristics of edge\[^:\]*:" 3 "profile_estimate"} } */
diff --git a/gcc/testsuite/g++.dg/predict-loop-exit-2.C b/gcc/testsuite/g++.dg/predict-loop-exit-2.C
index 172fab1..15e9866 100644
--- a/gcc/testsuite/g++.dg/predict-loop-exit-2.C
+++ b/gcc/testsuite/g++.dg/predict-loop-exit-2.C
@@ -9,5 +9,5 @@ void test() {
   return;
 }
 
-/* { dg-final { scan-tree-dump-times "extra loop exit heuristics:" 1 "profile_estimate"} } */
-/* { dg-final { scan-tree-dump-times "loop exit heuristics:" 2 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "extra loop exit heuristics of edge\[^:\]*:" 1 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop exit heuristics of edge\[^:\]*:" 2 "profile_estimate"} } */
diff --git a/gcc/testsuite/g++.dg/predict-loop-exit-3.C b/gcc/testsuite/g++.dg/predict-loop-exit-3.C
index e6ceec8..61af84b 100644
--- a/gcc/testsuite/g++.dg/predict-loop-exit-3.C
+++ b/gcc/testsuite/g++.dg/predict-loop-exit-3.C
@@ -9,5 +9,5 @@ void test() {
   return;
 }
 
-/* { dg-final { scan-tree-dump-times "extra loop exit heuristics:" 2 "profile_estimate"} } */
-/* { dg-final { scan-tree-dump-times "loop exit heuristics:" 3 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "extra loop exit heuristics of edge\[^:\]*:" 2 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop exit heuristics of edge\[^:\]*:" 3 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-1.c b/gcc/testsuite/gcc.dg/predict-1.c
index a2a0604..852ccb1 100644
--- a/gcc/testsuite/gcc.dg/predict-1.c
+++ b/gcc/testsuite/gcc.dg/predict-1.c
@@ -23,4 +23,4 @@ void foo (int bound)
     }
 }
 
-/* { dg-final { scan-tree-dump-times "loop iv compare heuristics: 0.0%" 5 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop iv compare heuristics of edge\[^:\]*: 0.0%" 5 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-3.c b/gcc/testsuite/gcc.dg/predict-3.c
index e1be7cc..d41a4ac 100644
--- a/gcc/testsuite/gcc.dg/predict-3.c
+++ b/gcc/testsuite/gcc.dg/predict-3.c
@@ -25,4 +25,4 @@ void foo (int bound)
     }
 }
 
-/* { dg-final { scan-tree-dump-times "loop iv compare heuristics: 100.0%" 3 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop iv compare heuristics of edge\[^:\]*: 100.0%" 3 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-4.c b/gcc/testsuite/gcc.dg/predict-4.c
index 3e7fb74..5779da3 100644
--- a/gcc/testsuite/gcc.dg/predict-4.c
+++ b/gcc/testsuite/gcc.dg/predict-4.c
@@ -15,4 +15,4 @@ void foo (int bound)
     }
 }
 
-/* { dg-final { scan-tree-dump "loop iv compare heuristics: 50.0%" "profile_estimate"} } */
+/* { dg-final { scan-tree-dump "loop iv compare heuristics of edge\[^:\]*: 50.0%" "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-5.c b/gcc/testsuite/gcc.dg/predict-5.c
index 3e7cc6f..d9bc27e 100644
--- a/gcc/testsuite/gcc.dg/predict-5.c
+++ b/gcc/testsuite/gcc.dg/predict-5.c
@@ -21,4 +21,4 @@ void foo (int base, int bound)
     }
 }
 
-/* { dg-final { scan-tree-dump-times "loop iv compare heuristics: 100.0%" 4 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop iv compare heuristics of edge\[^:\]*: 100.0%" 4 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-6.c b/gcc/testsuite/gcc.dg/predict-6.c
index cda30e2..608eb7b 100644
--- a/gcc/testsuite/gcc.dg/predict-6.c
+++ b/gcc/testsuite/gcc.dg/predict-6.c
@@ -21,4 +21,4 @@ void foo (int base, int bound)
     }
 }
 
-/* { dg-final { scan-tree-dump-times "loop iv compare heuristics: 0.0%" 4 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop iv compare heuristics of edge\[^:\]*: 0.0%" 4 "profile_estimate"} } */
-- 
2.8.3

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] Add edge predictions pruning
  2016-06-02 11:57 ` [PATCH 2/2] Add edge predictions pruning marxin
@ 2016-06-08 12:25   ` Martin Liška
  2016-06-08 12:41     ` Jan Hubicka
  0 siblings, 1 reply; 14+ messages in thread
From: Martin Liška @ 2016-06-08 12:25 UTC (permalink / raw)
  To: gcc-patches; +Cc: Jan Hubicka

[-- Attachment #1: Type: text/plain, Size: 124 bytes --]

Hi.

I'm sending second version of the patch, where I fixed dump_prediction function to
dump a proper edge.

Thanks,
Martin

[-- Attachment #2: 0002-Add-edge-predictions-pruning-v2.patch --]
[-- Type: text/x-patch, Size: 10526 bytes --]

From 0d82e8def140636fe186888a525fe84e329d676b Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Tue, 31 May 2016 17:29:53 +0200
Subject: [PATCH 2/4] Add edge predictions pruning

contrib/ChangeLog:

2016-06-01  Martin Liska  <mliska@suse.cz>

	* analyze_brprob.py: Cover new dump output format.

gcc/ChangeLog:

2016-06-01  Martin Liska  <mliska@suse.cz>

	* predict.c (dump_prediction): Add new argument.
	(enum predictor_reason): New enum.
	(struct predictor_hash): New struct.
	(predictor_hash::hash): New function.
	(predictor_hash::equal): Likewise.
	(not_removed_prediction_p): New function.
	(prune_predictions_for_bb): Likewise.
	(combine_predictions_for_bb): Prune predictions.
---
 contrib/analyze_brprob.py |  10 +--
 gcc/predict.c             | 180 ++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 165 insertions(+), 25 deletions(-)

diff --git a/contrib/analyze_brprob.py b/contrib/analyze_brprob.py
index 36371ff..9416eed 100755
--- a/contrib/analyze_brprob.py
+++ b/contrib/analyze_brprob.py
@@ -122,14 +122,14 @@ if len(sys.argv) != 2:
     exit(1)
 
 profile = Profile(sys.argv[1])
-r = re.compile('  (.*) heuristics: (.*)%.*exec ([0-9]*) hit ([0-9]*)')
+r = re.compile('  (.*) heuristics( of edge [0-9]*->[0-9]*)?( \\(.*\\))?: (.*)%.*exec ([0-9]*) hit ([0-9]*)')
 for l in open(profile.filename).readlines():
     m = r.match(l)
-    if m != None:
+    if m != None and m.group(3) == None:
         name = m.group(1)
-        prediction = float(m.group(2))
-        count = int(m.group(3))
-        hits = int(m.group(4))
+        prediction = float(m.group(4))
+        count = int(m.group(5))
+        hits = int(m.group(6))
 
         profile.add(name, prediction, count, hits)
 
diff --git a/gcc/predict.c b/gcc/predict.c
index e058793..f2ecc4a 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -55,13 +55,25 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-loop.h"
 #include "tree-scalar-evolution.h"
 
+enum predictor_reason
+{
+  NONE,
+  IGNORED,
+  SINGLE_EDGE_DUPLICATE,
+  EDGE_PAIR_DUPLICATE
+};
+
+static const char *reason_messages[] = {"", " (ignored)",
+    " (single edge duplicate)", " (edge pair duplicate)"};
+
 /* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE,
 		   1/REG_BR_PROB_BASE, 0.5, BB_FREQ_MAX.  */
 static sreal real_almost_one, real_br_prob_base,
 	     real_inv_br_prob_base, real_one_half, real_bb_freq_max;
 
 static void combine_predictions_for_insn (rtx_insn *, basic_block);
-static void dump_prediction (FILE *, enum br_predictor, int, basic_block, int);
+static void dump_prediction (FILE *, enum br_predictor, int, basic_block,
+			     enum predictor_reason, edge);
 static void predict_paths_leading_to (basic_block, enum br_predictor, enum prediction);
 static void predict_paths_leading_to_edge (edge, enum br_predictor, enum prediction);
 static bool can_predict_insn_p (const rtx_insn *);
@@ -723,21 +735,31 @@ invert_br_probabilities (rtx insn)
 
 static void
 dump_prediction (FILE *file, enum br_predictor predictor, int probability,
-		 basic_block bb, int used)
+		 basic_block bb, enum predictor_reason reason = NONE,
+		 edge ep_edge = NULL)
 {
-  edge e;
+  edge e = ep_edge;
   edge_iterator ei;
 
   if (!file)
     return;
 
-  FOR_EACH_EDGE (e, ei, bb->succs)
-    if (! (e->flags & EDGE_FALLTHRU))
-      break;
+  if (e == NULL)
+    FOR_EACH_EDGE (e, ei, bb->succs)
+      if (! (e->flags & EDGE_FALLTHRU))
+	break;
 
-  fprintf (file, "  %s heuristics%s: %.1f%%",
+  char edge_info_str[128];
+  if (ep_edge)
+    sprintf (edge_info_str, " of edge %d->%d", ep_edge->src->index,
+	     ep_edge->dest->index);
+  else
+    edge_info_str[0] = '\0';
+
+  fprintf (file, "  %s heuristics%s%s: %.1f%%",
 	   predictor_info[predictor].name,
-	   used ? "" : " (ignored)", probability * 100.0 / REG_BR_PROB_BASE);
+	   edge_info_str, reason_messages[reason],
+	   probability * 100.0 / REG_BR_PROB_BASE);
 
   if (bb->count)
     {
@@ -834,18 +856,18 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
 
   if (!found)
     dump_prediction (dump_file, PRED_NO_PREDICTION,
-		     combined_probability, bb, true);
+		     combined_probability, bb);
   else
     {
       dump_prediction (dump_file, PRED_DS_THEORY, combined_probability,
-		       bb, !first_match);
+		       bb, !first_match ? NONE : IGNORED);
       dump_prediction (dump_file, PRED_FIRST_MATCH, best_probability,
-		       bb, first_match);
+		       bb, first_match ? NONE: IGNORED);
     }
 
   if (first_match)
     combined_probability = best_probability;
-  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb, true);
+  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb);
 
   while (*pnote)
     {
@@ -856,7 +878,8 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
 	  int probability = INTVAL (XEXP (XEXP (*pnote, 0), 1));
 
 	  dump_prediction (dump_file, predictor, probability, bb,
-			   !first_match || best_predictor == predictor);
+			   (!first_match || best_predictor == predictor)
+			   ? NONE : IGNORED);
 	  *pnote = XEXP (*pnote, 1);
 	}
       else
@@ -887,6 +910,121 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
     single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
 }
 
+/* Edge prediction hash traits.  */
+
+struct predictor_hash: pointer_hash <edge_prediction>
+{
+
+  static inline hashval_t hash (const edge_prediction *);
+  static inline bool equal (const edge_prediction *, const edge_prediction *);
+};
+
+/* Calculate hash value of an edge prediction P based on predictor and
+   normalized probability.  */
+
+inline hashval_t
+predictor_hash::hash (const edge_prediction *p)
+{
+  inchash::hash hstate;
+  hstate.add_int (p->ep_predictor);
+
+  int prob = p->ep_probability;
+  if (prob > REG_BR_PROB_BASE / 2)
+    prob = REG_BR_PROB_BASE - prob;
+
+  hstate.add_int (prob);
+
+  return hstate.end ();
+}
+
+/* Return true whether edge predictions P1 and P2 use the same predictor and
+   have equal (or opposed probability).  */
+
+inline bool
+predictor_hash::equal (const edge_prediction *p1, const edge_prediction *p2)
+{
+  return (p1->ep_predictor == p2->ep_predictor
+	  && (p1->ep_probability == p2->ep_probability
+	      || p1->ep_probability == REG_BR_PROB_BASE - p2->ep_probability));
+}
+
+struct predictor_hash_traits: predictor_hash,
+  typed_noop_remove <edge_prediction *> {};
+
+/* Return true if edge prediction P is not in DATA hash set.  */
+
+static bool
+not_removed_prediction_p (edge_prediction *p, void *data)
+{
+  hash_set<edge_prediction *> *remove = (hash_set<edge_prediction *> *) data;
+  return !remove->contains (p);
+}
+
+/* Prune predictions for a basic block BB.  Currently we do following
+   clean-up steps:
+
+   1) remove duplicate prediction that is guessed with the same probability
+      (different than 1/2) to both edge
+   2) remove duplicates for a prediction that belongs with the same probability
+      to a single edge
+
+  */
+
+static void
+prune_predictions_for_bb (basic_block bb)
+{
+  edge_prediction **preds = bb_predictions->get (bb);
+
+  if (preds)
+    {
+      hash_table <predictor_hash_traits> s (13);
+      hash_set <edge_prediction *> remove;
+
+      /* Step 1: identify predictors that should be removed.  */
+      for (edge_prediction *pred = *preds; pred; pred = pred->ep_next)
+	{
+	  edge_prediction *existing = s.find (pred);
+	  if (existing)
+	    {
+	      if (pred->ep_edge == existing->ep_edge
+		  && pred->ep_probability == existing->ep_probability)
+		{
+		  /* Remove a duplicate predictor.  */
+		  dump_prediction (dump_file, pred->ep_predictor,
+				   pred->ep_probability, bb,
+				   SINGLE_EDGE_DUPLICATE, pred->ep_edge);
+
+		  remove.add (pred);
+		}
+	      else if (pred->ep_edge != existing->ep_edge
+		       && pred->ep_probability == existing->ep_probability
+		       && pred->ep_probability != REG_BR_PROB_BASE / 2)
+		{
+		  /* Remove both predictors as they predict the same
+		     for both edges.  */
+		  dump_prediction (dump_file, existing->ep_predictor,
+				   pred->ep_probability, bb,
+				   EDGE_PAIR_DUPLICATE,
+				   existing->ep_edge);
+		  dump_prediction (dump_file, pred->ep_predictor,
+				   pred->ep_probability, bb,
+				   EDGE_PAIR_DUPLICATE,
+				   pred->ep_edge);
+
+		  remove.add (existing);
+		  remove.add (pred);
+		}
+	    }
+
+	  edge_prediction **slot2 = s.find_slot (pred, INSERT);
+	  *slot2 = pred;
+	}
+
+      /* Step 2: Remove predictors.  */
+      filter_predictions (preds, not_removed_prediction_p, &remove);
+    }
+}
+
 /* Combine predictions into single probability and store them into CFG.
    Remove now useless prediction entries.
    If DRY_RUN is set, only produce dumps and do not modify profile.  */
@@ -935,7 +1073,10 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
   if (dump_file)
     fprintf (dump_file, "Predictions for bb %i\n", bb->index);
 
+  prune_predictions_for_bb (bb);
+
   edge_prediction **preds = bb_predictions->get (bb);
+
   if (preds)
     {
       /* We implement "first match" heuristics and use probability guessed
@@ -1001,18 +1142,18 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
     first_match = true;
 
   if (!found)
-    dump_prediction (dump_file, PRED_NO_PREDICTION, combined_probability, bb, true);
+    dump_prediction (dump_file, PRED_NO_PREDICTION, combined_probability, bb);
   else
     {
       dump_prediction (dump_file, PRED_DS_THEORY, combined_probability, bb,
-		       !first_match);
+		       !first_match ? NONE : IGNORED);
       dump_prediction (dump_file, PRED_FIRST_MATCH, best_probability, bb,
-		       first_match);
+		       first_match ? NONE : IGNORED);
     }
 
   if (first_match)
     combined_probability = best_probability;
-  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb, true);
+  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb);
 
   if (preds)
     {
@@ -1021,10 +1162,9 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
 	  enum br_predictor predictor = pred->ep_predictor;
 	  int probability = pred->ep_probability;
 
-	  if (pred->ep_edge != EDGE_SUCC (bb, 0))
-	    probability = REG_BR_PROB_BASE - probability;
 	  dump_prediction (dump_file, predictor, probability, bb,
-			   !first_match || best_predictor == predictor);
+			   (!first_match || best_predictor == predictor)
+			   ? NONE : IGNORED, pred->ep_edge);
 	}
     }
   clear_bb_predictions (bb);
-- 
2.8.3


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 3/N] Add sorting support to analyze_brprob script
  2016-06-02 11:57 [PATCH 0/2] Deduplicate edge predictors marxin
  2016-06-02 11:57 ` [PATCH 1/2] Introduce filtering for edge_predictions marxin
  2016-06-02 11:57 ` [PATCH 2/2] Add edge predictions pruning marxin
@ 2016-06-08 12:26 ` Martin Liška
  2016-06-08 15:02   ` Jan Hubicka
  2016-06-08 12:29 ` [PATCH 4/N] Add new analyze_brprob_spec.py script Martin Liška
  3 siblings, 1 reply; 14+ messages in thread
From: Martin Liška @ 2016-06-08 12:26 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2842 bytes --]

Hello.

This is a small followup, where I would like to add new argument to analyze_brprob.py
script file. With the patch, one can sort predictors by e.g. hitrate:


Example CPU2006
HEURISTICS                           BRANCHES  (REL)  HITRATE                COVERAGE COVERAGE  (REL)
loop iv compare                            33   0.1%  20.27% /  86.24%       30630826   30.63M   0.0%
no prediction                           10406  19.5%  33.41% /  84.76%   139755242456  139.76G  14.1%
early return (on trees)                  6328  11.9%  54.20% /  86.48%    33569991740   33.57G   3.4%
guessed loop iterations                   112   0.2%  62.06% /  64.49%      958458522  958.46M   0.1%
fail alloc                                595   1.1%  62.18% / 100.00%            595   595.00   0.0%
opcode values positive (on trees)        4266   8.0%  64.30% /  91.28%    16931889792   16.93G   1.7%
opcode values nonequal (on trees)        6600  12.4%  66.23% /  80.60%    71483051282   71.48G   7.2%
continue                                  507   0.9%  66.66% /  82.85%    10086808016   10.09G   1.0%
call                                    11351  21.3%  67.16% /  92.24%    34680666103   34.68G   3.5%
loop iterations                          2689   5.0%  67.99% /  67.99%   408309517405  408.31G  41.3%
DS theory                               26385  49.4%  68.62% /  85.44%   146974369890  146.97G  14.9%
const return                              271   0.5%  69.39% /  87.09%      301566712  301.57M   0.0%
pointer (on trees)                       6230  11.7%  69.59% /  87.18%    16667735314   16.67G   1.7%
combined                                53398 100.0%  70.31% /  80.36%   989164856862  989.16G 100.0%
goto                                       78   0.1%  70.36% /  96.96%      951041538  951.04M   0.1%
first match                             16607  31.1%  78.00% /  78.42%   702435244516  702.44G  71.0%
extra loop exit                           141   0.3%  82.80% /  88.17%     1696946942    1.70G   0.2%
null return                               393   0.7%  91.47% /  93.08%     3268678197    3.27G   0.3%
loop exit                                9909  18.6%  91.80% /  92.81%   282927773783  282.93G  28.6%
guess loop iv compare                     178   0.3%  97.81% /  97.85%     4375086453    4.38G   0.4%
negative return                           277   0.5%  97.94% /  99.23%     1062119028    1.06G   0.1%
noreturn call                            2372   4.4% 100.00% / 100.00%     8356562323    8.36G   0.8%
overflow                                 1282   2.4% 100.00% / 100.00%      175074177  175.07M   0.0%
zero-sized array                          677   1.3% 100.00% / 100.00%      112723803  112.72M   0.0%
unconditional jump                        103   0.2% 100.00% / 100.00%         491001  491.00K   0.0%

Martin

[-- Attachment #2: 0003-Add-sorting-support-to-analyze_brprob-script.patch --]
[-- Type: text/x-patch, Size: 2852 bytes --]

From fc40cf57a5b822558d32182b9937ba6dafd62377 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Thu, 2 Jun 2016 13:15:08 +0200
Subject: [PATCH 3/4] Add sorting support to analyze_brprob script

contrib/ChangeLog:

2016-06-08  Martin Liska  <mliska@suse.cz>

	* analyze_brprob.py: Add new argument --sorting.
---
 contrib/analyze_brprob.py | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/contrib/analyze_brprob.py b/contrib/analyze_brprob.py
index 9416eed..9808c46 100755
--- a/contrib/analyze_brprob.py
+++ b/contrib/analyze_brprob.py
@@ -65,6 +65,7 @@
 import sys
 import os
 import re
+import argparse
 
 def percentage(a, b):
     return 100.0 * a / b
@@ -77,6 +78,9 @@ class Summary:
         self.hits = 0
         self.fits = 0
 
+    def get_hitrate(self):
+        return self.hits / self.count
+
     def count_formatted(self):
         v = self.count
         for unit in ['','K','M','G','T','P','E','Z']:
@@ -108,22 +112,30 @@ class Profile:
     def count_max(self):
         return max([v.count for k, v in self.heuristics.items()])
 
-    def dump(self):
+    def dump(self, sorting):
+        sorter = lambda x: x[1].branches
+        if sorting == 'hitrate':
+            sorter = lambda x: x[1].get_hitrate()
+        elif sorting == 'coverage':
+            sorter = lambda x: x[1].count
+
         print('%-36s %8s %6s  %-16s %14s %8s %6s' % ('HEURISTICS', 'BRANCHES', '(REL)',
               'HITRATE', 'COVERAGE', 'COVERAGE', '(REL)'))
-        for (k, v) in sorted(self.heuristics.items(), key = lambda x: x[1].branches):
+        for (k, v) in sorted(self.heuristics.items(), key = sorter):
             print('%-36s %8i %5.1f%% %6.2f%% / %6.2f%% %14i %8s %5.1f%%' %
             (k, v.branches, percentage(v.branches, self.branches_max ()),
              percentage(v.hits, v.count), percentage(v.fits, v.count),
              v.count, v.count_formatted(), percentage(v.count, self.count_max()) ))
 
-if len(sys.argv) != 2:
-    print('Usage: ./analyze_brprob.py dump_file')
-    exit(1)
+parser = argparse.ArgumentParser()
+parser.add_argument('dump_file', metavar = 'dump_file', help = 'IPA profile dump file')
+parser.add_argument('-s', '--sorting', dest = 'sorting', choices = ['branches', 'hitrate', 'coverage'], default = 'branches')
+
+args = parser.parse_args()
 
 profile = Profile(sys.argv[1])
 r = re.compile('  (.*) heuristics( of edge [0-9]*->[0-9]*)?( \\(.*\\))?: (.*)%.*exec ([0-9]*) hit ([0-9]*)')
-for l in open(profile.filename).readlines():
+for l in open(args.dump_file).readlines():
     m = r.match(l)
     if m != None and m.group(3) == None:
         name = m.group(1)
@@ -133,4 +145,4 @@ for l in open(profile.filename).readlines():
 
         profile.add(name, prediction, count, hits)
 
-profile.dump()
+profile.dump(args.sorting)
-- 
2.8.3


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 4/N] Add new analyze_brprob_spec.py script
  2016-06-02 11:57 [PATCH 0/2] Deduplicate edge predictors marxin
                   ` (2 preceding siblings ...)
  2016-06-08 12:26 ` [PATCH 3/N] Add sorting support to analyze_brprob script Martin Liška
@ 2016-06-08 12:29 ` Martin Liška
  2016-06-08 15:12   ` Jan Hubicka
  3 siblings, 1 reply; 14+ messages in thread
From: Martin Liška @ 2016-06-08 12:29 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3635 bytes --]

Hi.

The second follow up patch adds new script which is a simple wrapper around
analyze_brprob.py and can be used to dump statistics for results that are in
different folder (like SPEC benchmarks).

Sample:
./contrib/analyze_brprob_spec.py --sorting=hitrate /home/marxin/Programming/cpu2006/benchspec/CPU2006/

Sample output:
401.bzip2
HEURISTICS                           BRANCHES  (REL)  HITRATE                COVERAGE COVERAGE  (REL)
no prediction                             107  14.0%  19.45% /  84.37%     2768134733    2.77G  10.8%
opcode values nonequal (on trees)          76  10.0%  32.24% /  85.06%     4034681344    4.03G  15.8%
call                                       95  12.5%  45.50% /  93.31%      152224913  152.22M   0.6%
DS theory                                 275  36.1%  45.56% /  84.30%     7308863904    7.31G  28.6%
continue                                   14   1.8%  48.44% /  73.14%     1479774996    1.48G   5.8%
guessed loop iterations                    12   1.6%  68.30% /  71.61%      269705737  269.71M   1.1%
combined                                  762 100.0%  69.52% /  89.32%    25553311262   25.55G 100.0%
goto                                       40   5.2%  72.41% /  98.80%      882062676  882.06M   3.5%
opcode values positive (on trees)          40   5.2%  76.74% /  88.09%     1394104926    1.39G   5.5%
pointer (on trees)                         61   8.0%  83.79% / 100.00%         931107  931.11K   0.0%
early return (on trees)                    31   4.1%  84.39% /  84.41%     2548058402    2.55G  10.0%
first match                               380  49.9%  89.79% /  92.57%    15476312625   15.48G  60.6%
loop exit                                 316  41.5%  90.09% /  92.88%    15065219828   15.07G  59.0%
guess loop iv compare                       2   0.3%  99.61% /  99.61%       26987995   26.99M   0.1%
loop iv compare                             1   0.1%  99.61% /  99.61%         105411  105.41K   0.0%
loop iterations                            38   5.0%  99.64% /  99.64%      140236649  140.24M   0.5%
null return                                 2   0.3% 100.00% / 100.00%             18    18.00   0.0%
noreturn call                              13   1.7% 100.00% / 100.00%        1045000    1.04M   0.0%
const return                                2   0.3% 100.00% / 100.00%            816   816.00   0.0%
negative return                            62   8.1% 100.00% / 100.00%      618097152  618.10M   2.4%

410.bwaves
HEURISTICS                           BRANCHES  (REL)  HITRATE                COVERAGE COVERAGE  (REL)
call                                        1   0.6%   0.00% / 100.00%             20    20.00   0.0%
no prediction                               6   3.7%   0.28% /  99.72%        2704184    2.70M   0.1%
opcode values nonequal (on trees)           4   2.4%  60.00% /  70.00%            200   200.00   0.0%
loop iterations                             7   4.3%  80.00% /  80.00%      112892000  112.89M   2.4%
first match                                83  50.6%  81.67% /  81.67%     4393885465    4.39G  92.1%
loop exit                                  76  46.3%  81.71% /  81.71%     4280993465    4.28G  89.8%
combined                                  164 100.0%  83.05% /  83.11%     4768545507    4.77G 100.0%
DS theory                                  75  45.7% 100.00% / 100.00%      371955858  371.96M   7.8%
early return (on trees)                     3   1.8% 100.00% / 100.00%            688   688.00   0.0%
opcode values positive (on trees)          71  43.3% 100.00% / 100.00%      371955658  371.96M   7.8%

...

Thanks,
Martin


[-- Attachment #2: 0004-Add-new-analyze_brprob_spec.py-script.patch --]
[-- Type: text/x-patch, Size: 2498 bytes --]

From ca9806bf77bd90df43913f5f1552ed16379dcf38 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Fri, 3 Jun 2016 12:46:43 +0200
Subject: [PATCH 4/4] Add new analyze_brprob_spec.py script

contrib/ChangeLog:

2016-06-08  Martin Liska  <mliska@suse.cz>

	* analyze_brprob_spec.py: New file.
---
 contrib/analyze_brprob_spec.py | 58 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)
 create mode 100755 contrib/analyze_brprob_spec.py

diff --git a/contrib/analyze_brprob_spec.py b/contrib/analyze_brprob_spec.py
new file mode 100755
index 0000000..a28eaac
--- /dev/null
+++ b/contrib/analyze_brprob_spec.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+
+# 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/>.  */
+
+import sys
+import os
+import subprocess
+import tempfile
+import argparse
+
+script_location = os.path.realpath(__file__)
+
+parser = argparse.ArgumentParser()
+parser.add_argument('location', metavar = 'dump_file', help = 'Location with SPEC benchmarks')
+parser.add_argument('-s', '--sorting', dest = 'sorting', choices = ['branches', 'hitrate', 'coverage'], default = 'branches')
+
+args = parser.parse_args()
+
+benchmarks = os.listdir(args.location)
+
+for b in sorted(benchmarks):
+    dumps = []
+    for root, dirs, files in os.walk(os.path.join(args.location, b)):
+        for x in files:
+            if x.endswith('.profile'):
+                dumps.append(os.path.join(root, x))
+
+    if len(dumps) == 0:
+        continue
+
+    temp = tempfile.NamedTemporaryFile(delete = False)
+    for d in dumps:
+        temp.write(open(d, 'rb').read())
+
+    temp.close()
+
+    print()
+    print(b)
+    sys.stdout.flush()
+    p = [os.path.join(os.path.dirname(script_location), 'analyze_brprob.py'), temp.name, '--sorting', args.sorting]
+    p = subprocess.check_call(p)
+    sys.stdout.flush()
+
+    os.remove(temp.name)
-- 
2.8.3


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] Add edge predictions pruning
  2016-06-08 12:25   ` Martin Liška
@ 2016-06-08 12:41     ` Jan Hubicka
  2016-06-09 11:24       ` Martin Liška
  0 siblings, 1 reply; 14+ messages in thread
From: Jan Hubicka @ 2016-06-08 12:41 UTC (permalink / raw)
  To: Martin Liška; +Cc: gcc-patches, Jan Hubicka

> 2016-06-01  Martin Liska  <mliska@suse.cz>
> 
> 	* analyze_brprob.py: Cover new dump output format.
> 
> gcc/ChangeLog:
> 
> 2016-06-01  Martin Liska  <mliska@suse.cz>
> 
> 	* predict.c (dump_prediction): Add new argument.
> 	(enum predictor_reason): New enum.
> 	(struct predictor_hash): New struct.
> 	(predictor_hash::hash): New function.
> 	(predictor_hash::equal): Likewise.
> 	(not_removed_prediction_p): New function.
> 	(prune_predictions_for_bb): Likewise.
> 	(combine_predictions_for_bb): Prune predictions.
> ---
>  contrib/analyze_brprob.py |  10 +--
>  gcc/predict.c             | 180 ++++++++++++++++++++++++++++++++++++++++------
>  2 files changed, 165 insertions(+), 25 deletions(-)
> 
> diff --git a/contrib/analyze_brprob.py b/contrib/analyze_brprob.py
> index 36371ff..9416eed 100755
> --- a/contrib/analyze_brprob.py
> +++ b/contrib/analyze_brprob.py
> @@ -122,14 +122,14 @@ if len(sys.argv) != 2:
>      exit(1)
>  
>  profile = Profile(sys.argv[1])
> -r = re.compile('  (.*) heuristics: (.*)%.*exec ([0-9]*) hit ([0-9]*)')
> +r = re.compile('  (.*) heuristics( of edge [0-9]*->[0-9]*)?( \\(.*\\))?: (.*)%.*exec ([0-9]*) hit ([0-9]*)')
>  for l in open(profile.filename).readlines():
>      m = r.match(l)
> -    if m != None:
> +    if m != None and m.group(3) == None:
>          name = m.group(1)
> -        prediction = float(m.group(2))
> -        count = int(m.group(3))
> -        hits = int(m.group(4))
> +        prediction = float(m.group(4))
> +        count = int(m.group(5))
> +        hits = int(m.group(6))
>  
>          profile.add(name, prediction, count, hits)
>  
> diff --git a/gcc/predict.c b/gcc/predict.c
> index e058793..f2ecc4a 100644
> --- a/gcc/predict.c
> +++ b/gcc/predict.c
> @@ -55,13 +55,25 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-ssa-loop.h"
>  #include "tree-scalar-evolution.h"
>  
> +enum predictor_reason
Add comment, please
> +{
> +  NONE,
> +  IGNORED,
> +  SINGLE_EDGE_DUPLICATE,
> +  EDGE_PAIR_DUPLICATE
> +};
> +
> +static const char *reason_messages[] = {"", " (ignored)",
> +    " (single edge duplicate)", " (edge pair duplicate)"};

And here too.
> +
>  /* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE,
>  		   1/REG_BR_PROB_BASE, 0.5, BB_FREQ_MAX.  */
>  static sreal real_almost_one, real_br_prob_base,
>  	     real_inv_br_prob_base, real_one_half, real_bb_freq_max;
>  
>  static void combine_predictions_for_insn (rtx_insn *, basic_block);
> -static void dump_prediction (FILE *, enum br_predictor, int, basic_block, int);
> +static void dump_prediction (FILE *, enum br_predictor, int, basic_block,
> +			     enum predictor_reason, edge);
>  static void predict_paths_leading_to (basic_block, enum br_predictor, enum prediction);
>  static void predict_paths_leading_to_edge (edge, enum br_predictor, enum prediction);
>  static bool can_predict_insn_p (const rtx_insn *);
> @@ -723,21 +735,31 @@ invert_br_probabilities (rtx insn)
>  
>  static void
>  dump_prediction (FILE *file, enum br_predictor predictor, int probability,
> -		 basic_block bb, int used)
> +		 basic_block bb, enum predictor_reason reason = NONE,
> +		 edge ep_edge = NULL)
>  {
> -  edge e;
> +  edge e = ep_edge;
>    edge_iterator ei;
>  
>    if (!file)
>      return;
>  
> -  FOR_EACH_EDGE (e, ei, bb->succs)
> -    if (! (e->flags & EDGE_FALLTHRU))
> -      break;
> +  if (e == NULL)
> +    FOR_EACH_EDGE (e, ei, bb->succs)
> +      if (! (e->flags & EDGE_FALLTHRU))
> +	break;
>  
> -  fprintf (file, "  %s heuristics%s: %.1f%%",
> +  char edge_info_str[128];
> +  if (ep_edge)
> +    sprintf (edge_info_str, " of edge %d->%d", ep_edge->src->index,
> +	     ep_edge->dest->index);
> +  else
> +    edge_info_str[0] = '\0';
> +
> +  fprintf (file, "  %s heuristics%s%s: %.1f%%",
>  	   predictor_info[predictor].name,
> -	   used ? "" : " (ignored)", probability * 100.0 / REG_BR_PROB_BASE);
> +	   edge_info_str, reason_messages[reason],
> +	   probability * 100.0 / REG_BR_PROB_BASE);
>  
>    if (bb->count)
>      {
> @@ -834,18 +856,18 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
>  
>    if (!found)
>      dump_prediction (dump_file, PRED_NO_PREDICTION,
> -		     combined_probability, bb, true);
> +		     combined_probability, bb);
>    else
>      {
>        dump_prediction (dump_file, PRED_DS_THEORY, combined_probability,
> -		       bb, !first_match);
> +		       bb, !first_match ? NONE : IGNORED);
>        dump_prediction (dump_file, PRED_FIRST_MATCH, best_probability,
> -		       bb, first_match);
> +		       bb, first_match ? NONE: IGNORED);
>      }
>  
>    if (first_match)
>      combined_probability = best_probability;
> -  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb, true);
> +  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb);
>  
>    while (*pnote)
>      {
> @@ -856,7 +878,8 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
>  	  int probability = INTVAL (XEXP (XEXP (*pnote, 0), 1));
>  
>  	  dump_prediction (dump_file, predictor, probability, bb,
> -			   !first_match || best_predictor == predictor);
> +			   (!first_match || best_predictor == predictor)
> +			   ? NONE : IGNORED);
>  	  *pnote = XEXP (*pnote, 1);
>  	}
>        else
> @@ -887,6 +910,121 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
>      single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
>  }
>  
> +/* Edge prediction hash traits.  */
> +
> +struct predictor_hash: pointer_hash <edge_prediction>
> +{
> +
> +  static inline hashval_t hash (const edge_prediction *);
> +  static inline bool equal (const edge_prediction *, const edge_prediction *);
> +};
> +
> +/* Calculate hash value of an edge prediction P based on predictor and
> +   normalized probability.  */
> +
> +inline hashval_t
> +predictor_hash::hash (const edge_prediction *p)
> +{
> +  inchash::hash hstate;
> +  hstate.add_int (p->ep_predictor);
> +
> +  int prob = p->ep_probability;
> +  if (prob > REG_BR_PROB_BASE / 2)
> +    prob = REG_BR_PROB_BASE - prob;
> +
> +  hstate.add_int (prob);
> +
> +  return hstate.end ();
> +}

Adding hash for this prupose is bit of an overkill (there are
definitly cheaper ways of solving so), but it will hardly affect compile
time, so the pathc is OK.

Thanks,
Honza
> +
> +/* Return true whether edge predictions P1 and P2 use the same predictor and
> +   have equal (or opposed probability).  */
> +
> +inline bool
> +predictor_hash::equal (const edge_prediction *p1, const edge_prediction *p2)
> +{
> +  return (p1->ep_predictor == p2->ep_predictor
> +	  && (p1->ep_probability == p2->ep_probability
> +	      || p1->ep_probability == REG_BR_PROB_BASE - p2->ep_probability));
> +}
> +
> +struct predictor_hash_traits: predictor_hash,
> +  typed_noop_remove <edge_prediction *> {};
> +
> +/* Return true if edge prediction P is not in DATA hash set.  */
> +
> +static bool
> +not_removed_prediction_p (edge_prediction *p, void *data)
> +{
> +  hash_set<edge_prediction *> *remove = (hash_set<edge_prediction *> *) data;
> +  return !remove->contains (p);
> +}
> +
> +/* Prune predictions for a basic block BB.  Currently we do following
> +   clean-up steps:
> +
> +   1) remove duplicate prediction that is guessed with the same probability
> +      (different than 1/2) to both edge
> +   2) remove duplicates for a prediction that belongs with the same probability
> +      to a single edge
> +
> +  */
> +
> +static void
> +prune_predictions_for_bb (basic_block bb)
> +{
> +  edge_prediction **preds = bb_predictions->get (bb);
> +
> +  if (preds)
> +    {
> +      hash_table <predictor_hash_traits> s (13);
> +      hash_set <edge_prediction *> remove;
> +
> +      /* Step 1: identify predictors that should be removed.  */
> +      for (edge_prediction *pred = *preds; pred; pred = pred->ep_next)
> +	{
> +	  edge_prediction *existing = s.find (pred);
> +	  if (existing)
> +	    {
> +	      if (pred->ep_edge == existing->ep_edge
> +		  && pred->ep_probability == existing->ep_probability)
> +		{
> +		  /* Remove a duplicate predictor.  */
> +		  dump_prediction (dump_file, pred->ep_predictor,
> +				   pred->ep_probability, bb,
> +				   SINGLE_EDGE_DUPLICATE, pred->ep_edge);
> +
> +		  remove.add (pred);
> +		}
> +	      else if (pred->ep_edge != existing->ep_edge
> +		       && pred->ep_probability == existing->ep_probability
> +		       && pred->ep_probability != REG_BR_PROB_BASE / 2)
> +		{
> +		  /* Remove both predictors as they predict the same
> +		     for both edges.  */
> +		  dump_prediction (dump_file, existing->ep_predictor,
> +				   pred->ep_probability, bb,
> +				   EDGE_PAIR_DUPLICATE,
> +				   existing->ep_edge);
> +		  dump_prediction (dump_file, pred->ep_predictor,
> +				   pred->ep_probability, bb,
> +				   EDGE_PAIR_DUPLICATE,
> +				   pred->ep_edge);
> +
> +		  remove.add (existing);
> +		  remove.add (pred);
> +		}
> +	    }
> +
> +	  edge_prediction **slot2 = s.find_slot (pred, INSERT);
> +	  *slot2 = pred;
> +	}
> +
> +      /* Step 2: Remove predictors.  */
> +      filter_predictions (preds, not_removed_prediction_p, &remove);
> +    }
> +}
> +
>  /* Combine predictions into single probability and store them into CFG.
>     Remove now useless prediction entries.
>     If DRY_RUN is set, only produce dumps and do not modify profile.  */
> @@ -935,7 +1073,10 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
>    if (dump_file)
>      fprintf (dump_file, "Predictions for bb %i\n", bb->index);
>  
> +  prune_predictions_for_bb (bb);
> +
>    edge_prediction **preds = bb_predictions->get (bb);
> +
>    if (preds)
>      {
>        /* We implement "first match" heuristics and use probability guessed
> @@ -1001,18 +1142,18 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
>      first_match = true;
>  
>    if (!found)
> -    dump_prediction (dump_file, PRED_NO_PREDICTION, combined_probability, bb, true);
> +    dump_prediction (dump_file, PRED_NO_PREDICTION, combined_probability, bb);
>    else
>      {
>        dump_prediction (dump_file, PRED_DS_THEORY, combined_probability, bb,
> -		       !first_match);
> +		       !first_match ? NONE : IGNORED);
>        dump_prediction (dump_file, PRED_FIRST_MATCH, best_probability, bb,
> -		       first_match);
> +		       first_match ? NONE : IGNORED);
>      }
>  
>    if (first_match)
>      combined_probability = best_probability;
> -  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb, true);
> +  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb);
>  
>    if (preds)
>      {
> @@ -1021,10 +1162,9 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
>  	  enum br_predictor predictor = pred->ep_predictor;
>  	  int probability = pred->ep_probability;
>  
> -	  if (pred->ep_edge != EDGE_SUCC (bb, 0))
> -	    probability = REG_BR_PROB_BASE - probability;
>  	  dump_prediction (dump_file, predictor, probability, bb,
> -			   !first_match || best_predictor == predictor);
> +			   (!first_match || best_predictor == predictor)
> +			   ? NONE : IGNORED, pred->ep_edge);
>  	}
>      }
>    clear_bb_predictions (bb);
> -- 
> 2.8.3
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/N] Add sorting support to analyze_brprob script
  2016-06-08 12:26 ` [PATCH 3/N] Add sorting support to analyze_brprob script Martin Liška
@ 2016-06-08 15:02   ` Jan Hubicka
  0 siblings, 0 replies; 14+ messages in thread
From: Jan Hubicka @ 2016-06-08 15:02 UTC (permalink / raw)
  To: Martin Liška; +Cc: gcc-patches

> Hello.
> 
> This is a small followup, where I would like to add new argument to analyze_brprob.py
> script file. With the patch, one can sort predictors by e.g. hitrate:

OK,
thanks!

Honza

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/N] Add new analyze_brprob_spec.py script
  2016-06-08 12:29 ` [PATCH 4/N] Add new analyze_brprob_spec.py script Martin Liška
@ 2016-06-08 15:12   ` Jan Hubicka
  0 siblings, 0 replies; 14+ messages in thread
From: Jan Hubicka @ 2016-06-08 15:12 UTC (permalink / raw)
  To: Martin Liška; +Cc: gcc-patches

> Hi.
> 
> The second follow up patch adds new script which is a simple wrapper around
> analyze_brprob.py and can be used to dump statistics for results that are in
> different folder (like SPEC benchmarks).
> 
> Sample:
> ./contrib/analyze_brprob_spec.py --sorting=hitrate /home/marxin/Programming/cpu2006/benchspec/CPU2006/
> 
> Sample output:
> 401.bzip2
> HEURISTICS                           BRANCHES  (REL)  HITRATE                COVERAGE COVERAGE  (REL)
> no prediction                             107  14.0%  19.45% /  84.37%     2768134733    2.77G  10.8%
> opcode values nonequal (on trees)          76  10.0%  32.24% /  85.06%     4034681344    4.03G  15.8%
> call                                       95  12.5%  45.50% /  93.31%      152224913  152.22M   0.6%
> DS theory                                 275  36.1%  45.56% /  84.30%     7308863904    7.31G  28.6%
> continue                                   14   1.8%  48.44% /  73.14%     1479774996    1.48G   5.8%
> guessed loop iterations                    12   1.6%  68.30% /  71.61%      269705737  269.71M   1.1%
> combined                                  762 100.0%  69.52% /  89.32%    25553311262   25.55G 100.0%
> goto                                       40   5.2%  72.41% /  98.80%      882062676  882.06M   3.5%
> opcode values positive (on trees)          40   5.2%  76.74% /  88.09%     1394104926    1.39G   5.5%
> pointer (on trees)                         61   8.0%  83.79% / 100.00%         931107  931.11K   0.0%
> early return (on trees)                    31   4.1%  84.39% /  84.41%     2548058402    2.55G  10.0%
> first match                               380  49.9%  89.79% /  92.57%    15476312625   15.48G  60.6%
> loop exit                                 316  41.5%  90.09% /  92.88%    15065219828   15.07G  59.0%
> guess loop iv compare                       2   0.3%  99.61% /  99.61%       26987995   26.99M   0.1%
> loop iv compare                             1   0.1%  99.61% /  99.61%         105411  105.41K   0.0%
> loop iterations                            38   5.0%  99.64% /  99.64%      140236649  140.24M   0.5%
> null return                                 2   0.3% 100.00% / 100.00%             18    18.00   0.0%
> noreturn call                              13   1.7% 100.00% / 100.00%        1045000    1.04M   0.0%
> const return                                2   0.3% 100.00% / 100.00%            816   816.00   0.0%
> negative return                            62   8.1% 100.00% / 100.00%      618097152  618.10M   2.4%
> 
> 410.bwaves
> HEURISTICS                           BRANCHES  (REL)  HITRATE                COVERAGE COVERAGE  (REL)
> call                                        1   0.6%   0.00% / 100.00%             20    20.00   0.0%
> no prediction                               6   3.7%   0.28% /  99.72%        2704184    2.70M   0.1%
> opcode values nonequal (on trees)           4   2.4%  60.00% /  70.00%            200   200.00   0.0%
> loop iterations                             7   4.3%  80.00% /  80.00%      112892000  112.89M   2.4%
> first match                                83  50.6%  81.67% /  81.67%     4393885465    4.39G  92.1%
> loop exit                                  76  46.3%  81.71% /  81.71%     4280993465    4.28G  89.8%
> combined                                  164 100.0%  83.05% /  83.11%     4768545507    4.77G 100.0%
> DS theory                                  75  45.7% 100.00% / 100.00%      371955858  371.96M   7.8%
> early return (on trees)                     3   1.8% 100.00% / 100.00%            688   688.00   0.0%
> opcode values positive (on trees)          71  43.3% 100.00% / 100.00%      371955658  371.96M   7.8%
> 
> ...
> 
> Thanks,
> Martin
> 

> >From ca9806bf77bd90df43913f5f1552ed16379dcf38 Mon Sep 17 00:00:00 2001
> From: marxin <mliska@suse.cz>
> Date: Fri, 3 Jun 2016 12:46:43 +0200
> Subject: [PATCH 4/4] Add new analyze_brprob_spec.py script
> 
> contrib/ChangeLog:
> 
> 2016-06-08  Martin Liska  <mliska@suse.cz>
> 
> 	* analyze_brprob_spec.py: New file.

OK,
thanks

Honza
> ---
>  contrib/analyze_brprob_spec.py | 58 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 58 insertions(+)
>  create mode 100755 contrib/analyze_brprob_spec.py
> 
> diff --git a/contrib/analyze_brprob_spec.py b/contrib/analyze_brprob_spec.py
> new file mode 100755
> index 0000000..a28eaac
> --- /dev/null
> +++ b/contrib/analyze_brprob_spec.py
> @@ -0,0 +1,58 @@
> +#!/usr/bin/env python3
> +
> +# 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/>.  */
> +
> +import sys
> +import os
> +import subprocess
> +import tempfile
> +import argparse
> +
> +script_location = os.path.realpath(__file__)
> +
> +parser = argparse.ArgumentParser()
> +parser.add_argument('location', metavar = 'dump_file', help = 'Location with SPEC benchmarks')
> +parser.add_argument('-s', '--sorting', dest = 'sorting', choices = ['branches', 'hitrate', 'coverage'], default = 'branches')
> +
> +args = parser.parse_args()
> +
> +benchmarks = os.listdir(args.location)
> +
> +for b in sorted(benchmarks):
> +    dumps = []
> +    for root, dirs, files in os.walk(os.path.join(args.location, b)):
> +        for x in files:
> +            if x.endswith('.profile'):
> +                dumps.append(os.path.join(root, x))
> +
> +    if len(dumps) == 0:
> +        continue
> +
> +    temp = tempfile.NamedTemporaryFile(delete = False)
> +    for d in dumps:
> +        temp.write(open(d, 'rb').read())
> +
> +    temp.close()
> +
> +    print()
> +    print(b)
> +    sys.stdout.flush()
> +    p = [os.path.join(os.path.dirname(script_location), 'analyze_brprob.py'), temp.name, '--sorting', args.sorting]
> +    p = subprocess.check_call(p)
> +    sys.stdout.flush()
> +
> +    os.remove(temp.name)
> -- 
> 2.8.3
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] Add edge predictions pruning
  2016-06-08 12:41     ` Jan Hubicka
@ 2016-06-09 11:24       ` Martin Liška
  2016-06-12 11:55         ` [BUILDROBOT] MPS430 build problem due to new enum (was: [PATCH 2/2] Add edge predictions pruning) Jan-Benedict Glaw
  0 siblings, 1 reply; 14+ messages in thread
From: Martin Liška @ 2016-06-09 11:24 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 356 bytes --]

On 06/08/2016 02:41 PM, Jan Hubicka wrote:
> Adding hash for this prupose is bit of an overkill (there are
> definitly cheaper ways of solving so), but it will hardly affect compile
> time, so the pathc is OK.
> 
> Thanks,
> Honza

Hi

Sending the final version where I added comments and I also changed
dump scanning to cover the new dump format.

Martin

[-- Attachment #2: 0002-Add-edge-predictions-pruning-v3.patch --]
[-- Type: text/x-patch, Size: 16828 bytes --]

From f83a515c952f3f17b45c757a3a84761d95959a39 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Tue, 31 May 2016 17:29:53 +0200
Subject: [PATCH 2/4] Add edge predictions pruning

contrib/ChangeLog:

2016-06-01  Martin Liska  <mliska@suse.cz>

	* analyze_brprob.py: Cover new dump output format.

gcc/ChangeLog:

2016-06-01  Martin Liska  <mliska@suse.cz>

	* predict.c (dump_prediction): Add new argument.
	(enum predictor_reason): New enum.
	(struct predictor_hash): New struct.
	(predictor_hash::hash): New function.
	(predictor_hash::equal): Likewise.
	(not_removed_prediction_p): New function.
	(prune_predictions_for_bb): Likewise.
	(combine_predictions_for_bb): Prune predictions.

gcc/testsuite/ChangeLog:

2016-06-08  Martin Liska  <mliska@suse.cz>

	* g++.dg/predict-loop-exit-1.C: Scan for a new dump format.
	* g++.dg/predict-loop-exit-2.C: Likewise.
	* g++.dg/predict-loop-exit-3.C: Likewise.
	* gcc.dg/predict-1.c: Likewise.
	* gcc.dg/predict-2.c: Likewise.
	* gcc.dg/predict-3.c: Likewise.
	* gcc.dg/predict-4.c: Likewise.
	* gcc.dg/predict-5.c: Likewise.
	* gcc.dg/predict-6.c: Likewise.
	* gcc.dg/predict-7.c: Likewise.
---
 contrib/analyze_brprob.py                  |  10 +-
 gcc/predict.c                              | 184 +++++++++++++++++++++++++----
 gcc/testsuite/g++.dg/predict-loop-exit-1.C |   4 +-
 gcc/testsuite/g++.dg/predict-loop-exit-2.C |   4 +-
 gcc/testsuite/g++.dg/predict-loop-exit-3.C |   4 +-
 gcc/testsuite/gcc.dg/predict-1.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-2.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-3.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-4.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-5.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-6.c           |   2 +-
 gcc/testsuite/gcc.dg/predict-7.c           |   2 +-
 12 files changed, 182 insertions(+), 38 deletions(-)

diff --git a/contrib/analyze_brprob.py b/contrib/analyze_brprob.py
index 36371ff..9416eed 100755
--- a/contrib/analyze_brprob.py
+++ b/contrib/analyze_brprob.py
@@ -122,14 +122,14 @@ if len(sys.argv) != 2:
     exit(1)
 
 profile = Profile(sys.argv[1])
-r = re.compile('  (.*) heuristics: (.*)%.*exec ([0-9]*) hit ([0-9]*)')
+r = re.compile('  (.*) heuristics( of edge [0-9]*->[0-9]*)?( \\(.*\\))?: (.*)%.*exec ([0-9]*) hit ([0-9]*)')
 for l in open(profile.filename).readlines():
     m = r.match(l)
-    if m != None:
+    if m != None and m.group(3) == None:
         name = m.group(1)
-        prediction = float(m.group(2))
-        count = int(m.group(3))
-        hits = int(m.group(4))
+        prediction = float(m.group(4))
+        count = int(m.group(5))
+        hits = int(m.group(6))
 
         profile.add(name, prediction, count, hits)
 
diff --git a/gcc/predict.c b/gcc/predict.c
index e058793..a61e01c 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -55,13 +55,29 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-loop.h"
 #include "tree-scalar-evolution.h"
 
+/* Enum with reasons why a predictor is ignored.  */
+
+enum predictor_reason
+{
+  NONE,
+  IGNORED,
+  SINGLE_EDGE_DUPLICATE,
+  EDGE_PAIR_DUPLICATE
+};
+
+/* String messages for the aforementioned enum.  */
+
+static const char *reason_messages[] = {"", " (ignored)",
+    " (single edge duplicate)", " (edge pair duplicate)"};
+
 /* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE,
 		   1/REG_BR_PROB_BASE, 0.5, BB_FREQ_MAX.  */
 static sreal real_almost_one, real_br_prob_base,
 	     real_inv_br_prob_base, real_one_half, real_bb_freq_max;
 
 static void combine_predictions_for_insn (rtx_insn *, basic_block);
-static void dump_prediction (FILE *, enum br_predictor, int, basic_block, int);
+static void dump_prediction (FILE *, enum br_predictor, int, basic_block,
+			     enum predictor_reason, edge);
 static void predict_paths_leading_to (basic_block, enum br_predictor, enum prediction);
 static void predict_paths_leading_to_edge (edge, enum br_predictor, enum prediction);
 static bool can_predict_insn_p (const rtx_insn *);
@@ -723,21 +739,31 @@ invert_br_probabilities (rtx insn)
 
 static void
 dump_prediction (FILE *file, enum br_predictor predictor, int probability,
-		 basic_block bb, int used)
+		 basic_block bb, enum predictor_reason reason = NONE,
+		 edge ep_edge = NULL)
 {
-  edge e;
+  edge e = ep_edge;
   edge_iterator ei;
 
   if (!file)
     return;
 
-  FOR_EACH_EDGE (e, ei, bb->succs)
-    if (! (e->flags & EDGE_FALLTHRU))
-      break;
+  if (e == NULL)
+    FOR_EACH_EDGE (e, ei, bb->succs)
+      if (! (e->flags & EDGE_FALLTHRU))
+	break;
+
+  char edge_info_str[128];
+  if (ep_edge)
+    sprintf (edge_info_str, " of edge %d->%d", ep_edge->src->index,
+	     ep_edge->dest->index);
+  else
+    edge_info_str[0] = '\0';
 
-  fprintf (file, "  %s heuristics%s: %.1f%%",
+  fprintf (file, "  %s heuristics%s%s: %.1f%%",
 	   predictor_info[predictor].name,
-	   used ? "" : " (ignored)", probability * 100.0 / REG_BR_PROB_BASE);
+	   edge_info_str, reason_messages[reason],
+	   probability * 100.0 / REG_BR_PROB_BASE);
 
   if (bb->count)
     {
@@ -834,18 +860,18 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
 
   if (!found)
     dump_prediction (dump_file, PRED_NO_PREDICTION,
-		     combined_probability, bb, true);
+		     combined_probability, bb);
   else
     {
       dump_prediction (dump_file, PRED_DS_THEORY, combined_probability,
-		       bb, !first_match);
+		       bb, !first_match ? NONE : IGNORED);
       dump_prediction (dump_file, PRED_FIRST_MATCH, best_probability,
-		       bb, first_match);
+		       bb, first_match ? NONE: IGNORED);
     }
 
   if (first_match)
     combined_probability = best_probability;
-  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb, true);
+  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb);
 
   while (*pnote)
     {
@@ -856,7 +882,8 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
 	  int probability = INTVAL (XEXP (XEXP (*pnote, 0), 1));
 
 	  dump_prediction (dump_file, predictor, probability, bb,
-			   !first_match || best_predictor == predictor);
+			   (!first_match || best_predictor == predictor)
+			   ? NONE : IGNORED);
 	  *pnote = XEXP (*pnote, 1);
 	}
       else
@@ -887,6 +914,121 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
     single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
 }
 
+/* Edge prediction hash traits.  */
+
+struct predictor_hash: pointer_hash <edge_prediction>
+{
+
+  static inline hashval_t hash (const edge_prediction *);
+  static inline bool equal (const edge_prediction *, const edge_prediction *);
+};
+
+/* Calculate hash value of an edge prediction P based on predictor and
+   normalized probability.  */
+
+inline hashval_t
+predictor_hash::hash (const edge_prediction *p)
+{
+  inchash::hash hstate;
+  hstate.add_int (p->ep_predictor);
+
+  int prob = p->ep_probability;
+  if (prob > REG_BR_PROB_BASE / 2)
+    prob = REG_BR_PROB_BASE - prob;
+
+  hstate.add_int (prob);
+
+  return hstate.end ();
+}
+
+/* Return true whether edge predictions P1 and P2 use the same predictor and
+   have equal (or opposed probability).  */
+
+inline bool
+predictor_hash::equal (const edge_prediction *p1, const edge_prediction *p2)
+{
+  return (p1->ep_predictor == p2->ep_predictor
+	  && (p1->ep_probability == p2->ep_probability
+	      || p1->ep_probability == REG_BR_PROB_BASE - p2->ep_probability));
+}
+
+struct predictor_hash_traits: predictor_hash,
+  typed_noop_remove <edge_prediction *> {};
+
+/* Return true if edge prediction P is not in DATA hash set.  */
+
+static bool
+not_removed_prediction_p (edge_prediction *p, void *data)
+{
+  hash_set<edge_prediction *> *remove = (hash_set<edge_prediction *> *) data;
+  return !remove->contains (p);
+}
+
+/* Prune predictions for a basic block BB.  Currently we do following
+   clean-up steps:
+
+   1) remove duplicate prediction that is guessed with the same probability
+      (different than 1/2) to both edge
+   2) remove duplicates for a prediction that belongs with the same probability
+      to a single edge
+
+  */
+
+static void
+prune_predictions_for_bb (basic_block bb)
+{
+  edge_prediction **preds = bb_predictions->get (bb);
+
+  if (preds)
+    {
+      hash_table <predictor_hash_traits> s (13);
+      hash_set <edge_prediction *> remove;
+
+      /* Step 1: identify predictors that should be removed.  */
+      for (edge_prediction *pred = *preds; pred; pred = pred->ep_next)
+	{
+	  edge_prediction *existing = s.find (pred);
+	  if (existing)
+	    {
+	      if (pred->ep_edge == existing->ep_edge
+		  && pred->ep_probability == existing->ep_probability)
+		{
+		  /* Remove a duplicate predictor.  */
+		  dump_prediction (dump_file, pred->ep_predictor,
+				   pred->ep_probability, bb,
+				   SINGLE_EDGE_DUPLICATE, pred->ep_edge);
+
+		  remove.add (pred);
+		}
+	      else if (pred->ep_edge != existing->ep_edge
+		       && pred->ep_probability == existing->ep_probability
+		       && pred->ep_probability != REG_BR_PROB_BASE / 2)
+		{
+		  /* Remove both predictors as they predict the same
+		     for both edges.  */
+		  dump_prediction (dump_file, existing->ep_predictor,
+				   pred->ep_probability, bb,
+				   EDGE_PAIR_DUPLICATE,
+				   existing->ep_edge);
+		  dump_prediction (dump_file, pred->ep_predictor,
+				   pred->ep_probability, bb,
+				   EDGE_PAIR_DUPLICATE,
+				   pred->ep_edge);
+
+		  remove.add (existing);
+		  remove.add (pred);
+		}
+	    }
+
+	  edge_prediction **slot2 = s.find_slot (pred, INSERT);
+	  *slot2 = pred;
+	}
+
+      /* Step 2: Remove predictors.  */
+      filter_predictions (preds, not_removed_prediction_p, &remove);
+    }
+}
+
 /* Combine predictions into single probability and store them into CFG.
    Remove now useless prediction entries.
    If DRY_RUN is set, only produce dumps and do not modify profile.  */
@@ -935,7 +1077,10 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
   if (dump_file)
     fprintf (dump_file, "Predictions for bb %i\n", bb->index);
 
+  prune_predictions_for_bb (bb);
+
   edge_prediction **preds = bb_predictions->get (bb);
+
   if (preds)
     {
       /* We implement "first match" heuristics and use probability guessed
@@ -1001,18 +1146,18 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
     first_match = true;
 
   if (!found)
-    dump_prediction (dump_file, PRED_NO_PREDICTION, combined_probability, bb, true);
+    dump_prediction (dump_file, PRED_NO_PREDICTION, combined_probability, bb);
   else
     {
       dump_prediction (dump_file, PRED_DS_THEORY, combined_probability, bb,
-		       !first_match);
+		       !first_match ? NONE : IGNORED);
       dump_prediction (dump_file, PRED_FIRST_MATCH, best_probability, bb,
-		       first_match);
+		       first_match ? NONE : IGNORED);
     }
 
   if (first_match)
     combined_probability = best_probability;
-  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb, true);
+  dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb);
 
   if (preds)
     {
@@ -1021,10 +1166,9 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
 	  enum br_predictor predictor = pred->ep_predictor;
 	  int probability = pred->ep_probability;
 
-	  if (pred->ep_edge != EDGE_SUCC (bb, 0))
-	    probability = REG_BR_PROB_BASE - probability;
 	  dump_prediction (dump_file, predictor, probability, bb,
-			   !first_match || best_predictor == predictor);
+			   (!first_match || best_predictor == predictor)
+			   ? NONE : IGNORED, pred->ep_edge);
 	}
     }
   clear_bb_predictions (bb);
diff --git a/gcc/testsuite/g++.dg/predict-loop-exit-1.C b/gcc/testsuite/g++.dg/predict-loop-exit-1.C
index 357397f..88262eb 100644
--- a/gcc/testsuite/g++.dg/predict-loop-exit-1.C
+++ b/gcc/testsuite/g++.dg/predict-loop-exit-1.C
@@ -9,5 +9,5 @@ void test() {
   return;
 }
 
-/* { dg-final { scan-tree-dump-times "extra loop exit heuristics:" 2 "profile_estimate"} } */
-/* { dg-final { scan-tree-dump-times "loop exit heuristics:" 3 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "extra loop exit heuristics of edge\[^:\]*:" 2 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop exit heuristics of edge\[^:\]*:" 3 "profile_estimate"} } */
diff --git a/gcc/testsuite/g++.dg/predict-loop-exit-2.C b/gcc/testsuite/g++.dg/predict-loop-exit-2.C
index 172fab1..15e9866 100644
--- a/gcc/testsuite/g++.dg/predict-loop-exit-2.C
+++ b/gcc/testsuite/g++.dg/predict-loop-exit-2.C
@@ -9,5 +9,5 @@ void test() {
   return;
 }
 
-/* { dg-final { scan-tree-dump-times "extra loop exit heuristics:" 1 "profile_estimate"} } */
-/* { dg-final { scan-tree-dump-times "loop exit heuristics:" 2 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "extra loop exit heuristics of edge\[^:\]*:" 1 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop exit heuristics of edge\[^:\]*:" 2 "profile_estimate"} } */
diff --git a/gcc/testsuite/g++.dg/predict-loop-exit-3.C b/gcc/testsuite/g++.dg/predict-loop-exit-3.C
index e6ceec8..61af84b 100644
--- a/gcc/testsuite/g++.dg/predict-loop-exit-3.C
+++ b/gcc/testsuite/g++.dg/predict-loop-exit-3.C
@@ -9,5 +9,5 @@ void test() {
   return;
 }
 
-/* { dg-final { scan-tree-dump-times "extra loop exit heuristics:" 2 "profile_estimate"} } */
-/* { dg-final { scan-tree-dump-times "loop exit heuristics:" 3 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "extra loop exit heuristics of edge\[^:\]*:" 2 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop exit heuristics of edge\[^:\]*:" 3 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-1.c b/gcc/testsuite/gcc.dg/predict-1.c
index 94f6b019..d0924f2 100644
--- a/gcc/testsuite/gcc.dg/predict-1.c
+++ b/gcc/testsuite/gcc.dg/predict-1.c
@@ -23,4 +23,4 @@ void foo (int bound)
     }
 }
 
-/* { dg-final { scan-tree-dump-times "loop iv compare heuristics: 2.0%" 5 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop iv compare heuristics of edge\[^:\]*: 2.0%" 5 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-2.c b/gcc/testsuite/gcc.dg/predict-2.c
index f2fc49d..3011686 100644
--- a/gcc/testsuite/gcc.dg/predict-2.c
+++ b/gcc/testsuite/gcc.dg/predict-2.c
@@ -23,4 +23,4 @@ void foo (int base, int bound)
     }
 }
 
-/* { dg-final { scan-tree-dump-not "loop iv compare heuristics" "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-not "loop iv compare heuristics of edge\[^:\]*:" "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-3.c b/gcc/testsuite/gcc.dg/predict-3.c
index 08db59a..6768c36 100644
--- a/gcc/testsuite/gcc.dg/predict-3.c
+++ b/gcc/testsuite/gcc.dg/predict-3.c
@@ -25,4 +25,4 @@ void foo (int bound)
     }
 }
 
-/* { dg-final { scan-tree-dump-times "loop iv compare heuristics: 98.0%" 3 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop iv compare heuristics of edge\[^:\]*:: 98.0%" 3 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-4.c b/gcc/testsuite/gcc.dg/predict-4.c
index 3e7fb74..5779da3 100644
--- a/gcc/testsuite/gcc.dg/predict-4.c
+++ b/gcc/testsuite/gcc.dg/predict-4.c
@@ -15,4 +15,4 @@ void foo (int bound)
     }
 }
 
-/* { dg-final { scan-tree-dump "loop iv compare heuristics: 50.0%" "profile_estimate"} } */
+/* { dg-final { scan-tree-dump "loop iv compare heuristics of edge\[^:\]*: 50.0%" "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-5.c b/gcc/testsuite/gcc.dg/predict-5.c
index 32178a8..56ada30 100644
--- a/gcc/testsuite/gcc.dg/predict-5.c
+++ b/gcc/testsuite/gcc.dg/predict-5.c
@@ -21,4 +21,4 @@ void foo (int base, int bound)
     }
 }
 
-/* { dg-final { scan-tree-dump-times "loop iv compare heuristics: 98.0%" 4 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop iv compare heuristics of edge\[^:\]*: 98.0%" 4 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-6.c b/gcc/testsuite/gcc.dg/predict-6.c
index 16ad16f..9ed41ed 100644
--- a/gcc/testsuite/gcc.dg/predict-6.c
+++ b/gcc/testsuite/gcc.dg/predict-6.c
@@ -21,4 +21,4 @@ void foo (int base, int bound)
     }
 }
 
-/* { dg-final { scan-tree-dump-times "loop iv compare heuristics: 2.0%" 4 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop iv compare heuristics of edge\[^:\]*: 2.0%" 4 "profile_estimate"} } */
diff --git a/gcc/testsuite/gcc.dg/predict-7.c b/gcc/testsuite/gcc.dg/predict-7.c
index a0ea37b..fe34ca5 100644
--- a/gcc/testsuite/gcc.dg/predict-7.c
+++ b/gcc/testsuite/gcc.dg/predict-7.c
@@ -13,4 +13,4 @@ void foo (int base)
       bar (i);
 }
 
-/* { dg-final { scan-tree-dump-times "loop branch heuristics" 0 "profile_estimate"} } */
+/* { dg-final { scan-tree-dump-times "loop branch heuristics of edge\[^:\]*" 0 "profile_estimate"} } */
-- 
2.8.3


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [BUILDROBOT] MPS430 build problem due to new enum (was: [PATCH 2/2] Add edge predictions pruning)
  2016-06-09 11:24       ` Martin Liška
@ 2016-06-12 11:55         ` Jan-Benedict Glaw
  2016-06-13  7:25           ` [BUILDROBOT] MPS430 build problem due to new enum Martin Liška
  2016-06-13  8:47           ` [BUILDROBOT] MPS430 build problem due to new enum (was: [PATCH 2/2] Add edge predictions pruning) Jan Hubicka
  0 siblings, 2 replies; 14+ messages in thread
From: Jan-Benedict Glaw @ 2016-06-12 11:55 UTC (permalink / raw)
  To: Martin Liška; +Cc: Jan Hubicka, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3139 bytes --]

Hi Martin,

On Thu, 2016-06-09 13:24:10 +0200, Martin Liška <mliska@suse.cz> wrote:
> On 06/08/2016 02:41 PM, Jan Hubicka wrote:
> > Adding hash for this prupose is bit of an overkill (there are
> > definitly cheaper ways of solving so), but it will hardly affect compile
> > time, so the pathc is OK.
> 
> Sending the final version where I added comments and I also changed
> dump scanning to cover the new dump format.

I just noticed a build problem my Build Robot found
(http://toolchain.lug-owl.de/buildbot/show_build_details.php?id=569576):

g++ -fno-PIE -c   -g -O2 -DIN_GCC  -DCROSS_DIRECTORY_STRUCTURE   -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fno-common  -DHAVE_CONFIG_H -I. -I. -I/scratch/4/jbglaw/regular/repos/gcc/gcc -I/scratch/4/jbglaw/regular/repos/gcc/gcc/. -I/scratch/4/jbglaw/regular/repos/gcc/gcc/../include -I/scratch/4/jbglaw/regular/repos/gcc/gcc/../libcpp/include  -I/scratch/4/jbglaw/regular/repos/gcc/gcc/../libdecnumber -I/scratch/4/jbglaw/regular/repos/gcc/gcc/../libdecnumber/dpd -I../libdecnumber -I/scratch/4/jbglaw/regular/repos/gcc/gcc/../libbacktrace   -o predict.o -MT predict.o -MMD -MP -MF ./.deps/predict.TPo /scratch/4/jbglaw/regular/repos/gcc/gcc/predict.c
/scratch/4/jbglaw/regular/repos/gcc/gcc/predict.c:62:3: error: redeclaration of ‘NONE’
   NONE,
   ^
In file included from ./options.h:8:0,
                 from ./tm.h:16,
                 from /scratch/4/jbglaw/regular/repos/gcc/gcc/backend.h:28,
                 from /scratch/4/jbglaw/regular/repos/gcc/gcc/predict.c:33:
/scratch/4/jbglaw/regular/repos/gcc/gcc/config/msp430/msp430-opts.h:25:3: note: previous declaration ‘msp430_hwmult_types NONE’
   NONE,
   ^
/scratch/4/jbglaw/regular/repos/gcc/gcc/predict.c:743:23: error: could not convert ‘NONE’ from ‘msp430_hwmult_types’ to ‘predictor_reason’
    edge ep_edge = NULL)
                       ^
/scratch/4/jbglaw/regular/repos/gcc/gcc/predict.c: In function ‘void combine_predictions_for_insn(rtx_insn*, basic_block)’:
/scratch/4/jbglaw/regular/repos/gcc/gcc/predict.c:863:32: error: cannot convert ‘msp430_hwmult_types’ to ‘predictor_reason’ for argument ‘5’ to ‘void dump_prediction(FILE*, br_predictor, int, basic_block, predictor_reason, edge)’
        combined_probability, bb);
                                ^
/scratch/4/jbglaw/regular/repos/gcc/gcc/predict.c:867:36: warning: enumeral mismatch in conditional expression: ‘msp430_hwmult_types’ vs ‘predictor_reason’ [-Wenum-compare]
          bb, !first_match ? NONE : IGNORED);
                                    ^
[...]


The new `NONE' from your enum clashes with a NONE used in a MSP430
private enum.

MfG, JBG

-- 
      Jan-Benedict Glaw      jbglaw@lug-owl.de              +49-172-7608481
Signature of: They that give up essential liberty to obtain temporary safety,
the second  : deserve neither liberty nor safety.  (Ben Franklin)

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [BUILDROBOT] MPS430 build problem due to new enum
  2016-06-12 11:55         ` [BUILDROBOT] MPS430 build problem due to new enum (was: [PATCH 2/2] Add edge predictions pruning) Jan-Benedict Glaw
@ 2016-06-13  7:25           ` Martin Liška
  2016-06-13  8:47           ` [BUILDROBOT] MPS430 build problem due to new enum (was: [PATCH 2/2] Add edge predictions pruning) Jan Hubicka
  1 sibling, 0 replies; 14+ messages in thread
From: Martin Liška @ 2016-06-13  7:25 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 304 bytes --]

On 06/12/2016 01:55 PM, Jan-Benedict Glaw wrote:
> The new `NONE' from your enum clashes with a NONE used in a MSP430
> private enum.
> 
> MfG, JBG

Hi.

Thanks for having heads up, I've been testing following patch. The patch
survives with --target=msp430-elf.

Ready after it finishes?
Thanks,
Martin


[-- Attachment #2: 0001-Change-enum-value-to-not-to-clash-with-a-MSP430-priv.patch --]
[-- Type: text/x-patch, Size: 2637 bytes --]

From 540c82e618ef6b38b69160c77533705d4e160895 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Mon, 13 Jun 2016 09:20:10 +0200
Subject: [PATCH] Change enum value to not to clash with a MSP430 private enum

gcc/ChangeLog:

2016-06-13  Martin Liska  <mliska@suse.cz>

	* predict.c (enum predictor_reason): Rename NONE to VALID.
	(combine_predictions_for_insn): Likewise.
	(combine_predictions_for_bb): Likewise.
---
 gcc/predict.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/gcc/predict.c b/gcc/predict.c
index 0fa8c5b..e1d161a 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -59,7 +59,7 @@ along with GCC; see the file COPYING3.  If not see
 
 enum predictor_reason
 {
-  NONE,
+  VALID,
   IGNORED,
   SINGLE_EDGE_DUPLICATE,
   EDGE_PAIR_DUPLICATE
@@ -739,7 +739,7 @@ invert_br_probabilities (rtx insn)
 
 static void
 dump_prediction (FILE *file, enum br_predictor predictor, int probability,
-		 basic_block bb, enum predictor_reason reason = NONE,
+		 basic_block bb, enum predictor_reason reason = VALID,
 		 edge ep_edge = NULL)
 {
   edge e = ep_edge;
@@ -864,9 +864,9 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
   else
     {
       dump_prediction (dump_file, PRED_DS_THEORY, combined_probability,
-		       bb, !first_match ? NONE : IGNORED);
+		       bb, !first_match ? VALID : IGNORED);
       dump_prediction (dump_file, PRED_FIRST_MATCH, best_probability,
-		       bb, first_match ? NONE: IGNORED);
+		       bb, first_match ? VALID : IGNORED);
     }
 
   if (first_match)
@@ -883,7 +883,7 @@ combine_predictions_for_insn (rtx_insn *insn, basic_block bb)
 
 	  dump_prediction (dump_file, predictor, probability, bb,
 			   (!first_match || best_predictor == predictor)
-			   ? NONE : IGNORED);
+			   ? VALID : IGNORED);
 	  *pnote = XEXP (*pnote, 1);
 	}
       else
@@ -1150,9 +1150,9 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
   else
     {
       dump_prediction (dump_file, PRED_DS_THEORY, combined_probability, bb,
-		       !first_match ? NONE : IGNORED);
+		       !first_match ? VALID : IGNORED);
       dump_prediction (dump_file, PRED_FIRST_MATCH, best_probability, bb,
-		       first_match ? NONE : IGNORED);
+		       first_match ? VALID : IGNORED);
     }
 
   if (first_match)
@@ -1168,7 +1168,7 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
 
 	  dump_prediction (dump_file, predictor, probability, bb,
 			   (!first_match || best_predictor == predictor)
-			   ? NONE : IGNORED, pred->ep_edge);
+			   ? VALID : IGNORED, pred->ep_edge);
 	}
     }
   clear_bb_predictions (bb);
-- 
2.8.3


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [BUILDROBOT] MPS430 build problem due to new enum (was: [PATCH 2/2] Add edge predictions pruning)
  2016-06-12 11:55         ` [BUILDROBOT] MPS430 build problem due to new enum (was: [PATCH 2/2] Add edge predictions pruning) Jan-Benedict Glaw
  2016-06-13  7:25           ` [BUILDROBOT] MPS430 build problem due to new enum Martin Liška
@ 2016-06-13  8:47           ` Jan Hubicka
  2016-06-13 10:01             ` [BUILDROBOT] MPS430 build problem due to new enum Martin Liška
  1 sibling, 1 reply; 14+ messages in thread
From: Jan Hubicka @ 2016-06-13  8:47 UTC (permalink / raw)
  To: Jan-Benedict Glaw; +Cc: Martin Liška, Jan Hubicka, gcc-patches

> Hi Martin,
> 
> On Thu, 2016-06-09 13:24:10 +0200, Martin Liška <mliska@suse.cz> wrote:
> > On 06/08/2016 02:41 PM, Jan Hubicka wrote:
> > > Adding hash for this prupose is bit of an overkill (there are
> > > definitly cheaper ways of solving so), but it will hardly affect compile
> > > time, so the pathc is OK.
> > 
> > Sending the final version where I added comments and I also changed
> > dump scanning to cover the new dump format.
> 
> I just noticed a build problem my Build Robot found
> (http://toolchain.lug-owl.de/buildbot/show_build_details.php?id=569576):
> 
> g++ -fno-PIE -c   -g -O2 -DIN_GCC  -DCROSS_DIRECTORY_STRUCTURE   -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fno-common  -DHAVE_CONFIG_H -I. -I. -I/scratch/4/jbglaw/regular/repos/gcc/gcc -I/scratch/4/jbglaw/regular/repos/gcc/gcc/. -I/scratch/4/jbglaw/regular/repos/gcc/gcc/../include -I/scratch/4/jbglaw/regular/repos/gcc/gcc/../libcpp/include  -I/scratch/4/jbglaw/regular/repos/gcc/gcc/../libdecnumber -I/scratch/4/jbglaw/regular/repos/gcc/gcc/../libdecnumber/dpd -I../libdecnumber -I/scratch/4/jbglaw/regular/repos/gcc/gcc/../libbacktrace   -o predict.o -MT predict.o -MMD -MP -MF ./.deps/predict.TPo /scratch/4/jbglaw/regular/repos/gcc/gcc/predict.c
> /scratch/4/jbglaw/regular/repos/gcc/gcc/predict.c:62:3: error: redeclaration of ‘NONE’
>    NONE,

Hmm, namespace conflict.  I guess renaming enum items to REASON_* should solve it easily.
Or we can add a namespace.

Martin, both variants of fix are pre-approved.
Honza

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [BUILDROBOT] MPS430 build problem due to new enum
  2016-06-13  8:47           ` [BUILDROBOT] MPS430 build problem due to new enum (was: [PATCH 2/2] Add edge predictions pruning) Jan Hubicka
@ 2016-06-13 10:01             ` Martin Liška
  0 siblings, 0 replies; 14+ messages in thread
From: Martin Liška @ 2016-06-13 10:01 UTC (permalink / raw)
  To: gcc-patches; +Cc: Jan Hubicka

On 06/13/2016 10:46 AM, Jan Hubicka wrote:
> Hmm, namespace conflict.  I guess renaming enum items to REASON_* should solve it easily.
> Or we can add a namespace.
> 
> Martin, both variants of fix are pre-approved.
> Honza

OK, I've just installed (r237370) a patch that prefixes all enum values.

Martin

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2016-06-13 10:01 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-02 11:57 [PATCH 0/2] Deduplicate edge predictors marxin
2016-06-02 11:57 ` [PATCH 1/2] Introduce filtering for edge_predictions marxin
2016-06-02 11:57 ` [PATCH 2/2] Add edge predictions pruning marxin
2016-06-08 12:25   ` Martin Liška
2016-06-08 12:41     ` Jan Hubicka
2016-06-09 11:24       ` Martin Liška
2016-06-12 11:55         ` [BUILDROBOT] MPS430 build problem due to new enum (was: [PATCH 2/2] Add edge predictions pruning) Jan-Benedict Glaw
2016-06-13  7:25           ` [BUILDROBOT] MPS430 build problem due to new enum Martin Liška
2016-06-13  8:47           ` [BUILDROBOT] MPS430 build problem due to new enum (was: [PATCH 2/2] Add edge predictions pruning) Jan Hubicka
2016-06-13 10:01             ` [BUILDROBOT] MPS430 build problem due to new enum Martin Liška
2016-06-08 12:26 ` [PATCH 3/N] Add sorting support to analyze_brprob script Martin Liška
2016-06-08 15:02   ` Jan Hubicka
2016-06-08 12:29 ` [PATCH 4/N] Add new analyze_brprob_spec.py script Martin Liška
2016-06-08 15:12   ` Jan Hubicka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).