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