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