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