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