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