ira-color.c 157 KB
Newer Older
Vladimir Makarov committed
1
/* IRA allocation based on graph coloring.
2
   Copyright (C) 2006-2019 Free Software Foundation, Inc.
Vladimir Makarov committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   Contributed by Vladimir Makarov <vmakarov@redhat.com>.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
24
#include "backend.h"
25
#include "target.h"
Vladimir Makarov committed
26
#include "rtl.h"
27 28
#include "tree.h"
#include "predict.h"
29
#include "df.h"
30
#include "memmodel.h"
Vladimir Makarov committed
31
#include "tm_p.h"
32
#include "insn-config.h"
Vladimir Makarov committed
33
#include "regs.h"
34 35
#include "ira.h"
#include "ira-int.h"
Vladimir Makarov committed
36
#include "reload.h"
37
#include "cfgloop.h"
Vladimir Makarov committed
38

39
typedef struct allocno_hard_regs *allocno_hard_regs_t;
Vladimir Makarov committed
40 41

/* The structure contains information about hard registers can be
42
   assigned to allocnos.  Usually it is allocno profitable hard
Vladimir Makarov committed
43 44 45 46
   registers but in some cases this set can be a bit different.  Major
   reason of the difference is a requirement to use hard register sets
   that form a tree or a forest (set of trees), i.e. hard register set
   of a node should contain hard register sets of its subnodes.  */
47
struct allocno_hard_regs
Vladimir Makarov committed
48 49 50 51 52
{
  /* Hard registers can be assigned to an allocno.  */
  HARD_REG_SET set;
  /* Overall (spilling) cost of all allocnos with given register
     set.  */
53
  int64_t cost;
Vladimir Makarov committed
54 55
};

56
typedef struct allocno_hard_regs_node *allocno_hard_regs_node_t;
Vladimir Makarov committed
57

58
/* A node representing allocno hard registers.  Such nodes form a
Vladimir Makarov committed
59
   forest (set of trees).  Each subnode of given node in the forest
60
   refers for hard register set (usually allocno profitable hard
Vladimir Makarov committed
61 62
   register set) which is a subset of one referred from given
   node.  */
63
struct allocno_hard_regs_node
Vladimir Makarov committed
64 65 66 67 68 69 70
{
  /* Set up number of the node in preorder traversing of the forest.  */
  int preorder_num;
  /* Used for different calculation like finding conflict size of an
     allocno.  */
  int check;
  /* Used for calculation of conflict size of an allocno.  The
71
     conflict size of the allocno is maximal number of given allocno
Vladimir Makarov committed
72 73 74 75 76 77 78 79 80 81
     hard registers needed for allocation of the conflicting allocnos.
     Given allocno is trivially colored if this number plus the number
     of hard registers needed for given allocno is not greater than
     the number of given allocno hard register set.  */
  int conflict_size;
  /* The number of hard registers given by member hard_regs.  */
  int hard_regs_num;
  /* The following member is used to form the final forest.  */
  bool used_p;
  /* Pointer to the corresponding profitable hard registers.  */
82
  allocno_hard_regs_t hard_regs;
Vladimir Makarov committed
83 84
  /* Parent, first subnode, previous and next node with the same
     parent in the forest.  */
85
  allocno_hard_regs_node_t parent, first, prev, next;
Vladimir Makarov committed
86 87
};

Vladimir Makarov committed
88 89 90 91 92 93 94 95 96 97 98
/* Info about changing hard reg costs of an allocno.  */
struct update_cost_record
{
  /* Hard regno for which we changed the cost.  */
  int hard_regno;
  /* Divisor used when we changed the cost of HARD_REGNO.  */
  int divisor;
  /* Next record for given allocno.  */
  struct update_cost_record *next;
};

Vladimir Makarov committed
99 100 101 102 103
/* To decrease footprint of ira_allocno structure we store all data
   needed only for coloring in the following structure.  */
struct allocno_color_data
{
  /* TRUE value means that the allocno was not removed yet from the
Kito Cheng committed
104
     conflicting graph during coloring.  */
Vladimir Makarov committed
105 106 107 108
  unsigned int in_graph_p : 1;
  /* TRUE if it is put on the stack to make other allocnos
     colorable.  */
  unsigned int may_be_spilled_p : 1;
109
  /* TRUE if the allocno is trivially colorable.  */
Vladimir Makarov committed
110 111 112 113 114
  unsigned int colorable_p : 1;
  /* Number of hard registers of the allocno class really
     available for the allocno allocation.  It is number of the
     profitable hard regs.  */
  int available_regs_num;
115 116 117
  /* Sum of frequencies of hard register preferences of all
     conflicting allocnos which are not the coloring stack yet.  */
  int conflict_allocno_hard_prefs;
Vladimir Makarov committed
118 119 120 121 122 123
  /* Allocnos in a bucket (used in coloring) chained by the following
     two members.  */
  ira_allocno_t next_bucket_allocno;
  ira_allocno_t prev_bucket_allocno;
  /* Used for temporary purposes.  */
  int temp;
124 125
  /* Used to exclude repeated processing.  */
  int last_process;
Vladimir Makarov committed
126 127 128 129 130
  /* Profitable hard regs available for this pseudo allocation.  It
     means that the set excludes unavailable hard regs and hard regs
     conflicting with given pseudo.  They should be of the allocno
     class.  */
  HARD_REG_SET profitable_hard_regs;
131 132 133 134 135
  /* The allocno hard registers node.  */
  allocno_hard_regs_node_t hard_regs_node;
  /* Array of structures allocno_hard_regs_subnode representing
     given allocno hard registers node (the 1st element in the array)
     and all its subnodes in the tree (forest) of allocno hard
Vladimir Makarov committed
136 137
     register nodes (see comments above).  */
  int hard_regs_subnodes_start;
138
  /* The length of the previous array.  */
Vladimir Makarov committed
139
  int hard_regs_subnodes_num;
Vladimir Makarov committed
140 141 142 143 144
  /* Records about updating allocno hard reg costs from copies.  If
     the allocno did not get expected hard register, these records are
     used to restore original hard reg costs of allocnos connected to
     this allocno by copies.  */
  struct update_cost_record *update_cost_records;
145 146 147 148 149 150 151 152 153
  /* Threads.  We collect allocnos connected by copies into threads
     and try to assign hard regs to allocnos by threads.  */
  /* Allocno representing all thread.  */
  ira_allocno_t first_thread_allocno;
  /* Allocnos in thread forms a cycle list through the following
     member.  */
  ira_allocno_t next_thread_allocno;
  /* All thread frequency.  Defined only for first thread allocno.  */
  int thread_freq;
Vladimir Makarov committed
154 155 156
};

/* See above.  */
157
typedef struct allocno_color_data *allocno_color_data_t;
Vladimir Makarov committed
158

159 160
/* Container for storing allocno data concerning coloring.  */
static allocno_color_data_t allocno_color_data;
Vladimir Makarov committed
161 162

/* Macro to access the data concerning coloring.  */
163 164 165 166 167 168
#define ALLOCNO_COLOR_DATA(a) ((allocno_color_data_t) ALLOCNO_ADD_DATA (a))

/* Used for finding allocno colorability to exclude repeated allocno
   processing and for updating preferencing to exclude repeated
   allocno processing during assignment.  */
static int curr_allocno_process;
Vladimir Makarov committed
169

Vladimir Makarov committed
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
/* This file contains code for regional graph coloring, spill/restore
   code placement optimization, and code helping the reload pass to do
   a better job.  */

/* Bitmap of allocnos which should be colored.  */
static bitmap coloring_allocno_bitmap;

/* Bitmap of allocnos which should be taken into account during
   coloring.  In general case it contains allocnos from
   coloring_allocno_bitmap plus other already colored conflicting
   allocnos.  */
static bitmap consideration_allocno_bitmap;

/* All allocnos sorted according their priorities.  */
static ira_allocno_t *sorted_allocnos;

/* Vec representing the stack of allocnos used during coloring.  */
187
static vec<ira_allocno_t> allocno_stack_vec;
Vladimir Makarov committed
188

189 190 191 192 193 194
/* Helper for qsort comparison callbacks - return a positive integer if
   X > Y, or a negative value otherwise.  Use a conditional expression
   instead of a difference computation to insulate from possible overflow
   issues, e.g. X - Y < 0 for some X > 0 and Y < 0.  */
#define SORTGT(x,y) (((x) > (y)) ? 1 : -1)

Vladimir Makarov committed
195 196


197
/* Definition of vector of allocno hard registers.  */
Vladimir Makarov committed
198

199
/* Vector of unique allocno hard registers.  */
200
static vec<allocno_hard_regs_t> allocno_hard_regs_vec;
Vladimir Makarov committed
201

202
struct allocno_hard_regs_hasher : nofree_ptr_hash <allocno_hard_regs>
Vladimir Makarov committed
203
{
204 205 206
  static inline hashval_t hash (const allocno_hard_regs *);
  static inline bool equal (const allocno_hard_regs *,
			    const allocno_hard_regs *);
207
};
Vladimir Makarov committed
208

209 210
/* Returns hash value for allocno hard registers V.  */
inline hashval_t
211
allocno_hard_regs_hasher::hash (const allocno_hard_regs *hv)
212
{
Vladimir Makarov committed
213 214 215
  return iterative_hash (&hv->set, sizeof (HARD_REG_SET), 0);
}

216
/* Compares allocno hard registers V1 and V2.  */
217
inline bool
218 219
allocno_hard_regs_hasher::equal (const allocno_hard_regs *hv1,
				 const allocno_hard_regs *hv2)
Vladimir Makarov committed
220
{
221
  return hv1->set == hv2->set;
Vladimir Makarov committed
222 223
}

224
/* Hash table of unique allocno hard registers.  */
225
static hash_table<allocno_hard_regs_hasher> *allocno_hard_regs_htab;
Vladimir Makarov committed
226

227 228 229
/* Return allocno hard registers in the hash table equal to HV.  */
static allocno_hard_regs_t
find_hard_regs (allocno_hard_regs_t hv)
Vladimir Makarov committed
230
{
231
  return allocno_hard_regs_htab->find (hv);
Vladimir Makarov committed
232 233 234 235
}

/* Insert allocno hard registers HV in the hash table (if it is not
   there yet) and return the value which in the table.  */
236 237
static allocno_hard_regs_t
insert_hard_regs (allocno_hard_regs_t hv)
Vladimir Makarov committed
238
{
239
  allocno_hard_regs **slot = allocno_hard_regs_htab->find_slot (hv, INSERT);
Vladimir Makarov committed
240 241 242

  if (*slot == NULL)
    *slot = hv;
243
  return *slot;
Vladimir Makarov committed
244 245
}

246
/* Initialize data concerning allocno hard registers.  */
Vladimir Makarov committed
247
static void
248
init_allocno_hard_regs (void)
Vladimir Makarov committed
249
{
250
  allocno_hard_regs_vec.create (200);
251 252
  allocno_hard_regs_htab
    = new hash_table<allocno_hard_regs_hasher> (200);
Vladimir Makarov committed
253 254
}

255
/* Add (or update info about) allocno hard registers with SET and
Vladimir Makarov committed
256
   COST.  */
257
static allocno_hard_regs_t
258
add_allocno_hard_regs (HARD_REG_SET set, int64_t cost)
Vladimir Makarov committed
259
{
260 261
  struct allocno_hard_regs temp;
  allocno_hard_regs_t hv;
Vladimir Makarov committed
262 263

  gcc_assert (! hard_reg_set_empty_p (set));
264
  temp.set = set;
Vladimir Makarov committed
265 266 267 268
  if ((hv = find_hard_regs (&temp)) != NULL)
    hv->cost += cost;
  else
    {
269 270
      hv = ((struct allocno_hard_regs *)
	    ira_allocate (sizeof (struct allocno_hard_regs)));
271
      hv->set = set;
Vladimir Makarov committed
272
      hv->cost = cost;
273
      allocno_hard_regs_vec.safe_push (hv);
Vladimir Makarov committed
274 275 276 277 278 279 280
      insert_hard_regs (hv);
    }
  return hv;
}

/* Finalize data concerning allocno hard registers.  */
static void
281
finish_allocno_hard_regs (void)
Vladimir Makarov committed
282 283
{
  int i;
284
  allocno_hard_regs_t hv;
Vladimir Makarov committed
285 286

  for (i = 0;
287
       allocno_hard_regs_vec.iterate (i, &hv);
Vladimir Makarov committed
288 289
       i++)
    ira_free (hv);
290 291
  delete allocno_hard_regs_htab;
  allocno_hard_regs_htab = NULL;
292
  allocno_hard_regs_vec.release ();
Vladimir Makarov committed
293 294 295 296
}

/* Sort hard regs according to their frequency of usage. */
static int
297
allocno_hard_regs_compare (const void *v1p, const void *v2p)
Vladimir Makarov committed
298
{
299 300
  allocno_hard_regs_t hv1 = *(const allocno_hard_regs_t *) v1p;
  allocno_hard_regs_t hv2 = *(const allocno_hard_regs_t *) v2p;
Vladimir Makarov committed
301 302 303 304 305

  if (hv2->cost > hv1->cost)
    return 1;
  else if (hv2->cost < hv1->cost)
    return -1;
306
  return SORTGT (allocno_hard_regs_hasher::hash(hv2), allocno_hard_regs_hasher::hash(hv1));
Vladimir Makarov committed
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
}



/* Used for finding a common ancestor of two allocno hard registers
   nodes in the forest.  We use the current value of
   'node_check_tick' to mark all nodes from one node to the top and
   then walking up from another node until we find a marked node.

   It is also used to figure out allocno colorability as a mark that
   we already reset value of member 'conflict_size' for the forest
   node corresponding to the processed allocno.  */
static int node_check_tick;

/* Roots of the forest containing hard register sets can be assigned
322 323
   to allocnos.  */
static allocno_hard_regs_node_t hard_regs_roots;
Vladimir Makarov committed
324

325
/* Definition of vector of allocno hard register nodes.  */
Vladimir Makarov committed
326 327

/* Vector used to create the forest.  */
328
static vec<allocno_hard_regs_node_t> hard_regs_node_vec;
Vladimir Makarov committed
329

330
/* Create and return allocno hard registers node containing allocno
Vladimir Makarov committed
331
   hard registers HV.  */
332 333
static allocno_hard_regs_node_t
create_new_allocno_hard_regs_node (allocno_hard_regs_t hv)
Vladimir Makarov committed
334
{
335
  allocno_hard_regs_node_t new_node;
Vladimir Makarov committed
336

337 338
  new_node = ((struct allocno_hard_regs_node *)
	      ira_allocate (sizeof (struct allocno_hard_regs_node)));
Vladimir Makarov committed
339 340 341 342 343 344 345 346
  new_node->check = 0;
  new_node->hard_regs = hv;
  new_node->hard_regs_num = hard_reg_set_size (hv->set);
  new_node->first = NULL;
  new_node->used_p = false;
  return new_node;
}

347
/* Add allocno hard registers node NEW_NODE to the forest on its level
Vladimir Makarov committed
348 349
   given by ROOTS.  */
static void
350 351
add_new_allocno_hard_regs_node_to_forest (allocno_hard_regs_node_t *roots,
					  allocno_hard_regs_node_t new_node)
Vladimir Makarov committed
352 353 354 355 356 357 358 359
{
  new_node->next = *roots;
  if (new_node->next != NULL)
    new_node->next->prev = new_node;
  new_node->prev = NULL;
  *roots = new_node;
}

360
/* Add allocno hard registers HV (or its best approximation if it is
Vladimir Makarov committed
361 362
   not possible) to the forest on its level given by ROOTS.  */
static void
363 364
add_allocno_hard_regs_to_forest (allocno_hard_regs_node_t *roots,
				 allocno_hard_regs_t hv)
Vladimir Makarov committed
365 366
{
  unsigned int i, start;
367
  allocno_hard_regs_node_t node, prev, new_node;
Vladimir Makarov committed
368
  HARD_REG_SET temp_set;
369
  allocno_hard_regs_t hv2;
Vladimir Makarov committed
370

371
  start = hard_regs_node_vec.length ();
Vladimir Makarov committed
372 373
  for (node = *roots; node != NULL; node = node->next)
    {
374
      if (hv->set == node->hard_regs->set)
Vladimir Makarov committed
375 376 377
	return;
      if (hard_reg_set_subset_p (hv->set, node->hard_regs->set))
	{
378
	  add_allocno_hard_regs_to_forest (&node->first, hv);
Vladimir Makarov committed
379 380 381
	  return;
	}
      if (hard_reg_set_subset_p (node->hard_regs->set, hv->set))
382
	hard_regs_node_vec.safe_push (node);
Vladimir Makarov committed
383 384
      else if (hard_reg_set_intersect_p (hv->set, node->hard_regs->set))
	{
385
	  temp_set = hv->set & node->hard_regs->set;
386 387
	  hv2 = add_allocno_hard_regs (temp_set, hv->cost);
	  add_allocno_hard_regs_to_forest (&node->first, hv2);
Vladimir Makarov committed
388 389
	}
    }
390
  if (hard_regs_node_vec.length ()
Vladimir Makarov committed
391 392 393 394 395
      > start + 1)
    {
      /* Create a new node which contains nodes in hard_regs_node_vec.  */
      CLEAR_HARD_REG_SET (temp_set);
      for (i = start;
396
	   i < hard_regs_node_vec.length ();
Vladimir Makarov committed
397 398
	   i++)
	{
399
	  node = hard_regs_node_vec[i];
400
	  temp_set |= node->hard_regs->set;
Vladimir Makarov committed
401
	}
402 403
      hv = add_allocno_hard_regs (temp_set, hv->cost);
      new_node = create_new_allocno_hard_regs_node (hv);
Vladimir Makarov committed
404 405
      prev = NULL;
      for (i = start;
406
	   i < hard_regs_node_vec.length ();
Vladimir Makarov committed
407 408
	   i++)
	{
409
	  node = hard_regs_node_vec[i];
Vladimir Makarov committed
410 411 412 413 414 415 416 417 418 419 420 421 422 423
	  if (node->prev == NULL)
	    *roots = node->next;
	  else
	    node->prev->next = node->next;
	  if (node->next != NULL)
	    node->next->prev = node->prev;
	  if (prev == NULL)
	    new_node->first = node;
	  else
	    prev->next = node;
	  node->prev = prev;
	  node->next = NULL;
	  prev = node;
	}
424
      add_new_allocno_hard_regs_node_to_forest (roots, new_node);
Vladimir Makarov committed
425
    }
426
  hard_regs_node_vec.truncate (start);
Vladimir Makarov committed
427 428
}

429
/* Add allocno hard registers nodes starting with the forest level
Vladimir Makarov committed
430 431
   given by FIRST which contains biggest set inside SET.  */
static void
432
collect_allocno_hard_regs_cover (allocno_hard_regs_node_t first,
Vladimir Makarov committed
433 434
				 HARD_REG_SET set)
{
435
  allocno_hard_regs_node_t node;
Vladimir Makarov committed
436 437 438 439

  ira_assert (first != NULL);
  for (node = first; node != NULL; node = node->next)
    if (hard_reg_set_subset_p (node->hard_regs->set, set))
440
      hard_regs_node_vec.safe_push (node);
Vladimir Makarov committed
441
    else if (hard_reg_set_intersect_p (set, node->hard_regs->set))
442
      collect_allocno_hard_regs_cover (node->first, set);
Vladimir Makarov committed
443 444
}

445
/* Set up field parent as PARENT in all allocno hard registers nodes
Vladimir Makarov committed
446 447
   in forest given by FIRST.  */
static void
448 449
setup_allocno_hard_regs_nodes_parent (allocno_hard_regs_node_t first,
				      allocno_hard_regs_node_t parent)
Vladimir Makarov committed
450
{
451
  allocno_hard_regs_node_t node;
Vladimir Makarov committed
452 453 454 455

  for (node = first; node != NULL; node = node->next)
    {
      node->parent = parent;
456
      setup_allocno_hard_regs_nodes_parent (node->first, node);
Vladimir Makarov committed
457 458 459
    }
}

460
/* Return allocno hard registers node which is a first common ancestor
Vladimir Makarov committed
461
   node of FIRST and SECOND in the forest.  */
462 463 464
static allocno_hard_regs_node_t
first_common_ancestor_node (allocno_hard_regs_node_t first,
			    allocno_hard_regs_node_t second)
Vladimir Makarov committed
465
{
466
  allocno_hard_regs_node_t node;
Vladimir Makarov committed
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505

  node_check_tick++;
  for (node = first; node != NULL; node = node->parent)
    node->check = node_check_tick;
  for (node = second; node != NULL; node = node->parent)
    if (node->check == node_check_tick)
      return node;
  return first_common_ancestor_node (second, first);
}

/* Print hard reg set SET to F.  */
static void
print_hard_reg_set (FILE *f, HARD_REG_SET set, bool new_line_p)
{
  int i, start;

  for (start = -1, i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    {
      if (TEST_HARD_REG_BIT (set, i))
	{
	  if (i == 0 || ! TEST_HARD_REG_BIT (set, i - 1))
	    start = i;
	}
      if (start >= 0
	  && (i == FIRST_PSEUDO_REGISTER - 1 || ! TEST_HARD_REG_BIT (set, i)))
	{
	  if (start == i - 1)
	    fprintf (f, " %d", start);
	  else if (start == i - 2)
	    fprintf (f, " %d %d", start, start + 1);
	  else
	    fprintf (f, " %d-%d", start, i - 1);
	  start = -1;
	}
    }
  if (new_line_p)
    fprintf (f, "\n");
}

506
/* Print allocno hard register subforest given by ROOTS and its LEVEL
Vladimir Makarov committed
507 508
   to F.  */
static void
509
print_hard_regs_subforest (FILE *f, allocno_hard_regs_node_t roots,
Vladimir Makarov committed
510 511 512
			   int level)
{
  int i;
513
  allocno_hard_regs_node_t node;
Vladimir Makarov committed
514 515 516 517 518 519 520 521

  for (node = roots; node != NULL; node = node->next)
    {
      fprintf (f, "    ");
      for (i = 0; i < level * 2; i++)
	fprintf (f, " ");
      fprintf (f, "%d:(", node->preorder_num);
      print_hard_reg_set (f, node->hard_regs->set, false);
522
      fprintf (f, ")@%" PRId64"\n", node->hard_regs->cost);
Vladimir Makarov committed
523 524 525 526
      print_hard_regs_subforest (f, node->first, level + 1);
    }
}

527
/* Print the allocno hard register forest to F.  */
Vladimir Makarov committed
528 529 530 531 532 533 534
static void
print_hard_regs_forest (FILE *f)
{
  fprintf (f, "    Hard reg set forest:\n");
  print_hard_regs_subforest (f, hard_regs_roots, 1);
}

535
/* Print the allocno hard register forest to stderr.  */
Vladimir Makarov committed
536 537 538 539 540 541
void
ira_debug_hard_regs_forest (void)
{
  print_hard_regs_forest (stderr);
}

542
/* Remove unused allocno hard registers nodes from forest given by its
Vladimir Makarov committed
543 544
   *ROOTS.  */
static void
545
remove_unused_allocno_hard_regs_nodes (allocno_hard_regs_node_t *roots)
Vladimir Makarov committed
546
{
547
  allocno_hard_regs_node_t node, prev, next, last;
Vladimir Makarov committed
548 549 550 551 552 553

  for (prev = NULL, node = *roots; node != NULL; node = next)
    {
      next = node->next;
      if (node->used_p)
	{
554
	  remove_unused_allocno_hard_regs_nodes (&node->first);
Vladimir Makarov committed
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
	  prev = node;
	}
      else
	{
	  for (last = node->first;
	       last != NULL && last->next != NULL;
	       last = last->next)
	    ;
	  if (last != NULL)
	    {
	      if (prev == NULL)
		*roots = node->first;
	      else 
		prev->next = node->first;
	      if (next != NULL)
		next->prev = last;
	      last->next = next;
	      next = node->first;
	    }
	  else
	    {
	      if (prev == NULL)
		*roots = next;
	      else
		prev->next = next;
	      if (next != NULL)
		next->prev = prev;
	    }
	  ira_free (node);
	}
    }
}

588
/* Set up fields preorder_num starting with START_NUM in all allocno
Vladimir Makarov committed
589 590 591
   hard registers nodes in forest given by FIRST.  Return biggest set
   PREORDER_NUM increased by 1.  */
static int
592 593 594
enumerate_allocno_hard_regs_nodes (allocno_hard_regs_node_t first,
				   allocno_hard_regs_node_t parent,
				   int start_num)
Vladimir Makarov committed
595
{
596
  allocno_hard_regs_node_t node;
Vladimir Makarov committed
597 598 599 600 601

  for (node = first; node != NULL; node = node->next)
    {
      node->preorder_num = start_num++;
      node->parent = parent;
602 603
      start_num = enumerate_allocno_hard_regs_nodes (node->first, node,
						     start_num);
Vladimir Makarov committed
604 605 606 607
    }
  return start_num;
}

608 609
/* Number of allocno hard registers nodes in the forest.  */
static int allocno_hard_regs_nodes_num;
Vladimir Makarov committed
610

611 612 613
/* Table preorder number of allocno hard registers node in the forest
   -> the allocno hard registers node.  */
static allocno_hard_regs_node_t *allocno_hard_regs_nodes;
Vladimir Makarov committed
614 615

/* See below.  */
616
typedef struct allocno_hard_regs_subnode *allocno_hard_regs_subnode_t;
Vladimir Makarov committed
617 618

/* The structure is used to describes all subnodes (not only immediate
619
   ones) in the mentioned above tree for given allocno hard register
Vladimir Makarov committed
620 621
   node.  The usage of such data accelerates calculation of
   colorability of given allocno.  */
622
struct allocno_hard_regs_subnode
Vladimir Makarov committed
623 624 625
{
  /* The conflict size of conflicting allocnos whose hard register
     sets are equal sets (plus supersets if given node is given
626
     allocno hard registers node) of one in the given node.  */
Vladimir Makarov committed
627 628 629 630 631 632 633 634 635 636 637 638
  int left_conflict_size;
  /* The summary conflict size of conflicting allocnos whose hard
     register sets are strict subsets of one in the given node.
     Overall conflict size is
     left_conflict_subnodes_size
       + MIN (max_node_impact - left_conflict_subnodes_size,
              left_conflict_size)
  */
  short left_conflict_subnodes_size;
  short max_node_impact;
};

639 640
/* Container for hard regs subnodes of all allocnos.  */
static allocno_hard_regs_subnode_t allocno_hard_regs_subnodes;
Vladimir Makarov committed
641

642 643
/* Table (preorder number of allocno hard registers node in the
   forest, preorder number of allocno hard registers subnode) -> index
Vladimir Makarov committed
644 645
   of the subnode relative to the node.  -1 if it is not a
   subnode.  */
646
static int *allocno_hard_regs_subnode_index;
Vladimir Makarov committed
647

648 649
/* Setup arrays ALLOCNO_HARD_REGS_NODES and
   ALLOCNO_HARD_REGS_SUBNODE_INDEX.  */
Vladimir Makarov committed
650
static void
651
setup_allocno_hard_regs_subnode_index (allocno_hard_regs_node_t first)
Vladimir Makarov committed
652
{
653
  allocno_hard_regs_node_t node, parent;
Vladimir Makarov committed
654 655 656 657
  int index;

  for (node = first; node != NULL; node = node->next)
    {
658
      allocno_hard_regs_nodes[node->preorder_num] = node;
Vladimir Makarov committed
659 660
      for (parent = node; parent != NULL; parent = parent->parent)
	{
661 662
	  index = parent->preorder_num * allocno_hard_regs_nodes_num;
	  allocno_hard_regs_subnode_index[index + node->preorder_num]
Vladimir Makarov committed
663 664
	    = node->preorder_num - parent->preorder_num;
	}
665
      setup_allocno_hard_regs_subnode_index (node->first);
Vladimir Makarov committed
666 667 668
    }
}

669
/* Count all allocno hard registers nodes in tree ROOT.  */
Vladimir Makarov committed
670
static int
671
get_allocno_hard_regs_subnodes_num (allocno_hard_regs_node_t root)
Vladimir Makarov committed
672 673 674 675
{
  int len = 1;

  for (root = root->first; root != NULL; root = root->next)
676
    len += get_allocno_hard_regs_subnodes_num (root);
Vladimir Makarov committed
677 678 679
  return len;
}

680
/* Build the forest of allocno hard registers nodes and assign each
Vladimir Makarov committed
681 682
   allocno a node from the forest.  */
static void
683
form_allocno_hard_regs_nodes_forest (void)
Vladimir Makarov committed
684 685
{
  unsigned int i, j, size, len;
686
  int start;
Vladimir Makarov committed
687
  ira_allocno_t a;
688
  allocno_hard_regs_t hv;
Vladimir Makarov committed
689 690
  bitmap_iterator bi;
  HARD_REG_SET temp;
691 692
  allocno_hard_regs_node_t node, allocno_hard_regs_node;
  allocno_color_data_t allocno_data;
Vladimir Makarov committed
693 694

  node_check_tick = 0;
695
  init_allocno_hard_regs ();
Vladimir Makarov committed
696
  hard_regs_roots = NULL;
697
  hard_regs_node_vec.create (100);
Vladimir Makarov committed
698 699 700 701 702
  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, i))
      {
	CLEAR_HARD_REG_SET (temp);
	SET_HARD_REG_BIT (temp, i);
703 704 705
	hv = add_allocno_hard_regs (temp, 0);
	node = create_new_allocno_hard_regs_node (hv);
	add_new_allocno_hard_regs_node_to_forest (&hard_regs_roots, node);
Vladimir Makarov committed
706
      }
