00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "bconfig.h"
00054 #include "system.h"
00055 #include "coretypes.h"
00056 #include "tm.h"
00057 #include "rtl.h"
00058 #include "errors.h"
00059 #include "gensupport.h"
00060
00061 #define OUTPUT_LABEL(INDENT_STRING, LABEL_NUMBER) \
00062 printf("%sL%d: ATTRIBUTE_UNUSED_LABEL\n", (INDENT_STRING), (LABEL_NUMBER))
00063
00064
00065 static char **insn_name_ptr = 0;
00066 static int insn_name_ptr_size = 0;
00067
00068
00069
00070
00071
00072 struct decision_head
00073 {
00074 struct decision *first;
00075 struct decision *last;
00076 };
00077
00078
00079
00080
00081
00082 struct decision_test
00083 {
00084
00085 struct decision_test *next;
00086
00087
00088 enum decision_type
00089 {
00090 DT_mode, DT_code, DT_veclen,
00091 DT_elt_zero_int, DT_elt_one_int, DT_elt_zero_wide, DT_elt_zero_wide_safe,
00092 DT_const_int,
00093 DT_veclen_ge, DT_dup, DT_pred, DT_c_test,
00094 DT_accept_op, DT_accept_insn
00095 } type;
00096
00097 union
00098 {
00099 enum machine_mode mode;
00100 RTX_CODE code;
00101
00102 struct
00103 {
00104 const char *name;
00105 const struct pred_data *data;
00106
00107 enum machine_mode mode;
00108 } pred;
00109
00110 const char *c_test;
00111 int veclen;
00112 int dup;
00113 HOST_WIDE_INT intval;
00114 int opno;
00115
00116 struct {
00117 int code_number;
00118 int lineno;
00119 int num_clobbers_to_add;
00120 } insn;
00121 } u;
00122 };
00123
00124
00125
00126 struct decision
00127 {
00128 struct decision_head success;
00129 struct decision *next;
00130 struct decision *prev;
00131 struct decision *afterward;
00132
00133
00134 const char *position;
00135
00136 struct decision_test *tests;
00137
00138 int number;
00139 int subroutine_number;
00140 int need_label;
00141 };
00142
00143 #define SUBROUTINE_THRESHOLD 100
00144
00145 static int next_subroutine_number;
00146
00147
00148
00149
00150
00151 enum routine_type {
00152 RECOG, SPLIT, PEEPHOLE2
00153 };
00154
00155 #define IS_SPLIT(X) ((X) != RECOG)
00156
00157
00158
00159 static int next_number;
00160
00161
00162
00163 static int next_insn_code;
00164
00165
00166
00167
00168 static int max_depth;
00169
00170
00171 static int pattern_lineno;
00172
00173
00174 static int error_count;
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 #define N 0
00213 #define Y 1
00214 #define I 2
00215
00216 #define TRISTATE_AND(a,b) \
00217 ((a) == I ? ((b) == N ? N : I) : \
00218 (b) == I ? ((a) == N ? N : I) : \
00219 (a) && (b))
00220
00221 #define TRISTATE_OR(a,b) \
00222 ((a) == I ? ((b) == Y ? Y : I) : \
00223 (b) == I ? ((a) == Y ? Y : I) : \
00224 (a) || (b))
00225
00226 #define TRISTATE_NOT(a) \
00227 ((a) == I ? I : !(a))
00228
00229
00230 static char did_you_mean_codes[NUM_RTX_CODE];
00231
00232
00233
00234 static void
00235 compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
00236 {
00237 char op0_codes[NUM_RTX_CODE];
00238 char op1_codes[NUM_RTX_CODE];
00239 char op2_codes[NUM_RTX_CODE];
00240 int i;
00241
00242 switch (GET_CODE (exp))
00243 {
00244 case AND:
00245 compute_predicate_codes (XEXP (exp, 0), op0_codes);
00246 compute_predicate_codes (XEXP (exp, 1), op1_codes);
00247 for (i = 0; i < NUM_RTX_CODE; i++)
00248 codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
00249 break;
00250
00251 case IOR:
00252 compute_predicate_codes (XEXP (exp, 0), op0_codes);
00253 compute_predicate_codes (XEXP (exp, 1), op1_codes);
00254 for (i = 0; i < NUM_RTX_CODE; i++)
00255 codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
00256 break;
00257 case NOT:
00258 compute_predicate_codes (XEXP (exp, 0), op0_codes);
00259 for (i = 0; i < NUM_RTX_CODE; i++)
00260 codes[i] = TRISTATE_NOT (op0_codes[i]);
00261 break;
00262
00263 case IF_THEN_ELSE:
00264
00265 compute_predicate_codes (XEXP (exp, 0), op0_codes);
00266 compute_predicate_codes (XEXP (exp, 1), op1_codes);
00267 compute_predicate_codes (XEXP (exp, 2), op2_codes);
00268 for (i = 0; i < NUM_RTX_CODE; i++)
00269 codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
00270 TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
00271 op2_codes[i]));
00272 break;
00273
00274 case MATCH_CODE:
00275
00276 memset (codes, N, NUM_RTX_CODE);
00277 {
00278 const char *next_code = XSTR (exp, 0);
00279 const char *code;
00280
00281 if (*next_code == '\0')
00282 {
00283 message_with_line (pattern_lineno, "empty match_code expression");
00284 error_count++;
00285 break;
00286 }
00287
00288 while ((code = scan_comma_elt (&next_code)) != 0)
00289 {
00290 size_t n = next_code - code;
00291 int found_it = 0;
00292
00293 for (i = 0; i < NUM_RTX_CODE; i++)
00294 if (!strncmp (code, GET_RTX_NAME (i), n)
00295 && GET_RTX_NAME (i)[n] == '\0')
00296 {
00297 codes[i] = Y;
00298 found_it = 1;
00299 break;
00300 }
00301 if (!found_it)
00302 {
00303 message_with_line (pattern_lineno, "match_code \"%.*s\" matches nothing",
00304 (int) n, code);
00305 error_count ++;
00306 for (i = 0; i < NUM_RTX_CODE; i++)
00307 if (!strncasecmp (code, GET_RTX_NAME (i), n)
00308 && GET_RTX_NAME (i)[n] == '\0'
00309 && !did_you_mean_codes[i])
00310 {
00311 did_you_mean_codes[i] = 1;
00312 message_with_line (pattern_lineno, "(did you mean \"%s\"?)", GET_RTX_NAME (i));
00313 }
00314 }
00315
00316 }
00317 }
00318 break;
00319
00320 case MATCH_OPERAND:
00321
00322
00323 {
00324 struct pred_data *p = lookup_predicate (XSTR (exp, 1));
00325 if (!p)
00326 {
00327 message_with_line (pattern_lineno,
00328 "reference to unknown predicate '%s'",
00329 XSTR (exp, 1));
00330 error_count++;
00331 break;
00332 }
00333 for (i = 0; i < NUM_RTX_CODE; i++)
00334 codes[i] = p->codes[i] ? I : N;
00335 }
00336 break;
00337
00338
00339 case MATCH_TEST:
00340
00341 memset (codes, I, NUM_RTX_CODE);
00342 break;
00343
00344 default:
00345 message_with_line (pattern_lineno,
00346 "'%s' cannot be used in a define_predicate expression",
00347 GET_RTX_NAME (GET_CODE (exp)));
00348 error_count++;
00349 memset (codes, I, NUM_RTX_CODE);
00350 break;
00351 }
00352 }
00353
00354 #undef TRISTATE_OR
00355 #undef TRISTATE_AND
00356 #undef TRISTATE_NOT
00357
00358
00359
00360 static void
00361 process_define_predicate (rtx desc)
00362 {
00363 struct pred_data *pred = xcalloc (sizeof (struct pred_data), 1);
00364 char codes[NUM_RTX_CODE];
00365 bool seen_one = false;
00366 int i;
00367
00368 pred->name = XSTR (desc, 0);
00369 if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
00370 pred->special = 1;
00371
00372 compute_predicate_codes (XEXP (desc, 1), codes);
00373
00374 for (i = 0; i < NUM_RTX_CODE; i++)
00375 if (codes[i] != N)
00376 {
00377 pred->codes[i] = true;
00378 if (GET_RTX_CLASS (i) != RTX_CONST_OBJ)
00379 pred->allows_non_const = true;
00380 if (i != REG
00381 && i != SUBREG
00382 && i != MEM
00383 && i != CONCAT
00384 && i != PARALLEL
00385 && i != STRICT_LOW_PART)
00386 pred->allows_non_lvalue = true;
00387
00388 if (seen_one)
00389 pred->singleton = UNKNOWN;
00390 else
00391 {
00392 pred->singleton = i;
00393 seen_one = true;
00394 }
00395 }
00396 add_predicate (pred);
00397 }
00398 #undef I
00399 #undef N
00400 #undef Y
00401
00402
00403 static struct decision *new_decision
00404 (const char *, struct decision_head *);
00405 static struct decision_test *new_decision_test
00406 (enum decision_type, struct decision_test ***);
00407 static rtx find_operand
00408 (rtx, int, rtx);
00409 static rtx find_matching_operand
00410 (rtx, int);
00411 static void validate_pattern
00412 (rtx, rtx, rtx, int);
00413 static struct decision *add_to_sequence
00414 (rtx, struct decision_head *, const char *, enum routine_type, int);
00415
00416 static int maybe_both_true_2
00417 (struct decision_test *, struct decision_test *);
00418 static int maybe_both_true_1
00419 (struct decision_test *, struct decision_test *);
00420 static int maybe_both_true
00421 (struct decision *, struct decision *, int);
00422
00423 static int nodes_identical_1
00424 (struct decision_test *, struct decision_test *);
00425 static int nodes_identical
00426 (struct decision *, struct decision *);
00427 static void merge_accept_insn
00428 (struct decision *, struct decision *);
00429 static void merge_trees
00430 (struct decision_head *, struct decision_head *);
00431
00432 static void factor_tests
00433 (struct decision_head *);
00434 static void simplify_tests
00435 (struct decision_head *);
00436 static int break_out_subroutines
00437 (struct decision_head *, int);
00438 static void find_afterward
00439 (struct decision_head *, struct decision *);
00440
00441 static void change_state
00442 (const char *, const char *, struct decision *, const char *);
00443 static void print_code
00444 (enum rtx_code);
00445 static void write_afterward
00446 (struct decision *, struct decision *, const char *);
00447 static struct decision *write_switch
00448 (struct decision *, int);
00449 static void write_cond
00450 (struct decision_test *, int, enum routine_type);
00451 static void write_action
00452 (struct decision *, struct decision_test *, int, int,
00453 struct decision *, enum routine_type);
00454 static int is_unconditional
00455 (struct decision_test *, enum routine_type);
00456 static int write_node
00457 (struct decision *, int, enum routine_type);
00458 static void write_tree_1
00459 (struct decision_head *, int, enum routine_type);
00460 static void write_tree
00461 (struct decision_head *, const char *, enum routine_type, int);
00462 static void write_subroutine
00463 (struct decision_head *, enum routine_type);
00464 static void write_subroutines
00465 (struct decision_head *, enum routine_type);
00466 static void write_header
00467 (void);
00468
00469 static struct decision_head make_insn_sequence
00470 (rtx, enum routine_type);
00471 static void process_tree
00472 (struct decision_head *, enum routine_type);
00473
00474 static void record_insn_name
00475 (int, const char *);
00476
00477 static void debug_decision_0
00478 (struct decision *, int, int);
00479 static void debug_decision_1
00480 (struct decision *, int);
00481 static void debug_decision_2
00482 (struct decision_test *);
00483 extern void debug_decision
00484 (struct decision *);
00485 extern void debug_decision_list
00486 (struct decision *);
00487
00488
00489
00490 static struct decision *
00491 new_decision (const char *position, struct decision_head *last)
00492 {
00493 struct decision *new = xcalloc (1, sizeof (struct decision));
00494
00495 new->success = *last;
00496 new->position = xstrdup (position);
00497 new->number = next_number++;
00498
00499 last->first = last->last = new;
00500 return new;
00501 }
00502
00503
00504
00505 static struct decision_test *
00506 new_decision_test (enum decision_type type, struct decision_test ***pplace)
00507 {
00508 struct decision_test **place = *pplace;
00509 struct decision_test *test;
00510
00511 test = xmalloc (sizeof (*test));
00512 test->next = *place;
00513 test->type = type;
00514 *place = test;
00515
00516 place = &test->next;
00517 *pplace = place;
00518
00519 return test;
00520 }
00521
00522
00523
00524 static rtx
00525 find_operand (rtx pattern, int n, rtx stop)
00526 {
00527 const char *fmt;
00528 RTX_CODE code;
00529 int i, j, len;
00530 rtx r;
00531
00532 if (pattern == stop)
00533 return stop;
00534
00535 code = GET_CODE (pattern);
00536 if ((code == MATCH_SCRATCH
00537 || code == MATCH_OPERAND
00538 || code == MATCH_OPERATOR
00539 || code == MATCH_PARALLEL)
00540 && XINT (pattern, 0) == n)
00541 return pattern;
00542
00543 fmt = GET_RTX_FORMAT (code);
00544 len = GET_RTX_LENGTH (code);
00545 for (i = 0; i < len; i++)
00546 {
00547 switch (fmt[i])
00548 {
00549 case 'e': case 'u':
00550 if ((r = find_operand (XEXP (pattern, i), n, stop)) != NULL_RTX)
00551 return r;
00552 break;
00553
00554 case 'V':
00555 if (! XVEC (pattern, i))
00556 break;
00557
00558
00559 case 'E':
00560 for (j = 0; j < XVECLEN (pattern, i); j++)
00561 if ((r = find_operand (XVECEXP (pattern, i, j), n, stop))
00562 != NULL_RTX)
00563 return r;
00564 break;
00565
00566 case 'i': case 'w': case '0': case 's':
00567 break;
00568
00569 default:
00570 gcc_unreachable ();
00571 }
00572 }
00573
00574 return NULL;
00575 }
00576
00577
00578
00579
00580 static rtx
00581 find_matching_operand (rtx pattern, int n)
00582 {
00583 const char *fmt;
00584 RTX_CODE code;
00585 int i, j, len;
00586 rtx r;
00587
00588 code = GET_CODE (pattern);
00589 if (code == MATCH_OPERAND
00590 && (XSTR (pattern, 2)[0] == '0' + n
00591 || (XSTR (pattern, 2)[0] == '%'
00592 && XSTR (pattern, 2)[1] == '0' + n)))
00593 return pattern;
00594
00595 fmt = GET_RTX_FORMAT (code);
00596 len = GET_RTX_LENGTH (code);
00597 for (i = 0; i < len; i++)
00598 {
00599 switch (fmt[i])
00600 {
00601 case 'e': case 'u':
00602 if ((r = find_matching_operand (XEXP (pattern, i), n)))
00603 return r;
00604 break;
00605
00606 case 'V':
00607 if (! XVEC (pattern, i))
00608 break;
00609
00610
00611 case 'E':
00612 for (j = 0; j < XVECLEN (pattern, i); j++)
00613 if ((r = find_matching_operand (XVECEXP (pattern, i, j), n)))
00614 return r;
00615 break;
00616
00617 case 'i': case 'w': case '0': case 's':
00618 break;
00619
00620 default:
00621 gcc_unreachable ();
00622 }
00623 }
00624
00625 return NULL;
00626 }
00627
00628
00629
00630
00631
00632
00633 static void
00634 validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
00635 {
00636 const char *fmt;
00637 RTX_CODE code;
00638 size_t i, len;
00639 int j;
00640
00641 code = GET_CODE (pattern);
00642 switch (code)
00643 {
00644 case MATCH_SCRATCH:
00645 return;
00646 case MATCH_DUP:
00647 case MATCH_OP_DUP:
00648 case MATCH_PAR_DUP:
00649 if (find_operand (insn, XINT (pattern, 0), pattern) == pattern)
00650 {
00651 message_with_line (pattern_lineno,
00652 "operand %i duplicated before defined",
00653 XINT (pattern, 0));
00654 error_count++;
00655 }
00656 break;
00657 case MATCH_OPERAND:
00658 case MATCH_OPERATOR:
00659 {
00660 const char *pred_name = XSTR (pattern, 1);
00661 const struct pred_data *pred;
00662 const char *c_test;
00663
00664 if (GET_CODE (insn) == DEFINE_INSN)
00665 c_test = XSTR (insn, 2);
00666 else
00667 c_test = XSTR (insn, 1);
00668
00669 if (pred_name[0] != 0)
00670 {
00671 pred = lookup_predicate (pred_name);
00672 if (!pred)
00673 message_with_line (pattern_lineno,
00674 "warning: unknown predicate '%s'",
00675 pred_name);
00676 }
00677 else
00678 pred = 0;
00679
00680 if (code == MATCH_OPERAND)
00681 {
00682 const char constraints0 = XSTR (pattern, 2)[0];
00683
00684
00685
00686
00687
00688 if (GET_CODE (insn) == DEFINE_EXPAND
00689 || GET_CODE (insn) == DEFINE_SPLIT
00690 || GET_CODE (insn) == DEFINE_PEEPHOLE2)
00691 {
00692 if (constraints0)
00693 message_with_line (pattern_lineno,
00694 "warning: constraints not supported in %s",
00695 rtx_name[GET_CODE (insn)]);
00696 }
00697
00698
00699 else if (set && constraints0)
00700 {
00701 if (set_code == '+')
00702 {
00703 if (constraints0 == '+')
00704 ;
00705
00706
00707 else if (constraints0 == '='
00708 && find_matching_operand (insn, XINT (pattern, 0)))
00709 ;
00710 else
00711 {
00712 message_with_line (pattern_lineno,
00713 "operand %d missing in-out reload",
00714 XINT (pattern, 0));
00715 error_count++;
00716 }
00717 }
00718 else if (constraints0 != '=' && constraints0 != '+')
00719 {
00720 message_with_line (pattern_lineno,
00721 "operand %d missing output reload",
00722 XINT (pattern, 0));
00723 error_count++;
00724 }
00725 }
00726 }
00727
00728
00729
00730
00731 if (set && pred && pred->allows_non_lvalue)
00732 message_with_line (pattern_lineno,
00733 "warning: destination operand %d "
00734 "allows non-lvalue",
00735 XINT (pattern, 0));
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745 if (GET_MODE (pattern) == VOIDmode
00746 && code == MATCH_OPERAND
00747 && GET_CODE (insn) == DEFINE_INSN
00748 && pred
00749 && !pred->special
00750 && pred->allows_non_const
00751 && strstr (c_test, "operands") == NULL
00752 && ! (set
00753 && GET_CODE (set) == SET
00754 && GET_CODE (SET_SRC (set)) == CALL))
00755 message_with_line (pattern_lineno,
00756 "warning: operand %d missing mode?",
00757 XINT (pattern, 0));
00758 return;
00759 }
00760
00761 case SET:
00762 {
00763 enum machine_mode dmode, smode;
00764 rtx dest, src;
00765
00766 dest = SET_DEST (pattern);
00767 src = SET_SRC (pattern);
00768
00769
00770
00771 if (GET_CODE (dest) == STRICT_LOW_PART)
00772 dest = XEXP (dest, 0);
00773
00774
00775
00776 if (GET_CODE (dest) == MATCH_DUP
00777 || GET_CODE (dest) == MATCH_OP_DUP
00778 || GET_CODE (dest) == MATCH_PAR_DUP)
00779 dest = find_operand (insn, XINT (dest, 0), NULL);
00780
00781 if (GET_CODE (src) == MATCH_DUP
00782 || GET_CODE (src) == MATCH_OP_DUP
00783 || GET_CODE (src) == MATCH_PAR_DUP)
00784 src = find_operand (insn, XINT (src, 0), NULL);
00785
00786 dmode = GET_MODE (dest);
00787 smode = GET_MODE (src);
00788
00789
00790
00791 if (GET_CODE (src) == MATCH_OPERAND
00792 && ! strcmp (XSTR (src, 1), "address_operand"))
00793 ;
00794
00795
00796
00797 else if (dmode != VOIDmode && smode != VOIDmode && dmode != smode)
00798 {
00799 message_with_line (pattern_lineno,
00800 "mode mismatch in set: %smode vs %smode",
00801 GET_MODE_NAME (dmode), GET_MODE_NAME (smode));
00802 error_count++;
00803 }
00804
00805
00806
00807 else if (dmode != smode
00808 && GET_CODE (dest) != PC
00809 && GET_CODE (dest) != CC0
00810 && GET_CODE (src) != PC
00811 && GET_CODE (src) != CC0
00812 && GET_CODE (src) != CONST_INT)
00813 {
00814 const char *which;
00815 which = (dmode == VOIDmode ? "destination" : "source");
00816 message_with_line (pattern_lineno,
00817 "warning: %s missing a mode?", which);
00818 }
00819
00820 if (dest != SET_DEST (pattern))
00821 validate_pattern (dest, insn, pattern, '=');
00822 validate_pattern (SET_DEST (pattern), insn, pattern, '=');
00823 validate_pattern (SET_SRC (pattern), insn, NULL_RTX, 0);
00824 return;
00825 }
00826
00827 case CLOBBER:
00828 validate_pattern (SET_DEST (pattern), insn, pattern, '=');
00829 return;
00830
00831 case ZERO_EXTRACT:
00832 validate_pattern (XEXP (pattern, 0), insn, set, set ? '+' : 0);
00833 validate_pattern (XEXP (pattern, 1), insn, NULL_RTX, 0);
00834 validate_pattern (XEXP (pattern, 2), insn, NULL_RTX, 0);
00835 return;
00836
00837 case STRICT_LOW_PART:
00838 validate_pattern (XEXP (pattern, 0), insn, set, set ? '+' : 0);
00839 return;
00840
00841 case LABEL_REF:
00842 if (GET_MODE (XEXP (pattern, 0)) != VOIDmode)
00843 {
00844 message_with_line (pattern_lineno,
00845 "operand to label_ref %smode not VOIDmode",
00846 GET_MODE_NAME (GET_MODE (XEXP (pattern, 0))));
00847 error_count++;
00848 }
00849 break;
00850
00851 default:
00852 break;
00853 }
00854
00855 fmt = GET_RTX_FORMAT (code);
00856 len = GET_RTX_LENGTH (code);
00857 for (i = 0; i < len; i++)
00858 {
00859 switch (fmt[i])
00860 {
00861 case 'e': case 'u':
00862 validate_pattern (XEXP (pattern, i), insn, NULL_RTX, 0);
00863 break;
00864
00865 case 'E':
00866 for (j = 0; j < XVECLEN (pattern, i); j++)
00867 validate_pattern (XVECEXP (pattern, i, j), insn, NULL_RTX, 0);
00868 break;
00869
00870 case 'i': case 'w': case '0': case 's':
00871 break;
00872
00873 default:
00874 gcc_unreachable ();
00875 }
00876 }
00877 }
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 static struct decision *
00892 add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
00893 enum routine_type insn_type, int top)
00894 {
00895 RTX_CODE code;
00896 struct decision *this, *sub;
00897 struct decision_test *test;
00898 struct decision_test **place;
00899 char *subpos;
00900 size_t i;
00901 const char *fmt;
00902 int depth = strlen (position);
00903 int len;
00904 enum machine_mode mode;
00905
00906 if (depth > max_depth)
00907 max_depth = depth;
00908
00909 subpos = xmalloc (depth + 2);
00910 strcpy (subpos, position);
00911 subpos[depth + 1] = 0;
00912
00913 sub = this = new_decision (position, last);
00914 place = &this->tests;
00915
00916 restart:
00917 mode = GET_MODE (pattern);
00918 code = GET_CODE (pattern);
00919
00920 switch (code)
00921 {
00922 case PARALLEL:
00923
00924 if (insn_type == PEEPHOLE2 && top)
00925 {
00926
00927 last->first = last->last = NULL;
00928
00929 for (i = 0; i < (size_t) XVECLEN (pattern, 0); i++)
00930 {
00931
00932
00933
00934 subpos[depth] = (i > 0 ? 'A' + i : 0);
00935 sub = add_to_sequence (XVECEXP (pattern, 0, i),
00936 last, subpos, insn_type, 0);
00937 last = &sub->success;
00938 }
00939 goto ret;
00940 }
00941
00942
00943 break;
00944
00945 case MATCH_PARALLEL:
00946
00947
00948
00949
00950
00951 test = new_decision_test (DT_veclen_ge, &place);
00952 test->u.veclen = XVECLEN (pattern, 2);
00953
00954
00955 case MATCH_OPERAND:
00956 case MATCH_SCRATCH:
00957 case MATCH_OPERATOR:
00958 {
00959 RTX_CODE was_code = code;
00960 const char *pred_name;
00961 bool allows_const_int = true;
00962
00963 if (code == MATCH_SCRATCH)
00964 {
00965 pred_name = "scratch_operand";
00966 code = UNKNOWN;
00967 }
00968 else
00969 {
00970 pred_name = XSTR (pattern, 1);
00971 if (code == MATCH_PARALLEL)
00972 code = PARALLEL;
00973 else
00974 code = UNKNOWN;
00975 }
00976
00977 if (pred_name[0] != 0)
00978 {
00979 const struct pred_data *pred;
00980
00981 test = new_decision_test (DT_pred, &place);
00982 test->u.pred.name = pred_name;
00983 test->u.pred.mode = mode;
00984
00985
00986
00987
00988
00989
00990
00991
00992 pred = lookup_predicate (pred_name);
00993 if (pred)
00994 {
00995 test->u.pred.data = pred;
00996 allows_const_int = pred->codes[CONST_INT];
00997 if (was_code == MATCH_PARALLEL
00998 && pred->singleton != PARALLEL)
00999 message_with_line (pattern_lineno,
01000 "predicate '%s' used in match_parallel "
01001 "does not allow only PARALLEL", pred->name);
01002 else
01003 code = pred->singleton;
01004 }
01005 else
01006 message_with_line (pattern_lineno,
01007 "warning: unknown predicate '%s' in '%s' expression",
01008 pred_name, GET_RTX_NAME (was_code));
01009 }
01010
01011
01012 if (allows_const_int)
01013 mode = VOIDmode;
01014
01015
01016 test = new_decision_test (DT_accept_op, &place);
01017 test->u.opno = XINT (pattern, 0);
01018
01019 if (was_code == MATCH_OPERATOR || was_code == MATCH_PARALLEL)
01020 {
01021 char base = (was_code == MATCH_OPERATOR ? '0' : 'a');
01022 for (i = 0; i < (size_t) XVECLEN (pattern, 2); i++)
01023 {
01024 subpos[depth] = i + base;
01025 sub = add_to_sequence (XVECEXP (pattern, 2, i),
01026 &sub->success, subpos, insn_type, 0);
01027 }
01028 }
01029 goto fini;
01030 }
01031
01032 case MATCH_OP_DUP:
01033 code = UNKNOWN;
01034
01035 test = new_decision_test (DT_dup, &place);
01036 test->u.dup = XINT (pattern, 0);
01037
01038 test = new_decision_test (DT_accept_op, &place);
01039 test->u.opno = XINT (pattern, 0);
01040
01041 for (i = 0; i < (size_t) XVECLEN (pattern, 1); i++)
01042 {
01043 subpos[depth] = i + '0';
01044 sub = add_to_sequence (XVECEXP (pattern, 1, i),
01045 &sub->success, subpos, insn_type, 0);
01046 }
01047 goto fini;
01048
01049 case MATCH_DUP:
01050 case MATCH_PAR_DUP:
01051 code = UNKNOWN;
01052
01053 test = new_decision_test (DT_dup, &place);
01054 test->u.dup = XINT (pattern, 0);
01055 goto fini;
01056
01057 case ADDRESS:
01058 pattern = XEXP (pattern, 0);
01059 goto restart;
01060
01061 default:
01062 break;
01063 }
01064
01065 fmt = GET_RTX_FORMAT (code);
01066 len = GET_RTX_LENGTH (code);
01067
01068
01069 for (i = 0; i < (size_t) len; i++)
01070 {
01071 if (fmt[i] == 'i')
01072 {
01073 gcc_assert (i < 2);
01074
01075 if (!i)
01076 {
01077 test = new_decision_test (DT_elt_zero_int, &place);
01078 test->u.intval = XINT (pattern, i);
01079 }
01080 else
01081 {
01082 test = new_decision_test (DT_elt_one_int, &place);
01083 test->u.intval = XINT (pattern, i);
01084 }
01085 }
01086 else if (fmt[i] == 'w')
01087 {
01088
01089
01090 enum decision_type type
01091 = ((int) XWINT (pattern, i) == XWINT (pattern, i))
01092 ? DT_elt_zero_wide_safe : DT_elt_zero_wide;
01093
01094 gcc_assert (!i);
01095
01096 test = new_decision_test (type, &place);
01097 test->u.intval = XWINT (pattern, i);
01098 }
01099 else if (fmt[i] == 'E')
01100 {
01101 gcc_assert (!i);
01102
01103 test = new_decision_test (DT_veclen, &place);
01104 test->u.veclen = XVECLEN (pattern, i);
01105 }
01106 }
01107
01108
01109 for (i = 0; i < (size_t) len; i++)
01110 {
01111 switch (fmt[i])
01112 {
01113 case 'e': case 'u':
01114 subpos[depth] = '0' + i;
01115 sub = add_to_sequence (XEXP (pattern, i), &sub->success,
01116 subpos, insn_type, 0);
01117 break;
01118
01119 case 'E':
01120 {
01121 int j;
01122 for (j = 0; j < XVECLEN (pattern, i); j++)
01123 {
01124 subpos[depth] = 'a' + j;
01125 sub = add_to_sequence (XVECEXP (pattern, i, j),
01126 &sub->success, subpos, insn_type, 0);
01127 }
01128 break;
01129 }
01130
01131 case 'i': case 'w':
01132
01133 break;
01134 case '0':
01135 break;
01136
01137 default:
01138 gcc_unreachable ();
01139 }
01140 }
01141
01142 fini:
01143
01144
01145 if (code != UNKNOWN)
01146 {
01147 place = &this->tests;
01148 test = new_decision_test (DT_code, &place);
01149 test->u.code = code;
01150 }
01151
01152 if (mode != VOIDmode)
01153 {
01154 place = &this->tests;
01155 test = new_decision_test (DT_mode, &place);
01156 test->u.mode = mode;
01157 }
01158
01159
01160 gcc_assert (this->tests);
01161
01162 ret:
01163 free (subpos);
01164 return sub;
01165 }
01166
01167
01168
01169
01170 static int
01171 maybe_both_true_2 (struct decision_test *d1, struct decision_test *d2)
01172 {
01173 if (d1->type == d2->type)
01174 {
01175 switch (d1->type)
01176 {
01177 case DT_mode:
01178 return d1->u.mode == d2->u.mode;
01179
01180 case DT_code:
01181 return d1->u.code == d2->u.code;
01182
01183 case DT_veclen:
01184 return d1->u.veclen == d2->u.veclen;
01185
01186 case DT_elt_zero_int:
01187 case DT_elt_one_int:
01188 case DT_elt_zero_wide:
01189 case DT_elt_zero_wide_safe:
01190 return d1->u.intval == d2->u.intval;
01191
01192 default:
01193 break;
01194 }
01195 }
01196
01197
01198
01199
01200
01201 if (d1->type == DT_pred || d2->type == DT_pred)
01202 {
01203 if (d2->type == DT_pred)
01204 {
01205 struct decision_test *tmp;
01206 tmp = d1, d1 = d2, d2 = tmp;
01207 }
01208
01209
01210 if (d1->u.pred.mode != VOIDmode)
01211 {
01212 if (d2->type == DT_mode)
01213 {
01214 if (d1->u.pred.mode != d2->u.mode
01215
01216
01217
01218
01219 && strcmp (d1->u.pred.name, "address_operand") != 0)
01220 return 0;
01221 }
01222
01223
01224
01225
01226 }
01227
01228 if (d1->u.pred.data)
01229 {
01230
01231
01232 if (d2->type == DT_code)
01233 {
01234 if (!d1->u.pred.data->codes[d2->u.code])
01235 return 0;
01236 }
01237
01238
01239 else if (d2->type == DT_pred && d2->u.pred.data)
01240 {
01241 bool common = false;
01242 enum rtx_code c;
01243
01244 for (c = 0; c < NUM_RTX_CODE; c++)
01245 if (d1->u.pred.data->codes[c] && d2->u.pred.data->codes[c])
01246 {
01247 common = true;
01248 break;
01249 }
01250
01251 if (!common)
01252 return 0;
01253 }
01254 }
01255 }
01256
01257
01258 if (d1->type == DT_veclen && d2->type == DT_veclen_ge)
01259 return d1->u.veclen >= d2->u.veclen;
01260 if (d1->type == DT_veclen_ge && d2->type == DT_veclen)
01261 return d2->u.veclen >= d1->u.veclen;
01262
01263 return -1;
01264 }
01265
01266
01267
01268
01269 static int
01270 maybe_both_true_1 (struct decision_test *d1, struct decision_test *d2)
01271 {
01272 struct decision_test *t1, *t2;
01273
01274
01275
01276 if (d1->type == DT_accept_op || d2->type == DT_accept_op)
01277 return 1;
01278
01279
01280 while (d1 && d2 && d1->type == d2->type)
01281 {
01282 if (maybe_both_true_2 (d1, d2) == 0)
01283 return 0;
01284 d1 = d1->next, d2 = d2->next;
01285 }
01286
01287
01288 for (t1 = d1; t1 ; t1 = t1->next)
01289 for (t2 = d2; t2 ; t2 = t2->next)
01290 if (maybe_both_true_2 (t1, t2) == 0)
01291 return 0;
01292
01293 return -1;
01294 }
01295
01296
01297
01298
01299
01300
01301
01302
01303 static int
01304 maybe_both_true (struct decision *d1, struct decision *d2,
01305 int toplevel)
01306 {
01307 struct decision *p1, *p2;
01308 int cmp;
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328 cmp = strcmp (d1->position, d2->position);
01329 if (cmp != 0)
01330 {
01331 gcc_assert (!toplevel);
01332
01333
01334 if (cmp > 0)
01335 p1 = d1, d1 = d2, d2 = p1;
01336
01337 if (d1->success.first == 0)
01338 return 1;
01339 for (p1 = d1->success.first; p1; p1 = p1->next)
01340 if (maybe_both_true (p1, d2, 0))
01341 return 1;
01342
01343 return 0;
01344 }
01345
01346
01347 cmp = maybe_both_true_1 (d1->tests, d2->tests);
01348 if (cmp >= 0)
01349 return cmp;
01350
01351
01352
01353
01354
01355
01356
01357 if (toplevel || d1->success.first == 0 || d2->success.first == 0)
01358 return 1;
01359
01360 for (p1 = d1->success.first; p1; p1 = p1->next)
01361 for (p2 = d2->success.first; p2; p2 = p2->next)
01362 if (maybe_both_true (p1, p2, 0))
01363 return 1;
01364
01365 return 0;
01366 }
01367
01368
01369
01370 static int
01371 nodes_identical_1 (struct decision_test *d1, struct decision_test *d2)
01372 {
01373 switch (d1->type)
01374 {
01375 case DT_mode:
01376 return d1->u.mode == d2->u.mode;
01377
01378 case DT_code:
01379 return d1->u.code == d2->u.code;
01380
01381 case DT_pred:
01382 return (d1->u.pred.mode == d2->u.pred.mode
01383 && strcmp (d1->u.pred.name, d2->u.pred.name) == 0);
01384
01385 case DT_c_test:
01386 return strcmp (d1->u.c_test, d2->u.c_test) == 0;
01387
01388 case DT_veclen:
01389 case DT_veclen_ge:
01390 return d1->u.veclen == d2->u.veclen;
01391
01392 case DT_dup:
01393 return d1->u.dup == d2->u.dup;
01394
01395 case DT_elt_zero_int:
01396 case DT_elt_one_int:
01397 case DT_elt_zero_wide:
01398 case DT_elt_zero_wide_safe:
01399 return d1->u.intval == d2->u.intval;
01400
01401 case DT_accept_op:
01402 return d1->u.opno == d2->u.opno;
01403
01404 case DT_accept_insn:
01405
01406 return 1;
01407
01408 default:
01409 gcc_unreachable ();
01410 }
01411 }
01412
01413
01414
01415
01416
01417 static int
01418 nodes_identical (struct decision *d1, struct decision *d2)
01419 {
01420 struct decision_test *t1, *t2;
01421
01422 for (t1 = d1->tests, t2 = d2->tests; t1 && t2; t1 = t1->next, t2 = t2->next)
01423 {
01424 if (t1->type != t2->type)
01425 return 0;
01426 if (! nodes_identical_1 (t1, t2))
01427 return 0;
01428 }
01429
01430
01431 if (t1 != t2)
01432 return 0;
01433
01434
01435
01436
01437
01438 if (d1->success.first
01439 && d2->success.first
01440 && strcmp (d1->success.first->position, d2->success.first->position))
01441 return 0;
01442
01443 return 1;
01444 }
01445
01446
01447
01448
01449
01450
01451
01452
01453 static void
01454 merge_accept_insn (struct decision *oldd, struct decision *addd)
01455 {
01456 struct decision_test *old, *add;
01457
01458 for (old = oldd->tests; old; old = old->next)
01459 if (old->type == DT_accept_insn)
01460 break;
01461 if (old == NULL)
01462 return;
01463
01464 for (add = addd->tests; add; add = add->next)
01465 if (add->type == DT_accept_insn)
01466 break;
01467 if (add == NULL)
01468 return;
01469
01470
01471
01472
01473 if (old->u.insn.num_clobbers_to_add == 0
01474 && add->u.insn.num_clobbers_to_add > 0)
01475 {
01476
01477 }
01478 else if (old->u.insn.num_clobbers_to_add > 0
01479 && add->u.insn.num_clobbers_to_add == 0)
01480 {
01481
01482 old->u.insn = add->u.insn;
01483 }
01484 else
01485 {
01486 message_with_line (add->u.insn.lineno, "`%s' matches `%s'",
01487 get_insn_name (add->u.insn.code_number),
01488 get_insn_name (old->u.insn.code_number));
01489 message_with_line (old->u.insn.lineno, "previous definition of `%s'",
01490 get_insn_name (old->u.insn.code_number));
01491 error_count++;
01492 }
01493 }
01494
01495
01496
01497 static void
01498 merge_trees (struct decision_head *oldh, struct decision_head *addh)
01499 {
01500 struct decision *next, *add;
01501
01502 if (addh->first == 0)
01503 return;
01504 if (oldh->first == 0)
01505 {
01506 *oldh = *addh;
01507 return;
01508 }
01509
01510
01511 gcc_assert (!strcmp (oldh->first->position, addh->first->position));
01512
01513 for (add = addh->first; add ; add = next)
01514 {
01515 struct decision *old, *insert_before = NULL;
01516
01517 next = add->next;
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535 for (old = oldh->last; old; old = old->prev)
01536 {
01537 if (nodes_identical (old, add))
01538 {
01539 merge_accept_insn (old, add);
01540 merge_trees (&old->success, &add->success);
01541 goto merged_nodes;
01542 }
01543
01544 if (maybe_both_true (old, add, 0))
01545 break;
01546
01547
01548
01549
01550
01551 if ((int) add->tests->type < (int) old->tests->type)
01552 insert_before = old;
01553 }
01554
01555 if (insert_before == NULL)
01556 {
01557 add->next = NULL;
01558 add->prev = oldh->last;
01559 oldh->last->next = add;
01560 oldh->last = add;
01561 }
01562 else
01563 {
01564 if ((add->prev = insert_before->prev) != NULL)
01565 add->prev->next = add;
01566 else
01567 oldh->first = add;
01568 add->next = insert_before;
01569 insert_before->prev = add;
01570 }
01571
01572 merged_nodes:;
01573 }
01574 }
01575
01576
01577
01578
01579
01580 static void
01581 factor_tests (struct decision_head *head)
01582 {
01583 struct decision *first, *next;
01584
01585 for (first = head->first; first && first->next; first = next)
01586 {
01587 enum decision_type type;
01588 struct decision *new, *old_last;
01589
01590 type = first->tests->type;
01591 next = first->next;
01592
01593
01594 if (next->tests->type != type)
01595 continue;
01596
01597
01598
01599 if (type != DT_mode
01600 && type != DT_code
01601 && type != DT_veclen
01602 && type != DT_elt_zero_int
01603 && type != DT_elt_one_int
01604 && type != DT_elt_zero_wide_safe)
01605 continue;
01606
01607
01608
01609 if (first->tests->next != NULL)
01610 {
01611 new = new_decision (first->position, &first->success);
01612 new->tests = first->tests->next;
01613 first->tests->next = NULL;
01614 }
01615
01616
01617 first->next = NULL;
01618 old_last = head->last;
01619 head->last = first;
01620
01621
01622
01623 do
01624 {
01625 struct decision_head h;
01626
01627 if (next->tests->next != NULL)
01628 {
01629 new = new_decision (next->position, &next->success);
01630 new->tests = next->tests->next;
01631 next->tests->next = NULL;
01632 }
01633 new = next;
01634 next = next->next;
01635 new->next = NULL;
01636 h.first = h.last = new;
01637
01638 merge_trees (head, &h);
01639 }
01640 while (next && next->tests->type == type);
01641
01642
01643
01644 if (next)
01645 {
01646 next->prev = head->last;
01647 head->last->next = next;
01648 head->last = old_last;
01649 }
01650 }
01651
01652
01653 for (first = head->first; first; first = first->next)
01654 factor_tests (&first->success);
01655 }
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665 static void
01666 simplify_tests (struct decision_head *head)
01667 {
01668 struct decision *tree;
01669
01670 for (tree = head->first; tree; tree = tree->next)
01671 {
01672 struct decision_test *a, *b;
01673
01674 a = tree->tests;
01675 b = a->next;
01676 if (b == NULL)
01677 continue;
01678
01679
01680 while (b && b->type != DT_pred)
01681 b = b->next;
01682 if (b)
01683 {
01684
01685
01686
01687 while (a->type == DT_mode || a->type == DT_code)
01688 a = a->next;
01689 tree->tests = a;
01690 }
01691 }
01692
01693
01694 for (tree = head->first; tree; tree = tree->next)
01695 simplify_tests (&tree->success);
01696 }
01697
01698
01699
01700
01701
01702 static int
01703 break_out_subroutines (struct decision_head *head, int initial)
01704 {
01705 int size = 0;
01706 struct decision *sub;
01707
01708 for (sub = head->first; sub; sub = sub->next)
01709 size += 1 + break_out_subroutines (&sub->success, 0);
01710
01711 if (size > SUBROUTINE_THRESHOLD && ! initial)
01712 {
01713 head->first->subroutine_number = ++next_subroutine_number;
01714 size = 1;
01715 }
01716 return size;
01717 }
01718
01719
01720
01721
01722 static void
01723 find_afterward (struct decision_head *head, struct decision *real_afterward)
01724 {
01725 struct decision *p, *q, *afterward;
01726
01727
01728
01729
01730 p = head->first;
01731 afterward = (p->subroutine_number > 0 ? NULL : real_afterward);
01732
01733 for ( ; p ; p = p->next)
01734 {
01735
01736 for (q = p->next; q ; q = q->next)
01737 if (maybe_both_true (p, q, 1))
01738 break;
01739
01740
01741
01742 if (!q)
01743 q = afterward;
01744 p->afterward = q;
01745 if (q)
01746 q->need_label = 1;
01747 }
01748
01749
01750 for (p = head->first; p ; p = p->next)
01751 if (p->success.first)
01752 find_afterward (&p->success, p->afterward);
01753
01754
01755
01756
01757 p = head->first;
01758 if (p->subroutine_number > 0)
01759 p->afterward = real_afterward;
01760 }
01761
01762
01763
01764
01765
01766
01767
01768
01769 static void
01770 change_state (const char *oldpos, const char *newpos,
01771 struct decision *afterward, const char *indent)
01772 {
01773 int odepth = strlen (oldpos);
01774 int ndepth = strlen (newpos);
01775 int depth;
01776 int old_has_insn, new_has_insn;
01777
01778
01779 for (depth = odepth; strncmp (oldpos, newpos, depth) != 0; --depth)
01780 continue;
01781
01782
01783 for (old_has_insn = odepth - 1; old_has_insn >= 0; --old_has_insn)
01784 if (ISUPPER (oldpos[old_has_insn]))
01785 break;
01786 for (new_has_insn = ndepth - 1; new_has_insn >= 0; --new_has_insn)
01787 if (ISUPPER (newpos[new_has_insn]))
01788 break;
01789
01790
01791 while (depth < ndepth)
01792 {
01793
01794 if (ISUPPER (newpos[depth]))
01795 {
01796
01797 if (old_has_insn >= 0 && oldpos[old_has_insn] >= newpos[depth])
01798 {
01799 printf ("%stem = peep2_next_insn (%d);\n",
01800 indent, newpos[depth] - 'A');
01801 }
01802 else
01803 {
01804 printf ("%stem = peep2_next_insn (%d);\n",
01805 indent, newpos[depth] - 'A');
01806 printf ("%sif (tem == NULL_RTX)\n", indent);
01807 if (afterward)
01808 printf ("%s goto L%d;\n", indent, afterward->number);
01809 else
01810 printf ("%s goto ret0;\n", indent);
01811 }
01812 printf ("%sx%d = PATTERN (tem);\n", indent, depth + 1);
01813 }
01814 else if (ISLOWER (newpos[depth]))
01815 printf ("%sx%d = XVECEXP (x%d, 0, %d);\n",
01816 indent, depth + 1, depth, newpos[depth] - 'a');
01817 else
01818 printf ("%sx%d = XEXP (x%d, %c);\n",
01819 indent, depth + 1, depth, newpos[depth]);
01820 ++depth;
01821 }
01822 }
01823
01824
01825
01826
01827 static void
01828 print_code (enum rtx_code code)
01829 {
01830 const char *p;
01831 for (p = GET_RTX_NAME (code); *p; p++)
01832 putchar (TOUPPER (*p));
01833 }
01834
01835
01836
01837 static void
01838 write_afterward (struct decision *start, struct decision *afterward,
01839 const char *indent)
01840 {
01841 if (!afterward || start->subroutine_number > 0)
01842 printf("%sgoto ret0;\n", indent);
01843 else
01844 {
01845 change_state (start->position, afterward->position, NULL, indent);
01846 printf ("%sgoto L%d;\n", indent, afterward->number);
01847 }
01848 }
01849
01850
01851
01852
01853
01854 static void
01855 print_host_wide_int (HOST_WIDE_INT val)
01856 {
01857 HOST_WIDE_INT min = (unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT-1);
01858 if (val == min)
01859 printf ("(" HOST_WIDE_INT_PRINT_DEC_C "-1)", val + 1);
01860 else
01861 printf (HOST_WIDE_INT_PRINT_DEC_C, val);
01862 }
01863
01864
01865
01866
01867 static struct decision *
01868 write_switch (struct decision *start, int depth)
01869 {
01870 struct decision *p = start;
01871 enum decision_type type = p->tests->type;
01872 struct decision *needs_label = NULL;
01873
01874
01875
01876
01877 if (!p->next
01878 || p->tests->next
01879 || p->next->tests->type != type
01880 || p->next->tests->next
01881 || nodes_identical_1 (p->tests, p->next->tests))
01882 return p;
01883
01884
01885
01886 if (type == DT_code)
01887 {
01888 char codemap[NUM_RTX_CODE];
01889 struct decision *ret;
01890 RTX_CODE code;
01891
01892 memset (codemap, 0, sizeof(codemap));
01893
01894 printf (" switch (GET_CODE (x%d))\n {\n", depth);
01895 code = p->tests->u.code;
01896 do
01897 {
01898 if (p != start && p->need_label && needs_label == NULL)
01899 needs_label = p;
01900
01901 printf (" case ");
01902 print_code (code);
01903 printf (":\n goto L%d;\n", p->success.first->number);
01904 p->success.first->need_label = 1;
01905
01906 codemap[code] = 1;
01907 p = p->next;
01908 }
01909 while (p
01910 && ! p->tests->next
01911 && p->tests->type == DT_code
01912 && ! codemap[code = p->tests->u.code]);
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924 if (needs_label != NULL)
01925 ret = needs_label;
01926 else
01927 ret = p;
01928
01929 while (p && p->tests->type == DT_pred && p->tests->u.pred.data)
01930 {
01931 const struct pred_data *data = p->tests->u.pred.data;
01932 RTX_CODE c;
01933 for (c = 0; c < NUM_RTX_CODE; c++)
01934 if (codemap[c] && data->codes[c])
01935 goto pred_done;
01936
01937 for (c = 0; c < NUM_RTX_CODE; c++)
01938 if (data->codes[c])
01939 {
01940 fputs (" case ", stdout);
01941 print_code (c);
01942 fputs (":\n", stdout);
01943 codemap[c] = 1;
01944 }
01945
01946 printf (" goto L%d;\n", p->number);
01947 p->need_label = 1;
01948 p = p->next;
01949 }
01950
01951 pred_done:
01952
01953
01954 printf (" default:\n");
01955 if (p != ret)
01956 {
01957 if (p)
01958 {
01959 printf (" goto L%d;\n", p->number);
01960 p->need_label = 1;
01961 }
01962 else
01963 write_afterward (start, start->afterward, " ");
01964 }
01965 else
01966 printf (" break;\n");
01967 printf (" }\n");
01968
01969 return ret;
01970 }
01971 else if (type == DT_mode
01972 || type == DT_veclen
01973 || type == DT_elt_zero_int
01974 || type == DT_elt_one_int
01975 || type == DT_elt_zero_wide_safe)
01976 {
01977 const char *indent = "";
01978
01979
01980
01981 if (type == DT_elt_zero_wide_safe)
01982 {
01983 indent = " ";
01984 printf(" if ((int) XWINT (x%d, 0) == XWINT (x%d, 0))\n", depth, depth);
01985 }
01986 printf ("%s switch (", indent);
01987 switch (type)
01988 {
01989 case DT_mode:
01990 printf ("GET_MODE (x%d)", depth);
01991 break;
01992 case DT_veclen:
01993 printf ("XVECLEN (x%d, 0)", depth);
01994 break;
01995 case DT_elt_zero_int:
01996 printf ("XINT (x%d, 0)", depth);
01997 break;
01998 case DT_elt_one_int:
01999 printf ("XINT (x%d, 1)", depth);
02000 break;
02001 case DT_elt_zero_wide_safe:
02002
02003
02004 printf ("(int) XWINT (x%d, 0)", depth);
02005 break;
02006 default:
02007 gcc_unreachable ();
02008 }
02009 printf (")\n%s {\n", indent);
02010
02011 do
02012 {
02013
02014
02015
02016 struct decision *q;
02017 for (q = start; q != p; q = q->next)
02018 if (nodes_identical_1 (p->tests, q->tests))
02019 goto case_done;
02020
02021 if (p != start && p->need_label && needs_label == NULL)
02022 needs_label = p;
02023
02024 printf ("%s case ", indent);
02025 switch (type)
02026 {
02027 case DT_mode:
02028 printf ("%smode", GET_MODE_NAME (p->tests->u.mode));
02029 break;
02030 case DT_veclen:
02031 printf ("%d", p->tests->u.veclen);
02032 break;
02033 case DT_elt_zero_int:
02034 case DT_elt_one_int:
02035 case DT_elt_zero_wide:
02036 case DT_elt_zero_wide_safe:
02037 print_host_wide_int (p->tests->u.intval);
02038 break;
02039 default:
02040 gcc_unreachable ();
02041 }
02042 printf (":\n%s goto L%d;\n", indent, p->success.first->number);
02043 p->success.first->need_label = 1;
02044
02045 p = p->next;
02046 }
02047 while (p && p->tests->type == type && !p->tests->next);
02048
02049 case_done:
02050 printf ("%s default:\n%s break;\n%s }\n",
02051 indent, indent, indent);
02052
02053 return needs_label != NULL ? needs_label : p;
02054 }
02055 else
02056 {
02057
02058 return p;
02059 }
02060 }
02061
02062
02063
02064 static void
02065 write_cond (struct decision_test *p, int depth,
02066 enum routine_type subroutine_type)
02067 {
02068 switch (p->type)
02069 {
02070 case DT_mode:
02071 printf ("GET_MODE (x%d) == %smode", depth, GET_MODE_NAME (p->u.mode));
02072 break;
02073
02074 case DT_code:
02075 printf ("GET_CODE (x%d) == ", depth);
02076 print_code (p->u.code);
02077 break;
02078
02079 case DT_veclen:
02080 printf ("XVECLEN (x%d, 0) == %d", depth, p->u.veclen);
02081 break;
02082
02083 case DT_elt_zero_int:
02084 printf ("XINT (x%d, 0) == %d", depth, (int) p->u.intval);
02085 break;
02086
02087 case DT_elt_one_int:
02088 printf ("XINT (x%d, 1) == %d", depth, (int) p->u.intval);
02089 break;
02090
02091 case DT_elt_zero_wide:
02092 case DT_elt_zero_wide_safe:
02093 printf ("XWINT (x%d, 0) == ", depth);
02094 print_host_wide_int (p->u.intval);
02095 break;
02096
02097 case DT_const_int:
02098 printf ("x%d == const_int_rtx[MAX_SAVED_CONST_INT + (%d)]",
02099 depth, (int) p->u.intval);
02100 break;
02101
02102 case DT_veclen_ge:
02103 printf ("XVECLEN (x%d, 0) >= %d", depth, p->u.veclen);
02104 break;
02105
02106 case DT_dup:
02107 printf ("rtx_equal_p (x%d, operands[%d])", depth, p->u.dup);
02108 break;
02109
02110 case DT_pred:
02111 printf ("%s (x%d, %smode)", p->u.pred.name, depth,
02112 GET_MODE_NAME (p->u.pred.mode));
02113 break;
02114
02115 case DT_c_test:
02116 printf ("(%s)", p->u.c_test);
02117 break;
02118
02119 case DT_accept_insn:
02120 gcc_assert (subroutine_type == RECOG);
02121 gcc_assert (p->u.insn.num_clobbers_to_add);
02122 printf ("pnum_clobbers != NULL");
02123 break;
02124
02125 default:
02126 gcc_unreachable ();
02127 }
02128 }
02129
02130
02131
02132
02133
02134 static void
02135 write_action (struct decision *p, struct decision_test *test,
02136 int depth, int uncond, struct decision *success,
02137 enum routine_type subroutine_type)
02138 {
02139 const char *indent;
02140 int want_close = 0;
02141
02142 if (uncond)
02143 indent = " ";
02144 else if (test->type == DT_accept_op || test->type == DT_accept_insn)
02145 {
02146 fputs (" {\n", stdout);
02147 indent = " ";
02148 want_close = 1;
02149 }
02150 else
02151 indent = " ";
02152
02153 if (test->type == DT_accept_op)
02154 {
02155 printf("%soperands[%d] = x%d;\n", indent, test->u.opno, depth);
02156
02157
02158 if (test->next)
02159 {
02160 test = test->next;
02161 gcc_assert (test->type == DT_accept_insn);
02162 }
02163 }
02164
02165
02166 gcc_assert (!test->next);
02167
02168 if (test->type == DT_accept_insn)
02169 {
02170 switch (subroutine_type)
02171 {
02172 case RECOG:
02173 if (test->u.insn.num_clobbers_to_add != 0)
02174 printf ("%s*pnum_clobbers = %d;\n",
02175 indent, test->u.insn.num_clobbers_to_add);
02176 printf ("%sreturn %d; /* %s */\n", indent,
02177 test->u.insn.code_number,
02178 insn_name_ptr[test->u.insn.code_number]);
02179 break;
02180
02181 case SPLIT:
02182 printf ("%sreturn gen_split_%d (insn, operands);\n",
02183 indent, test->u.insn.code_number);
02184 break;
02185
02186 case PEEPHOLE2:
02187 {
02188 int match_len = 0, i;
02189
02190 for (i = strlen (p->position) - 1; i >= 0; --i)
02191 if (ISUPPER (p->position[i]))
02192 {
02193 match_len = p->position[i] - 'A';
02194 break;
02195 }
02196 printf ("%s*_pmatch_len = %d;\n", indent, match_len);
02197 printf ("%stem = gen_peephole2_%d (insn, operands);\n",
02198 indent, test->u.insn.code_number);
02199 printf ("%sif (tem != 0)\n%s return tem;\n", indent, indent);
02200 }
02201 break;
02202
02203 default:
02204 gcc_unreachable ();
02205 }
02206 }
02207 else
02208 {
02209 printf("%sgoto L%d;\n", indent, success->number);
02210 success->need_label = 1;
02211 }
02212
02213 if (want_close)
02214 fputs (" }\n", stdout);
02215 }
02216
02217
02218
02219
02220
02221
02222 static int
02223 is_unconditional (struct decision_test *t, enum routine_type subroutine_type)
02224 {
02225 if (t->type == DT_accept_op)
02226 return 1;
02227
02228 if (t->type == DT_accept_insn)
02229 {
02230 switch (subroutine_type)
02231 {
02232 case RECOG:
02233 return (t->u.insn.num_clobbers_to_add == 0);
02234 case SPLIT:
02235 return 1;
02236 case PEEPHOLE2:
02237 return -1;
02238 default:
02239 gcc_unreachable ();
02240 }
02241 }
02242
02243 return 0;
02244 }
02245
02246
02247
02248
02249 static int
02250 write_node (struct decision *p, int depth,
02251 enum routine_type subroutine_type)
02252 {
02253 struct decision_test *test, *last_test;
02254 int uncond;
02255
02256
02257
02258 for (test = p->tests; test; test = test->next)
02259 {
02260 if (test->type == DT_code
02261 && test->u.code == CONST_INT
02262 && test->next
02263 && test->next->type == DT_elt_zero_wide_safe
02264 && -MAX_SAVED_CONST_INT <= test->next->u.intval
02265 && test->next->u.intval <= MAX_SAVED_CONST_INT)
02266 {
02267 test->type = DT_const_int;
02268 test->u.intval = test->next->u.intval;
02269 test->next = test->next->next;
02270 }
02271 }
02272
02273 last_test = test = p->tests;
02274 uncond = is_unconditional (test, subroutine_type);
02275 if (uncond == 0)
02276 {
02277 printf (" if (");
02278 write_cond (test, depth, subroutine_type);
02279
02280 while ((test = test->next) != NULL)
02281 {
02282 last_test = test;
02283 if (is_unconditional (test, subroutine_type))
02284 break;
02285
02286 printf ("\n && ");
02287 write_cond (test, depth, subroutine_type);
02288 }
02289
02290 printf (")\n");
02291 }
02292
02293 write_action (p, last_test, depth, uncond, p->success.first, subroutine_type);
02294
02295 return uncond > 0;
02296 }
02297
02298
02299
02300 static void
02301 write_tree_1 (struct decision_head *head, int depth,
02302 enum routine_type subroutine_type)
02303 {
02304 struct decision *p, *next;
02305 int uncond = 0;
02306
02307 for (p = head->first; p ; p = next)
02308 {
02309
02310 if (p != head->first && p->need_label)
02311 OUTPUT_LABEL (" ", p->number);
02312
02313
02314 next = write_switch (p, depth);
02315 if (p != next)
02316 uncond = 0;
02317 else
02318 {
02319
02320 uncond = write_node (p, depth, subroutine_type);
02321 next = p->next;
02322 }
02323 }
02324
02325
02326
02327 if (! uncond)
02328 write_afterward (head->last, head->last->afterward, " ");
02329 }
02330
02331
02332
02333
02334 static void
02335 write_tree (struct decision_head *head, const char *prevpos,
02336 enum routine_type type, int initial)
02337 {
02338 struct decision *p = head->first;
02339
02340 putchar ('\n');
02341 if (p->need_label)
02342 OUTPUT_LABEL (" ", p->number);
02343
02344 if (! initial && p->subroutine_number > 0)
02345 {
02346 static const char * const name_prefix[] = {
02347 "recog", "split", "peephole2"
02348 };
02349
02350 static const char * const call_suffix[] = {
02351 ", pnum_clobbers", "", ", _pmatch_len"
02352 };
02353
02354
02355
02356
02357 if (p->afterward)
02358 {
02359 printf (" tem = %s_%d (x0, insn%s);\n",
02360 name_prefix[type], p->subroutine_number, call_suffix[type]);
02361 if (IS_SPLIT (type))
02362 printf (" if (tem != 0)\n return tem;\n");
02363 else
02364 printf (" if (tem >= 0)\n return tem;\n");
02365
02366 change_state (p->position, p->afterward->position, NULL, " ");
02367 printf (" goto L%d;\n", p->afterward->number);
02368 }
02369 else
02370 {
02371 printf (" return %s_%d (x0, insn%s);\n",
02372 name_prefix[type], p->subroutine_number, call_suffix[type]);
02373 }
02374 }
02375 else
02376 {
02377 int depth = strlen (p->position);
02378
02379 change_state (prevpos, p->position, head->last->afterward, " ");
02380 write_tree_1 (head, depth, type);
02381
02382 for (p = head->first; p; p = p->next)
02383 if (p->success.first)
02384 write_tree (&p->success, p->position, type, 0);
02385 }
02386 }
02387
02388
02389
02390
02391 static void
02392 write_subroutine (struct decision_head *head, enum routine_type type)
02393 {
02394 int subfunction = head->first ? head->first->subroutine_number : 0;
02395 const char *s_or_e;
02396 char extension[32];
02397 int i;
02398
02399 s_or_e = subfunction ? "static " : "";
02400
02401 if (subfunction)
02402 sprintf (extension, "_%d", subfunction);
02403 else if (type == RECOG)
02404 extension[0] = '\0';
02405 else
02406 strcpy (extension, "_insns");
02407
02408 switch (type)
02409 {
02410 case RECOG:
02411 printf ("%sint\n\
02412 recog%s (rtx x0 ATTRIBUTE_UNUSED,\n\trtx insn ATTRIBUTE_UNUSED,\n\tint *pnum_clobbers ATTRIBUTE_UNUSED)\n", s_or_e, extension);
02413 break;
02414 case SPLIT:
02415 printf ("%srtx\n\
02416 split%s (rtx x0 ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED)\n",
02417 s_or_e, extension);
02418 break;
02419 case PEEPHOLE2:
02420 printf ("%srtx\n\
02421 peephole2%s (rtx x0 ATTRIBUTE_UNUSED,\n\trtx insn ATTRIBUTE_UNUSED,\n\tint *_pmatch_len ATTRIBUTE_UNUSED)\n",
02422 s_or_e, extension);
02423 break;
02424 }
02425
02426 printf ("{\n rtx * const operands ATTRIBUTE_UNUSED = &recog_data.operand[0];\n");
02427 for (i = 1; i <= max_depth; i++)
02428 printf (" rtx x%d ATTRIBUTE_UNUSED;\n", i);
02429
02430 printf (" %s tem ATTRIBUTE_UNUSED;\n", IS_SPLIT (type) ? "rtx" : "int");
02431
02432 if (!subfunction)
02433 printf (" recog_data.insn = NULL_RTX;\n");
02434
02435 if (head->first)
02436 write_tree (head, "", type, 1);
02437 else
02438 printf (" goto ret0;\n");
02439
02440 printf (" ret0:\n return %d;\n}\n\n", IS_SPLIT (type) ? 0 : -1);
02441 }
02442
02443
02444
02445
02446 static void
02447 write_subroutines (struct decision_head *head, enum routine_type type)
02448 {
02449 struct decision *p;
02450
02451 for (p = head->first; p ; p = p->next)
02452 if (p->success.first)
02453 write_subroutines (&p->success, type);
02454
02455 if (head->first->subroutine_number > 0)
02456 write_subroutine (head, type);
02457 }
02458
02459
02460
02461 static void
02462 write_header (void)
02463 {
02464 puts ("\
02465 /* Generated automatically by the program `genrecog' from the target\n\
02466 machine description file. */\n\
02467 \n\
02468 #include \"config.h\"\n\
02469 #include \"system.h\"\n\
02470 #include \"coretypes.h\"\n\
02471 #include \"tm.h\"\n\
02472 #include \"rtl.h\"\n\
02473 #include \"tm_p.h\"\n\
02474 #include \"function.h\"\n\
02475 #include \"insn-config.h\"\n\
02476 #include \"recog.h\"\n\
02477 #include \"real.h\"\n\
02478 #include \"output.h\"\n\
02479 #include \"flags.h\"\n\
02480 #include \"hard-reg-set.h\"\n\
02481 #include \"resource.h\"\n\
02482 #include \"toplev.h\"\n\
02483 #include \"reload.h\"\n\
02484 \n");
02485
02486 puts ("\n\
02487 /* `recog' contains a decision tree that recognizes whether the rtx\n\
02488 X0 is a valid instruction.\n\
02489 \n\
02490 recog returns -1 if the rtx is not valid. If the rtx is valid, recog\n\
02491 returns a nonnegative number which is the insn code number for the\n\
02492 pattern that matched. This is the same as the order in the machine\n\
02493 description of the entry that matched. This number can be used as an\n\
02494 index into `insn_data' and other tables.\n");
02495 puts ("\
02496 The third argument to recog is an optional pointer to an int. If\n\
02497 present, recog will accept a pattern if it matches except for missing\n\
02498 CLOBBER expressions at the end. In that case, the value pointed to by\n\
02499 the optional pointer will be set to the number of CLOBBERs that need\n\
02500 to be added (it should be initialized to zero by the caller). If it");
02501 puts ("\
02502 is set nonzero, the caller should allocate a PARALLEL of the\n\
02503 appropriate size, copy the initial entries, and call add_clobbers\n\
02504 (found in insn-emit.c) to fill in the CLOBBERs.\n\
02505 ");
02506
02507 puts ("\n\
02508 The function split_insns returns 0 if the rtl could not\n\
02509 be split or the split rtl as an INSN list if it can be.\n\
02510 \n\
02511 The function peephole2_insns returns 0 if the rtl could not\n\
02512 be matched. If there was a match, the new rtl is returned in an INSN list,\n\
02513 and LAST_INSN will point to the last recognized insn in the old sequence.\n\
02514 */\n\n");
02515 }
02516
02517
02518
02519
02520
02521
02522
02523 static struct decision_head
02524 make_insn_sequence (rtx insn, enum routine_type type)
02525 {
02526 rtx x;
02527 const char *c_test = XSTR (insn, type == RECOG ? 2 : 1);
02528 int truth = maybe_eval_c_test (c_test);
02529 struct decision *last;
02530 struct decision_test *test, **place;
02531 struct decision_head head;
02532 char c_test_pos[2];
02533
02534
02535 gcc_assert (truth);
02536
02537 record_insn_name (next_insn_code, (type == RECOG ? XSTR (insn, 0) : NULL));
02538
02539 c_test_pos[0] = '\0';
02540 if (type == PEEPHOLE2)
02541 {
02542 int i, j;
02543
02544
02545
02546
02547
02548 x = rtx_alloc (PARALLEL);
02549 PUT_MODE (x, VOIDmode);
02550 XVEC (x, 0) = rtvec_alloc (XVECLEN (insn, 0));
02551 for (i = j = 0; i < XVECLEN (insn, 0); i++)
02552 {
02553 rtx tmp = XVECEXP (insn, 0, i);
02554 if (GET_CODE (tmp) != MATCH_SCRATCH && GET_CODE (tmp) != MATCH_DUP)
02555 {
02556 XVECEXP (x, 0, j) = tmp;
02557 j++;
02558 }
02559 }
02560 XVECLEN (x, 0) = j;
02561
02562 c_test_pos[0] = 'A' + j - 1;
02563 c_test_pos[1] = '\0';
02564 }
02565 else if (XVECLEN (insn, type == RECOG) == 1)
02566 x = XVECEXP (insn, type == RECOG, 0);
02567 else
02568 {
02569 x = rtx_alloc (PARALLEL);
02570 XVEC (x, 0) = XVEC (insn, type == RECOG);
02571 PUT_MODE (x, VOIDmode);
02572 }
02573
02574 validate_pattern (x, insn, NULL_RTX, 0);
02575
02576 memset(&head, 0, sizeof(head));
02577 last = add_to_sequence (x, &head, "", type, 1);
02578
02579
02580 for (test = last->tests; test->next; test = test->next)
02581 continue;
02582 place = &test->next;
02583
02584
02585 if (truth == -1)
02586 {
02587
02588 if (test->type == DT_accept_op)
02589 {
02590 last = new_decision (c_test_pos, &last->success);
02591 place = &last->tests;
02592 }
02593 test = new_decision_test (DT_c_test, &place);
02594 test->u.c_test = c_test;
02595 }
02596
02597 test = new_decision_test (DT_accept_insn, &place);
02598 test->u.insn.code_number = next_insn_code;
02599 test->u.insn.lineno = pattern_lineno;
02600 test->u.insn.num_clobbers_to_add = 0;
02601
02602 switch (type)
02603 {
02604 case RECOG:
02605
02606
02607
02608
02609 if (GET_CODE (x) == PARALLEL)
02610 {
02611 int i;
02612
02613
02614 for (i = XVECLEN (x, 0); i > 0; i--)
02615 {
02616 rtx y = XVECEXP (x, 0, i - 1);
02617 if (GET_CODE (y) != CLOBBER
02618 || (!REG_P (XEXP (y, 0))
02619 && GET_CODE (XEXP (y, 0)) != MATCH_SCRATCH))
02620 break;
02621 }
02622
02623 if (i != XVECLEN (x, 0))
02624 {
02625 rtx new;
02626 struct decision_head clobber_head;
02627
02628
02629 if (i == 1)
02630 new = XVECEXP (x, 0, 0);
02631 else
02632 {
02633 int j;
02634
02635 new = rtx_alloc (PARALLEL);
02636 XVEC (new, 0) = rtvec_alloc (i);
02637 for (j = i - 1; j >= 0; j--)
02638 XVECEXP (new, 0, j) = XVECEXP (x, 0, j);
02639 }
02640
02641
02642 memset (&clobber_head, 0, sizeof(clobber_head));
02643 last = add_to_sequence (new, &clobber_head, "", type, 1);
02644
02645
02646 for (test = last->tests; test->next; test = test->next)
02647 continue;
02648
02649
02650
02651 place = &test->next;
02652 if (test->type == DT_accept_op)
02653 {
02654 last = new_decision ("", &last->success);
02655 place = &last->tests;
02656 }
02657
02658
02659
02660 if (truth == -1)
02661 {
02662 test = new_decision_test (DT_c_test, &place);
02663 test->u.c_test = c_test;
02664 }
02665
02666 test = new_decision_test (DT_accept_insn, &place);
02667 test->u.insn.code_number = next_insn_code;
02668 test->u.insn.lineno = pattern_lineno;
02669 test->u.insn.num_clobbers_to_add = XVECLEN (x, 0) - i;
02670
02671 merge_trees (&head, &clobber_head);
02672 }
02673 }
02674 break;
02675
02676 case SPLIT:
02677
02678 printf ("extern rtx gen_split_%d (rtx, rtx *);\n", next_insn_code);
02679 break;
02680
02681 case PEEPHOLE2:
02682
02683 printf ("extern rtx gen_peephole2_%d (rtx, rtx *);\n",
02684 next_insn_code);
02685 break;
02686 }
02687
02688 return head;
02689 }
02690
02691 static void
02692 process_tree (struct decision_head *head, enum routine_type subroutine_type)
02693 {
02694 if (head->first == NULL)
02695 {
02696
02697 if (subroutine_type == PEEPHOLE2)
02698 return;
02699 }
02700 else
02701 {
02702 factor_tests (head);
02703
02704 next_subroutine_number = 0;
02705 break_out_subroutines (head, 1);
02706 find_afterward (head, NULL);
02707
02708
02709
02710
02711 simplify_tests(head);
02712
02713 write_subroutines (head, subroutine_type);
02714 }
02715
02716 write_subroutine (head, subroutine_type);
02717 }
02718
02719 extern int main (int, char **);
02720
02721 int
02722 main (int argc, char **argv)
02723 {
02724 rtx desc;
02725 struct decision_head recog_tree, split_tree, peephole2_tree, h;
02726
02727 progname = "genrecog";
02728
02729 memset (&recog_tree, 0, sizeof recog_tree);
02730 memset (&split_tree, 0, sizeof split_tree);
02731 memset (&peephole2_tree, 0, sizeof peephole2_tree);
02732
02733 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
02734 return (FATAL_EXIT_CODE);
02735
02736 next_insn_code = 0;
02737
02738 write_header ();
02739
02740
02741
02742 while (1)
02743 {
02744 desc = read_md_rtx (&pattern_lineno, &next_insn_code);
02745 if (desc == NULL)
02746 break;
02747
02748 switch (GET_CODE (desc))
02749 {
02750 case DEFINE_PREDICATE:
02751 case DEFINE_SPECIAL_PREDICATE:
02752 process_define_predicate (desc);
02753 break;
02754
02755 case DEFINE_INSN:
02756 h = make_insn_sequence (desc, RECOG);
02757 merge_trees (&recog_tree, &h);
02758 break;
02759
02760 case DEFINE_SPLIT:
02761 h = make_insn_sequence (desc, SPLIT);
02762 merge_trees (&split_tree, &h);
02763 break;
02764
02765 case DEFINE_PEEPHOLE2:
02766 h = make_insn_sequence (desc, PEEPHOLE2);
02767 merge_trees (&peephole2_tree, &h);
02768
02769 default:
02770 ;
02771 }
02772 }
02773
02774 if (error_count || have_error)
02775 return FATAL_EXIT_CODE;
02776
02777 puts ("\n\n");
02778
02779 process_tree (&recog_tree, RECOG);
02780 process_tree (&split_tree, SPLIT);
02781 process_tree (&peephole2_tree, PEEPHOLE2);
02782
02783 fflush (stdout);
02784 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
02785 }
02786
02787
02788 const char *
02789 get_insn_name (int code)
02790 {
02791 if (code < insn_name_ptr_size)
02792 return insn_name_ptr[code];
02793 else
02794 return NULL;
02795 }
02796
02797 static void
02798 record_insn_name (int code, const char *name)
02799 {
02800 static const char *last_real_name = "insn";
02801 static int last_real_code = 0;
02802 char *new;
02803
02804 if (insn_name_ptr_size <= code)
02805 {
02806 int new_size;
02807 new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
02808 insn_name_ptr = xrealloc (insn_name_ptr, sizeof(char *) * new_size);
02809 memset (insn_name_ptr + insn_name_ptr_size, 0,
02810 sizeof(char *) * (new_size - insn_name_ptr_size));
02811 insn_name_ptr_size = new_size;
02812 }
02813
02814 if (!name || name[0] == '\0')
02815 {
02816 new = xmalloc (strlen (last_real_name) + 10);
02817 sprintf (new, "%s+%d", last_real_name, code - last_real_code);
02818 }
02819 else
02820 {
02821 last_real_name = new = xstrdup (name);
02822 last_real_code = code;
02823 }
02824
02825 insn_name_ptr[code] = new;
02826 }
02827
02828 static void
02829 debug_decision_2 (struct decision_test *test)
02830 {
02831 switch (test->type)
02832 {
02833 case DT_mode:
02834 fprintf (stderr, "mode=%s", GET_MODE_NAME (test->u.mode));
02835 break;
02836 case DT_code:
02837 fprintf (stderr, "code=%s", GET_RTX_NAME (test->u.code));
02838 break;
02839 case DT_veclen:
02840 fprintf (stderr, "veclen=%d", test->u.veclen);
02841 break;
02842 case DT_elt_zero_int:
02843 fprintf (stderr, "elt0_i=%d", (int) test->u.intval);
02844 break;
02845 case DT_elt_one_int:
02846 fprintf (stderr, "elt1_i=%d", (int) test->u.intval);
02847 break;
02848 case DT_elt_zero_wide:
02849 fprintf (stderr, "elt0_w=" HOST_WIDE_INT_PRINT_DEC, test->u.intval);
02850 break;
02851 case DT_elt_zero_wide_safe:
02852 fprintf (stderr, "elt0_ws=" HOST_WIDE_INT_PRINT_DEC, test->u.intval);
02853 break;
02854 case DT_veclen_ge:
02855 fprintf (stderr, "veclen>=%d", test->u.veclen);
02856 break;
02857 case DT_dup:
02858 fprintf (stderr, "dup=%d", test->u.dup);
02859 break;
02860 case DT_pred:
02861 fprintf (stderr, "pred=(%s,%s)",
02862 test->u.pred.name, GET_MODE_NAME(test->u.pred.mode));
02863 break;
02864 case DT_c_test:
02865 {
02866 char sub[16+4];
02867 strncpy (sub, test->u.c_test, sizeof(sub));
02868 memcpy (sub+16, "...", 4);
02869 fprintf (stderr, "c_test=\"%s\"", sub);
02870 }
02871 break;
02872 case DT_accept_op:
02873 fprintf (stderr, "A_op=%d", test->u.opno);
02874 break;
02875 case DT_accept_insn:
02876 fprintf (stderr, "A_insn=(%d,%d)",
02877 test->u.insn.code_number, test->u.insn.num_clobbers_to_add);
02878 break;
02879
02880 default:
02881 gcc_unreachable ();
02882 }
02883 }
02884
02885 static void
02886 debug_decision_1 (struct decision *d, int indent)
02887 {
02888 int i;
02889 struct decision_test *test;
02890
02891 if (d == NULL)
02892 {
02893 for (i = 0; i < indent; ++i)
02894 putc (' ', stderr);
02895 fputs ("(nil)\n", stderr);
02896 return;
02897 }
02898
02899 for (i = 0; i < indent; ++i)
02900 putc (' ', stderr);
02901
02902 putc ('{', stderr);
02903 test = d->tests;
02904 if (test)
02905 {
02906 debug_decision_2 (test);
02907 while ((test = test->next) != NULL)
02908 {
02909 fputs (" + ", stderr);
02910 debug_decision_2 (test);
02911 }
02912 }
02913 fprintf (stderr, "} %d n %d a %d\n", d->number,
02914 (d->next ? d->next->number : -1),
02915 (d->afterward ? d->afterward->number : -1));
02916 }
02917
02918 static void
02919 debug_decision_0 (struct decision *d, int indent, int maxdepth)
02920 {
02921 struct decision *n;
02922 int i;
02923
02924 if (maxdepth < 0)
02925 return;
02926 if (d == NULL)
02927 {
02928 for (i = 0; i < indent; ++i)
02929 putc (' ', stderr);
02930 fputs ("(nil)\n", stderr);
02931 return;
02932 }
02933
02934 debug_decision_1 (d, indent);
02935 for (n = d->success.first; n ; n = n->next)
02936 debug_decision_0 (n, indent + 2, maxdepth - 1);
02937 }
02938
02939 void
02940 debug_decision (struct decision *d)
02941 {
02942 debug_decision_0 (d, 0, 1000000);
02943 }
02944
02945 void
02946 debug_decision_list (struct decision *d)
02947 {
02948 while (d)
02949 {
02950 debug_decision_0 (d, 0, 0);
02951 d = d->next;
02952 }
02953 }