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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #include "config.h"
00078 #include "system.h"
00079 #include "coretypes.h"
00080 #include "tm.h"
00081 #include "rtl.h"
00082 #include "regs.h"
00083 #include "output.h"
00084 #include "insn-config.h"
00085 #include "flags.h"
00086 #include "recog.h"
00087 #include "tm_p.h"
00088 #include "target.h"
00089 #include "emit-rtl.h"
00090 #include "reload.h"
00091
00092 static void merge_memattrs (rtx, rtx);
00093 static bool set_dest_equiv_p (rtx x, rtx y, struct equiv_info *info);
00094 static bool set_dest_addr_equiv_p (rtx x, rtx y, struct equiv_info *info);
00095 static void find_dying_inputs (struct equiv_info *info);
00096 static bool resolve_input_conflict (struct equiv_info *info);
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 #define IMPOSSIBLE_MOVE_FACTOR 20000
00110
00111
00112
00113
00114
00115
00116 void
00117 merge_memattrs (rtx x, rtx y)
00118 {
00119 int i;
00120 int j;
00121 enum rtx_code code;
00122 const char *fmt;
00123
00124 if (x == y)
00125 return;
00126 if (x == 0 || y == 0)
00127 return;
00128
00129 code = GET_CODE (x);
00130
00131 if (code != GET_CODE (y))
00132 return;
00133
00134 if (GET_MODE (x) != GET_MODE (y))
00135 return;
00136
00137 if (code == MEM && MEM_ATTRS (x) != MEM_ATTRS (y))
00138 {
00139 if (! MEM_ATTRS (x))
00140 MEM_ATTRS (y) = 0;
00141 else if (! MEM_ATTRS (y))
00142 MEM_ATTRS (x) = 0;
00143 else
00144 {
00145 rtx mem_size;
00146
00147 if (MEM_ALIAS_SET (x) != MEM_ALIAS_SET (y))
00148 {
00149 set_mem_alias_set (x, 0);
00150 set_mem_alias_set (y, 0);
00151 }
00152
00153 if (! mem_expr_equal_p (MEM_EXPR (x), MEM_EXPR (y)))
00154 {
00155 set_mem_expr (x, 0);
00156 set_mem_expr (y, 0);
00157 set_mem_offset (x, 0);
00158 set_mem_offset (y, 0);
00159 }
00160 else if (MEM_OFFSET (x) != MEM_OFFSET (y))
00161 {
00162 set_mem_offset (x, 0);
00163 set_mem_offset (y, 0);
00164 }
00165
00166 if (!MEM_SIZE (x))
00167 mem_size = NULL_RTX;
00168 else if (!MEM_SIZE (y))
00169 mem_size = NULL_RTX;
00170 else
00171 mem_size = GEN_INT (MAX (INTVAL (MEM_SIZE (x)),
00172 INTVAL (MEM_SIZE (y))));
00173 set_mem_size (x, mem_size);
00174 set_mem_size (y, mem_size);
00175
00176 set_mem_align (x, MIN (MEM_ALIGN (x), MEM_ALIGN (y)));
00177 set_mem_align (y, MEM_ALIGN (x));
00178 }
00179 }
00180
00181 fmt = GET_RTX_FORMAT (code);
00182 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00183 {
00184 switch (fmt[i])
00185 {
00186 case 'E':
00187
00188 if (XVECLEN (x, i) != XVECLEN (y, i))
00189 return;
00190
00191 for (j = 0; j < XVECLEN (x, i); j++)
00192 merge_memattrs (XVECEXP (x, i, j), XVECEXP (y, i, j));
00193
00194 break;
00195
00196 case 'e':
00197 merge_memattrs (XEXP (x, i), XEXP (y, i));
00198 }
00199 }
00200 return;
00201 }
00202
00203
00204
00205
00206
00207 static int
00208 assign_reg_reg_set (regset set, rtx reg, int value)
00209 {
00210 unsigned regno = REGNO (reg);
00211 int nregs, i, old;
00212
00213 if (regno >= FIRST_PSEUDO_REGISTER)
00214 {
00215 gcc_assert (!reload_completed);
00216 nregs = 1;
00217 }
00218 else
00219 nregs = hard_regno_nregs[regno][GET_MODE (reg)];
00220 for (old = 0, i = nregs; --i >= 0; regno++)
00221 {
00222 if ((value != 0) == REGNO_REG_SET_P (set, regno))
00223 continue;
00224 if (value)
00225 old++, SET_REGNO_REG_SET (set, regno);
00226 else
00227 old--, CLEAR_REGNO_REG_SET (set, regno);
00228 }
00229 return old;
00230 }
00231
00232
00233
00234 static inline void
00235 struct_equiv_make_checkpoint (struct struct_equiv_checkpoint *p,
00236 struct equiv_info *info)
00237 {
00238 *p = info->cur;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 static void
00248 struct_equiv_improve_checkpoint (struct struct_equiv_checkpoint *p,
00249 struct equiv_info *info)
00250 {
00251 #ifdef HAVE_cc0
00252 if (reg_mentioned_p (cc0_rtx, info->cur.x_start)
00253 && !sets_cc0_p (info->cur.x_start))
00254 return;
00255 #endif
00256 if (info->cur.input_count >= IMPOSSIBLE_MOVE_FACTOR)
00257 return;
00258 if (info->input_cost >= 0
00259 ? (COSTS_N_INSNS(info->cur.ninsns - p->ninsns)
00260 > info->input_cost * (info->cur.input_count - p->input_count))
00261 : info->cur.ninsns > p->ninsns && !info->cur.input_count)
00262 {
00263 if (info->check_input_conflict && ! resolve_input_conflict (info))
00264 return;
00265
00266
00267
00268 if (info->mode & STRUCT_EQUIV_FINAL)
00269 confirm_change_group ();
00270 else
00271 cancel_changes (0);
00272 struct_equiv_make_checkpoint (p, info);
00273 }
00274 }
00275
00276
00277
00278 static void
00279 struct_equiv_restore_checkpoint (struct struct_equiv_checkpoint *p,
00280 struct equiv_info *info)
00281 {
00282 info->cur.ninsns = p->ninsns;
00283 info->cur.x_start = p->x_start;
00284 info->cur.y_start = p->y_start;
00285 info->cur.input_count = p->input_count;
00286 info->cur.input_valid = p->input_valid;
00287 while (info->cur.local_count > p->local_count)
00288 {
00289 info->cur.local_count--;
00290 info->cur.version--;
00291 if (REGNO_REG_SET_P (info->x_local_live,
00292 REGNO (info->x_local[info->cur.local_count])))
00293 {
00294 assign_reg_reg_set (info->x_local_live,
00295 info->x_local[info->cur.local_count], 0);
00296 assign_reg_reg_set (info->y_local_live,
00297 info->y_local[info->cur.local_count], 0);
00298 info->cur.version--;
00299 }
00300 }
00301 if (info->cur.version != p->version)
00302 info->need_rerun = true;
00303 }
00304
00305
00306
00307
00308
00309
00310 static int
00311 note_local_live (struct equiv_info *info, rtx x, rtx y, int rvalue)
00312 {
00313 unsigned x_regno = REGNO (x);
00314 unsigned y_regno = REGNO (y);
00315 int x_nominal_nregs = (x_regno >= FIRST_PSEUDO_REGISTER
00316 ? 1 : hard_regno_nregs[x_regno][GET_MODE (x)]);
00317 int y_nominal_nregs = (y_regno >= FIRST_PSEUDO_REGISTER
00318 ? 1 : hard_regno_nregs[y_regno][GET_MODE (y)]);
00319 int x_change = assign_reg_reg_set (info->x_local_live, x, rvalue);
00320 int y_change = assign_reg_reg_set (info->y_local_live, y, rvalue);
00321
00322 gcc_assert (x_nominal_nregs && y_nominal_nregs);
00323 gcc_assert (x_change * y_nominal_nregs == y_change * x_nominal_nregs);
00324 if (y_change)
00325 {
00326 if (reload_completed)
00327 {
00328 unsigned x_regno ATTRIBUTE_UNUSED = REGNO (x);
00329 unsigned y_regno = REGNO (y);
00330 enum machine_mode x_mode = GET_MODE (x);
00331
00332 if (secondary_reload_class (0, REGNO_REG_CLASS (y_regno), x_mode, x)
00333 != NO_REGS
00334 #ifdef SECONDARY_MEMORY_NEEDED
00335 || SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (y_regno),
00336 REGNO_REG_CLASS (x_regno), x_mode)
00337 #endif
00338 )
00339 y_change *= IMPOSSIBLE_MOVE_FACTOR;
00340 }
00341 info->cur.input_count += y_change;
00342 info->cur.version++;
00343 }
00344 return x_change;
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 bool
00358 rtx_equiv_p (rtx *xp, rtx y, int rvalue, struct equiv_info *info)
00359 {
00360 rtx x = *xp;
00361 enum rtx_code code;
00362 int length;
00363 const char *format;
00364 int i;
00365
00366 if (!y || !x)
00367 return x == y;
00368 code = GET_CODE (y);
00369 if (code != REG && x == y)
00370 return true;
00371 if (GET_CODE (x) != code
00372 || GET_MODE (x) != GET_MODE (y))
00373 return false;
00374
00375
00376 switch (code)
00377 {
00378 case REG:
00379 {
00380 unsigned x_regno = REGNO (x);
00381 unsigned y_regno = REGNO (y);
00382 int x_common_live, y_common_live;
00383
00384 if (reload_completed
00385 && (x_regno >= FIRST_PSEUDO_REGISTER
00386 || y_regno >= FIRST_PSEUDO_REGISTER))
00387 {
00388
00389 gcc_assert (!info->live_update);
00390
00391 return false;
00392 }
00393 #ifdef STACK_REGS
00394
00395 if (info->mode & CLEANUP_POST_REGSTACK
00396 && (IN_RANGE (x_regno, FIRST_STACK_REG, LAST_STACK_REG)
00397 || IN_RANGE (y_regno, FIRST_STACK_REG, LAST_STACK_REG)))
00398 return x_regno == y_regno;
00399 #endif
00400
00401
00402
00403
00404 if (REGNO_REG_SET_P (info->x_local_live, x_regno))
00405 {
00406 if (!REGNO_REG_SET_P (info->y_local_live, y_regno))
00407 return false;
00408 }
00409 else if (REGNO_REG_SET_P (info->y_local_live, y_regno))
00410 return false;
00411 else if (x_regno == y_regno)
00412 {
00413 if (!rvalue && info->cur.input_valid
00414 && (reg_overlap_mentioned_p (x, info->x_input)
00415 || reg_overlap_mentioned_p (x, info->y_input)))
00416 return false;
00417
00418
00419 if (info->live_update
00420 && assign_reg_reg_set (info->common_live, x, rvalue))
00421 info->cur.version++;
00422
00423 return true;
00424 }
00425
00426 x_common_live = REGNO_REG_SET_P (info->common_live, x_regno);
00427 y_common_live = REGNO_REG_SET_P (info->common_live, y_regno);
00428 if (x_common_live != y_common_live)
00429 return false;
00430 else if (x_common_live)
00431 {
00432 if (! rvalue || info->input_cost < 0 || no_new_pseudos)
00433 return false;
00434
00435
00436
00437 if (info->live_update && !info->cur.input_valid)
00438 {
00439 info->cur.input_valid = true;
00440 info->x_input = x;
00441 info->y_input = y;
00442 info->cur.input_count += optimize_size ? 2 : 1;
00443 if (info->input_reg
00444 && GET_MODE (info->input_reg) != GET_MODE (info->x_input))
00445 info->input_reg = NULL_RTX;
00446 if (!info->input_reg)
00447 info->input_reg = gen_reg_rtx (GET_MODE (info->x_input));
00448 }
00449 else if ((info->live_update
00450 ? ! info->cur.input_valid : ! info->x_input)
00451 || ! rtx_equal_p (x, info->x_input)
00452 || ! rtx_equal_p (y, info->y_input))
00453 return false;
00454 validate_change (info->cur.x_start, xp, info->input_reg, 1);
00455 }
00456 else
00457 {
00458 int x_nregs = (x_regno >= FIRST_PSEUDO_REGISTER
00459 ? 1 : hard_regno_nregs[x_regno][GET_MODE (x)]);
00460 int y_nregs = (y_regno >= FIRST_PSEUDO_REGISTER
00461 ? 1 : hard_regno_nregs[y_regno][GET_MODE (y)]);
00462 int size = GET_MODE_SIZE (GET_MODE (x));
00463 enum machine_mode x_mode = GET_MODE (x);
00464 unsigned x_regno_i, y_regno_i;
00465 int x_nregs_i, y_nregs_i, size_i;
00466 int local_count = info->cur.local_count;
00467
00468
00469
00470 for (i = local_count - 1; i >= 0; i--)
00471 {
00472 x_regno_i = REGNO (info->x_local[i]);
00473 x_nregs_i = (x_regno_i >= FIRST_PSEUDO_REGISTER
00474 ? 1 : hard_regno_nregs[x_regno_i][GET_MODE (x)]);
00475 y_regno_i = REGNO (info->y_local[i]);
00476 y_nregs_i = (y_regno_i >= FIRST_PSEUDO_REGISTER
00477 ? 1 : hard_regno_nregs[y_regno_i][GET_MODE (y)]);
00478 size_i = GET_MODE_SIZE (GET_MODE (info->x_local[i]));
00479
00480
00481
00482
00483
00484
00485
00486
00487 if (info->live_update
00488 && (x_mode != GET_MODE (info->x_local[i])
00489 ? size >= size_i : size > size_i))
00490 {
00491
00492
00493
00494
00495 if ((x_regno <= x_regno_i
00496 && x_regno + x_nregs >= x_regno_i + x_nregs_i
00497 && x_nregs == y_nregs && x_nregs_i == y_nregs_i
00498 && x_regno - x_regno_i == y_regno - y_regno_i)
00499 || (x_regno == x_regno_i && y_regno == y_regno_i
00500 && x_nregs >= x_nregs_i && y_nregs >= y_nregs_i))
00501 {
00502 info->cur.local_count = --local_count;
00503 info->x_local[i] = info->x_local[local_count];
00504 info->y_local[i] = info->y_local[local_count];
00505 continue;
00506 }
00507 }
00508 else
00509 {
00510
00511
00512
00513 if (x_regno >= x_regno_i
00514 && x_regno + x_nregs <= x_regno_i + x_nregs_i
00515 && x_nregs == y_nregs && x_nregs_i == y_nregs_i
00516 && x_regno - x_regno_i == y_regno - y_regno_i)
00517 break;
00518 if (x_regno == x_regno_i && y_regno == y_regno_i
00519 && x_nregs <= x_nregs_i && y_nregs <= y_nregs_i)
00520 break;
00521 }
00522
00523
00524 if (x_regno + x_nregs > x_regno_i
00525 && x_regno_i + x_nregs_i > x_regno)
00526 return false;
00527 if (y_regno + y_nregs > y_regno_i
00528 && y_regno_i + y_nregs_i > y_regno)
00529 return false;
00530 }
00531 if (i < 0)
00532 {
00533
00534 if (!info->live_update
00535 || info->cur.local_count >= STRUCT_EQUIV_MAX_LOCAL)
00536 return false;
00537 info->x_local[info->cur.local_count] = x;
00538 info->y_local[info->cur.local_count] = y;
00539 info->cur.local_count++;
00540 info->cur.version++;
00541 }
00542 note_local_live (info, x, y, rvalue);
00543 }
00544 return true;
00545 }
00546 case SET:
00547 gcc_assert (rvalue < 0);
00548
00549
00550
00551
00552 if(!set_dest_addr_equiv_p (SET_DEST (x), SET_DEST (y), info))
00553 return false;
00554
00555 return rtx_equiv_p (&SET_SRC (x), SET_SRC (y), 1, info);
00556 case PRE_MODIFY:
00557
00558 if (!rtx_equiv_p (&XEXP (x, 0), XEXP (y, 0), 0, info))
00559 return false;
00560
00561 return rtx_equiv_p (&XEXP (x, 1), XEXP (y, 1), 1, info);
00562 case POST_MODIFY:
00563 {
00564 rtx x_dest0, x_dest1;
00565
00566
00567 x_dest0 = XEXP (x, 0);
00568 gcc_assert (REG_P (x_dest0));
00569 if (!rtx_equiv_p (&XEXP (x, 0), XEXP (y, 0), 0, info))
00570 return false;
00571 x_dest1 = XEXP (x, 0);
00572
00573
00574 XEXP (x, 0) = x_dest0;
00575 if (!rtx_equiv_p (&XEXP (x, 0), XEXP (y, 0), 1, info))
00576 return false;
00577 gcc_assert (x_dest1 == XEXP (x, 0));
00578
00579 return rtx_equiv_p (&XEXP (x, 1), XEXP (y, 1), 1, info);
00580 }
00581 case CLOBBER:
00582 gcc_assert (rvalue < 0);
00583 return true;
00584
00585
00586
00587
00588 case STRICT_LOW_PART:
00589 case ZERO_EXTEND:
00590 case SIGN_EXTEND:
00591 {
00592 rtx x_inner, y_inner;
00593 enum rtx_code code;
00594 int change;
00595
00596 if (rvalue)
00597 break;
00598 x_inner = XEXP (x, 0);
00599 y_inner = XEXP (y, 0);
00600 if (GET_MODE (x_inner) != GET_MODE (y_inner))
00601 return false;
00602 code = GET_CODE (x_inner);
00603 if (code != GET_CODE (y_inner))
00604 return false;
00605
00606
00607 if (code == SUBREG)
00608 {
00609 if (SUBREG_BYTE (x_inner) != SUBREG_BYTE (y_inner))
00610 return false;
00611 x = x_inner;
00612 x_inner = SUBREG_REG (x_inner);
00613 y_inner = SUBREG_REG (y_inner);
00614 if (GET_MODE (x_inner) != GET_MODE (y_inner))
00615 return false;
00616 code = GET_CODE (x_inner);
00617 if (code != GET_CODE (y_inner))
00618 return false;
00619 }
00620 if (code == MEM)
00621 return true;
00622 gcc_assert (code == REG);
00623 if (! rtx_equiv_p (&XEXP (x, 0), y_inner, rvalue, info))
00624 return false;
00625 if (REGNO (x_inner) == REGNO (y_inner))
00626 {
00627 change = assign_reg_reg_set (info->common_live, x_inner, 1);
00628 info->cur.version++;
00629 }
00630 else
00631 change = note_local_live (info, x_inner, y_inner, 1);
00632 gcc_assert (change);
00633 return true;
00634 }
00635
00636
00637
00638 case MEM:
00639 return !rvalue || rtx_equiv_p (&XEXP (x, 0), XEXP (y, 0), rvalue, info);
00640 case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC:
00641 return (rtx_equiv_p (&XEXP (x, 0), XEXP (y, 0), 0, info)
00642 && rtx_equiv_p (&XEXP (x, 0), XEXP (y, 0), 1, info));
00643 case PARALLEL:
00644
00645
00646
00647 gcc_assert (rvalue < 0 || GET_MODE (x) != VOIDmode);
00648 break;
00649 case LABEL_REF:
00650
00651 if (XEXP (y, 0) == info->y_label)
00652 return (XEXP (x, 0) == info->x_label);
00653
00654 if (LABEL_REF_NONLOCAL_P (x) || LABEL_REF_NONLOCAL_P (y))
00655 return XEXP (x, 0) == XEXP (y, 0);
00656
00657
00658
00659 return (next_real_insn (XEXP (x, 0))
00660 == next_real_insn (XEXP (y, 0)));
00661 case SYMBOL_REF:
00662 return XSTR (x, 0) == XSTR (y, 0);
00663
00664
00665 case CONST_INT:
00666 case CODE_LABEL:
00667 return false;
00668 default:
00669 break;
00670 }
00671
00672
00673
00674 if (targetm.commutative_p (x, UNKNOWN))
00675 return ((rtx_equiv_p (&XEXP (x, 0), XEXP (y, 0), rvalue, info)
00676 && rtx_equiv_p (&XEXP (x, 1), XEXP (y, 1), rvalue, info))
00677 || (rtx_equiv_p (&XEXP (x, 0), XEXP (y, 1), rvalue, info)
00678 && rtx_equiv_p (&XEXP (x, 1), XEXP (y, 0), rvalue, info)));
00679
00680
00681 length = GET_RTX_LENGTH (code);
00682 format = GET_RTX_FORMAT (code);
00683
00684 for (i = 0; i < length; ++i)
00685 {
00686 switch (format[i])
00687 {
00688 case 'w':
00689 if (XWINT (x, i) != XWINT (y, i))
00690 return false;
00691 break;
00692 case 'n':
00693 case 'i':
00694 if (XINT (x, i) != XINT (y, i))
00695 return false;
00696 break;
00697 case 'V':
00698 case 'E':
00699 if (XVECLEN (x, i) != XVECLEN (y, i))
00700 return false;
00701 if (XVEC (x, i) != 0)
00702 {
00703 int j;
00704 for (j = 0; j < XVECLEN (x, i); ++j)
00705 {
00706 if (! rtx_equiv_p (&XVECEXP (x, i, j), XVECEXP (y, i, j),
00707 rvalue, info))
00708 return false;
00709 }
00710 }
00711 break;
00712 case 'e':
00713 if (! rtx_equiv_p (&XEXP (x, i), XEXP (y, i), rvalue, info))
00714 return false;
00715 break;
00716 case 'S':
00717 case 's':
00718 if ((XSTR (x, i) || XSTR (y, i))
00719 && (! XSTR (x, i) || ! XSTR (y, i)
00720 || strcmp (XSTR (x, i), XSTR (y, i))))
00721 return false;
00722 break;
00723 case 'u':
00724
00725 break;
00726 case '0':
00727 case 't':
00728 break;
00729
00730
00731
00732 default:
00733 gcc_unreachable ();
00734 }
00735 }
00736 return true;
00737 }
00738
00739
00740
00741
00742 static bool
00743 set_dest_equiv_p (rtx x, rtx y, struct equiv_info *info)
00744 {
00745 if (!x || !y)
00746 return x == y;
00747 if (GET_CODE (x) != GET_CODE (y))
00748 return false;
00749 else if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
00750 return rtx_equiv_p (&XEXP (x, 0), XEXP (y, 0), 0, info);
00751 else if (GET_CODE (x) == PARALLEL)
00752 {
00753 int j;
00754
00755 if (XVECLEN (x, 0) != XVECLEN (y, 0))
00756 return false;
00757 for (j = 0; j < XVECLEN (x, 0); ++j)
00758 {
00759 rtx xe = XVECEXP (x, 0, j);
00760 rtx ye = XVECEXP (y, 0, j);
00761
00762 if (GET_CODE (xe) != GET_CODE (ye))
00763 return false;
00764 if ((GET_CODE (xe) == SET || GET_CODE (xe) == CLOBBER)
00765 && ! rtx_equiv_p (&XEXP (xe, 0), XEXP (ye, 0), 0, info))
00766 return false;
00767 }
00768 }
00769 return true;
00770 }
00771
00772
00773
00774
00775
00776
00777
00778 static bool
00779 set_dest_addr_equiv_p (rtx x, rtx y, struct equiv_info *info)
00780 {
00781 enum rtx_code code = GET_CODE (x);
00782 int length;
00783 const char *format;
00784 int i;
00785
00786 if (code != GET_CODE (y))
00787 return false;
00788 if (code == MEM)
00789 return rtx_equiv_p (&XEXP (x, 0), XEXP (y, 0), 1, info);
00790
00791
00792 length = GET_RTX_LENGTH (code);
00793 format = GET_RTX_FORMAT (code);
00794
00795 for (i = 0; i < length; ++i)
00796 {
00797 switch (format[i])
00798 {
00799 case 'V':
00800 case 'E':
00801 if (XVECLEN (x, i) != XVECLEN (y, i))
00802 return false;
00803 if (XVEC (x, i) != 0)
00804 {
00805 int j;
00806 for (j = 0; j < XVECLEN (x, i); ++j)
00807 {
00808 if (! set_dest_addr_equiv_p (XVECEXP (x, i, j),
00809 XVECEXP (y, i, j), info))
00810 return false;
00811 }
00812 }
00813 break;
00814 case 'e':
00815 if (! set_dest_addr_equiv_p (XEXP (x, i), XEXP (y, i), info))
00816 return false;
00817 break;
00818 default:
00819 break;
00820 }
00821 }
00822 return true;
00823 }
00824
00825
00826
00827
00828
00829 static bool
00830 death_notes_match_p (rtx i1 ATTRIBUTE_UNUSED, rtx i2 ATTRIBUTE_UNUSED,
00831 struct equiv_info *info ATTRIBUTE_UNUSED)
00832 {
00833 #ifdef STACK_REGS
00834
00835
00836
00837 if ((info->mode & CLEANUP_POST_REGSTACK) && stack_regs_mentioned (i1))
00838 {
00839
00840
00841
00842
00843 rtx note;
00844 HARD_REG_SET i1_regset, i2_regset;
00845
00846 CLEAR_HARD_REG_SET (i1_regset);
00847 CLEAR_HARD_REG_SET (i2_regset);
00848
00849 for (note = REG_NOTES (i1); note; note = XEXP (note, 1))
00850 if (REG_NOTE_KIND (note) == REG_DEAD && STACK_REG_P (XEXP (note, 0)))
00851 SET_HARD_REG_BIT (i1_regset, REGNO (XEXP (note, 0)));
00852
00853 for (note = REG_NOTES (i2); note; note = XEXP (note, 1))
00854 if (REG_NOTE_KIND (note) == REG_DEAD && STACK_REG_P (XEXP (note, 0)))
00855 {
00856 unsigned regno = REGNO (XEXP (note, 0));
00857 int i;
00858
00859 for (i = info->cur.local_count - 1; i >= 0; i--)
00860 if (regno == REGNO (info->y_local[i]))
00861 {
00862 regno = REGNO (info->x_local[i]);
00863 break;
00864 }
00865 SET_HARD_REG_BIT (i2_regset, regno);
00866 }
00867
00868 GO_IF_HARD_REG_EQUAL (i1_regset, i2_regset, done);
00869
00870 return false;
00871
00872 done:
00873 ;
00874 }
00875 #endif
00876 return true;
00877 }
00878
00879
00880
00881 bool
00882 insns_match_p (rtx i1, rtx i2, struct equiv_info *info)
00883 {
00884 int rvalue_change_start;
00885 struct struct_equiv_checkpoint before_rvalue_change;
00886
00887
00888 if (GET_CODE (i1) != GET_CODE (i2))
00889 return false;
00890
00891 info->cur.x_start = i1;
00892 info->cur.y_start = i2;
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 if (CALL_P (i1))
00905 {
00906 if (SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2)
00907 || ! set_dest_equiv_p (PATTERN (i1), PATTERN (i2), info)
00908 || ! set_dest_equiv_p (CALL_INSN_FUNCTION_USAGE (i1),
00909 CALL_INSN_FUNCTION_USAGE (i2), info)
00910 || ! rtx_equiv_p (&CALL_INSN_FUNCTION_USAGE (i1),
00911 CALL_INSN_FUNCTION_USAGE (i2), -1, info))
00912 {
00913 cancel_changes (0);
00914 return false;
00915 }
00916 }
00917 else if (INSN_P (i1))
00918 {
00919 if (! set_dest_equiv_p (PATTERN (i1), PATTERN (i2), info))
00920 {
00921 cancel_changes (0);
00922 return false;
00923 }
00924 }
00925 rvalue_change_start = num_validated_changes ();
00926 struct_equiv_make_checkpoint (&before_rvalue_change, info);
00927
00928
00929 if (! INSN_P (i1)
00930 || (!bitmap_bit_p (info->equiv_used, info->cur.ninsns)
00931 && rtx_equiv_p (&PATTERN (i1), PATTERN (i2), -1, info)
00932 && death_notes_match_p (i1, i2, info)
00933 && verify_changes (0)))
00934 return true;
00935
00936
00937
00938
00939
00940
00941 if (!reload_completed)
00942 {
00943 rtx equiv1, equiv2;
00944
00945 cancel_changes (rvalue_change_start);
00946 struct_equiv_restore_checkpoint (&before_rvalue_change, info);
00947
00948
00949 equiv1 = find_reg_equal_equiv_note (i1);
00950 equiv2 = find_reg_equal_equiv_note (i2);
00951 if (equiv1 && equiv2
00952
00953
00954
00955 && (! reload_completed
00956 || (CONSTANT_P (XEXP (equiv1, 0))
00957 && rtx_equal_p (XEXP (equiv1, 0), XEXP (equiv2, 0)))))
00958 {
00959 rtx s1 = single_set (i1);
00960 rtx s2 = single_set (i2);
00961
00962 if (s1 != 0 && s2 != 0)
00963 {
00964 validate_change (i1, &SET_SRC (s1), XEXP (equiv1, 0), 1);
00965 validate_change (i2, &SET_SRC (s2), XEXP (equiv2, 0), 1);
00966
00967
00968
00969 if (rtx_equiv_p (&PATTERN (i1), PATTERN (i2), -1, info)
00970 && death_notes_match_p (i1, i2, info)
00971 && verify_changes (0))
00972 {
00973
00974
00975 bitmap_set_bit (info->equiv_used, info->cur.ninsns);
00976 return true;
00977 }
00978 }
00979 }
00980 }
00981
00982 cancel_changes (0);
00983 return false;
00984 }
00985
00986
00987 bool
00988 struct_equiv_init (int mode, struct equiv_info *info)
00989 {
00990 if ((info->x_block->flags | info->y_block->flags) & BB_DIRTY)
00991 update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
00992 (PROP_DEATH_NOTES
00993 | ((mode & CLEANUP_POST_REGSTACK)
00994 ? PROP_POST_REGSTACK : 0)));
00995 if (!REG_SET_EQUAL_P (info->x_block->il.rtl->global_live_at_end,
00996 info->y_block->il.rtl->global_live_at_end))
00997 {
00998 #ifdef STACK_REGS
00999 unsigned rn;
01000
01001 if (!(mode & CLEANUP_POST_REGSTACK))
01002 return false;
01003
01004
01005
01006
01007 for (rn = FIRST_STACK_REG; rn <= LAST_STACK_REG; rn++)
01008 {
01009 CLEAR_REGNO_REG_SET (info->x_block->il.rtl->global_live_at_end, rn);
01010 CLEAR_REGNO_REG_SET (info->y_block->il.rtl->global_live_at_end, rn);
01011 }
01012 if (!REG_SET_EQUAL_P (info->x_block->il.rtl->global_live_at_end,
01013 info->y_block->il.rtl->global_live_at_end))
01014 #endif
01015 return false;
01016 }
01017 info->mode = mode;
01018 if (mode & STRUCT_EQUIV_START)
01019 {
01020 info->x_input = info->y_input = info->input_reg = NULL_RTX;
01021 info->equiv_used = ALLOC_REG_SET (®_obstack);
01022 info->check_input_conflict = false;
01023 }
01024 info->had_input_conflict = false;
01025 info->cur.ninsns = info->cur.version = 0;
01026 info->cur.local_count = info->cur.input_count = 0;
01027 info->cur.x_start = info->cur.y_start = NULL_RTX;
01028 info->x_label = info->y_label = NULL_RTX;
01029 info->need_rerun = false;
01030 info->live_update = true;
01031 info->cur.input_valid = false;
01032 info->common_live = ALLOC_REG_SET (®_obstack);
01033 info->x_local_live = ALLOC_REG_SET (®_obstack);
01034 info->y_local_live = ALLOC_REG_SET (®_obstack);
01035 COPY_REG_SET (info->common_live, info->x_block->il.rtl->global_live_at_end);
01036 struct_equiv_make_checkpoint (&info->best_match, info);
01037 return true;
01038 }
01039
01040
01041
01042 static void
01043 struct_equiv_merge (rtx xi, rtx yi, struct equiv_info *info)
01044 {
01045 rtx equiv1, equiv2;
01046
01047 merge_memattrs (xi, yi);
01048
01049
01050
01051 info->live_update = false;
01052 equiv1 = find_reg_equal_equiv_note (xi);
01053 equiv2 = find_reg_equal_equiv_note (yi);
01054 if (equiv1 && !equiv2)
01055 remove_note (xi, equiv1);
01056 else if (!equiv1 && equiv2)
01057 remove_note (yi, equiv2);
01058 else if (equiv1 && equiv2
01059 && !rtx_equiv_p (&XEXP (equiv1, 0), XEXP (equiv2, 0),
01060 1, info))
01061 {
01062 remove_note (xi, equiv1);
01063 remove_note (yi, equiv2);
01064 }
01065 info->live_update = true;
01066 }
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080 int
01081 struct_equiv_block_eq (int mode, struct equiv_info *info)
01082 {
01083 rtx x_stop, y_stop;
01084 rtx xi, yi;
01085 int i;
01086
01087 if (mode & STRUCT_EQUIV_START)
01088 {
01089 x_stop = BB_HEAD (info->x_block);
01090 y_stop = BB_HEAD (info->y_block);
01091 if (!x_stop || !y_stop)
01092 return 0;
01093 }
01094 else
01095 {
01096 x_stop = info->cur.x_start;
01097 y_stop = info->cur.y_start;
01098 }
01099 if (!struct_equiv_init (mode, info))
01100 gcc_unreachable ();
01101
01102
01103
01104
01105 xi = BB_END (info->x_block);
01106 if (onlyjump_p (xi)
01107 || (returnjump_p (xi) && !side_effects_p (PATTERN (xi))))
01108 {
01109 info->cur.x_start = xi;
01110 xi = PREV_INSN (xi);
01111 }
01112
01113 yi = BB_END (info->y_block);
01114 if (onlyjump_p (yi)
01115 || (returnjump_p (yi) && !side_effects_p (PATTERN (yi))))
01116 {
01117 info->cur.y_start = yi;
01118
01119
01120
01121 if (!simplejump_p (yi) && !returnjump_p (yi) && info->cur.x_start)
01122 info->cur.ninsns++;
01123 yi = PREV_INSN (yi);
01124 }
01125
01126 if (mode & STRUCT_EQUIV_MATCH_JUMPS)
01127 {
01128
01129
01130 gcc_assert (!info->cur.x_start == !info->cur.y_start);
01131 if (info->cur.x_start)
01132 {
01133 if (any_condjump_p (info->cur.x_start)
01134 ? !condjump_equiv_p (info, false)
01135 : !insns_match_p (info->cur.x_start, info->cur.y_start, info))
01136 gcc_unreachable ();
01137 }
01138 else if (any_condjump_p (xi) && any_condjump_p (yi))
01139 {
01140 info->cur.x_start = xi;
01141 info->cur.y_start = yi;
01142 xi = PREV_INSN (xi);
01143 yi = PREV_INSN (yi);
01144 info->cur.ninsns++;
01145 if (!condjump_equiv_p (info, false))
01146 gcc_unreachable ();
01147 }
01148 if (info->cur.x_start && info->mode & STRUCT_EQUIV_FINAL)
01149 struct_equiv_merge (info->cur.x_start, info->cur.y_start, info);
01150 }
01151
01152 struct_equiv_improve_checkpoint (&info->best_match, info);
01153 info->x_end = xi;
01154 info->y_end = yi;
01155 if (info->cur.x_start != x_stop)
01156 for (;;)
01157 {
01158
01159 while (!INSN_P (xi) && xi != x_stop)
01160 xi = PREV_INSN (xi);
01161
01162 while (!INSN_P (yi) && yi != y_stop)
01163 yi = PREV_INSN (yi);
01164
01165 if (!insns_match_p (xi, yi, info))
01166 break;
01167 if (INSN_P (xi))
01168 {
01169 if (info->mode & STRUCT_EQUIV_FINAL)
01170 struct_equiv_merge (xi, yi, info);
01171 info->cur.ninsns++;
01172 struct_equiv_improve_checkpoint (&info->best_match, info);
01173 }
01174 if (xi == x_stop || yi == y_stop)
01175 {
01176
01177
01178
01179
01180 if (info->best_match.x_start != info->cur.x_start
01181 && (xi == BB_HEAD (info->x_block)
01182 || yi == BB_HEAD (info->y_block)))
01183 {
01184 info->cur.ninsns++;
01185 struct_equiv_improve_checkpoint (&info->best_match, info);
01186 info->cur.ninsns--;
01187 if (info->best_match.ninsns > info->cur.ninsns)
01188 info->best_match.ninsns = info->cur.ninsns;
01189 }
01190 break;
01191 }
01192 xi = PREV_INSN (xi);
01193 yi = PREV_INSN (yi);
01194 }
01195
01196
01197
01198 cancel_changes (0);
01199
01200
01201 struct_equiv_restore_checkpoint (&info->best_match, info);
01202
01203
01204
01205
01206 if (info->cur.ninsns)
01207 {
01208 xi = info->cur.x_start;
01209 yi = info->cur.y_start;
01210 while (xi != x_stop && !INSN_P (PREV_INSN (xi)))
01211 xi = PREV_INSN (xi);
01212
01213 while (yi != y_stop && !INSN_P (PREV_INSN (yi)))
01214 yi = PREV_INSN (yi);
01215
01216 info->cur.x_start = xi;
01217 info->cur.y_start = yi;
01218 }
01219
01220 if (!info->cur.input_valid)
01221 info->x_input = info->y_input = info->input_reg = NULL_RTX;
01222 if (!info->need_rerun)
01223 {
01224 find_dying_inputs (info);
01225 if (info->mode & STRUCT_EQUIV_FINAL)
01226 {
01227 if (info->check_input_conflict && ! resolve_input_conflict (info))
01228 gcc_unreachable ();
01229 }
01230 else
01231 {
01232 bool input_conflict = info->had_input_conflict;
01233
01234 if (!input_conflict
01235 && info->dying_inputs > 1
01236 && bitmap_intersect_p (info->x_local_live, info->y_local_live))
01237 {
01238 regset_head clobbered_regs;
01239
01240 INIT_REG_SET (&clobbered_regs);
01241 for (i = 0; i < info->cur.local_count; i++)
01242 {
01243 if (assign_reg_reg_set (&clobbered_regs, info->y_local[i], 0))
01244 {
01245 input_conflict = true;
01246 break;
01247 }
01248 assign_reg_reg_set (&clobbered_regs, info->x_local[i], 1);
01249 }
01250 CLEAR_REG_SET (&clobbered_regs);
01251 }
01252 if (input_conflict && !info->check_input_conflict)
01253 info->need_rerun = true;
01254 info->check_input_conflict = input_conflict;
01255 }
01256 }
01257
01258 if (info->mode & STRUCT_EQUIV_NEED_FULL_BLOCK
01259 && (info->cur.x_start != x_stop || info->cur.y_start != y_stop))
01260 return 0;
01261 return info->cur.ninsns;
01262 }
01263
01264
01265
01266 static void
01267 find_dying_inputs (struct equiv_info *info)
01268 {
01269 int i;
01270
01271 info->dying_inputs = 0;
01272 for (i = info->cur.local_count-1; i >=0; i--)
01273 {
01274 rtx x = info->x_local[i];
01275 unsigned regno = REGNO (x);
01276 int nregs = (regno >= FIRST_PSEUDO_REGISTER
01277 ? 1 : hard_regno_nregs[regno][GET_MODE (x)]);
01278
01279 for (info->local_rvalue[i] = false; nregs > 0; regno++, --nregs)
01280 if (REGNO_REG_SET_P (info->x_local_live, regno))
01281 {
01282 info->dying_inputs++;
01283 info->local_rvalue[i] = true;
01284 break;
01285 }
01286 }
01287 }
01288
01289
01290
01291
01292
01293 static bool
01294 resolve_input_conflict (struct equiv_info *info)
01295 {
01296 int i, j, end;
01297 int nswaps = 0;
01298 rtx save_x_local[STRUCT_EQUIV_MAX_LOCAL];
01299 rtx save_y_local[STRUCT_EQUIV_MAX_LOCAL];
01300
01301 find_dying_inputs (info);
01302 if (info->dying_inputs <= 1)
01303 return true;
01304 memcpy (save_x_local, info->x_local, sizeof save_x_local);
01305 memcpy (save_y_local, info->y_local, sizeof save_y_local);
01306 end = info->cur.local_count - 1;
01307 for (i = 0; i <= end; i++)
01308 {
01309
01310
01311
01312 int max_swaps = end - i;
01313
01314
01315 if (!info->local_rvalue[i])
01316 continue;
01317
01318 for (j = i + 1; j <= end; j++)
01319 {
01320 rtx tmp;
01321
01322 if (!info->local_rvalue[j])
01323 continue;
01324 if (!reg_overlap_mentioned_p (info->x_local[i], info->y_local[j]))
01325 continue;
01326 if (--max_swaps < 0)
01327 {
01328 memcpy (info->x_local, save_x_local, sizeof save_x_local);
01329 memcpy (info->y_local, save_y_local, sizeof save_y_local);
01330 return false;
01331 }
01332 nswaps++;
01333 tmp = info->x_local[i];
01334 info->x_local[i] = info->x_local[j];
01335 info->x_local[j] = tmp;
01336 tmp = info->y_local[i];
01337 info->y_local[i] = info->y_local[j];
01338 info->y_local[j] = tmp;
01339 j = i;
01340 }
01341 }
01342 info->had_input_conflict = true;
01343 if (dump_file && nswaps)
01344 fprintf (dump_file, "Resolved input conflict, %d %s.\n",
01345 nswaps, nswaps == 1 ? "swap" : "swaps");
01346 return true;
01347 }