707
  start = allocno_hard_regs_vec.length ();
Vladimir Makarov committed
708 709 710
  EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
    {
      a = ira_allocnos[i];
711 712 713 714 715 716 717
      allocno_data = ALLOCNO_COLOR_DATA (a);
      
      if (hard_reg_set_empty_p (allocno_data->profitable_hard_regs))
	continue;
      hv = (add_allocno_hard_regs
	    (allocno_data->profitable_hard_regs,
	     ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a)));
Vladimir Makarov committed
718
    }
719
  temp = ~ira_no_alloc_regs;
720
  add_allocno_hard_regs (temp, 0);
721 722
  qsort (allocno_hard_regs_vec.address () + start,
	 allocno_hard_regs_vec.length () - start,
723
	 sizeof (allocno_hard_regs_t), allocno_hard_regs_compare);
Vladimir Makarov committed
724
  for (i = start;
725
       allocno_hard_regs_vec.iterate (i, &hv);
Vladimir Makarov committed
726 727
       i++)
    {
728
      add_allocno_hard_regs_to_forest (&hard_regs_roots, hv);
729
      ira_assert (hard_regs_node_vec.length () == 0);
Vladimir Makarov committed
730 731 732
    }
  /* We need to set up parent fields for right work of
     first_common_ancestor_node. */
733
  setup_allocno_hard_regs_nodes_parent (hard_regs_roots, NULL);
Vladimir Makarov committed
734 735 736
  EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
    {
      a = ira_allocnos[i];
737 738 739
      allocno_data = ALLOCNO_COLOR_DATA (a);
      if (hard_reg_set_empty_p (allocno_data->profitable_hard_regs))
	continue;
740
      hard_regs_node_vec.truncate (0);
741 742 743
      collect_allocno_hard_regs_cover (hard_regs_roots,
				       allocno_data->profitable_hard_regs);
      allocno_hard_regs_node = NULL;
744
      for (j = 0; hard_regs_node_vec.iterate (j, &node); j++)
745 746 747 748 749 750 751
	allocno_hard_regs_node
	  = (j == 0
	     ? node
	     : first_common_ancestor_node (node, allocno_hard_regs_node));
      /* That is a temporary storage.  */
      allocno_hard_regs_node->used_p = true;
      allocno_data->hard_regs_node = allocno_hard_regs_node;
Vladimir Makarov committed
752 753 754
    }
  ira_assert (hard_regs_roots->next == NULL);
  hard_regs_roots->used_p = true;
755 756 757 758 759 760 761 762 763
  remove_unused_allocno_hard_regs_nodes (&hard_regs_roots);
  allocno_hard_regs_nodes_num
    = enumerate_allocno_hard_regs_nodes (hard_regs_roots, NULL, 0);
  allocno_hard_regs_nodes
    = ((allocno_hard_regs_node_t *)
       ira_allocate (allocno_hard_regs_nodes_num
		     * sizeof (allocno_hard_regs_node_t)));
  size = allocno_hard_regs_nodes_num * allocno_hard_regs_nodes_num;
  allocno_hard_regs_subnode_index
Vladimir Makarov committed
764 765
    = (int *) ira_allocate (size * sizeof (int));
  for (i = 0; i < size; i++)
766 767
    allocno_hard_regs_subnode_index[i] = -1;
  setup_allocno_hard_regs_subnode_index (hard_regs_roots);
Vladimir Makarov committed
768 769 770 771
  start = 0;
  EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
    {
      a = ira_allocnos[i];
772 773 774 775 776 777 778
      allocno_data = ALLOCNO_COLOR_DATA (a);
      if (hard_reg_set_empty_p (allocno_data->profitable_hard_regs))
	continue;
      len = get_allocno_hard_regs_subnodes_num (allocno_data->hard_regs_node);
      allocno_data->hard_regs_subnodes_start = start;
      allocno_data->hard_regs_subnodes_num = len;
      start += len;
Vladimir Makarov committed
779
    }
780 781 782
  allocno_hard_regs_subnodes
    = ((allocno_hard_regs_subnode_t)
       ira_allocate (sizeof (struct allocno_hard_regs_subnode) * start));
783
  hard_regs_node_vec.release ();
Vladimir Makarov committed
784 785
}

786
/* Free tree of allocno hard registers nodes given by its ROOT.  */
Vladimir Makarov committed
787
static void
788
finish_allocno_hard_regs_nodes_tree (allocno_hard_regs_node_t root)
Vladimir Makarov committed
789
{
790
  allocno_hard_regs_node_t child, next;
Vladimir Makarov committed
791 792 793 794

  for (child = root->first; child != NULL; child = next)
    {
      next = child->next;
795
      finish_allocno_hard_regs_nodes_tree (child);
Vladimir Makarov committed
796 797 798 799
    }
  ira_free (root);
}

800
/* Finish work with the forest of allocno hard registers nodes.  */
Vladimir Makarov committed
801
static void
802
finish_allocno_hard_regs_nodes_forest (void)
Vladimir Makarov committed
803
{
804
  allocno_hard_regs_node_t node, next;
Vladimir Makarov committed
805
  
806
  ira_free (allocno_hard_regs_subnodes);
Vladimir Makarov committed
807 808 809
  for (node = hard_regs_roots; node != NULL; node = next)
    {
      next = node->next;
810
      finish_allocno_hard_regs_nodes_tree (node);
Vladimir Makarov committed
811
    }
812 813 814
  ira_free (allocno_hard_regs_nodes);
  ira_free (allocno_hard_regs_subnode_index);
  finish_allocno_hard_regs ();
Vladimir Makarov committed
815 816 817 818 819
}

/* Set up left conflict sizes and left conflict subnodes sizes of hard
   registers subnodes of allocno A.  Return TRUE if allocno A is
   trivially colorable.  */
820
static bool
Vladimir Makarov committed
821
setup_left_conflict_sizes_p (ira_allocno_t a)
822
{
823 824
  int i, k, nobj, start;
  int conflict_size, left_conflict_subnodes_size, node_preorder_num;
Vladimir Makarov committed
825
  allocno_color_data_t data;
826 827 828 829
  HARD_REG_SET profitable_hard_regs;
  allocno_hard_regs_subnode_t subnodes;
  allocno_hard_regs_node_t node;
  HARD_REG_SET node_set;
830

Vladimir Makarov committed
831 832
  nobj = ALLOCNO_NUM_OBJECTS (a);
  data = ALLOCNO_COLOR_DATA (a);
833
  subnodes = allocno_hard_regs_subnodes + data->hard_regs_subnodes_start;
834
  profitable_hard_regs = data->profitable_hard_regs;
835 836
  node = data->hard_regs_node;
  node_preorder_num = node->preorder_num;
837
  node_set = node->hard_regs->set;
838
  node_check_tick++;
Vladimir Makarov committed
839 840 841 842 843 844 845 846 847 848
  for (k = 0; k < nobj; k++)
    {
      ira_object_t obj = ALLOCNO_OBJECT (a, k);
      ira_object_t conflict_obj;
      ira_object_conflict_iterator oci;
      
      FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
	{
	  int size;
 	  ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
849
	  allocno_hard_regs_node_t conflict_node, temp_node;
Vladimir Makarov committed
850
	  HARD_REG_SET conflict_node_set;
851
	  allocno_color_data_t conflict_data;
Vladimir Makarov committed
852

853
	  conflict_data = ALLOCNO_COLOR_DATA (conflict_a);
Vladimir Makarov committed
854 855
	  if (! ALLOCNO_COLOR_DATA (conflict_a)->in_graph_p
	      || ! hard_reg_set_intersect_p (profitable_hard_regs,
856
					     conflict_data
Vladimir Makarov committed
857 858
					     ->profitable_hard_regs))
	    continue;
859
	  conflict_node = conflict_data->hard_regs_node;
860
	  conflict_node_set = conflict_node->hard_regs->set;
Vladimir Makarov committed
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879
	  if (hard_reg_set_subset_p (node_set, conflict_node_set))
	    temp_node = node;
	  else
	    {
	      ira_assert (hard_reg_set_subset_p (conflict_node_set, node_set));
	      temp_node = conflict_node;
	    }
	  if (temp_node->check != node_check_tick)
	    {
	      temp_node->check = node_check_tick;
	      temp_node->conflict_size = 0;
	    }
	  size = (ira_reg_class_max_nregs
		  [ALLOCNO_CLASS (conflict_a)][ALLOCNO_MODE (conflict_a)]);
	  if (ALLOCNO_NUM_OBJECTS (conflict_a) > 1)
	    /* We will deal with the subwords individually.  */
	    size = 1;
	  temp_node->conflict_size += size;
	}
880 881 882 883 884 885 886 887 888 889 890 891 892
    }
  for (i = 0; i < data->hard_regs_subnodes_num; i++)
    {
      allocno_hard_regs_node_t temp_node;
      
      temp_node = allocno_hard_regs_nodes[i + node_preorder_num];
      ira_assert (temp_node->preorder_num == i + node_preorder_num);
      subnodes[i].left_conflict_size = (temp_node->check != node_check_tick
					? 0 : temp_node->conflict_size);
      if (hard_reg_set_subset_p (temp_node->hard_regs->set,
				 profitable_hard_regs))
	subnodes[i].max_node_impact = temp_node->hard_regs_num;
      else
Vladimir Makarov committed
893
	{
894 895 896 897
	  HARD_REG_SET temp_set;
	  int j, n, hard_regno;
	  enum reg_class aclass;
	  
898
	  temp_set = temp_node->hard_regs->set & profitable_hard_regs;
899 900
	  aclass = ALLOCNO_CLASS (a);
	  for (n = 0, j = ira_class_hard_regs_num[aclass] - 1; j >= 0; j--)
Vladimir Makarov committed
901
	    {
902 903 904
	      hard_regno = ira_class_hard_regs[aclass][j];
	      if (TEST_HARD_REG_BIT (temp_set, hard_regno))
		n++;
Vladimir Makarov committed
905
	    }
906
	  subnodes[i].max_node_impact = n;
Vladimir Makarov committed
907
	}
908 909 910
      subnodes[i].left_conflict_subnodes_size = 0;
    }
  start = node_preorder_num * allocno_hard_regs_nodes_num;
911
  for (i = data->hard_regs_subnodes_num - 1; i > 0; i--)
912 913 914 915 916 917 918 919 920
    {
      int size, parent_i;
      allocno_hard_regs_node_t parent;
      
      size = (subnodes[i].left_conflict_subnodes_size
	      + MIN (subnodes[i].max_node_impact
		     - subnodes[i].left_conflict_subnodes_size,
		     subnodes[i].left_conflict_size));
      parent = allocno_hard_regs_nodes[i + node_preorder_num]->parent;
921
      gcc_checking_assert(parent);
922 923
      parent_i
	= allocno_hard_regs_subnode_index[start + parent->preorder_num];
924
      gcc_checking_assert(parent_i >= 0);
925
      subnodes[parent_i].left_conflict_subnodes_size += size;
Vladimir Makarov committed
926
    }
927 928
  left_conflict_subnodes_size = subnodes[0].left_conflict_subnodes_size;
  conflict_size
929 930 931
    = (left_conflict_subnodes_size
       + MIN (subnodes[0].max_node_impact - left_conflict_subnodes_size,
	      subnodes[0].left_conflict_size));
Vladimir Makarov committed
932 933 934 935
  conflict_size += ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)];
  data->colorable_p = conflict_size <= data->available_regs_num;
  return data->colorable_p;
}
936

Vladimir Makarov committed
937
/* Update left conflict sizes of hard registers subnodes of allocno A
938 939
   after removing allocno REMOVED_A with SIZE from the conflict graph.
   Return TRUE if A is trivially colorable.  */
Vladimir Makarov committed
940 941
static bool
update_left_conflict_sizes_p (ira_allocno_t a,
942
			      ira_allocno_t removed_a, int size)
Vladimir Makarov committed
943
{
944
  int i, conflict_size, before_conflict_size, diff, start;
Vladimir Makarov committed
945
  int node_preorder_num, parent_i;
946 947
  allocno_hard_regs_node_t node, removed_node, parent;
  allocno_hard_regs_subnode_t subnodes;
Vladimir Makarov committed
948 949 950
  allocno_color_data_t data = ALLOCNO_COLOR_DATA (a);

  ira_assert (! data->colorable_p);
951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969
  node = data->hard_regs_node;
  node_preorder_num = node->preorder_num;
  removed_node = ALLOCNO_COLOR_DATA (removed_a)->hard_regs_node;
  ira_assert (hard_reg_set_subset_p (removed_node->hard_regs->set,
			       node->hard_regs->set)
	      || hard_reg_set_subset_p (node->hard_regs->set,
					removed_node->hard_regs->set));
  start = node_preorder_num * allocno_hard_regs_nodes_num;
  i = allocno_hard_regs_subnode_index[start + removed_node->preorder_num];
  if (i < 0)
    i = 0;
  subnodes = allocno_hard_regs_subnodes + data->hard_regs_subnodes_start;
  before_conflict_size
    = (subnodes[i].left_conflict_subnodes_size
       + MIN (subnodes[i].max_node_impact
	      - subnodes[i].left_conflict_subnodes_size,
	      subnodes[i].left_conflict_size));
  subnodes[i].left_conflict_size -= size;
  for (;;)
970
    {
971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
      conflict_size
	= (subnodes[i].left_conflict_subnodes_size
	   + MIN (subnodes[i].max_node_impact
		  - subnodes[i].left_conflict_subnodes_size,
		  subnodes[i].left_conflict_size));
      if ((diff = before_conflict_size - conflict_size) == 0)
	break;
      ira_assert (conflict_size < before_conflict_size);
      parent = allocno_hard_regs_nodes[i + node_preorder_num]->parent;
      if (parent == NULL)
	break;
      parent_i
	= allocno_hard_regs_subnode_index[start + parent->preorder_num];
      if (parent_i < 0)
	break;
      i = parent_i;
Vladimir Makarov committed
987 988 989 990 991
      before_conflict_size
	= (subnodes[i].left_conflict_subnodes_size
	   + MIN (subnodes[i].max_node_impact
		  - subnodes[i].left_conflict_subnodes_size,
		  subnodes[i].left_conflict_size));
992
      subnodes[i].left_conflict_subnodes_size -= diff;
993
    }
994 995 996 997 998 999 1000
  if (i != 0
      || (conflict_size 
	  + ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]
	  > data->available_regs_num))
    return false;
  data->colorable_p = true;
  return true;
1001 1002
}

1003
/* Return true if allocno A has empty profitable hard regs.  */
1004
static bool
Vladimir Makarov committed
1005
empty_profitable_hard_regs (ira_allocno_t a)
1006
{
1007
  allocno_color_data_t data = ALLOCNO_COLOR_DATA (a);
Vladimir Makarov committed
1008

1009
  return hard_reg_set_empty_p (data->profitable_hard_regs);
1010 1011
}

Vladimir Makarov committed
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
/* Set up profitable hard registers for each allocno being
   colored.  */
static void
setup_profitable_hard_regs (void)
{
  unsigned int i;
  int j, k, nobj, hard_regno, nregs, class_size;
  ira_allocno_t a;
  bitmap_iterator bi;
  enum reg_class aclass;
1022
  machine_mode mode;
1023
  allocno_color_data_t data;
Vladimir Makarov committed
1024

1025 1026
  /* Initial set up from allocno classes and explicitly conflicting
     hard regs.  */
Vladimir Makarov committed
1027 1028 1029 1030 1031
  EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
    {
      a = ira_allocnos[i];
      if ((aclass = ALLOCNO_CLASS (a)) == NO_REGS)
	continue;
1032 1033
      data = ALLOCNO_COLOR_DATA (a);
      if (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL
1034 1035 1036 1037
	  && ALLOCNO_CLASS_COST (a) > ALLOCNO_MEMORY_COST (a)
	  /* Do not empty profitable regs for static chain pointer
	     pseudo when non-local goto is used.  */
	  && ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
1038 1039
	CLEAR_HARD_REG_SET (data->profitable_hard_regs);
      else
Vladimir Makarov committed
1040
	{
1041
	  mode = ALLOCNO_MODE (a);
1042 1043
	  data->profitable_hard_regs
	    = ira_useful_class_mode_regs[aclass][mode];
1044 1045
	  nobj = ALLOCNO_NUM_OBJECTS (a);
	  for (k = 0; k < nobj; k++)
Vladimir Makarov committed
1046
	    {
1047 1048
	      ira_object_t obj = ALLOCNO_OBJECT (a, k);
	      
1049 1050
	      data->profitable_hard_regs
		&= ~OBJECT_TOTAL_CONFLICT_HARD_REGS (obj);
Vladimir Makarov committed
1051 1052 1053
	    }
	}
    }
1054
  /* Exclude hard regs already assigned for conflicting objects.  */
Vladimir Makarov committed
1055 1056 1057 1058 1059 1060 1061 1062
  EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, i, bi)
    {
      a = ira_allocnos[i];
      if ((aclass = ALLOCNO_CLASS (a)) == NO_REGS
	  || ! ALLOCNO_ASSIGNED_P (a)
	  || (hard_regno = ALLOCNO_HARD_REGNO (a)) < 0)
	continue;
      mode = ALLOCNO_MODE (a);
1063
      nregs = hard_regno_nregs (hard_regno, mode);
Vladimir Makarov committed
1064 1065 1066 1067 1068 1069 1070 1071 1072
      nobj = ALLOCNO_NUM_OBJECTS (a);
      for (k = 0; k < nobj; k++)
	{
	  ira_object_t obj = ALLOCNO_OBJECT (a, k);
	  ira_object_t conflict_obj;
	  ira_object_conflict_iterator oci;

	  FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
	    {
1073 1074 1075 1076
	      ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);

	      /* We can process the conflict allocno repeatedly with
		 the same result.  */
Vladimir Makarov committed
1077 1078 1079 1080
	      if (nregs == nobj && nregs > 1)
		{
		  int num = OBJECT_SUBWORD (conflict_obj);
		  
1081
		  if (REG_WORDS_BIG_ENDIAN)
Vladimir Makarov committed
1082
		    CLEAR_HARD_REG_BIT
1083
		      (ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs,
Vladimir Makarov committed
1084 1085 1086
		       hard_regno + nobj - num - 1);
		  else
		    CLEAR_HARD_REG_BIT
1087
		      (ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs,
Vladimir Makarov committed
1088 1089 1090
		       hard_regno + num);
		}
	      else
1091 1092
		ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs
		  &= ~ira_reg_mode_hard_regset[hard_regno][mode];
Vladimir Makarov committed
1093 1094 1095
	    }
	}
    }
1096
  /* Exclude too costly hard regs.  */
Vladimir Makarov committed
1097 1098 1099 1100 1101 1102 1103 1104 1105
  EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
    {
      int min_cost = INT_MAX;
      int *costs;

      a = ira_allocnos[i];
      if ((aclass = ALLOCNO_CLASS (a)) == NO_REGS
	  || empty_profitable_hard_regs (a))
	continue;
1106 1107 1108
      data = ALLOCNO_COLOR_DATA (a);
      if ((costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a)) != NULL
	  || (costs = ALLOCNO_HARD_REG_COSTS (a)) != NULL)
Vladimir Makarov committed
1109
	{
1110 1111
	  class_size = ira_class_hard_regs_num[aclass];
	  for (j = 0; j < class_size; j++)
Vladimir Makarov committed
1112
	    {
1113 1114 1115 1116
	      hard_regno = ira_class_hard_regs[aclass][j];
	      if (! TEST_HARD_REG_BIT (data->profitable_hard_regs,
				       hard_regno))
		continue;
1117 1118 1119 1120
	      if (ALLOCNO_UPDATED_MEMORY_COST (a) < costs[j]
		  /* Do not remove HARD_REGNO for static chain pointer
		     pseudo when non-local goto is used.  */
		  && ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
1121 1122 1123 1124
		CLEAR_HARD_REG_BIT (data->profitable_hard_regs,
				    hard_regno);
	      else if (min_cost > costs[j])
		min_cost = costs[j];
Vladimir Makarov committed
1125 1126
	    }
	}
1127
      else if (ALLOCNO_UPDATED_MEMORY_COST (a)
1128 1129 1130 1131
	       < ALLOCNO_UPDATED_CLASS_COST (a)
	       /* Do not empty profitable regs for static chain
		  pointer pseudo when non-local goto is used.  */
	       && ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
1132
	CLEAR_HARD_REG_SET (data->profitable_hard_regs);
Vladimir Makarov committed
1133 1134 1135 1136
      if (ALLOCNO_UPDATED_CLASS_COST (a) > min_cost)
	ALLOCNO_UPDATED_CLASS_COST (a) = min_cost;
    }
}
1137 1138 1139



Vladimir Makarov committed
1140 1141 1142
/* This page contains functions used to choose hard registers for
   allocnos.  */

Vladimir Makarov committed
1143
/* Pool for update cost records.  */
1144
static object_allocator<update_cost_record> update_cost_record_pool
1145
  ("update cost records");
Vladimir Makarov committed
1146 1147 1148 1149 1150 1151 1152 1153

/* Return new update cost record with given params.  */
static struct update_cost_record *
get_update_cost_record (int hard_regno, int divisor,
			struct update_cost_record *next)
{
  struct update_cost_record *record;

1154
  record = update_cost_record_pool.allocate ();
Vladimir Makarov committed
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
  record->hard_regno = hard_regno;
  record->divisor = divisor;
  record->next = next;
  return record;
}

/* Free memory for all records in LIST.  */
static void
free_update_cost_record_list (struct update_cost_record *list)
{
  struct update_cost_record *next;

  while (list != NULL)
    {
      next = list->next;
1170
      update_cost_record_pool.remove (list);
Vladimir Makarov committed
1171 1172 1173 1174 1175 1176 1177 1178
      list = next;
    }
}

/* Free memory allocated for all update cost records.  */
static void
finish_update_cost_records (void)
{
1179
  update_cost_record_pool.release ();
Vladimir Makarov committed
1180 1181
}

Vladimir Makarov committed
1182 1183 1184 1185
/* Array whose element value is TRUE if the corresponding hard
   register was already allocated for an allocno.  */
static bool allocated_hardreg_p[FIRST_PSEUDO_REGISTER];

1186
/* Describes one element in a queue of allocnos whose costs need to be
Vladimir Makarov committed
1187 1188
   updated.  Each allocno in the queue is known to have an allocno
   class.  */
1189 1190
struct update_cost_queue_elem
{
1191 1192 1193 1194 1195 1196 1197
  /* This element is in the queue iff CHECK == update_cost_check.  */
  int check;

  /* COST_HOP_DIVISOR**N, where N is the length of the shortest path
     connecting this allocno to the one being allocated.  */
  int divisor;

Kito Cheng committed
1198
  /* Allocno from which we are chaining costs of connected allocnos.
Vladimir Makarov committed
1199 1200 1201 1202
     It is used not go back in graph of allocnos connected by
     copies.  */
  ira_allocno_t from;

1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217
  /* The next allocno in the queue, or null if this is the last element.  */
  ira_allocno_t next;
};

/* The first element in a queue of allocnos whose copy costs need to be
   updated.  Null if the queue is empty.  */
static ira_allocno_t update_cost_queue;

/* The last element in the queue described by update_cost_queue.
   Not valid if update_cost_queue is null.  */
static struct update_cost_queue_elem *update_cost_queue_tail;

/* A pool of elements in the queue described by update_cost_queue.
   Elements are indexed by ALLOCNO_NUM.  */
static struct update_cost_queue_elem *update_cost_queue_elems;
Vladimir Makarov committed
1218

Vladimir Makarov committed
1219
/* The current value of update_costs_from_copies call count.  */
Vladimir Makarov committed
1220 1221 1222
static int update_cost_check;

/* Allocate and initialize data necessary for function
1223
   update_costs_from_copies.  */
Vladimir Makarov committed
1224 1225 1226
static void
initiate_cost_update (void)
{
1227 1228 1229 1230 1231 1232
  size_t size;

  size = ira_allocnos_num * sizeof (struct update_cost_queue_elem);
  update_cost_queue_elems
    = (struct update_cost_queue_elem *) ira_allocate (size);
  memset (update_cost_queue_elems, 0, size);
Vladimir Makarov committed
1233 1234 1235
  update_cost_check = 0;
}

Vladimir Makarov committed
1236
/* Deallocate data used by function update_costs_from_copies.  */
Vladimir Makarov committed
1237 1238 1239
static void
finish_cost_update (void)
{
1240
  ira_free (update_cost_queue_elems);
Vladimir Makarov committed
1241
  finish_update_cost_records ();
Vladimir Makarov committed
1242 1243
}

1244 1245 1246 1247 1248
/* When we traverse allocnos to update hard register costs, the cost
   divisor will be multiplied by the following macro value for each
   hop from given allocno to directly connected allocnos.  */
#define COST_HOP_DIVISOR 4

1249
/* Start a new cost-updating pass.  */
Vladimir Makarov committed
1250
static void
1251
start_update_cost (void)
Vladimir Makarov committed
1252
{
1253 1254 1255
  update_cost_check++;
  update_cost_queue = NULL;
}
Vladimir Makarov committed
1256

Vladimir Makarov committed
1257
/* Add (ALLOCNO, FROM, DIVISOR) to the end of update_cost_queue, unless
Vladimir Makarov committed
1258
   ALLOCNO is already in the queue, or has NO_REGS class.  */
1259
static inline void
Vladimir Makarov committed
1260
queue_update_cost (ira_allocno_t allocno, ira_allocno_t from, int divisor)
1261 1262 1263 1264 1265
{
  struct update_cost_queue_elem *elem;

  elem = &update_cost_queue_elems[ALLOCNO_NUM (allocno)];
  if (elem->check != update_cost_check
Vladimir Makarov committed
1266
      && ALLOCNO_CLASS (allocno) != NO_REGS)
Vladimir Makarov committed
1267
    {
1268
      elem->check = update_cost_check;
Vladimir Makarov committed
1269
      elem->from = from;
1270 1271 1272 1273
      elem->divisor = divisor;
      elem->next = NULL;
      if (update_cost_queue == NULL)
	update_cost_queue = allocno;
Vladimir Makarov committed
1274
      else
1275 1276
	update_cost_queue_tail->next = allocno;
      update_cost_queue_tail = elem;
Vladimir Makarov committed
1277 1278 1279
    }
}

Vladimir Makarov committed
1280 1281 1282
/* Try to remove the first element from update_cost_queue.  Return
   false if the queue was empty, otherwise make (*ALLOCNO, *FROM,
   *DIVISOR) describe the removed element.  */
1283
static inline bool
Vladimir Makarov committed
1284
get_next_update_cost (ira_allocno_t *allocno, ira_allocno_t *from, int *divisor)
Vladimir Makarov committed
1285
{
1286 1287 1288 1289 1290 1291 1292
  struct update_cost_queue_elem *elem;

  if (update_cost_queue == NULL)
    return false;

  *allocno = update_cost_queue;
  elem = &update_cost_queue_elems[ALLOCNO_NUM (*allocno)];
Vladimir Makarov committed
1293
  *from = elem->from;
1294 1295 1296
  *divisor = elem->divisor;
  update_cost_queue = elem->next;
  return true;
Vladimir Makarov committed
1297 1298
}

1299 1300 1301
/* Increase costs of HARD_REGNO by UPDATE_COST and conflict cost by
   UPDATE_CONFLICT_COST for ALLOCNO.  Return true if we really
   modified the cost.  */
