From d9e253e0cea39634ccb196680ad95e855cba41f0 Mon Sep 17 00:00:00 2001
From: Maxim Kuvyrkov <maxim@codesourcery.com>
Date: Mon, 19 Sep 2011 12:33:33 -0700
Subject: [PATCH] Improve ipa-inline-analysis.c:account_size_time() to distribute data
 	across entries with similar predicates.

	* ipa-inline-analysis.c (predicate_distance,):
	(find_size_time_entry_with_closest_predicate): New functions.
	(account_size_time): Use them instead of mushing data into entry[0].
---
 gcc/ipa-inline-analysis.c |   92 ++++++++++++++++++++++++++++++++++++--------
 1 files changed, 75 insertions(+), 17 deletions(-)

diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index 6bc96c7..b53962d 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -485,14 +485,80 @@ dump_predicate (FILE *f, conditions conds, struct predicate *pred)
 }
 
 
+/* Return number of different clauses between predicates P and P2.  */
+
+static int
+predicate_distance (struct predicate *p, struct predicate *p2)
+{
+  int i;
+  int distance = 0;
+
+  for (i = 0; p->clause[i]; i++)
+    if (p->clause[i] != p2->clause[i])
+      ++distance;
+
+  /* Increase distance by the number of extra clauses in P2.  */
+  for (; p2->clause[i]; i++)
+    ++distance;
+
+  return distance;
+}
+
+
+/* Find size_time_entry in SUMMARY with the closest predicate to PRED.
+   Return the entry and set *EXACT to true if we found an exact match.
+   Return NULL if there is space for a new entry.  */
+
+static size_time_entry *
+find_size_time_entry_with_closest_predicate (struct inline_summary *summary,
+					     struct predicate *pred,
+					     bool *exact)
+{
+  size_time_entry *e;
+  int i;
+
+  /* Try to find the exact match.  */
+  *exact = true;
+  for (i = 0; VEC_iterate (size_time_entry, summary->entry, i, e); i++)
+    if (predicates_equal_p (&e->predicate, pred))
+      return e;
+
+  /* Return NULL to indicate that we still have room for a new new entry.  */
+  if (i < 32)
+    return NULL;
+
+  /* No exact match and don't want to create new entries.
+     Find entry with the closest predicate.  */
+  *exact = false;
+  {
+    int min_distance = MAX_CLAUSES + 1;
+    size_time_entry *best_entry = NULL;
+
+    for (i = 0; VEC_iterate (size_time_entry, summary->entry, i, e); i++)
+      {
+	int distance = predicate_distance (&e->predicate, pred);
+
+	if (distance < min_distance)
+	  {
+	    min_distance = distance;
+	    best_entry = e;
+	  }
+      }
+
+    gcc_assert (0 <= min_distance && min_distance <= MAX_CLAUSES);
+    gcc_assert (best_entry != NULL);
+    return best_entry;
+  }
+}
+
+
 /* Record SIZE and TIME under condition PRED into the inline summary.  */
 
 static void
 account_size_time (struct inline_summary *summary, int size, int time, struct predicate *pred)
 {
   size_time_entry *e;
-  bool found = false;
-  int i;
+  bool exact;
 
   if (false_predicate_p (pred))
     return;
@@ -507,27 +573,16 @@ account_size_time (struct inline_summary *summary, int size, int time, struct pr
     time = MAX_TIME * INLINE_TIME_SCALE;
   gcc_assert (time >= 0);
 
-  for (i = 0; VEC_iterate (size_time_entry, summary->entry, i, e); i++)
-    if (predicates_equal_p (&e->predicate, pred))
-      {
-	found = true;
-        break;
-      }
-  if (i == 32)
-    {
-      i = 0;
-      found = true;
-      e = VEC_index (size_time_entry, summary->entry, 0);
-      gcc_assert (!e->predicate.clause[0]);
-    }
+  e = find_size_time_entry_with_closest_predicate (summary, pred, &exact);
+
   if (dump_file && (dump_flags & TDF_DETAILS) && (time || size))
     {
       fprintf (dump_file, "\t\tAccounting size:%3.2f, time:%3.2f on %spredicate:",
 	       ((double)size) / INLINE_SIZE_SCALE, ((double)time) / INLINE_TIME_SCALE,
-	       found ? "" : "new ");
+	       e != NULL ? "" : "new ");
       dump_predicate (dump_file, summary->conds, pred);
     }
-  if (!found)
+  if (e == NULL)
     {
       struct size_time_entry new_entry;
       new_entry.size = size;
@@ -537,6 +592,9 @@ account_size_time (struct inline_summary *summary, int size, int time, struct pr
     }
   else
     {
+      if (!exact)
+	e->predicate = or_predicates (summary->conds, &e->predicate, pred);
+
       e->size += size;
       e->time += time;
       if (e->time > MAX_TIME * INLINE_TIME_SCALE)
-- 
1.7.4.1

