[PATCH] rework PRE PHI translation cache

Richard Biener rguenther@suse.de
Fri Nov 6 17:07:54 GMT 2020


Turns out its size and time requirements can be stripped down
dramatically.

Bootstrap & regtest running on x86_64-unknown-linux-gnu.

2020-11-06  Richard Biener  <rguenther@suse.de>

	* tree-ssa-pre.c (expr_pred_trans_d): Modify so elements
	are embedded rather than allocated.  Remove hashval member,
	make all members integers.
	(phi_trans_add): Adjust accordingly.
	(phi_translate): Likewise.  Deal with re-allocation
	of the table.
---
 gcc/tree-ssa-pre.c | 104 +++++++++++++++++++++++++++++----------------
 1 file changed, 68 insertions(+), 36 deletions(-)

diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 65e8aaaca02..3496891f8b5 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -545,45 +545,74 @@ static bitmap_obstack grand_bitmap_obstack;
 /* A three tuple {e, pred, v} used to cache phi translations in the
    phi_translate_table.  */
 
-typedef struct expr_pred_trans_d : free_ptr_hash<expr_pred_trans_d>
+typedef struct expr_pred_trans_d : public typed_noop_remove <expr_pred_trans_d>
 {
-  /* The expression.  */
-  pre_expr e;
+  typedef expr_pred_trans_d value_type;
+  typedef expr_pred_trans_d compare_type;
 
-  /* The predecessor block along which we translated the expression.  */
-  basic_block pred;
+  /* The expression ID.  */
+  unsigned e;
 
-  /* The value that resulted from the translation.  */
-  pre_expr v;
+  /* The predecessor block index along which we translated the expression.  */
+  int pred;
 
-  /* The hashcode for the expression, pred pair. This is cached for
-     speed reasons.  */
-  hashval_t hashcode;
+  /* The value expression ID that resulted from the translation.  */
+  unsigned v;
 
   /* hash_table support.  */
-  static inline hashval_t hash (const expr_pred_trans_d *);
-  static inline int equal (const expr_pred_trans_d *, const expr_pred_trans_d *);
+  static inline void mark_empty (expr_pred_trans_d &);
+  static inline bool is_empty (const expr_pred_trans_d &);
+  static inline void mark_deleted (expr_pred_trans_d &);
+  static inline bool is_deleted (const expr_pred_trans_d &);
+  static const bool empty_zero_p = true;
+  static inline hashval_t hash (const expr_pred_trans_d &);
+  static inline int equal (const expr_pred_trans_d &, const expr_pred_trans_d &);
 } *expr_pred_trans_t;
 typedef const struct expr_pred_trans_d *const_expr_pred_trans_t;
 
+inline bool
+expr_pred_trans_d::is_empty (const expr_pred_trans_d &e)
+{
+  return e.e == 0;
+}
+
+inline bool
+expr_pred_trans_d::is_deleted (const expr_pred_trans_d &e)
+{
+  return e.e == -1u;
+}
+
+inline void
+expr_pred_trans_d::mark_empty (expr_pred_trans_d &e)
+{
+  e.e = 0;
+}
+
+inline void
+expr_pred_trans_d::mark_deleted (expr_pred_trans_d &e)
+{
+  e.e = -1u;
+}
+
 inline hashval_t
-expr_pred_trans_d::hash (const expr_pred_trans_d *e)
+expr_pred_trans_d::hash (const expr_pred_trans_d &e)
 {
-  return e->hashcode;
+  return iterative_hash_hashval_t (e.e, e.pred);
 }
 
 inline int
-expr_pred_trans_d::equal (const expr_pred_trans_d *ve1,
-			  const expr_pred_trans_d *ve2)
+expr_pred_trans_d::equal (const expr_pred_trans_d &ve1,
+			  const expr_pred_trans_d &ve2)
 {
-  basic_block b1 = ve1->pred;
-  basic_block b2 = ve2->pred;
+  int b1 = ve1.pred;
+  int b2 = ve2.pred;
 
   /* If they are not translations for the same basic block, they can't
      be equal.  */
   if (b1 != b2)
     return false;
-  return pre_expr_d::equal (ve1->e, ve2->e);
+
+  return ve1.e == ve2.e;
 }
 
 /* The phi_translate_table caches phi translations for a given
@@ -596,24 +625,22 @@ static hash_table<expr_pred_trans_d> *phi_translate_table;
 static inline bool
 phi_trans_add (expr_pred_trans_t *entry, pre_expr e, basic_block pred)
 {
-  expr_pred_trans_t *slot;
+  expr_pred_trans_t slot;
   expr_pred_trans_d tem;
-  hashval_t hash = iterative_hash_hashval_t (pre_expr_d::hash (e),
-					     pred->index);
-  tem.e = e;
-  tem.pred = pred;
-  tem.hashcode = hash;
-  slot = phi_translate_table->find_slot_with_hash (&tem, hash, INSERT);
-  if (*slot)
+  unsigned id = get_expression_id (e);
+  hashval_t hash = iterative_hash_hashval_t (id, pred->index);
+  tem.e = id;
+  tem.pred = pred->index;
+  slot = phi_translate_table->find_slot_with_hash (tem, hash, INSERT);
+  if (slot->e)
     {
-      *entry = *slot;
+      *entry = slot;
       return true;
     }
 
-  *entry = *slot = XNEW (struct expr_pred_trans_d);
-  (*entry)->e = e;
-  (*entry)->pred = pred;
-  (*entry)->hashcode = hash;
+  *entry = slot;
+  slot->e = id;
+  slot->pred = pred->index;
   return false;
 }
 
@@ -1675,6 +1702,7 @@ phi_translate (bitmap_set_t dest, pre_expr expr,
 	       bitmap_set_t set1, bitmap_set_t set2, edge e)
 {
   expr_pred_trans_t slot = NULL;
+  size_t slot_size = 0;
   pre_expr phitrans;
 
   if (!expr)
@@ -1691,10 +1719,11 @@ phi_translate (bitmap_set_t dest, pre_expr expr,
   if (expr->kind != NAME)
     {
       if (phi_trans_add (&slot, expr, e->src))
-	return slot->v;
+	return slot->v == 0 ? NULL : expression_for_id (slot->v);
       /* Store NULL for the value we want to return in the case of
 	 recursing.  */
-      slot->v = NULL;
+      slot->v = 0;
+      slot_size = phi_translate_table->size ();
     }
 
   /* Translate.  */
@@ -1705,12 +1734,15 @@ phi_translate (bitmap_set_t dest, pre_expr expr,
 
   if (slot)
     {
+      /* Check for reallocation.  */
+      if (phi_translate_table->size () != slot_size)
+	phi_trans_add (&slot, expr, e->src);
       if (phitrans)
-	slot->v = phitrans;
+	slot->v = get_expression_id (phitrans);
       else
 	/* Remove failed translations again, they cause insert
 	   iteration to not pick up new opportunities reliably.  */
-	phi_translate_table->remove_elt_with_hash (slot, slot->hashcode);
+	phi_translate_table->clear_slot (slot);
     }
 
   return phitrans;
-- 
2.26.2


More information about the Gcc-patches mailing list