Vladimir Makarov committed
1302
static bool
1303 1304
update_allocno_cost (ira_allocno_t allocno, int hard_regno,
		     int update_cost, int update_conflict_cost)
Vladimir Makarov committed
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319
{
  int i;
  enum reg_class aclass = ALLOCNO_CLASS (allocno);

  i = ira_class_hard_reg_index[aclass][hard_regno];
  if (i < 0)
    return false;
  ira_allocate_and_set_or_copy_costs
    (&ALLOCNO_UPDATED_HARD_REG_COSTS (allocno), aclass,
     ALLOCNO_UPDATED_CLASS_COST (allocno),
     ALLOCNO_HARD_REG_COSTS (allocno));
  ira_allocate_and_set_or_copy_costs
    (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno),
     aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (allocno));
  ALLOCNO_UPDATED_HARD_REG_COSTS (allocno)[i] += update_cost;
1320
  ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno)[i] += update_conflict_cost;
Vladimir Makarov committed
1321 1322 1323 1324 1325 1326 1327
  return true;
}

/* Update (decrease if DECR_P) HARD_REGNO cost of allocnos connected
   by copies to ALLOCNO to increase chances to remove some copies as
   the result of subsequent assignment.  Record cost updates if
   RECORD_P is true.  */
1328
static void
Vladimir Makarov committed
1329 1330
update_costs_from_allocno (ira_allocno_t allocno, int hard_regno,
			   int divisor, bool decr_p, bool record_p)
1331
{
1332
  int cost, update_cost, update_conflict_cost;
1333
  machine_mode mode;
Vladimir Makarov committed
1334
  enum reg_class rclass, aclass;
Vladimir Makarov committed
1335
  ira_allocno_t another_allocno, from = NULL;
1336 1337
  ira_copy_t cp, next_cp;

1338 1339
  rclass = REGNO_REG_CLASS (hard_regno);
  do
1340
    {
1341
      mode = ALLOCNO_MODE (allocno);
Vladimir Makarov committed
1342
      ira_init_register_move_cost_if_necessary (mode);
1343
      for (cp = ALLOCNO_COPIES (allocno); cp != NULL; cp = next_cp)
1344
	{
1345
	  if (cp->first == allocno)
1346
	    {
1347 1348 1349 1350 1351 1352 1353
	      next_cp = cp->next_first_allocno_copy;
	      another_allocno = cp->second;
	    }
	  else if (cp->second == allocno)
	    {
	      next_cp = cp->next_second_allocno_copy;
	      another_allocno = cp->first;
1354
	    }
1355 1356 1357
	  else
	    gcc_unreachable ();

Vladimir Makarov committed
1358 1359 1360
	  if (another_allocno == from)
	    continue;

Vladimir Makarov committed
1361 1362
	  aclass = ALLOCNO_CLASS (another_allocno);
	  if (! TEST_HARD_REG_BIT (reg_class_contents[aclass],
1363
				   hard_regno)
1364 1365 1366
	      || ALLOCNO_ASSIGNED_P (another_allocno))
	    continue;

1367 1368 1369 1370 1371 1372 1373 1374
	  /* If we have different modes use the smallest one.  It is
	     a sub-register move.  It is hard to predict what LRA
	     will reload (the pseudo or its sub-register) but LRA
	     will try to minimize the data movement.  Also for some
	     register classes bigger modes might be invalid,
	     e.g. DImode for AREG on x86.  For such cases the
	     register move cost will be maximal.  */
	  mode = narrower_subreg_mode (mode, ALLOCNO_MODE (cp->second));
1375
	  ira_init_register_move_cost_if_necessary (mode);
1376
	  
1377
	  cost = (cp->second == allocno
Vladimir Makarov committed
1378 1379
		  ? ira_register_move_cost[mode][rclass][aclass]
		  : ira_register_move_cost[mode][aclass][rclass]);
1380 1381 1382
	  if (decr_p)
	    cost = -cost;

1383 1384 1385 1386 1387 1388 1389 1390 1391
	  update_conflict_cost = update_cost = cp->freq * cost / divisor;

	  if (ALLOCNO_COLOR_DATA (another_allocno) != NULL
	      && (ALLOCNO_COLOR_DATA (allocno)->first_thread_allocno
		  != ALLOCNO_COLOR_DATA (another_allocno)->first_thread_allocno))
	    /* Decrease conflict cost of ANOTHER_ALLOCNO if it is not
	       in the same allocation thread.  */
	    update_conflict_cost /= COST_HOP_DIVISOR;

1392 1393 1394
	  if (update_cost == 0)
	    continue;

1395 1396
	  if (! update_allocno_cost (another_allocno, hard_regno,
				     update_cost, update_conflict_cost))
Vladimir Makarov committed
1397
	    continue;
Vladimir Makarov committed
1398 1399 1400 1401 1402 1403
	  queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR);
	  if (record_p && ALLOCNO_COLOR_DATA (another_allocno) != NULL)
	    ALLOCNO_COLOR_DATA (another_allocno)->update_cost_records
	      = get_update_cost_record (hard_regno, divisor,
					ALLOCNO_COLOR_DATA (another_allocno)
					->update_cost_records);
1404 1405
	}
    }
Vladimir Makarov committed
1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424
  while (get_next_update_cost (&allocno, &from, &divisor));
}

/* Decrease preferred ALLOCNO hard register costs and costs of
   allocnos connected to ALLOCNO through copy.  */
static void
update_costs_from_prefs (ira_allocno_t allocno)
{
  ira_pref_t pref;

  start_update_cost ();
  for (pref = ALLOCNO_PREFS (allocno); pref != NULL; pref = pref->next_pref)
    update_costs_from_allocno (allocno, pref->hard_regno,
			       COST_HOP_DIVISOR, true, true);
}

/* Update (decrease if DECR_P) the cost of allocnos connected to
   ALLOCNO through copies to increase chances to remove some copies as
   the result of subsequent assignment.  ALLOCNO was just assigned to
1425
   a hard register.  Record cost updates if RECORD_P is true.  */
Vladimir Makarov committed
1426
static void
1427
update_costs_from_copies (ira_allocno_t allocno, bool decr_p, bool record_p)
Vladimir Makarov committed
1428 1429 1430 1431 1432 1433
{
  int hard_regno;

  hard_regno = ALLOCNO_HARD_REGNO (allocno);
  ira_assert (hard_regno >= 0 && ALLOCNO_CLASS (allocno) != NO_REGS);
  start_update_cost ();
1434
  update_costs_from_allocno (allocno, hard_regno, 1, decr_p, record_p);
Vladimir Makarov committed
1435 1436
}

1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466
/* Update conflict_allocno_hard_prefs of allocnos conflicting with
   ALLOCNO.  */
static void
update_conflict_allocno_hard_prefs (ira_allocno_t allocno)
{
  int l, nr = ALLOCNO_NUM_OBJECTS (allocno);
  
  for (l = 0; l < nr; l++)
    {
      ira_object_t conflict_obj, obj = ALLOCNO_OBJECT (allocno, l);
      ira_object_conflict_iterator oci;
      
      FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
	{
	  ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
	  allocno_color_data_t conflict_data = ALLOCNO_COLOR_DATA (conflict_a);
	  ira_pref_t pref;

	  if (!(hard_reg_set_intersect_p
		(ALLOCNO_COLOR_DATA (allocno)->profitable_hard_regs,
		 conflict_data->profitable_hard_regs)))
	    continue;
	  for (pref = ALLOCNO_PREFS (allocno);
	       pref != NULL;
	       pref = pref->next_pref)
	    conflict_data->conflict_allocno_hard_prefs += pref->freq;
	}
    }
}

Vladimir Makarov committed
1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486
/* Restore costs of allocnos connected to ALLOCNO by copies as it was
   before updating costs of these allocnos from given allocno.  This
   is a wise thing to do as if given allocno did not get an expected
   hard reg, using smaller cost of the hard reg for allocnos connected
   by copies to given allocno becomes actually misleading.  Free all
   update cost records for ALLOCNO as we don't need them anymore.  */
static void
restore_costs_from_copies (ira_allocno_t allocno)
{
  struct update_cost_record *records, *curr;

  if (ALLOCNO_COLOR_DATA (allocno) == NULL)
    return;
  records = ALLOCNO_COLOR_DATA (allocno)->update_cost_records;
  start_update_cost ();
  for (curr = records; curr != NULL; curr = curr->next)
    update_costs_from_allocno (allocno, curr->hard_regno,
			       curr->divisor, true, false);
  free_update_cost_record_list (records);
  ALLOCNO_COLOR_DATA (allocno)->update_cost_records = NULL;
1487 1488
}

1489
/* This function updates COSTS (decrease if DECR_P) for hard_registers
Vladimir Makarov committed
1490
   of ACLASS by conflict costs of the unassigned allocnos
1491 1492
   connected by copies with allocnos in update_cost_queue.  This
   update increases chances to remove some copies.  */
1493
static void
Vladimir Makarov committed
1494
update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
1495
				  bool decr_p)
1496 1497
{
  int i, cost, class_size, freq, mult, div, divisor;
1498
  int index, hard_regno;
1499 1500
  int *conflict_costs;
  bool cont_p;
Vladimir Makarov committed
1501
  enum reg_class another_aclass;
Vladimir Makarov committed
1502
  ira_allocno_t allocno, another_allocno, from;
1503 1504
  ira_copy_t cp, next_cp;

Vladimir Makarov committed
1505
  while (get_next_update_cost (&allocno, &from, &divisor))
1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519
    for (cp = ALLOCNO_COPIES (allocno); cp != NULL; cp = next_cp)
      {
	if (cp->first == allocno)
	  {
	    next_cp = cp->next_first_allocno_copy;
	    another_allocno = cp->second;
	  }
	else if (cp->second == allocno)
	  {
	    next_cp = cp->next_second_allocno_copy;
	    another_allocno = cp->first;
	  }
	else
	  gcc_unreachable ();
Vladimir Makarov committed
1520 1521 1522 1523

	if (another_allocno == from)
	  continue;

Vladimir Makarov committed
1524 1525
 	another_aclass = ALLOCNO_CLASS (another_allocno);
 	if (! ira_reg_classes_intersect_p[aclass][another_aclass]
1526
	    || ALLOCNO_ASSIGNED_P (another_allocno)
Vladimir Makarov committed
1527
	    || ALLOCNO_COLOR_DATA (another_allocno)->may_be_spilled_p)
1528
	  continue;
Vladimir Makarov committed
1529
	class_size = ira_class_hard_regs_num[another_aclass];
1530 1531
	ira_allocate_and_copy_costs
	  (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno),
Vladimir Makarov committed
1532
	   another_aclass, ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno));
1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
	conflict_costs
	  = ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno);
	if (conflict_costs == NULL)
	  cont_p = true;
	else
	  {
	    mult = cp->freq;
	    freq = ALLOCNO_FREQ (another_allocno);
	    if (freq == 0)
	      freq = 1;
	    div = freq * divisor;
	    cont_p = false;
	    for (i = class_size - 1; i >= 0; i--)
	      {
Vladimir Makarov committed
1547
		hard_regno = ira_class_hard_regs[another_aclass][i];
1548
		ira_assert (hard_regno >= 0);
Vladimir Makarov committed
1549
		index = ira_class_hard_reg_index[aclass][hard_regno];
1550 1551
		if (index < 0)
		  continue;
1552
		cost = (int) (((int64_t) conflict_costs [i] * mult) / div);
1553 1554 1555 1556 1557
		if (cost == 0)
		  continue;
		cont_p = true;
		if (decr_p)
		  cost = -cost;
1558
		costs[index] += cost;
1559 1560 1561 1562 1563 1564 1565 1566
	      }
	  }
	/* Probably 5 hops will be enough.  */
	if (cont_p
	    && divisor <= (COST_HOP_DIVISOR
			   * COST_HOP_DIVISOR
			   * COST_HOP_DIVISOR
			   * COST_HOP_DIVISOR))
Vladimir Makarov committed
1567
	  queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR);
1568
      }
1569 1570
}

1571 1572 1573
/* Set up conflicting (through CONFLICT_REGS) for each object of
   allocno A and the start allocno profitable regs (through
   START_PROFITABLE_REGS).  Remember that the start profitable regs
1574
   exclude hard regs which cannot hold value of mode of allocno A.
1575 1576
   This covers mostly cases when multi-register value should be
   aligned.  */
Vladimir Makarov committed
1577
static inline void
1578 1579 1580
get_conflict_and_start_profitable_regs (ira_allocno_t a, bool retry_p,
					HARD_REG_SET *conflict_regs,
					HARD_REG_SET *start_profitable_regs)
Vladimir Makarov committed
1581 1582 1583 1584 1585 1586 1587 1588
{
  int i, nwords;
  ira_object_t obj;

  nwords = ALLOCNO_NUM_OBJECTS (a);
  for (i = 0; i < nwords; i++)
    {
      obj = ALLOCNO_OBJECT (a, i);
1589
      conflict_regs[i] = OBJECT_TOTAL_CONFLICT_HARD_REGS (obj);
Vladimir Makarov committed
1590
    }
1591
  if (retry_p)
1592 1593 1594 1595
    *start_profitable_regs
      = (reg_class_contents[ALLOCNO_CLASS (a)]
	 &~ (ira_prohibited_class_mode_regs
	     [ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]));
1596
  else
1597
    *start_profitable_regs = ALLOCNO_COLOR_DATA (a)->profitable_hard_regs;
Vladimir Makarov committed
1598 1599
}

1600 1601
/* Return true if HARD_REGNO is ok for assigning to allocno A with
   PROFITABLE_REGS and whose objects have CONFLICT_REGS.  */
Vladimir Makarov committed
1602 1603
static inline bool
check_hard_reg_p (ira_allocno_t a, int hard_regno,
1604
		  HARD_REG_SET *conflict_regs, HARD_REG_SET profitable_regs)
Vladimir Makarov committed
1605 1606
{
  int j, nwords, nregs;
1607
  enum reg_class aclass;
1608
  machine_mode mode;
Vladimir Makarov committed
1609

1610 1611 1612 1613 1614
  aclass = ALLOCNO_CLASS (a);
  mode = ALLOCNO_MODE (a);
  if (TEST_HARD_REG_BIT (ira_prohibited_class_mode_regs[aclass][mode],
			 hard_regno))
    return false;
1615 1616 1617
  /* Checking only profitable hard regs.  */
  if (! TEST_HARD_REG_BIT (profitable_regs, hard_regno))
    return false;
1618
  nregs = hard_regno_nregs (hard_regno, mode);
Vladimir Makarov committed
1619 1620 1621 1622 1623 1624 1625 1626
  nwords = ALLOCNO_NUM_OBJECTS (a);
  for (j = 0; j < nregs; j++)
    {
      int k;
      int set_to_test_start = 0, set_to_test_end = nwords;
      
      if (nregs == nwords)
	{
1627
	  if (REG_WORDS_BIG_ENDIAN)
Vladimir Makarov committed
1628 1629 1630 1631 1632 1633
	    set_to_test_start = nwords - j - 1;
	  else
	    set_to_test_start = j;
	  set_to_test_end = set_to_test_start + 1;
	}
      for (k = set_to_test_start; k < set_to_test_end; k++)
1634
	if (TEST_HARD_REG_BIT (conflict_regs[k], hard_regno + j))
Vladimir Makarov committed
1635 1636 1637 1638 1639 1640
	  break;
      if (k != set_to_test_end)
	break;
    }
  return j == nregs;
}
1641 1642 1643 1644 1645

/* Return number of registers needed to be saved and restored at
   function prologue/epilogue if we allocate HARD_REGNO to hold value
   of MODE.  */
static int
1646
calculate_saved_nregs (int hard_regno, machine_mode mode)
1647 1648 1649 1650 1651
{
  int i;
  int nregs = 0;

  ira_assert (hard_regno >= 0);
1652
  for (i = hard_regno_nregs (hard_regno, mode) - 1; i >= 0; i--)
1653
    if (!allocated_hardreg_p[hard_regno + i]
1654
	&& !crtl->abi->clobbers_full_reg_p (hard_regno + i)
1655 1656 1657 1658
	&& !LOCAL_REGNO (hard_regno + i))
      nregs++;
  return nregs;
}
Vladimir Makarov committed
1659

1660 1661
/* Choose a hard register for allocno A.  If RETRY_P is TRUE, it means
   that the function called from function
Vladimir Makarov committed
1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682
   `ira_reassign_conflict_allocnos' and `allocno_reload_assign'.  In
   this case some allocno data are not defined or updated and we
   should not touch these data.  The function returns true if we
   managed to assign a hard register to the allocno.

   To assign a hard register, first of all we calculate all conflict
   hard registers which can come from conflicting allocnos with
   already assigned hard registers.  After that we find first free
   hard register with the minimal cost.  During hard register cost
   calculation we take conflict hard register costs into account to
   give a chance for conflicting allocnos to get a better hard
   register in the future.

   If the best hard register cost is bigger than cost of memory usage
   for the allocno, we don't assign a hard register to given allocno
   at all.

   If we assign a hard register to the allocno, we update costs of the
   hard register for allocnos connected by copies to improve a chance
   to coalesce insns represented by the copies when we assign hard
   registers to the allocnos connected by the copies.  */
Vladimir Makarov committed
1683
static bool
1684
assign_hard_reg (ira_allocno_t a, bool retry_p)
Vladimir Makarov committed
1685
{
1686
  HARD_REG_SET conflicting_regs[2], profitable_hard_regs;
1687
  int i, j, hard_regno, best_hard_regno, class_size;
1688
  int cost, mem_cost, min_cost, full_cost, min_full_cost, nwords, word;
Vladimir Makarov committed
1689
  int *a_costs;
Vladimir Makarov committed
1690
  enum reg_class aclass;
1691
  machine_mode mode;
Vladimir Makarov committed
1692
  static int costs[FIRST_PSEUDO_REGISTER], full_costs[FIRST_PSEUDO_REGISTER];
1693
  int saved_nregs;
1694 1695
  enum reg_class rclass;
  int add_cost;
Vladimir Makarov committed
1696 1697 1698 1699
#ifdef STACK_REGS
  bool no_stack_reg_p;
#endif

1700
  ira_assert (! ALLOCNO_ASSIGNED_P (a));
1701 1702 1703
  get_conflict_and_start_profitable_regs (a, retry_p,
					  conflicting_regs,
					  &profitable_hard_regs);
Vladimir Makarov committed
1704 1705
  aclass = ALLOCNO_CLASS (a);
  class_size = ira_class_hard_regs_num[aclass];
Vladimir Makarov committed
1706 1707 1708 1709 1710 1711 1712 1713
  best_hard_regno = -1;
  memset (full_costs, 0, sizeof (int) * class_size);
  mem_cost = 0;
  memset (costs, 0, sizeof (int) * class_size);
  memset (full_costs, 0, sizeof (int) * class_size);
#ifdef STACK_REGS
  no_stack_reg_p = false;
#endif
Vladimir Makarov committed
1714 1715
  if (! retry_p)
    start_update_cost ();
1716 1717 1718
  mem_cost += ALLOCNO_UPDATED_MEMORY_COST (a);
  
  ira_allocate_and_copy_costs (&ALLOCNO_UPDATED_HARD_REG_COSTS (a),
Vladimir Makarov committed
1719
			       aclass, ALLOCNO_HARD_REG_COSTS (a));
1720
  a_costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a);
Vladimir Makarov committed
1721
#ifdef STACK_REGS
1722
  no_stack_reg_p = no_stack_reg_p || ALLOCNO_TOTAL_NO_STACK_REG_P (a);
Vladimir Makarov committed
1723
#endif
Vladimir Makarov committed
1724
  cost = ALLOCNO_UPDATED_CLASS_COST (a);
1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735
  for (i = 0; i < class_size; i++)
    if (a_costs != NULL)
      {
	costs[i] += a_costs[i];
	full_costs[i] += a_costs[i];
      }
    else
      {
	costs[i] += cost;
	full_costs[i] += cost;
      }
Vladimir Makarov committed
1736
  nwords = ALLOCNO_NUM_OBJECTS (a);
1737
  curr_allocno_process++;
1738 1739 1740 1741 1742 1743 1744 1745
  for (word = 0; word < nwords; word++)
    {
      ira_object_t conflict_obj;
      ira_object_t obj = ALLOCNO_OBJECT (a, word);
      ira_object_conflict_iterator oci;
      
      /* Take preferences of conflicting allocnos into account.  */
      FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
Vladimir Makarov committed
1746
        {
1747
	  ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
Vladimir Makarov committed
1748
	  enum reg_class conflict_aclass;
1749
	  allocno_color_data_t data = ALLOCNO_COLOR_DATA (conflict_a);
Vladimir Makarov committed
1750

1751 1752
	  /* Reload can give another class so we need to check all
	     allocnos.  */
Vladimir Makarov committed
1753
	  if (!retry_p
1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769
	      && ((!ALLOCNO_ASSIGNED_P (conflict_a)
		   || ALLOCNO_HARD_REGNO (conflict_a) < 0)
		  && !(hard_reg_set_intersect_p
		       (profitable_hard_regs,
			ALLOCNO_COLOR_DATA
			(conflict_a)->profitable_hard_regs))))
	    {
	      /* All conflict allocnos are in consideration bitmap
		 when retry_p is false.  It might change in future and
		 if it happens the assert will be broken.  It means
		 the code should be modified for the new
		 assumptions.  */
	      ira_assert (bitmap_bit_p (consideration_allocno_bitmap,
					ALLOCNO_NUM (conflict_a)));
	      continue;
	    }
Vladimir Makarov committed
1770
	  conflict_aclass = ALLOCNO_CLASS (conflict_a);
1771
	  ira_assert (ira_reg_classes_intersect_p
Vladimir Makarov committed
1772
		      [aclass][conflict_aclass]);
1773
	  if (ALLOCNO_ASSIGNED_P (conflict_a))
1774
	    {
1775 1776
	      hard_regno = ALLOCNO_HARD_REGNO (conflict_a);
	      if (hard_regno >= 0
1777 1778 1779
		  && (ira_hard_reg_set_intersection_p
		      (hard_regno, ALLOCNO_MODE (conflict_a),
		       reg_class_contents[aclass])))
1780
		{
1781
		  int n_objects = ALLOCNO_NUM_OBJECTS (conflict_a);
1782
		  int conflict_nregs;
Vladimir Makarov committed
1783

1784
		  mode = ALLOCNO_MODE (conflict_a);
1785
		  conflict_nregs = hard_regno_nregs (hard_regno, mode);
1786
		  if (conflict_nregs == n_objects && conflict_nregs > 1)
1787
		    {
1788
		      int num = OBJECT_SUBWORD (conflict_obj);
1789

1790
		      if (REG_WORDS_BIG_ENDIAN)
1791 1792 1793 1794 1795
			SET_HARD_REG_BIT (conflicting_regs[word],
					  hard_regno + n_objects - num - 1);
		      else
			SET_HARD_REG_BIT (conflicting_regs[word],
					  hard_regno + num);
1796
		    }
1797
		  else
1798 1799
		    conflicting_regs[word]
		      |= ira_reg_mode_hard_regset[hard_regno][mode];
1800
		  if (hard_reg_set_subset_p (profitable_hard_regs,
1801 1802
					     conflicting_regs[word]))
		    goto fail;
1803 1804
		}
	    }
Vladimir Makarov committed
1805
	  else if (! retry_p
1806 1807 1808 1809
		   && ! ALLOCNO_COLOR_DATA (conflict_a)->may_be_spilled_p
		   /* Don't process the conflict allocno twice.  */
		   && (ALLOCNO_COLOR_DATA (conflict_a)->last_process
		       != curr_allocno_process))
1810 1811 1812
	    {
	      int k, *conflict_costs;
	      
1813 1814
	      ALLOCNO_COLOR_DATA (conflict_a)->last_process
		= curr_allocno_process;
1815 1816
	      ira_allocate_and_copy_costs
		(&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_a),
Vladimir Makarov committed
1817
		 conflict_aclass,
1818 1819 1820 1821 1822 1823
		 ALLOCNO_CONFLICT_HARD_REG_COSTS (conflict_a));
	      conflict_costs
		= ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_a);
	      if (conflict_costs != NULL)
		for (j = class_size - 1; j >= 0; j--)
		  {
Vladimir Makarov committed
1824
		    hard_regno = ira_class_hard_regs[aclass][j];
1825
		    ira_assert (hard_regno >= 0);
Vladimir Makarov committed
1826
		    k = ira_class_hard_reg_index[conflict_aclass][hard_regno];
1827 1828 1829 1830 1831 1832
		    if (k < 0
			   /* If HARD_REGNO is not available for CONFLICT_A,
			      the conflict would be ignored, since HARD_REGNO
			      will never be assigned to CONFLICT_A.  */
			|| !TEST_HARD_REG_BIT (data->profitable_hard_regs,
					       hard_regno))
1833 1834 1835
		      continue;
		    full_costs[j] -= conflict_costs[k];
		  }
Vladimir Makarov committed
1836 1837
	      queue_update_cost (conflict_a, NULL, COST_HOP_DIVISOR);

1838
	    }
1839
	}
Vladimir Makarov committed
1840
    }
Vladimir Makarov committed
1841 1842 1843 1844
  if (! retry_p)
    /* Take into account preferences of allocnos connected by copies to
       the conflict allocnos.  */
    update_conflict_hard_regno_costs (full_costs, aclass, true);
1845

1846 1847
  /* Take preferences of allocnos connected by copies into
     account.  */
Vladimir Makarov committed
1848 1849 1850
  if (! retry_p)
    {
      start_update_cost ();
Vladimir Makarov committed
1851
      queue_update_cost (a, NULL,  COST_HOP_DIVISOR);
Vladimir Makarov committed
1852 1853
      update_conflict_hard_regno_costs (full_costs, aclass, false);
    }
Vladimir Makarov committed
1854 1855 1856 1857 1858
  min_cost = min_full_cost = INT_MAX;
  /* We don't care about giving callee saved registers to allocnos no
     living through calls because call clobbered registers are
     allocated first (it is usual practice to put them first in
     REG_ALLOC_ORDER).  */
Vladimir Makarov committed
1859
  mode = ALLOCNO_MODE (a);
Vladimir Makarov committed
1860 1861
  for (i = 0; i < class_size; i++)
    {
Vladimir Makarov committed
1862
      hard_regno = ira_class_hard_regs[aclass][i];
Vladimir Makarov committed
1863 1864 1865 1866 1867
#ifdef STACK_REGS
      if (no_stack_reg_p
	  && FIRST_STACK_REG <= hard_regno && hard_regno <= LAST_STACK_REG)
	continue;
#endif
Vladimir Makarov committed
1868 1869
      if (! check_hard_reg_p (a, hard_regno,
			      conflicting_regs, profitable_hard_regs))
Vladimir Makarov committed
1870 1871 1872
	continue;
      cost = costs[i];
      full_cost = full_costs[i];
1873
      if (!HONOR_REG_ALLOC_ORDER)
Vladimir Makarov committed
1874
	{
1875 1876 1877 1878 1879 1880 1881
	  if ((saved_nregs = calculate_saved_nregs (hard_regno, mode)) != 0)
	  /* We need to save/restore the hard register in
	     epilogue/prologue.  Therefore we increase the cost.  */
	  {
	    rclass = REGNO_REG_CLASS (hard_regno);
	    add_cost = ((ira_memory_move_cost[mode][rclass][0]
		         + ira_memory_move_cost[mode][rclass][1])
1882 1883
		        * saved_nregs / hard_regno_nregs (hard_regno,
							  mode) - 1);
1884 1885 1886
	    cost += add_cost;
	    full_cost += add_cost;
	  }
Vladimir Makarov committed
1887 1888 1889 1890 1891 1892 1893 1894 1895 1896
	}
      if (min_cost > cost)
	min_cost = cost;
      if (min_full_cost > full_cost)
	{
	  min_full_cost = full_cost;
	  best_hard_regno = hard_regno;
	  ira_assert (hard_regno >= 0);
	}
    }
