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
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 #define REG_OK_STRICT
00090
00091 #include "config.h"
00092 #include "system.h"
00093 #include "coretypes.h"
00094 #include "tm.h"
00095 #include "rtl.h"
00096 #include "tm_p.h"
00097 #include "insn-config.h"
00098 #include "expr.h"
00099 #include "optabs.h"
00100 #include "recog.h"
00101 #include "reload.h"
00102 #include "regs.h"
00103 #include "addresses.h"
00104 #include "hard-reg-set.h"
00105 #include "flags.h"
00106 #include "real.h"
00107 #include "output.h"
00108 #include "function.h"
00109 #include "toplev.h"
00110 #include "params.h"
00111 #include "target.h"
00112
00113
00114 #define CONST_POOL_OK_P(X) \
00115 (CONSTANT_P (X) \
00116 && GET_CODE (X) != HIGH \
00117 && !targetm.cannot_force_const_mem (X))
00118
00119
00120
00121 #define SMALL_REGISTER_CLASS_P(C) \
00122 (reg_class_size [(C)] == 1 \
00123 || (reg_class_size [(C)] >= 1 && CLASS_LIKELY_SPILLED_P (C)))
00124
00125
00126
00127
00128 int n_reloads;
00129 struct reload rld[MAX_RELOADS];
00130
00131
00132
00133 int n_earlyclobbers;
00134 rtx reload_earlyclobbers[MAX_RECOG_OPERANDS];
00135
00136 int reload_n_operands;
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 static int replace_reloads;
00147
00148
00149 struct replacement
00150 {
00151 rtx *where;
00152 rtx *subreg_loc;
00153
00154 int what;
00155 enum machine_mode mode;
00156 };
00157
00158 static struct replacement replacements[MAX_RECOG_OPERANDS * ((MAX_REGS_PER_ADDRESS * 2) + 1)];
00159
00160
00161 static int n_replacements;
00162
00163
00164 struct decomposition
00165 {
00166 int reg_flag;
00167 int safe;
00168 rtx base;
00169 HOST_WIDE_INT start;
00170 HOST_WIDE_INT end;
00171 };
00172
00173 #ifdef SECONDARY_MEMORY_NEEDED
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 static rtx secondary_memlocs[NUM_MACHINE_MODES];
00184 static rtx secondary_memlocs_elim[NUM_MACHINE_MODES][MAX_RECOG_OPERANDS];
00185 static int secondary_memlocs_elim_used = 0;
00186 #endif
00187
00188
00189
00190 static rtx this_insn;
00191
00192
00193 static int this_insn_is_asm;
00194
00195
00196
00197
00198 static int hard_regs_live_known;
00199
00200
00201
00202
00203
00204 static short *static_reload_reg_p;
00205
00206
00207 static int subst_reg_equivs_changed;
00208
00209
00210
00211 static int output_reloadnum;
00212
00213
00214 #define MATCHES(x, y) \
00215 (x == y || (x != 0 && (REG_P (x) \
00216 ? REG_P (y) && REGNO (x) == REGNO (y) \
00217 : rtx_equal_p (x, y) && ! side_effects_p (x))))
00218
00219
00220
00221 #define MERGABLE_RELOADS(when1, when2, op1, op2) \
00222 ((when1) == RELOAD_OTHER || (when2) == RELOAD_OTHER \
00223 || ((when1) == (when2) && (op1) == (op2)) \
00224 || ((when1) == RELOAD_FOR_INPUT && (when2) == RELOAD_FOR_INPUT) \
00225 || ((when1) == RELOAD_FOR_OPERAND_ADDRESS \
00226 && (when2) == RELOAD_FOR_OPERAND_ADDRESS) \
00227 || ((when1) == RELOAD_FOR_OTHER_ADDRESS \
00228 && (when2) == RELOAD_FOR_OTHER_ADDRESS))
00229
00230
00231 #define MERGE_TO_OTHER(when1, when2, op1, op2) \
00232 ((when1) != (when2) \
00233 || ! ((op1) == (op2) \
00234 || (when1) == RELOAD_FOR_INPUT \
00235 || (when1) == RELOAD_FOR_OPERAND_ADDRESS \
00236 || (when1) == RELOAD_FOR_OTHER_ADDRESS))
00237
00238
00239
00240 #define ADDR_TYPE(type) \
00241 ((type) == RELOAD_FOR_INPUT_ADDRESS \
00242 ? RELOAD_FOR_INPADDR_ADDRESS \
00243 : ((type) == RELOAD_FOR_OUTPUT_ADDRESS \
00244 ? RELOAD_FOR_OUTADDR_ADDRESS \
00245 : (type)))
00246
00247 static int push_secondary_reload (int, rtx, int, int, enum reg_class,
00248 enum machine_mode, enum reload_type,
00249 enum insn_code *, secondary_reload_info *);
00250 static enum reg_class find_valid_class (enum machine_mode, enum machine_mode,
00251 int, unsigned int);
00252 static int reload_inner_reg_of_subreg (rtx, enum machine_mode, int);
00253 static void push_replacement (rtx *, int, enum machine_mode);
00254 static void dup_replacements (rtx *, rtx *);
00255 static void combine_reloads (void);
00256 static int find_reusable_reload (rtx *, rtx, enum reg_class,
00257 enum reload_type, int, int);
00258 static rtx find_dummy_reload (rtx, rtx, rtx *, rtx *, enum machine_mode,
00259 enum machine_mode, enum reg_class, int, int);
00260 static int hard_reg_set_here_p (unsigned int, unsigned int, rtx);
00261 static struct decomposition decompose (rtx);
00262 static int immune_p (rtx, rtx, struct decomposition);
00263 static int alternative_allows_memconst (const char *, int);
00264 static rtx find_reloads_toplev (rtx, int, enum reload_type, int, int, rtx,
00265 int *);
00266 static rtx make_memloc (rtx, int);
00267 static int maybe_memory_address_p (enum machine_mode, rtx, rtx *);
00268 static int find_reloads_address (enum machine_mode, rtx *, rtx, rtx *,
00269 int, enum reload_type, int, rtx);
00270 static rtx subst_reg_equivs (rtx, rtx);
00271 static rtx subst_indexed_address (rtx);
00272 static void update_auto_inc_notes (rtx, int, int);
00273 static int find_reloads_address_1 (enum machine_mode, rtx, int,
00274 enum rtx_code, enum rtx_code, rtx *,
00275 int, enum reload_type,int, rtx);
00276 static void find_reloads_address_part (rtx, rtx *, enum reg_class,
00277 enum machine_mode, int,
00278 enum reload_type, int);
00279 static rtx find_reloads_subreg_address (rtx, int, int, enum reload_type,
00280 int, rtx);
00281 static void copy_replacements_1 (rtx *, rtx *, int);
00282 static int find_inc_amount (rtx, rtx);
00283 static int refers_to_mem_for_reload_p (rtx);
00284 static int refers_to_regno_for_reload_p (unsigned int, unsigned int,
00285 rtx, rtx *);
00286
00287
00288
00289
00290 static void
00291 push_reg_equiv_alt_mem (int regno, rtx mem)
00292 {
00293 rtx it;
00294
00295 for (it = reg_equiv_alt_mem_list [regno]; it; it = XEXP (it, 1))
00296 if (rtx_equal_p (XEXP (it, 0), mem))
00297 return;
00298
00299 reg_equiv_alt_mem_list [regno]
00300 = alloc_EXPR_LIST (REG_EQUIV, mem,
00301 reg_equiv_alt_mem_list [regno]);
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 static int
00314 push_secondary_reload (int in_p, rtx x, int opnum, int optional,
00315 enum reg_class reload_class,
00316 enum machine_mode reload_mode, enum reload_type type,
00317 enum insn_code *picode, secondary_reload_info *prev_sri)
00318 {
00319 enum reg_class class = NO_REGS;
00320 enum reg_class scratch_class;
00321 enum machine_mode mode = reload_mode;
00322 enum insn_code icode = CODE_FOR_nothing;
00323 enum insn_code t_icode = CODE_FOR_nothing;
00324 enum reload_type secondary_type;
00325 int s_reload, t_reload = -1;
00326 const char *scratch_constraint;
00327 char letter;
00328 secondary_reload_info sri;
00329
00330 if (type == RELOAD_FOR_INPUT_ADDRESS
00331 || type == RELOAD_FOR_OUTPUT_ADDRESS
00332 || type == RELOAD_FOR_INPADDR_ADDRESS
00333 || type == RELOAD_FOR_OUTADDR_ADDRESS)
00334 secondary_type = type;
00335 else
00336 secondary_type = in_p ? RELOAD_FOR_INPUT_ADDRESS : RELOAD_FOR_OUTPUT_ADDRESS;
00337
00338 *picode = CODE_FOR_nothing;
00339
00340
00341
00342 if (GET_CODE (x) == SUBREG
00343 && (GET_MODE_SIZE (GET_MODE (x))
00344 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
00345 {
00346 x = SUBREG_REG (x);
00347 reload_mode = GET_MODE (x);
00348 }
00349
00350
00351
00352
00353
00354
00355
00356 if (REG_P (x) && REGNO (x) >= FIRST_PSEUDO_REGISTER
00357 && reg_equiv_mem[REGNO (x)] != 0)
00358 x = reg_equiv_mem[REGNO (x)];
00359
00360 sri.icode = CODE_FOR_nothing;
00361 sri.prev_sri = prev_sri;
00362 class = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri);
00363 icode = sri.icode;
00364
00365
00366 if (class == NO_REGS && icode == CODE_FOR_nothing)
00367 return -1;
00368
00369 if (class != NO_REGS)
00370 t_reload = push_secondary_reload (in_p, x, opnum, optional, class,
00371 reload_mode, type, &t_icode, &sri);
00372
00373
00374
00375
00376 if (icode != CODE_FOR_nothing)
00377 {
00378
00379
00380
00381
00382
00383
00384
00385
00386 gcc_assert (insn_data[(int) icode].n_operands == 3);
00387
00388
00389
00390
00391
00392 gcc_assert (class == NO_REGS);
00393
00394 scratch_constraint = insn_data[(int) icode].operand[2].constraint;
00395 gcc_assert (*scratch_constraint == '=');
00396 scratch_constraint++;
00397 if (*scratch_constraint == '&')
00398 scratch_constraint++;
00399 letter = *scratch_constraint;
00400 scratch_class = (letter == 'r' ? GENERAL_REGS
00401 : REG_CLASS_FROM_CONSTRAINT ((unsigned char) letter,
00402 scratch_constraint));
00403
00404 class = scratch_class;
00405 mode = insn_data[(int) icode].operand[2].mode;
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 gcc_assert (!in_p || class != reload_class || icode != CODE_FOR_nothing
00423 || t_icode != CODE_FOR_nothing);
00424
00425
00426 for (s_reload = 0; s_reload < n_reloads; s_reload++)
00427 if (rld[s_reload].secondary_p
00428 && (reg_class_subset_p (class, rld[s_reload].class)
00429 || reg_class_subset_p (rld[s_reload].class, class))
00430 && ((in_p && rld[s_reload].inmode == mode)
00431 || (! in_p && rld[s_reload].outmode == mode))
00432 && ((in_p && rld[s_reload].secondary_in_reload == t_reload)
00433 || (! in_p && rld[s_reload].secondary_out_reload == t_reload))
00434 && ((in_p && rld[s_reload].secondary_in_icode == t_icode)
00435 || (! in_p && rld[s_reload].secondary_out_icode == t_icode))
00436 && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
00437 && MERGABLE_RELOADS (secondary_type, rld[s_reload].when_needed,
00438 opnum, rld[s_reload].opnum))
00439 {
00440 if (in_p)
00441 rld[s_reload].inmode = mode;
00442 if (! in_p)
00443 rld[s_reload].outmode = mode;
00444
00445 if (reg_class_subset_p (class, rld[s_reload].class))
00446 rld[s_reload].class = class;
00447
00448 rld[s_reload].opnum = MIN (rld[s_reload].opnum, opnum);
00449 rld[s_reload].optional &= optional;
00450 rld[s_reload].secondary_p = 1;
00451 if (MERGE_TO_OTHER (secondary_type, rld[s_reload].when_needed,
00452 opnum, rld[s_reload].opnum))
00453 rld[s_reload].when_needed = RELOAD_OTHER;
00454 }
00455
00456 if (s_reload == n_reloads)
00457 {
00458 #ifdef SECONDARY_MEMORY_NEEDED
00459
00460
00461
00462
00463
00464 if (in_p && icode == CODE_FOR_nothing
00465 && SECONDARY_MEMORY_NEEDED (class, reload_class, mode))
00466 {
00467 get_secondary_mem (x, reload_mode, opnum, type);
00468
00469
00470
00471 s_reload = n_reloads;
00472 }
00473 #endif
00474
00475
00476 rld[s_reload].in = rld[s_reload].out = 0;
00477 rld[s_reload].class = class;
00478
00479 rld[s_reload].inmode = in_p ? mode : VOIDmode;
00480 rld[s_reload].outmode = ! in_p ? mode : VOIDmode;
00481 rld[s_reload].reg_rtx = 0;
00482 rld[s_reload].optional = optional;
00483 rld[s_reload].inc = 0;
00484
00485 rld[s_reload].nocombine = 1;
00486 rld[s_reload].in_reg = 0;
00487 rld[s_reload].out_reg = 0;
00488 rld[s_reload].opnum = opnum;
00489 rld[s_reload].when_needed = secondary_type;
00490 rld[s_reload].secondary_in_reload = in_p ? t_reload : -1;
00491 rld[s_reload].secondary_out_reload = ! in_p ? t_reload : -1;
00492 rld[s_reload].secondary_in_icode = in_p ? t_icode : CODE_FOR_nothing;
00493 rld[s_reload].secondary_out_icode
00494 = ! in_p ? t_icode : CODE_FOR_nothing;
00495 rld[s_reload].secondary_p = 1;
00496
00497 n_reloads++;
00498
00499 #ifdef SECONDARY_MEMORY_NEEDED
00500 if (! in_p && icode == CODE_FOR_nothing
00501 && SECONDARY_MEMORY_NEEDED (reload_class, class, mode))
00502 get_secondary_mem (x, mode, opnum, type);
00503 #endif
00504 }
00505
00506 *picode = icode;
00507 return s_reload;
00508 }
00509
00510
00511
00512
00513 enum reg_class
00514 secondary_reload_class (bool in_p, enum reg_class class,
00515 enum machine_mode mode, rtx x)
00516 {
00517 enum insn_code icode;
00518 secondary_reload_info sri;
00519
00520 sri.icode = CODE_FOR_nothing;
00521 sri.prev_sri = NULL;
00522 class = targetm.secondary_reload (in_p, x, class, mode, &sri);
00523 icode = sri.icode;
00524
00525
00526
00527 if (icode == CODE_FOR_nothing || class != NO_REGS)
00528 return class;
00529
00530
00531
00532 return scratch_reload_class (icode);
00533 }
00534
00535
00536
00537
00538
00539
00540 enum reg_class
00541 scratch_reload_class (enum insn_code icode)
00542 {
00543 const char *scratch_constraint;
00544 char scratch_letter;
00545 enum reg_class class;
00546
00547 gcc_assert (insn_data[(int) icode].n_operands == 3);
00548 scratch_constraint = insn_data[(int) icode].operand[2].constraint;
00549 gcc_assert (*scratch_constraint == '=');
00550 scratch_constraint++;
00551 if (*scratch_constraint == '&')
00552 scratch_constraint++;
00553 scratch_letter = *scratch_constraint;
00554 if (scratch_letter == 'r')
00555 return GENERAL_REGS;
00556 class = REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter,
00557 scratch_constraint);
00558 gcc_assert (class != NO_REGS);
00559 return class;
00560 }
00561
00562 #ifdef SECONDARY_MEMORY_NEEDED
00563
00564
00565
00566
00567
00568 rtx
00569 get_secondary_mem (rtx x ATTRIBUTE_UNUSED, enum machine_mode mode,
00570 int opnum, enum reload_type type)
00571 {
00572 rtx loc;
00573 int mem_valid;
00574
00575
00576
00577
00578
00579
00580 #ifdef SECONDARY_MEMORY_NEEDED_MODE
00581 mode = SECONDARY_MEMORY_NEEDED_MODE (mode);
00582 #else
00583 if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD && INTEGRAL_MODE_P (mode))
00584 mode = mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0);
00585 #endif
00586
00587
00588 if (secondary_memlocs_elim[(int) mode][opnum] != 0)
00589 return secondary_memlocs_elim[(int) mode][opnum];
00590
00591
00592
00593
00594
00595 if (secondary_memlocs[(int) mode] == 0)
00596 {
00597 #ifdef SECONDARY_MEMORY_NEEDED_RTX
00598 secondary_memlocs[(int) mode] = SECONDARY_MEMORY_NEEDED_RTX (mode);
00599 #else
00600 secondary_memlocs[(int) mode]
00601 = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
00602 #endif
00603 }
00604
00605
00606
00607
00608 loc = eliminate_regs (secondary_memlocs[(int) mode], VOIDmode, NULL_RTX);
00609 mem_valid = strict_memory_address_p (mode, XEXP (loc, 0));
00610
00611 if (! mem_valid && loc == secondary_memlocs[(int) mode])
00612 loc = copy_rtx (loc);
00613
00614
00615
00616
00617
00618
00619
00620
00621 if (! mem_valid)
00622 {
00623 type = (type == RELOAD_FOR_INPUT ? RELOAD_FOR_INPUT_ADDRESS
00624 : type == RELOAD_FOR_OUTPUT ? RELOAD_FOR_OUTPUT_ADDRESS
00625 : RELOAD_OTHER);
00626
00627 find_reloads_address (mode, &loc, XEXP (loc, 0), &XEXP (loc, 0),
00628 opnum, type, 0, 0);
00629 }
00630
00631 secondary_memlocs_elim[(int) mode][opnum] = loc;
00632 if (secondary_memlocs_elim_used <= (int)mode)
00633 secondary_memlocs_elim_used = (int)mode + 1;
00634 return loc;
00635 }
00636
00637
00638
00639 void
00640 clear_secondary_mem (void)
00641 {
00642 memset (secondary_memlocs, 0, sizeof secondary_memlocs);
00643 }
00644 #endif
00645
00646
00647
00648
00649
00650
00651
00652 static enum reg_class
00653 find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
00654 enum machine_mode inner ATTRIBUTE_UNUSED, int n,
00655 unsigned int dest_regno ATTRIBUTE_UNUSED)
00656 {
00657 int best_cost = -1;
00658 int class;
00659 int regno;
00660 enum reg_class best_class = NO_REGS;
00661 enum reg_class dest_class ATTRIBUTE_UNUSED = REGNO_REG_CLASS (dest_regno);
00662 unsigned int best_size = 0;
00663 int cost;
00664
00665 for (class = 1; class < N_REG_CLASSES; class++)
00666 {
00667 int bad = 0;
00668 int good = 0;
00669 for (regno = 0; regno < FIRST_PSEUDO_REGISTER - n && ! bad; regno++)
00670 if (TEST_HARD_REG_BIT (reg_class_contents[class], regno))
00671 {
00672 if (HARD_REGNO_MODE_OK (regno, inner))
00673 {
00674 good = 1;
00675 if (! TEST_HARD_REG_BIT (reg_class_contents[class], regno + n)
00676 || ! HARD_REGNO_MODE_OK (regno + n, outer))
00677 bad = 1;
00678 }
00679 }
00680
00681 if (bad || !good)
00682 continue;
00683 cost = REGISTER_MOVE_COST (outer, class, dest_class);
00684
00685 if ((reg_class_size[class] > best_size
00686 && (best_cost < 0 || best_cost >= cost))
00687 || best_cost > cost)
00688 {
00689 best_class = class;
00690 best_size = reg_class_size[class];
00691 best_cost = REGISTER_MOVE_COST (outer, class, dest_class);
00692 }
00693 }
00694
00695 gcc_assert (best_size != 0);
00696
00697 return best_class;
00698 }
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 static int
00709 find_reusable_reload (rtx *p_in, rtx out, enum reg_class class,
00710 enum reload_type type, int opnum, int dont_share)
00711 {
00712 rtx in = *p_in;
00713 int i;
00714
00715
00716
00717 if (earlyclobber_operand_p (out))
00718 return n_reloads;
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729 for (i = 0; i < n_reloads; i++)
00730 if ((reg_class_subset_p (class, rld[i].class)
00731 || reg_class_subset_p (rld[i].class, class))
00732
00733 && (rld[i].reg_rtx == 0
00734 || TEST_HARD_REG_BIT (reg_class_contents[(int) class],
00735 true_regnum (rld[i].reg_rtx)))
00736 && ((in != 0 && MATCHES (rld[i].in, in) && ! dont_share
00737 && (out == 0 || rld[i].out == 0 || MATCHES (rld[i].out, out)))
00738 || (out != 0 && MATCHES (rld[i].out, out)
00739 && (in == 0 || rld[i].in == 0 || MATCHES (rld[i].in, in))))
00740 && (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
00741 && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
00742 && MERGABLE_RELOADS (type, rld[i].when_needed, opnum, rld[i].opnum))
00743 return i;
00744
00745
00746
00747
00748
00749
00750 for (i = 0; i < n_reloads; i++)
00751 if ((reg_class_subset_p (class, rld[i].class)
00752 || reg_class_subset_p (rld[i].class, class))
00753
00754
00755 && (rld[i].reg_rtx == 0
00756 || TEST_HARD_REG_BIT (reg_class_contents[(int) class],
00757 true_regnum (rld[i].reg_rtx)))
00758 && out == 0 && rld[i].out == 0 && rld[i].in != 0
00759 && ((REG_P (in)
00760 && GET_RTX_CLASS (GET_CODE (rld[i].in)) == RTX_AUTOINC
00761 && MATCHES (XEXP (rld[i].in, 0), in))
00762 || (REG_P (rld[i].in)
00763 && GET_RTX_CLASS (GET_CODE (in)) == RTX_AUTOINC
00764 && MATCHES (XEXP (in, 0), rld[i].in)))
00765 && (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
00766 && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
00767 && MERGABLE_RELOADS (type, rld[i].when_needed,
00768 opnum, rld[i].opnum))
00769 {
00770
00771
00772 if (REG_P (in))
00773 *p_in = rld[i].in;
00774 return i;
00775 }
00776 return n_reloads;
00777 }
00778
00779
00780
00781
00782 static int
00783 reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, int output)
00784 {
00785 rtx inner;
00786
00787
00788 if (GET_CODE (x) != SUBREG)
00789 return 0;
00790
00791 inner = SUBREG_REG (x);
00792
00793
00794 if (CONSTANT_P (inner) || GET_CODE (inner) == PLUS)
00795 return 1;
00796
00797
00798
00799 if (!REG_P (inner)
00800 || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
00801 return 0;
00802
00803
00804 if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode))
00805 return 1;
00806
00807
00808
00809
00810 return (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
00811 && output
00812 && GET_MODE_SIZE (GET_MODE (inner)) > UNITS_PER_WORD
00813 && ((GET_MODE_SIZE (GET_MODE (inner)) / UNITS_PER_WORD)
00814 != (int) hard_regno_nregs[REGNO (inner)][GET_MODE (inner)]));
00815 }
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831 static int
00832 can_reload_into (rtx in, int regno, enum machine_mode mode)
00833 {
00834 rtx dst, test_insn;
00835 int r = 0;
00836 struct recog_data save_recog_data;
00837
00838
00839
00840
00841
00842
00843 if (REG_P (in))
00844 return 1;
00845
00846
00847
00848
00849
00850 if (MEM_P (in))
00851 return 1;
00852
00853
00854
00855 dst = gen_rtx_REG (mode, regno);
00856 test_insn = make_insn_raw (gen_rtx_SET (VOIDmode, dst, in));
00857 save_recog_data = recog_data;
00858 if (recog_memoized (test_insn) >= 0)
00859 {
00860 extract_insn (test_insn);
00861 r = constrain_operands (1);
00862 }
00863 recog_data = save_recog_data;
00864 return r;
00865 }
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900 int
00901 push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
00902 enum reg_class class, enum machine_mode inmode,
00903 enum machine_mode outmode, int strict_low, int optional,
00904 int opnum, enum reload_type type)
00905 {
00906 int i;
00907 int dont_share = 0;
00908 int dont_remove_subreg = 0;
00909 rtx *in_subreg_loc = 0, *out_subreg_loc = 0;
00910 int secondary_in_reload = -1, secondary_out_reload = -1;
00911 enum insn_code secondary_in_icode = CODE_FOR_nothing;
00912 enum insn_code secondary_out_icode = CODE_FOR_nothing;
00913
00914
00915
00916
00917 if (inmode == VOIDmode && in != 0)
00918 inmode = GET_MODE (in);
00919 if (outmode == VOIDmode && out != 0)
00920 outmode = GET_MODE (out);
00921
00922
00923
00924
00925
00926 if (in != 0 && REG_P (in))
00927 {
00928 int regno = REGNO (in);
00929
00930 if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
00931 && reg_equiv_constant[regno] != 0)
00932 in = reg_equiv_constant[regno];
00933 }
00934
00935
00936
00937
00938 if (out != 0 && REG_P (out))
00939 {
00940 int regno = REGNO (out);
00941
00942 if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
00943 && reg_equiv_constant[regno] != 0)
00944 out = reg_equiv_constant[regno];
00945 }
00946
00947
00948
00949 if (in != 0 && out != 0 && MEM_P (in) && rtx_equal_p (in, out))
00950 switch (GET_CODE (XEXP (in, 0)))
00951 {
00952 case POST_INC: case POST_DEC: case POST_MODIFY:
00953 in = replace_equiv_address_nv (in, XEXP (XEXP (in, 0), 0));
00954 break;
00955
00956 case PRE_INC: case PRE_DEC: case PRE_MODIFY:
00957 out = replace_equiv_address_nv (out, XEXP (XEXP (out, 0), 0));
00958 break;
00959
00960 default:
00961 break;
00962 }
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994 if (in != 0 && GET_CODE (in) == SUBREG
00995 && (subreg_lowpart_p (in) || strict_low)
00996 #ifdef CANNOT_CHANGE_MODE_CLASS
00997 && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, class)
00998 #endif
00999 && (CONSTANT_P (SUBREG_REG (in))
01000 || GET_CODE (SUBREG_REG (in)) == PLUS
01001 || strict_low
01002 || (((REG_P (SUBREG_REG (in))
01003 && REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER)
01004 || MEM_P (SUBREG_REG (in)))
01005 && ((GET_MODE_SIZE (inmode)
01006 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
01007 #ifdef LOAD_EXTEND_OP
01008 || (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
01009 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
01010 <= UNITS_PER_WORD)
01011 && (GET_MODE_SIZE (inmode)
01012 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
01013 && INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in)))
01014 && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != UNKNOWN)
01015 #endif
01016 #ifdef WORD_REGISTER_OPERATIONS
01017 || ((GET_MODE_SIZE (inmode)
01018 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
01019 && ((GET_MODE_SIZE (inmode) - 1) / UNITS_PER_WORD ==
01020 ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) - 1)
01021 / UNITS_PER_WORD)))
01022 #endif
01023 ))
01024 || (REG_P (SUBREG_REG (in))
01025 && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
01026
01027
01028 && (out == 0 || subreg_lowpart_p (in))
01029 && ((GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
01030 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
01031 > UNITS_PER_WORD)
01032 && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
01033 / UNITS_PER_WORD)
01034 != (int) hard_regno_nregs[REGNO (SUBREG_REG (in))]
01035 [GET_MODE (SUBREG_REG (in))]))
01036 || ! HARD_REGNO_MODE_OK (subreg_regno (in), inmode)))
01037 || (secondary_reload_class (1, class, inmode, in) != NO_REGS
01038 && (secondary_reload_class (1, class, GET_MODE (SUBREG_REG (in)),
01039 SUBREG_REG (in))
01040 == NO_REGS))
01041 #ifdef CANNOT_CHANGE_MODE_CLASS
01042 || (REG_P (SUBREG_REG (in))
01043 && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
01044 && REG_CANNOT_CHANGE_MODE_P
01045 (REGNO (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in)), inmode))
01046 #endif
01047 ))
01048 {
01049 in_subreg_loc = inloc;
01050 inloc = &SUBREG_REG (in);
01051 in = *inloc;
01052 #if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
01053 if (MEM_P (in))
01054
01055
01056 gcc_assert (GET_MODE_SIZE (GET_MODE (in)) <= GET_MODE_SIZE (inmode));
01057 #endif
01058 inmode = GET_MODE (in);
01059 }
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071 if (in != 0 && reload_inner_reg_of_subreg (in, inmode, 0))
01072 {
01073 enum reg_class in_class = class;
01074
01075 if (REG_P (SUBREG_REG (in)))
01076 in_class
01077 = find_valid_class (inmode, GET_MODE (SUBREG_REG (in)),
01078 subreg_regno_offset (REGNO (SUBREG_REG (in)),
01079 GET_MODE (SUBREG_REG (in)),
01080 SUBREG_BYTE (in),
01081 GET_MODE (in)),
01082 REGNO (SUBREG_REG (in)));
01083
01084
01085
01086
01087
01088
01089 push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), (rtx *) 0,
01090 in_class, VOIDmode, VOIDmode, 0, 0, opnum, type);
01091 dont_remove_subreg = 1;
01092 }
01093
01094
01095
01096
01097
01098
01099
01100 if (out != 0 && GET_CODE (out) == SUBREG
01101 && (subreg_lowpart_p (out) || strict_low)
01102 #ifdef CANNOT_CHANGE_MODE_CLASS
01103 && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, class)
01104 #endif
01105 && (CONSTANT_P (SUBREG_REG (out))
01106 || strict_low
01107 || (((REG_P (SUBREG_REG (out))
01108 && REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER)
01109 || MEM_P (SUBREG_REG (out)))
01110 && ((GET_MODE_SIZE (outmode)
01111 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
01112 #ifdef WORD_REGISTER_OPERATIONS
01113 || ((GET_MODE_SIZE (outmode)
01114 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
01115 && ((GET_MODE_SIZE (outmode) - 1) / UNITS_PER_WORD ==
01116 ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - 1)
01117 / UNITS_PER_WORD)))
01118 #endif
01119 ))
01120 || (REG_P (SUBREG_REG (out))
01121 && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
01122 && ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
01123 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
01124 > UNITS_PER_WORD)
01125 && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
01126 / UNITS_PER_WORD)
01127 != (int) hard_regno_nregs[REGNO (SUBREG_REG (out))]
01128 [GET_MODE (SUBREG_REG (out))]))
01129 || ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
01130 || (secondary_reload_class (0, class, outmode, out) != NO_REGS
01131 && (secondary_reload_class (0, class, GET_MODE (SUBREG_REG (out)),
01132 SUBREG_REG (out))
01133 == NO_REGS))
01134 #ifdef CANNOT_CHANGE_MODE_CLASS
01135 || (REG_P (SUBREG_REG (out))
01136 && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
01137 && REG_CANNOT_CHANGE_MODE_P (REGNO (SUBREG_REG (out)),
01138 GET_MODE (SUBREG_REG (out)),
01139 outmode))
01140 #endif
01141 ))
01142 {
01143 out_subreg_loc = outloc;
01144 outloc = &SUBREG_REG (out);
01145 out = *outloc;
01146 #if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
01147 gcc_assert (!MEM_P (out)
01148 || GET_MODE_SIZE (GET_MODE (out))
01149 <= GET_MODE_SIZE (outmode));
01150 #endif
01151 outmode = GET_MODE (out);
01152 }
01153
01154
01155
01156
01157
01158
01159
01160
01161 if (out != 0 && reload_inner_reg_of_subreg (out, outmode, 1))
01162 {
01163
01164
01165
01166
01167
01168 dont_remove_subreg = 1;
01169 push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
01170 &SUBREG_REG (out),
01171 find_valid_class (outmode, GET_MODE (SUBREG_REG (out)),
01172 subreg_regno_offset (REGNO (SUBREG_REG (out)),
01173 GET_MODE (SUBREG_REG (out)),
01174 SUBREG_BYTE (out),
01175 GET_MODE (out)),
01176 REGNO (SUBREG_REG (out))),
01177 VOIDmode, VOIDmode, 0, 0,
01178 opnum, RELOAD_OTHER);
01179 }
01180
01181
01182 if (in != 0 && out != 0 && MEM_P (out)
01183 && (REG_P (in) || MEM_P (in))
01184 && reg_overlap_mentioned_for_reload_p (in, XEXP (out, 0)))
01185 dont_share = 1;
01186
01187
01188
01189
01190 if (in != 0 && GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))
01191 && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
01192 && ! dont_remove_subreg)
01193 in = gen_rtx_REG (GET_MODE (in), subreg_regno (in));
01194
01195
01196 if (out != 0 && GET_CODE (out) == SUBREG
01197 && REG_P (SUBREG_REG (out))
01198 && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
01199 && ! dont_remove_subreg)
01200 out = gen_rtx_REG (GET_MODE (out), subreg_regno (out));
01201
01202
01203
01204 {
01205 enum reg_class preferred_class = class;
01206
01207 if (in != 0)
01208 preferred_class = PREFERRED_RELOAD_CLASS (in, class);
01209
01210
01211 #ifdef PREFERRED_OUTPUT_RELOAD_CLASS
01212 if (out != 0)
01213 preferred_class = PREFERRED_OUTPUT_RELOAD_CLASS (out, preferred_class);
01214 #endif
01215
01216
01217 if (preferred_class != NO_REGS
01218 || (optional && type == RELOAD_FOR_OUTPUT))
01219 class = preferred_class;
01220 }
01221
01222
01223
01224
01225
01226 #ifdef LIMIT_RELOAD_CLASS
01227 if (in_subreg_loc)
01228 class = LIMIT_RELOAD_CLASS (inmode, class);
01229 else if (in != 0 && GET_CODE (in) == SUBREG)
01230 class = LIMIT_RELOAD_CLASS (GET_MODE (SUBREG_REG (in)), class);
01231
01232 if (out_subreg_loc)
01233 class = LIMIT_RELOAD_CLASS (outmode, class);
01234 if (out != 0 && GET_CODE (out) == SUBREG)
01235 class = LIMIT_RELOAD_CLASS (GET_MODE (SUBREG_REG (out)), class);
01236 #endif
01237
01238
01239
01240 if (this_insn_is_asm)
01241 {
01242 enum machine_mode mode;
01243 if (GET_MODE_SIZE (inmode) > GET_MODE_SIZE (outmode))
01244 mode = inmode;
01245 else
01246 mode = outmode;
01247 if (mode == VOIDmode)
01248 {
01249 error_for_asm (this_insn, "cannot reload integer constant "
01250 "operand in %<asm%>");
01251 mode = word_mode;
01252 if (in != 0)
01253 inmode = word_mode;
01254 if (out != 0)
01255 outmode = word_mode;
01256 }
01257 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01258 if (HARD_REGNO_MODE_OK (i, mode)
01259 && TEST_HARD_REG_BIT (reg_class_contents[(int) class], i))
01260 {
01261 int nregs = hard_regno_nregs[i][mode];
01262
01263 int j;
01264 for (j = 1; j < nregs; j++)
01265 if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class], i + j))
01266 break;
01267 if (j == nregs)
01268 break;
01269 }
01270 if (i == FIRST_PSEUDO_REGISTER)
01271 {
01272 error_for_asm (this_insn, "impossible register constraint "
01273 "in %<asm%>");
01274
01275 PATTERN (this_insn) = gen_rtx_USE (VOIDmode, const0_rtx);
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286 return 0;
01287 }
01288 }
01289
01290
01291
01292
01293 gcc_assert (class != NO_REGS
01294 || (optional != 0 && type == RELOAD_FOR_OUTPUT));
01295
01296 i = find_reusable_reload (&in, out, class, type, opnum, dont_share);
01297
01298 if (i == n_reloads)
01299 {
01300
01301
01302
01303
01304 if (in != 0)
01305 secondary_in_reload
01306 = push_secondary_reload (1, in, opnum, optional, class, inmode, type,
01307 &secondary_in_icode, NULL);
01308 if (out != 0 && GET_CODE (out) != SCRATCH)
01309 secondary_out_reload
01310 = push_secondary_reload (0, out, opnum, optional, class, outmode,
01311 type, &secondary_out_icode, NULL);
01312
01313
01314
01315
01316 #ifdef SECONDARY_MEMORY_NEEDED
01317
01318 if (in != 0
01319 && (REG_P (in)
01320 || (GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))))
01321 && reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
01322 && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
01323 class, inmode))
01324 get_secondary_mem (in, inmode, opnum, type);
01325 #endif
01326
01327 i = n_reloads;
01328 rld[i].in = in;
01329 rld[i].out = out;
01330 rld[i].class = class;
01331 rld[i].inmode = inmode;
01332 rld[i].outmode = outmode;
01333 rld[i].reg_rtx = 0;
01334 rld[i].optional = optional;
01335 rld[i].inc = 0;
01336 rld[i].nocombine = 0;
01337 rld[i].in_reg = inloc ? *inloc : 0;
01338 rld[i].out_reg = outloc ? *outloc : 0;
01339 rld[i].opnum = opnum;
01340 rld[i].when_needed = type;
01341 rld[i].secondary_in_reload = secondary_in_reload;
01342 rld[i].secondary_out_reload = secondary_out_reload;
01343 rld[i].secondary_in_icode = secondary_in_icode;
01344 rld[i].secondary_out_icode = secondary_out_icode;
01345 rld[i].secondary_p = 0;
01346
01347 n_reloads++;
01348
01349 #ifdef SECONDARY_MEMORY_NEEDED
01350 if (out != 0
01351 && (REG_P (out)
01352 || (GET_CODE (out) == SUBREG && REG_P (SUBREG_REG (out))))
01353 && reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
01354 && SECONDARY_MEMORY_NEEDED (class,
01355 REGNO_REG_CLASS (reg_or_subregno (out)),
01356 outmode))
01357 get_secondary_mem (out, outmode, opnum, type);
01358 #endif
01359 }
01360 else
01361 {
01362
01363
01364
01365
01366
01367
01368
01369 if (inmode != VOIDmode
01370 && GET_MODE_SIZE (inmode) > GET_MODE_SIZE (rld[i].inmode))
01371 rld[i].inmode = inmode;
01372 if (outmode != VOIDmode
01373 && GET_MODE_SIZE (outmode) > GET_MODE_SIZE (rld[i].outmode))
01374 rld[i].outmode = outmode;
01375 if (in != 0)
01376 {
01377 rtx in_reg = inloc ? *inloc : 0;
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392 if (rld[i].in != in && rtx_equal_p (in, rld[i].in)
01393 && ! (rld[i].optional && optional))
01394 {
01395
01396
01397 if (opnum > rld[i].opnum)
01398 {
01399 remove_address_replacements (in);
01400 in = rld[i].in;
01401 in_reg = rld[i].in_reg;
01402 }
01403 else
01404 remove_address_replacements (rld[i].in);
01405 }
01406 rld[i].in = in;
01407 rld[i].in_reg = in_reg;
01408 }
01409 if (out != 0)
01410 {
01411 rld[i].out = out;
01412 rld[i].out_reg = outloc ? *outloc : 0;
01413 }
01414 if (reg_class_subset_p (class, rld[i].class))
01415 rld[i].class = class;
01416 rld[i].optional &= optional;
01417 if (MERGE_TO_OTHER (type, rld[i].when_needed,
01418 opnum, rld[i].opnum))
01419 rld[i].when_needed = RELOAD_OTHER;
01420 rld[i].opnum = MIN (rld[i].opnum, opnum);
01421 }
01422
01423
01424
01425
01426
01427 if (in != 0 && in != *inloc)
01428 rld[i].nocombine = 1;
01429
01430 #if 0
01431
01432
01433
01434
01435
01436
01437
01438
01439 if (out != 0 && sets_cc0_p (PATTERN (this_insn)))
01440 {
01441 out = 0;
01442 rld[i].out = 0;
01443 rld[i].inc = find_inc_amount (PATTERN (this_insn), in);
01444
01445
01446
01447 gcc_assert (rld[i].inc != 0);
01448 }
01449 #endif
01450
01451
01452
01453
01454
01455 if (replace_reloads)
01456 {
01457 if (inloc != 0)
01458 {
01459 struct replacement *r = &replacements[n_replacements++];
01460 r->what = i;
01461 r->subreg_loc = in_subreg_loc;
01462 r->where = inloc;
01463 r->mode = inmode;
01464 }
01465 if (outloc != 0 && outloc != inloc)
01466 {
01467 struct replacement *r = &replacements[n_replacements++];
01468 r->what = i;
01469 r->where = outloc;
01470 r->subreg_loc = out_subreg_loc;
01471 r->mode = outmode;
01472 }
01473 }
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483 if (in != 0 && out != 0 && in != out && rld[i].reg_rtx == 0)
01484 {
01485 rld[i].reg_rtx = find_dummy_reload (in, out, inloc, outloc,
01486 inmode, outmode,
01487 rld[i].class, i,
01488 earlyclobber_operand_p (out));
01489
01490
01491
01492
01493
01494 if (rld[i].reg_rtx == out
01495 && (REG_P (in) || CONSTANT_P (in))
01496 && 0 != find_equiv_reg (in, this_insn, 0, REGNO (out),
01497 static_reload_reg_p, i, inmode))
01498 rld[i].in = out;
01499 }
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513 if (rld[i].reg_rtx == 0 && in != 0 && hard_regs_live_known)
01514 {
01515 rtx note;
01516 int regno;
01517 enum machine_mode rel_mode = inmode;
01518
01519 if (out && GET_MODE_SIZE (outmode) > GET_MODE_SIZE (inmode))
01520 rel_mode = outmode;
01521
01522 for (note = REG_NOTES (this_insn); note; note = XEXP (note, 1))
01523 if (REG_NOTE_KIND (note) == REG_DEAD
01524 && REG_P (XEXP (note, 0))
01525 && (regno = REGNO (XEXP (note, 0))) < FIRST_PSEUDO_REGISTER
01526 && reg_mentioned_p (XEXP (note, 0), in)
01527
01528
01529 && (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
01530 || ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
01531 ORIGINAL_REGNO (XEXP (note, 0))))
01532 && ! refers_to_regno_for_reload_p (regno,
01533 (regno
01534 + hard_regno_nregs[regno]
01535 [rel_mode]),
01536 PATTERN (this_insn), inloc)
01537
01538
01539
01540 && (out == 0 || in == out
01541 || ! hard_reg_set_here_p (regno,
01542 (regno
01543 + hard_regno_nregs[regno]
01544 [rel_mode]),
01545 PATTERN (this_insn)))
01546
01547
01548
01549 && (in != out
01550 || (GET_CODE (in) == SUBREG
01551 && (((GET_MODE_SIZE (GET_MODE (in)) + (UNITS_PER_WORD - 1))
01552 / UNITS_PER_WORD)
01553 == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
01554 + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))))
01555
01556 && (GET_MODE_SIZE (rel_mode)
01557 <= GET_MODE_SIZE (GET_MODE (XEXP (note, 0))))
01558 && HARD_REGNO_MODE_OK (regno, inmode)
01559 && HARD_REGNO_MODE_OK (regno, outmode))
01560 {
01561 unsigned int offs;
01562 unsigned int nregs = MAX (hard_regno_nregs[regno][inmode],
01563 hard_regno_nregs[regno][outmode]);
01564
01565 for (offs = 0; offs < nregs; offs++)
01566 if (fixed_regs[regno + offs]
01567 || ! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
01568 regno + offs))
01569 break;
01570
01571 if (offs == nregs
01572 && (! (refers_to_regno_for_reload_p
01573 (regno, (regno + hard_regno_nregs[regno][inmode]),
01574 in, (rtx *)0))
01575 || can_reload_into (in, regno, inmode)))
01576 {
01577 rld[i].reg_rtx = gen_rtx_REG (rel_mode, regno);
01578 break;
01579 }
01580 }
01581 }
01582
01583 if (out)
01584 output_reloadnum = i;
01585
01586 return i;
01587 }
01588
01589
01590
01591
01592
01593
01594
01595 static void
01596 push_replacement (rtx *loc, int reloadnum, enum machine_mode mode)
01597 {
01598 if (replace_reloads)
01599 {
01600 struct replacement *r = &replacements[n_replacements++];
01601 r->what = reloadnum;
01602 r->where = loc;
01603 r->subreg_loc = 0;
01604 r->mode = mode;
01605 }
01606 }
01607
01608
01609
01610
01611
01612 static void
01613 dup_replacements (rtx *dup_loc, rtx *orig_loc)
01614 {
01615 int i, n = n_replacements;
01616
01617 for (i = 0; i < n; i++)
01618 {
01619 struct replacement *r = &replacements[i];
01620 if (r->where == orig_loc)
01621 push_replacement (dup_loc, r->what, r->mode);
01622 }
01623 }
01624
01625
01626
01627
01628 void
01629 transfer_replacements (int to, int from)
01630 {
01631 int i;
01632
01633 for (i = 0; i < n_replacements; i++)
01634 if (replacements[i].what == from)
01635 replacements[i].what = to;
01636 }
01637
01638
01639
01640
01641
01642 int
01643 remove_address_replacements (rtx in_rtx)
01644 {
01645 int i, j;
01646 char reload_flags[MAX_RELOADS];
01647 int something_changed = 0;
01648
01649 memset (reload_flags, 0, sizeof reload_flags);
01650 for (i = 0, j = 0; i < n_replacements; i++)
01651 {
01652 if (loc_mentioned_in_p (replacements[i].where, in_rtx))
01653 reload_flags[replacements[i].what] |= 1;
01654 else
01655 {
01656 replacements[j++] = replacements[i];
01657 reload_flags[replacements[i].what] |= 2;
01658 }
01659 }
01660
01661 n_replacements = j;
01662
01663 for (i = n_reloads - 1; i >= 0; i--)
01664 {
01665 if (reload_flags[i] == 1)
01666 {
01667 deallocate_reload_reg (i);
01668 remove_address_replacements (rld[i].in);
01669 rld[i].in = 0;
01670 something_changed = 1;
01671 }
01672 }
01673 return something_changed;
01674 }
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688 static void
01689 combine_reloads (void)
01690 {
01691 int i;
01692 int output_reload = -1;
01693 int secondary_out = -1;
01694 rtx note;
01695
01696
01697
01698
01699 for (i = 0; i < n_reloads; i++)
01700 if (rld[i].out != 0)
01701 {
01702 if (output_reload >= 0)
01703 return;
01704 output_reload = i;
01705 }
01706
01707 if (output_reload < 0 || rld[output_reload].optional)
01708 return;
01709
01710
01711
01712 if (rld[output_reload].in != 0)
01713 return;
01714
01715
01716 if (earlyclobber_operand_p (rld[output_reload].out))
01717 return;
01718
01719
01720
01721
01722
01723 for (i = 0; i < n_reloads; i++)
01724 if ((rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS
01725 || rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS)
01726 && rld[i].opnum == rld[output_reload].opnum)
01727 return;
01728
01729
01730
01731 for (i = 0; i < n_reloads; i++)
01732 if (rld[i].in && ! rld[i].optional && ! rld[i].nocombine
01733
01734 && rld[i].when_needed != RELOAD_FOR_OUTPUT_ADDRESS
01735 && rld[i].when_needed != RELOAD_FOR_OUTADDR_ADDRESS
01736 && rld[i].when_needed != RELOAD_OTHER
01737 && (CLASS_MAX_NREGS (rld[i].class, rld[i].inmode)
01738 == CLASS_MAX_NREGS (rld[output_reload].class,
01739 rld[output_reload].outmode))
01740 && rld[i].inc == 0
01741 && rld[i].reg_rtx == 0
01742 #ifdef SECONDARY_MEMORY_NEEDED
01743
01744
01745 && (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum] == 0
01746 || secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum] == 0
01747 || rtx_equal_p (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum],
01748 secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum]))
01749 #endif
01750 && (SMALL_REGISTER_CLASSES
01751 ? (rld[i].class == rld[output_reload].class)
01752 : (reg_class_subset_p (rld[i].class,
01753 rld[output_reload].class)
01754 || reg_class_subset_p (rld[output_reload].class,
01755 rld[i].class)))
01756 && (MATCHES (rld[i].in, rld[output_reload].out)
01757
01758
01759
01760 || (! reg_overlap_mentioned_for_reload_p (rld[output_reload].out,
01761 rld[i].in)
01762
01763
01764
01765
01766
01767
01768 && ! (REG_P (rld[i].in)
01769 && reg_overlap_mentioned_for_reload_p (rld[i].in,
01770 rld[output_reload].out))))
01771 && ! reload_inner_reg_of_subreg (rld[i].in, rld[i].inmode,
01772 rld[i].when_needed != RELOAD_FOR_INPUT)
01773 && (reg_class_size[(int) rld[i].class]
01774 || SMALL_REGISTER_CLASSES)
01775
01776
01777 && (rld[i].when_needed == RELOAD_FOR_INPUT
01778 || rld[i].when_needed == RELOAD_FOR_OUTPUT))
01779 {
01780 int j;
01781
01782
01783 rld[i].out = rld[output_reload].out;
01784 rld[i].out_reg = rld[output_reload].out_reg;
01785 rld[i].outmode = rld[output_reload].outmode;
01786
01787 rld[output_reload].out = 0;
01788
01789 rld[i].when_needed = RELOAD_OTHER;
01790
01791 if (rld[output_reload].secondary_out_reload != -1)
01792 {
01793 rld[i].secondary_out_reload
01794 = rld[output_reload].secondary_out_reload;
01795 rld[i].secondary_out_icode
01796 = rld[output_reload].secondary_out_icode;
01797 }
01798
01799 #ifdef SECONDARY_MEMORY_NEEDED
01800
01801 if (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum] != 0)
01802 secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum]
01803 = secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum];
01804 #endif
01805
01806 if (reg_class_subset_p (rld[output_reload].class,
01807 rld[i].class))
01808 rld[i].class = rld[output_reload].class;
01809
01810
01811 for (j = 0; j < n_replacements; j++)
01812 if (replacements[j].what == output_reload)
01813 replacements[j].what = i;
01814
01815 return;
01816 }
01817
01818
01819
01820
01821
01822
01823
01824 if (INSN_CODE (this_insn) == -1)
01825 return;
01826
01827 for (i = 1; i < insn_data[INSN_CODE (this_insn)].n_operands; i++)
01828 if (insn_data[INSN_CODE (this_insn)].operand[i].constraint[0] == '='
01829 || insn_data[INSN_CODE (this_insn)].operand[i].constraint[0] == '+')
01830 return;
01831
01832
01833
01834
01835 for (note = REG_NOTES (this_insn); note; note = XEXP (note, 1))
01836 if (REG_NOTE_KIND (note) == REG_DEAD
01837 && REG_P (XEXP (note, 0))
01838 && ! reg_overlap_mentioned_for_reload_p (XEXP (note, 0),
01839 rld[output_reload].out)
01840 && REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
01841 && HARD_REGNO_MODE_OK (REGNO (XEXP (note, 0)), rld[output_reload].outmode)
01842 && TEST_HARD_REG_BIT (reg_class_contents[(int) rld[output_reload].class],
01843 REGNO (XEXP (note, 0)))
01844 && (hard_regno_nregs[REGNO (XEXP (note, 0))][rld[output_reload].outmode]
01845 <= hard_regno_nregs[REGNO (XEXP (note, 0))][GET_MODE (XEXP (note, 0))])
01846
01847
01848 && ((secondary_out = rld[output_reload].secondary_out_reload) == -1
01849 || (! (TEST_HARD_REG_BIT
01850 (reg_class_contents[(int) rld[secondary_out].class],
01851 REGNO (XEXP (note, 0))))
01852 && ((secondary_out = rld[secondary_out].secondary_out_reload) == -1
01853 || ! (TEST_HARD_REG_BIT
01854 (reg_class_contents[(int) rld[secondary_out].class],
01855 REGNO (XEXP (note, 0)))))))
01856 && ! fixed_regs[REGNO (XEXP (note, 0))]
01857
01858
01859 && (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
01860 || ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
01861 ORIGINAL_REGNO (XEXP (note, 0)))))
01862 {
01863 rld[output_reload].reg_rtx
01864 = gen_rtx_REG (rld[output_reload].outmode,
01865 REGNO (XEXP (note, 0)));
01866 return;
01867 }
01868 }
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890 static rtx
01891 find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
01892 enum machine_mode inmode, enum machine_mode outmode,
01893 enum reg_class class, int for_real, int earlyclobber)
01894 {
01895 rtx in = real_in;
01896 rtx out = real_out;
01897 int in_offset = 0;
01898 int out_offset = 0;
01899 rtx value = 0;
01900
01901
01902
01903 if (GET_MODE_SIZE (outmode) != GET_MODE_SIZE (inmode)
01904 && (GET_MODE_SIZE (outmode) > UNITS_PER_WORD
01905 || GET_MODE_SIZE (inmode) > UNITS_PER_WORD))
01906 return 0;
01907
01908
01909
01910
01911
01912 while (GET_CODE (out) == SUBREG)
01913 {
01914 if (REG_P (SUBREG_REG (out))
01915 && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER)
01916 out_offset += subreg_regno_offset (REGNO (SUBREG_REG (out)),
01917 GET_MODE (SUBREG_REG (out)),
01918 SUBREG_BYTE (out),
01919 GET_MODE (out));
01920 out = SUBREG_REG (out);
01921 }
01922 while (GET_CODE (in) == SUBREG)
01923 {
01924 if (REG_P (SUBREG_REG (in))
01925 && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER)
01926 in_offset += subreg_regno_offset (REGNO (SUBREG_REG (in)),
01927 GET_MODE (SUBREG_REG (in)),
01928 SUBREG_BYTE (in),
01929 GET_MODE (in));
01930 in = SUBREG_REG (in);
01931 }
01932
01933
01934
01935 {
01936 enum reg_class preferred_class = PREFERRED_RELOAD_CLASS (in, class);
01937 if (preferred_class != NO_REGS)
01938 class = preferred_class;
01939 }
01940
01941
01942 if (REG_P (out)
01943 && REGNO (out) < FIRST_PSEUDO_REGISTER)
01944 {
01945 unsigned int regno = REGNO (out) + out_offset;
01946 unsigned int nwords = hard_regno_nregs[regno][outmode];
01947 rtx saved_rtx;
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958 saved_rtx = *inloc;
01959 *inloc = const0_rtx;
01960
01961 if (regno < FIRST_PSEUDO_REGISTER
01962 && HARD_REGNO_MODE_OK (regno, outmode)
01963 && ! refers_to_regno_for_reload_p (regno, regno + nwords,
01964 PATTERN (this_insn), outloc))
01965 {
01966 unsigned int i;
01967
01968 for (i = 0; i < nwords; i++)
01969 if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
01970 regno + i))
01971 break;
01972
01973 if (i == nwords)
01974 {
01975 if (REG_P (real_out))
01976 value = real_out;
01977 else
01978 value = gen_rtx_REG (outmode, regno);
01979 }
01980 }
01981
01982 *inloc = saved_rtx;
01983 }
01984
01985
01986
01987
01988
01989
01990
01991 if (hard_regs_live_known
01992 && REG_P (in)
01993 && REGNO (in) < FIRST_PSEUDO_REGISTER
01994 && (value == 0
01995 || find_reg_note (this_insn, REG_UNUSED, real_out))
01996 && find_reg_note (this_insn, REG_DEAD, real_in)
01997 && !fixed_regs[REGNO (in)]
01998 && HARD_REGNO_MODE_OK (REGNO (in),
01999
02000
02001
02002
02003 (GET_MODE (out) != VOIDmode
02004 ? GET_MODE (out) : outmode))
02005
02006
02007
02008
02009
02010
02011
02012 && (ORIGINAL_REGNO (in) < FIRST_PSEUDO_REGISTER
02013 || ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
02014 ORIGINAL_REGNO (in))))
02015 {
02016 unsigned int regno = REGNO (in) + in_offset;
02017 unsigned int nwords = hard_regno_nregs[regno][inmode];
02018
02019 if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, (rtx*) 0)
02020 && ! hard_reg_set_here_p (regno, regno + nwords,
02021 PATTERN (this_insn))
02022 && (! earlyclobber
02023 || ! refers_to_regno_for_reload_p (regno, regno + nwords,
02024 PATTERN (this_insn), inloc)))
02025 {
02026 unsigned int i;
02027
02028 for (i = 0; i < nwords; i++)
02029 if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
02030 regno + i))
02031 break;
02032
02033 if (i == nwords)
02034 {
02035
02036
02037
02038 if (for_real >= 0 && value == real_out)
02039 rld[for_real].out = 0;
02040 if (REG_P (real_in))
02041 value = real_in;
02042 else
02043 value = gen_rtx_REG (inmode, regno);
02044 }
02045 }
02046 }
02047
02048 return value;
02049 }
02050
02051
02052
02053
02054
02055
02056
02057 int
02058 earlyclobber_operand_p (rtx x)
02059 {
02060 int i;
02061
02062 for (i = 0; i < n_earlyclobbers; i++)
02063 if (reload_earlyclobbers[i] == x)
02064 return 1;
02065
02066 return 0;
02067 }
02068
02069
02070
02071
02072
02073
02074 static int
02075 hard_reg_set_here_p (unsigned int beg_regno, unsigned int end_regno, rtx x)
02076 {
02077 if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
02078 {
02079 rtx op0 = SET_DEST (x);
02080
02081 while (GET_CODE (op0) == SUBREG)
02082 op0 = SUBREG_REG (op0);
02083 if (REG_P (op0))
02084 {
02085 unsigned int r = REGNO (op0);
02086
02087
02088 if (r < end_regno
02089 && r + hard_regno_nregs[r][GET_MODE (op0)] > beg_regno)
02090 return 1;
02091 }
02092 }
02093 else if (GET_CODE (x) == PARALLEL)
02094 {
02095 int i = XVECLEN (x, 0) - 1;
02096
02097 for (; i >= 0; i--)
02098 if (hard_reg_set_here_p (beg_regno, end_regno, XVECEXP (x, 0, i)))
02099 return 1;
02100 }
02101
02102 return 0;
02103 }
02104
02105
02106
02107
02108
02109 int
02110 strict_memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
02111 {
02112 GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
02113 return 0;
02114
02115 win:
02116 return 1;
02117 }
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134 int
02135 operands_match_p (rtx x, rtx y)
02136 {
02137 int i;
02138 RTX_CODE code = GET_CODE (x);
02139 const char *fmt;
02140 int success_2;
02141
02142 if (x == y)
02143 return 1;
02144 if ((code == REG || (code == SUBREG && REG_P (SUBREG_REG (x))))
02145 && (REG_P (y) || (GET_CODE (y) == SUBREG
02146 && REG_P (SUBREG_REG (y)))))
02147 {
02148 int j;
02149
02150 if (code == SUBREG)
02151 {
02152 i = REGNO (SUBREG_REG (x));
02153 if (i >= FIRST_PSEUDO_REGISTER)
02154 goto slow;
02155 i += subreg_regno_offset (REGNO (SUBREG_REG (x)),
02156 GET_MODE (SUBREG_REG (x)),
02157 SUBREG_BYTE (x),
02158 GET_MODE (x));
02159 }
02160 else
02161 i = REGNO (x);
02162
02163 if (GET_CODE (y) == SUBREG)
02164 {
02165 j = REGNO (SUBREG_REG (y));
02166 if (j >= FIRST_PSEUDO_REGISTER)
02167 goto slow;
02168 j += subreg_regno_offset (REGNO (SUBREG_REG (y)),
02169 GET_MODE (SUBREG_REG (y)),
02170 SUBREG_BYTE (y),
02171 GET_MODE (y));
02172 }
02173 else
02174 j = REGNO (y);
02175
02176
02177
02178
02179
02180 if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
02181 && SCALAR_INT_MODE_P (GET_MODE (x))
02182 && i < FIRST_PSEUDO_REGISTER)
02183 i += hard_regno_nregs[i][GET_MODE (x)] - 1;
02184 if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (y)) > UNITS_PER_WORD
02185 && SCALAR_INT_MODE_P (GET_MODE (y))
02186 && j < FIRST_PSEUDO_REGISTER)
02187 j += hard_regno_nregs[j][GET_MODE (y)] - 1;
02188
02189 return i == j;
02190 }
02191
02192
02193
02194
02195
02196 if (code == POST_DEC || code == POST_INC || code == POST_MODIFY)
02197 return operands_match_p (XEXP (x, 0), y);
02198
02199
02200
02201
02202
02203
02204 if (GET_CODE (y) == PRE_DEC || GET_CODE (y) == PRE_INC
02205 || GET_CODE (y) == PRE_MODIFY)
02206 return operands_match_p (x, XEXP (y, 0)) ? 2 : 0;
02207
02208 slow:
02209
02210
02211
02212 if (code != GET_CODE (y))
02213 return 0;
02214
02215
02216 if (GET_MODE (x) != GET_MODE (y))
02217 return 0;
02218
02219 switch (code)
02220 {
02221 case CONST_INT:
02222 case CONST_DOUBLE:
02223 return 0;
02224
02225 case LABEL_REF:
02226 return XEXP (x, 0) == XEXP (y, 0);
02227 case SYMBOL_REF:
02228 return XSTR (x, 0) == XSTR (y, 0);
02229
02230 default:
02231 break;
02232 }
02233
02234
02235
02236
02237 success_2 = 0;
02238 fmt = GET_RTX_FORMAT (code);
02239 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02240 {
02241 int val, j;
02242 switch (fmt[i])
02243 {
02244 case 'w':
02245 if (XWINT (x, i) != XWINT (y, i))
02246 return 0;
02247 break;
02248
02249 case 'i':
02250 if (XINT (x, i) != XINT (y, i))
02251 return 0;
02252 break;
02253
02254 case 'e':
02255 val = operands_match_p (XEXP (x, i), XEXP (y, i));
02256 if (val == 0)
02257 return 0;
02258
02259
02260 if (val == 2)
02261 success_2 = 1;
02262 break;
02263
02264 case '0':
02265 break;
02266
02267 case 'E':
02268 if (XVECLEN (x, i) != XVECLEN (y, i))
02269 return 0;
02270 for (j = XVECLEN (x, i) - 1; j >= 0; --j)
02271 {
02272 val = operands_match_p (XVECEXP (x, i, j), XVECEXP (y, i, j));
02273 if (val == 0)
02274 return 0;
02275 if (val == 2)
02276 success_2 = 1;
02277 }
02278 break;
02279
02280
02281
02282
02283 default:
02284 gcc_unreachable ();
02285 }
02286 }
02287 return 1 + success_2;
02288 }
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298 static struct decomposition
02299 decompose (rtx x)
02300 {
02301 struct decomposition val;
02302 int all_const = 0;
02303
02304 memset (&val, 0, sizeof (val));
02305
02306 switch (GET_CODE (x))
02307 {
02308 case MEM:
02309 {
02310 rtx base = NULL_RTX, offset = 0;
02311 rtx addr = XEXP (x, 0);
02312
02313 if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC
02314 || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)
02315 {
02316 val.base = XEXP (addr, 0);
02317 val.start = -GET_MODE_SIZE (GET_MODE (x));
02318 val.end = GET_MODE_SIZE (GET_MODE (x));
02319 val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;
02320 return val;
02321 }
02322
02323 if (GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
02324 {
02325 if (GET_CODE (XEXP (addr, 1)) == PLUS
02326 && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
02327 && CONSTANT_P (XEXP (XEXP (addr, 1), 1)))
02328 {
02329 val.base = XEXP (addr, 0);
02330 val.start = -INTVAL (XEXP (XEXP (addr, 1), 1));
02331 val.end = INTVAL (XEXP (XEXP (addr, 1), 1));
02332 val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;
02333 return val;
02334 }
02335 }
02336
02337 if (GET_CODE (addr) == CONST)
02338 {
02339 addr = XEXP (addr, 0);
02340 all_const = 1;
02341 }
02342 if (GET_CODE (addr) == PLUS)
02343 {
02344 if (CONSTANT_P (XEXP (addr, 0)))
02345 {
02346 base = XEXP (addr, 1);
02347 offset = XEXP (addr, 0);
02348 }
02349 else if (CONSTANT_P (XEXP (addr, 1)))
02350 {
02351 base = XEXP (addr, 0);
02352 offset = XEXP (addr, 1);
02353 }
02354 }
02355
02356 if (offset == 0)
02357 {
02358 base = addr;
02359 offset = const0_rtx;
02360 }
02361 if (GET_CODE (offset) == CONST)
02362 offset = XEXP (offset, 0);
02363 if (GET_CODE (offset) == PLUS)
02364 {
02365 if (GET_CODE (XEXP (offset, 0)) == CONST_INT)
02366 {
02367 base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1));
02368 offset = XEXP (offset, 0);
02369 }
02370 else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)
02371 {
02372 base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0));
02373 offset = XEXP (offset, 1);
02374 }
02375 else
02376 {
02377 base = gen_rtx_PLUS (GET_MODE (base), base, offset);
02378 offset = const0_rtx;
02379 }
02380 }
02381 else if (GET_CODE (offset) != CONST_INT)
02382 {
02383 base = gen_rtx_PLUS (GET_MODE (base), base, offset);
02384 offset = const0_rtx;
02385 }
02386
02387 if (all_const && GET_CODE (base) == PLUS)
02388 base = gen_rtx_CONST (GET_MODE (base), base);
02389
02390 gcc_assert (GET_CODE (offset) == CONST_INT);
02391
02392 val.start = INTVAL (offset);
02393 val.end = val.start + GET_MODE_SIZE (GET_MODE (x));
02394 val.base = base;
02395 }
02396 break;
02397
02398 case REG:
02399 val.reg_flag = 1;
02400 val.start = true_regnum (x);
02401 if (val.start < 0 || val.start >= FIRST_PSEUDO_REGISTER)
02402 {
02403
02404 val.start = REGNO (x);
02405 val.end = val.start + 1;
02406 }
02407 else
02408
02409 val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
02410 break;
02411
02412 case SUBREG:
02413 if (!REG_P (SUBREG_REG (x)))
02414
02415 return decompose (SUBREG_REG (x));
02416 val.reg_flag = 1;
02417 val.start = true_regnum (x);
02418 if (val.start < 0 || val.start >= FIRST_PSEUDO_REGISTER)
02419 return decompose (SUBREG_REG (x));
02420 else
02421
02422 val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
02423 break;
02424
02425 case SCRATCH:
02426
02427 val.safe = 1;
02428 break;
02429
02430 default:
02431 gcc_assert (CONSTANT_P (x));
02432 val.safe = 1;
02433 break;
02434 }
02435 return val;
02436 }
02437
02438
02439
02440
02441 static int
02442 immune_p (rtx x, rtx y, struct decomposition ydata)
02443 {
02444 struct decomposition xdata;
02445
02446 if (ydata.reg_flag)
02447 return !refers_to_regno_for_reload_p (ydata.start, ydata.end, x, (rtx*) 0);
02448 if (ydata.safe)
02449 return 1;
02450
02451 gcc_assert (MEM_P (y));
02452
02453 if (!MEM_P (x))
02454 return 1;
02455
02456 xdata = decompose (x);
02457
02458 if (! rtx_equal_p (xdata.base, ydata.base))
02459 {
02460
02461 if (CONSTANT_P (xdata.base) && CONSTANT_P (ydata.base))
02462 return 1;
02463
02464 if (CONSTANT_P (xdata.base)
02465 && (ydata.base == frame_pointer_rtx
02466 || ydata.base == hard_frame_pointer_rtx
02467 || ydata.base == stack_pointer_rtx))
02468 return 1;
02469 if (CONSTANT_P (ydata.base)
02470 && (xdata.base == frame_pointer_rtx
02471 || xdata.base == hard_frame_pointer_rtx
02472 || xdata.base == stack_pointer_rtx))
02473 return 1;
02474
02475 return 0;
02476 }
02477
02478 return (xdata.start >= ydata.end || ydata.start >= xdata.end);
02479 }
02480
02481
02482
02483 int
02484 safe_from_earlyclobber (rtx op, rtx clobber)
02485 {
02486 struct decomposition early_data;
02487
02488 early_data = decompose (clobber);
02489 return immune_p (op, clobber, early_data);
02490 }
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514 int
02515 find_reloads (rtx insn, int replace, int ind_levels, int live_known,
02516 short *reload_reg_p)
02517 {
02518 int insn_code_number;
02519 int i, j;
02520 int noperands;
02521
02522
02523 char *constraints[MAX_RECOG_OPERANDS];
02524
02525
02526 enum reg_class preferred_class[MAX_RECOG_OPERANDS];
02527 char pref_or_nothing[MAX_RECOG_OPERANDS];
02528
02529
02530 int address_reloaded[MAX_RECOG_OPERANDS];
02531
02532
02533 int address_operand_reloaded[MAX_RECOG_OPERANDS];
02534
02535 enum reload_type operand_type[MAX_RECOG_OPERANDS];
02536
02537 enum reload_type address_type[MAX_RECOG_OPERANDS];
02538
02539 enum reload_usage { RELOAD_READ, RELOAD_READ_WRITE, RELOAD_WRITE } modified[MAX_RECOG_OPERANDS];
02540 int no_input_reloads = 0, no_output_reloads = 0;
02541 int n_alternatives;
02542 int this_alternative[MAX_RECOG_OPERANDS];
02543 char this_alternative_match_win[MAX_RECOG_OPERANDS];
02544 char this_alternative_win[MAX_RECOG_OPERANDS];
02545 char this_alternative_offmemok[MAX_RECOG_OPERANDS];
02546 char this_alternative_earlyclobber[MAX_RECOG_OPERANDS];
02547 int this_alternative_matches[MAX_RECOG_OPERANDS];
02548 int swapped;
02549 int goal_alternative[MAX_RECOG_OPERANDS];
02550 int this_alternative_number;
02551 int goal_alternative_number = 0;
02552 int operand_reloadnum[MAX_RECOG_OPERANDS];
02553 int goal_alternative_matches[MAX_RECOG_OPERANDS];
02554 int goal_alternative_matched[MAX_RECOG_OPERANDS];
02555 char goal_alternative_match_win[MAX_RECOG_OPERANDS];
02556 char goal_alternative_win[MAX_RECOG_OPERANDS];
02557 char goal_alternative_offmemok[MAX_RECOG_OPERANDS];
02558 char goal_alternative_earlyclobber[MAX_RECOG_OPERANDS];
02559 int goal_alternative_swapped;
02560 int best;
02561 int commutative;
02562 char operands_match[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS];
02563 rtx substed_operand[MAX_RECOG_OPERANDS];
02564 rtx body = PATTERN (insn);
02565 rtx set = single_set (insn);
02566 int goal_earlyclobber = 0, this_earlyclobber;
02567 enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
02568 int retval = 0;
02569
02570 this_insn = insn;
02571 n_reloads = 0;
02572 n_replacements = 0;
02573 n_earlyclobbers = 0;
02574 replace_reloads = replace;
02575 hard_regs_live_known = live_known;
02576 static_reload_reg_p = reload_reg_p;
02577
02578
02579
02580
02581 if (JUMP_P (insn) || CALL_P (insn))
02582 no_output_reloads = 1;
02583
02584 #ifdef HAVE_cc0
02585 if (reg_referenced_p (cc0_rtx, PATTERN (insn)))
02586 no_input_reloads = 1;
02587 if (reg_set_p (cc0_rtx, PATTERN (insn)))
02588 no_output_reloads = 1;
02589 #endif
02590
02591 #ifdef SECONDARY_MEMORY_NEEDED
02592
02593
02594
02595 if (secondary_memlocs_elim_used)
02596 {
02597 memset (secondary_memlocs_elim, 0,
02598 sizeof (secondary_memlocs_elim[0]) * secondary_memlocs_elim_used);
02599 secondary_memlocs_elim_used = 0;
02600 }
02601 #endif
02602
02603
02604
02605
02606 if (GET_CODE (body) == SET
02607 && REG_P (SET_DEST (body))
02608 && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER
02609 && REG_P (SET_SRC (body))
02610 && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
02611 && REGISTER_MOVE_COST (GET_MODE (SET_SRC (body)),
02612 REGNO_REG_CLASS (REGNO (SET_SRC (body))),
02613 REGNO_REG_CLASS (REGNO (SET_DEST (body)))) == 2)
02614 return 0;
02615
02616 extract_insn (insn);
02617
02618 noperands = reload_n_operands = recog_data.n_operands;
02619 n_alternatives = recog_data.n_alternatives;
02620
02621
02622 if (noperands == 0 || n_alternatives == 0)
02623 return 0;
02624
02625 insn_code_number = INSN_CODE (insn);
02626 this_insn_is_asm = insn_code_number < 0;
02627
02628 memcpy (operand_mode, recog_data.operand_mode,
02629 noperands * sizeof (enum machine_mode));
02630 memcpy (constraints, recog_data.constraints, noperands * sizeof (char *));
02631
02632 commutative = -1;
02633
02634
02635
02636
02637
02638
02639 for (i = 0; i < noperands; i++)
02640 {
02641 char *p;
02642 int c;
02643
02644 substed_operand[i] = recog_data.operand[i];
02645 p = constraints[i];
02646
02647 modified[i] = RELOAD_READ;
02648
02649
02650
02651
02652 while ((c = *p))
02653 {
02654 p += CONSTRAINT_LEN (c, p);
02655 switch (c)
02656 {
02657 case '=':
02658 modified[i] = RELOAD_WRITE;
02659 break;
02660 case '+':
02661 modified[i] = RELOAD_READ_WRITE;
02662 break;
02663 case '%':
02664 {
02665
02666 gcc_assert (i != noperands - 1);
02667
02668
02669
02670
02671
02672
02673
02674
02675 if (commutative < 0)
02676 commutative = i;
02677 else
02678 gcc_assert (this_insn_is_asm);
02679 }
02680 break;
02681
02682
02683 case '0': case '1': case '2': case '3': case '4':
02684 case '5': case '6': case '7': case '8': case '9':
02685 {
02686 c = strtoul (p - 1, &p, 10);
02687
02688 operands_match[c][i]
02689 = operands_match_p (recog_data.operand[c],
02690 recog_data.operand[i]);
02691
02692
02693 gcc_assert (c != i);
02694
02695
02696
02697 if (commutative >= 0)
02698 {
02699 if (c == commutative || c == commutative + 1)
02700 {
02701 int other = c + (c == commutative ? 1 : -1);
02702 operands_match[other][i]
02703 = operands_match_p (recog_data.operand[other],
02704 recog_data.operand[i]);
02705 }
02706 if (i == commutative || i == commutative + 1)
02707 {
02708 int other = i + (i == commutative ? 1 : -1);
02709 operands_match[c][other]
02710 = operands_match_p (recog_data.operand[c],
02711 recog_data.operand[other]);
02712 }
02713
02714
02715
02716 }
02717 }
02718 }
02719 }
02720 }
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730 for (i = 0; i < noperands; i++)
02731 {
02732 RTX_CODE code = GET_CODE (recog_data.operand[i]);
02733
02734 address_reloaded[i] = 0;
02735 address_operand_reloaded[i] = 0;
02736 operand_type[i] = (modified[i] == RELOAD_READ ? RELOAD_FOR_INPUT
02737 : modified[i] == RELOAD_WRITE ? RELOAD_FOR_OUTPUT
02738 : RELOAD_OTHER);
02739 address_type[i]
02740 = (modified[i] == RELOAD_READ ? RELOAD_FOR_INPUT_ADDRESS
02741 : modified[i] == RELOAD_WRITE ? RELOAD_FOR_OUTPUT_ADDRESS
02742 : RELOAD_OTHER);
02743
02744 if (*constraints[i] == 0)
02745
02746 ;
02747 else if (constraints[i][0] == 'p'
02748 || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
02749 {
02750 address_operand_reloaded[i]
02751 = find_reloads_address (recog_data.operand_mode[i], (rtx*) 0,
02752 recog_data.operand[i],
02753 recog_data.operand_loc[i],
02754 i, operand_type[i], ind_levels, insn);
02755
02756
02757
02758 if ((OBJECT_P (*recog_data.operand_loc[i])
02759 || GET_CODE (*recog_data.operand_loc[i]) == SUBREG)
02760 && (GET_CODE (recog_data.operand[i]) == MULT
02761 || GET_CODE (recog_data.operand[i]) == PLUS))
02762 {
02763 INSN_CODE (insn) = -1;
02764 retval = find_reloads (insn, replace, ind_levels, live_known,
02765 reload_reg_p);
02766 return retval;
02767 }
02768
02769 recog_data.operand[i] = *recog_data.operand_loc[i];
02770 substed_operand[i] = recog_data.operand[i];
02771
02772
02773
02774 operand_mode[i] = GET_MODE (recog_data.operand[i]);
02775 }
02776 else if (code == MEM)
02777 {
02778 address_reloaded[i]
02779 = find_reloads_address (GET_MODE (recog_data.operand[i]),
02780 recog_data.operand_loc[i],
02781 XEXP (recog_data.operand[i], 0),
02782 &XEXP (recog_data.operand[i], 0),
02783 i, address_type[i], ind_levels, insn);
02784 recog_data.operand[i] = *recog_data.operand_loc[i];
02785 substed_operand[i] = recog_data.operand[i];
02786 }
02787 else if (code == SUBREG)
02788 {
02789 rtx reg = SUBREG_REG (recog_data.operand[i]);
02790 rtx op
02791 = find_reloads_toplev (recog_data.operand[i], i, address_type[i],
02792 ind_levels,
02793 set != 0
02794 && &SET_DEST (set) == recog_data.operand_loc[i],
02795 insn,
02796 &address_reloaded[i]);
02797
02798
02799
02800
02801
02802
02803 if (replace
02804 && MEM_P (op)
02805 && REG_P (reg)
02806 && (GET_MODE_SIZE (GET_MODE (reg))
02807 >= GET_MODE_SIZE (GET_MODE (op))))
02808 set_unique_reg_note (emit_insn_before (gen_rtx_USE (VOIDmode, reg),
02809 insn),
02810 REG_EQUAL, reg_equiv_memory_loc[REGNO (reg)]);
02811
02812 substed_operand[i] = recog_data.operand[i] = op;
02813 }
02814 else if (code == PLUS || GET_RTX_CLASS (code) == RTX_UNARY)
02815
02816
02817
02818 substed_operand[i] = recog_data.operand[i]
02819 = find_reloads_toplev (recog_data.operand[i], i, address_type[i],
02820 ind_levels, 0, insn,
02821 &address_reloaded[i]);
02822 else if (code == REG)
02823 {
02824
02825
02826
02827
02828
02829
02830 int regno = REGNO (recog_data.operand[i]);
02831 if (reg_equiv_constant[regno] != 0
02832 && (set == 0 || &SET_DEST (set) != recog_data.operand_loc[i]))
02833 {
02834
02835
02836
02837 if (operand_mode[i] == VOIDmode)
02838 operand_mode[i] = GET_MODE (recog_data.operand[i]);
02839
02840 substed_operand[i] = recog_data.operand[i]
02841 = reg_equiv_constant[regno];
02842 }
02843 if (reg_equiv_memory_loc[regno] != 0
02844 && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
02845
02846
02847 substed_operand[i] = recog_data.operand[i]
02848 = find_reloads_toplev (recog_data.operand[i], i, address_type[i],
02849 ind_levels, 0, insn,
02850 &address_reloaded[i]);
02851 }
02852
02853
02854 code = GET_CODE (recog_data.operand[i]);
02855 preferred_class[i]
02856 = ((code == REG && REGNO (recog_data.operand[i])
02857 >= FIRST_PSEUDO_REGISTER)
02858 ? reg_preferred_class (REGNO (recog_data.operand[i]))
02859 : NO_REGS);
02860 pref_or_nothing[i]
02861 = (code == REG
02862 && REGNO (recog_data.operand[i]) >= FIRST_PSEUDO_REGISTER
02863 && reg_alternate_class (REGNO (recog_data.operand[i])) == NO_REGS);
02864 }
02865
02866
02867
02868 if (set != 0 && noperands >= 2 && recog_data.operand[0] == SET_DEST (set)
02869 && recog_data.operand[1] == SET_SRC (set))
02870 {
02871 preferred_class[0] = preferred_class[1]
02872 = reg_class_subunion[(int) preferred_class[0]][(int) preferred_class[1]];
02873 pref_or_nothing[0] |= pref_or_nothing[1];
02874 pref_or_nothing[1] |= pref_or_nothing[0];
02875 }
02876
02877
02878
02879
02880
02881 best = MAX_RECOG_OPERANDS * 2 + 600;
02882
02883 swapped = 0;
02884 goal_alternative_swapped = 0;
02885 try_swapped:
02886
02887
02888
02889
02890
02891
02892
02893
02894 for (this_alternative_number = 0;
02895 this_alternative_number < n_alternatives;
02896 this_alternative_number++)
02897 {
02898
02899
02900
02901 int losers = 0;
02902
02903
02904 int bad = 0;
02905
02906
02907
02908
02909
02910
02911 int reject = 0;
02912
02913 this_earlyclobber = 0;
02914
02915 for (i = 0; i < noperands; i++)
02916 {
02917 char *p = constraints[i];
02918 char *end;
02919 int len;
02920 int win = 0;
02921 int did_match = 0;
02922
02923 int badop = 1;
02924
02925 int winreg = 0;
02926 int c;
02927 int m;
02928 rtx operand = recog_data.operand[i];
02929 int offset = 0;
02930
02931
02932 int force_reload = 0;
02933 int offmemok = 0;
02934
02935
02936 int constmemok = 0;
02937 int earlyclobber = 0;
02938
02939
02940
02941
02942 if (UNARY_P (operand) && *p != 0)
02943 operand = XEXP (operand, 0);
02944
02945
02946
02947
02948
02949 while (GET_CODE (operand) == SUBREG)
02950 {
02951
02952
02953
02954
02955 if (REG_P (SUBREG_REG (operand))
02956 && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
02957 {
02958 if (!subreg_offset_representable_p
02959 (REGNO (SUBREG_REG (operand)),
02960 GET_MODE (SUBREG_REG (operand)),
02961 SUBREG_BYTE (operand),
02962 GET_MODE (operand)))
02963 force_reload = 1;
02964 offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
02965 GET_MODE (SUBREG_REG (operand)),
02966 SUBREG_BYTE (operand),
02967 GET_MODE (operand));
02968 }
02969 operand = SUBREG_REG (operand);
02970
02971
02972 if (CONSTANT_P (operand)
02973 || GET_CODE (operand) == PLUS
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998 || ((MEM_P (operand)
02999 || (REG_P (operand)
03000 && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
03001 #ifndef WORD_REGISTER_OPERATIONS
03002 && (((GET_MODE_BITSIZE (GET_MODE (operand))
03003 < BIGGEST_ALIGNMENT)
03004 && (GET_MODE_SIZE (operand_mode[i])
03005 > GET_MODE_SIZE (GET_MODE (operand))))
03006 || BYTES_BIG_ENDIAN
03007 #ifdef LOAD_EXTEND_OP
03008 || (GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
03009 && (GET_MODE_SIZE (GET_MODE (operand))
03010 <= UNITS_PER_WORD)
03011 && (GET_MODE_SIZE (operand_mode[i])
03012 > GET_MODE_SIZE (GET_MODE (operand)))
03013 && INTEGRAL_MODE_P (GET_MODE (operand))
03014 && LOAD_EXTEND_OP (GET_MODE (operand)) != UNKNOWN)
03015 #endif
03016 )
03017 #endif
03018 )
03019 )
03020 force_reload = 1;
03021 }
03022
03023 this_alternative[i] = (int) NO_REGS;
03024 this_alternative_win[i] = 0;
03025 this_alternative_match_win[i] = 0;
03026 this_alternative_offmemok[i] = 0;
03027 this_alternative_earlyclobber[i] = 0;
03028 this_alternative_matches[i] = -1;
03029
03030
03031
03032 if (*p == 0 || *p == ',')
03033 win = 1, badop = 0;
03034
03035
03036
03037
03038
03039
03040
03041
03042 do
03043 switch ((c = *p, len = CONSTRAINT_LEN (c, p)), c)
03044 {
03045 case '\0':
03046 len = 0;
03047 break;
03048 case ',':
03049 c = '\0';
03050 break;
03051
03052 case '=': case '+': case '*':
03053 break;
03054
03055 case '%':
03056
03057
03058 break;
03059
03060 case '?':
03061 reject += 6;
03062 break;
03063
03064 case '!':
03065 reject = 600;
03066 break;
03067
03068 case '#':
03069
03070
03071 do
03072 p++;
03073 while (*p && *p != ',');
03074 len = 0;
03075 break;
03076
03077 case '0': case '1': case '2': case '3': case '4':
03078 case '5': case '6': case '7': case '8': case '9':
03079 m = strtoul (p, &end, 10);
03080 p = end;
03081 len = 0;
03082
03083 this_alternative_matches[i] = m;
03084
03085
03086
03087
03088
03089
03090
03091 if ((swapped && (m != commutative || i != commutative + 1))
03092
03093
03094
03095
03096
03097
03098 ? (operands_match
03099 [(m == commutative || m == commutative + 1)
03100 ? 2 * commutative + 1 - m : m]
03101 [(i == commutative || i == commutative + 1)
03102 ? 2 * commutative + 1 - i : i])
03103 : operands_match[m][i])
03104 {
03105
03106
03107
03108 if (this_alternative_offmemok[m]
03109 && MEM_P (recog_data.operand[m])
03110 && this_alternative[m] == (int) NO_REGS
03111 && ! this_alternative_win[m])
03112 bad = 1;
03113
03114 did_match = this_alternative_win[m];
03115 }
03116 else
03117 {
03118
03119 rtx value;
03120 int loc1, loc2;
03121
03122
03123 if (this_alternative_win[m])
03124 losers++;
03125 this_alternative_win[m] = 0;
03126 if (this_alternative[m] == (int) NO_REGS)
03127 bad = 1;
03128
03129
03130
03131
03132 if (swapped && i == commutative)
03133 loc1 = commutative + 1;
03134 else if (swapped && i == commutative + 1)
03135 loc1 = commutative;
03136 else
03137 loc1 = i;
03138 if (swapped && m == commutative)
03139 loc2 = commutative + 1;
03140 else if (swapped && m == commutative + 1)
03141 loc2 = commutative;
03142 else
03143 loc2 = m;
03144 value
03145 = find_dummy_reload (recog_data.operand[i],
03146 recog_data.operand[m],
03147 recog_data.operand_loc[loc1],
03148 recog_data.operand_loc[loc2],
03149 operand_mode[i], operand_mode[m],
03150 this_alternative[m], -1,
03151 this_alternative_earlyclobber[m]);
03152
03153 if (value != 0)
03154 losers--;
03155 }
03156
03157
03158 badop = 0;
03159 this_alternative[i] = this_alternative[m];
03160
03161
03162
03163
03164
03165 if (! did_match || force_reload)
03166 for (j = 0; j < i; j++)
03167 if (this_alternative_matches[j]
03168 == this_alternative_matches[i])
03169 badop = 1;
03170 break;
03171
03172 case 'p':
03173
03174
03175 this_alternative[i]
03176 = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
03177 win = 1;
03178 badop = 0;
03179 break;
03180
03181 case 'm':
03182 if (force_reload)
03183 break;
03184 if (MEM_P (operand)
03185 || (REG_P (operand)
03186 && REGNO (operand) >= FIRST_PSEUDO_REGISTER
03187 && reg_renumber[REGNO (operand)] < 0))
03188 win = 1;
03189 if (CONST_POOL_OK_P (operand))
03190 badop = 0;
03191 constmemok = 1;
03192 break;
03193
03194 case '<':
03195 if (MEM_P (operand)
03196 && ! address_reloaded[i]
03197 && (GET_CODE (XEXP (operand, 0)) == PRE_DEC
03198 || GET_CODE (XEXP (operand, 0)) == POST_DEC))
03199 win = 1;
03200 break;
03201
03202 case '>':
03203 if (MEM_P (operand)
03204 && ! address_reloaded[i]
03205 && (GET_CODE (XEXP (operand, 0)) == PRE_INC
03206 || GET_CODE (XEXP (operand, 0)) == POST_INC))
03207 win = 1;
03208 break;
03209
03210
03211 case 'V':
03212 if (force_reload)
03213 break;
03214 if (MEM_P (operand)
03215 && ! (ind_levels ? offsettable_memref_p (operand)
03216 : offsettable_nonstrict_memref_p (operand))
03217
03218
03219
03220
03221 && !(REG_P (XEXP (operand, 0))
03222 && (ind_levels == 0
03223 || reg_equiv_address[REGNO (XEXP (operand, 0))] != 0)))
03224 win = 1;
03225 break;
03226
03227
03228 case 'o':
03229 if (force_reload)
03230 break;
03231 if ((MEM_P (operand)
03232
03233
03234
03235 && ((ind_levels ? offsettable_memref_p (operand)
03236 : offsettable_nonstrict_memref_p (operand))
03237
03238
03239 || address_reloaded[i] == 1))
03240 || (REG_P (operand)
03241 && REGNO (operand) >= FIRST_PSEUDO_REGISTER
03242 && reg_renumber[REGNO (operand)] < 0
03243
03244
03245
03246
03247 && ((reg_equiv_mem[REGNO (operand)] != 0
03248 && offsettable_memref_p (reg_equiv_mem[REGNO (operand)]))
03249 || (reg_equiv_address[REGNO (operand)] != 0))))
03250 win = 1;
03251 if (CONST_POOL_OK_P (operand)
03252 || MEM_P (operand))
03253 badop = 0;
03254 constmemok = 1;
03255 offmemok = 1;
03256 break;
03257
03258 case '&':
03259
03260
03261 earlyclobber = 1, this_earlyclobber = 1;
03262 break;
03263
03264 case 'E':
03265 case 'F':
03266 if (GET_CODE (operand) == CONST_DOUBLE
03267 || (GET_CODE (operand) == CONST_VECTOR
03268 && (GET_MODE_CLASS (GET_MODE (operand))
03269 == MODE_VECTOR_FLOAT)))
03270 win = 1;
03271 break;
03272
03273 case 'G':
03274 case 'H':
03275 if (GET_CODE (operand) == CONST_DOUBLE
03276 && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (operand, c, p))
03277 win = 1;
03278 break;
03279
03280 case 's':
03281 if (GET_CODE (operand) == CONST_INT
03282 || (GET_CODE (operand) == CONST_DOUBLE
03283 && GET_MODE (operand) == VOIDmode))
03284 break;
03285 case 'i':
03286 if (CONSTANT_P (operand)
03287 && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (operand)))
03288 win = 1;
03289 break;
03290
03291 case 'n':
03292 if (GET_CODE (operand) == CONST_INT
03293 || (GET_CODE (operand) == CONST_DOUBLE
03294 && GET_MODE (operand) == VOIDmode))
03295 win = 1;
03296 break;
03297
03298 case 'I':
03299 case 'J':
03300 case 'K':
03301 case 'L':
03302 case 'M':
03303 case 'N':
03304 case 'O':
03305 case 'P':
03306 if (GET_CODE (operand) == CONST_INT
03307 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operand), c, p))
03308 win = 1;
03309 break;
03310
03311 case 'X':
03312 force_reload = 0;
03313 win = 1;
03314 break;
03315
03316 case 'g':
03317 if (! force_reload
03318
03319
03320 && GET_CODE (operand) != PLUS
03321
03322 && GET_CODE (operand) != SCRATCH
03323 && (! CONSTANT_P (operand)
03324 || ! flag_pic
03325 || LEGITIMATE_PIC_OPERAND_P (operand))
03326 && (GENERAL_REGS == ALL_REGS
03327 || !REG_P (operand)
03328 || (REGNO (operand) >= FIRST_PSEUDO_REGISTER
03329 && reg_renumber[REGNO (operand)] < 0)))
03330 win = 1;
03331
03332
03333 case 'r':
03334 this_alternative[i]
03335 = (int) reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
03336 goto reg;
03337
03338 default:
03339 if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS)
03340 {
03341 #ifdef EXTRA_CONSTRAINT_STR
03342 if (EXTRA_MEMORY_CONSTRAINT (c, p))
03343 {
03344 if (force_reload)
03345 break;
03346 if (EXTRA_CONSTRAINT_STR (operand, c, p))
03347 win = 1;
03348
03349
03350 else if (MEM_P (operand)
03351 && address_reloaded[i] == 1)
03352 win = 1;
03353
03354
03355
03356 else if (REG_P (operand)
03357 && REGNO (operand) >= FIRST_PSEUDO_REGISTER
03358 && reg_renumber[REGNO (operand)] < 0
03359 && ((reg_equiv_mem[REGNO (operand)] != 0
03360 && EXTRA_CONSTRAINT_STR (reg_equiv_mem[REGNO (operand)], c, p))
03361 || (reg_equiv_address[REGNO (operand)] != 0)))
03362 win = 1;
03363
03364
03365
03366
03367 if (CONST_POOL_OK_P (operand)
03368 || MEM_P (operand))
03369 badop = 0;
03370 constmemok = 1;
03371 offmemok = 1;
03372 break;
03373 }
03374 if (EXTRA_ADDRESS_CONSTRAINT (c, p))
03375 {
03376 if (EXTRA_CONSTRAINT_STR (operand, c, p))
03377 win = 1;
03378
03379
03380
03381 this_alternative[i]
03382 = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
03383 badop = 0;
03384 break;
03385 }
03386
03387 if (EXTRA_CONSTRAINT_STR (operand, c, p))
03388 win = 1;
03389 #endif
03390 break;
03391 }
03392
03393 this_alternative[i]
03394 = (int) (reg_class_subunion
03395 [this_alternative[i]]
03396 [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
03397 reg:
03398 if (GET_MODE (operand) == BLKmode)
03399 break;
03400 winreg = 1;
03401 if (REG_P (operand)
03402 && reg_fits_class_p (operand, this_alternative[i],
03403 offset, GET_MODE (recog_data.operand[i])))
03404 win = 1;
03405 break;
03406 }
03407 while ((p += len), c);
03408
03409 constraints[i] = p;
03410
03411
03412
03413 if (winreg && this_alternative[i] != (int) NO_REGS)
03414 badop = 0;
03415
03416
03417 this_alternative_earlyclobber[i] = earlyclobber;
03418 if (win && ! force_reload)
03419 this_alternative_win[i] = 1;
03420 else if (did_match && ! force_reload)
03421 this_alternative_match_win[i] = 1;
03422 else
03423 {
03424 int const_to_mem = 0;
03425
03426 this_alternative_offmemok[i] = offmemok;
03427 losers++;
03428 if (badop)
03429 bad = 1;
03430
03431 if (REG_P (operand)
03432 && this_alternative[i] == (int) NO_REGS
03433 && this_alternative_matches[i] < 0)
03434 bad = 1;
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444 if (CONST_POOL_OK_P (operand)
03445 && ((PREFERRED_RELOAD_CLASS (operand,
03446 (enum reg_class) this_alternative[i])
03447 == NO_REGS)
03448 || no_input_reloads)
03449 && operand_mode[i] != VOIDmode)
03450 {
03451 const_to_mem = 1;
03452 if (this_alternative[i] != (int) NO_REGS)
03453 losers++;
03454 }
03455
03456
03457
03458
03459 if (GET_CODE (operand) != SCRATCH
03460 && modified[i] != RELOAD_READ && no_output_reloads
03461 && ! find_reg_note (insn, REG_UNUSED, operand))
03462 bad = 1;
03463 else if (modified[i] != RELOAD_WRITE && no_input_reloads
03464 && ! const_to_mem)
03465 bad = 1;
03466
03467
03468
03469
03470
03471
03472 if (! CONSTANT_P (operand)
03473 && (enum reg_class) this_alternative[i] != NO_REGS)
03474 {
03475 if (PREFERRED_RELOAD_CLASS
03476 (operand, (enum reg_class) this_alternative[i])
03477 == NO_REGS)
03478 reject = 600;
03479
03480 #ifdef PREFERRED_OUTPUT_RELOAD_CLASS
03481 if (operand_type[i] == RELOAD_FOR_OUTPUT
03482 && PREFERRED_OUTPUT_RELOAD_CLASS
03483 (operand, (enum reg_class) this_alternative[i])
03484 == NO_REGS)
03485 reject = 600;
03486 #endif
03487 }
03488
03489
03490
03491
03492
03493
03494
03495
03496
03497 if (! (REG_P (operand)
03498 && REGNO (operand) >= FIRST_PSEUDO_REGISTER)
03499 && GET_CODE (operand) != SCRATCH
03500 && ! (const_to_mem && constmemok))
03501 reject += 2;
03502
03503
03504
03505 if (operand_type[i] != RELOAD_FOR_INPUT
03506 && GET_CODE (operand) != SCRATCH)
03507 reject++;
03508 }
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523
03524
03525
03526
03527
03528
03529
03530
03531 if (! win && ! did_match
03532 && this_alternative[i] != (int) NO_REGS
03533 && GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
03534 && reg_class_size [(int) preferred_class[i]] > 0
03535 && ! SMALL_REGISTER_CLASS_P (preferred_class[i]))
03536 {
03537 if (! reg_class_subset_p (this_alternative[i],
03538 preferred_class[i]))
03539 {
03540
03541
03542
03543
03544 if (reg_class_subset_p (preferred_class[i],
03545 this_alternative[i]))
03546 this_alternative[i] = (int) preferred_class[i];
03547 else
03548 reject += (2 + 2 * pref_or_nothing[i]);
03549 }
03550 }
03551 }
03552
03553
03554
03555
03556
03557 for (i = 0; i < noperands; i++)
03558 if (this_alternative_earlyclobber[i]
03559 && (this_alternative_win[i] || this_alternative_match_win[i]))
03560 {
03561 struct decomposition early_data;
03562
03563 early_data = decompose (recog_data.operand[i]);
03564
03565 gcc_assert (modified[i] != RELOAD_READ);
03566
03567 if (this_alternative[i] == NO_REGS)
03568 {
03569 this_alternative_earlyclobber[i] = 0;
03570 gcc_assert (this_insn_is_asm);
03571 error_for_asm (this_insn,
03572 "%<&%> constraint used with no register class");
03573 }
03574
03575 for (j = 0; j < noperands; j++)
03576
03577 if ((MEM_P (recog_data.operand[j])
03578 || modified[j] != RELOAD_WRITE)
03579 && j != i
03580
03581 && *recog_data.constraints[j] != 0
03582
03583
03584 && ! (this_alternative_matches[j] == i
03585 && rtx_equal_p (recog_data.operand[i],
03586 recog_data.operand[j]))
03587
03588 && !immune_p (recog_data.operand[j], recog_data.operand[i],
03589 early_data))
03590 {
03591
03592
03593 if (SMALL_REGISTER_CLASS_P (this_alternative[i])
03594 && (REG_P (recog_data.operand[j])
03595 || GET_CODE (recog_data.operand[j]) == SUBREG))
03596 {
03597 losers++;
03598 this_alternative_win[j] = 0;
03599 this_alternative_match_win[j] = 0;
03600 }
03601 else
03602 break;
03603 }
03604
03605
03606 if (j != noperands)
03607 {
03608 losers++;
03609 this_alternative_win[i] = 0;
03610 this_alternative_match_win[j] = 0;
03611 for (j = 0; j < noperands; j++)
03612 if (this_alternative_matches[j] == i
03613 && this_alternative_match_win[j])
03614 {
03615 this_alternative_win[j] = 0;
03616 this_alternative_match_win[j] = 0;
03617 losers++;
03618 }
03619 }
03620 }
03621
03622
03623
03624 if (losers == 0)
03625 {
03626
03627 if (commutative >= 0)
03628 {
03629 recog_data.operand[commutative] = substed_operand[commutative];
03630 recog_data.operand[commutative + 1]
03631 = substed_operand[commutative + 1];
03632 }
03633 for (i = 0; i < noperands; i++)
03634 {
03635 goal_alternative_win[i] = this_alternative_win[i];
03636 goal_alternative_match_win[i] = this_alternative_match_win[i];
03637 goal_alternative[i] = this_alternative[i];
03638 goal_alternative_offmemok[i] = this_alternative_offmemok[i];
03639 goal_alternative_matches[i] = this_alternative_matches[i];
03640 goal_alternative_earlyclobber[i]
03641 = this_alternative_earlyclobber[i];
03642 }
03643 goal_alternative_number = this_alternative_number;
03644 goal_alternative_swapped = swapped;
03645 goal_earlyclobber = this_earlyclobber;
03646 goto finish;
03647 }
03648
03649
03650
03651
03652
03653 losers = losers * 6 + reject;
03654
03655
03656
03657
03658 if (! bad && best > losers)
03659 {
03660 for (i = 0; i < noperands; i++)
03661 {
03662 goal_alternative[i] = this_alternative[i];
03663 goal_alternative_win[i] = this_alternative_win[i];
03664 goal_alternative_match_win[i] = this_alternative_match_win[i];
03665 goal_alternative_offmemok[i] = this_alternative_offmemok[i];
03666 goal_alternative_matches[i] = this_alternative_matches[i];
03667 goal_alternative_earlyclobber[i]
03668 = this_alternative_earlyclobber[i];
03669 }
03670 goal_alternative_swapped = swapped;
03671 best = losers;
03672 goal_alternative_number = this_alternative_number;
03673 goal_earlyclobber = this_earlyclobber;
03674 }
03675 }
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685
03686 if (commutative >= 0)
03687 {
03688 swapped = !swapped;
03689 if (swapped)
03690 {
03691 enum reg_class tclass;
03692 int t;
03693
03694 recog_data.operand[commutative] = substed_operand[commutative + 1];
03695 recog_data.operand[commutative + 1] = substed_operand[commutative];
03696
03697 for (i = 0; i < recog_data.n_dups; i++)
03698 if (recog_data.dup_num[i] == commutative
03699 || recog_data.dup_num[i] == commutative + 1)
03700 *recog_data.dup_loc[i]
03701 = recog_data.operand[(int) recog_data.dup_num[i]];
03702
03703 tclass = preferred_class[commutative];
03704 preferred_class[commutative] = preferred_class[commutative + 1];
03705 preferred_class[commutative + 1] = tclass;
03706
03707 t = pref_or_nothing[commutative];
03708 pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
03709 pref_or_nothing[commutative + 1] = t;
03710
03711 t = address_reloaded[commutative];
03712 address_reloaded[commutative] = address_reloaded[commutative + 1];
03713 address_reloaded[commutative + 1] = t;
03714
03715 memcpy (constraints, recog_data.constraints,
03716 noperands * sizeof (char *));
03717 goto try_swapped;
03718 }
03719 else
03720 {
03721 recog_data.operand[commutative] = substed_operand[commutative];
03722 recog_data.operand[commutative + 1]
03723 = substed_operand[commutative + 1];
03724
03725 for (i = 0; i < recog_data.n_dups; i++)
03726 if (recog_data.dup_num[i] == commutative
03727 || recog_data.dup_num[i] == commutative + 1)
03728 *recog_data.dup_loc[i]
03729 = recog_data.operand[(int) recog_data.dup_num[i]];
03730 }
03731 }
03732
03733
03734
03735
03736
03737
03738 if (best == MAX_RECOG_OPERANDS * 2 + 600)
03739 {
03740
03741 if (insn_code_number >= 0)
03742 fatal_insn ("unable to generate reloads for:", insn);
03743 error_for_asm (insn, "inconsistent operand constraints in an %<asm%>");
03744
03745 PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
03746 n_reloads = 0;
03747 return 0;
03748 }
03749
03750
03751
03752 finish:
03753
03754
03755
03756
03757
03758
03759
03760 for (i = 0; i < noperands; i++)
03761 goal_alternative_matched[i] = -1;
03762
03763 for (i = 0; i < noperands; i++)
03764 if (! goal_alternative_win[i]
03765 && goal_alternative_matches[i] >= 0)
03766 goal_alternative_matched[goal_alternative_matches[i]] = i;
03767
03768 for (i = 0; i < noperands; i++)
03769 goal_alternative_win[i] |= goal_alternative_match_win[i];
03770
03771
03772
03773
03774
03775 if (goal_alternative_swapped)
03776 {
03777 rtx tem;
03778
03779 tem = substed_operand[commutative];
03780 substed_operand[commutative] = substed_operand[commutative + 1];
03781 substed_operand[commutative + 1] = tem;
03782 tem = recog_data.operand[commutative];
03783 recog_data.operand[commutative] = recog_data.operand[commutative + 1];
03784 recog_data.operand[commutative + 1] = tem;
03785 tem = *recog_data.operand_loc[commutative];
03786 *recog_data.operand_loc[commutative]
03787 = *recog_data.operand_loc[commutative + 1];
03788 *recog_data.operand_loc[commutative + 1] = tem;
03789
03790 for (i = 0; i < n_reloads; i++)
03791 {
03792 if (rld[i].opnum == commutative)
03793 rld[i].opnum = commutative + 1;
03794 else if (rld[i].opnum == commutative + 1)
03795 rld[i].opnum = commutative;
03796 }
03797 }
03798
03799 for (i = 0; i < noperands; i++)
03800 {
03801 operand_reloadnum[i] = -1;
03802
03803
03804
03805
03806
03807
03808
03809
03810
03811
03812
03813
03814
03815
03816
03817
03818
03819
03820 if (goal_alternative_earlyclobber[i] && operand_type[i] != RELOAD_OTHER)
03821 operand_type[i]
03822 = (find_reg_note (insn, REG_UNUSED, recog_data.operand[i])
03823 ? RELOAD_FOR_INSN : RELOAD_OTHER);
03824 }
03825
03826
03827
03828 for (i = 0; i < noperands; i++)
03829 if (! goal_alternative_win[i]
03830 && CONST_POOL_OK_P (recog_data.operand[i])
03831 && ((PREFERRED_RELOAD_CLASS (recog_data.operand[i],
03832 (enum reg_class) goal_alternative[i])
03833 == NO_REGS)
03834 || no_input_reloads)
03835 && operand_mode[i] != VOIDmode)
03836 {
03837 substed_operand[i] = recog_data.operand[i]
03838 = find_reloads_toplev (force_const_mem (operand_mode[i],
03839 recog_data.operand[i]),
03840 i, address_type[i], ind_levels, 0, insn,
03841 NULL);
03842 if (alternative_allows_memconst (recog_data.constraints[i],
03843 goal_alternative_number))
03844 goal_alternative_win[i] = 1;
03845 }
03846
03847
03848
03849 for (i = 0; i < noperands; i++)
03850 if (! goal_alternative_win[i]
03851 && GET_CODE (recog_data.operand[i]) == PLUS
03852 && CONST_POOL_OK_P (XEXP (recog_data.operand[i], 1))
03853 && (PREFERRED_RELOAD_CLASS (XEXP (recog_data.operand[i], 1),
03854 (enum reg_class) goal_alternative[i])
03855 == NO_REGS)
03856 && operand_mode[i] != VOIDmode)
03857 {
03858 rtx tem = force_const_mem (operand_mode[i],
03859 XEXP (recog_data.operand[i], 1));
03860 tem = gen_rtx_PLUS (operand_mode[i],
03861 XEXP (recog_data.operand[i], 0), tem);
03862
03863 substed_operand[i] = recog_data.operand[i]
03864 = find_reloads_toplev (tem, i, address_type[i],
03865 ind_levels, 0, insn, NULL);
03866 }
03867
03868
03869 if (goal_earlyclobber)
03870 for (i = 0; i < noperands; i++)
03871 if (goal_alternative_earlyclobber[i])
03872 reload_earlyclobbers[n_earlyclobbers++] = recog_data.operand[i];
03873
03874
03875 for (i = 0; i < noperands; i++)
03876 if (! goal_alternative_win[i])
03877 {
03878
03879 if (goal_alternative_matches[i] >= 0)
03880 ;
03881
03882
03883
03884
03885
03886
03887
03888 else if (goal_alternative_matched[i] == -1
03889 && goal_alternative_offmemok[i]
03890 && MEM_P (recog_data.operand[i]))
03891 {
03892
03893
03894
03895 enum machine_mode address_mode;
03896 address_mode = GET_MODE (XEXP (recog_data.operand[i], 0));
03897 if (address_mode == VOIDmode)
03898 address_mode = Pmode;
03899
03900 operand_reloadnum[i]
03901 = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
03902 &XEXP (recog_data.operand[i], 0), (rtx*) 0,
03903 base_reg_class (VOIDmode, MEM, SCRATCH),
03904 address_mode,
03905 VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
03906 rld[operand_reloadnum[i]].inc
03907 = GET_MODE_SIZE (GET_MODE (recog_data.operand[i]));
03908
03909
03910
03911
03912
03913
03914 if (modified[i] == RELOAD_WRITE)
03915 {
03916 for (j = 0; j < n_reloads; j++)
03917 {
03918 if (rld[j].opnum == i)
03919 {
03920 if (rld[j].when_needed == RELOAD_FOR_OUTPUT_ADDRESS)
03921 rld[j].when_needed = RELOAD_FOR_INPUT_ADDRESS;
03922 else if (rld[j].when_needed
03923 == RELOAD_FOR_OUTADDR_ADDRESS)
03924 rld[j].when_needed = RELOAD_FOR_INPADDR_ADDRESS;
03925 }
03926 }
03927 }
03928 }
03929 else if (goal_alternative_matched[i] == -1)
03930 {
03931 operand_reloadnum[i]
03932 = push_reload ((modified[i] != RELOAD_WRITE
03933 ? recog_data.operand[i] : 0),
03934 (modified[i] != RELOAD_READ
03935 ? recog_data.operand[i] : 0),
03936 (modified[i] != RELOAD_WRITE
03937 ? recog_data.operand_loc[i] : 0),
03938 (modified[i] != RELOAD_READ
03939 ? recog_data.operand_loc[i] : 0),
03940 (enum reg_class) goal_alternative[i],
03941 (modified[i] == RELOAD_WRITE
03942 ? VOIDmode : operand_mode[i]),
03943 (modified[i] == RELOAD_READ
03944 ? VOIDmode : operand_mode[i]),
03945 (insn_code_number < 0 ? 0
03946 : insn_data[insn_code_number].operand[i].strict_low),
03947 0, i, operand_type[i]);
03948 }
03949
03950
03951
03952 else if (modified[i] == RELOAD_READ
03953 && modified[goal_alternative_matched[i]] == RELOAD_WRITE)
03954 {
03955 operand_reloadnum[i]
03956 = push_reload (recog_data.operand[i],
03957 recog_data.operand[goal_alternative_matched[i]],
03958 recog_data.operand_loc[i],
03959 recog_data.operand_loc[goal_alternative_matched[i]],
03960 (enum reg_class) goal_alternative[i],
03961 operand_mode[i],
03962 operand_mode[goal_alternative_matched[i]],
03963 0, 0, i, RELOAD_OTHER);
03964 operand_reloadnum[goal_alternative_matched[i]] = output_reloadnum;
03965 }
03966 else if (modified[i] == RELOAD_WRITE
03967 && modified[goal_alternative_matched[i]] == RELOAD_READ)
03968 {
03969 operand_reloadnum[goal_alternative_matched[i]]
03970 = push_reload (recog_data.operand[goal_alternative_matched[i]],
03971 recog_data.operand[i],
03972 recog_data.operand_loc[goal_alternative_matched[i]],
03973 recog_data.operand_loc[i],
03974 (enum reg_class) goal_alternative[i],
03975 operand_mode[goal_alternative_matched[i]],
03976 operand_mode[i],
03977 0, 0, i, RELOAD_OTHER);
03978 operand_reloadnum[i] = output_reloadnum;
03979 }
03980 else
03981 {
03982 gcc_assert (insn_code_number < 0);
03983 error_for_asm (insn, "inconsistent operand constraints "
03984 "in an %<asm%>");
03985
03986 PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
03987 n_reloads = 0;
03988 return 0;
03989 }
03990 }
03991 else if (goal_alternative_matched[i] < 0
03992 && goal_alternative_matches[i] < 0
03993 && address_operand_reloaded[i] != 1
03994 && optimize)
03995 {
03996
03997
03998
03999
04000 rtx operand = recog_data.operand[i];
04001
04002 while (GET_CODE (operand) == SUBREG)
04003 operand = SUBREG_REG (operand);
04004 if ((MEM_P (operand)
04005 || (REG_P (operand)
04006 && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
04007
04008
04009
04010 && ((enum reg_class) goal_alternative[i] != NO_REGS
04011 || modified[i] == RELOAD_WRITE)
04012 && ! no_input_reloads
04013
04014
04015
04016
04017
04018
04019
04020 && (modified[i] == RELOAD_READ
04021 || (! no_output_reloads && ! this_insn_is_asm)))
04022 operand_reloadnum[i]
04023 = push_reload ((modified[i] != RELOAD_WRITE
04024 ? recog_data.operand[i] : 0),
04025 (modified[i] != RELOAD_READ
04026 ? recog_data.operand[i] : 0),
04027 (modified[i] != RELOAD_WRITE
04028 ? recog_data.operand_loc[i] : 0),
04029 (modified[i] != RELOAD_READ
04030 ? recog_data.operand_loc[i] : 0),
04031 (enum reg_class) goal_alternative[i],
04032 (modified[i] == RELOAD_WRITE
04033 ? VOIDmode : operand_mode[i]),
04034 (modified[i] == RELOAD_READ
04035 ? VOIDmode : operand_mode[i]),
04036 (insn_code_number < 0 ? 0
04037 : insn_data[insn_code_number].operand[i].strict_low),
04038 1, i, operand_type[i]);
04039
04040
04041
04042
04043
04044 else if (replace
04045 && (MEM_P (operand)
04046 || (REG_P (operand)
04047 && REGNO (operand) >= FIRST_PSEUDO_REGISTER
04048 && reg_renumber [REGNO (operand)] < 0)))
04049 {
04050 operand = *recog_data.operand_loc[i];
04051
04052 while (GET_CODE (operand) == SUBREG)
04053 operand = SUBREG_REG (operand);
04054 if (REG_P (operand))
04055 {
04056 if (modified[i] != RELOAD_WRITE)
04057
04058
04059
04060 PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, operand),
04061 insn), QImode);
04062 if (modified[i] != RELOAD_READ)
04063 emit_insn_after (gen_rtx_CLOBBER (VOIDmode, operand), insn);
04064 }
04065 }
04066 }
04067 else if (goal_alternative_matches[i] >= 0
04068 && goal_alternative_win[goal_alternative_matches[i]]
04069 && modified[i] == RELOAD_READ
04070 && modified[goal_alternative_matches[i]] == RELOAD_WRITE
04071 && ! no_input_reloads && ! no_output_reloads
04072 && optimize)
04073 {
04074
04075
04076
04077 rtx operand = recog_data.operand[i];
04078
04079 while (GET_CODE (operand) == SUBREG)
04080 operand = SUBREG_REG (operand);
04081 if ((MEM_P (operand)
04082 || (REG_P (operand)
04083 && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
04084 && ((enum reg_class) goal_alternative[goal_alternative_matches[i]]
04085 != NO_REGS))
04086 operand_reloadnum[i] = operand_reloadnum[goal_alternative_matches[i]]
04087 = push_reload (recog_data.operand[goal_alternative_matches[i]],
04088 recog_data.operand[i],
04089 recog_data.operand_loc[goal_alternative_matches[i]],
04090 recog_data.operand_loc[i],
04091 (enum reg_class) goal_alternative[goal_alternative_matches[i]],
04092 operand_mode[goal_alternative_matches[i]],
04093 operand_mode[i],
04094 0, 1, goal_alternative_matches[i], RELOAD_OTHER);
04095 }
04096
04097
04098
04099
04100
04101 for (i = 0; i < noperands; i++)
04102 {
04103
04104
04105
04106
04107
04108 if (replace)
04109 {
04110 rtx substitution = substed_operand[i];
04111
04112 *recog_data.operand_loc[i] = substitution;
04113
04114
04115
04116
04117 if (!JUMP_P (insn)
04118 && GET_CODE (substitution) == LABEL_REF
04119 && !find_reg_note (insn, REG_LABEL, XEXP (substitution, 0)))
04120 REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
04121 XEXP (substitution, 0),
04122 REG_NOTES (insn));
04123 }
04124 else
04125 retval |= (substed_operand[i] != *recog_data.operand_loc[i]);
04126 }
04127
04128
04129
04130
04131
04132
04133
04134
04135
04136 if (insn_code_number >= 0 && replace)
04137 for (i = insn_data[insn_code_number].n_dups - 1; i >= 0; i--)
04138 {
04139 int opno = recog_data.dup_num[i];
04140 *recog_data.dup_loc[i] = *recog_data.operand_loc[opno];
04141 dup_replacements (recog_data.dup_loc[i], recog_data.operand_loc[opno]);
04142 }
04143
04144 #if 0
04145
04146
04147
04148
04149
04150
04151
04152
04153
04154 for (i = 0; i < n_reloads; i++)
04155 if (rld[i].reg_rtx == 0
04156 && rld[i].in != 0
04157 && REG_P (rld[i].in)
04158 && rld[i].out == 0)
04159 {
04160 rld[i].reg_rtx
04161 = find_equiv_reg (rld[i].in, insn, rld[i].class, -1,
04162 static_reload_reg_p, 0, rld[i].inmode);
04163
04164
04165 if (rld[i].reg_rtx)
04166 rld[i].in = rld[i].reg_rtx;
04167 }
04168 #endif
04169
04170
04171
04172 if (GET_CODE (PATTERN (insn)) == USE
04173 && GET_CODE (XEXP (PATTERN (insn), 0)) == CONST_INT)
04174 n_reloads = 0;
04175
04176
04177
04178 if (!goal_earlyclobber)
04179 combine_reloads ();
04180
04181
04182
04183
04184
04185
04186 for (i = 0; i < n_reloads; i++)
04187 {
04188 int k;
04189
04190 for (j = i + 1; j < n_reloads; j++)
04191 if ((rld[i].when_needed == RELOAD_FOR_INPUT_ADDRESS
04192 || rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS
04193 || rld[i].when_needed == RELOAD_FOR_INPADDR_ADDRESS
04194 || rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS)
04195 && (rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
04196 || rld[j].when_needed == RELOAD_FOR_OUTPUT_ADDRESS
04197 || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS
04198 || rld[j].when_needed == RELOAD_FOR_OUTADDR_ADDRESS)
04199 && rtx_equal_p (rld[i].in, rld[j].in)
04200 && (operand_reloadnum[rld[i].opnum] < 0
04201 || rld[operand_reloadnum[rld[i].opnum]].optional)
04202 && (operand_reloadnum[rld[j].opnum] < 0
04203 || rld[operand_reloadnum[rld[j].opnum]].optional)
04204 && (goal_alternative_matches[rld[i].opnum] == rld[j].opnum
04205 || (goal_alternative_matches[rld[j].opnum]
04206 == rld[i].opnum)))
04207 {
04208 for (k = 0; k < n_replacements; k++)
04209 if (replacements[k].what == j)
04210 replacements[k].what = i;
04211
04212 if (rld[i].when_needed == RELOAD_FOR_INPADDR_ADDRESS
04213 || rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS)
04214 rld[i].when_needed = RELOAD_FOR_OPADDR_ADDR;
04215 else
04216 rld[i].when_needed = RELOAD_FOR_OPERAND_ADDRESS;
04217 rld[j].in = 0;
04218 }
04219 }
04220
04221
04222
04223
04224
04225
04226
04227
04228
04229
04230
04231
04232
04233
04234
04235
04236
04237
04238 for (i = 0; i < n_reloads; i++)
04239 {
04240 if (rld[i].secondary_p
04241 && rld[i].when_needed == operand_type[rld[i].opnum])
04242 rld[i].when_needed = address_type[rld[i].opnum];
04243
04244 if ((rld[i].when_needed == RELOAD_FOR_INPUT_ADDRESS
04245 || rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS
04246 || rld[i].when_needed == RELOAD_FOR_INPADDR_ADDRESS
04247 || rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS)
04248 && (operand_reloadnum[rld[i].opnum] < 0
04249 || rld[operand_reloadnum[rld[i].opnum]].optional))
04250 {
04251
04252
04253
04254 if ((rld[i].when_needed == RELOAD_FOR_INPUT_ADDRESS
04255 || rld[i].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
04256 && rld[i].secondary_in_reload != -1)
04257 {
04258 int secondary_in_reload = rld[i].secondary_in_reload;
04259
04260 rld[secondary_in_reload].when_needed = RELOAD_FOR_OPADDR_ADDR;
04261
04262
04263 if (secondary_in_reload > 0
04264 && rld[secondary_in_reload].secondary_in_reload != -1)
04265 rld[rld[secondary_in_reload].secondary_in_reload].when_needed
04266 = RELOAD_FOR_OPADDR_ADDR;
04267 }
04268
04269 if ((rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS
04270 || rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS)
04271 && rld[i].secondary_out_reload != -1)
04272 {
04273 int secondary_out_reload = rld[i].secondary_out_reload;
04274
04275 rld[secondary_out_reload].when_needed = RELOAD_FOR_OPADDR_ADDR;
04276
04277
04278 if (secondary_out_reload
04279 && rld[secondary_out_reload].secondary_out_reload != -1)
04280 rld[rld[secondary_out_reload].secondary_out_reload].when_needed
04281 = RELOAD_FOR_OPADDR_ADDR;
04282 }
04283
04284 if (rld[i].when_needed == RELOAD_FOR_INPADDR_ADDRESS
04285 || rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS)
04286 rld[i].when_needed = RELOAD_FOR_OPADDR_ADDR;
04287 else
04288 rld[i].when_needed = RELOAD_FOR_OPERAND_ADDRESS;
04289 }
04290
04291 if ((rld[i].when_needed == RELOAD_FOR_INPUT_ADDRESS
04292 || rld[i].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
04293 && operand_reloadnum[rld[i].opnum] >= 0
04294 && (rld[operand_reloadnum[rld[i].opnum]].when_needed
04295 == RELOAD_OTHER))
04296 rld[i].when_needed = RELOAD_FOR_OTHER_ADDRESS;
04297
04298 if (goal_alternative_matches[rld[i].opnum] >= 0)
04299 rld[i].opnum = goal_alternative_matches[rld[i].opnum];
04300 }
04301
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325 {
04326 int first_op_addr_num = -2;
04327 int first_inpaddr_num[MAX_RECOG_OPERANDS];
04328 int first_outpaddr_num[MAX_RECOG_OPERANDS];
04329 int need_change = 0;
04330
04331
04332
04333
04334
04335
04336 for (i = 0; i < noperands; i++)
04337 first_inpaddr_num[i] = first_outpaddr_num[i] = -2;
04338 for (i = n_reloads - 1; i >= 0; i--)
04339 {
04340 switch (rld[i].when_needed)
04341 {
04342 case RELOAD_FOR_OPERAND_ADDRESS:
04343 if (++first_op_addr_num >= 0)
04344 {
04345 first_op_addr_num = i;
04346 need_change = 1;
04347 }
04348 break;
04349 case RELOAD_FOR_INPUT_ADDRESS:
04350 if (++first_inpaddr_num[rld[i].opnum] >= 0)
04351 {
04352 first_inpaddr_num[rld[i].opnum] = i;
04353 need_change = 1;
04354 }
04355 break;
04356 case RELOAD_FOR_OUTPUT_ADDRESS:
04357 if (++first_outpaddr_num[rld[i].opnum] >= 0)
04358 {
04359 first_outpaddr_num[rld[i].opnum] = i;
04360 need_change = 1;
04361 }
04362 break;
04363 default:
04364 break;
04365 }
04366 }
04367
04368 if (need_change)
04369 {
04370 for (i = 0; i < n_reloads; i++)
04371 {
04372 int first_num;
04373 enum reload_type type;
04374
04375 switch (rld[i].when_needed)
04376 {
04377 case RELOAD_FOR_OPADDR_ADDR:
04378 first_num = first_op_addr_num;
04379 type = RELOAD_FOR_OPERAND_ADDRESS;
04380 break;
04381 case RELOAD_FOR_INPADDR_ADDRESS:
04382 first_num = first_inpaddr_num[rld[i].opnum];
04383 type = RELOAD_FOR_INPUT_ADDRESS;
04384 break;
04385 case RELOAD_FOR_OUTADDR_ADDRESS:
04386 first_num = first_outpaddr_num[rld[i].opnum];
04387 type = RELOAD_FOR_OUTPUT_ADDRESS;
04388 break;
04389 default:
04390 continue;
04391 }
04392 if (first_num < 0)
04393 continue;
04394 else if (i > first_num)
04395 rld[i].when_needed = type;
04396 else
04397 {
04398
04399
04400 for (j = n_reloads - 1; j > first_num; j--)
04401 {
04402 if (rld[j].when_needed == type
04403 && (rld[i].secondary_p
04404 ? rld[j].secondary_in_reload == i
04405 : reg_mentioned_p (rld[i].in, rld[j].in)))
04406 {
04407 rld[i].when_needed = type;
04408 break;
04409 }
04410 }
04411 }
04412 }
04413 }
04414 }
04415
04416
04417
04418
04419
04420
04421 for (i = 0; i < n_reloads; i++)
04422 if (rld[i].in != 0 && rld[i].out == 0
04423 && (rld[i].when_needed == RELOAD_FOR_OPERAND_ADDRESS
04424 || rld[i].when_needed == RELOAD_FOR_OPADDR_ADDR
04425 || rld[i].when_needed == RELOAD_FOR_OTHER_ADDRESS))
04426 for (j = 0; j < n_reloads; j++)
04427 if (i != j && rld[j].in != 0 && rld[j].out == 0
04428 && rld[j].when_needed == rld[i].when_needed
04429 && MATCHES (rld[i].in, rld[j].in)
04430 && rld[i].class == rld[j].class
04431 && !rld[i].nocombine && !rld[j].nocombine
04432 && rld[i].reg_rtx == rld[j].reg_rtx)
04433 {
04434 rld[i].opnum = MIN (rld[i].opnum, rld[j].opnum);
04435 transfer_replacements (i, j);
04436 rld[j].in = 0;
04437 }
04438
04439 #ifdef HAVE_cc0
04440
04441
04442
04443 if (no_input_reloads)
04444 for (i = 0; i < n_reloads; i++)
04445 gcc_assert (rld[i].in == 0
04446 || rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS
04447 || rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS);
04448 #endif
04449
04450
04451 for (i = 0; i < n_reloads; i++)
04452 {
04453 rld[i].mode
04454 = (rld[i].inmode == VOIDmode
04455 || (GET_MODE_SIZE (rld[i].outmode)
04456 > GET_MODE_SIZE (rld[i].inmode)))
04457 ? rld[i].outmode : rld[i].inmode;
04458
04459 rld[i].nregs = CLASS_MAX_NREGS (rld[i].class, rld[i].mode);
04460 }
04461
04462
04463
04464 for (i = 0; i < n_reloads; i++)
04465 if (rld[i].when_needed == RELOAD_FOR_INPUT
04466 && GET_CODE (PATTERN (insn)) == SET
04467 && REG_P (SET_DEST (PATTERN (insn)))
04468 && SET_SRC (PATTERN (insn)) == rld[i].in)
04469 {
04470 rtx dest = SET_DEST (PATTERN (insn));
04471 unsigned int regno = REGNO (dest);
04472
04473 if (regno < FIRST_PSEUDO_REGISTER
04474 && TEST_HARD_REG_BIT (reg_class_contents[rld[i].class], regno)
04475 && HARD_REGNO_MODE_OK (regno, rld[i].mode))
04476 {
04477 int nr = hard_regno_nregs[regno][rld[i].mode];
04478 int ok = 1, nri;
04479
04480 for (nri = 1; nri < nr; nri ++)
04481 if (! TEST_HARD_REG_BIT (reg_class_contents[rld[i].class], regno + nri))
04482 ok = 0;
04483
04484 if (ok)
04485 rld[i].reg_rtx = dest;
04486 }
04487 }
04488
04489 return retval;
04490 }
04491
04492
04493
04494
04495 static int
04496 alternative_allows_memconst (const char *constraint, int altnum)
04497 {
04498 int c;
04499
04500 while (altnum > 0)
04501 {
04502 while (*constraint++ != ',');
04503 altnum--;
04504 }
04505
04506
04507 for (; (c = *constraint) && c != ',' && c != '#';
04508 constraint += CONSTRAINT_LEN (c, constraint))
04509 if (c == 'm' || c == 'o' || EXTRA_MEMORY_CONSTRAINT (c, constraint))
04510 return 1;
04511 return 0;
04512 }
04513
04514
04515
04516
04517
04518
04519
04520
04521
04522
04523
04524
04525
04526
04527
04528
04529
04530
04531
04532
04533
04534
04535
04536 static rtx
04537 find_reloads_toplev (rtx x, int opnum, enum reload_type type,
04538 int ind_levels, int is_set_dest, rtx insn,
04539 int *address_reloaded)
04540 {
04541 RTX_CODE code = GET_CODE (x);
04542
04543 const char *fmt = GET_RTX_FORMAT (code);
04544 int i;
04545 int copied;
04546
04547 if (code == REG)
04548 {
04549
04550 int regno = REGNO (x);
04551 if (reg_equiv_constant[regno] != 0 && !is_set_dest)
04552 x = reg_equiv_constant[regno];
04553 #if 0
04554
04555
04556 else if (reg_equiv_mem[regno] != 0)
04557 x = reg_equiv_mem[regno];
04558 #endif
04559 else if (reg_equiv_memory_loc[regno]
04560 && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
04561 {
04562 rtx mem = make_memloc (x, regno);
04563 if (reg_equiv_address[regno]
04564 || ! rtx_equal_p (mem, reg_equiv_mem[regno]))
04565 {
04566
04567
04568
04569 if (replace_reloads && recog_data.operand[opnum] != x)
04570
04571
04572
04573 PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, x), insn),
04574 QImode);
04575 x = mem;
04576 i = find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
04577 opnum, type, ind_levels, insn);
04578 if (x != mem)
04579 push_reg_equiv_alt_mem (regno, x);
04580 if (address_reloaded)
04581 *address_reloaded = i;
04582 }
04583 }
04584 return x;
04585 }
04586 if (code == MEM)
04587 {
04588 rtx tem = x;
04589
04590 i = find_reloads_address (GET_MODE (x), &tem, XEXP (x, 0), &XEXP (x, 0),
04591 opnum, type, ind_levels, insn);
04592 if (address_reloaded)
04593 *address_reloaded = i;
04594
04595 return tem;
04596 }
04597
04598 if (code == SUBREG && REG_P (SUBREG_REG (x)))
04599 {
04600
04601
04602
04603
04604
04605
04606
04607
04608
04609 int regno = REGNO (SUBREG_REG (x));
04610 rtx tem;
04611
04612 if (subreg_lowpart_p (x)
04613 && regno >= FIRST_PSEUDO_REGISTER
04614 && reg_renumber[regno] < 0
04615 && reg_equiv_constant[regno] != 0
04616 && (tem = gen_lowpart_common (GET_MODE (x),
04617 reg_equiv_constant[regno])) != 0)
04618 return tem;
04619
04620 if (regno >= FIRST_PSEUDO_REGISTER
04621 && reg_renumber[regno] < 0
04622 && reg_equiv_constant[regno] != 0)
04623 {
04624 tem =
04625 simplify_gen_subreg (GET_MODE (x), reg_equiv_constant[regno],
04626 GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
04627 gcc_assert (tem);
04628 return tem;
04629 }
04630
04631
04632
04633
04634
04635
04636
04637
04638
04639
04640
04641
04642
04643
04644 if (regno >= FIRST_PSEUDO_REGISTER
04645 #ifdef LOAD_EXTEND_OP
04646 && (GET_MODE_SIZE (GET_MODE (x))
04647 <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
04648 #endif
04649 && (reg_equiv_address[regno] != 0
04650 || (reg_equiv_mem[regno] != 0
04651 && (! strict_memory_address_p (GET_MODE (x),
04652 XEXP (reg_equiv_mem[regno], 0))
04653 || ! offsettable_memref_p (reg_equiv_mem[regno])
04654 || num_not_at_initial_offset))))
04655 x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
04656 insn);
04657 }
04658
04659 for (copied = 0, i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
04660 {
04661 if (fmt[i] == 'e')
04662 {
04663 rtx new_part = find_reloads_toplev (XEXP (x, i), opnum, type,
04664 ind_levels, is_set_dest, insn,
04665 address_reloaded);
04666
04667
04668
04669
04670
04671 if (new_part != XEXP (x, i) && ! CONSTANT_P (new_part) && ! copied)
04672 {
04673 x = shallow_copy_rtx (x);
04674 copied = 1;
04675 }
04676 XEXP (x, i) = new_part;
04677 }
04678 }
04679 return x;
04680 }
04681
04682
04683
04684
04685 static rtx
04686 make_memloc (rtx ad, int regno)
04687 {
04688
04689
04690 rtx tem
04691 = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0, NULL_RTX), 0);
04692
04693
04694
04695 if (rtx_varies_p (tem, 0))
04696 tem = copy_rtx (tem);
04697
04698 tem = replace_equiv_address_nv (reg_equiv_memory_loc[regno], tem);
04699 tem = adjust_address_nv (tem, GET_MODE (ad), 0);
04700
04701
04702
04703 if (tem == reg_equiv_memory_loc[regno])
04704 tem = copy_rtx (tem);
04705 return tem;
04706 }
04707
04708
04709
04710
04711
04712 static int
04713 maybe_memory_address_p (enum machine_mode mode, rtx ad, rtx *part)
04714 {
04715 int retv;
04716 rtx tem = *part;
04717 rtx reg = gen_rtx_REG (GET_MODE (tem), max_reg_num ());
04718
04719 *part = reg;
04720 retv = memory_address_p (mode, ad);
04721 *part = tem;
04722
04723 return retv;
04724 }
04725
04726
04727
04728
04729
04730
04731
04732
04733
04734
04735
04736
04737
04738
04739
04740
04741
04742
04743
04744
04745
04746
04747
04748
04749
04750
04751 static int
04752 find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
04753 rtx *loc, int opnum, enum reload_type type,
04754 int ind_levels, rtx insn)
04755 {
04756 int regno;
04757 int removed_and = 0;
04758 int op_index;
04759 rtx tem;
04760
04761
04762
04763
04764
04765 if (REG_P (ad))
04766 {
04767 regno = REGNO (ad);
04768
04769
04770
04771 tem = reg_equiv_constant[regno];
04772 if (tem != 0
04773 && (tem = eliminate_regs (tem, mode, insn))
04774 && strict_memory_address_p (mode, tem))
04775 {
04776 *loc = ad = tem;
04777 return 0;
04778 }
04779
04780 tem = reg_equiv_memory_loc[regno];
04781 if (tem != 0)
04782 {
04783 if (reg_equiv_address[regno] != 0 || num_not_at_initial_offset)
04784 {
04785 tem = make_memloc (ad, regno);
04786 if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
04787 {
04788 rtx orig = tem;
04789
04790 find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
04791 &XEXP (tem, 0), opnum,
04792 ADDR_TYPE (type), ind_levels, insn);
04793 if (tem != orig)
04794 push_reg_equiv_alt_mem (regno, tem);
04795 }
04796
04797
04798
04799
04800
04801 if (ind_levels > 0
04802 && strict_memory_address_p (mode, tem)
04803 && (REG_P (XEXP (tem, 0))
04804 || (GET_CODE (XEXP (tem, 0)) == PLUS
04805 && REG_P (XEXP (XEXP (tem, 0), 0))
04806 && CONSTANT_P (XEXP (XEXP (tem, 0), 1)))))
04807 {
04808
04809
04810
04811 if (replace_reloads
04812 && num_not_at_initial_offset
04813 && ! rtx_equal_p (tem, reg_equiv_mem[regno]))
04814 {
04815 *loc = tem;
04816
04817
04818
04819 PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, ad),
04820 insn), QImode);
04821
04822
04823
04824 }
04825 return 0;
04826 }
04827 ad = tem;
04828 }
04829 }
04830
04831
04832
04833
04834
04835 else if (regno < FIRST_PSEUDO_REGISTER
04836 && regno_ok_for_base_p (regno, mode, MEM, SCRATCH)
04837 && ! regno_clobbered_p (regno, this_insn, mode, 0))
04838 return 0;
04839
04840
04841 push_reload (ad, NULL_RTX, loc, (rtx*) 0, base_reg_class (mode, MEM, SCRATCH),
04842 GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
04843 return 1;
04844 }
04845
04846 if (strict_memory_address_p (mode, ad))
04847 {
04848
04849
04850
04851
04852
04853
04854
04855
04856 if (GET_CODE (ad) == PLUS
04857 && GET_CODE (XEXP (ad, 1)) == CONST_INT
04858 && REG_P (XEXP (ad, 0))
04859 && reg_equiv_constant[REGNO (XEXP (ad, 0))] == 0)
04860 return 0;
04861
04862 subst_reg_equivs_changed = 0;
04863 *loc = subst_reg_equivs (ad, insn);
04864
04865 if (! subst_reg_equivs_changed)
04866 return 0;
04867
04868
04869 if (strict_memory_address_p (mode, ad))
04870 return 0;
04871 }
04872
04873 #ifdef LEGITIMIZE_RELOAD_ADDRESS
04874 do
04875 {
04876 if (memrefloc)
04877 {
04878 LEGITIMIZE_RELOAD_ADDRESS (ad, GET_MODE (*memrefloc), opnum, type,
04879 ind_levels, win);
04880 }
04881 break;
04882 win:
04883 *memrefloc = copy_rtx (*memrefloc);
04884 XEXP (*memrefloc, 0) = ad;
04885 move_replacements (&ad, &XEXP (*memrefloc, 0));
04886 return -1;
04887 }
04888 while (0);
04889 #endif
04890
04891
04892
04893
04894 if (GET_CODE (ad) == AND)
04895 {
04896 removed_and = 1;
04897 loc = &XEXP (ad, 0);
04898 ad = *loc;
04899 }
04900
04901
04902
04903
04904
04905
04906
04907 if (MEM_P (ad))
04908 {
04909
04910
04911 tem = ad;
04912 find_reloads_address (GET_MODE (ad), &tem, XEXP (ad, 0), &XEXP (ad, 0),
04913 opnum, ADDR_TYPE (type),
04914 ind_levels == 0 ? 0 : ind_levels - 1, insn);
04915
04916
04917
04918 if (tem != ad && memrefloc)
04919 {
04920 *memrefloc = copy_rtx (*memrefloc);
04921 copy_replacements (tem, XEXP (*memrefloc, 0));
04922 loc = &XEXP (*memrefloc, 0);
04923 if (removed_and)
04924 loc = &XEXP (*loc, 0);
04925 }
04926
04927
04928
04929
04930
04931 if (ind_levels == 0
04932 || (GET_CODE (XEXP (tem, 0)) == SYMBOL_REF && ! indirect_symref_ok)
04933 || MEM_P (XEXP (tem, 0))
04934 || ! (REG_P (XEXP (tem, 0))
04935 || (GET_CODE (XEXP (tem, 0)) == PLUS
04936 && REG_P (XEXP (XEXP (tem, 0), 0))
04937 && GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT)))
04938 {
04939
04940
04941 push_reload (tem, NULL_RTX, loc, (rtx*) 0,
04942 base_reg_class (mode, MEM, SCRATCH), GET_MODE (tem),
04943 VOIDmode, 0,
04944 0, opnum, type);
04945 return ! removed_and;
04946 }
04947 else
04948 return 0;
04949 }
04950
04951
04952
04953
04954
04955
04956 else if (GET_CODE (ad) == PLUS
04957 && REG_P (XEXP (ad, 0))
04958 && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
04959 && GET_CODE (XEXP (ad, 1)) == CONST_INT
04960 && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS,
04961 CONST_INT))
04962
04963 {
04964
04965 if (memrefloc)
04966 {
04967 *memrefloc = copy_rtx (*memrefloc);
04968 loc = &XEXP (*memrefloc, 0);
04969 if (removed_and)
04970 loc = &XEXP (*loc, 0);
04971 }
04972
04973 if (double_reg_address_ok)
04974 {
04975
04976 *loc = ad = copy_rtx (ad);
04977
04978
04979
04980 find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1),
04981 INDEX_REG_CLASS, GET_MODE (ad), opnum,
04982 type, ind_levels);
04983 return 0;
04984 }
04985 else
04986 {
04987
04988
04989
04990 find_reloads_address_part (ad, loc,
04991 base_reg_class (mode, MEM, SCRATCH),
04992 Pmode, opnum, type, ind_levels);
04993 }
04994 return ! removed_and;
04995 }
04996
04997
04998
04999
05000
05001
05002
05003
05004
05005
05006
05007
05008
05009
05010
05011
05012
05013
05014
05015
05016
05017
05018
05019
05020
05021
05022
05023 for (op_index = 0; op_index < 2; ++op_index)
05024 {
05025 rtx operand, addend;
05026 enum rtx_code inner_code;
05027
05028 if (GET_CODE (ad) != PLUS)
05029 continue;
05030
05031 inner_code = GET_CODE (XEXP (ad, 0));
05032 if (!(GET_CODE (ad) == PLUS
05033 && GET_CODE (XEXP (ad, 1)) == CONST_INT
05034 && (inner_code == PLUS || inner_code == LO_SUM)))
05035 continue;
05036
05037 operand = XEXP (XEXP (ad, 0), op_index);
05038 if (!REG_P (operand) || REGNO (operand) >= FIRST_PSEUDO_REGISTER)
05039 continue;
05040
05041 addend = XEXP (XEXP (ad, 0), 1 - op_index);
05042
05043 if ((regno_ok_for_base_p (REGNO (operand), mode, inner_code,
05044 GET_CODE (addend))
05045 || operand == frame_pointer_rtx
05046 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
05047 || operand == hard_frame_pointer_rtx
05048 #endif
05049 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
05050 || operand == arg_pointer_rtx
05051 #endif
05052 || operand == stack_pointer_rtx)
05053 && ! maybe_memory_address_p (mode, ad,
05054 &XEXP (XEXP (ad, 0), 1 - op_index)))
05055 {
05056 rtx offset_reg;
05057 enum reg_class cls;
05058
05059 offset_reg = plus_constant (operand, INTVAL (XEXP (ad, 1)));
05060
05061
05062 if (GET_CODE (XEXP (ad, 0)) == PLUS)
05063 ad = gen_rtx_PLUS (GET_MODE (ad),
05064 op_index == 0 ? offset_reg : addend,
05065 op_index == 0 ? addend : offset_reg);
05066 else
05067 ad = gen_rtx_LO_SUM (GET_MODE (ad),
05068 op_index == 0 ? offset_reg : addend,
05069 op_index == 0 ? addend : offset_reg);
05070 *loc = ad;
05071
05072 cls = base_reg_class (mode, MEM, GET_CODE (addend));
05073 find_reloads_address_part (XEXP (ad, op_index),
05074 &XEXP (ad, op_index), cls,
05075 GET_MODE (ad), opnum, type, ind_levels);
05076 find_reloads_address_1 (mode,
05077 XEXP (ad, 1 - op_index), 1, GET_CODE (ad),
05078 GET_CODE (XEXP (ad, op_index)),
05079 &XEXP (ad, 1 - op_index), opnum,
05080 type, 0, insn);
05081
05082 return 0;
05083 }
05084 }
05085
05086
05087
05088
05089 tem = ad;
05090 if (GET_CODE (ad) == PLUS)
05091 tem = subst_indexed_address (ad);
05092 if (tem != ad && strict_memory_address_p (mode, tem))
05093 {
05094
05095
05096
05097 subst_reg_equivs_changed = 0;
05098 tem = subst_reg_equivs (tem, insn);
05099
05100
05101
05102 if (! subst_reg_equivs_changed || strict_memory_address_p (mode, tem))
05103 {
05104 *loc = tem;
05105 return 0;
05106 }
05107 }
05108
05109
05110
05111 if (CONSTANT_P (ad) && ! strict_memory_address_p (mode, ad))
05112 {
05113
05114
05115 if (memrefloc && GET_CODE (ad) == SYMBOL_REF
05116 && CONSTANT_POOL_ADDRESS_P (ad))
05117 {
05118 *memrefloc = copy_rtx (*memrefloc);
05119 loc = &XEXP (*memrefloc, 0);
05120 if (removed_and)
05121 loc = &XEXP (*loc, 0);
05122 }
05123
05124 find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
05125 Pmode, opnum, type, ind_levels);
05126 return ! removed_and;
05127 }
05128
05129 return find_reloads_address_1 (mode, ad, 0, MEM, SCRATCH, loc, opnum, type,
05130 ind_levels, insn);
05131 }
05132
05133
05134
05135
05136
05137
05138
05139 static rtx
05140 subst_reg_equivs (rtx ad, rtx insn)
05141 {
05142 RTX_CODE code = GET_CODE (ad);
05143 int i;
05144 const char *fmt;
05145
05146 switch (code)
05147 {
05148 case HIGH:
05149 case CONST_INT:
05150 case CONST:
05151 case CONST_DOUBLE:
05152 case CONST_VECTOR:
05153 case SYMBOL_REF:
05154 case LABEL_REF:
05155 case PC:
05156 case CC0:
05157 return ad;
05158
05159 case REG:
05160 {
05161 int regno = REGNO (ad);
05162
05163 if (reg_equiv_constant[regno] != 0)
05164 {
05165 subst_reg_equivs_changed = 1;
05166 return reg_equiv_constant[regno];
05167 }
05168 if (reg_equiv_memory_loc[regno] && num_not_at_initial_offset)
05169 {
05170 rtx mem = make_memloc (ad, regno);
05171 if (! rtx_equal_p (mem, reg_equiv_mem[regno]))
05172 {
05173 subst_reg_equivs_changed = 1;
05174
05175
05176
05177 PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, ad), insn),
05178 QImode);
05179 return mem;
05180 }
05181 }
05182 }
05183 return ad;
05184
05185 case PLUS:
05186
05187 if (XEXP (ad, 0) == frame_pointer_rtx
05188 && GET_CODE (XEXP (ad, 1)) == CONST_INT)
05189 return ad;
05190 break;
05191
05192 default:
05193 break;
05194 }
05195
05196 fmt = GET_RTX_FORMAT (code);
05197 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
05198 if (fmt[i] == 'e')
05199 XEXP (ad, i) = subst_reg_equivs (XEXP (ad, i), insn);
05200 return ad;
05201 }
05202
05203
05204
05205
05206
05207
05208
05209
05210 rtx
05211 form_sum (rtx x, rtx y)
05212 {
05213 rtx tem;
05214 enum machine_mode mode = GET_MODE (x);
05215
05216 if (mode == VOIDmode)
05217 mode = GET_MODE (y);
05218
05219 if (mode == VOIDmode)
05220 mode = Pmode;
05221
05222 if (GET_CODE (x) == CONST_INT)
05223 return plus_constant (y, INTVAL (x));
05224 else if (GET_CODE (y) == CONST_INT)
05225 return plus_constant (x, INTVAL (y));
05226 else if (CONSTANT_P (x))
05227 tem = x, x = y, y = tem;
05228
05229 if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)))
05230 return form_sum (XEXP (x, 0), form_sum (XEXP (x, 1), y));
05231
05232
05233
05234 if (GET_CODE (y) == PLUS && CONSTANT_P (XEXP (y, 1)))
05235 return form_sum (form_sum (x, XEXP (y, 0)), XEXP (y, 1));
05236
05237
05238
05239 if (CONSTANT_P (x) && CONSTANT_P (y))
05240 {
05241 if (GET_CODE (x) == CONST)
05242 x = XEXP (x, 0);
05243 if (GET_CODE (y) == CONST)
05244 y = XEXP (y, 0);
05245
05246 return gen_rtx_CONST (VOIDmode, gen_rtx_PLUS (mode, x, y));
05247 }
05248
05249 return gen_rtx_PLUS (mode, x, y);
05250 }
05251
05252
05253
05254
05255
05256
05257
05258
05259
05260
05261
05262
05263
05264 static rtx
05265 subst_indexed_address (rtx addr)
05266 {
05267 rtx op0 = 0, op1 = 0, op2 = 0;
05268 rtx tem;
05269 int regno;
05270
05271 if (GET_CODE (addr) == PLUS)
05272 {
05273
05274 op0 = XEXP (addr, 0), op1 = XEXP (addr, 1), op2 = 0;
05275 if (REG_P (op0)
05276 && (regno = REGNO (op0)) >= FIRST_PSEUDO_REGISTER
05277 && reg_renumber[regno] < 0
05278 && reg_equiv_constant[regno] != 0)
05279 op0 = reg_equiv_constant[regno];
05280 else if (REG_P (op1)
05281 && (regno = REGNO (op1)) >= FIRST_PSEUDO_REGISTER
05282 && reg_renumber[regno] < 0
05283 && reg_equiv_constant[regno] != 0)
05284 op1 = reg_equiv_constant[regno];
05285 else if (GET_CODE (op0) == PLUS
05286 && (tem = subst_indexed_address (op0)) != op0)
05287 op0 = tem;
05288 else if (GET_CODE (op1) == PLUS
05289 && (tem = subst_indexed_address (op1)) != op1)
05290 op1 = tem;
05291 else
05292 return addr;
05293
05294
05295 if (GET_CODE (op1) == PLUS)
05296 op2 = XEXP (op1, 1), op1 = XEXP (op1, 0);
05297 else if (GET_CODE (op0) == PLUS)
05298 op2 = op1, op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
05299
05300
05301 if (op2 != 0)
05302 op1 = form_sum (op1, op2);
05303 if (op1 != 0)
05304 op0 = form_sum (op0, op1);
05305
05306 return op0;
05307 }
05308 return addr;
05309 }
05310
05311
05312
05313
05314
05315
05316
05317
05318
05319
05320
05321 static void
05322 update_auto_inc_notes (rtx insn ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED,
05323 int reloadnum ATTRIBUTE_UNUSED)
05324 {
05325 #ifdef AUTO_INC_DEC
05326 rtx link;
05327
05328 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
05329 if (REG_NOTE_KIND (link) == REG_INC
05330 && (int) REGNO (XEXP (link, 0)) == regno)
05331 push_replacement (&XEXP (link, 0), reloadnum, VOIDmode);
05332 #endif
05333 }
05334
05335
05336
05337
05338
05339
05340
05341
05342
05343
05344
05345
05346
05347
05348
05349
05350
05351
05352
05353
05354
05355
05356
05357
05358
05359
05360
05361
05362
05363
05364
05365 static int
05366 find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
05367 enum rtx_code outer_code, enum rtx_code index_code,
05368 rtx *loc, int opnum, enum reload_type type,
05369 int ind_levels, rtx insn)
05370 {
05371 #define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, OUTER, INDEX) \
05372 ((CONTEXT) == 0 \
05373 ? regno_ok_for_base_p (REGNO, MODE, OUTER, INDEX) \
05374 : REGNO_OK_FOR_INDEX_P (REGNO))
05375
05376 enum reg_class context_reg_class;
05377 RTX_CODE code = GET_CODE (x);
05378
05379 if (context == 1)
05380 context_reg_class = INDEX_REG_CLASS;
05381 else
05382 context_reg_class = base_reg_class (mode, outer_code, index_code);
05383
05384 switch (code)
05385 {
05386 case PLUS:
05387 {
05388 rtx orig_op0 = XEXP (x, 0);
05389 rtx orig_op1 = XEXP (x, 1);
05390 RTX_CODE code0 = GET_CODE (orig_op0);
05391 RTX_CODE code1 = GET_CODE (orig_op1);
05392 rtx op0 = orig_op0;
05393 rtx op1 = orig_op1;
05394
05395 if (GET_CODE (op0) == SUBREG)
05396 {
05397 op0 = SUBREG_REG (op0);
05398 code0 = GET_CODE (op0);
05399 if (code0 == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER)
05400 op0 = gen_rtx_REG (word_mode,
05401 (REGNO (op0) +
05402 subreg_regno_offset (REGNO (SUBREG_REG (orig_op0)),
05403 GET_MODE (SUBREG_REG (orig_op0)),
05404 SUBREG_BYTE (orig_op0),
05405 GET_MODE (orig_op0))));
05406 }
05407
05408 if (GET_CODE (op1) == SUBREG)
05409 {
05410 op1 = SUBREG_REG (op1);
05411 code1 = GET_CODE (op1);
05412 if (code1 == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER)
05413
05414
05415 op1 = gen_rtx_REG (GET_MODE (op1),
05416 (REGNO (op1) +
05417 subreg_regno_offset (REGNO (SUBREG_REG (orig_op1)),
05418 GET_MODE (SUBREG_REG (orig_op1)),
05419 SUBREG_BYTE (orig_op1),
05420 GET_MODE (orig_op1))));
05421 }
05422
05423
05424
05425
05426 if (context == 1)
05427 {
05428 find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
05429 opnum, ADDR_TYPE (type), ind_levels, insn);
05430 push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
05431 context_reg_class,
05432 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
05433 return 1;
05434 }
05435
05436 if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
05437 || code0 == ZERO_EXTEND || code1 == MEM)
05438 {
05439 find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
05440 &XEXP (x, 0), opnum, type, ind_levels,
05441 insn);
05442 find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
05443 &XEXP (x, 1), opnum, type, ind_levels,
05444 insn);
05445 }
05446
05447 else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
05448 || code1 == ZERO_EXTEND || code0 == MEM)
05449 {
05450 find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
05451 &XEXP (x, 0), opnum, type, ind_levels,
05452 insn);
05453 find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
05454 &XEXP (x, 1), opnum, type, ind_levels,
05455 insn);
05456 }
05457
05458 else if (code0 == CONST_INT || code0 == CONST
05459 || code0 == SYMBOL_REF || code0 == LABEL_REF)
05460 find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
05461 &XEXP (x, 1), opnum, type, ind_levels,
05462 insn);
05463
05464 else if (code1 == CONST_INT || code1 == CONST
05465 || code1 == SYMBOL_REF || code1 == LABEL_REF)
05466 find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
05467 &XEXP (x, 0), opnum, type, ind_levels,
05468 insn);
05469
05470 else if (code0 == REG && code1 == REG)
05471 {
05472 if (REGNO_OK_FOR_INDEX_P (REGNO (op0))
05473 && regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
05474 return 0;
05475 else if (REGNO_OK_FOR_INDEX_P (REGNO (op1))
05476 && regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
05477 return 0;
05478 else if (regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
05479 find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
05480 &XEXP (x, 0), opnum, type, ind_levels,
05481 insn);
05482 else if (regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
05483 find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
05484 &XEXP (x, 1), opnum, type, ind_levels,
05485 insn);
05486 else if (REGNO_OK_FOR_INDEX_P (REGNO (op1)))
05487 find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
05488 &XEXP (x, 0), opnum, type, ind_levels,
05489 insn);
05490 else if (REGNO_OK_FOR_INDEX_P (REGNO (op0)))
05491 find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
05492 &XEXP (x, 1), opnum, type, ind_levels,
05493 insn);
05494 else
05495 {
05496 find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
05497 &XEXP (x, 0), opnum, type, ind_levels,
05498 insn);
05499 find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
05500 &XEXP (x, 1), opnum, type, ind_levels,
05501 insn);
05502 }
05503 }
05504
05505 else if (code0 == REG)
05506 {
05507 find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
05508 &XEXP (x, 0), opnum, type, ind_levels,
05509 insn);
05510 find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
05511 &XEXP (x, 1), opnum, type, ind_levels,
05512 insn);
05513 }
05514
05515 else if (code1 == REG)
05516 {
05517 find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
05518 &XEXP (x, 1), opnum, type, ind_levels,
05519 insn);
05520 find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
05521 &XEXP (x, 0), opnum, type, ind_levels,
05522 insn);
05523 }
05524 }
05525
05526 return 0;
05527
05528 case POST_MODIFY:
05529 case PRE_MODIFY:
05530 {
05531 rtx op0 = XEXP (x, 0);
05532 rtx op1 = XEXP (x, 1);
05533 enum rtx_code index_code;
05534 int regno;
05535 int reloadnum;
05536
05537 if (GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)
05538 return 0;
05539
05540
05541
05542
05543
05544 gcc_assert (op0 == XEXP (op1, 0));
05545
05546
05547
05548
05549
05550
05551
05552
05553
05554
05555
05556 if (REG_P (XEXP (op1, 1)))
05557 if (!REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
05558 find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH,
05559 &XEXP (op1, 1), opnum, RELOAD_OTHER,
05560 ind_levels, insn);
05561
05562 gcc_assert (REG_P (XEXP (op1, 0)));
05563
05564 regno = REGNO (XEXP (op1, 0));
05565 index_code = GET_CODE (XEXP (op1, 1));
05566
05567
05568 gcc_assert (regno < FIRST_PSEUDO_REGISTER
05569 || reg_equiv_constant[regno] == 0);
05570
05571
05572
05573 if (reg_equiv_memory_loc[regno] != 0
05574 && (reg_equiv_address[regno] != 0
05575 || num_not_at_initial_offset))
05576 {
05577 rtx tem = make_memloc (XEXP (x, 0), regno);
05578
05579 if (reg_equiv_address[regno]
05580 || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
05581 {
05582 rtx orig = tem;
05583
05584
05585
05586
05587
05588 find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
05589 &XEXP (tem, 0), opnum,
05590 RELOAD_OTHER,
05591 ind_levels, insn);
05592
05593 if (tem != orig)
05594 push_reg_equiv_alt_mem (regno, tem);
05595
05596
05597
05598 reloadnum = push_reload (tem, tem, &XEXP (x, 0),
05599 &XEXP (op1, 0),
05600 base_reg_class (mode, code,
05601 index_code),
05602 GET_MODE (x), GET_MODE (x), 0,
05603 0, opnum, RELOAD_OTHER);
05604
05605 update_auto_inc_notes (this_insn, regno, reloadnum);
05606 return 0;
05607 }
05608 }
05609
05610 if (reg_renumber[regno] >= 0)
05611 regno = reg_renumber[regno];
05612
05613
05614 if (!regno_ok_for_base_p (regno, GET_MODE (x), code, index_code))
05615 {
05616 reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
05617 &XEXP (op1, 0), &XEXP (x, 0),
05618 base_reg_class (mode, code, index_code),
05619 GET_MODE (x), GET_MODE (x), 0, 0,
05620 opnum, RELOAD_OTHER);
05621
05622 update_auto_inc_notes (this_insn, regno, reloadnum);
05623 return 0;
05624 }
05625 }
05626 return 0;
05627
05628 case POST_INC:
05629 case POST_DEC:
05630 case PRE_INC:
05631 case PRE_DEC:
05632 if (REG_P (XEXP (x, 0)))
05633 {
05634 int regno = REGNO (XEXP (x, 0));
05635 int value = 0;
05636 rtx x_orig = x;
05637
05638
05639 gcc_assert (regno < FIRST_PSEUDO_REGISTER
05640 || reg_equiv_constant[regno] == 0);
05641
05642
05643
05644 if (reg_equiv_memory_loc[regno] != 0
05645 && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
05646 {
05647 rtx tem = make_memloc (XEXP (x, 0), regno);
05648 if (reg_equiv_address[regno]
05649 || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
05650 {
05651 rtx orig = tem;
05652
05653
05654
05655
05656
05657 find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
05658 &XEXP (tem, 0), opnum, type,
05659 ind_levels, insn);
05660 if (tem != orig)
05661 push_reg_equiv_alt_mem (regno, tem);
05662
05663 x = gen_rtx_fmt_e (GET_CODE (x), GET_MODE (x), tem);
05664
05665 }
05666 }
05667
05668
05669
05670
05671
05672
05673
05674
05675
05676
05677
05678
05679 if (reg_renumber[regno] >= 0)
05680 regno = reg_renumber[regno];
05681 if (regno >= FIRST_PSEUDO_REGISTER
05682 || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
05683 index_code))
05684 {
05685 int reloadnum;
05686
05687
05688
05689
05690
05691
05692
05693
05694
05695 rtx equiv = (MEM_P (XEXP (x, 0))
05696 ? XEXP (x, 0)
05697 : reg_equiv_mem[regno]);
05698 int icode = (int) add_optab->handlers[(int) Pmode].insn_code;
05699 if (insn && NONJUMP_INSN_P (insn) && equiv
05700 && memory_operand (equiv, GET_MODE (equiv))
05701 #ifdef HAVE_cc0
05702 && ! sets_cc0_p (PATTERN (insn))
05703 #endif
05704 && ! (icode != CODE_FOR_nothing
05705 && ((*insn_data[icode].operand[0].predicate)
05706 (equiv, Pmode))
05707 && ((*insn_data[icode].operand[1].predicate)
05708 (equiv, Pmode))))
05709 {
05710
05711
05712
05713
05714
05715 loc = &XEXP (x_orig, 0);
05716 x = XEXP (x, 0);
05717 reloadnum
05718 = push_reload (x, x, loc, loc,
05719 context_reg_class,
05720 GET_MODE (x), GET_MODE (x), 0, 0,
05721 opnum, RELOAD_OTHER);
05722 }
05723 else
05724 {
05725 reloadnum
05726 = push_reload (x, NULL_RTX, loc, (rtx*) 0,
05727 context_reg_class,
05728 GET_MODE (x), GET_MODE (x), 0, 0,
05729 opnum, type);
05730 rld[reloadnum].inc
05731 = find_inc_amount (PATTERN (this_insn), XEXP (x_orig, 0));
05732
05733 value = 1;
05734 }
05735
05736 update_auto_inc_notes (this_insn, REGNO (XEXP (x_orig, 0)),
05737 reloadnum);
05738 }
05739 return value;
05740 }
05741
05742 else if (MEM_P (XEXP (x, 0)))
05743 {
05744
05745
05746
05747
05748
05749 rtx tem ATTRIBUTE_UNUSED = XEXP (x, 0);
05750 rtx link;
05751 int reloadnum;
05752
05753
05754
05755
05756
05757
05758
05759
05760
05761
05762 find_reloads_address (GET_MODE (x), &XEXP (x, 0),
05763 XEXP (XEXP (x, 0), 0), &XEXP (XEXP (x, 0), 0),
05764 opnum, type, ind_levels, insn);
05765
05766 reloadnum = push_reload (x, NULL_RTX, loc, (rtx*) 0,
05767 context_reg_class,
05768 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
05769 rld[reloadnum].inc
05770 = find_inc_amount (PATTERN (this_insn), XEXP (x, 0));
05771
05772 link = FIND_REG_INC_NOTE (this_insn, tem);
05773 if (link != 0)
05774 push_replacement (&XEXP (link, 0), reloadnum, VOIDmode);
05775
05776 return 1;
05777 }
05778 return 0;
05779
05780 case TRUNCATE:
05781 case SIGN_EXTEND:
05782 case ZERO_EXTEND:
05783
05784
05785
05786
05787
05788
05789
05790 find_reloads_address_1 (GET_MODE (XEXP (x, 0)), XEXP (x, 0),
05791 context, code, SCRATCH, &XEXP (x, 0), opnum,
05792 type, ind_levels, insn);
05793 push_reload (x, NULL_RTX, loc, (rtx*) 0,
05794 context_reg_class,
05795 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
05796 return 1;
05797
05798 case MEM:
05799
05800
05801
05802
05803
05804
05805
05806
05807
05808
05809
05810
05811 find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
05812 opnum, ADDR_TYPE (type), ind_levels, insn);
05813 push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
05814 context_reg_class,
05815 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
05816 return 1;
05817
05818 case REG:
05819 {
05820 int regno = REGNO (x);
05821
05822 if (reg_equiv_constant[regno] != 0)
05823 {
05824 find_reloads_address_part (reg_equiv_constant[regno], loc,
05825 context_reg_class,
05826 GET_MODE (x), opnum, type, ind_levels);
05827 return 1;
05828 }
05829
05830 #if 0
05831
05832 if (reg_equiv_mem[regno] != 0)
05833 {
05834 push_reload (reg_equiv_mem[regno], NULL_RTX, loc, (rtx*) 0,
05835 context_reg_class,
05836 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
05837 return 1;
05838 }
05839 #endif
05840
05841 if (reg_equiv_memory_loc[regno]
05842 && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
05843 {
05844 rtx tem = make_memloc (x, regno);
05845 if (reg_equiv_address[regno] != 0
05846 || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
05847 {
05848 x = tem;
05849 find_reloads_address (GET_MODE (x), &x, XEXP (x, 0),
05850 &XEXP (x, 0), opnum, ADDR_TYPE (type),
05851 ind_levels, insn);
05852 if (x != tem)
05853 push_reg_equiv_alt_mem (regno, x);
05854 }
05855 }
05856
05857 if (reg_renumber[regno] >= 0)
05858 regno = reg_renumber[regno];
05859
05860 if (regno >= FIRST_PSEUDO_REGISTER
05861 || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
05862 index_code))
05863 {
05864 push_reload (x, NULL_RTX, loc, (rtx*) 0,
05865 context_reg_class,
05866 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
05867 return 1;
05868 }
05869
05870
05871
05872
05873
05874 if (regno_clobbered_p (regno, this_insn, GET_MODE (x), 0))
05875 {
05876 push_reload (x, NULL_RTX, loc, (rtx*) 0,
05877 context_reg_class,
05878 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
05879 return 1;
05880 }
05881 }
05882 return 0;
05883
05884 case SUBREG:
05885 if (REG_P (SUBREG_REG (x)))
05886 {
05887
05888
05889
05890 if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
05891 {
05892 int regno ATTRIBUTE_UNUSED = subreg_regno (x);
05893
05894 if (!REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
05895 index_code))
05896 {
05897 push_reload (x, NULL_RTX, loc, (rtx*) 0,
05898 context_reg_class,
05899 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
05900 return 1;
05901 }
05902 }
05903
05904
05905 else
05906 {
05907 enum reg_class class = context_reg_class;
05908 if ((unsigned) CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
05909 > reg_class_size[class])
05910 {
05911 x = find_reloads_subreg_address (x, 0, opnum,
05912 ADDR_TYPE (type),
05913 ind_levels, insn);
05914 push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
05915 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
05916 return 1;
05917 }
05918 }
05919 }
05920 break;
05921
05922 default:
05923 break;
05924 }
05925
05926 {
05927 const char *fmt = GET_RTX_FORMAT (code);
05928 int i;
05929
05930 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
05931 {
05932 if (fmt[i] == 'e')
05933
05934
05935 find_reloads_address_1 (mode, XEXP (x, i), context, code, SCRATCH,
05936 &XEXP (x, i), opnum, type, ind_levels, insn);
05937 }
05938 }
05939
05940 #undef REG_OK_FOR_CONTEXT
05941 return 0;
05942 }
05943
05944
05945
05946
05947
05948
05949
05950
05951
05952
05953
05954
05955
05956
05957
05958
05959 static void
05960 find_reloads_address_part (rtx x, rtx *loc, enum reg_class class,
05961 enum machine_mode mode, int opnum,
05962 enum reload_type type, int ind_levels)
05963 {
05964 if (CONSTANT_P (x)
05965 && (! LEGITIMATE_CONSTANT_P (x)
05966 || PREFERRED_RELOAD_CLASS (x, class) == NO_REGS))
05967 {
05968 rtx tem;
05969
05970 tem = x = force_const_mem (mode, x);
05971 find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
05972 opnum, type, ind_levels, 0);
05973 }
05974
05975 else if (GET_CODE (x) == PLUS
05976 && CONSTANT_P (XEXP (x, 1))
05977 && (! LEGITIMATE_CONSTANT_P (XEXP (x, 1))
05978 || PREFERRED_RELOAD_CLASS (XEXP (x, 1), class) == NO_REGS))
05979 {
05980 rtx tem;
05981
05982 tem = force_const_mem (GET_MODE (x), XEXP (x, 1));
05983 x = gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0), tem);
05984 find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
05985 opnum, type, ind_levels, 0);
05986 }
05987
05988 push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
05989 mode, VOIDmode, 0, 0, opnum, type);
05990 }
05991
05992
05993
05994
05995
05996
05997
05998
05999
06000
06001
06002
06003
06004
06005
06006
06007
06008
06009
06010
06011
06012
06013
06014 static rtx
06015 find_reloads_subreg_address (rtx x, int force_replace, int opnum,
06016 enum reload_type type, int ind_levels, rtx insn)
06017 {
06018 int regno = REGNO (SUBREG_REG (x));
06019
06020 if (reg_equiv_memory_loc[regno])
06021 {
06022
06023
06024 if (! force_replace
06025 && (reg_equiv_address[regno]
06026 || ! offsettable_memref_p (reg_equiv_mem[regno])))
06027 force_replace = 1;
06028
06029 if (force_replace || num_not_at_initial_offset)
06030 {
06031 rtx tem = make_memloc (SUBREG_REG (x), regno);
06032
06033
06034
06035 if (force_replace
06036 || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
06037 {
06038 unsigned outer_size = GET_MODE_SIZE (GET_MODE (x));
06039 unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
06040 int offset;
06041 rtx orig = tem;
06042 enum machine_mode orig_mode = GET_MODE (orig);
06043 int reloaded;
06044
06045
06046
06047 if (BYTES_BIG_ENDIAN && outer_size > inner_size)
06048 offset = inner_size - outer_size;
06049 else
06050 offset = SUBREG_BYTE (x);
06051
06052 XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
06053 PUT_MODE (tem, GET_MODE (x));
06054
06055
06056
06057
06058 if (outer_size > inner_size)
06059 {
06060 rtx base;
06061
06062 base = XEXP (tem, 0);
06063 if (GET_CODE (base) == PLUS)
06064 {
06065 if (GET_CODE (XEXP (base, 1)) == CONST_INT
06066 && INTVAL (XEXP (base, 1)) % outer_size != 0)
06067 return x;
06068 base = XEXP (base, 0);
06069 }
06070 if (!REG_P (base)
06071 || (REGNO_POINTER_ALIGN (REGNO (base))
06072 < outer_size * BITS_PER_UNIT))
06073 return x;
06074 }
06075
06076 reloaded = find_reloads_address (GET_MODE (tem), &tem,
06077 XEXP (tem, 0), &XEXP (tem, 0),
06078 opnum, type, ind_levels, insn);
06079
06080 if (!offset && tem != orig)
06081 push_reg_equiv_alt_mem (regno, tem);
06082
06083
06084
06085
06086
06087
06088
06089
06090
06091
06092
06093 if (reloaded != 1
06094 && strict_memory_address_p (orig_mode, XEXP (tem, 0))
06095 && !strict_memory_address_p (GET_MODE (tem),
06096 XEXP (tem, 0)))
06097 push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
06098 base_reg_class (GET_MODE (tem), MEM, SCRATCH),
06099 GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
06100 opnum, type);
06101
06102
06103
06104
06105 if (replace_reloads && recog_data.operand[opnum] != x)
06106
06107
06108
06109 PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode,
06110 SUBREG_REG (x)),
06111 insn), QImode);
06112 x = tem;
06113 }
06114 }
06115 }
06116 return x;
06117 }
06118
06119
06120
06121
06122
06123
06124
06125
06126 void
06127 subst_reloads (rtx insn)
06128 {
06129 int i;
06130
06131 for (i = 0; i < n_replacements; i++)
06132 {
06133 struct replacement *r = &replacements[i];
06134 rtx reloadreg = rld[r->what].reg_rtx;
06135 if (reloadreg)
06136 {
06137 #ifdef ENABLE_CHECKING
06138
06139
06140
06141
06142
06143
06144
06145 int check_regno;
06146
06147 for (check_regno = 0; check_regno < max_regno; check_regno++)
06148 {
06149 #define CHECK_MODF(ARRAY) \
06150 gcc_assert (!ARRAY[check_regno] \
06151 || !loc_mentioned_in_p (r->where, \
06152 ARRAY[check_regno]))
06153
06154 CHECK_MODF (reg_equiv_constant);
06155 CHECK_MODF (reg_equiv_memory_loc);
06156 CHECK_MODF (reg_equiv_address);
06157 CHECK_MODF (reg_equiv_mem);
06158 #undef CHECK_MODF
06159 }
06160 #endif
06161
06162
06163
06164
06165 if (GET_CODE (*r->where) == LABEL_REF
06166 && JUMP_P (insn))
06167 {
06168 REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
06169 XEXP (*r->where, 0),
06170 REG_NOTES (insn));
06171 JUMP_LABEL (insn) = XEXP (*r->where, 0);
06172 }
06173
06174
06175
06176
06177
06178 if (GET_MODE (reloadreg) != r->mode && r->mode != VOIDmode)
06179 reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode);
06180
06181
06182
06183
06184
06185 if (r->subreg_loc != 0 && GET_CODE (reloadreg) == SUBREG)
06186 {
06187 if (GET_MODE (*r->subreg_loc)
06188 == GET_MODE (SUBREG_REG (reloadreg)))
06189 *r->subreg_loc = SUBREG_REG (reloadreg);
06190 else
06191 {
06192 int final_offset =
06193 SUBREG_BYTE (*r->subreg_loc) + SUBREG_BYTE (reloadreg);
06194
06195
06196
06197 final_offset = (final_offset /
06198 GET_MODE_SIZE (GET_MODE (*r->subreg_loc)));
06199 final_offset = (final_offset *
06200 GET_MODE_SIZE (GET_MODE (*r->subreg_loc)));
06201
06202 *r->where = SUBREG_REG (reloadreg);
06203 SUBREG_BYTE (*r->subreg_loc) = final_offset;
06204 }
06205 }
06206 else
06207 *r->where = reloadreg;
06208 }
06209
06210 else
06211 gcc_assert (rld[r->what].optional);
06212 }
06213 }
06214
06215
06216
06217
06218 void
06219 copy_replacements (rtx x, rtx y)
06220 {
06221
06222
06223 gcc_assert (GET_CODE (x) != SUBREG);
06224
06225 copy_replacements_1 (&x, &y, n_replacements);
06226 }
06227
06228 static void
06229 copy_replacements_1 (rtx *px, rtx *py, int orig_replacements)
06230 {
06231 int i, j;
06232 rtx x, y;
06233 struct replacement *r;
06234 enum rtx_code code;
06235 const char *fmt;
06236
06237 for (j = 0; j < orig_replacements; j++)
06238 {
06239 if (replacements[j].subreg_loc == px)
06240 {
06241 r = &replacements[n_replacements++];
06242 r->where = replacements[j].where;
06243 r->subreg_loc = py;
06244 r->what = replacements[j].what;
06245 r->mode = replacements[j].mode;
06246 }
06247 else if (replacements[j].where == px)
06248 {
06249 r = &replacements[n_replacements++];
06250 r->where = py;
06251 r->subreg_loc = 0;
06252 r->what = replacements[j].what;
06253 r->mode = replacements[j].mode;
06254 }
06255 }
06256
06257 x = *px;
06258 y = *py;
06259 code = GET_CODE (x);
06260 fmt = GET_RTX_FORMAT (code);
06261
06262 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
06263 {
06264 if (fmt[i] == 'e')
06265 copy_replacements_1 (&XEXP (x, i), &XEXP (y, i), orig_replacements);
06266 else if (fmt[i] == 'E')
06267 for (j = XVECLEN (x, i); --j >= 0; )
06268 copy_replacements_1 (&XVECEXP (x, i, j), &XVECEXP (y, i, j),
06269 orig_replacements);
06270 }
06271 }
06272
06273
06274
06275 void
06276 move_replacements (rtx *x, rtx *y)
06277 {
06278 int i;
06279
06280 for (i = 0; i < n_replacements; i++)
06281 if (replacements[i].subreg_loc == x)
06282 replacements[i].subreg_loc = y;
06283 else if (replacements[i].where == x)
06284 {
06285 replacements[i].where = y;
06286 replacements[i].subreg_loc = 0;
06287 }
06288 }
06289
06290
06291
06292
06293 rtx
06294 find_replacement (rtx *loc)
06295 {
06296 struct replacement *r;
06297
06298 for (r = &replacements[0]; r < &replacements[n_replacements]; r++)
06299 {
06300 rtx reloadreg = rld[r->what].reg_rtx;
06301
06302 if (reloadreg && r->where == loc)
06303 {
06304 if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode)
06305 reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg));
06306
06307 return reloadreg;
06308 }
06309 else if (reloadreg && r->subreg_loc == loc)
06310 {
06311
06312
06313
06314
06315 if (REG_P (reloadreg))
06316 return gen_rtx_REG (GET_MODE (*loc),
06317 (REGNO (reloadreg) +
06318 subreg_regno_offset (REGNO (SUBREG_REG (*loc)),
06319 GET_MODE (SUBREG_REG (*loc)),
06320 SUBREG_BYTE (*loc),
06321 GET_MODE (*loc))));
06322 else if (GET_MODE (reloadreg) == GET_MODE (*loc))
06323 return reloadreg;
06324 else
06325 {
06326 int final_offset = SUBREG_BYTE (reloadreg) + SUBREG_BYTE (*loc);
06327
06328
06329
06330 final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (*loc)));
06331 final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (*loc)));
06332 return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg),
06333 final_offset);
06334 }
06335 }
06336 }
06337
06338
06339
06340 if (GET_CODE (*loc) == PLUS || GET_CODE (*loc) == MINUS
06341 || GET_CODE (*loc) == MULT)
06342 {
06343 rtx x = find_replacement (&XEXP (*loc, 0));
06344 rtx y = find_replacement (&XEXP (*loc, 1));
06345
06346 if (x != XEXP (*loc, 0) || y != XEXP (*loc, 1))
06347 return gen_rtx_fmt_ee (GET_CODE (*loc), GET_MODE (*loc), x, y);
06348 }
06349
06350 return *loc;
06351 }
06352
06353
06354
06355
06356
06357
06358
06359
06360
06361
06362
06363 static int
06364 refers_to_regno_for_reload_p (unsigned int regno, unsigned int endregno,
06365 rtx x, rtx *loc)
06366 {
06367 int i;
06368 unsigned int r;
06369 RTX_CODE code;
06370 const char *fmt;
06371
06372 if (x == 0)
06373 return 0;
06374
06375 repeat:
06376 code = GET_CODE (x);
06377
06378 switch (code)
06379 {
06380 case REG:
06381 r = REGNO (x);
06382
06383
06384
06385 if (r >= FIRST_PSEUDO_REGISTER)
06386 {
06387 if (reg_equiv_memory_loc[r])
06388 return refers_to_regno_for_reload_p (regno, endregno,
06389 reg_equiv_memory_loc[r],
06390 (rtx*) 0);
06391
06392 gcc_assert (reg_equiv_constant[r] || reg_equiv_invariant[r]);
06393 return 0;
06394 }
06395
06396 return (endregno > r
06397 && regno < r + (r < FIRST_PSEUDO_REGISTER
06398 ? hard_regno_nregs[r][GET_MODE (x)]
06399 : 1));
06400
06401 case SUBREG:
06402
06403
06404 if (REG_P (SUBREG_REG (x))
06405 && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
06406 {
06407 unsigned int inner_regno = subreg_regno (x);
06408 unsigned int inner_endregno
06409 = inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
06410 ? hard_regno_nregs[inner_regno][GET_MODE (x)] : 1);
06411
06412 return endregno > inner_regno && regno < inner_endregno;
06413 }
06414 break;
06415
06416 case CLOBBER:
06417 case SET:
06418 if (&SET_DEST (x) != loc
06419
06420
06421
06422 && ((GET_CODE (SET_DEST (x)) == SUBREG
06423 && loc != &SUBREG_REG (SET_DEST (x))
06424 && REG_P (SUBREG_REG (SET_DEST (x)))
06425 && REGNO (SUBREG_REG (SET_DEST (x))) >= FIRST_PSEUDO_REGISTER
06426 && refers_to_regno_for_reload_p (regno, endregno,
06427 SUBREG_REG (SET_DEST (x)),
06428 loc))
06429
06430
06431 || ((!REG_P (SET_DEST (x))
06432 || earlyclobber_operand_p (SET_DEST (x)))
06433 && refers_to_regno_for_reload_p (regno, endregno,
06434 SET_DEST (x), loc))))
06435 return 1;
06436
06437 if (code == CLOBBER || loc == &SET_SRC (x))
06438 return 0;
06439 x = SET_SRC (x);
06440 goto repeat;
06441
06442 default:
06443 break;
06444 }
06445
06446
06447
06448 fmt = GET_RTX_FORMAT (code);
06449 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
06450 {
06451 if (fmt[i] == 'e' && loc != &XEXP (x, i))
06452 {
06453 if (i == 0)
06454 {
06455 x = XEXP (x, 0);
06456 goto repeat;
06457 }
06458 else
06459 if (refers_to_regno_for_reload_p (regno, endregno,
06460 XEXP (x, i), loc))
06461 return 1;
06462 }
06463 else if (fmt[i] == 'E')
06464 {
06465 int j;
06466 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
06467 if (loc != &XVECEXP (x, i, j)
06468 && refers_to_regno_for_reload_p (regno, endregno,
06469 XVECEXP (x, i, j), loc))
06470 return 1;
06471 }
06472 }
06473 return 0;
06474 }
06475
06476
06477
06478
06479
06480
06481
06482
06483
06484
06485 int
06486 reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
06487 {
06488 int regno, endregno;
06489
06490
06491 if (GET_CODE (x) == STRICT_LOW_PART
06492 || GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC)
06493 x = XEXP (x, 0);
06494
06495
06496 if (CONSTANT_P (x) || CONSTANT_P (in))
06497 return 0;
06498 else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
06499 return refers_to_mem_for_reload_p (in);
06500 else if (GET_CODE (x) == SUBREG)
06501 {
06502 regno = REGNO (SUBREG_REG (x));
06503 if (regno < FIRST_PSEUDO_REGISTER)
06504 regno += subreg_regno_offset (REGNO (SUBREG_REG (x)),
06505 GET_MODE (SUBREG_REG (x)),
06506 SUBREG_BYTE (x),
06507 GET_MODE (x));
06508 }
06509 else if (REG_P (x))
06510 {
06511 regno = REGNO (x);
06512
06513
06514
06515
06516 if (regno >= FIRST_PSEUDO_REGISTER)
06517 {
06518 if (reg_equiv_memory_loc[regno])
06519 return refers_to_mem_for_reload_p (in);
06520 gcc_assert (reg_equiv_constant[regno]);
06521 return 0;
06522 }
06523 }
06524 else if (MEM_P (x))
06525 return refers_to_mem_for_reload_p (in);
06526 else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
06527 || GET_CODE (x) == CC0)
06528 return reg_mentioned_p (x, in);
06529 else
06530 {
06531 gcc_assert (GET_CODE (x) == PLUS);
06532
06533
06534
06535
06536
06537
06538 while (MEM_P (in))
06539 in = XEXP (in, 0);
06540 if (REG_P (in))
06541 return 0;
06542 else if (GET_CODE (in) == PLUS)
06543 return (reg_overlap_mentioned_for_reload_p (x, XEXP (in, 0))
06544 || reg_overlap_mentioned_for_reload_p (x, XEXP (in, 1)));
06545 else return (reg_overlap_mentioned_for_reload_p (XEXP (x, 0), in)
06546 || reg_overlap_mentioned_for_reload_p (XEXP (x, 1), in));
06547 }
06548
06549 endregno = regno + (regno < FIRST_PSEUDO_REGISTER
06550 ? hard_regno_nregs[regno][GET_MODE (x)] : 1);
06551
06552 return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
06553 }
06554
06555
06556
06557
06558 static int
06559 refers_to_mem_for_reload_p (rtx x)
06560 {
06561 const char *fmt;
06562 int i;
06563
06564 if (MEM_P (x))
06565 return 1;
06566
06567 if (REG_P (x))
06568 return (REGNO (x) >= FIRST_PSEUDO_REGISTER
06569 && reg_equiv_memory_loc[REGNO (x)]);
06570
06571 fmt = GET_RTX_FORMAT (GET_CODE (x));
06572 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
06573 if (fmt[i] == 'e'
06574 && (MEM_P (XEXP (x, i))
06575 || refers_to_mem_for_reload_p (XEXP (x, i))))
06576 return 1;
06577
06578 return 0;
06579 }
06580
06581
06582
06583
06584
06585
06586
06587
06588
06589
06590
06591
06592
06593
06594
06595
06596
06597
06598
06599
06600
06601
06602
06603
06604
06605
06606
06607
06608 rtx
06609 find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
06610 short *reload_reg_p, int goalreg, enum machine_mode mode)
06611 {
06612 rtx p = insn;
06613 rtx goaltry, valtry, value, where;
06614 rtx pat;
06615 int regno = -1;
06616 int valueno;
06617 int goal_mem = 0;
06618 int goal_const = 0;
06619 int goal_mem_addr_varies = 0;
06620 int need_stable_sp = 0;
06621 int nregs;
06622 int valuenregs;
06623 int num = 0;
06624
06625 if (goal == 0)
06626 regno = goalreg;
06627 else if (REG_P (goal))
06628 regno = REGNO (goal);
06629 else if (MEM_P (goal))
06630 {
06631 enum rtx_code code = GET_CODE (XEXP (goal, 0));
06632 if (MEM_VOLATILE_P (goal))
06633 return 0;
06634 if (flag_float_store && SCALAR_FLOAT_MODE_P (GET_MODE (goal)))
06635 return 0;
06636
06637 switch (code)
06638 {
06639 case POST_INC:
06640 case PRE_INC:
06641 case POST_DEC:
06642 case PRE_DEC:
06643 case POST_MODIFY:
06644 case PRE_MODIFY:
06645 return 0;
06646 default:
06647 break;
06648 }
06649 goal_mem = 1;
06650 }
06651 else if (CONSTANT_P (goal))
06652 goal_const = 1;
06653 else if (GET_CODE (goal) == PLUS
06654 && XEXP (goal, 0) == stack_pointer_rtx
06655 && CONSTANT_P (XEXP (goal, 1)))
06656 goal_const = need_stable_sp = 1;
06657 else if (GET_CODE (goal) == PLUS
06658 && XEXP (goal, 0) == frame_pointer_rtx
06659 && CONSTANT_P (XEXP (goal, 1)))
06660 goal_const = 1;
06661 else
06662 return 0;
06663
06664 num = 0;
06665
06666
06667
06668
06669 while (1)
06670 {
06671 p = PREV_INSN (p);
06672 num++;
06673 if (p == 0 || LABEL_P (p)
06674 || num > PARAM_VALUE (PARAM_MAX_RELOAD_SEARCH_INSNS))
06675 return 0;
06676
06677 if (NONJUMP_INSN_P (p)
06678
06679 && (! (reload_reg_p != 0
06680 && reload_reg_p != (short *) (HOST_WIDE_INT) 1)
06681
06682
06683
06684
06685
06686
06687
06688
06689 || INSN_UID (p) < reload_first_uid))
06690 {
06691 rtx tem;
06692 pat = single_set (p);
06693
06694
06695 if (pat != 0
06696 && ((regno >= 0
06697 && true_regnum (SET_SRC (pat)) == regno
06698 && (valueno = true_regnum (valtry = SET_DEST (pat))) >= 0)
06699 ||
06700 (regno >= 0
06701 && true_regnum (SET_DEST (pat)) == regno
06702 && (valueno = true_regnum (valtry = SET_SRC (pat))) >= 0)
06703 ||
06704 (goal_const && rtx_equal_p (SET_SRC (pat), goal)
06705
06706
06707 && !reg_overlap_mentioned_for_reload_p (SET_DEST (pat), goal)
06708 && (valueno = true_regnum (valtry = SET_DEST (pat))) >= 0)
06709 || (goal_mem
06710 && (valueno = true_regnum (valtry = SET_DEST (pat))) >= 0
06711 && rtx_renumbered_equal_p (goal, SET_SRC (pat)))
06712 || (goal_mem
06713 && (valueno = true_regnum (valtry = SET_SRC (pat))) >= 0
06714 && rtx_renumbered_equal_p (goal, SET_DEST (pat)))
06715
06716
06717
06718 || (goal_const && REG_NOTES (p) != 0
06719 && (tem = find_reg_note (p, REG_EQUIV, NULL_RTX))
06720 && ((rtx_equal_p (XEXP (tem, 0), goal)
06721 && (valueno
06722 = true_regnum (valtry = SET_DEST (pat))) >= 0)
06723 || (REG_P (SET_DEST (pat))
06724 && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
06725 && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
06726 && GET_CODE (goal) == CONST_INT
06727 && 0 != (goaltry
06728 = operand_subword (XEXP (tem, 0), 0, 0,
06729 VOIDmode))
06730 && rtx_equal_p (goal, goaltry)
06731 && (valtry
06732 = operand_subword (SET_DEST (pat), 0, 0,
06733 VOIDmode))
06734 && (valueno = true_regnum (valtry)) >= 0)))
06735 || (goal_const && (tem = find_reg_note (p, REG_EQUIV,
06736 NULL_RTX))
06737 && REG_P (SET_DEST (pat))
06738 && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
06739 && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
06740 && GET_CODE (goal) == CONST_INT
06741 && 0 != (goaltry = operand_subword (XEXP (tem, 0), 1, 0,
06742 VOIDmode))
06743 && rtx_equal_p (goal, goaltry)
06744 && (valtry
06745 = operand_subword (SET_DEST (pat), 1, 0, VOIDmode))
06746 && (valueno = true_regnum (valtry)) >= 0)))
06747 {
06748 if (other >= 0)
06749 {
06750 if (valueno != other)
06751 continue;
06752 }
06753 else if ((unsigned) valueno >= FIRST_PSEUDO_REGISTER)
06754 continue;
06755 else
06756 {
06757 int i;
06758
06759 for (i = hard_regno_nregs[valueno][mode] - 1; i >= 0; i--)
06760 if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
06761 valueno + i))
06762 break;
06763 if (i >= 0)
06764 continue;
06765 }
06766 value = valtry;
06767 where = p;
06768 break;
06769 }
06770 }
06771 }
06772
06773
06774
06775
06776
06777
06778
06779
06780
06781 if (REG_NOTES (where) != 0 && find_reg_note (where, REG_UNUSED, value))
06782 return 0;
06783
06784
06785
06786 if (valueno == STACK_POINTER_REGNUM || regno == STACK_POINTER_REGNUM
06787 || (goal_mem && reg_overlap_mentioned_for_reload_p (stack_pointer_rtx,
06788 goal)))
06789 need_stable_sp = 1;
06790
06791
06792 if (GET_MODE (value) != mode)
06793 return 0;
06794
06795
06796
06797
06798 if (goal_mem && value == SET_DEST (single_set (where))
06799 && refers_to_regno_for_reload_p (valueno,
06800 (valueno
06801 + hard_regno_nregs[valueno][mode]),
06802 goal, (rtx*) 0))
06803 return 0;
06804
06805
06806
06807 if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER)
06808 nregs = hard_regno_nregs[regno][mode];
06809 else
06810 nregs = 1;
06811 valuenregs = hard_regno_nregs[valueno][mode];
06812
06813 if (!goal_mem && !goal_const
06814 && regno + nregs > valueno && regno < valueno + valuenregs)
06815 return 0;
06816
06817
06818
06819
06820
06821
06822
06823 if (reload_reg_p != 0 && reload_reg_p != (short *) (HOST_WIDE_INT) 1)
06824 {
06825 int i;
06826 for (i = 0; i < valuenregs; ++i)
06827 if (reload_reg_p[valueno + i] >= 0)
06828 return 0;
06829 }
06830
06831
06832
06833
06834 if (reload_reg_p != 0)
06835 {
06836 int i;
06837 for (i = 0; i < n_reloads; i++)
06838 if (rld[i].reg_rtx != 0 && rld[i].in)
06839 {
06840 int regno1 = REGNO (rld[i].reg_rtx);
06841 int nregs1 = hard_regno_nregs[regno1]
06842 [GET_MODE (rld[i].reg_rtx)];
06843 if (regno1 < valueno + valuenregs
06844 && regno1 + nregs1 > valueno)
06845 return 0;
06846 }
06847 }
06848
06849 if (goal_mem)
06850
06851
06852 goal_mem_addr_varies = !CONSTANT_ADDRESS_P (XEXP (goal, 0));
06853
06854
06855
06856
06857 p = insn;
06858 while (1)
06859 {
06860 p = PREV_INSN (p);
06861 if (p == where)
06862 return value;
06863
06864
06865
06866 if (CALL_P (p))
06867 {
06868 int i;
06869
06870 if (goal_mem || need_stable_sp)
06871 return 0;
06872
06873 if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER)
06874 for (i = 0; i < nregs; ++i)
06875 if (call_used_regs[regno + i]
06876 || HARD_REGNO_CALL_PART_CLOBBERED (regno + i, mode))
06877 return 0;
06878
06879 if (valueno >= 0 && valueno < FIRST_PSEUDO_REGISTER)
06880 for (i = 0; i < valuenregs; ++i)
06881 if (call_used_regs[valueno + i]
06882 || HARD_REGNO_CALL_PART_CLOBBERED (valueno + i, mode))
06883 return 0;
06884 }
06885
06886 if (INSN_P (p))
06887 {
06888 pat = PATTERN (p);
06889
06890
06891 if (volatile_insn_p (pat))
06892 return 0;
06893
06894
06895
06896
06897
06898
06899 if (GET_CODE (pat) == COND_EXEC)
06900 pat = COND_EXEC_CODE (pat);
06901 if (GET_CODE (pat) == SET || GET_CODE (pat) == CLOBBER)
06902 {
06903 rtx dest = SET_DEST (pat);
06904 while (GET_CODE (dest) == SUBREG
06905 || GET_CODE (dest) == ZERO_EXTRACT
06906 || GET_CODE (dest) == STRICT_LOW_PART)
06907 dest = XEXP (dest, 0);
06908 if (REG_P (dest))
06909 {
06910 int xregno = REGNO (dest);
06911 int xnregs;
06912 if (REGNO (dest) < FIRST_PSEUDO_REGISTER)
06913 xnregs = hard_regno_nregs[xregno][GET_MODE (dest)];
06914 else
06915 xnregs = 1;
06916 if (xregno < regno + nregs && xregno + xnregs > regno)
06917 return 0;
06918 if (xregno < valueno + valuenregs
06919 && xregno + xnregs > valueno)
06920 return 0;
06921 if (goal_mem_addr_varies
06922 && reg_overlap_mentioned_for_reload_p (dest, goal))
06923 return 0;
06924 if (xregno == STACK_POINTER_REGNUM && need_stable_sp)
06925 return 0;
06926 }
06927 else if (goal_mem && MEM_P (dest)
06928 && ! push_operand (dest, GET_MODE (dest)))
06929 return 0;
06930 else if (MEM_P (dest) && regno >= FIRST_PSEUDO_REGISTER
06931 && reg_equiv_memory_loc[regno] != 0)
06932 return 0;
06933 else if (need_stable_sp && push_operand (dest, GET_MODE (dest)))
06934 return 0;
06935 }
06936 else if (GET_CODE (pat) == PARALLEL)
06937 {
06938 int i;
06939 for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)
06940 {
06941 rtx v1 = XVECEXP (pat, 0, i);
06942 if (GET_CODE (v1) == COND_EXEC)
06943 v1 = COND_EXEC_CODE (v1);
06944 if (GET_CODE (v1) == SET || GET_CODE (v1) == CLOBBER)
06945 {
06946 rtx dest = SET_DEST (v1);
06947 while (GET_CODE (dest) == SUBREG
06948 || GET_CODE (dest) == ZERO_EXTRACT
06949 || GET_CODE (dest) == STRICT_LOW_PART)
06950 dest = XEXP (dest, 0);
06951 if (REG_P (dest))
06952 {
06953 int xregno = REGNO (dest);
06954 int xnregs;
06955 if (REGNO (dest) < FIRST_PSEUDO_REGISTER)
06956 xnregs = hard_regno_nregs[xregno][GET_MODE (dest)];
06957 else
06958 xnregs = 1;
06959 if (xregno < regno + nregs
06960 && xregno + xnregs > regno)
06961 return 0;
06962 if (xregno < valueno + valuenregs
06963 && xregno + xnregs > valueno)
06964 return 0;
06965 if (goal_mem_addr_varies
06966 && reg_overlap_mentioned_for_reload_p (dest,
06967 goal))
06968 return 0;
06969 if (xregno == STACK_POINTER_REGNUM && need_stable_sp)
06970 return 0;
06971 }
06972 else if (goal_mem && MEM_P (dest)
06973 && ! push_operand (dest, GET_MODE (dest)))
06974 return 0;
06975 else if (MEM_P (dest) && regno >= FIRST_PSEUDO_REGISTER
06976 && reg_equiv_memory_loc[regno] != 0)
06977 return 0;
06978 else if (need_stable_sp
06979 && push_operand (dest, GET_MODE (dest)))
06980 return 0;
06981 }
06982 }
06983 }
06984
06985 if (CALL_P (p) && CALL_INSN_FUNCTION_USAGE (p))
06986 {
06987 rtx link;
06988
06989 for (link = CALL_INSN_FUNCTION_USAGE (p); XEXP (link, 1) != 0;
06990 link = XEXP (link, 1))
06991 {
06992 pat = XEXP (link, 0);
06993 if (GET_CODE (pat) == CLOBBER)
06994 {
06995 rtx dest = SET_DEST (pat);
06996
06997 if (REG_P (dest))
06998 {
06999 int xregno = REGNO (dest);
07000 int xnregs
07001 = hard_regno_nregs[xregno][GET_MODE (dest)];
07002
07003 if (xregno < regno + nregs
07004 && xregno + xnregs > regno)
07005 return 0;
07006 else if (xregno < valueno + valuenregs
07007 && xregno + xnregs > valueno)
07008 return 0;
07009 else if (goal_mem_addr_varies
07010 && reg_overlap_mentioned_for_reload_p (dest,
07011 goal))
07012 return 0;
07013 }
07014
07015 else if (goal_mem && MEM_P (dest)
07016 && ! push_operand (dest, GET_MODE (dest)))
07017 return 0;
07018 else if (need_stable_sp
07019 && push_operand (dest, GET_MODE (dest)))
07020 return 0;
07021 }
07022 }
07023 }
07024
07025 #ifdef AUTO_INC_DEC
07026
07027
07028
07029
07030 {
07031 rtx link;
07032
07033 for (link = REG_NOTES (p); link; link = XEXP (link, 1))
07034 if (REG_NOTE_KIND (link) == REG_INC
07035 && REG_P (XEXP (link, 0)))
07036 {
07037 int incno = REGNO (XEXP (link, 0));
07038 if (incno < regno + nregs && incno >= regno)
07039 return 0;
07040 if (incno < valueno + valuenregs && incno >= valueno)
07041 return 0;
07042 if (goal_mem_addr_varies
07043 && reg_overlap_mentioned_for_reload_p (XEXP (link, 0),
07044 goal))
07045 return 0;
07046 }
07047 }
07048 #endif
07049 }
07050 }
07051 }
07052
07053
07054
07055
07056
07057 static int
07058 find_inc_amount (rtx x, rtx inced)
07059 {
07060 enum rtx_code code = GET_CODE (x);
07061 const char *fmt;
07062 int i;
07063
07064 if (code == MEM)
07065 {
07066 rtx addr = XEXP (x, 0);
07067 if ((GET_CODE (addr) == PRE_DEC
07068 || GET_CODE (addr) == POST_DEC
07069 || GET_CODE (addr) == PRE_INC
07070 || GET_CODE (addr) == POST_INC)
07071 && XEXP (addr, 0) == inced)
07072 return GET_MODE_SIZE (GET_MODE (x));
07073 else if ((GET_CODE (addr) == PRE_MODIFY
07074 || GET_CODE (addr) == POST_MODIFY)
07075 && GET_CODE (XEXP (addr, 1)) == PLUS
07076 && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
07077 && XEXP (addr, 0) == inced
07078 && GET_CODE (XEXP (XEXP (addr, 1), 1)) == CONST_INT)
07079 {
07080 i = INTVAL (XEXP (XEXP (addr, 1), 1));
07081 return i < 0 ? -i : i;
07082 }
07083 }
07084
07085 fmt = GET_RTX_FORMAT (code);
07086 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
07087 {
07088 if (fmt[i] == 'e')
07089 {
07090 int tem = find_inc_amount (XEXP (x, i), inced);
07091 if (tem != 0)
07092 return tem;
07093 }
07094 if (fmt[i] == 'E')
07095 {
07096 int j;
07097 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
07098 {
07099 int tem = find_inc_amount (XVECEXP (x, i, j), inced);
07100 if (tem != 0)
07101 return tem;
07102 }
07103 }
07104 }
07105
07106 return 0;
07107 }
07108
07109
07110
07111
07112 #ifdef AUTO_INC_DEC
07113 static int
07114 reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno,
07115 rtx insn)
07116 {
07117 rtx link;
07118
07119 gcc_assert (insn);
07120
07121 if (! INSN_P (insn))
07122 return 0;
07123
07124 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
07125 if (REG_NOTE_KIND (link) == REG_INC)
07126 {
07127 unsigned int test = (int) REGNO (XEXP (link, 0));
07128 if (test >= regno && test < endregno)
07129 return 1;
07130 }
07131 return 0;
07132 }
07133 #else
07134
07135 #define reg_inc_found_and_valid_p(regno,endregno,insn) 0
07136
07137 #endif
07138
07139
07140
07141
07142
07143 int
07144 regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
07145 int sets)
07146 {
07147 unsigned int nregs, endregno;
07148
07149
07150 gcc_assert (regno < FIRST_PSEUDO_REGISTER);
07151
07152 nregs = hard_regno_nregs[regno][mode];
07153 endregno = regno + nregs;
07154
07155 if ((GET_CODE (PATTERN (insn)) == CLOBBER
07156 || (sets == 1 && GET_CODE (PATTERN (insn)) == SET))
07157 && REG_P (XEXP (PATTERN (insn), 0)))
07158 {
07159 unsigned int test = REGNO (XEXP (PATTERN (insn), 0));
07160
07161 return test >= regno && test < endregno;
07162 }
07163
07164 if (sets == 2 && reg_inc_found_and_valid_p (regno, endregno, insn))
07165 return 1;
07166
07167 if (GET_CODE (PATTERN (insn)) == PARALLEL)
07168 {
07169 int i = XVECLEN (PATTERN (insn), 0) - 1;
07170
07171 for (; i >= 0; i--)
07172 {
07173 rtx elt = XVECEXP (PATTERN (insn), 0, i);
07174 if ((GET_CODE (elt) == CLOBBER
07175 || (sets == 1 && GET_CODE (PATTERN (insn)) == SET))
07176 && REG_P (XEXP (elt, 0)))
07177 {
07178 unsigned int test = REGNO (XEXP (elt, 0));
07179
07180 if (test >= regno && test < endregno)
07181 return 1;
07182 }
07183 if (sets == 2
07184 && reg_inc_found_and_valid_p (regno, endregno, elt))
07185 return 1;
07186 }
07187 }
07188
07189 return 0;
07190 }
07191
07192
07193 rtx
07194 reload_adjust_reg_for_mode (rtx reloadreg, enum machine_mode mode)
07195 {
07196 int regno;
07197
07198 if (GET_MODE (reloadreg) == mode)
07199 return reloadreg;
07200
07201 regno = REGNO (reloadreg);
07202
07203 if (WORDS_BIG_ENDIAN)
07204 regno += (int) hard_regno_nregs[regno][GET_MODE (reloadreg)]
07205 - (int) hard_regno_nregs[regno][mode];
07206
07207 return gen_rtx_REG (mode, regno);
07208 }
07209
07210 static const char *const reload_when_needed_name[] =
07211 {
07212 "RELOAD_FOR_INPUT",
07213 "RELOAD_FOR_OUTPUT",
07214 "RELOAD_FOR_INSN",
07215 "RELOAD_FOR_INPUT_ADDRESS",
07216 "RELOAD_FOR_INPADDR_ADDRESS",
07217 "RELOAD_FOR_OUTPUT_ADDRESS",
07218 "RELOAD_FOR_OUTADDR_ADDRESS",
07219 "RELOAD_FOR_OPERAND_ADDRESS",
07220 "RELOAD_FOR_OPADDR_ADDR",
07221 "RELOAD_OTHER",
07222 "RELOAD_FOR_OTHER_ADDRESS"
07223 };
07224
07225
07226
07227 void
07228 debug_reload_to_stream (FILE *f)
07229 {
07230 int r;
07231 const char *prefix;
07232
07233 if (! f)
07234 f = stderr;
07235 for (r = 0; r < n_reloads; r++)
07236 {
07237 fprintf (f, "Reload %d: ", r);
07238
07239 if (rld[r].in != 0)
07240 {
07241 fprintf (f, "reload_in (%s) = ",
07242 GET_MODE_NAME (rld[r].inmode));
07243 print_inline_rtx (f, rld[r].in, 24);
07244 fprintf (f, "\n\t");
07245 }
07246
07247 if (rld[r].out != 0)
07248 {
07249 fprintf (f, "reload_out (%s) = ",
07250 GET_MODE_NAME (rld[r].outmode));
07251 print_inline_rtx (f, rld[r].out, 24);
07252 fprintf (f, "\n\t");
07253 }
07254
07255 fprintf (f, "%s, ", reg_class_names[(int) rld[r].class]);
07256
07257 fprintf (f, "%s (opnum = %d)",
07258 reload_when_needed_name[(int) rld[r].when_needed],
07259 rld[r].opnum);
07260
07261 if (rld[r].optional)
07262 fprintf (f, ", optional");
07263
07264 if (rld[r].nongroup)
07265 fprintf (f, ", nongroup");
07266
07267 if (rld[r].inc != 0)
07268 fprintf (f, ", inc by %d", rld[r].inc);
07269
07270 if (rld[r].nocombine)
07271 fprintf (f, ", can't combine");
07272
07273 if (rld[r].secondary_p)
07274 fprintf (f, ", secondary_reload_p");
07275
07276 if (rld[r].in_reg != 0)
07277 {
07278 fprintf (f, "\n\treload_in_reg: ");
07279 print_inline_rtx (f, rld[r].in_reg, 24);
07280 }
07281
07282 if (rld[r].out_reg != 0)
07283 {
07284 fprintf (f, "\n\treload_out_reg: ");
07285 print_inline_rtx (f, rld[r].out_reg, 24);
07286 }
07287
07288 if (rld[r].reg_rtx != 0)
07289 {
07290 fprintf (f, "\n\treload_reg_rtx: ");
07291 print_inline_rtx (f, rld[r].reg_rtx, 24);
07292 }
07293
07294 prefix = "\n\t";
07295 if (rld[r].secondary_in_reload != -1)
07296 {
07297 fprintf (f, "%ssecondary_in_reload = %d",
07298 prefix, rld[r].secondary_in_reload);
07299 prefix = ", ";
07300 }
07301
07302 if (rld[r].secondary_out_reload != -1)
07303 fprintf (f, "%ssecondary_out_reload = %d\n",
07304 prefix, rld[r].secondary_out_reload);
07305
07306 prefix = "\n\t";
07307 if (rld[r].secondary_in_icode != CODE_FOR_nothing)
07308 {
07309 fprintf (f, "%ssecondary_in_icode = %s", prefix,
07310 insn_data[rld[r].secondary_in_icode].name);
07311 prefix = ", ";
07312 }
07313
07314 if (rld[r].secondary_out_icode != CODE_FOR_nothing)
07315 fprintf (f, "%ssecondary_out_icode = %s", prefix,
07316 insn_data[rld[r].secondary_out_icode].name);
07317
07318 fprintf (f, "\n");
07319 }
07320 }
07321
07322 void
07323 debug_reload (void)
07324 {
07325 debug_reload_to_stream (stderr);
07326 }