00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.h"
00027 #include "rtl.h"
00028 #include "tm_p.h"
00029 #include "insn-config.h"
00030 #include "insn-attr.h"
00031 #include "hard-reg-set.h"
00032 #include "recog.h"
00033 #include "regs.h"
00034 #include "expr.h"
00035 #include "function.h"
00036 #include "flags.h"
00037 #include "real.h"
00038 #include "toplev.h"
00039 #include "basic-block.h"
00040 #include "output.h"
00041 #include "reload.h"
00042
00043 #ifndef STACK_PUSH_CODE
00044 #ifdef STACK_GROWS_DOWNWARD
00045 #define STACK_PUSH_CODE PRE_DEC
00046 #else
00047 #define STACK_PUSH_CODE PRE_INC
00048 #endif
00049 #endif
00050
00051 #ifndef STACK_POP_CODE
00052 #ifdef STACK_GROWS_DOWNWARD
00053 #define STACK_POP_CODE POST_INC
00054 #else
00055 #define STACK_POP_CODE POST_DEC
00056 #endif
00057 #endif
00058
00059 static void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx);
00060 static rtx *find_single_use_1 (rtx, rtx *);
00061 static void validate_replace_src_1 (rtx *, void *);
00062 static rtx split_insn (rtx);
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 int volatile_ok;
00073
00074 struct recog_data recog_data;
00075
00076
00077
00078 struct operand_alternative recog_op_alt[MAX_RECOG_OPERANDS][MAX_RECOG_ALTERNATIVES];
00079
00080
00081
00082
00083 int which_alternative;
00084
00085
00086
00087
00088
00089 int reload_completed;
00090
00091
00092 int epilogue_completed;
00093
00094
00095
00096
00097
00098 void
00099 init_recog_no_volatile (void)
00100 {
00101 volatile_ok = 0;
00102 }
00103
00104 void
00105 init_recog (void)
00106 {
00107 volatile_ok = 1;
00108 }
00109
00110
00111
00112
00113
00114 int
00115 check_asm_operands (rtx x)
00116 {
00117 int noperands;
00118 rtx *operands;
00119 const char **constraints;
00120 int i;
00121
00122
00123 if (reload_completed)
00124 {
00125
00126 extract_insn (make_insn_raw (x));
00127 constrain_operands (1);
00128 return which_alternative >= 0;
00129 }
00130
00131 noperands = asm_noperands (x);
00132 if (noperands < 0)
00133 return 0;
00134 if (noperands == 0)
00135 return 1;
00136
00137 operands = alloca (noperands * sizeof (rtx));
00138 constraints = alloca (noperands * sizeof (char *));
00139
00140 decode_asm_operands (x, operands, NULL, constraints, NULL);
00141
00142 for (i = 0; i < noperands; i++)
00143 {
00144 const char *c = constraints[i];
00145 if (c[0] == '%')
00146 c++;
00147 if (ISDIGIT ((unsigned char) c[0]) && c[1] == '\0')
00148 c = constraints[c[0] - '0'];
00149
00150 if (! asm_operand_ok (operands[i], c))
00151 return 0;
00152 }
00153
00154 return 1;
00155 }
00156
00157
00158
00159 typedef struct change_t
00160 {
00161 rtx object;
00162 int old_code;
00163 rtx *loc;
00164 rtx old;
00165 } change_t;
00166
00167 static change_t *changes;
00168 static int changes_allocated;
00169
00170 static int num_changes = 0;
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 int
00191 validate_change (rtx object, rtx *loc, rtx new, int in_group)
00192 {
00193 rtx old = *loc;
00194
00195 if (old == new || rtx_equal_p (old, new))
00196 return 1;
00197
00198 gcc_assert (in_group != 0 || num_changes == 0);
00199
00200 *loc = new;
00201
00202
00203 if (num_changes >= changes_allocated)
00204 {
00205 if (changes_allocated == 0)
00206
00207
00208 changes_allocated = MAX_RECOG_OPERANDS * 5;
00209 else
00210 changes_allocated *= 2;
00211
00212 changes = xrealloc (changes, sizeof (change_t) * changes_allocated);
00213 }
00214
00215 changes[num_changes].object = object;
00216 changes[num_changes].loc = loc;
00217 changes[num_changes].old = old;
00218
00219 if (object && !MEM_P (object))
00220 {
00221
00222
00223 changes[num_changes].old_code = INSN_CODE (object);
00224 INSN_CODE (object) = -1;
00225 }
00226
00227 num_changes++;
00228
00229
00230
00231
00232 if (in_group)
00233 return 1;
00234 else
00235 return apply_change_group ();
00236 }
00237
00238
00239
00240
00241 int
00242 insn_invalid_p (rtx insn)
00243 {
00244 rtx pat = PATTERN (insn);
00245 int num_clobbers = 0;
00246
00247
00248 int icode = recog (pat, insn,
00249 (GET_CODE (pat) == SET
00250 && ! reload_completed && ! reload_in_progress)
00251 ? &num_clobbers : 0);
00252 int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0;
00253
00254
00255
00256
00257 if ((is_asm && ! check_asm_operands (PATTERN (insn)))
00258 || (!is_asm && icode < 0))
00259 return 1;
00260
00261
00262
00263
00264 if (num_clobbers > 0)
00265 {
00266 rtx newpat;
00267
00268 if (added_clobbers_hard_reg_p (icode))
00269 return 1;
00270
00271 newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_clobbers + 1));
00272 XVECEXP (newpat, 0, 0) = pat;
00273 add_clobbers (newpat, icode);
00274 PATTERN (insn) = pat = newpat;
00275 }
00276
00277
00278 if (reload_completed)
00279 {
00280 extract_insn (insn);
00281
00282 if (! constrain_operands (1))
00283 return 1;
00284 }
00285
00286 INSN_CODE (insn) = icode;
00287 return 0;
00288 }
00289
00290
00291 int
00292 num_changes_pending (void)
00293 {
00294 return num_changes;
00295 }
00296
00297
00298
00299
00300 int
00301 apply_change_group (void)
00302 {
00303 int i;
00304 rtx last_validated = NULL_RTX;
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 for (i = 0; i < num_changes; i++)
00316 {
00317 rtx object = changes[i].object;
00318
00319
00320
00321 if (object == 0 || object == last_validated)
00322 continue;
00323
00324 if (MEM_P (object))
00325 {
00326 if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
00327 break;
00328 }
00329 else if (insn_invalid_p (object))
00330 {
00331 rtx pat = PATTERN (object);
00332
00333
00334
00335
00336
00337
00338 if (GET_CODE (pat) == PARALLEL
00339 && GET_CODE (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1)) == CLOBBER
00340 && asm_noperands (PATTERN (object)) < 0)
00341 {
00342 rtx newpat;
00343
00344 if (XVECLEN (pat, 0) == 2)
00345 newpat = XVECEXP (pat, 0, 0);
00346 else
00347 {
00348 int j;
00349
00350 newpat
00351 = gen_rtx_PARALLEL (VOIDmode,
00352 rtvec_alloc (XVECLEN (pat, 0) - 1));
00353 for (j = 0; j < XVECLEN (newpat, 0); j++)
00354 XVECEXP (newpat, 0, j) = XVECEXP (pat, 0, j);
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 validate_change (object, &PATTERN (object), newpat, 1);
00367 continue;
00368 }
00369 else if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
00370
00371
00372 continue;
00373 else
00374 break;
00375 }
00376 last_validated = object;
00377 }
00378
00379 if (i == num_changes)
00380 {
00381 basic_block bb;
00382
00383 for (i = 0; i < num_changes; i++)
00384 if (changes[i].object
00385 && INSN_P (changes[i].object)
00386 && (bb = BLOCK_FOR_INSN (changes[i].object)))
00387 bb->flags |= BB_DIRTY;
00388
00389 num_changes = 0;
00390 return 1;
00391 }
00392 else
00393 {
00394 cancel_changes (0);
00395 return 0;
00396 }
00397 }
00398
00399
00400
00401 int
00402 num_validated_changes (void)
00403 {
00404 return num_changes;
00405 }
00406
00407
00408
00409 void
00410 cancel_changes (int num)
00411 {
00412 int i;
00413
00414
00415
00416 for (i = num_changes - 1; i >= num; i--)
00417 {
00418 *changes[i].loc = changes[i].old;
00419 if (changes[i].object && !MEM_P (changes[i].object))
00420 INSN_CODE (changes[i].object) = changes[i].old_code;
00421 }
00422 num_changes = num;
00423 }
00424
00425
00426
00427
00428 static void
00429 validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
00430 {
00431 int i, j;
00432 const char *fmt;
00433 rtx x = *loc;
00434 enum rtx_code code;
00435 enum machine_mode op0_mode = VOIDmode;
00436 int prev_changes = num_changes;
00437 rtx new;
00438
00439 if (!x)
00440 return;
00441
00442 code = GET_CODE (x);
00443 fmt = GET_RTX_FORMAT (code);
00444 if (fmt[0] == 'e')
00445 op0_mode = GET_MODE (XEXP (x, 0));
00446
00447
00448
00449
00450
00451 if (x == from
00452 || (REG_P (x) && REG_P (from)
00453 && GET_MODE (x) == GET_MODE (from)
00454 && REGNO (x) == REGNO (from))
00455 || (GET_CODE (x) == GET_CODE (from) && GET_MODE (x) == GET_MODE (from)
00456 && rtx_equal_p (x, from)))
00457 {
00458 validate_change (object, loc, to, 1);
00459 return;
00460 }
00461
00462
00463
00464
00465
00466
00467 if (GET_CODE (x) == PARALLEL)
00468 {
00469 for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
00470 {
00471 if (j && GET_CODE (XVECEXP (x, 0, j)) == SET
00472 && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == ASM_OPERANDS)
00473 {
00474
00475 gcc_assert (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0)))
00476 == ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP
00477 (x, 0, j))));
00478 validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)),
00479 from, to, object);
00480 }
00481 else
00482 validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object);
00483 }
00484 }
00485 else
00486 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00487 {
00488 if (fmt[i] == 'e')
00489 validate_replace_rtx_1 (&XEXP (x, i), from, to, object);
00490 else if (fmt[i] == 'E')
00491 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
00492 validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object);
00493 }
00494
00495
00496 if (num_changes == prev_changes)
00497 return;
00498
00499
00500
00501 if (fmt[0] == 'e' && GET_MODE (XEXP (x, 0)) != VOIDmode)
00502 op0_mode = GET_MODE (XEXP (x, 0));
00503
00504
00505
00506
00507 if (SWAPPABLE_OPERANDS_P (x)
00508 && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
00509 {
00510 validate_change (object, loc,
00511 gen_rtx_fmt_ee (COMMUTATIVE_ARITH_P (x) ? code
00512 : swap_condition (code),
00513 GET_MODE (x), XEXP (x, 1),
00514 XEXP (x, 0)), 1);
00515 x = *loc;
00516 code = GET_CODE (x);
00517 }
00518
00519 switch (code)
00520 {
00521 case PLUS:
00522
00523
00524
00525
00526 if (GET_CODE (XEXP (x, 1)) == CONST_INT && XEXP (x, 1) == to)
00527 validate_change (object, loc,
00528 simplify_gen_binary
00529 (PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1);
00530 break;
00531 case MINUS:
00532 if (GET_CODE (XEXP (x, 1)) == CONST_INT
00533 || GET_CODE (XEXP (x, 1)) == CONST_DOUBLE)
00534 validate_change (object, loc,
00535 simplify_gen_binary
00536 (PLUS, GET_MODE (x), XEXP (x, 0),
00537 simplify_gen_unary (NEG,
00538 GET_MODE (x), XEXP (x, 1),
00539 GET_MODE (x))), 1);
00540 break;
00541 case ZERO_EXTEND:
00542 case SIGN_EXTEND:
00543 if (GET_MODE (XEXP (x, 0)) == VOIDmode)
00544 {
00545 new = simplify_gen_unary (code, GET_MODE (x), XEXP (x, 0),
00546 op0_mode);
00547
00548
00549 if (!new)
00550 new = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
00551 validate_change (object, loc, new, 1);
00552 }
00553 break;
00554 case SUBREG:
00555
00556 new = simplify_subreg (GET_MODE (x), SUBREG_REG (x), op0_mode,
00557 SUBREG_BYTE (x));
00558
00559
00560 if (!new && GET_MODE (SUBREG_REG (x)) == VOIDmode)
00561 new = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
00562 if (new)
00563 validate_change (object, loc, new, 1);
00564 break;
00565 case ZERO_EXTRACT:
00566 case SIGN_EXTRACT:
00567
00568
00569
00570
00571
00572 if (MEM_P (XEXP (x, 0))
00573 && GET_CODE (XEXP (x, 1)) == CONST_INT
00574 && GET_CODE (XEXP (x, 2)) == CONST_INT
00575 && !mode_dependent_address_p (XEXP (XEXP (x, 0), 0))
00576 && !MEM_VOLATILE_P (XEXP (x, 0)))
00577 {
00578 enum machine_mode wanted_mode = VOIDmode;
00579 enum machine_mode is_mode = GET_MODE (XEXP (x, 0));
00580 int pos = INTVAL (XEXP (x, 2));
00581
00582 if (GET_CODE (x) == ZERO_EXTRACT)
00583 {
00584 enum machine_mode new_mode
00585 = mode_for_extraction (EP_extzv, 1);
00586 if (new_mode != MAX_MACHINE_MODE)
00587 wanted_mode = new_mode;
00588 }
00589 else if (GET_CODE (x) == SIGN_EXTRACT)
00590 {
00591 enum machine_mode new_mode
00592 = mode_for_extraction (EP_extv, 1);
00593 if (new_mode != MAX_MACHINE_MODE)
00594 wanted_mode = new_mode;
00595 }
00596
00597
00598 if (wanted_mode != VOIDmode
00599 && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
00600 {
00601 int offset = pos / BITS_PER_UNIT;
00602 rtx newmem;
00603
00604
00605
00606 if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
00607 offset =
00608 (GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (wanted_mode) -
00609 offset);
00610
00611 pos %= GET_MODE_BITSIZE (wanted_mode);
00612
00613 newmem = adjust_address_nv (XEXP (x, 0), wanted_mode, offset);
00614
00615 validate_change (object, &XEXP (x, 2), GEN_INT (pos), 1);
00616 validate_change (object, &XEXP (x, 0), newmem, 1);
00617 }
00618 }
00619
00620 break;
00621
00622 default:
00623 break;
00624 }
00625 }
00626
00627
00628
00629
00630
00631 int
00632 validate_replace_rtx_subexp (rtx from, rtx to, rtx insn, rtx *loc)
00633 {
00634 validate_replace_rtx_1 (loc, from, to, insn);
00635 return apply_change_group ();
00636 }
00637
00638
00639
00640
00641 int
00642 validate_replace_rtx (rtx from, rtx to, rtx insn)
00643 {
00644 validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
00645 return apply_change_group ();
00646 }
00647
00648
00649
00650 void
00651 validate_replace_rtx_group (rtx from, rtx to, rtx insn)
00652 {
00653 validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
00654 }
00655
00656
00657 struct validate_replace_src_data
00658 {
00659 rtx from;
00660 rtx to;
00661 rtx insn;
00662 };
00663
00664 static void
00665 validate_replace_src_1 (rtx *x, void *data)
00666 {
00667 struct validate_replace_src_data *d
00668 = (struct validate_replace_src_data *) data;
00669
00670 validate_replace_rtx_1 (x, d->from, d->to, d->insn);
00671 }
00672
00673
00674
00675
00676 void
00677 validate_replace_src_group (rtx from, rtx to, rtx insn)
00678 {
00679 struct validate_replace_src_data d;
00680
00681 d.from = from;
00682 d.to = to;
00683 d.insn = insn;
00684 note_uses (&PATTERN (insn), validate_replace_src_1, &d);
00685 }
00686
00687 #ifdef HAVE_cc0
00688
00689
00690
00691
00692 int
00693 next_insn_tests_no_inequality (rtx insn)
00694 {
00695 rtx next = next_cc0_user (insn);
00696
00697
00698 if (next == 0)
00699 return 0;
00700
00701 return (INSN_P (next)
00702 && ! inequality_comparisons_p (PATTERN (next)));
00703 }
00704 #endif
00705
00706
00707
00708
00709
00710
00711 static rtx *
00712 find_single_use_1 (rtx dest, rtx *loc)
00713 {
00714 rtx x = *loc;
00715 enum rtx_code code = GET_CODE (x);
00716 rtx *result = 0;
00717 rtx *this_result;
00718 int i;
00719 const char *fmt;
00720
00721 switch (code)
00722 {
00723 case CONST_INT:
00724 case CONST:
00725 case LABEL_REF:
00726 case SYMBOL_REF:
00727 case CONST_DOUBLE:
00728 case CONST_VECTOR:
00729 case CLOBBER:
00730 return 0;
00731
00732 case SET:
00733
00734
00735
00736
00737 if (GET_CODE (SET_DEST (x)) != CC0
00738 && GET_CODE (SET_DEST (x)) != PC
00739 && !REG_P (SET_DEST (x))
00740 && ! (GET_CODE (SET_DEST (x)) == SUBREG
00741 && REG_P (SUBREG_REG (SET_DEST (x)))
00742 && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
00743 + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
00744 == ((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
00745 + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))))
00746 break;
00747
00748 return find_single_use_1 (dest, &SET_SRC (x));
00749
00750 case MEM:
00751 case SUBREG:
00752 return find_single_use_1 (dest, &XEXP (x, 0));
00753
00754 default:
00755 break;
00756 }
00757
00758
00759
00760
00761 fmt = GET_RTX_FORMAT (code);
00762 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00763 {
00764 if (fmt[i] == 'e')
00765 {
00766 if (dest == XEXP (x, i)
00767 || (REG_P (dest) && REG_P (XEXP (x, i))
00768 && REGNO (dest) == REGNO (XEXP (x, i))))
00769 this_result = loc;
00770 else
00771 this_result = find_single_use_1 (dest, &XEXP (x, i));
00772
00773 if (result == 0)
00774 result = this_result;
00775 else if (this_result)
00776
00777 return 0;
00778 }
00779 else if (fmt[i] == 'E')
00780 {
00781 int j;
00782
00783 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
00784 {
00785 if (XVECEXP (x, i, j) == dest
00786 || (REG_P (dest)
00787 && REG_P (XVECEXP (x, i, j))
00788 && REGNO (XVECEXP (x, i, j)) == REGNO (dest)))
00789 this_result = loc;
00790 else
00791 this_result = find_single_use_1 (dest, &XVECEXP (x, i, j));
00792
00793 if (result == 0)
00794 result = this_result;
00795 else if (this_result)
00796 return 0;
00797 }
00798 }
00799 }
00800
00801 return result;
00802 }
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822 rtx *
00823 find_single_use (rtx dest, rtx insn, rtx *ploc)
00824 {
00825 rtx next;
00826 rtx *result;
00827 rtx link;
00828
00829 #ifdef HAVE_cc0
00830 if (dest == cc0_rtx)
00831 {
00832 next = NEXT_INSN (insn);
00833 if (next == 0
00834 || (!NONJUMP_INSN_P (next) && !JUMP_P (next)))
00835 return 0;
00836
00837 result = find_single_use_1 (dest, &PATTERN (next));
00838 if (result && ploc)
00839 *ploc = next;
00840 return result;
00841 }
00842 #endif
00843
00844 if (reload_completed || reload_in_progress || !REG_P (dest))
00845 return 0;
00846
00847 for (next = next_nonnote_insn (insn);
00848 next != 0 && !LABEL_P (next);
00849 next = next_nonnote_insn (next))
00850 if (INSN_P (next) && dead_or_set_p (next, dest))
00851 {
00852 for (link = LOG_LINKS (next); link; link = XEXP (link, 1))
00853 if (XEXP (link, 0) == insn)
00854 break;
00855
00856 if (link)
00857 {
00858 result = find_single_use_1 (dest, &PATTERN (next));
00859 if (ploc)
00860 *ploc = next;
00861 return result;
00862 }
00863 }
00864
00865 return 0;
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885 int
00886 general_operand (rtx op, enum machine_mode mode)
00887 {
00888 enum rtx_code code = GET_CODE (op);
00889
00890 if (mode == VOIDmode)
00891 mode = GET_MODE (op);
00892
00893
00894
00895 if (GET_MODE (op) == VOIDmode && mode != VOIDmode
00896 && GET_MODE_CLASS (mode) != MODE_INT
00897 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
00898 return 0;
00899
00900 if (GET_CODE (op) == CONST_INT
00901 && mode != VOIDmode
00902 && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
00903 return 0;
00904
00905 if (CONSTANT_P (op))
00906 return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode
00907 || mode == VOIDmode)
00908 && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
00909 && LEGITIMATE_CONSTANT_P (op));
00910
00911
00912
00913
00914 if (GET_MODE (op) != mode)
00915 return 0;
00916
00917 if (code == SUBREG)
00918 {
00919 rtx sub = SUBREG_REG (op);
00920
00921 #ifdef INSN_SCHEDULING
00922
00923
00924
00925
00926 if (!reload_completed && MEM_P (sub)
00927 && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (sub)))
00928 return 0;
00929 #endif
00930
00931
00932
00933
00934
00935
00936 if (!reload_completed && SUBREG_BYTE (op) != 0
00937 && MEM_P (sub))
00938 return 0;
00939
00940
00941
00942 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
00943 && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
00944 return 0;
00945
00946 op = sub;
00947 code = GET_CODE (op);
00948 }
00949
00950 if (code == REG)
00951
00952 return (REGNO (op) >= FIRST_PSEUDO_REGISTER
00953 || REGNO_REG_CLASS (REGNO (op)) != NO_REGS);
00954
00955 if (code == MEM)
00956 {
00957 rtx y = XEXP (op, 0);
00958
00959 if (! volatile_ok && MEM_VOLATILE_P (op))
00960 return 0;
00961
00962
00963 if (memory_address_p (GET_MODE (op), y))
00964 return 1;
00965 }
00966
00967 return 0;
00968 }
00969
00970
00971
00972
00973
00974
00975
00976 int
00977 address_operand (rtx op, enum machine_mode mode)
00978 {
00979 return memory_address_p (mode, op);
00980 }
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996 int
00997 register_operand (rtx op, enum machine_mode mode)
00998 {
00999 if (GET_MODE (op) != mode && mode != VOIDmode)
01000 return 0;
01001
01002 if (GET_CODE (op) == SUBREG)
01003 {
01004 rtx sub = SUBREG_REG (op);
01005
01006
01007
01008
01009
01010
01011
01012 if (! reload_completed && MEM_P (sub))
01013 return general_operand (op, mode);
01014
01015 #ifdef CANNOT_CHANGE_MODE_CLASS
01016 if (REG_P (sub)
01017 && REGNO (sub) < FIRST_PSEUDO_REGISTER
01018 && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
01019 && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
01020 && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
01021 return 0;
01022 #endif
01023
01024
01025
01026 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
01027 && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
01028 return 0;
01029
01030 op = sub;
01031 }
01032
01033
01034
01035 return (REG_P (op)
01036 && (REGNO (op) >= FIRST_PSEUDO_REGISTER
01037 || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
01038 }
01039
01040
01041
01042 int
01043 pmode_register_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01044 {
01045 return register_operand (op, Pmode);
01046 }
01047
01048
01049
01050
01051 int
01052 scratch_operand (rtx op, enum machine_mode mode)
01053 {
01054 if (GET_MODE (op) != mode && mode != VOIDmode)
01055 return 0;
01056
01057 return (GET_CODE (op) == SCRATCH
01058 || (REG_P (op)
01059 && REGNO (op) < FIRST_PSEUDO_REGISTER));
01060 }
01061
01062
01063
01064
01065
01066
01067 int
01068 immediate_operand (rtx op, enum machine_mode mode)
01069 {
01070
01071
01072 if (GET_MODE (op) == VOIDmode && mode != VOIDmode
01073 && GET_MODE_CLASS (mode) != MODE_INT
01074 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
01075 return 0;
01076
01077 if (GET_CODE (op) == CONST_INT
01078 && mode != VOIDmode
01079 && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
01080 return 0;
01081
01082 return (CONSTANT_P (op)
01083 && (GET_MODE (op) == mode || mode == VOIDmode
01084 || GET_MODE (op) == VOIDmode)
01085 && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
01086 && LEGITIMATE_CONSTANT_P (op));
01087 }
01088
01089
01090
01091 int
01092 const_int_operand (rtx op, enum machine_mode mode)
01093 {
01094 if (GET_CODE (op) != CONST_INT)
01095 return 0;
01096
01097 if (mode != VOIDmode
01098 && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
01099 return 0;
01100
01101 return 1;
01102 }
01103
01104
01105
01106
01107 int
01108 const_double_operand (rtx op, enum machine_mode mode)
01109 {
01110
01111
01112 if (GET_MODE (op) == VOIDmode && mode != VOIDmode
01113 && GET_MODE_CLASS (mode) != MODE_INT
01114 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
01115 return 0;
01116
01117 return ((GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT)
01118 && (mode == VOIDmode || GET_MODE (op) == mode
01119 || GET_MODE (op) == VOIDmode));
01120 }
01121
01122
01123
01124 int
01125 nonimmediate_operand (rtx op, enum machine_mode mode)
01126 {
01127 return (general_operand (op, mode) && ! CONSTANT_P (op));
01128 }
01129
01130
01131
01132 int
01133 nonmemory_operand (rtx op, enum machine_mode mode)
01134 {
01135 if (CONSTANT_P (op))
01136 {
01137
01138
01139 if (GET_MODE (op) == VOIDmode && mode != VOIDmode
01140 && GET_MODE_CLASS (mode) != MODE_INT
01141 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
01142 return 0;
01143
01144 if (GET_CODE (op) == CONST_INT
01145 && mode != VOIDmode
01146 && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
01147 return 0;
01148
01149 return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode
01150 || mode == VOIDmode)
01151 && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
01152 && LEGITIMATE_CONSTANT_P (op));
01153 }
01154
01155 if (GET_MODE (op) != mode && mode != VOIDmode)
01156 return 0;
01157
01158 if (GET_CODE (op) == SUBREG)
01159 {
01160
01161
01162
01163
01164
01165
01166 if (! reload_completed && MEM_P (SUBREG_REG (op)))
01167 return general_operand (op, mode);
01168 op = SUBREG_REG (op);
01169 }
01170
01171
01172
01173 return (REG_P (op)
01174 && (REGNO (op) >= FIRST_PSEUDO_REGISTER
01175 || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
01176 }
01177
01178
01179
01180
01181
01182
01183
01184 int
01185 push_operand (rtx op, enum machine_mode mode)
01186 {
01187 unsigned int rounded_size = GET_MODE_SIZE (mode);
01188
01189 #ifdef PUSH_ROUNDING
01190 rounded_size = PUSH_ROUNDING (rounded_size);
01191 #endif
01192
01193 if (!MEM_P (op))
01194 return 0;
01195
01196 if (mode != VOIDmode && GET_MODE (op) != mode)
01197 return 0;
01198
01199 op = XEXP (op, 0);
01200
01201 if (rounded_size == GET_MODE_SIZE (mode))
01202 {
01203 if (GET_CODE (op) != STACK_PUSH_CODE)
01204 return 0;
01205 }
01206 else
01207 {
01208 if (GET_CODE (op) != PRE_MODIFY
01209 || GET_CODE (XEXP (op, 1)) != PLUS
01210 || XEXP (XEXP (op, 1), 0) != XEXP (op, 0)
01211 || GET_CODE (XEXP (XEXP (op, 1), 1)) != CONST_INT
01212 #ifdef STACK_GROWS_DOWNWARD
01213 || INTVAL (XEXP (XEXP (op, 1), 1)) != - (int) rounded_size
01214 #else
01215 || INTVAL (XEXP (XEXP (op, 1), 1)) != (int) rounded_size
01216 #endif
01217 )
01218 return 0;
01219 }
01220
01221 return XEXP (op, 0) == stack_pointer_rtx;
01222 }
01223
01224
01225
01226
01227
01228
01229
01230 int
01231 pop_operand (rtx op, enum machine_mode mode)
01232 {
01233 if (!MEM_P (op))
01234 return 0;
01235
01236 if (mode != VOIDmode && GET_MODE (op) != mode)
01237 return 0;
01238
01239 op = XEXP (op, 0);
01240
01241 if (GET_CODE (op) != STACK_POP_CODE)
01242 return 0;
01243
01244 return XEXP (op, 0) == stack_pointer_rtx;
01245 }
01246
01247
01248
01249 int
01250 memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
01251 {
01252 GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
01253 return 0;
01254
01255 win:
01256 return 1;
01257 }
01258
01259
01260
01261
01262
01263
01264
01265 int
01266 memory_operand (rtx op, enum machine_mode mode)
01267 {
01268 rtx inner;
01269
01270 if (! reload_completed)
01271
01272
01273 return MEM_P (op) && general_operand (op, mode);
01274
01275 if (mode != VOIDmode && GET_MODE (op) != mode)
01276 return 0;
01277
01278 inner = op;
01279 if (GET_CODE (inner) == SUBREG)
01280 inner = SUBREG_REG (inner);
01281
01282 return (MEM_P (inner) && general_operand (op, mode));
01283 }
01284
01285
01286
01287
01288 int
01289 indirect_operand (rtx op, enum machine_mode mode)
01290 {
01291
01292 if (! reload_completed
01293 && GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op)))
01294 {
01295 int offset = SUBREG_BYTE (op);
01296 rtx inner = SUBREG_REG (op);
01297
01298 if (mode != VOIDmode && GET_MODE (op) != mode)
01299 return 0;
01300
01301
01302
01303
01304
01305
01306 return ((offset == 0 && general_operand (XEXP (inner, 0), Pmode))
01307 || (GET_CODE (XEXP (inner, 0)) == PLUS
01308 && GET_CODE (XEXP (XEXP (inner, 0), 1)) == CONST_INT
01309 && INTVAL (XEXP (XEXP (inner, 0), 1)) == -offset
01310 && general_operand (XEXP (XEXP (inner, 0), 0), Pmode)));
01311 }
01312
01313 return (MEM_P (op)
01314 && memory_operand (op, mode)
01315 && general_operand (XEXP (op, 0), Pmode));
01316 }
01317
01318
01319
01320
01321 int
01322 comparison_operator (rtx op, enum machine_mode mode)
01323 {
01324 return ((mode == VOIDmode || GET_MODE (op) == mode)
01325 && COMPARISON_P (op));
01326 }
01327
01328
01329
01330
01331
01332 int
01333 asm_noperands (rtx body)
01334 {
01335 switch (GET_CODE (body))
01336 {
01337 case ASM_OPERANDS:
01338
01339 return ASM_OPERANDS_INPUT_LENGTH (body);
01340 case SET:
01341 if (GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
01342
01343 return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body)) + 1;
01344 else
01345 return -1;
01346 case PARALLEL:
01347 if (GET_CODE (XVECEXP (body, 0, 0)) == SET
01348 && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS)
01349 {
01350
01351
01352 int i;
01353 int n_sets;
01354
01355
01356 for (i = XVECLEN (body, 0); i > 0; i--)
01357 {
01358 if (GET_CODE (XVECEXP (body, 0, i - 1)) == SET)
01359 break;
01360 if (GET_CODE (XVECEXP (body, 0, i - 1)) != CLOBBER)
01361 return -1;
01362 }
01363
01364
01365 n_sets = i;
01366
01367
01368
01369
01370 for (i = 0; i < n_sets; i++)
01371 {
01372 rtx elt = XVECEXP (body, 0, i);
01373 if (GET_CODE (elt) != SET)
01374 return -1;
01375 if (GET_CODE (SET_SRC (elt)) != ASM_OPERANDS)
01376 return -1;
01377
01378
01379 if (ASM_OPERANDS_INPUT_VEC (SET_SRC (elt))
01380 != ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (body, 0, 0))))
01381 return -1;
01382 }
01383 return (ASM_OPERANDS_INPUT_LENGTH (SET_SRC (XVECEXP (body, 0, 0)))
01384 + n_sets);
01385 }
01386 else if (GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
01387 {
01388
01389
01390 int i;
01391
01392
01393 for (i = XVECLEN (body, 0) - 1; i > 0; i--)
01394 if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
01395 return -1;
01396
01397 return ASM_OPERANDS_INPUT_LENGTH (XVECEXP (body, 0, 0));
01398 }
01399 else
01400 return -1;
01401 default:
01402 return -1;
01403 }
01404 }
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416 const char *
01417 decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
01418 const char **constraints, enum machine_mode *modes)
01419 {
01420 int i;
01421 int noperands;
01422 const char *template = 0;
01423
01424 if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
01425 {
01426 rtx asmop = SET_SRC (body);
01427
01428
01429 noperands = ASM_OPERANDS_INPUT_LENGTH (asmop) + 1;
01430
01431 for (i = 1; i < noperands; i++)
01432 {
01433 if (operand_locs)
01434 operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i - 1);
01435 if (operands)
01436 operands[i] = ASM_OPERANDS_INPUT (asmop, i - 1);
01437 if (constraints)
01438 constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i - 1);
01439 if (modes)
01440 modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i - 1);
01441 }
01442
01443
01444
01445 if (operands)
01446 operands[0] = SET_DEST (body);
01447 if (operand_locs)
01448 operand_locs[0] = &SET_DEST (body);
01449 if (constraints)
01450 constraints[0] = ASM_OPERANDS_OUTPUT_CONSTRAINT (asmop);
01451 if (modes)
01452 modes[0] = GET_MODE (SET_DEST (body));
01453 template = ASM_OPERANDS_TEMPLATE (asmop);
01454 }
01455 else if (GET_CODE (body) == ASM_OPERANDS)
01456 {
01457 rtx asmop = body;
01458
01459
01460 noperands = ASM_OPERANDS_INPUT_LENGTH (asmop);
01461
01462
01463
01464 for (i = 0; i < noperands; i++)
01465 {
01466 if (operand_locs)
01467 operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i);
01468 if (operands)
01469 operands[i] = ASM_OPERANDS_INPUT (asmop, i);
01470 if (constraints)
01471 constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
01472 if (modes)
01473 modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
01474 }
01475 template = ASM_OPERANDS_TEMPLATE (asmop);
01476 }
01477 else if (GET_CODE (body) == PARALLEL
01478 && GET_CODE (XVECEXP (body, 0, 0)) == SET
01479 && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS)
01480 {
01481 rtx asmop = SET_SRC (XVECEXP (body, 0, 0));
01482 int nparallel = XVECLEN (body, 0);
01483 int nin = ASM_OPERANDS_INPUT_LENGTH (asmop);
01484 int nout = 0;
01485
01486
01487
01488
01489
01490 for (i = 0; i < nparallel; i++)
01491 {
01492 if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
01493 break;
01494
01495 if (operands)
01496 operands[i] = SET_DEST (XVECEXP (body, 0, i));
01497 if (operand_locs)
01498 operand_locs[i] = &SET_DEST (XVECEXP (body, 0, i));
01499 if (constraints)
01500 constraints[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 1);
01501 if (modes)
01502 modes[i] = GET_MODE (SET_DEST (XVECEXP (body, 0, i)));
01503 nout++;
01504 }
01505
01506 for (i = 0; i < nin; i++)
01507 {
01508 if (operand_locs)
01509 operand_locs[i + nout] = &ASM_OPERANDS_INPUT (asmop, i);
01510 if (operands)
01511 operands[i + nout] = ASM_OPERANDS_INPUT (asmop, i);
01512 if (constraints)
01513 constraints[i + nout] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
01514 if (modes)
01515 modes[i + nout] = ASM_OPERANDS_INPUT_MODE (asmop, i);
01516 }
01517
01518 template = ASM_OPERANDS_TEMPLATE (asmop);
01519 }
01520 else if (GET_CODE (body) == PARALLEL
01521 && GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
01522 {
01523
01524
01525 rtx asmop = XVECEXP (body, 0, 0);
01526 int nin = ASM_OPERANDS_INPUT_LENGTH (asmop);
01527
01528 for (i = 0; i < nin; i++)
01529 {
01530 if (operand_locs)
01531 operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i);
01532 if (operands)
01533 operands[i] = ASM_OPERANDS_INPUT (asmop, i);
01534 if (constraints)
01535 constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
01536 if (modes)
01537 modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
01538 }
01539
01540 template = ASM_OPERANDS_TEMPLATE (asmop);
01541 }
01542
01543 return template;
01544 }
01545
01546
01547
01548
01549 int
01550 asm_operand_ok (rtx op, const char *constraint)
01551 {
01552 int result = 0;
01553
01554
01555 gcc_assert (!reload_completed);
01556
01557 while (*constraint)
01558 {
01559 char c = *constraint;
01560 int len;
01561 switch (c)
01562 {
01563 case ',':
01564 constraint++;
01565 continue;
01566 case '=':
01567 case '+':
01568 case '*':
01569 case '%':
01570 case '!':
01571 case '#':
01572 case '&':
01573 case '?':
01574 break;
01575
01576 case '0': case '1': case '2': case '3': case '4':
01577 case '5': case '6': case '7': case '8': case '9':
01578
01579
01580
01581
01582 do
01583 constraint++;
01584 while (ISDIGIT (*constraint));
01585 if (! result)
01586 result = -1;
01587 continue;
01588
01589 case 'p':
01590 if (address_operand (op, VOIDmode))
01591 result = 1;
01592 break;
01593
01594 case 'm':
01595 case 'V':
01596 if (memory_operand (op, VOIDmode))
01597 result = 1;
01598 break;
01599
01600 case 'o':
01601 if (offsettable_nonstrict_memref_p (op))
01602 result = 1;
01603 break;
01604
01605 case '<':
01606
01607
01608
01609
01610
01611
01612
01613 if (MEM_P (op)
01614 && (1
01615 || GET_CODE (XEXP (op, 0)) == PRE_DEC
01616 || GET_CODE (XEXP (op, 0)) == POST_DEC))
01617 result = 1;
01618 break;
01619
01620 case '>':
01621 if (MEM_P (op)
01622 && (1
01623 || GET_CODE (XEXP (op, 0)) == PRE_INC
01624 || GET_CODE (XEXP (op, 0)) == POST_INC))
01625 result = 1;
01626 break;
01627
01628 case 'E':
01629 case 'F':
01630 if (GET_CODE (op) == CONST_DOUBLE
01631 || (GET_CODE (op) == CONST_VECTOR
01632 && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
01633 result = 1;
01634 break;
01635
01636 case 'G':
01637 if (GET_CODE (op) == CONST_DOUBLE
01638 && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'G', constraint))
01639 result = 1;
01640 break;
01641 case 'H':
01642 if (GET_CODE (op) == CONST_DOUBLE
01643 && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'H', constraint))
01644 result = 1;
01645 break;
01646
01647 case 's':
01648 if (GET_CODE (op) == CONST_INT
01649 || (GET_CODE (op) == CONST_DOUBLE
01650 && GET_MODE (op) == VOIDmode))
01651 break;
01652
01653
01654 case 'i':
01655 if (CONSTANT_P (op) && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op)))
01656 result = 1;
01657 break;
01658
01659 case 'n':
01660 if (GET_CODE (op) == CONST_INT
01661 || (GET_CODE (op) == CONST_DOUBLE
01662 && GET_MODE (op) == VOIDmode))
01663 result = 1;
01664 break;
01665
01666 case 'I':
01667 if (GET_CODE (op) == CONST_INT
01668 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'I', constraint))
01669 result = 1;
01670 break;
01671 case 'J':
01672 if (GET_CODE (op) == CONST_INT
01673 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'J', constraint))
01674 result = 1;
01675 break;
01676 case 'K':
01677 if (GET_CODE (op) == CONST_INT
01678 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', constraint))
01679 result = 1;
01680 break;
01681 case 'L':
01682 if (GET_CODE (op) == CONST_INT
01683 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'L', constraint))
01684 result = 1;
01685 break;
01686 case 'M':
01687 if (GET_CODE (op) == CONST_INT
01688 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'M', constraint))
01689 result = 1;
01690 break;
01691 case 'N':
01692 if (GET_CODE (op) == CONST_INT
01693 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'N', constraint))
01694 result = 1;
01695 break;
01696 case 'O':
01697 if (GET_CODE (op) == CONST_INT
01698 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'O', constraint))
01699 result = 1;
01700 break;
01701 case 'P':
01702 if (GET_CODE (op) == CONST_INT
01703 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'P', constraint))
01704 result = 1;
01705 break;
01706
01707 case 'X':
01708 result = 1;
01709 break;
01710
01711 case 'g':
01712 if (general_operand (op, VOIDmode))
01713 result = 1;
01714 break;
01715
01716 default:
01717
01718
01719 if (REG_CLASS_FROM_CONSTRAINT (c, constraint) != NO_REGS)
01720 {
01721 case 'r':
01722 if (GET_MODE (op) == BLKmode)
01723 break;
01724 if (register_operand (op, VOIDmode))
01725 result = 1;
01726 }
01727 #ifdef EXTRA_CONSTRAINT_STR
01728 else if (EXTRA_CONSTRAINT_STR (op, c, constraint))
01729 result = 1;
01730 else if (EXTRA_MEMORY_CONSTRAINT (c, constraint)
01731
01732 && memory_operand (op, VOIDmode))
01733 result = 1;
01734 else if (EXTRA_ADDRESS_CONSTRAINT (c, constraint)
01735
01736 && address_operand (op, VOIDmode))
01737 result = 1;
01738 #endif
01739 break;
01740 }
01741 len = CONSTRAINT_LEN (c, constraint);
01742 do
01743 constraint++;
01744 while (--len && *constraint);
01745 if (len)
01746 return 0;
01747 }
01748
01749 return result;
01750 }
01751
01752
01753
01754
01755
01756 rtx *
01757 find_constant_term_loc (rtx *p)
01758 {
01759 rtx *tem;
01760 enum rtx_code code = GET_CODE (*p);
01761
01762
01763
01764 if (code == CONST_INT || code == SYMBOL_REF || code == LABEL_REF
01765 || code == CONST)
01766 return p;
01767
01768
01769
01770 if (GET_CODE (*p) != PLUS)
01771 return 0;
01772
01773
01774
01775 if (XEXP (*p, 0) && CONSTANT_P (XEXP (*p, 0))
01776 && XEXP (*p, 1) && CONSTANT_P (XEXP (*p, 1)))
01777 return p;
01778
01779
01780
01781 if (XEXP (*p, 0) != 0)
01782 {
01783 tem = find_constant_term_loc (&XEXP (*p, 0));
01784 if (tem != 0)
01785 return tem;
01786 }
01787
01788 if (XEXP (*p, 1) != 0)
01789 {
01790 tem = find_constant_term_loc (&XEXP (*p, 1));
01791 if (tem != 0)
01792 return tem;
01793 }
01794
01795 return 0;
01796 }
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809 int
01810 offsettable_memref_p (rtx op)
01811 {
01812 return ((MEM_P (op))
01813 && offsettable_address_p (1, GET_MODE (op), XEXP (op, 0)));
01814 }
01815
01816
01817
01818
01819 int
01820 offsettable_nonstrict_memref_p (rtx op)
01821 {
01822 return ((MEM_P (op))
01823 && offsettable_address_p (0, GET_MODE (op), XEXP (op, 0)));
01824 }
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836 int
01837 offsettable_address_p (int strictp, enum machine_mode mode, rtx y)
01838 {
01839 enum rtx_code ycode = GET_CODE (y);
01840 rtx z;
01841 rtx y1 = y;
01842 rtx *y2;
01843 int (*addressp) (enum machine_mode, rtx) =
01844 (strictp ? strict_memory_address_p : memory_address_p);
01845 unsigned int mode_sz = GET_MODE_SIZE (mode);
01846
01847 if (CONSTANT_ADDRESS_P (y))
01848 return 1;
01849
01850
01851
01852
01853 if (mode_dependent_address_p (y))
01854 return 0;
01855
01856
01857
01858
01859
01860 if (mode_sz == 0)
01861 mode_sz = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
01862
01863
01864
01865
01866 if ((ycode == PLUS) && (y2 = find_constant_term_loc (&y1)))
01867 {
01868 int good;
01869
01870 y1 = *y2;
01871 *y2 = plus_constant (*y2, mode_sz - 1);
01872
01873
01874 good = (*addressp) (QImode, y);
01875
01876
01877 *y2 = y1;
01878 return good;
01879 }
01880
01881 if (GET_RTX_CLASS (ycode) == RTX_AUTOINC)
01882 return 0;
01883
01884
01885
01886
01887
01888
01889 if (GET_CODE (y) == LO_SUM
01890 && mode != BLKmode
01891 && mode_sz <= GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT)
01892 z = gen_rtx_LO_SUM (GET_MODE (y), XEXP (y, 0),
01893 plus_constant (XEXP (y, 1), mode_sz - 1));
01894 else
01895 z = plus_constant (y, mode_sz - 1);
01896
01897
01898
01899 return (*addressp) (QImode, z);
01900 }
01901
01902
01903
01904
01905
01906
01907
01908 int
01909 mode_dependent_address_p (rtx addr ATTRIBUTE_UNUSED )
01910 {
01911 GO_IF_MODE_DEPENDENT_ADDRESS (addr, win);
01912 return 0;
01913
01914 win: ATTRIBUTE_UNUSED_LABEL
01915 return 1;
01916 }
01917
01918
01919
01920
01921
01922 void
01923 extract_insn_cached (rtx insn)
01924 {
01925 if (recog_data.insn == insn && INSN_CODE (insn) >= 0)
01926 return;
01927 extract_insn (insn);
01928 recog_data.insn = insn;
01929 }
01930
01931
01932 void
01933 extract_constrain_insn_cached (rtx insn)
01934 {
01935 extract_insn_cached (insn);
01936 if (which_alternative == -1
01937 && !constrain_operands (reload_completed))
01938 fatal_insn_not_found (insn);
01939 }
01940
01941 int
01942 constrain_operands_cached (int strict)
01943 {
01944 if (which_alternative == -1)
01945 return constrain_operands (strict);
01946 else
01947 return 1;
01948 }
01949
01950
01951
01952 void
01953 extract_insn (rtx insn)
01954 {
01955 int i;
01956 int icode;
01957 int noperands;
01958 rtx body = PATTERN (insn);
01959
01960 recog_data.insn = NULL;
01961 recog_data.n_operands = 0;
01962 recog_data.n_alternatives = 0;
01963 recog_data.n_dups = 0;
01964 which_alternative = -1;
01965
01966 switch (GET_CODE (body))
01967 {
01968 case USE:
01969 case CLOBBER:
01970 case ASM_INPUT:
01971 case ADDR_VEC:
01972 case ADDR_DIFF_VEC:
01973 return;
01974
01975 case SET:
01976 if (GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
01977 goto asm_insn;
01978 else
01979 goto normal_insn;
01980 case PARALLEL:
01981 if ((GET_CODE (XVECEXP (body, 0, 0)) == SET
01982 && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS)
01983 || GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
01984 goto asm_insn;
01985 else
01986 goto normal_insn;
01987 case ASM_OPERANDS:
01988 asm_insn:
01989 recog_data.n_operands = noperands = asm_noperands (body);
01990 if (noperands >= 0)
01991 {
01992
01993
01994
01995 gcc_assert (noperands <= MAX_RECOG_OPERANDS);
01996
01997
01998 decode_asm_operands (body, recog_data.operand,
01999 recog_data.operand_loc,
02000 recog_data.constraints,
02001 recog_data.operand_mode);
02002 if (noperands > 0)
02003 {
02004 const char *p = recog_data.constraints[0];
02005 recog_data.n_alternatives = 1;
02006 while (*p)
02007 recog_data.n_alternatives += (*p++ == ',');
02008 }
02009 break;
02010 }
02011 fatal_insn_not_found (insn);
02012
02013 default:
02014 normal_insn:
02015
02016
02017
02018 icode = recog_memoized (insn);
02019 if (icode < 0)
02020 fatal_insn_not_found (insn);
02021
02022 recog_data.n_operands = noperands = insn_data[icode].n_operands;
02023 recog_data.n_alternatives = insn_data[icode].n_alternatives;
02024 recog_data.n_dups = insn_data[icode].n_dups;
02025
02026 insn_extract (insn);
02027
02028 for (i = 0; i < noperands; i++)
02029 {
02030 recog_data.constraints[i] = insn_data[icode].operand[i].constraint;
02031 recog_data.operand_mode[i] = insn_data[icode].operand[i].mode;
02032
02033 if (recog_data.operand_mode[i] == VOIDmode)
02034 recog_data.operand_mode[i] = GET_MODE (recog_data.operand[i]);
02035 }
02036 }
02037 for (i = 0; i < noperands; i++)
02038 recog_data.operand_type[i]
02039 = (recog_data.constraints[i][0] == '=' ? OP_OUT
02040 : recog_data.constraints[i][0] == '+' ? OP_INOUT
02041 : OP_IN);
02042
02043 gcc_assert (recog_data.n_alternatives <= MAX_RECOG_ALTERNATIVES);
02044 }
02045
02046
02047
02048
02049 void
02050 preprocess_constraints (void)
02051 {
02052 int i;
02053
02054 for (i = 0; i < recog_data.n_operands; i++)
02055 memset (recog_op_alt[i], 0, (recog_data.n_alternatives
02056 * sizeof (struct operand_alternative)));
02057
02058 for (i = 0; i < recog_data.n_operands; i++)
02059 {
02060 int j;
02061 struct operand_alternative *op_alt;
02062 const char *p = recog_data.constraints[i];
02063
02064 op_alt = recog_op_alt[i];
02065
02066 for (j = 0; j < recog_data.n_alternatives; j++)
02067 {
02068 op_alt[j].cl = NO_REGS;
02069 op_alt[j].constraint = p;
02070 op_alt[j].matches = -1;
02071 op_alt[j].matched = -1;
02072
02073 if (*p == '\0' || *p == ',')
02074 {
02075 op_alt[j].anything_ok = 1;
02076 continue;
02077 }
02078
02079 for (;;)
02080 {
02081 char c = *p;
02082 if (c == '#')
02083 do
02084 c = *++p;
02085 while (c != ',' && c != '\0');
02086 if (c == ',' || c == '\0')
02087 {
02088 p++;
02089 break;
02090 }
02091
02092 switch (c)
02093 {
02094 case '=': case '+': case '*': case '%':
02095 case 'E': case 'F': case 'G': case 'H':
02096 case 's': case 'i': case 'n':
02097 case 'I': case 'J': case 'K': case 'L':
02098 case 'M': case 'N': case 'O': case 'P':
02099
02100 break;
02101
02102 case '?':
02103 op_alt[j].reject += 6;
02104 break;
02105 case '!':
02106 op_alt[j].reject += 600;
02107 break;
02108 case '&':
02109 op_alt[j].earlyclobber = 1;
02110 break;
02111
02112 case '0': case '1': case '2': case '3': case '4':
02113 case '5': case '6': case '7': case '8': case '9':
02114 {
02115 char *end;
02116 op_alt[j].matches = strtoul (p, &end, 10);
02117 recog_op_alt[op_alt[j].matches][j].matched = i;
02118 p = end;
02119 }
02120 continue;
02121
02122 case 'm':
02123 op_alt[j].memory_ok = 1;
02124 break;
02125 case '<':
02126 op_alt[j].decmem_ok = 1;
02127 break;
02128 case '>':
02129 op_alt[j].incmem_ok = 1;
02130 break;
02131 case 'V':
02132 op_alt[j].nonoffmem_ok = 1;
02133 break;
02134 case 'o':
02135 op_alt[j].offmem_ok = 1;
02136 break;
02137 case 'X':
02138 op_alt[j].anything_ok = 1;
02139 break;
02140
02141 case 'p':
02142 op_alt[j].is_address = 1;
02143 op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl]
02144 [(int) MODE_BASE_REG_CLASS (VOIDmode)];
02145 break;
02146
02147 case 'g':
02148 case 'r':
02149 op_alt[j].cl =
02150 reg_class_subunion[(int) op_alt[j].cl][(int) GENERAL_REGS];
02151 break;
02152
02153 default:
02154 if (EXTRA_MEMORY_CONSTRAINT (c, p))
02155 {
02156 op_alt[j].memory_ok = 1;
02157 break;
02158 }
02159 if (EXTRA_ADDRESS_CONSTRAINT (c, p))
02160 {
02161 op_alt[j].is_address = 1;
02162 op_alt[j].cl
02163 = (reg_class_subunion
02164 [(int) op_alt[j].cl]
02165 [(int) MODE_BASE_REG_CLASS (VOIDmode)]);
02166 break;
02167 }
02168
02169 op_alt[j].cl
02170 = (reg_class_subunion
02171 [(int) op_alt[j].cl]
02172 [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
02173 break;
02174 }
02175 p += CONSTRAINT_LEN (c, p);
02176 }
02177 }
02178 }
02179 }
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208 struct funny_match
02209 {
02210 int this, other;
02211 };
02212
02213 int
02214 constrain_operands (int strict)
02215 {
02216 const char *constraints[MAX_RECOG_OPERANDS];
02217 int matching_operands[MAX_RECOG_OPERANDS];
02218 int earlyclobber[MAX_RECOG_OPERANDS];
02219 int c;
02220
02221 struct funny_match funny_match[MAX_RECOG_OPERANDS];
02222 int funny_match_index;
02223
02224 which_alternative = 0;
02225 if (recog_data.n_operands == 0 || recog_data.n_alternatives == 0)
02226 return 1;
02227
02228 for (c = 0; c < recog_data.n_operands; c++)
02229 {
02230 constraints[c] = recog_data.constraints[c];
02231 matching_operands[c] = -1;
02232 }
02233
02234 do
02235 {
02236 int seen_earlyclobber_at = -1;
02237 int opno;
02238 int lose = 0;
02239 funny_match_index = 0;
02240
02241 for (opno = 0; opno < recog_data.n_operands; opno++)
02242 {
02243 rtx op = recog_data.operand[opno];
02244 enum machine_mode mode = GET_MODE (op);
02245 const char *p = constraints[opno];
02246 int offset = 0;
02247 int win = 0;
02248 int val;
02249 int len;
02250
02251 earlyclobber[opno] = 0;
02252
02253
02254
02255 if (UNARY_P (op))
02256 op = XEXP (op, 0);
02257
02258 if (GET_CODE (op) == SUBREG)
02259 {
02260 if (REG_P (SUBREG_REG (op))
02261 && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
02262 offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
02263 GET_MODE (SUBREG_REG (op)),
02264 SUBREG_BYTE (op),
02265 GET_MODE (op));
02266 op = SUBREG_REG (op);
02267 }
02268
02269
02270
02271 if (*p == 0 || *p == ',')
02272 win = 1;
02273
02274 do
02275 switch (c = *p, len = CONSTRAINT_LEN (c, p), c)
02276 {
02277 case '\0':
02278 len = 0;
02279 break;
02280 case ',':
02281 c = '\0';
02282 break;
02283
02284 case '?': case '!': case '*': case '%':
02285 case '=': case '+':
02286 break;
02287
02288 case '#':
02289
02290
02291 do
02292 p++;
02293 while (*p && *p != ',');
02294 len = 0;
02295 break;
02296
02297 case '&':
02298 earlyclobber[opno] = 1;
02299 if (seen_earlyclobber_at < 0)
02300 seen_earlyclobber_at = opno;
02301 break;
02302
02303 case '0': case '1': case '2': case '3': case '4':
02304 case '5': case '6': case '7': case '8': case '9':
02305 {
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315 char *end;
02316 int match;
02317
02318 match = strtoul (p, &end, 10);
02319 p = end;
02320
02321 if (strict < 0)
02322 val = 1;
02323 else
02324 {
02325 rtx op1 = recog_data.operand[match];
02326 rtx op2 = recog_data.operand[opno];
02327
02328
02329
02330 if (UNARY_P (op1))
02331 op1 = XEXP (op1, 0);
02332 if (UNARY_P (op2))
02333 op2 = XEXP (op2, 0);
02334
02335 val = operands_match_p (op1, op2);
02336 }
02337
02338 matching_operands[opno] = match;
02339 matching_operands[match] = opno;
02340
02341 if (val != 0)
02342 win = 1;
02343
02344
02345
02346
02347 if (val == 2 && strict > 0)
02348 {
02349 funny_match[funny_match_index].this = opno;
02350 funny_match[funny_match_index++].other = match;
02351 }
02352 }
02353 len = 0;
02354 break;
02355
02356 case 'p':
02357
02358
02359
02360
02361 if (strict <= 0
02362 || (strict_memory_address_p (recog_data.operand_mode[opno],
02363 op)))
02364 win = 1;
02365 break;
02366
02367
02368
02369 case 'g':
02370
02371
02372 if (strict < 0
02373 || GENERAL_REGS == ALL_REGS
02374 || !REG_P (op)
02375 || (reload_in_progress
02376 && REGNO (op) >= FIRST_PSEUDO_REGISTER)
02377 || reg_fits_class_p (op, GENERAL_REGS, offset, mode))
02378 win = 1;
02379 break;
02380
02381 case 'X':
02382
02383
02384
02385 win = 1;
02386 break;
02387
02388 case 'm':
02389
02390
02391 if (MEM_P (op))
02392 {
02393 if (strict > 0
02394 && !strict_memory_address_p (GET_MODE (op),
02395 XEXP (op, 0)))
02396 break;
02397 if (strict == 0
02398 && !memory_address_p (GET_MODE (op), XEXP (op, 0)))
02399 break;
02400 win = 1;
02401 }
02402
02403 else if (strict < 0 && CONSTANT_P (op))
02404 win = 1;
02405
02406 else if (reload_in_progress && REG_P (op)
02407 && REGNO (op) >= FIRST_PSEUDO_REGISTER)
02408 win = 1;
02409 break;
02410
02411 case '<':
02412 if (MEM_P (op)
02413 && (GET_CODE (XEXP (op, 0)) == PRE_DEC
02414 || GET_CODE (XEXP (op, 0)) == POST_DEC))
02415 win = 1;
02416 break;
02417
02418 case '>':
02419 if (MEM_P (op)
02420 && (GET_CODE (XEXP (op, 0)) == PRE_INC
02421 || GET_CODE (XEXP (op, 0)) == POST_INC))
02422 win = 1;
02423 break;
02424
02425 case 'E':
02426 case 'F':
02427 if (GET_CODE (op) == CONST_DOUBLE
02428 || (GET_CODE (op) == CONST_VECTOR
02429 && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
02430 win = 1;
02431 break;
02432
02433 case 'G':
02434 case 'H':
02435 if (GET_CODE (op) == CONST_DOUBLE
02436 && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
02437 win = 1;
02438 break;
02439
02440 case 's':
02441 if (GET_CODE (op) == CONST_INT
02442 || (GET_CODE (op) == CONST_DOUBLE
02443 && GET_MODE (op) == VOIDmode))
02444 break;
02445 case 'i':
02446 if (CONSTANT_P (op))
02447 win = 1;
02448 break;
02449
02450 case 'n':
02451 if (GET_CODE (op) == CONST_INT
02452 || (GET_CODE (op) == CONST_DOUBLE
02453 && GET_MODE (op) == VOIDmode))
02454 win = 1;
02455 break;
02456
02457 case 'I':
02458 case 'J':
02459 case 'K':
02460 case 'L':
02461 case 'M':
02462 case 'N':
02463 case 'O':
02464 case 'P':
02465 if (GET_CODE (op) == CONST_INT
02466 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
02467 win = 1;
02468 break;
02469
02470 case 'V':
02471 if (MEM_P (op)
02472 && ((strict > 0 && ! offsettable_memref_p (op))
02473 || (strict < 0
02474 && !(CONSTANT_P (op) || MEM_P (op)))
02475 || (reload_in_progress
02476 && !(REG_P (op)
02477 && REGNO (op) >= FIRST_PSEUDO_REGISTER))))
02478 win = 1;
02479 break;
02480
02481 case 'o':
02482 if ((strict > 0 && offsettable_memref_p (op))
02483 || (strict == 0 && offsettable_nonstrict_memref_p (op))
02484
02485 || (strict < 0
02486 && (CONSTANT_P (op) || MEM_P (op)))
02487
02488 || (reload_in_progress && REG_P (op)
02489 && REGNO (op) >= FIRST_PSEUDO_REGISTER))
02490 win = 1;
02491 break;
02492
02493 default:
02494 {
02495 enum reg_class cl;
02496
02497 cl = (c == 'r'
02498 ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
02499 if (cl != NO_REGS)
02500 {
02501 if (strict < 0
02502 || (strict == 0
02503 && REG_P (op)
02504 && REGNO (op) >= FIRST_PSEUDO_REGISTER)
02505 || (strict == 0 && GET_CODE (op) == SCRATCH)
02506 || (REG_P (op)
02507 && reg_fits_class_p (op, cl, offset, mode)))
02508 win = 1;
02509 }
02510 #ifdef EXTRA_CONSTRAINT_STR
02511 else if (EXTRA_CONSTRAINT_STR (op, c, p))
02512 win = 1;
02513
02514 else if (EXTRA_MEMORY_CONSTRAINT (c, p)
02515
02516 && ((strict < 0 && MEM_P (op))
02517
02518
02519 || (strict < 0 && CONSTANT_P (op))
02520
02521 || (reload_in_progress && REG_P (op)
02522 && REGNO (op) >= FIRST_PSEUDO_REGISTER)))
02523 win = 1;
02524 else if (EXTRA_ADDRESS_CONSTRAINT (c, p)
02525
02526 && strict < 0)
02527 win = 1;
02528 #endif
02529 break;
02530 }
02531 }
02532 while (p += len, c);
02533
02534 constraints[opno] = p;
02535
02536
02537 if (! win)
02538 lose = 1;
02539 }
02540
02541
02542 if (! lose)
02543 {
02544 int opno, eopno;
02545
02546
02547
02548
02549 if (strict > 0 && seen_earlyclobber_at >= 0)
02550 for (eopno = seen_earlyclobber_at;
02551 eopno < recog_data.n_operands;
02552 eopno++)
02553
02554
02555
02556 if (earlyclobber[eopno]
02557 && REG_P (recog_data.operand[eopno]))
02558 for (opno = 0; opno < recog_data.n_operands; opno++)
02559 if ((MEM_P (recog_data.operand[opno])
02560 || recog_data.operand_type[opno] != OP_OUT)
02561 && opno != eopno
02562
02563 && *recog_data.constraints[opno] != 0
02564 && ! (matching_operands[opno] == eopno
02565 && operands_match_p (recog_data.operand[opno],
02566 recog_data.operand[eopno]))
02567 && ! safe_from_earlyclobber (recog_data.operand[opno],
02568 recog_data.operand[eopno]))
02569 lose = 1;
02570
02571 if (! lose)
02572 {
02573 while (--funny_match_index >= 0)
02574 {
02575 recog_data.operand[funny_match[funny_match_index].other]
02576 = recog_data.operand[funny_match[funny_match_index].this];
02577 }
02578
02579 return 1;
02580 }
02581 }
02582
02583 which_alternative++;
02584 }
02585 while (which_alternative < recog_data.n_alternatives);
02586
02587 which_alternative = -1;
02588
02589
02590 if (strict == 0)
02591 return constrain_operands (-1);
02592 else
02593 return 0;
02594 }
02595
02596
02597
02598
02599
02600
02601 int
02602 reg_fits_class_p (rtx operand, enum reg_class cl, int offset,
02603 enum machine_mode mode)
02604 {
02605 int regno = REGNO (operand);
02606 if (regno < FIRST_PSEUDO_REGISTER
02607 && TEST_HARD_REG_BIT (reg_class_contents[(int) cl],
02608 regno + offset))
02609 {
02610 int sr;
02611 regno += offset;
02612 for (sr = hard_regno_nregs[regno][mode] - 1;
02613 sr > 0; sr--)
02614 if (! TEST_HARD_REG_BIT (reg_class_contents[(int) cl],
02615 regno + sr))
02616 break;
02617 return sr == 0;
02618 }
02619
02620 return 0;
02621 }
02622
02623
02624
02625
02626
02627 static rtx
02628 split_insn (rtx insn)
02629 {
02630
02631 rtx first = PREV_INSN (insn);
02632 rtx last = try_split (PATTERN (insn), insn, 1);
02633
02634 if (last == insn)
02635 return NULL_RTX;
02636
02637
02638 SET_INSN_DELETED (insn);
02639
02640
02641
02642 if (reload_completed && first != last)
02643 {
02644 first = NEXT_INSN (first);
02645 for (;;)
02646 {
02647 if (INSN_P (first))
02648 cleanup_subreg_operands (first);
02649 if (first == last)
02650 break;
02651 first = NEXT_INSN (first);
02652 }
02653 }
02654 return last;
02655 }
02656
02657
02658
02659 void
02660 split_all_insns (int upd_life)
02661 {
02662 sbitmap blocks;
02663 bool changed;
02664 basic_block bb;
02665
02666 blocks = sbitmap_alloc (last_basic_block);
02667 sbitmap_zero (blocks);
02668 changed = false;
02669
02670 FOR_EACH_BB_REVERSE (bb)
02671 {
02672 rtx insn, next;
02673 bool finish = false;
02674
02675 for (insn = BB_HEAD (bb); !finish ; insn = next)
02676 {
02677
02678
02679 next = NEXT_INSN (insn);
02680 finish = (insn == BB_END (bb));
02681 if (INSN_P (insn))
02682 {
02683 rtx set = single_set (insn);
02684
02685
02686
02687
02688 if (set && set_noop_p (set))
02689 {
02690
02691
02692
02693
02694
02695 if (reload_completed)
02696 {
02697
02698
02699 if (find_reg_note (insn, REG_UNUSED, NULL_RTX))
02700 {
02701 SET_BIT (blocks, bb->index);
02702 changed = true;
02703 }
02704
02705 delete_insn_and_edges (insn);
02706 }
02707 }
02708 else
02709 {
02710 rtx last = split_insn (insn);
02711 if (last)
02712 {
02713
02714
02715
02716
02717 while (BARRIER_P (last))
02718 last = PREV_INSN (last);
02719 SET_BIT (blocks, bb->index);
02720 changed = true;
02721 }
02722 }
02723 }
02724 }
02725 }
02726
02727 if (changed)
02728 {
02729 int old_last_basic_block = last_basic_block;
02730
02731 find_many_sub_basic_blocks (blocks);
02732
02733 if (old_last_basic_block != last_basic_block && upd_life)
02734 blocks = sbitmap_resize (blocks, last_basic_block, 1);
02735 }
02736
02737 if (changed && upd_life)
02738 update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
02739 PROP_DEATH_NOTES);
02740
02741 #ifdef ENABLE_CHECKING
02742 verify_flow_info ();
02743 #endif
02744
02745 sbitmap_free (blocks);
02746 }
02747
02748
02749
02750
02751 void
02752 split_all_insns_noflow (void)
02753 {
02754 rtx next, insn;
02755
02756 for (insn = get_insns (); insn; insn = next)
02757 {
02758 next = NEXT_INSN (insn);
02759 if (INSN_P (insn))
02760 {
02761
02762
02763
02764 rtx set = single_set (insn);
02765 if (set && set_noop_p (set))
02766 {
02767
02768
02769
02770
02771
02772
02773
02774 if (reload_completed)
02775 delete_insn_and_edges (insn);
02776 }
02777 else
02778 split_insn (insn);
02779 }
02780 }
02781 }
02782
02783 #ifdef HAVE_peephole2
02784 struct peep2_insn_data
02785 {
02786 rtx insn;
02787 regset live_before;
02788 };
02789
02790 static struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
02791 static int peep2_current;
02792
02793
02794
02795
02796 #define PEEP2_EOB pc_rtx
02797
02798
02799
02800
02801
02802 rtx
02803 peep2_next_insn (int n)
02804 {
02805 gcc_assert (n < MAX_INSNS_PER_PEEP2 + 1);
02806
02807 n += peep2_current;
02808 if (n >= MAX_INSNS_PER_PEEP2 + 1)
02809 n -= MAX_INSNS_PER_PEEP2 + 1;
02810
02811 if (peep2_insn_data[n].insn == PEEP2_EOB)
02812 return NULL_RTX;
02813 return peep2_insn_data[n].insn;
02814 }
02815
02816
02817
02818
02819 int
02820 peep2_regno_dead_p (int ofs, int regno)
02821 {
02822 gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
02823
02824 ofs += peep2_current;
02825 if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
02826 ofs -= MAX_INSNS_PER_PEEP2 + 1;
02827
02828 gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
02829
02830 return ! REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno);
02831 }
02832
02833
02834
02835 int
02836 peep2_reg_dead_p (int ofs, rtx reg)
02837 {
02838 int regno, n;
02839
02840 gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
02841
02842 ofs += peep2_current;
02843 if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
02844 ofs -= MAX_INSNS_PER_PEEP2 + 1;
02845
02846 gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
02847
02848 regno = REGNO (reg);
02849 n = hard_regno_nregs[regno][GET_MODE (reg)];
02850 while (--n >= 0)
02851 if (REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno + n))
02852 return 0;
02853 return 1;
02854 }
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867 rtx
02868 peep2_find_free_register (int from, int to, const char *class_str,
02869 enum machine_mode mode, HARD_REG_SET *reg_set)
02870 {
02871 static int search_ofs;
02872 enum reg_class cl;
02873 HARD_REG_SET live;
02874 int i;
02875
02876 gcc_assert (from < MAX_INSNS_PER_PEEP2 + 1);
02877 gcc_assert (to < MAX_INSNS_PER_PEEP2 + 1);
02878
02879 from += peep2_current;
02880 if (from >= MAX_INSNS_PER_PEEP2 + 1)
02881 from -= MAX_INSNS_PER_PEEP2 + 1;
02882 to += peep2_current;
02883 if (to >= MAX_INSNS_PER_PEEP2 + 1)
02884 to -= MAX_INSNS_PER_PEEP2 + 1;
02885
02886 gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
02887 REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
02888
02889 while (from != to)
02890 {
02891 HARD_REG_SET this_live;
02892
02893 if (++from >= MAX_INSNS_PER_PEEP2 + 1)
02894 from = 0;
02895 gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
02896 REG_SET_TO_HARD_REG_SET (this_live, peep2_insn_data[from].live_before);
02897 IOR_HARD_REG_SET (live, this_live);
02898 }
02899
02900 cl = (class_str[0] == 'r' ? GENERAL_REGS
02901 : REG_CLASS_FROM_CONSTRAINT (class_str[0], class_str));
02902
02903 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
02904 {
02905 int raw_regno, regno, success, j;
02906
02907
02908 raw_regno = search_ofs + i;
02909 if (raw_regno >= FIRST_PSEUDO_REGISTER)
02910 raw_regno -= FIRST_PSEUDO_REGISTER;
02911 #ifdef REG_ALLOC_ORDER
02912 regno = reg_alloc_order[raw_regno];
02913 #else
02914 regno = raw_regno;
02915 #endif
02916
02917
02918 if (fixed_regs[regno])
02919 continue;
02920
02921 if (! TEST_HARD_REG_BIT (reg_class_contents[cl], regno))
02922 continue;
02923
02924 if (! HARD_REGNO_MODE_OK (regno, mode))
02925 continue;
02926
02927 if (! call_used_regs[regno] && ! regs_ever_live[regno])
02928 continue;
02929
02930 if ((regno == FRAME_POINTER_REGNUM || regno == HARD_FRAME_POINTER_REGNUM)
02931 && (! reload_completed || frame_pointer_needed))
02932 continue;
02933
02934 success = 1;
02935 for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--)
02936 {
02937 if (TEST_HARD_REG_BIT (*reg_set, regno + j)
02938 || TEST_HARD_REG_BIT (live, regno + j))
02939 {
02940 success = 0;
02941 break;
02942 }
02943 }
02944 if (success)
02945 {
02946 for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--)
02947 SET_HARD_REG_BIT (*reg_set, regno + j);
02948
02949
02950 if (++raw_regno >= FIRST_PSEUDO_REGISTER)
02951 raw_regno = 0;
02952 search_ofs = raw_regno;
02953
02954 return gen_rtx_REG (mode, regno);
02955 }
02956 }
02957
02958 search_ofs = 0;
02959 return NULL_RTX;
02960 }
02961
02962
02963
02964 void
02965 peephole2_optimize (FILE *dump_file ATTRIBUTE_UNUSED)
02966 {
02967 rtx insn, prev;
02968 regset live;
02969 int i;
02970 basic_block bb;
02971 #ifdef HAVE_conditional_execution
02972 sbitmap blocks;
02973 bool changed;
02974 #endif
02975 bool do_cleanup_cfg = false;
02976 bool do_global_life_update = false;
02977 bool do_rebuild_jump_labels = false;
02978
02979
02980 for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
02981 peep2_insn_data[i].live_before = ALLOC_REG_SET (®_obstack);
02982 live = ALLOC_REG_SET (®_obstack);
02983
02984 #ifdef HAVE_conditional_execution
02985 blocks = sbitmap_alloc (last_basic_block);
02986 sbitmap_zero (blocks);
02987 changed = false;
02988 #else
02989 count_or_remove_death_notes (NULL, 1);
02990 #endif
02991
02992 FOR_EACH_BB_REVERSE (bb)
02993 {
02994 struct propagate_block_info *pbi;
02995 reg_set_iterator rsi;
02996 unsigned int j;
02997
02998
02999 for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
03000 peep2_insn_data[i].insn = NULL_RTX;
03001
03002
03003 peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
03004 peep2_current = MAX_INSNS_PER_PEEP2;
03005
03006
03007 COPY_REG_SET (live, bb->global_live_at_end);
03008 COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
03009
03010 #ifdef HAVE_conditional_execution
03011 pbi = init_propagate_block_info (bb, live, NULL, NULL, 0);
03012 #else
03013 pbi = init_propagate_block_info (bb, live, NULL, NULL, PROP_DEATH_NOTES);
03014 #endif
03015
03016 for (insn = BB_END (bb); ; insn = prev)
03017 {
03018 prev = PREV_INSN (insn);
03019 if (INSN_P (insn))
03020 {
03021 rtx try, before_try, x;
03022 int match_len;
03023 rtx note;
03024 bool was_call = false;
03025
03026
03027 if (--peep2_current < 0)
03028 peep2_current = MAX_INSNS_PER_PEEP2;
03029 peep2_insn_data[peep2_current].insn = insn;
03030 propagate_one_insn (pbi, insn);
03031 COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
03032
03033
03034 try = peephole2_insns (PATTERN (insn), insn, &match_len);
03035 if (try != NULL)
03036 {
03037
03038
03039
03040 for (i = 0; i <= match_len; ++i)
03041 {
03042 int j;
03043 rtx old_insn, new_insn, note;
03044
03045 j = i + peep2_current;
03046 if (j >= MAX_INSNS_PER_PEEP2 + 1)
03047 j -= MAX_INSNS_PER_PEEP2 + 1;
03048 old_insn = peep2_insn_data[j].insn;
03049 if (!CALL_P (old_insn))
03050 continue;
03051 was_call = true;
03052
03053 new_insn = try;
03054 while (new_insn != NULL_RTX)
03055 {
03056 if (CALL_P (new_insn))
03057 break;
03058 new_insn = NEXT_INSN (new_insn);
03059 }
03060
03061 gcc_assert (new_insn != NULL_RTX);
03062
03063 CALL_INSN_FUNCTION_USAGE (new_insn)
03064 = CALL_INSN_FUNCTION_USAGE (old_insn);
03065
03066 for (note = REG_NOTES (old_insn);
03067 note;
03068 note = XEXP (note, 1))
03069 switch (REG_NOTE_KIND (note))
03070 {
03071 case REG_NORETURN:
03072 case REG_SETJMP:
03073 case REG_ALWAYS_RETURN:
03074 REG_NOTES (new_insn)
03075 = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
03076 XEXP (note, 0),
03077 REG_NOTES (new_insn));
03078 default:
03079
03080 break;
03081 }
03082
03083
03084 while (++i <= match_len)
03085 {
03086 j = i + peep2_current;
03087 if (j >= MAX_INSNS_PER_PEEP2 + 1)
03088 j -= MAX_INSNS_PER_PEEP2 + 1;
03089 old_insn = peep2_insn_data[j].insn;
03090 gcc_assert (!CALL_P (old_insn));
03091 }
03092 break;
03093 }
03094
03095 i = match_len + peep2_current;
03096 if (i >= MAX_INSNS_PER_PEEP2 + 1)
03097 i -= MAX_INSNS_PER_PEEP2 + 1;
03098
03099 note = find_reg_note (peep2_insn_data[i].insn,
03100 REG_EH_REGION, NULL_RTX);
03101
03102
03103 try = emit_insn_after_setloc (try, peep2_insn_data[i].insn,
03104 INSN_LOCATOR (peep2_insn_data[i].insn));
03105 before_try = PREV_INSN (insn);
03106 delete_insn_chain (insn, peep2_insn_data[i].insn);
03107
03108
03109 if (note || (was_call && nonlocal_goto_handler_labels))
03110 {
03111 edge eh_edge;
03112 edge_iterator ei;
03113
03114 FOR_EACH_EDGE (eh_edge, ei, bb->succs)
03115 if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
03116 break;
03117
03118 for (x = try ; x != before_try ; x = PREV_INSN (x))
03119 if (CALL_P (x)
03120 || (flag_non_call_exceptions
03121 && may_trap_p (PATTERN (x))
03122 && !find_reg_note (x, REG_EH_REGION, NULL)))
03123 {
03124 if (note)
03125 REG_NOTES (x)
03126 = gen_rtx_EXPR_LIST (REG_EH_REGION,
03127 XEXP (note, 0),
03128 REG_NOTES (x));
03129
03130 if (x != BB_END (bb) && eh_edge)
03131 {
03132 edge nfte, nehe;
03133 int flags;
03134
03135 nfte = split_block (bb, x);
03136 flags = (eh_edge->flags
03137 & (EDGE_EH | EDGE_ABNORMAL));
03138 if (CALL_P (x))
03139 flags |= EDGE_ABNORMAL_CALL;
03140 nehe = make_edge (nfte->src, eh_edge->dest,
03141 flags);
03142
03143 nehe->probability = eh_edge->probability;
03144 nfte->probability
03145 = REG_BR_PROB_BASE - nehe->probability;
03146
03147 do_cleanup_cfg |= purge_dead_edges (nfte->dest);
03148 #ifdef HAVE_conditional_execution
03149 SET_BIT (blocks, nfte->dest->index);
03150 changed = true;
03151 #endif
03152 bb = nfte->src;
03153 eh_edge = nehe;
03154 }
03155 }
03156
03157
03158
03159 do_cleanup_cfg |= purge_dead_edges (bb);
03160 }
03161
03162 #ifdef HAVE_conditional_execution
03163
03164
03165
03166
03167
03168 SET_BIT (blocks, bb->index);
03169 changed = true;
03170
03171 for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
03172 peep2_insn_data[i].insn = NULL_RTX;
03173 peep2_insn_data[peep2_current].insn = PEEP2_EOB;
03174 #else
03175
03176
03177 if (++i >= MAX_INSNS_PER_PEEP2 + 1)
03178 i = 0;
03179 COPY_REG_SET (live, peep2_insn_data[i].live_before);
03180
03181
03182 x = try;
03183 do
03184 {
03185 if (INSN_P (x))
03186 {
03187 if (--i < 0)
03188 i = MAX_INSNS_PER_PEEP2;
03189 peep2_insn_data[i].insn = x;
03190 propagate_one_insn (pbi, x);
03191 COPY_REG_SET (peep2_insn_data[i].live_before, live);
03192 }
03193 x = PREV_INSN (x);
03194 }
03195 while (x != prev);
03196
03197
03198
03199
03200 peep2_current = i;
03201 #endif
03202
03203
03204
03205 for (x = try; x != before_try; x = PREV_INSN (x))
03206 if (JUMP_P (x))
03207 {
03208 do_rebuild_jump_labels = true;
03209 break;
03210 }
03211 }
03212 }
03213
03214 if (insn == BB_HEAD (bb))
03215 break;
03216 }
03217
03218
03219
03220 EXECUTE_IF_AND_COMPL_IN_BITMAP (bb->global_live_at_start, live,
03221 0, j, rsi)
03222 {
03223 do_global_life_update = true;
03224 break;
03225 }
03226
03227 free_propagate_block_info (pbi);
03228 }
03229
03230 for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
03231 FREE_REG_SET (peep2_insn_data[i].live_before);
03232 FREE_REG_SET (live);
03233
03234 if (do_rebuild_jump_labels)
03235 rebuild_jump_labels (get_insns ());
03236
03237
03238
03239
03240 if (do_cleanup_cfg)
03241 {
03242 cleanup_cfg (0);
03243 do_global_life_update = true;
03244 }
03245 if (do_global_life_update)
03246 update_life_info (0, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
03247 #ifdef HAVE_conditional_execution
03248 else
03249 {
03250 count_or_remove_death_notes (blocks, 1);
03251 update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
03252 }
03253 sbitmap_free (blocks);
03254 #endif
03255 }
03256 #endif
03257
03258
03259
03260
03261
03262
03263
03264
03265 int
03266 store_data_bypass_p (rtx out_insn, rtx in_insn)
03267 {
03268 rtx out_set, in_set;
03269
03270 in_set = single_set (in_insn);
03271 gcc_assert (in_set);
03272
03273 if (!MEM_P (SET_DEST (in_set)))
03274 return false;
03275
03276 out_set = single_set (out_insn);
03277 if (out_set)
03278 {
03279 if (reg_mentioned_p (SET_DEST (out_set), SET_DEST (in_set)))
03280 return false;
03281 }
03282 else
03283 {
03284 rtx out_pat;
03285 int i;
03286
03287 out_pat = PATTERN (out_insn);
03288 gcc_assert (GET_CODE (out_pat) == PARALLEL);
03289
03290 for (i = 0; i < XVECLEN (out_pat, 0); i++)
03291 {
03292 rtx exp = XVECEXP (out_pat, 0, i);
03293
03294 if (GET_CODE (exp) == CLOBBER)
03295 continue;
03296
03297 gcc_assert (GET_CODE (exp) == SET);
03298
03299 if (reg_mentioned_p (SET_DEST (exp), SET_DEST (in_set)))
03300 return false;
03301 }
03302 }
03303
03304 return true;
03305 }
03306
03307
03308
03309
03310
03311
03312 int
03313 if_test_bypass_p (rtx out_insn, rtx in_insn)
03314 {
03315 rtx out_set, in_set;
03316
03317 in_set = single_set (in_insn);
03318 if (! in_set)
03319 {
03320 gcc_assert (JUMP_P (in_insn) || CALL_P (in_insn));
03321 return false;
03322 }
03323
03324 if (GET_CODE (SET_SRC (in_set)) != IF_THEN_ELSE)
03325 return false;
03326 in_set = SET_SRC (in_set);
03327
03328 out_set = single_set (out_insn);
03329 if (out_set)
03330 {
03331 if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
03332 || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
03333 return false;
03334 }
03335 else
03336 {
03337 rtx out_pat;
03338 int i;
03339
03340 out_pat = PATTERN (out_insn);
03341 gcc_assert (GET_CODE (out_pat) == PARALLEL);
03342
03343 for (i = 0; i < XVECLEN (out_pat, 0); i++)
03344 {
03345 rtx exp = XVECEXP (out_pat, 0, i);
03346
03347 if (GET_CODE (exp) == CLOBBER)
03348 continue;
03349
03350 gcc_assert (GET_CODE (exp) == SET);
03351
03352 if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
03353 || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
03354 return false;
03355 }
03356 }
03357
03358 return true;
03359 }