1897 1898 1899 1900
  if (min_full_cost > mem_cost
      /* Do not spill static chain pointer pseudo when non-local goto
	 is used.  */
      && ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
Vladimir Makarov committed
1901 1902 1903 1904 1905 1906 1907 1908
    {
      if (! retry_p && internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
	fprintf (ira_dump_file, "(memory is more profitable %d vs %d) ",
		 mem_cost, min_full_cost);
      best_hard_regno = -1;
    }
 fail:
  if (best_hard_regno >= 0)
1909
    {
1910
      for (i = hard_regno_nregs (best_hard_regno, mode) - 1; i >= 0; i--)
1911
	allocated_hardreg_p[best_hard_regno + i] = true;
1912
    }
1913 1914
  if (! retry_p)
    restore_costs_from_copies (a);
1915 1916 1917
  ALLOCNO_HARD_REGNO (a) = best_hard_regno;
  ALLOCNO_ASSIGNED_P (a) = true;
  if (best_hard_regno >= 0)
1918
    update_costs_from_copies (a, true, ! retry_p);
Vladimir Makarov committed
1919
  ira_assert (ALLOCNO_CLASS (a) == aclass);
1920
  /* We don't need updated costs anymore.  */
1921
  ira_free_allocno_updated_costs (a);
Vladimir Makarov committed
1922 1923 1924 1925 1926
  return best_hard_regno >= 0;
}



1927 1928 1929
/* An array used to sort copies.  */
static ira_copy_t *sorted_copies;

1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941
/* If allocno A is a cap, return non-cap allocno from which A is
   created.  Otherwise, return A.  */
static ira_allocno_t
get_cap_member (ira_allocno_t a)
{
  ira_allocno_t member;
  
  while ((member = ALLOCNO_CAP_MEMBER (a)) != NULL)
    a = member;
  return a;
}

1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960
/* Return TRUE if live ranges of allocnos A1 and A2 intersect.  It is
   used to find a conflict for new allocnos or allocnos with the
   different allocno classes.  */
static bool
allocnos_conflict_by_live_ranges_p (ira_allocno_t a1, ira_allocno_t a2)
{
  rtx reg1, reg2;
  int i, j;
  int n1 = ALLOCNO_NUM_OBJECTS (a1);
  int n2 = ALLOCNO_NUM_OBJECTS (a2);

  if (a1 == a2)
    return false;
  reg1 = regno_reg_rtx[ALLOCNO_REGNO (a1)];
  reg2 = regno_reg_rtx[ALLOCNO_REGNO (a2)];
  if (reg1 != NULL && reg2 != NULL
      && ORIGINAL_REGNO (reg1) == ORIGINAL_REGNO (reg2))
    return false;

1961 1962 1963 1964
  /* We don't keep live ranges for caps because they can be quite big.
     Use ranges of non-cap allocno from which caps are created.  */
  a1 = get_cap_member (a1);
  a2 = get_cap_member (a2);
1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993
  for (i = 0; i < n1; i++)
    {
      ira_object_t c1 = ALLOCNO_OBJECT (a1, i);

      for (j = 0; j < n2; j++)
	{
	  ira_object_t c2 = ALLOCNO_OBJECT (a2, j);

	  if (ira_live_ranges_intersect_p (OBJECT_LIVE_RANGES (c1),
					   OBJECT_LIVE_RANGES (c2)))
	    return true;
	}
    }
  return false;
}

/* The function is used to sort copies according to their execution
   frequencies.  */
static int
copy_freq_compare_func (const void *v1p, const void *v2p)
{
  ira_copy_t cp1 = *(const ira_copy_t *) v1p, cp2 = *(const ira_copy_t *) v2p;
  int pri1, pri2;

  pri1 = cp1->freq;
  pri2 = cp2->freq;
  if (pri2 - pri1)
    return pri2 - pri1;

Kito Cheng committed
1994
  /* If frequencies are equal, sort by copies, so that the results of
1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048
     qsort leave nothing to chance.  */
  return cp1->num - cp2->num;
}



/* Return true if any allocno from thread of A1 conflicts with any
   allocno from thread A2.  */
static bool
allocno_thread_conflict_p (ira_allocno_t a1, ira_allocno_t a2)
{
  ira_allocno_t a, conflict_a;

  for (a = ALLOCNO_COLOR_DATA (a2)->next_thread_allocno;;
       a = ALLOCNO_COLOR_DATA (a)->next_thread_allocno)
    {
      for (conflict_a = ALLOCNO_COLOR_DATA (a1)->next_thread_allocno;;
	   conflict_a = ALLOCNO_COLOR_DATA (conflict_a)->next_thread_allocno)
	{
	  if (allocnos_conflict_by_live_ranges_p (a, conflict_a))
	    return true;
	  if (conflict_a == a1)
	    break;
	}
      if (a == a2)
	break;
    }
  return false;
}

/* Merge two threads given correspondingly by their first allocnos T1
   and T2 (more accurately merging T2 into T1).  */
static void
merge_threads (ira_allocno_t t1, ira_allocno_t t2)
{
  ira_allocno_t a, next, last;

  gcc_assert (t1 != t2
	      && ALLOCNO_COLOR_DATA (t1)->first_thread_allocno == t1
	      && ALLOCNO_COLOR_DATA (t2)->first_thread_allocno == t2);
  for (last = t2, a = ALLOCNO_COLOR_DATA (t2)->next_thread_allocno;;
       a = ALLOCNO_COLOR_DATA (a)->next_thread_allocno)
    {
      ALLOCNO_COLOR_DATA (a)->first_thread_allocno = t1;
      if (a == t2)
	break;
      last = a;
    }
  next = ALLOCNO_COLOR_DATA (t1)->next_thread_allocno;
  ALLOCNO_COLOR_DATA (t1)->next_thread_allocno = t2;
  ALLOCNO_COLOR_DATA (last)->next_thread_allocno = next;
  ALLOCNO_COLOR_DATA (t1)->thread_freq += ALLOCNO_COLOR_DATA (t2)->thread_freq;
}

Kito Cheng committed
2049
/* Create threads by processing CP_NUM copies from sorted copies.  We
2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188
   process the most expensive copies first.  */
static void
form_threads_from_copies (int cp_num)
{
  ira_allocno_t a, thread1, thread2;
  ira_copy_t cp;
  int i, n;

  qsort (sorted_copies, cp_num, sizeof (ira_copy_t), copy_freq_compare_func);
  /* Form threads processing copies, most frequently executed
     first.  */
  for (; cp_num != 0;)
    {
      for (i = 0; i < cp_num; i++)
	{
	  cp = sorted_copies[i];
	  thread1 = ALLOCNO_COLOR_DATA (cp->first)->first_thread_allocno;
	  thread2 = ALLOCNO_COLOR_DATA (cp->second)->first_thread_allocno;
	  if (thread1 == thread2)
	    continue;
	  if (! allocno_thread_conflict_p (thread1, thread2))
	    {
	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
		fprintf
		  (ira_dump_file,
		   "      Forming thread by copy %d:a%dr%d-a%dr%d (freq=%d):\n",
		   cp->num, ALLOCNO_NUM (cp->first), ALLOCNO_REGNO (cp->first),
		   ALLOCNO_NUM (cp->second), ALLOCNO_REGNO (cp->second),
		   cp->freq);
	      merge_threads (thread1, thread2);
	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
		{
		  thread1 = ALLOCNO_COLOR_DATA (thread1)->first_thread_allocno;
		  fprintf (ira_dump_file, "        Result (freq=%d): a%dr%d(%d)",
			   ALLOCNO_COLOR_DATA (thread1)->thread_freq,
			   ALLOCNO_NUM (thread1), ALLOCNO_REGNO (thread1),
			   ALLOCNO_FREQ (thread1));
		  for (a = ALLOCNO_COLOR_DATA (thread1)->next_thread_allocno;
		       a != thread1;
		       a = ALLOCNO_COLOR_DATA (a)->next_thread_allocno)
		    fprintf (ira_dump_file, " a%dr%d(%d)",
			     ALLOCNO_NUM (a), ALLOCNO_REGNO (a),
			     ALLOCNO_FREQ (a));
		  fprintf (ira_dump_file, "\n");
		}
	      i++;
	      break;
	    }
	}
      /* Collect the rest of copies.  */
      for (n = 0; i < cp_num; i++)
	{
	  cp = sorted_copies[i];
	  if (ALLOCNO_COLOR_DATA (cp->first)->first_thread_allocno
	      != ALLOCNO_COLOR_DATA (cp->second)->first_thread_allocno)
	    sorted_copies[n++] = cp;
	}
      cp_num = n;
    }
}

/* Create threads by processing copies of all alocnos from BUCKET.  We
   process the most expensive copies first.  */
static void
form_threads_from_bucket (ira_allocno_t bucket)
{
  ira_allocno_t a;
  ira_copy_t cp, next_cp;
  int cp_num = 0;

  for (a = bucket; a != NULL; a = ALLOCNO_COLOR_DATA (a)->next_bucket_allocno)
    {
      for (cp = ALLOCNO_COPIES (a); cp != NULL; cp = next_cp)
	{
	  if (cp->first == a)
	    {
	      next_cp = cp->next_first_allocno_copy;
	      sorted_copies[cp_num++] = cp;
	    }
	  else if (cp->second == a)
	    next_cp = cp->next_second_allocno_copy;
	  else
	    gcc_unreachable ();
	}
    }
  form_threads_from_copies (cp_num);
}

/* Create threads by processing copies of colorable allocno A.  We
   process most expensive copies first.  */
static void
form_threads_from_colorable_allocno (ira_allocno_t a)
{
  ira_allocno_t another_a;
  ira_copy_t cp, next_cp;
  int cp_num = 0;

  for (cp = ALLOCNO_COPIES (a); cp != NULL; cp = next_cp)
    {
      if (cp->first == a)
	{
	  next_cp = cp->next_first_allocno_copy;
	  another_a = cp->second;
	}
      else if (cp->second == a)
	{
	  next_cp = cp->next_second_allocno_copy;
	  another_a = cp->first;
	}
      else
	gcc_unreachable ();
      if ((! ALLOCNO_COLOR_DATA (another_a)->in_graph_p
	   && !ALLOCNO_COLOR_DATA (another_a)->may_be_spilled_p)
	   || ALLOCNO_COLOR_DATA (another_a)->colorable_p)
	sorted_copies[cp_num++] = cp;
    }
  form_threads_from_copies (cp_num);
}

/* Form initial threads which contain only one allocno.  */
static void
init_allocno_threads (void)
{
  ira_allocno_t a;
  unsigned int j;
  bitmap_iterator bi;

  EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, j, bi)
    {
      a = ira_allocnos[j];
      /* Set up initial thread data: */
      ALLOCNO_COLOR_DATA (a)->first_thread_allocno
	= ALLOCNO_COLOR_DATA (a)->next_thread_allocno = a;
      ALLOCNO_COLOR_DATA (a)->thread_freq = ALLOCNO_FREQ (a);
    }
}



Vladimir Makarov committed
2189 2190 2191 2192 2193 2194 2195 2196 2197
/* This page contains the allocator based on the Chaitin-Briggs algorithm.  */

/* Bucket of allocnos that can colored currently without spilling.  */
static ira_allocno_t colorable_allocno_bucket;

/* Bucket of allocnos that might be not colored currently without
   spilling.  */
static ira_allocno_t uncolorable_allocno_bucket;

Vladimir Makarov committed
2198 2199
/* The current number of allocnos in the uncolorable_bucket.  */
static int uncolorable_allocnos_num;
Vladimir Makarov committed
2200

2201 2202
/* Return the current spill priority of allocno A.  The less the
   number, the more preferable the allocno for spilling.  */
Vladimir Makarov committed
2203
static inline int
2204 2205
allocno_spill_priority (ira_allocno_t a)
{
Vladimir Makarov committed
2206 2207 2208 2209 2210
  allocno_color_data_t data = ALLOCNO_COLOR_DATA (a);

  return (data->temp
	  / (ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a)
	     * ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]
2211 2212 2213
	     + 1));
}

Vladimir Makarov committed
2214
/* Add allocno A to bucket *BUCKET_PTR.  A should be not in a bucket
Vladimir Makarov committed
2215 2216
   before the call.  */
static void
Vladimir Makarov committed
2217
add_allocno_to_bucket (ira_allocno_t a, ira_allocno_t *bucket_ptr)
Vladimir Makarov committed
2218
{
Vladimir Makarov committed
2219 2220
  ira_allocno_t first_a;
  allocno_color_data_t data;
Vladimir Makarov committed
2221 2222

  if (bucket_ptr == &uncolorable_allocno_bucket
Vladimir Makarov committed
2223
      && ALLOCNO_CLASS (a) != NO_REGS)
Vladimir Makarov committed
2224
    {
Vladimir Makarov committed
2225 2226
      uncolorable_allocnos_num++;
      ira_assert (uncolorable_allocnos_num > 0);
Vladimir Makarov committed
2227
    }
Vladimir Makarov committed
2228 2229 2230 2231 2232 2233 2234
  first_a = *bucket_ptr;
  data = ALLOCNO_COLOR_DATA (a);
  data->next_bucket_allocno = first_a;
  data->prev_bucket_allocno = NULL;
  if (first_a != NULL)
    ALLOCNO_COLOR_DATA (first_a)->prev_bucket_allocno = a;
  *bucket_ptr = a;
Vladimir Makarov committed
2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248
}

/* Compare two allocnos to define which allocno should be pushed first
   into the coloring stack.  If the return is a negative number, the
   allocno given by the first parameter will be pushed first.  In this
   case such allocno has less priority than the second one and the
   hard register will be assigned to it after assignment to the second
   one.  As the result of such assignment order, the second allocno
   has a better chance to get the best hard register.  */
static int
bucket_allocno_compare_func (const void *v1p, const void *v2p)
{
  ira_allocno_t a1 = *(const ira_allocno_t *) v1p;
  ira_allocno_t a2 = *(const ira_allocno_t *) v2p;
2249
  int diff, freq1, freq2, a1_num, a2_num, pref1, pref2;
2250 2251
  ira_allocno_t t1 = ALLOCNO_COLOR_DATA (a1)->first_thread_allocno;
  ira_allocno_t t2 = ALLOCNO_COLOR_DATA (a2)->first_thread_allocno;
2252 2253
  int cl1 = ALLOCNO_CLASS (a1), cl2 = ALLOCNO_CLASS (a2);

2254 2255 2256 2257 2258 2259 2260 2261
  freq1 = ALLOCNO_COLOR_DATA (t1)->thread_freq;
  freq2 = ALLOCNO_COLOR_DATA (t2)->thread_freq;
  if ((diff = freq1 - freq2) != 0)
    return diff;
  
  if ((diff = ALLOCNO_NUM (t2) - ALLOCNO_NUM (t1)) != 0)
    return diff;

2262 2263 2264
  /* Push pseudos requiring less hard registers first.  It means that
     we will assign pseudos requiring more hard registers first
     avoiding creation small holes in free hard register file into
2265
     which the pseudos requiring more hard registers cannot fit.  */
2266 2267
  if ((diff = (ira_reg_class_max_nregs[cl1][ALLOCNO_MODE (a1)]
	       - ira_reg_class_max_nregs[cl2][ALLOCNO_MODE (a2)])) != 0)
Vladimir Makarov committed
2268
    return diff;
2269 2270 2271 2272

  freq1 = ALLOCNO_FREQ (a1);
  freq2 = ALLOCNO_FREQ (a2);
  if ((diff = freq1 - freq2) != 0)
Vladimir Makarov committed
2273
    return diff;
2274

Vladimir Makarov committed
2275 2276 2277
  a1_num = ALLOCNO_COLOR_DATA (a1)->available_regs_num;
  a2_num = ALLOCNO_COLOR_DATA (a2)->available_regs_num;
  if ((diff = a2_num - a1_num) != 0)
2278
    return diff;
2279 2280 2281 2282 2283
  /* Push allocnos with minimal conflict_allocno_hard_prefs first.  */
  pref1 = ALLOCNO_COLOR_DATA (a1)->conflict_allocno_hard_prefs;
  pref2 = ALLOCNO_COLOR_DATA (a2)->conflict_allocno_hard_prefs;
  if ((diff = pref1 - pref2) != 0)
    return diff;
Vladimir Makarov committed
2284 2285 2286 2287 2288 2289
  return ALLOCNO_NUM (a2) - ALLOCNO_NUM (a1);
}

/* Sort bucket *BUCKET_PTR and return the result through
   BUCKET_PTR.  */
static void
Vladimir Makarov committed
2290 2291
sort_bucket (ira_allocno_t *bucket_ptr,
	     int (*compare_func) (const void *, const void *))
Vladimir Makarov committed
2292 2293 2294 2295
{
  ira_allocno_t a, head;
  int n;

Vladimir Makarov committed
2296 2297 2298
  for (n = 0, a = *bucket_ptr;
       a != NULL;
       a = ALLOCNO_COLOR_DATA (a)->next_bucket_allocno)
Vladimir Makarov committed
2299 2300 2301
    sorted_allocnos[n++] = a;
  if (n <= 1)
    return;
Vladimir Makarov committed
2302
  qsort (sorted_allocnos, n, sizeof (ira_allocno_t), compare_func);
Vladimir Makarov committed
2303 2304 2305 2306
  head = NULL;
  for (n--; n >= 0; n--)
    {
      a = sorted_allocnos[n];
Vladimir Makarov committed
2307 2308
      ALLOCNO_COLOR_DATA (a)->next_bucket_allocno = head;
      ALLOCNO_COLOR_DATA (a)->prev_bucket_allocno = NULL;
Vladimir Makarov committed
2309
      if (head != NULL)
Vladimir Makarov committed
2310
	ALLOCNO_COLOR_DATA (head)->prev_bucket_allocno = a;
Vladimir Makarov committed
2311 2312 2313 2314 2315
      head = a;
    }
  *bucket_ptr = head;
}

2316
/* Add ALLOCNO to colorable bucket maintaining the order according
Vladimir Makarov committed
2317 2318 2319
   their priority.  ALLOCNO should be not in a bucket before the
   call.  */
static void
2320
add_allocno_to_ordered_colorable_bucket (ira_allocno_t allocno)
Vladimir Makarov committed
2321 2322 2323
{
  ira_allocno_t before, after;

2324 2325
  form_threads_from_colorable_allocno (allocno);
  for (before = colorable_allocno_bucket, after = NULL;
Vladimir Makarov committed
2326
       before != NULL;
Vladimir Makarov committed
2327 2328
       after = before,
	 before = ALLOCNO_COLOR_DATA (before)->next_bucket_allocno)
Vladimir Makarov committed
2329 2330
    if (bucket_allocno_compare_func (&allocno, &before) < 0)
      break;
Vladimir Makarov committed
2331 2332
  ALLOCNO_COLOR_DATA (allocno)->next_bucket_allocno = before;
  ALLOCNO_COLOR_DATA (allocno)->prev_bucket_allocno = after;
Vladimir Makarov committed
2333
  if (after == NULL)
2334
    colorable_allocno_bucket = allocno;
Vladimir Makarov committed
2335
  else
Vladimir Makarov committed
2336
    ALLOCNO_COLOR_DATA (after)->next_bucket_allocno = allocno;
Vladimir Makarov committed
2337
  if (before != NULL)
Vladimir Makarov committed
2338
    ALLOCNO_COLOR_DATA (before)->prev_bucket_allocno = allocno;
Vladimir Makarov committed
2339 2340 2341 2342 2343 2344 2345 2346 2347 2348
}

/* Delete ALLOCNO from bucket *BUCKET_PTR.  It should be there before
   the call.  */
static void
delete_allocno_from_bucket (ira_allocno_t allocno, ira_allocno_t *bucket_ptr)
{
  ira_allocno_t prev_allocno, next_allocno;

  if (bucket_ptr == &uncolorable_allocno_bucket
Vladimir Makarov committed
2349
      && ALLOCNO_CLASS (allocno) != NO_REGS)
Vladimir Makarov committed
2350
    {
Vladimir Makarov committed
2351 2352
      uncolorable_allocnos_num--;
      ira_assert (uncolorable_allocnos_num >= 0);
Vladimir Makarov committed
2353
    }
Vladimir Makarov committed
2354 2355
  prev_allocno = ALLOCNO_COLOR_DATA (allocno)->prev_bucket_allocno;
  next_allocno = ALLOCNO_COLOR_DATA (allocno)->next_bucket_allocno;
Vladimir Makarov committed
2356
  if (prev_allocno != NULL)
Vladimir Makarov committed
2357
    ALLOCNO_COLOR_DATA (prev_allocno)->next_bucket_allocno = next_allocno;
Vladimir Makarov committed
2358 2359 2360 2361 2362 2363
  else
    {
      ira_assert (*bucket_ptr == allocno);
      *bucket_ptr = next_allocno;
    }
  if (next_allocno != NULL)
Vladimir Makarov committed
2364
    ALLOCNO_COLOR_DATA (next_allocno)->prev_bucket_allocno = prev_allocno;
Vladimir Makarov committed
2365 2366
}

2367
/* Put allocno A onto the coloring stack without removing it from its
Vladimir Makarov committed
2368 2369
   bucket.  Pushing allocno to the coloring stack can result in moving
   conflicting allocnos from the uncolorable bucket to the colorable
2370 2371
   one.  Update conflict_allocno_hard_prefs of the conflicting
   allocnos which are not on stack yet.  */
Vladimir Makarov committed
2372
static void
2373
push_allocno_to_stack (ira_allocno_t a)
Vladimir Makarov committed
2374
{
Vladimir Makarov committed
2375 2376 2377 2378 2379 2380
  enum reg_class aclass;
  allocno_color_data_t data, conflict_data;
  int size, i, n = ALLOCNO_NUM_OBJECTS (a);
    
  data = ALLOCNO_COLOR_DATA (a);
  data->in_graph_p = false;
2381
  allocno_stack_vec.safe_push (a);
Vladimir Makarov committed
2382 2383
  aclass = ALLOCNO_CLASS (a);
  if (aclass == NO_REGS)
Vladimir Makarov committed
2384
    return;
Vladimir Makarov committed
2385 2386
  size = ira_reg_class_max_nregs[aclass][ALLOCNO_MODE (a)];
  if (n > 1)
2387 2388
    {
      /* We will deal with the subwords individually.  */
2389
      gcc_assert (size == ALLOCNO_NUM_OBJECTS (a));
2390 2391
      size = 1;
    }
2392
  for (i = 0; i < n; i++)
Vladimir Makarov committed
2393
    {
2394 2395 2396 2397 2398
      ira_object_t obj = ALLOCNO_OBJECT (a, i);
      ira_object_t conflict_obj;
      ira_object_conflict_iterator oci;
      
      FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
2399
	{
2400
	  ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
2401 2402
	  ira_pref_t pref;

Vladimir Makarov committed
2403
	  conflict_data = ALLOCNO_COLOR_DATA (conflict_a);
2404
	  if (! conflict_data->in_graph_p
Vladimir Makarov committed
2405 2406
	      || ALLOCNO_ASSIGNED_P (conflict_a)
	      || !(hard_reg_set_intersect_p
2407 2408
		   (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs,
		    conflict_data->profitable_hard_regs)))
2409
	    continue;
2410 2411 2412 2413
	  for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = pref->next_pref)
	    conflict_data->conflict_allocno_hard_prefs -= pref->freq;
	  if (conflict_data->colorable_p)
	    continue;
Vladimir Makarov committed
2414 2415
	  ira_assert (bitmap_bit_p (coloring_allocno_bitmap,
				    ALLOCNO_NUM (conflict_a)));
2416
	  if (update_left_conflict_sizes_p (conflict_a, a, size))
2417 2418
	    {
	      delete_allocno_from_bucket
2419
		(conflict_a, &uncolorable_allocno_bucket);
2420
	      add_allocno_to_ordered_colorable_bucket (conflict_a);
Vladimir Makarov committed
2421 2422 2423 2424 2425 2426
	      if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
		{
		  fprintf (ira_dump_file, "        Making");
		  ira_print_expanded_allocno (conflict_a);
		  fprintf (ira_dump_file, " colorable\n");
		}
2427
	    }
Vladimir Makarov committed
2428
	  
2429
	}
Vladimir Makarov committed
2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444
    }
}

/* Put ALLOCNO onto the coloring stack and remove it from its bucket.
   The allocno is in the colorable bucket if COLORABLE_P is TRUE.  */
static void
remove_allocno_from_bucket_and_push (ira_allocno_t allocno, bool colorable_p)
{
  if (colorable_p)
    delete_allocno_from_bucket (allocno, &colorable_allocno_bucket);
  else
    delete_allocno_from_bucket (allocno, &uncolorable_allocno_bucket);
  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
    {
      fprintf (ira_dump_file, "      Pushing");
2445
      ira_print_expanded_allocno (allocno);
2446
      if (colorable_p)
Vladimir Makarov committed
2447 2448
	fprintf (ira_dump_file, "(cost %d)\n",
		 ALLOCNO_COLOR_DATA (allocno)->temp);
2449 2450 2451
      else
	fprintf (ira_dump_file, "(potential spill: %spri=%d, cost=%d)\n",
		 ALLOCNO_BAD_SPILL_P (allocno) ? "bad spill, " : "",
Vladimir Makarov committed
2452 2453 2454
		 allocno_spill_priority (allocno),
		 ALLOCNO_COLOR_DATA (allocno)->temp);
    }
Vladimir Makarov committed
2455
  if (! colorable_p)
Vladimir Makarov committed
2456
    ALLOCNO_COLOR_DATA (allocno)->may_be_spilled_p = true;
2457
  push_allocno_to_stack (allocno);
Vladimir Makarov committed
2458 2459 2460 2461 2462 2463
}

/* Put all allocnos from colorable bucket onto the coloring stack.  */
static void
push_only_colorable (void)
{
2464
  form_threads_from_bucket (colorable_allocno_bucket);
Vladimir Makarov committed
2465
  sort_bucket (&colorable_allocno_bucket, bucket_allocno_compare_func);
Vladimir Makarov committed
2466 2467 2468 2469 2470
  for (;colorable_allocno_bucket != NULL;)
    remove_allocno_from_bucket_and_push (colorable_allocno_bucket, true);
}

/* Return the frequency of exit edges (if EXIT_P) or entry from/to the
H.J. Lu committed
2471
   loop given by its LOOP_NODE.  */
Vladimir Makarov committed
2472 2473 2474 2475 2476 2477
int
ira_loop_edge_freq (ira_loop_tree_node_t loop_node, int regno, bool exit_p)
{
  int freq, i;
  edge_iterator ei;
  edge e;
2478
  vec<edge> edges;
Vladimir Makarov committed
2479

2480
  ira_assert (current_loops != NULL && loop_node->loop != NULL
Vladimir Makarov committed
2481 2482 2483 2484 2485 2486 2487
	      && (regno < 0 || regno >= FIRST_PSEUDO_REGISTER));
  freq = 0;
  if (! exit_p)
    {
      FOR_EACH_EDGE (e, ei, loop_node->loop->header->preds)
	if (e->src != loop_node->loop->latch
	    && (regno < 0
2488 2489
		|| (bitmap_bit_p (df_get_live_out (e->src), regno)
		    && bitmap_bit_p (df_get_live_in (e->dest), regno))))
Vladimir Makarov committed
2490 2491 2492 2493 2494
	  freq += EDGE_FREQUENCY (e);
    }
  else
    {
      edges = get_loop_exit_edges (loop_node->loop);
2495
      FOR_EACH_VEC_ELT (edges, i, e)
Vladimir Makarov committed
2496
	if (regno < 0
2497 2498
	    || (bitmap_bit_p (df_get_live_out (e->src), regno)
		&& bitmap_bit_p (df_get_live_in (e->dest), regno)))
Vladimir Makarov committed
2499
	  freq += EDGE_FREQUENCY (e);
2500
      edges.release ();
Vladimir Makarov committed
2501 2502 2503 2504 2505 2506 2507 2508 2509 2510
    }

  return REG_FREQ_FROM_EDGE_FREQ (freq);
}

