+
+/* Compute the hash value for an address -> temp slot mapping.
+ The value is cached on the mapping entry. */
+static hashval_t
+temp_slot_address_compute_hash (struct temp_slot_address_entry *t)
+{
+ int do_not_record = 0;
+ return hash_rtx (t->address, GET_MODE (t->address),
+ &do_not_record, NULL, false);
+}
+
+/* Return the hash value for an address -> temp slot mapping. */
+static hashval_t
+temp_slot_address_hash (const void *p)
+{
+ const struct temp_slot_address_entry *t;
+ t = (const struct temp_slot_address_entry *) p;
+ return t->hash;
+}
+
+/* Compare two address -> temp slot mapping entries. */
+static int
+temp_slot_address_eq (const void *p1, const void *p2)
+{
+ const struct temp_slot_address_entry *t1, *t2;
+ t1 = (const struct temp_slot_address_entry *) p1;
+ t2 = (const struct temp_slot_address_entry *) p2;
+ return exp_equiv_p (t1->address, t2->address, 0, true);
+}
+
+/* Add ADDRESS as an alias of TEMP_SLOT to the addess -> temp slot mapping. */
+static void
+insert_temp_slot_address (rtx address, struct temp_slot *temp_slot)
+{
+ void **slot;
+ struct temp_slot_address_entry *t = GGC_NEW (struct temp_slot_address_entry);
+ t->address = address;
+ t->temp_slot = temp_slot;
+ t->hash = temp_slot_address_compute_hash (t);
+ slot = htab_find_slot_with_hash (temp_slot_address_table, t, t->hash, INSERT);
+ *slot = t;
+}
+
+/* Remove an address -> temp slot mapping entry if the temp slot is
+ not in use anymore. Callback for remove_unused_temp_slot_addresses. */
+static int
+remove_unused_temp_slot_addresses_1 (void **slot, void *data ATTRIBUTE_UNUSED)
+{
+ const struct temp_slot_address_entry *t;
+ t = (const struct temp_slot_address_entry *) *slot;
+ if (! t->temp_slot->in_use)
+ *slot = NULL;
+ return 1;
+}
+
+/* Remove all mappings of addresses to unused temp slots. */
+static void
+remove_unused_temp_slot_addresses (void)
+{
+ htab_traverse (temp_slot_address_table,
+ remove_unused_temp_slot_addresses_1,
+ NULL);
+}
+
+/* Find the temp slot corresponding to the object at address X. */
+
+static struct temp_slot *
+find_temp_slot_from_address (rtx x)
+{
+ struct temp_slot *p;
+ struct temp_slot_address_entry tmp, *t;
+
+ /* First try the easy way:
+ See if X exists in the address -> temp slot mapping. */
+ tmp.address = x;
+ tmp.temp_slot = NULL;
+ tmp.hash = temp_slot_address_compute_hash (&tmp);
+ t = (struct temp_slot_address_entry *)
+ htab_find_with_hash (temp_slot_address_table, &tmp, tmp.hash);
+ if (t)
+ return t->temp_slot;
+
+ /* If we have a sum involving a register, see if it points to a temp
+ slot. */
+ if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0))
+ && (p = find_temp_slot_from_address (XEXP (x, 0))) != 0)
+ return p;
+ else if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 1))
+ && (p = find_temp_slot_from_address (XEXP (x, 1))) != 0)
+ return p;
+
+ /* Last resort: Address is a virtual stack var address. */
+ if (GET_CODE (x) == PLUS
+ && XEXP (x, 0) == virtual_stack_vars_rtx
+ && GET_CODE (XEXP (x, 1)) == CONST_INT)
+ {
+ int i;
+ for (i = max_slot_level (); i >= 0; i--)
+ for (p = *temp_slots_at_level (i); p; p = p->next)
+ {
+ if (INTVAL (XEXP (x, 1)) >= p->base_offset
+ && INTVAL (XEXP (x, 1)) < p->base_offset + p->full_size)
+ return p;
+ }
+ }
+
+ return NULL;
+}