xref: /dragonfly/contrib/gcc-4.7/gcc/ira-color.c (revision e4b17023)
1*e4b17023SJohn Marino /* IRA allocation based on graph coloring.
2*e4b17023SJohn Marino    Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "tm.h"
26*e4b17023SJohn Marino #include "rtl.h"
27*e4b17023SJohn Marino #include "tm_p.h"
28*e4b17023SJohn Marino #include "target.h"
29*e4b17023SJohn Marino #include "regs.h"
30*e4b17023SJohn Marino #include "flags.h"
31*e4b17023SJohn Marino #include "sbitmap.h"
32*e4b17023SJohn Marino #include "bitmap.h"
33*e4b17023SJohn Marino #include "hard-reg-set.h"
34*e4b17023SJohn Marino #include "basic-block.h"
35*e4b17023SJohn Marino #include "expr.h"
36*e4b17023SJohn Marino #include "diagnostic-core.h"
37*e4b17023SJohn Marino #include "reload.h"
38*e4b17023SJohn Marino #include "params.h"
39*e4b17023SJohn Marino #include "df.h"
40*e4b17023SJohn Marino #include "ira-int.h"
41*e4b17023SJohn Marino 
42*e4b17023SJohn Marino typedef struct allocno_hard_regs *allocno_hard_regs_t;
43*e4b17023SJohn Marino 
44*e4b17023SJohn Marino /* The structure contains information about hard registers can be
45*e4b17023SJohn Marino    assigned to allocnos.  Usually it is allocno profitable hard
46*e4b17023SJohn Marino    registers but in some cases this set can be a bit different.  Major
47*e4b17023SJohn Marino    reason of the difference is a requirement to use hard register sets
48*e4b17023SJohn Marino    that form a tree or a forest (set of trees), i.e. hard register set
49*e4b17023SJohn Marino    of a node should contain hard register sets of its subnodes.  */
50*e4b17023SJohn Marino struct allocno_hard_regs
51*e4b17023SJohn Marino {
52*e4b17023SJohn Marino   /* Hard registers can be assigned to an allocno.  */
53*e4b17023SJohn Marino   HARD_REG_SET set;
54*e4b17023SJohn Marino   /* Overall (spilling) cost of all allocnos with given register
55*e4b17023SJohn Marino      set.  */
56*e4b17023SJohn Marino   HOST_WIDEST_INT cost;
57*e4b17023SJohn Marino };
58*e4b17023SJohn Marino 
59*e4b17023SJohn Marino typedef struct allocno_hard_regs_node *allocno_hard_regs_node_t;
60*e4b17023SJohn Marino 
61*e4b17023SJohn Marino /* A node representing allocno hard registers.  Such nodes form a
62*e4b17023SJohn Marino    forest (set of trees).  Each subnode of given node in the forest
63*e4b17023SJohn Marino    refers for hard register set (usually allocno profitable hard
64*e4b17023SJohn Marino    register set) which is a subset of one referred from given
65*e4b17023SJohn Marino    node.  */
66*e4b17023SJohn Marino struct allocno_hard_regs_node
67*e4b17023SJohn Marino {
68*e4b17023SJohn Marino   /* Set up number of the node in preorder traversing of the forest.  */
69*e4b17023SJohn Marino   int preorder_num;
70*e4b17023SJohn Marino   /* Used for different calculation like finding conflict size of an
71*e4b17023SJohn Marino      allocno.  */
72*e4b17023SJohn Marino   int check;
73*e4b17023SJohn Marino   /* Used for calculation of conflict size of an allocno.  The
74*e4b17023SJohn Marino      conflict size of the allocno is maximal number of given allocno
75*e4b17023SJohn Marino      hard registers needed for allocation of the conflicting allocnos.
76*e4b17023SJohn Marino      Given allocno is trivially colored if this number plus the number
77*e4b17023SJohn Marino      of hard registers needed for given allocno is not greater than
78*e4b17023SJohn Marino      the number of given allocno hard register set.  */
79*e4b17023SJohn Marino   int conflict_size;
80*e4b17023SJohn Marino   /* The number of hard registers given by member hard_regs.  */
81*e4b17023SJohn Marino   int hard_regs_num;
82*e4b17023SJohn Marino   /* The following member is used to form the final forest.  */
83*e4b17023SJohn Marino   bool used_p;
84*e4b17023SJohn Marino   /* Pointer to the corresponding profitable hard registers.  */
85*e4b17023SJohn Marino   allocno_hard_regs_t hard_regs;
86*e4b17023SJohn Marino   /* Parent, first subnode, previous and next node with the same
87*e4b17023SJohn Marino      parent in the forest.  */
88*e4b17023SJohn Marino   allocno_hard_regs_node_t parent, first, prev, next;
89*e4b17023SJohn Marino };
90*e4b17023SJohn Marino 
91*e4b17023SJohn Marino /* To decrease footprint of ira_allocno structure we store all data
92*e4b17023SJohn Marino    needed only for coloring in the following structure.  */
93*e4b17023SJohn Marino struct allocno_color_data
94*e4b17023SJohn Marino {
95*e4b17023SJohn Marino   /* TRUE value means that the allocno was not removed yet from the
96*e4b17023SJohn Marino      conflicting graph during colouring.  */
97*e4b17023SJohn Marino   unsigned int in_graph_p : 1;
98*e4b17023SJohn Marino   /* TRUE if it is put on the stack to make other allocnos
99*e4b17023SJohn Marino      colorable.  */
100*e4b17023SJohn Marino   unsigned int may_be_spilled_p : 1;
101*e4b17023SJohn Marino   /* TRUE if the allocno is trivially colorable.  */
102*e4b17023SJohn Marino   unsigned int colorable_p : 1;
103*e4b17023SJohn Marino   /* Number of hard registers of the allocno class really
104*e4b17023SJohn Marino      available for the allocno allocation.  It is number of the
105*e4b17023SJohn Marino      profitable hard regs.  */
106*e4b17023SJohn Marino   int available_regs_num;
107*e4b17023SJohn Marino   /* Allocnos in a bucket (used in coloring) chained by the following
108*e4b17023SJohn Marino      two members.  */
109*e4b17023SJohn Marino   ira_allocno_t next_bucket_allocno;
110*e4b17023SJohn Marino   ira_allocno_t prev_bucket_allocno;
111*e4b17023SJohn Marino   /* Used for temporary purposes.  */
112*e4b17023SJohn Marino   int temp;
113*e4b17023SJohn Marino   /* Used to exclude repeated processing.  */
114*e4b17023SJohn Marino   int last_process;
115*e4b17023SJohn Marino   /* Profitable hard regs available for this pseudo allocation.  It
116*e4b17023SJohn Marino      means that the set excludes unavailable hard regs and hard regs
117*e4b17023SJohn Marino      conflicting with given pseudo.  They should be of the allocno
118*e4b17023SJohn Marino      class.  */
119*e4b17023SJohn Marino   HARD_REG_SET profitable_hard_regs;
120*e4b17023SJohn Marino   /* The allocno hard registers node.  */
121*e4b17023SJohn Marino   allocno_hard_regs_node_t hard_regs_node;
122*e4b17023SJohn Marino   /* Array of structures allocno_hard_regs_subnode representing
123*e4b17023SJohn Marino      given allocno hard registers node (the 1st element in the array)
124*e4b17023SJohn Marino      and all its subnodes in the tree (forest) of allocno hard
125*e4b17023SJohn Marino      register nodes (see comments above).  */
126*e4b17023SJohn Marino   int hard_regs_subnodes_start;
127*e4b17023SJohn Marino   /* The length of the previous array. */
128*e4b17023SJohn Marino   int hard_regs_subnodes_num;
129*e4b17023SJohn Marino };
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino /* See above.  */
132*e4b17023SJohn Marino typedef struct allocno_color_data *allocno_color_data_t;
133*e4b17023SJohn Marino 
134*e4b17023SJohn Marino /* Container for storing allocno data concerning coloring.  */
135*e4b17023SJohn Marino static allocno_color_data_t allocno_color_data;
136*e4b17023SJohn Marino 
137*e4b17023SJohn Marino /* Macro to access the data concerning coloring.  */
138*e4b17023SJohn Marino #define ALLOCNO_COLOR_DATA(a) ((allocno_color_data_t) ALLOCNO_ADD_DATA (a))
139*e4b17023SJohn Marino 
140*e4b17023SJohn Marino /* Used for finding allocno colorability to exclude repeated allocno
141*e4b17023SJohn Marino    processing and for updating preferencing to exclude repeated
142*e4b17023SJohn Marino    allocno processing during assignment.  */
143*e4b17023SJohn Marino static int curr_allocno_process;
144*e4b17023SJohn Marino 
145*e4b17023SJohn Marino /* This file contains code for regional graph coloring, spill/restore
146*e4b17023SJohn Marino    code placement optimization, and code helping the reload pass to do
147*e4b17023SJohn Marino    a better job.  */
148*e4b17023SJohn Marino 
149*e4b17023SJohn Marino /* Bitmap of allocnos which should be colored.  */
150*e4b17023SJohn Marino static bitmap coloring_allocno_bitmap;
151*e4b17023SJohn Marino 
152*e4b17023SJohn Marino /* Bitmap of allocnos which should be taken into account during
153*e4b17023SJohn Marino    coloring.  In general case it contains allocnos from
154*e4b17023SJohn Marino    coloring_allocno_bitmap plus other already colored conflicting
155*e4b17023SJohn Marino    allocnos.  */
156*e4b17023SJohn Marino static bitmap consideration_allocno_bitmap;
157*e4b17023SJohn Marino 
158*e4b17023SJohn Marino /* All allocnos sorted according their priorities.  */
159*e4b17023SJohn Marino static ira_allocno_t *sorted_allocnos;
160*e4b17023SJohn Marino 
161*e4b17023SJohn Marino /* Vec representing the stack of allocnos used during coloring.  */
162*e4b17023SJohn Marino static VEC(ira_allocno_t,heap) *allocno_stack_vec;
163*e4b17023SJohn Marino 
164*e4b17023SJohn Marino /* Helper for qsort comparison callbacks - return a positive integer if
165*e4b17023SJohn Marino    X > Y, or a negative value otherwise.  Use a conditional expression
166*e4b17023SJohn Marino    instead of a difference computation to insulate from possible overflow
167*e4b17023SJohn Marino    issues, e.g. X - Y < 0 for some X > 0 and Y < 0.  */
168*e4b17023SJohn Marino #define SORTGT(x,y) (((x) > (y)) ? 1 : -1)
169*e4b17023SJohn Marino 
170*e4b17023SJohn Marino 
171*e4b17023SJohn Marino 
172*e4b17023SJohn Marino /* Definition of vector of allocno hard registers.  */
173*e4b17023SJohn Marino DEF_VEC_P(allocno_hard_regs_t);
174*e4b17023SJohn Marino DEF_VEC_ALLOC_P(allocno_hard_regs_t, heap);
175*e4b17023SJohn Marino 
176*e4b17023SJohn Marino /* Vector of unique allocno hard registers.  */
VEC(allocno_hard_regs_t,heap)177*e4b17023SJohn Marino static VEC(allocno_hard_regs_t, heap) *allocno_hard_regs_vec;
178*e4b17023SJohn Marino 
179*e4b17023SJohn Marino /* Returns hash value for allocno hard registers V.  */
180*e4b17023SJohn Marino static hashval_t
181*e4b17023SJohn Marino allocno_hard_regs_hash (const void *v)
182*e4b17023SJohn Marino {
183*e4b17023SJohn Marino   const struct allocno_hard_regs *hv = (const struct allocno_hard_regs *) v;
184*e4b17023SJohn Marino 
185*e4b17023SJohn Marino   return iterative_hash (&hv->set, sizeof (HARD_REG_SET), 0);
186*e4b17023SJohn Marino }
187*e4b17023SJohn Marino 
188*e4b17023SJohn Marino /* Compares allocno hard registers V1 and V2.  */
189*e4b17023SJohn Marino static int
allocno_hard_regs_eq(const void * v1,const void * v2)190*e4b17023SJohn Marino allocno_hard_regs_eq (const void *v1, const void *v2)
191*e4b17023SJohn Marino {
192*e4b17023SJohn Marino   const struct allocno_hard_regs *hv1 = (const struct allocno_hard_regs *) v1;
193*e4b17023SJohn Marino   const struct allocno_hard_regs *hv2 = (const struct allocno_hard_regs *) v2;
194*e4b17023SJohn Marino 
195*e4b17023SJohn Marino   return hard_reg_set_equal_p (hv1->set, hv2->set);
196*e4b17023SJohn Marino }
197*e4b17023SJohn Marino 
198*e4b17023SJohn Marino /* Hash table of unique allocno hard registers.  */
199*e4b17023SJohn Marino static htab_t allocno_hard_regs_htab;
200*e4b17023SJohn Marino 
201*e4b17023SJohn Marino /* Return allocno hard registers in the hash table equal to HV.  */
202*e4b17023SJohn Marino static allocno_hard_regs_t
find_hard_regs(allocno_hard_regs_t hv)203*e4b17023SJohn Marino find_hard_regs (allocno_hard_regs_t hv)
204*e4b17023SJohn Marino {
205*e4b17023SJohn Marino   return (allocno_hard_regs_t) htab_find (allocno_hard_regs_htab, hv);
206*e4b17023SJohn Marino }
207*e4b17023SJohn Marino 
208*e4b17023SJohn Marino /* Insert allocno hard registers HV in the hash table (if it is not
209*e4b17023SJohn Marino    there yet) and return the value which in the table.  */
210*e4b17023SJohn Marino static allocno_hard_regs_t
insert_hard_regs(allocno_hard_regs_t hv)211*e4b17023SJohn Marino insert_hard_regs (allocno_hard_regs_t hv)
212*e4b17023SJohn Marino {
213*e4b17023SJohn Marino   PTR *slot = htab_find_slot (allocno_hard_regs_htab, hv, INSERT);
214*e4b17023SJohn Marino 
215*e4b17023SJohn Marino   if (*slot == NULL)
216*e4b17023SJohn Marino     *slot = hv;
217*e4b17023SJohn Marino   return (allocno_hard_regs_t) *slot;
218*e4b17023SJohn Marino }
219*e4b17023SJohn Marino 
220*e4b17023SJohn Marino /* Initialize data concerning allocno hard registers.  */
221*e4b17023SJohn Marino static void
init_allocno_hard_regs(void)222*e4b17023SJohn Marino init_allocno_hard_regs (void)
223*e4b17023SJohn Marino {
224*e4b17023SJohn Marino   allocno_hard_regs_vec = VEC_alloc (allocno_hard_regs_t, heap, 200);
225*e4b17023SJohn Marino   allocno_hard_regs_htab
226*e4b17023SJohn Marino     = htab_create (200, allocno_hard_regs_hash, allocno_hard_regs_eq, NULL);
227*e4b17023SJohn Marino }
228*e4b17023SJohn Marino 
229*e4b17023SJohn Marino /* Add (or update info about) allocno hard registers with SET and
230*e4b17023SJohn Marino    COST.  */
231*e4b17023SJohn Marino static allocno_hard_regs_t
add_allocno_hard_regs(HARD_REG_SET set,HOST_WIDEST_INT cost)232*e4b17023SJohn Marino add_allocno_hard_regs (HARD_REG_SET set, HOST_WIDEST_INT cost)
233*e4b17023SJohn Marino {
234*e4b17023SJohn Marino   struct allocno_hard_regs temp;
235*e4b17023SJohn Marino   allocno_hard_regs_t hv;
236*e4b17023SJohn Marino 
237*e4b17023SJohn Marino   gcc_assert (! hard_reg_set_empty_p (set));
238*e4b17023SJohn Marino   COPY_HARD_REG_SET (temp.set, set);
239*e4b17023SJohn Marino   if ((hv = find_hard_regs (&temp)) != NULL)
240*e4b17023SJohn Marino     hv->cost += cost;
241*e4b17023SJohn Marino   else
242*e4b17023SJohn Marino     {
243*e4b17023SJohn Marino       hv = ((struct allocno_hard_regs *)
244*e4b17023SJohn Marino 	    ira_allocate (sizeof (struct allocno_hard_regs)));
245*e4b17023SJohn Marino       COPY_HARD_REG_SET (hv->set, set);
246*e4b17023SJohn Marino       hv->cost = cost;
247*e4b17023SJohn Marino       VEC_safe_push (allocno_hard_regs_t, heap, allocno_hard_regs_vec, hv);
248*e4b17023SJohn Marino       insert_hard_regs (hv);
249*e4b17023SJohn Marino     }
250*e4b17023SJohn Marino   return hv;
251*e4b17023SJohn Marino }
252*e4b17023SJohn Marino 
253*e4b17023SJohn Marino /* Finalize data concerning allocno hard registers.  */
254*e4b17023SJohn Marino static void
finish_allocno_hard_regs(void)255*e4b17023SJohn Marino finish_allocno_hard_regs (void)
256*e4b17023SJohn Marino {
257*e4b17023SJohn Marino   int i;
258*e4b17023SJohn Marino   allocno_hard_regs_t hv;
259*e4b17023SJohn Marino 
260*e4b17023SJohn Marino   for (i = 0;
261*e4b17023SJohn Marino        VEC_iterate (allocno_hard_regs_t, allocno_hard_regs_vec, i, hv);
262*e4b17023SJohn Marino        i++)
263*e4b17023SJohn Marino     ira_free (hv);
264*e4b17023SJohn Marino   htab_delete (allocno_hard_regs_htab);
265*e4b17023SJohn Marino   VEC_free (allocno_hard_regs_t, heap, allocno_hard_regs_vec);
266*e4b17023SJohn Marino }
267*e4b17023SJohn Marino 
268*e4b17023SJohn Marino /* Sort hard regs according to their frequency of usage. */
269*e4b17023SJohn Marino static int
allocno_hard_regs_compare(const void * v1p,const void * v2p)270*e4b17023SJohn Marino allocno_hard_regs_compare (const void *v1p, const void *v2p)
271*e4b17023SJohn Marino {
272*e4b17023SJohn Marino   allocno_hard_regs_t hv1 = *(const allocno_hard_regs_t *) v1p;
273*e4b17023SJohn Marino   allocno_hard_regs_t hv2 = *(const allocno_hard_regs_t *) v2p;
274*e4b17023SJohn Marino 
275*e4b17023SJohn Marino   if (hv2->cost > hv1->cost)
276*e4b17023SJohn Marino     return 1;
277*e4b17023SJohn Marino   else if (hv2->cost < hv1->cost)
278*e4b17023SJohn Marino     return -1;
279*e4b17023SJohn Marino   else
280*e4b17023SJohn Marino     return 0;
281*e4b17023SJohn Marino }
282*e4b17023SJohn Marino 
283*e4b17023SJohn Marino 
284*e4b17023SJohn Marino 
285*e4b17023SJohn Marino /* Used for finding a common ancestor of two allocno hard registers
286*e4b17023SJohn Marino    nodes in the forest.  We use the current value of
287*e4b17023SJohn Marino    'node_check_tick' to mark all nodes from one node to the top and
288*e4b17023SJohn Marino    then walking up from another node until we find a marked node.
289*e4b17023SJohn Marino 
290*e4b17023SJohn Marino    It is also used to figure out allocno colorability as a mark that
291*e4b17023SJohn Marino    we already reset value of member 'conflict_size' for the forest
292*e4b17023SJohn Marino    node corresponding to the processed allocno.  */
293*e4b17023SJohn Marino static int node_check_tick;
294*e4b17023SJohn Marino 
295*e4b17023SJohn Marino /* Roots of the forest containing hard register sets can be assigned
296*e4b17023SJohn Marino    to allocnos.  */
297*e4b17023SJohn Marino static allocno_hard_regs_node_t hard_regs_roots;
298*e4b17023SJohn Marino 
299*e4b17023SJohn Marino /* Definition of vector of allocno hard register nodes.  */
300*e4b17023SJohn Marino DEF_VEC_P(allocno_hard_regs_node_t);
301*e4b17023SJohn Marino DEF_VEC_ALLOC_P(allocno_hard_regs_node_t, heap);
302*e4b17023SJohn Marino 
303*e4b17023SJohn Marino /* Vector used to create the forest.  */
VEC(allocno_hard_regs_node_t,heap)304*e4b17023SJohn Marino static VEC(allocno_hard_regs_node_t, heap) *hard_regs_node_vec;
305*e4b17023SJohn Marino 
306*e4b17023SJohn Marino /* Create and return allocno hard registers node containing allocno
307*e4b17023SJohn Marino    hard registers HV.  */
308*e4b17023SJohn Marino static allocno_hard_regs_node_t
309*e4b17023SJohn Marino create_new_allocno_hard_regs_node (allocno_hard_regs_t hv)
310*e4b17023SJohn Marino {
311*e4b17023SJohn Marino   allocno_hard_regs_node_t new_node;
312*e4b17023SJohn Marino 
313*e4b17023SJohn Marino   new_node = ((struct allocno_hard_regs_node *)
314*e4b17023SJohn Marino 	      ira_allocate (sizeof (struct allocno_hard_regs_node)));
315*e4b17023SJohn Marino   new_node->check = 0;
316*e4b17023SJohn Marino   new_node->hard_regs = hv;
317*e4b17023SJohn Marino   new_node->hard_regs_num = hard_reg_set_size (hv->set);
318*e4b17023SJohn Marino   new_node->first = NULL;
319*e4b17023SJohn Marino   new_node->used_p = false;
320*e4b17023SJohn Marino   return new_node;
321*e4b17023SJohn Marino }
322*e4b17023SJohn Marino 
323*e4b17023SJohn Marino /* Add allocno hard registers node NEW_NODE to the forest on its level
324*e4b17023SJohn Marino    given by ROOTS.  */
325*e4b17023SJohn Marino static void
add_new_allocno_hard_regs_node_to_forest(allocno_hard_regs_node_t * roots,allocno_hard_regs_node_t new_node)326*e4b17023SJohn Marino add_new_allocno_hard_regs_node_to_forest (allocno_hard_regs_node_t *roots,
327*e4b17023SJohn Marino 					  allocno_hard_regs_node_t new_node)
328*e4b17023SJohn Marino {
329*e4b17023SJohn Marino   new_node->next = *roots;
330*e4b17023SJohn Marino   if (new_node->next != NULL)
331*e4b17023SJohn Marino     new_node->next->prev = new_node;
332*e4b17023SJohn Marino   new_node->prev = NULL;
333*e4b17023SJohn Marino   *roots = new_node;
334*e4b17023SJohn Marino }
335*e4b17023SJohn Marino 
336*e4b17023SJohn Marino /* Add allocno hard registers HV (or its best approximation if it is
337*e4b17023SJohn Marino    not possible) to the forest on its level given by ROOTS.  */
338*e4b17023SJohn Marino static void
add_allocno_hard_regs_to_forest(allocno_hard_regs_node_t * roots,allocno_hard_regs_t hv)339*e4b17023SJohn Marino add_allocno_hard_regs_to_forest (allocno_hard_regs_node_t *roots,
340*e4b17023SJohn Marino 				 allocno_hard_regs_t hv)
341*e4b17023SJohn Marino {
342*e4b17023SJohn Marino   unsigned int i, start;
343*e4b17023SJohn Marino   allocno_hard_regs_node_t node, prev, new_node;
344*e4b17023SJohn Marino   HARD_REG_SET temp_set;
345*e4b17023SJohn Marino   allocno_hard_regs_t hv2;
346*e4b17023SJohn Marino 
347*e4b17023SJohn Marino   start = VEC_length (allocno_hard_regs_node_t, hard_regs_node_vec);
348*e4b17023SJohn Marino   for (node = *roots; node != NULL; node = node->next)
349*e4b17023SJohn Marino     {
350*e4b17023SJohn Marino       if (hard_reg_set_equal_p (hv->set, node->hard_regs->set))
351*e4b17023SJohn Marino 	return;
352*e4b17023SJohn Marino       if (hard_reg_set_subset_p (hv->set, node->hard_regs->set))
353*e4b17023SJohn Marino 	{
354*e4b17023SJohn Marino 	  add_allocno_hard_regs_to_forest (&node->first, hv);
355*e4b17023SJohn Marino 	  return;
356*e4b17023SJohn Marino 	}
357*e4b17023SJohn Marino       if (hard_reg_set_subset_p (node->hard_regs->set, hv->set))
358*e4b17023SJohn Marino 	VEC_safe_push (allocno_hard_regs_node_t, heap,
359*e4b17023SJohn Marino 		       hard_regs_node_vec, node);
360*e4b17023SJohn Marino       else if (hard_reg_set_intersect_p (hv->set, node->hard_regs->set))
361*e4b17023SJohn Marino 	{
362*e4b17023SJohn Marino 	  COPY_HARD_REG_SET (temp_set, hv->set);
363*e4b17023SJohn Marino 	  AND_HARD_REG_SET (temp_set, node->hard_regs->set);
364*e4b17023SJohn Marino 	  hv2 = add_allocno_hard_regs (temp_set, hv->cost);
365*e4b17023SJohn Marino 	  add_allocno_hard_regs_to_forest (&node->first, hv2);
366*e4b17023SJohn Marino 	}
367*e4b17023SJohn Marino     }
368*e4b17023SJohn Marino   if (VEC_length (allocno_hard_regs_node_t, hard_regs_node_vec)
369*e4b17023SJohn Marino       > start + 1)
370*e4b17023SJohn Marino     {
371*e4b17023SJohn Marino       /* Create a new node which contains nodes in hard_regs_node_vec.  */
372*e4b17023SJohn Marino       CLEAR_HARD_REG_SET (temp_set);
373*e4b17023SJohn Marino       for (i = start;
374*e4b17023SJohn Marino 	   i < VEC_length (allocno_hard_regs_node_t, hard_regs_node_vec);
375*e4b17023SJohn Marino 	   i++)
376*e4b17023SJohn Marino 	{
377*e4b17023SJohn Marino 	  node = VEC_index (allocno_hard_regs_node_t, hard_regs_node_vec, i);
378*e4b17023SJohn Marino 	  IOR_HARD_REG_SET (temp_set, node->hard_regs->set);
379*e4b17023SJohn Marino 	}
380*e4b17023SJohn Marino       hv = add_allocno_hard_regs (temp_set, hv->cost);
381*e4b17023SJohn Marino       new_node = create_new_allocno_hard_regs_node (hv);
382*e4b17023SJohn Marino       prev = NULL;
383*e4b17023SJohn Marino       for (i = start;
384*e4b17023SJohn Marino 	   i < VEC_length (allocno_hard_regs_node_t, hard_regs_node_vec);
385*e4b17023SJohn Marino 	   i++)
386*e4b17023SJohn Marino 	{
387*e4b17023SJohn Marino 	  node = VEC_index (allocno_hard_regs_node_t, hard_regs_node_vec, i);
388*e4b17023SJohn Marino 	  if (node->prev == NULL)
389*e4b17023SJohn Marino 	    *roots = node->next;
390*e4b17023SJohn Marino 	  else
391*e4b17023SJohn Marino 	    node->prev->next = node->next;
392*e4b17023SJohn Marino 	  if (node->next != NULL)
393*e4b17023SJohn Marino 	    node->next->prev = node->prev;
394*e4b17023SJohn Marino 	  if (prev == NULL)
395*e4b17023SJohn Marino 	    new_node->first = node;
396*e4b17023SJohn Marino 	  else
397*e4b17023SJohn Marino 	    prev->next = node;
398*e4b17023SJohn Marino 	  node->prev = prev;
399*e4b17023SJohn Marino 	  node->next = NULL;
400*e4b17023SJohn Marino 	  prev = node;
401*e4b17023SJohn Marino 	}
402*e4b17023SJohn Marino       add_new_allocno_hard_regs_node_to_forest (roots, new_node);
403*e4b17023SJohn Marino     }
404*e4b17023SJohn Marino   VEC_truncate (allocno_hard_regs_node_t, hard_regs_node_vec, start);
405*e4b17023SJohn Marino }
406*e4b17023SJohn Marino 
407*e4b17023SJohn Marino /* Add allocno hard registers nodes starting with the forest level
408*e4b17023SJohn Marino    given by FIRST which contains biggest set inside SET.  */
409*e4b17023SJohn Marino static void
collect_allocno_hard_regs_cover(allocno_hard_regs_node_t first,HARD_REG_SET set)410*e4b17023SJohn Marino collect_allocno_hard_regs_cover (allocno_hard_regs_node_t first,
411*e4b17023SJohn Marino 				 HARD_REG_SET set)
412*e4b17023SJohn Marino {
413*e4b17023SJohn Marino   allocno_hard_regs_node_t node;
414*e4b17023SJohn Marino 
415*e4b17023SJohn Marino   ira_assert (first != NULL);
416*e4b17023SJohn Marino   for (node = first; node != NULL; node = node->next)
417*e4b17023SJohn Marino     if (hard_reg_set_subset_p (node->hard_regs->set, set))
418*e4b17023SJohn Marino       VEC_safe_push (allocno_hard_regs_node_t, heap, hard_regs_node_vec,
419*e4b17023SJohn Marino 		     node);
420*e4b17023SJohn Marino     else if (hard_reg_set_intersect_p (set, node->hard_regs->set))
421*e4b17023SJohn Marino       collect_allocno_hard_regs_cover (node->first, set);
422*e4b17023SJohn Marino }
423*e4b17023SJohn Marino 
424*e4b17023SJohn Marino /* Set up field parent as PARENT in all allocno hard registers nodes
425*e4b17023SJohn Marino    in forest given by FIRST.  */
426*e4b17023SJohn Marino static void
setup_allocno_hard_regs_nodes_parent(allocno_hard_regs_node_t first,allocno_hard_regs_node_t parent)427*e4b17023SJohn Marino setup_allocno_hard_regs_nodes_parent (allocno_hard_regs_node_t first,
428*e4b17023SJohn Marino 				      allocno_hard_regs_node_t parent)
429*e4b17023SJohn Marino {
430*e4b17023SJohn Marino   allocno_hard_regs_node_t node;
431*e4b17023SJohn Marino 
432*e4b17023SJohn Marino   for (node = first; node != NULL; node = node->next)
433*e4b17023SJohn Marino     {
434*e4b17023SJohn Marino       node->parent = parent;
435*e4b17023SJohn Marino       setup_allocno_hard_regs_nodes_parent (node->first, node);
436*e4b17023SJohn Marino     }
437*e4b17023SJohn Marino }
438*e4b17023SJohn Marino 
439*e4b17023SJohn Marino /* Return allocno hard registers node which is a first common ancestor
440*e4b17023SJohn Marino    node of FIRST and SECOND in the forest.  */
441*e4b17023SJohn Marino static allocno_hard_regs_node_t
first_common_ancestor_node(allocno_hard_regs_node_t first,allocno_hard_regs_node_t second)442*e4b17023SJohn Marino first_common_ancestor_node (allocno_hard_regs_node_t first,
443*e4b17023SJohn Marino 			    allocno_hard_regs_node_t second)
444*e4b17023SJohn Marino {
445*e4b17023SJohn Marino   allocno_hard_regs_node_t node;
446*e4b17023SJohn Marino 
447*e4b17023SJohn Marino   node_check_tick++;
448*e4b17023SJohn Marino   for (node = first; node != NULL; node = node->parent)
449*e4b17023SJohn Marino     node->check = node_check_tick;
450*e4b17023SJohn Marino   for (node = second; node != NULL; node = node->parent)
451*e4b17023SJohn Marino     if (node->check == node_check_tick)
452*e4b17023SJohn Marino       return node;
453*e4b17023SJohn Marino   return first_common_ancestor_node (second, first);
454*e4b17023SJohn Marino }
455*e4b17023SJohn Marino 
456*e4b17023SJohn Marino /* Print hard reg set SET to F.  */
457*e4b17023SJohn Marino static void
print_hard_reg_set(FILE * f,HARD_REG_SET set,bool new_line_p)458*e4b17023SJohn Marino print_hard_reg_set (FILE *f, HARD_REG_SET set, bool new_line_p)
459*e4b17023SJohn Marino {
460*e4b17023SJohn Marino   int i, start;
461*e4b17023SJohn Marino 
462*e4b17023SJohn Marino   for (start = -1, i = 0; i < FIRST_PSEUDO_REGISTER; i++)
463*e4b17023SJohn Marino     {
464*e4b17023SJohn Marino       if (TEST_HARD_REG_BIT (set, i))
465*e4b17023SJohn Marino 	{
466*e4b17023SJohn Marino 	  if (i == 0 || ! TEST_HARD_REG_BIT (set, i - 1))
467*e4b17023SJohn Marino 	    start = i;
468*e4b17023SJohn Marino 	}
469*e4b17023SJohn Marino       if (start >= 0
470*e4b17023SJohn Marino 	  && (i == FIRST_PSEUDO_REGISTER - 1 || ! TEST_HARD_REG_BIT (set, i)))
471*e4b17023SJohn Marino 	{
472*e4b17023SJohn Marino 	  if (start == i - 1)
473*e4b17023SJohn Marino 	    fprintf (f, " %d", start);
474*e4b17023SJohn Marino 	  else if (start == i - 2)
475*e4b17023SJohn Marino 	    fprintf (f, " %d %d", start, start + 1);
476*e4b17023SJohn Marino 	  else
477*e4b17023SJohn Marino 	    fprintf (f, " %d-%d", start, i - 1);
478*e4b17023SJohn Marino 	  start = -1;
479*e4b17023SJohn Marino 	}
480*e4b17023SJohn Marino     }
481*e4b17023SJohn Marino   if (new_line_p)
482*e4b17023SJohn Marino     fprintf (f, "\n");
483*e4b17023SJohn Marino }
484*e4b17023SJohn Marino 
485*e4b17023SJohn Marino /* Print allocno hard register subforest given by ROOTS and its LEVEL
486*e4b17023SJohn Marino    to F.  */
487*e4b17023SJohn Marino static void
print_hard_regs_subforest(FILE * f,allocno_hard_regs_node_t roots,int level)488*e4b17023SJohn Marino print_hard_regs_subforest (FILE *f, allocno_hard_regs_node_t roots,
489*e4b17023SJohn Marino 			   int level)
490*e4b17023SJohn Marino {
491*e4b17023SJohn Marino   int i;
492*e4b17023SJohn Marino   allocno_hard_regs_node_t node;
493*e4b17023SJohn Marino 
494*e4b17023SJohn Marino   for (node = roots; node != NULL; node = node->next)
495*e4b17023SJohn Marino     {
496*e4b17023SJohn Marino       fprintf (f, "    ");
497*e4b17023SJohn Marino       for (i = 0; i < level * 2; i++)
498*e4b17023SJohn Marino 	fprintf (f, " ");
499*e4b17023SJohn Marino       fprintf (f, "%d:(", node->preorder_num);
500*e4b17023SJohn Marino       print_hard_reg_set (f, node->hard_regs->set, false);
501*e4b17023SJohn Marino       fprintf (f, ")@" HOST_WIDEST_INT_PRINT_DEC "\n", node->hard_regs->cost);
502*e4b17023SJohn Marino       print_hard_regs_subforest (f, node->first, level + 1);
503*e4b17023SJohn Marino     }
504*e4b17023SJohn Marino }
505*e4b17023SJohn Marino 
506*e4b17023SJohn Marino /* Print the allocno hard register forest to F.  */
507*e4b17023SJohn Marino static void
print_hard_regs_forest(FILE * f)508*e4b17023SJohn Marino print_hard_regs_forest (FILE *f)
509*e4b17023SJohn Marino {
510*e4b17023SJohn Marino   fprintf (f, "    Hard reg set forest:\n");
511*e4b17023SJohn Marino   print_hard_regs_subforest (f, hard_regs_roots, 1);
512*e4b17023SJohn Marino }
513*e4b17023SJohn Marino 
514*e4b17023SJohn Marino /* Print the allocno hard register forest to stderr.  */
515*e4b17023SJohn Marino void
ira_debug_hard_regs_forest(void)516*e4b17023SJohn Marino ira_debug_hard_regs_forest (void)
517*e4b17023SJohn Marino {
518*e4b17023SJohn Marino   print_hard_regs_forest (stderr);
519*e4b17023SJohn Marino }
520*e4b17023SJohn Marino 
521*e4b17023SJohn Marino /* Remove unused allocno hard registers nodes from forest given by its
522*e4b17023SJohn Marino    *ROOTS.  */
523*e4b17023SJohn Marino static void
remove_unused_allocno_hard_regs_nodes(allocno_hard_regs_node_t * roots)524*e4b17023SJohn Marino remove_unused_allocno_hard_regs_nodes (allocno_hard_regs_node_t *roots)
525*e4b17023SJohn Marino {
526*e4b17023SJohn Marino   allocno_hard_regs_node_t node, prev, next, last;
527*e4b17023SJohn Marino 
528*e4b17023SJohn Marino   for (prev = NULL, node = *roots; node != NULL; node = next)
529*e4b17023SJohn Marino     {
530*e4b17023SJohn Marino       next = node->next;
531*e4b17023SJohn Marino       if (node->used_p)
532*e4b17023SJohn Marino 	{
533*e4b17023SJohn Marino 	  remove_unused_allocno_hard_regs_nodes (&node->first);
534*e4b17023SJohn Marino 	  prev = node;
535*e4b17023SJohn Marino 	}
536*e4b17023SJohn Marino       else
537*e4b17023SJohn Marino 	{
538*e4b17023SJohn Marino 	  for (last = node->first;
539*e4b17023SJohn Marino 	       last != NULL && last->next != NULL;
540*e4b17023SJohn Marino 	       last = last->next)
541*e4b17023SJohn Marino 	    ;
542*e4b17023SJohn Marino 	  if (last != NULL)
543*e4b17023SJohn Marino 	    {
544*e4b17023SJohn Marino 	      if (prev == NULL)
545*e4b17023SJohn Marino 		*roots = node->first;
546*e4b17023SJohn Marino 	      else
547*e4b17023SJohn Marino 		prev->next = node->first;
548*e4b17023SJohn Marino 	      if (next != NULL)
549*e4b17023SJohn Marino 		next->prev = last;
550*e4b17023SJohn Marino 	      last->next = next;
551*e4b17023SJohn Marino 	      next = node->first;
552*e4b17023SJohn Marino 	    }
553*e4b17023SJohn Marino 	  else
554*e4b17023SJohn Marino 	    {
555*e4b17023SJohn Marino 	      if (prev == NULL)
556*e4b17023SJohn Marino 		*roots = next;
557*e4b17023SJohn Marino 	      else
558*e4b17023SJohn Marino 		prev->next = next;
559*e4b17023SJohn Marino 	      if (next != NULL)
560*e4b17023SJohn Marino 		next->prev = prev;
561*e4b17023SJohn Marino 	    }
562*e4b17023SJohn Marino 	  ira_free (node);
563*e4b17023SJohn Marino 	}
564*e4b17023SJohn Marino     }
565*e4b17023SJohn Marino }
566*e4b17023SJohn Marino 
567*e4b17023SJohn Marino /* Set up fields preorder_num starting with START_NUM in all allocno
568*e4b17023SJohn Marino    hard registers nodes in forest given by FIRST.  Return biggest set
569*e4b17023SJohn Marino    PREORDER_NUM increased by 1.  */
570*e4b17023SJohn Marino static int
enumerate_allocno_hard_regs_nodes(allocno_hard_regs_node_t first,allocno_hard_regs_node_t parent,int start_num)571*e4b17023SJohn Marino enumerate_allocno_hard_regs_nodes (allocno_hard_regs_node_t first,
572*e4b17023SJohn Marino 				   allocno_hard_regs_node_t parent,
573*e4b17023SJohn Marino 				   int start_num)
574*e4b17023SJohn Marino {
575*e4b17023SJohn Marino   allocno_hard_regs_node_t node;
576*e4b17023SJohn Marino 
577*e4b17023SJohn Marino   for (node = first; node != NULL; node = node->next)
578*e4b17023SJohn Marino     {
579*e4b17023SJohn Marino       node->preorder_num = start_num++;
580*e4b17023SJohn Marino       node->parent = parent;
581*e4b17023SJohn Marino       start_num = enumerate_allocno_hard_regs_nodes (node->first, node,
582*e4b17023SJohn Marino 						     start_num);
583*e4b17023SJohn Marino     }
584*e4b17023SJohn Marino   return start_num;
585*e4b17023SJohn Marino }
586*e4b17023SJohn Marino 
587*e4b17023SJohn Marino /* Number of allocno hard registers nodes in the forest.  */
588*e4b17023SJohn Marino static int allocno_hard_regs_nodes_num;
589*e4b17023SJohn Marino 
590*e4b17023SJohn Marino /* Table preorder number of allocno hard registers node in the forest
591*e4b17023SJohn Marino    -> the allocno hard registers node.  */
592*e4b17023SJohn Marino static allocno_hard_regs_node_t *allocno_hard_regs_nodes;
593*e4b17023SJohn Marino 
594*e4b17023SJohn Marino /* See below.  */
595*e4b17023SJohn Marino typedef struct allocno_hard_regs_subnode *allocno_hard_regs_subnode_t;
596*e4b17023SJohn Marino 
597*e4b17023SJohn Marino /* The structure is used to describes all subnodes (not only immediate
598*e4b17023SJohn Marino    ones) in the mentioned above tree for given allocno hard register
599*e4b17023SJohn Marino    node.  The usage of such data accelerates calculation of
600*e4b17023SJohn Marino    colorability of given allocno.  */
601*e4b17023SJohn Marino struct allocno_hard_regs_subnode
602*e4b17023SJohn Marino {
603*e4b17023SJohn Marino   /* The conflict size of conflicting allocnos whose hard register
604*e4b17023SJohn Marino      sets are equal sets (plus supersets if given node is given
605*e4b17023SJohn Marino      allocno hard registers node) of one in the given node.  */
606*e4b17023SJohn Marino   int left_conflict_size;
607*e4b17023SJohn Marino   /* The summary conflict size of conflicting allocnos whose hard
608*e4b17023SJohn Marino      register sets are strict subsets of one in the given node.
609*e4b17023SJohn Marino      Overall conflict size is
610*e4b17023SJohn Marino      left_conflict_subnodes_size
611*e4b17023SJohn Marino        + MIN (max_node_impact - left_conflict_subnodes_size,
612*e4b17023SJohn Marino               left_conflict_size)
613*e4b17023SJohn Marino   */
614*e4b17023SJohn Marino   short left_conflict_subnodes_size;
615*e4b17023SJohn Marino   short max_node_impact;
616*e4b17023SJohn Marino };
617*e4b17023SJohn Marino 
618*e4b17023SJohn Marino /* Container for hard regs subnodes of all allocnos.  */
619*e4b17023SJohn Marino static allocno_hard_regs_subnode_t allocno_hard_regs_subnodes;
620*e4b17023SJohn Marino 
621*e4b17023SJohn Marino /* Table (preorder number of allocno hard registers node in the
622*e4b17023SJohn Marino    forest, preorder number of allocno hard registers subnode) -> index
623*e4b17023SJohn Marino    of the subnode relative to the node.  -1 if it is not a
624*e4b17023SJohn Marino    subnode.  */
625*e4b17023SJohn Marino static int *allocno_hard_regs_subnode_index;
626*e4b17023SJohn Marino 
627*e4b17023SJohn Marino /* Setup arrays ALLOCNO_HARD_REGS_NODES and
628*e4b17023SJohn Marino    ALLOCNO_HARD_REGS_SUBNODE_INDEX.  */
629*e4b17023SJohn Marino static void
setup_allocno_hard_regs_subnode_index(allocno_hard_regs_node_t first)630*e4b17023SJohn Marino setup_allocno_hard_regs_subnode_index (allocno_hard_regs_node_t first)
631*e4b17023SJohn Marino {
632*e4b17023SJohn Marino   allocno_hard_regs_node_t node, parent;
633*e4b17023SJohn Marino   int index;
634*e4b17023SJohn Marino 
635*e4b17023SJohn Marino   for (node = first; node != NULL; node = node->next)
636*e4b17023SJohn Marino     {
637*e4b17023SJohn Marino       allocno_hard_regs_nodes[node->preorder_num] = node;
638*e4b17023SJohn Marino       for (parent = node; parent != NULL; parent = parent->parent)
639*e4b17023SJohn Marino 	{
640*e4b17023SJohn Marino 	  index = parent->preorder_num * allocno_hard_regs_nodes_num;
641*e4b17023SJohn Marino 	  allocno_hard_regs_subnode_index[index + node->preorder_num]
642*e4b17023SJohn Marino 	    = node->preorder_num - parent->preorder_num;
643*e4b17023SJohn Marino 	}
644*e4b17023SJohn Marino       setup_allocno_hard_regs_subnode_index (node->first);
645*e4b17023SJohn Marino     }
646*e4b17023SJohn Marino }
647*e4b17023SJohn Marino 
648*e4b17023SJohn Marino /* Count all allocno hard registers nodes in tree ROOT.  */
649*e4b17023SJohn Marino static int
get_allocno_hard_regs_subnodes_num(allocno_hard_regs_node_t root)650*e4b17023SJohn Marino get_allocno_hard_regs_subnodes_num (allocno_hard_regs_node_t root)
651*e4b17023SJohn Marino {
652*e4b17023SJohn Marino   int len = 1;
653*e4b17023SJohn Marino 
654*e4b17023SJohn Marino   for (root = root->first; root != NULL; root = root->next)
655*e4b17023SJohn Marino     len += get_allocno_hard_regs_subnodes_num (root);
656*e4b17023SJohn Marino   return len;
657*e4b17023SJohn Marino }
658*e4b17023SJohn Marino 
659*e4b17023SJohn Marino /* Build the forest of allocno hard registers nodes and assign each
660*e4b17023SJohn Marino    allocno a node from the forest.  */
661*e4b17023SJohn Marino static void
form_allocno_hard_regs_nodes_forest(void)662*e4b17023SJohn Marino form_allocno_hard_regs_nodes_forest (void)
663*e4b17023SJohn Marino {
664*e4b17023SJohn Marino   unsigned int i, j, size, len;
665*e4b17023SJohn Marino   int start;
666*e4b17023SJohn Marino   ira_allocno_t a;
667*e4b17023SJohn Marino   allocno_hard_regs_t hv;
668*e4b17023SJohn Marino   bitmap_iterator bi;
669*e4b17023SJohn Marino   HARD_REG_SET temp;
670*e4b17023SJohn Marino   allocno_hard_regs_node_t node, allocno_hard_regs_node;
671*e4b17023SJohn Marino   allocno_color_data_t allocno_data;
672*e4b17023SJohn Marino 
673*e4b17023SJohn Marino   node_check_tick = 0;
674*e4b17023SJohn Marino   init_allocno_hard_regs ();
675*e4b17023SJohn Marino   hard_regs_roots = NULL;
676*e4b17023SJohn Marino   hard_regs_node_vec = VEC_alloc (allocno_hard_regs_node_t, heap, 100);
677*e4b17023SJohn Marino   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
678*e4b17023SJohn Marino     if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, i))
679*e4b17023SJohn Marino       {
680*e4b17023SJohn Marino 	CLEAR_HARD_REG_SET (temp);
681*e4b17023SJohn Marino 	SET_HARD_REG_BIT (temp, i);
682*e4b17023SJohn Marino 	hv = add_allocno_hard_regs (temp, 0);
683*e4b17023SJohn Marino 	node = create_new_allocno_hard_regs_node (hv);
684*e4b17023SJohn Marino 	add_new_allocno_hard_regs_node_to_forest (&hard_regs_roots, node);
685*e4b17023SJohn Marino       }
686*e4b17023SJohn Marino   start = VEC_length (allocno_hard_regs_t, allocno_hard_regs_vec);
687*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
688*e4b17023SJohn Marino     {
689*e4b17023SJohn Marino       a = ira_allocnos[i];
690*e4b17023SJohn Marino       allocno_data = ALLOCNO_COLOR_DATA (a);
691*e4b17023SJohn Marino 
692*e4b17023SJohn Marino       if (hard_reg_set_empty_p (allocno_data->profitable_hard_regs))
693*e4b17023SJohn Marino 	continue;
694*e4b17023SJohn Marino       hv = (add_allocno_hard_regs
695*e4b17023SJohn Marino 	    (allocno_data->profitable_hard_regs,
696*e4b17023SJohn Marino 	     ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a)));
697*e4b17023SJohn Marino     }
698*e4b17023SJohn Marino   SET_HARD_REG_SET (temp);
699*e4b17023SJohn Marino   AND_COMPL_HARD_REG_SET (temp, ira_no_alloc_regs);
700*e4b17023SJohn Marino   add_allocno_hard_regs (temp, 0);
701*e4b17023SJohn Marino   qsort (VEC_address (allocno_hard_regs_t, allocno_hard_regs_vec) + start,
702*e4b17023SJohn Marino 	 VEC_length (allocno_hard_regs_t, allocno_hard_regs_vec) - start,
703*e4b17023SJohn Marino 	 sizeof (allocno_hard_regs_t), allocno_hard_regs_compare);
704*e4b17023SJohn Marino   for (i = start;
705*e4b17023SJohn Marino        VEC_iterate (allocno_hard_regs_t, allocno_hard_regs_vec, i, hv);
706*e4b17023SJohn Marino        i++)
707*e4b17023SJohn Marino     {
708*e4b17023SJohn Marino       add_allocno_hard_regs_to_forest (&hard_regs_roots, hv);
709*e4b17023SJohn Marino       ira_assert (VEC_length (allocno_hard_regs_node_t,
710*e4b17023SJohn Marino 			      hard_regs_node_vec) == 0);
711*e4b17023SJohn Marino     }
712*e4b17023SJohn Marino   /* We need to set up parent fields for right work of
713*e4b17023SJohn Marino      first_common_ancestor_node. */
714*e4b17023SJohn Marino   setup_allocno_hard_regs_nodes_parent (hard_regs_roots, NULL);
715*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
716*e4b17023SJohn Marino     {
717*e4b17023SJohn Marino       a = ira_allocnos[i];
718*e4b17023SJohn Marino       allocno_data = ALLOCNO_COLOR_DATA (a);
719*e4b17023SJohn Marino       if (hard_reg_set_empty_p (allocno_data->profitable_hard_regs))
720*e4b17023SJohn Marino 	continue;
721*e4b17023SJohn Marino       VEC_truncate (allocno_hard_regs_node_t, hard_regs_node_vec, 0);
722*e4b17023SJohn Marino       collect_allocno_hard_regs_cover (hard_regs_roots,
723*e4b17023SJohn Marino 				       allocno_data->profitable_hard_regs);
724*e4b17023SJohn Marino       allocno_hard_regs_node = NULL;
725*e4b17023SJohn Marino       for (j = 0;
726*e4b17023SJohn Marino 	   VEC_iterate (allocno_hard_regs_node_t, hard_regs_node_vec,
727*e4b17023SJohn Marino 			j, node);
728*e4b17023SJohn Marino 	   j++)
729*e4b17023SJohn Marino 	allocno_hard_regs_node
730*e4b17023SJohn Marino 	  = (j == 0
731*e4b17023SJohn Marino 	     ? node
732*e4b17023SJohn Marino 	     : first_common_ancestor_node (node, allocno_hard_regs_node));
733*e4b17023SJohn Marino       /* That is a temporary storage.  */
734*e4b17023SJohn Marino       allocno_hard_regs_node->used_p = true;
735*e4b17023SJohn Marino       allocno_data->hard_regs_node = allocno_hard_regs_node;
736*e4b17023SJohn Marino     }
737*e4b17023SJohn Marino   ira_assert (hard_regs_roots->next == NULL);
738*e4b17023SJohn Marino   hard_regs_roots->used_p = true;
739*e4b17023SJohn Marino   remove_unused_allocno_hard_regs_nodes (&hard_regs_roots);
740*e4b17023SJohn Marino   allocno_hard_regs_nodes_num
741*e4b17023SJohn Marino     = enumerate_allocno_hard_regs_nodes (hard_regs_roots, NULL, 0);
742*e4b17023SJohn Marino   allocno_hard_regs_nodes
743*e4b17023SJohn Marino     = ((allocno_hard_regs_node_t *)
744*e4b17023SJohn Marino        ira_allocate (allocno_hard_regs_nodes_num
745*e4b17023SJohn Marino 		     * sizeof (allocno_hard_regs_node_t)));
746*e4b17023SJohn Marino   size = allocno_hard_regs_nodes_num * allocno_hard_regs_nodes_num;
747*e4b17023SJohn Marino   allocno_hard_regs_subnode_index
748*e4b17023SJohn Marino     = (int *) ira_allocate (size * sizeof (int));
749*e4b17023SJohn Marino   for (i = 0; i < size; i++)
750*e4b17023SJohn Marino     allocno_hard_regs_subnode_index[i] = -1;
751*e4b17023SJohn Marino   setup_allocno_hard_regs_subnode_index (hard_regs_roots);
752*e4b17023SJohn Marino   start = 0;
753*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
754*e4b17023SJohn Marino     {
755*e4b17023SJohn Marino       a = ira_allocnos[i];
756*e4b17023SJohn Marino       allocno_data = ALLOCNO_COLOR_DATA (a);
757*e4b17023SJohn Marino       if (hard_reg_set_empty_p (allocno_data->profitable_hard_regs))
758*e4b17023SJohn Marino 	continue;
759*e4b17023SJohn Marino       len = get_allocno_hard_regs_subnodes_num (allocno_data->hard_regs_node);
760*e4b17023SJohn Marino       allocno_data->hard_regs_subnodes_start = start;
761*e4b17023SJohn Marino       allocno_data->hard_regs_subnodes_num = len;
762*e4b17023SJohn Marino       start += len;
763*e4b17023SJohn Marino     }
764*e4b17023SJohn Marino   allocno_hard_regs_subnodes
765*e4b17023SJohn Marino     = ((allocno_hard_regs_subnode_t)
766*e4b17023SJohn Marino        ira_allocate (sizeof (struct allocno_hard_regs_subnode) * start));
767*e4b17023SJohn Marino   VEC_free (allocno_hard_regs_node_t, heap, hard_regs_node_vec);
768*e4b17023SJohn Marino }
769*e4b17023SJohn Marino 
770*e4b17023SJohn Marino /* Free tree of allocno hard registers nodes given by its ROOT.  */
771*e4b17023SJohn Marino static void
finish_allocno_hard_regs_nodes_tree(allocno_hard_regs_node_t root)772*e4b17023SJohn Marino finish_allocno_hard_regs_nodes_tree (allocno_hard_regs_node_t root)
773*e4b17023SJohn Marino {
774*e4b17023SJohn Marino   allocno_hard_regs_node_t child, next;
775*e4b17023SJohn Marino 
776*e4b17023SJohn Marino   for (child = root->first; child != NULL; child = next)
777*e4b17023SJohn Marino     {
778*e4b17023SJohn Marino       next = child->next;
779*e4b17023SJohn Marino       finish_allocno_hard_regs_nodes_tree (child);
780*e4b17023SJohn Marino     }
781*e4b17023SJohn Marino   ira_free (root);
782*e4b17023SJohn Marino }
783*e4b17023SJohn Marino 
784*e4b17023SJohn Marino /* Finish work with the forest of allocno hard registers nodes.  */
785*e4b17023SJohn Marino static void
finish_allocno_hard_regs_nodes_forest(void)786*e4b17023SJohn Marino finish_allocno_hard_regs_nodes_forest (void)
787*e4b17023SJohn Marino {
788*e4b17023SJohn Marino   allocno_hard_regs_node_t node, next;
789*e4b17023SJohn Marino 
790*e4b17023SJohn Marino   ira_free (allocno_hard_regs_subnodes);
791*e4b17023SJohn Marino   for (node = hard_regs_roots; node != NULL; node = next)
792*e4b17023SJohn Marino     {
793*e4b17023SJohn Marino       next = node->next;
794*e4b17023SJohn Marino       finish_allocno_hard_regs_nodes_tree (node);
795*e4b17023SJohn Marino     }
796*e4b17023SJohn Marino   ira_free (allocno_hard_regs_nodes);
797*e4b17023SJohn Marino   ira_free (allocno_hard_regs_subnode_index);
798*e4b17023SJohn Marino   finish_allocno_hard_regs ();
799*e4b17023SJohn Marino }
800*e4b17023SJohn Marino 
801*e4b17023SJohn Marino /* Set up left conflict sizes and left conflict subnodes sizes of hard
802*e4b17023SJohn Marino    registers subnodes of allocno A.  Return TRUE if allocno A is
803*e4b17023SJohn Marino    trivially colorable.  */
804*e4b17023SJohn Marino static bool
setup_left_conflict_sizes_p(ira_allocno_t a)805*e4b17023SJohn Marino setup_left_conflict_sizes_p (ira_allocno_t a)
806*e4b17023SJohn Marino {
807*e4b17023SJohn Marino   int i, k, nobj, start;
808*e4b17023SJohn Marino   int conflict_size, left_conflict_subnodes_size, node_preorder_num;
809*e4b17023SJohn Marino   allocno_color_data_t data;
810*e4b17023SJohn Marino   HARD_REG_SET profitable_hard_regs;
811*e4b17023SJohn Marino   allocno_hard_regs_subnode_t subnodes;
812*e4b17023SJohn Marino   allocno_hard_regs_node_t node;
813*e4b17023SJohn Marino   HARD_REG_SET node_set;
814*e4b17023SJohn Marino 
815*e4b17023SJohn Marino   nobj = ALLOCNO_NUM_OBJECTS (a);
816*e4b17023SJohn Marino   conflict_size = 0;
817*e4b17023SJohn Marino   data = ALLOCNO_COLOR_DATA (a);
818*e4b17023SJohn Marino   subnodes = allocno_hard_regs_subnodes + data->hard_regs_subnodes_start;
819*e4b17023SJohn Marino   COPY_HARD_REG_SET (profitable_hard_regs, data->profitable_hard_regs);
820*e4b17023SJohn Marino   node = data->hard_regs_node;
821*e4b17023SJohn Marino   node_preorder_num = node->preorder_num;
822*e4b17023SJohn Marino   COPY_HARD_REG_SET (node_set, node->hard_regs->set);
823*e4b17023SJohn Marino   node_check_tick++;
824*e4b17023SJohn Marino   for (k = 0; k < nobj; k++)
825*e4b17023SJohn Marino     {
826*e4b17023SJohn Marino       ira_object_t obj = ALLOCNO_OBJECT (a, k);
827*e4b17023SJohn Marino       ira_object_t conflict_obj;
828*e4b17023SJohn Marino       ira_object_conflict_iterator oci;
829*e4b17023SJohn Marino 
830*e4b17023SJohn Marino       FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
831*e4b17023SJohn Marino 	{
832*e4b17023SJohn Marino 	  int size;
833*e4b17023SJohn Marino  	  ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
834*e4b17023SJohn Marino 	  allocno_hard_regs_node_t conflict_node, temp_node;
835*e4b17023SJohn Marino 	  HARD_REG_SET conflict_node_set;
836*e4b17023SJohn Marino 	  allocno_color_data_t conflict_data;
837*e4b17023SJohn Marino 
838*e4b17023SJohn Marino 	  conflict_data = ALLOCNO_COLOR_DATA (conflict_a);
839*e4b17023SJohn Marino 	  if (! ALLOCNO_COLOR_DATA (conflict_a)->in_graph_p
840*e4b17023SJohn Marino 	      || ! hard_reg_set_intersect_p (profitable_hard_regs,
841*e4b17023SJohn Marino 					     conflict_data
842*e4b17023SJohn Marino 					     ->profitable_hard_regs))
843*e4b17023SJohn Marino 	    continue;
844*e4b17023SJohn Marino 	  conflict_node = conflict_data->hard_regs_node;
845*e4b17023SJohn Marino 	  COPY_HARD_REG_SET (conflict_node_set, conflict_node->hard_regs->set);
846*e4b17023SJohn Marino 	  if (hard_reg_set_subset_p (node_set, conflict_node_set))
847*e4b17023SJohn Marino 	    temp_node = node;
848*e4b17023SJohn Marino 	  else
849*e4b17023SJohn Marino 	    {
850*e4b17023SJohn Marino 	      ira_assert (hard_reg_set_subset_p (conflict_node_set, node_set));
851*e4b17023SJohn Marino 	      temp_node = conflict_node;
852*e4b17023SJohn Marino 	    }
853*e4b17023SJohn Marino 	  if (temp_node->check != node_check_tick)
854*e4b17023SJohn Marino 	    {
855*e4b17023SJohn Marino 	      temp_node->check = node_check_tick;
856*e4b17023SJohn Marino 	      temp_node->conflict_size = 0;
857*e4b17023SJohn Marino 	    }
858*e4b17023SJohn Marino 	  size = (ira_reg_class_max_nregs
859*e4b17023SJohn Marino 		  [ALLOCNO_CLASS (conflict_a)][ALLOCNO_MODE (conflict_a)]);
860*e4b17023SJohn Marino 	  if (ALLOCNO_NUM_OBJECTS (conflict_a) > 1)
861*e4b17023SJohn Marino 	    /* We will deal with the subwords individually.  */
862*e4b17023SJohn Marino 	    size = 1;
863*e4b17023SJohn Marino 	  temp_node->conflict_size += size;
864*e4b17023SJohn Marino 	}
865*e4b17023SJohn Marino     }
866*e4b17023SJohn Marino   for (i = 0; i < data->hard_regs_subnodes_num; i++)
867*e4b17023SJohn Marino     {
868*e4b17023SJohn Marino       allocno_hard_regs_node_t temp_node;
869*e4b17023SJohn Marino 
870*e4b17023SJohn Marino       temp_node = allocno_hard_regs_nodes[i + node_preorder_num];
871*e4b17023SJohn Marino       ira_assert (temp_node->preorder_num == i + node_preorder_num);
872*e4b17023SJohn Marino       subnodes[i].left_conflict_size = (temp_node->check != node_check_tick
873*e4b17023SJohn Marino 					? 0 : temp_node->conflict_size);
874*e4b17023SJohn Marino       if (hard_reg_set_subset_p (temp_node->hard_regs->set,
875*e4b17023SJohn Marino 				 profitable_hard_regs))
876*e4b17023SJohn Marino 	subnodes[i].max_node_impact = temp_node->hard_regs_num;
877*e4b17023SJohn Marino       else
878*e4b17023SJohn Marino 	{
879*e4b17023SJohn Marino 	  HARD_REG_SET temp_set;
880*e4b17023SJohn Marino 	  int j, n, hard_regno;
881*e4b17023SJohn Marino 	  enum reg_class aclass;
882*e4b17023SJohn Marino 
883*e4b17023SJohn Marino 	  COPY_HARD_REG_SET (temp_set, temp_node->hard_regs->set);
884*e4b17023SJohn Marino 	  AND_HARD_REG_SET (temp_set, profitable_hard_regs);
885*e4b17023SJohn Marino 	  aclass = ALLOCNO_CLASS (a);
886*e4b17023SJohn Marino 	  for (n = 0, j = ira_class_hard_regs_num[aclass] - 1; j >= 0; j--)
887*e4b17023SJohn Marino 	    {
888*e4b17023SJohn Marino 	      hard_regno = ira_class_hard_regs[aclass][j];
889*e4b17023SJohn Marino 	      if (TEST_HARD_REG_BIT (temp_set, hard_regno))
890*e4b17023SJohn Marino 		n++;
891*e4b17023SJohn Marino 	    }
892*e4b17023SJohn Marino 	  subnodes[i].max_node_impact = n;
893*e4b17023SJohn Marino 	}
894*e4b17023SJohn Marino       subnodes[i].left_conflict_subnodes_size = 0;
895*e4b17023SJohn Marino     }
896*e4b17023SJohn Marino   start = node_preorder_num * allocno_hard_regs_nodes_num;
897*e4b17023SJohn Marino   for (i = data->hard_regs_subnodes_num - 1; i >= 0; i--)
898*e4b17023SJohn Marino     {
899*e4b17023SJohn Marino       int size, parent_i;
900*e4b17023SJohn Marino       allocno_hard_regs_node_t parent;
901*e4b17023SJohn Marino 
902*e4b17023SJohn Marino       size = (subnodes[i].left_conflict_subnodes_size
903*e4b17023SJohn Marino 	      + MIN (subnodes[i].max_node_impact
904*e4b17023SJohn Marino 		     - subnodes[i].left_conflict_subnodes_size,
905*e4b17023SJohn Marino 		     subnodes[i].left_conflict_size));
906*e4b17023SJohn Marino       parent = allocno_hard_regs_nodes[i + node_preorder_num]->parent;
907*e4b17023SJohn Marino       if (parent == NULL)
908*e4b17023SJohn Marino 	continue;
909*e4b17023SJohn Marino       parent_i
910*e4b17023SJohn Marino 	= allocno_hard_regs_subnode_index[start + parent->preorder_num];
911*e4b17023SJohn Marino       if (parent_i < 0)
912*e4b17023SJohn Marino 	continue;
913*e4b17023SJohn Marino       subnodes[parent_i].left_conflict_subnodes_size += size;
914*e4b17023SJohn Marino     }
915*e4b17023SJohn Marino   left_conflict_subnodes_size = subnodes[0].left_conflict_subnodes_size;
916*e4b17023SJohn Marino   conflict_size
917*e4b17023SJohn Marino     += (left_conflict_subnodes_size
918*e4b17023SJohn Marino 	+ MIN (subnodes[0].max_node_impact - left_conflict_subnodes_size,
919*e4b17023SJohn Marino 	       subnodes[0].left_conflict_size));
920*e4b17023SJohn Marino   conflict_size += ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)];
921*e4b17023SJohn Marino   data->colorable_p = conflict_size <= data->available_regs_num;
922*e4b17023SJohn Marino   return data->colorable_p;
923*e4b17023SJohn Marino }
924*e4b17023SJohn Marino 
925*e4b17023SJohn Marino /* Update left conflict sizes of hard registers subnodes of allocno A
926*e4b17023SJohn Marino    after removing allocno REMOVED_A with SIZE from the conflict graph.
927*e4b17023SJohn Marino    Return TRUE if A is trivially colorable.  */
928*e4b17023SJohn Marino static bool
update_left_conflict_sizes_p(ira_allocno_t a,ira_allocno_t removed_a,int size)929*e4b17023SJohn Marino update_left_conflict_sizes_p (ira_allocno_t a,
930*e4b17023SJohn Marino 			      ira_allocno_t removed_a, int size)
931*e4b17023SJohn Marino {
932*e4b17023SJohn Marino   int i, conflict_size, before_conflict_size, diff, start;
933*e4b17023SJohn Marino   int node_preorder_num, parent_i;
934*e4b17023SJohn Marino   allocno_hard_regs_node_t node, removed_node, parent;
935*e4b17023SJohn Marino   allocno_hard_regs_subnode_t subnodes;
936*e4b17023SJohn Marino   allocno_color_data_t data = ALLOCNO_COLOR_DATA (a);
937*e4b17023SJohn Marino 
938*e4b17023SJohn Marino   ira_assert (! data->colorable_p);
939*e4b17023SJohn Marino   node = data->hard_regs_node;
940*e4b17023SJohn Marino   node_preorder_num = node->preorder_num;
941*e4b17023SJohn Marino   removed_node = ALLOCNO_COLOR_DATA (removed_a)->hard_regs_node;
942*e4b17023SJohn Marino   ira_assert (hard_reg_set_subset_p (removed_node->hard_regs->set,
943*e4b17023SJohn Marino 			       node->hard_regs->set)
944*e4b17023SJohn Marino 	      || hard_reg_set_subset_p (node->hard_regs->set,
945*e4b17023SJohn Marino 					removed_node->hard_regs->set));
946*e4b17023SJohn Marino   start = node_preorder_num * allocno_hard_regs_nodes_num;
947*e4b17023SJohn Marino   i = allocno_hard_regs_subnode_index[start + removed_node->preorder_num];
948*e4b17023SJohn Marino   if (i < 0)
949*e4b17023SJohn Marino     i = 0;
950*e4b17023SJohn Marino   subnodes = allocno_hard_regs_subnodes + data->hard_regs_subnodes_start;
951*e4b17023SJohn Marino   before_conflict_size
952*e4b17023SJohn Marino     = (subnodes[i].left_conflict_subnodes_size
953*e4b17023SJohn Marino        + MIN (subnodes[i].max_node_impact
954*e4b17023SJohn Marino 	      - subnodes[i].left_conflict_subnodes_size,
955*e4b17023SJohn Marino 	      subnodes[i].left_conflict_size));
956*e4b17023SJohn Marino   subnodes[i].left_conflict_size -= size;
957*e4b17023SJohn Marino   for (;;)
958*e4b17023SJohn Marino     {
959*e4b17023SJohn Marino       conflict_size
960*e4b17023SJohn Marino 	= (subnodes[i].left_conflict_subnodes_size
961*e4b17023SJohn Marino 	   + MIN (subnodes[i].max_node_impact
962*e4b17023SJohn Marino 		  - subnodes[i].left_conflict_subnodes_size,
963*e4b17023SJohn Marino 		  subnodes[i].left_conflict_size));
964*e4b17023SJohn Marino       if ((diff = before_conflict_size - conflict_size) == 0)
965*e4b17023SJohn Marino 	break;
966*e4b17023SJohn Marino       ira_assert (conflict_size < before_conflict_size);
967*e4b17023SJohn Marino       parent = allocno_hard_regs_nodes[i + node_preorder_num]->parent;
968*e4b17023SJohn Marino       if (parent == NULL)
969*e4b17023SJohn Marino 	break;
970*e4b17023SJohn Marino       parent_i
971*e4b17023SJohn Marino 	= allocno_hard_regs_subnode_index[start + parent->preorder_num];
972*e4b17023SJohn Marino       if (parent_i < 0)
973*e4b17023SJohn Marino 	break;
974*e4b17023SJohn Marino       i = parent_i;
975*e4b17023SJohn Marino       before_conflict_size
976*e4b17023SJohn Marino 	= (subnodes[i].left_conflict_subnodes_size
977*e4b17023SJohn Marino 	   + MIN (subnodes[i].max_node_impact
978*e4b17023SJohn Marino 		  - subnodes[i].left_conflict_subnodes_size,
979*e4b17023SJohn Marino 		  subnodes[i].left_conflict_size));
980*e4b17023SJohn Marino       subnodes[i].left_conflict_subnodes_size -= diff;
981*e4b17023SJohn Marino     }
982*e4b17023SJohn Marino   if (i != 0
983*e4b17023SJohn Marino       || (conflict_size
984*e4b17023SJohn Marino 	  + ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]
985*e4b17023SJohn Marino 	  > data->available_regs_num))
986*e4b17023SJohn Marino     return false;
987*e4b17023SJohn Marino   data->colorable_p = true;
988*e4b17023SJohn Marino   return true;
989*e4b17023SJohn Marino }
990*e4b17023SJohn Marino 
991*e4b17023SJohn Marino /* Return true if allocno A has empty profitable hard regs.  */
992*e4b17023SJohn Marino static bool
empty_profitable_hard_regs(ira_allocno_t a)993*e4b17023SJohn Marino empty_profitable_hard_regs (ira_allocno_t a)
994*e4b17023SJohn Marino {
995*e4b17023SJohn Marino   allocno_color_data_t data = ALLOCNO_COLOR_DATA (a);
996*e4b17023SJohn Marino 
997*e4b17023SJohn Marino   return hard_reg_set_empty_p (data->profitable_hard_regs);
998*e4b17023SJohn Marino }
999*e4b17023SJohn Marino 
1000*e4b17023SJohn Marino /* Set up profitable hard registers for each allocno being
1001*e4b17023SJohn Marino    colored.  */
1002*e4b17023SJohn Marino static void
setup_profitable_hard_regs(void)1003*e4b17023SJohn Marino setup_profitable_hard_regs (void)
1004*e4b17023SJohn Marino {
1005*e4b17023SJohn Marino   unsigned int i;
1006*e4b17023SJohn Marino   int j, k, nobj, hard_regno, nregs, class_size;
1007*e4b17023SJohn Marino   ira_allocno_t a;
1008*e4b17023SJohn Marino   bitmap_iterator bi;
1009*e4b17023SJohn Marino   enum reg_class aclass;
1010*e4b17023SJohn Marino   enum machine_mode mode;
1011*e4b17023SJohn Marino   allocno_color_data_t data;
1012*e4b17023SJohn Marino 
1013*e4b17023SJohn Marino   /* Initial set up from allocno classes and explicitly conflicting
1014*e4b17023SJohn Marino      hard regs.  */
1015*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
1016*e4b17023SJohn Marino     {
1017*e4b17023SJohn Marino       a = ira_allocnos[i];
1018*e4b17023SJohn Marino       if ((aclass = ALLOCNO_CLASS (a)) == NO_REGS)
1019*e4b17023SJohn Marino 	continue;
1020*e4b17023SJohn Marino       data = ALLOCNO_COLOR_DATA (a);
1021*e4b17023SJohn Marino       if (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL
1022*e4b17023SJohn Marino 	  && ALLOCNO_CLASS_COST (a) > ALLOCNO_MEMORY_COST (a))
1023*e4b17023SJohn Marino 	CLEAR_HARD_REG_SET (data->profitable_hard_regs);
1024*e4b17023SJohn Marino       else
1025*e4b17023SJohn Marino 	{
1026*e4b17023SJohn Marino 	  COPY_HARD_REG_SET (data->profitable_hard_regs,
1027*e4b17023SJohn Marino 			     reg_class_contents[aclass]);
1028*e4b17023SJohn Marino 	  AND_COMPL_HARD_REG_SET (data->profitable_hard_regs,
1029*e4b17023SJohn Marino 				  ira_no_alloc_regs);
1030*e4b17023SJohn Marino 	  nobj = ALLOCNO_NUM_OBJECTS (a);
1031*e4b17023SJohn Marino 	  for (k = 0; k < nobj; k++)
1032*e4b17023SJohn Marino 	    {
1033*e4b17023SJohn Marino 	      ira_object_t obj = ALLOCNO_OBJECT (a, k);
1034*e4b17023SJohn Marino 
1035*e4b17023SJohn Marino 	      AND_COMPL_HARD_REG_SET (data->profitable_hard_regs,
1036*e4b17023SJohn Marino 				      OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
1037*e4b17023SJohn Marino 	    }
1038*e4b17023SJohn Marino 	}
1039*e4b17023SJohn Marino     }
1040*e4b17023SJohn Marino   /* Exclude hard regs already assigned for conflicting objects.  */
1041*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, i, bi)
1042*e4b17023SJohn Marino     {
1043*e4b17023SJohn Marino       a = ira_allocnos[i];
1044*e4b17023SJohn Marino       if ((aclass = ALLOCNO_CLASS (a)) == NO_REGS
1045*e4b17023SJohn Marino 	  || ! ALLOCNO_ASSIGNED_P (a)
1046*e4b17023SJohn Marino 	  || (hard_regno = ALLOCNO_HARD_REGNO (a)) < 0)
1047*e4b17023SJohn Marino 	continue;
1048*e4b17023SJohn Marino       mode = ALLOCNO_MODE (a);
1049*e4b17023SJohn Marino       nregs = hard_regno_nregs[hard_regno][mode];
1050*e4b17023SJohn Marino       nobj = ALLOCNO_NUM_OBJECTS (a);
1051*e4b17023SJohn Marino       for (k = 0; k < nobj; k++)
1052*e4b17023SJohn Marino 	{
1053*e4b17023SJohn Marino 	  ira_object_t obj = ALLOCNO_OBJECT (a, k);
1054*e4b17023SJohn Marino 	  ira_object_t conflict_obj;
1055*e4b17023SJohn Marino 	  ira_object_conflict_iterator oci;
1056*e4b17023SJohn Marino 
1057*e4b17023SJohn Marino 	  FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
1058*e4b17023SJohn Marino 	    {
1059*e4b17023SJohn Marino 	      ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
1060*e4b17023SJohn Marino 
1061*e4b17023SJohn Marino 	      /* We can process the conflict allocno repeatedly with
1062*e4b17023SJohn Marino 		 the same result.  */
1063*e4b17023SJohn Marino 	      if (nregs == nobj && nregs > 1)
1064*e4b17023SJohn Marino 		{
1065*e4b17023SJohn Marino 		  int num = OBJECT_SUBWORD (conflict_obj);
1066*e4b17023SJohn Marino 
1067*e4b17023SJohn Marino 		  if (REG_WORDS_BIG_ENDIAN)
1068*e4b17023SJohn Marino 		    CLEAR_HARD_REG_BIT
1069*e4b17023SJohn Marino 		      (ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs,
1070*e4b17023SJohn Marino 		       hard_regno + nobj - num - 1);
1071*e4b17023SJohn Marino 		  else
1072*e4b17023SJohn Marino 		    CLEAR_HARD_REG_BIT
1073*e4b17023SJohn Marino 		      (ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs,
1074*e4b17023SJohn Marino 		       hard_regno + num);
1075*e4b17023SJohn Marino 		}
1076*e4b17023SJohn Marino 	      else
1077*e4b17023SJohn Marino 		AND_COMPL_HARD_REG_SET
1078*e4b17023SJohn Marino 		  (ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs,
1079*e4b17023SJohn Marino 		   ira_reg_mode_hard_regset[hard_regno][mode]);
1080*e4b17023SJohn Marino 	    }
1081*e4b17023SJohn Marino 	}
1082*e4b17023SJohn Marino     }
1083*e4b17023SJohn Marino   /* Exclude too costly hard regs.  */
1084*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
1085*e4b17023SJohn Marino     {
1086*e4b17023SJohn Marino       int min_cost = INT_MAX;
1087*e4b17023SJohn Marino       int *costs;
1088*e4b17023SJohn Marino 
1089*e4b17023SJohn Marino       a = ira_allocnos[i];
1090*e4b17023SJohn Marino       if ((aclass = ALLOCNO_CLASS (a)) == NO_REGS
1091*e4b17023SJohn Marino 	  || empty_profitable_hard_regs (a))
1092*e4b17023SJohn Marino 	continue;
1093*e4b17023SJohn Marino       data = ALLOCNO_COLOR_DATA (a);
1094*e4b17023SJohn Marino       mode = ALLOCNO_MODE (a);
1095*e4b17023SJohn Marino       if ((costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a)) != NULL
1096*e4b17023SJohn Marino 	  || (costs = ALLOCNO_HARD_REG_COSTS (a)) != NULL)
1097*e4b17023SJohn Marino 	{
1098*e4b17023SJohn Marino 	  class_size = ira_class_hard_regs_num[aclass];
1099*e4b17023SJohn Marino 	  for (j = 0; j < class_size; j++)
1100*e4b17023SJohn Marino 	    {
1101*e4b17023SJohn Marino 	      hard_regno = ira_class_hard_regs[aclass][j];
1102*e4b17023SJohn Marino 	      if (! TEST_HARD_REG_BIT (data->profitable_hard_regs,
1103*e4b17023SJohn Marino 				       hard_regno))
1104*e4b17023SJohn Marino 		continue;
1105*e4b17023SJohn Marino 	      if (ALLOCNO_UPDATED_MEMORY_COST (a) < costs[j])
1106*e4b17023SJohn Marino 		CLEAR_HARD_REG_BIT (data->profitable_hard_regs,
1107*e4b17023SJohn Marino 				    hard_regno);
1108*e4b17023SJohn Marino 	      else if (min_cost > costs[j])
1109*e4b17023SJohn Marino 		min_cost = costs[j];
1110*e4b17023SJohn Marino 	    }
1111*e4b17023SJohn Marino 	}
1112*e4b17023SJohn Marino       else if (ALLOCNO_UPDATED_MEMORY_COST (a)
1113*e4b17023SJohn Marino 	       < ALLOCNO_UPDATED_CLASS_COST (a))
1114*e4b17023SJohn Marino 	CLEAR_HARD_REG_SET (data->profitable_hard_regs);
1115*e4b17023SJohn Marino       if (ALLOCNO_UPDATED_CLASS_COST (a) > min_cost)
1116*e4b17023SJohn Marino 	ALLOCNO_UPDATED_CLASS_COST (a) = min_cost;
1117*e4b17023SJohn Marino     }
1118*e4b17023SJohn Marino }
1119*e4b17023SJohn Marino 
1120*e4b17023SJohn Marino 
1121*e4b17023SJohn Marino 
1122*e4b17023SJohn Marino /* This page contains functions used to choose hard registers for
1123*e4b17023SJohn Marino    allocnos.  */
1124*e4b17023SJohn Marino 
1125*e4b17023SJohn Marino /* Array whose element value is TRUE if the corresponding hard
1126*e4b17023SJohn Marino    register was already allocated for an allocno.  */
1127*e4b17023SJohn Marino static bool allocated_hardreg_p[FIRST_PSEUDO_REGISTER];
1128*e4b17023SJohn Marino 
1129*e4b17023SJohn Marino /* Describes one element in a queue of allocnos whose costs need to be
1130*e4b17023SJohn Marino    updated.  Each allocno in the queue is known to have an allocno
1131*e4b17023SJohn Marino    class.  */
1132*e4b17023SJohn Marino struct update_cost_queue_elem
1133*e4b17023SJohn Marino {
1134*e4b17023SJohn Marino   /* This element is in the queue iff CHECK == update_cost_check.  */
1135*e4b17023SJohn Marino   int check;
1136*e4b17023SJohn Marino 
1137*e4b17023SJohn Marino   /* COST_HOP_DIVISOR**N, where N is the length of the shortest path
1138*e4b17023SJohn Marino      connecting this allocno to the one being allocated.  */
1139*e4b17023SJohn Marino   int divisor;
1140*e4b17023SJohn Marino 
1141*e4b17023SJohn Marino   /* The next allocno in the queue, or null if this is the last element.  */
1142*e4b17023SJohn Marino   ira_allocno_t next;
1143*e4b17023SJohn Marino };
1144*e4b17023SJohn Marino 
1145*e4b17023SJohn Marino /* The first element in a queue of allocnos whose copy costs need to be
1146*e4b17023SJohn Marino    updated.  Null if the queue is empty.  */
1147*e4b17023SJohn Marino static ira_allocno_t update_cost_queue;
1148*e4b17023SJohn Marino 
1149*e4b17023SJohn Marino /* The last element in the queue described by update_cost_queue.
1150*e4b17023SJohn Marino    Not valid if update_cost_queue is null.  */
1151*e4b17023SJohn Marino static struct update_cost_queue_elem *update_cost_queue_tail;
1152*e4b17023SJohn Marino 
1153*e4b17023SJohn Marino /* A pool of elements in the queue described by update_cost_queue.
1154*e4b17023SJohn Marino    Elements are indexed by ALLOCNO_NUM.  */
1155*e4b17023SJohn Marino static struct update_cost_queue_elem *update_cost_queue_elems;
1156*e4b17023SJohn Marino 
1157*e4b17023SJohn Marino /* The current value of update_copy_cost call count.  */
1158*e4b17023SJohn Marino static int update_cost_check;
1159*e4b17023SJohn Marino 
1160*e4b17023SJohn Marino /* Allocate and initialize data necessary for function
1161*e4b17023SJohn Marino    update_copy_costs.  */
1162*e4b17023SJohn Marino static void
initiate_cost_update(void)1163*e4b17023SJohn Marino initiate_cost_update (void)
1164*e4b17023SJohn Marino {
1165*e4b17023SJohn Marino   size_t size;
1166*e4b17023SJohn Marino 
1167*e4b17023SJohn Marino   size = ira_allocnos_num * sizeof (struct update_cost_queue_elem);
1168*e4b17023SJohn Marino   update_cost_queue_elems
1169*e4b17023SJohn Marino     = (struct update_cost_queue_elem *) ira_allocate (size);
1170*e4b17023SJohn Marino   memset (update_cost_queue_elems, 0, size);
1171*e4b17023SJohn Marino   update_cost_check = 0;
1172*e4b17023SJohn Marino }
1173*e4b17023SJohn Marino 
1174*e4b17023SJohn Marino /* Deallocate data used by function update_copy_costs.  */
1175*e4b17023SJohn Marino static void
finish_cost_update(void)1176*e4b17023SJohn Marino finish_cost_update (void)
1177*e4b17023SJohn Marino {
1178*e4b17023SJohn Marino   ira_free (update_cost_queue_elems);
1179*e4b17023SJohn Marino }
1180*e4b17023SJohn Marino 
1181*e4b17023SJohn Marino /* When we traverse allocnos to update hard register costs, the cost
1182*e4b17023SJohn Marino    divisor will be multiplied by the following macro value for each
1183*e4b17023SJohn Marino    hop from given allocno to directly connected allocnos.  */
1184*e4b17023SJohn Marino #define COST_HOP_DIVISOR 4
1185*e4b17023SJohn Marino 
1186*e4b17023SJohn Marino /* Start a new cost-updating pass.  */
1187*e4b17023SJohn Marino static void
start_update_cost(void)1188*e4b17023SJohn Marino start_update_cost (void)
1189*e4b17023SJohn Marino {
1190*e4b17023SJohn Marino   update_cost_check++;
1191*e4b17023SJohn Marino   update_cost_queue = NULL;
1192*e4b17023SJohn Marino }
1193*e4b17023SJohn Marino 
1194*e4b17023SJohn Marino /* Add (ALLOCNO, DIVISOR) to the end of update_cost_queue, unless
1195*e4b17023SJohn Marino    ALLOCNO is already in the queue, or has NO_REGS class.  */
1196*e4b17023SJohn Marino static inline void
queue_update_cost(ira_allocno_t allocno,int divisor)1197*e4b17023SJohn Marino queue_update_cost (ira_allocno_t allocno, int divisor)
1198*e4b17023SJohn Marino {
1199*e4b17023SJohn Marino   struct update_cost_queue_elem *elem;
1200*e4b17023SJohn Marino 
1201*e4b17023SJohn Marino   elem = &update_cost_queue_elems[ALLOCNO_NUM (allocno)];
1202*e4b17023SJohn Marino   if (elem->check != update_cost_check
1203*e4b17023SJohn Marino       && ALLOCNO_CLASS (allocno) != NO_REGS)
1204*e4b17023SJohn Marino     {
1205*e4b17023SJohn Marino       elem->check = update_cost_check;
1206*e4b17023SJohn Marino       elem->divisor = divisor;
1207*e4b17023SJohn Marino       elem->next = NULL;
1208*e4b17023SJohn Marino       if (update_cost_queue == NULL)
1209*e4b17023SJohn Marino 	update_cost_queue = allocno;
1210*e4b17023SJohn Marino       else
1211*e4b17023SJohn Marino 	update_cost_queue_tail->next = allocno;
1212*e4b17023SJohn Marino       update_cost_queue_tail = elem;
1213*e4b17023SJohn Marino     }
1214*e4b17023SJohn Marino }
1215*e4b17023SJohn Marino 
1216*e4b17023SJohn Marino /* Try to remove the first element from update_cost_queue.  Return false
1217*e4b17023SJohn Marino    if the queue was empty, otherwise make (*ALLOCNO, *DIVISOR) describe
1218*e4b17023SJohn Marino    the removed element.  */
1219*e4b17023SJohn Marino static inline bool
get_next_update_cost(ira_allocno_t * allocno,int * divisor)1220*e4b17023SJohn Marino get_next_update_cost (ira_allocno_t *allocno, int *divisor)
1221*e4b17023SJohn Marino {
1222*e4b17023SJohn Marino   struct update_cost_queue_elem *elem;
1223*e4b17023SJohn Marino 
1224*e4b17023SJohn Marino   if (update_cost_queue == NULL)
1225*e4b17023SJohn Marino     return false;
1226*e4b17023SJohn Marino 
1227*e4b17023SJohn Marino   *allocno = update_cost_queue;
1228*e4b17023SJohn Marino   elem = &update_cost_queue_elems[ALLOCNO_NUM (*allocno)];
1229*e4b17023SJohn Marino   *divisor = elem->divisor;
1230*e4b17023SJohn Marino   update_cost_queue = elem->next;
1231*e4b17023SJohn Marino   return true;
1232*e4b17023SJohn Marino }
1233*e4b17023SJohn Marino 
1234*e4b17023SJohn Marino /* Update the cost of allocnos to increase chances to remove some
1235*e4b17023SJohn Marino    copies as the result of subsequent assignment.  */
1236*e4b17023SJohn Marino static void
update_copy_costs(ira_allocno_t allocno,bool decr_p)1237*e4b17023SJohn Marino update_copy_costs (ira_allocno_t allocno, bool decr_p)
1238*e4b17023SJohn Marino {
1239*e4b17023SJohn Marino   int i, cost, update_cost, hard_regno, divisor;
1240*e4b17023SJohn Marino   enum machine_mode mode;
1241*e4b17023SJohn Marino   enum reg_class rclass, aclass;
1242*e4b17023SJohn Marino   ira_allocno_t another_allocno;
1243*e4b17023SJohn Marino   ira_copy_t cp, next_cp;
1244*e4b17023SJohn Marino 
1245*e4b17023SJohn Marino   hard_regno = ALLOCNO_HARD_REGNO (allocno);
1246*e4b17023SJohn Marino   ira_assert (hard_regno >= 0);
1247*e4b17023SJohn Marino 
1248*e4b17023SJohn Marino   aclass = ALLOCNO_CLASS (allocno);
1249*e4b17023SJohn Marino   if (aclass == NO_REGS)
1250*e4b17023SJohn Marino     return;
1251*e4b17023SJohn Marino   i = ira_class_hard_reg_index[aclass][hard_regno];
1252*e4b17023SJohn Marino   ira_assert (i >= 0);
1253*e4b17023SJohn Marino   rclass = REGNO_REG_CLASS (hard_regno);
1254*e4b17023SJohn Marino 
1255*e4b17023SJohn Marino   start_update_cost ();
1256*e4b17023SJohn Marino   divisor = 1;
1257*e4b17023SJohn Marino   do
1258*e4b17023SJohn Marino     {
1259*e4b17023SJohn Marino       mode = ALLOCNO_MODE (allocno);
1260*e4b17023SJohn Marino       ira_init_register_move_cost_if_necessary (mode);
1261*e4b17023SJohn Marino       for (cp = ALLOCNO_COPIES (allocno); cp != NULL; cp = next_cp)
1262*e4b17023SJohn Marino 	{
1263*e4b17023SJohn Marino 	  if (cp->first == allocno)
1264*e4b17023SJohn Marino 	    {
1265*e4b17023SJohn Marino 	      next_cp = cp->next_first_allocno_copy;
1266*e4b17023SJohn Marino 	      another_allocno = cp->second;
1267*e4b17023SJohn Marino 	    }
1268*e4b17023SJohn Marino 	  else if (cp->second == allocno)
1269*e4b17023SJohn Marino 	    {
1270*e4b17023SJohn Marino 	      next_cp = cp->next_second_allocno_copy;
1271*e4b17023SJohn Marino 	      another_allocno = cp->first;
1272*e4b17023SJohn Marino 	    }
1273*e4b17023SJohn Marino 	  else
1274*e4b17023SJohn Marino 	    gcc_unreachable ();
1275*e4b17023SJohn Marino 
1276*e4b17023SJohn Marino 	  aclass = ALLOCNO_CLASS (another_allocno);
1277*e4b17023SJohn Marino 	  if (! TEST_HARD_REG_BIT (reg_class_contents[aclass],
1278*e4b17023SJohn Marino 				   hard_regno)
1279*e4b17023SJohn Marino 	      || ALLOCNO_ASSIGNED_P (another_allocno))
1280*e4b17023SJohn Marino 	    continue;
1281*e4b17023SJohn Marino 
1282*e4b17023SJohn Marino 	  cost = (cp->second == allocno
1283*e4b17023SJohn Marino 		  ? ira_register_move_cost[mode][rclass][aclass]
1284*e4b17023SJohn Marino 		  : ira_register_move_cost[mode][aclass][rclass]);
1285*e4b17023SJohn Marino 	  if (decr_p)
1286*e4b17023SJohn Marino 	    cost = -cost;
1287*e4b17023SJohn Marino 
1288*e4b17023SJohn Marino 	  update_cost = cp->freq * cost / divisor;
1289*e4b17023SJohn Marino 	  if (update_cost == 0)
1290*e4b17023SJohn Marino 	    continue;
1291*e4b17023SJohn Marino 
1292*e4b17023SJohn Marino 	  ira_allocate_and_set_or_copy_costs
1293*e4b17023SJohn Marino 	    (&ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno), aclass,
1294*e4b17023SJohn Marino 	     ALLOCNO_UPDATED_CLASS_COST (another_allocno),
1295*e4b17023SJohn Marino 	     ALLOCNO_HARD_REG_COSTS (another_allocno));
1296*e4b17023SJohn Marino 	  ira_allocate_and_set_or_copy_costs
1297*e4b17023SJohn Marino 	    (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno),
1298*e4b17023SJohn Marino 	     aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno));
1299*e4b17023SJohn Marino 	  i = ira_class_hard_reg_index[aclass][hard_regno];
1300*e4b17023SJohn Marino 	  if (i < 0)
1301*e4b17023SJohn Marino 	    continue;
1302*e4b17023SJohn Marino 	  ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno)[i] += update_cost;
1303*e4b17023SJohn Marino 	  ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno)[i]
1304*e4b17023SJohn Marino 	    += update_cost;
1305*e4b17023SJohn Marino 
1306*e4b17023SJohn Marino 	  queue_update_cost (another_allocno, divisor * COST_HOP_DIVISOR);
1307*e4b17023SJohn Marino 	}
1308*e4b17023SJohn Marino     }
1309*e4b17023SJohn Marino   while (get_next_update_cost (&allocno, &divisor));
1310*e4b17023SJohn Marino }
1311*e4b17023SJohn Marino 
1312*e4b17023SJohn Marino /* This function updates COSTS (decrease if DECR_P) for hard_registers
1313*e4b17023SJohn Marino    of ACLASS by conflict costs of the unassigned allocnos
1314*e4b17023SJohn Marino    connected by copies with allocnos in update_cost_queue.  This
1315*e4b17023SJohn Marino    update increases chances to remove some copies.  */
1316*e4b17023SJohn Marino static void
update_conflict_hard_regno_costs(int * costs,enum reg_class aclass,bool decr_p)1317*e4b17023SJohn Marino update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
1318*e4b17023SJohn Marino 				  bool decr_p)
1319*e4b17023SJohn Marino {
1320*e4b17023SJohn Marino   int i, cost, class_size, freq, mult, div, divisor;
1321*e4b17023SJohn Marino   int index, hard_regno;
1322*e4b17023SJohn Marino   int *conflict_costs;
1323*e4b17023SJohn Marino   bool cont_p;
1324*e4b17023SJohn Marino   enum reg_class another_aclass;
1325*e4b17023SJohn Marino   ira_allocno_t allocno, another_allocno;
1326*e4b17023SJohn Marino   ira_copy_t cp, next_cp;
1327*e4b17023SJohn Marino 
1328*e4b17023SJohn Marino   while (get_next_update_cost (&allocno, &divisor))
1329*e4b17023SJohn Marino     for (cp = ALLOCNO_COPIES (allocno); cp != NULL; cp = next_cp)
1330*e4b17023SJohn Marino       {
1331*e4b17023SJohn Marino 	if (cp->first == allocno)
1332*e4b17023SJohn Marino 	  {
1333*e4b17023SJohn Marino 	    next_cp = cp->next_first_allocno_copy;
1334*e4b17023SJohn Marino 	    another_allocno = cp->second;
1335*e4b17023SJohn Marino 	  }
1336*e4b17023SJohn Marino 	else if (cp->second == allocno)
1337*e4b17023SJohn Marino 	  {
1338*e4b17023SJohn Marino 	    next_cp = cp->next_second_allocno_copy;
1339*e4b17023SJohn Marino 	    another_allocno = cp->first;
1340*e4b17023SJohn Marino 	  }
1341*e4b17023SJohn Marino 	else
1342*e4b17023SJohn Marino 	  gcc_unreachable ();
1343*e4b17023SJohn Marino  	another_aclass = ALLOCNO_CLASS (another_allocno);
1344*e4b17023SJohn Marino  	if (! ira_reg_classes_intersect_p[aclass][another_aclass]
1345*e4b17023SJohn Marino 	    || ALLOCNO_ASSIGNED_P (another_allocno)
1346*e4b17023SJohn Marino 	    || ALLOCNO_COLOR_DATA (another_allocno)->may_be_spilled_p)
1347*e4b17023SJohn Marino 	  continue;
1348*e4b17023SJohn Marino 	class_size = ira_class_hard_regs_num[another_aclass];
1349*e4b17023SJohn Marino 	ira_allocate_and_copy_costs
1350*e4b17023SJohn Marino 	  (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno),
1351*e4b17023SJohn Marino 	   another_aclass, ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno));
1352*e4b17023SJohn Marino 	conflict_costs
1353*e4b17023SJohn Marino 	  = ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno);
1354*e4b17023SJohn Marino 	if (conflict_costs == NULL)
1355*e4b17023SJohn Marino 	  cont_p = true;
1356*e4b17023SJohn Marino 	else
1357*e4b17023SJohn Marino 	  {
1358*e4b17023SJohn Marino 	    mult = cp->freq;
1359*e4b17023SJohn Marino 	    freq = ALLOCNO_FREQ (another_allocno);
1360*e4b17023SJohn Marino 	    if (freq == 0)
1361*e4b17023SJohn Marino 	      freq = 1;
1362*e4b17023SJohn Marino 	    div = freq * divisor;
1363*e4b17023SJohn Marino 	    cont_p = false;
1364*e4b17023SJohn Marino 	    for (i = class_size - 1; i >= 0; i--)
1365*e4b17023SJohn Marino 	      {
1366*e4b17023SJohn Marino 		hard_regno = ira_class_hard_regs[another_aclass][i];
1367*e4b17023SJohn Marino 		ira_assert (hard_regno >= 0);
1368*e4b17023SJohn Marino 		index = ira_class_hard_reg_index[aclass][hard_regno];
1369*e4b17023SJohn Marino 		if (index < 0)
1370*e4b17023SJohn Marino 		  continue;
1371*e4b17023SJohn Marino 		cost = conflict_costs [i] * mult / div;
1372*e4b17023SJohn Marino 		if (cost == 0)
1373*e4b17023SJohn Marino 		  continue;
1374*e4b17023SJohn Marino 		cont_p = true;
1375*e4b17023SJohn Marino 		if (decr_p)
1376*e4b17023SJohn Marino 		  cost = -cost;
1377*e4b17023SJohn Marino 		costs[index] += cost;
1378*e4b17023SJohn Marino 	      }
1379*e4b17023SJohn Marino 	  }
1380*e4b17023SJohn Marino 	/* Probably 5 hops will be enough.  */
1381*e4b17023SJohn Marino 	if (cont_p
1382*e4b17023SJohn Marino 	    && divisor <= (COST_HOP_DIVISOR
1383*e4b17023SJohn Marino 			   * COST_HOP_DIVISOR
1384*e4b17023SJohn Marino 			   * COST_HOP_DIVISOR
1385*e4b17023SJohn Marino 			   * COST_HOP_DIVISOR))
1386*e4b17023SJohn Marino 	  queue_update_cost (another_allocno, divisor * COST_HOP_DIVISOR);
1387*e4b17023SJohn Marino       }
1388*e4b17023SJohn Marino }
1389*e4b17023SJohn Marino 
1390*e4b17023SJohn Marino /* Set up conflicting (through CONFLICT_REGS) for each object of
1391*e4b17023SJohn Marino    allocno A and the start allocno profitable regs (through
1392*e4b17023SJohn Marino    START_PROFITABLE_REGS).  Remember that the start profitable regs
1393*e4b17023SJohn Marino    exclude hard regs which can not hold value of mode of allocno A.
1394*e4b17023SJohn Marino    This covers mostly cases when multi-register value should be
1395*e4b17023SJohn Marino    aligned.  */
1396*e4b17023SJohn Marino static inline void
get_conflict_and_start_profitable_regs(ira_allocno_t a,bool retry_p,HARD_REG_SET * conflict_regs,HARD_REG_SET * start_profitable_regs)1397*e4b17023SJohn Marino get_conflict_and_start_profitable_regs (ira_allocno_t a, bool retry_p,
1398*e4b17023SJohn Marino 					HARD_REG_SET *conflict_regs,
1399*e4b17023SJohn Marino 					HARD_REG_SET *start_profitable_regs)
1400*e4b17023SJohn Marino {
1401*e4b17023SJohn Marino   int i, nwords;
1402*e4b17023SJohn Marino   ira_object_t obj;
1403*e4b17023SJohn Marino 
1404*e4b17023SJohn Marino   nwords = ALLOCNO_NUM_OBJECTS (a);
1405*e4b17023SJohn Marino   for (i = 0; i < nwords; i++)
1406*e4b17023SJohn Marino     {
1407*e4b17023SJohn Marino       obj = ALLOCNO_OBJECT (a, i);
1408*e4b17023SJohn Marino       COPY_HARD_REG_SET (conflict_regs[i],
1409*e4b17023SJohn Marino 			 OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
1410*e4b17023SJohn Marino     }
1411*e4b17023SJohn Marino   if (retry_p)
1412*e4b17023SJohn Marino     {
1413*e4b17023SJohn Marino       COPY_HARD_REG_SET (*start_profitable_regs,
1414*e4b17023SJohn Marino 			 reg_class_contents[ALLOCNO_CLASS (a)]);
1415*e4b17023SJohn Marino       AND_COMPL_HARD_REG_SET (*start_profitable_regs,
1416*e4b17023SJohn Marino 			      ira_prohibited_class_mode_regs
1417*e4b17023SJohn Marino 			      [ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]);
1418*e4b17023SJohn Marino     }
1419*e4b17023SJohn Marino   else
1420*e4b17023SJohn Marino     COPY_HARD_REG_SET (*start_profitable_regs,
1421*e4b17023SJohn Marino 		       ALLOCNO_COLOR_DATA (a)->profitable_hard_regs);
1422*e4b17023SJohn Marino }
1423*e4b17023SJohn Marino 
1424*e4b17023SJohn Marino /* Return true if HARD_REGNO is ok for assigning to allocno A with
1425*e4b17023SJohn Marino    PROFITABLE_REGS and whose objects have CONFLICT_REGS.  */
1426*e4b17023SJohn Marino static inline bool
check_hard_reg_p(ira_allocno_t a,int hard_regno,HARD_REG_SET * conflict_regs,HARD_REG_SET profitable_regs)1427*e4b17023SJohn Marino check_hard_reg_p (ira_allocno_t a, int hard_regno,
1428*e4b17023SJohn Marino 		  HARD_REG_SET *conflict_regs, HARD_REG_SET profitable_regs)
1429*e4b17023SJohn Marino {
1430*e4b17023SJohn Marino   int j, nwords, nregs;
1431*e4b17023SJohn Marino   enum reg_class aclass;
1432*e4b17023SJohn Marino   enum machine_mode mode;
1433*e4b17023SJohn Marino 
1434*e4b17023SJohn Marino   aclass = ALLOCNO_CLASS (a);
1435*e4b17023SJohn Marino   mode = ALLOCNO_MODE (a);
1436*e4b17023SJohn Marino   if (TEST_HARD_REG_BIT (ira_prohibited_class_mode_regs[aclass][mode],
1437*e4b17023SJohn Marino 			 hard_regno))
1438*e4b17023SJohn Marino     return false;
1439*e4b17023SJohn Marino   /* Checking only profitable hard regs.  */
1440*e4b17023SJohn Marino   if (! TEST_HARD_REG_BIT (profitable_regs, hard_regno))
1441*e4b17023SJohn Marino     return false;
1442*e4b17023SJohn Marino   nregs = hard_regno_nregs[hard_regno][mode];
1443*e4b17023SJohn Marino   nwords = ALLOCNO_NUM_OBJECTS (a);
1444*e4b17023SJohn Marino   for (j = 0; j < nregs; j++)
1445*e4b17023SJohn Marino     {
1446*e4b17023SJohn Marino       int k;
1447*e4b17023SJohn Marino       int set_to_test_start = 0, set_to_test_end = nwords;
1448*e4b17023SJohn Marino 
1449*e4b17023SJohn Marino       if (nregs == nwords)
1450*e4b17023SJohn Marino 	{
1451*e4b17023SJohn Marino 	  if (REG_WORDS_BIG_ENDIAN)
1452*e4b17023SJohn Marino 	    set_to_test_start = nwords - j - 1;
1453*e4b17023SJohn Marino 	  else
1454*e4b17023SJohn Marino 	    set_to_test_start = j;
1455*e4b17023SJohn Marino 	  set_to_test_end = set_to_test_start + 1;
1456*e4b17023SJohn Marino 	}
1457*e4b17023SJohn Marino       for (k = set_to_test_start; k < set_to_test_end; k++)
1458*e4b17023SJohn Marino 	if (TEST_HARD_REG_BIT (conflict_regs[k], hard_regno + j))
1459*e4b17023SJohn Marino 	  break;
1460*e4b17023SJohn Marino       if (k != set_to_test_end)
1461*e4b17023SJohn Marino 	break;
1462*e4b17023SJohn Marino     }
1463*e4b17023SJohn Marino   return j == nregs;
1464*e4b17023SJohn Marino }
1465*e4b17023SJohn Marino #ifndef HONOR_REG_ALLOC_ORDER
1466*e4b17023SJohn Marino 
1467*e4b17023SJohn Marino /* Return number of registers needed to be saved and restored at
1468*e4b17023SJohn Marino    function prologue/epilogue if we allocate HARD_REGNO to hold value
1469*e4b17023SJohn Marino    of MODE.  */
1470*e4b17023SJohn Marino static int
calculate_saved_nregs(int hard_regno,enum machine_mode mode)1471*e4b17023SJohn Marino calculate_saved_nregs (int hard_regno, enum machine_mode mode)
1472*e4b17023SJohn Marino {
1473*e4b17023SJohn Marino   int i;
1474*e4b17023SJohn Marino   int nregs = 0;
1475*e4b17023SJohn Marino 
1476*e4b17023SJohn Marino   ira_assert (hard_regno >= 0);
1477*e4b17023SJohn Marino   for (i = hard_regno_nregs[hard_regno][mode] - 1; i >= 0; i--)
1478*e4b17023SJohn Marino     if (!allocated_hardreg_p[hard_regno + i]
1479*e4b17023SJohn Marino 	&& !TEST_HARD_REG_BIT (call_used_reg_set, hard_regno + i)
1480*e4b17023SJohn Marino 	&& !LOCAL_REGNO (hard_regno + i))
1481*e4b17023SJohn Marino       nregs++;
1482*e4b17023SJohn Marino   return nregs;
1483*e4b17023SJohn Marino }
1484*e4b17023SJohn Marino #endif
1485*e4b17023SJohn Marino 
1486*e4b17023SJohn Marino /* Choose a hard register for allocno A.  If RETRY_P is TRUE, it means
1487*e4b17023SJohn Marino    that the function called from function
1488*e4b17023SJohn Marino    `ira_reassign_conflict_allocnos' and `allocno_reload_assign'.  In
1489*e4b17023SJohn Marino    this case some allocno data are not defined or updated and we
1490*e4b17023SJohn Marino    should not touch these data.  The function returns true if we
1491*e4b17023SJohn Marino    managed to assign a hard register to the allocno.
1492*e4b17023SJohn Marino 
1493*e4b17023SJohn Marino    To assign a hard register, first of all we calculate all conflict
1494*e4b17023SJohn Marino    hard registers which can come from conflicting allocnos with
1495*e4b17023SJohn Marino    already assigned hard registers.  After that we find first free
1496*e4b17023SJohn Marino    hard register with the minimal cost.  During hard register cost
1497*e4b17023SJohn Marino    calculation we take conflict hard register costs into account to
1498*e4b17023SJohn Marino    give a chance for conflicting allocnos to get a better hard
1499*e4b17023SJohn Marino    register in the future.
1500*e4b17023SJohn Marino 
1501*e4b17023SJohn Marino    If the best hard register cost is bigger than cost of memory usage
1502*e4b17023SJohn Marino    for the allocno, we don't assign a hard register to given allocno
1503*e4b17023SJohn Marino    at all.
1504*e4b17023SJohn Marino 
1505*e4b17023SJohn Marino    If we assign a hard register to the allocno, we update costs of the
1506*e4b17023SJohn Marino    hard register for allocnos connected by copies to improve a chance
1507*e4b17023SJohn Marino    to coalesce insns represented by the copies when we assign hard
1508*e4b17023SJohn Marino    registers to the allocnos connected by the copies.  */
1509*e4b17023SJohn Marino static bool
assign_hard_reg(ira_allocno_t a,bool retry_p)1510*e4b17023SJohn Marino assign_hard_reg (ira_allocno_t a, bool retry_p)
1511*e4b17023SJohn Marino {
1512*e4b17023SJohn Marino   HARD_REG_SET conflicting_regs[2], profitable_hard_regs;
1513*e4b17023SJohn Marino   int i, j, hard_regno, best_hard_regno, class_size;
1514*e4b17023SJohn Marino   int cost, mem_cost, min_cost, full_cost, min_full_cost, nwords, word;
1515*e4b17023SJohn Marino   int *a_costs;
1516*e4b17023SJohn Marino   enum reg_class aclass;
1517*e4b17023SJohn Marino   enum machine_mode mode;
1518*e4b17023SJohn Marino   static int costs[FIRST_PSEUDO_REGISTER], full_costs[FIRST_PSEUDO_REGISTER];
1519*e4b17023SJohn Marino #ifndef HONOR_REG_ALLOC_ORDER
1520*e4b17023SJohn Marino   int saved_nregs;
1521*e4b17023SJohn Marino   enum reg_class rclass;
1522*e4b17023SJohn Marino   int add_cost;
1523*e4b17023SJohn Marino #endif
1524*e4b17023SJohn Marino #ifdef STACK_REGS
1525*e4b17023SJohn Marino   bool no_stack_reg_p;
1526*e4b17023SJohn Marino #endif
1527*e4b17023SJohn Marino 
1528*e4b17023SJohn Marino   ira_assert (! ALLOCNO_ASSIGNED_P (a));
1529*e4b17023SJohn Marino   get_conflict_and_start_profitable_regs (a, retry_p,
1530*e4b17023SJohn Marino 					  conflicting_regs,
1531*e4b17023SJohn Marino 					  &profitable_hard_regs);
1532*e4b17023SJohn Marino   aclass = ALLOCNO_CLASS (a);
1533*e4b17023SJohn Marino   class_size = ira_class_hard_regs_num[aclass];
1534*e4b17023SJohn Marino   best_hard_regno = -1;
1535*e4b17023SJohn Marino   memset (full_costs, 0, sizeof (int) * class_size);
1536*e4b17023SJohn Marino   mem_cost = 0;
1537*e4b17023SJohn Marino   memset (costs, 0, sizeof (int) * class_size);
1538*e4b17023SJohn Marino   memset (full_costs, 0, sizeof (int) * class_size);
1539*e4b17023SJohn Marino #ifdef STACK_REGS
1540*e4b17023SJohn Marino   no_stack_reg_p = false;
1541*e4b17023SJohn Marino #endif
1542*e4b17023SJohn Marino   if (! retry_p)
1543*e4b17023SJohn Marino     start_update_cost ();
1544*e4b17023SJohn Marino   mem_cost += ALLOCNO_UPDATED_MEMORY_COST (a);
1545*e4b17023SJohn Marino 
1546*e4b17023SJohn Marino   ira_allocate_and_copy_costs (&ALLOCNO_UPDATED_HARD_REG_COSTS (a),
1547*e4b17023SJohn Marino 			       aclass, ALLOCNO_HARD_REG_COSTS (a));
1548*e4b17023SJohn Marino   a_costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a);
1549*e4b17023SJohn Marino #ifdef STACK_REGS
1550*e4b17023SJohn Marino   no_stack_reg_p = no_stack_reg_p || ALLOCNO_TOTAL_NO_STACK_REG_P (a);
1551*e4b17023SJohn Marino #endif
1552*e4b17023SJohn Marino   cost = ALLOCNO_UPDATED_CLASS_COST (a);
1553*e4b17023SJohn Marino   for (i = 0; i < class_size; i++)
1554*e4b17023SJohn Marino     if (a_costs != NULL)
1555*e4b17023SJohn Marino       {
1556*e4b17023SJohn Marino 	costs[i] += a_costs[i];
1557*e4b17023SJohn Marino 	full_costs[i] += a_costs[i];
1558*e4b17023SJohn Marino       }
1559*e4b17023SJohn Marino     else
1560*e4b17023SJohn Marino       {
1561*e4b17023SJohn Marino 	costs[i] += cost;
1562*e4b17023SJohn Marino 	full_costs[i] += cost;
1563*e4b17023SJohn Marino       }
1564*e4b17023SJohn Marino   nwords = ALLOCNO_NUM_OBJECTS (a);
1565*e4b17023SJohn Marino   curr_allocno_process++;
1566*e4b17023SJohn Marino   for (word = 0; word < nwords; word++)
1567*e4b17023SJohn Marino     {
1568*e4b17023SJohn Marino       ira_object_t conflict_obj;
1569*e4b17023SJohn Marino       ira_object_t obj = ALLOCNO_OBJECT (a, word);
1570*e4b17023SJohn Marino       ira_object_conflict_iterator oci;
1571*e4b17023SJohn Marino 
1572*e4b17023SJohn Marino       /* Take preferences of conflicting allocnos into account.  */
1573*e4b17023SJohn Marino       FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
1574*e4b17023SJohn Marino         {
1575*e4b17023SJohn Marino 	  ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
1576*e4b17023SJohn Marino 	  enum reg_class conflict_aclass;
1577*e4b17023SJohn Marino 
1578*e4b17023SJohn Marino 	  /* Reload can give another class so we need to check all
1579*e4b17023SJohn Marino 	     allocnos.  */
1580*e4b17023SJohn Marino 	  if (!retry_p
1581*e4b17023SJohn Marino 	      && (!bitmap_bit_p (consideration_allocno_bitmap,
1582*e4b17023SJohn Marino 				 ALLOCNO_NUM (conflict_a))
1583*e4b17023SJohn Marino 		  || ((!ALLOCNO_ASSIGNED_P (conflict_a)
1584*e4b17023SJohn Marino 		       || ALLOCNO_HARD_REGNO (conflict_a) < 0)
1585*e4b17023SJohn Marino 		      && !(hard_reg_set_intersect_p
1586*e4b17023SJohn Marino 			   (profitable_hard_regs,
1587*e4b17023SJohn Marino 			    ALLOCNO_COLOR_DATA
1588*e4b17023SJohn Marino 			    (conflict_a)->profitable_hard_regs)))))
1589*e4b17023SJohn Marino 	    continue;
1590*e4b17023SJohn Marino 	  conflict_aclass = ALLOCNO_CLASS (conflict_a);
1591*e4b17023SJohn Marino 	  ira_assert (ira_reg_classes_intersect_p
1592*e4b17023SJohn Marino 		      [aclass][conflict_aclass]);
1593*e4b17023SJohn Marino 	  if (ALLOCNO_ASSIGNED_P (conflict_a))
1594*e4b17023SJohn Marino 	    {
1595*e4b17023SJohn Marino 	      hard_regno = ALLOCNO_HARD_REGNO (conflict_a);
1596*e4b17023SJohn Marino 	      if (hard_regno >= 0
1597*e4b17023SJohn Marino 		  && (ira_hard_reg_set_intersection_p
1598*e4b17023SJohn Marino 		      (hard_regno, ALLOCNO_MODE (conflict_a),
1599*e4b17023SJohn Marino 		       reg_class_contents[aclass])))
1600*e4b17023SJohn Marino 		{
1601*e4b17023SJohn Marino 		  int n_objects = ALLOCNO_NUM_OBJECTS (conflict_a);
1602*e4b17023SJohn Marino 		  int conflict_nregs;
1603*e4b17023SJohn Marino 
1604*e4b17023SJohn Marino 		  mode = ALLOCNO_MODE (conflict_a);
1605*e4b17023SJohn Marino 		  conflict_nregs = hard_regno_nregs[hard_regno][mode];
1606*e4b17023SJohn Marino 		  if (conflict_nregs == n_objects && conflict_nregs > 1)
1607*e4b17023SJohn Marino 		    {
1608*e4b17023SJohn Marino 		      int num = OBJECT_SUBWORD (conflict_obj);
1609*e4b17023SJohn Marino 
1610*e4b17023SJohn Marino 		      if (REG_WORDS_BIG_ENDIAN)
1611*e4b17023SJohn Marino 			SET_HARD_REG_BIT (conflicting_regs[word],
1612*e4b17023SJohn Marino 					  hard_regno + n_objects - num - 1);
1613*e4b17023SJohn Marino 		      else
1614*e4b17023SJohn Marino 			SET_HARD_REG_BIT (conflicting_regs[word],
1615*e4b17023SJohn Marino 					  hard_regno + num);
1616*e4b17023SJohn Marino 		    }
1617*e4b17023SJohn Marino 		  else
1618*e4b17023SJohn Marino 		    IOR_HARD_REG_SET
1619*e4b17023SJohn Marino 		      (conflicting_regs[word],
1620*e4b17023SJohn Marino 		       ira_reg_mode_hard_regset[hard_regno][mode]);
1621*e4b17023SJohn Marino 		  if (hard_reg_set_subset_p (profitable_hard_regs,
1622*e4b17023SJohn Marino 					     conflicting_regs[word]))
1623*e4b17023SJohn Marino 		    goto fail;
1624*e4b17023SJohn Marino 		}
1625*e4b17023SJohn Marino 	    }
1626*e4b17023SJohn Marino 	  else if (! retry_p
1627*e4b17023SJohn Marino 		   && ! ALLOCNO_COLOR_DATA (conflict_a)->may_be_spilled_p
1628*e4b17023SJohn Marino 		   /* Don't process the conflict allocno twice.  */
1629*e4b17023SJohn Marino 		   && (ALLOCNO_COLOR_DATA (conflict_a)->last_process
1630*e4b17023SJohn Marino 		       != curr_allocno_process))
1631*e4b17023SJohn Marino 	    {
1632*e4b17023SJohn Marino 	      int k, *conflict_costs;
1633*e4b17023SJohn Marino 
1634*e4b17023SJohn Marino 	      ALLOCNO_COLOR_DATA (conflict_a)->last_process
1635*e4b17023SJohn Marino 		= curr_allocno_process;
1636*e4b17023SJohn Marino 	      ira_allocate_and_copy_costs
1637*e4b17023SJohn Marino 		(&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_a),
1638*e4b17023SJohn Marino 		 conflict_aclass,
1639*e4b17023SJohn Marino 		 ALLOCNO_CONFLICT_HARD_REG_COSTS (conflict_a));
1640*e4b17023SJohn Marino 	      conflict_costs
1641*e4b17023SJohn Marino 		= ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_a);
1642*e4b17023SJohn Marino 	      if (conflict_costs != NULL)
1643*e4b17023SJohn Marino 		for (j = class_size - 1; j >= 0; j--)
1644*e4b17023SJohn Marino 		  {
1645*e4b17023SJohn Marino 		    hard_regno = ira_class_hard_regs[aclass][j];
1646*e4b17023SJohn Marino 		    ira_assert (hard_regno >= 0);
1647*e4b17023SJohn Marino 		    k = ira_class_hard_reg_index[conflict_aclass][hard_regno];
1648*e4b17023SJohn Marino 		    if (k < 0)
1649*e4b17023SJohn Marino 		      continue;
1650*e4b17023SJohn Marino 		    full_costs[j] -= conflict_costs[k];
1651*e4b17023SJohn Marino 		  }
1652*e4b17023SJohn Marino 	      queue_update_cost (conflict_a, COST_HOP_DIVISOR);
1653*e4b17023SJohn Marino 	    }
1654*e4b17023SJohn Marino 	}
1655*e4b17023SJohn Marino     }
1656*e4b17023SJohn Marino   if (! retry_p)
1657*e4b17023SJohn Marino     /* Take into account preferences of allocnos connected by copies to
1658*e4b17023SJohn Marino        the conflict allocnos.  */
1659*e4b17023SJohn Marino     update_conflict_hard_regno_costs (full_costs, aclass, true);
1660*e4b17023SJohn Marino 
1661*e4b17023SJohn Marino   /* Take preferences of allocnos connected by copies into
1662*e4b17023SJohn Marino      account.  */
1663*e4b17023SJohn Marino   if (! retry_p)
1664*e4b17023SJohn Marino     {
1665*e4b17023SJohn Marino       start_update_cost ();
1666*e4b17023SJohn Marino       queue_update_cost (a, COST_HOP_DIVISOR);
1667*e4b17023SJohn Marino       update_conflict_hard_regno_costs (full_costs, aclass, false);
1668*e4b17023SJohn Marino     }
1669*e4b17023SJohn Marino   min_cost = min_full_cost = INT_MAX;
1670*e4b17023SJohn Marino   /* We don't care about giving callee saved registers to allocnos no
1671*e4b17023SJohn Marino      living through calls because call clobbered registers are
1672*e4b17023SJohn Marino      allocated first (it is usual practice to put them first in
1673*e4b17023SJohn Marino      REG_ALLOC_ORDER).  */
1674*e4b17023SJohn Marino   mode = ALLOCNO_MODE (a);
1675*e4b17023SJohn Marino   for (i = 0; i < class_size; i++)
1676*e4b17023SJohn Marino     {
1677*e4b17023SJohn Marino       hard_regno = ira_class_hard_regs[aclass][i];
1678*e4b17023SJohn Marino #ifdef STACK_REGS
1679*e4b17023SJohn Marino       if (no_stack_reg_p
1680*e4b17023SJohn Marino 	  && FIRST_STACK_REG <= hard_regno && hard_regno <= LAST_STACK_REG)
1681*e4b17023SJohn Marino 	continue;
1682*e4b17023SJohn Marino #endif
1683*e4b17023SJohn Marino       if (! check_hard_reg_p (a, hard_regno,
1684*e4b17023SJohn Marino 			      conflicting_regs, profitable_hard_regs))
1685*e4b17023SJohn Marino 	continue;
1686*e4b17023SJohn Marino       cost = costs[i];
1687*e4b17023SJohn Marino       full_cost = full_costs[i];
1688*e4b17023SJohn Marino #ifndef HONOR_REG_ALLOC_ORDER
1689*e4b17023SJohn Marino       if ((saved_nregs = calculate_saved_nregs (hard_regno, mode)) != 0)
1690*e4b17023SJohn Marino 	/* We need to save/restore the hard register in
1691*e4b17023SJohn Marino 	   epilogue/prologue.  Therefore we increase the cost.  */
1692*e4b17023SJohn Marino 	{
1693*e4b17023SJohn Marino 	  rclass = REGNO_REG_CLASS (hard_regno);
1694*e4b17023SJohn Marino 	  add_cost = ((ira_memory_move_cost[mode][rclass][0]
1695*e4b17023SJohn Marino 		       + ira_memory_move_cost[mode][rclass][1])
1696*e4b17023SJohn Marino 		      * saved_nregs / hard_regno_nregs[hard_regno][mode] - 1);
1697*e4b17023SJohn Marino 	  cost += add_cost;
1698*e4b17023SJohn Marino 	  full_cost += add_cost;
1699*e4b17023SJohn Marino 	}
1700*e4b17023SJohn Marino #endif
1701*e4b17023SJohn Marino       if (min_cost > cost)
1702*e4b17023SJohn Marino 	min_cost = cost;
1703*e4b17023SJohn Marino       if (min_full_cost > full_cost)
1704*e4b17023SJohn Marino 	{
1705*e4b17023SJohn Marino 	  min_full_cost = full_cost;
1706*e4b17023SJohn Marino 	  best_hard_regno = hard_regno;
1707*e4b17023SJohn Marino 	  ira_assert (hard_regno >= 0);
1708*e4b17023SJohn Marino 	}
1709*e4b17023SJohn Marino     }
1710*e4b17023SJohn Marino   if (min_full_cost > mem_cost)
1711*e4b17023SJohn Marino     {
1712*e4b17023SJohn Marino       if (! retry_p && internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
1713*e4b17023SJohn Marino 	fprintf (ira_dump_file, "(memory is more profitable %d vs %d) ",
1714*e4b17023SJohn Marino 		 mem_cost, min_full_cost);
1715*e4b17023SJohn Marino       best_hard_regno = -1;
1716*e4b17023SJohn Marino     }
1717*e4b17023SJohn Marino  fail:
1718*e4b17023SJohn Marino   if (best_hard_regno >= 0)
1719*e4b17023SJohn Marino     {
1720*e4b17023SJohn Marino       for (i = hard_regno_nregs[best_hard_regno][mode] - 1; i >= 0; i--)
1721*e4b17023SJohn Marino 	allocated_hardreg_p[best_hard_regno + i] = true;
1722*e4b17023SJohn Marino     }
1723*e4b17023SJohn Marino   ALLOCNO_HARD_REGNO (a) = best_hard_regno;
1724*e4b17023SJohn Marino   ALLOCNO_ASSIGNED_P (a) = true;
1725*e4b17023SJohn Marino   if (best_hard_regno >= 0)
1726*e4b17023SJohn Marino     update_copy_costs (a, true);
1727*e4b17023SJohn Marino   ira_assert (ALLOCNO_CLASS (a) == aclass);
1728*e4b17023SJohn Marino   /* We don't need updated costs anymore: */
1729*e4b17023SJohn Marino   ira_free_allocno_updated_costs (a);
1730*e4b17023SJohn Marino   return best_hard_regno >= 0;
1731*e4b17023SJohn Marino }
1732*e4b17023SJohn Marino 
1733*e4b17023SJohn Marino 
1734*e4b17023SJohn Marino 
1735*e4b17023SJohn Marino /* This page contains the allocator based on the Chaitin-Briggs algorithm.  */
1736*e4b17023SJohn Marino 
1737*e4b17023SJohn Marino /* Bucket of allocnos that can colored currently without spilling.  */
1738*e4b17023SJohn Marino static ira_allocno_t colorable_allocno_bucket;
1739*e4b17023SJohn Marino 
1740*e4b17023SJohn Marino /* Bucket of allocnos that might be not colored currently without
1741*e4b17023SJohn Marino    spilling.  */
1742*e4b17023SJohn Marino static ira_allocno_t uncolorable_allocno_bucket;
1743*e4b17023SJohn Marino 
1744*e4b17023SJohn Marino /* The current number of allocnos in the uncolorable_bucket.  */
1745*e4b17023SJohn Marino static int uncolorable_allocnos_num;
1746*e4b17023SJohn Marino 
1747*e4b17023SJohn Marino /* Return the current spill priority of allocno A.  The less the
1748*e4b17023SJohn Marino    number, the more preferable the allocno for spilling.  */
1749*e4b17023SJohn Marino static inline int
allocno_spill_priority(ira_allocno_t a)1750*e4b17023SJohn Marino allocno_spill_priority (ira_allocno_t a)
1751*e4b17023SJohn Marino {
1752*e4b17023SJohn Marino   allocno_color_data_t data = ALLOCNO_COLOR_DATA (a);
1753*e4b17023SJohn Marino 
1754*e4b17023SJohn Marino   return (data->temp
1755*e4b17023SJohn Marino 	  / (ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a)
1756*e4b17023SJohn Marino 	     * ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]
1757*e4b17023SJohn Marino 	     + 1));
1758*e4b17023SJohn Marino }
1759*e4b17023SJohn Marino 
1760*e4b17023SJohn Marino /* Add allocno A to bucket *BUCKET_PTR.  A should be not in a bucket
1761*e4b17023SJohn Marino    before the call.  */
1762*e4b17023SJohn Marino static void
add_allocno_to_bucket(ira_allocno_t a,ira_allocno_t * bucket_ptr)1763*e4b17023SJohn Marino add_allocno_to_bucket (ira_allocno_t a, ira_allocno_t *bucket_ptr)
1764*e4b17023SJohn Marino {
1765*e4b17023SJohn Marino   ira_allocno_t first_a;
1766*e4b17023SJohn Marino   allocno_color_data_t data;
1767*e4b17023SJohn Marino 
1768*e4b17023SJohn Marino   if (bucket_ptr == &uncolorable_allocno_bucket
1769*e4b17023SJohn Marino       && ALLOCNO_CLASS (a) != NO_REGS)
1770*e4b17023SJohn Marino     {
1771*e4b17023SJohn Marino       uncolorable_allocnos_num++;
1772*e4b17023SJohn Marino       ira_assert (uncolorable_allocnos_num > 0);
1773*e4b17023SJohn Marino     }
1774*e4b17023SJohn Marino   first_a = *bucket_ptr;
1775*e4b17023SJohn Marino   data = ALLOCNO_COLOR_DATA (a);
1776*e4b17023SJohn Marino   data->next_bucket_allocno = first_a;
1777*e4b17023SJohn Marino   data->prev_bucket_allocno = NULL;
1778*e4b17023SJohn Marino   if (first_a != NULL)
1779*e4b17023SJohn Marino     ALLOCNO_COLOR_DATA (first_a)->prev_bucket_allocno = a;
1780*e4b17023SJohn Marino   *bucket_ptr = a;
1781*e4b17023SJohn Marino }
1782*e4b17023SJohn Marino 
1783*e4b17023SJohn Marino /* Compare two allocnos to define which allocno should be pushed first
1784*e4b17023SJohn Marino    into the coloring stack.  If the return is a negative number, the
1785*e4b17023SJohn Marino    allocno given by the first parameter will be pushed first.  In this
1786*e4b17023SJohn Marino    case such allocno has less priority than the second one and the
1787*e4b17023SJohn Marino    hard register will be assigned to it after assignment to the second
1788*e4b17023SJohn Marino    one.  As the result of such assignment order, the second allocno
1789*e4b17023SJohn Marino    has a better chance to get the best hard register.  */
1790*e4b17023SJohn Marino static int
bucket_allocno_compare_func(const void * v1p,const void * v2p)1791*e4b17023SJohn Marino bucket_allocno_compare_func (const void *v1p, const void *v2p)
1792*e4b17023SJohn Marino {
1793*e4b17023SJohn Marino   ira_allocno_t a1 = *(const ira_allocno_t *) v1p;
1794*e4b17023SJohn Marino   ira_allocno_t a2 = *(const ira_allocno_t *) v2p;
1795*e4b17023SJohn Marino   int diff, a1_freq, a2_freq, a1_num, a2_num;
1796*e4b17023SJohn Marino   int cl1 = ALLOCNO_CLASS (a1), cl2 = ALLOCNO_CLASS (a2);
1797*e4b17023SJohn Marino 
1798*e4b17023SJohn Marino   /* Push pseudos requiring less hard registers first.  It means that
1799*e4b17023SJohn Marino      we will assign pseudos requiring more hard registers first
1800*e4b17023SJohn Marino      avoiding creation small holes in free hard register file into
1801*e4b17023SJohn Marino      which the pseudos requiring more hard registers can not fit.  */
1802*e4b17023SJohn Marino   if ((diff = (ira_reg_class_max_nregs[cl1][ALLOCNO_MODE (a1)]
1803*e4b17023SJohn Marino 	       - ira_reg_class_max_nregs[cl2][ALLOCNO_MODE (a2)])) != 0)
1804*e4b17023SJohn Marino     return diff;
1805*e4b17023SJohn Marino   a1_freq = ALLOCNO_FREQ (a1);
1806*e4b17023SJohn Marino   a2_freq = ALLOCNO_FREQ (a2);
1807*e4b17023SJohn Marino   if ((diff = a1_freq - a2_freq) != 0)
1808*e4b17023SJohn Marino     return diff;
1809*e4b17023SJohn Marino   a1_num = ALLOCNO_COLOR_DATA (a1)->available_regs_num;
1810*e4b17023SJohn Marino   a2_num = ALLOCNO_COLOR_DATA (a2)->available_regs_num;
1811*e4b17023SJohn Marino   if ((diff = a2_num - a1_num) != 0)
1812*e4b17023SJohn Marino     return diff;
1813*e4b17023SJohn Marino   return ALLOCNO_NUM (a2) - ALLOCNO_NUM (a1);
1814*e4b17023SJohn Marino }
1815*e4b17023SJohn Marino 
1816*e4b17023SJohn Marino /* Sort bucket *BUCKET_PTR and return the result through
1817*e4b17023SJohn Marino    BUCKET_PTR.  */
1818*e4b17023SJohn Marino static void
sort_bucket(ira_allocno_t * bucket_ptr,int (* compare_func)(const void *,const void *))1819*e4b17023SJohn Marino sort_bucket (ira_allocno_t *bucket_ptr,
1820*e4b17023SJohn Marino 	     int (*compare_func) (const void *, const void *))
1821*e4b17023SJohn Marino {
1822*e4b17023SJohn Marino   ira_allocno_t a, head;
1823*e4b17023SJohn Marino   int n;
1824*e4b17023SJohn Marino 
1825*e4b17023SJohn Marino   for (n = 0, a = *bucket_ptr;
1826*e4b17023SJohn Marino        a != NULL;
1827*e4b17023SJohn Marino        a = ALLOCNO_COLOR_DATA (a)->next_bucket_allocno)
1828*e4b17023SJohn Marino     sorted_allocnos[n++] = a;
1829*e4b17023SJohn Marino   if (n <= 1)
1830*e4b17023SJohn Marino     return;
1831*e4b17023SJohn Marino   qsort (sorted_allocnos, n, sizeof (ira_allocno_t), compare_func);
1832*e4b17023SJohn Marino   head = NULL;
1833*e4b17023SJohn Marino   for (n--; n >= 0; n--)
1834*e4b17023SJohn Marino     {
1835*e4b17023SJohn Marino       a = sorted_allocnos[n];
1836*e4b17023SJohn Marino       ALLOCNO_COLOR_DATA (a)->next_bucket_allocno = head;
1837*e4b17023SJohn Marino       ALLOCNO_COLOR_DATA (a)->prev_bucket_allocno = NULL;
1838*e4b17023SJohn Marino       if (head != NULL)
1839*e4b17023SJohn Marino 	ALLOCNO_COLOR_DATA (head)->prev_bucket_allocno = a;
1840*e4b17023SJohn Marino       head = a;
1841*e4b17023SJohn Marino     }
1842*e4b17023SJohn Marino   *bucket_ptr = head;
1843*e4b17023SJohn Marino }
1844*e4b17023SJohn Marino 
1845*e4b17023SJohn Marino /* Add ALLOCNO to bucket *BUCKET_PTR maintaining the order according
1846*e4b17023SJohn Marino    their priority.  ALLOCNO should be not in a bucket before the
1847*e4b17023SJohn Marino    call.  */
1848*e4b17023SJohn Marino static void
add_allocno_to_ordered_bucket(ira_allocno_t allocno,ira_allocno_t * bucket_ptr)1849*e4b17023SJohn Marino add_allocno_to_ordered_bucket (ira_allocno_t allocno,
1850*e4b17023SJohn Marino 			       ira_allocno_t *bucket_ptr)
1851*e4b17023SJohn Marino {
1852*e4b17023SJohn Marino   ira_allocno_t before, after;
1853*e4b17023SJohn Marino 
1854*e4b17023SJohn Marino   if (bucket_ptr == &uncolorable_allocno_bucket
1855*e4b17023SJohn Marino       && ALLOCNO_CLASS (allocno) != NO_REGS)
1856*e4b17023SJohn Marino     {
1857*e4b17023SJohn Marino       uncolorable_allocnos_num++;
1858*e4b17023SJohn Marino       ira_assert (uncolorable_allocnos_num > 0);
1859*e4b17023SJohn Marino     }
1860*e4b17023SJohn Marino   for (before = *bucket_ptr, after = NULL;
1861*e4b17023SJohn Marino        before != NULL;
1862*e4b17023SJohn Marino        after = before,
1863*e4b17023SJohn Marino 	 before = ALLOCNO_COLOR_DATA (before)->next_bucket_allocno)
1864*e4b17023SJohn Marino     if (bucket_allocno_compare_func (&allocno, &before) < 0)
1865*e4b17023SJohn Marino       break;
1866*e4b17023SJohn Marino   ALLOCNO_COLOR_DATA (allocno)->next_bucket_allocno = before;
1867*e4b17023SJohn Marino   ALLOCNO_COLOR_DATA (allocno)->prev_bucket_allocno = after;
1868*e4b17023SJohn Marino   if (after == NULL)
1869*e4b17023SJohn Marino     *bucket_ptr = allocno;
1870*e4b17023SJohn Marino   else
1871*e4b17023SJohn Marino     ALLOCNO_COLOR_DATA (after)->next_bucket_allocno = allocno;
1872*e4b17023SJohn Marino   if (before != NULL)
1873*e4b17023SJohn Marino     ALLOCNO_COLOR_DATA (before)->prev_bucket_allocno = allocno;
1874*e4b17023SJohn Marino }
1875*e4b17023SJohn Marino 
1876*e4b17023SJohn Marino /* Delete ALLOCNO from bucket *BUCKET_PTR.  It should be there before
1877*e4b17023SJohn Marino    the call.  */
1878*e4b17023SJohn Marino static void
delete_allocno_from_bucket(ira_allocno_t allocno,ira_allocno_t * bucket_ptr)1879*e4b17023SJohn Marino delete_allocno_from_bucket (ira_allocno_t allocno, ira_allocno_t *bucket_ptr)
1880*e4b17023SJohn Marino {
1881*e4b17023SJohn Marino   ira_allocno_t prev_allocno, next_allocno;
1882*e4b17023SJohn Marino 
1883*e4b17023SJohn Marino   if (bucket_ptr == &uncolorable_allocno_bucket
1884*e4b17023SJohn Marino       && ALLOCNO_CLASS (allocno) != NO_REGS)
1885*e4b17023SJohn Marino     {
1886*e4b17023SJohn Marino       uncolorable_allocnos_num--;
1887*e4b17023SJohn Marino       ira_assert (uncolorable_allocnos_num >= 0);
1888*e4b17023SJohn Marino     }
1889*e4b17023SJohn Marino   prev_allocno = ALLOCNO_COLOR_DATA (allocno)->prev_bucket_allocno;
1890*e4b17023SJohn Marino   next_allocno = ALLOCNO_COLOR_DATA (allocno)->next_bucket_allocno;
1891*e4b17023SJohn Marino   if (prev_allocno != NULL)
1892*e4b17023SJohn Marino     ALLOCNO_COLOR_DATA (prev_allocno)->next_bucket_allocno = next_allocno;
1893*e4b17023SJohn Marino   else
1894*e4b17023SJohn Marino     {
1895*e4b17023SJohn Marino       ira_assert (*bucket_ptr == allocno);
1896*e4b17023SJohn Marino       *bucket_ptr = next_allocno;
1897*e4b17023SJohn Marino     }
1898*e4b17023SJohn Marino   if (next_allocno != NULL)
1899*e4b17023SJohn Marino     ALLOCNO_COLOR_DATA (next_allocno)->prev_bucket_allocno = prev_allocno;
1900*e4b17023SJohn Marino }
1901*e4b17023SJohn Marino 
1902*e4b17023SJohn Marino /* Put allocno A onto the coloring stack without removing it from its
1903*e4b17023SJohn Marino    bucket.  Pushing allocno to the coloring stack can result in moving
1904*e4b17023SJohn Marino    conflicting allocnos from the uncolorable bucket to the colorable
1905*e4b17023SJohn Marino    one.  */
1906*e4b17023SJohn Marino static void
push_allocno_to_stack(ira_allocno_t a)1907*e4b17023SJohn Marino push_allocno_to_stack (ira_allocno_t a)
1908*e4b17023SJohn Marino {
1909*e4b17023SJohn Marino   enum reg_class aclass;
1910*e4b17023SJohn Marino   allocno_color_data_t data, conflict_data;
1911*e4b17023SJohn Marino   int size, i, n = ALLOCNO_NUM_OBJECTS (a);
1912*e4b17023SJohn Marino 
1913*e4b17023SJohn Marino   data = ALLOCNO_COLOR_DATA (a);
1914*e4b17023SJohn Marino   data->in_graph_p = false;
1915*e4b17023SJohn Marino   VEC_safe_push (ira_allocno_t, heap, allocno_stack_vec, a);
1916*e4b17023SJohn Marino   aclass = ALLOCNO_CLASS (a);
1917*e4b17023SJohn Marino   if (aclass == NO_REGS)
1918*e4b17023SJohn Marino     return;
1919*e4b17023SJohn Marino   size = ira_reg_class_max_nregs[aclass][ALLOCNO_MODE (a)];
1920*e4b17023SJohn Marino   if (n > 1)
1921*e4b17023SJohn Marino     {
1922*e4b17023SJohn Marino       /* We will deal with the subwords individually.  */
1923*e4b17023SJohn Marino       gcc_assert (size == ALLOCNO_NUM_OBJECTS (a));
1924*e4b17023SJohn Marino       size = 1;
1925*e4b17023SJohn Marino     }
1926*e4b17023SJohn Marino   for (i = 0; i < n; i++)
1927*e4b17023SJohn Marino     {
1928*e4b17023SJohn Marino       ira_object_t obj = ALLOCNO_OBJECT (a, i);
1929*e4b17023SJohn Marino       ira_object_t conflict_obj;
1930*e4b17023SJohn Marino       ira_object_conflict_iterator oci;
1931*e4b17023SJohn Marino 
1932*e4b17023SJohn Marino       FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
1933*e4b17023SJohn Marino 	{
1934*e4b17023SJohn Marino 	  ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
1935*e4b17023SJohn Marino 
1936*e4b17023SJohn Marino 	  conflict_data = ALLOCNO_COLOR_DATA (conflict_a);
1937*e4b17023SJohn Marino 	  if (conflict_data->colorable_p
1938*e4b17023SJohn Marino 	      || ! conflict_data->in_graph_p
1939*e4b17023SJohn Marino 	      || ALLOCNO_ASSIGNED_P (conflict_a)
1940*e4b17023SJohn Marino 	      || !(hard_reg_set_intersect_p
1941*e4b17023SJohn Marino 		   (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs,
1942*e4b17023SJohn Marino 		    conflict_data->profitable_hard_regs)))
1943*e4b17023SJohn Marino 	    continue;
1944*e4b17023SJohn Marino 	  ira_assert (bitmap_bit_p (coloring_allocno_bitmap,
1945*e4b17023SJohn Marino 				    ALLOCNO_NUM (conflict_a)));
1946*e4b17023SJohn Marino 	  if (update_left_conflict_sizes_p (conflict_a, a, size))
1947*e4b17023SJohn Marino 	    {
1948*e4b17023SJohn Marino 	      delete_allocno_from_bucket
1949*e4b17023SJohn Marino 		(conflict_a, &uncolorable_allocno_bucket);
1950*e4b17023SJohn Marino 	      add_allocno_to_ordered_bucket
1951*e4b17023SJohn Marino 		(conflict_a, &colorable_allocno_bucket);
1952*e4b17023SJohn Marino 	      if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
1953*e4b17023SJohn Marino 		{
1954*e4b17023SJohn Marino 		  fprintf (ira_dump_file, "        Making");
1955*e4b17023SJohn Marino 		  ira_print_expanded_allocno (conflict_a);
1956*e4b17023SJohn Marino 		  fprintf (ira_dump_file, " colorable\n");
1957*e4b17023SJohn Marino 		}
1958*e4b17023SJohn Marino 	    }
1959*e4b17023SJohn Marino 
1960*e4b17023SJohn Marino 	}
1961*e4b17023SJohn Marino     }
1962*e4b17023SJohn Marino }
1963*e4b17023SJohn Marino 
1964*e4b17023SJohn Marino /* Put ALLOCNO onto the coloring stack and remove it from its bucket.
1965*e4b17023SJohn Marino    The allocno is in the colorable bucket if COLORABLE_P is TRUE.  */
1966*e4b17023SJohn Marino static void
remove_allocno_from_bucket_and_push(ira_allocno_t allocno,bool colorable_p)1967*e4b17023SJohn Marino remove_allocno_from_bucket_and_push (ira_allocno_t allocno, bool colorable_p)
1968*e4b17023SJohn Marino {
1969*e4b17023SJohn Marino   if (colorable_p)
1970*e4b17023SJohn Marino     delete_allocno_from_bucket (allocno, &colorable_allocno_bucket);
1971*e4b17023SJohn Marino   else
1972*e4b17023SJohn Marino     delete_allocno_from_bucket (allocno, &uncolorable_allocno_bucket);
1973*e4b17023SJohn Marino   if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
1974*e4b17023SJohn Marino     {
1975*e4b17023SJohn Marino       fprintf (ira_dump_file, "      Pushing");
1976*e4b17023SJohn Marino       ira_print_expanded_allocno (allocno);
1977*e4b17023SJohn Marino       if (colorable_p)
1978*e4b17023SJohn Marino 	fprintf (ira_dump_file, "(cost %d)\n",
1979*e4b17023SJohn Marino 		 ALLOCNO_COLOR_DATA (allocno)->temp);
1980*e4b17023SJohn Marino       else
1981*e4b17023SJohn Marino 	fprintf (ira_dump_file, "(potential spill: %spri=%d, cost=%d)\n",
1982*e4b17023SJohn Marino 		 ALLOCNO_BAD_SPILL_P (allocno) ? "bad spill, " : "",
1983*e4b17023SJohn Marino 		 allocno_spill_priority (allocno),
1984*e4b17023SJohn Marino 		 ALLOCNO_COLOR_DATA (allocno)->temp);
1985*e4b17023SJohn Marino     }
1986*e4b17023SJohn Marino   if (! colorable_p)
1987*e4b17023SJohn Marino     ALLOCNO_COLOR_DATA (allocno)->may_be_spilled_p = true;
1988*e4b17023SJohn Marino   push_allocno_to_stack (allocno);
1989*e4b17023SJohn Marino }
1990*e4b17023SJohn Marino 
1991*e4b17023SJohn Marino /* Put all allocnos from colorable bucket onto the coloring stack.  */
1992*e4b17023SJohn Marino static void
push_only_colorable(void)1993*e4b17023SJohn Marino push_only_colorable (void)
1994*e4b17023SJohn Marino {
1995*e4b17023SJohn Marino   sort_bucket (&colorable_allocno_bucket, bucket_allocno_compare_func);
1996*e4b17023SJohn Marino   for (;colorable_allocno_bucket != NULL;)
1997*e4b17023SJohn Marino     remove_allocno_from_bucket_and_push (colorable_allocno_bucket, true);
1998*e4b17023SJohn Marino }
1999*e4b17023SJohn Marino 
2000*e4b17023SJohn Marino /* Return the frequency of exit edges (if EXIT_P) or entry from/to the
2001*e4b17023SJohn Marino    loop given by its LOOP_NODE.  */
2002*e4b17023SJohn Marino int
ira_loop_edge_freq(ira_loop_tree_node_t loop_node,int regno,bool exit_p)2003*e4b17023SJohn Marino ira_loop_edge_freq (ira_loop_tree_node_t loop_node, int regno, bool exit_p)
2004*e4b17023SJohn Marino {
2005*e4b17023SJohn Marino   int freq, i;
2006*e4b17023SJohn Marino   edge_iterator ei;
2007*e4b17023SJohn Marino   edge e;
2008*e4b17023SJohn Marino   VEC (edge, heap) *edges;
2009*e4b17023SJohn Marino 
2010*e4b17023SJohn Marino   ira_assert (current_loops != NULL && loop_node->loop != NULL
2011*e4b17023SJohn Marino 	      && (regno < 0 || regno >= FIRST_PSEUDO_REGISTER));
2012*e4b17023SJohn Marino   freq = 0;
2013*e4b17023SJohn Marino   if (! exit_p)
2014*e4b17023SJohn Marino     {
2015*e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, loop_node->loop->header->preds)
2016*e4b17023SJohn Marino 	if (e->src != loop_node->loop->latch
2017*e4b17023SJohn Marino 	    && (regno < 0
2018*e4b17023SJohn Marino 		|| (bitmap_bit_p (DF_LR_OUT (e->src), regno)
2019*e4b17023SJohn Marino 		    && bitmap_bit_p (DF_LR_IN (e->dest), regno))))
2020*e4b17023SJohn Marino 	  freq += EDGE_FREQUENCY (e);
2021*e4b17023SJohn Marino     }
2022*e4b17023SJohn Marino   else
2023*e4b17023SJohn Marino     {
2024*e4b17023SJohn Marino       edges = get_loop_exit_edges (loop_node->loop);
2025*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (edge, edges, i, e)
2026*e4b17023SJohn Marino 	if (regno < 0
2027*e4b17023SJohn Marino 	    || (bitmap_bit_p (DF_LR_OUT (e->src), regno)
2028*e4b17023SJohn Marino 		&& bitmap_bit_p (DF_LR_IN (e->dest), regno)))
2029*e4b17023SJohn Marino 	  freq += EDGE_FREQUENCY (e);
2030*e4b17023SJohn Marino       VEC_free (edge, heap, edges);
2031*e4b17023SJohn Marino     }
2032*e4b17023SJohn Marino 
2033*e4b17023SJohn Marino   return REG_FREQ_FROM_EDGE_FREQ (freq);
2034*e4b17023SJohn Marino }
2035*e4b17023SJohn Marino 
2036*e4b17023SJohn Marino /* Calculate and return the cost of putting allocno A into memory.  */
2037*e4b17023SJohn Marino static int
calculate_allocno_spill_cost(ira_allocno_t a)2038*e4b17023SJohn Marino calculate_allocno_spill_cost (ira_allocno_t a)
2039*e4b17023SJohn Marino {
2040*e4b17023SJohn Marino   int regno, cost;
2041*e4b17023SJohn Marino   enum machine_mode mode;
2042*e4b17023SJohn Marino   enum reg_class rclass;
2043*e4b17023SJohn Marino   ira_allocno_t parent_allocno;
2044*e4b17023SJohn Marino   ira_loop_tree_node_t parent_node, loop_node;
2045*e4b17023SJohn Marino 
2046*e4b17023SJohn Marino   regno = ALLOCNO_REGNO (a);
2047*e4b17023SJohn Marino   cost = ALLOCNO_UPDATED_MEMORY_COST (a) - ALLOCNO_UPDATED_CLASS_COST (a);
2048*e4b17023SJohn Marino   if (ALLOCNO_CAP (a) != NULL)
2049*e4b17023SJohn Marino     return cost;
2050*e4b17023SJohn Marino   loop_node = ALLOCNO_LOOP_TREE_NODE (a);
2051*e4b17023SJohn Marino   if ((parent_node = loop_node->parent) == NULL)
2052*e4b17023SJohn Marino     return cost;
2053*e4b17023SJohn Marino   if ((parent_allocno = parent_node->regno_allocno_map[regno]) == NULL)
2054*e4b17023SJohn Marino     return cost;
2055*e4b17023SJohn Marino   mode = ALLOCNO_MODE (a);
2056*e4b17023SJohn Marino   rclass = ALLOCNO_CLASS (a);
2057*e4b17023SJohn Marino   if (ALLOCNO_HARD_REGNO (parent_allocno) < 0)
2058*e4b17023SJohn Marino     cost -= (ira_memory_move_cost[mode][rclass][0]
2059*e4b17023SJohn Marino 	     * ira_loop_edge_freq (loop_node, regno, true)
2060*e4b17023SJohn Marino 	     + ira_memory_move_cost[mode][rclass][1]
2061*e4b17023SJohn Marino 	     * ira_loop_edge_freq (loop_node, regno, false));
2062*e4b17023SJohn Marino   else
2063*e4b17023SJohn Marino     {
2064*e4b17023SJohn Marino       ira_init_register_move_cost_if_necessary (mode);
2065*e4b17023SJohn Marino       cost += ((ira_memory_move_cost[mode][rclass][1]
2066*e4b17023SJohn Marino 		* ira_loop_edge_freq (loop_node, regno, true)
2067*e4b17023SJohn Marino 		+ ira_memory_move_cost[mode][rclass][0]
2068*e4b17023SJohn Marino 		* ira_loop_edge_freq (loop_node, regno, false))
2069*e4b17023SJohn Marino 	       - (ira_register_move_cost[mode][rclass][rclass]
2070*e4b17023SJohn Marino 		  * (ira_loop_edge_freq (loop_node, regno, false)
2071*e4b17023SJohn Marino 		     + ira_loop_edge_freq (loop_node, regno, true))));
2072*e4b17023SJohn Marino     }
2073*e4b17023SJohn Marino   return cost;
2074*e4b17023SJohn Marino }
2075*e4b17023SJohn Marino 
2076*e4b17023SJohn Marino /* Used for sorting allocnos for spilling.  */
2077*e4b17023SJohn Marino static inline int
allocno_spill_priority_compare(ira_allocno_t a1,ira_allocno_t a2)2078*e4b17023SJohn Marino allocno_spill_priority_compare (ira_allocno_t a1, ira_allocno_t a2)
2079*e4b17023SJohn Marino {
2080*e4b17023SJohn Marino   int pri1, pri2, diff;
2081*e4b17023SJohn Marino 
2082*e4b17023SJohn Marino   if (ALLOCNO_BAD_SPILL_P (a1) && ! ALLOCNO_BAD_SPILL_P (a2))
2083*e4b17023SJohn Marino     return 1;
2084*e4b17023SJohn Marino   if (ALLOCNO_BAD_SPILL_P (a2) && ! ALLOCNO_BAD_SPILL_P (a1))
2085*e4b17023SJohn Marino     return -1;
2086*e4b17023SJohn Marino   pri1 = allocno_spill_priority (a1);
2087*e4b17023SJohn Marino   pri2 = allocno_spill_priority (a2);
2088*e4b17023SJohn Marino   if ((diff = pri1 - pri2) != 0)
2089*e4b17023SJohn Marino     return diff;
2090*e4b17023SJohn Marino   if ((diff
2091*e4b17023SJohn Marino        = ALLOCNO_COLOR_DATA (a1)->temp - ALLOCNO_COLOR_DATA (a2)->temp) != 0)
2092*e4b17023SJohn Marino     return diff;
2093*e4b17023SJohn Marino   return ALLOCNO_NUM (a1) - ALLOCNO_NUM (a2);
2094*e4b17023SJohn Marino }
2095*e4b17023SJohn Marino 
2096*e4b17023SJohn Marino /* Used for sorting allocnos for spilling.  */
2097*e4b17023SJohn Marino static int
allocno_spill_sort_compare(const void * v1p,const void * v2p)2098*e4b17023SJohn Marino allocno_spill_sort_compare (const void *v1p, const void *v2p)
2099*e4b17023SJohn Marino {
2100*e4b17023SJohn Marino   ira_allocno_t p1 = *(const ira_allocno_t *) v1p;
2101*e4b17023SJohn Marino   ira_allocno_t p2 = *(const ira_allocno_t *) v2p;
2102*e4b17023SJohn Marino 
2103*e4b17023SJohn Marino   return allocno_spill_priority_compare (p1, p2);
2104*e4b17023SJohn Marino }
2105*e4b17023SJohn Marino 
2106*e4b17023SJohn Marino /* Push allocnos to the coloring stack.  The order of allocnos in the
2107*e4b17023SJohn Marino    stack defines the order for the subsequent coloring.  */
2108*e4b17023SJohn Marino static void
push_allocnos_to_stack(void)2109*e4b17023SJohn Marino push_allocnos_to_stack (void)
2110*e4b17023SJohn Marino {
2111*e4b17023SJohn Marino   ira_allocno_t a;
2112*e4b17023SJohn Marino   int cost;
2113*e4b17023SJohn Marino 
2114*e4b17023SJohn Marino   /* Calculate uncolorable allocno spill costs.  */
2115*e4b17023SJohn Marino   for (a = uncolorable_allocno_bucket;
2116*e4b17023SJohn Marino        a != NULL;
2117*e4b17023SJohn Marino        a = ALLOCNO_COLOR_DATA (a)->next_bucket_allocno)
2118*e4b17023SJohn Marino     if (ALLOCNO_CLASS (a) != NO_REGS)
2119*e4b17023SJohn Marino       {
2120*e4b17023SJohn Marino 	cost = calculate_allocno_spill_cost (a);
2121*e4b17023SJohn Marino 	/* ??? Remove cost of copies between the coalesced
2122*e4b17023SJohn Marino 	   allocnos.  */
2123*e4b17023SJohn Marino 	ALLOCNO_COLOR_DATA (a)->temp = cost;
2124*e4b17023SJohn Marino       }
2125*e4b17023SJohn Marino   sort_bucket (&uncolorable_allocno_bucket, allocno_spill_sort_compare);
2126*e4b17023SJohn Marino   for (;;)
2127*e4b17023SJohn Marino     {
2128*e4b17023SJohn Marino       push_only_colorable ();
2129*e4b17023SJohn Marino       a = uncolorable_allocno_bucket;
2130*e4b17023SJohn Marino       if (a == NULL)
2131*e4b17023SJohn Marino 	break;
2132*e4b17023SJohn Marino       remove_allocno_from_bucket_and_push (a, false);
2133*e4b17023SJohn Marino     }
2134*e4b17023SJohn Marino   ira_assert (colorable_allocno_bucket == NULL
2135*e4b17023SJohn Marino 	      && uncolorable_allocno_bucket == NULL);
2136*e4b17023SJohn Marino   ira_assert (uncolorable_allocnos_num == 0);
2137*e4b17023SJohn Marino }
2138*e4b17023SJohn Marino 
2139*e4b17023SJohn Marino /* Pop the coloring stack and assign hard registers to the popped
2140*e4b17023SJohn Marino    allocnos.  */
2141*e4b17023SJohn Marino static void
pop_allocnos_from_stack(void)2142*e4b17023SJohn Marino pop_allocnos_from_stack (void)
2143*e4b17023SJohn Marino {
2144*e4b17023SJohn Marino   ira_allocno_t allocno;
2145*e4b17023SJohn Marino   enum reg_class aclass;
2146*e4b17023SJohn Marino 
2147*e4b17023SJohn Marino   for (;VEC_length (ira_allocno_t, allocno_stack_vec) != 0;)
2148*e4b17023SJohn Marino     {
2149*e4b17023SJohn Marino       allocno = VEC_pop (ira_allocno_t, allocno_stack_vec);
2150*e4b17023SJohn Marino       aclass = ALLOCNO_CLASS (allocno);
2151*e4b17023SJohn Marino       if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
2152*e4b17023SJohn Marino 	{
2153*e4b17023SJohn Marino 	  fprintf (ira_dump_file, "      Popping");
2154*e4b17023SJohn Marino 	  ira_print_expanded_allocno (allocno);
2155*e4b17023SJohn Marino 	  fprintf (ira_dump_file, "  -- ");
2156*e4b17023SJohn Marino 	}
2157*e4b17023SJohn Marino       if (aclass == NO_REGS)
2158*e4b17023SJohn Marino 	{
2159*e4b17023SJohn Marino 	  ALLOCNO_HARD_REGNO (allocno) = -1;
2160*e4b17023SJohn Marino 	  ALLOCNO_ASSIGNED_P (allocno) = true;
2161*e4b17023SJohn Marino 	  ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (allocno) == NULL);
2162*e4b17023SJohn Marino 	  ira_assert
2163*e4b17023SJohn Marino 	    (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno) == NULL);
2164*e4b17023SJohn Marino 	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
2165*e4b17023SJohn Marino 	    fprintf (ira_dump_file, "assign memory\n");
2166*e4b17023SJohn Marino 	}
2167*e4b17023SJohn Marino       else if (assign_hard_reg (allocno, false))
2168*e4b17023SJohn Marino 	{
2169*e4b17023SJohn Marino 	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
2170*e4b17023SJohn Marino 	    fprintf (ira_dump_file, "assign reg %d\n",
2171*e4b17023SJohn Marino 		     ALLOCNO_HARD_REGNO (allocno));
2172*e4b17023SJohn Marino 	}
2173*e4b17023SJohn Marino       else if (ALLOCNO_ASSIGNED_P (allocno))
2174*e4b17023SJohn Marino 	{
2175*e4b17023SJohn Marino 	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
2176*e4b17023SJohn Marino 	    fprintf (ira_dump_file, "spill\n");
2177*e4b17023SJohn Marino 	}
2178*e4b17023SJohn Marino       ALLOCNO_COLOR_DATA (allocno)->in_graph_p = true;
2179*e4b17023SJohn Marino     }
2180*e4b17023SJohn Marino }
2181*e4b17023SJohn Marino 
2182*e4b17023SJohn Marino /* Set up number of available hard registers for allocno A.  */
2183*e4b17023SJohn Marino static void
setup_allocno_available_regs_num(ira_allocno_t a)2184*e4b17023SJohn Marino setup_allocno_available_regs_num (ira_allocno_t a)
2185*e4b17023SJohn Marino {
2186*e4b17023SJohn Marino   int i, n, hard_regno, hard_regs_num, nwords;
2187*e4b17023SJohn Marino   enum reg_class aclass;
2188*e4b17023SJohn Marino   allocno_color_data_t data;
2189*e4b17023SJohn Marino 
2190*e4b17023SJohn Marino   aclass = ALLOCNO_CLASS (a);
2191*e4b17023SJohn Marino   data = ALLOCNO_COLOR_DATA (a);
2192*e4b17023SJohn Marino   data->available_regs_num = 0;
2193*e4b17023SJohn Marino   if (aclass == NO_REGS)
2194*e4b17023SJohn Marino     return;
2195*e4b17023SJohn Marino   hard_regs_num = ira_class_hard_regs_num[aclass];
2196*e4b17023SJohn Marino   nwords = ALLOCNO_NUM_OBJECTS (a);
2197*e4b17023SJohn Marino   for (n = 0, i = hard_regs_num - 1; i >= 0; i--)
2198*e4b17023SJohn Marino     {
2199*e4b17023SJohn Marino       hard_regno = ira_class_hard_regs[aclass][i];
2200*e4b17023SJohn Marino       /* Checking only profitable hard regs.  */
2201*e4b17023SJohn Marino       if (TEST_HARD_REG_BIT (data->profitable_hard_regs, hard_regno))
2202*e4b17023SJohn Marino 	n++;
2203*e4b17023SJohn Marino     }
2204*e4b17023SJohn Marino   data->available_regs_num = n;
2205*e4b17023SJohn Marino   if (internal_flag_ira_verbose <= 2 || ira_dump_file == NULL)
2206*e4b17023SJohn Marino     return;
2207*e4b17023SJohn Marino   fprintf
2208*e4b17023SJohn Marino     (ira_dump_file,
2209*e4b17023SJohn Marino      "      Allocno a%dr%d of %s(%d) has %d avail. regs ",
2210*e4b17023SJohn Marino      ALLOCNO_NUM (a), ALLOCNO_REGNO (a),
2211*e4b17023SJohn Marino      reg_class_names[aclass], ira_class_hard_regs_num[aclass], n);
2212*e4b17023SJohn Marino   print_hard_reg_set (ira_dump_file, data->profitable_hard_regs, false);
2213*e4b17023SJohn Marino   fprintf (ira_dump_file, ", %snode: ",
2214*e4b17023SJohn Marino 	   hard_reg_set_equal_p (data->profitable_hard_regs,
2215*e4b17023SJohn Marino 				 data->hard_regs_node->hard_regs->set)
2216*e4b17023SJohn Marino 	   ? "" : "^");
2217*e4b17023SJohn Marino   print_hard_reg_set (ira_dump_file,
2218*e4b17023SJohn Marino 		      data->hard_regs_node->hard_regs->set, false);
2219*e4b17023SJohn Marino   for (i = 0; i < nwords; i++)
2220*e4b17023SJohn Marino     {
2221*e4b17023SJohn Marino       ira_object_t obj = ALLOCNO_OBJECT (a, i);
2222*e4b17023SJohn Marino 
2223*e4b17023SJohn Marino       if (nwords != 1)
2224*e4b17023SJohn Marino 	{
2225*e4b17023SJohn Marino 	  if (i != 0)
2226*e4b17023SJohn Marino 	    fprintf (ira_dump_file, ", ");
2227*e4b17023SJohn Marino 	  fprintf (ira_dump_file, " obj %d", i);
2228*e4b17023SJohn Marino 	}
2229*e4b17023SJohn Marino       fprintf (ira_dump_file, " (confl regs = ");
2230*e4b17023SJohn Marino       print_hard_reg_set (ira_dump_file, OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
2231*e4b17023SJohn Marino 			  false);
2232*e4b17023SJohn Marino       fprintf (ira_dump_file, ")");
2233*e4b17023SJohn Marino     }
2234*e4b17023SJohn Marino   fprintf (ira_dump_file, "\n");
2235*e4b17023SJohn Marino }
2236*e4b17023SJohn Marino 
2237*e4b17023SJohn Marino /* Put ALLOCNO in a bucket corresponding to its number and size of its
2238*e4b17023SJohn Marino    conflicting allocnos and hard registers.  */
2239*e4b17023SJohn Marino static void
put_allocno_into_bucket(ira_allocno_t allocno)2240*e4b17023SJohn Marino put_allocno_into_bucket (ira_allocno_t allocno)
2241*e4b17023SJohn Marino {
2242*e4b17023SJohn Marino   ALLOCNO_COLOR_DATA (allocno)->in_graph_p = true;
2243*e4b17023SJohn Marino   setup_allocno_available_regs_num (allocno);
2244*e4b17023SJohn Marino   if (setup_left_conflict_sizes_p (allocno))
2245*e4b17023SJohn Marino     add_allocno_to_bucket (allocno, &colorable_allocno_bucket);
2246*e4b17023SJohn Marino   else
2247*e4b17023SJohn Marino     add_allocno_to_bucket (allocno, &uncolorable_allocno_bucket);
2248*e4b17023SJohn Marino }
2249*e4b17023SJohn Marino 
2250*e4b17023SJohn Marino /* Map: allocno number -> allocno priority.  */
2251*e4b17023SJohn Marino static int *allocno_priorities;
2252*e4b17023SJohn Marino 
2253*e4b17023SJohn Marino /* Set up priorities for N allocnos in array
2254*e4b17023SJohn Marino    CONSIDERATION_ALLOCNOS.  */
2255*e4b17023SJohn Marino static void
setup_allocno_priorities(ira_allocno_t * consideration_allocnos,int n)2256*e4b17023SJohn Marino setup_allocno_priorities (ira_allocno_t *consideration_allocnos, int n)
2257*e4b17023SJohn Marino {
2258*e4b17023SJohn Marino   int i, length, nrefs, priority, max_priority, mult;
2259*e4b17023SJohn Marino   ira_allocno_t a;
2260*e4b17023SJohn Marino 
2261*e4b17023SJohn Marino   max_priority = 0;
2262*e4b17023SJohn Marino   for (i = 0; i < n; i++)
2263*e4b17023SJohn Marino     {
2264*e4b17023SJohn Marino       a = consideration_allocnos[i];
2265*e4b17023SJohn Marino       nrefs = ALLOCNO_NREFS (a);
2266*e4b17023SJohn Marino       ira_assert (nrefs >= 0);
2267*e4b17023SJohn Marino       mult = floor_log2 (ALLOCNO_NREFS (a)) + 1;
2268*e4b17023SJohn Marino       ira_assert (mult >= 0);
2269*e4b17023SJohn Marino       allocno_priorities[ALLOCNO_NUM (a)]
2270*e4b17023SJohn Marino 	= priority
2271*e4b17023SJohn Marino 	= (mult
2272*e4b17023SJohn Marino 	   * (ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a))
2273*e4b17023SJohn Marino 	   * ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]);
2274*e4b17023SJohn Marino       if (priority < 0)
2275*e4b17023SJohn Marino 	priority = -priority;
2276*e4b17023SJohn Marino       if (max_priority < priority)
2277*e4b17023SJohn Marino 	max_priority = priority;
2278*e4b17023SJohn Marino     }
2279*e4b17023SJohn Marino   mult = max_priority == 0 ? 1 : INT_MAX / max_priority;
2280*e4b17023SJohn Marino   for (i = 0; i < n; i++)
2281*e4b17023SJohn Marino     {
2282*e4b17023SJohn Marino       a = consideration_allocnos[i];
2283*e4b17023SJohn Marino       length = ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
2284*e4b17023SJohn Marino       if (ALLOCNO_NUM_OBJECTS (a) > 1)
2285*e4b17023SJohn Marino 	length /= ALLOCNO_NUM_OBJECTS (a);
2286*e4b17023SJohn Marino       if (length <= 0)
2287*e4b17023SJohn Marino 	length = 1;
2288*e4b17023SJohn Marino       allocno_priorities[ALLOCNO_NUM (a)]
2289*e4b17023SJohn Marino 	= allocno_priorities[ALLOCNO_NUM (a)] * mult / length;
2290*e4b17023SJohn Marino     }
2291*e4b17023SJohn Marino }
2292*e4b17023SJohn Marino 
2293*e4b17023SJohn Marino /* Sort allocnos according to the profit of usage of a hard register
2294*e4b17023SJohn Marino    instead of memory for them. */
2295*e4b17023SJohn Marino static int
allocno_cost_compare_func(const void * v1p,const void * v2p)2296*e4b17023SJohn Marino allocno_cost_compare_func (const void *v1p, const void *v2p)
2297*e4b17023SJohn Marino {
2298*e4b17023SJohn Marino   ira_allocno_t p1 = *(const ira_allocno_t *) v1p;
2299*e4b17023SJohn Marino   ira_allocno_t p2 = *(const ira_allocno_t *) v2p;
2300*e4b17023SJohn Marino   int c1, c2;
2301*e4b17023SJohn Marino 
2302*e4b17023SJohn Marino   c1 = ALLOCNO_UPDATED_MEMORY_COST (p1) - ALLOCNO_UPDATED_CLASS_COST (p1);
2303*e4b17023SJohn Marino   c2 = ALLOCNO_UPDATED_MEMORY_COST (p2) - ALLOCNO_UPDATED_CLASS_COST (p2);
2304*e4b17023SJohn Marino   if (c1 - c2)
2305*e4b17023SJohn Marino     return c1 - c2;
2306*e4b17023SJohn Marino 
2307*e4b17023SJohn Marino   /* If regs are equally good, sort by allocno numbers, so that the
2308*e4b17023SJohn Marino      results of qsort leave nothing to chance.  */
2309*e4b17023SJohn Marino   return ALLOCNO_NUM (p1) - ALLOCNO_NUM (p2);
2310*e4b17023SJohn Marino }
2311*e4b17023SJohn Marino 
2312*e4b17023SJohn Marino /* We used Chaitin-Briggs coloring to assign as many pseudos as
2313*e4b17023SJohn Marino    possible to hard registers.  Let us try to improve allocation with
2314*e4b17023SJohn Marino    cost point of view.  This function improves the allocation by
2315*e4b17023SJohn Marino    spilling some allocnos and assigning the freed hard registers to
2316*e4b17023SJohn Marino    other allocnos if it decreases the overall allocation cost.  */
2317*e4b17023SJohn Marino static void
improve_allocation(void)2318*e4b17023SJohn Marino improve_allocation (void)
2319*e4b17023SJohn Marino {
2320*e4b17023SJohn Marino   unsigned int i;
2321*e4b17023SJohn Marino   int j, k, n, hregno, conflict_hregno, base_cost, class_size, word, nwords;
2322*e4b17023SJohn Marino   int check, spill_cost, min_cost, nregs, conflict_nregs, r, best;
2323*e4b17023SJohn Marino   bool try_p;
2324*e4b17023SJohn Marino   enum reg_class aclass;
2325*e4b17023SJohn Marino   enum machine_mode mode;
2326*e4b17023SJohn Marino   int *allocno_costs;
2327*e4b17023SJohn Marino   int costs[FIRST_PSEUDO_REGISTER];
2328*e4b17023SJohn Marino   HARD_REG_SET conflicting_regs[2], profitable_hard_regs;
2329*e4b17023SJohn Marino   ira_allocno_t a;
2330*e4b17023SJohn Marino   bitmap_iterator bi;
2331*e4b17023SJohn Marino 
2332*e4b17023SJohn Marino   /* Clear counts used to process conflicting allocnos only once for
2333*e4b17023SJohn Marino      each allocno.  */
2334*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
2335*e4b17023SJohn Marino     ALLOCNO_COLOR_DATA (ira_allocnos[i])->temp = 0;
2336*e4b17023SJohn Marino   check = n = 0;
2337*e4b17023SJohn Marino   /* Process each allocno and try to assign a hard register to it by
2338*e4b17023SJohn Marino      spilling some its conflicting allocnos.  */
2339*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
2340*e4b17023SJohn Marino     {
2341*e4b17023SJohn Marino       a = ira_allocnos[i];
2342*e4b17023SJohn Marino       ALLOCNO_COLOR_DATA (a)->temp = 0;
2343*e4b17023SJohn Marino       if (empty_profitable_hard_regs (a))
2344*e4b17023SJohn Marino 	continue;
2345*e4b17023SJohn Marino       check++;
2346*e4b17023SJohn Marino       aclass = ALLOCNO_CLASS (a);
2347*e4b17023SJohn Marino       allocno_costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a);
2348*e4b17023SJohn Marino       if (allocno_costs == NULL)
2349*e4b17023SJohn Marino 	allocno_costs = ALLOCNO_HARD_REG_COSTS (a);
2350*e4b17023SJohn Marino       if ((hregno = ALLOCNO_HARD_REGNO (a)) < 0)
2351*e4b17023SJohn Marino 	base_cost = ALLOCNO_UPDATED_MEMORY_COST (a);
2352*e4b17023SJohn Marino       else if (allocno_costs == NULL)
2353*e4b17023SJohn Marino 	/* It means that assigning a hard register is not profitable
2354*e4b17023SJohn Marino 	   (we don't waste memory for hard register costs in this
2355*e4b17023SJohn Marino 	   case).  */
2356*e4b17023SJohn Marino 	continue;
2357*e4b17023SJohn Marino       else
2358*e4b17023SJohn Marino 	base_cost = allocno_costs[ira_class_hard_reg_index[aclass][hregno]];
2359*e4b17023SJohn Marino       try_p = false;
2360*e4b17023SJohn Marino       get_conflict_and_start_profitable_regs (a, false,
2361*e4b17023SJohn Marino 					      conflicting_regs,
2362*e4b17023SJohn Marino 					      &profitable_hard_regs);
2363*e4b17023SJohn Marino       class_size = ira_class_hard_regs_num[aclass];
2364*e4b17023SJohn Marino       /* Set up cost improvement for usage of each profitable hard
2365*e4b17023SJohn Marino 	 register for allocno A.  */
2366*e4b17023SJohn Marino       for (j = 0; j < class_size; j++)
2367*e4b17023SJohn Marino 	{
2368*e4b17023SJohn Marino 	  hregno = ira_class_hard_regs[aclass][j];
2369*e4b17023SJohn Marino 	  if (! check_hard_reg_p (a, hregno,
2370*e4b17023SJohn Marino 				  conflicting_regs, profitable_hard_regs))
2371*e4b17023SJohn Marino 	    continue;
2372*e4b17023SJohn Marino 	  ira_assert (ira_class_hard_reg_index[aclass][hregno] == j);
2373*e4b17023SJohn Marino 	  k = allocno_costs == NULL ? 0 : j;
2374*e4b17023SJohn Marino 	  costs[hregno] = (allocno_costs == NULL
2375*e4b17023SJohn Marino 			   ? ALLOCNO_UPDATED_CLASS_COST (a) : allocno_costs[k]);
2376*e4b17023SJohn Marino 	  costs[hregno] -= base_cost;
2377*e4b17023SJohn Marino 	  if (costs[hregno] < 0)
2378*e4b17023SJohn Marino 	    try_p = true;
2379*e4b17023SJohn Marino 	}
2380*e4b17023SJohn Marino       if (! try_p)
2381*e4b17023SJohn Marino 	/* There is no chance to improve the allocation cost by
2382*e4b17023SJohn Marino 	   assigning hard register to allocno A even without spilling
2383*e4b17023SJohn Marino 	   conflicting allocnos.  */
2384*e4b17023SJohn Marino 	continue;
2385*e4b17023SJohn Marino       mode = ALLOCNO_MODE (a);
2386*e4b17023SJohn Marino       nwords = ALLOCNO_NUM_OBJECTS (a);
2387*e4b17023SJohn Marino       /* Process each allocno conflicting with A and update the cost
2388*e4b17023SJohn Marino 	 improvement for profitable hard registers of A.  To use a
2389*e4b17023SJohn Marino 	 hard register for A we need to spill some conflicting
2390*e4b17023SJohn Marino 	 allocnos and that creates penalty for the cost
2391*e4b17023SJohn Marino 	 improvement.  */
2392*e4b17023SJohn Marino       for (word = 0; word < nwords; word++)
2393*e4b17023SJohn Marino 	{
2394*e4b17023SJohn Marino 	  ira_object_t conflict_obj;
2395*e4b17023SJohn Marino 	  ira_object_t obj = ALLOCNO_OBJECT (a, word);
2396*e4b17023SJohn Marino 	  ira_object_conflict_iterator oci;
2397*e4b17023SJohn Marino 
2398*e4b17023SJohn Marino 	  FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
2399*e4b17023SJohn Marino 	    {
2400*e4b17023SJohn Marino 	      ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
2401*e4b17023SJohn Marino 
2402*e4b17023SJohn Marino 	      if (ALLOCNO_COLOR_DATA (conflict_a)->temp == check)
2403*e4b17023SJohn Marino 		/* We already processed this conflicting allocno
2404*e4b17023SJohn Marino 		   because we processed earlier another object of the
2405*e4b17023SJohn Marino 		   conflicting allocno.  */
2406*e4b17023SJohn Marino 		continue;
2407*e4b17023SJohn Marino 	      ALLOCNO_COLOR_DATA (conflict_a)->temp = check;
2408*e4b17023SJohn Marino 	      if ((conflict_hregno = ALLOCNO_HARD_REGNO (conflict_a)) < 0)
2409*e4b17023SJohn Marino 		continue;
2410*e4b17023SJohn Marino 	      spill_cost = ALLOCNO_UPDATED_MEMORY_COST (conflict_a);
2411*e4b17023SJohn Marino 	      k = (ira_class_hard_reg_index
2412*e4b17023SJohn Marino 		   [ALLOCNO_CLASS (conflict_a)][conflict_hregno]);
2413*e4b17023SJohn Marino 	      ira_assert (k >= 0);
2414*e4b17023SJohn Marino 	      if ((allocno_costs = ALLOCNO_UPDATED_HARD_REG_COSTS (conflict_a))
2415*e4b17023SJohn Marino 		  != NULL)
2416*e4b17023SJohn Marino 		spill_cost -= allocno_costs[k];
2417*e4b17023SJohn Marino 	      else if ((allocno_costs = ALLOCNO_HARD_REG_COSTS (conflict_a))
2418*e4b17023SJohn Marino 		       != NULL)
2419*e4b17023SJohn Marino 		spill_cost -= allocno_costs[k];
2420*e4b17023SJohn Marino 	      else
2421*e4b17023SJohn Marino 		spill_cost -= ALLOCNO_UPDATED_CLASS_COST (conflict_a);
2422*e4b17023SJohn Marino 	      conflict_nregs
2423*e4b17023SJohn Marino 		= hard_regno_nregs[conflict_hregno][ALLOCNO_MODE (conflict_a)];
2424*e4b17023SJohn Marino 	      for (r = conflict_hregno;
2425*e4b17023SJohn Marino 		   r >= 0 && r + hard_regno_nregs[r][mode] > conflict_hregno;
2426*e4b17023SJohn Marino 		   r--)
2427*e4b17023SJohn Marino 		if (check_hard_reg_p (a, r,
2428*e4b17023SJohn Marino 				      conflicting_regs, profitable_hard_regs))
2429*e4b17023SJohn Marino 		  costs[r] += spill_cost;
2430*e4b17023SJohn Marino 	      for (r = conflict_hregno + 1;
2431*e4b17023SJohn Marino 		   r < conflict_hregno + conflict_nregs;
2432*e4b17023SJohn Marino 		   r++)
2433*e4b17023SJohn Marino 		if (check_hard_reg_p (a, r,
2434*e4b17023SJohn Marino 				      conflicting_regs, profitable_hard_regs))
2435*e4b17023SJohn Marino 		  costs[r] += spill_cost;
2436*e4b17023SJohn Marino 	    }
2437*e4b17023SJohn Marino 	}
2438*e4b17023SJohn Marino       min_cost = INT_MAX;
2439*e4b17023SJohn Marino       best = -1;
2440*e4b17023SJohn Marino       /* Now we choose hard register for A which results in highest
2441*e4b17023SJohn Marino 	 allocation cost improvement.  */
2442*e4b17023SJohn Marino       for (j = 0; j < class_size; j++)
2443*e4b17023SJohn Marino 	{
2444*e4b17023SJohn Marino 	  hregno = ira_class_hard_regs[aclass][j];
2445*e4b17023SJohn Marino 	  if (check_hard_reg_p (a, hregno,
2446*e4b17023SJohn Marino 				conflicting_regs, profitable_hard_regs)
2447*e4b17023SJohn Marino 	      && min_cost > costs[hregno])
2448*e4b17023SJohn Marino 	    {
2449*e4b17023SJohn Marino 	      best = hregno;
2450*e4b17023SJohn Marino 	      min_cost = costs[hregno];
2451*e4b17023SJohn Marino 	    }
2452*e4b17023SJohn Marino 	}
2453*e4b17023SJohn Marino       if (min_cost >= 0)
2454*e4b17023SJohn Marino 	/* We are in a situation when assigning any hard register to A
2455*e4b17023SJohn Marino 	   by spilling some conflicting allocnos does not improve the
2456*e4b17023SJohn Marino 	   allocation cost.  */
2457*e4b17023SJohn Marino 	continue;
2458*e4b17023SJohn Marino       nregs = hard_regno_nregs[best][mode];
2459*e4b17023SJohn Marino       /* Now spill conflicting allocnos which contain a hard register
2460*e4b17023SJohn Marino 	 of A when we assign the best chosen hard register to it.  */
2461*e4b17023SJohn Marino       for (word = 0; word < nwords; word++)
2462*e4b17023SJohn Marino 	{
2463*e4b17023SJohn Marino 	  ira_object_t conflict_obj;
2464*e4b17023SJohn Marino 	  ira_object_t obj = ALLOCNO_OBJECT (a, word);
2465*e4b17023SJohn Marino 	  ira_object_conflict_iterator oci;
2466*e4b17023SJohn Marino 
2467*e4b17023SJohn Marino 	  FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
2468*e4b17023SJohn Marino 	    {
2469*e4b17023SJohn Marino 	      ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
2470*e4b17023SJohn Marino 
2471*e4b17023SJohn Marino 	      if ((conflict_hregno = ALLOCNO_HARD_REGNO (conflict_a)) < 0)
2472*e4b17023SJohn Marino 		continue;
2473*e4b17023SJohn Marino 	      conflict_nregs
2474*e4b17023SJohn Marino 		= hard_regno_nregs[conflict_hregno][ALLOCNO_MODE (conflict_a)];
2475*e4b17023SJohn Marino 	      if (best + nregs <= conflict_hregno
2476*e4b17023SJohn Marino 		  || conflict_hregno + conflict_nregs <= best)
2477*e4b17023SJohn Marino 		/* No intersection.  */
2478*e4b17023SJohn Marino 		continue;
2479*e4b17023SJohn Marino 	      ALLOCNO_HARD_REGNO (conflict_a) = -1;
2480*e4b17023SJohn Marino 	      sorted_allocnos[n++] = conflict_a;
2481*e4b17023SJohn Marino 	      if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
2482*e4b17023SJohn Marino 		fprintf (ira_dump_file, "Spilling a%dr%d for a%dr%d\n",
2483*e4b17023SJohn Marino 			 ALLOCNO_NUM (conflict_a), ALLOCNO_REGNO (conflict_a),
2484*e4b17023SJohn Marino 			 ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
2485*e4b17023SJohn Marino 	    }
2486*e4b17023SJohn Marino 	}
2487*e4b17023SJohn Marino       /* Assign the best chosen hard register to A.  */
2488*e4b17023SJohn Marino       ALLOCNO_HARD_REGNO (a) = best;
2489*e4b17023SJohn Marino       if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
2490*e4b17023SJohn Marino 	fprintf (ira_dump_file, "Assigning %d to a%dr%d\n",
2491*e4b17023SJohn Marino 		 best, ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
2492*e4b17023SJohn Marino     }
2493*e4b17023SJohn Marino   if (n == 0)
2494*e4b17023SJohn Marino     return;
2495*e4b17023SJohn Marino   /* We spilled some allocnos to assign their hard registers to other
2496*e4b17023SJohn Marino      allocnos.  The spilled allocnos are now in array
2497*e4b17023SJohn Marino      'sorted_allocnos'.  There is still a possibility that some of the
2498*e4b17023SJohn Marino      spilled allocnos can get hard registers.  So let us try assign
2499*e4b17023SJohn Marino      them hard registers again (just a reminder -- function
2500*e4b17023SJohn Marino      'assign_hard_reg' assigns hard registers only if it is possible
2501*e4b17023SJohn Marino      and profitable).  We process the spilled allocnos with biggest
2502*e4b17023SJohn Marino      benefit to get hard register first -- see function
2503*e4b17023SJohn Marino      'allocno_cost_compare_func'.  */
2504*e4b17023SJohn Marino   qsort (sorted_allocnos, n, sizeof (ira_allocno_t),
2505*e4b17023SJohn Marino 	 allocno_cost_compare_func);
2506*e4b17023SJohn Marino   for (j = 0; j < n; j++)
2507*e4b17023SJohn Marino     {
2508*e4b17023SJohn Marino       a = sorted_allocnos[j];
2509*e4b17023SJohn Marino       ALLOCNO_ASSIGNED_P (a) = false;
2510*e4b17023SJohn Marino       if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
2511*e4b17023SJohn Marino 	{
2512*e4b17023SJohn Marino 	  fprintf (ira_dump_file, "      ");
2513*e4b17023SJohn Marino 	  ira_print_expanded_allocno (a);
2514*e4b17023SJohn Marino 	  fprintf (ira_dump_file, "  -- ");
2515*e4b17023SJohn Marino 	}
2516*e4b17023SJohn Marino       if (assign_hard_reg (a, false))
2517*e4b17023SJohn Marino 	{
2518*e4b17023SJohn Marino 	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
2519*e4b17023SJohn Marino 	    fprintf (ira_dump_file, "assign hard reg %d\n",
2520*e4b17023SJohn Marino 		     ALLOCNO_HARD_REGNO (a));
2521*e4b17023SJohn Marino 	}
2522*e4b17023SJohn Marino       else
2523*e4b17023SJohn Marino 	{
2524*e4b17023SJohn Marino 	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
2525*e4b17023SJohn Marino 	    fprintf (ira_dump_file, "assign memory\n");
2526*e4b17023SJohn Marino 	}
2527*e4b17023SJohn Marino     }
2528*e4b17023SJohn Marino }
2529*e4b17023SJohn Marino 
2530*e4b17023SJohn Marino /* Sort allocnos according to their priorities which are calculated
2531*e4b17023SJohn Marino    analogous to ones in file `global.c'.  */
2532*e4b17023SJohn Marino static int
allocno_priority_compare_func(const void * v1p,const void * v2p)2533*e4b17023SJohn Marino allocno_priority_compare_func (const void *v1p, const void *v2p)
2534*e4b17023SJohn Marino {
2535*e4b17023SJohn Marino   ira_allocno_t a1 = *(const ira_allocno_t *) v1p;
2536*e4b17023SJohn Marino   ira_allocno_t a2 = *(const ira_allocno_t *) v2p;
2537*e4b17023SJohn Marino   int pri1, pri2;
2538*e4b17023SJohn Marino 
2539*e4b17023SJohn Marino   pri1 = allocno_priorities[ALLOCNO_NUM (a1)];
2540*e4b17023SJohn Marino   pri2 = allocno_priorities[ALLOCNO_NUM (a2)];
2541*e4b17023SJohn Marino   if (pri2 != pri1)
2542*e4b17023SJohn Marino     return SORTGT (pri2, pri1);
2543*e4b17023SJohn Marino 
2544*e4b17023SJohn Marino   /* If regs are equally good, sort by allocnos, so that the results of
2545*e4b17023SJohn Marino      qsort leave nothing to chance.  */
2546*e4b17023SJohn Marino   return ALLOCNO_NUM (a1) - ALLOCNO_NUM (a2);
2547*e4b17023SJohn Marino }
2548*e4b17023SJohn Marino 
2549*e4b17023SJohn Marino /* Chaitin-Briggs coloring for allocnos in COLORING_ALLOCNO_BITMAP
2550*e4b17023SJohn Marino    taking into account allocnos in CONSIDERATION_ALLOCNO_BITMAP.  */
2551*e4b17023SJohn Marino static void
color_allocnos(void)2552*e4b17023SJohn Marino color_allocnos (void)
2553*e4b17023SJohn Marino {
2554*e4b17023SJohn Marino   unsigned int i, n;
2555*e4b17023SJohn Marino   bitmap_iterator bi;
2556*e4b17023SJohn Marino   ira_allocno_t a;
2557*e4b17023SJohn Marino 
2558*e4b17023SJohn Marino   setup_profitable_hard_regs ();
2559*e4b17023SJohn Marino   if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY)
2560*e4b17023SJohn Marino     {
2561*e4b17023SJohn Marino       n = 0;
2562*e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
2563*e4b17023SJohn Marino 	{
2564*e4b17023SJohn Marino 	  a = ira_allocnos[i];
2565*e4b17023SJohn Marino 	  if (ALLOCNO_CLASS (a) == NO_REGS)
2566*e4b17023SJohn Marino 	    {
2567*e4b17023SJohn Marino 	      ALLOCNO_HARD_REGNO (a) = -1;
2568*e4b17023SJohn Marino 	      ALLOCNO_ASSIGNED_P (a) = true;
2569*e4b17023SJohn Marino 	      ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL);
2570*e4b17023SJohn Marino 	      ira_assert (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) == NULL);
2571*e4b17023SJohn Marino 	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
2572*e4b17023SJohn Marino 		{
2573*e4b17023SJohn Marino 		  fprintf (ira_dump_file, "      Spill");
2574*e4b17023SJohn Marino 		  ira_print_expanded_allocno (a);
2575*e4b17023SJohn Marino 		  fprintf (ira_dump_file, "\n");
2576*e4b17023SJohn Marino 		}
2577*e4b17023SJohn Marino 	      continue;
2578*e4b17023SJohn Marino 	    }
2579*e4b17023SJohn Marino 	  sorted_allocnos[n++] = a;
2580*e4b17023SJohn Marino 	}
2581*e4b17023SJohn Marino       if (n != 0)
2582*e4b17023SJohn Marino 	{
2583*e4b17023SJohn Marino 	  setup_allocno_priorities (sorted_allocnos, n);
2584*e4b17023SJohn Marino 	  qsort (sorted_allocnos, n, sizeof (ira_allocno_t),
2585*e4b17023SJohn Marino 		 allocno_priority_compare_func);
2586*e4b17023SJohn Marino 	  for (i = 0; i < n; i++)
2587*e4b17023SJohn Marino 	    {
2588*e4b17023SJohn Marino 	      a = sorted_allocnos[i];
2589*e4b17023SJohn Marino 	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
2590*e4b17023SJohn Marino 		{
2591*e4b17023SJohn Marino 		  fprintf (ira_dump_file, "      ");
2592*e4b17023SJohn Marino 		  ira_print_expanded_allocno (a);
2593*e4b17023SJohn Marino 		  fprintf (ira_dump_file, "  -- ");
2594*e4b17023SJohn Marino 		}
2595*e4b17023SJohn Marino 	      if (assign_hard_reg (a, false))
2596*e4b17023SJohn Marino 		{
2597*e4b17023SJohn Marino 		  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
2598*e4b17023SJohn Marino 		    fprintf (ira_dump_file, "assign hard reg %d\n",
2599*e4b17023SJohn Marino 			     ALLOCNO_HARD_REGNO (a));
2600*e4b17023SJohn Marino 		}
2601*e4b17023SJohn Marino 	      else
2602*e4b17023SJohn Marino 		{
2603*e4b17023SJohn Marino 		  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
2604*e4b17023SJohn Marino 		    fprintf (ira_dump_file, "assign memory\n");
2605*e4b17023SJohn Marino 		}
2606*e4b17023SJohn Marino 	    }
2607*e4b17023SJohn Marino 	}
2608*e4b17023SJohn Marino     }
2609*e4b17023SJohn Marino   else
2610*e4b17023SJohn Marino     {
2611*e4b17023SJohn Marino       form_allocno_hard_regs_nodes_forest ();
2612*e4b17023SJohn Marino       if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
2613*e4b17023SJohn Marino 	print_hard_regs_forest (ira_dump_file);
2614*e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
2615*e4b17023SJohn Marino 	{
2616*e4b17023SJohn Marino 	  a = ira_allocnos[i];
2617*e4b17023SJohn Marino 	  if (ALLOCNO_CLASS (a) != NO_REGS && ! empty_profitable_hard_regs (a))
2618*e4b17023SJohn Marino 	    ALLOCNO_COLOR_DATA (a)->in_graph_p = true;
2619*e4b17023SJohn Marino 	  else
2620*e4b17023SJohn Marino 	    {
2621*e4b17023SJohn Marino 	      ALLOCNO_HARD_REGNO (a) = -1;
2622*e4b17023SJohn Marino 	      ALLOCNO_ASSIGNED_P (a) = true;
2623*e4b17023SJohn Marino 	      /* We don't need updated costs anymore.  */
2624*e4b17023SJohn Marino 	      ira_free_allocno_updated_costs (a);
2625*e4b17023SJohn Marino 	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
2626*e4b17023SJohn Marino 		{
2627*e4b17023SJohn Marino 		  fprintf (ira_dump_file, "      Spill");
2628*e4b17023SJohn Marino 		  ira_print_expanded_allocno (a);
2629*e4b17023SJohn Marino 		  fprintf (ira_dump_file, "\n");
2630*e4b17023SJohn Marino 		}
2631*e4b17023SJohn Marino 	    }
2632*e4b17023SJohn Marino 	}
2633*e4b17023SJohn Marino       /* Put the allocnos into the corresponding buckets.  */
2634*e4b17023SJohn Marino       colorable_allocno_bucket = NULL;
2635*e4b17023SJohn Marino       uncolorable_allocno_bucket = NULL;
2636*e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
2637*e4b17023SJohn Marino 	{
2638*e4b17023SJohn Marino 	  a = ira_allocnos[i];
2639*e4b17023SJohn Marino 	  if (ALLOCNO_COLOR_DATA (a)->in_graph_p)
2640*e4b17023SJohn Marino 	    put_allocno_into_bucket (a);
2641*e4b17023SJohn Marino 	}
2642*e4b17023SJohn Marino       push_allocnos_to_stack ();
2643*e4b17023SJohn Marino       pop_allocnos_from_stack ();
2644*e4b17023SJohn Marino       finish_allocno_hard_regs_nodes_forest ();
2645*e4b17023SJohn Marino     }
2646*e4b17023SJohn Marino   improve_allocation ();
2647*e4b17023SJohn Marino }
2648*e4b17023SJohn Marino 
2649*e4b17023SJohn Marino 
2650*e4b17023SJohn Marino 
2651*e4b17023SJohn Marino /* Output information about the loop given by its LOOP_TREE_NODE. */
2652*e4b17023SJohn Marino static void
print_loop_title(ira_loop_tree_node_t loop_tree_node)2653*e4b17023SJohn Marino print_loop_title (ira_loop_tree_node_t loop_tree_node)
2654*e4b17023SJohn Marino {
2655*e4b17023SJohn Marino   unsigned int j;
2656*e4b17023SJohn Marino   bitmap_iterator bi;
2657*e4b17023SJohn Marino   ira_loop_tree_node_t subloop_node, dest_loop_node;
2658*e4b17023SJohn Marino   edge e;
2659*e4b17023SJohn Marino   edge_iterator ei;
2660*e4b17023SJohn Marino 
2661*e4b17023SJohn Marino   if (loop_tree_node->parent == NULL)
2662*e4b17023SJohn Marino     fprintf (ira_dump_file,
2663*e4b17023SJohn Marino 	     "\n  Loop 0 (parent -1, header bb%d, depth 0)\n    bbs:",
2664*e4b17023SJohn Marino 	     NUM_FIXED_BLOCKS);
2665*e4b17023SJohn Marino   else
2666*e4b17023SJohn Marino     {
2667*e4b17023SJohn Marino       ira_assert (current_loops != NULL && loop_tree_node->loop != NULL);
2668*e4b17023SJohn Marino       fprintf (ira_dump_file,
2669*e4b17023SJohn Marino 	       "\n  Loop %d (parent %d, header bb%d, depth %d)\n    bbs:",
2670*e4b17023SJohn Marino 	       loop_tree_node->loop_num, loop_tree_node->parent->loop_num,
2671*e4b17023SJohn Marino 	       loop_tree_node->loop->header->index,
2672*e4b17023SJohn Marino 	       loop_depth (loop_tree_node->loop));
2673*e4b17023SJohn Marino     }
2674*e4b17023SJohn Marino   for (subloop_node = loop_tree_node->children;
2675*e4b17023SJohn Marino        subloop_node != NULL;
2676*e4b17023SJohn Marino        subloop_node = subloop_node->next)
2677*e4b17023SJohn Marino     if (subloop_node->bb != NULL)
2678*e4b17023SJohn Marino       {
2679*e4b17023SJohn Marino 	fprintf (ira_dump_file, " %d", subloop_node->bb->index);
2680*e4b17023SJohn Marino 	FOR_EACH_EDGE (e, ei, subloop_node->bb->succs)
2681*e4b17023SJohn Marino 	  if (e->dest != EXIT_BLOCK_PTR
2682*e4b17023SJohn Marino 	      && ((dest_loop_node = IRA_BB_NODE (e->dest)->parent)
2683*e4b17023SJohn Marino 		  != loop_tree_node))
2684*e4b17023SJohn Marino 	    fprintf (ira_dump_file, "(->%d:l%d)",
2685*e4b17023SJohn Marino 		     e->dest->index, dest_loop_node->loop_num);
2686*e4b17023SJohn Marino       }
2687*e4b17023SJohn Marino   fprintf (ira_dump_file, "\n    all:");
2688*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (loop_tree_node->all_allocnos, 0, j, bi)
2689*e4b17023SJohn Marino     fprintf (ira_dump_file, " %dr%d", j, ALLOCNO_REGNO (ira_allocnos[j]));
2690*e4b17023SJohn Marino   fprintf (ira_dump_file, "\n    modified regnos:");
2691*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (loop_tree_node->modified_regnos, 0, j, bi)
2692*e4b17023SJohn Marino     fprintf (ira_dump_file, " %d", j);
2693*e4b17023SJohn Marino   fprintf (ira_dump_file, "\n    border:");
2694*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (loop_tree_node->border_allocnos, 0, j, bi)
2695*e4b17023SJohn Marino     fprintf (ira_dump_file, " %dr%d", j, ALLOCNO_REGNO (ira_allocnos[j]));
2696*e4b17023SJohn Marino   fprintf (ira_dump_file, "\n    Pressure:");
2697*e4b17023SJohn Marino   for (j = 0; (int) j < ira_pressure_classes_num; j++)
2698*e4b17023SJohn Marino     {
2699*e4b17023SJohn Marino       enum reg_class pclass;
2700*e4b17023SJohn Marino 
2701*e4b17023SJohn Marino       pclass = ira_pressure_classes[j];
2702*e4b17023SJohn Marino       if (loop_tree_node->reg_pressure[pclass] == 0)
2703*e4b17023SJohn Marino 	continue;
2704*e4b17023SJohn Marino       fprintf (ira_dump_file, " %s=%d", reg_class_names[pclass],
2705*e4b17023SJohn Marino 	       loop_tree_node->reg_pressure[pclass]);
2706*e4b17023SJohn Marino     }
2707*e4b17023SJohn Marino   fprintf (ira_dump_file, "\n");
2708*e4b17023SJohn Marino }
2709*e4b17023SJohn Marino 
2710*e4b17023SJohn Marino /* Color the allocnos inside loop (in the extreme case it can be all
2711*e4b17023SJohn Marino    of the function) given the corresponding LOOP_TREE_NODE.  The
2712*e4b17023SJohn Marino    function is called for each loop during top-down traverse of the
2713*e4b17023SJohn Marino    loop tree.  */
2714*e4b17023SJohn Marino static void
color_pass(ira_loop_tree_node_t loop_tree_node)2715*e4b17023SJohn Marino color_pass (ira_loop_tree_node_t loop_tree_node)
2716*e4b17023SJohn Marino {
2717*e4b17023SJohn Marino   int regno, hard_regno, index = -1, n;
2718*e4b17023SJohn Marino   int cost, exit_freq, enter_freq;
2719*e4b17023SJohn Marino   unsigned int j;
2720*e4b17023SJohn Marino   bitmap_iterator bi;
2721*e4b17023SJohn Marino   enum machine_mode mode;
2722*e4b17023SJohn Marino   enum reg_class rclass, aclass, pclass;
2723*e4b17023SJohn Marino   ira_allocno_t a, subloop_allocno;
2724*e4b17023SJohn Marino   ira_loop_tree_node_t subloop_node;
2725*e4b17023SJohn Marino 
2726*e4b17023SJohn Marino   ira_assert (loop_tree_node->bb == NULL);
2727*e4b17023SJohn Marino   if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL)
2728*e4b17023SJohn Marino     print_loop_title (loop_tree_node);
2729*e4b17023SJohn Marino 
2730*e4b17023SJohn Marino   bitmap_copy (coloring_allocno_bitmap, loop_tree_node->all_allocnos);
2731*e4b17023SJohn Marino   bitmap_copy (consideration_allocno_bitmap, coloring_allocno_bitmap);
2732*e4b17023SJohn Marino   n = 0;
2733*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, j, bi)
2734*e4b17023SJohn Marino     {
2735*e4b17023SJohn Marino       a = ira_allocnos[j];
2736*e4b17023SJohn Marino       n++;
2737*e4b17023SJohn Marino       if (! ALLOCNO_ASSIGNED_P (a))
2738*e4b17023SJohn Marino 	continue;
2739*e4b17023SJohn Marino       bitmap_clear_bit (coloring_allocno_bitmap, ALLOCNO_NUM (a));
2740*e4b17023SJohn Marino     }
2741*e4b17023SJohn Marino   allocno_color_data
2742*e4b17023SJohn Marino     = (allocno_color_data_t) ira_allocate (sizeof (struct allocno_color_data)
2743*e4b17023SJohn Marino 					   * n);
2744*e4b17023SJohn Marino   memset (allocno_color_data, 0, sizeof (struct allocno_color_data) * n);
2745*e4b17023SJohn Marino   curr_allocno_process = 0;
2746*e4b17023SJohn Marino   n = 0;
2747*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, j, bi)
2748*e4b17023SJohn Marino     {
2749*e4b17023SJohn Marino       a = ira_allocnos[j];
2750*e4b17023SJohn Marino       ALLOCNO_ADD_DATA (a) = allocno_color_data + n;
2751*e4b17023SJohn Marino       n++;
2752*e4b17023SJohn Marino     }
2753*e4b17023SJohn Marino   /* Color all mentioned allocnos including transparent ones.  */
2754*e4b17023SJohn Marino   color_allocnos ();
2755*e4b17023SJohn Marino   /* Process caps.  They are processed just once.  */
2756*e4b17023SJohn Marino   if (flag_ira_region == IRA_REGION_MIXED
2757*e4b17023SJohn Marino       || flag_ira_region == IRA_REGION_ALL)
2758*e4b17023SJohn Marino     EXECUTE_IF_SET_IN_BITMAP (loop_tree_node->all_allocnos, 0, j, bi)
2759*e4b17023SJohn Marino       {
2760*e4b17023SJohn Marino 	a = ira_allocnos[j];
2761*e4b17023SJohn Marino 	if (ALLOCNO_CAP_MEMBER (a) == NULL)
2762*e4b17023SJohn Marino 	  continue;
2763*e4b17023SJohn Marino 	/* Remove from processing in the next loop.  */
2764*e4b17023SJohn Marino 	bitmap_clear_bit (consideration_allocno_bitmap, j);
2765*e4b17023SJohn Marino 	rclass = ALLOCNO_CLASS (a);
2766*e4b17023SJohn Marino 	pclass = ira_pressure_class_translate[rclass];
2767*e4b17023SJohn Marino 	if (flag_ira_region == IRA_REGION_MIXED
2768*e4b17023SJohn Marino 	    && (loop_tree_node->reg_pressure[pclass]
2769*e4b17023SJohn Marino 		<= ira_available_class_regs[pclass]))
2770*e4b17023SJohn Marino 	  {
2771*e4b17023SJohn Marino 	    mode = ALLOCNO_MODE (a);
2772*e4b17023SJohn Marino 	    hard_regno = ALLOCNO_HARD_REGNO (a);
2773*e4b17023SJohn Marino 	    if (hard_regno >= 0)
2774*e4b17023SJohn Marino 	      {
2775*e4b17023SJohn Marino 		index = ira_class_hard_reg_index[rclass][hard_regno];
2776*e4b17023SJohn Marino 		ira_assert (index >= 0);
2777*e4b17023SJohn Marino 	      }
2778*e4b17023SJohn Marino 	    regno = ALLOCNO_REGNO (a);
2779*e4b17023SJohn Marino 	    subloop_allocno = ALLOCNO_CAP_MEMBER (a);
2780*e4b17023SJohn Marino 	    subloop_node = ALLOCNO_LOOP_TREE_NODE (subloop_allocno);
2781*e4b17023SJohn Marino 	    ira_assert (!ALLOCNO_ASSIGNED_P (subloop_allocno));
2782*e4b17023SJohn Marino 	    ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
2783*e4b17023SJohn Marino 	    ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
2784*e4b17023SJohn Marino 	    if (hard_regno >= 0)
2785*e4b17023SJohn Marino 	      update_copy_costs (subloop_allocno, true);
2786*e4b17023SJohn Marino 	    /* We don't need updated costs anymore: */
2787*e4b17023SJohn Marino 	    ira_free_allocno_updated_costs (subloop_allocno);
2788*e4b17023SJohn Marino 	  }
2789*e4b17023SJohn Marino       }
2790*e4b17023SJohn Marino   /* Update costs of the corresponding allocnos (not caps) in the
2791*e4b17023SJohn Marino      subloops.  */
2792*e4b17023SJohn Marino   for (subloop_node = loop_tree_node->subloops;
2793*e4b17023SJohn Marino        subloop_node != NULL;
2794*e4b17023SJohn Marino        subloop_node = subloop_node->subloop_next)
2795*e4b17023SJohn Marino     {
2796*e4b17023SJohn Marino       ira_assert (subloop_node->bb == NULL);
2797*e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, j, bi)
2798*e4b17023SJohn Marino         {
2799*e4b17023SJohn Marino 	  a = ira_allocnos[j];
2800*e4b17023SJohn Marino 	  ira_assert (ALLOCNO_CAP_MEMBER (a) == NULL);
2801*e4b17023SJohn Marino 	  mode = ALLOCNO_MODE (a);
2802*e4b17023SJohn Marino 	  rclass = ALLOCNO_CLASS (a);
2803*e4b17023SJohn Marino 	  pclass = ira_pressure_class_translate[rclass];
2804*e4b17023SJohn Marino 	  hard_regno = ALLOCNO_HARD_REGNO (a);
2805*e4b17023SJohn Marino 	  /* Use hard register class here.  ??? */
2806*e4b17023SJohn Marino 	  if (hard_regno >= 0)
2807*e4b17023SJohn Marino 	    {
2808*e4b17023SJohn Marino 	      index = ira_class_hard_reg_index[rclass][hard_regno];
2809*e4b17023SJohn Marino 	      ira_assert (index >= 0);
2810*e4b17023SJohn Marino 	    }
2811*e4b17023SJohn Marino 	  regno = ALLOCNO_REGNO (a);
2812*e4b17023SJohn Marino 	  /* ??? conflict costs */
2813*e4b17023SJohn Marino 	  subloop_allocno = subloop_node->regno_allocno_map[regno];
2814*e4b17023SJohn Marino 	  if (subloop_allocno == NULL
2815*e4b17023SJohn Marino 	      || ALLOCNO_CAP (subloop_allocno) != NULL)
2816*e4b17023SJohn Marino 	    continue;
2817*e4b17023SJohn Marino 	  ira_assert (ALLOCNO_CLASS (subloop_allocno) == rclass);
2818*e4b17023SJohn Marino 	  ira_assert (bitmap_bit_p (subloop_node->all_allocnos,
2819*e4b17023SJohn Marino 				    ALLOCNO_NUM (subloop_allocno)));
2820*e4b17023SJohn Marino 	  if ((flag_ira_region == IRA_REGION_MIXED)
2821*e4b17023SJohn Marino 	      && (loop_tree_node->reg_pressure[pclass]
2822*e4b17023SJohn Marino 		  <= ira_available_class_regs[pclass]))
2823*e4b17023SJohn Marino 	    {
2824*e4b17023SJohn Marino 	      if (! ALLOCNO_ASSIGNED_P (subloop_allocno))
2825*e4b17023SJohn Marino 		{
2826*e4b17023SJohn Marino 		  ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
2827*e4b17023SJohn Marino 		  ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
2828*e4b17023SJohn Marino 		  if (hard_regno >= 0)
2829*e4b17023SJohn Marino 		    update_copy_costs (subloop_allocno, true);
2830*e4b17023SJohn Marino 		  /* We don't need updated costs anymore: */
2831*e4b17023SJohn Marino 		  ira_free_allocno_updated_costs (subloop_allocno);
2832*e4b17023SJohn Marino 		}
2833*e4b17023SJohn Marino 	      continue;
2834*e4b17023SJohn Marino 	    }
2835*e4b17023SJohn Marino 	  exit_freq = ira_loop_edge_freq (subloop_node, regno, true);
2836*e4b17023SJohn Marino 	  enter_freq = ira_loop_edge_freq (subloop_node, regno, false);
2837*e4b17023SJohn Marino 	  ira_assert (regno < ira_reg_equiv_len);
2838*e4b17023SJohn Marino 	  if (ira_reg_equiv_invariant_p[regno]
2839*e4b17023SJohn Marino 	      || ira_reg_equiv_const[regno] != NULL_RTX)
2840*e4b17023SJohn Marino 	    {
2841*e4b17023SJohn Marino 	      if (! ALLOCNO_ASSIGNED_P (subloop_allocno))
2842*e4b17023SJohn Marino 		{
2843*e4b17023SJohn Marino 		  ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
2844*e4b17023SJohn Marino 		  ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
2845*e4b17023SJohn Marino 		  if (hard_regno >= 0)
2846*e4b17023SJohn Marino 		    update_copy_costs (subloop_allocno, true);
2847*e4b17023SJohn Marino 		  /* We don't need updated costs anymore: */
2848*e4b17023SJohn Marino 		  ira_free_allocno_updated_costs (subloop_allocno);
2849*e4b17023SJohn Marino 		}
2850*e4b17023SJohn Marino 	    }
2851*e4b17023SJohn Marino 	  else if (hard_regno < 0)
2852*e4b17023SJohn Marino 	    {
2853*e4b17023SJohn Marino 	      ALLOCNO_UPDATED_MEMORY_COST (subloop_allocno)
2854*e4b17023SJohn Marino 		-= ((ira_memory_move_cost[mode][rclass][1] * enter_freq)
2855*e4b17023SJohn Marino 		    + (ira_memory_move_cost[mode][rclass][0] * exit_freq));
2856*e4b17023SJohn Marino 	    }
2857*e4b17023SJohn Marino 	  else
2858*e4b17023SJohn Marino 	    {
2859*e4b17023SJohn Marino 	      aclass = ALLOCNO_CLASS (subloop_allocno);
2860*e4b17023SJohn Marino 	      ira_init_register_move_cost_if_necessary (mode);
2861*e4b17023SJohn Marino 	      cost = (ira_register_move_cost[mode][rclass][rclass]
2862*e4b17023SJohn Marino 		      * (exit_freq + enter_freq));
2863*e4b17023SJohn Marino 	      ira_allocate_and_set_or_copy_costs
2864*e4b17023SJohn Marino 		(&ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno), aclass,
2865*e4b17023SJohn Marino 		 ALLOCNO_UPDATED_CLASS_COST (subloop_allocno),
2866*e4b17023SJohn Marino 		 ALLOCNO_HARD_REG_COSTS (subloop_allocno));
2867*e4b17023SJohn Marino 	      ira_allocate_and_set_or_copy_costs
2868*e4b17023SJohn Marino 		(&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (subloop_allocno),
2869*e4b17023SJohn Marino 		 aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (subloop_allocno));
2870*e4b17023SJohn Marino 	      ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno)[index] -= cost;
2871*e4b17023SJohn Marino 	      ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (subloop_allocno)[index]
2872*e4b17023SJohn Marino 		-= cost;
2873*e4b17023SJohn Marino 	      if (ALLOCNO_UPDATED_CLASS_COST (subloop_allocno)
2874*e4b17023SJohn Marino 		  > ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno)[index])
2875*e4b17023SJohn Marino 		ALLOCNO_UPDATED_CLASS_COST (subloop_allocno)
2876*e4b17023SJohn Marino 		  = ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno)[index];
2877*e4b17023SJohn Marino 	      ALLOCNO_UPDATED_MEMORY_COST (subloop_allocno)
2878*e4b17023SJohn Marino 		+= (ira_memory_move_cost[mode][rclass][0] * enter_freq
2879*e4b17023SJohn Marino 		    + ira_memory_move_cost[mode][rclass][1] * exit_freq);
2880*e4b17023SJohn Marino 	    }
2881*e4b17023SJohn Marino 	}
2882*e4b17023SJohn Marino     }
2883*e4b17023SJohn Marino   ira_free (allocno_color_data);
2884*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, j, bi)
2885*e4b17023SJohn Marino     {
2886*e4b17023SJohn Marino       a = ira_allocnos[j];
2887*e4b17023SJohn Marino       ALLOCNO_ADD_DATA (a) = NULL;
2888*e4b17023SJohn Marino     }
2889*e4b17023SJohn Marino }
2890*e4b17023SJohn Marino 
2891*e4b17023SJohn Marino /* Initialize the common data for coloring and calls functions to do
2892*e4b17023SJohn Marino    Chaitin-Briggs and regional coloring.  */
2893*e4b17023SJohn Marino static void
do_coloring(void)2894*e4b17023SJohn Marino do_coloring (void)
2895*e4b17023SJohn Marino {
2896*e4b17023SJohn Marino   coloring_allocno_bitmap = ira_allocate_bitmap ();
2897*e4b17023SJohn Marino   if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
2898*e4b17023SJohn Marino     fprintf (ira_dump_file, "\n**** Allocnos coloring:\n\n");
2899*e4b17023SJohn Marino 
2900*e4b17023SJohn Marino   ira_traverse_loop_tree (false, ira_loop_tree_root, color_pass, NULL);
2901*e4b17023SJohn Marino 
2902*e4b17023SJohn Marino   if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL)
2903*e4b17023SJohn Marino     ira_print_disposition (ira_dump_file);
2904*e4b17023SJohn Marino 
2905*e4b17023SJohn Marino   ira_free_bitmap (coloring_allocno_bitmap);
2906*e4b17023SJohn Marino }
2907*e4b17023SJohn Marino 
2908*e4b17023SJohn Marino 
2909*e4b17023SJohn Marino 
2910*e4b17023SJohn Marino /* Move spill/restore code, which are to be generated in ira-emit.c,
2911*e4b17023SJohn Marino    to less frequent points (if it is profitable) by reassigning some
2912*e4b17023SJohn Marino    allocnos (in loop with subloops containing in another loop) to
2913*e4b17023SJohn Marino    memory which results in longer live-range where the corresponding
2914*e4b17023SJohn Marino    pseudo-registers will be in memory.  */
2915*e4b17023SJohn Marino static void
move_spill_restore(void)2916*e4b17023SJohn Marino move_spill_restore (void)
2917*e4b17023SJohn Marino {
2918*e4b17023SJohn Marino   int cost, regno, hard_regno, hard_regno2, index;
2919*e4b17023SJohn Marino   bool changed_p;
2920*e4b17023SJohn Marino   int enter_freq, exit_freq;
2921*e4b17023SJohn Marino   enum machine_mode mode;
2922*e4b17023SJohn Marino   enum reg_class rclass;
2923*e4b17023SJohn Marino   ira_allocno_t a, parent_allocno, subloop_allocno;
2924*e4b17023SJohn Marino   ira_loop_tree_node_t parent, loop_node, subloop_node;
2925*e4b17023SJohn Marino   ira_allocno_iterator ai;
2926*e4b17023SJohn Marino 
2927*e4b17023SJohn Marino   for (;;)
2928*e4b17023SJohn Marino     {
2929*e4b17023SJohn Marino       changed_p = false;
2930*e4b17023SJohn Marino       if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
2931*e4b17023SJohn Marino 	fprintf (ira_dump_file, "New iteration of spill/restore move\n");
2932*e4b17023SJohn Marino       FOR_EACH_ALLOCNO (a, ai)
2933*e4b17023SJohn Marino 	{
2934*e4b17023SJohn Marino 	  regno = ALLOCNO_REGNO (a);
2935*e4b17023SJohn Marino 	  loop_node = ALLOCNO_LOOP_TREE_NODE (a);
2936*e4b17023SJohn Marino 	  if (ALLOCNO_CAP_MEMBER (a) != NULL
2937*e4b17023SJohn Marino 	      || ALLOCNO_CAP (a) != NULL
2938*e4b17023SJohn Marino 	      || (hard_regno = ALLOCNO_HARD_REGNO (a)) < 0
2939*e4b17023SJohn Marino 	      || loop_node->children == NULL
2940*e4b17023SJohn Marino 	      /* don't do the optimization because it can create
2941*e4b17023SJohn Marino 		 copies and the reload pass can spill the allocno set
2942*e4b17023SJohn Marino 		 by copy although the allocno will not get memory
2943*e4b17023SJohn Marino 		 slot.  */
2944*e4b17023SJohn Marino 	      || ira_reg_equiv_invariant_p[regno]
2945*e4b17023SJohn Marino 	      || ira_reg_equiv_const[regno] != NULL_RTX
2946*e4b17023SJohn Marino 	      || !bitmap_bit_p (loop_node->border_allocnos, ALLOCNO_NUM (a)))
2947*e4b17023SJohn Marino 	    continue;
2948*e4b17023SJohn Marino 	  mode = ALLOCNO_MODE (a);
2949*e4b17023SJohn Marino 	  rclass = ALLOCNO_CLASS (a);
2950*e4b17023SJohn Marino 	  index = ira_class_hard_reg_index[rclass][hard_regno];
2951*e4b17023SJohn Marino 	  ira_assert (index >= 0);
2952*e4b17023SJohn Marino 	  cost = (ALLOCNO_MEMORY_COST (a)
2953*e4b17023SJohn Marino 		  - (ALLOCNO_HARD_REG_COSTS (a) == NULL
2954*e4b17023SJohn Marino 		     ? ALLOCNO_CLASS_COST (a)
2955*e4b17023SJohn Marino 		     : ALLOCNO_HARD_REG_COSTS (a)[index]));
2956*e4b17023SJohn Marino 	  ira_init_register_move_cost_if_necessary (mode);
2957*e4b17023SJohn Marino 	  for (subloop_node = loop_node->subloops;
2958*e4b17023SJohn Marino 	       subloop_node != NULL;
2959*e4b17023SJohn Marino 	       subloop_node = subloop_node->subloop_next)
2960*e4b17023SJohn Marino 	    {
2961*e4b17023SJohn Marino 	      ira_assert (subloop_node->bb == NULL);
2962*e4b17023SJohn Marino 	      subloop_allocno = subloop_node->regno_allocno_map[regno];
2963*e4b17023SJohn Marino 	      if (subloop_allocno == NULL)
2964*e4b17023SJohn Marino 		continue;
2965*e4b17023SJohn Marino 	      ira_assert (rclass == ALLOCNO_CLASS (subloop_allocno));
2966*e4b17023SJohn Marino 	      /* We have accumulated cost.  To get the real cost of
2967*e4b17023SJohn Marino 		 allocno usage in the loop we should subtract costs of
2968*e4b17023SJohn Marino 		 the subloop allocnos.  */
2969*e4b17023SJohn Marino 	      cost -= (ALLOCNO_MEMORY_COST (subloop_allocno)
2970*e4b17023SJohn Marino 		       - (ALLOCNO_HARD_REG_COSTS (subloop_allocno) == NULL
2971*e4b17023SJohn Marino 			  ? ALLOCNO_CLASS_COST (subloop_allocno)
2972*e4b17023SJohn Marino 			  : ALLOCNO_HARD_REG_COSTS (subloop_allocno)[index]));
2973*e4b17023SJohn Marino 	      exit_freq = ira_loop_edge_freq (subloop_node, regno, true);
2974*e4b17023SJohn Marino 	      enter_freq = ira_loop_edge_freq (subloop_node, regno, false);
2975*e4b17023SJohn Marino 	      if ((hard_regno2 = ALLOCNO_HARD_REGNO (subloop_allocno)) < 0)
2976*e4b17023SJohn Marino 		cost -= (ira_memory_move_cost[mode][rclass][0] * exit_freq
2977*e4b17023SJohn Marino 			 + ira_memory_move_cost[mode][rclass][1] * enter_freq);
2978*e4b17023SJohn Marino 	      else
2979*e4b17023SJohn Marino 		{
2980*e4b17023SJohn Marino 		  cost
2981*e4b17023SJohn Marino 		    += (ira_memory_move_cost[mode][rclass][0] * exit_freq
2982*e4b17023SJohn Marino 			+ ira_memory_move_cost[mode][rclass][1] * enter_freq);
2983*e4b17023SJohn Marino 		  if (hard_regno2 != hard_regno)
2984*e4b17023SJohn Marino 		    cost -= (ira_register_move_cost[mode][rclass][rclass]
2985*e4b17023SJohn Marino 			     * (exit_freq + enter_freq));
2986*e4b17023SJohn Marino 		}
2987*e4b17023SJohn Marino 	    }
2988*e4b17023SJohn Marino 	  if ((parent = loop_node->parent) != NULL
2989*e4b17023SJohn Marino 	      && (parent_allocno = parent->regno_allocno_map[regno]) != NULL)
2990*e4b17023SJohn Marino 	    {
2991*e4b17023SJohn Marino 	      ira_assert (rclass == ALLOCNO_CLASS (parent_allocno));
2992*e4b17023SJohn Marino 	      exit_freq	= ira_loop_edge_freq (loop_node, regno, true);
2993*e4b17023SJohn Marino 	      enter_freq = ira_loop_edge_freq (loop_node, regno, false);
2994*e4b17023SJohn Marino 	      if ((hard_regno2 = ALLOCNO_HARD_REGNO (parent_allocno)) < 0)
2995*e4b17023SJohn Marino 		cost -= (ira_memory_move_cost[mode][rclass][0] * exit_freq
2996*e4b17023SJohn Marino 			 + ira_memory_move_cost[mode][rclass][1] * enter_freq);
2997*e4b17023SJohn Marino 	      else
2998*e4b17023SJohn Marino 		{
2999*e4b17023SJohn Marino 		  cost
3000*e4b17023SJohn Marino 		    += (ira_memory_move_cost[mode][rclass][1] * exit_freq
3001*e4b17023SJohn Marino 			+ ira_memory_move_cost[mode][rclass][0] * enter_freq);
3002*e4b17023SJohn Marino 		  if (hard_regno2 != hard_regno)
3003*e4b17023SJohn Marino 		    cost -= (ira_register_move_cost[mode][rclass][rclass]
3004*e4b17023SJohn Marino 			     * (exit_freq + enter_freq));
3005*e4b17023SJohn Marino 		}
3006*e4b17023SJohn Marino 	    }
3007*e4b17023SJohn Marino 	  if (cost < 0)
3008*e4b17023SJohn Marino 	    {
3009*e4b17023SJohn Marino 	      ALLOCNO_HARD_REGNO (a) = -1;
3010*e4b17023SJohn Marino 	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
3011*e4b17023SJohn Marino 		{
3012*e4b17023SJohn Marino 		  fprintf
3013*e4b17023SJohn Marino 		    (ira_dump_file,
3014*e4b17023SJohn Marino 		     "      Moving spill/restore for a%dr%d up from loop %d",
3015*e4b17023SJohn Marino 		     ALLOCNO_NUM (a), regno, loop_node->loop_num);
3016*e4b17023SJohn Marino 		  fprintf (ira_dump_file, " - profit %d\n", -cost);
3017*e4b17023SJohn Marino 		}
3018*e4b17023SJohn Marino 	      changed_p = true;
3019*e4b17023SJohn Marino 	    }
3020*e4b17023SJohn Marino 	}
3021*e4b17023SJohn Marino       if (! changed_p)
3022*e4b17023SJohn Marino 	break;
3023*e4b17023SJohn Marino     }
3024*e4b17023SJohn Marino }
3025*e4b17023SJohn Marino 
3026*e4b17023SJohn Marino 
3027*e4b17023SJohn Marino 
3028*e4b17023SJohn Marino /* Update current hard reg costs and current conflict hard reg costs
3029*e4b17023SJohn Marino    for allocno A.  It is done by processing its copies containing
3030*e4b17023SJohn Marino    other allocnos already assigned.  */
3031*e4b17023SJohn Marino static void
update_curr_costs(ira_allocno_t a)3032*e4b17023SJohn Marino update_curr_costs (ira_allocno_t a)
3033*e4b17023SJohn Marino {
3034*e4b17023SJohn Marino   int i, hard_regno, cost;
3035*e4b17023SJohn Marino   enum machine_mode mode;
3036*e4b17023SJohn Marino   enum reg_class aclass, rclass;
3037*e4b17023SJohn Marino   ira_allocno_t another_a;
3038*e4b17023SJohn Marino   ira_copy_t cp, next_cp;
3039*e4b17023SJohn Marino 
3040*e4b17023SJohn Marino   ira_free_allocno_updated_costs (a);
3041*e4b17023SJohn Marino   ira_assert (! ALLOCNO_ASSIGNED_P (a));
3042*e4b17023SJohn Marino   aclass = ALLOCNO_CLASS (a);
3043*e4b17023SJohn Marino   if (aclass == NO_REGS)
3044*e4b17023SJohn Marino     return;
3045*e4b17023SJohn Marino   mode = ALLOCNO_MODE (a);
3046*e4b17023SJohn Marino   ira_init_register_move_cost_if_necessary (mode);
3047*e4b17023SJohn Marino   for (cp = ALLOCNO_COPIES (a); cp != NULL; cp = next_cp)
3048*e4b17023SJohn Marino     {
3049*e4b17023SJohn Marino       if (cp->first == a)
3050*e4b17023SJohn Marino 	{
3051*e4b17023SJohn Marino 	  next_cp = cp->next_first_allocno_copy;
3052*e4b17023SJohn Marino 	  another_a = cp->second;
3053*e4b17023SJohn Marino 	}
3054*e4b17023SJohn Marino       else if (cp->second == a)
3055*e4b17023SJohn Marino 	{
3056*e4b17023SJohn Marino 	  next_cp = cp->next_second_allocno_copy;
3057*e4b17023SJohn Marino 	  another_a = cp->first;
3058*e4b17023SJohn Marino 	}
3059*e4b17023SJohn Marino       else
3060*e4b17023SJohn Marino 	gcc_unreachable ();
3061*e4b17023SJohn Marino       if (! ira_reg_classes_intersect_p[aclass][ALLOCNO_CLASS (another_a)]
3062*e4b17023SJohn Marino 	  || ! ALLOCNO_ASSIGNED_P (another_a)
3063*e4b17023SJohn Marino 	  || (hard_regno = ALLOCNO_HARD_REGNO (another_a)) < 0)
3064*e4b17023SJohn Marino 	continue;
3065*e4b17023SJohn Marino       rclass = REGNO_REG_CLASS (hard_regno);
3066*e4b17023SJohn Marino       i = ira_class_hard_reg_index[aclass][hard_regno];
3067*e4b17023SJohn Marino       if (i < 0)
3068*e4b17023SJohn Marino 	continue;
3069*e4b17023SJohn Marino       cost = (cp->first == a
3070*e4b17023SJohn Marino 	      ? ira_register_move_cost[mode][rclass][aclass]
3071*e4b17023SJohn Marino 	      : ira_register_move_cost[mode][aclass][rclass]);
3072*e4b17023SJohn Marino       ira_allocate_and_set_or_copy_costs
3073*e4b17023SJohn Marino 	(&ALLOCNO_UPDATED_HARD_REG_COSTS (a), aclass, ALLOCNO_CLASS_COST (a),
3074*e4b17023SJohn Marino 	 ALLOCNO_HARD_REG_COSTS (a));
3075*e4b17023SJohn Marino       ira_allocate_and_set_or_copy_costs
3076*e4b17023SJohn Marino 	(&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a),
3077*e4b17023SJohn Marino 	 aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (a));
3078*e4b17023SJohn Marino       ALLOCNO_UPDATED_HARD_REG_COSTS (a)[i] -= cp->freq * cost;
3079*e4b17023SJohn Marino       ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a)[i] -= cp->freq * cost;
3080*e4b17023SJohn Marino     }
3081*e4b17023SJohn Marino }
3082*e4b17023SJohn Marino 
3083*e4b17023SJohn Marino /* Try to assign hard registers to the unassigned allocnos and
3084*e4b17023SJohn Marino    allocnos conflicting with them or conflicting with allocnos whose
3085*e4b17023SJohn Marino    regno >= START_REGNO.  The function is called after ira_flattening,
3086*e4b17023SJohn Marino    so more allocnos (including ones created in ira-emit.c) will have a
3087*e4b17023SJohn Marino    chance to get a hard register.  We use simple assignment algorithm
3088*e4b17023SJohn Marino    based on priorities.  */
3089*e4b17023SJohn Marino void
ira_reassign_conflict_allocnos(int start_regno)3090*e4b17023SJohn Marino ira_reassign_conflict_allocnos (int start_regno)
3091*e4b17023SJohn Marino {
3092*e4b17023SJohn Marino   int i, allocnos_to_color_num;
3093*e4b17023SJohn Marino   ira_allocno_t a;
3094*e4b17023SJohn Marino   enum reg_class aclass;
3095*e4b17023SJohn Marino   bitmap allocnos_to_color;
3096*e4b17023SJohn Marino   ira_allocno_iterator ai;
3097*e4b17023SJohn Marino 
3098*e4b17023SJohn Marino   allocnos_to_color = ira_allocate_bitmap ();
3099*e4b17023SJohn Marino   allocnos_to_color_num = 0;
3100*e4b17023SJohn Marino   FOR_EACH_ALLOCNO (a, ai)
3101*e4b17023SJohn Marino     {
3102*e4b17023SJohn Marino       int n = ALLOCNO_NUM_OBJECTS (a);
3103*e4b17023SJohn Marino 
3104*e4b17023SJohn Marino       if (! ALLOCNO_ASSIGNED_P (a)
3105*e4b17023SJohn Marino 	  && ! bitmap_bit_p (allocnos_to_color, ALLOCNO_NUM (a)))
3106*e4b17023SJohn Marino 	{
3107*e4b17023SJohn Marino 	  if (ALLOCNO_CLASS (a) != NO_REGS)
3108*e4b17023SJohn Marino 	    sorted_allocnos[allocnos_to_color_num++] = a;
3109*e4b17023SJohn Marino 	  else
3110*e4b17023SJohn Marino 	    {
3111*e4b17023SJohn Marino 	      ALLOCNO_ASSIGNED_P (a) = true;
3112*e4b17023SJohn Marino 	      ALLOCNO_HARD_REGNO (a) = -1;
3113*e4b17023SJohn Marino 	      ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL);
3114*e4b17023SJohn Marino 	      ira_assert (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) == NULL);
3115*e4b17023SJohn Marino 	    }
3116*e4b17023SJohn Marino 	  bitmap_set_bit (allocnos_to_color, ALLOCNO_NUM (a));
3117*e4b17023SJohn Marino 	}
3118*e4b17023SJohn Marino       if (ALLOCNO_REGNO (a) < start_regno
3119*e4b17023SJohn Marino 	  || (aclass = ALLOCNO_CLASS (a)) == NO_REGS)
3120*e4b17023SJohn Marino 	continue;
3121*e4b17023SJohn Marino       for (i = 0; i < n; i++)
3122*e4b17023SJohn Marino 	{
3123*e4b17023SJohn Marino 	  ira_object_t obj = ALLOCNO_OBJECT (a, i);
3124*e4b17023SJohn Marino 	  ira_object_t conflict_obj;
3125*e4b17023SJohn Marino 	  ira_object_conflict_iterator oci;
3126*e4b17023SJohn Marino 
3127*e4b17023SJohn Marino 	  FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
3128*e4b17023SJohn Marino 	    {
3129*e4b17023SJohn Marino 	      ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
3130*e4b17023SJohn Marino 
3131*e4b17023SJohn Marino 	      ira_assert (ira_reg_classes_intersect_p
3132*e4b17023SJohn Marino 			  [aclass][ALLOCNO_CLASS (conflict_a)]);
3133*e4b17023SJohn Marino 	      if (!bitmap_set_bit (allocnos_to_color, ALLOCNO_NUM (conflict_a)))
3134*e4b17023SJohn Marino 		continue;
3135*e4b17023SJohn Marino 	      sorted_allocnos[allocnos_to_color_num++] = conflict_a;
3136*e4b17023SJohn Marino 	    }
3137*e4b17023SJohn Marino 	}
3138*e4b17023SJohn Marino     }
3139*e4b17023SJohn Marino   ira_free_bitmap (allocnos_to_color);
3140*e4b17023SJohn Marino   if (allocnos_to_color_num > 1)
3141*e4b17023SJohn Marino     {
3142*e4b17023SJohn Marino       setup_allocno_priorities (sorted_allocnos, allocnos_to_color_num);
3143*e4b17023SJohn Marino       qsort (sorted_allocnos, allocnos_to_color_num, sizeof (ira_allocno_t),
3144*e4b17023SJohn Marino 	     allocno_priority_compare_func);
3145*e4b17023SJohn Marino     }
3146*e4b17023SJohn Marino   for (i = 0; i < allocnos_to_color_num; i++)
3147*e4b17023SJohn Marino     {
3148*e4b17023SJohn Marino       a = sorted_allocnos[i];
3149*e4b17023SJohn Marino       ALLOCNO_ASSIGNED_P (a) = false;
3150*e4b17023SJohn Marino       update_curr_costs (a);
3151*e4b17023SJohn Marino     }
3152*e4b17023SJohn Marino   for (i = 0; i < allocnos_to_color_num; i++)
3153*e4b17023SJohn Marino     {
3154*e4b17023SJohn Marino       a = sorted_allocnos[i];
3155*e4b17023SJohn Marino       if (assign_hard_reg (a, true))
3156*e4b17023SJohn Marino 	{
3157*e4b17023SJohn Marino 	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
3158*e4b17023SJohn Marino 	    fprintf
3159*e4b17023SJohn Marino 	      (ira_dump_file,
3160*e4b17023SJohn Marino 	       "      Secondary allocation: assign hard reg %d to reg %d\n",
3161*e4b17023SJohn Marino 	       ALLOCNO_HARD_REGNO (a), ALLOCNO_REGNO (a));
3162*e4b17023SJohn Marino 	}
3163*e4b17023SJohn Marino     }
3164*e4b17023SJohn Marino }
3165*e4b17023SJohn Marino 
3166*e4b17023SJohn Marino 
3167*e4b17023SJohn Marino 
3168*e4b17023SJohn Marino /* This page contains functions used to find conflicts using allocno
3169*e4b17023SJohn Marino    live ranges.  */
3170*e4b17023SJohn Marino 
3171*e4b17023SJohn Marino /* Return TRUE if live ranges of allocnos A1 and A2 intersect.  It is
3172*e4b17023SJohn Marino    used to find a conflict for new allocnos or allocnos with the
3173*e4b17023SJohn Marino    different allocno classes.  */
3174*e4b17023SJohn Marino static bool
allocnos_conflict_by_live_ranges_p(ira_allocno_t a1,ira_allocno_t a2)3175*e4b17023SJohn Marino allocnos_conflict_by_live_ranges_p (ira_allocno_t a1, ira_allocno_t a2)
3176*e4b17023SJohn Marino {
3177*e4b17023SJohn Marino   rtx reg1, reg2;
3178*e4b17023SJohn Marino   int i, j;
3179*e4b17023SJohn Marino   int n1 = ALLOCNO_NUM_OBJECTS (a1);
3180*e4b17023SJohn Marino   int n2 = ALLOCNO_NUM_OBJECTS (a2);
3181*e4b17023SJohn Marino 
3182*e4b17023SJohn Marino   if (a1 == a2)
3183*e4b17023SJohn Marino     return false;
3184*e4b17023SJohn Marino   reg1 = regno_reg_rtx[ALLOCNO_REGNO (a1)];
3185*e4b17023SJohn Marino   reg2 = regno_reg_rtx[ALLOCNO_REGNO (a2)];
3186*e4b17023SJohn Marino   if (reg1 != NULL && reg2 != NULL
3187*e4b17023SJohn Marino       && ORIGINAL_REGNO (reg1) == ORIGINAL_REGNO (reg2))
3188*e4b17023SJohn Marino     return false;
3189*e4b17023SJohn Marino 
3190*e4b17023SJohn Marino   for (i = 0; i < n1; i++)
3191*e4b17023SJohn Marino     {
3192*e4b17023SJohn Marino       ira_object_t c1 = ALLOCNO_OBJECT (a1, i);
3193*e4b17023SJohn Marino 
3194*e4b17023SJohn Marino       for (j = 0; j < n2; j++)
3195*e4b17023SJohn Marino 	{
3196*e4b17023SJohn Marino 	  ira_object_t c2 = ALLOCNO_OBJECT (a2, j);
3197*e4b17023SJohn Marino 
3198*e4b17023SJohn Marino 	  if (ira_live_ranges_intersect_p (OBJECT_LIVE_RANGES (c1),
3199*e4b17023SJohn Marino 					   OBJECT_LIVE_RANGES (c2)))
3200*e4b17023SJohn Marino 	    return true;
3201*e4b17023SJohn Marino 	}
3202*e4b17023SJohn Marino     }
3203*e4b17023SJohn Marino   return false;
3204*e4b17023SJohn Marino }
3205*e4b17023SJohn Marino 
3206*e4b17023SJohn Marino #ifdef ENABLE_IRA_CHECKING
3207*e4b17023SJohn Marino 
3208*e4b17023SJohn Marino /* Return TRUE if live ranges of pseudo-registers REGNO1 and REGNO2
3209*e4b17023SJohn Marino    intersect.  This should be used when there is only one region.
3210*e4b17023SJohn Marino    Currently this is used during reload.  */
3211*e4b17023SJohn Marino static bool
conflict_by_live_ranges_p(int regno1,int regno2)3212*e4b17023SJohn Marino conflict_by_live_ranges_p (int regno1, int regno2)
3213*e4b17023SJohn Marino {
3214*e4b17023SJohn Marino   ira_allocno_t a1, a2;
3215*e4b17023SJohn Marino 
3216*e4b17023SJohn Marino   ira_assert (regno1 >= FIRST_PSEUDO_REGISTER
3217*e4b17023SJohn Marino 	      && regno2 >= FIRST_PSEUDO_REGISTER);
3218*e4b17023SJohn Marino   /* Reg info caclulated by dataflow infrastructure can be different
3219*e4b17023SJohn Marino      from one calculated by regclass.  */
3220*e4b17023SJohn Marino   if ((a1 = ira_loop_tree_root->regno_allocno_map[regno1]) == NULL
3221*e4b17023SJohn Marino       || (a2 = ira_loop_tree_root->regno_allocno_map[regno2]) == NULL)
3222*e4b17023SJohn Marino     return false;
3223*e4b17023SJohn Marino   return allocnos_conflict_by_live_ranges_p (a1, a2);
3224*e4b17023SJohn Marino }
3225*e4b17023SJohn Marino 
3226*e4b17023SJohn Marino #endif
3227*e4b17023SJohn Marino 
3228*e4b17023SJohn Marino 
3229*e4b17023SJohn Marino 
3230*e4b17023SJohn Marino /* This page contains code to coalesce memory stack slots used by
3231*e4b17023SJohn Marino    spilled allocnos.  This results in smaller stack frame, better data
3232*e4b17023SJohn Marino    locality, and in smaller code for some architectures like
3233*e4b17023SJohn Marino    x86/x86_64 where insn size depends on address displacement value.
3234*e4b17023SJohn Marino    On the other hand, it can worsen insn scheduling after the RA but
3235*e4b17023SJohn Marino    in practice it is less important than smaller stack frames.  */
3236*e4b17023SJohn Marino 
3237*e4b17023SJohn Marino /* TRUE if we coalesced some allocnos.  In other words, if we got
3238*e4b17023SJohn Marino    loops formed by members first_coalesced_allocno and
3239*e4b17023SJohn Marino    next_coalesced_allocno containing more one allocno.  */
3240*e4b17023SJohn Marino static bool allocno_coalesced_p;
3241*e4b17023SJohn Marino 
3242*e4b17023SJohn Marino /* Bitmap used to prevent a repeated allocno processing because of
3243*e4b17023SJohn Marino    coalescing.  */
3244*e4b17023SJohn Marino static bitmap processed_coalesced_allocno_bitmap;
3245*e4b17023SJohn Marino 
3246*e4b17023SJohn Marino /* See below.  */
3247*e4b17023SJohn Marino typedef struct coalesce_data *coalesce_data_t;
3248*e4b17023SJohn Marino 
3249*e4b17023SJohn Marino /* To decrease footprint of ira_allocno structure we store all data
3250*e4b17023SJohn Marino    needed only for coalescing in the following structure.  */
3251*e4b17023SJohn Marino struct coalesce_data
3252*e4b17023SJohn Marino {
3253*e4b17023SJohn Marino   /* Coalesced allocnos form a cyclic list.  One allocno given by
3254*e4b17023SJohn Marino      FIRST represents all coalesced allocnos.  The
3255*e4b17023SJohn Marino      list is chained by NEXT.  */
3256*e4b17023SJohn Marino   ira_allocno_t first;
3257*e4b17023SJohn Marino   ira_allocno_t next;
3258*e4b17023SJohn Marino   int temp;
3259*e4b17023SJohn Marino };
3260*e4b17023SJohn Marino 
3261*e4b17023SJohn Marino /* Container for storing allocno data concerning coalescing.  */
3262*e4b17023SJohn Marino static coalesce_data_t allocno_coalesce_data;
3263*e4b17023SJohn Marino 
3264*e4b17023SJohn Marino /* Macro to access the data concerning coalescing.  */
3265*e4b17023SJohn Marino #define ALLOCNO_COALESCE_DATA(a) ((coalesce_data_t) ALLOCNO_ADD_DATA (a))
3266*e4b17023SJohn Marino 
3267*e4b17023SJohn Marino /* The function is used to sort allocnos according to their execution
3268*e4b17023SJohn Marino    frequencies.  */
3269*e4b17023SJohn Marino static int
copy_freq_compare_func(const void * v1p,const void * v2p)3270*e4b17023SJohn Marino copy_freq_compare_func (const void *v1p, const void *v2p)
3271*e4b17023SJohn Marino {
3272*e4b17023SJohn Marino   ira_copy_t cp1 = *(const ira_copy_t *) v1p, cp2 = *(const ira_copy_t *) v2p;
3273*e4b17023SJohn Marino   int pri1, pri2;
3274*e4b17023SJohn Marino 
3275*e4b17023SJohn Marino   pri1 = cp1->freq;
3276*e4b17023SJohn Marino   pri2 = cp2->freq;
3277*e4b17023SJohn Marino   if (pri2 - pri1)
3278*e4b17023SJohn Marino     return pri2 - pri1;
3279*e4b17023SJohn Marino 
3280*e4b17023SJohn Marino   /* If freqencies are equal, sort by copies, so that the results of
3281*e4b17023SJohn Marino      qsort leave nothing to chance.  */
3282*e4b17023SJohn Marino   return cp1->num - cp2->num;
3283*e4b17023SJohn Marino }
3284*e4b17023SJohn Marino 
3285*e4b17023SJohn Marino /* Merge two sets of coalesced allocnos given correspondingly by
3286*e4b17023SJohn Marino    allocnos A1 and A2 (more accurately merging A2 set into A1
3287*e4b17023SJohn Marino    set).  */
3288*e4b17023SJohn Marino static void
merge_allocnos(ira_allocno_t a1,ira_allocno_t a2)3289*e4b17023SJohn Marino merge_allocnos (ira_allocno_t a1, ira_allocno_t a2)
3290*e4b17023SJohn Marino {
3291*e4b17023SJohn Marino   ira_allocno_t a, first, last, next;
3292*e4b17023SJohn Marino 
3293*e4b17023SJohn Marino   first = ALLOCNO_COALESCE_DATA (a1)->first;
3294*e4b17023SJohn Marino   a = ALLOCNO_COALESCE_DATA (a2)->first;
3295*e4b17023SJohn Marino   if (first == a)
3296*e4b17023SJohn Marino     return;
3297*e4b17023SJohn Marino   for (last = a2, a = ALLOCNO_COALESCE_DATA (a2)->next;;
3298*e4b17023SJohn Marino        a = ALLOCNO_COALESCE_DATA (a)->next)
3299*e4b17023SJohn Marino     {
3300*e4b17023SJohn Marino       ALLOCNO_COALESCE_DATA (a)->first = first;
3301*e4b17023SJohn Marino       if (a == a2)
3302*e4b17023SJohn Marino 	break;
3303*e4b17023SJohn Marino       last = a;
3304*e4b17023SJohn Marino     }
3305*e4b17023SJohn Marino   next = allocno_coalesce_data[ALLOCNO_NUM (first)].next;
3306*e4b17023SJohn Marino   allocno_coalesce_data[ALLOCNO_NUM (first)].next = a2;
3307*e4b17023SJohn Marino   allocno_coalesce_data[ALLOCNO_NUM (last)].next = next;
3308*e4b17023SJohn Marino }
3309*e4b17023SJohn Marino 
3310*e4b17023SJohn Marino /* Return TRUE if there are conflicting allocnos from two sets of
3311*e4b17023SJohn Marino    coalesced allocnos given correspondingly by allocnos A1 and A2.  We
3312*e4b17023SJohn Marino    use live ranges to find conflicts because conflicts are represented
3313*e4b17023SJohn Marino    only for allocnos of the same allocno class and during the reload
3314*e4b17023SJohn Marino    pass we coalesce allocnos for sharing stack memory slots.  */
3315*e4b17023SJohn Marino static bool
coalesced_allocno_conflict_p(ira_allocno_t a1,ira_allocno_t a2)3316*e4b17023SJohn Marino coalesced_allocno_conflict_p (ira_allocno_t a1, ira_allocno_t a2)
3317*e4b17023SJohn Marino {
3318*e4b17023SJohn Marino   ira_allocno_t a, conflict_a;
3319*e4b17023SJohn Marino 
3320*e4b17023SJohn Marino   if (allocno_coalesced_p)
3321*e4b17023SJohn Marino     {
3322*e4b17023SJohn Marino       bitmap_clear (processed_coalesced_allocno_bitmap);
3323*e4b17023SJohn Marino       for (a = ALLOCNO_COALESCE_DATA (a1)->next;;
3324*e4b17023SJohn Marino 	   a = ALLOCNO_COALESCE_DATA (a)->next)
3325*e4b17023SJohn Marino 	{
3326*e4b17023SJohn Marino 	  bitmap_set_bit (processed_coalesced_allocno_bitmap, ALLOCNO_NUM (a));
3327*e4b17023SJohn Marino 	  if (a == a1)
3328*e4b17023SJohn Marino 	    break;
3329*e4b17023SJohn Marino 	}
3330*e4b17023SJohn Marino     }
3331*e4b17023SJohn Marino   for (a = ALLOCNO_COALESCE_DATA (a2)->next;;
3332*e4b17023SJohn Marino        a = ALLOCNO_COALESCE_DATA (a)->next)
3333*e4b17023SJohn Marino     {
3334*e4b17023SJohn Marino       for (conflict_a = ALLOCNO_COALESCE_DATA (a1)->next;;
3335*e4b17023SJohn Marino 	   conflict_a = ALLOCNO_COALESCE_DATA (conflict_a)->next)
3336*e4b17023SJohn Marino 	{
3337*e4b17023SJohn Marino 	  if (allocnos_conflict_by_live_ranges_p (a, conflict_a))
3338*e4b17023SJohn Marino 	    return true;
3339*e4b17023SJohn Marino 	  if (conflict_a == a1)
3340*e4b17023SJohn Marino 	    break;
3341*e4b17023SJohn Marino 	}
3342*e4b17023SJohn Marino       if (a == a2)
3343*e4b17023SJohn Marino 	break;
3344*e4b17023SJohn Marino     }
3345*e4b17023SJohn Marino   return false;
3346*e4b17023SJohn Marino }
3347*e4b17023SJohn Marino 
3348*e4b17023SJohn Marino /* The major function for aggressive allocno coalescing.  We coalesce
3349*e4b17023SJohn Marino    only spilled allocnos.  If some allocnos have been coalesced, we
3350*e4b17023SJohn Marino    set up flag allocno_coalesced_p.  */
3351*e4b17023SJohn Marino static void
coalesce_allocnos(void)3352*e4b17023SJohn Marino coalesce_allocnos (void)
3353*e4b17023SJohn Marino {
3354*e4b17023SJohn Marino   ira_allocno_t a;
3355*e4b17023SJohn Marino   ira_copy_t cp, next_cp, *sorted_copies;
3356*e4b17023SJohn Marino   unsigned int j;
3357*e4b17023SJohn Marino   int i, n, cp_num, regno;
3358*e4b17023SJohn Marino   bitmap_iterator bi;
3359*e4b17023SJohn Marino 
3360*e4b17023SJohn Marino   sorted_copies = (ira_copy_t *) ira_allocate (ira_copies_num
3361*e4b17023SJohn Marino 					       * sizeof (ira_copy_t));
3362*e4b17023SJohn Marino   cp_num = 0;
3363*e4b17023SJohn Marino   /* Collect copies.  */
3364*e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, j, bi)
3365*e4b17023SJohn Marino     {
3366*e4b17023SJohn Marino       a = ira_allocnos[j];
3367*e4b17023SJohn Marino       regno = ALLOCNO_REGNO (a);
3368*e4b17023SJohn Marino       if (! ALLOCNO_ASSIGNED_P (a) || ALLOCNO_HARD_REGNO (a) >= 0
3369*e4b17023SJohn Marino 	  || (regno < ira_reg_equiv_len
3370*e4b17023SJohn Marino 	      && (ira_reg_equiv_const[regno] != NULL_RTX
3371*e4b17023SJohn Marino 		  || ira_reg_equiv_invariant_p[regno])))
3372*e4b17023SJohn Marino 	continue;
3373*e4b17023SJohn Marino       for (cp = ALLOCNO_COPIES (a); cp != NULL; cp = next_cp)
3374*e4b17023SJohn Marino 	{
3375*e4b17023SJohn Marino 	  if (cp->first == a)
3376*e4b17023SJohn Marino 	    {
3377*e4b17023SJohn Marino 	      next_cp = cp->next_first_allocno_copy;
3378*e4b17023SJohn Marino 	      regno = ALLOCNO_REGNO (cp->second);
3379*e4b17023SJohn Marino 	      /* For priority coloring we coalesce allocnos only with
3380*e4b17023SJohn Marino 		 the same allocno class not with intersected allocno
3381*e4b17023SJohn Marino 		 classes as it were possible.  It is done for
3382*e4b17023SJohn Marino 		 simplicity.  */
3383*e4b17023SJohn Marino 	      if ((cp->insn != NULL || cp->constraint_p)
3384*e4b17023SJohn Marino 		  && ALLOCNO_ASSIGNED_P (cp->second)
3385*e4b17023SJohn Marino 		  && ALLOCNO_HARD_REGNO (cp->second) < 0
3386*e4b17023SJohn Marino 		  && (regno >= ira_reg_equiv_len
3387*e4b17023SJohn Marino 		      || (! ira_reg_equiv_invariant_p[regno]
3388*e4b17023SJohn Marino 			  && ira_reg_equiv_const[regno] == NULL_RTX)))
3389*e4b17023SJohn Marino 		sorted_copies[cp_num++] = cp;
3390*e4b17023SJohn Marino 	    }
3391*e4b17023SJohn Marino 	  else if (cp->second == a)
3392*e4b17023SJohn Marino 	    next_cp = cp->next_second_allocno_copy;
3393*e4b17023SJohn Marino 	  else
3394*e4b17023SJohn Marino 	    gcc_unreachable ();
3395*e4b17023SJohn Marino 	}
3396*e4b17023SJohn Marino     }
3397*e4b17023SJohn Marino   qsort (sorted_copies, cp_num, sizeof (ira_copy_t), copy_freq_compare_func);
3398*e4b17023SJohn Marino   /* Coalesced copies, most frequently executed first.  */
3399*e4b17023SJohn Marino   for (; cp_num != 0;)
3400*e4b17023SJohn Marino     {
3401*e4b17023SJohn Marino       for (i = 0; i < cp_num; i++)
3402*e4b17023SJohn Marino 	{
3403*e4b17023SJohn Marino 	  cp = sorted_copies[i];
3404*e4b17023SJohn Marino 	  if (! coalesced_allocno_conflict_p (cp->first, cp->second))
3405*e4b17023SJohn Marino 	    {
3406*e4b17023SJohn Marino 	      allocno_coalesced_p = true;
3407*e4b17023SJohn Marino 	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
3408*e4b17023SJohn Marino 		fprintf
3409*e4b17023SJohn Marino 		  (ira_dump_file,
3410*e4b17023SJohn Marino 		   "      Coalescing copy %d:a%dr%d-a%dr%d (freq=%d)\n",
3411*e4b17023SJohn Marino 		   cp->num, ALLOCNO_NUM (cp->first), ALLOCNO_REGNO (cp->first),
3412*e4b17023SJohn Marino 		   ALLOCNO_NUM (cp->second), ALLOCNO_REGNO (cp->second),
3413*e4b17023SJohn Marino 		   cp->freq);
3414*e4b17023SJohn Marino 	      merge_allocnos (cp->first, cp->second);
3415*e4b17023SJohn Marino 	      i++;
3416*e4b17023SJohn Marino 	      break;
3417*e4b17023SJohn Marino 	    }
3418*e4b17023SJohn Marino 	}
3419*e4b17023SJohn Marino       /* Collect the rest of copies.  */
3420*e4b17023SJohn Marino       for (n = 0; i < cp_num; i++)
3421*e4b17023SJohn Marino 	{
3422*e4b17023SJohn Marino 	  cp = sorted_copies[i];
3423*e4b17023SJohn Marino 	  if (allocno_coalesce_data[ALLOCNO_NUM (cp->first)].first
3424*e4b17023SJohn Marino 	      != allocno_coalesce_data[ALLOCNO_NUM (cp->second)].first)
3425*e4b17023SJohn Marino 	    sorted_copies[n++] = cp;
3426*e4b17023SJohn Marino 	}
3427*e4b17023SJohn Marino       cp_num = n;
3428*e4b17023SJohn Marino     }
3429*e4b17023SJohn Marino   ira_free (sorted_copies);
3430*e4b17023SJohn Marino }
3431*e4b17023SJohn Marino 
3432*e4b17023SJohn Marino /* Usage cost and order number of coalesced allocno set to which
3433*e4b17023SJohn Marino    given pseudo register belongs to.  */
3434*e4b17023SJohn Marino static int *regno_coalesced_allocno_cost;
3435*e4b17023SJohn Marino static int *regno_coalesced_allocno_num;
3436*e4b17023SJohn Marino 
3437*e4b17023SJohn Marino /* Sort pseudos according frequencies of coalesced allocno sets they
3438*e4b17023SJohn Marino    belong to (putting most frequently ones first), and according to
3439*e4b17023SJohn Marino    coalesced allocno set order numbers.  */
3440*e4b17023SJohn Marino static int
coalesced_pseudo_reg_freq_compare(const void * v1p,const void * v2p)3441*e4b17023SJohn Marino coalesced_pseudo_reg_freq_compare (const void *v1p, const void *v2p)
3442*e4b17023SJohn Marino {
3443*e4b17023SJohn Marino   const int regno1 = *(const int *) v1p;
3444*e4b17023SJohn Marino   const int regno2 = *(const int *) v2p;
3445*e4b17023SJohn Marino   int diff;
3446*e4b17023SJohn Marino 
3447*e4b17023SJohn Marino   if ((diff = (regno_coalesced_allocno_cost[regno2]
3448*e4b17023SJohn Marino 	       - regno_coalesced_allocno_cost[regno1])) != 0)
3449*e4b17023SJohn Marino     return diff;
3450*e4b17023SJohn Marino   if ((diff = (regno_coalesced_allocno_num[regno1]
3451*e4b17023SJohn Marino 	       - regno_coalesced_allocno_num[regno2])) != 0)
3452*e4b17023SJohn Marino     return diff;
3453*e4b17023SJohn Marino   return regno1 - regno2;
3454*e4b17023SJohn Marino }
3455*e4b17023SJohn Marino 
3456*e4b17023SJohn Marino /* Widest width in which each pseudo reg is referred to (via subreg).
3457*e4b17023SJohn Marino    It is used for sorting pseudo registers.  */
3458*e4b17023SJohn Marino static unsigned int *regno_max_ref_width;
3459*e4b17023SJohn Marino 
3460*e4b17023SJohn Marino /* Redefine STACK_GROWS_DOWNWARD in terms of 0 or 1.  */
3461*e4b17023SJohn Marino #ifdef STACK_GROWS_DOWNWARD
3462*e4b17023SJohn Marino # undef STACK_GROWS_DOWNWARD
3463*e4b17023SJohn Marino # define STACK_GROWS_DOWNWARD 1
3464*e4b17023SJohn Marino #else
3465*e4b17023SJohn Marino # define STACK_GROWS_DOWNWARD 0
3466*e4b17023SJohn Marino #endif
3467*e4b17023SJohn Marino 
3468*e4b17023SJohn Marino /* Sort pseudos according their slot numbers (putting ones with
3469*e4b17023SJohn Marino   smaller numbers first, or last when the frame pointer is not
3470*e4b17023SJohn Marino   needed).  */
3471*e4b17023SJohn Marino static int
coalesced_pseudo_reg_slot_compare(const void * v1p,const void * v2p)3472*e4b17023SJohn Marino coalesced_pseudo_reg_slot_compare (const void *v1p, const void *v2p)
3473*e4b17023SJohn Marino {
3474*e4b17023SJohn Marino   const int regno1 = *(const int *) v1p;
3475*e4b17023SJohn Marino   const int regno2 = *(const int *) v2p;
3476*e4b17023SJohn Marino   ira_allocno_t a1 = ira_regno_allocno_map[regno1];
3477*e4b17023SJohn Marino   ira_allocno_t a2 = ira_regno_allocno_map[regno2];
3478*e4b17023SJohn Marino   int diff, slot_num1, slot_num2;
3479*e4b17023SJohn Marino   int total_size1, total_size2;
3480*e4b17023SJohn Marino 
3481*e4b17023SJohn Marino   if (a1 == NULL || ALLOCNO_HARD_REGNO (a1) >= 0)
3482*e4b17023SJohn Marino     {
3483*e4b17023SJohn Marino       if (a2 == NULL || ALLOCNO_HARD_REGNO (a2) >= 0)
3484*e4b17023SJohn Marino 	return regno1 - regno2;
3485*e4b17023SJohn Marino       return 1;
3486*e4b17023SJohn Marino     }
3487*e4b17023SJohn Marino   else if (a2 == NULL || ALLOCNO_HARD_REGNO (a2) >= 0)
3488*e4b17023SJohn Marino     return -1;
3489*e4b17023SJohn Marino   slot_num1 = -ALLOCNO_HARD_REGNO (a1);
3490*e4b17023SJohn Marino   slot_num2 = -ALLOCNO_HARD_REGNO (a2);
3491*e4b17023SJohn Marino   if ((diff = slot_num1 - slot_num2) != 0)
3492*e4b17023SJohn Marino     return (frame_pointer_needed
3493*e4b17023SJohn Marino 	    || !FRAME_GROWS_DOWNWARD == STACK_GROWS_DOWNWARD ? diff : -diff);
3494*e4b17023SJohn Marino   total_size1 = MAX (PSEUDO_REGNO_BYTES (regno1),
3495*e4b17023SJohn Marino 		     regno_max_ref_width[regno1]);
3496*e4b17023SJohn Marino   total_size2 = MAX (PSEUDO_REGNO_BYTES (regno2),
3497*e4b17023SJohn Marino 		     regno_max_ref_width[regno2]);
3498*e4b17023SJohn Marino   if ((diff = total_size2 - total_size1) != 0)
3499*e4b17023SJohn Marino     return diff;
3500*e4b17023SJohn Marino   return regno1 - regno2;
3501*e4b17023SJohn Marino }
3502*e4b17023SJohn Marino 
3503*e4b17023SJohn Marino /* Setup REGNO_COALESCED_ALLOCNO_COST and REGNO_COALESCED_ALLOCNO_NUM
3504*e4b17023SJohn Marino    for coalesced allocno sets containing allocnos with their regnos
3505*e4b17023SJohn Marino    given in array PSEUDO_REGNOS of length N.  */
3506*e4b17023SJohn Marino static void
setup_coalesced_allocno_costs_and_nums(int * pseudo_regnos,int n)3507*e4b17023SJohn Marino setup_coalesced_allocno_costs_and_nums (int *pseudo_regnos, int n)
3508*e4b17023SJohn Marino {
3509*e4b17023SJohn Marino   int i, num, regno, cost;
3510*e4b17023SJohn Marino   ira_allocno_t allocno, a;
3511*e4b17023SJohn Marino 
3512*e4b17023SJohn Marino   for (num = i = 0; i < n; i++)
3513*e4b17023SJohn Marino     {
3514*e4b17023SJohn Marino       regno = pseudo_regnos[i];
3515*e4b17023SJohn Marino       allocno = ira_regno_allocno_map[regno];
3516*e4b17023SJohn Marino       if (allocno == NULL)
3517*e4b17023SJohn Marino 	{
3518*e4b17023SJohn Marino 	  regno_coalesced_allocno_cost[regno] = 0;
3519*e4b17023SJohn Marino 	  regno_coalesced_allocno_num[regno] = ++num;
3520*e4b17023SJohn Marino 	  continue;
3521*e4b17023SJohn Marino 	}
3522*e4b17023SJohn Marino       if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno)
3523*e4b17023SJohn Marino 	continue;
3524*e4b17023SJohn Marino       num++;
3525*e4b17023SJohn Marino       for (cost = 0, a = ALLOCNO_COALESCE_DATA (allocno)->next;;
3526*e4b17023SJohn Marino 	   a = ALLOCNO_COALESCE_DATA (a)->next)
3527*e4b17023SJohn Marino 	{
3528*e4b17023SJohn Marino 	  cost += ALLOCNO_FREQ (a);
3529*e4b17023SJohn Marino 	  if (a == allocno)
3530*e4b17023SJohn Marino 	    break;
3531*e4b17023SJohn Marino 	}
3532*e4b17023SJohn Marino       for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
3533*e4b17023SJohn Marino 	   a = ALLOCNO_COALESCE_DATA (a)->next)
3534*e4b17023SJohn Marino 	{
3535*e4b17023SJohn Marino 	  regno_coalesced_allocno_num[ALLOCNO_REGNO (a)] = num;
3536*e4b17023SJohn Marino 	  regno_coalesced_allocno_cost[ALLOCNO_REGNO (a)] = cost;
3537*e4b17023SJohn Marino 	  if (a == allocno)
3538*e4b17023SJohn Marino 	    break;
3539*e4b17023SJohn Marino 	}
3540*e4b17023SJohn Marino     }
3541*e4b17023SJohn Marino }
3542*e4b17023SJohn Marino 
3543*e4b17023SJohn Marino /* Collect spilled allocnos representing coalesced allocno sets (the
3544*e4b17023SJohn Marino    first coalesced allocno).  The collected allocnos are returned
3545*e4b17023SJohn Marino    through array SPILLED_COALESCED_ALLOCNOS.  The function returns the
3546*e4b17023SJohn Marino    number of the collected allocnos.  The allocnos are given by their
3547*e4b17023SJohn Marino    regnos in array PSEUDO_REGNOS of length N.  */
3548*e4b17023SJohn Marino static int
collect_spilled_coalesced_allocnos(int * pseudo_regnos,int n,ira_allocno_t * spilled_coalesced_allocnos)3549*e4b17023SJohn Marino collect_spilled_coalesced_allocnos (int *pseudo_regnos, int n,
3550*e4b17023SJohn Marino 				    ira_allocno_t *spilled_coalesced_allocnos)
3551*e4b17023SJohn Marino {
3552*e4b17023SJohn Marino   int i, num, regno;
3553*e4b17023SJohn Marino   ira_allocno_t allocno;
3554*e4b17023SJohn Marino 
3555*e4b17023SJohn Marino   for (num = i = 0; i < n; i++)
3556*e4b17023SJohn Marino     {
3557*e4b17023SJohn Marino       regno = pseudo_regnos[i];
3558*e4b17023SJohn Marino       allocno = ira_regno_allocno_map[regno];
3559*e4b17023SJohn Marino       if (allocno == NULL || ALLOCNO_HARD_REGNO (allocno) >= 0
3560*e4b17023SJohn Marino 	  || ALLOCNO_COALESCE_DATA (allocno)->first != allocno)
3561*e4b17023SJohn Marino 	continue;
3562*e4b17023SJohn Marino       spilled_coalesced_allocnos[num++] = allocno;
3563*e4b17023SJohn Marino     }
3564*e4b17023SJohn Marino   return num;
3565*e4b17023SJohn Marino }
3566*e4b17023SJohn Marino 
3567*e4b17023SJohn Marino /* Array of live ranges of size IRA_ALLOCNOS_NUM.  Live range for
3568*e4b17023SJohn Marino    given slot contains live ranges of coalesced allocnos assigned to
3569*e4b17023SJohn Marino    given slot.  */
3570*e4b17023SJohn Marino static live_range_t *slot_coalesced_allocnos_live_ranges;
3571*e4b17023SJohn Marino 
3572*e4b17023SJohn Marino /* Return TRUE if coalesced allocnos represented by ALLOCNO has live
3573*e4b17023SJohn Marino    ranges intersected with live ranges of coalesced allocnos assigned
3574*e4b17023SJohn Marino    to slot with number N.  */
3575*e4b17023SJohn Marino static bool
slot_coalesced_allocno_live_ranges_intersect_p(ira_allocno_t allocno,int n)3576*e4b17023SJohn Marino slot_coalesced_allocno_live_ranges_intersect_p (ira_allocno_t allocno, int n)
3577*e4b17023SJohn Marino {
3578*e4b17023SJohn Marino   ira_allocno_t a;
3579*e4b17023SJohn Marino 
3580*e4b17023SJohn Marino   for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
3581*e4b17023SJohn Marino        a = ALLOCNO_COALESCE_DATA (a)->next)
3582*e4b17023SJohn Marino     {
3583*e4b17023SJohn Marino       int i;
3584*e4b17023SJohn Marino       int nr = ALLOCNO_NUM_OBJECTS (a);
3585*e4b17023SJohn Marino 
3586*e4b17023SJohn Marino       for (i = 0; i < nr; i++)
3587*e4b17023SJohn Marino 	{
3588*e4b17023SJohn Marino 	  ira_object_t obj = ALLOCNO_OBJECT (a, i);
3589*e4b17023SJohn Marino 
3590*e4b17023SJohn Marino 	  if (ira_live_ranges_intersect_p
3591*e4b17023SJohn Marino 	      (slot_coalesced_allocnos_live_ranges[n],
3592*e4b17023SJohn Marino 	       OBJECT_LIVE_RANGES (obj)))
3593*e4b17023SJohn Marino 	    return true;
3594*e4b17023SJohn Marino 	}
3595*e4b17023SJohn Marino       if (a == allocno)
3596*e4b17023SJohn Marino 	break;
3597*e4b17023SJohn Marino     }
3598*e4b17023SJohn Marino   return false;
3599*e4b17023SJohn Marino }
3600*e4b17023SJohn Marino 
3601*e4b17023SJohn Marino /* Update live ranges of slot to which coalesced allocnos represented
3602*e4b17023SJohn Marino    by ALLOCNO were assigned.  */
3603*e4b17023SJohn Marino static void
setup_slot_coalesced_allocno_live_ranges(ira_allocno_t allocno)3604*e4b17023SJohn Marino setup_slot_coalesced_allocno_live_ranges (ira_allocno_t allocno)
3605*e4b17023SJohn Marino {
3606*e4b17023SJohn Marino   int i, n;
3607*e4b17023SJohn Marino   ira_allocno_t a;
3608*e4b17023SJohn Marino   live_range_t r;
3609*e4b17023SJohn Marino 
3610*e4b17023SJohn Marino   n = ALLOCNO_COALESCE_DATA (allocno)->temp;
3611*e4b17023SJohn Marino   for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
3612*e4b17023SJohn Marino        a = ALLOCNO_COALESCE_DATA (a)->next)
3613*e4b17023SJohn Marino     {
3614*e4b17023SJohn Marino       int nr = ALLOCNO_NUM_OBJECTS (a);
3615*e4b17023SJohn Marino       for (i = 0; i < nr; i++)
3616*e4b17023SJohn Marino 	{
3617*e4b17023SJohn Marino 	  ira_object_t obj = ALLOCNO_OBJECT (a, i);
3618*e4b17023SJohn Marino 
3619*e4b17023SJohn Marino 	  r = ira_copy_live_range_list (OBJECT_LIVE_RANGES (obj));
3620*e4b17023SJohn Marino 	  slot_coalesced_allocnos_live_ranges[n]
3621*e4b17023SJohn Marino 	    = ira_merge_live_ranges
3622*e4b17023SJohn Marino 	      (slot_coalesced_allocnos_live_ranges[n], r);
3623*e4b17023SJohn Marino 	}
3624*e4b17023SJohn Marino       if (a == allocno)
3625*e4b17023SJohn Marino 	break;
3626*e4b17023SJohn Marino     }
3627*e4b17023SJohn Marino }
3628*e4b17023SJohn Marino 
3629*e4b17023SJohn Marino /* We have coalesced allocnos involving in copies.  Coalesce allocnos
3630*e4b17023SJohn Marino    further in order to share the same memory stack slot.  Allocnos
3631*e4b17023SJohn Marino    representing sets of allocnos coalesced before the call are given
3632*e4b17023SJohn Marino    in array SPILLED_COALESCED_ALLOCNOS of length NUM.  Return TRUE if
3633*e4b17023SJohn Marino    some allocnos were coalesced in the function.  */
3634*e4b17023SJohn Marino static bool
coalesce_spill_slots(ira_allocno_t * spilled_coalesced_allocnos,int num)3635*e4b17023SJohn Marino coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num)
3636*e4b17023SJohn Marino {
3637*e4b17023SJohn Marino   int i, j, n, last_coalesced_allocno_num;
3638*e4b17023SJohn Marino   ira_allocno_t allocno, a;
3639*e4b17023SJohn Marino   bool merged_p = false;
3640*e4b17023SJohn Marino   bitmap set_jump_crosses = regstat_get_setjmp_crosses ();
3641*e4b17023SJohn Marino 
3642*e4b17023SJohn Marino   slot_coalesced_allocnos_live_ranges
3643*e4b17023SJohn Marino     = (live_range_t *) ira_allocate (sizeof (live_range_t) * ira_allocnos_num);
3644*e4b17023SJohn Marino   memset (slot_coalesced_allocnos_live_ranges, 0,
3645*e4b17023SJohn Marino 	  sizeof (live_range_t) * ira_allocnos_num);
3646*e4b17023SJohn Marino   last_coalesced_allocno_num = 0;
3647*e4b17023SJohn Marino   /* Coalesce non-conflicting spilled allocnos preferring most
3648*e4b17023SJohn Marino      frequently used.  */
3649*e4b17023SJohn Marino   for (i = 0; i < num; i++)
3650*e4b17023SJohn Marino     {
3651*e4b17023SJohn Marino       allocno = spilled_coalesced_allocnos[i];
3652*e4b17023SJohn Marino       if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno
3653*e4b17023SJohn Marino 	  || bitmap_bit_p (set_jump_crosses, ALLOCNO_REGNO (allocno))
3654*e4b17023SJohn Marino 	  || (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len
3655*e4b17023SJohn Marino 	      && (ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX
3656*e4b17023SJohn Marino 		  || ira_reg_equiv_invariant_p[ALLOCNO_REGNO (allocno)])))
3657*e4b17023SJohn Marino 	continue;
3658*e4b17023SJohn Marino       for (j = 0; j < i; j++)
3659*e4b17023SJohn Marino 	{
3660*e4b17023SJohn Marino 	  a = spilled_coalesced_allocnos[j];
3661*e4b17023SJohn Marino 	  n = ALLOCNO_COALESCE_DATA (a)->temp;
3662*e4b17023SJohn Marino 	  if (ALLOCNO_COALESCE_DATA (a)->first == a
3663*e4b17023SJohn Marino 	      && ! bitmap_bit_p (set_jump_crosses, ALLOCNO_REGNO (a))
3664*e4b17023SJohn Marino 	      && (ALLOCNO_REGNO (a) >= ira_reg_equiv_len
3665*e4b17023SJohn Marino 		  || (! ira_reg_equiv_invariant_p[ALLOCNO_REGNO (a)]
3666*e4b17023SJohn Marino 		      && ira_reg_equiv_const[ALLOCNO_REGNO (a)] == NULL_RTX))
3667*e4b17023SJohn Marino 	      && ! slot_coalesced_allocno_live_ranges_intersect_p (allocno, n))
3668*e4b17023SJohn Marino 	    break;
3669*e4b17023SJohn Marino 	}
3670*e4b17023SJohn Marino       if (j >= i)
3671*e4b17023SJohn Marino 	{
3672*e4b17023SJohn Marino 	  /* No coalescing: set up number for coalesced allocnos
3673*e4b17023SJohn Marino 	     represented by ALLOCNO.  */
3674*e4b17023SJohn Marino 	  ALLOCNO_COALESCE_DATA (allocno)->temp = last_coalesced_allocno_num++;
3675*e4b17023SJohn Marino 	  setup_slot_coalesced_allocno_live_ranges (allocno);
3676*e4b17023SJohn Marino 	}
3677*e4b17023SJohn Marino       else
3678*e4b17023SJohn Marino 	{
3679*e4b17023SJohn Marino 	  allocno_coalesced_p = true;
3680*e4b17023SJohn Marino 	  merged_p = true;
3681*e4b17023SJohn Marino 	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
3682*e4b17023SJohn Marino 	    fprintf (ira_dump_file,
3683*e4b17023SJohn Marino 		     "      Coalescing spilled allocnos a%dr%d->a%dr%d\n",
3684*e4b17023SJohn Marino 		     ALLOCNO_NUM (allocno), ALLOCNO_REGNO (allocno),
3685*e4b17023SJohn Marino 		     ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
3686*e4b17023SJohn Marino 	  ALLOCNO_COALESCE_DATA (allocno)->temp
3687*e4b17023SJohn Marino 	    = ALLOCNO_COALESCE_DATA (a)->temp;
3688*e4b17023SJohn Marino 	  setup_slot_coalesced_allocno_live_ranges (allocno);
3689*e4b17023SJohn Marino 	  merge_allocnos (a, allocno);
3690*e4b17023SJohn Marino 	  ira_assert (ALLOCNO_COALESCE_DATA (a)->first == a);
3691*e4b17023SJohn Marino 	}
3692*e4b17023SJohn Marino     }
3693*e4b17023SJohn Marino   for (i = 0; i < ira_allocnos_num; i++)
3694*e4b17023SJohn Marino     ira_finish_live_range_list (slot_coalesced_allocnos_live_ranges[i]);
3695*e4b17023SJohn Marino   ira_free (slot_coalesced_allocnos_live_ranges);
3696*e4b17023SJohn Marino   return merged_p;
3697*e4b17023SJohn Marino }
3698*e4b17023SJohn Marino 
3699*e4b17023SJohn Marino /* Sort pseudo-register numbers in array PSEUDO_REGNOS of length N for
3700*e4b17023SJohn Marino    subsequent assigning stack slots to them in the reload pass.  To do
3701*e4b17023SJohn Marino    this we coalesce spilled allocnos first to decrease the number of
3702*e4b17023SJohn Marino    memory-memory move insns.  This function is called by the
3703*e4b17023SJohn Marino    reload.  */
3704*e4b17023SJohn Marino void
ira_sort_regnos_for_alter_reg(int * pseudo_regnos,int n,unsigned int * reg_max_ref_width)3705*e4b17023SJohn Marino ira_sort_regnos_for_alter_reg (int *pseudo_regnos, int n,
3706*e4b17023SJohn Marino 			       unsigned int *reg_max_ref_width)
3707*e4b17023SJohn Marino {
3708*e4b17023SJohn Marino   int max_regno = max_reg_num ();
3709*e4b17023SJohn Marino   int i, regno, num, slot_num;
3710*e4b17023SJohn Marino   ira_allocno_t allocno, a;
3711*e4b17023SJohn Marino   ira_allocno_iterator ai;
3712*e4b17023SJohn Marino   ira_allocno_t *spilled_coalesced_allocnos;
3713*e4b17023SJohn Marino 
3714*e4b17023SJohn Marino   /* Set up allocnos can be coalesced.  */
3715*e4b17023SJohn Marino   coloring_allocno_bitmap = ira_allocate_bitmap ();
3716*e4b17023SJohn Marino   for (i = 0; i < n; i++)
3717*e4b17023SJohn Marino     {
3718*e4b17023SJohn Marino       regno = pseudo_regnos[i];
3719*e4b17023SJohn Marino       allocno = ira_regno_allocno_map[regno];
3720*e4b17023SJohn Marino       if (allocno != NULL)
3721*e4b17023SJohn Marino 	bitmap_set_bit (coloring_allocno_bitmap, ALLOCNO_NUM (allocno));
3722*e4b17023SJohn Marino     }
3723*e4b17023SJohn Marino   allocno_coalesced_p = false;
3724*e4b17023SJohn Marino   processed_coalesced_allocno_bitmap = ira_allocate_bitmap ();
3725*e4b17023SJohn Marino   allocno_coalesce_data
3726*e4b17023SJohn Marino     = (coalesce_data_t) ira_allocate (sizeof (struct coalesce_data)
3727*e4b17023SJohn Marino 				      * ira_allocnos_num);
3728*e4b17023SJohn Marino   /* Initialize coalesce data for allocnos.  */
3729*e4b17023SJohn Marino   FOR_EACH_ALLOCNO (a, ai)
3730*e4b17023SJohn Marino     {
3731*e4b17023SJohn Marino       ALLOCNO_ADD_DATA (a) = allocno_coalesce_data + ALLOCNO_NUM (a);
3732*e4b17023SJohn Marino       ALLOCNO_COALESCE_DATA (a)->first = a;
3733*e4b17023SJohn Marino       ALLOCNO_COALESCE_DATA (a)->next = a;
3734*e4b17023SJohn Marino     }
3735*e4b17023SJohn Marino   coalesce_allocnos ();
3736*e4b17023SJohn Marino   ira_free_bitmap (coloring_allocno_bitmap);
3737*e4b17023SJohn Marino   regno_coalesced_allocno_cost
3738*e4b17023SJohn Marino     = (int *) ira_allocate (max_regno * sizeof (int));
3739*e4b17023SJohn Marino   regno_coalesced_allocno_num
3740*e4b17023SJohn Marino     = (int *) ira_allocate (max_regno * sizeof (int));
3741*e4b17023SJohn Marino   memset (regno_coalesced_allocno_num, 0, max_regno * sizeof (int));
3742*e4b17023SJohn Marino   setup_coalesced_allocno_costs_and_nums (pseudo_regnos, n);
3743*e4b17023SJohn Marino   /* Sort regnos according frequencies of the corresponding coalesced
3744*e4b17023SJohn Marino      allocno sets.  */
3745*e4b17023SJohn Marino   qsort (pseudo_regnos, n, sizeof (int), coalesced_pseudo_reg_freq_compare);
3746*e4b17023SJohn Marino   spilled_coalesced_allocnos
3747*e4b17023SJohn Marino     = (ira_allocno_t *) ira_allocate (ira_allocnos_num
3748*e4b17023SJohn Marino 				      * sizeof (ira_allocno_t));
3749*e4b17023SJohn Marino   /* Collect allocnos representing the spilled coalesced allocno
3750*e4b17023SJohn Marino      sets.  */
3751*e4b17023SJohn Marino   num = collect_spilled_coalesced_allocnos (pseudo_regnos, n,
3752*e4b17023SJohn Marino 					    spilled_coalesced_allocnos);
3753*e4b17023SJohn Marino   if (flag_ira_share_spill_slots
3754*e4b17023SJohn Marino       && coalesce_spill_slots (spilled_coalesced_allocnos, num))
3755*e4b17023SJohn Marino     {
3756*e4b17023SJohn Marino       setup_coalesced_allocno_costs_and_nums (pseudo_regnos, n);
3757*e4b17023SJohn Marino       qsort (pseudo_regnos, n, sizeof (int),
3758*e4b17023SJohn Marino 	     coalesced_pseudo_reg_freq_compare);
3759*e4b17023SJohn Marino       num = collect_spilled_coalesced_allocnos (pseudo_regnos, n,
3760*e4b17023SJohn Marino 						spilled_coalesced_allocnos);
3761*e4b17023SJohn Marino     }
3762*e4b17023SJohn Marino   ira_free_bitmap (processed_coalesced_allocno_bitmap);
3763*e4b17023SJohn Marino   allocno_coalesced_p = false;
3764*e4b17023SJohn Marino   /* Assign stack slot numbers to spilled allocno sets, use smaller
3765*e4b17023SJohn Marino      numbers for most frequently used coalesced allocnos.  -1 is
3766*e4b17023SJohn Marino      reserved for dynamic search of stack slots for pseudos spilled by
3767*e4b17023SJohn Marino      the reload.  */
3768*e4b17023SJohn Marino   slot_num = 1;
3769*e4b17023SJohn Marino   for (i = 0; i < num; i++)
3770*e4b17023SJohn Marino     {
3771*e4b17023SJohn Marino       allocno = spilled_coalesced_allocnos[i];
3772*e4b17023SJohn Marino       if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno
3773*e4b17023SJohn Marino 	  || ALLOCNO_HARD_REGNO (allocno) >= 0
3774*e4b17023SJohn Marino 	  || (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len
3775*e4b17023SJohn Marino 	      && (ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX
3776*e4b17023SJohn Marino 		  || ira_reg_equiv_invariant_p[ALLOCNO_REGNO (allocno)])))
3777*e4b17023SJohn Marino 	continue;
3778*e4b17023SJohn Marino       if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
3779*e4b17023SJohn Marino 	fprintf (ira_dump_file, "      Slot %d (freq,size):", slot_num);
3780*e4b17023SJohn Marino       slot_num++;
3781*e4b17023SJohn Marino       for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
3782*e4b17023SJohn Marino 	   a = ALLOCNO_COALESCE_DATA (a)->next)
3783*e4b17023SJohn Marino 	{
3784*e4b17023SJohn Marino 	  ira_assert (ALLOCNO_HARD_REGNO (a) < 0);
3785*e4b17023SJohn Marino 	  ALLOCNO_HARD_REGNO (a) = -slot_num;
3786*e4b17023SJohn Marino 	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
3787*e4b17023SJohn Marino 	    fprintf (ira_dump_file, " a%dr%d(%d,%d)",
3788*e4b17023SJohn Marino 		     ALLOCNO_NUM (a), ALLOCNO_REGNO (a), ALLOCNO_FREQ (a),
3789*e4b17023SJohn Marino 		     MAX (PSEUDO_REGNO_BYTES (ALLOCNO_REGNO (a)),
3790*e4b17023SJohn Marino 			  reg_max_ref_width[ALLOCNO_REGNO (a)]));
3791*e4b17023SJohn Marino 
3792*e4b17023SJohn Marino 	  if (a == allocno)
3793*e4b17023SJohn Marino 	    break;
3794*e4b17023SJohn Marino 	}
3795*e4b17023SJohn Marino       if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
3796*e4b17023SJohn Marino 	fprintf (ira_dump_file, "\n");
3797*e4b17023SJohn Marino     }
3798*e4b17023SJohn Marino   ira_spilled_reg_stack_slots_num = slot_num - 1;
3799*e4b17023SJohn Marino   ira_free (spilled_coalesced_allocnos);
3800*e4b17023SJohn Marino   /* Sort regnos according the slot numbers.  */
3801*e4b17023SJohn Marino   regno_max_ref_width = reg_max_ref_width;
3802*e4b17023SJohn Marino   qsort (pseudo_regnos, n, sizeof (int), coalesced_pseudo_reg_slot_compare);
3803*e4b17023SJohn Marino   FOR_EACH_ALLOCNO (a, ai)
3804*e4b17023SJohn Marino     ALLOCNO_ADD_DATA (a) = NULL;
3805*e4b17023SJohn Marino   ira_free (allocno_coalesce_data);
3806*e4b17023SJohn Marino   ira_free (regno_coalesced_allocno_num);
3807*e4b17023SJohn Marino   ira_free (regno_coalesced_allocno_cost);
3808*e4b17023SJohn Marino }
3809*e4b17023SJohn Marino 
3810*e4b17023SJohn Marino 
3811*e4b17023SJohn Marino 
3812*e4b17023SJohn Marino /* This page contains code used by the reload pass to improve the
3813*e4b17023SJohn Marino    final code.  */
3814*e4b17023SJohn Marino 
3815*e4b17023SJohn Marino /* The function is called from reload to mark changes in the
3816*e4b17023SJohn Marino    allocation of REGNO made by the reload.  Remember that reg_renumber
3817*e4b17023SJohn Marino    reflects the change result.  */
3818*e4b17023SJohn Marino void
ira_mark_allocation_change(int regno)3819*e4b17023SJohn Marino ira_mark_allocation_change (int regno)
3820*e4b17023SJohn Marino {
3821*e4b17023SJohn Marino   ira_allocno_t a = ira_regno_allocno_map[regno];
3822*e4b17023SJohn Marino   int old_hard_regno, hard_regno, cost;
3823*e4b17023SJohn Marino   enum reg_class aclass = ALLOCNO_CLASS (a);
3824*e4b17023SJohn Marino 
3825*e4b17023SJohn Marino   ira_assert (a != NULL);
3826*e4b17023SJohn Marino   hard_regno = reg_renumber[regno];
3827*e4b17023SJohn Marino   if ((old_hard_regno = ALLOCNO_HARD_REGNO (a)) == hard_regno)
3828*e4b17023SJohn Marino     return;
3829*e4b17023SJohn Marino   if (old_hard_regno < 0)
3830*e4b17023SJohn Marino     cost = -ALLOCNO_MEMORY_COST (a);
3831*e4b17023SJohn Marino   else
3832*e4b17023SJohn Marino     {
3833*e4b17023SJohn Marino       ira_assert (ira_class_hard_reg_index[aclass][old_hard_regno] >= 0);
3834*e4b17023SJohn Marino       cost = -(ALLOCNO_HARD_REG_COSTS (a) == NULL
3835*e4b17023SJohn Marino 	       ? ALLOCNO_CLASS_COST (a)
3836*e4b17023SJohn Marino 	       : ALLOCNO_HARD_REG_COSTS (a)
3837*e4b17023SJohn Marino 	         [ira_class_hard_reg_index[aclass][old_hard_regno]]);
3838*e4b17023SJohn Marino       update_copy_costs (a, false);
3839*e4b17023SJohn Marino     }
3840*e4b17023SJohn Marino   ira_overall_cost -= cost;
3841*e4b17023SJohn Marino   ALLOCNO_HARD_REGNO (a) = hard_regno;
3842*e4b17023SJohn Marino   if (hard_regno < 0)
3843*e4b17023SJohn Marino     {
3844*e4b17023SJohn Marino       ALLOCNO_HARD_REGNO (a) = -1;
3845*e4b17023SJohn Marino       cost += ALLOCNO_MEMORY_COST (a);
3846*e4b17023SJohn Marino     }
3847*e4b17023SJohn Marino   else if (ira_class_hard_reg_index[aclass][hard_regno] >= 0)
3848*e4b17023SJohn Marino     {
3849*e4b17023SJohn Marino       cost += (ALLOCNO_HARD_REG_COSTS (a) == NULL
3850*e4b17023SJohn Marino 	       ? ALLOCNO_CLASS_COST (a)
3851*e4b17023SJohn Marino 	       : ALLOCNO_HARD_REG_COSTS (a)
3852*e4b17023SJohn Marino 	         [ira_class_hard_reg_index[aclass][hard_regno]]);
3853*e4b17023SJohn Marino       update_copy_costs (a, true);
3854*e4b17023SJohn Marino     }
3855*e4b17023SJohn Marino   else
3856*e4b17023SJohn Marino     /* Reload changed class of the allocno.  */
3857*e4b17023SJohn Marino     cost = 0;
3858*e4b17023SJohn Marino   ira_overall_cost += cost;
3859*e4b17023SJohn Marino }
3860*e4b17023SJohn Marino 
3861*e4b17023SJohn Marino /* This function is called when reload deletes memory-memory move.  In
3862*e4b17023SJohn Marino    this case we marks that the allocation of the corresponding
3863*e4b17023SJohn Marino    allocnos should be not changed in future.  Otherwise we risk to get
3864*e4b17023SJohn Marino    a wrong code.  */
3865*e4b17023SJohn Marino void
ira_mark_memory_move_deletion(int dst_regno,int src_regno)3866*e4b17023SJohn Marino ira_mark_memory_move_deletion (int dst_regno, int src_regno)
3867*e4b17023SJohn Marino {
3868*e4b17023SJohn Marino   ira_allocno_t dst = ira_regno_allocno_map[dst_regno];
3869*e4b17023SJohn Marino   ira_allocno_t src = ira_regno_allocno_map[src_regno];
3870*e4b17023SJohn Marino 
3871*e4b17023SJohn Marino   ira_assert (dst != NULL && src != NULL
3872*e4b17023SJohn Marino 	      && ALLOCNO_HARD_REGNO (dst) < 0
3873*e4b17023SJohn Marino 	      && ALLOCNO_HARD_REGNO (src) < 0);
3874*e4b17023SJohn Marino   ALLOCNO_DONT_REASSIGN_P (dst) = true;
3875*e4b17023SJohn Marino   ALLOCNO_DONT_REASSIGN_P (src) = true;
3876*e4b17023SJohn Marino }
3877*e4b17023SJohn Marino 
3878*e4b17023SJohn Marino /* Try to assign a hard register (except for FORBIDDEN_REGS) to
3879*e4b17023SJohn Marino    allocno A and return TRUE in the case of success.  */
3880*e4b17023SJohn Marino static bool
allocno_reload_assign(ira_allocno_t a,HARD_REG_SET forbidden_regs)3881*e4b17023SJohn Marino allocno_reload_assign (ira_allocno_t a, HARD_REG_SET forbidden_regs)
3882*e4b17023SJohn Marino {
3883*e4b17023SJohn Marino   int hard_regno;
3884*e4b17023SJohn Marino   enum reg_class aclass;
3885*e4b17023SJohn Marino   int regno = ALLOCNO_REGNO (a);
3886*e4b17023SJohn Marino   HARD_REG_SET saved[2];
3887*e4b17023SJohn Marino   int i, n;
3888*e4b17023SJohn Marino 
3889*e4b17023SJohn Marino   n = ALLOCNO_NUM_OBJECTS (a);
3890*e4b17023SJohn Marino   for (i = 0; i < n; i++)
3891*e4b17023SJohn Marino     {
3892*e4b17023SJohn Marino       ira_object_t obj = ALLOCNO_OBJECT (a, i);
3893*e4b17023SJohn Marino       COPY_HARD_REG_SET (saved[i], OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
3894*e4b17023SJohn Marino       IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), forbidden_regs);
3895*e4b17023SJohn Marino       if (! flag_caller_saves && ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
3896*e4b17023SJohn Marino 	IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
3897*e4b17023SJohn Marino 			  call_used_reg_set);
3898*e4b17023SJohn Marino     }
3899*e4b17023SJohn Marino   ALLOCNO_ASSIGNED_P (a) = false;
3900*e4b17023SJohn Marino   aclass = ALLOCNO_CLASS (a);
3901*e4b17023SJohn Marino   update_curr_costs (a);
3902*e4b17023SJohn Marino   assign_hard_reg (a, true);
3903*e4b17023SJohn Marino   hard_regno = ALLOCNO_HARD_REGNO (a);
3904*e4b17023SJohn Marino   reg_renumber[regno] = hard_regno;
3905*e4b17023SJohn Marino   if (hard_regno < 0)
3906*e4b17023SJohn Marino     ALLOCNO_HARD_REGNO (a) = -1;
3907*e4b17023SJohn Marino   else
3908*e4b17023SJohn Marino     {
3909*e4b17023SJohn Marino       ira_assert (ira_class_hard_reg_index[aclass][hard_regno] >= 0);
3910*e4b17023SJohn Marino       ira_overall_cost
3911*e4b17023SJohn Marino 	-= (ALLOCNO_MEMORY_COST (a)
3912*e4b17023SJohn Marino 	    - (ALLOCNO_HARD_REG_COSTS (a) == NULL
3913*e4b17023SJohn Marino 	       ? ALLOCNO_CLASS_COST (a)
3914*e4b17023SJohn Marino 	       : ALLOCNO_HARD_REG_COSTS (a)[ira_class_hard_reg_index
3915*e4b17023SJohn Marino 					    [aclass][hard_regno]]));
3916*e4b17023SJohn Marino       if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0
3917*e4b17023SJohn Marino 	  && ira_hard_reg_set_intersection_p (hard_regno, ALLOCNO_MODE (a),
3918*e4b17023SJohn Marino 					      call_used_reg_set))
3919*e4b17023SJohn Marino 	{
3920*e4b17023SJohn Marino 	  ira_assert (flag_caller_saves);
3921*e4b17023SJohn Marino 	  caller_save_needed = 1;
3922*e4b17023SJohn Marino 	}
3923*e4b17023SJohn Marino     }
3924*e4b17023SJohn Marino 
3925*e4b17023SJohn Marino   /* If we found a hard register, modify the RTL for the pseudo
3926*e4b17023SJohn Marino      register to show the hard register, and mark the pseudo register
3927*e4b17023SJohn Marino      live.  */
3928*e4b17023SJohn Marino   if (reg_renumber[regno] >= 0)
3929*e4b17023SJohn Marino     {
3930*e4b17023SJohn Marino       if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
3931*e4b17023SJohn Marino 	fprintf (ira_dump_file, ": reassign to %d\n", reg_renumber[regno]);
3932*e4b17023SJohn Marino       SET_REGNO (regno_reg_rtx[regno], reg_renumber[regno]);
3933*e4b17023SJohn Marino       mark_home_live (regno);
3934*e4b17023SJohn Marino     }
3935*e4b17023SJohn Marino   else if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
3936*e4b17023SJohn Marino     fprintf (ira_dump_file, "\n");
3937*e4b17023SJohn Marino   for (i = 0; i < n; i++)
3938*e4b17023SJohn Marino     {
3939*e4b17023SJohn Marino       ira_object_t obj = ALLOCNO_OBJECT (a, i);
3940*e4b17023SJohn Marino       COPY_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), saved[i]);
3941*e4b17023SJohn Marino     }
3942*e4b17023SJohn Marino   return reg_renumber[regno] >= 0;
3943*e4b17023SJohn Marino }
3944*e4b17023SJohn Marino 
3945*e4b17023SJohn Marino /* Sort pseudos according their usage frequencies (putting most
3946*e4b17023SJohn Marino    frequently ones first).  */
3947*e4b17023SJohn Marino static int
pseudo_reg_compare(const void * v1p,const void * v2p)3948*e4b17023SJohn Marino pseudo_reg_compare (const void *v1p, const void *v2p)
3949*e4b17023SJohn Marino {
3950*e4b17023SJohn Marino   int regno1 = *(const int *) v1p;
3951*e4b17023SJohn Marino   int regno2 = *(const int *) v2p;
3952*e4b17023SJohn Marino   int diff;
3953*e4b17023SJohn Marino 
3954*e4b17023SJohn Marino   if ((diff = REG_FREQ (regno2) - REG_FREQ (regno1)) != 0)
3955*e4b17023SJohn Marino     return diff;
3956*e4b17023SJohn Marino   return regno1 - regno2;
3957*e4b17023SJohn Marino }
3958*e4b17023SJohn Marino 
3959*e4b17023SJohn Marino /* Try to allocate hard registers to SPILLED_PSEUDO_REGS (there are
3960*e4b17023SJohn Marino    NUM of them) or spilled pseudos conflicting with pseudos in
3961*e4b17023SJohn Marino    SPILLED_PSEUDO_REGS.  Return TRUE and update SPILLED, if the
3962*e4b17023SJohn Marino    allocation has been changed.  The function doesn't use
3963*e4b17023SJohn Marino    BAD_SPILL_REGS and hard registers in PSEUDO_FORBIDDEN_REGS and
3964*e4b17023SJohn Marino    PSEUDO_PREVIOUS_REGS for the corresponding pseudos.  The function
3965*e4b17023SJohn Marino    is called by the reload pass at the end of each reload
3966*e4b17023SJohn Marino    iteration.  */
3967*e4b17023SJohn Marino bool
ira_reassign_pseudos(int * spilled_pseudo_regs,int num,HARD_REG_SET bad_spill_regs,HARD_REG_SET * pseudo_forbidden_regs,HARD_REG_SET * pseudo_previous_regs,bitmap spilled)3968*e4b17023SJohn Marino ira_reassign_pseudos (int *spilled_pseudo_regs, int num,
3969*e4b17023SJohn Marino 		      HARD_REG_SET bad_spill_regs,
3970*e4b17023SJohn Marino 		      HARD_REG_SET *pseudo_forbidden_regs,
3971*e4b17023SJohn Marino 		      HARD_REG_SET *pseudo_previous_regs,
3972*e4b17023SJohn Marino 		      bitmap spilled)
3973*e4b17023SJohn Marino {
3974*e4b17023SJohn Marino   int i, n, regno;
3975*e4b17023SJohn Marino   bool changed_p;
3976*e4b17023SJohn Marino   ira_allocno_t a;
3977*e4b17023SJohn Marino   HARD_REG_SET forbidden_regs;
3978*e4b17023SJohn Marino   bitmap temp = BITMAP_ALLOC (NULL);
3979*e4b17023SJohn Marino 
3980*e4b17023SJohn Marino   /* Add pseudos which conflict with pseudos already in
3981*e4b17023SJohn Marino      SPILLED_PSEUDO_REGS to SPILLED_PSEUDO_REGS.  This is preferable
3982*e4b17023SJohn Marino      to allocating in two steps as some of the conflicts might have
3983*e4b17023SJohn Marino      a higher priority than the pseudos passed in SPILLED_PSEUDO_REGS.  */
3984*e4b17023SJohn Marino   for (i = 0; i < num; i++)
3985*e4b17023SJohn Marino     bitmap_set_bit (temp, spilled_pseudo_regs[i]);
3986*e4b17023SJohn Marino 
3987*e4b17023SJohn Marino   for (i = 0, n = num; i < n; i++)
3988*e4b17023SJohn Marino     {
3989*e4b17023SJohn Marino       int nr, j;
3990*e4b17023SJohn Marino       int regno = spilled_pseudo_regs[i];
3991*e4b17023SJohn Marino       bitmap_set_bit (temp, regno);
3992*e4b17023SJohn Marino 
3993*e4b17023SJohn Marino       a = ira_regno_allocno_map[regno];
3994*e4b17023SJohn Marino       nr = ALLOCNO_NUM_OBJECTS (a);
3995*e4b17023SJohn Marino       for (j = 0; j < nr; j++)
3996*e4b17023SJohn Marino 	{
3997*e4b17023SJohn Marino 	  ira_object_t conflict_obj;
3998*e4b17023SJohn Marino 	  ira_object_t obj = ALLOCNO_OBJECT (a, j);
3999*e4b17023SJohn Marino 	  ira_object_conflict_iterator oci;
4000*e4b17023SJohn Marino 
4001*e4b17023SJohn Marino 	  FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
4002*e4b17023SJohn Marino 	    {
4003*e4b17023SJohn Marino 	      ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
4004*e4b17023SJohn Marino 	      if (ALLOCNO_HARD_REGNO (conflict_a) < 0
4005*e4b17023SJohn Marino 		  && ! ALLOCNO_DONT_REASSIGN_P (conflict_a)
4006*e4b17023SJohn Marino 		  && bitmap_set_bit (temp, ALLOCNO_REGNO (conflict_a)))
4007*e4b17023SJohn Marino 		{
4008*e4b17023SJohn Marino 		  spilled_pseudo_regs[num++] = ALLOCNO_REGNO (conflict_a);
4009*e4b17023SJohn Marino 		  /* ?!? This seems wrong.  */
4010*e4b17023SJohn Marino 		  bitmap_set_bit (consideration_allocno_bitmap,
4011*e4b17023SJohn Marino 				  ALLOCNO_NUM (conflict_a));
4012*e4b17023SJohn Marino 		}
4013*e4b17023SJohn Marino 	    }
4014*e4b17023SJohn Marino 	}
4015*e4b17023SJohn Marino     }
4016*e4b17023SJohn Marino 
4017*e4b17023SJohn Marino   if (num > 1)
4018*e4b17023SJohn Marino     qsort (spilled_pseudo_regs, num, sizeof (int), pseudo_reg_compare);
4019*e4b17023SJohn Marino   changed_p = false;
4020*e4b17023SJohn Marino   /* Try to assign hard registers to pseudos from
4021*e4b17023SJohn Marino      SPILLED_PSEUDO_REGS.  */
4022*e4b17023SJohn Marino   for (i = 0; i < num; i++)
4023*e4b17023SJohn Marino     {
4024*e4b17023SJohn Marino       regno = spilled_pseudo_regs[i];
4025*e4b17023SJohn Marino       COPY_HARD_REG_SET (forbidden_regs, bad_spill_regs);
4026*e4b17023SJohn Marino       IOR_HARD_REG_SET (forbidden_regs, pseudo_forbidden_regs[regno]);
4027*e4b17023SJohn Marino       IOR_HARD_REG_SET (forbidden_regs, pseudo_previous_regs[regno]);
4028*e4b17023SJohn Marino       gcc_assert (reg_renumber[regno] < 0);
4029*e4b17023SJohn Marino       a = ira_regno_allocno_map[regno];
4030*e4b17023SJohn Marino       ira_mark_allocation_change (regno);
4031*e4b17023SJohn Marino       ira_assert (reg_renumber[regno] < 0);
4032*e4b17023SJohn Marino       if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
4033*e4b17023SJohn Marino 	fprintf (ira_dump_file,
4034*e4b17023SJohn Marino 		 "      Try Assign %d(a%d), cost=%d", regno, ALLOCNO_NUM (a),
4035*e4b17023SJohn Marino 		 ALLOCNO_MEMORY_COST (a)
4036*e4b17023SJohn Marino 		 - ALLOCNO_CLASS_COST (a));
4037*e4b17023SJohn Marino       allocno_reload_assign (a, forbidden_regs);
4038*e4b17023SJohn Marino       if (reg_renumber[regno] >= 0)
4039*e4b17023SJohn Marino 	{
4040*e4b17023SJohn Marino 	  CLEAR_REGNO_REG_SET (spilled, regno);
4041*e4b17023SJohn Marino 	  changed_p = true;
4042*e4b17023SJohn Marino 	}
4043*e4b17023SJohn Marino     }
4044*e4b17023SJohn Marino   BITMAP_FREE (temp);
4045*e4b17023SJohn Marino   return changed_p;
4046*e4b17023SJohn Marino }
4047*e4b17023SJohn Marino 
4048*e4b17023SJohn Marino /* The function is called by reload and returns already allocated
4049*e4b17023SJohn Marino    stack slot (if any) for REGNO with given INHERENT_SIZE and
4050*e4b17023SJohn Marino    TOTAL_SIZE.  In the case of failure to find a slot which can be
4051*e4b17023SJohn Marino    used for REGNO, the function returns NULL.  */
4052*e4b17023SJohn Marino rtx
ira_reuse_stack_slot(int regno,unsigned int inherent_size,unsigned int total_size)4053*e4b17023SJohn Marino ira_reuse_stack_slot (int regno, unsigned int inherent_size,
4054*e4b17023SJohn Marino 		      unsigned int total_size)
4055*e4b17023SJohn Marino {
4056*e4b17023SJohn Marino   unsigned int i;
4057*e4b17023SJohn Marino   int slot_num, best_slot_num;
4058*e4b17023SJohn Marino   int cost, best_cost;
4059*e4b17023SJohn Marino   ira_copy_t cp, next_cp;
4060*e4b17023SJohn Marino   ira_allocno_t another_allocno, allocno = ira_regno_allocno_map[regno];
4061*e4b17023SJohn Marino   rtx x;
4062*e4b17023SJohn Marino   bitmap_iterator bi;
4063*e4b17023SJohn Marino   struct ira_spilled_reg_stack_slot *slot = NULL;
4064*e4b17023SJohn Marino 
4065*e4b17023SJohn Marino   ira_assert (inherent_size == PSEUDO_REGNO_BYTES (regno)
4066*e4b17023SJohn Marino 	      && inherent_size <= total_size
4067*e4b17023SJohn Marino 	      && ALLOCNO_HARD_REGNO (allocno) < 0);
4068*e4b17023SJohn Marino   if (! flag_ira_share_spill_slots)
4069*e4b17023SJohn Marino     return NULL_RTX;
4070*e4b17023SJohn Marino   slot_num = -ALLOCNO_HARD_REGNO (allocno) - 2;
4071*e4b17023SJohn Marino   if (slot_num != -1)
4072*e4b17023SJohn Marino     {
4073*e4b17023SJohn Marino       slot = &ira_spilled_reg_stack_slots[slot_num];
4074*e4b17023SJohn Marino       x = slot->mem;
4075*e4b17023SJohn Marino     }
4076*e4b17023SJohn Marino   else
4077*e4b17023SJohn Marino     {
4078*e4b17023SJohn Marino       best_cost = best_slot_num = -1;
4079*e4b17023SJohn Marino       x = NULL_RTX;
4080*e4b17023SJohn Marino       /* It means that the pseudo was spilled in the reload pass, try
4081*e4b17023SJohn Marino 	 to reuse a slot.  */
4082*e4b17023SJohn Marino       for (slot_num = 0;
4083*e4b17023SJohn Marino 	   slot_num < ira_spilled_reg_stack_slots_num;
4084*e4b17023SJohn Marino 	   slot_num++)
4085*e4b17023SJohn Marino 	{
4086*e4b17023SJohn Marino 	  slot = &ira_spilled_reg_stack_slots[slot_num];
4087*e4b17023SJohn Marino 	  if (slot->mem == NULL_RTX)
4088*e4b17023SJohn Marino 	    continue;
4089*e4b17023SJohn Marino 	  if (slot->width < total_size
4090*e4b17023SJohn Marino 	      || GET_MODE_SIZE (GET_MODE (slot->mem)) < inherent_size)
4091*e4b17023SJohn Marino 	    continue;
4092*e4b17023SJohn Marino 
4093*e4b17023SJohn Marino 	  EXECUTE_IF_SET_IN_BITMAP (&slot->spilled_regs,
4094*e4b17023SJohn Marino 				    FIRST_PSEUDO_REGISTER, i, bi)
4095*e4b17023SJohn Marino 	    {
4096*e4b17023SJohn Marino 	      another_allocno = ira_regno_allocno_map[i];
4097*e4b17023SJohn Marino 	      if (allocnos_conflict_by_live_ranges_p (allocno,
4098*e4b17023SJohn Marino 						      another_allocno))
4099*e4b17023SJohn Marino 		goto cont;
4100*e4b17023SJohn Marino 	    }
4101*e4b17023SJohn Marino 	  for (cost = 0, cp = ALLOCNO_COPIES (allocno);
4102*e4b17023SJohn Marino 	       cp != NULL;
4103*e4b17023SJohn Marino 	       cp = next_cp)
4104*e4b17023SJohn Marino 	    {
4105*e4b17023SJohn Marino 	      if (cp->first == allocno)
4106*e4b17023SJohn Marino 		{
4107*e4b17023SJohn Marino 		  next_cp = cp->next_first_allocno_copy;
4108*e4b17023SJohn Marino 		  another_allocno = cp->second;
4109*e4b17023SJohn Marino 		}
4110*e4b17023SJohn Marino 	      else if (cp->second == allocno)
4111*e4b17023SJohn Marino 		{
4112*e4b17023SJohn Marino 		  next_cp = cp->next_second_allocno_copy;
4113*e4b17023SJohn Marino 		  another_allocno = cp->first;
4114*e4b17023SJohn Marino 		}
4115*e4b17023SJohn Marino 	      else
4116*e4b17023SJohn Marino 		gcc_unreachable ();
4117*e4b17023SJohn Marino 	      if (cp->insn == NULL_RTX)
4118*e4b17023SJohn Marino 		continue;
4119*e4b17023SJohn Marino 	      if (bitmap_bit_p (&slot->spilled_regs,
4120*e4b17023SJohn Marino 				ALLOCNO_REGNO (another_allocno)))
4121*e4b17023SJohn Marino 		cost += cp->freq;
4122*e4b17023SJohn Marino 	    }
4123*e4b17023SJohn Marino 	  if (cost > best_cost)
4124*e4b17023SJohn Marino 	    {
4125*e4b17023SJohn Marino 	      best_cost = cost;
4126*e4b17023SJohn Marino 	      best_slot_num = slot_num;
4127*e4b17023SJohn Marino 	    }
4128*e4b17023SJohn Marino 	cont:
4129*e4b17023SJohn Marino 	  ;
4130*e4b17023SJohn Marino 	}
4131*e4b17023SJohn Marino       if (best_cost >= 0)
4132*e4b17023SJohn Marino 	{
4133*e4b17023SJohn Marino 	  slot_num = best_slot_num;
4134*e4b17023SJohn Marino 	  slot = &ira_spilled_reg_stack_slots[slot_num];
4135*e4b17023SJohn Marino 	  SET_REGNO_REG_SET (&slot->spilled_regs, regno);
4136*e4b17023SJohn Marino 	  x = slot->mem;
4137*e4b17023SJohn Marino 	  ALLOCNO_HARD_REGNO (allocno) = -slot_num - 2;
4138*e4b17023SJohn Marino 	}
4139*e4b17023SJohn Marino     }
4140*e4b17023SJohn Marino   if (x != NULL_RTX)
4141*e4b17023SJohn Marino     {
4142*e4b17023SJohn Marino       ira_assert (slot->width >= total_size);
4143*e4b17023SJohn Marino #ifdef ENABLE_IRA_CHECKING
4144*e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (&slot->spilled_regs,
4145*e4b17023SJohn Marino 				FIRST_PSEUDO_REGISTER, i, bi)
4146*e4b17023SJohn Marino 	{
4147*e4b17023SJohn Marino 	  ira_assert (! conflict_by_live_ranges_p (regno, i));
4148*e4b17023SJohn Marino 	}
4149*e4b17023SJohn Marino #endif
4150*e4b17023SJohn Marino       SET_REGNO_REG_SET (&slot->spilled_regs, regno);
4151*e4b17023SJohn Marino       if (internal_flag_ira_verbose > 3 && ira_dump_file)
4152*e4b17023SJohn Marino 	{
4153*e4b17023SJohn Marino 	  fprintf (ira_dump_file, "      Assigning %d(freq=%d) slot %d of",
4154*e4b17023SJohn Marino 		   regno, REG_FREQ (regno), slot_num);
4155*e4b17023SJohn Marino 	  EXECUTE_IF_SET_IN_BITMAP (&slot->spilled_regs,
4156*e4b17023SJohn Marino 				    FIRST_PSEUDO_REGISTER, i, bi)
4157*e4b17023SJohn Marino 	    {
4158*e4b17023SJohn Marino 	      if ((unsigned) regno != i)
4159*e4b17023SJohn Marino 		fprintf (ira_dump_file, " %d", i);
4160*e4b17023SJohn Marino 	    }
4161*e4b17023SJohn Marino 	  fprintf (ira_dump_file, "\n");
4162*e4b17023SJohn Marino 	}
4163*e4b17023SJohn Marino     }
4164*e4b17023SJohn Marino   return x;
4165*e4b17023SJohn Marino }
4166*e4b17023SJohn Marino 
4167*e4b17023SJohn Marino /* This is called by reload every time a new stack slot X with
4168*e4b17023SJohn Marino    TOTAL_SIZE was allocated for REGNO.  We store this info for
4169*e4b17023SJohn Marino    subsequent ira_reuse_stack_slot calls.  */
4170*e4b17023SJohn Marino void
ira_mark_new_stack_slot(rtx x,int regno,unsigned int total_size)4171*e4b17023SJohn Marino ira_mark_new_stack_slot (rtx x, int regno, unsigned int total_size)
4172*e4b17023SJohn Marino {
4173*e4b17023SJohn Marino   struct ira_spilled_reg_stack_slot *slot;
4174*e4b17023SJohn Marino   int slot_num;
4175*e4b17023SJohn Marino   ira_allocno_t allocno;
4176*e4b17023SJohn Marino 
4177*e4b17023SJohn Marino   ira_assert (PSEUDO_REGNO_BYTES (regno) <= total_size);
4178*e4b17023SJohn Marino   allocno = ira_regno_allocno_map[regno];
4179*e4b17023SJohn Marino   slot_num = -ALLOCNO_HARD_REGNO (allocno) - 2;
4180*e4b17023SJohn Marino   if (slot_num == -1)
4181*e4b17023SJohn Marino     {
4182*e4b17023SJohn Marino       slot_num = ira_spilled_reg_stack_slots_num++;
4183*e4b17023SJohn Marino       ALLOCNO_HARD_REGNO (allocno) = -slot_num - 2;
4184*e4b17023SJohn Marino     }
4185*e4b17023SJohn Marino   slot = &ira_spilled_reg_stack_slots[slot_num];
4186*e4b17023SJohn Marino   INIT_REG_SET (&slot->spilled_regs);
4187*e4b17023SJohn Marino   SET_REGNO_REG_SET (&slot->spilled_regs, regno);
4188*e4b17023SJohn Marino   slot->mem = x;
4189*e4b17023SJohn Marino   slot->width = total_size;
4190*e4b17023SJohn Marino   if (internal_flag_ira_verbose > 3 && ira_dump_file)
4191*e4b17023SJohn Marino     fprintf (ira_dump_file, "      Assigning %d(freq=%d) a new slot %d\n",
4192*e4b17023SJohn Marino 	     regno, REG_FREQ (regno), slot_num);
4193*e4b17023SJohn Marino }
4194*e4b17023SJohn Marino 
4195*e4b17023SJohn Marino 
4196*e4b17023SJohn Marino /* Return spill cost for pseudo-registers whose numbers are in array
4197*e4b17023SJohn Marino    REGNOS (with a negative number as an end marker) for reload with
4198*e4b17023SJohn Marino    given IN and OUT for INSN.  Return also number points (through
4199*e4b17023SJohn Marino    EXCESS_PRESSURE_LIVE_LENGTH) where the pseudo-register lives and
4200*e4b17023SJohn Marino    the register pressure is high, number of references of the
4201*e4b17023SJohn Marino    pseudo-registers (through NREFS), number of callee-clobbered
4202*e4b17023SJohn Marino    hard-registers occupied by the pseudo-registers (through
4203*e4b17023SJohn Marino    CALL_USED_COUNT), and the first hard regno occupied by the
4204*e4b17023SJohn Marino    pseudo-registers (through FIRST_HARD_REGNO).  */
4205*e4b17023SJohn Marino static int
calculate_spill_cost(int * regnos,rtx in,rtx out,rtx insn,int * excess_pressure_live_length,int * nrefs,int * call_used_count,int * first_hard_regno)4206*e4b17023SJohn Marino calculate_spill_cost (int *regnos, rtx in, rtx out, rtx insn,
4207*e4b17023SJohn Marino 		      int *excess_pressure_live_length,
4208*e4b17023SJohn Marino 		      int *nrefs, int *call_used_count, int *first_hard_regno)
4209*e4b17023SJohn Marino {
4210*e4b17023SJohn Marino   int i, cost, regno, hard_regno, j, count, saved_cost, nregs;
4211*e4b17023SJohn Marino   bool in_p, out_p;
4212*e4b17023SJohn Marino   int length;
4213*e4b17023SJohn Marino   ira_allocno_t a;
4214*e4b17023SJohn Marino 
4215*e4b17023SJohn Marino   *nrefs = 0;
4216*e4b17023SJohn Marino   for (length = count = cost = i = 0;; i++)
4217*e4b17023SJohn Marino     {
4218*e4b17023SJohn Marino       regno = regnos[i];
4219*e4b17023SJohn Marino       if (regno < 0)
4220*e4b17023SJohn Marino 	break;
4221*e4b17023SJohn Marino       *nrefs += REG_N_REFS (regno);
4222*e4b17023SJohn Marino       hard_regno = reg_renumber[regno];
4223*e4b17023SJohn Marino       ira_assert (hard_regno >= 0);
4224*e4b17023SJohn Marino       a = ira_regno_allocno_map[regno];
4225*e4b17023SJohn Marino       length += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) / ALLOCNO_NUM_OBJECTS (a);
4226*e4b17023SJohn Marino       cost += ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a);
4227*e4b17023SJohn Marino       nregs = hard_regno_nregs[hard_regno][ALLOCNO_MODE (a)];
4228*e4b17023SJohn Marino       for (j = 0; j < nregs; j++)
4229*e4b17023SJohn Marino 	if (! TEST_HARD_REG_BIT (call_used_reg_set, hard_regno + j))
4230*e4b17023SJohn Marino 	  break;
4231*e4b17023SJohn Marino       if (j == nregs)
4232*e4b17023SJohn Marino 	count++;
4233*e4b17023SJohn Marino       in_p = in && REG_P (in) && (int) REGNO (in) == hard_regno;
4234*e4b17023SJohn Marino       out_p = out && REG_P (out) && (int) REGNO (out) == hard_regno;
4235*e4b17023SJohn Marino       if ((in_p || out_p)
4236*e4b17023SJohn Marino 	  && find_regno_note (insn, REG_DEAD, hard_regno) != NULL_RTX)
4237*e4b17023SJohn Marino 	{
4238*e4b17023SJohn Marino 	  saved_cost = 0;
4239*e4b17023SJohn Marino 	  if (in_p)
4240*e4b17023SJohn Marino 	    saved_cost += ira_memory_move_cost
4241*e4b17023SJohn Marino 	                  [ALLOCNO_MODE (a)][ALLOCNO_CLASS (a)][1];
4242*e4b17023SJohn Marino 	  if (out_p)
4243*e4b17023SJohn Marino 	    saved_cost
4244*e4b17023SJohn Marino 	      += ira_memory_move_cost
4245*e4b17023SJohn Marino 	         [ALLOCNO_MODE (a)][ALLOCNO_CLASS (a)][0];
4246*e4b17023SJohn Marino 	  cost -= REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn)) * saved_cost;
4247*e4b17023SJohn Marino 	}
4248*e4b17023SJohn Marino     }
4249*e4b17023SJohn Marino   *excess_pressure_live_length = length;
4250*e4b17023SJohn Marino   *call_used_count = count;
4251*e4b17023SJohn Marino   hard_regno = -1;
4252*e4b17023SJohn Marino   if (regnos[0] >= 0)
4253*e4b17023SJohn Marino     {
4254*e4b17023SJohn Marino       hard_regno = reg_renumber[regnos[0]];
4255*e4b17023SJohn Marino     }
4256*e4b17023SJohn Marino   *first_hard_regno = hard_regno;
4257*e4b17023SJohn Marino   return cost;
4258*e4b17023SJohn Marino }
4259*e4b17023SJohn Marino 
4260*e4b17023SJohn Marino /* Return TRUE if spilling pseudo-registers whose numbers are in array
4261*e4b17023SJohn Marino    REGNOS is better than spilling pseudo-registers with numbers in
4262*e4b17023SJohn Marino    OTHER_REGNOS for reload with given IN and OUT for INSN.  The
4263*e4b17023SJohn Marino    function used by the reload pass to make better register spilling
4264*e4b17023SJohn Marino    decisions.  */
4265*e4b17023SJohn Marino bool
ira_better_spill_reload_regno_p(int * regnos,int * other_regnos,rtx in,rtx out,rtx insn)4266*e4b17023SJohn Marino ira_better_spill_reload_regno_p (int *regnos, int *other_regnos,
4267*e4b17023SJohn Marino 				 rtx in, rtx out, rtx insn)
4268*e4b17023SJohn Marino {
4269*e4b17023SJohn Marino   int cost, other_cost;
4270*e4b17023SJohn Marino   int length, other_length;
4271*e4b17023SJohn Marino   int nrefs, other_nrefs;
4272*e4b17023SJohn Marino   int call_used_count, other_call_used_count;
4273*e4b17023SJohn Marino   int hard_regno, other_hard_regno;
4274*e4b17023SJohn Marino 
4275*e4b17023SJohn Marino   cost = calculate_spill_cost (regnos, in, out, insn,
4276*e4b17023SJohn Marino 			       &length, &nrefs, &call_used_count, &hard_regno);
4277*e4b17023SJohn Marino   other_cost = calculate_spill_cost (other_regnos, in, out, insn,
4278*e4b17023SJohn Marino 				     &other_length, &other_nrefs,
4279*e4b17023SJohn Marino 				     &other_call_used_count,
4280*e4b17023SJohn Marino 				     &other_hard_regno);
4281*e4b17023SJohn Marino   if (nrefs == 0 && other_nrefs != 0)
4282*e4b17023SJohn Marino     return true;
4283*e4b17023SJohn Marino   if (nrefs != 0 && other_nrefs == 0)
4284*e4b17023SJohn Marino     return false;
4285*e4b17023SJohn Marino   if (cost != other_cost)
4286*e4b17023SJohn Marino     return cost < other_cost;
4287*e4b17023SJohn Marino   if (length != other_length)
4288*e4b17023SJohn Marino     return length > other_length;
4289*e4b17023SJohn Marino #ifdef REG_ALLOC_ORDER
4290*e4b17023SJohn Marino   if (hard_regno >= 0 && other_hard_regno >= 0)
4291*e4b17023SJohn Marino     return (inv_reg_alloc_order[hard_regno]
4292*e4b17023SJohn Marino 	    < inv_reg_alloc_order[other_hard_regno]);
4293*e4b17023SJohn Marino #else
4294*e4b17023SJohn Marino   if (call_used_count != other_call_used_count)
4295*e4b17023SJohn Marino     return call_used_count > other_call_used_count;
4296*e4b17023SJohn Marino #endif
4297*e4b17023SJohn Marino   return false;
4298*e4b17023SJohn Marino }
4299*e4b17023SJohn Marino 
4300*e4b17023SJohn Marino 
4301*e4b17023SJohn Marino 
4302*e4b17023SJohn Marino /* Allocate and initialize data necessary for assign_hard_reg.  */
4303*e4b17023SJohn Marino void
ira_initiate_assign(void)4304*e4b17023SJohn Marino ira_initiate_assign (void)
4305*e4b17023SJohn Marino {
4306*e4b17023SJohn Marino   sorted_allocnos
4307*e4b17023SJohn Marino     = (ira_allocno_t *) ira_allocate (sizeof (ira_allocno_t)
4308*e4b17023SJohn Marino 				      * ira_allocnos_num);
4309*e4b17023SJohn Marino   consideration_allocno_bitmap = ira_allocate_bitmap ();
4310*e4b17023SJohn Marino   initiate_cost_update ();
4311*e4b17023SJohn Marino   allocno_priorities = (int *) ira_allocate (sizeof (int) * ira_allocnos_num);
4312*e4b17023SJohn Marino }
4313*e4b17023SJohn Marino 
4314*e4b17023SJohn Marino /* Deallocate data used by assign_hard_reg.  */
4315*e4b17023SJohn Marino void
ira_finish_assign(void)4316*e4b17023SJohn Marino ira_finish_assign (void)
4317*e4b17023SJohn Marino {
4318*e4b17023SJohn Marino   ira_free (sorted_allocnos);
4319*e4b17023SJohn Marino   ira_free_bitmap (consideration_allocno_bitmap);
4320*e4b17023SJohn Marino   finish_cost_update ();
4321*e4b17023SJohn Marino   ira_free (allocno_priorities);
4322*e4b17023SJohn Marino }
4323*e4b17023SJohn Marino 
4324*e4b17023SJohn Marino 
4325*e4b17023SJohn Marino 
4326*e4b17023SJohn Marino /* Entry function doing color-based register allocation.  */
4327*e4b17023SJohn Marino static void
color(void)4328*e4b17023SJohn Marino color (void)
4329*e4b17023SJohn Marino {
4330*e4b17023SJohn Marino   allocno_stack_vec = VEC_alloc (ira_allocno_t, heap, ira_allocnos_num);
4331*e4b17023SJohn Marino   memset (allocated_hardreg_p, 0, sizeof (allocated_hardreg_p));
4332*e4b17023SJohn Marino   ira_initiate_assign ();
4333*e4b17023SJohn Marino   do_coloring ();
4334*e4b17023SJohn Marino   ira_finish_assign ();
4335*e4b17023SJohn Marino   VEC_free (ira_allocno_t, heap, allocno_stack_vec);
4336*e4b17023SJohn Marino   move_spill_restore ();
4337*e4b17023SJohn Marino }
4338*e4b17023SJohn Marino 
4339*e4b17023SJohn Marino 
4340*e4b17023SJohn Marino 
4341*e4b17023SJohn Marino /* This page contains a simple register allocator without usage of
4342*e4b17023SJohn Marino    allocno conflicts.  This is used for fast allocation for -O0.  */
4343*e4b17023SJohn Marino 
4344*e4b17023SJohn Marino /* Do register allocation by not using allocno conflicts.  It uses
4345*e4b17023SJohn Marino    only allocno live ranges.  The algorithm is close to Chow's
4346*e4b17023SJohn Marino    priority coloring.  */
4347*e4b17023SJohn Marino static void
fast_allocation(void)4348*e4b17023SJohn Marino fast_allocation (void)
4349*e4b17023SJohn Marino {
4350*e4b17023SJohn Marino   int i, j, k, num, class_size, hard_regno;
4351*e4b17023SJohn Marino #ifdef STACK_REGS
4352*e4b17023SJohn Marino   bool no_stack_reg_p;
4353*e4b17023SJohn Marino #endif
4354*e4b17023SJohn Marino   enum reg_class aclass;
4355*e4b17023SJohn Marino   enum machine_mode mode;
4356*e4b17023SJohn Marino   ira_allocno_t a;
4357*e4b17023SJohn Marino   ira_allocno_iterator ai;
4358*e4b17023SJohn Marino   live_range_t r;
4359*e4b17023SJohn Marino   HARD_REG_SET conflict_hard_regs, *used_hard_regs;
4360*e4b17023SJohn Marino 
4361*e4b17023SJohn Marino   sorted_allocnos = (ira_allocno_t *) ira_allocate (sizeof (ira_allocno_t)
4362*e4b17023SJohn Marino 						    * ira_allocnos_num);
4363*e4b17023SJohn Marino   num = 0;
4364*e4b17023SJohn Marino   FOR_EACH_ALLOCNO (a, ai)
4365*e4b17023SJohn Marino     sorted_allocnos[num++] = a;
4366*e4b17023SJohn Marino   allocno_priorities = (int *) ira_allocate (sizeof (int) * ira_allocnos_num);
4367*e4b17023SJohn Marino   setup_allocno_priorities (sorted_allocnos, num);
4368*e4b17023SJohn Marino   used_hard_regs = (HARD_REG_SET *) ira_allocate (sizeof (HARD_REG_SET)
4369*e4b17023SJohn Marino 						  * ira_max_point);
4370*e4b17023SJohn Marino   for (i = 0; i < ira_max_point; i++)
4371*e4b17023SJohn Marino     CLEAR_HARD_REG_SET (used_hard_regs[i]);
4372*e4b17023SJohn Marino   qsort (sorted_allocnos, num, sizeof (ira_allocno_t),
4373*e4b17023SJohn Marino 	 allocno_priority_compare_func);
4374*e4b17023SJohn Marino   for (i = 0; i < num; i++)
4375*e4b17023SJohn Marino     {
4376*e4b17023SJohn Marino       int nr, l;
4377*e4b17023SJohn Marino 
4378*e4b17023SJohn Marino       a = sorted_allocnos[i];
4379*e4b17023SJohn Marino       nr = ALLOCNO_NUM_OBJECTS (a);
4380*e4b17023SJohn Marino       CLEAR_HARD_REG_SET (conflict_hard_regs);
4381*e4b17023SJohn Marino       for (l = 0; l < nr; l++)
4382*e4b17023SJohn Marino 	{
4383*e4b17023SJohn Marino 	  ira_object_t obj = ALLOCNO_OBJECT (a, l);
4384*e4b17023SJohn Marino 	  IOR_HARD_REG_SET (conflict_hard_regs,
4385*e4b17023SJohn Marino 			    OBJECT_CONFLICT_HARD_REGS (obj));
4386*e4b17023SJohn Marino 	  for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
4387*e4b17023SJohn Marino 	    for (j = r->start; j <= r->finish; j++)
4388*e4b17023SJohn Marino 	      IOR_HARD_REG_SET (conflict_hard_regs, used_hard_regs[j]);
4389*e4b17023SJohn Marino 	}
4390*e4b17023SJohn Marino       aclass = ALLOCNO_CLASS (a);
4391*e4b17023SJohn Marino       ALLOCNO_ASSIGNED_P (a) = true;
4392*e4b17023SJohn Marino       ALLOCNO_HARD_REGNO (a) = -1;
4393*e4b17023SJohn Marino       if (hard_reg_set_subset_p (reg_class_contents[aclass],
4394*e4b17023SJohn Marino 				 conflict_hard_regs))
4395*e4b17023SJohn Marino 	continue;
4396*e4b17023SJohn Marino       mode = ALLOCNO_MODE (a);
4397*e4b17023SJohn Marino #ifdef STACK_REGS
4398*e4b17023SJohn Marino       no_stack_reg_p = ALLOCNO_NO_STACK_REG_P (a);
4399*e4b17023SJohn Marino #endif
4400*e4b17023SJohn Marino       class_size = ira_class_hard_regs_num[aclass];
4401*e4b17023SJohn Marino       for (j = 0; j < class_size; j++)
4402*e4b17023SJohn Marino 	{
4403*e4b17023SJohn Marino 	  hard_regno = ira_class_hard_regs[aclass][j];
4404*e4b17023SJohn Marino #ifdef STACK_REGS
4405*e4b17023SJohn Marino 	  if (no_stack_reg_p && FIRST_STACK_REG <= hard_regno
4406*e4b17023SJohn Marino 	      && hard_regno <= LAST_STACK_REG)
4407*e4b17023SJohn Marino 	    continue;
4408*e4b17023SJohn Marino #endif
4409*e4b17023SJohn Marino 	  if (ira_hard_reg_set_intersection_p (hard_regno, mode, conflict_hard_regs)
4410*e4b17023SJohn Marino 	      || (TEST_HARD_REG_BIT
4411*e4b17023SJohn Marino 		  (ira_prohibited_class_mode_regs[aclass][mode], hard_regno)))
4412*e4b17023SJohn Marino 	    continue;
4413*e4b17023SJohn Marino 	  ALLOCNO_HARD_REGNO (a) = hard_regno;
4414*e4b17023SJohn Marino 	  for (l = 0; l < nr; l++)
4415*e4b17023SJohn Marino 	    {
4416*e4b17023SJohn Marino 	      ira_object_t obj = ALLOCNO_OBJECT (a, l);
4417*e4b17023SJohn Marino 	      for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
4418*e4b17023SJohn Marino 		for (k = r->start; k <= r->finish; k++)
4419*e4b17023SJohn Marino 		  IOR_HARD_REG_SET (used_hard_regs[k],
4420*e4b17023SJohn Marino 				    ira_reg_mode_hard_regset[hard_regno][mode]);
4421*e4b17023SJohn Marino 	    }
4422*e4b17023SJohn Marino 	  break;
4423*e4b17023SJohn Marino 	}
4424*e4b17023SJohn Marino     }
4425*e4b17023SJohn Marino   ira_free (sorted_allocnos);
4426*e4b17023SJohn Marino   ira_free (used_hard_regs);
4427*e4b17023SJohn Marino   ira_free (allocno_priorities);
4428*e4b17023SJohn Marino   if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL)
4429*e4b17023SJohn Marino     ira_print_disposition (ira_dump_file);
4430*e4b17023SJohn Marino }
4431*e4b17023SJohn Marino 
4432*e4b17023SJohn Marino 
4433*e4b17023SJohn Marino 
4434*e4b17023SJohn Marino /* Entry function doing coloring.  */
4435*e4b17023SJohn Marino void
ira_color(void)4436*e4b17023SJohn Marino ira_color (void)
4437*e4b17023SJohn Marino {
4438*e4b17023SJohn Marino   ira_allocno_t a;
4439*e4b17023SJohn Marino   ira_allocno_iterator ai;
4440*e4b17023SJohn Marino 
4441*e4b17023SJohn Marino   /* Setup updated costs.  */
4442*e4b17023SJohn Marino   FOR_EACH_ALLOCNO (a, ai)
4443*e4b17023SJohn Marino     {
4444*e4b17023SJohn Marino       ALLOCNO_UPDATED_MEMORY_COST (a) = ALLOCNO_MEMORY_COST (a);
4445*e4b17023SJohn Marino       ALLOCNO_UPDATED_CLASS_COST (a) = ALLOCNO_CLASS_COST (a);
4446*e4b17023SJohn Marino     }
4447*e4b17023SJohn Marino   if (ira_conflicts_p)
4448*e4b17023SJohn Marino     color ();
4449*e4b17023SJohn Marino   else
4450*e4b17023SJohn Marino     fast_allocation ();
4451*e4b17023SJohn Marino }
4452