/* Calculate and return the cost of putting allocno A into memory.  */
static int
calculate_allocno_spill_cost (ira_allocno_t a)
{
  int regno, cost;
2511
  machine_mode mode;
Vladimir Makarov committed
2512 2513 2514 2515 2516
  enum reg_class rclass;
  ira_allocno_t parent_allocno;
  ira_loop_tree_node_t parent_node, loop_node;

  regno = ALLOCNO_REGNO (a);
Vladimir Makarov committed
2517
  cost = ALLOCNO_UPDATED_MEMORY_COST (a) - ALLOCNO_UPDATED_CLASS_COST (a);
Vladimir Makarov committed
2518 2519 2520 2521 2522 2523 2524 2525
  if (ALLOCNO_CAP (a) != NULL)
    return cost;
  loop_node = ALLOCNO_LOOP_TREE_NODE (a);
  if ((parent_node = loop_node->parent) == NULL)
    return cost;
  if ((parent_allocno = parent_node->regno_allocno_map[regno]) == NULL)
    return cost;
  mode = ALLOCNO_MODE (a);
Vladimir Makarov committed
2526
  rclass = ALLOCNO_CLASS (a);
Vladimir Makarov committed
2527 2528 2529 2530 2531 2532
  if (ALLOCNO_HARD_REGNO (parent_allocno) < 0)
    cost -= (ira_memory_move_cost[mode][rclass][0]
	     * ira_loop_edge_freq (loop_node, regno, true)
	     + ira_memory_move_cost[mode][rclass][1]
	     * ira_loop_edge_freq (loop_node, regno, false));
  else
Vladimir Makarov committed
2533 2534 2535 2536 2537 2538 2539 2540 2541 2542
    {
      ira_init_register_move_cost_if_necessary (mode);
      cost += ((ira_memory_move_cost[mode][rclass][1]
		* ira_loop_edge_freq (loop_node, regno, true)
		+ ira_memory_move_cost[mode][rclass][0]
		* ira_loop_edge_freq (loop_node, regno, false))
	       - (ira_register_move_cost[mode][rclass][rclass]
		  * (ira_loop_edge_freq (loop_node, regno, false)
		     + ira_loop_edge_freq (loop_node, regno, true))));
    }
Vladimir Makarov committed
2543 2544 2545
  return cost;
}

Vladimir Makarov committed
2546 2547 2548
/* Used for sorting allocnos for spilling.  */
static inline int
allocno_spill_priority_compare (ira_allocno_t a1, ira_allocno_t a2)
Vladimir Makarov committed
2549 2550
{
  int pri1, pri2, diff;
H.J. Lu committed
2551

2552 2553 2554 2555 2556 2557
  /* Avoid spilling static chain pointer pseudo when non-local goto is
     used.  */
  if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a1)))
    return 1;
  else if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a2)))
    return -1;
Vladimir Makarov committed
2558 2559 2560 2561 2562 2563
  if (ALLOCNO_BAD_SPILL_P (a1) && ! ALLOCNO_BAD_SPILL_P (a2))
    return 1;
  if (ALLOCNO_BAD_SPILL_P (a2) && ! ALLOCNO_BAD_SPILL_P (a1))
    return -1;
  pri1 = allocno_spill_priority (a1);
  pri2 = allocno_spill_priority (a2);
Vladimir Makarov committed
2564 2565
  if ((diff = pri1 - pri2) != 0)
    return diff;
Vladimir Makarov committed
2566 2567
  if ((diff
       = ALLOCNO_COLOR_DATA (a1)->temp - ALLOCNO_COLOR_DATA (a2)->temp) != 0)
Vladimir Makarov committed
2568 2569 2570 2571
    return diff;
  return ALLOCNO_NUM (a1) - ALLOCNO_NUM (a2);
}

Vladimir Makarov committed
2572 2573 2574
/* Used for sorting allocnos for spilling.  */
static int
allocno_spill_sort_compare (const void *v1p, const void *v2p)
2575
{
Vladimir Makarov committed
2576 2577
  ira_allocno_t p1 = *(const ira_allocno_t *) v1p;
  ira_allocno_t p2 = *(const ira_allocno_t *) v2p;
2578

Vladimir Makarov committed
2579
  return allocno_spill_priority_compare (p1, p2);
Vladimir Makarov committed
2580 2581 2582
}

/* Push allocnos to the coloring stack.  The order of allocnos in the
Vladimir Makarov committed
2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608
   stack defines the order for the subsequent coloring.  */
static void
push_allocnos_to_stack (void)
{
  ira_allocno_t a;
  int cost;

  /* Calculate uncolorable allocno spill costs.  */
  for (a = uncolorable_allocno_bucket;
       a != NULL;
       a = ALLOCNO_COLOR_DATA (a)->next_bucket_allocno)
    if (ALLOCNO_CLASS (a) != NO_REGS)
      {
	cost = calculate_allocno_spill_cost (a);
	/* ??? Remove cost of copies between the coalesced
	   allocnos.  */
	ALLOCNO_COLOR_DATA (a)->temp = cost;
      }
  sort_bucket (&uncolorable_allocno_bucket, allocno_spill_sort_compare);
  for (;;)
    {
      push_only_colorable ();
      a = uncolorable_allocno_bucket;
      if (a == NULL)
	break;
      remove_allocno_from_bucket_and_push (a, false);
Vladimir Makarov committed
2609 2610 2611
    }
  ira_assert (colorable_allocno_bucket == NULL
	      && uncolorable_allocno_bucket == NULL);
Vladimir Makarov committed
2612
  ira_assert (uncolorable_allocnos_num == 0);
Vladimir Makarov committed
2613 2614 2615 2616 2617 2618 2619 2620
}

/* Pop the coloring stack and assign hard registers to the popped
   allocnos.  */
static void
pop_allocnos_from_stack (void)
{
  ira_allocno_t allocno;
Vladimir Makarov committed
2621
  enum reg_class aclass;
Vladimir Makarov committed
2622

2623
  for (;allocno_stack_vec.length () != 0;)
Vladimir Makarov committed
2624
    {
2625
      allocno = allocno_stack_vec.pop ();
Vladimir Makarov committed
2626
      aclass = ALLOCNO_CLASS (allocno);
Vladimir Makarov committed
2627 2628 2629
      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
	{
	  fprintf (ira_dump_file, "      Popping");
2630
	  ira_print_expanded_allocno (allocno);
Vladimir Makarov committed
2631 2632
	  fprintf (ira_dump_file, "  -- ");
	}
Vladimir Makarov committed
2633
      if (aclass == NO_REGS)
Vladimir Makarov committed
2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651
	{
	  ALLOCNO_HARD_REGNO (allocno) = -1;
	  ALLOCNO_ASSIGNED_P (allocno) = true;
	  ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (allocno) == NULL);
	  ira_assert
	    (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno) == NULL);
	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
	    fprintf (ira_dump_file, "assign memory\n");
	}
      else if (assign_hard_reg (allocno, false))
	{
	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
	    fprintf (ira_dump_file, "assign reg %d\n",
		     ALLOCNO_HARD_REGNO (allocno));
	}
      else if (ALLOCNO_ASSIGNED_P (allocno))
	{
	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
Vladimir Makarov committed
2652 2653 2654
	    fprintf (ira_dump_file, "spill%s\n",
		     ALLOCNO_COLOR_DATA (allocno)->may_be_spilled_p
		     ? "" : "!");
Vladimir Makarov committed
2655
	}
Vladimir Makarov committed
2656
      ALLOCNO_COLOR_DATA (allocno)->in_graph_p = true;
2657 2658 2659
    }
}

2660
/* Set up number of available hard registers for allocno A.  */
Vladimir Makarov committed
2661
static void
2662
setup_allocno_available_regs_num (ira_allocno_t a)
Vladimir Makarov committed
2663
{
2664
  int i, n, hard_regno, hard_regs_num, nwords;
Vladimir Makarov committed
2665 2666
  enum reg_class aclass;
  allocno_color_data_t data;
Vladimir Makarov committed
2667

Vladimir Makarov committed
2668 2669 2670 2671
  aclass = ALLOCNO_CLASS (a);
  data = ALLOCNO_COLOR_DATA (a);
  data->available_regs_num = 0;
  if (aclass == NO_REGS)
Vladimir Makarov committed
2672
    return;
Vladimir Makarov committed
2673 2674
  hard_regs_num = ira_class_hard_regs_num[aclass];
  nwords = ALLOCNO_NUM_OBJECTS (a);
Vladimir Makarov committed
2675
  for (n = 0, i = hard_regs_num - 1; i >= 0; i--)
2676
    {
Vladimir Makarov committed
2677
      hard_regno = ira_class_hard_regs[aclass][i];
2678 2679
      /* Checking only profitable hard regs.  */
      if (TEST_HARD_REG_BIT (data->profitable_hard_regs, hard_regno))
2680 2681
	n++;
    }
Vladimir Makarov committed
2682 2683 2684 2685 2686
  data->available_regs_num = n;
  if (internal_flag_ira_verbose <= 2 || ira_dump_file == NULL)
    return;
  fprintf
    (ira_dump_file,
2687
     "      Allocno a%dr%d of %s(%d) has %d avail. regs ",
Vladimir Makarov committed
2688 2689
     ALLOCNO_NUM (a), ALLOCNO_REGNO (a),
     reg_class_names[aclass], ira_class_hard_regs_num[aclass], n);
2690 2691
  print_hard_reg_set (ira_dump_file, data->profitable_hard_regs, false);
  fprintf (ira_dump_file, ", %snode: ",
2692
	   data->profitable_hard_regs == data->hard_regs_node->hard_regs->set
2693 2694 2695
	   ? "" : "^");
  print_hard_reg_set (ira_dump_file,
		      data->hard_regs_node->hard_regs->set, false);
Vladimir Makarov committed
2696
  for (i = 0; i < nwords; i++)
2697
    {
Vladimir Makarov committed
2698
      ira_object_t obj = ALLOCNO_OBJECT (a, i);
2699

Vladimir Makarov committed
2700
      if (nwords != 1)
2701
	{
Vladimir Makarov committed
2702 2703 2704
	  if (i != 0)
	    fprintf (ira_dump_file, ", ");
	  fprintf (ira_dump_file, " obj %d", i);
2705
	}
Vladimir Makarov committed
2706 2707 2708
      fprintf (ira_dump_file, " (confl regs = ");
      print_hard_reg_set (ira_dump_file, OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
			  false);
2709
      fprintf (ira_dump_file, ")");
2710
    }
Vladimir Makarov committed
2711
  fprintf (ira_dump_file, "\n");
Vladimir Makarov committed
2712 2713 2714 2715 2716 2717 2718
}

/* Put ALLOCNO in a bucket corresponding to its number and size of its
   conflicting allocnos and hard registers.  */
static void
put_allocno_into_bucket (ira_allocno_t allocno)
{
Vladimir Makarov committed
2719
  ALLOCNO_COLOR_DATA (allocno)->in_graph_p = true;
Vladimir Makarov committed
2720
  setup_allocno_available_regs_num (allocno);
Vladimir Makarov committed
2721
  if (setup_left_conflict_sizes_p (allocno))
2722
    add_allocno_to_bucket (allocno, &colorable_allocno_bucket);
Vladimir Makarov committed
2723
  else
2724
    add_allocno_to_bucket (allocno, &uncolorable_allocno_bucket);
Vladimir Makarov committed
2725 2726
}

2727 2728
/* Map: allocno number -> allocno priority.  */
static int *allocno_priorities;
Vladimir Makarov committed
2729

2730 2731
/* Set up priorities for N allocnos in array
   CONSIDERATION_ALLOCNOS.  */
Vladimir Makarov committed
2732
static void
2733
setup_allocno_priorities (ira_allocno_t *consideration_allocnos, int n)
Vladimir Makarov committed
2734
{
2735 2736
  int i, length, nrefs, priority, max_priority, mult;
  ira_allocno_t a;
Vladimir Makarov committed
2737

2738 2739
  max_priority = 0;
  for (i = 0; i < n; i++)
2740 2741 2742 2743 2744 2745 2746 2747 2748
    {
      a = consideration_allocnos[i];
      nrefs = ALLOCNO_NREFS (a);
      ira_assert (nrefs >= 0);
      mult = floor_log2 (ALLOCNO_NREFS (a)) + 1;
      ira_assert (mult >= 0);
      allocno_priorities[ALLOCNO_NUM (a)]
	= priority
	= (mult
Vladimir Makarov committed
2749 2750
	   * (ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a))
	   * ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]);
2751 2752 2753 2754 2755 2756 2757 2758 2759 2760
      if (priority < 0)
	priority = -priority;
      if (max_priority < priority)
	max_priority = priority;
    }
  mult = max_priority == 0 ? 1 : INT_MAX / max_priority;
  for (i = 0; i < n; i++)
    {
      a = consideration_allocnos[i];
      length = ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
2761 2762
      if (ALLOCNO_NUM_OBJECTS (a) > 1)
	length /= ALLOCNO_NUM_OBJECTS (a);
2763 2764 2765 2766 2767 2768 2769
      if (length <= 0)
	length = 1;
      allocno_priorities[ALLOCNO_NUM (a)]
	= allocno_priorities[ALLOCNO_NUM (a)] * mult / length;
    }
}

Vladimir Makarov committed
2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788
/* Sort allocnos according to the profit of usage of a hard register
   instead of memory for them. */
static int
allocno_cost_compare_func (const void *v1p, const void *v2p)
{
  ira_allocno_t p1 = *(const ira_allocno_t *) v1p;
  ira_allocno_t p2 = *(const ira_allocno_t *) v2p;
  int c1, c2;

  c1 = ALLOCNO_UPDATED_MEMORY_COST (p1) - ALLOCNO_UPDATED_CLASS_COST (p1);
  c2 = ALLOCNO_UPDATED_MEMORY_COST (p2) - ALLOCNO_UPDATED_CLASS_COST (p2);
  if (c1 - c2)
    return c1 - c2;

  /* If regs are equally good, sort by allocno numbers, so that the
     results of qsort leave nothing to chance.  */
  return ALLOCNO_NUM (p1) - ALLOCNO_NUM (p2);
}

2789 2790 2791 2792 2793 2794
/* Return savings on removed copies when ALLOCNO is assigned to
   HARD_REGNO.  */
static int
allocno_copy_cost_saving (ira_allocno_t allocno, int hard_regno)
{
  int cost = 0;
2795
  machine_mode allocno_mode = ALLOCNO_MODE (allocno);
2796 2797 2798 2799
  enum reg_class rclass;
  ira_copy_t cp, next_cp;

  rclass = REGNO_REG_CLASS (hard_regno);
2800 2801 2802 2803 2804
  if (ira_reg_class_max_nregs[rclass][allocno_mode]
      > ira_class_hard_regs_num[rclass])
    /* For the above condition the cost can be wrong.  Use the allocno
       class in this case.  */
    rclass = ALLOCNO_CLASS (allocno);
2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820
  for (cp = ALLOCNO_COPIES (allocno); cp != NULL; cp = next_cp)
    {
      if (cp->first == allocno)
	{
	  next_cp = cp->next_first_allocno_copy;
	  if (ALLOCNO_HARD_REGNO (cp->second) != hard_regno)
	    continue;
	}
      else if (cp->second == allocno)
	{
	  next_cp = cp->next_second_allocno_copy;
	  if (ALLOCNO_HARD_REGNO (cp->first) != hard_regno)
	    continue;
	}
      else
	gcc_unreachable ();
2821
      ira_init_register_move_cost_if_necessary (allocno_mode);
2822
      cost += cp->freq * ira_register_move_cost[allocno_mode][rclass][rclass];
2823 2824 2825 2826
    }
  return cost;
}

Vladimir Makarov committed
2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839
/* We used Chaitin-Briggs coloring to assign as many pseudos as
   possible to hard registers.  Let us try to improve allocation with
   cost point of view.  This function improves the allocation by
   spilling some allocnos and assigning the freed hard registers to
   other allocnos if it decreases the overall allocation cost.  */
static void
improve_allocation (void)
{
  unsigned int i;
  int j, k, n, hregno, conflict_hregno, base_cost, class_size, word, nwords;
  int check, spill_cost, min_cost, nregs, conflict_nregs, r, best;
  bool try_p;
  enum reg_class aclass;
2840
  machine_mode mode;
Vladimir Makarov committed
2841 2842
  int *allocno_costs;
  int costs[FIRST_PSEUDO_REGISTER];
2843
  HARD_REG_SET conflicting_regs[2], profitable_hard_regs;
Vladimir Makarov committed
2844 2845 2846
  ira_allocno_t a;
  bitmap_iterator bi;

2847 2848 2849 2850 2851
  /* Don't bother to optimize the code with static chain pointer and
     non-local goto in order not to spill the chain pointer
     pseudo.  */
  if (cfun->static_chain_decl && crtl->has_nonlocal_goto)
    return;
Vladimir Makarov committed
2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866
  /* Clear counts used to process conflicting allocnos only once for
     each allocno.  */
  EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
    ALLOCNO_COLOR_DATA (ira_allocnos[i])->temp = 0;
  check = n = 0;
  /* Process each allocno and try to assign a hard register to it by
     spilling some its conflicting allocnos.  */
  EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
    {
      a = ira_allocnos[i];
      ALLOCNO_COLOR_DATA (a)->temp = 0;
      if (empty_profitable_hard_regs (a))
	continue;
      check++;
      aclass = ALLOCNO_CLASS (a);
2867
      allocno_costs = ALLOCNO_HARD_REG_COSTS (a);
Vladimir Makarov committed
2868 2869 2870 2871 2872 2873 2874 2875
      if ((hregno = ALLOCNO_HARD_REGNO (a)) < 0)
	base_cost = ALLOCNO_UPDATED_MEMORY_COST (a);
      else if (allocno_costs == NULL)
	/* It means that assigning a hard register is not profitable
	   (we don't waste memory for hard register costs in this
	   case).  */
	continue;
      else
2876 2877
	base_cost = (allocno_costs[ira_class_hard_reg_index[aclass][hregno]]
		     - allocno_copy_cost_saving (a, hregno));
Vladimir Makarov committed
2878
      try_p = false;
2879 2880 2881
      get_conflict_and_start_profitable_regs (a, false,
					      conflicting_regs,
					      &profitable_hard_regs);
Vladimir Makarov committed
2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894
      class_size = ira_class_hard_regs_num[aclass];
      /* Set up cost improvement for usage of each profitable hard
	 register for allocno A.  */
      for (j = 0; j < class_size; j++)
	{
	  hregno = ira_class_hard_regs[aclass][j];
	  if (! check_hard_reg_p (a, hregno,
				  conflicting_regs, profitable_hard_regs))
	    continue;
	  ira_assert (ira_class_hard_reg_index[aclass][hregno] == j);
	  k = allocno_costs == NULL ? 0 : j;
	  costs[hregno] = (allocno_costs == NULL
			   ? ALLOCNO_UPDATED_CLASS_COST (a) : allocno_costs[k]);
2895
	  costs[hregno] -= allocno_copy_cost_saving (a, hregno);
Vladimir Makarov committed
2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933
	  costs[hregno] -= base_cost;
	  if (costs[hregno] < 0)
	    try_p = true;
	}
      if (! try_p)
	/* There is no chance to improve the allocation cost by
	   assigning hard register to allocno A even without spilling
	   conflicting allocnos.  */
	continue;
      mode = ALLOCNO_MODE (a);
      nwords = ALLOCNO_NUM_OBJECTS (a);
      /* Process each allocno conflicting with A and update the cost
	 improvement for profitable hard registers of A.  To use a
	 hard register for A we need to spill some conflicting
	 allocnos and that creates penalty for the cost
	 improvement.  */
      for (word = 0; word < nwords; word++)
	{
	  ira_object_t conflict_obj;
	  ira_object_t obj = ALLOCNO_OBJECT (a, word);
	  ira_object_conflict_iterator oci;
      
	  FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
	    {
	      ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);

	      if (ALLOCNO_COLOR_DATA (conflict_a)->temp == check)
		/* We already processed this conflicting allocno
		   because we processed earlier another object of the
		   conflicting allocno.  */
		continue;
	      ALLOCNO_COLOR_DATA (conflict_a)->temp = check;
	      if ((conflict_hregno = ALLOCNO_HARD_REGNO (conflict_a)) < 0)
		continue;
	      spill_cost = ALLOCNO_UPDATED_MEMORY_COST (conflict_a);
	      k = (ira_class_hard_reg_index
		   [ALLOCNO_CLASS (conflict_a)][conflict_hregno]);
	      ira_assert (k >= 0);
2934
	      if ((allocno_costs = ALLOCNO_HARD_REG_COSTS (conflict_a))
Vladimir Makarov committed
2935 2936 2937 2938
		  != NULL)
		spill_cost -= allocno_costs[k];
	      else
		spill_cost -= ALLOCNO_UPDATED_CLASS_COST (conflict_a);
2939 2940
	      spill_cost
		+= allocno_copy_cost_saving (conflict_a, conflict_hregno);
2941 2942
	      conflict_nregs = hard_regno_nregs (conflict_hregno,
						 ALLOCNO_MODE (conflict_a));
Vladimir Makarov committed
2943
	      for (r = conflict_hregno;
2944
		   r >= 0 && (int) end_hard_regno (mode, r) > conflict_hregno;
Vladimir Makarov committed
2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976
		   r--)
		if (check_hard_reg_p (a, r,
				      conflicting_regs, profitable_hard_regs))
		  costs[r] += spill_cost;
	      for (r = conflict_hregno + 1;
		   r < conflict_hregno + conflict_nregs;
		   r++)
		if (check_hard_reg_p (a, r,
				      conflicting_regs, profitable_hard_regs))
		  costs[r] += spill_cost;
	    }
	}
      min_cost = INT_MAX;
      best = -1;
      /* Now we choose hard register for A which results in highest
	 allocation cost improvement.  */
      for (j = 0; j < class_size; j++)
	{
	  hregno = ira_class_hard_regs[aclass][j];
	  if (check_hard_reg_p (a, hregno,
				conflicting_regs, profitable_hard_regs)
	      && min_cost > costs[hregno])
	    {
	      best = hregno;
	      min_cost = costs[hregno];
	    }
	}
      if (min_cost >= 0)
	/* We are in a situation when assigning any hard register to A
	   by spilling some conflicting allocnos does not improve the
	   allocation cost.  */
	continue;
2977
      nregs = hard_regno_nregs (best, mode);
Vladimir Makarov committed
2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991
      /* Now spill conflicting allocnos which contain a hard register
	 of A when we assign the best chosen hard register to it.  */
      for (word = 0; word < nwords; word++)
	{
	  ira_object_t conflict_obj;
	  ira_object_t obj = ALLOCNO_OBJECT (a, word);
	  ira_object_conflict_iterator oci;
      
	  FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
	    {
	      ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);

	      if ((conflict_hregno = ALLOCNO_HARD_REGNO (conflict_a)) < 0)
		continue;
2992 2993
	      conflict_nregs = hard_regno_nregs (conflict_hregno,
						 ALLOCNO_MODE (conflict_a));
Vladimir Makarov committed
2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048
	      if (best + nregs <= conflict_hregno
		  || conflict_hregno + conflict_nregs <= best)
		/* No intersection.  */
		continue;
	      ALLOCNO_HARD_REGNO (conflict_a) = -1;
	      sorted_allocnos[n++] = conflict_a;
	      if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
		fprintf (ira_dump_file, "Spilling a%dr%d for a%dr%d\n",
			 ALLOCNO_NUM (conflict_a), ALLOCNO_REGNO (conflict_a),
			 ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
	    }
	}
      /* Assign the best chosen hard register to A.  */
      ALLOCNO_HARD_REGNO (a) = best;
      if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
	fprintf (ira_dump_file, "Assigning %d to a%dr%d\n",
		 best, ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
    }
  if (n == 0)
    return;
  /* We spilled some allocnos to assign their hard registers to other
     allocnos.  The spilled allocnos are now in array
     'sorted_allocnos'.  There is still a possibility that some of the
     spilled allocnos can get hard registers.  So let us try assign
     them hard registers again (just a reminder -- function
     'assign_hard_reg' assigns hard registers only if it is possible
     and profitable).  We process the spilled allocnos with biggest
     benefit to get hard register first -- see function
     'allocno_cost_compare_func'.  */
  qsort (sorted_allocnos, n, sizeof (ira_allocno_t),
	 allocno_cost_compare_func);
  for (j = 0; j < n; j++)
    {
      a = sorted_allocnos[j];
      ALLOCNO_ASSIGNED_P (a) = false;
      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
	{
	  fprintf (ira_dump_file, "      ");
	  ira_print_expanded_allocno (a);
	  fprintf (ira_dump_file, "  -- ");
	}
      if (assign_hard_reg (a, false))
	{
	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
	    fprintf (ira_dump_file, "assign hard reg %d\n",
		     ALLOCNO_HARD_REGNO (a));
	}
      else
	{
	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
	    fprintf (ira_dump_file, "assign memory\n");
	}
    }
}

3049
/* Sort allocnos according to their priorities.  */
3050 3051 3052 3053 3054
static int
allocno_priority_compare_func (const void *v1p, const void *v2p)
{
  ira_allocno_t a1 = *(const ira_allocno_t *) v1p;
  ira_allocno_t a2 = *(const ira_allocno_t *) v2p;
3055
  int pri1, pri2, diff;
3056

3057 3058
  /* Assign hard reg to static chain pointer pseudo first when
     non-local goto is used.  */
3059 3060 3061
  if ((diff = (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a2))
	       - non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a1)))) != 0)
    return diff;
3062 3063
  pri1 = allocno_priorities[ALLOCNO_NUM (a1)];
  pri2 = allocno_priorities[ALLOCNO_NUM (a2)];
3064 3065
  if (pri2 != pri1)
    return SORTGT (pri2, pri1);
3066 3067 3068 3069 3070 3071

  /* If regs are equally good, sort by allocnos, so that the results of
     qsort leave nothing to chance.  */
  return ALLOCNO_NUM (a1) - ALLOCNO_NUM (a2);
}

Vladimir Makarov committed
3072 3073 3074 3075 3076
/* Chaitin-Briggs coloring for allocnos in COLORING_ALLOCNO_BITMAP
   taking into account allocnos in CONSIDERATION_ALLOCNO_BITMAP.  */
static void
color_allocnos (void)
{
3077
  unsigned int i, n;
Vladimir Makarov committed
3078 3079 3080
  bitmap_iterator bi;
  ira_allocno_t a;

3081
  setup_profitable_hard_regs ();
Vladimir Makarov committed
3082 3083 3084 3085 3086 3087 3088
  EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
    {
      allocno_color_data_t data;
      ira_pref_t pref, next_pref;

      a = ira_allocnos[i];
      data = ALLOCNO_COLOR_DATA (a);
3089
      data->conflict_allocno_hard_prefs = 0;
Vladimir Makarov committed
3090 3091 3092 3093 3094 3095 3096 3097 3098
      for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = next_pref)
	{
	  next_pref = pref->next_pref;
	  if (! ira_hard_reg_in_set_p (pref->hard_regno,
				       ALLOCNO_MODE (a),
				       data->profitable_hard_regs))
	    ira_remove_pref (pref);
	}
    }
3099
  
3100
  if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY)
Vladimir Makarov committed
3101
    {
3102 3103
      n = 0;
      EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
Vladimir Makarov committed
3104
	{
3105
	  a = ira_allocnos[i];
Vladimir Makarov committed
3106
	  if (ALLOCNO_CLASS (a) == NO_REGS)
Vladimir Makarov committed
3107
	    {
3108 3109 3110 3111 3112 3113 3114
	      ALLOCNO_HARD_REGNO (a) = -1;
	      ALLOCNO_ASSIGNED_P (a) = true;
	      ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL);
	      ira_assert (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) == NULL);
	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
		{
		  fprintf (ira_dump_file, "      Spill");
3115
		  ira_print_expanded_allocno (a);
3116 3117 3118
		  fprintf (ira_dump_file, "\n");
		}
	      continue;
Vladimir Makarov committed
3119
	    }
