00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "rtl.h"
00026 #include "hard-reg-set.h"
00027 #include "regs.h"
00028 #include "fibheap.h"
00029 #include "output.h"
00030 #include "target.h"
00031 #include "expr.h"
00032 #include "flags.h"
00033 #include "insn-attr.h"
00034 #include "function.h"
00035 #include "except.h"
00036 #include "tm_p.h"
00037
00038
00039
00040 typedef struct btr_def_group_s
00041 {
00042 struct btr_def_group_s *next;
00043 rtx src;
00044 struct btr_def_s *members;
00045 } *btr_def_group;
00046
00047 typedef struct btr_user_s
00048 {
00049 struct btr_user_s *next;
00050 basic_block bb;
00051 int luid;
00052 rtx insn;
00053
00054
00055
00056
00057 rtx use;
00058 int n_reaching_defs;
00059 int first_reaching_def;
00060 char other_use_this_block;
00061 } *btr_user;
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 typedef struct btr_def_s
00073 {
00074 struct btr_def_s *next_this_bb;
00075 struct btr_def_s *next_this_group;
00076 basic_block bb;
00077 int luid;
00078 rtx insn;
00079 int btr;
00080 int cost;
00081
00082
00083
00084
00085 btr_def_group group;
00086 btr_user uses;
00087
00088
00089
00090 char has_ambiguous_use;
00091
00092
00093
00094
00095
00096
00097
00098
00099 char other_btr_uses_before_def;
00100 char other_btr_uses_after_use;
00101
00102
00103
00104 char own_end;
00105 bitmap live_range;
00106 } *btr_def;
00107
00108 static int issue_rate;
00109
00110 static int basic_block_freq (basic_block);
00111 static int insn_sets_btr_p (rtx, int, int *);
00112 static rtx *find_btr_use (rtx);
00113 static int btr_referenced_p (rtx, rtx *);
00114 static int find_btr_reference (rtx *, void *);
00115 static void find_btr_def_group (btr_def_group *, btr_def);
00116 static btr_def add_btr_def (fibheap_t, basic_block, int, rtx,
00117 unsigned int, int, btr_def_group *);
00118 static btr_user new_btr_user (basic_block, int, rtx);
00119 static void dump_hard_reg_set (HARD_REG_SET);
00120 static void dump_btrs_live (int);
00121 static void note_other_use_this_block (unsigned int, btr_user);
00122 static void compute_defs_uses_and_gen (fibheap_t, btr_def *,btr_user *,
00123 sbitmap *, sbitmap *, HARD_REG_SET *);
00124 static void compute_kill (sbitmap *, sbitmap *, HARD_REG_SET *);
00125 static void compute_out (sbitmap *bb_out, sbitmap *, sbitmap *, int);
00126 static void link_btr_uses (btr_def *, btr_user *, sbitmap *, sbitmap *, int);
00127 static void build_btr_def_use_webs (fibheap_t);
00128 static int block_at_edge_of_live_range_p (int, btr_def);
00129 static void clear_btr_from_live_range (btr_def def);
00130 static void add_btr_to_live_range (btr_def, int);
00131 static void augment_live_range (bitmap, HARD_REG_SET *, basic_block,
00132 basic_block, int);
00133 static int choose_btr (HARD_REG_SET);
00134 static void combine_btr_defs (btr_def, HARD_REG_SET *);
00135 static void btr_def_live_range (btr_def, HARD_REG_SET *);
00136 static void move_btr_def (basic_block, int, btr_def, bitmap, HARD_REG_SET *);
00137 static int migrate_btr_def (btr_def, int);
00138 static void migrate_btr_defs (enum reg_class, int);
00139 static int can_move_up (basic_block, rtx, int);
00140 static void note_btr_set (rtx, rtx, void *);
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 static struct obstack migrate_btrl_obstack;
00158
00159
00160
00161 static HARD_REG_SET *btrs_live;
00162
00163
00164
00165 static HARD_REG_SET *btrs_live_at_end;
00166
00167
00168 static HARD_REG_SET all_btrs;
00169
00170
00171
00172 static int first_btr, last_btr;
00173
00174
00175
00176
00177 static int
00178 basic_block_freq (basic_block bb)
00179 {
00180 return bb->frequency;
00181 }
00182
00183 static rtx *btr_reference_found;
00184
00185
00186
00187
00188
00189 static int
00190 find_btr_reference (rtx *px, void *preg)
00191 {
00192 rtx x;
00193 int regno, i;
00194
00195 if (px == preg)
00196 return -1;
00197 x = *px;
00198 if (!REG_P (x))
00199 return 0;
00200 regno = REGNO (x);
00201 for (i = hard_regno_nregs[regno][GET_MODE (x)] - 1; i >= 0; i--)
00202 if (TEST_HARD_REG_BIT (all_btrs, regno+i))
00203 {
00204 btr_reference_found = px;
00205 return 1;
00206 }
00207 return -1;
00208 }
00209
00210
00211
00212
00213 static int
00214 btr_referenced_p (rtx x, rtx *excludep)
00215 {
00216 return for_each_rtx (&x, find_btr_reference, excludep);
00217 }
00218
00219
00220
00221
00222
00223 static int
00224 insn_sets_btr_p (rtx insn, int check_const, int *regno)
00225 {
00226 rtx set;
00227
00228 if (NONJUMP_INSN_P (insn)
00229 && (set = single_set (insn)))
00230 {
00231 rtx dest = SET_DEST (set);
00232 rtx src = SET_SRC (set);
00233
00234 if (GET_CODE (dest) == SUBREG)
00235 dest = XEXP (dest, 0);
00236
00237 if (REG_P (dest)
00238 && TEST_HARD_REG_BIT (all_btrs, REGNO (dest)))
00239 {
00240 gcc_assert (!btr_referenced_p (src, NULL));
00241
00242 if (!check_const || CONSTANT_P (src))
00243 {
00244 if (regno)
00245 *regno = REGNO (dest);
00246 return 1;
00247 }
00248 }
00249 }
00250 return 0;
00251 }
00252
00253
00254 static rtx *
00255 find_btr_use (rtx insn)
00256 {
00257 return btr_referenced_p (insn, NULL) ? btr_reference_found : NULL;
00258 }
00259
00260
00261
00262
00263 static void
00264 find_btr_def_group (btr_def_group *all_btr_def_groups, btr_def def)
00265 {
00266 if (insn_sets_btr_p (def->insn, 1, NULL))
00267 {
00268 btr_def_group this_group;
00269 rtx def_src = SET_SRC (single_set (def->insn));
00270
00271
00272
00273 for (this_group = *all_btr_def_groups;
00274 this_group != NULL;
00275 this_group = this_group->next)
00276 if (rtx_equal_p (def_src, this_group->src))
00277 break;
00278
00279 if (!this_group)
00280 {
00281 this_group = obstack_alloc (&migrate_btrl_obstack,
00282 sizeof (struct btr_def_group_s));
00283 this_group->src = def_src;
00284 this_group->members = NULL;
00285 this_group->next = *all_btr_def_groups;
00286 *all_btr_def_groups = this_group;
00287 }
00288 def->group = this_group;
00289 def->next_this_group = this_group->members;
00290 this_group->members = def;
00291 }
00292 else
00293 def->group = NULL;
00294 }
00295
00296
00297
00298
00299 static btr_def
00300 add_btr_def (fibheap_t all_btr_defs, basic_block bb, int insn_luid, rtx insn,
00301 unsigned int dest_reg, int other_btr_uses_before_def,
00302 btr_def_group *all_btr_def_groups)
00303 {
00304 btr_def this
00305 = obstack_alloc (&migrate_btrl_obstack, sizeof (struct btr_def_s));
00306 this->bb = bb;
00307 this->luid = insn_luid;
00308 this->insn = insn;
00309 this->btr = dest_reg;
00310 this->cost = basic_block_freq (bb);
00311 this->has_ambiguous_use = 0;
00312 this->other_btr_uses_before_def = other_btr_uses_before_def;
00313 this->other_btr_uses_after_use = 0;
00314 this->next_this_bb = NULL;
00315 this->next_this_group = NULL;
00316 this->uses = NULL;
00317 this->live_range = NULL;
00318 find_btr_def_group (all_btr_def_groups, this);
00319
00320 fibheap_insert (all_btr_defs, -this->cost, this);
00321
00322 if (dump_file)
00323 fprintf (dump_file,
00324 "Found target reg definition: sets %u { bb %d, insn %d }%s priority %d\n",
00325 dest_reg, bb->index, INSN_UID (insn), (this->group ? "" : ":not const"),
00326 this->cost);
00327
00328 return this;
00329 }
00330
00331
00332
00333 static btr_user
00334 new_btr_user (basic_block bb, int insn_luid, rtx insn)
00335 {
00336
00337
00338
00339
00340 rtx *usep = find_btr_use (PATTERN (insn));
00341 rtx use;
00342 btr_user user = NULL;
00343
00344 if (usep)
00345 {
00346 int unambiguous_single_use;
00347
00348
00349
00350
00351 unambiguous_single_use = !btr_referenced_p (PATTERN (insn), usep);
00352 if (!unambiguous_single_use)
00353 usep = NULL;
00354 }
00355 use = usep ? *usep : NULL_RTX;
00356 user = obstack_alloc (&migrate_btrl_obstack, sizeof (struct btr_user_s));
00357 user->bb = bb;
00358 user->luid = insn_luid;
00359 user->insn = insn;
00360 user->use = use;
00361 user->other_use_this_block = 0;
00362 user->next = NULL;
00363 user->n_reaching_defs = 0;
00364 user->first_reaching_def = -1;
00365
00366 if (dump_file)
00367 {
00368 fprintf (dump_file, "Uses target reg: { bb %d, insn %d }",
00369 bb->index, INSN_UID (insn));
00370
00371 if (user->use)
00372 fprintf (dump_file, ": unambiguous use of reg %d\n",
00373 REGNO (user->use));
00374 }
00375
00376 return user;
00377 }
00378
00379
00380 static void
00381 dump_hard_reg_set (HARD_REG_SET s)
00382 {
00383 int reg;
00384 for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
00385 if (TEST_HARD_REG_BIT (s, reg))
00386 fprintf (dump_file, " %d", reg);
00387 }
00388
00389
00390 static void
00391 dump_btrs_live (int bb)
00392 {
00393 fprintf (dump_file, "BB%d live:", bb);
00394 dump_hard_reg_set (btrs_live[bb]);
00395 fprintf (dump_file, "\n");
00396 }
00397
00398
00399
00400
00401
00402 static void
00403 note_other_use_this_block (unsigned int regno, btr_user users_this_bb)
00404 {
00405 btr_user user;
00406
00407 for (user = users_this_bb; user != NULL; user = user->next)
00408 if (user->use && REGNO (user->use) == regno)
00409 user->other_use_this_block = 1;
00410 }
00411
00412 typedef struct {
00413 btr_user users_this_bb;
00414 HARD_REG_SET btrs_written_in_block;
00415 HARD_REG_SET btrs_live_in_block;
00416 sbitmap bb_gen;
00417 sbitmap *btr_defset;
00418 } defs_uses_info;
00419
00420
00421
00422
00423
00424 static void
00425 note_btr_set (rtx dest, rtx set ATTRIBUTE_UNUSED, void *data)
00426 {
00427 defs_uses_info *info = data;
00428 int regno, end_regno;
00429
00430 if (!REG_P (dest))
00431 return;
00432 regno = REGNO (dest);
00433 end_regno = regno + hard_regno_nregs[regno][GET_MODE (dest)];
00434 for (; regno < end_regno; regno++)
00435 if (TEST_HARD_REG_BIT (all_btrs, regno))
00436 {
00437 note_other_use_this_block (regno, info->users_this_bb);
00438 SET_HARD_REG_BIT (info->btrs_written_in_block, regno);
00439 SET_HARD_REG_BIT (info->btrs_live_in_block, regno);
00440 sbitmap_difference (info->bb_gen, info->bb_gen,
00441 info->btr_defset[regno - first_btr]);
00442 }
00443 }
00444
00445 static void
00446 compute_defs_uses_and_gen (fibheap_t all_btr_defs, btr_def *def_array,
00447 btr_user *use_array, sbitmap *btr_defset,
00448 sbitmap *bb_gen, HARD_REG_SET *btrs_written)
00449 {
00450
00451
00452
00453
00454
00455
00456 int i;
00457 int insn_luid = 0;
00458 btr_def_group all_btr_def_groups = NULL;
00459 defs_uses_info info;
00460
00461 sbitmap_vector_zero (bb_gen, n_basic_blocks);
00462 for (i = 0; i < n_basic_blocks; i++)
00463 {
00464 basic_block bb = BASIC_BLOCK (i);
00465 int reg;
00466 btr_def defs_this_bb = NULL;
00467 rtx insn;
00468 rtx last;
00469 int can_throw = 0;
00470
00471 info.users_this_bb = NULL;
00472 info.bb_gen = bb_gen[i];
00473 info.btr_defset = btr_defset;
00474
00475 CLEAR_HARD_REG_SET (info.btrs_live_in_block);
00476 CLEAR_HARD_REG_SET (info.btrs_written_in_block);
00477 for (reg = first_btr; reg <= last_btr; reg++)
00478 if (TEST_HARD_REG_BIT (all_btrs, reg)
00479 && REGNO_REG_SET_P (bb->global_live_at_start, reg))
00480 SET_HARD_REG_BIT (info.btrs_live_in_block, reg);
00481
00482 for (insn = BB_HEAD (bb), last = NEXT_INSN (BB_END (bb));
00483 insn != last;
00484 insn = NEXT_INSN (insn), insn_luid++)
00485 {
00486 if (INSN_P (insn))
00487 {
00488 int regno;
00489 int insn_uid = INSN_UID (insn);
00490
00491 if (insn_sets_btr_p (insn, 0, ®no))
00492 {
00493 btr_def def = add_btr_def (
00494 all_btr_defs, bb, insn_luid, insn, regno,
00495 TEST_HARD_REG_BIT (info.btrs_live_in_block, regno),
00496 &all_btr_def_groups);
00497
00498 def_array[insn_uid] = def;
00499 SET_HARD_REG_BIT (info.btrs_written_in_block, regno);
00500 SET_HARD_REG_BIT (info.btrs_live_in_block, regno);
00501 sbitmap_difference (bb_gen[i], bb_gen[i],
00502 btr_defset[regno - first_btr]);
00503 SET_BIT (bb_gen[i], insn_uid);
00504 def->next_this_bb = defs_this_bb;
00505 defs_this_bb = def;
00506 SET_BIT (btr_defset[regno - first_btr], insn_uid);
00507 note_other_use_this_block (regno, info.users_this_bb);
00508 }
00509 else
00510 {
00511 if (btr_referenced_p (PATTERN (insn), NULL))
00512 {
00513 btr_user user = new_btr_user (bb, insn_luid, insn);
00514
00515 use_array[insn_uid] = user;
00516 if (user->use)
00517 SET_HARD_REG_BIT (info.btrs_live_in_block,
00518 REGNO (user->use));
00519 else
00520 {
00521 int reg;
00522 for (reg = first_btr; reg <= last_btr; reg++)
00523 if (TEST_HARD_REG_BIT (all_btrs, reg)
00524 && refers_to_regno_p (reg, reg + 1, user->insn,
00525 NULL))
00526 {
00527 note_other_use_this_block (reg,
00528 info.users_this_bb);
00529 SET_HARD_REG_BIT (info.btrs_live_in_block, reg);
00530 }
00531 note_stores (PATTERN (insn), note_btr_set, &info);
00532 }
00533 user->next = info.users_this_bb;
00534 info.users_this_bb = user;
00535 }
00536 if (CALL_P (insn))
00537 {
00538 HARD_REG_SET *clobbered = &call_used_reg_set;
00539 HARD_REG_SET call_saved;
00540 rtx pat = PATTERN (insn);
00541 int i;
00542
00543
00544 if (GET_CODE (pat) == PARALLEL)
00545 for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)
00546 if (GET_CODE (XVECEXP (pat, 0, i)) == RETURN)
00547 {
00548 COMPL_HARD_REG_SET (call_saved,
00549 call_used_reg_set);
00550 clobbered = &call_saved;
00551 }
00552
00553 for (regno = first_btr; regno <= last_btr; regno++)
00554 if (TEST_HARD_REG_BIT (*clobbered, regno))
00555 note_btr_set (regno_reg_rtx[regno], NULL_RTX, &info);
00556 }
00557 }
00558 }
00559 }
00560
00561 COPY_HARD_REG_SET (btrs_live[i], info.btrs_live_in_block);
00562 COPY_HARD_REG_SET (btrs_written[i], info.btrs_written_in_block);
00563
00564 REG_SET_TO_HARD_REG_SET (btrs_live_at_end[i], bb->global_live_at_end);
00565
00566
00567 for (insn = BB_END (bb); insn != BB_HEAD (bb) && ! INSN_P (insn); )
00568 insn = PREV_INSN (insn);
00569
00570
00571
00572
00573
00574 if (can_throw_internal (insn))
00575 {
00576 HARD_REG_SET tmp;
00577
00578 COPY_HARD_REG_SET (tmp, call_used_reg_set);
00579 AND_HARD_REG_SET (tmp, all_btrs);
00580 IOR_HARD_REG_SET (btrs_live_at_end[i], tmp);
00581 can_throw = 1;
00582 }
00583 if (can_throw || JUMP_P (insn))
00584 {
00585 int regno;
00586
00587 for (regno = first_btr; regno <= last_btr; regno++)
00588 if (refers_to_regno_p (regno, regno+1, insn, NULL))
00589 SET_HARD_REG_BIT (btrs_live_at_end[i], regno);
00590 }
00591
00592 if (dump_file)
00593 dump_btrs_live(i);
00594 }
00595 }
00596
00597 static void
00598 compute_kill (sbitmap *bb_kill, sbitmap *btr_defset,
00599 HARD_REG_SET *btrs_written)
00600 {
00601 int i;
00602 int regno;
00603
00604
00605
00606 sbitmap_vector_zero (bb_kill, n_basic_blocks);
00607 for (i = 0; i < n_basic_blocks; i++)
00608 {
00609 for (regno = first_btr; regno <= last_btr; regno++)
00610 if (TEST_HARD_REG_BIT (all_btrs, regno)
00611 && TEST_HARD_REG_BIT (btrs_written[i], regno))
00612 sbitmap_a_or_b (bb_kill[i], bb_kill[i],
00613 btr_defset[regno - first_btr]);
00614 }
00615 }
00616
00617 static void
00618 compute_out (sbitmap *bb_out, sbitmap *bb_gen, sbitmap *bb_kill, int max_uid)
00619 {
00620
00621
00622
00623
00624
00625
00626 int i;
00627 int changed;
00628 sbitmap bb_in = sbitmap_alloc (max_uid);
00629
00630 for (i = 0; i < n_basic_blocks; i++)
00631 sbitmap_copy (bb_out[i], bb_gen[i]);
00632
00633 changed = 1;
00634 while (changed)
00635 {
00636 changed = 0;
00637 for (i = 0; i < n_basic_blocks; i++)
00638 {
00639 sbitmap_union_of_preds (bb_in, bb_out, i);
00640 changed |= sbitmap_union_of_diff_cg (bb_out[i], bb_gen[i],
00641 bb_in, bb_kill[i]);
00642 }
00643 }
00644 sbitmap_free (bb_in);
00645 }
00646
00647 static void
00648 link_btr_uses (btr_def *def_array, btr_user *use_array, sbitmap *bb_out,
00649 sbitmap *btr_defset, int max_uid)
00650 {
00651 int i;
00652 sbitmap reaching_defs = sbitmap_alloc (max_uid);
00653
00654
00655
00656 for (i = 0; i < n_basic_blocks; i++)
00657 {
00658 basic_block bb = BASIC_BLOCK (i);
00659 rtx insn;
00660 rtx last;
00661
00662 sbitmap_union_of_preds (reaching_defs, bb_out, i);
00663 for (insn = BB_HEAD (bb), last = NEXT_INSN (BB_END (bb));
00664 insn != last;
00665 insn = NEXT_INSN (insn))
00666 {
00667 if (INSN_P (insn))
00668 {
00669 int insn_uid = INSN_UID (insn);
00670
00671 btr_def def = def_array[insn_uid];
00672 btr_user user = use_array[insn_uid];
00673 if (def != NULL)
00674 {
00675
00676
00677 sbitmap_difference (reaching_defs, reaching_defs,
00678 btr_defset[def->btr - first_btr]);
00679 SET_BIT(reaching_defs, insn_uid);
00680 }
00681
00682 if (user != NULL)
00683 {
00684
00685 sbitmap reaching_defs_of_reg = sbitmap_alloc(max_uid);
00686 int uid;
00687
00688 if (user->use)
00689 sbitmap_a_and_b (
00690 reaching_defs_of_reg,
00691 reaching_defs,
00692 btr_defset[REGNO (user->use) - first_btr]);
00693 else
00694 {
00695 int reg;
00696
00697 sbitmap_zero (reaching_defs_of_reg);
00698 for (reg = first_btr; reg <= last_btr; reg++)
00699 if (TEST_HARD_REG_BIT (all_btrs, reg)
00700 && refers_to_regno_p (reg, reg + 1, user->insn,
00701 NULL))
00702 sbitmap_a_or_b_and_c (reaching_defs_of_reg,
00703 reaching_defs_of_reg,
00704 reaching_defs,
00705 btr_defset[reg - first_btr]);
00706 }
00707 EXECUTE_IF_SET_IN_SBITMAP (reaching_defs_of_reg, 0, uid,
00708 {
00709 btr_def def = def_array[uid];
00710
00711
00712
00713 if (dump_file)
00714 fprintf (dump_file,
00715 "Def in insn %d reaches use in insn %d\n",
00716 uid, insn_uid);
00717
00718 user->n_reaching_defs++;
00719 if (!user->use)
00720 def->has_ambiguous_use = 1;
00721 if (user->first_reaching_def != -1)
00722 {
00723
00724
00725 def->has_ambiguous_use = 1;
00726 def_array[user->first_reaching_def]
00727 ->has_ambiguous_use = 1;
00728 if (dump_file)
00729 fprintf (dump_file,
00730 "(use %d has multiple reaching defs)\n",
00731 insn_uid);
00732 }
00733 else
00734 user->first_reaching_def = uid;
00735 if (user->other_use_this_block)
00736 def->other_btr_uses_after_use = 1;
00737 user->next = def->uses;
00738 def->uses = user;
00739 });
00740 sbitmap_free (reaching_defs_of_reg);
00741 }
00742
00743 if (CALL_P (insn))
00744 {
00745 int regno;
00746
00747 for (regno = first_btr; regno <= last_btr; regno++)
00748 if (TEST_HARD_REG_BIT (all_btrs, regno)
00749 && TEST_HARD_REG_BIT (call_used_reg_set, regno))
00750 sbitmap_difference (reaching_defs, reaching_defs,
00751 btr_defset[regno - first_btr]);
00752 }
00753 }
00754 }
00755 }
00756 sbitmap_free (reaching_defs);
00757 }
00758
00759 static void
00760 build_btr_def_use_webs (fibheap_t all_btr_defs)
00761 {
00762 const int max_uid = get_max_uid ();
00763 btr_def *def_array = xcalloc (max_uid, sizeof (btr_def));
00764 btr_user *use_array = xcalloc (max_uid, sizeof (btr_user));
00765 sbitmap *btr_defset = sbitmap_vector_alloc (
00766 (last_btr - first_btr) + 1, max_uid);
00767 sbitmap *bb_gen = sbitmap_vector_alloc (n_basic_blocks, max_uid);
00768 HARD_REG_SET *btrs_written = xcalloc (n_basic_blocks, sizeof (HARD_REG_SET));
00769 sbitmap *bb_kill;
00770 sbitmap *bb_out;
00771
00772 sbitmap_vector_zero (btr_defset, (last_btr - first_btr) + 1);
00773
00774 compute_defs_uses_and_gen (all_btr_defs, def_array, use_array, btr_defset,
00775 bb_gen, btrs_written);
00776
00777 bb_kill = sbitmap_vector_alloc (n_basic_blocks, max_uid);
00778 compute_kill (bb_kill, btr_defset, btrs_written);
00779 free (btrs_written);
00780
00781 bb_out = sbitmap_vector_alloc (n_basic_blocks, max_uid);
00782 compute_out (bb_out, bb_gen, bb_kill, max_uid);
00783
00784 sbitmap_vector_free (bb_gen);
00785 sbitmap_vector_free (bb_kill);
00786
00787 link_btr_uses (def_array, use_array, bb_out, btr_defset, max_uid);
00788
00789 sbitmap_vector_free (bb_out);
00790 sbitmap_vector_free (btr_defset);
00791 free (use_array);
00792 free (def_array);
00793 }
00794
00795
00796
00797
00798 static int
00799 block_at_edge_of_live_range_p (int bb, btr_def def)
00800 {
00801 if (def->other_btr_uses_before_def && BASIC_BLOCK (bb) == def->bb)
00802 return 1;
00803 else if (def->other_btr_uses_after_use)
00804 {
00805 btr_user user;
00806 for (user = def->uses; user != NULL; user = user->next)
00807 if (BASIC_BLOCK (bb) == user->bb)
00808 return 1;
00809 }
00810 return 0;
00811 }
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821 static void
00822 clear_btr_from_live_range (btr_def def)
00823 {
00824 unsigned bb;
00825 bitmap_iterator bi;
00826
00827 EXECUTE_IF_SET_IN_BITMAP (def->live_range, 0, bb, bi)
00828 {
00829 if ((!def->other_btr_uses_before_def
00830 && !def->other_btr_uses_after_use)
00831 || !block_at_edge_of_live_range_p (bb, def))
00832 {
00833 CLEAR_HARD_REG_BIT (btrs_live[bb], def->btr);
00834 CLEAR_HARD_REG_BIT (btrs_live_at_end[bb], def->btr);
00835 if (dump_file)
00836 dump_btrs_live (bb);
00837 }
00838 }
00839 if (def->own_end)
00840 CLEAR_HARD_REG_BIT (btrs_live_at_end[def->bb->index], def->btr);
00841 }
00842
00843
00844
00845
00846
00847
00848
00849 static void
00850 add_btr_to_live_range (btr_def def, int own_end)
00851 {
00852 unsigned bb;
00853 bitmap_iterator bi;
00854
00855 EXECUTE_IF_SET_IN_BITMAP (def->live_range, 0, bb, bi)
00856 {
00857 SET_HARD_REG_BIT (btrs_live[bb], def->btr);
00858 SET_HARD_REG_BIT (btrs_live_at_end[bb], def->btr);
00859 if (dump_file)
00860 dump_btrs_live (bb);
00861 }
00862 if (own_end)
00863 {
00864 SET_HARD_REG_BIT (btrs_live_at_end[def->bb->index], def->btr);
00865 def->own_end = 1;
00866 }
00867 }
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881 static void
00882 augment_live_range (bitmap live_range, HARD_REG_SET *btrs_live_in_range,
00883 basic_block head_bb, basic_block new_bb, int full_range)
00884 {
00885 basic_block *worklist, *tos;
00886
00887 tos = worklist = xmalloc (sizeof (basic_block) * (n_basic_blocks + 1));
00888
00889 if (dominated_by_p (CDI_DOMINATORS, new_bb, head_bb))
00890 {
00891 if (new_bb == head_bb)
00892 {
00893 if (full_range)
00894 IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[new_bb->index]);
00895 return;
00896 }
00897 *tos++ = new_bb;
00898 }
00899 else
00900 {
00901 edge e;
00902 edge_iterator ei;
00903 int new_block = new_bb->index;
00904
00905 gcc_assert (dominated_by_p (CDI_DOMINATORS, head_bb, new_bb));
00906
00907 IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[head_bb->index]);
00908 bitmap_set_bit (live_range, new_block);
00909
00910
00911
00912 IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live_at_end[new_block]);
00913 if (full_range)
00914 IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[new_block]);
00915 if (dump_file)
00916 {
00917 fprintf (dump_file,
00918 "Adding end of block %d and rest of %d to live range\n",
00919 new_block, head_bb->index);
00920 fprintf (dump_file,"Now live btrs are ");
00921 dump_hard_reg_set (*btrs_live_in_range);
00922 fprintf (dump_file, "\n");
00923 }
00924 FOR_EACH_EDGE (e, ei, head_bb->preds)
00925 *tos++ = e->src;
00926 }
00927
00928 while (tos != worklist)
00929 {
00930 basic_block bb = *--tos;
00931 if (!bitmap_bit_p (live_range, bb->index))
00932 {
00933 edge e;
00934 edge_iterator ei;
00935
00936 bitmap_set_bit (live_range, bb->index);
00937 IOR_HARD_REG_SET (*btrs_live_in_range,
00938 btrs_live[bb->index]);
00939
00940
00941 IOR_HARD_REG_SET (*btrs_live_in_range,
00942 btrs_live_at_end[bb->index]);
00943 if (dump_file)
00944 {
00945 fprintf (dump_file,
00946 "Adding block %d to live range\n", bb->index);
00947 fprintf (dump_file,"Now live btrs are ");
00948 dump_hard_reg_set (*btrs_live_in_range);
00949 fprintf (dump_file, "\n");
00950 }
00951
00952 FOR_EACH_EDGE (e, ei, bb->preds)
00953 {
00954 basic_block pred = e->src;
00955 if (!bitmap_bit_p (live_range, pred->index))
00956 *tos++ = pred;
00957 }
00958 }
00959 }
00960
00961 free (worklist);
00962 }
00963
00964
00965
00966 static int
00967 choose_btr (HARD_REG_SET used_btrs)
00968 {
00969 int i;
00970 GO_IF_HARD_REG_SUBSET (all_btrs, used_btrs, give_up);
00971
00972 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00973 {
00974 #ifdef REG_ALLOC_ORDER
00975 int regno = reg_alloc_order[i];
00976 #else
00977 int regno = i;
00978 #endif
00979 if (TEST_HARD_REG_BIT (all_btrs, regno)
00980 && !TEST_HARD_REG_BIT (used_btrs, regno))
00981 return regno;
00982 }
00983 give_up:
00984 return -1;
00985 }
00986
00987
00988
00989
00990
00991
00992 static void
00993 btr_def_live_range (btr_def def, HARD_REG_SET *btrs_live_in_range)
00994 {
00995 if (!def->live_range)
00996 {
00997 btr_user user;
00998
00999 def->live_range = BITMAP_ALLOC (NULL);
01000
01001 bitmap_set_bit (def->live_range, def->bb->index);
01002 COPY_HARD_REG_SET (*btrs_live_in_range,
01003 (flag_btr_bb_exclusive
01004 ? btrs_live : btrs_live_at_end)[def->bb->index]);
01005
01006 for (user = def->uses; user != NULL; user = user->next)
01007 augment_live_range (def->live_range, btrs_live_in_range,
01008 def->bb, user->bb,
01009 (flag_btr_bb_exclusive
01010 || user->insn != BB_END (def->bb)
01011 || GET_CODE (user->insn) != JUMP_INSN));
01012 }
01013 else
01014 {
01015
01016
01017
01018
01019 unsigned bb;
01020 unsigned def_bb = flag_btr_bb_exclusive ? -1 : def->bb->index;
01021 bitmap_iterator bi;
01022
01023 CLEAR_HARD_REG_SET (*btrs_live_in_range);
01024 EXECUTE_IF_SET_IN_BITMAP (def->live_range, 0, bb, bi)
01025 {
01026 IOR_HARD_REG_SET (*btrs_live_in_range,
01027 (def_bb == bb
01028 ? btrs_live_at_end : btrs_live) [bb]);
01029 }
01030 }
01031 if (!def->other_btr_uses_before_def &&
01032 !def->other_btr_uses_after_use)
01033 CLEAR_HARD_REG_BIT (*btrs_live_in_range, def->btr);
01034 }
01035
01036
01037
01038
01039 static void
01040 combine_btr_defs (btr_def def, HARD_REG_SET *btrs_live_in_range)
01041 {
01042 btr_def other_def;
01043
01044 for (other_def = def->group->members;
01045 other_def != NULL;
01046 other_def = other_def->next_this_group)
01047 {
01048 if (other_def != def
01049 && other_def->uses != NULL
01050 && ! other_def->has_ambiguous_use
01051 && dominated_by_p (CDI_DOMINATORS, other_def->bb, def->bb))
01052 {
01053
01054
01055
01056
01057 int btr;
01058 HARD_REG_SET combined_btrs_live;
01059 bitmap combined_live_range = BITMAP_ALLOC (NULL);
01060 btr_user user;
01061
01062 if (other_def->live_range == NULL)
01063 {
01064 HARD_REG_SET dummy_btrs_live_in_range;
01065 btr_def_live_range (other_def, &dummy_btrs_live_in_range);
01066 }
01067 COPY_HARD_REG_SET (combined_btrs_live, *btrs_live_in_range);
01068 bitmap_copy (combined_live_range, def->live_range);
01069
01070 for (user = other_def->uses; user != NULL; user = user->next)
01071 augment_live_range (combined_live_range, &combined_btrs_live,
01072 def->bb, user->bb,
01073 (flag_btr_bb_exclusive
01074 || user->insn != BB_END (def->bb)
01075 || GET_CODE (user->insn) != JUMP_INSN));
01076
01077 btr = choose_btr (combined_btrs_live);
01078 if (btr != -1)
01079 {
01080
01081 if (dump_file)
01082 fprintf (dump_file,
01083 "Combining def in insn %d with def in insn %d\n",
01084 INSN_UID (other_def->insn), INSN_UID (def->insn));
01085
01086 def->btr = btr;
01087 user = other_def->uses;
01088 while (user != NULL)
01089 {
01090 btr_user next = user->next;
01091
01092 user->next = def->uses;
01093 def->uses = user;
01094 user = next;
01095 }
01096
01097
01098
01099
01100
01101
01102 for (user = def->uses; user != NULL; user = user->next)
01103 remove_note (user->insn,
01104 find_regno_note (user->insn, REG_DEAD,
01105 REGNO (user->use)));
01106 clear_btr_from_live_range (other_def);
01107 other_def->uses = NULL;
01108 bitmap_copy (def->live_range, combined_live_range);
01109 if (other_def->btr == btr && other_def->other_btr_uses_after_use)
01110 def->other_btr_uses_after_use = 1;
01111 COPY_HARD_REG_SET (*btrs_live_in_range, combined_btrs_live);
01112
01113
01114 delete_insn (other_def->insn);
01115
01116 }
01117 BITMAP_FREE (combined_live_range);
01118 }
01119 }
01120 }
01121
01122
01123
01124
01125
01126
01127
01128 static void
01129 move_btr_def (basic_block new_def_bb, int btr, btr_def def, bitmap live_range,
01130 HARD_REG_SET *btrs_live_in_range)
01131 {
01132
01133
01134
01135
01136
01137 basic_block b = new_def_bb;
01138 rtx insp = BB_HEAD (b);
01139 rtx old_insn = def->insn;
01140 rtx src;
01141 rtx btr_rtx;
01142 rtx new_insn;
01143 enum machine_mode btr_mode;
01144 btr_user user;
01145 rtx set;
01146
01147 if (dump_file)
01148 fprintf(dump_file, "migrating to basic block %d, using reg %d\n",
01149 new_def_bb->index, btr);
01150
01151 clear_btr_from_live_range (def);
01152 def->btr = btr;
01153 def->bb = new_def_bb;
01154 def->luid = 0;
01155 def->cost = basic_block_freq (new_def_bb);
01156 bitmap_copy (def->live_range, live_range);
01157 combine_btr_defs (def, btrs_live_in_range);
01158 btr = def->btr;
01159 def->other_btr_uses_before_def
01160 = TEST_HARD_REG_BIT (btrs_live[b->index], btr) ? 1 : 0;
01161 add_btr_to_live_range (def, 1);
01162 if (LABEL_P (insp))
01163 insp = NEXT_INSN (insp);
01164
01165
01166
01167
01168
01169 if (def->other_btr_uses_before_def)
01170 {
01171 insp = BB_END (b);
01172 for (insp = BB_END (b); ! INSN_P (insp); insp = PREV_INSN (insp))
01173 gcc_assert (insp != BB_HEAD (b));
01174
01175 if (JUMP_P (insp) || can_throw_internal (insp))
01176 insp = PREV_INSN (insp);
01177 }
01178
01179 set = single_set (old_insn);
01180 src = SET_SRC (set);
01181 btr_mode = GET_MODE (SET_DEST (set));
01182 btr_rtx = gen_rtx_REG (btr_mode, btr);
01183
01184 new_insn = gen_move_insn (btr_rtx, src);
01185
01186
01187 def->insn = emit_insn_after (new_insn, insp);
01188
01189 regs_ever_live[btr] = 1;
01190
01191 if (dump_file)
01192 fprintf (dump_file, "New pt is insn %d, inserted after insn %d\n",
01193 INSN_UID (def->insn), INSN_UID (insp));
01194
01195
01196 delete_insn (old_insn);
01197
01198
01199
01200 for (user = def->uses; user != NULL; user = user->next)
01201 {
01202
01203
01204
01205
01206 rtx replacement_rtx;
01207 if (GET_MODE (user->use) == GET_MODE (btr_rtx)
01208 || GET_MODE (user->use) == VOIDmode)
01209 replacement_rtx = btr_rtx;
01210 else
01211 replacement_rtx = gen_rtx_REG (GET_MODE (user->use), btr);
01212 replace_rtx (user->insn, user->use, replacement_rtx);
01213 user->use = replacement_rtx;
01214 }
01215 }
01216
01217
01218
01219 static int
01220 can_move_up (basic_block bb, rtx insn, int n_insns)
01221 {
01222 while (insn != BB_HEAD (bb) && n_insns > 0)
01223 {
01224 insn = PREV_INSN (insn);
01225
01226
01227
01228 if (INSN_P (insn))
01229 n_insns--;
01230 }
01231 return n_insns <= 0;
01232 }
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253 static int
01254 migrate_btr_def (btr_def def, int min_cost)
01255 {
01256 bitmap live_range;
01257 HARD_REG_SET btrs_live_in_range;
01258 int btr_used_near_def = 0;
01259 int def_basic_block_freq;
01260 basic_block try;
01261 int give_up = 0;
01262 int def_moved = 0;
01263 btr_user user;
01264 int def_latency;
01265
01266 if (dump_file)
01267 fprintf (dump_file,
01268 "Attempting to migrate pt from insn %d (cost = %d, min_cost = %d) ... ",
01269 INSN_UID (def->insn), def->cost, min_cost);
01270
01271 if (!def->group || def->has_ambiguous_use)
01272
01273 {
01274 if (dump_file)
01275 fprintf (dump_file, "it's not migratable\n");
01276 return 0;
01277 }
01278
01279 if (!def->uses)
01280
01281
01282
01283 {
01284 if (dump_file)
01285 fprintf (dump_file, "it's already combined with another pt\n");
01286 return 0;
01287 }
01288
01289 btr_def_live_range (def, &btrs_live_in_range);
01290 live_range = BITMAP_ALLOC (NULL);
01291 bitmap_copy (live_range, def->live_range);
01292
01293 #ifdef INSN_SCHEDULING
01294 def_latency = insn_default_latency (def->insn) * issue_rate;
01295 #else
01296 def_latency = issue_rate;
01297 #endif
01298
01299 for (user = def->uses; user != NULL; user = user->next)
01300 {
01301 if (user->bb == def->bb
01302 && user->luid > def->luid
01303 && (def->luid + def_latency) > user->luid
01304 && ! can_move_up (def->bb, def->insn,
01305 (def->luid + def_latency) - user->luid))
01306 {
01307 btr_used_near_def = 1;
01308 break;
01309 }
01310 }
01311
01312 def_basic_block_freq = basic_block_freq (def->bb);
01313
01314 for (try = get_immediate_dominator (CDI_DOMINATORS, def->bb);
01315 !give_up && try && try != ENTRY_BLOCK_PTR && def->cost >= min_cost;
01316 try = get_immediate_dominator (CDI_DOMINATORS, try))
01317 {
01318
01319
01320 int try_freq = basic_block_freq (try);
01321
01322 if (dump_file)
01323 fprintf (dump_file, "trying block %d ...", try->index);
01324
01325 if (try_freq < def_basic_block_freq
01326 || (try_freq == def_basic_block_freq && btr_used_near_def))
01327 {
01328 int btr;
01329 augment_live_range (live_range, &btrs_live_in_range, def->bb, try,
01330 flag_btr_bb_exclusive);
01331 if (dump_file)
01332 {
01333 fprintf (dump_file, "Now btrs live in range are: ");
01334 dump_hard_reg_set (btrs_live_in_range);
01335 fprintf (dump_file, "\n");
01336 }
01337 btr = choose_btr (btrs_live_in_range);
01338 if (btr != -1)
01339 {
01340 move_btr_def (try, btr, def, live_range, &btrs_live_in_range);
01341 bitmap_copy(live_range, def->live_range);
01342 btr_used_near_def = 0;
01343 def_moved = 1;
01344 def_basic_block_freq = basic_block_freq (def->bb);
01345 }
01346 else
01347 {
01348
01349
01350 give_up = 1;
01351 if (dump_file)
01352 fprintf (dump_file,
01353 "giving up because there are no free target registers\n");
01354 }
01355
01356 }
01357 }
01358 if (!def_moved)
01359 {
01360 give_up = 1;
01361 if (dump_file)
01362 fprintf (dump_file, "failed to move\n");
01363 }
01364 BITMAP_FREE (live_range);
01365 return !give_up;
01366 }
01367
01368
01369
01370 static void
01371 migrate_btr_defs (enum reg_class btr_class, int allow_callee_save)
01372 {
01373 fibheap_t all_btr_defs = fibheap_new ();
01374 int reg;
01375
01376 gcc_obstack_init (&migrate_btrl_obstack);
01377 if (dump_file)
01378 {
01379 int i;
01380
01381 for (i = 0; i < n_basic_blocks; i++)
01382 {
01383 basic_block bb = BASIC_BLOCK (i);
01384 fprintf(dump_file,
01385 "Basic block %d: count = " HOST_WIDEST_INT_PRINT_DEC
01386 " loop-depth = %d idom = %d\n",
01387 i, (HOST_WIDEST_INT) bb->count, bb->loop_depth,
01388 get_immediate_dominator (CDI_DOMINATORS, bb)->index);
01389 }
01390 }
01391
01392 CLEAR_HARD_REG_SET (all_btrs);
01393 for (first_btr = -1, reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
01394 if (TEST_HARD_REG_BIT (reg_class_contents[(int) btr_class], reg)
01395 && (allow_callee_save || call_used_regs[reg] || regs_ever_live[reg]))
01396 {
01397 SET_HARD_REG_BIT (all_btrs, reg);
01398 last_btr = reg;
01399 if (first_btr < 0)
01400 first_btr = reg;
01401 }
01402
01403 btrs_live = xcalloc (n_basic_blocks, sizeof (HARD_REG_SET));
01404 btrs_live_at_end = xcalloc (n_basic_blocks, sizeof (HARD_REG_SET));
01405
01406 build_btr_def_use_webs (all_btr_defs);
01407
01408 while (!fibheap_empty (all_btr_defs))
01409 {
01410 btr_def def = fibheap_extract_min (all_btr_defs);
01411 int min_cost = -fibheap_min_key (all_btr_defs);
01412 if (migrate_btr_def (def, min_cost))
01413 {
01414 fibheap_insert (all_btr_defs, -def->cost, (void *) def);
01415 if (dump_file)
01416 {
01417 fprintf (dump_file,
01418 "Putting insn %d back on queue with priority %d\n",
01419 INSN_UID (def->insn), def->cost);
01420 }
01421 }
01422 else
01423 BITMAP_FREE (def->live_range);
01424 }
01425
01426 free (btrs_live);
01427 free (btrs_live_at_end);
01428 obstack_free (&migrate_btrl_obstack, NULL);
01429 fibheap_delete (all_btr_defs);
01430 }
01431
01432 void
01433 branch_target_load_optimize (bool after_prologue_epilogue_gen)
01434 {
01435 enum reg_class class = targetm.branch_target_register_class ();
01436 if (class != NO_REGS)
01437 {
01438
01439 if (targetm.sched.issue_rate)
01440 issue_rate = targetm.sched.issue_rate ();
01441 else
01442 issue_rate = 1;
01443
01444
01445 #if 1
01446
01447
01448 cleanup_cfg (optimize ? CLEANUP_EXPENSIVE : 0);
01449 #endif
01450
01451 life_analysis (NULL, 0);
01452
01453
01454 calculate_dominance_info (CDI_DOMINATORS);
01455 migrate_btr_defs (class,
01456 (targetm.branch_target_register_callee_saved
01457 (after_prologue_epilogue_gen)));
01458
01459 free_dominance_info (CDI_DOMINATORS);
01460
01461 update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
01462 PROP_DEATH_NOTES | PROP_REG_INFO);
01463 }
01464 }