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