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