+/* Hashing routine for EDGE_TO_CASE_LEADER. */
+
+static hashval_t
+edge_to_case_leader_hash (const void *p)
+{
+ edge e = ((struct edge_to_case_leader_elt *)p)->e;
+
+ /* Hash on the edge itself (which is a pointer). */
+ return htab_hash_pointer (e);
+}
+
+/* Equality routine for EDGE_TO_CASE_LEADER, edges are unique, so testing
+ for equality is just a pointer comparison. */
+
+static int
+edge_to_case_leader_eq (const void *p1, const void *p2)
+{
+ edge e1 = ((struct edge_to_case_leader_elt *)p1)->e;
+ edge e2 = ((struct edge_to_case_leader_elt *)p2)->e;
+
+ return e1 == e2;
+}
+
+/* Record that CASE_LABEL (a CASE_LABEL_EXPR) references edge E. */
+
+static void
+record_switch_edge (edge e, tree case_label)
+{
+ struct edge_to_case_leader_elt *elt;
+ void **slot;
+
+ /* Build a hash table element so we can see if E is already
+ in the table. */
+ elt = xmalloc (sizeof (struct edge_to_case_leader_elt));
+ elt->e = e;
+ elt->case_label = case_label;
+
+ slot = htab_find_slot (edge_to_case_leader, elt, INSERT);
+
+ if (*slot == NULL)
+ {
+ /* E was not in the hash table. Install E into the hash table. */
+ *slot = (void *)elt;
+ }
+ else
+ {
+ /* E was already in the hash table. Free ELT as we do not need it
+ anymore. */
+ free (elt);
+
+ /* Get the entry stored in the hash table. */
+ elt = (struct edge_to_case_leader_elt *) *slot;
+
+ /* Make ELT->case_label the leader for CASE_LABEL. */
+ CASE_LEADER_OR_LABEL (case_label) = elt->case_label;
+ }
+}
+
+/* Subroutine of get_case_leader_for_edge; returns the case leader for the
+ chain of CASE_LABEL_EXPRs associated with E using a hash table lookup. */
+
+static tree
+get_case_leader_for_edge_hash (edge e)
+{
+ struct edge_to_case_leader_elt elt, *elt_p;
+ void **slot;
+
+ elt.e = e;
+ elt.case_label = NULL;
+ slot = htab_find_slot (edge_to_case_leader, &elt, NO_INSERT);
+
+ if (slot)
+ {
+ tree t;
+
+ elt_p = (struct edge_to_case_leader_elt *)*slot;
+ t = elt_p->case_label;
+
+ while (TREE_CODE (CASE_LEADER_OR_LABEL (t)) == CASE_LABEL_EXPR)
+ t = CASE_LEADER_OR_LABEL (t);
+ return t;
+ }
+
+ return NULL;
+}
+
+/* Given an edge E, return the case leader for the chain of CASE_LABEL_EXPRs
+ which use E. */
+
+static tree
+get_case_leader_for_edge (edge e)
+{
+ tree vec, stmt;
+ size_t i, n;
+
+ /* If we have a hash table, then use it as it's significantly faster. */
+ if (edge_to_case_leader)
+ return get_case_leader_for_edge_hash (e);
+
+ /* No hash table. We have to walk the case vector. */
+ stmt = bsi_stmt (bsi_last (e->src));
+ vec = SWITCH_LABELS (stmt);
+ n = TREE_VEC_LENGTH (vec);
+
+ for (i = 0; i < n; i++)
+ {
+ tree elt = TREE_VEC_ELT (vec, i);
+ tree t = CASE_LEADER_OR_LABEL (elt);
+
+ if (TREE_CODE (t) == LABEL_DECL
+ && label_to_block (t) == e->dest)
+ return elt;
+ }
+
+ abort ();
+}