3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132
	  sorted_allocnos[n++] = a;
	}
      if (n != 0)
	{
	  setup_allocno_priorities (sorted_allocnos, n);
	  qsort (sorted_allocnos, n, sizeof (ira_allocno_t),
		 allocno_priority_compare_func);
	  for (i = 0; i < n; i++)
	    {
	      a = sorted_allocnos[i];
	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
		{
		  fprintf (ira_dump_file, "      ");
3133
		  ira_print_expanded_allocno (a);
3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151
		  fprintf (ira_dump_file, "  -- ");
		}
	      if (assign_hard_reg (a, false))
		{
		  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
		    fprintf (ira_dump_file, "assign hard reg %d\n",
			     ALLOCNO_HARD_REGNO (a));
		}
	      else
		{
		  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
		    fprintf (ira_dump_file, "assign memory\n");
		}
	    }
	}
    }
  else
    {
3152
      form_allocno_hard_regs_nodes_forest ();
Vladimir Makarov committed
3153 3154
      if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
	print_hard_regs_forest (ira_dump_file);
3155 3156 3157
      EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
	{
	  a = ira_allocnos[i];
Vladimir Makarov committed
3158
	  if (ALLOCNO_CLASS (a) != NO_REGS && ! empty_profitable_hard_regs (a))
Vladimir Makarov committed
3159 3160 3161
	    {
	      ALLOCNO_COLOR_DATA (a)->in_graph_p = true;
	      update_costs_from_prefs (a);
3162
	      update_conflict_allocno_hard_prefs (a);
Vladimir Makarov committed
3163
	    }
Vladimir Makarov committed
3164
	  else
3165 3166 3167
	    {
	      ALLOCNO_HARD_REGNO (a) = -1;
	      ALLOCNO_ASSIGNED_P (a) = true;
Vladimir Makarov committed
3168 3169
	      /* We don't need updated costs anymore.  */
	      ira_free_allocno_updated_costs (a);
3170 3171 3172
	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
		{
		  fprintf (ira_dump_file, "      Spill");
3173
		  ira_print_expanded_allocno (a);
3174 3175 3176
		  fprintf (ira_dump_file, "\n");
		}
	    }
Vladimir Makarov committed
3177 3178 3179 3180 3181 3182 3183 3184 3185
	}
      /* Put the allocnos into the corresponding buckets.  */
      colorable_allocno_bucket = NULL;
      uncolorable_allocno_bucket = NULL;
      EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
	{
	  a = ira_allocnos[i];
	  if (ALLOCNO_COLOR_DATA (a)->in_graph_p)
	    put_allocno_into_bucket (a);
Vladimir Makarov committed
3186
	}
3187 3188
      push_allocnos_to_stack ();
      pop_allocnos_from_stack ();
3189
      finish_allocno_hard_regs_nodes_forest ();
Vladimir Makarov committed
3190
    }
Vladimir Makarov committed
3191
  improve_allocation ();
Vladimir Makarov committed
3192 3193 3194 3195
}



3196
/* Output information about the loop given by its LOOP_TREE_NODE.  */
Vladimir Makarov committed
3197 3198 3199 3200 3201
static void
print_loop_title (ira_loop_tree_node_t loop_tree_node)
{
  unsigned int j;
  bitmap_iterator bi;
3202 3203 3204
  ira_loop_tree_node_t subloop_node, dest_loop_node;
  edge e;
  edge_iterator ei;
Vladimir Makarov committed
3205

3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218
  if (loop_tree_node->parent == NULL)
    fprintf (ira_dump_file,
	     "\n  Loop 0 (parent -1, header bb%d, depth 0)\n    bbs:",
	     NUM_FIXED_BLOCKS);
  else
    {
      ira_assert (current_loops != NULL && loop_tree_node->loop != NULL);
      fprintf (ira_dump_file,
	       "\n  Loop %d (parent %d, header bb%d, depth %d)\n    bbs:",
	       loop_tree_node->loop_num, loop_tree_node->parent->loop_num,
	       loop_tree_node->loop->header->index,
	       loop_depth (loop_tree_node->loop));
    }
3219 3220 3221 3222 3223 3224 3225
  for (subloop_node = loop_tree_node->children;
       subloop_node != NULL;
       subloop_node = subloop_node->next)
    if (subloop_node->bb != NULL)
      {
	fprintf (ira_dump_file, " %d", subloop_node->bb->index);
	FOR_EACH_EDGE (e, ei, subloop_node->bb->succs)
3226
	  if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
3227 3228 3229
	      && ((dest_loop_node = IRA_BB_NODE (e->dest)->parent)
		  != loop_tree_node))
	    fprintf (ira_dump_file, "(->%d:l%d)",
3230
		     e->dest->index, dest_loop_node->loop_num);
3231 3232
      }
  fprintf (ira_dump_file, "\n    all:");
3233
  EXECUTE_IF_SET_IN_BITMAP (loop_tree_node->all_allocnos, 0, j, bi)
Vladimir Makarov committed
3234 3235 3236 3237 3238 3239 3240 3241
    fprintf (ira_dump_file, " %dr%d", j, ALLOCNO_REGNO (ira_allocnos[j]));
  fprintf (ira_dump_file, "\n    modified regnos:");
  EXECUTE_IF_SET_IN_BITMAP (loop_tree_node->modified_regnos, 0, j, bi)
    fprintf (ira_dump_file, " %d", j);
  fprintf (ira_dump_file, "\n    border:");
  EXECUTE_IF_SET_IN_BITMAP (loop_tree_node->border_allocnos, 0, j, bi)
    fprintf (ira_dump_file, " %dr%d", j, ALLOCNO_REGNO (ira_allocnos[j]));
  fprintf (ira_dump_file, "\n    Pressure:");
Vladimir Makarov committed
3242
  for (j = 0; (int) j < ira_pressure_classes_num; j++)
Vladimir Makarov committed
3243
    {
Vladimir Makarov committed
3244
      enum reg_class pclass;
H.J. Lu committed
3245

Vladimir Makarov committed
3246 3247
      pclass = ira_pressure_classes[j];
      if (loop_tree_node->reg_pressure[pclass] == 0)
Vladimir Makarov committed
3248
	continue;
Vladimir Makarov committed
3249 3250
      fprintf (ira_dump_file, " %s=%d", reg_class_names[pclass],
	       loop_tree_node->reg_pressure[pclass]);
Vladimir Makarov committed
3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261
    }
  fprintf (ira_dump_file, "\n");
}

/* Color the allocnos inside loop (in the extreme case it can be all
   of the function) given the corresponding LOOP_TREE_NODE.  The
   function is called for each loop during top-down traverse of the
   loop tree.  */
static void
color_pass (ira_loop_tree_node_t loop_tree_node)
{
3262
  int regno, hard_regno, index = -1, n;
Vladimir Makarov committed
3263 3264 3265
  int cost, exit_freq, enter_freq;
  unsigned int j;
  bitmap_iterator bi;
3266
  machine_mode mode;
Vladimir Makarov committed
3267
  enum reg_class rclass, aclass, pclass;
Vladimir Makarov committed
3268 3269 3270 3271 3272 3273 3274
  ira_allocno_t a, subloop_allocno;
  ira_loop_tree_node_t subloop_node;

  ira_assert (loop_tree_node->bb == NULL);
  if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL)
    print_loop_title (loop_tree_node);

3275
  bitmap_copy (coloring_allocno_bitmap, loop_tree_node->all_allocnos);
Vladimir Makarov committed
3276
  bitmap_copy (consideration_allocno_bitmap, coloring_allocno_bitmap);
3277
  n = 0;
Vladimir Makarov committed
3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289
  EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, j, bi)
    {
      a = ira_allocnos[j];
      n++;
      if (! ALLOCNO_ASSIGNED_P (a))
	continue;
      bitmap_clear_bit (coloring_allocno_bitmap, ALLOCNO_NUM (a));
    }
  allocno_color_data
    = (allocno_color_data_t) ira_allocate (sizeof (struct allocno_color_data)
					   * n);
  memset (allocno_color_data, 0, sizeof (struct allocno_color_data) * n);
3290 3291
  curr_allocno_process = 0;
  n = 0;
Vladimir Makarov committed
3292 3293 3294
  EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, j, bi)
    {
      a = ira_allocnos[j];
Vladimir Makarov committed
3295 3296
      ALLOCNO_ADD_DATA (a) = allocno_color_data + n;
      n++;
Vladimir Makarov committed
3297
    }
3298
  init_allocno_threads ();
Vladimir Makarov committed
3299 3300 3301
  /* Color all mentioned allocnos including transparent ones.  */
  color_allocnos ();
  /* Process caps.  They are processed just once.  */
3302 3303
  if (flag_ira_region == IRA_REGION_MIXED
      || flag_ira_region == IRA_REGION_ALL)
3304
    EXECUTE_IF_SET_IN_BITMAP (loop_tree_node->all_allocnos, 0, j, bi)
Vladimir Makarov committed
3305 3306 3307 3308 3309 3310
      {
	a = ira_allocnos[j];
	if (ALLOCNO_CAP_MEMBER (a) == NULL)
	  continue;
	/* Remove from processing in the next loop.  */
	bitmap_clear_bit (consideration_allocno_bitmap, j);
Vladimir Makarov committed
3311 3312
	rclass = ALLOCNO_CLASS (a);
	pclass = ira_pressure_class_translate[rclass];
3313
	if (flag_ira_region == IRA_REGION_MIXED
Vladimir Makarov committed
3314
	    && (loop_tree_node->reg_pressure[pclass]
3315
		<= ira_class_hard_regs_num[pclass]))
Vladimir Makarov committed
3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330
	  {
	    mode = ALLOCNO_MODE (a);
	    hard_regno = ALLOCNO_HARD_REGNO (a);
	    if (hard_regno >= 0)
	      {
		index = ira_class_hard_reg_index[rclass][hard_regno];
		ira_assert (index >= 0);
	      }
	    regno = ALLOCNO_REGNO (a);
	    subloop_allocno = ALLOCNO_CAP_MEMBER (a);
	    subloop_node = ALLOCNO_LOOP_TREE_NODE (subloop_allocno);
	    ira_assert (!ALLOCNO_ASSIGNED_P (subloop_allocno));
	    ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
	    ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
	    if (hard_regno >= 0)
3331
	      update_costs_from_copies (subloop_allocno, true, true);
3332
	    /* We don't need updated costs anymore.  */
Vladimir Makarov committed
3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347
	    ira_free_allocno_updated_costs (subloop_allocno);
	  }
      }
  /* Update costs of the corresponding allocnos (not caps) in the
     subloops.  */
  for (subloop_node = loop_tree_node->subloops;
       subloop_node != NULL;
       subloop_node = subloop_node->subloop_next)
    {
      ira_assert (subloop_node->bb == NULL);
      EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, j, bi)
        {
	  a = ira_allocnos[j];
	  ira_assert (ALLOCNO_CAP_MEMBER (a) == NULL);
	  mode = ALLOCNO_MODE (a);
Vladimir Makarov committed
3348 3349
	  rclass = ALLOCNO_CLASS (a);
	  pclass = ira_pressure_class_translate[rclass];
Vladimir Makarov committed
3350
	  hard_regno = ALLOCNO_HARD_REGNO (a);
3351
	  /* Use hard register class here.  ??? */
Vladimir Makarov committed
3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362
	  if (hard_regno >= 0)
	    {
	      index = ira_class_hard_reg_index[rclass][hard_regno];
	      ira_assert (index >= 0);
	    }
	  regno = ALLOCNO_REGNO (a);
	  /* ??? conflict costs */
	  subloop_allocno = subloop_node->regno_allocno_map[regno];
	  if (subloop_allocno == NULL
	      || ALLOCNO_CAP (subloop_allocno) != NULL)
	    continue;
Vladimir Makarov committed
3363
	  ira_assert (ALLOCNO_CLASS (subloop_allocno) == rclass);
3364 3365
	  ira_assert (bitmap_bit_p (subloop_node->all_allocnos,
				    ALLOCNO_NUM (subloop_allocno)));
3366 3367 3368 3369
	  if ((flag_ira_region == IRA_REGION_MIXED
	       && (loop_tree_node->reg_pressure[pclass]
		   <= ira_class_hard_regs_num[pclass]))
	      || (pic_offset_table_rtx != NULL
3370 3371 3372 3373 3374
		  && regno == (int) REGNO (pic_offset_table_rtx))
	      /* Avoid overlapped multi-registers. Moves between them
		 might result in wrong code generation.  */
	      || (hard_regno >= 0
		  && ira_reg_class_max_nregs[pclass][mode] > 1))
Vladimir Makarov committed
3375 3376 3377 3378 3379 3380
	    {
	      if (! ALLOCNO_ASSIGNED_P (subloop_allocno))
		{
		  ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
		  ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
		  if (hard_regno >= 0)
3381
		    update_costs_from_copies (subloop_allocno, true, true);
3382
		  /* We don't need updated costs anymore.  */
Vladimir Makarov committed
3383 3384 3385 3386 3387 3388 3389
		  ira_free_allocno_updated_costs (subloop_allocno);
		}
	      continue;
	    }
	  exit_freq = ira_loop_edge_freq (subloop_node, regno, true);
	  enter_freq = ira_loop_edge_freq (subloop_node, regno, false);
	  ira_assert (regno < ira_reg_equiv_len);
3390
	  if (ira_equiv_no_lvalue_p (regno))
Vladimir Makarov committed
3391 3392 3393 3394 3395 3396
	    {
	      if (! ALLOCNO_ASSIGNED_P (subloop_allocno))
		{
		  ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
		  ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
		  if (hard_regno >= 0)
3397
		    update_costs_from_copies (subloop_allocno, true, true);
3398
		  /* We don't need updated costs anymore.  */
Vladimir Makarov committed
3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409
		  ira_free_allocno_updated_costs (subloop_allocno);
		}
	    }
	  else if (hard_regno < 0)
	    {
	      ALLOCNO_UPDATED_MEMORY_COST (subloop_allocno)
		-= ((ira_memory_move_cost[mode][rclass][1] * enter_freq)
		    + (ira_memory_move_cost[mode][rclass][0] * exit_freq));
	    }
	  else
	    {
Vladimir Makarov committed
3410 3411 3412
	      aclass = ALLOCNO_CLASS (subloop_allocno);
	      ira_init_register_move_cost_if_necessary (mode);
	      cost = (ira_register_move_cost[mode][rclass][rclass]
Vladimir Makarov committed
3413
		      * (exit_freq + enter_freq));
3414
	      ira_allocate_and_set_or_copy_costs
Vladimir Makarov committed
3415 3416
		(&ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno), aclass,
		 ALLOCNO_UPDATED_CLASS_COST (subloop_allocno),
3417 3418 3419
		 ALLOCNO_HARD_REG_COSTS (subloop_allocno));
	      ira_allocate_and_set_or_copy_costs
		(&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (subloop_allocno),
Vladimir Makarov committed
3420
		 aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (subloop_allocno));
3421 3422
	      ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno)[index] -= cost;
	      ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (subloop_allocno)[index]
Vladimir Makarov committed
3423
		-= cost;
Vladimir Makarov committed
3424
	      if (ALLOCNO_UPDATED_CLASS_COST (subloop_allocno)
3425
		  > ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno)[index])
Vladimir Makarov committed
3426
		ALLOCNO_UPDATED_CLASS_COST (subloop_allocno)
3427
		  = ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno)[index];
Vladimir Makarov committed
3428 3429 3430 3431 3432 3433
	      ALLOCNO_UPDATED_MEMORY_COST (subloop_allocno)
		+= (ira_memory_move_cost[mode][rclass][0] * enter_freq
		    + ira_memory_move_cost[mode][rclass][1] * exit_freq);
	    }
	}
    }
Vladimir Makarov committed
3434
  ira_free (allocno_color_data);
3435
  EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, j, bi)
Vladimir Makarov committed
3436 3437 3438 3439
    {
      a = ira_allocnos[j];
      ALLOCNO_ADD_DATA (a) = NULL;
    }
Vladimir Makarov committed
3440 3441 3442 3443 3444 3445 3446 3447 3448 3449
}

/* Initialize the common data for coloring and calls functions to do
   Chaitin-Briggs and regional coloring.  */
static void
do_coloring (void)
{
  coloring_allocno_bitmap = ira_allocate_bitmap ();
  if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
    fprintf (ira_dump_file, "\n**** Allocnos coloring:\n\n");
H.J. Lu committed
3450

Vladimir Makarov committed
3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471
  ira_traverse_loop_tree (false, ira_loop_tree_root, color_pass, NULL);

  if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL)
    ira_print_disposition (ira_dump_file);

  ira_free_bitmap (coloring_allocno_bitmap);
}



/* Move spill/restore code, which are to be generated in ira-emit.c,
   to less frequent points (if it is profitable) by reassigning some
   allocnos (in loop with subloops containing in another loop) to
   memory which results in longer live-range where the corresponding
   pseudo-registers will be in memory.  */
static void
move_spill_restore (void)
{
  int cost, regno, hard_regno, hard_regno2, index;
  bool changed_p;
  int enter_freq, exit_freq;
3472
  machine_mode mode;
Vladimir Makarov committed
3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494
  enum reg_class rclass;
  ira_allocno_t a, parent_allocno, subloop_allocno;
  ira_loop_tree_node_t parent, loop_node, subloop_node;
  ira_allocno_iterator ai;

  for (;;)
    {
      changed_p = false;
      if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
	fprintf (ira_dump_file, "New iteration of spill/restore move\n");
      FOR_EACH_ALLOCNO (a, ai)
	{
	  regno = ALLOCNO_REGNO (a);
	  loop_node = ALLOCNO_LOOP_TREE_NODE (a);
	  if (ALLOCNO_CAP_MEMBER (a) != NULL
	      || ALLOCNO_CAP (a) != NULL
	      || (hard_regno = ALLOCNO_HARD_REGNO (a)) < 0
	      || loop_node->children == NULL
	      /* don't do the optimization because it can create
		 copies and the reload pass can spill the allocno set
		 by copy although the allocno will not get memory
		 slot.  */
3495
	      || ira_equiv_no_lvalue_p (regno)
3496 3497 3498 3499
	      || !bitmap_bit_p (loop_node->border_allocnos, ALLOCNO_NUM (a))
	      /* Do not spill static chain pointer pseudo when
		 non-local goto is used.  */
	      || non_spilled_static_chain_regno_p (regno))
Vladimir Makarov committed
3500 3501
	    continue;
	  mode = ALLOCNO_MODE (a);
Vladimir Makarov committed
3502
	  rclass = ALLOCNO_CLASS (a);
Vladimir Makarov committed
3503 3504 3505 3506
	  index = ira_class_hard_reg_index[rclass][hard_regno];
	  ira_assert (index >= 0);
	  cost = (ALLOCNO_MEMORY_COST (a)
		  - (ALLOCNO_HARD_REG_COSTS (a) == NULL
Vladimir Makarov committed
3507
		     ? ALLOCNO_CLASS_COST (a)
Vladimir Makarov committed
3508
		     : ALLOCNO_HARD_REG_COSTS (a)[index]));
Vladimir Makarov committed
3509
	  ira_init_register_move_cost_if_necessary (mode);
Vladimir Makarov committed
3510 3511 3512 3513 3514 3515 3516 3517
	  for (subloop_node = loop_node->subloops;
	       subloop_node != NULL;
	       subloop_node = subloop_node->subloop_next)
	    {
	      ira_assert (subloop_node->bb == NULL);
	      subloop_allocno = subloop_node->regno_allocno_map[regno];
	      if (subloop_allocno == NULL)
		continue;
Vladimir Makarov committed
3518
	      ira_assert (rclass == ALLOCNO_CLASS (subloop_allocno));
Vladimir Makarov committed
3519 3520 3521 3522 3523
	      /* We have accumulated cost.  To get the real cost of
		 allocno usage in the loop we should subtract costs of
		 the subloop allocnos.  */
	      cost -= (ALLOCNO_MEMORY_COST (subloop_allocno)
		       - (ALLOCNO_HARD_REG_COSTS (subloop_allocno) == NULL
Vladimir Makarov committed
3524
			  ? ALLOCNO_CLASS_COST (subloop_allocno)
Vladimir Makarov committed
3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536
			  : ALLOCNO_HARD_REG_COSTS (subloop_allocno)[index]));
	      exit_freq = ira_loop_edge_freq (subloop_node, regno, true);
	      enter_freq = ira_loop_edge_freq (subloop_node, regno, false);
	      if ((hard_regno2 = ALLOCNO_HARD_REGNO (subloop_allocno)) < 0)
		cost -= (ira_memory_move_cost[mode][rclass][0] * exit_freq
			 + ira_memory_move_cost[mode][rclass][1] * enter_freq);
	      else
		{
		  cost
		    += (ira_memory_move_cost[mode][rclass][0] * exit_freq
			+ ira_memory_move_cost[mode][rclass][1] * enter_freq);
		  if (hard_regno2 != hard_regno)
Vladimir Makarov committed
3537
		    cost -= (ira_register_move_cost[mode][rclass][rclass]
Vladimir Makarov committed
3538 3539 3540 3541 3542 3543
			     * (exit_freq + enter_freq));
		}
	    }
	  if ((parent = loop_node->parent) != NULL
	      && (parent_allocno = parent->regno_allocno_map[regno]) != NULL)
	    {
Vladimir Makarov committed
3544
	      ira_assert (rclass == ALLOCNO_CLASS (parent_allocno));
Vladimir Makarov committed
3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555
	      exit_freq	= ira_loop_edge_freq (loop_node, regno, true);
	      enter_freq = ira_loop_edge_freq (loop_node, regno, false);
	      if ((hard_regno2 = ALLOCNO_HARD_REGNO (parent_allocno)) < 0)
		cost -= (ira_memory_move_cost[mode][rclass][0] * exit_freq
			 + ira_memory_move_cost[mode][rclass][1] * enter_freq);
	      else
		{
		  cost
		    += (ira_memory_move_cost[mode][rclass][1] * exit_freq
			+ ira_memory_move_cost[mode][rclass][0] * enter_freq);
		  if (hard_regno2 != hard_regno)
Vladimir Makarov committed
3556
		    cost -= (ira_register_move_cost[mode][rclass][rclass]
Vladimir Makarov committed
3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567
			     * (exit_freq + enter_freq));
		}
	    }
	  if (cost < 0)
	    {
	      ALLOCNO_HARD_REGNO (a) = -1;
	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
		{
		  fprintf
		    (ira_dump_file,
		     "      Moving spill/restore for a%dr%d up from loop %d",
3568
		     ALLOCNO_NUM (a), regno, loop_node->loop_num);
Vladimir Makarov committed
3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587
		  fprintf (ira_dump_file, " - profit %d\n", -cost);
		}
	      changed_p = true;
	    }
	}
      if (! changed_p)
	break;
    }
}



/* Update current hard reg costs and current conflict hard reg costs
   for allocno A.  It is done by processing its copies containing
   other allocnos already assigned.  */
static void
update_curr_costs (ira_allocno_t a)
{
  int i, hard_regno, cost;
3588
  machine_mode mode;
Vladimir Makarov committed
3589
  enum reg_class aclass, rclass;
Vladimir Makarov committed
3590 3591 3592
  ira_allocno_t another_a;
  ira_copy_t cp, next_cp;

3593
  ira_free_allocno_updated_costs (a);
Vladimir Makarov committed
3594
  ira_assert (! ALLOCNO_ASSIGNED_P (a));
Vladimir Makarov committed
3595 3596
  aclass = ALLOCNO_CLASS (a);
  if (aclass == NO_REGS)
Vladimir Makarov committed
3597 3598
    return;
  mode = ALLOCNO_MODE (a);
Vladimir Makarov committed
3599
  ira_init_register_move_cost_if_necessary (mode);
Vladimir Makarov committed
3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613
  for (cp = ALLOCNO_COPIES (a); cp != NULL; cp = next_cp)
    {
      if (cp->first == a)
	{
	  next_cp = cp->next_first_allocno_copy;
	  another_a = cp->second;
	}
      else if (cp->second == a)
	{
	  next_cp = cp->next_second_allocno_copy;
	  another_a = cp->first;
	}
      else
	gcc_unreachable ();
Vladimir Makarov committed
3614
      if (! ira_reg_classes_intersect_p[aclass][ALLOCNO_CLASS (another_a)]
Vladimir Makarov committed
3615 3616 3617 3618
	  || ! ALLOCNO_ASSIGNED_P (another_a)
	  || (hard_regno = ALLOCNO_HARD_REGNO (another_a)) < 0)
	continue;
      rclass = REGNO_REG_CLASS (hard_regno);
Vladimir Makarov committed
3619
      i = ira_class_hard_reg_index[aclass][hard_regno];
3620 3621
      if (i < 0)
	continue;
Vladimir Makarov committed
3622
      cost = (cp->first == a
Vladimir Makarov committed
3623 3624
	      ? ira_register_move_cost[mode][rclass][aclass]
	      : ira_register_move_cost[mode][aclass][rclass]);
Vladimir Makarov committed
3625
      ira_allocate_and_set_or_copy_costs
Vladimir Makarov committed
3626
	(&ALLOCNO_UPDATED_HARD_REG_COSTS (a), aclass, ALLOCNO_CLASS_COST (a),
Vladimir Makarov committed
3627 3628 3629
	 ALLOCNO_HARD_REG_COSTS (a));
      ira_allocate_and_set_or_copy_costs
	(&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a),
Vladimir Makarov committed
3630
	 aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (a));
Vladimir Makarov committed
3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645
      ALLOCNO_UPDATED_HARD_REG_COSTS (a)[i] -= cp->freq * cost;
      ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a)[i] -= cp->freq * cost;
    }
}

/* Try to assign hard registers to the unassigned allocnos and
   allocnos conflicting with them or conflicting with allocnos whose
   regno >= START_REGNO.  The function is called after ira_flattening,
   so more allocnos (including ones created in ira-emit.c) will have a
   chance to get a hard register.  We use simple assignment algorithm
   based on priorities.  */
void
ira_reassign_conflict_allocnos (int start_regno)
{
  int i, allocnos_to_color_num;
3646
  ira_allocno_t a;
Vladimir Makarov committed
3647
  enum reg_class aclass;
Vladimir Makarov committed
3648 3649 3650 3651 3652 3653 3654
  bitmap allocnos_to_color;
  ira_allocno_iterator ai;

  allocnos_to_color = ira_allocate_bitmap ();
  allocnos_to_color_num = 0;
  FOR_EACH_ALLOCNO (a, ai)
    {
3655
      int n = ALLOCNO_NUM_OBJECTS (a);
3656

Vladimir Makarov committed
3657 3658 3659
      if (! ALLOCNO_ASSIGNED_P (a)
	  && ! bitmap_bit_p (allocnos_to_color, ALLOCNO_NUM (a)))
	{
Vladimir Makarov committed
3660
	  if (ALLOCNO_CLASS (a) != NO_REGS)
Vladimir Makarov committed
3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671
	    sorted_allocnos[allocnos_to_color_num++] = a;
	  else
	    {
	      ALLOCNO_ASSIGNED_P (a) = true;
	      ALLOCNO_HARD_REGNO (a) = -1;
	      ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL);
	      ira_assert (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) == NULL);
	    }
	  bitmap_set_bit (allocnos_to_color, ALLOCNO_NUM (a));
	}
      if (ALLOCNO_REGNO (a) < start_regno
Vladimir Makarov committed
3672
	  || (aclass = ALLOCNO_CLASS (a)) == NO_REGS)
Vladimir Makarov committed
3673
	continue;
3674
      for (i = 0; i < n; i++)
Vladimir Makarov committed
3675
	{
3676 3677 3678
	  ira_object_t obj = ALLOCNO_OBJECT (a, i);
	  ira_object_t conflict_obj;
	  ira_object_conflict_iterator oci;
Vladimir Makarov committed
3679

3680 3681 3682
	  FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
	    {
	      ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
Vladimir Makarov committed
3683

3684
	      ira_assert (ira_reg_classes_intersect_p
Vladimir Makarov committed
3685
			  [aclass][ALLOCNO_CLASS (conflict_a)]);
3686
	      if (!bitmap_set_bit (allocnos_to_color, ALLOCNO_NUM (conflict_a)))
3687 3688 3689
		continue;
	      sorted_allocnos[allocnos_to_color_num++] = conflict_a;
	    }
Vladimir Makarov committed
3690 3691 3692 3693 3694
	}
    }
  ira_free_bitmap (allocnos_to_color);
  if (allocnos_to_color_num > 1)
    {
3695
      setup_allocno_priorities (sorted_allocnos, allocnos_to_color_num);
Vladimir Makarov committed
3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720
      qsort (sorted_allocnos, allocnos_to_color_num, sizeof (ira_allocno_t),
	     allocno_priority_compare_func);
    }
  for (i = 0; i < allocnos_to_color_num; i++)
    {
      a = sorted_allocnos[i];
      ALLOCNO_ASSIGNED_P (a) = false;
      update_curr_costs (a);
    }
  for (i = 0; i < allocnos_to_color_num; i++)
    {
      a = sorted_allocnos[i];
      if (assign_hard_reg (a, true))
	{
	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
	    fprintf
	      (ira_dump_file,
	       "      Secondary allocation: assign hard reg %d to reg %d\n",
	       ALLOCNO_HARD_REGNO (a), ALLOCNO_REGNO (a));
	}
    }
}



Vladimir Makarov committed
3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735
/* This page contains functions used to find conflicts using allocno
   live ranges.  */

#ifdef ENABLE_IRA_CHECKING

/* Return TRUE if live ranges of pseudo-registers REGNO1 and REGNO2
   intersect.  This should be used when there is only one region.
   Currently this is used during reload.  */
