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