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