typedef struct live_range *live_range_t;
typedef struct ira_allocno *ira_allocno_t;
typedef struct ira_allocno_copy *ira_copy_t;
+typedef struct ira_object *ira_object_t;
/* Definition of vector of allocnos and copies. */
DEF_VEC_P(ira_allocno_t);
DEF_VEC_ALLOC_P(ira_allocno_t, heap);
+DEF_VEC_P(ira_object_t);
+DEF_VEC_ALLOC_P(ira_object_t, heap);
DEF_VEC_P(ira_copy_t);
DEF_VEC_ALLOC_P(ira_copy_t, heap);
#define IRA_LOOP_NODE(loop) IRA_LOOP_NODE_BY_INDEX ((loop)->num)
\f
-
/* The structure describes program points where a given allocno lives.
To save memory we store allocno conflicts only for the same cover
class allocnos which is enough to assign hard registers. To find
intersected, the allocnos are in conflict. */
struct live_range
{
- /* Allocno whose live range is described by given structure. */
- ira_allocno_t allocno;
+ /* Object whose live range is described by given structure. */
+ ira_object_t object;
/* Program point range. */
int start, finish;
/* Next structure describing program points where the allocno
live ranges with given start/finish point. */
extern live_range_t *ira_start_point_ranges, *ira_finish_point_ranges;
+/* A structure representing conflict information for an allocno
+ (or one of its subwords). */
+struct ira_object
+{
+ /* The allocno associated with this record. */
+ ira_allocno_t allocno;
+ /* Vector of accumulated conflicting conflict_redords with NULL end
+ marker (if OBJECT_CONFLICT_VEC_P is true) or conflict bit vector
+ otherwise. Only ira_objects belonging to allocnos with the
+ same cover class are in the vector or in the bit vector. */
+ void *conflicts_array;
+ /* Pointer to structures describing at what program point the
+ object lives. We always maintain the list in such way that *the
+ ranges in the list are not intersected and ordered by decreasing
+ their program points*. */
+ live_range_t live_ranges;
+ /* The subword within ALLOCNO which is represented by this object.
+ Zero means the lowest-order subword (or the entire allocno in case
+ it is not being tracked in subwords). */
+ int subword;
+ /* Allocated size of the conflicts array. */
+ unsigned int conflicts_array_size;
+ /* A unique number for every instance of this structure, which is used
+ to represent it in conflict bit vectors. */
+ int id;
+ /* Before building conflicts, MIN and MAX are initialized to
+ correspondingly minimal and maximal points of the accumulated
+ live ranges. Afterwards, they hold the minimal and maximal ids
+ of other ira_objects that this one can conflict with. */
+ int min, max;
+ /* Initial and accumulated hard registers conflicting with this
+ object and as a consequences can not be assigned to the allocno.
+ All non-allocatable hard regs and hard regs of cover classes
+ different from given allocno one are included in the sets. */
+ HARD_REG_SET conflict_hard_regs, total_conflict_hard_regs;
+ /* Number of accumulated conflicts in the vector of conflicting
+ objects. */
+ int num_accumulated_conflicts;
+ /* TRUE if conflicts are represented by a vector of pointers to
+ ira_object structures. Otherwise, we use a bit vector indexed
+ by conflict ID numbers. */
+ unsigned int conflict_vec_p : 1;
+};
+
/* A structure representing an allocno (allocation entity). Allocno
represents a pseudo-register in an allocation region. If
pseudo-register does not live in a region but it lives in the
list is chained by NEXT_COALESCED_ALLOCNO. */
ira_allocno_t first_coalesced_allocno;
ira_allocno_t next_coalesced_allocno;
- /* Pointer to structures describing at what program point the
- allocno lives. We always maintain the list in such way that *the
- ranges in the list are not intersected and ordered by decreasing
- their program points*. */
- live_range_t live_ranges;
- /* Before building conflicts the two member values are
- correspondingly minimal and maximal points of the accumulated
- allocno live ranges. After building conflicts the values are
- correspondingly minimal and maximal conflict ids of allocnos with
- which given allocno can conflict. */
- int min, max;
- /* Vector of accumulated conflicting allocnos with NULL end marker
- (if CONFLICT_VEC_P is true) or conflict bit vector otherwise.
- Only allocnos with the same cover class are in the vector or in
- the bit vector. */
- void *conflict_allocno_array;
- /* The unique member value represents given allocno in conflict bit
- vectors. */
- int conflict_id;
- /* Allocated size of the previous array. */
- unsigned int conflict_allocno_array_size;
- /* Initial and accumulated hard registers conflicting with this
- allocno and as a consequences can not be assigned to the allocno.
- All non-allocatable hard regs and hard regs of cover classes
- different from given allocno one are included in the sets. */
- HARD_REG_SET conflict_hard_regs, total_conflict_hard_regs;
- /* Number of accumulated conflicts in the vector of conflicting
- allocnos. */
- int conflict_allocnos_num;
+ /* The number of objects tracked in the following array. */
+ int num_objects;
+ /* An array of structures describing conflict information and live
+ ranges for each object associated with the allocno. There may be
+ more than one such object in cases where the allocno represents a
+ multi-word register. */
+ ira_object_t objects[2];
/* Accumulated frequency of calls which given allocno
intersects. */
int call_freq;
/* TRUE if the allocno was removed from the splay tree used to
choose allocn for spilling (see ira-color.c::. */
unsigned int splay_removed_p : 1;
- /* TRUE if conflicts for given allocno are represented by vector of
- pointers to the conflicting allocnos. Otherwise, we use a bit
- vector where a bit with given index represents allocno with the
- same number. */
- unsigned int conflict_vec_p : 1;
/* Non NULL if we remove restoring value from given allocno to
MEM_OPTIMIZED_DEST at loop exit (see ira-emit.c) because the
allocno value is not changed inside the loop. */
#define ALLOCNO_LOOP_TREE_NODE(A) ((A)->loop_tree_node)
#define ALLOCNO_CAP(A) ((A)->cap)
#define ALLOCNO_CAP_MEMBER(A) ((A)->cap_member)
-#define ALLOCNO_CONFLICT_ALLOCNO_ARRAY(A) ((A)->conflict_allocno_array)
-#define ALLOCNO_CONFLICT_ALLOCNO_ARRAY_SIZE(A) \
- ((A)->conflict_allocno_array_size)
-#define ALLOCNO_CONFLICT_ALLOCNOS_NUM(A) \
- ((A)->conflict_allocnos_num)
-#define ALLOCNO_CONFLICT_HARD_REGS(A) ((A)->conflict_hard_regs)
-#define ALLOCNO_TOTAL_CONFLICT_HARD_REGS(A) ((A)->total_conflict_hard_regs)
#define ALLOCNO_NREFS(A) ((A)->nrefs)
#define ALLOCNO_FREQ(A) ((A)->freq)
#define ALLOCNO_HARD_REGNO(A) ((A)->hard_regno)
#define ALLOCNO_ASSIGNED_P(A) ((A)->assigned_p)
#define ALLOCNO_MAY_BE_SPILLED_P(A) ((A)->may_be_spilled_p)
#define ALLOCNO_SPLAY_REMOVED_P(A) ((A)->splay_removed_p)
-#define ALLOCNO_CONFLICT_VEC_P(A) ((A)->conflict_vec_p)
#define ALLOCNO_MODE(A) ((A)->mode)
#define ALLOCNO_COPIES(A) ((A)->allocno_copies)
#define ALLOCNO_HARD_REG_COSTS(A) ((A)->hard_reg_costs)
#define ALLOCNO_TEMP(A) ((A)->temp)
#define ALLOCNO_FIRST_COALESCED_ALLOCNO(A) ((A)->first_coalesced_allocno)
#define ALLOCNO_NEXT_COALESCED_ALLOCNO(A) ((A)->next_coalesced_allocno)
-#define ALLOCNO_LIVE_RANGES(A) ((A)->live_ranges)
-#define ALLOCNO_MIN(A) ((A)->min)
-#define ALLOCNO_MAX(A) ((A)->max)
-#define ALLOCNO_CONFLICT_ID(A) ((A)->conflict_id)
+#define ALLOCNO_OBJECT(A,N) ((A)->objects[N])
+#define ALLOCNO_NUM_OBJECTS(A) ((A)->num_objects)
+
+#define OBJECT_ALLOCNO(C) ((C)->allocno)
+#define OBJECT_SUBWORD(C) ((C)->subword)
+#define OBJECT_CONFLICT_ARRAY(C) ((C)->conflicts_array)
+#define OBJECT_CONFLICT_VEC(C) ((ira_object_t *)(C)->conflicts_array)
+#define OBJECT_CONFLICT_BITVEC(C) ((IRA_INT_TYPE *)(C)->conflicts_array)
+#define OBJECT_CONFLICT_ARRAY_SIZE(C) ((C)->conflicts_array_size)
+#define OBJECT_CONFLICT_VEC_P(C) ((C)->conflict_vec_p)
+#define OBJECT_NUM_CONFLICTS(C) ((C)->num_accumulated_conflicts)
+#define OBJECT_CONFLICT_HARD_REGS(C) ((C)->conflict_hard_regs)
+#define OBJECT_TOTAL_CONFLICT_HARD_REGS(C) ((C)->total_conflict_hard_regs)
+#define OBJECT_MIN(C) ((C)->min)
+#define OBJECT_MAX(C) ((C)->max)
+#define OBJECT_CONFLICT_ID(C) ((C)->id)
+#define OBJECT_LIVE_RANGES(A) ((A)->live_ranges)
/* Map regno -> allocnos with given regno (see comments for
allocno member `next_regno_allocno'). */
have NULL element value. */
extern ira_allocno_t *ira_allocnos;
-/* Sizes of the previous array. */
+/* The size of the previous array. */
extern int ira_allocnos_num;
-/* Map conflict id -> allocno with given conflict id (see comments for
- allocno member `conflict_id'). */
-extern ira_allocno_t *ira_conflict_id_allocno_map;
+/* Map a conflict id to its corresponding ira_object structure. */
+extern ira_object_t *ira_object_id_map;
+
+/* The size of the previous array. */
+extern int ira_objects_num;
/* The following structure represents a copy of two allocnos. The
copies represent move insns or potential move insns usually because
/* The type used as elements in the array, and the number of bits in
this type. */
+
#define IRA_INT_BITS HOST_BITS_PER_WIDE_INT
#define IRA_INT_TYPE HOST_WIDE_INT
i->word = i->nel == 0 ? 0 : vec[0];
}
-/* Return TRUE if we have more elements to visit, in which case *N is
+/* Return TRUE if we have more allocnos to visit, in which case *N is
set to the number of the element to be visited. Otherwise, return
FALSE. */
static inline bool
extern ira_allocno_t ira_parent_allocno (ira_allocno_t);
extern ira_allocno_t ira_parent_or_cap_allocno (ira_allocno_t);
extern ira_allocno_t ira_create_allocno (int, bool, ira_loop_tree_node_t);
+extern void ira_create_allocno_objects (ira_allocno_t);
extern void ira_set_allocno_cover_class (ira_allocno_t, enum reg_class);
-extern bool ira_conflict_vector_profitable_p (ira_allocno_t, int);
-extern void ira_allocate_allocno_conflict_vec (ira_allocno_t, int);
-extern void ira_allocate_allocno_conflicts (ira_allocno_t, int);
-extern void ira_add_allocno_conflict (ira_allocno_t, ira_allocno_t);
+extern bool ira_conflict_vector_profitable_p (ira_object_t, int);
+extern void ira_allocate_conflict_vec (ira_object_t, int);
+extern void ira_allocate_object_conflicts (ira_object_t, int);
+extern void ior_hard_reg_conflicts (ira_allocno_t, HARD_REG_SET *);
extern void ira_print_expanded_allocno (ira_allocno_t);
-extern live_range_t ira_create_allocno_live_range (ira_allocno_t, int, int,
- live_range_t);
-extern live_range_t ira_copy_allocno_live_range_list (live_range_t);
-extern live_range_t ira_merge_allocno_live_ranges (live_range_t, live_range_t);
-extern bool ira_allocno_live_ranges_intersect_p (live_range_t, live_range_t);
-extern void ira_finish_allocno_live_range (live_range_t);
-extern void ira_finish_allocno_live_range_list (live_range_t);
+extern void ira_add_live_range_to_object (ira_object_t, int, int);
+extern live_range_t ira_create_live_range (ira_object_t, int, int,
+ live_range_t);
+extern live_range_t ira_copy_live_range_list (live_range_t);
+extern live_range_t ira_merge_live_ranges (live_range_t, live_range_t);
+extern bool ira_live_ranges_intersect_p (live_range_t, live_range_t);
+extern void ira_finish_live_range (live_range_t);
+extern void ira_finish_live_range_list (live_range_t);
extern void ira_free_allocno_updated_costs (ira_allocno_t);
extern ira_copy_t ira_create_copy (ira_allocno_t, ira_allocno_t,
int, bool, rtx, ira_loop_tree_node_t);
#define FOR_EACH_ALLOCNO(A, ITER) \
for (ira_allocno_iter_init (&(ITER)); \
ira_allocno_iter_cond (&(ITER), &(A));)
+\f
+/* The iterator for all objects. */
+typedef struct {
+ /* The number of the current element in ira_object_id_map. */
+ int n;
+} ira_object_iterator;
+
+/* Initialize the iterator I. */
+static inline void
+ira_object_iter_init (ira_object_iterator *i)
+{
+ i->n = 0;
+}
+
+/* Return TRUE if we have more objects to visit, in which case *OBJ is
+ set to the object to be visited. Otherwise, return FALSE. */
+static inline bool
+ira_object_iter_cond (ira_object_iterator *i, ira_object_t *obj)
+{
+ int n;
+
+ for (n = i->n; n < ira_objects_num; n++)
+ if (ira_object_id_map[n] != NULL)
+ {
+ *obj = ira_object_id_map[n];
+ i->n = n + 1;
+ return true;
+ }
+ return false;
+}
+
+/* Loop over all objects. In each iteration, OBJ is set to the next
+ object. ITER is an instance of ira_object_iterator used to iterate
+ the objects. */
+#define FOR_EACH_OBJECT(OBJ, ITER) \
+ for (ira_object_iter_init (&(ITER)); \
+ ira_object_iter_cond (&(ITER), &(OBJ));)
+\f
+/* The iterator for objects associated with an allocno. */
+typedef struct {
+ /* The number of the element the allocno's object array. */
+ int n;
+} ira_allocno_object_iterator;
+/* Initialize the iterator I. */
+static inline void
+ira_allocno_object_iter_init (ira_allocno_object_iterator *i)
+{
+ i->n = 0;
+}
+
+/* Return TRUE if we have more objects to visit in allocno A, in which
+ case *O is set to the object to be visited. Otherwise, return
+ FALSE. */
+static inline bool
+ira_allocno_object_iter_cond (ira_allocno_object_iterator *i, ira_allocno_t a,
+ ira_object_t *o)
+{
+ *o = ALLOCNO_OBJECT (a, i->n);
+ return i->n++ < ALLOCNO_NUM_OBJECTS (a);
+}
+/* Loop over all objects associated with allocno A. In each
+ iteration, O is set to the next object. ITER is an instance of
+ ira_allocno_object_iterator used to iterate the conflicts. */
+#define FOR_EACH_ALLOCNO_OBJECT(A, O, ITER) \
+ for (ira_allocno_object_iter_init (&(ITER)); \
+ ira_allocno_object_iter_cond (&(ITER), (A), &(O));)
\f
/* The iterator for copies. */
#define FOR_EACH_COPY(C, ITER) \
for (ira_copy_iter_init (&(ITER)); \
ira_copy_iter_cond (&(ITER), &(C));)
-
-
\f
-
-/* The iterator for allocno conflicts. */
+/* The iterator for object conflicts. */
typedef struct {
/* TRUE if the conflicts are represented by vector of allocnos. */
- bool allocno_conflict_vec_p;
+ bool conflict_vec_p;
/* The conflict vector or conflict bit vector. */
void *vec;
/* The number of the current element in the vector (of type
- ira_allocno_t or IRA_INT_TYPE). */
+ ira_object_t or IRA_INT_TYPE). */
unsigned int word_num;
/* The bit vector size. It is defined only if
- ALLOCNO_CONFLICT_VEC_P is FALSE. */
+ OBJECT_CONFLICT_VEC_P is FALSE. */
unsigned int size;
/* The current bit index of bit vector. It is defined only if
- ALLOCNO_CONFLICT_VEC_P is FALSE. */
+ OBJECT_CONFLICT_VEC_P is FALSE. */
unsigned int bit_num;
- /* Allocno conflict id corresponding to the 1st bit of the bit
- vector. It is defined only if ALLOCNO_CONFLICT_VEC_P is
- FALSE. */
+ /* The object id corresponding to the 1st bit of the bit vector. It
+ is defined only if OBJECT_CONFLICT_VEC_P is FALSE. */
int base_conflict_id;
/* The word of bit vector currently visited. It is defined only if
- ALLOCNO_CONFLICT_VEC_P is FALSE. */
+ OBJECT_CONFLICT_VEC_P is FALSE. */
unsigned IRA_INT_TYPE word;
-} ira_allocno_conflict_iterator;
+} ira_object_conflict_iterator;
/* Initialize the iterator I with ALLOCNO conflicts. */
static inline void
-ira_allocno_conflict_iter_init (ira_allocno_conflict_iterator *i,
- ira_allocno_t allocno)
+ira_object_conflict_iter_init (ira_object_conflict_iterator *i,
+ ira_object_t obj)
{
- i->allocno_conflict_vec_p = ALLOCNO_CONFLICT_VEC_P (allocno);
- i->vec = ALLOCNO_CONFLICT_ALLOCNO_ARRAY (allocno);
+ i->conflict_vec_p = OBJECT_CONFLICT_VEC_P (obj);
+ i->vec = OBJECT_CONFLICT_ARRAY (obj);
i->word_num = 0;
- if (i->allocno_conflict_vec_p)
+ if (i->conflict_vec_p)
i->size = i->bit_num = i->base_conflict_id = i->word = 0;
else
{
- if (ALLOCNO_MIN (allocno) > ALLOCNO_MAX (allocno))
+ if (OBJECT_MIN (obj) > OBJECT_MAX (obj))
i->size = 0;
else
- i->size = ((ALLOCNO_MAX (allocno) - ALLOCNO_MIN (allocno)
+ i->size = ((OBJECT_MAX (obj) - OBJECT_MIN (obj)
+ IRA_INT_BITS)
/ IRA_INT_BITS) * sizeof (IRA_INT_TYPE);
i->bit_num = 0;
- i->base_conflict_id = ALLOCNO_MIN (allocno);
+ i->base_conflict_id = OBJECT_MIN (obj);
i->word = (i->size == 0 ? 0 : ((IRA_INT_TYPE *) i->vec)[0]);
}
}
case *A is set to the allocno to be visited. Otherwise, return
FALSE. */
static inline bool
-ira_allocno_conflict_iter_cond (ira_allocno_conflict_iterator *i,
- ira_allocno_t *a)
+ira_object_conflict_iter_cond (ira_object_conflict_iterator *i,
+ ira_object_t *pobj)
{
- ira_allocno_t conflict_allocno;
+ ira_object_t obj;
- if (i->allocno_conflict_vec_p)
+ if (i->conflict_vec_p)
{
- conflict_allocno = ((ira_allocno_t *) i->vec)[i->word_num];
- if (conflict_allocno == NULL)
+ obj = ((ira_object_t *) i->vec)[i->word_num];
+ if (obj == NULL)
return false;
- *a = conflict_allocno;
- return true;
}
else
{
for (; (i->word & 1) == 0; i->word >>= 1)
i->bit_num++;
- *a = ira_conflict_id_allocno_map[i->bit_num + i->base_conflict_id];
-
- return true;
+ obj = ira_object_id_map[i->bit_num + i->base_conflict_id];
}
+
+ *pobj = obj;
+ return true;
}
/* Advance to the next conflicting allocno. */
static inline void
-ira_allocno_conflict_iter_next (ira_allocno_conflict_iterator *i)
+ira_object_conflict_iter_next (ira_object_conflict_iterator *i)
{
- if (i->allocno_conflict_vec_p)
+ if (i->conflict_vec_p)
i->word_num++;
else
{
}
}
-/* Loop over all allocnos conflicting with ALLOCNO. In each
- iteration, A is set to the next conflicting allocno. ITER is an
- instance of ira_allocno_conflict_iterator used to iterate the
- conflicts. */
-#define FOR_EACH_ALLOCNO_CONFLICT(ALLOCNO, A, ITER) \
- for (ira_allocno_conflict_iter_init (&(ITER), (ALLOCNO)); \
- ira_allocno_conflict_iter_cond (&(ITER), &(A)); \
- ira_allocno_conflict_iter_next (&(ITER)))
+/* Loop over all objects conflicting with OBJ. In each iteration,
+ CONF is set to the next conflicting object. ITER is an instance
+ of ira_object_conflict_iterator used to iterate the conflicts. */
+#define FOR_EACH_OBJECT_CONFLICT(OBJ, CONF, ITER) \
+ for (ira_object_conflict_iter_init (&(ITER), (OBJ)); \
+ ira_object_conflict_iter_cond (&(ITER), &(CONF)); \
+ ira_object_conflict_iter_next (&(ITER)))
\f