static bool
conflict_by_live_ranges_p (int regno1, int regno2)
{
  ira_allocno_t a1, a2;

  ira_assert (regno1 >= FIRST_PSEUDO_REGISTER
	      && regno2 >= FIRST_PSEUDO_REGISTER);
Kito Cheng committed
3736
  /* Reg info calculated by dataflow infrastructure can be different
Vladimir Makarov committed
3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747
     from one calculated by regclass.  */
  if ((a1 = ira_loop_tree_root->regno_allocno_map[regno1]) == NULL
      || (a2 = ira_loop_tree_root->regno_allocno_map[regno2]) == NULL)
    return false;
  return allocnos_conflict_by_live_ranges_p (a1, a2);
}

#endif



Vladimir Makarov committed
3748 3749 3750 3751 3752 3753 3754
/* This page contains code to coalesce memory stack slots used by
   spilled allocnos.  This results in smaller stack frame, better data
   locality, and in smaller code for some architectures like
   x86/x86_64 where insn size depends on address displacement value.
   On the other hand, it can worsen insn scheduling after the RA but
   in practice it is less important than smaller stack frames.  */

3755 3756 3757 3758 3759 3760 3761 3762 3763
/* TRUE if we coalesced some allocnos.  In other words, if we got
   loops formed by members first_coalesced_allocno and
   next_coalesced_allocno containing more one allocno.  */
static bool allocno_coalesced_p;

/* Bitmap used to prevent a repeated allocno processing because of
   coalescing.  */
static bitmap processed_coalesced_allocno_bitmap;

Vladimir Makarov committed
3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784
/* See below.  */
typedef struct coalesce_data *coalesce_data_t;

/* To decrease footprint of ira_allocno structure we store all data
   needed only for coalescing in the following structure.  */
struct coalesce_data
{
  /* Coalesced allocnos form a cyclic list.  One allocno given by
     FIRST represents all coalesced allocnos.  The
     list is chained by NEXT.  */
  ira_allocno_t first;
  ira_allocno_t next;
  int temp;
};

/* Container for storing allocno data concerning coalescing.  */
static coalesce_data_t allocno_coalesce_data;

/* Macro to access the data concerning coalescing.  */
#define ALLOCNO_COALESCE_DATA(a) ((coalesce_data_t) ALLOCNO_ADD_DATA (a))

3785 3786 3787 3788 3789 3790 3791 3792
/* Merge two sets of coalesced allocnos given correspondingly by
   allocnos A1 and A2 (more accurately merging A2 set into A1
   set).  */
static void
merge_allocnos (ira_allocno_t a1, ira_allocno_t a2)
{
  ira_allocno_t a, first, last, next;

Vladimir Makarov committed
3793 3794 3795
  first = ALLOCNO_COALESCE_DATA (a1)->first;
  a = ALLOCNO_COALESCE_DATA (a2)->first;
  if (first == a)
3796
    return;
Vladimir Makarov committed
3797 3798
  for (last = a2, a = ALLOCNO_COALESCE_DATA (a2)->next;;
       a = ALLOCNO_COALESCE_DATA (a)->next)
3799
    {
Vladimir Makarov committed
3800
      ALLOCNO_COALESCE_DATA (a)->first = first;
3801 3802 3803 3804
      if (a == a2)
	break;
      last = a;
    }
Vladimir Makarov committed
3805 3806 3807
  next = allocno_coalesce_data[ALLOCNO_NUM (first)].next;
  allocno_coalesce_data[ALLOCNO_NUM (first)].next = a2;
  allocno_coalesce_data[ALLOCNO_NUM (last)].next = next;
3808 3809
}

Vladimir Makarov committed
3810 3811 3812 3813 3814
/* Return TRUE if there are conflicting allocnos from two sets of
   coalesced allocnos given correspondingly by allocnos A1 and A2.  We
   use live ranges to find conflicts because conflicts are represented
   only for allocnos of the same allocno class and during the reload
   pass we coalesce allocnos for sharing stack memory slots.  */
3815 3816 3817
static bool
coalesced_allocno_conflict_p (ira_allocno_t a1, ira_allocno_t a2)
{
Vladimir Makarov committed
3818
  ira_allocno_t a, conflict_a;
3819 3820 3821

  if (allocno_coalesced_p)
    {
Vladimir Makarov committed
3822 3823 3824
      bitmap_clear (processed_coalesced_allocno_bitmap);
      for (a = ALLOCNO_COALESCE_DATA (a1)->next;;
	   a = ALLOCNO_COALESCE_DATA (a)->next)
3825
	{
Vladimir Makarov committed
3826
	  bitmap_set_bit (processed_coalesced_allocno_bitmap, ALLOCNO_NUM (a));
3827 3828 3829 3830
	  if (a == a1)
	    break;
	}
    }
Vladimir Makarov committed
3831 3832
  for (a = ALLOCNO_COALESCE_DATA (a2)->next;;
       a = ALLOCNO_COALESCE_DATA (a)->next)
3833
    {
Vladimir Makarov committed
3834 3835
      for (conflict_a = ALLOCNO_COALESCE_DATA (a1)->next;;
	   conflict_a = ALLOCNO_COALESCE_DATA (conflict_a)->next)
3836
	{
Vladimir Makarov committed
3837
	  if (allocnos_conflict_by_live_ranges_p (a, conflict_a))
3838
	    return true;
Vladimir Makarov committed
3839
	  if (conflict_a == a1)
3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854
	    break;
	}
      if (a == a2)
	break;
    }
  return false;
}

/* The major function for aggressive allocno coalescing.  We coalesce
   only spilled allocnos.  If some allocnos have been coalesced, we
   set up flag allocno_coalesced_p.  */
static void
coalesce_allocnos (void)
{
  ira_allocno_t a;
3855
  ira_copy_t cp, next_cp;
3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866
  unsigned int j;
  int i, n, cp_num, regno;
  bitmap_iterator bi;

  cp_num = 0;
  /* Collect copies.  */
  EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, j, bi)
    {
      a = ira_allocnos[j];
      regno = ALLOCNO_REGNO (a);
      if (! ALLOCNO_ASSIGNED_P (a) || ALLOCNO_HARD_REGNO (a) >= 0
3867
	  || ira_equiv_no_lvalue_p (regno))
3868 3869 3870 3871 3872 3873 3874 3875
	continue;
      for (cp = ALLOCNO_COPIES (a); cp != NULL; cp = next_cp)
	{
	  if (cp->first == a)
	    {
	      next_cp = cp->next_first_allocno_copy;
	      regno = ALLOCNO_REGNO (cp->second);
	      /* For priority coloring we coalesce allocnos only with
Vladimir Makarov committed
3876
		 the same allocno class not with intersected allocno
3877 3878 3879 3880 3881
		 classes as it were possible.  It is done for
		 simplicity.  */
	      if ((cp->insn != NULL || cp->constraint_p)
		  && ALLOCNO_ASSIGNED_P (cp->second)
		  && ALLOCNO_HARD_REGNO (cp->second) < 0
3882
		  && ! ira_equiv_no_lvalue_p (regno))
3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916
		sorted_copies[cp_num++] = cp;
	    }
	  else if (cp->second == a)
	    next_cp = cp->next_second_allocno_copy;
	  else
	    gcc_unreachable ();
	}
    }
  qsort (sorted_copies, cp_num, sizeof (ira_copy_t), copy_freq_compare_func);
  /* Coalesced copies, most frequently executed first.  */
  for (; cp_num != 0;)
    {
      for (i = 0; i < cp_num; i++)
	{
	  cp = sorted_copies[i];
	  if (! coalesced_allocno_conflict_p (cp->first, cp->second))
	    {
	      allocno_coalesced_p = true;
	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
		fprintf
		  (ira_dump_file,
		   "      Coalescing copy %d:a%dr%d-a%dr%d (freq=%d)\n",
		   cp->num, ALLOCNO_NUM (cp->first), ALLOCNO_REGNO (cp->first),
		   ALLOCNO_NUM (cp->second), ALLOCNO_REGNO (cp->second),
		   cp->freq);
	      merge_allocnos (cp->first, cp->second);
	      i++;
	      break;
	    }
	}
      /* Collect the rest of copies.  */
      for (n = 0; i < cp_num; i++)
	{
	  cp = sorted_copies[i];
Vladimir Makarov committed
3917 3918
	  if (allocno_coalesce_data[ALLOCNO_NUM (cp->first)].first
	      != allocno_coalesce_data[ALLOCNO_NUM (cp->second)].first)
3919 3920 3921 3922 3923 3924
	    sorted_copies[n++] = cp;
	}
      cp_num = n;
    }
}

Vladimir Makarov committed
3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950
/* Usage cost and order number of coalesced allocno set to which
   given pseudo register belongs to.  */
static int *regno_coalesced_allocno_cost;
static int *regno_coalesced_allocno_num;

/* Sort pseudos according frequencies of coalesced allocno sets they
   belong to (putting most frequently ones first), and according to
   coalesced allocno set order numbers.  */
static int
coalesced_pseudo_reg_freq_compare (const void *v1p, const void *v2p)
{
  const int regno1 = *(const int *) v1p;
  const int regno2 = *(const int *) v2p;
  int diff;

  if ((diff = (regno_coalesced_allocno_cost[regno2]
	       - regno_coalesced_allocno_cost[regno1])) != 0)
    return diff;
  if ((diff = (regno_coalesced_allocno_num[regno1]
	       - regno_coalesced_allocno_num[regno2])) != 0)
    return diff;
  return regno1 - regno2;
}

/* Widest width in which each pseudo reg is referred to (via subreg).
   It is used for sorting pseudo registers.  */
3951
static machine_mode *regno_max_ref_mode;
Vladimir Makarov committed
3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963

/* Sort pseudos according their slot numbers (putting ones with
  smaller numbers first, or last when the frame pointer is not
  needed).  */
static int
coalesced_pseudo_reg_slot_compare (const void *v1p, const void *v2p)
{
  const int regno1 = *(const int *) v1p;
  const int regno2 = *(const int *) v2p;
  ira_allocno_t a1 = ira_regno_allocno_map[regno1];
  ira_allocno_t a2 = ira_regno_allocno_map[regno2];
  int diff, slot_num1, slot_num2;
3964
  machine_mode mode1, mode2;
Vladimir Makarov committed
3965 3966 3967 3968

  if (a1 == NULL || ALLOCNO_HARD_REGNO (a1) >= 0)
    {
      if (a2 == NULL || ALLOCNO_HARD_REGNO (a2) >= 0)
3969
	return regno1 - regno2;
Vladimir Makarov committed
3970 3971 3972 3973 3974 3975 3976 3977
      return 1;
    }
  else if (a2 == NULL || ALLOCNO_HARD_REGNO (a2) >= 0)
    return -1;
  slot_num1 = -ALLOCNO_HARD_REGNO (a1);
  slot_num2 = -ALLOCNO_HARD_REGNO (a2);
  if ((diff = slot_num1 - slot_num2) != 0)
    return (frame_pointer_needed
3978
	    || (!FRAME_GROWS_DOWNWARD) == STACK_GROWS_DOWNWARD ? diff : -diff);
3979 3980 3981 3982
  mode1 = wider_subreg_mode (PSEUDO_REGNO_MODE (regno1),
			     regno_max_ref_mode[regno1]);
  mode2 = wider_subreg_mode (PSEUDO_REGNO_MODE (regno2),
			     regno_max_ref_mode[regno2]);
3983 3984
  if ((diff = compare_sizes_for_sort (GET_MODE_SIZE (mode2),
				      GET_MODE_SIZE (mode1))) != 0)
Vladimir Makarov committed
3985
    return diff;
3986
  return regno1 - regno2;
Vladimir Makarov committed
3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007
}

/* Setup REGNO_COALESCED_ALLOCNO_COST and REGNO_COALESCED_ALLOCNO_NUM
   for coalesced allocno sets containing allocnos with their regnos
   given in array PSEUDO_REGNOS of length N.  */
static void
setup_coalesced_allocno_costs_and_nums (int *pseudo_regnos, int n)
{
  int i, num, regno, cost;
  ira_allocno_t allocno, a;

  for (num = i = 0; i < n; i++)
    {
      regno = pseudo_regnos[i];
      allocno = ira_regno_allocno_map[regno];
      if (allocno == NULL)
	{
	  regno_coalesced_allocno_cost[regno] = 0;
	  regno_coalesced_allocno_num[regno] = ++num;
	  continue;
	}
Vladimir Makarov committed
4008
      if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno)
Vladimir Makarov committed
4009 4010
	continue;
      num++;
Vladimir Makarov committed
4011 4012
      for (cost = 0, a = ALLOCNO_COALESCE_DATA (allocno)->next;;
	   a = ALLOCNO_COALESCE_DATA (a)->next)
Vladimir Makarov committed
4013 4014 4015 4016 4017
	{
	  cost += ALLOCNO_FREQ (a);
	  if (a == allocno)
	    break;
	}
Vladimir Makarov committed
4018 4019
      for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
	   a = ALLOCNO_COALESCE_DATA (a)->next)
Vladimir Makarov committed
4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045
	{
	  regno_coalesced_allocno_num[ALLOCNO_REGNO (a)] = num;
	  regno_coalesced_allocno_cost[ALLOCNO_REGNO (a)] = cost;
	  if (a == allocno)
	    break;
	}
    }
}

/* Collect spilled allocnos representing coalesced allocno sets (the
   first coalesced allocno).  The collected allocnos are returned
   through array SPILLED_COALESCED_ALLOCNOS.  The function returns the
   number of the collected allocnos.  The allocnos are given by their
   regnos in array PSEUDO_REGNOS of length N.  */
static int
collect_spilled_coalesced_allocnos (int *pseudo_regnos, int n,
				    ira_allocno_t *spilled_coalesced_allocnos)
{
  int i, num, regno;
  ira_allocno_t allocno;

  for (num = i = 0; i < n; i++)
    {
      regno = pseudo_regnos[i];
      allocno = ira_regno_allocno_map[regno];
      if (allocno == NULL || ALLOCNO_HARD_REGNO (allocno) >= 0
Vladimir Makarov committed
4046
	  || ALLOCNO_COALESCE_DATA (allocno)->first != allocno)
Vladimir Makarov committed
4047 4048 4049 4050 4051 4052
	continue;
      spilled_coalesced_allocnos[num++] = allocno;
    }
  return num;
}

4053 4054 4055
/* Array of live ranges of size IRA_ALLOCNOS_NUM.  Live range for
   given slot contains live ranges of coalesced allocnos assigned to
   given slot.  */
4056
static live_range_t *slot_coalesced_allocnos_live_ranges;
4057

4058 4059 4060
/* Return TRUE if coalesced allocnos represented by ALLOCNO has live
   ranges intersected with live ranges of coalesced allocnos assigned
   to slot with number N.  */
4061
static bool
4062
slot_coalesced_allocno_live_ranges_intersect_p (ira_allocno_t allocno, int n)
4063 4064 4065
{
  ira_allocno_t a;

Vladimir Makarov committed
4066 4067
  for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
       a = ALLOCNO_COALESCE_DATA (a)->next)
4068
    {
4069 4070
      int i;
      int nr = ALLOCNO_NUM_OBJECTS (a);
4071
      gcc_assert (ALLOCNO_CAP_MEMBER (a) == NULL);
4072 4073 4074
      for (i = 0; i < nr; i++)
	{
	  ira_object_t obj = ALLOCNO_OBJECT (a, i);
Vladimir Makarov committed
4075 4076 4077 4078

	  if (ira_live_ranges_intersect_p
	      (slot_coalesced_allocnos_live_ranges[n],
	       OBJECT_LIVE_RANGES (obj)))
4079 4080
	    return true;
	}
4081 4082 4083 4084 4085 4086
      if (a == allocno)
	break;
    }
  return false;
}

4087 4088
/* Update live ranges of slot to which coalesced allocnos represented
   by ALLOCNO were assigned.  */
4089
static void
4090
setup_slot_coalesced_allocno_live_ranges (ira_allocno_t allocno)
4091
{
4092
  int i, n;
4093
  ira_allocno_t a;
4094
  live_range_t r;
4095

Vladimir Makarov committed
4096 4097 4098
  n = ALLOCNO_COALESCE_DATA (allocno)->temp;
  for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
       a = ALLOCNO_COALESCE_DATA (a)->next)
4099
    {
4100
      int nr = ALLOCNO_NUM_OBJECTS (a);
4101
      gcc_assert (ALLOCNO_CAP_MEMBER (a) == NULL);
4102 4103 4104
      for (i = 0; i < nr; i++)
	{
	  ira_object_t obj = ALLOCNO_OBJECT (a, i);
Vladimir Makarov committed
4105

4106 4107 4108
	  r = ira_copy_live_range_list (OBJECT_LIVE_RANGES (obj));
	  slot_coalesced_allocnos_live_ranges[n]
	    = ira_merge_live_ranges
Vladimir Makarov committed
4109
	      (slot_coalesced_allocnos_live_ranges[n], r);
4110
	}
4111 4112 4113 4114 4115
      if (a == allocno)
	break;
    }
}

Vladimir Makarov committed
4116 4117 4118 4119 4120 4121 4122 4123
/* We have coalesced allocnos involving in copies.  Coalesce allocnos
   further in order to share the same memory stack slot.  Allocnos
   representing sets of allocnos coalesced before the call are given
   in array SPILLED_COALESCED_ALLOCNOS of length NUM.  Return TRUE if
   some allocnos were coalesced in the function.  */
static bool
coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num)
{
4124
  int i, j, n, last_coalesced_allocno_num;
Vladimir Makarov committed
4125 4126
  ira_allocno_t allocno, a;
  bool merged_p = false;
4127
  bitmap set_jump_crosses = regstat_get_setjmp_crosses ();
Vladimir Makarov committed
4128

4129
  slot_coalesced_allocnos_live_ranges
4130
    = (live_range_t *) ira_allocate (sizeof (live_range_t) * ira_allocnos_num);
4131
  memset (slot_coalesced_allocnos_live_ranges, 0,
4132
	  sizeof (live_range_t) * ira_allocnos_num);
4133
  last_coalesced_allocno_num = 0;
Vladimir Makarov committed
4134 4135 4136 4137 4138
  /* Coalesce non-conflicting spilled allocnos preferring most
     frequently used.  */
  for (i = 0; i < num; i++)
    {
      allocno = spilled_coalesced_allocnos[i];
Vladimir Makarov committed
4139
      if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno
4140
	  || bitmap_bit_p (set_jump_crosses, ALLOCNO_REGNO (allocno))
4141
	  || ira_equiv_no_lvalue_p (ALLOCNO_REGNO (allocno)))
Vladimir Makarov committed
4142 4143 4144 4145
	continue;
      for (j = 0; j < i; j++)
	{
	  a = spilled_coalesced_allocnos[j];
Vladimir Makarov committed
4146 4147
	  n = ALLOCNO_COALESCE_DATA (a)->temp;
	  if (ALLOCNO_COALESCE_DATA (a)->first == a
4148
	      && ! bitmap_bit_p (set_jump_crosses, ALLOCNO_REGNO (a))
4149
	      && ! ira_equiv_no_lvalue_p (ALLOCNO_REGNO (a))
4150
	      && ! slot_coalesced_allocno_live_ranges_intersect_p (allocno, n))
4151 4152 4153 4154 4155 4156
	    break;
	}
      if (j >= i)
	{
	  /* No coalescing: set up number for coalesced allocnos
	     represented by ALLOCNO.  */
Vladimir Makarov committed
4157
	  ALLOCNO_COALESCE_DATA (allocno)->temp = last_coalesced_allocno_num++;
4158
	  setup_slot_coalesced_allocno_live_ranges (allocno);
4159 4160 4161
	}
      else
	{
Vladimir Makarov committed
4162 4163 4164 4165 4166 4167 4168
	  allocno_coalesced_p = true;
	  merged_p = true;
	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
	    fprintf (ira_dump_file,
		     "      Coalescing spilled allocnos a%dr%d->a%dr%d\n",
		     ALLOCNO_NUM (allocno), ALLOCNO_REGNO (allocno),
		     ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
Vladimir Makarov committed
4169 4170
	  ALLOCNO_COALESCE_DATA (allocno)->temp
	    = ALLOCNO_COALESCE_DATA (a)->temp;
4171
	  setup_slot_coalesced_allocno_live_ranges (allocno);
Vladimir Makarov committed
4172
	  merge_allocnos (a, allocno);
Vladimir Makarov committed
4173
	  ira_assert (ALLOCNO_COALESCE_DATA (a)->first == a);
Vladimir Makarov committed
4174 4175
	}
    }
4176
  for (i = 0; i < ira_allocnos_num; i++)
4177
    ira_finish_live_range_list (slot_coalesced_allocnos_live_ranges[i]);
4178
  ira_free (slot_coalesced_allocnos_live_ranges);
Vladimir Makarov committed
4179 4180 4181 4182 4183 4184 4185 4186 4187 4188
  return merged_p;
}

/* Sort pseudo-register numbers in array PSEUDO_REGNOS of length N for
   subsequent assigning stack slots to them in the reload pass.  To do
   this we coalesce spilled allocnos first to decrease the number of
   memory-memory move insns.  This function is called by the
   reload.  */
void
ira_sort_regnos_for_alter_reg (int *pseudo_regnos, int n,
4189
			       machine_mode *reg_max_ref_mode)
Vladimir Makarov committed
4190 4191 4192 4193 4194 4195 4196
{
  int max_regno = max_reg_num ();
  int i, regno, num, slot_num;
  ira_allocno_t allocno, a;
  ira_allocno_iterator ai;
  ira_allocno_t *spilled_coalesced_allocnos;

4197 4198
  ira_assert (! ira_use_lra_p);

Vladimir Makarov committed
4199 4200 4201 4202 4203 4204 4205
  /* Set up allocnos can be coalesced.  */
  coloring_allocno_bitmap = ira_allocate_bitmap ();
  for (i = 0; i < n; i++)
    {
      regno = pseudo_regnos[i];
      allocno = ira_regno_allocno_map[regno];
      if (allocno != NULL)
Vladimir Makarov committed
4206
	bitmap_set_bit (coloring_allocno_bitmap, ALLOCNO_NUM (allocno));
Vladimir Makarov committed
4207 4208
    }
  allocno_coalesced_p = false;
4209
  processed_coalesced_allocno_bitmap = ira_allocate_bitmap ();
Vladimir Makarov committed
4210 4211 4212 4213 4214 4215 4216 4217 4218 4219
  allocno_coalesce_data
    = (coalesce_data_t) ira_allocate (sizeof (struct coalesce_data)
				      * ira_allocnos_num);
  /* Initialize coalesce data for allocnos.  */
  FOR_EACH_ALLOCNO (a, ai)
    {
      ALLOCNO_ADD_DATA (a) = allocno_coalesce_data + ALLOCNO_NUM (a);
      ALLOCNO_COALESCE_DATA (a)->first = a;
      ALLOCNO_COALESCE_DATA (a)->next = a;
    }
4220
  coalesce_allocnos ();
Vladimir Makarov committed
4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256
  ira_free_bitmap (coloring_allocno_bitmap);
  regno_coalesced_allocno_cost
    = (int *) ira_allocate (max_regno * sizeof (int));
  regno_coalesced_allocno_num
    = (int *) ira_allocate (max_regno * sizeof (int));
  memset (regno_coalesced_allocno_num, 0, max_regno * sizeof (int));
  setup_coalesced_allocno_costs_and_nums (pseudo_regnos, n);
  /* Sort regnos according frequencies of the corresponding coalesced
     allocno sets.  */
  qsort (pseudo_regnos, n, sizeof (int), coalesced_pseudo_reg_freq_compare);
  spilled_coalesced_allocnos
    = (ira_allocno_t *) ira_allocate (ira_allocnos_num
				      * sizeof (ira_allocno_t));
  /* Collect allocnos representing the spilled coalesced allocno
     sets.  */
  num = collect_spilled_coalesced_allocnos (pseudo_regnos, n,
					    spilled_coalesced_allocnos);
  if (flag_ira_share_spill_slots
      && coalesce_spill_slots (spilled_coalesced_allocnos, num))
    {
      setup_coalesced_allocno_costs_and_nums (pseudo_regnos, n);
      qsort (pseudo_regnos, n, sizeof (int),
	     coalesced_pseudo_reg_freq_compare);
      num = collect_spilled_coalesced_allocnos (pseudo_regnos, n,
						spilled_coalesced_allocnos);
    }
  ira_free_bitmap (processed_coalesced_allocno_bitmap);
  allocno_coalesced_p = false;
  /* Assign stack slot numbers to spilled allocno sets, use smaller
     numbers for most frequently used coalesced allocnos.  -1 is
     reserved for dynamic search of stack slots for pseudos spilled by
     the reload.  */
  slot_num = 1;
  for (i = 0; i < num; i++)
    {
      allocno = spilled_coalesced_allocnos[i];
Vladimir Makarov committed
4257
      if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno
Vladimir Makarov committed
4258
	  || ALLOCNO_HARD_REGNO (allocno) >= 0
4259
	  || ira_equiv_no_lvalue_p (ALLOCNO_REGNO (allocno)))
Vladimir Makarov committed
4260 4261 4262 4263
	continue;
      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
	fprintf (ira_dump_file, "      Slot %d (freq,size):", slot_num);
      slot_num++;
Vladimir Makarov committed
4264 4265
      for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
	   a = ALLOCNO_COALESCE_DATA (a)->next)
Vladimir Makarov committed
4266 4267 4268 4269
	{
	  ira_assert (ALLOCNO_HARD_REGNO (a) < 0);
	  ALLOCNO_HARD_REGNO (a) = -slot_num;
	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
4270 4271 4272 4273
	    {
	      machine_mode mode = wider_subreg_mode
		(PSEUDO_REGNO_MODE (ALLOCNO_REGNO (a)),
		 reg_max_ref_mode[ALLOCNO_REGNO (a)]);
4274 4275 4276 4277
	      fprintf (ira_dump_file, " a%dr%d(%d,",
		       ALLOCNO_NUM (a), ALLOCNO_REGNO (a), ALLOCNO_FREQ (a));
	      print_dec (GET_MODE_SIZE (mode), ira_dump_file, SIGNED);
	      fprintf (ira_dump_file, ")\n");
4278
	    }
H.J. Lu committed
4279

Vladimir Makarov committed
4280 4281 4282 4283 4284 4285 4286 4287 4288
	  if (a == allocno)
	    break;
	}
      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
	fprintf (ira_dump_file, "\n");
    }
  ira_spilled_reg_stack_slots_num = slot_num - 1;
  ira_free (spilled_coalesced_allocnos);
  /* Sort regnos according the slot numbers.  */
4289
  regno_max_ref_mode = reg_max_ref_mode;
Vladimir Makarov committed
4290 4291
  qsort (pseudo_regnos, n, sizeof (int), coalesced_pseudo_reg_slot_compare);
  FOR_EACH_ALLOCNO (a, ai)
Vladimir Makarov committed
4292 4293
    ALLOCNO_ADD_DATA (a) = NULL;
  ira_free (allocno_coalesce_data);
Vladimir Makarov committed
4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310
  ira_free (regno_coalesced_allocno_num);
  ira_free (regno_coalesced_allocno_cost);
}



/* This page contains code used by the reload pass to improve the
   final code.  */

/* The function is called from reload to mark changes in the
   allocation of REGNO made by the reload.  Remember that reg_renumber
   reflects the change result.  */
void
ira_mark_allocation_change (int regno)
{
  ira_allocno_t a = ira_regno_allocno_map[regno];
  int old_hard_regno, hard_regno, cost;
Vladimir Makarov committed
4311
  enum reg_class aclass = ALLOCNO_CLASS (a);
Vladimir Makarov committed
4312 4313 4314 4315 4316 4317 4318 4319 4320

  ira_assert (a != NULL);
  hard_regno = reg_renumber[regno];
  if ((old_hard_regno = ALLOCNO_HARD_REGNO (a)) == hard_regno)
    return;
  if (old_hard_regno < 0)
    cost = -ALLOCNO_MEMORY_COST (a);
  else
    {
Vladimir Makarov committed
4321
      ira_assert (ira_class_hard_reg_index[aclass][old_hard_regno] >= 0);
Vladimir Makarov committed
4322
      cost = -(ALLOCNO_HARD_REG_COSTS (a) == NULL
Vladimir Makarov committed
4323
	       ? ALLOCNO_CLASS_COST (a)
Vladimir Makarov committed
4324
	       : ALLOCNO_HARD_REG_COSTS (a)
Vladimir Makarov committed
4325
	         [ira_class_hard_reg_index[aclass][old_hard_regno]]);
4326
      update_costs_from_copies (a, false, false);
Vladimir Makarov committed
4327 4328 4329 4330 4331 4332 4333 4334
    }
  ira_overall_cost -= cost;
  ALLOCNO_HARD_REGNO (a) = hard_regno;
  if (hard_regno < 0)
    {
      ALLOCNO_HARD_REGNO (a) = -1;
      cost += ALLOCNO_MEMORY_COST (a);
    }
Vladimir Makarov committed
4335
  else if (ira_class_hard_reg_index[aclass][hard_regno] >= 0)
Vladimir Makarov committed
4336 4337
    {
      cost += (ALLOCNO_HARD_REG_COSTS (a) == NULL
Vladimir Makarov committed
4338
	       ? ALLOCNO_CLASS_COST (a)
Vladimir Makarov committed
4339
	       : ALLOCNO_HARD_REG_COSTS (a)
Vladimir Makarov committed
4340
	         [ira_class_hard_reg_index[aclass][hard_regno]]);
4341
      update_costs_from_copies (a, true, false);
Vladimir Makarov committed
4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366
    }
  else
    /* Reload changed class of the allocno.  */
    cost = 0;
  ira_overall_cost += cost;
}

