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 "tm_p.h"
00028 #include "insn-config.h"
00029 #include "regs.h"
00030 #include "addresses.h"
00031 #include "hard-reg-set.h"
00032 #include "basic-block.h"
00033 #include "reload.h"
00034 #include "output.h"
00035 #include "function.h"
00036 #include "recog.h"
00037 #include "flags.h"
00038 #include "toplev.h"
00039 #include "obstack.h"
00040 #include "timevar.h"
00041 #include "tree-pass.h"
00042
00043 struct du_chain
00044 {
00045 struct du_chain *next_chain;
00046 struct du_chain *next_use;
00047
00048 rtx insn;
00049 rtx *loc;
00050 ENUM_BITFIELD(reg_class) cl : 16;
00051 unsigned int need_caller_save_reg:1;
00052 unsigned int earlyclobber:1;
00053 };
00054
00055 enum scan_actions
00056 {
00057 terminate_all_read,
00058 terminate_overlapping_read,
00059 terminate_write,
00060 terminate_dead,
00061 mark_read,
00062 mark_write,
00063
00064
00065
00066 mark_access
00067 };
00068
00069 static const char * const scan_actions_name[] =
00070 {
00071 "terminate_all_read",
00072 "terminate_overlapping_read",
00073 "terminate_write",
00074 "terminate_dead",
00075 "mark_read",
00076 "mark_write",
00077 "mark_access"
00078 };
00079
00080 static struct obstack rename_obstack;
00081
00082 static void do_replace (struct du_chain *, int);
00083 static void scan_rtx_reg (rtx, rtx *, enum reg_class,
00084 enum scan_actions, enum op_type, int);
00085 static void scan_rtx_address (rtx, rtx *, enum reg_class,
00086 enum scan_actions, enum machine_mode);
00087 static void scan_rtx (rtx, rtx *, enum reg_class, enum scan_actions,
00088 enum op_type, int);
00089 static struct du_chain *build_def_use (basic_block);
00090 static void dump_def_use_chain (struct du_chain *);
00091 static void note_sets (rtx, rtx, void *);
00092 static void clear_dead_regs (HARD_REG_SET *, enum machine_mode, rtx);
00093 static void merge_overlapping_regs (basic_block, HARD_REG_SET *,
00094 struct du_chain *);
00095
00096
00097
00098
00099 static void
00100 note_sets (rtx x, rtx set ATTRIBUTE_UNUSED, void *data)
00101 {
00102 HARD_REG_SET *pset = (HARD_REG_SET *) data;
00103 unsigned int regno;
00104 int nregs;
00105
00106 if (GET_CODE (x) == SUBREG)
00107 x = SUBREG_REG (x);
00108 if (!REG_P (x))
00109 return;
00110 regno = REGNO (x);
00111 nregs = hard_regno_nregs[regno][GET_MODE (x)];
00112
00113
00114 gcc_assert (regno + nregs <= FIRST_PSEUDO_REGISTER);
00115
00116 while (nregs-- > 0)
00117 SET_HARD_REG_BIT (*pset, regno + nregs);
00118 }
00119
00120
00121
00122
00123 static void
00124 clear_dead_regs (HARD_REG_SET *pset, enum machine_mode kind, rtx notes)
00125 {
00126 rtx note;
00127 for (note = notes; note; note = XEXP (note, 1))
00128 if (REG_NOTE_KIND (note) == kind && REG_P (XEXP (note, 0)))
00129 {
00130 rtx reg = XEXP (note, 0);
00131 unsigned int regno = REGNO (reg);
00132 int nregs = hard_regno_nregs[regno][GET_MODE (reg)];
00133
00134
00135 gcc_assert (regno + nregs <= FIRST_PSEUDO_REGISTER);
00136
00137 while (nregs-- > 0)
00138 CLEAR_HARD_REG_BIT (*pset, regno + nregs);
00139 }
00140 }
00141
00142
00143
00144
00145 static void
00146 merge_overlapping_regs (basic_block b, HARD_REG_SET *pset,
00147 struct du_chain *chain)
00148 {
00149 struct du_chain *t = chain;
00150 rtx insn;
00151 HARD_REG_SET live;
00152
00153 REG_SET_TO_HARD_REG_SET (live, b->il.rtl->global_live_at_start);
00154 insn = BB_HEAD (b);
00155 while (t)
00156 {
00157
00158
00159 while (insn != t->insn)
00160 {
00161 if (INSN_P (insn))
00162 {
00163 clear_dead_regs (&live, REG_DEAD, REG_NOTES (insn));
00164 note_stores (PATTERN (insn), note_sets, (void *) &live);
00165
00166
00167 if (t != chain)
00168 IOR_HARD_REG_SET (*pset, live);
00169 clear_dead_regs (&live, REG_UNUSED, REG_NOTES (insn));
00170 }
00171 insn = NEXT_INSN (insn);
00172 }
00173
00174 IOR_HARD_REG_SET (*pset, live);
00175
00176
00177
00178
00179 if (! t->next_use)
00180 note_stores (PATTERN (insn), note_sets, (void *) pset);
00181
00182 t = t->next_use;
00183 }
00184 }
00185
00186
00187
00188 static void
00189 regrename_optimize (void)
00190 {
00191 int tick[FIRST_PSEUDO_REGISTER];
00192 int this_tick = 0;
00193 basic_block bb;
00194 char *first_obj;
00195
00196 memset (tick, 0, sizeof tick);
00197
00198 gcc_obstack_init (&rename_obstack);
00199 first_obj = obstack_alloc (&rename_obstack, 0);
00200
00201 FOR_EACH_BB (bb)
00202 {
00203 struct du_chain *all_chains = 0;
00204 HARD_REG_SET unavailable;
00205 HARD_REG_SET regs_seen;
00206
00207 CLEAR_HARD_REG_SET (unavailable);
00208
00209 if (dump_file)
00210 fprintf (dump_file, "\nBasic block %d:\n", bb->index);
00211
00212 all_chains = build_def_use (bb);
00213
00214 if (dump_file)
00215 dump_def_use_chain (all_chains);
00216
00217 CLEAR_HARD_REG_SET (unavailable);
00218
00219 if (frame_pointer_needed)
00220 {
00221 int i;
00222
00223 for (i = hard_regno_nregs[FRAME_POINTER_REGNUM][Pmode]; i--;)
00224 SET_HARD_REG_BIT (unavailable, FRAME_POINTER_REGNUM + i);
00225
00226 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
00227 for (i = hard_regno_nregs[HARD_FRAME_POINTER_REGNUM][Pmode]; i--;)
00228 SET_HARD_REG_BIT (unavailable, HARD_FRAME_POINTER_REGNUM + i);
00229 #endif
00230 }
00231
00232 CLEAR_HARD_REG_SET (regs_seen);
00233 while (all_chains)
00234 {
00235 int new_reg, best_new_reg;
00236 int n_uses;
00237 struct du_chain *this = all_chains;
00238 struct du_chain *tmp, *last;
00239 HARD_REG_SET this_unavailable;
00240 int reg = REGNO (*this->loc);
00241 int i;
00242
00243 all_chains = this->next_chain;
00244
00245 best_new_reg = reg;
00246
00247 #if 0
00248
00249 if (! TEST_HARD_REG_BIT (regs_seen, reg))
00250 {
00251 SET_HARD_REG_BIT (regs_seen, reg);
00252 continue;
00253 }
00254 #endif
00255
00256 if (fixed_regs[reg] || global_regs[reg]
00257 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
00258 || (frame_pointer_needed && reg == HARD_FRAME_POINTER_REGNUM)
00259 #else
00260 || (frame_pointer_needed && reg == FRAME_POINTER_REGNUM)
00261 #endif
00262 )
00263 continue;
00264
00265 COPY_HARD_REG_SET (this_unavailable, unavailable);
00266
00267
00268
00269
00270 n_uses = 0;
00271 for (last = this; last->next_use; last = last->next_use)
00272 {
00273 n_uses++;
00274 IOR_COMPL_HARD_REG_SET (this_unavailable,
00275 reg_class_contents[last->cl]);
00276 }
00277 if (n_uses < 1)
00278 continue;
00279
00280 IOR_COMPL_HARD_REG_SET (this_unavailable,
00281 reg_class_contents[last->cl]);
00282
00283 if (this->need_caller_save_reg)
00284 IOR_HARD_REG_SET (this_unavailable, call_used_reg_set);
00285
00286 merge_overlapping_regs (bb, &this_unavailable, this);
00287
00288
00289
00290 for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
00291 {
00292 int nregs = hard_regno_nregs[new_reg][GET_MODE (*this->loc)];
00293
00294 for (i = nregs - 1; i >= 0; --i)
00295 if (TEST_HARD_REG_BIT (this_unavailable, new_reg + i)
00296 || fixed_regs[new_reg + i]
00297 || global_regs[new_reg + i]
00298
00299 || (! regs_ever_live[new_reg + i]
00300 && ! call_used_regs[new_reg + i])
00301 #ifdef LEAF_REGISTERS
00302
00303
00304 || (current_function_is_leaf
00305 && !LEAF_REGISTERS[new_reg + i])
00306 #endif
00307 #ifdef HARD_REGNO_RENAME_OK
00308 || ! HARD_REGNO_RENAME_OK (reg + i, new_reg + i)
00309 #endif
00310 )
00311 break;
00312 if (i >= 0)
00313 continue;
00314
00315
00316
00317 for (tmp = this; tmp; tmp = tmp->next_use)
00318 if (! HARD_REGNO_MODE_OK (new_reg, GET_MODE (*tmp->loc))
00319 || (tmp->need_caller_save_reg
00320 && ! (HARD_REGNO_CALL_PART_CLOBBERED
00321 (reg, GET_MODE (*tmp->loc)))
00322 && (HARD_REGNO_CALL_PART_CLOBBERED
00323 (new_reg, GET_MODE (*tmp->loc)))))
00324 break;
00325 if (! tmp)
00326 {
00327 if (tick[best_new_reg] > tick[new_reg])
00328 best_new_reg = new_reg;
00329 }
00330 }
00331
00332 if (dump_file)
00333 {
00334 fprintf (dump_file, "Register %s in insn %d",
00335 reg_names[reg], INSN_UID (last->insn));
00336 if (last->need_caller_save_reg)
00337 fprintf (dump_file, " crosses a call");
00338 }
00339
00340 if (best_new_reg == reg)
00341 {
00342 tick[reg] = ++this_tick;
00343 if (dump_file)
00344 fprintf (dump_file, "; no available better choice\n");
00345 continue;
00346 }
00347
00348 do_replace (this, best_new_reg);
00349 tick[best_new_reg] = ++this_tick;
00350 regs_ever_live[best_new_reg] = 1;
00351
00352 if (dump_file)
00353 fprintf (dump_file, ", renamed as %s\n", reg_names[best_new_reg]);
00354 }
00355
00356 obstack_free (&rename_obstack, first_obj);
00357 }
00358
00359 obstack_free (&rename_obstack, NULL);
00360
00361 if (dump_file)
00362 fputc ('\n', dump_file);
00363
00364 count_or_remove_death_notes (NULL, 1);
00365 update_life_info (NULL, UPDATE_LIFE_LOCAL,
00366 PROP_DEATH_NOTES);
00367 }
00368
00369 static void
00370 do_replace (struct du_chain *chain, int reg)
00371 {
00372 while (chain)
00373 {
00374 unsigned int regno = ORIGINAL_REGNO (*chain->loc);
00375 struct reg_attrs * attr = REG_ATTRS (*chain->loc);
00376
00377 *chain->loc = gen_raw_REG (GET_MODE (*chain->loc), reg);
00378 if (regno >= FIRST_PSEUDO_REGISTER)
00379 ORIGINAL_REGNO (*chain->loc) = regno;
00380 REG_ATTRS (*chain->loc) = attr;
00381 chain = chain->next_use;
00382 }
00383 }
00384
00385
00386 static struct du_chain *open_chains;
00387 static struct du_chain *closed_chains;
00388
00389 static void
00390 scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl,
00391 enum scan_actions action, enum op_type type, int earlyclobber)
00392 {
00393 struct du_chain **p;
00394 rtx x = *loc;
00395 enum machine_mode mode = GET_MODE (x);
00396 int this_regno = REGNO (x);
00397 int this_nregs = hard_regno_nregs[this_regno][mode];
00398
00399 if (action == mark_write)
00400 {
00401 if (type == OP_OUT)
00402 {
00403 struct du_chain *this
00404 = obstack_alloc (&rename_obstack, sizeof (struct du_chain));
00405 this->next_use = 0;
00406 this->next_chain = open_chains;
00407 this->loc = loc;
00408 this->insn = insn;
00409 this->cl = cl;
00410 this->need_caller_save_reg = 0;
00411 this->earlyclobber = earlyclobber;
00412 open_chains = this;
00413 }
00414 return;
00415 }
00416
00417 if ((type == OP_OUT) != (action == terminate_write || action == mark_access))
00418 return;
00419
00420 for (p = &open_chains; *p;)
00421 {
00422 struct du_chain *this = *p;
00423
00424
00425
00426
00427
00428
00429
00430
00431 if (*this->loc == cc0_rtx)
00432 p = &this->next_chain;
00433 else
00434 {
00435 int regno = REGNO (*this->loc);
00436 int nregs = hard_regno_nregs[regno][GET_MODE (*this->loc)];
00437 int exact_match = (regno == this_regno && nregs == this_nregs);
00438
00439 if (regno + nregs <= this_regno
00440 || this_regno + this_nregs <= regno)
00441 {
00442 p = &this->next_chain;
00443 continue;
00444 }
00445
00446 if (action == mark_read || action == mark_access)
00447 {
00448 gcc_assert (exact_match);
00449
00450
00451
00452
00453
00454 if (cl != NO_REGS)
00455 {
00456 this = obstack_alloc (&rename_obstack, sizeof (struct du_chain));
00457 this->next_use = 0;
00458 this->next_chain = (*p)->next_chain;
00459 this->loc = loc;
00460 this->insn = insn;
00461 this->cl = cl;
00462 this->need_caller_save_reg = 0;
00463 while (*p)
00464 p = &(*p)->next_use;
00465 *p = this;
00466 return;
00467 }
00468 }
00469
00470 if (action != terminate_overlapping_read || ! exact_match)
00471 {
00472 struct du_chain *next = this->next_chain;
00473
00474
00475
00476
00477
00478 if ((action == terminate_dead || action == terminate_write)
00479 && exact_match)
00480 {
00481 this->next_chain = closed_chains;
00482 closed_chains = this;
00483 if (dump_file)
00484 fprintf (dump_file,
00485 "Closing chain %s at insn %d (%s)\n",
00486 reg_names[REGNO (*this->loc)], INSN_UID (insn),
00487 scan_actions_name[(int) action]);
00488 }
00489 else
00490 {
00491 if (dump_file)
00492 fprintf (dump_file,
00493 "Discarding chain %s at insn %d (%s)\n",
00494 reg_names[REGNO (*this->loc)], INSN_UID (insn),
00495 scan_actions_name[(int) action]);
00496 }
00497 *p = next;
00498 }
00499 else
00500 p = &this->next_chain;
00501 }
00502 }
00503 }
00504
00505
00506
00507
00508 static void
00509 scan_rtx_address (rtx insn, rtx *loc, enum reg_class cl,
00510 enum scan_actions action, enum machine_mode mode)
00511 {
00512 rtx x = *loc;
00513 RTX_CODE code = GET_CODE (x);
00514 const char *fmt;
00515 int i, j;
00516
00517 if (action == mark_write || action == mark_access)
00518 return;
00519
00520 switch (code)
00521 {
00522 case PLUS:
00523 {
00524 rtx orig_op0 = XEXP (x, 0);
00525 rtx orig_op1 = XEXP (x, 1);
00526 RTX_CODE code0 = GET_CODE (orig_op0);
00527 RTX_CODE code1 = GET_CODE (orig_op1);
00528 rtx op0 = orig_op0;
00529 rtx op1 = orig_op1;
00530 rtx *locI = NULL;
00531 rtx *locB = NULL;
00532 enum rtx_code index_code = SCRATCH;
00533
00534 if (GET_CODE (op0) == SUBREG)
00535 {
00536 op0 = SUBREG_REG (op0);
00537 code0 = GET_CODE (op0);
00538 }
00539
00540 if (GET_CODE (op1) == SUBREG)
00541 {
00542 op1 = SUBREG_REG (op1);
00543 code1 = GET_CODE (op1);
00544 }
00545
00546 if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
00547 || code0 == ZERO_EXTEND || code1 == MEM)
00548 {
00549 locI = &XEXP (x, 0);
00550 locB = &XEXP (x, 1);
00551 index_code = GET_CODE (*locI);
00552 }
00553 else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
00554 || code1 == ZERO_EXTEND || code0 == MEM)
00555 {
00556 locI = &XEXP (x, 1);
00557 locB = &XEXP (x, 0);
00558 index_code = GET_CODE (*locI);
00559 }
00560 else if (code0 == CONST_INT || code0 == CONST
00561 || code0 == SYMBOL_REF || code0 == LABEL_REF)
00562 {
00563 locB = &XEXP (x, 1);
00564 index_code = GET_CODE (XEXP (x, 0));
00565 }
00566 else if (code1 == CONST_INT || code1 == CONST
00567 || code1 == SYMBOL_REF || code1 == LABEL_REF)
00568 {
00569 locB = &XEXP (x, 0);
00570 index_code = GET_CODE (XEXP (x, 1));
00571 }
00572 else if (code0 == REG && code1 == REG)
00573 {
00574 int index_op;
00575 unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
00576
00577 if (REGNO_OK_FOR_INDEX_P (regno0)
00578 && regno_ok_for_base_p (regno1, mode, PLUS, REG))
00579 index_op = 0;
00580 else if (REGNO_OK_FOR_INDEX_P (regno1)
00581 && regno_ok_for_base_p (regno0, mode, PLUS, REG))
00582 index_op = 1;
00583 else if (regno_ok_for_base_p (regno1, mode, PLUS, REG))
00584 index_op = 0;
00585 else if (regno_ok_for_base_p (regno0, mode, PLUS, REG))
00586 index_op = 1;
00587 else if (REGNO_OK_FOR_INDEX_P (regno1))
00588 index_op = 1;
00589 else
00590 index_op = 0;
00591
00592 locI = &XEXP (x, index_op);
00593 locB = &XEXP (x, !index_op);
00594 index_code = GET_CODE (*locI);
00595 }
00596 else if (code0 == REG)
00597 {
00598 locI = &XEXP (x, 0);
00599 locB = &XEXP (x, 1);
00600 index_code = GET_CODE (*locI);
00601 }
00602 else if (code1 == REG)
00603 {
00604 locI = &XEXP (x, 1);
00605 locB = &XEXP (x, 0);
00606 index_code = GET_CODE (*locI);
00607 }
00608
00609 if (locI)
00610 scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode);
00611 if (locB)
00612 scan_rtx_address (insn, locB, base_reg_class (mode, PLUS, index_code),
00613 action, mode);
00614
00615 return;
00616 }
00617
00618 case POST_INC:
00619 case POST_DEC:
00620 case POST_MODIFY:
00621 case PRE_INC:
00622 case PRE_DEC:
00623 case PRE_MODIFY:
00624 #ifndef AUTO_INC_DEC
00625
00626
00627 action = terminate_all_read;
00628 #endif
00629 break;
00630
00631 case MEM:
00632 scan_rtx_address (insn, &XEXP (x, 0),
00633 base_reg_class (GET_MODE (x), MEM, SCRATCH), action,
00634 GET_MODE (x));
00635 return;
00636
00637 case REG:
00638 scan_rtx_reg (insn, loc, cl, action, OP_IN, 0);
00639 return;
00640
00641 default:
00642 break;
00643 }
00644
00645 fmt = GET_RTX_FORMAT (code);
00646 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00647 {
00648 if (fmt[i] == 'e')
00649 scan_rtx_address (insn, &XEXP (x, i), cl, action, mode);
00650 else if (fmt[i] == 'E')
00651 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
00652 scan_rtx_address (insn, &XVECEXP (x, i, j), cl, action, mode);
00653 }
00654 }
00655
00656 static void
00657 scan_rtx (rtx insn, rtx *loc, enum reg_class cl,
00658 enum scan_actions action, enum op_type type, int earlyclobber)
00659 {
00660 const char *fmt;
00661 rtx x = *loc;
00662 enum rtx_code code = GET_CODE (x);
00663 int i, j;
00664
00665 code = GET_CODE (x);
00666 switch (code)
00667 {
00668 case CONST:
00669 case CONST_INT:
00670 case CONST_DOUBLE:
00671 case CONST_VECTOR:
00672 case SYMBOL_REF:
00673 case LABEL_REF:
00674 case CC0:
00675 case PC:
00676 return;
00677
00678 case REG:
00679 scan_rtx_reg (insn, loc, cl, action, type, earlyclobber);
00680 return;
00681
00682 case MEM:
00683 scan_rtx_address (insn, &XEXP (x, 0),
00684 base_reg_class (GET_MODE (x), MEM, SCRATCH), action,
00685 GET_MODE (x));
00686 return;
00687
00688 case SET:
00689 scan_rtx (insn, &SET_SRC (x), cl, action, OP_IN, 0);
00690 scan_rtx (insn, &SET_DEST (x), cl, action,
00691 GET_CODE (PATTERN (insn)) == COND_EXEC ? OP_INOUT : OP_OUT, 0);
00692 return;
00693
00694 case STRICT_LOW_PART:
00695 scan_rtx (insn, &XEXP (x, 0), cl, action, OP_INOUT, earlyclobber);
00696 return;
00697
00698 case ZERO_EXTRACT:
00699 case SIGN_EXTRACT:
00700 scan_rtx (insn, &XEXP (x, 0), cl, action,
00701 type == OP_IN ? OP_IN : OP_INOUT, earlyclobber);
00702 scan_rtx (insn, &XEXP (x, 1), cl, action, OP_IN, 0);
00703 scan_rtx (insn, &XEXP (x, 2), cl, action, OP_IN, 0);
00704 return;
00705
00706 case POST_INC:
00707 case PRE_INC:
00708 case POST_DEC:
00709 case PRE_DEC:
00710 case POST_MODIFY:
00711 case PRE_MODIFY:
00712
00713 gcc_unreachable ();
00714
00715 case CLOBBER:
00716 scan_rtx (insn, &SET_DEST (x), cl, action,
00717 GET_CODE (PATTERN (insn)) == COND_EXEC ? OP_INOUT : OP_OUT, 0);
00718 return;
00719
00720 case EXPR_LIST:
00721 scan_rtx (insn, &XEXP (x, 0), cl, action, type, 0);
00722 if (XEXP (x, 1))
00723 scan_rtx (insn, &XEXP (x, 1), cl, action, type, 0);
00724 return;
00725
00726 default:
00727 break;
00728 }
00729
00730 fmt = GET_RTX_FORMAT (code);
00731 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00732 {
00733 if (fmt[i] == 'e')
00734 scan_rtx (insn, &XEXP (x, i), cl, action, type, 0);
00735 else if (fmt[i] == 'E')
00736 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
00737 scan_rtx (insn, &XVECEXP (x, i, j), cl, action, type, 0);
00738 }
00739 }
00740
00741
00742
00743 static struct du_chain *
00744 build_def_use (basic_block bb)
00745 {
00746 rtx insn;
00747
00748 open_chains = closed_chains = NULL;
00749
00750 for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
00751 {
00752 if (INSN_P (insn))
00753 {
00754 int n_ops;
00755 rtx note;
00756 rtx old_operands[MAX_RECOG_OPERANDS];
00757 rtx old_dups[MAX_DUP_OPERANDS];
00758 int i, icode;
00759 int alt;
00760 int predicated;
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778 icode = recog_memoized (insn);
00779 extract_insn (insn);
00780 if (! constrain_operands (1))
00781 fatal_insn_not_found (insn);
00782 preprocess_constraints ();
00783 alt = which_alternative;
00784 n_ops = recog_data.n_operands;
00785
00786
00787
00788
00789
00790 predicated = GET_CODE (PATTERN (insn)) == COND_EXEC;
00791 for (i = 0; i < n_ops; ++i)
00792 {
00793 int matches = recog_op_alt[i][alt].matches;
00794 if (matches >= 0)
00795 recog_op_alt[i][alt].cl = recog_op_alt[matches][alt].cl;
00796 if (matches >= 0 || recog_op_alt[i][alt].matched >= 0
00797 || (predicated && recog_data.operand_type[i] == OP_OUT))
00798 recog_data.operand_type[i] = OP_INOUT;
00799 }
00800
00801
00802 for (i = 0; i < n_ops; i++)
00803 scan_rtx (insn, recog_data.operand_loc[i],
00804 NO_REGS, terminate_overlapping_read,
00805 recog_data.operand_type[i], 0);
00806
00807
00808
00809
00810
00811 for (i = 0; i < n_ops; i++)
00812 {
00813 old_operands[i] = recog_data.operand[i];
00814
00815
00816
00817 if (recog_data.constraints[i][0] == '\0')
00818 continue;
00819 *recog_data.operand_loc[i] = cc0_rtx;
00820 }
00821 for (i = 0; i < recog_data.n_dups; i++)
00822 {
00823 int dup_num = recog_data.dup_num[i];
00824
00825 old_dups[i] = *recog_data.dup_loc[i];
00826 *recog_data.dup_loc[i] = cc0_rtx;
00827
00828
00829
00830 if (icode >= 0
00831 && insn_data[icode].operand[dup_num].eliminable == 0)
00832 old_dups[i] = recog_data.operand[dup_num];
00833 }
00834
00835 scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_all_read,
00836 OP_IN, 0);
00837
00838 for (i = 0; i < recog_data.n_dups; i++)
00839 *recog_data.dup_loc[i] = old_dups[i];
00840 for (i = 0; i < n_ops; i++)
00841 *recog_data.operand_loc[i] = old_operands[i];
00842
00843
00844 if (CALL_P (insn) && CALL_INSN_FUNCTION_USAGE (insn))
00845 scan_rtx (insn, &CALL_INSN_FUNCTION_USAGE (insn),
00846 NO_REGS, terminate_all_read, OP_IN, 0);
00847
00848
00849
00850 if (asm_noperands (PATTERN (insn)) > 0)
00851 for (i = 0; i < n_ops; i++)
00852 {
00853 rtx *loc = recog_data.operand_loc[i];
00854 rtx op = *loc;
00855
00856 if (REG_P (op)
00857 && REGNO (op) == ORIGINAL_REGNO (op)
00858 && (recog_data.operand_type[i] == OP_IN
00859 || recog_data.operand_type[i] == OP_INOUT))
00860 scan_rtx (insn, loc, NO_REGS, terminate_all_read, OP_IN, 0);
00861 }
00862
00863
00864 for (i = 0; i < n_ops + recog_data.n_dups; i++)
00865 {
00866 int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops];
00867 rtx *loc = (i < n_ops
00868 ? recog_data.operand_loc[opn]
00869 : recog_data.dup_loc[i - n_ops]);
00870 enum reg_class cl = recog_op_alt[opn][alt].cl;
00871 enum op_type type = recog_data.operand_type[opn];
00872
00873
00874
00875
00876 if (recog_data.constraints[opn][0] == '\0')
00877 continue;
00878
00879 if (recog_op_alt[opn][alt].is_address)
00880 scan_rtx_address (insn, loc, cl, mark_read, VOIDmode);
00881 else
00882 scan_rtx (insn, loc, cl, mark_read, type, 0);
00883 }
00884
00885
00886
00887 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
00888 if (REG_NOTE_KIND (note) == REG_INC
00889 || REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR)
00890 scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_read,
00891 OP_INOUT, 0);
00892
00893
00894 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
00895 if (REG_NOTE_KIND (note) == REG_DEAD)
00896 scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
00897 OP_IN, 0);
00898
00899
00900
00901 if (CALL_P (insn))
00902 {
00903 struct du_chain *p;
00904 for (p = open_chains; p; p = p->next_chain)
00905 p->need_caller_save_reg = 1;
00906 }
00907
00908
00909
00910
00911
00912 for (i = 0; i < n_ops; i++)
00913 {
00914 old_operands[i] = recog_data.operand[i];
00915 if (recog_data.operand_type[i] == OP_INOUT)
00916 *recog_data.operand_loc[i] = cc0_rtx;
00917 }
00918 for (i = 0; i < recog_data.n_dups; i++)
00919 {
00920 int opn = recog_data.dup_num[i];
00921 old_dups[i] = *recog_data.dup_loc[i];
00922 if (recog_data.operand_type[opn] == OP_INOUT)
00923 *recog_data.dup_loc[i] = cc0_rtx;
00924 }
00925
00926 scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_write, OP_IN, 0);
00927
00928 for (i = 0; i < recog_data.n_dups; i++)
00929 *recog_data.dup_loc[i] = old_dups[i];
00930 for (i = 0; i < n_ops; i++)
00931 *recog_data.operand_loc[i] = old_operands[i];
00932
00933
00934
00935
00936
00937
00938
00939 if (asm_noperands (PATTERN (insn)) > 0)
00940 {
00941 for (i = 0; i < n_ops; i++)
00942 if (recog_data.operand_type[i] == OP_OUT)
00943 {
00944 rtx *loc = recog_data.operand_loc[i];
00945 rtx op = *loc;
00946 enum reg_class cl = recog_op_alt[i][alt].cl;
00947
00948 if (REG_P (op)
00949 && REGNO (op) == ORIGINAL_REGNO (op))
00950 continue;
00951
00952 scan_rtx (insn, loc, cl, mark_write, OP_OUT,
00953 recog_op_alt[i][alt].earlyclobber);
00954 }
00955 }
00956 else if (!CALL_P (insn))
00957 for (i = 0; i < n_ops + recog_data.n_dups; i++)
00958 {
00959 int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops];
00960 rtx *loc = (i < n_ops
00961 ? recog_data.operand_loc[opn]
00962 : recog_data.dup_loc[i - n_ops]);
00963 enum reg_class cl = recog_op_alt[opn][alt].cl;
00964
00965 if (recog_data.operand_type[opn] == OP_OUT)
00966 scan_rtx (insn, loc, cl, mark_write, OP_OUT,
00967 recog_op_alt[opn][alt].earlyclobber);
00968 }
00969
00970
00971
00972 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
00973 if (REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR)
00974 scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_access,
00975 OP_INOUT, 0);
00976
00977
00978
00979 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
00980 if (REG_NOTE_KIND (note) == REG_UNUSED)
00981 scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
00982 OP_IN, 0);
00983 }
00984 if (insn == BB_END (bb))
00985 break;
00986 }
00987
00988
00989
00990 return closed_chains;
00991 }
00992
00993
00994
00995
00996 static void
00997 dump_def_use_chain (struct du_chain *chains)
00998 {
00999 while (chains)
01000 {
01001 struct du_chain *this = chains;
01002 int r = REGNO (*this->loc);
01003 int nregs = hard_regno_nregs[r][GET_MODE (*this->loc)];
01004 fprintf (dump_file, "Register %s (%d):", reg_names[r], nregs);
01005 while (this)
01006 {
01007 fprintf (dump_file, " %d [%s]", INSN_UID (this->insn),
01008 reg_class_names[this->cl]);
01009 this = this->next_use;
01010 }
01011 fprintf (dump_file, "\n");
01012 chains = chains->next_chain;
01013 }
01014 }
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028 struct value_data_entry
01029 {
01030 enum machine_mode mode;
01031 unsigned int oldest_regno;
01032 unsigned int next_regno;
01033 };
01034
01035 struct value_data
01036 {
01037 struct value_data_entry e[FIRST_PSEUDO_REGISTER];
01038 unsigned int max_value_regs;
01039 };
01040
01041 static void kill_value_one_regno (unsigned, struct value_data *);
01042 static void kill_value_regno (unsigned, unsigned, struct value_data *);
01043 static void kill_value (rtx, struct value_data *);
01044 static void set_value_regno (unsigned, enum machine_mode, struct value_data *);
01045 static void init_value_data (struct value_data *);
01046 static void kill_clobbered_value (rtx, rtx, void *);
01047 static void kill_set_value (rtx, rtx, void *);
01048 static int kill_autoinc_value (rtx *, void *);
01049 static void copy_value (rtx, rtx, struct value_data *);
01050 static bool mode_change_ok (enum machine_mode, enum machine_mode,
01051 unsigned int);
01052 static rtx maybe_mode_change (enum machine_mode, enum machine_mode,
01053 enum machine_mode, unsigned int, unsigned int);
01054 static rtx find_oldest_value_reg (enum reg_class, rtx, struct value_data *);
01055 static bool replace_oldest_value_reg (rtx *, enum reg_class, rtx,
01056 struct value_data *);
01057 static bool replace_oldest_value_addr (rtx *, enum reg_class,
01058 enum machine_mode, rtx,
01059 struct value_data *);
01060 static bool replace_oldest_value_mem (rtx, rtx, struct value_data *);
01061 static bool copyprop_hardreg_forward_1 (basic_block, struct value_data *);
01062 extern void debug_value_data (struct value_data *);
01063 #ifdef ENABLE_CHECKING
01064 static void validate_value_data (struct value_data *);
01065 #endif
01066
01067
01068
01069
01070
01071
01072 static void
01073 kill_value_one_regno (unsigned int regno, struct value_data *vd)
01074 {
01075 unsigned int i, next;
01076
01077 if (vd->e[regno].oldest_regno != regno)
01078 {
01079 for (i = vd->e[regno].oldest_regno;
01080 vd->e[i].next_regno != regno;
01081 i = vd->e[i].next_regno)
01082 continue;
01083 vd->e[i].next_regno = vd->e[regno].next_regno;
01084 }
01085 else if ((next = vd->e[regno].next_regno) != INVALID_REGNUM)
01086 {
01087 for (i = next; i != INVALID_REGNUM; i = vd->e[i].next_regno)
01088 vd->e[i].oldest_regno = next;
01089 }
01090
01091 vd->e[regno].mode = VOIDmode;
01092 vd->e[regno].oldest_regno = regno;
01093 vd->e[regno].next_regno = INVALID_REGNUM;
01094
01095 #ifdef ENABLE_CHECKING
01096 validate_value_data (vd);
01097 #endif
01098 }
01099
01100
01101
01102
01103 static void
01104 kill_value_regno (unsigned int regno, unsigned int nregs,
01105 struct value_data *vd)
01106 {
01107 unsigned int j;
01108
01109
01110 for (j = 0; j < nregs; ++j)
01111 kill_value_one_regno (regno + j, vd);
01112
01113
01114 if (regno < vd->max_value_regs)
01115 j = 0;
01116 else
01117 j = regno - vd->max_value_regs;
01118 for (; j < regno; ++j)
01119 {
01120 unsigned int i, n;
01121 if (vd->e[j].mode == VOIDmode)
01122 continue;
01123 n = hard_regno_nregs[j][vd->e[j].mode];
01124 if (j + n > regno)
01125 for (i = 0; i < n; ++i)
01126 kill_value_one_regno (j + i, vd);
01127 }
01128 }
01129
01130
01131
01132
01133 static void
01134 kill_value (rtx x, struct value_data *vd)
01135 {
01136 rtx orig_rtx = x;
01137
01138 if (GET_CODE (x) == SUBREG)
01139 {
01140 x = simplify_subreg (GET_MODE (x), SUBREG_REG (x),
01141 GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
01142 if (x == NULL_RTX)
01143 x = SUBREG_REG (orig_rtx);
01144 }
01145 if (REG_P (x))
01146 {
01147 unsigned int regno = REGNO (x);
01148 unsigned int n = hard_regno_nregs[regno][GET_MODE (x)];
01149
01150 kill_value_regno (regno, n, vd);
01151 }
01152 }
01153
01154
01155
01156 static void
01157 set_value_regno (unsigned int regno, enum machine_mode mode,
01158 struct value_data *vd)
01159 {
01160 unsigned int nregs;
01161
01162 vd->e[regno].mode = mode;
01163
01164 nregs = hard_regno_nregs[regno][mode];
01165 if (nregs > vd->max_value_regs)
01166 vd->max_value_regs = nregs;
01167 }
01168
01169
01170
01171 static void
01172 init_value_data (struct value_data *vd)
01173 {
01174 int i;
01175 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
01176 {
01177 vd->e[i].mode = VOIDmode;
01178 vd->e[i].oldest_regno = i;
01179 vd->e[i].next_regno = INVALID_REGNUM;
01180 }
01181 vd->max_value_regs = 0;
01182 }
01183
01184
01185
01186 static void
01187 kill_clobbered_value (rtx x, rtx set, void *data)
01188 {
01189 struct value_data *vd = data;
01190 if (GET_CODE (set) == CLOBBER)
01191 kill_value (x, vd);
01192 }
01193
01194
01195
01196
01197 static void
01198 kill_set_value (rtx x, rtx set, void *data)
01199 {
01200 struct value_data *vd = data;
01201 if (GET_CODE (set) != CLOBBER)
01202 {
01203 kill_value (x, vd);
01204 if (REG_P (x))
01205 set_value_regno (REGNO (x), GET_MODE (x), vd);
01206 }
01207 }
01208
01209
01210
01211
01212
01213 static int
01214 kill_autoinc_value (rtx *px, void *data)
01215 {
01216 rtx x = *px;
01217 struct value_data *vd = data;
01218
01219 if (GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC)
01220 {
01221 x = XEXP (x, 0);
01222 kill_value (x, vd);
01223 set_value_regno (REGNO (x), Pmode, vd);
01224 return -1;
01225 }
01226
01227 return 0;
01228 }
01229
01230
01231
01232
01233 static void
01234 copy_value (rtx dest, rtx src, struct value_data *vd)
01235 {
01236 unsigned int dr = REGNO (dest);
01237 unsigned int sr = REGNO (src);
01238 unsigned int dn, sn;
01239 unsigned int i;
01240
01241
01242
01243 if (sr == dr)
01244 return;
01245
01246
01247
01248 if (dr == STACK_POINTER_REGNUM)
01249 return;
01250
01251
01252 if (frame_pointer_needed && dr == HARD_FRAME_POINTER_REGNUM)
01253 return;
01254
01255
01256
01257
01258 if (fixed_regs[dr] || global_regs[dr])
01259 return;
01260
01261
01262 dn = hard_regno_nregs[dr][GET_MODE (dest)];
01263 sn = hard_regno_nregs[sr][GET_MODE (dest)];
01264 if ((dr > sr && dr < sr + sn)
01265 || (sr > dr && sr < dr + dn))
01266 return;
01267
01268
01269
01270
01271 if (vd->e[sr].mode == VOIDmode)
01272 set_value_regno (sr, vd->e[dr].mode, vd);
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289 else if (sn < (unsigned int) hard_regno_nregs[sr][vd->e[sr].mode]
01290 && (GET_MODE_SIZE (vd->e[sr].mode) > UNITS_PER_WORD
01291 ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
01292 return;
01293
01294
01295
01296
01297 else if (sn > (unsigned int) hard_regno_nregs[sr][vd->e[sr].mode])
01298 return;
01299
01300
01301
01302 vd->e[dr].oldest_regno = vd->e[sr].oldest_regno;
01303
01304 for (i = sr; vd->e[i].next_regno != INVALID_REGNUM; i = vd->e[i].next_regno)
01305 continue;
01306 vd->e[i].next_regno = dr;
01307
01308 #ifdef ENABLE_CHECKING
01309 validate_value_data (vd);
01310 #endif
01311 }
01312
01313
01314
01315 static bool
01316 mode_change_ok (enum machine_mode orig_mode, enum machine_mode new_mode,
01317 unsigned int regno ATTRIBUTE_UNUSED)
01318 {
01319 if (GET_MODE_SIZE (orig_mode) < GET_MODE_SIZE (new_mode))
01320 return false;
01321
01322 #ifdef CANNOT_CHANGE_MODE_CLASS
01323 return !REG_CANNOT_CHANGE_MODE_P (regno, orig_mode, new_mode);
01324 #endif
01325
01326 return true;
01327 }
01328
01329
01330
01331
01332
01333
01334 static rtx
01335 maybe_mode_change (enum machine_mode orig_mode, enum machine_mode copy_mode,
01336 enum machine_mode new_mode, unsigned int regno,
01337 unsigned int copy_regno ATTRIBUTE_UNUSED)
01338 {
01339 if (orig_mode == new_mode)
01340 return gen_rtx_raw_REG (new_mode, regno);
01341 else if (mode_change_ok (orig_mode, new_mode, regno))
01342 {
01343 int copy_nregs = hard_regno_nregs[copy_regno][copy_mode];
01344 int use_nregs = hard_regno_nregs[copy_regno][new_mode];
01345 int copy_offset
01346 = GET_MODE_SIZE (copy_mode) / copy_nregs * (copy_nregs - use_nregs);
01347 int offset
01348 = GET_MODE_SIZE (orig_mode) - GET_MODE_SIZE (new_mode) - copy_offset;
01349 int byteoffset = offset % UNITS_PER_WORD;
01350 int wordoffset = offset - byteoffset;
01351
01352 offset = ((WORDS_BIG_ENDIAN ? wordoffset : 0)
01353 + (BYTES_BIG_ENDIAN ? byteoffset : 0));
01354 return gen_rtx_raw_REG (new_mode,
01355 regno + subreg_regno_offset (regno, orig_mode,
01356 offset,
01357 new_mode));
01358 }
01359 return NULL_RTX;
01360 }
01361
01362
01363
01364
01365
01366 static rtx
01367 find_oldest_value_reg (enum reg_class cl, rtx reg, struct value_data *vd)
01368 {
01369 unsigned int regno = REGNO (reg);
01370 enum machine_mode mode = GET_MODE (reg);
01371 unsigned int i;
01372
01373
01374
01375
01376
01377
01378
01379
01380 if (mode != vd->e[regno].mode)
01381 {
01382 if (hard_regno_nregs[regno][mode]
01383 > hard_regno_nregs[regno][vd->e[regno].mode])
01384 return NULL_RTX;
01385 }
01386
01387 for (i = vd->e[regno].oldest_regno; i != regno; i = vd->e[i].next_regno)
01388 {
01389 enum machine_mode oldmode = vd->e[i].mode;
01390 rtx new;
01391 unsigned int last;
01392
01393 for (last = i; last < i + hard_regno_nregs[i][mode]; last++)
01394 if (!TEST_HARD_REG_BIT (reg_class_contents[cl], last))
01395 return NULL_RTX;
01396
01397 new = maybe_mode_change (oldmode, vd->e[regno].mode, mode, i, regno);
01398 if (new)
01399 {
01400 ORIGINAL_REGNO (new) = ORIGINAL_REGNO (reg);
01401 REG_ATTRS (new) = REG_ATTRS (reg);
01402 return new;
01403 }
01404 }
01405
01406 return NULL_RTX;
01407 }
01408
01409
01410
01411
01412 static bool
01413 replace_oldest_value_reg (rtx *loc, enum reg_class cl, rtx insn,
01414 struct value_data *vd)
01415 {
01416 rtx new = find_oldest_value_reg (cl, *loc, vd);
01417 if (new)
01418 {
01419 if (dump_file)
01420 fprintf (dump_file, "insn %u: replaced reg %u with %u\n",
01421 INSN_UID (insn), REGNO (*loc), REGNO (new));
01422
01423 validate_change (insn, loc, new, 1);
01424 return true;
01425 }
01426 return false;
01427 }
01428
01429
01430
01431
01432
01433 static bool
01434 replace_oldest_value_addr (rtx *loc, enum reg_class cl,
01435 enum machine_mode mode, rtx insn,
01436 struct value_data *vd)
01437 {
01438 rtx x = *loc;
01439 RTX_CODE code = GET_CODE (x);
01440 const char *fmt;
01441 int i, j;
01442 bool changed = false;
01443
01444 switch (code)
01445 {
01446 case PLUS:
01447 {
01448 rtx orig_op0 = XEXP (x, 0);
01449 rtx orig_op1 = XEXP (x, 1);
01450 RTX_CODE code0 = GET_CODE (orig_op0);
01451 RTX_CODE code1 = GET_CODE (orig_op1);
01452 rtx op0 = orig_op0;
01453 rtx op1 = orig_op1;
01454 rtx *locI = NULL;
01455 rtx *locB = NULL;
01456 enum rtx_code index_code = SCRATCH;
01457
01458 if (GET_CODE (op0) == SUBREG)
01459 {
01460 op0 = SUBREG_REG (op0);
01461 code0 = GET_CODE (op0);
01462 }
01463
01464 if (GET_CODE (op1) == SUBREG)
01465 {
01466 op1 = SUBREG_REG (op1);
01467 code1 = GET_CODE (op1);
01468 }
01469
01470 if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
01471 || code0 == ZERO_EXTEND || code1 == MEM)
01472 {
01473 locI = &XEXP (x, 0);
01474 locB = &XEXP (x, 1);
01475 index_code = GET_CODE (*locI);
01476 }
01477 else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
01478 || code1 == ZERO_EXTEND || code0 == MEM)
01479 {
01480 locI = &XEXP (x, 1);
01481 locB = &XEXP (x, 0);
01482 index_code = GET_CODE (*locI);
01483 }
01484 else if (code0 == CONST_INT || code0 == CONST
01485 || code0 == SYMBOL_REF || code0 == LABEL_REF)
01486 {
01487 locB = &XEXP (x, 1);
01488 index_code = GET_CODE (XEXP (x, 0));
01489 }
01490 else if (code1 == CONST_INT || code1 == CONST
01491 || code1 == SYMBOL_REF || code1 == LABEL_REF)
01492 {
01493 locB = &XEXP (x, 0);
01494 index_code = GET_CODE (XEXP (x, 1));
01495 }
01496 else if (code0 == REG && code1 == REG)
01497 {
01498 int index_op;
01499 unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
01500
01501 if (REGNO_OK_FOR_INDEX_P (regno0)
01502 && regno_ok_for_base_p (regno1, mode, PLUS, REG))
01503 index_op = 0;
01504 else if (REGNO_OK_FOR_INDEX_P (regno1)
01505 && regno_ok_for_base_p (regno0, mode, PLUS, REG))
01506 index_op = 1;
01507 else if (regno_ok_for_base_p (regno1, mode, PLUS, REG))
01508 index_op = 0;
01509 else if (regno_ok_for_base_p (regno0, mode, PLUS, REG))
01510 index_op = 1;
01511 else if (REGNO_OK_FOR_INDEX_P (regno1))
01512 index_op = 1;
01513 else
01514 index_op = 0;
01515
01516 locI = &XEXP (x, index_op);
01517 locB = &XEXP (x, !index_op);
01518 index_code = GET_CODE (*locI);
01519 }
01520 else if (code0 == REG)
01521 {
01522 locI = &XEXP (x, 0);
01523 locB = &XEXP (x, 1);
01524 index_code = GET_CODE (*locI);
01525 }
01526 else if (code1 == REG)
01527 {
01528 locI = &XEXP (x, 1);
01529 locB = &XEXP (x, 0);
01530 index_code = GET_CODE (*locI);
01531 }
01532
01533 if (locI)
01534 changed |= replace_oldest_value_addr (locI, INDEX_REG_CLASS, mode,
01535 insn, vd);
01536 if (locB)
01537 changed |= replace_oldest_value_addr (locB,
01538 base_reg_class (mode, PLUS,
01539 index_code),
01540 mode, insn, vd);
01541 return changed;
01542 }
01543
01544 case POST_INC:
01545 case POST_DEC:
01546 case POST_MODIFY:
01547 case PRE_INC:
01548 case PRE_DEC:
01549 case PRE_MODIFY:
01550 return false;
01551
01552 case MEM:
01553 return replace_oldest_value_mem (x, insn, vd);
01554
01555 case REG:
01556 return replace_oldest_value_reg (loc, cl, insn, vd);
01557
01558 default:
01559 break;
01560 }
01561
01562 fmt = GET_RTX_FORMAT (code);
01563 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
01564 {
01565 if (fmt[i] == 'e')
01566 changed |= replace_oldest_value_addr (&XEXP (x, i), cl, mode,
01567 insn, vd);
01568 else if (fmt[i] == 'E')
01569 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
01570 changed |= replace_oldest_value_addr (&XVECEXP (x, i, j), cl,
01571 mode, insn, vd);
01572 }
01573
01574 return changed;
01575 }
01576
01577
01578
01579 static bool
01580 replace_oldest_value_mem (rtx x, rtx insn, struct value_data *vd)
01581 {
01582 return replace_oldest_value_addr (&XEXP (x, 0),
01583 base_reg_class (GET_MODE (x), MEM,
01584 SCRATCH),
01585 GET_MODE (x), insn, vd);
01586 }
01587
01588
01589
01590 static bool
01591 copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
01592 {
01593 bool changed = false;
01594 rtx insn;
01595
01596 for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
01597 {
01598 int n_ops, i, alt, predicated;
01599 bool is_asm, any_replacements;
01600 rtx set;
01601 bool replaced[MAX_RECOG_OPERANDS];
01602
01603 if (! INSN_P (insn))
01604 {
01605 if (insn == BB_END (bb))
01606 break;
01607 else
01608 continue;
01609 }
01610
01611 set = single_set (insn);
01612 extract_insn (insn);
01613 if (! constrain_operands (1))
01614 fatal_insn_not_found (insn);
01615 preprocess_constraints ();
01616 alt = which_alternative;
01617 n_ops = recog_data.n_operands;
01618 is_asm = asm_noperands (PATTERN (insn)) >= 0;
01619
01620
01621
01622
01623
01624 predicated = GET_CODE (PATTERN (insn)) == COND_EXEC;
01625 for (i = 0; i < n_ops; ++i)
01626 {
01627 int matches = recog_op_alt[i][alt].matches;
01628 if (matches >= 0)
01629 recog_op_alt[i][alt].cl = recog_op_alt[matches][alt].cl;
01630 if (matches >= 0 || recog_op_alt[i][alt].matched >= 0
01631 || (predicated && recog_data.operand_type[i] == OP_OUT))
01632 recog_data.operand_type[i] = OP_INOUT;
01633 }
01634
01635
01636 for (i = 0; i < n_ops; i++)
01637 if (recog_op_alt[i][alt].earlyclobber)
01638 kill_value (recog_data.operand[i], vd);
01639
01640
01641
01642
01643 note_stores (PATTERN (insn), kill_clobbered_value, vd);
01644
01645
01646
01647 for_each_rtx (&PATTERN (insn), kill_autoinc_value, vd);
01648
01649
01650 for (i = 0; i < n_ops; i++)
01651 if (recog_op_alt[i][alt].earlyclobber)
01652 kill_value (recog_data.operand[i], vd);
01653
01654
01655
01656 if (set && REG_P (SET_SRC (set)))
01657 {
01658 rtx src = SET_SRC (set);
01659 unsigned int regno = REGNO (src);
01660 enum machine_mode mode = GET_MODE (src);
01661 unsigned int i;
01662 rtx new;
01663
01664
01665
01666 if (mode != vd->e[regno].mode)
01667 {
01668 if (hard_regno_nregs[regno][mode]
01669 > hard_regno_nregs[regno][vd->e[regno].mode])
01670 goto no_move_special_case;
01671 }
01672
01673
01674
01675 if (REG_P (SET_DEST (set)))
01676 {
01677 new = find_oldest_value_reg (REGNO_REG_CLASS (regno), src, vd);
01678 if (new && validate_change (insn, &SET_SRC (set), new, 0))
01679 {
01680 if (dump_file)
01681 fprintf (dump_file,
01682 "insn %u: replaced reg %u with %u\n",
01683 INSN_UID (insn), regno, REGNO (new));
01684 changed = true;
01685 goto did_replacement;
01686 }
01687 }
01688
01689
01690 for (i = vd->e[regno].oldest_regno; i != regno;
01691 i = vd->e[i].next_regno)
01692 {
01693 new = maybe_mode_change (vd->e[i].mode, vd->e[regno].mode,
01694 mode, i, regno);
01695 if (new != NULL_RTX)
01696 {
01697 if (validate_change (insn, &SET_SRC (set), new, 0))
01698 {
01699 ORIGINAL_REGNO (new) = ORIGINAL_REGNO (src);
01700 REG_ATTRS (new) = REG_ATTRS (src);
01701 if (dump_file)
01702 fprintf (dump_file,
01703 "insn %u: replaced reg %u with %u\n",
01704 INSN_UID (insn), regno, REGNO (new));
01705 changed = true;
01706 goto did_replacement;
01707 }
01708 }
01709 }
01710 }
01711 no_move_special_case:
01712
01713 any_replacements = false;
01714
01715
01716
01717 for (i = 0; i < n_ops; i++)
01718 {
01719 replaced[i] = false;
01720
01721
01722
01723
01724 if (recog_data.constraints[i][0] == '\0')
01725 continue;
01726
01727
01728 if (is_asm && REG_P (recog_data.operand[i])
01729 && (REGNO (recog_data.operand[i])
01730 == ORIGINAL_REGNO (recog_data.operand[i])))
01731 continue;
01732
01733 if (recog_data.operand_type[i] == OP_IN)
01734 {
01735 if (recog_op_alt[i][alt].is_address)
01736 replaced[i]
01737 = replace_oldest_value_addr (recog_data.operand_loc[i],
01738 recog_op_alt[i][alt].cl,
01739 VOIDmode, insn, vd);
01740 else if (REG_P (recog_data.operand[i]))
01741 replaced[i]
01742 = replace_oldest_value_reg (recog_data.operand_loc[i],
01743 recog_op_alt[i][alt].cl,
01744 insn, vd);
01745 else if (MEM_P (recog_data.operand[i]))
01746 replaced[i] = replace_oldest_value_mem (recog_data.operand[i],
01747 insn, vd);
01748 }
01749 else if (MEM_P (recog_data.operand[i]))
01750 replaced[i] = replace_oldest_value_mem (recog_data.operand[i],
01751 insn, vd);
01752
01753
01754 if (replaced[i])
01755 {
01756 int j;
01757 rtx new;
01758
01759 new = *recog_data.operand_loc[i];
01760 recog_data.operand[i] = new;
01761 for (j = 0; j < recog_data.n_dups; j++)
01762 if (recog_data.dup_num[j] == i)
01763 validate_change (insn, recog_data.dup_loc[j], new, 1);
01764
01765 any_replacements = true;
01766 }
01767 }
01768
01769 if (any_replacements)
01770 {
01771 if (! apply_change_group ())
01772 {
01773 for (i = 0; i < n_ops; i++)
01774 if (replaced[i])
01775 {
01776 rtx old = *recog_data.operand_loc[i];
01777 recog_data.operand[i] = old;
01778 }
01779
01780 if (dump_file)
01781 fprintf (dump_file,
01782 "insn %u: reg replacements not verified\n",
01783 INSN_UID (insn));
01784 }
01785 else
01786 changed = true;
01787 }
01788
01789 did_replacement:
01790
01791 if (CALL_P (insn))
01792 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01793 if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
01794 kill_value_regno (i, 1, vd);
01795
01796
01797 note_stores (PATTERN (insn), kill_set_value, vd);
01798
01799
01800 if (set && REG_P (SET_DEST (set)) && REG_P (SET_SRC (set)))
01801 copy_value (SET_DEST (set), SET_SRC (set), vd);
01802
01803 if (insn == BB_END (bb))
01804 break;
01805 }
01806
01807 return changed;
01808 }
01809
01810
01811
01812 static void
01813 copyprop_hardreg_forward (void)
01814 {
01815 struct value_data *all_vd;
01816 bool need_refresh;
01817 basic_block bb;
01818 sbitmap visited;
01819
01820 need_refresh = false;
01821
01822 all_vd = XNEWVEC (struct value_data, last_basic_block);
01823
01824 visited = sbitmap_alloc (last_basic_block);
01825 sbitmap_zero (visited);
01826
01827 FOR_EACH_BB (bb)
01828 {
01829 SET_BIT (visited, bb->index);
01830
01831
01832
01833
01834
01835 if (single_pred_p (bb)
01836 && TEST_BIT (visited, single_pred (bb)->index)
01837 && ! (single_pred_edge (bb)->flags & (EDGE_ABNORMAL_CALL | EDGE_EH)))
01838 all_vd[bb->index] = all_vd[single_pred (bb)->index];
01839 else
01840 init_value_data (all_vd + bb->index);
01841
01842 if (copyprop_hardreg_forward_1 (bb, all_vd + bb->index))
01843 need_refresh = true;
01844 }
01845
01846 sbitmap_free (visited);
01847
01848 if (need_refresh)
01849 {
01850 if (dump_file)
01851 fputs ("\n\n", dump_file);
01852
01853
01854
01855
01856 delete_noop_moves ();
01857 update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
01858 PROP_DEATH_NOTES
01859 | PROP_SCAN_DEAD_CODE
01860 | PROP_KILL_DEAD_CODE);
01861 }
01862
01863 free (all_vd);
01864 }
01865
01866
01867
01868 void
01869 debug_value_data (struct value_data *vd)
01870 {
01871 HARD_REG_SET set;
01872 unsigned int i, j;
01873
01874 CLEAR_HARD_REG_SET (set);
01875
01876 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
01877 if (vd->e[i].oldest_regno == i)
01878 {
01879 if (vd->e[i].mode == VOIDmode)
01880 {
01881 if (vd->e[i].next_regno != INVALID_REGNUM)
01882 fprintf (stderr, "[%u] Bad next_regno for empty chain (%u)\n",
01883 i, vd->e[i].next_regno);
01884 continue;
01885 }
01886
01887 SET_HARD_REG_BIT (set, i);
01888 fprintf (stderr, "[%u %s] ", i, GET_MODE_NAME (vd->e[i].mode));
01889
01890 for (j = vd->e[i].next_regno;
01891 j != INVALID_REGNUM;
01892 j = vd->e[j].next_regno)
01893 {
01894 if (TEST_HARD_REG_BIT (set, j))
01895 {
01896 fprintf (stderr, "[%u] Loop in regno chain\n", j);
01897 return;
01898 }
01899
01900 if (vd->e[j].oldest_regno != i)
01901 {
01902 fprintf (stderr, "[%u] Bad oldest_regno (%u)\n",
01903 j, vd->e[j].oldest_regno);
01904 return;
01905 }
01906 SET_HARD_REG_BIT (set, j);
01907 fprintf (stderr, "[%u %s] ", j, GET_MODE_NAME (vd->e[j].mode));
01908 }
01909 fputc ('\n', stderr);
01910 }
01911
01912 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
01913 if (! TEST_HARD_REG_BIT (set, i)
01914 && (vd->e[i].mode != VOIDmode
01915 || vd->e[i].oldest_regno != i
01916 || vd->e[i].next_regno != INVALID_REGNUM))
01917 fprintf (stderr, "[%u] Non-empty reg in chain (%s %u %i)\n",
01918 i, GET_MODE_NAME (vd->e[i].mode), vd->e[i].oldest_regno,
01919 vd->e[i].next_regno);
01920 }
01921
01922 #ifdef ENABLE_CHECKING
01923 static void
01924 validate_value_data (struct value_data *vd)
01925 {
01926 HARD_REG_SET set;
01927 unsigned int i, j;
01928
01929 CLEAR_HARD_REG_SET (set);
01930
01931 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
01932 if (vd->e[i].oldest_regno == i)
01933 {
01934 if (vd->e[i].mode == VOIDmode)
01935 {
01936 if (vd->e[i].next_regno != INVALID_REGNUM)
01937 internal_error ("validate_value_data: [%u] Bad next_regno for empty chain (%u)",
01938 i, vd->e[i].next_regno);
01939 continue;
01940 }
01941
01942 SET_HARD_REG_BIT (set, i);
01943
01944 for (j = vd->e[i].next_regno;
01945 j != INVALID_REGNUM;
01946 j = vd->e[j].next_regno)
01947 {
01948 if (TEST_HARD_REG_BIT (set, j))
01949 internal_error ("validate_value_data: Loop in regno chain (%u)",
01950 j);
01951 if (vd->e[j].oldest_regno != i)
01952 internal_error ("validate_value_data: [%u] Bad oldest_regno (%u)",
01953 j, vd->e[j].oldest_regno);
01954
01955 SET_HARD_REG_BIT (set, j);
01956 }
01957 }
01958
01959 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
01960 if (! TEST_HARD_REG_BIT (set, i)
01961 && (vd->e[i].mode != VOIDmode
01962 || vd->e[i].oldest_regno != i
01963 || vd->e[i].next_regno != INVALID_REGNUM))
01964 internal_error ("validate_value_data: [%u] Non-empty reg in chain (%s %u %i)",
01965 i, GET_MODE_NAME (vd->e[i].mode), vd->e[i].oldest_regno,
01966 vd->e[i].next_regno);
01967 }
01968 #endif
01969
01970 static bool
01971 gate_handle_regrename (void)
01972 {
01973 return (optimize > 0 && (flag_rename_registers || flag_cprop_registers));
01974 }
01975
01976
01977
01978 static unsigned int
01979 rest_of_handle_regrename (void)
01980 {
01981 if (flag_rename_registers)
01982 regrename_optimize ();
01983 if (flag_cprop_registers)
01984 copyprop_hardreg_forward ();
01985 return 0;
01986 }
01987
01988 struct tree_opt_pass pass_regrename =
01989 {
01990 "rnreg",
01991 gate_handle_regrename,
01992 rest_of_handle_regrename,
01993 NULL,
01994 NULL,
01995 0,
01996 TV_RENAME_REGISTERS,
01997 0,
01998 0,
01999 0,
02000 0,
02001 TODO_dump_func,
02002 'n'
02003 };
02004