+/* Info about reg classes whose costs are calculated for a pseudo. */
+struct cost_classes
+{
+ /* Number of the cost classes in the subsequent array. */
+ int num;
+ /* Container of the cost classes. */
+ enum reg_class classes[N_REG_CLASSES];
+ /* Map reg class -> index of the reg class in the previous array.
+ -1 if it is not a cost classe. */
+ int index[N_REG_CLASSES];
+ /* Map hard regno index of first class in array CLASSES containing
+ the hard regno, -1 otherwise. */
+ int hard_regno_index[FIRST_PSEUDO_REGISTER];
+};
+
+/* Types of pointers to the structure above. */
+typedef struct cost_classes *cost_classes_t;
+typedef const struct cost_classes *const_cost_classes_t;
+
+/* Info about cost classes for each pseudo. */
+static cost_classes_t *regno_cost_classes;
+
+/* Returns hash value for cost classes info V. */
+static hashval_t
+cost_classes_hash (const void *v)
+{
+ const_cost_classes_t hv = (const_cost_classes_t) v;
+
+ return iterative_hash (&hv->classes, sizeof (enum reg_class) * hv->num, 0);
+}
+
+/* Compares cost classes info V1 and V2. */
+static int
+cost_classes_eq (const void *v1, const void *v2)
+{
+ const_cost_classes_t hv1 = (const_cost_classes_t) v1;
+ const_cost_classes_t hv2 = (const_cost_classes_t) v2;
+
+ return hv1->num == hv2->num && memcmp (hv1->classes, hv2->classes,
+ sizeof (enum reg_class) * hv1->num);
+}
+
+/* Delete cost classes info V from the hash table. */
+static void
+cost_classes_del (void *v)
+{
+ ira_free (v);
+}
+
+/* Hash table of unique cost classes. */
+static htab_t cost_classes_htab;
+
+/* Map allocno class -> cost classes for pseudo of given allocno
+ class. */
+static cost_classes_t cost_classes_aclass_cache[N_REG_CLASSES];
+
+/* Map mode -> cost classes for pseudo of give mode. */
+static cost_classes_t cost_classes_mode_cache[MAX_MACHINE_MODE];
+
+/* Initialize info about the cost classes for each pseudo. */
+static void
+initiate_regno_cost_classes (void)
+{
+ int size = sizeof (cost_classes_t) * max_reg_num ();
+
+ regno_cost_classes = (cost_classes_t *) ira_allocate (size);
+ memset (regno_cost_classes, 0, size);
+ memset (cost_classes_aclass_cache, 0,
+ sizeof (cost_classes_t) * N_REG_CLASSES);
+ memset (cost_classes_mode_cache, 0,
+ sizeof (cost_classes_t) * MAX_MACHINE_MODE);
+ cost_classes_htab
+ = htab_create (200, cost_classes_hash, cost_classes_eq, cost_classes_del);
+}
+
+/* Create new cost classes from cost classes FROM and set up members
+ index and hard_regno_index. Return the new classes. The function
+ implements some common code of two functions
+ setup_regno_cost_classes_by_aclass and
+ setup_regno_cost_classes_by_mode. */
+static cost_classes_t
+setup_cost_classes (cost_classes_t from)
+{
+ cost_classes_t classes_ptr;
+ enum reg_class cl;
+ int i, j, hard_regno;
+
+ classes_ptr = (cost_classes_t) ira_allocate (sizeof (struct cost_classes));
+ classes_ptr->num = from->num;
+ for (i = 0; i < N_REG_CLASSES; i++)
+ classes_ptr->index[i] = -1;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ classes_ptr->hard_regno_index[i] = -1;
+ for (i = 0; i < from->num; i++)
+ {
+ cl = classes_ptr->classes[i] = from->classes[i];
+ classes_ptr->index[cl] = i;
+ for (j = ira_class_hard_regs_num[cl] - 1; j >= 0; j--)
+ {
+ hard_regno = ira_class_hard_regs[cl][j];
+ if (classes_ptr->hard_regno_index[hard_regno] < 0)
+ classes_ptr->hard_regno_index[hard_regno] = i;
+ }
+ }
+ return classes_ptr;
+}
+
+/* Setup cost classes for pseudo REGNO whose allocno class is ACLASS.
+ This function is used when we know an initial approximation of
+ allocno class of the pseudo already, e.g. on the second iteration
+ of class cost calculation or after class cost calculation in
+ register-pressure sensitive insn scheduling or register-pressure
+ sensitive loop-invariant motion. */
+static void
+setup_regno_cost_classes_by_aclass (int regno, enum reg_class aclass)
+{
+ static struct cost_classes classes;
+ cost_classes_t classes_ptr;
+ enum reg_class cl;
+ int i;
+ PTR *slot;
+ HARD_REG_SET temp, temp2;
+ bool exclude_p;
+
+ if ((classes_ptr = cost_classes_aclass_cache[aclass]) == NULL)
+ {
+ COPY_HARD_REG_SET (temp, reg_class_contents[aclass]);
+ AND_COMPL_HARD_REG_SET (temp, ira_no_alloc_regs);
+ /* We exclude classes from consideration which are subsets of
+ ACLASS only if ACLASS is a pressure class or subset of a
+ pressure class. It means by the definition of pressure classes
+ that cost of moving between susbets of ACLASS is cheaper than
+ load or store. */
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ {
+ cl = ira_pressure_classes[i];
+ if (cl == aclass)
+ break;
+ COPY_HARD_REG_SET (temp2, reg_class_contents[cl]);
+ AND_COMPL_HARD_REG_SET (temp2, ira_no_alloc_regs);
+ if (hard_reg_set_subset_p (temp, temp2))
+ break;
+ }
+ exclude_p = i < ira_pressure_classes_num;
+ classes.num = 0;
+ for (i = 0; i < ira_important_classes_num; i++)
+ {
+ cl = ira_important_classes[i];
+ if (exclude_p)
+ {
+ /* Exclude no-pressure classes which are subsets of
+ ACLASS. */
+ COPY_HARD_REG_SET (temp2, reg_class_contents[cl]);
+ AND_COMPL_HARD_REG_SET (temp2, ira_no_alloc_regs);
+ if (! ira_reg_pressure_class_p[cl]
+ && hard_reg_set_subset_p (temp2, temp) && cl != aclass)
+ continue;
+ }
+ classes.classes[classes.num++] = cl;
+ }
+ slot = htab_find_slot (cost_classes_htab, &classes, INSERT);
+ if (*slot == NULL)
+ {
+ classes_ptr = setup_cost_classes (&classes);
+ *slot = classes_ptr;
+ }
+ classes_ptr = cost_classes_aclass_cache[aclass] = (cost_classes_t) *slot;
+ }
+ regno_cost_classes[regno] = classes_ptr;
+}
+
+/* Setup cost classes for pseudo REGNO with MODE. Usage of MODE can
+ decrease number of cost classes for the pseudo, if hard registers
+ of some important classes can not hold a value of MODE. So the
+ pseudo can not get hard register of some important classes and cost
+ calculation for such important classes is only waisting CPU
+ time. */
+static void
+setup_regno_cost_classes_by_mode (int regno, enum machine_mode mode)
+{
+ static struct cost_classes classes;
+ cost_classes_t classes_ptr;
+ enum reg_class cl;
+ int i;
+ PTR *slot;
+ HARD_REG_SET temp;
+
+ if ((classes_ptr = cost_classes_mode_cache[mode]) == NULL)
+ {
+ classes.num = 0;
+ for (i = 0; i < ira_important_classes_num; i++)
+ {
+ cl = ira_important_classes[i];
+ COPY_HARD_REG_SET (temp, ira_prohibited_class_mode_regs[cl][mode]);
+ IOR_HARD_REG_SET (temp, ira_no_alloc_regs);
+ if (hard_reg_set_subset_p (reg_class_contents[cl], temp))
+ continue;
+ classes.classes[classes.num++] = cl;
+ }
+ slot = htab_find_slot (cost_classes_htab, &classes, INSERT);
+ if (*slot == NULL)
+ {
+ classes_ptr = setup_cost_classes (&classes);
+ *slot = classes_ptr;
+ }
+ else
+ classes_ptr = (cost_classes_t) *slot;
+ cost_classes_mode_cache[mode] = (cost_classes_t) *slot;
+ }
+ regno_cost_classes[regno] = classes_ptr;
+}
+
+/* Finilize info about the cost classes for each pseudo. */
+static void
+finish_regno_cost_classes (void)
+{
+ ira_free (regno_cost_classes);
+ htab_delete (cost_classes_htab);
+}
+
+\f
+