/* This function is called when reload deletes memory-memory move.  In
   this case we marks that the allocation of the corresponding
   allocnos should be not changed in future.  Otherwise we risk to get
   a wrong code.  */
void
ira_mark_memory_move_deletion (int dst_regno, int src_regno)
{
  ira_allocno_t dst = ira_regno_allocno_map[dst_regno];
  ira_allocno_t src = ira_regno_allocno_map[src_regno];

  ira_assert (dst != NULL && src != NULL
	      && ALLOCNO_HARD_REGNO (dst) < 0
	      && ALLOCNO_HARD_REGNO (src) < 0);
  ALLOCNO_DONT_REASSIGN_P (dst) = true;
  ALLOCNO_DONT_REASSIGN_P (src) = true;
}

/* Try to assign a hard register (except for FORBIDDEN_REGS) to
4367
   allocno A and return TRUE in the case of success.  */
Vladimir Makarov committed
4368 4369 4370 4371
static bool
allocno_reload_assign (ira_allocno_t a, HARD_REG_SET forbidden_regs)
{
  int hard_regno;
Vladimir Makarov committed
4372
  enum reg_class aclass;
Vladimir Makarov committed
4373
  int regno = ALLOCNO_REGNO (a);
4374 4375
  HARD_REG_SET saved[2];
  int i, n;
Vladimir Makarov committed
4376

4377 4378 4379 4380
  n = ALLOCNO_NUM_OBJECTS (a);
  for (i = 0; i < n; i++)
    {
      ira_object_t obj = ALLOCNO_OBJECT (a, i);
4381
      saved[i] = OBJECT_TOTAL_CONFLICT_HARD_REGS (obj);
4382
      OBJECT_TOTAL_CONFLICT_HARD_REGS (obj) |= forbidden_regs;
4383
      if (! flag_caller_saves && ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
4384
	OBJECT_TOTAL_CONFLICT_HARD_REGS (obj) |= ira_need_caller_save_regs (a);
4385
    }
Vladimir Makarov committed
4386
  ALLOCNO_ASSIGNED_P (a) = false;
Vladimir Makarov committed
4387
  aclass = ALLOCNO_CLASS (a);
Vladimir Makarov committed
4388 4389 4390 4391 4392 4393 4394 4395
  update_curr_costs (a);
  assign_hard_reg (a, true);
  hard_regno = ALLOCNO_HARD_REGNO (a);
  reg_renumber[regno] = hard_regno;
  if (hard_regno < 0)
    ALLOCNO_HARD_REGNO (a) = -1;
  else
    {
Vladimir Makarov committed
4396 4397 4398 4399 4400 4401 4402
      ira_assert (ira_class_hard_reg_index[aclass][hard_regno] >= 0);
      ira_overall_cost
	-= (ALLOCNO_MEMORY_COST (a)
	    - (ALLOCNO_HARD_REG_COSTS (a) == NULL
	       ? ALLOCNO_CLASS_COST (a)
	       : ALLOCNO_HARD_REG_COSTS (a)[ira_class_hard_reg_index
					    [aclass][hard_regno]]));
4403
      if (ira_need_caller_save_p (a, hard_regno))
Vladimir Makarov committed
4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421
	{
	  ira_assert (flag_caller_saves);
	  caller_save_needed = 1;
	}
    }

  /* If we found a hard register, modify the RTL for the pseudo
     register to show the hard register, and mark the pseudo register
     live.  */
  if (reg_renumber[regno] >= 0)
    {
      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
	fprintf (ira_dump_file, ": reassign to %d\n", reg_renumber[regno]);
      SET_REGNO (regno_reg_rtx[regno], reg_renumber[regno]);
      mark_home_live (regno);
    }
  else if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
    fprintf (ira_dump_file, "\n");
4422 4423 4424
  for (i = 0; i < n; i++)
    {
      ira_object_t obj = ALLOCNO_OBJECT (a, i);
4425
      OBJECT_TOTAL_CONFLICT_HARD_REGS (obj) = saved[i];
4426
    }
Vladimir Makarov committed
4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455
  return reg_renumber[regno] >= 0;
}

/* Sort pseudos according their usage frequencies (putting most
   frequently ones first).  */
static int
pseudo_reg_compare (const void *v1p, const void *v2p)
{
  int regno1 = *(const int *) v1p;
  int regno2 = *(const int *) v2p;
  int diff;

  if ((diff = REG_FREQ (regno2) - REG_FREQ (regno1)) != 0)
    return diff;
  return regno1 - regno2;
}

/* Try to allocate hard registers to SPILLED_PSEUDO_REGS (there are
   NUM of them) or spilled pseudos conflicting with pseudos in
   SPILLED_PSEUDO_REGS.  Return TRUE and update SPILLED, if the
   allocation has been changed.  The function doesn't use
   BAD_SPILL_REGS and hard registers in PSEUDO_FORBIDDEN_REGS and
   PSEUDO_PREVIOUS_REGS for the corresponding pseudos.  The function
   is called by the reload pass at the end of each reload
   iteration.  */
bool
ira_reassign_pseudos (int *spilled_pseudo_regs, int num,
		      HARD_REG_SET bad_spill_regs,
		      HARD_REG_SET *pseudo_forbidden_regs,
4456 4457
		      HARD_REG_SET *pseudo_previous_regs,
		      bitmap spilled)
Vladimir Makarov committed
4458
{
4459
  int i, n, regno;
Vladimir Makarov committed
4460
  bool changed_p;
4461
  ira_allocno_t a;
Vladimir Makarov committed
4462
  HARD_REG_SET forbidden_regs;
4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473
  bitmap temp = BITMAP_ALLOC (NULL);

  /* Add pseudos which conflict with pseudos already in
     SPILLED_PSEUDO_REGS to SPILLED_PSEUDO_REGS.  This is preferable
     to allocating in two steps as some of the conflicts might have
     a higher priority than the pseudos passed in SPILLED_PSEUDO_REGS.  */
  for (i = 0; i < num; i++)
    bitmap_set_bit (temp, spilled_pseudo_regs[i]);

  for (i = 0, n = num; i < n; i++)
    {
4474
      int nr, j;
4475 4476 4477 4478
      int regno = spilled_pseudo_regs[i];
      bitmap_set_bit (temp, regno);

      a = ira_regno_allocno_map[regno];
4479 4480
      nr = ALLOCNO_NUM_OBJECTS (a);
      for (j = 0; j < nr; j++)
4481
	{
4482 4483 4484 4485 4486
	  ira_object_t conflict_obj;
	  ira_object_t obj = ALLOCNO_OBJECT (a, j);
	  ira_object_conflict_iterator oci;

	  FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
4487
	    {
4488 4489 4490
	      ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
	      if (ALLOCNO_HARD_REGNO (conflict_a) < 0
		  && ! ALLOCNO_DONT_REASSIGN_P (conflict_a)
4491
		  && bitmap_set_bit (temp, ALLOCNO_REGNO (conflict_a)))
4492 4493 4494 4495 4496 4497
		{
		  spilled_pseudo_regs[num++] = ALLOCNO_REGNO (conflict_a);
		  /* ?!? This seems wrong.  */
		  bitmap_set_bit (consideration_allocno_bitmap,
				  ALLOCNO_NUM (conflict_a));
		}
4498 4499
	    }
	}
4500
    }
Vladimir Makarov committed
4501 4502 4503 4504 4505 4506

  if (num > 1)
    qsort (spilled_pseudo_regs, num, sizeof (int), pseudo_reg_compare);
  changed_p = false;
  /* Try to assign hard registers to pseudos from
     SPILLED_PSEUDO_REGS.  */
4507
  for (i = 0; i < num; i++)
Vladimir Makarov committed
4508 4509
    {
      regno = spilled_pseudo_regs[i];
4510 4511 4512
      forbidden_regs = (bad_spill_regs
			| pseudo_forbidden_regs[regno]
			| pseudo_previous_regs[regno]);
Vladimir Makarov committed
4513 4514 4515 4516 4517 4518
      gcc_assert (reg_renumber[regno] < 0);
      a = ira_regno_allocno_map[regno];
      ira_mark_allocation_change (regno);
      ira_assert (reg_renumber[regno] < 0);
      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
	fprintf (ira_dump_file,
4519
		 "      Try Assign %d(a%d), cost=%d", regno, ALLOCNO_NUM (a),
Vladimir Makarov committed
4520
		 ALLOCNO_MEMORY_COST (a)
Vladimir Makarov committed
4521
		 - ALLOCNO_CLASS_COST (a));
Vladimir Makarov committed
4522 4523 4524 4525 4526 4527 4528
      allocno_reload_assign (a, forbidden_regs);
      if (reg_renumber[regno] >= 0)
	{
	  CLEAR_REGNO_REG_SET (spilled, regno);
	  changed_p = true;
	}
    }
4529
  BITMAP_FREE (temp);
Vladimir Makarov committed
4530 4531 4532 4533 4534 4535 4536 4537
  return changed_p;
}

/* The function is called by reload and returns already allocated
   stack slot (if any) for REGNO with given INHERENT_SIZE and
   TOTAL_SIZE.  In the case of failure to find a slot which can be
   used for REGNO, the function returns NULL.  */
rtx
4538 4539
ira_reuse_stack_slot (int regno, poly_uint64 inherent_size,
		      poly_uint64 total_size)
Vladimir Makarov committed
4540 4541 4542 4543 4544 4545 4546 4547
{
  unsigned int i;
  int slot_num, best_slot_num;
  int cost, best_cost;
  ira_copy_t cp, next_cp;
  ira_allocno_t another_allocno, allocno = ira_regno_allocno_map[regno];
  rtx x;
  bitmap_iterator bi;
4548
  class ira_spilled_reg_stack_slot *slot = NULL;
Vladimir Makarov committed
4549

4550 4551
  ira_assert (! ira_use_lra_p);

4552 4553
  ira_assert (known_eq (inherent_size, PSEUDO_REGNO_BYTES (regno))
	      && known_le (inherent_size, total_size)
Vladimir Makarov committed
4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575
	      && ALLOCNO_HARD_REGNO (allocno) < 0);
  if (! flag_ira_share_spill_slots)
    return NULL_RTX;
  slot_num = -ALLOCNO_HARD_REGNO (allocno) - 2;
  if (slot_num != -1)
    {
      slot = &ira_spilled_reg_stack_slots[slot_num];
      x = slot->mem;
    }
  else
    {
      best_cost = best_slot_num = -1;
      x = NULL_RTX;
      /* It means that the pseudo was spilled in the reload pass, try
	 to reuse a slot.  */
      for (slot_num = 0;
	   slot_num < ira_spilled_reg_stack_slots_num;
	   slot_num++)
	{
	  slot = &ira_spilled_reg_stack_slots[slot_num];
	  if (slot->mem == NULL_RTX)
	    continue;
4576 4577
	  if (maybe_lt (slot->width, total_size)
	      || maybe_lt (GET_MODE_SIZE (GET_MODE (slot->mem)), inherent_size))
Vladimir Makarov committed
4578
	    continue;
H.J. Lu committed
4579

Vladimir Makarov committed
4580 4581 4582 4583
	  EXECUTE_IF_SET_IN_BITMAP (&slot->spilled_regs,
				    FIRST_PSEUDO_REGISTER, i, bi)
	    {
	      another_allocno = ira_regno_allocno_map[i];
Vladimir Makarov committed
4584 4585
	      if (allocnos_conflict_by_live_ranges_p (allocno,
						      another_allocno))
Vladimir Makarov committed
4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619
		goto cont;
	    }
	  for (cost = 0, cp = ALLOCNO_COPIES (allocno);
	       cp != NULL;
	       cp = next_cp)
	    {
	      if (cp->first == allocno)
		{
		  next_cp = cp->next_first_allocno_copy;
		  another_allocno = cp->second;
		}
	      else if (cp->second == allocno)
		{
		  next_cp = cp->next_second_allocno_copy;
		  another_allocno = cp->first;
		}
	      else
		gcc_unreachable ();
	      if (cp->insn == NULL_RTX)
		continue;
	      if (bitmap_bit_p (&slot->spilled_regs,
				ALLOCNO_REGNO (another_allocno)))
		cost += cp->freq;
	    }
	  if (cost > best_cost)
	    {
	      best_cost = cost;
	      best_slot_num = slot_num;
	    }
	cont:
	  ;
	}
      if (best_cost >= 0)
	{
4620 4621
	  slot_num = best_slot_num;
	  slot = &ira_spilled_reg_stack_slots[slot_num];
Vladimir Makarov committed
4622 4623
	  SET_REGNO_REG_SET (&slot->spilled_regs, regno);
	  x = slot->mem;
4624
	  ALLOCNO_HARD_REGNO (allocno) = -slot_num - 2;
Vladimir Makarov committed
4625 4626 4627 4628
	}
    }
  if (x != NULL_RTX)
    {
4629
      ira_assert (known_ge (slot->width, total_size));
4630
#ifdef ENABLE_IRA_CHECKING
Vladimir Makarov committed
4631 4632 4633
      EXECUTE_IF_SET_IN_BITMAP (&slot->spilled_regs,
				FIRST_PSEUDO_REGISTER, i, bi)
	{
Vladimir Makarov committed
4634
	  ira_assert (! conflict_by_live_ranges_p (regno, i));
Vladimir Makarov committed
4635
	}
4636
#endif
Vladimir Makarov committed
4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657
      SET_REGNO_REG_SET (&slot->spilled_regs, regno);
      if (internal_flag_ira_verbose > 3 && ira_dump_file)
	{
	  fprintf (ira_dump_file, "      Assigning %d(freq=%d) slot %d of",
		   regno, REG_FREQ (regno), slot_num);
	  EXECUTE_IF_SET_IN_BITMAP (&slot->spilled_regs,
				    FIRST_PSEUDO_REGISTER, i, bi)
	    {
	      if ((unsigned) regno != i)
		fprintf (ira_dump_file, " %d", i);
	    }
	  fprintf (ira_dump_file, "\n");
	}
    }
  return x;
}

/* This is called by reload every time a new stack slot X with
   TOTAL_SIZE was allocated for REGNO.  We store this info for
   subsequent ira_reuse_stack_slot calls.  */
void
4658
ira_mark_new_stack_slot (rtx x, int regno, poly_uint64 total_size)
Vladimir Makarov committed
4659
{
4660
  class ira_spilled_reg_stack_slot *slot;
Vladimir Makarov committed
4661 4662 4663
  int slot_num;
  ira_allocno_t allocno;

4664 4665
  ira_assert (! ira_use_lra_p);

4666
  ira_assert (known_le (PSEUDO_REGNO_BYTES (regno), total_size));
Vladimir Makarov committed
4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689
  allocno = ira_regno_allocno_map[regno];
  slot_num = -ALLOCNO_HARD_REGNO (allocno) - 2;
  if (slot_num == -1)
    {
      slot_num = ira_spilled_reg_stack_slots_num++;
      ALLOCNO_HARD_REGNO (allocno) = -slot_num - 2;
    }
  slot = &ira_spilled_reg_stack_slots[slot_num];
  INIT_REG_SET (&slot->spilled_regs);
  SET_REGNO_REG_SET (&slot->spilled_regs, regno);
  slot->mem = x;
  slot->width = total_size;
  if (internal_flag_ira_verbose > 3 && ira_dump_file)
    fprintf (ira_dump_file, "      Assigning %d(freq=%d) a new slot %d\n",
	     regno, REG_FREQ (regno), slot_num);
}


/* Return spill cost for pseudo-registers whose numbers are in array
   REGNOS (with a negative number as an end marker) for reload with
   given IN and OUT for INSN.  Return also number points (through
   EXCESS_PRESSURE_LIVE_LENGTH) where the pseudo-register lives and
   the register pressure is high, number of references of the
4690 4691 4692
   pseudo-registers (through NREFS), the number of psuedo registers
   whose allocated register wouldn't need saving in the prologue
   (through CALL_USED_COUNT), and the first hard regno occupied by the
Vladimir Makarov committed
4693 4694
   pseudo-registers (through FIRST_HARD_REGNO).  */
static int
4695
calculate_spill_cost (int *regnos, rtx in, rtx out, rtx_insn *insn,
Vladimir Makarov committed
4696 4697 4698
		      int *excess_pressure_live_length,
		      int *nrefs, int *call_used_count, int *first_hard_regno)
{
4699
  int i, cost, regno, hard_regno, count, saved_cost;
Vladimir Makarov committed
4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713
  bool in_p, out_p;
  int length;
  ira_allocno_t a;

  *nrefs = 0;
  for (length = count = cost = i = 0;; i++)
    {
      regno = regnos[i];
      if (regno < 0)
	break;
      *nrefs += REG_N_REFS (regno);
      hard_regno = reg_renumber[regno];
      ira_assert (hard_regno >= 0);
      a = ira_regno_allocno_map[regno];
4714
      length += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) / ALLOCNO_NUM_OBJECTS (a);
Vladimir Makarov committed
4715
      cost += ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a);
4716 4717
      if (in_hard_reg_set_p (crtl->abi->full_reg_clobbers (),
			     ALLOCNO_MODE (a), hard_regno))
Vladimir Makarov committed
4718 4719 4720 4721 4722 4723 4724 4725 4726
	count++;
      in_p = in && REG_P (in) && (int) REGNO (in) == hard_regno;
      out_p = out && REG_P (out) && (int) REGNO (out) == hard_regno;
      if ((in_p || out_p)
	  && find_regno_note (insn, REG_DEAD, hard_regno) != NULL_RTX)
	{
	  saved_cost = 0;
	  if (in_p)
	    saved_cost += ira_memory_move_cost
Vladimir Makarov committed
4727
	                  [ALLOCNO_MODE (a)][ALLOCNO_CLASS (a)][1];
Vladimir Makarov committed
4728 4729 4730
	  if (out_p)
	    saved_cost
	      += ira_memory_move_cost
Vladimir Makarov committed
4731
	         [ALLOCNO_MODE (a)][ALLOCNO_CLASS (a)][0];
Vladimir Makarov committed
4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752
	  cost -= REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn)) * saved_cost;
	}
    }
  *excess_pressure_live_length = length;
  *call_used_count = count;
  hard_regno = -1;
  if (regnos[0] >= 0)
    {
      hard_regno = reg_renumber[regnos[0]];
    }
  *first_hard_regno = hard_regno;
  return cost;
}

/* Return TRUE if spilling pseudo-registers whose numbers are in array
   REGNOS is better than spilling pseudo-registers with numbers in
   OTHER_REGNOS for reload with given IN and OUT for INSN.  The
   function used by the reload pass to make better register spilling
   decisions.  */
bool
ira_better_spill_reload_regno_p (int *regnos, int *other_regnos,
4753
				 rtx in, rtx out, rtx_insn *insn)
Vladimir Makarov committed
4754 4755 4756 4757 4758 4759 4760
{
  int cost, other_cost;
  int length, other_length;
  int nrefs, other_nrefs;
  int call_used_count, other_call_used_count;
  int hard_regno, other_hard_regno;

H.J. Lu committed
4761
  cost = calculate_spill_cost (regnos, in, out, insn,
Vladimir Makarov committed
4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797
			       &length, &nrefs, &call_used_count, &hard_regno);
  other_cost = calculate_spill_cost (other_regnos, in, out, insn,
				     &other_length, &other_nrefs,
				     &other_call_used_count,
				     &other_hard_regno);
  if (nrefs == 0 && other_nrefs != 0)
    return true;
  if (nrefs != 0 && other_nrefs == 0)
    return false;
  if (cost != other_cost)
    return cost < other_cost;
  if (length != other_length)
    return length > other_length;
#ifdef REG_ALLOC_ORDER
  if (hard_regno >= 0 && other_hard_regno >= 0)
    return (inv_reg_alloc_order[hard_regno]
	    < inv_reg_alloc_order[other_hard_regno]);
#else
  if (call_used_count != other_call_used_count)
    return call_used_count > other_call_used_count;
#endif
  return false;
}



/* Allocate and initialize data necessary for assign_hard_reg.  */
void
ira_initiate_assign (void)
{
  sorted_allocnos
    = (ira_allocno_t *) ira_allocate (sizeof (ira_allocno_t)
				      * ira_allocnos_num);
  consideration_allocno_bitmap = ira_allocate_bitmap ();
  initiate_cost_update ();
  allocno_priorities = (int *) ira_allocate (sizeof (int) * ira_allocnos_num);
4798 4799
  sorted_copies = (ira_copy_t *) ira_allocate (ira_copies_num
					       * sizeof (ira_copy_t));
Vladimir Makarov committed
4800 4801 4802 4803 4804 4805 4806 4807 4808 4809
}

/* Deallocate data used by assign_hard_reg.  */
void
ira_finish_assign (void)
{
  ira_free (sorted_allocnos);
  ira_free_bitmap (consideration_allocno_bitmap);
  finish_cost_update ();
  ira_free (allocno_priorities);
4810
  ira_free (sorted_copies);
Vladimir Makarov committed
4811 4812 4813 4814 4815
}



/* Entry function doing color-based register allocation.  */
4816 4817
static void
color (void)
Vladimir Makarov committed
4818
{
4819
  allocno_stack_vec.create (ira_allocnos_num);
Vladimir Makarov committed
4820 4821 4822 4823
  memset (allocated_hardreg_p, 0, sizeof (allocated_hardreg_p));
  ira_initiate_assign ();
  do_coloring ();
  ira_finish_assign ();
4824
  allocno_stack_vec.release ();
Vladimir Makarov committed
4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835
  move_spill_restore ();
}



/* This page contains a simple register allocator without usage of
   allocno conflicts.  This is used for fast allocation for -O0.  */

/* Do register allocation by not using allocno conflicts.  It uses
   only allocno live ranges.  The algorithm is close to Chow's
   priority coloring.  */
4836 4837
static void
fast_allocation (void)
Vladimir Makarov committed
4838
{
4839 4840
  int i, j, k, num, class_size, hard_regno, best_hard_regno, cost, min_cost;
  int *costs;
Vladimir Makarov committed
4841 4842 4843
#ifdef STACK_REGS
  bool no_stack_reg_p;
#endif
Vladimir Makarov committed
4844
  enum reg_class aclass;
4845
  machine_mode mode;
Vladimir Makarov committed
4846 4847
  ira_allocno_t a;
  ira_allocno_iterator ai;
4848
  live_range_t r;
Vladimir Makarov committed
4849 4850 4851 4852 4853 4854 4855
  HARD_REG_SET conflict_hard_regs, *used_hard_regs;

  sorted_allocnos = (ira_allocno_t *) ira_allocate (sizeof (ira_allocno_t)
						    * ira_allocnos_num);
  num = 0;
  FOR_EACH_ALLOCNO (a, ai)
    sorted_allocnos[num++] = a;
4856 4857 4858 4859 4860 4861
  allocno_priorities = (int *) ira_allocate (sizeof (int) * ira_allocnos_num);
  setup_allocno_priorities (sorted_allocnos, num);
  used_hard_regs = (HARD_REG_SET *) ira_allocate (sizeof (HARD_REG_SET)
						  * ira_max_point);
  for (i = 0; i < ira_max_point; i++)
    CLEAR_HARD_REG_SET (used_hard_regs[i]);
4862
  qsort (sorted_allocnos, num, sizeof (ira_allocno_t),
Vladimir Makarov committed
4863 4864 4865
	 allocno_priority_compare_func);
  for (i = 0; i < num; i++)
    {
4866 4867
      int nr, l;

Vladimir Makarov committed
4868
      a = sorted_allocnos[i];
4869 4870 4871 4872 4873
      nr = ALLOCNO_NUM_OBJECTS (a);
      CLEAR_HARD_REG_SET (conflict_hard_regs);
      for (l = 0; l < nr; l++)
	{
	  ira_object_t obj = ALLOCNO_OBJECT (a, l);
4874
	  conflict_hard_regs |= OBJECT_CONFLICT_HARD_REGS (obj);
4875 4876
	  for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
	    for (j = r->start; j <= r->finish; j++)
4877
	      conflict_hard_regs |= used_hard_regs[j];
4878
	}
Vladimir Makarov committed
4879
      aclass = ALLOCNO_CLASS (a);
4880 4881
      ALLOCNO_ASSIGNED_P (a) = true;
      ALLOCNO_HARD_REGNO (a) = -1;
Vladimir Makarov committed
4882
      if (hard_reg_set_subset_p (reg_class_contents[aclass],
Vladimir Makarov committed
4883 4884 4885 4886 4887 4888
				 conflict_hard_regs))
	continue;
      mode = ALLOCNO_MODE (a);
#ifdef STACK_REGS
      no_stack_reg_p = ALLOCNO_NO_STACK_REG_P (a);
#endif
Vladimir Makarov committed
4889
      class_size = ira_class_hard_regs_num[aclass];
4890 4891 4892
      costs = ALLOCNO_HARD_REG_COSTS (a);
      min_cost = INT_MAX;
      best_hard_regno = -1;
Vladimir Makarov committed
4893 4894
      for (j = 0; j < class_size; j++)
	{
Vladimir Makarov committed
4895
	  hard_regno = ira_class_hard_regs[aclass][j];
Vladimir Makarov committed
4896 4897 4898 4899 4900
#ifdef STACK_REGS
	  if (no_stack_reg_p && FIRST_STACK_REG <= hard_regno
	      && hard_regno <= LAST_STACK_REG)
	    continue;
#endif
4901
	  if (ira_hard_reg_set_intersection_p (hard_regno, mode, conflict_hard_regs)
Vladimir Makarov committed
4902
	      || (TEST_HARD_REG_BIT
Vladimir Makarov committed
4903
		  (ira_prohibited_class_mode_regs[aclass][mode], hard_regno)))
Vladimir Makarov committed
4904
	    continue;
4905 4906 4907 4908 4909 4910 4911
	  if (costs == NULL)
	    {
	      best_hard_regno = hard_regno;
	      break;
	    }
	  cost = costs[j];
	  if (min_cost > cost)
4912
	    {
4913 4914
	      min_cost = cost;
	      best_hard_regno = hard_regno;
4915
	    }
4916 4917 4918 4919 4920 4921 4922 4923 4924
	}
      if (best_hard_regno < 0)
	continue;
      ALLOCNO_HARD_REGNO (a) = hard_regno = best_hard_regno;
      for (l = 0; l < nr; l++)
	{
	  ira_object_t obj = ALLOCNO_OBJECT (a, l);
	  for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
	    for (k = r->start; k <= r->finish; k++)
4925
	      used_hard_regs[k] |= ira_reg_mode_hard_regset[hard_regno][mode];
Vladimir Makarov committed
4926 4927 4928 4929 4930 4931 4932 4933
	}
    }
  ira_free (sorted_allocnos);
  ira_free (used_hard_regs);
  ira_free (allocno_priorities);
  if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL)
    ira_print_disposition (ira_dump_file);
}
4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947



/* Entry function doing coloring.  */
void
ira_color (void)
{
  ira_allocno_t a;
  ira_allocno_iterator ai;

  /* Setup updated costs.  */
  FOR_EACH_ALLOCNO (a, ai)
    {
      ALLOCNO_UPDATED_MEMORY_COST (a) = ALLOCNO_MEMORY_COST (a);
Vladimir Makarov committed
4948
      ALLOCNO_UPDATED_CLASS_COST (a) = ALLOCNO_CLASS_COST (a);
4949
    }
4950
  if (ira_conflicts_p)
4951 4952 4953 4954
    color ();
  else
    fast_allocation ();
}