improve VN PHI hashing
authorRichard Biener <rguenther@suse.de>
Fri, 13 Nov 2020 12:17:01 +0000 (13:17 +0100)
committerRichard Biener <rguenther@suse.de>
Fri, 13 Nov 2020 14:19:49 +0000 (15:19 +0100)
This reduces the number of collisions for PHIs in the VN hashtable
by always hashing the number of predecessors and separately hashing
the block number when we never merge PHIs from different blocks.

This improves collisions seen for the PR69609 testcase dramatically.

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

* tree-ssa-sccvn.c (vn_phi_compute_hash): Always hash the
number of predecessors.  Hash the block number also for
loop header PHIs.
(expressions_equal_p): Short-cut SSA name compares, remove
test for NULL operands.
(vn_phi_eq): Cache number of predecessors, change inlined
test from expressions_equal_p.

gcc/tree-ssa-sccvn.c

index 8c93e515b6cef1569cdebc1b22d74354d03df3ad..4d78054b1e00a78afc71779d6ef27660d72f1a5f 100644 (file)
@@ -4126,13 +4126,27 @@ vn_nary_op_insert_stmt (gimple *stmt, tree result)
 static inline hashval_t
 vn_phi_compute_hash (vn_phi_t vp1)
 {
-  inchash::hash hstate (EDGE_COUNT (vp1->block->preds) > 2
-                       ? vp1->block->index : EDGE_COUNT (vp1->block->preds));
+  inchash::hash hstate;
   tree phi1op;
   tree type;
   edge e;
   edge_iterator ei;
 
+  hstate.add_int (EDGE_COUNT (vp1->block->preds));
+  switch (EDGE_COUNT (vp1->block->preds))
+    {
+    case 1:
+      break;
+    case 2:
+      if (vp1->block->loop_father->header == vp1->block)
+       ;
+      else
+       break;
+      /* Fallthru.  */
+    default:
+      hstate.add_int (vp1->block->index);
+    }
+
   /* If all PHI arguments are constants we need to distinguish
      the PHI node via its type.  */
   type = vp1->type;
@@ -4277,11 +4291,12 @@ vn_phi_eq (const_vn_phi_t const vp1, const_vn_phi_t const vp2)
 
   /* Any phi in the same block will have it's arguments in the
      same edge order, because of how we store phi nodes.  */
-  for (unsigned i = 0; i < EDGE_COUNT (vp1->block->preds); ++i)
+  unsigned nargs = EDGE_COUNT (vp1->block->preds);
+  for (unsigned i = 0; i < nargs; ++i)
     {
       tree phi1op = vp1->phiargs[i];
       tree phi2op = vp2->phiargs[i];
-      if (phi1op == VN_TOP || phi2op == VN_TOP)
+      if (phi1op == phi2op)
        continue;
       if (!expressions_equal_p (phi1op, phi2op))
        return false;
@@ -5612,8 +5627,8 @@ expressions_equal_p (tree e1, tree e2)
   if (e1 == VN_TOP || e2 == VN_TOP)
     return true;
 
-  /* If only one of them is null, they cannot be equal.  */
-  if (!e1 || !e2)
+  /* SSA_NAME compare pointer equal.  */
+  if (TREE_CODE (e1) == SSA_NAME || TREE_CODE (e2) == SSA_NAME)
     return false;
 
   /* Now perform the actual comparison.  */