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
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 #define ATTR_IND_SIMPLIFIED_P(RTX) (RTX_FLAG((RTX), unchanging))
00103 #define ATTR_CURR_SIMPLIFIED_P(RTX) (RTX_FLAG((RTX), in_struct))
00104 #define ATTR_PERMANENT_P(RTX) (RTX_FLAG((RTX), integrated))
00105 #define ATTR_EQ_ATTR_P(RTX) (RTX_FLAG((RTX), volatil))
00106
00107 #include "hconfig.h"
00108 #include "system.h"
00109 #include "rtl.h"
00110 #include "ggc.h"
00111 #include "gensupport.h"
00112
00113 #ifdef HAVE_SYS_RESOURCE_H
00114 # include <sys/resource.h>
00115 #endif
00116
00117
00118
00119 #include "obstack.h"
00120 #include "errors.h"
00121
00122 #include "genattrtab.h"
00123
00124 static struct obstack obstack1, obstack2;
00125 struct obstack *hash_obstack = &obstack1;
00126 struct obstack *temp_obstack = &obstack2;
00127
00128
00129 #define MAX_DIGITS (HOST_BITS_PER_INT * 3 / 10 + 3)
00130
00131
00132
00133
00134
00135
00136
00137
00138 struct insn_def
00139 {
00140 struct insn_def *next;
00141 rtx def;
00142 int insn_code;
00143 int insn_index;
00144 int lineno;
00145 int num_alternatives;
00146 int vec_idx;
00147 };
00148
00149
00150
00151
00152
00153 struct insn_ent
00154 {
00155 struct insn_ent *next;
00156 int insn_code;
00157 int insn_index;
00158 int lineno;
00159 };
00160
00161
00162
00163
00164
00165 struct attr_value
00166 {
00167 rtx value;
00168 struct attr_value *next;
00169 struct insn_ent *first_insn;
00170 int num_insns;
00171 int has_asm_insn;
00172 };
00173
00174
00175
00176 struct attr_desc
00177 {
00178 char *name;
00179 struct attr_desc *next;
00180 unsigned is_numeric : 1;
00181 unsigned negative_ok : 1;
00182 unsigned unsigned_p : 1;
00183 unsigned is_const : 1;
00184 unsigned is_special : 1;
00185 unsigned func_units_p : 1;
00186 unsigned blockage_p : 1;
00187 struct attr_value *first_value;
00188 struct attr_value *default_val;
00189 int lineno;
00190 };
00191
00192 #define NULL_ATTR (struct attr_desc *) NULL
00193
00194
00195
00196 struct range
00197 {
00198 int min;
00199 int max;
00200 };
00201
00202
00203
00204 struct delay_desc
00205 {
00206 rtx def;
00207 struct delay_desc *next;
00208 int num;
00209 int lineno;
00210 };
00211
00212
00213
00214 struct function_unit_op
00215 {
00216 rtx condexp;
00217 struct function_unit_op *next;
00218 int num;
00219 int ready;
00220 int issue_delay;
00221 rtx conflict_exp;
00222 rtx issue_exp;
00223 int lineno;
00224 };
00225
00226
00227
00228
00229 struct function_unit
00230 {
00231 const char *name;
00232 struct function_unit *next;
00233 int num;
00234 int multiplicity;
00235 int simultaneity;
00236
00237 rtx condexp;
00238 int num_opclasses;
00239 struct function_unit_op *ops;
00240 int needs_conflict_function;
00241 int needs_blockage_function;
00242 int needs_range_function;
00243 rtx default_cost;
00244 struct range issue_delay;
00245 int max_blockage;
00246 int first_lineno;
00247 };
00248
00249
00250
00251
00252 #define MAX_ATTRS_INDEX 256
00253 static struct attr_desc *attrs[MAX_ATTRS_INDEX];
00254 static struct insn_def *defs;
00255 static struct delay_desc *delays;
00256 static struct function_unit *units;
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 struct dimension
00294 {
00295 struct attr_desc *attr;
00296 rtx values;
00297 rtx current_value;
00298 int num_values;
00299 };
00300
00301
00302
00303 static int insn_code_number;
00304 static int insn_index_number;
00305 static int got_define_asm_attributes;
00306 static int must_extract;
00307 static int must_constrain;
00308 static int address_used;
00309 static int length_used;
00310 static int num_delays;
00311 static int have_annul_true, have_annul_false;
00312 static int num_units, num_unit_opclasses;
00313 static int num_insn_ents;
00314
00315 int num_dfa_decls;
00316
00317
00318
00319 enum operator {PLUS_OP, MINUS_OP, POS_MINUS_OP, EQ_OP, OR_OP, ORX_OP, MAX_OP, MIN_OP, RANGE_OP};
00320
00321
00322
00323 static int *insn_n_alternatives;
00324
00325
00326
00327
00328 static int *insn_alternatives;
00329
00330
00331
00332
00333
00334 static const char *current_alternative_string;
00335
00336
00337
00338 static rtx true_rtx, false_rtx;
00339
00340
00341
00342 static char *alternative_name;
00343
00344
00345
00346
00347 int reload_completed = 0;
00348
00349
00350
00351
00352 int optimize = 0;
00353
00354
00355
00356 #define SIMPLIFY_TEST_EXP(EXP,INSN_CODE,INSN_INDEX) \
00357 (ATTR_IND_SIMPLIFIED_P (EXP) || ATTR_CURR_SIMPLIFIED_P (EXP) ? (EXP) \
00358 : simplify_test_exp (EXP, INSN_CODE, INSN_INDEX))
00359
00360
00361
00362 #define SIMPLIFY_ALTERNATIVE(EXP) \
00363 if (current_alternative_string \
00364 && GET_CODE ((EXP)) == EQ_ATTR \
00365 && XSTR ((EXP), 0) == alternative_name) \
00366 (EXP) = (XSTR ((EXP), 1) == current_alternative_string \
00367 ? true_rtx : false_rtx);
00368
00369
00370
00371
00372 rtx global_rtl[GR_MAX];
00373 rtx pic_offset_table_rtx;
00374
00375 static void attr_hash_add_rtx PARAMS ((int, rtx));
00376 static void attr_hash_add_string PARAMS ((int, char *));
00377 static rtx attr_rtx PARAMS ((enum rtx_code, ...));
00378 static rtx attr_rtx_1 PARAMS ((enum rtx_code, va_list));
00379 static char *attr_string PARAMS ((const char *, int));
00380 static rtx check_attr_value PARAMS ((rtx, struct attr_desc *));
00381 static rtx convert_set_attr_alternative PARAMS ((rtx, struct insn_def *));
00382 static rtx convert_set_attr PARAMS ((rtx, struct insn_def *));
00383 static void check_defs PARAMS ((void));
00384 #if 0
00385 static rtx convert_const_symbol_ref PARAMS ((rtx, struct attr_desc *));
00386 #endif
00387 static rtx make_canonical PARAMS ((struct attr_desc *, rtx));
00388 static struct attr_value *get_attr_value PARAMS ((rtx, struct attr_desc *, int));
00389 static rtx copy_rtx_unchanging PARAMS ((rtx));
00390 static rtx copy_boolean PARAMS ((rtx));
00391 static void expand_delays PARAMS ((void));
00392 static rtx operate_exp PARAMS ((enum operator, rtx, rtx));
00393 static void expand_units PARAMS ((void));
00394 static rtx simplify_knowing PARAMS ((rtx, rtx));
00395 static rtx encode_units_mask PARAMS ((rtx));
00396 static void fill_attr PARAMS ((struct attr_desc *));
00397 static rtx substitute_address PARAMS ((rtx, rtx (*) (rtx), rtx (*) (rtx)));
00398 static void make_length_attrs PARAMS ((void));
00399 static rtx identity_fn PARAMS ((rtx));
00400 static rtx zero_fn PARAMS ((rtx));
00401 static rtx one_fn PARAMS ((rtx));
00402 static rtx max_fn PARAMS ((rtx));
00403 static void write_length_unit_log PARAMS ((void));
00404 static rtx simplify_cond PARAMS ((rtx, int, int));
00405 #if 0
00406 static rtx simplify_by_alternatives PARAMS ((rtx, int, int));
00407 #endif
00408 static rtx simplify_by_exploding PARAMS ((rtx));
00409 static int find_and_mark_used_attributes PARAMS ((rtx, rtx *, int *));
00410 static void unmark_used_attributes PARAMS ((rtx, struct dimension *, int));
00411 static int add_values_to_cover PARAMS ((struct dimension *));
00412 static int increment_current_value PARAMS ((struct dimension *, int));
00413 static rtx test_for_current_value PARAMS ((struct dimension *, int));
00414 static rtx simplify_with_current_value PARAMS ((rtx, struct dimension *, int));
00415 static rtx simplify_with_current_value_aux PARAMS ((rtx));
00416 static void clear_struct_flag PARAMS ((rtx));
00417 static int count_sub_rtxs PARAMS ((rtx, int));
00418 static void remove_insn_ent PARAMS ((struct attr_value *, struct insn_ent *));
00419 static void insert_insn_ent PARAMS ((struct attr_value *, struct insn_ent *));
00420 static rtx insert_right_side PARAMS ((enum rtx_code, rtx, rtx, int, int));
00421 static rtx make_alternative_compare PARAMS ((int));
00422 static int compute_alternative_mask PARAMS ((rtx, enum rtx_code));
00423 static rtx evaluate_eq_attr PARAMS ((rtx, rtx, int, int));
00424 static rtx simplify_and_tree PARAMS ((rtx, rtx *, int, int));
00425 static rtx simplify_or_tree PARAMS ((rtx, rtx *, int, int));
00426 static rtx simplify_test_exp PARAMS ((rtx, int, int));
00427 static rtx simplify_test_exp_in_temp PARAMS ((rtx, int, int));
00428 static void optimize_attrs PARAMS ((void));
00429 static void gen_attr PARAMS ((rtx, int));
00430 static int count_alternatives PARAMS ((rtx));
00431 static int compares_alternatives_p PARAMS ((rtx));
00432 static int contained_in_p PARAMS ((rtx, rtx));
00433 static void gen_insn PARAMS ((rtx, int));
00434 static void gen_delay PARAMS ((rtx, int));
00435 static void gen_unit PARAMS ((rtx, int));
00436 static void write_test_expr PARAMS ((rtx, int));
00437 static int max_attr_value PARAMS ((rtx, int*));
00438 static int or_attr_value PARAMS ((rtx, int*));
00439 static void walk_attr_value PARAMS ((rtx));
00440 static void write_attr_get PARAMS ((struct attr_desc *));
00441 static rtx eliminate_known_true PARAMS ((rtx, rtx, int, int));
00442 static void write_attr_set PARAMS ((struct attr_desc *, int, rtx,
00443 const char *, const char *, rtx,
00444 int, int));
00445 static void write_attr_case PARAMS ((struct attr_desc *, struct attr_value *,
00446 int, const char *, const char *, int, rtx));
00447 static void write_unit_name PARAMS ((const char *, int, const char *));
00448 static void write_attr_valueq PARAMS ((struct attr_desc *, const char *));
00449 static void write_attr_value PARAMS ((struct attr_desc *, rtx));
00450 static void write_upcase PARAMS ((const char *));
00451 static void write_indent PARAMS ((int));
00452 static void write_eligible_delay PARAMS ((const char *));
00453 static void write_function_unit_info PARAMS ((void));
00454 static void write_complex_function PARAMS ((struct function_unit *, const char *,
00455 const char *));
00456 static int write_expr_attr_cache PARAMS ((rtx, struct attr_desc *));
00457 static void write_toplevel_expr PARAMS ((rtx));
00458 static void write_const_num_delay_slots PARAMS ((void));
00459 static char *next_comma_elt PARAMS ((const char **));
00460 static struct attr_desc *find_attr PARAMS ((const char *, int));
00461 static struct attr_value *find_most_used PARAMS ((struct attr_desc *));
00462 static rtx find_single_value PARAMS ((struct attr_desc *));
00463 static void extend_range PARAMS ((struct range *, int, int));
00464 static rtx attr_eq PARAMS ((const char *, const char *));
00465 static const char *attr_numeral PARAMS ((int));
00466 static int attr_equal_p PARAMS ((rtx, rtx));
00467 static rtx attr_copy_rtx PARAMS ((rtx));
00468 static int attr_rtx_cost PARAMS ((rtx));
00469
00470 #define oballoc(size) obstack_alloc (hash_obstack, size)
00471
00472
00473
00474
00475
00476
00477
00478 struct attr_hash
00479 {
00480 struct attr_hash *next;
00481 int hashcode;
00482 union
00483 {
00484 char *str;
00485 rtx rtl;
00486 } u;
00487 };
00488
00489
00490
00491
00492
00493
00494
00495
00496 #define RTL_HASH_SIZE 4093
00497 struct attr_hash *attr_hash_table[RTL_HASH_SIZE];
00498
00499
00500
00501 #define RTL_HASH(RTL) ((long) (RTL) & 0777777)
00502
00503
00504
00505 static void
00506 attr_hash_add_rtx (hashcode, rtl)
00507 int hashcode;
00508 rtx rtl;
00509 {
00510 struct attr_hash *h;
00511
00512 h = (struct attr_hash *) obstack_alloc (hash_obstack,
00513 sizeof (struct attr_hash));
00514 h->hashcode = hashcode;
00515 h->u.rtl = rtl;
00516 h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
00517 attr_hash_table[hashcode % RTL_HASH_SIZE] = h;
00518 }
00519
00520
00521
00522 static void
00523 attr_hash_add_string (hashcode, str)
00524 int hashcode;
00525 char *str;
00526 {
00527 struct attr_hash *h;
00528
00529 h = (struct attr_hash *) obstack_alloc (hash_obstack,
00530 sizeof (struct attr_hash));
00531 h->hashcode = -hashcode;
00532 h->u.str = str;
00533 h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
00534 attr_hash_table[hashcode % RTL_HASH_SIZE] = h;
00535 }
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 static rtx
00548 attr_rtx_1 (code, p)
00549 enum rtx_code code;
00550 va_list p;
00551 {
00552 rtx rt_val = NULL_RTX;
00553 int hashcode;
00554 struct attr_hash *h;
00555 struct obstack *old_obstack = rtl_obstack;
00556
00557
00558
00559
00560
00561 if (GET_RTX_CLASS (code) == '1')
00562 {
00563 rtx arg0 = va_arg (p, rtx);
00564
00565
00566 if (! ATTR_PERMANENT_P (arg0))
00567 {
00568 rt_val = rtx_alloc (code);
00569 XEXP (rt_val, 0) = arg0;
00570 return rt_val;
00571 }
00572
00573 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0));
00574 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
00575 if (h->hashcode == hashcode
00576 && GET_CODE (h->u.rtl) == code
00577 && XEXP (h->u.rtl, 0) == arg0)
00578 return h->u.rtl;
00579
00580 if (h == 0)
00581 {
00582 rtl_obstack = hash_obstack;
00583 rt_val = rtx_alloc (code);
00584 XEXP (rt_val, 0) = arg0;
00585 }
00586 }
00587 else if (GET_RTX_CLASS (code) == 'c'
00588 || GET_RTX_CLASS (code) == '2'
00589 || GET_RTX_CLASS (code) == '<')
00590 {
00591 rtx arg0 = va_arg (p, rtx);
00592 rtx arg1 = va_arg (p, rtx);
00593
00594
00595 if (! ATTR_PERMANENT_P (arg0) || ! ATTR_PERMANENT_P (arg1))
00596 {
00597 rt_val = rtx_alloc (code);
00598 XEXP (rt_val, 0) = arg0;
00599 XEXP (rt_val, 1) = arg1;
00600 return rt_val;
00601 }
00602
00603 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1));
00604 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
00605 if (h->hashcode == hashcode
00606 && GET_CODE (h->u.rtl) == code
00607 && XEXP (h->u.rtl, 0) == arg0
00608 && XEXP (h->u.rtl, 1) == arg1)
00609 return h->u.rtl;
00610
00611 if (h == 0)
00612 {
00613 rtl_obstack = hash_obstack;
00614 rt_val = rtx_alloc (code);
00615 XEXP (rt_val, 0) = arg0;
00616 XEXP (rt_val, 1) = arg1;
00617 }
00618 }
00619 else if (GET_RTX_LENGTH (code) == 1
00620 && GET_RTX_FORMAT (code)[0] == 's')
00621 {
00622 char *arg0 = va_arg (p, char *);
00623
00624 if (code == SYMBOL_REF)
00625 arg0 = attr_string (arg0, strlen (arg0));
00626
00627 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0));
00628 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
00629 if (h->hashcode == hashcode
00630 && GET_CODE (h->u.rtl) == code
00631 && XSTR (h->u.rtl, 0) == arg0)
00632 return h->u.rtl;
00633
00634 if (h == 0)
00635 {
00636 rtl_obstack = hash_obstack;
00637 rt_val = rtx_alloc (code);
00638 XSTR (rt_val, 0) = arg0;
00639 }
00640 }
00641 else if (GET_RTX_LENGTH (code) == 2
00642 && GET_RTX_FORMAT (code)[0] == 's'
00643 && GET_RTX_FORMAT (code)[1] == 's')
00644 {
00645 char *arg0 = va_arg (p, char *);
00646 char *arg1 = va_arg (p, char *);
00647
00648 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1));
00649 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
00650 if (h->hashcode == hashcode
00651 && GET_CODE (h->u.rtl) == code
00652 && XSTR (h->u.rtl, 0) == arg0
00653 && XSTR (h->u.rtl, 1) == arg1)
00654 return h->u.rtl;
00655
00656 if (h == 0)
00657 {
00658 rtl_obstack = hash_obstack;
00659 rt_val = rtx_alloc (code);
00660 XSTR (rt_val, 0) = arg0;
00661 XSTR (rt_val, 1) = arg1;
00662 }
00663 }
00664 else if (code == CONST_INT)
00665 {
00666 HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT);
00667 if (arg0 == 0)
00668 return false_rtx;
00669 else if (arg0 == 1)
00670 return true_rtx;
00671 else
00672 goto nohash;
00673 }
00674 else
00675 {
00676 int i;
00677 const char *fmt;
00678 nohash:
00679 rt_val = rtx_alloc (code);
00680
00681 fmt = GET_RTX_FORMAT (code);
00682 for (i = 0; i < GET_RTX_LENGTH (code); i++)
00683 {
00684 switch (*fmt++)
00685 {
00686 case '0':
00687 break;
00688
00689 case 'i':
00690 XINT (rt_val, i) = va_arg (p, int);
00691 break;
00692
00693 case 'w':
00694 XWINT (rt_val, i) = va_arg (p, HOST_WIDE_INT);
00695 break;
00696
00697 case 's':
00698 XSTR (rt_val, i) = va_arg (p, char *);
00699 break;
00700
00701 case 'e':
00702 case 'u':
00703 XEXP (rt_val, i) = va_arg (p, rtx);
00704 break;
00705
00706 case 'E':
00707 XVEC (rt_val, i) = va_arg (p, rtvec);
00708 break;
00709
00710 default:
00711 abort ();
00712 }
00713 }
00714 return rt_val;
00715 }
00716
00717 rtl_obstack = old_obstack;
00718 attr_hash_add_rtx (hashcode, rt_val);
00719 ATTR_PERMANENT_P (rt_val) = 1;
00720 return rt_val;
00721 }
00722
00723 static rtx
00724 attr_rtx VPARAMS ((enum rtx_code code, ...))
00725 {
00726 rtx result;
00727
00728 #ifndef SGI_MONGOOSE
00729 VA_OPEN (p, code);
00730 VA_FIXEDARG (p, enum rtx_code, code);
00731 #else
00732 va_list p;
00733
00734 VA_START (p, code);
00735 #endif
00736 result = attr_rtx_1 (code, p);
00737 #ifndef SGI_MONGOOSE
00738 VA_CLOSE (p);
00739 #else
00740 va_end (p);
00741 #endif
00742 return result;
00743 }
00744
00745
00746
00747
00748
00749
00750 char *
00751 attr_printf VPARAMS ((unsigned int len, const char *fmt, ...))
00752 {
00753 char str[256];
00754
00755 #ifndef SGI_MONGOOSE
00756 VA_OPEN (p, fmt);
00757 VA_FIXEDARG (p, unsigned int, len);
00758 VA_FIXEDARG (p, const char *, fmt);
00759 #else
00760 va_list p;
00761
00762 VA_START (p, fmt);
00763 #endif
00764
00765 if (len > sizeof str - 1)
00766 abort ();
00767
00768 vsprintf (str, fmt, p);
00769 #ifndef SGI_MONGOOSE
00770 VA_CLOSE (p);
00771 #else
00772 va_end (p);
00773 #endif
00774
00775 return attr_string (str, strlen (str));
00776 }
00777
00778 static rtx
00779 attr_eq (name, value)
00780 const char *name, *value;
00781 {
00782 return attr_rtx (EQ_ATTR, attr_string (name, strlen (name)),
00783 attr_string (value, strlen (value)));
00784 }
00785
00786 static const char *
00787 attr_numeral (n)
00788 int n;
00789 {
00790 return XSTR (make_numeric_value (n), 0);
00791 }
00792
00793
00794
00795
00796 static char *
00797 attr_string (str, len)
00798 const char *str;
00799 int len;
00800 {
00801 struct attr_hash *h;
00802 int hashcode;
00803 int i;
00804 char *new_str;
00805
00806
00807 hashcode = (len + 1) * 613 + (unsigned) str[0];
00808 for (i = 1; i <= len; i += 2)
00809 hashcode = ((hashcode * 613) + (unsigned) str[i]);
00810 if (hashcode < 0)
00811 hashcode = -hashcode;
00812
00813
00814 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
00815 if (h->hashcode == -hashcode && h->u.str[0] == str[0]
00816 && !strncmp (h->u.str, str, len))
00817 return h->u.str;
00818
00819
00820 new_str = (char *) obstack_alloc (hash_obstack, len + 1);
00821 memcpy (new_str, str, len);
00822 new_str[len] = '\0';
00823 attr_hash_add_string (hashcode, new_str);
00824
00825 return new_str;
00826 }
00827
00828
00829
00830
00831
00832 static int
00833 attr_equal_p (x, y)
00834 rtx x, y;
00835 {
00836 return (x == y || (! (ATTR_PERMANENT_P (x) && ATTR_PERMANENT_P (y))
00837 && rtx_equal_p (x, y)));
00838 }
00839
00840
00841
00842
00843
00844 static rtx
00845 attr_copy_rtx (orig)
00846 rtx orig;
00847 {
00848 rtx copy;
00849 int i, j;
00850 RTX_CODE code;
00851 const char *format_ptr;
00852
00853
00854 if (ATTR_PERMANENT_P (orig))
00855 return orig;
00856
00857 code = GET_CODE (orig);
00858
00859 switch (code)
00860 {
00861 case REG:
00862 case QUEUED:
00863 case CONST_INT:
00864 case CONST_DOUBLE:
00865 case CONST_VECTOR:
00866 case SYMBOL_REF:
00867 case CODE_LABEL:
00868 case PC:
00869 case CC0:
00870 return orig;
00871
00872 default:
00873 break;
00874 }
00875
00876 copy = rtx_alloc (code);
00877 PUT_MODE (copy, GET_MODE (orig));
00878 ATTR_IND_SIMPLIFIED_P (copy) = ATTR_IND_SIMPLIFIED_P (orig);
00879 ATTR_CURR_SIMPLIFIED_P (copy) = ATTR_CURR_SIMPLIFIED_P (orig);
00880 ATTR_PERMANENT_P (copy) = ATTR_PERMANENT_P (orig);
00881 ATTR_EQ_ATTR_P (copy) = ATTR_EQ_ATTR_P (orig);
00882
00883 format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
00884
00885 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
00886 {
00887 switch (*format_ptr++)
00888 {
00889 case 'e':
00890 XEXP (copy, i) = XEXP (orig, i);
00891 if (XEXP (orig, i) != NULL)
00892 XEXP (copy, i) = attr_copy_rtx (XEXP (orig, i));
00893 break;
00894
00895 case 'E':
00896 case 'V':
00897 XVEC (copy, i) = XVEC (orig, i);
00898 if (XVEC (orig, i) != NULL)
00899 {
00900 XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
00901 for (j = 0; j < XVECLEN (copy, i); j++)
00902 XVECEXP (copy, i, j) = attr_copy_rtx (XVECEXP (orig, i, j));
00903 }
00904 break;
00905
00906 case 'n':
00907 case 'i':
00908 XINT (copy, i) = XINT (orig, i);
00909 break;
00910
00911 case 'w':
00912 XWINT (copy, i) = XWINT (orig, i);
00913 break;
00914
00915 case 's':
00916 case 'S':
00917 XSTR (copy, i) = XSTR (orig, i);
00918 break;
00919
00920 default:
00921 abort ();
00922 }
00923 }
00924 return copy;
00925 }
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 rtx
00942 check_attr_test (exp, is_const, lineno)
00943 rtx exp;
00944 int is_const;
00945 int lineno;
00946 {
00947 struct attr_desc *attr;
00948 struct attr_value *av;
00949 const char *name_ptr, *p;
00950 rtx orexp, newexp;
00951
00952 switch (GET_CODE (exp))
00953 {
00954 case EQ_ATTR:
00955
00956 if (XSTR (exp, 1)[0] == '!')
00957 return check_attr_test (attr_rtx (NOT,
00958 attr_eq (XSTR (exp, 0),
00959 &XSTR (exp, 1)[1])),
00960 is_const, lineno);
00961
00962 else if (n_comma_elts (XSTR (exp, 1)) == 1)
00963 {
00964 attr = find_attr (XSTR (exp, 0), 0);
00965 if (attr == NULL)
00966 {
00967 if (! strcmp (XSTR (exp, 0), "alternative"))
00968 {
00969 XSTR (exp, 0) = alternative_name;
00970
00971 ATTR_IND_SIMPLIFIED_P (exp) = 1;
00972 return exp;
00973 }
00974 else
00975 fatal ("unknown attribute `%s' in EQ_ATTR", XSTR (exp, 0));
00976 }
00977
00978 if (is_const && ! attr->is_const)
00979 fatal ("constant expression uses insn attribute `%s' in EQ_ATTR",
00980 XSTR (exp, 0));
00981
00982
00983
00984 exp = attr_eq (XSTR (exp, 0), XSTR (exp, 1));
00985
00986
00987
00988
00989 if (attr->is_const)
00990 ATTR_IND_SIMPLIFIED_P (exp) = 1;
00991
00992 if (attr->is_numeric)
00993 {
00994 for (p = XSTR (exp, 1); *p; p++)
00995 if (! ISDIGIT (*p))
00996 fatal ("attribute `%s' takes only numeric values",
00997 XSTR (exp, 0));
00998 }
00999 else
01000 {
01001 for (av = attr->first_value; av; av = av->next)
01002 if (GET_CODE (av->value) == CONST_STRING
01003 && ! strcmp (XSTR (exp, 1), XSTR (av->value, 0)))
01004 break;
01005
01006 if (av == NULL)
01007 fatal ("unknown value `%s' for `%s' attribute",
01008 XSTR (exp, 1), XSTR (exp, 0));
01009 }
01010 }
01011 else
01012 {
01013
01014 orexp = false_rtx;
01015 name_ptr = XSTR (exp, 1);
01016 while ((p = next_comma_elt (&name_ptr)) != NULL)
01017 {
01018 newexp = attr_eq (XSTR (exp, 0), p);
01019 orexp = insert_right_side (IOR, orexp, newexp, -2, -2);
01020 }
01021
01022 return check_attr_test (orexp, is_const, lineno);
01023 }
01024 break;
01025
01026 case ATTR_FLAG:
01027 break;
01028
01029 case CONST_INT:
01030
01031 if (XWINT (exp, 0))
01032 return true_rtx;
01033 else
01034 return false_rtx;
01035
01036 case IOR:
01037 case AND:
01038 XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const, lineno);
01039 XEXP (exp, 1) = check_attr_test (XEXP (exp, 1), is_const, lineno);
01040 break;
01041
01042 case NOT:
01043 XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const, lineno);
01044 break;
01045
01046 case MATCH_INSN:
01047 case MATCH_OPERAND:
01048 if (is_const)
01049 fatal ("RTL operator \"%s\" not valid in constant attribute test",
01050 GET_RTX_NAME (GET_CODE (exp)));
01051
01052 ATTR_IND_SIMPLIFIED_P (exp) = 1;
01053 break;
01054
01055 case LE: case LT: case GT: case GE:
01056 case LEU: case LTU: case GTU: case GEU:
01057 case NE: case EQ:
01058 if (GET_CODE (XEXP (exp, 0)) == SYMBOL_REF
01059 && GET_CODE (XEXP (exp, 1)) == SYMBOL_REF)
01060 exp = attr_rtx (GET_CODE (exp),
01061 attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 0), 0)),
01062 attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 1), 0)));
01063
01064 ATTR_IND_SIMPLIFIED_P (exp) = 1;
01065 break;
01066
01067 case SYMBOL_REF:
01068 if (is_const)
01069 {
01070
01071
01072 exp = attr_rtx (SYMBOL_REF, XSTR (exp, 0));
01073 ATTR_IND_SIMPLIFIED_P (exp) = 1;
01074 break;
01075 }
01076 default:
01077 fatal ("RTL operator \"%s\" not valid in attribute test",
01078 GET_RTX_NAME (GET_CODE (exp)));
01079 }
01080
01081 return exp;
01082 }
01083
01084
01085
01086
01087
01088
01089
01090 static rtx
01091 check_attr_value (exp, attr)
01092 rtx exp;
01093 struct attr_desc *attr;
01094 {
01095 struct attr_value *av;
01096 const char *p;
01097 int i;
01098
01099 switch (GET_CODE (exp))
01100 {
01101 case CONST_INT:
01102 if (attr && ! attr->is_numeric)
01103 {
01104 message_with_line (attr->lineno,
01105 "CONST_INT not valid for non-numeric attribute %s",
01106 attr->name);
01107 have_error = 1;
01108 break;
01109 }
01110
01111 if (INTVAL (exp) < 0 && ! attr->negative_ok)
01112 {
01113 message_with_line (attr->lineno,
01114 "negative numeric value specified for attribute %s",
01115 attr->name);
01116 have_error = 1;
01117 break;
01118 }
01119 break;
01120
01121 case CONST_STRING:
01122 if (! strcmp (XSTR (exp, 0), "*"))
01123 break;
01124
01125 if (attr == 0 || attr->is_numeric)
01126 {
01127 p = XSTR (exp, 0);
01128 if (attr && attr->negative_ok && *p == '-')
01129 p++;
01130 for (; *p; p++)
01131 if (! ISDIGIT (*p))
01132 {
01133 message_with_line (attr ? attr->lineno : 0,
01134 "non-numeric value for numeric attribute %s",
01135 attr ? attr->name : "internal");
01136 have_error = 1;
01137 break;
01138 }
01139 break;
01140 }
01141
01142 for (av = attr->first_value; av; av = av->next)
01143 if (GET_CODE (av->value) == CONST_STRING
01144 && ! strcmp (XSTR (av->value, 0), XSTR (exp, 0)))
01145 break;
01146
01147 if (av == NULL)
01148 {
01149 message_with_line (attr->lineno,
01150 "unknown value `%s' for `%s' attribute",
01151 XSTR (exp, 0), attr ? attr->name : "internal");
01152 have_error = 1;
01153 }
01154 break;
01155
01156 case IF_THEN_ELSE:
01157 XEXP (exp, 0) = check_attr_test (XEXP (exp, 0),
01158 attr ? attr->is_const : 0,
01159 attr ? attr->lineno : 0);
01160 XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
01161 XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
01162 break;
01163
01164 case PLUS:
01165 case MINUS:
01166 case MULT:
01167 case DIV:
01168 case MOD:
01169 if (attr && !attr->is_numeric)
01170 {
01171 message_with_line (attr->lineno,
01172 "invalid operation `%s' for non-numeric attribute value",
01173 GET_RTX_NAME (GET_CODE (exp)));
01174 have_error = 1;
01175 break;
01176 }
01177
01178
01179 case IOR:
01180 case AND:
01181 XEXP (exp, 0) = check_attr_value (XEXP (exp, 0), attr);
01182 XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
01183 break;
01184
01185 case FFS:
01186 XEXP (exp, 0) = check_attr_value (XEXP (exp, 0), attr);
01187 break;
01188
01189 case COND:
01190 if (XVECLEN (exp, 0) % 2 != 0)
01191 {
01192 message_with_line (attr->lineno,
01193 "first operand of COND must have even length");
01194 have_error = 1;
01195 break;
01196 }
01197
01198 for (i = 0; i < XVECLEN (exp, 0); i += 2)
01199 {
01200 XVECEXP (exp, 0, i) = check_attr_test (XVECEXP (exp, 0, i),
01201 attr ? attr->is_const : 0,
01202 attr ? attr->lineno : 0);
01203 XVECEXP (exp, 0, i + 1)
01204 = check_attr_value (XVECEXP (exp, 0, i + 1), attr);
01205 }
01206
01207 XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
01208 break;
01209
01210 case ATTR:
01211 {
01212 struct attr_desc *attr2 = find_attr (XSTR (exp, 0), 0);
01213 if (attr2 == NULL)
01214 {
01215 message_with_line (attr ? attr->lineno : 0,
01216 "unknown attribute `%s' in ATTR",
01217 XSTR (exp, 0));
01218 have_error = 1;
01219 }
01220 else if (attr && attr->is_const && ! attr2->is_const)
01221 {
01222 message_with_line (attr->lineno,
01223 "non-constant attribute `%s' referenced from `%s'",
01224 XSTR (exp, 0), attr->name);
01225 have_error = 1;
01226 }
01227 else if (attr
01228 && (attr->is_numeric != attr2->is_numeric
01229 || (! attr->negative_ok && attr2->negative_ok)))
01230 {
01231 message_with_line (attr->lineno,
01232 "numeric attribute mismatch calling `%s' from `%s'",
01233 XSTR (exp, 0), attr->name);
01234 have_error = 1;
01235 }
01236 }
01237 break;
01238
01239 case SYMBOL_REF:
01240
01241
01242
01243 return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
01244
01245 default:
01246 message_with_line (attr ? attr->lineno : 0,
01247 "invalid operation `%s' for attribute value",
01248 GET_RTX_NAME (GET_CODE (exp)));
01249 have_error = 1;
01250 break;
01251 }
01252
01253 return exp;
01254 }
01255
01256
01257
01258
01259 static rtx
01260 convert_set_attr_alternative (exp, id)
01261 rtx exp;
01262 struct insn_def *id;
01263 {
01264 int num_alt = id->num_alternatives;
01265 rtx condexp;
01266 int i;
01267
01268 if (XVECLEN (exp, 1) != num_alt)
01269 {
01270 message_with_line (id->lineno,
01271 "bad number of entries in SET_ATTR_ALTERNATIVE");
01272 have_error = 1;
01273 return NULL_RTX;
01274 }
01275
01276
01277
01278 condexp = rtx_alloc (COND);
01279 XVEC (condexp, 0) = rtvec_alloc ((num_alt - 1) * 2);
01280
01281 for (i = 0; i < num_alt - 1; i++)
01282 {
01283 const char *p;
01284 p = attr_numeral (i);
01285
01286 XVECEXP (condexp, 0, 2 * i) = attr_eq (alternative_name, p);
01287 XVECEXP (condexp, 0, 2 * i + 1) = XVECEXP (exp, 1, i);
01288 }
01289
01290 XEXP (condexp, 1) = XVECEXP (exp, 1, i);
01291
01292 return attr_rtx (SET, attr_rtx (ATTR, XSTR (exp, 0)), condexp);
01293 }
01294
01295
01296
01297
01298 static rtx
01299 convert_set_attr (exp, id)
01300 rtx exp;
01301 struct insn_def *id;
01302 {
01303 rtx newexp;
01304 const char *name_ptr;
01305 char *p;
01306 int n;
01307
01308
01309 n = n_comma_elts (XSTR (exp, 1));
01310 if (n == 1)
01311 return attr_rtx (SET,
01312 attr_rtx (ATTR, XSTR (exp, 0)),
01313 attr_rtx (CONST_STRING, XSTR (exp, 1)));
01314
01315 newexp = rtx_alloc (SET_ATTR_ALTERNATIVE);
01316 XSTR (newexp, 0) = XSTR (exp, 0);
01317 XVEC (newexp, 1) = rtvec_alloc (n);
01318
01319
01320 name_ptr = XSTR (exp, 1);
01321 n = 0;
01322 while ((p = next_comma_elt (&name_ptr)) != NULL)
01323 XVECEXP (newexp, 1, n++) = attr_rtx (CONST_STRING, p);
01324
01325 return convert_set_attr_alternative (newexp, id);
01326 }
01327
01328
01329
01330
01331
01332 static void
01333 check_defs ()
01334 {
01335 struct insn_def *id;
01336 struct attr_desc *attr;
01337 int i;
01338 rtx value;
01339
01340 for (id = defs; id; id = id->next)
01341 {
01342 if (XVEC (id->def, id->vec_idx) == NULL)
01343 continue;
01344
01345 for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
01346 {
01347 value = XVECEXP (id->def, id->vec_idx, i);
01348 switch (GET_CODE (value))
01349 {
01350 case SET:
01351 if (GET_CODE (XEXP (value, 0)) != ATTR)
01352 {
01353 message_with_line (id->lineno, "bad attribute set");
01354 have_error = 1;
01355 value = NULL_RTX;
01356 }
01357 break;
01358
01359 case SET_ATTR_ALTERNATIVE:
01360 value = convert_set_attr_alternative (value, id);
01361 break;
01362
01363 case SET_ATTR:
01364 value = convert_set_attr (value, id);
01365 break;
01366
01367 default:
01368 message_with_line (id->lineno, "invalid attribute code %s",
01369 GET_RTX_NAME (GET_CODE (value)));
01370 have_error = 1;
01371 value = NULL_RTX;
01372 }
01373 if (value == NULL_RTX)
01374 continue;
01375
01376 if ((attr = find_attr (XSTR (XEXP (value, 0), 0), 0)) == NULL)
01377 {
01378 message_with_line (id->lineno, "unknown attribute %s",
01379 XSTR (XEXP (value, 0), 0));
01380 have_error = 1;
01381 continue;
01382 }
01383
01384 XVECEXP (id->def, id->vec_idx, i) = value;
01385 XEXP (value, 1) = check_attr_value (XEXP (value, 1), attr);
01386 }
01387 }
01388 }
01389
01390 #if 0
01391
01392
01393
01394 static rtx
01395 convert_const_symbol_ref (exp, attr)
01396 rtx exp;
01397 struct attr_desc *attr;
01398 {
01399 rtx condexp;
01400 struct attr_value *av;
01401 int i;
01402 int num_alt = 0;
01403
01404 for (av = attr->first_value; av; av = av->next)
01405 num_alt++;
01406
01407
01408
01409
01410
01411 condexp = rtx_alloc (COND);
01412 XVEC (condexp, 0) = rtvec_alloc ((num_alt - 1) * 2);
01413 av = attr->first_value;
01414 XEXP (condexp, 1) = av->value;
01415
01416 for (i = num_alt - 2; av = av->next, i >= 0; i--)
01417 {
01418 char *p, *string;
01419 rtx value;
01420
01421 string = p = (char *) oballoc (2
01422 + strlen (attr->name)
01423 + strlen (XSTR (av->value, 0)));
01424 strcpy (p, attr->name);
01425 strcat (p, "_");
01426 strcat (p, XSTR (av->value, 0));
01427 for (; *p != '\0'; p++)
01428 *p = TOUPPER (*p);
01429
01430 value = attr_rtx (SYMBOL_REF, string);
01431 ATTR_IND_SIMPLIFIED_P (value) = 1;
01432
01433 XVECEXP (condexp, 0, 2 * i) = attr_rtx (EQ, exp, value);
01434
01435 XVECEXP (condexp, 0, 2 * i + 1) = av->value;
01436 }
01437
01438 return condexp;
01439 }
01440 #endif
01441
01442
01443
01444
01445
01446
01447 static rtx
01448 make_canonical (attr, exp)
01449 struct attr_desc *attr;
01450 rtx exp;
01451 {
01452 int i;
01453 rtx newexp;
01454
01455 switch (GET_CODE (exp))
01456 {
01457 case CONST_INT:
01458 exp = make_numeric_value (INTVAL (exp));
01459 break;
01460
01461 case CONST_STRING:
01462 if (! strcmp (XSTR (exp, 0), "*"))
01463 {
01464 if (attr == 0 || attr->default_val == 0)
01465 fatal ("(attr_value \"*\") used in invalid context");
01466 exp = attr->default_val->value;
01467 }
01468
01469 break;
01470
01471 case SYMBOL_REF:
01472 if (!attr->is_const || ATTR_IND_SIMPLIFIED_P (exp))
01473 break;
01474
01475
01476
01477 ATTR_IND_SIMPLIFIED_P (exp) = 1;
01478 #if 0
01479
01480
01481
01482 exp = convert_const_symbol_ref (exp, attr);
01483 ATTR_IND_SIMPLIFIED_P (exp) = 1;
01484 exp = check_attr_value (exp, attr);
01485
01486
01487
01488 goto cond;
01489 #else
01490 exp = check_attr_value (exp, attr);
01491 break;
01492 #endif
01493
01494 case IF_THEN_ELSE:
01495 newexp = rtx_alloc (COND);
01496 XVEC (newexp, 0) = rtvec_alloc (2);
01497 XVECEXP (newexp, 0, 0) = XEXP (exp, 0);
01498 XVECEXP (newexp, 0, 1) = XEXP (exp, 1);
01499
01500 XEXP (newexp, 1) = XEXP (exp, 2);
01501
01502 exp = newexp;
01503
01504
01505 case COND:
01506 {
01507 int allsame = 1;
01508 rtx defval;
01509
01510
01511 if (XVECLEN (exp, 0) == 0)
01512 return make_canonical (attr, XEXP (exp, 1));
01513 defval = XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1));
01514
01515 for (i = 0; i < XVECLEN (exp, 0); i += 2)
01516 {
01517 XVECEXP (exp, 0, i) = copy_boolean (XVECEXP (exp, 0, i));
01518 XVECEXP (exp, 0, i + 1)
01519 = make_canonical (attr, XVECEXP (exp, 0, i + 1));
01520 if (! rtx_equal_p (XVECEXP (exp, 0, i + 1), defval))
01521 allsame = 0;
01522 }
01523 if (allsame)
01524 return defval;
01525 }
01526 break;
01527
01528 default:
01529 break;
01530 }
01531
01532 return exp;
01533 }
01534
01535 static rtx
01536 copy_boolean (exp)
01537 rtx exp;
01538 {
01539 if (GET_CODE (exp) == AND || GET_CODE (exp) == IOR)
01540 return attr_rtx (GET_CODE (exp), copy_boolean (XEXP (exp, 0)),
01541 copy_boolean (XEXP (exp, 1)));
01542 return exp;
01543 }
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554 static struct attr_value *
01555 get_attr_value (value, attr, insn_code)
01556 rtx value;
01557 struct attr_desc *attr;
01558 int insn_code;
01559 {
01560 struct attr_value *av;
01561 int num_alt = 0;
01562
01563 value = make_canonical (attr, value);
01564 if (compares_alternatives_p (value))
01565 {
01566 if (insn_code < 0 || insn_alternatives == NULL)
01567 fatal ("(eq_attr \"alternatives\" ...) used in non-insn context");
01568 else
01569 num_alt = insn_alternatives[insn_code];
01570 }
01571
01572 for (av = attr->first_value; av; av = av->next)
01573 if (rtx_equal_p (value, av->value)
01574 && (num_alt == 0 || av->first_insn == NULL
01575 || insn_alternatives[av->first_insn->insn_code]))
01576 return av;
01577
01578 av = (struct attr_value *) oballoc (sizeof (struct attr_value));
01579 av->value = value;
01580 av->next = attr->first_value;
01581 attr->first_value = av;
01582 av->first_insn = NULL;
01583 av->num_insns = 0;
01584 av->has_asm_insn = 0;
01585
01586 return av;
01587 }
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603 static void
01604 expand_delays ()
01605 {
01606 struct delay_desc *delay;
01607 rtx condexp;
01608 rtx newexp;
01609 int i;
01610 char *p;
01611
01612
01613
01614 condexp = rtx_alloc (COND);
01615 XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
01616 XEXP (condexp, 1) = make_numeric_value (0);
01617
01618 for (i = 0, delay = delays; delay; i += 2, delay = delay->next)
01619 {
01620 XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
01621 XVECEXP (condexp, 0, i + 1)
01622 = make_numeric_value (XVECLEN (delay->def, 1) / 3);
01623 }
01624
01625 make_internal_attr ("*num_delay_slots", condexp, 0);
01626
01627
01628 if (num_delays > 1)
01629 {
01630 condexp = rtx_alloc (COND);
01631 XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
01632 XEXP (condexp, 1) = make_numeric_value (0);
01633
01634 for (i = 0, delay = delays; delay; i += 2, delay = delay->next)
01635 {
01636 XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
01637 XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num);
01638 }
01639
01640 make_internal_attr ("*delay_type", condexp, 1);
01641 }
01642
01643
01644
01645
01646 for (delay = delays; delay; delay = delay->next)
01647 {
01648 for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
01649 {
01650 condexp = XVECEXP (delay->def, 1, i);
01651 if (condexp == 0)
01652 condexp = false_rtx;
01653 newexp = attr_rtx (IF_THEN_ELSE, condexp,
01654 make_numeric_value (1), make_numeric_value (0));
01655
01656 p = attr_printf (sizeof "*delay__" + MAX_DIGITS * 2,
01657 "*delay_%d_%d", delay->num, i / 3);
01658 make_internal_attr (p, newexp, 1);
01659
01660 if (have_annul_true)
01661 {
01662 condexp = XVECEXP (delay->def, 1, i + 1);
01663 if (condexp == 0) condexp = false_rtx;
01664 newexp = attr_rtx (IF_THEN_ELSE, condexp,
01665 make_numeric_value (1),
01666 make_numeric_value (0));
01667 p = attr_printf (sizeof "*annul_true__" + MAX_DIGITS * 2,
01668 "*annul_true_%d_%d", delay->num, i / 3);
01669 make_internal_attr (p, newexp, 1);
01670 }
01671
01672 if (have_annul_false)
01673 {
01674 condexp = XVECEXP (delay->def, 1, i + 2);
01675 if (condexp == 0) condexp = false_rtx;
01676 newexp = attr_rtx (IF_THEN_ELSE, condexp,
01677 make_numeric_value (1),
01678 make_numeric_value (0));
01679 p = attr_printf (sizeof "*annul_false__" + MAX_DIGITS * 2,
01680 "*annul_false_%d_%d", delay->num, i / 3);
01681 make_internal_attr (p, newexp, 1);
01682 }
01683 }
01684 }
01685 }
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695 static rtx
01696 operate_exp (op, left, right)
01697 enum operator op;
01698 rtx left, right;
01699 {
01700 int left_value, right_value;
01701 rtx newexp;
01702 int i;
01703
01704
01705 if (GET_CODE (left) == CONST_STRING)
01706 {
01707
01708 if (GET_CODE (right) == CONST_STRING)
01709 {
01710 left_value = atoi (XSTR (left, 0));
01711 right_value = atoi (XSTR (right, 0));
01712 switch (op)
01713 {
01714 case PLUS_OP:
01715 i = left_value + right_value;
01716 break;
01717
01718 case MINUS_OP:
01719 i = left_value - right_value;
01720 break;
01721
01722 case POS_MINUS_OP:
01723 if (left_value > right_value)
01724 i = left_value - right_value;
01725 else
01726 i = 0;
01727 break;
01728
01729 case OR_OP:
01730 case ORX_OP:
01731 i = left_value | right_value;
01732 break;
01733
01734 case EQ_OP:
01735 i = left_value == right_value;
01736 break;
01737
01738 case RANGE_OP:
01739 i = (left_value << (HOST_BITS_PER_INT / 2)) | right_value;
01740 break;
01741
01742 case MAX_OP:
01743 if (left_value > right_value)
01744 i = left_value;
01745 else
01746 i = right_value;
01747 break;
01748
01749 case MIN_OP:
01750 if (left_value < right_value)
01751 i = left_value;
01752 else
01753 i = right_value;
01754 break;
01755
01756 default:
01757 abort ();
01758 }
01759
01760 if (i == left_value)
01761 return left;
01762 if (i == right_value)
01763 return right;
01764 return make_numeric_value (i);
01765 }
01766 else if (GET_CODE (right) == IF_THEN_ELSE)
01767 {
01768
01769 rtx newleft = operate_exp (op, left, XEXP (right, 1));
01770 rtx newright = operate_exp (op, left, XEXP (right, 2));
01771 if (rtx_equal_p (newleft, newright))
01772 return newleft;
01773 return attr_rtx (IF_THEN_ELSE, XEXP (right, 0), newleft, newright);
01774 }
01775 else if (GET_CODE (right) == COND)
01776 {
01777 int allsame = 1;
01778 rtx defval;
01779
01780 newexp = rtx_alloc (COND);
01781 XVEC (newexp, 0) = rtvec_alloc (XVECLEN (right, 0));
01782 defval = XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1));
01783
01784 for (i = 0; i < XVECLEN (right, 0); i += 2)
01785 {
01786 XVECEXP (newexp, 0, i) = XVECEXP (right, 0, i);
01787 XVECEXP (newexp, 0, i + 1)
01788 = operate_exp (op, left, XVECEXP (right, 0, i + 1));
01789 if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),
01790 defval))
01791 allsame = 0;
01792 }
01793
01794
01795
01796 if (allsame)
01797 return operate_exp (op, left, XEXP (right, 1));
01798
01799 return newexp;
01800 }
01801 else
01802 fatal ("badly formed attribute value");
01803 }
01804
01805
01806
01807 else if (op == ORX_OP && GET_CODE (right) == IF_THEN_ELSE)
01808 {
01809 return attr_rtx (IOR, left, right);
01810 }
01811
01812
01813 else if (GET_CODE (left) == IF_THEN_ELSE)
01814 {
01815 rtx newleft = operate_exp (op, XEXP (left, 1), right);
01816 rtx newright = operate_exp (op, XEXP (left, 2), right);
01817 if (rtx_equal_p (newleft, newright))
01818 return newleft;
01819 return attr_rtx (IF_THEN_ELSE, XEXP (left, 0), newleft, newright);
01820 }
01821 else if (GET_CODE (left) == COND)
01822 {
01823 int allsame = 1;
01824 rtx defval;
01825
01826 newexp = rtx_alloc (COND);
01827 XVEC (newexp, 0) = rtvec_alloc (XVECLEN (left, 0));
01828 defval = XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right);
01829
01830 for (i = 0; i < XVECLEN (left, 0); i += 2)
01831 {
01832 XVECEXP (newexp, 0, i) = XVECEXP (left, 0, i);
01833 XVECEXP (newexp, 0, i + 1)
01834 = operate_exp (op, XVECEXP (left, 0, i + 1), right);
01835 if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),
01836 defval))
01837 allsame = 0;
01838 }
01839
01840
01841
01842 if (allsame)
01843 return operate_exp (op, XEXP (left, 1), right);
01844
01845
01846
01847 if (rtx_equal_p (newexp, left))
01848 return left;
01849
01850 return newexp;
01851 }
01852
01853 else
01854 fatal ("badly formed attribute value");
01855
01856 return NULL;
01857 }
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891 static void
01892 expand_units ()
01893 {
01894 struct function_unit *unit, **unit_num;
01895 struct function_unit_op *op, **op_array, ***unit_ops;
01896 rtx unitsmask;
01897 rtx readycost;
01898 rtx newexp;
01899 const char *str;
01900 int i, j, u, num, nvalues;
01901
01902
01903
01904
01905
01906
01907
01908 for (unit = units; unit; unit = unit->next)
01909 {
01910 unit->condexp = check_attr_test (unit->condexp, 0, unit->first_lineno);
01911
01912 for (op = unit->ops; op; op = op->next)
01913 {
01914 rtx issue_delay = make_numeric_value (op->issue_delay);
01915 rtx issue_exp = issue_delay;
01916
01917
01918 if (op->conflict_exp != true_rtx)
01919 issue_exp = attr_rtx (IF_THEN_ELSE, op->conflict_exp,
01920 issue_exp, make_numeric_value (0));
01921 issue_exp = check_attr_value (make_canonical (NULL_ATTR,
01922 issue_exp),
01923 NULL_ATTR);
01924 issue_exp = simplify_knowing (issue_exp, unit->condexp);
01925 op->issue_exp = issue_exp;
01926
01927
01928 unit->needs_conflict_function = (unit->issue_delay.min
01929 != unit->issue_delay.max);
01930 if (unit->needs_conflict_function)
01931 {
01932 str = attr_printf ((strlen (unit->name) + sizeof "*_cost_"
01933 + MAX_DIGITS),
01934 "*%s_cost_%d", unit->name, op->num);
01935 make_internal_attr (str, issue_exp, 1);
01936 }
01937
01938
01939 op->condexp = check_attr_test (op->condexp, 0, op->lineno);
01940 }
01941 }
01942
01943
01944
01945 unitsmask = make_numeric_value (0);
01946 newexp = rtx_alloc (IF_THEN_ELSE);
01947 XEXP (newexp, 2) = make_numeric_value (0);
01948
01949
01950
01951
01952
01953
01954 #define NUM_UNITOP_CUTOFF 20
01955
01956 if (num_unit_opclasses < NUM_UNITOP_CUTOFF)
01957 {
01958
01959 for (unit = units; unit; unit = unit->next)
01960 {
01961 XEXP (newexp, 0) = unit->condexp;
01962 XEXP (newexp, 1) = make_numeric_value (1 << unit->num);
01963 unitsmask = operate_exp (OR_OP, unitsmask, newexp);
01964 }
01965 }
01966 else
01967 {
01968
01969 for (unit = units; unit; unit = unit->next)
01970 {
01971 XEXP (newexp, 0) = unit->condexp;
01972 XEXP (newexp, 1) = make_numeric_value (1 << unit->num);
01973 unitsmask = operate_exp (ORX_OP, unitsmask, attr_copy_rtx (newexp));
01974 }
01975 }
01976
01977
01978
01979 unitsmask = simplify_by_exploding (unitsmask);
01980
01981 if (num_unit_opclasses < NUM_UNITOP_CUTOFF)
01982 unitsmask = encode_units_mask (unitsmask);
01983 else
01984 {
01985
01986
01987
01988 unitsmask = attr_rtx (FFS, unitsmask);
01989 }
01990
01991 make_internal_attr ("*function_units_used", unitsmask, 10);
01992
01993
01994
01995 unit_ops = (struct function_unit_op ***)
01996 xmalloc ((num_units + 1) * sizeof (struct function_unit_op **));
01997 unit_num = (struct function_unit **)
01998 xmalloc ((num_units + 1) * sizeof (struct function_unit *));
01999
02000 unit_num[num_units] = unit = (struct function_unit *)
02001 xmalloc (sizeof (struct function_unit));
02002 unit->num = num_units;
02003 unit->num_opclasses = 0;
02004
02005 for (unit = units; unit; unit = unit->next)
02006 {
02007 unit_num[num_units]->num_opclasses += unit->num_opclasses;
02008 unit_num[unit->num] = unit;
02009 unit_ops[unit->num] = op_array = (struct function_unit_op **)
02010 xmalloc (unit->num_opclasses * sizeof (struct function_unit_op *));
02011
02012 for (op = unit->ops; op; op = op->next)
02013 op_array[op->num] = op;
02014 }
02015
02016
02017 unit_ops[num_units] = op_array = (struct function_unit_op **)
02018 xmalloc (unit_num[num_units]->num_opclasses
02019 * sizeof (struct function_unit_op *));
02020
02021 for (unit = units, i = 0; unit; i += unit->num_opclasses, unit = unit->next)
02022 memcpy (&op_array[i], unit_ops[unit->num],
02023 unit->num_opclasses * sizeof (struct function_unit_op *));
02024
02025
02026
02027 for (u = 0; u <= num_units; u++)
02028 {
02029 rtx orexp;
02030 int value;
02031
02032 unit = unit_num[u];
02033 op_array = unit_ops[unit->num];
02034 num = unit->num_opclasses;
02035
02036
02037 for (i = 0; i < num; i++)
02038 for (j = num - 1; j > i; j--)
02039 if (op_array[j - 1]->ready < op_array[j]->ready)
02040 {
02041 op = op_array[j];
02042 op_array[j] = op_array[j - 1];
02043 op_array[j - 1] = op;
02044 }
02045
02046
02047
02048 nvalues = 0; value = 1;
02049 for (i = num - 1; i >= 0; i--)
02050 if (op_array[i]->ready > value)
02051 {
02052 value = op_array[i]->ready;
02053 nvalues++;
02054 }
02055
02056 if (nvalues == 0)
02057 readycost = make_numeric_value (1);
02058 else
02059 {
02060
02061
02062 readycost = rtx_alloc (COND);
02063 XVEC (readycost, 0) = rtvec_alloc (nvalues * 2);
02064 XEXP (readycost, 1) = make_numeric_value (1);
02065
02066 nvalues = 0;
02067 orexp = false_rtx;
02068 value = op_array[0]->ready;
02069 for (i = 0; i < num; i++)
02070 {
02071 op = op_array[i];
02072 if (op->ready <= 1)
02073 break;
02074 else if (op->ready == value)
02075 orexp = insert_right_side (IOR, orexp, op->condexp, -2, -2);
02076 else
02077 {
02078 XVECEXP (readycost, 0, nvalues * 2) = orexp;
02079 XVECEXP (readycost, 0, nvalues * 2 + 1)
02080 = make_numeric_value (value);
02081 nvalues++;
02082 value = op->ready;
02083 orexp = op->condexp;
02084 }
02085 }
02086 XVECEXP (readycost, 0, nvalues * 2) = orexp;
02087 XVECEXP (readycost, 0, nvalues * 2 + 1) = make_numeric_value (value);
02088 }
02089
02090 if (u < num_units)
02091 {
02092 rtx max_blockage = 0, min_blockage = 0;
02093
02094
02095
02096 readycost = simplify_knowing (readycost, unit->condexp);
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140 for (op = unit->ops; op; op = op->next)
02141 {
02142 rtx blockage = op->issue_exp;
02143 blockage = simplify_knowing (blockage, unit->condexp);
02144
02145
02146
02147 if (max_blockage == 0)
02148 max_blockage = min_blockage = blockage;
02149 else
02150 {
02151 max_blockage
02152 = simplify_knowing (operate_exp (MAX_OP, max_blockage,
02153 blockage),
02154 unit->condexp);
02155 min_blockage
02156 = simplify_knowing (operate_exp (MIN_OP, min_blockage,
02157 blockage),
02158 unit->condexp);
02159 }
02160
02161
02162 str = attr_printf ((strlen (unit->name) + sizeof "*_block_"
02163 + MAX_DIGITS),
02164 "*%s_block_%d", unit->name, op->num);
02165 make_internal_attr (str, blockage, 1);
02166 }
02167
02168
02169 {
02170 int unknown;
02171 unit->max_blockage = max_attr_value (max_blockage, &unknown);
02172 }
02173
02174
02175
02176
02177 newexp = operate_exp (EQ_OP, max_blockage, min_blockage);
02178 newexp = simplify_knowing (newexp, unit->condexp);
02179 unit->needs_blockage_function
02180 = (GET_CODE (newexp) != CONST_STRING
02181 || atoi (XSTR (newexp, 0)) != 1);
02182
02183
02184
02185 unit->needs_range_function
02186 = (unit->needs_blockage_function
02187 || GET_CODE (max_blockage) != CONST_STRING);
02188
02189 if (unit->needs_range_function)
02190 {
02191
02192
02193 newexp = operate_exp (RANGE_OP, min_blockage, max_blockage);
02194 newexp = simplify_knowing (newexp, unit->condexp);
02195
02196 str = attr_printf ((strlen (unit->name)
02197 + sizeof "*_unit_blockage_range"),
02198 "*%s_unit_blockage_range", unit->name);
02199 make_internal_attr (str, newexp, 20);
02200 }
02201
02202 str = attr_printf (strlen (unit->name) + sizeof "*_unit_ready_cost",
02203 "*%s_unit_ready_cost", unit->name);
02204 }
02205 else
02206 str = "*result_ready_cost";
02207
02208
02209
02210 make_internal_attr (str, readycost, 0);
02211 }
02212
02213
02214
02215 for (unit = units; unit; unit = unit->next)
02216 {
02217 rtx caseexp;
02218
02219 if (! unit->needs_conflict_function
02220 && ! unit->needs_blockage_function)
02221 continue;
02222
02223 caseexp = rtx_alloc (COND);
02224 XVEC (caseexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2);
02225
02226 for (op = unit->ops; op; op = op->next)
02227 {
02228
02229
02230
02231 if (op->num == unit->num_opclasses - 1)
02232 {
02233 XEXP (caseexp, 1) = make_numeric_value (op->num);
02234 }
02235 else
02236 {
02237 XVECEXP (caseexp, 0, op->num * 2) = op->condexp;
02238 XVECEXP (caseexp, 0, op->num * 2 + 1)
02239 = make_numeric_value (op->num);
02240 }
02241 }
02242
02243
02244 str = attr_printf (strlen (unit->name) + sizeof "*_cases",
02245 "*%s_cases", unit->name);
02246 make_internal_attr (str, caseexp, 1);
02247 }
02248 }
02249
02250
02251
02252 static rtx
02253 simplify_knowing (exp, known_true)
02254 rtx exp, known_true;
02255 {
02256 if (GET_CODE (exp) != CONST_STRING)
02257 {
02258 int unknown = 0, max;
02259 max = max_attr_value (exp, &unknown);
02260 if (! unknown)
02261 {
02262 exp = attr_rtx (IF_THEN_ELSE, known_true, exp,
02263 make_numeric_value (max));
02264 exp = simplify_by_exploding (exp);
02265 }
02266 }
02267 return exp;
02268 }
02269
02270
02271
02272
02273
02274
02275 static rtx
02276 encode_units_mask (x)
02277 rtx x;
02278 {
02279 int i;
02280 int j;
02281 enum rtx_code code;
02282 const char *fmt;
02283
02284 code = GET_CODE (x);
02285
02286 switch (code)
02287 {
02288 case CONST_STRING:
02289 i = atoi (XSTR (x, 0));
02290 if (i < 0)
02291
02292 abort ();
02293 else if (i != 0 && i == (i & -i))
02294
02295 for (j = 0; (i >>= 1) != 0; j++)
02296 ;
02297 else
02298 j = ~i;
02299 return attr_rtx (CONST_STRING, attr_printf (MAX_DIGITS, "%d", j));
02300
02301 case REG:
02302 case QUEUED:
02303 case CONST_INT:
02304 case CONST_DOUBLE:
02305 case CONST_VECTOR:
02306 case SYMBOL_REF:
02307 case CODE_LABEL:
02308 case PC:
02309 case CC0:
02310 case EQ_ATTR:
02311 return x;
02312
02313 default:
02314 break;
02315 }
02316
02317
02318
02319
02320 fmt = GET_RTX_FORMAT (code);
02321 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02322 {
02323 switch (fmt[i])
02324 {
02325 case 'V':
02326 case 'E':
02327 for (j = 0; j < XVECLEN (x, i); j++)
02328 XVECEXP (x, i, j) = encode_units_mask (XVECEXP (x, i, j));
02329 break;
02330
02331 case 'e':
02332 XEXP (x, i) = encode_units_mask (XEXP (x, i));
02333 break;
02334 }
02335 }
02336 return x;
02337 }
02338
02339
02340
02341
02342
02343 static void
02344 fill_attr (attr)
02345 struct attr_desc *attr;
02346 {
02347 struct attr_value *av;
02348 struct insn_ent *ie;
02349 struct insn_def *id;
02350 int i;
02351 rtx value;
02352
02353
02354
02355 if (attr->is_const)
02356 return;
02357
02358 for (id = defs; id; id = id->next)
02359 {
02360
02361
02362 value = NULL;
02363 if (XVEC (id->def, id->vec_idx))
02364 for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
02365 if (! strcmp (XSTR (XEXP (XVECEXP (id->def, id->vec_idx, i), 0), 0),
02366 attr->name))
02367 value = XEXP (XVECEXP (id->def, id->vec_idx, i), 1);
02368
02369 if (value == NULL)
02370 av = attr->default_val;
02371 else
02372 av = get_attr_value (value, attr, id->insn_code);
02373
02374 ie = (struct insn_ent *) oballoc (sizeof (struct insn_ent));
02375 ie->insn_code = id->insn_code;
02376 ie->insn_index = id->insn_code;
02377 insert_insn_ent (av, ie);
02378 }
02379 }
02380
02381
02382
02383
02384
02385
02386
02387
02388 static rtx
02389 substitute_address (exp, no_address_fn, address_fn)
02390 rtx exp;
02391 rtx (*no_address_fn) PARAMS ((rtx));
02392 rtx (*address_fn) PARAMS ((rtx));
02393 {
02394 int i;
02395 rtx newexp;
02396
02397 if (GET_CODE (exp) == COND)
02398 {
02399
02400 address_used = 0;
02401 for (i = 0; i < XVECLEN (exp, 0); i += 2)
02402 walk_attr_value (XVECEXP (exp, 0, i));
02403
02404 if (address_used)
02405 return (*address_fn) (exp);
02406
02407
02408 newexp = rtx_alloc (COND);
02409 XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0));
02410 for (i = 0; i < XVECLEN (exp, 0); i += 2)
02411 {
02412 XVECEXP (newexp, 0, i) = XVECEXP (exp, 0, i);
02413 XVECEXP (newexp, 0, i + 1)
02414 = substitute_address (XVECEXP (exp, 0, i + 1),
02415 no_address_fn, address_fn);
02416 }
02417
02418 XEXP (newexp, 1) = substitute_address (XEXP (exp, 1),
02419 no_address_fn, address_fn);
02420
02421 return newexp;
02422 }
02423
02424 else if (GET_CODE (exp) == IF_THEN_ELSE)
02425 {
02426 address_used = 0;
02427 walk_attr_value (XEXP (exp, 0));
02428 if (address_used)
02429 return (*address_fn) (exp);
02430
02431 return attr_rtx (IF_THEN_ELSE,
02432 substitute_address (XEXP (exp, 0),
02433 no_address_fn, address_fn),
02434 substitute_address (XEXP (exp, 1),
02435 no_address_fn, address_fn),
02436 substitute_address (XEXP (exp, 2),
02437 no_address_fn, address_fn));
02438 }
02439
02440 return (*no_address_fn) (exp);
02441 }
02442
02443
02444 #ifdef SGI_MONGOOSE
02445 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
02446 #endif
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467 static void
02468 make_length_attrs ()
02469 {
02470 static const char *const new_names[] = {"*insn_default_length",
02471 "*insn_variable_length_p",
02472 "*insn_current_length"};
02473 static rtx (*const no_address_fn[]) PARAMS ((rtx)) = {identity_fn, zero_fn, zero_fn};
02474 static rtx (*const address_fn[]) PARAMS ((rtx)) = {max_fn, one_fn, identity_fn};
02475 size_t i;
02476 struct attr_desc *length_attr, *new_attr;
02477 struct attr_value *av, *new_av;
02478 struct insn_ent *ie, *new_ie;
02479
02480
02481
02482 length_attr = find_attr ("length", 0);
02483 if (length_attr == 0)
02484 return;
02485
02486 if (! length_attr->is_numeric)
02487 fatal ("length attribute must be numeric");
02488
02489 length_attr->is_const = 0;
02490 length_attr->is_special = 1;
02491
02492
02493 for (i = 0; i < ARRAY_SIZE (new_names); i++)
02494 {
02495 make_internal_attr (new_names[i],
02496 substitute_address (length_attr->default_val->value,
02497 no_address_fn[i], address_fn[i]),
02498 0);
02499 new_attr = find_attr (new_names[i], 0);
02500 for (av = length_attr->first_value; av; av = av->next)
02501 for (ie = av->first_insn; ie; ie = ie->next)
02502 {
02503 new_av = get_attr_value (substitute_address (av->value,
02504 no_address_fn[i],
02505 address_fn[i]),
02506 new_attr, ie->insn_code);
02507 new_ie = (struct insn_ent *) oballoc (sizeof (struct insn_ent));
02508 new_ie->insn_code = ie->insn_code;
02509 new_ie->insn_index = ie->insn_index;
02510 insert_insn_ent (new_av, new_ie);
02511 }
02512 }
02513 }
02514
02515
02516
02517 static rtx
02518 identity_fn (exp)
02519 rtx exp;
02520 {
02521 return exp;
02522 }
02523
02524 static rtx
02525 zero_fn (exp)
02526 rtx exp ATTRIBUTE_UNUSED;
02527 {
02528 return make_numeric_value (0);
02529 }
02530
02531 static rtx
02532 one_fn (exp)
02533 rtx exp ATTRIBUTE_UNUSED;
02534 {
02535 return make_numeric_value (1);
02536 }
02537
02538 static rtx
02539 max_fn (exp)
02540 rtx exp;
02541 {
02542 int unknown;
02543 return make_numeric_value (max_attr_value (exp, &unknown));
02544 }
02545
02546 static void
02547 write_length_unit_log ()
02548 {
02549 struct attr_desc *length_attr = find_attr ("length", 0);
02550 struct attr_value *av;
02551 struct insn_ent *ie;
02552 unsigned int length_unit_log, length_or;
02553 int unknown = 0;
02554
02555 if (length_attr == 0)
02556 return;
02557 length_or = or_attr_value (length_attr->default_val->value, &unknown);
02558 for (av = length_attr->first_value; av; av = av->next)
02559 for (ie = av->first_insn; ie; ie = ie->next)
02560 length_or |= or_attr_value (av->value, &unknown);
02561
02562 if (unknown)
02563 length_unit_log = 0;
02564 else
02565 {
02566 length_or = ~length_or;
02567 for (length_unit_log = 0; length_or & 1; length_or >>= 1)
02568 length_unit_log++;
02569 }
02570 printf ("int length_unit_log = %u;\n", length_unit_log);
02571 }
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581 static rtx
02582 simplify_cond (exp, insn_code, insn_index)
02583 rtx exp;
02584 int insn_code, insn_index;
02585 {
02586 int i, j;
02587
02588
02589 rtx defval = XEXP (exp, 1);
02590 rtx new_defval = XEXP (exp, 1);
02591 int len = XVECLEN (exp, 0);
02592 rtx *tests = (rtx *) xmalloc (len * sizeof (rtx));
02593 int allsame = 1;
02594 char *first_spacer;
02595 rtx ret;
02596
02597
02598 first_spacer = (char *) obstack_finish (rtl_obstack);
02599
02600 memcpy (tests, XVEC (exp, 0)->elem, len * sizeof (rtx));
02601
02602
02603 if (GET_CODE (defval) == COND)
02604 new_defval = simplify_cond (defval, insn_code, insn_index);
02605
02606
02607
02608 for (i = 0; i < len; i += 2)
02609 {
02610 rtx newtest, newval;
02611
02612
02613 newtest = simplify_test_exp_in_temp (tests[i], insn_code, insn_index);
02614 tests[i] = newtest;
02615
02616 newval = tests[i + 1];
02617
02618 if (GET_CODE (newval) == COND)
02619 newval = simplify_cond (newval, insn_code, insn_index);
02620
02621
02622 if (newtest == true_rtx)
02623 {
02624
02625
02626 len = i;
02627 defval = tests[i + 1];
02628 new_defval = newval;
02629 }
02630
02631 else if (newtest == false_rtx)
02632 {
02633
02634 for (j = i; j < len - 2; j++)
02635 tests[j] = tests[j + 2];
02636 len -= 2;
02637 }
02638
02639 else if (i > 0 && attr_equal_p (newval, tests[i - 1]))
02640 {
02641
02642
02643
02644 tests[i - 2]
02645 = insert_right_side (IOR, tests[i - 2], newtest,
02646 insn_code, insn_index);
02647
02648
02649 for (j = i; j < len - 2; j++)
02650 tests[j] = tests[j + 2];
02651 len -= 2;
02652 }
02653
02654 else
02655 tests[i + 1] = newval;
02656 }
02657
02658
02659
02660
02661 while (len > 0 && attr_equal_p (tests[len - 1], new_defval))
02662 len -= 2;
02663
02664
02665 if (len != XVECLEN (exp, 0) || new_defval != XEXP (exp, 1))
02666 allsame = 0;
02667 else
02668 for (i = 0; i < len; i++)
02669 if (! attr_equal_p (tests[i], XVECEXP (exp, 0, i)))
02670 {
02671 allsame = 0;
02672 break;
02673 }
02674
02675 if (len == 0)
02676 {
02677 if (GET_CODE (defval) == COND)
02678 ret = simplify_cond (defval, insn_code, insn_index);
02679 else
02680 ret = defval;
02681 }
02682 else if (allsame)
02683 ret = exp;
02684 else
02685 {
02686 rtx newexp = rtx_alloc (COND);
02687
02688 XVEC (newexp, 0) = rtvec_alloc (len);
02689 memcpy (XVEC (newexp, 0)->elem, tests, len * sizeof (rtx));
02690 XEXP (newexp, 1) = new_defval;
02691 ret = newexp;
02692 }
02693 free (tests);
02694 return ret;
02695 }
02696
02697
02698
02699 static void
02700 remove_insn_ent (av, ie)
02701 struct attr_value *av;
02702 struct insn_ent *ie;
02703 {
02704 struct insn_ent *previe;
02705
02706 if (av->first_insn == ie)
02707 av->first_insn = ie->next;
02708 else
02709 {
02710 for (previe = av->first_insn; previe->next != ie; previe = previe->next)
02711 ;
02712 previe->next = ie->next;
02713 }
02714
02715 av->num_insns--;
02716 if (ie->insn_code == -1)
02717 av->has_asm_insn = 0;
02718
02719 num_insn_ents--;
02720 }
02721
02722
02723
02724 static void
02725 insert_insn_ent (av, ie)
02726 struct attr_value *av;
02727 struct insn_ent *ie;
02728 {
02729 ie->next = av->first_insn;
02730 av->first_insn = ie;
02731 av->num_insns++;
02732 if (ie->insn_code == -1)
02733 av->has_asm_insn = 1;
02734
02735 num_insn_ents++;
02736 }
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747 static rtx
02748 insert_right_side (code, exp, term, insn_code, insn_index)
02749 enum rtx_code code;
02750 rtx exp;
02751 rtx term;
02752 int insn_code, insn_index;
02753 {
02754 rtx newexp;
02755
02756
02757 if (code == AND && term == true_rtx)
02758 return exp;
02759 if (code == AND && term == false_rtx)
02760 return false_rtx;
02761 if (code == AND && exp == true_rtx)
02762 return term;
02763 if (code == AND && exp == false_rtx)
02764 return false_rtx;
02765 if (code == IOR && term == true_rtx)
02766 return true_rtx;
02767 if (code == IOR && term == false_rtx)
02768 return exp;
02769 if (code == IOR && exp == true_rtx)
02770 return true_rtx;
02771 if (code == IOR && exp == false_rtx)
02772 return term;
02773 if (attr_equal_p (exp, term))
02774 return exp;
02775
02776 if (GET_CODE (term) == code)
02777 {
02778 exp = insert_right_side (code, exp, XEXP (term, 0),
02779 insn_code, insn_index);
02780 exp = insert_right_side (code, exp, XEXP (term, 1),
02781 insn_code, insn_index);
02782
02783 return exp;
02784 }
02785
02786 if (GET_CODE (exp) == code)
02787 {
02788 rtx new = insert_right_side (code, XEXP (exp, 1),
02789 term, insn_code, insn_index);
02790 if (new != XEXP (exp, 1))
02791
02792 newexp = attr_rtx (code, XEXP (exp, 0), new);
02793 else
02794 newexp = exp;
02795 }
02796 else
02797 {
02798
02799 newexp = attr_rtx (code, exp, term);
02800 }
02801
02802 return simplify_test_exp_in_temp (newexp, insn_code, insn_index);
02803 }
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813 static int
02814 compute_alternative_mask (exp, code)
02815 rtx exp;
02816 enum rtx_code code;
02817 {
02818 const char *string;
02819 if (GET_CODE (exp) == code)
02820 return compute_alternative_mask (XEXP (exp, 0), code)
02821 | compute_alternative_mask (XEXP (exp, 1), code);
02822
02823 else if (code == AND && GET_CODE (exp) == NOT
02824 && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
02825 && XSTR (XEXP (exp, 0), 0) == alternative_name)
02826 string = XSTR (XEXP (exp, 0), 1);
02827
02828 else if (code == IOR && GET_CODE (exp) == EQ_ATTR
02829 && XSTR (exp, 0) == alternative_name)
02830 string = XSTR (exp, 1);
02831
02832 else
02833 return 0;
02834
02835 if (string[1] == 0)
02836 return 1 << (string[0] - '0');
02837 return 1 << atoi (string);
02838 }
02839
02840
02841
02842
02843 static rtx
02844 make_alternative_compare (mask)
02845 int mask;
02846 {
02847 rtx newexp;
02848 int i;
02849
02850
02851 for (i = 0; (mask & (1 << i)) == 0; i++)
02852 ;
02853
02854 newexp = attr_rtx (EQ_ATTR, alternative_name, attr_numeral (i));
02855 ATTR_IND_SIMPLIFIED_P (newexp) = 1;
02856
02857 return newexp;
02858 }
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869 static rtx
02870 evaluate_eq_attr (exp, value, insn_code, insn_index)
02871 rtx exp;
02872 rtx value;
02873 int insn_code, insn_index;
02874 {
02875 rtx orexp, andexp;
02876 rtx right;
02877 rtx newexp;
02878 int i;
02879
02880 if (GET_CODE (value) == CONST_STRING)
02881 {
02882 if (! strcmp (XSTR (value, 0), XSTR (exp, 1)))
02883 newexp = true_rtx;
02884 else
02885 newexp = false_rtx;
02886 }
02887 else if (GET_CODE (value) == SYMBOL_REF)
02888 {
02889 char *p;
02890 char string[256];
02891
02892 if (GET_CODE (exp) != EQ_ATTR)
02893 abort ();
02894
02895 if (strlen (XSTR (exp, 0)) + strlen (XSTR (exp, 1)) + 2 > 256)
02896 abort ();
02897
02898 strcpy (string, XSTR (exp, 0));
02899 strcat (string, "_");
02900 strcat (string, XSTR (exp, 1));
02901 for (p = string; *p; p++)
02902 *p = TOUPPER (*p);
02903
02904 newexp = attr_rtx (EQ, value,
02905 attr_rtx (SYMBOL_REF,
02906 attr_string (string, strlen (string))));
02907 }
02908 else if (GET_CODE (value) == COND)
02909 {
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922 orexp = false_rtx;
02923 andexp = true_rtx;
02924
02925 if (current_alternative_string)
02926 clear_struct_flag (value);
02927
02928 for (i = 0; i < XVECLEN (value, 0); i += 2)
02929 {
02930 rtx this = simplify_test_exp_in_temp (XVECEXP (value, 0, i),
02931 insn_code, insn_index);
02932
02933 SIMPLIFY_ALTERNATIVE (this);
02934
02935 right = insert_right_side (AND, andexp, this,
02936 insn_code, insn_index);
02937 right = insert_right_side (AND, right,
02938 evaluate_eq_attr (exp,
02939 XVECEXP (value, 0,
02940 i + 1),
02941 insn_code, insn_index),
02942 insn_code, insn_index);
02943 orexp = insert_right_side (IOR, orexp, right,
02944 insn_code, insn_index);
02945
02946
02947 newexp = attr_rtx (NOT, this);
02948 andexp = insert_right_side (AND, andexp, newexp,
02949 insn_code, insn_index);
02950 }
02951
02952
02953 right = insert_right_side (AND, andexp,
02954 evaluate_eq_attr (exp, XEXP (value, 1),
02955 insn_code, insn_index),
02956 insn_code, insn_index);
02957 newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index);
02958 }
02959 else
02960 abort ();
02961
02962
02963
02964
02965 address_used = 0;
02966 walk_attr_value (newexp);
02967
02968 if (address_used)
02969 {
02970
02971 if (! ATTR_IND_SIMPLIFIED_P (exp))
02972 return copy_rtx_unchanging (exp);
02973 return exp;
02974 }
02975 else
02976 return newexp;
02977 }
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993 static rtx
02994 simplify_and_tree (exp, pterm, insn_code, insn_index)
02995 rtx exp;
02996 rtx *pterm;
02997 int insn_code, insn_index;
02998 {
02999 rtx left, right;
03000 rtx newexp;
03001 rtx temp;
03002 int left_eliminates_term, right_eliminates_term;
03003
03004 if (GET_CODE (exp) == AND)
03005 {
03006 left = simplify_and_tree (XEXP (exp, 0), pterm, insn_code, insn_index);
03007 right = simplify_and_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
03008 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
03009 {
03010 newexp = attr_rtx (GET_CODE (exp), left, right);
03011
03012 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
03013 }
03014 }
03015
03016 else if (GET_CODE (exp) == IOR)
03017 {
03018
03019
03020 temp = *pterm;
03021 left = simplify_and_tree (XEXP (exp, 0), &temp, insn_code, insn_index);
03022 left_eliminates_term = (temp == true_rtx);
03023
03024 temp = *pterm;
03025 right = simplify_and_tree (XEXP (exp, 1), &temp, insn_code, insn_index);
03026 right_eliminates_term = (temp == true_rtx);
03027
03028 if (left_eliminates_term && right_eliminates_term)
03029 *pterm = true_rtx;
03030
03031 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
03032 {
03033 newexp = attr_rtx (GET_CODE (exp), left, right);
03034
03035 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
03036 }
03037 }
03038
03039
03040
03041
03042 if (exp == *pterm)
03043 return true_rtx;
03044
03045 else if (GET_CODE (exp) == NOT && XEXP (exp, 0) == *pterm)
03046 return false_rtx;
03047
03048 else if (GET_CODE (*pterm) == NOT && exp == XEXP (*pterm, 0))
03049 return false_rtx;
03050
03051 else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == EQ_ATTR)
03052 {
03053 if (XSTR (exp, 0) != XSTR (*pterm, 0))
03054 return exp;
03055
03056 if (! strcmp (XSTR (exp, 1), XSTR (*pterm, 1)))
03057 return true_rtx;
03058 else
03059 return false_rtx;
03060 }
03061
03062 else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
03063 && GET_CODE (XEXP (exp, 0)) == EQ_ATTR)
03064 {
03065 if (XSTR (*pterm, 0) != XSTR (XEXP (exp, 0), 0))
03066 return exp;
03067
03068 if (! strcmp (XSTR (*pterm, 1), XSTR (XEXP (exp, 0), 1)))
03069 return false_rtx;
03070 else
03071 return true_rtx;
03072 }
03073
03074 else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
03075 && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR)
03076 {
03077 if (XSTR (exp, 0) != XSTR (XEXP (*pterm, 0), 0))
03078 return exp;
03079
03080 if (! strcmp (XSTR (exp, 1), XSTR (XEXP (*pterm, 0), 1)))
03081 return false_rtx;
03082 else
03083 *pterm = true_rtx;
03084 }
03085
03086 else if (GET_CODE (exp) == NOT && GET_CODE (*pterm) == NOT)
03087 {
03088 if (attr_equal_p (XEXP (exp, 0), XEXP (*pterm, 0)))
03089 return true_rtx;
03090 }
03091
03092 else if (GET_CODE (exp) == NOT)
03093 {
03094 if (attr_equal_p (XEXP (exp, 0), *pterm))
03095 return false_rtx;
03096 }
03097
03098 else if (GET_CODE (*pterm) == NOT)
03099 {
03100 if (attr_equal_p (XEXP (*pterm, 0), exp))
03101 return false_rtx;
03102 }
03103
03104 else if (attr_equal_p (exp, *pterm))
03105 return true_rtx;
03106
03107 return exp;
03108 }
03109
03110
03111
03112 static rtx
03113 simplify_or_tree (exp, pterm, insn_code, insn_index)
03114 rtx exp;
03115 rtx *pterm;
03116 int insn_code, insn_index;
03117 {
03118 rtx left, right;
03119 rtx newexp;
03120 rtx temp;
03121 int left_eliminates_term, right_eliminates_term;
03122
03123 if (GET_CODE (exp) == IOR)
03124 {
03125 left = simplify_or_tree (XEXP (exp, 0), pterm, insn_code, insn_index);
03126 right = simplify_or_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
03127 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
03128 {
03129 newexp = attr_rtx (GET_CODE (exp), left, right);
03130
03131 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
03132 }
03133 }
03134
03135 else if (GET_CODE (exp) == AND)
03136 {
03137
03138
03139 temp = *pterm;
03140 left = simplify_or_tree (XEXP (exp, 0), &temp, insn_code, insn_index);
03141 left_eliminates_term = (temp == false_rtx);
03142
03143 temp = *pterm;
03144 right = simplify_or_tree (XEXP (exp, 1), &temp, insn_code, insn_index);
03145 right_eliminates_term = (temp == false_rtx);
03146
03147 if (left_eliminates_term && right_eliminates_term)
03148 *pterm = false_rtx;
03149
03150 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
03151 {
03152 newexp = attr_rtx (GET_CODE (exp), left, right);
03153
03154 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
03155 }
03156 }
03157
03158 if (attr_equal_p (exp, *pterm))
03159 return false_rtx;
03160
03161 else if (GET_CODE (exp) == NOT && attr_equal_p (XEXP (exp, 0), *pterm))
03162 return true_rtx;
03163
03164 else if (GET_CODE (*pterm) == NOT && attr_equal_p (XEXP (*pterm, 0), exp))
03165 return true_rtx;
03166
03167 else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
03168 && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
03169 && XSTR (*pterm, 0) == XSTR (XEXP (exp, 0), 0))
03170 *pterm = false_rtx;
03171
03172 else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
03173 && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR
03174 && XSTR (exp, 0) == XSTR (XEXP (*pterm, 0), 0))
03175 return false_rtx;
03176
03177 return exp;
03178 }
03179
03180
03181 static int
03182 attr_rtx_cost (x)
03183 rtx x;
03184 {
03185 int cost = 0;
03186 enum rtx_code code;
03187 if (!x)
03188 return 0;
03189 code = GET_CODE (x);
03190 switch (code)
03191 {
03192 case MATCH_OPERAND:
03193 if (XSTR (x, 1)[0])
03194 return 10;
03195 else
03196 return 0;
03197 case EQ_ATTR:
03198
03199 if (!strcmp (XSTR (x, 0), "alternative"))
03200 return 0;
03201 else
03202 return 5;
03203 default:
03204 {
03205 int i, j;
03206 const char *fmt = GET_RTX_FORMAT (code);
03207 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
03208 {
03209 switch (fmt[i])
03210 {
03211 case 'V':
03212 case 'E':
03213 for (j = 0; j < XVECLEN (x, i); j++)
03214 cost += attr_rtx_cost (XVECEXP (x, i, j));
03215 break;
03216 case 'e':
03217 cost += attr_rtx_cost (XEXP (x, i));
03218 break;
03219 }
03220 }
03221 }
03222 break;
03223 }
03224 return cost;
03225 }
03226
03227
03228
03229
03230
03231
03232 static rtx
03233 simplify_test_exp_in_temp (exp, insn_code, insn_index)
03234 rtx exp;
03235 int insn_code, insn_index;
03236 {
03237 rtx x;
03238 struct obstack *old;
03239 if (ATTR_IND_SIMPLIFIED_P (exp))
03240 return exp;
03241 old = rtl_obstack;
03242 rtl_obstack = temp_obstack;
03243 x = simplify_test_exp (exp, insn_code, insn_index);
03244 rtl_obstack = old;
03245 if (x == exp || rtl_obstack == temp_obstack)
03246 return x;
03247 return attr_copy_rtx (x);
03248 }
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259 static rtx
03260 simplify_test_exp (exp, insn_code, insn_index)
03261 rtx exp;
03262 int insn_code, insn_index;
03263 {
03264 rtx left, right;
03265 struct attr_desc *attr;
03266 struct attr_value *av;
03267 struct insn_ent *ie;
03268 int i;
03269 rtx newexp = exp;
03270
03271
03272 if (ATTR_IND_SIMPLIFIED_P (exp) || ATTR_CURR_SIMPLIFIED_P (exp))
03273 return exp;
03274
03275 switch (GET_CODE (exp))
03276 {
03277 case AND:
03278 left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
03279 SIMPLIFY_ALTERNATIVE (left);
03280 if (left == false_rtx)
03281 return false_rtx;
03282 right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
03283 SIMPLIFY_ALTERNATIVE (right);
03284 if (left == false_rtx)
03285 return false_rtx;
03286
03287
03288
03289
03290 if ((GET_CODE (left) == IOR || GET_CODE (right) == IOR)
03291 && compute_alternative_mask (left, IOR)
03292 && compute_alternative_mask (right, IOR))
03293 {
03294 if (GET_CODE (left) == IOR)
03295 {
03296 rtx tem = left;
03297 left = right;
03298 right = tem;
03299 }
03300
03301 newexp = attr_rtx (IOR,
03302 attr_rtx (AND, left, XEXP (right, 0)),
03303 attr_rtx (AND, left, XEXP (right, 1)));
03304
03305 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
03306 }
03307
03308
03309 right = simplify_and_tree (right, &left, insn_code, insn_index);
03310 if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
03311 left = simplify_and_tree (left, &right, insn_code, insn_index);
03312
03313 if (left == false_rtx || right == false_rtx)
03314 return false_rtx;
03315 else if (left == true_rtx)
03316 {
03317 return right;
03318 }
03319 else if (right == true_rtx)
03320 {
03321 return left;
03322 }
03323
03324
03325
03326 else if (insn_code >= 0
03327 && (GET_CODE (left) == AND
03328 || (GET_CODE (left) == NOT
03329 && GET_CODE (XEXP (left, 0)) == EQ_ATTR
03330 && XSTR (XEXP (left, 0), 0) == alternative_name)
03331 || GET_CODE (right) == AND
03332 || (GET_CODE (right) == NOT
03333 && GET_CODE (XEXP (right, 0)) == EQ_ATTR
03334 && XSTR (XEXP (right, 0), 0) == alternative_name)))
03335 {
03336 i = compute_alternative_mask (exp, AND);
03337 if (i & ~insn_alternatives[insn_code])
03338 fatal ("invalid alternative specified for pattern number %d",
03339 insn_index);
03340
03341
03342 i ^= insn_alternatives[insn_code];
03343 if (i == 0)
03344 return false_rtx;
03345 else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
03346 {
03347
03348
03349
03350
03351 left = make_alternative_compare (i);
03352 right = simplify_and_tree (exp, &left, insn_code, insn_index);
03353 newexp = attr_rtx (AND, left, right);
03354
03355 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
03356 }
03357 }
03358
03359 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
03360 {
03361 newexp = attr_rtx (AND, left, right);
03362 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
03363 }
03364 break;
03365
03366 case IOR:
03367 left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
03368 SIMPLIFY_ALTERNATIVE (left);
03369 if (left == true_rtx)
03370 return true_rtx;
03371 right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
03372 SIMPLIFY_ALTERNATIVE (right);
03373 if (right == true_rtx)
03374 return true_rtx;
03375
03376 right = simplify_or_tree (right, &left, insn_code, insn_index);
03377 if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
03378 left = simplify_or_tree (left, &right, insn_code, insn_index);
03379
03380 if (right == true_rtx || left == true_rtx)
03381 return true_rtx;
03382 else if (left == false_rtx)
03383 {
03384 return right;
03385 }
03386 else if (right == false_rtx)
03387 {
03388 return left;
03389 }
03390
03391
03392
03393
03394
03395
03396
03397
03398 else if (GET_CODE (left) == AND && GET_CODE (right) == AND
03399 && attr_equal_p (XEXP (left, 0), XEXP (right, 0)))
03400 {
03401 newexp = attr_rtx (IOR, XEXP (left, 1), XEXP (right, 1));
03402
03403 left = XEXP (left, 0);
03404 right = newexp;
03405 newexp = attr_rtx (AND, left, right);
03406 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
03407 }
03408
03409
03410
03411
03412 else if (insn_code >= 0
03413 && (GET_CODE (left) == IOR
03414 || (GET_CODE (left) == EQ_ATTR
03415 && XSTR (left, 0) == alternative_name)
03416 || GET_CODE (right) == IOR
03417 || (GET_CODE (right) == EQ_ATTR
03418 && XSTR (right, 0) == alternative_name)))
03419 {
03420 i = compute_alternative_mask (exp, IOR);
03421 if (i & ~insn_alternatives[insn_code])
03422 fatal ("invalid alternative specified for pattern number %d",
03423 insn_index);
03424
03425
03426 i ^= insn_alternatives[insn_code];
03427 if (i == 0)
03428 return true_rtx;
03429 else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
03430 {
03431
03432
03433
03434
03435 left = make_alternative_compare (i);
03436 right = simplify_and_tree (exp, &left, insn_code, insn_index);
03437 newexp = attr_rtx (IOR, attr_rtx (NOT, left), right);
03438
03439 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
03440 }
03441 }
03442
03443 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
03444 {
03445 newexp = attr_rtx (IOR, left, right);
03446 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
03447 }
03448 break;
03449
03450 case NOT:
03451 if (GET_CODE (XEXP (exp, 0)) == NOT)
03452 {
03453 left = SIMPLIFY_TEST_EXP (XEXP (XEXP (exp, 0), 0),
03454 insn_code, insn_index);
03455 SIMPLIFY_ALTERNATIVE (left);
03456 return left;
03457 }
03458
03459 left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
03460 SIMPLIFY_ALTERNATIVE (left);
03461 if (GET_CODE (left) == NOT)
03462 return XEXP (left, 0);
03463
03464 if (left == false_rtx)
03465 return true_rtx;
03466 else if (left == true_rtx)
03467 return false_rtx;
03468
03469
03470 else if (GET_CODE (left) == IOR)
03471 {
03472 newexp = attr_rtx (AND,
03473 attr_rtx (NOT, XEXP (left, 0)),
03474 attr_rtx (NOT, XEXP (left, 1)));
03475
03476 newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
03477 }
03478 else if (GET_CODE (left) == AND)
03479 {
03480 newexp = attr_rtx (IOR,
03481 attr_rtx (NOT, XEXP (left, 0)),
03482 attr_rtx (NOT, XEXP (left, 1)));
03483
03484 newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
03485 }
03486 else if (left != XEXP (exp, 0))
03487 {
03488 newexp = attr_rtx (NOT, left);
03489 }
03490 break;
03491
03492 case EQ_ATTR:
03493 if (current_alternative_string && XSTR (exp, 0) == alternative_name)
03494 return (XSTR (exp, 1) == current_alternative_string
03495 ? true_rtx : false_rtx);
03496
03497
03498
03499
03500 if (XSTR (exp, 0) != alternative_name
03501 && (attr = find_attr (XSTR (exp, 0), 0)) != NULL)
03502 for (av = attr->first_value; av; av = av->next)
03503 for (ie = av->first_insn; ie; ie = ie->next)
03504 if (ie->insn_code == insn_code)
03505 {
03506 rtx x;
03507 x = evaluate_eq_attr (exp, av->value, insn_code, insn_index);
03508 x = SIMPLIFY_TEST_EXP (x, insn_code, insn_index);
03509 if (attr_rtx_cost(x) < 20)
03510 return x;
03511 }
03512 break;
03513
03514 default:
03515 break;
03516 }
03517
03518
03519
03520
03521 if (insn_code != -2
03522 && ! ATTR_IND_SIMPLIFIED_P (newexp))
03523 return copy_rtx_unchanging (newexp);
03524
03525 return newexp;
03526 }
03527
03528
03529
03530
03531
03532 static void
03533 optimize_attrs ()
03534 {
03535 struct attr_desc *attr;
03536 struct attr_value *av;
03537 struct insn_ent *ie;
03538 rtx newexp;
03539 int i;
03540 struct attr_value_list
03541 {
03542 struct attr_value *av;
03543 struct insn_ent *ie;
03544 struct attr_desc *attr;
03545 struct attr_value_list *next;
03546 };
03547 struct attr_value_list **insn_code_values;
03548 struct attr_value_list *ivbuf;
03549 struct attr_value_list *iv;
03550
03551
03552
03553
03554 if (num_insn_ents == 0)
03555 return;
03556
03557
03558 insn_code_values
03559 = (struct attr_value_list **) xmalloc ((insn_code_number + 2)
03560 * sizeof (struct attr_value_list *));
03561 memset ((char *) insn_code_values, 0,
03562 (insn_code_number + 2) * sizeof (struct attr_value_list *));
03563
03564
03565 insn_code_values += 2;
03566
03567 iv = ivbuf = ((struct attr_value_list *)
03568 xmalloc (num_insn_ents * sizeof (struct attr_value_list)));
03569
03570 for (i = 0; i < MAX_ATTRS_INDEX; i++)
03571 for (attr = attrs[i]; attr; attr = attr->next)
03572 for (av = attr->first_value; av; av = av->next)
03573 for (ie = av->first_insn; ie; ie = ie->next)
03574 {
03575 iv->attr = attr;
03576 iv->av = av;
03577 iv->ie = ie;
03578 iv->next = insn_code_values[ie->insn_code];
03579 insn_code_values[ie->insn_code] = iv;
03580 iv++;
03581 }
03582
03583
03584 if (iv != ivbuf + num_insn_ents)
03585 abort ();
03586
03587
03588 for (i = -2; i < insn_code_number; i++)
03589 {
03590
03591
03592 for (iv = insn_code_values[i]; iv; iv = iv->next)
03593 clear_struct_flag (iv->av->value);
03594
03595 for (iv = insn_code_values[i]; iv; iv = iv->next)
03596 {
03597 struct obstack *old = rtl_obstack;
03598
03599 attr = iv->attr;
03600 av = iv->av;
03601 ie = iv->ie;
03602 if (GET_CODE (av->value) != COND)
03603 continue;
03604
03605 rtl_obstack = temp_obstack;
03606 #if 0
03607 if (insn_n_alternatives[ie->insn_code] > 6
03608 && count_sub_rtxs (av->value, 200) >= 200)
03609 newexp = simplify_by_alternatives (av->value, ie->insn_code,
03610 ie->insn_index);
03611 else
03612 #endif
03613 newexp = av->value;
03614 while (GET_CODE (newexp) == COND)
03615 {
03616 rtx newexp2 = simplify_cond (newexp, ie->insn_code,
03617 ie->insn_index);
03618 if (newexp2 == newexp)
03619 break;
03620 newexp = newexp2;
03621 }
03622
03623 rtl_obstack = old;
03624 if (newexp != av->value)
03625 {
03626 newexp = attr_copy_rtx (newexp);
03627 remove_insn_ent (av, ie);
03628 av = get_attr_value (newexp, attr, ie->insn_code);
03629 iv->av = av;
03630 insert_insn_ent (av, ie);
03631 }
03632 }
03633 }
03634
03635 free (ivbuf);
03636 free (insn_code_values - 2);
03637 }
03638
03639 #if 0
03640 static rtx
03641 simplify_by_alternatives (exp, insn_code, insn_index)
03642 rtx exp;
03643 int insn_code, insn_index;
03644 {
03645 int i;
03646 int len = insn_n_alternatives[insn_code];
03647 rtx newexp = rtx_alloc (COND);
03648 rtx ultimate;
03649
03650 XVEC (newexp, 0) = rtvec_alloc (len * 2);
03651
03652
03653
03654
03655 for (ultimate = exp; GET_CODE (ultimate) == COND;)
03656 ultimate = XEXP (ultimate, 1);
03657 XEXP (newexp, 1) = ultimate;
03658
03659 for (i = 0; i < insn_n_alternatives[insn_code]; i++)
03660 {
03661 current_alternative_string = attr_numeral (i);
03662 XVECEXP (newexp, 0, i * 2) = make_alternative_compare (1 << i);
03663 XVECEXP (newexp, 0, i * 2 + 1)
03664 = simplify_cond (exp, insn_code, insn_index);
03665 }
03666
03667 current_alternative_string = 0;
03668 return simplify_cond (newexp, insn_code, insn_index);
03669 }
03670 #endif
03671
03672
03673
03674
03675
03676 static rtx
03677 simplify_by_exploding (exp)
03678 rtx exp;
03679 {
03680 rtx list = 0, link, condexp, defval = NULL_RTX;
03681 struct dimension *space;
03682 rtx *condtest, *condval;
03683 int i, j, total, ndim = 0;
03684 int most_tests, num_marks, new_marks;
03685 rtx ret;
03686
03687
03688 if (! find_and_mark_used_attributes (exp, &list, &ndim) || ndim == 0)
03689 {
03690 unmark_used_attributes (list, 0, 0);
03691 return exp;
03692 }
03693
03694
03695
03696
03697
03698
03699
03700 space = (struct dimension *) xmalloc (ndim * sizeof (struct dimension));
03701
03702 total = 1;
03703 for (ndim = 0; list; ndim++)
03704 {
03705
03706
03707 const char *name = XSTR (XEXP (list, 0), 0);
03708 rtx *prev;
03709
03710 if ((space[ndim].attr = find_attr (name, 0)) == 0
03711 || space[ndim].attr->is_numeric)
03712 {
03713 unmark_used_attributes (list, space, ndim);
03714 return exp;
03715 }
03716
03717
03718 space[ndim].num_values = 0;
03719 space[ndim].values = 0;
03720 prev = &list;
03721 for (link = list; link; link = *prev)
03722 if (! strcmp (XSTR (XEXP (link, 0), 0), name))
03723 {
03724 space[ndim].num_values++;
03725 *prev = XEXP (link, 1);
03726 XEXP (link, 1) = space[ndim].values;
03727 space[ndim].values = link;
03728 }
03729 else
03730 prev = &XEXP (link, 1);
03731
03732
03733
03734
03735 total *= add_values_to_cover (&space[ndim]);
03736 }
03737
03738
03739
03740 for (i = 0; i < ndim; i++)
03741 for (j = ndim - 1; j > i; j--)
03742 if ((space[j-1].attr->is_const && !space[j].attr->is_const)
03743 || space[j-1].num_values < space[j].num_values)
03744 {
03745 struct dimension tmp;
03746 tmp = space[j];
03747 space[j] = space[j - 1];
03748 space[j - 1] = tmp;
03749 }
03750
03751
03752 for (i = 0; i < ndim; i++)
03753 space[i].current_value = space[i].values;
03754
03755 condtest = (rtx *) xmalloc (total * sizeof (rtx));
03756 condval = (rtx *) xmalloc (total * sizeof (rtx));
03757
03758
03759
03760 for (i = 0;; i++)
03761 {
03762 condtest[i] = test_for_current_value (space, ndim);
03763 condval[i] = simplify_with_current_value (exp, space, ndim);
03764 if (! increment_current_value (space, ndim))
03765 break;
03766 }
03767 if (i != total - 1)
03768 abort ();
03769
03770
03771 unmark_used_attributes (0, space, ndim);
03772 free (space);
03773
03774
03775 most_tests = -1;
03776 for (i = num_marks = 0; i < total; i++)
03777 if (GET_CODE (condval[i]) == CONST_STRING
03778 && ! ATTR_EQ_ATTR_P (condval[i]))
03779 {
03780
03781 ATTR_EQ_ATTR_P (condval[i]) = 1;
03782 for (j = new_marks = 0; j < total; j++)
03783 if (GET_CODE (condval[j]) == CONST_STRING
03784 && ATTR_EQ_ATTR_P (condval[j]))
03785 new_marks++;
03786 if (new_marks - num_marks > most_tests)
03787 {
03788 most_tests = new_marks - num_marks;
03789 defval = condval[i];
03790 }
03791 num_marks = new_marks;
03792 }
03793
03794 for (i = 0; i < total; i++)
03795 ATTR_EQ_ATTR_P (condval[i]) = 0;
03796
03797
03798 if (num_marks == 0)
03799 ret = exp;
03800
03801
03802 else if (total == most_tests)
03803 ret = defval;
03804
03805
03806
03807
03808 else
03809 {
03810 condexp = rtx_alloc (COND);
03811 XVEC (condexp, 0) = rtvec_alloc ((total - most_tests) * 2);
03812 XEXP (condexp, 1) = defval;
03813 for (i = j = 0; i < total; i++)
03814 if (condval[i] != defval)
03815 {
03816 XVECEXP (condexp, 0, 2 * j) = condtest[i];
03817 XVECEXP (condexp, 0, 2 * j + 1) = condval[i];
03818 j++;
03819 }
03820 ret = condexp;
03821 }
03822 free (condtest);
03823 free (condval);
03824 return ret;
03825 }
03826
03827
03828
03829
03830
03831 static int
03832 find_and_mark_used_attributes (exp, terms, nterms)
03833 rtx exp, *terms;
03834 int *nterms;
03835 {
03836 int i;
03837
03838 switch (GET_CODE (exp))
03839 {
03840 case EQ_ATTR:
03841 if (! ATTR_EQ_ATTR_P (exp))
03842 {
03843 rtx link = rtx_alloc (EXPR_LIST);
03844 XEXP (link, 0) = exp;
03845 XEXP (link, 1) = *terms;
03846 *terms = link;
03847 *nterms += 1;
03848 ATTR_EQ_ATTR_P (exp) = 1;
03849 }
03850 return 1;
03851
03852 case CONST_STRING:
03853 case CONST_INT:
03854 return 1;
03855
03856 case IF_THEN_ELSE:
03857 if (! find_and_mark_used_attributes (XEXP (exp, 2), terms, nterms))
03858 return 0;
03859 case IOR:
03860 case AND:
03861 if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms))
03862 return 0;
03863 case NOT:
03864 if (! find_and_mark_used_attributes (XEXP (exp, 0), terms, nterms))
03865 return 0;
03866 return 1;
03867
03868 case COND:
03869 for (i = 0; i < XVECLEN (exp, 0); i++)
03870 if (! find_and_mark_used_attributes (XVECEXP (exp, 0, i), terms, nterms))
03871 return 0;
03872 if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms))
03873 return 0;
03874 return 1;
03875
03876 default:
03877 return 0;
03878 }
03879 }
03880
03881
03882
03883
03884 static void
03885 unmark_used_attributes (list, space, ndim)
03886 rtx list;
03887 struct dimension *space;
03888 int ndim;
03889 {
03890 rtx link, exp;
03891 int i;
03892
03893 for (i = 0; i < ndim; i++)
03894 unmark_used_attributes (space[i].values, 0, 0);
03895
03896 for (link = list; link; link = XEXP (link, 1))
03897 {
03898 exp = XEXP (link, 0);
03899 if (GET_CODE (exp) == EQ_ATTR)
03900 ATTR_EQ_ATTR_P (exp) = 0;
03901 }
03902 }
03903
03904
03905
03906
03907 static int
03908 add_values_to_cover (dim)
03909 struct dimension *dim;
03910 {
03911 struct attr_value *av;
03912 rtx exp, link, *prev;
03913 int nalt = 0;
03914
03915 for (av = dim->attr->first_value; av; av = av->next)
03916 if (GET_CODE (av->value) == CONST_STRING)
03917 nalt++;
03918
03919 if (nalt < dim->num_values)
03920 abort ();
03921 else if (nalt == dim->num_values)
03922
03923 ;
03924 else if (nalt * 2 < dim->num_values * 3)
03925 {
03926
03927
03928 prev = &dim->values;
03929 for (link = dim->values; link; link = *prev)
03930 prev = &XEXP (link, 1);
03931
03932 for (av = dim->attr->first_value; av; av = av->next)
03933 if (GET_CODE (av->value) == CONST_STRING)
03934 {
03935 exp = attr_eq (dim->attr->name, XSTR (av->value, 0));
03936 if (ATTR_EQ_ATTR_P (exp))
03937 continue;
03938
03939 link = rtx_alloc (EXPR_LIST);
03940 XEXP (link, 0) = exp;
03941 XEXP (link, 1) = 0;
03942 *prev = link;
03943 prev = &XEXP (link, 1);
03944 }
03945 dim->num_values = nalt;
03946 }
03947 else
03948 {
03949 rtx orexp = false_rtx;
03950
03951
03952
03953
03954 prev = &dim->values;
03955 for (link = dim->values; link; link = *prev)
03956 {
03957 orexp = insert_right_side (IOR, orexp, XEXP (link, 0), -2, -2);
03958 prev = &XEXP (link, 1);
03959 }
03960 link = rtx_alloc (EXPR_LIST);
03961 XEXP (link, 0) = attr_rtx (NOT, orexp);
03962 XEXP (link, 1) = 0;
03963 *prev = link;
03964 dim->num_values++;
03965 }
03966 return dim->num_values;
03967 }
03968
03969
03970
03971
03972 static int
03973 increment_current_value (space, ndim)
03974 struct dimension *space;
03975 int ndim;
03976 {
03977 int i;
03978
03979 for (i = ndim - 1; i >= 0; i--)
03980 {
03981 if ((space[i].current_value = XEXP (space[i].current_value, 1)) == 0)
03982 space[i].current_value = space[i].values;
03983 else
03984 return 1;
03985 }
03986 return 0;
03987 }
03988
03989
03990
03991
03992 static rtx
03993 test_for_current_value (space, ndim)
03994 struct dimension *space;
03995 int ndim;
03996 {
03997 int i;
03998 rtx exp = true_rtx;
03999
04000 for (i = 0; i < ndim; i++)
04001 exp = insert_right_side (AND, exp, XEXP (space[i].current_value, 0),
04002 -2, -2);
04003
04004 return exp;
04005 }
04006
04007
04008
04009
04010
04011
04012 static rtx
04013 simplify_with_current_value (exp, space, ndim)
04014 rtx exp;
04015 struct dimension *space;
04016 int ndim;
04017 {
04018 int i;
04019 rtx x;
04020
04021
04022 for (i = 0; i < ndim; i++)
04023 {
04024 x = XEXP (space[i].current_value, 0);
04025 if (GET_CODE (x) == EQ_ATTR)
04026 ATTR_EQ_ATTR_P (x) = 0;
04027 }
04028
04029 exp = simplify_with_current_value_aux (exp);
04030
04031
04032 for (i = 0; i < ndim; i++)
04033 {
04034 x = XEXP (space[i].current_value, 0);
04035 if (GET_CODE (x) == EQ_ATTR)
04036 ATTR_EQ_ATTR_P (x) = 1;
04037 }
04038
04039 return exp;
04040 }
04041
04042
04043
04044
04045 static rtx
04046 simplify_with_current_value_aux (exp)
04047 rtx exp;
04048 {
04049 int i;
04050 rtx cond;
04051
04052 switch (GET_CODE (exp))
04053 {
04054 case EQ_ATTR:
04055 if (ATTR_EQ_ATTR_P (exp))
04056 return false_rtx;
04057 else
04058 return true_rtx;
04059 case CONST_STRING:
04060 case CONST_INT:
04061 return exp;
04062
04063 case IF_THEN_ELSE:
04064 cond = simplify_with_current_value_aux (XEXP (exp, 0));
04065 if (cond == true_rtx)
04066 return simplify_with_current_value_aux (XEXP (exp, 1));
04067 else if (cond == false_rtx)
04068 return simplify_with_current_value_aux (XEXP (exp, 2));
04069 else
04070 return attr_rtx (IF_THEN_ELSE, cond,
04071 simplify_with_current_value_aux (XEXP (exp, 1)),
04072 simplify_with_current_value_aux (XEXP (exp, 2)));
04073
04074 case IOR:
04075 cond = simplify_with_current_value_aux (XEXP (exp, 1));
04076 if (cond == true_rtx)
04077 return cond;
04078 else if (cond == false_rtx)
04079 return simplify_with_current_value_aux (XEXP (exp, 0));
04080 else
04081 return attr_rtx (IOR, cond,
04082 simplify_with_current_value_aux (XEXP (exp, 0)));
04083
04084 case AND:
04085 cond = simplify_with_current_value_aux (XEXP (exp, 1));
04086 if (cond == true_rtx)
04087 return simplify_with_current_value_aux (XEXP (exp, 0));
04088 else if (cond == false_rtx)
04089 return cond;
04090 else
04091 return attr_rtx (AND, cond,
04092 simplify_with_current_value_aux (XEXP (exp, 0)));
04093
04094 case NOT:
04095 cond = simplify_with_current_value_aux (XEXP (exp, 0));
04096 if (cond == true_rtx)
04097 return false_rtx;
04098 else if (cond == false_rtx)
04099 return true_rtx;
04100 else
04101 return attr_rtx (NOT, cond);
04102
04103 case COND:
04104 for (i = 0; i < XVECLEN (exp, 0); i += 2)
04105 {
04106 cond = simplify_with_current_value_aux (XVECEXP (exp, 0, i));
04107 if (cond == true_rtx)
04108 return simplify_with_current_value_aux (XVECEXP (exp, 0, i + 1));
04109 else if (cond == false_rtx)
04110 continue;
04111 else
04112 abort ();
04113
04114 }
04115 return simplify_with_current_value_aux (XEXP (exp, 1));
04116
04117 default:
04118 abort ();
04119 }
04120 }
04121
04122
04123
04124 static void
04125 clear_struct_flag (x)
04126 rtx x;
04127 {
04128 int i;
04129 int j;
04130 enum rtx_code code;
04131 const char *fmt;
04132
04133 ATTR_CURR_SIMPLIFIED_P (x) = 0;
04134 if (ATTR_IND_SIMPLIFIED_P (x))
04135 return;
04136
04137 code = GET_CODE (x);
04138
04139 switch (code)
04140 {
04141 case REG:
04142 case QUEUED:
04143 case CONST_INT:
04144 case CONST_DOUBLE:
04145 case CONST_VECTOR:
04146 case SYMBOL_REF:
04147 case CODE_LABEL:
04148 case PC:
04149 case CC0:
04150 case EQ_ATTR:
04151 case ATTR_FLAG:
04152 return;
04153
04154 default:
04155 break;
04156 }
04157
04158
04159
04160
04161 fmt = GET_RTX_FORMAT (code);
04162 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
04163 {
04164 switch (fmt[i])
04165 {
04166 case 'V':
04167 case 'E':
04168 for (j = 0; j < XVECLEN (x, i); j++)
04169 clear_struct_flag (XVECEXP (x, i, j));
04170 break;
04171
04172 case 'e':
04173 clear_struct_flag (XEXP (x, i));
04174 break;
04175 }
04176 }
04177 }
04178
04179
04180
04181
04182 static int
04183 count_sub_rtxs (x, max)
04184 rtx x;
04185 int max;
04186 {
04187 int i;
04188 int j;
04189 enum rtx_code code;
04190 const char *fmt;
04191 int total = 0;
04192
04193 code = GET_CODE (x);
04194
04195 switch (code)
04196 {
04197 case REG:
04198 case QUEUED:
04199 case CONST_INT:
04200 case CONST_DOUBLE:
04201 case CONST_VECTOR:
04202 case SYMBOL_REF:
04203 case CODE_LABEL:
04204 case PC:
04205 case CC0:
04206 case EQ_ATTR:
04207 case ATTR_FLAG:
04208 return 1;
04209
04210 default:
04211 break;
04212 }
04213
04214
04215
04216
04217 fmt = GET_RTX_FORMAT (code);
04218 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
04219 {
04220 if (total >= max)
04221 return total;
04222
04223 switch (fmt[i])
04224 {
04225 case 'V':
04226 case 'E':
04227 for (j = 0; j < XVECLEN (x, i); j++)
04228 total += count_sub_rtxs (XVECEXP (x, i, j), max);
04229 break;
04230
04231 case 'e':
04232 total += count_sub_rtxs (XEXP (x, i), max);
04233 break;
04234 }
04235 }
04236 return total;
04237
04238 }
04239
04240
04241
04242 static void
04243 gen_attr (exp, lineno)
04244 rtx exp;
04245 int lineno;
04246 {
04247 struct attr_desc *attr;
04248 struct attr_value *av;
04249 const char *name_ptr;
04250 char *p;
04251
04252
04253
04254 attr = find_attr (XSTR (exp, 0), 1);
04255 if (attr->default_val)
04256 {
04257 message_with_line (lineno, "duplicate definition for attribute %s",
04258 attr->name);
04259 message_with_line (attr->lineno, "previous definition");
04260 have_error = 1;
04261 return;
04262 }
04263 attr->lineno = lineno;
04264
04265 if (*XSTR (exp, 1) == '\0')
04266 attr->is_numeric = 1;
04267 else
04268 {
04269 name_ptr = XSTR (exp, 1);
04270 while ((p = next_comma_elt (&name_ptr)) != NULL)
04271 {
04272 av = (struct attr_value *) oballoc (sizeof (struct attr_value));
04273 av->value = attr_rtx (CONST_STRING, p);
04274 av->next = attr->first_value;
04275 attr->first_value = av;
04276 av->first_insn = NULL;
04277 av->num_insns = 0;
04278 av->has_asm_insn = 0;
04279 }
04280 }
04281
04282 if (GET_CODE (XEXP (exp, 2)) == CONST)
04283 {
04284 attr->is_const = 1;
04285 if (attr->is_numeric)
04286 {
04287 message_with_line (lineno,
04288 "constant attributes may not take numeric values");
04289 have_error = 1;
04290 }
04291
04292
04293 XEXP (exp, 2) = XEXP (XEXP (exp, 2), 0);
04294 }
04295
04296 if (! strcmp (attr->name, "length") && ! attr->is_numeric)
04297 {
04298 message_with_line (lineno,
04299 "`length' attribute must take numeric values");
04300 have_error = 1;
04301 }
04302
04303
04304 XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
04305 attr->default_val = get_attr_value (XEXP (exp, 2), attr, -2);
04306 }
04307
04308
04309
04310
04311
04312 static int
04313 count_alternatives (exp)
04314 rtx exp;
04315 {
04316 int i, j, n;
04317 const char *fmt;
04318
04319 if (GET_CODE (exp) == MATCH_OPERAND)
04320 return n_comma_elts (XSTR (exp, 2));
04321
04322 for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
04323 i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
04324 switch (*fmt++)
04325 {
04326 case 'e':
04327 case 'u':
04328 n = count_alternatives (XEXP (exp, i));
04329 if (n)
04330 return n;
04331 break;
04332
04333 case 'E':
04334 case 'V':
04335 if (XVEC (exp, i) != NULL)
04336 for (j = 0; j < XVECLEN (exp, i); j++)
04337 {
04338 n = count_alternatives (XVECEXP (exp, i, j));
04339 if (n)
04340 return n;
04341 }
04342 }
04343
04344 return 0;
04345 }
04346
04347
04348
04349
04350 static int
04351 compares_alternatives_p (exp)
04352 rtx exp;
04353 {
04354 int i, j;
04355 const char *fmt;
04356
04357 if (GET_CODE (exp) == EQ_ATTR && XSTR (exp, 0) == alternative_name)
04358 return 1;
04359
04360 for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
04361 i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
04362 switch (*fmt++)
04363 {
04364 case 'e':
04365 case 'u':
04366 if (compares_alternatives_p (XEXP (exp, i)))
04367 return 1;
04368 break;
04369
04370 case 'E':
04371 for (j = 0; j < XVECLEN (exp, i); j++)
04372 if (compares_alternatives_p (XVECEXP (exp, i, j)))
04373 return 1;
04374 break;
04375 }
04376
04377 return 0;
04378 }
04379
04380
04381
04382 static int
04383 contained_in_p (inner, exp)
04384 rtx inner;
04385 rtx exp;
04386 {
04387 int i, j;
04388 const char *fmt;
04389
04390 if (rtx_equal_p (inner, exp))
04391 return 1;
04392
04393 for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
04394 i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
04395 switch (*fmt++)
04396 {
04397 case 'e':
04398 case 'u':
04399 if (contained_in_p (inner, XEXP (exp, i)))
04400 return 1;
04401 break;
04402
04403 case 'E':
04404 for (j = 0; j < XVECLEN (exp, i); j++)
04405 if (contained_in_p (inner, XVECEXP (exp, i, j)))
04406 return 1;
04407 break;
04408 }
04409
04410 return 0;
04411 }
04412
04413
04414
04415 static void
04416 gen_insn (exp, lineno)
04417 rtx exp;
04418 int lineno;
04419 {
04420 struct insn_def *id;
04421
04422 id = (struct insn_def *) oballoc (sizeof (struct insn_def));
04423 id->next = defs;
04424 defs = id;
04425 id->def = exp;
04426 id->lineno = lineno;
04427
04428 switch (GET_CODE (exp))
04429 {
04430 case DEFINE_INSN:
04431 id->insn_code = insn_code_number;
04432 id->insn_index = insn_index_number;
04433 id->num_alternatives = count_alternatives (exp);
04434 if (id->num_alternatives == 0)
04435 id->num_alternatives = 1;
04436 id->vec_idx = 4;
04437 break;
04438
04439 case DEFINE_PEEPHOLE:
04440 id->insn_code = insn_code_number;
04441 id->insn_index = insn_index_number;
04442 id->num_alternatives = count_alternatives (exp);
04443 if (id->num_alternatives == 0)
04444 id->num_alternatives = 1;
04445 id->vec_idx = 3;
04446 break;
04447
04448 case DEFINE_ASM_ATTRIBUTES:
04449 id->insn_code = -1;
04450 id->insn_index = -1;
04451 id->num_alternatives = 1;
04452 id->vec_idx = 0;
04453 got_define_asm_attributes = 1;
04454 break;
04455
04456 default:
04457 abort ();
04458 }
04459 }
04460
04461
04462
04463
04464 static void
04465 gen_delay (def, lineno)
04466 rtx def;
04467 int lineno;
04468 {
04469 struct delay_desc *delay;
04470 int i;
04471
04472 if (XVECLEN (def, 1) % 3 != 0)
04473 {
04474 message_with_line (lineno,
04475 "number of elements in DEFINE_DELAY must be multiple of three");
04476 have_error = 1;
04477 return;
04478 }
04479
04480 for (i = 0; i < XVECLEN (def, 1); i += 3)
04481 {
04482 if (XVECEXP (def, 1, i + 1))
04483 have_annul_true = 1;
04484 if (XVECEXP (def, 1, i + 2))
04485 have_annul_false = 1;
04486 }
04487
04488 delay = (struct delay_desc *) oballoc (sizeof (struct delay_desc));
04489 delay->def = def;
04490 delay->num = ++num_delays;
04491 delay->next = delays;
04492 delay->lineno = lineno;
04493 delays = delay;
04494 }
04495
04496
04497
04498
04499
04500
04501
04502 static void
04503 gen_unit (def, lineno)
04504 rtx def;
04505 int lineno;
04506 {
04507 struct function_unit *unit;
04508 struct function_unit_op *op;
04509 const char *name = XSTR (def, 0);
04510 int multiplicity = XINT (def, 1);
04511 int simultaneity = XINT (def, 2);
04512 rtx condexp = XEXP (def, 3);
04513 int ready_cost = MAX (XINT (def, 4), 1);
04514 int issue_delay = MAX (XINT (def, 5), 1);
04515
04516
04517
04518
04519 for (unit = units; unit; unit = unit->next)
04520 if (! strcmp (unit->name, name))
04521 {
04522 if (unit->multiplicity != multiplicity
04523 || unit->simultaneity != simultaneity)
04524 {
04525 message_with_line (lineno,
04526 "differing specifications given for function unit %s",
04527 unit->name);
04528 message_with_line (unit->first_lineno, "previous definition");
04529 have_error = 1;
04530 return;
04531 }
04532 break;
04533 }
04534
04535 if (unit == 0)
04536 {
04537 unit = (struct function_unit *) oballoc (sizeof (struct function_unit));
04538 unit->name = name;
04539 unit->multiplicity = multiplicity;
04540 unit->simultaneity = simultaneity;
04541 unit->issue_delay.min = unit->issue_delay.max = issue_delay;
04542 unit->num = num_units++;
04543 unit->num_opclasses = 0;
04544 unit->condexp = false_rtx;
04545 unit->ops = 0;
04546 unit->next = units;
04547 unit->first_lineno = lineno;
04548 units = unit;
04549 }
04550
04551
04552 op = (struct function_unit_op *) oballoc (sizeof (struct function_unit_op));
04553 op->condexp = condexp;
04554 op->num = unit->num_opclasses++;
04555 op->ready = ready_cost;
04556 op->issue_delay = issue_delay;
04557 op->next = unit->ops;
04558 op->lineno = lineno;
04559 unit->ops = op;
04560 num_unit_opclasses++;
04561
04562
04563
04564 if (XVEC (def, 6))
04565 {
04566
04567 rtx orexp = false_rtx;
04568 int i;
04569
04570 for (i = 0; i < XVECLEN (def, 6); i++)
04571 orexp = insert_right_side (IOR, orexp, XVECEXP (def, 6, i), -2, -2);
04572
04573 op->conflict_exp = orexp;
04574 extend_range (&unit->issue_delay, 1, issue_delay);
04575 }
04576 else
04577 {
04578 op->conflict_exp = true_rtx;
04579 extend_range (&unit->issue_delay, issue_delay, issue_delay);
04580 }
04581
04582
04583
04584 unit->condexp = insert_right_side (IOR, unit->condexp, op->condexp, -2, -2);
04585 }
04586
04587
04588
04589
04590
04591
04592
04593
04594
04595 static void
04596 write_test_expr (exp, flags)
04597 rtx exp;
04598 int flags;
04599 {
04600 int comparison_operator = 0;
04601 RTX_CODE code;
04602 struct attr_desc *attr;
04603
04604
04605
04606
04607 printf ("(");
04608 code = GET_CODE (exp);
04609 switch (code)
04610 {
04611
04612 case EQ: case NE:
04613 case GE: case GT: case GEU: case GTU:
04614 case LE: case LT: case LEU: case LTU:
04615 comparison_operator = 1;
04616
04617 case PLUS: case MINUS: case MULT: case DIV: case MOD:
04618 case AND: case IOR: case XOR:
04619 case ASHIFT: case LSHIFTRT: case ASHIFTRT:
04620 write_test_expr (XEXP (exp, 0), flags | comparison_operator);
04621 switch (code)
04622 {
04623 case EQ:
04624 printf (" == ");
04625 break;
04626 case NE:
04627 printf (" != ");
04628 break;
04629 case GE:
04630 printf (" >= ");
04631 break;
04632 case GT:
04633 printf (" > ");
04634 break;
04635 case GEU:
04636 printf (" >= (unsigned) ");
04637 break;
04638 case GTU:
04639 printf (" > (unsigned) ");
04640 break;
04641 case LE:
04642 printf (" <= ");
04643 break;
04644 case LT:
04645 printf (" < ");
04646 break;
04647 case LEU:
04648 printf (" <= (unsigned) ");
04649 break;
04650 case LTU:
04651 printf (" < (unsigned) ");
04652 break;
04653 case PLUS:
04654 printf (" + ");
04655 break;
04656 case MINUS:
04657 printf (" - ");
04658 break;
04659 case MULT:
04660 printf (" * ");
04661 break;
04662 case DIV:
04663 printf (" / ");
04664 break;
04665 case MOD:
04666 printf (" %% ");
04667 break;
04668 case AND:
04669 if (flags & 1)
04670 printf (" & ");
04671 else
04672 printf (" && ");
04673 break;
04674 case IOR:
04675 if (flags & 1)
04676 printf (" | ");
04677 else
04678 printf (" || ");
04679 break;
04680 case XOR:
04681 printf (" ^ ");
04682 break;
04683 case ASHIFT:
04684 printf (" << ");
04685 break;
04686 case LSHIFTRT:
04687 case ASHIFTRT:
04688 printf (" >> ");
04689 break;
04690 default:
04691 abort ();
04692 }
04693
04694 write_test_expr (XEXP (exp, 1), flags | comparison_operator);
04695 break;
04696
04697 case NOT:
04698
04699 if (! (flags & 1) && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
04700 && XSTR (XEXP (exp, 0), 0) == alternative_name)
04701 {
04702 printf ("which_alternative != %s", XSTR (XEXP (exp, 0), 1));
04703 break;
04704 }
04705
04706
04707
04708
04709 case ABS: case NEG:
04710 switch (code)
04711 {
04712 case NOT:
04713 if (flags & 1)
04714 printf ("~ ");
04715 else
04716 printf ("! ");
04717 break;
04718 case ABS:
04719 printf ("abs ");
04720 break;
04721 case NEG:
04722 printf ("-");
04723 break;
04724 default:
04725 abort ();
04726 }
04727
04728 write_test_expr (XEXP (exp, 0), flags);
04729 break;
04730
04731
04732
04733
04734 case EQ_ATTR:
04735 if (flags & 1)
04736 fatal ("EQ_ATTR not valid inside comparison");
04737
04738 if (XSTR (exp, 0) == alternative_name)
04739 {
04740 printf ("which_alternative == %s", XSTR (exp, 1));
04741 break;
04742 }
04743
04744 attr = find_attr (XSTR (exp, 0), 0);
04745 if (! attr)
04746 abort ();
04747
04748
04749 if (attr->is_const)
04750 {
04751 write_test_expr (evaluate_eq_attr (exp, attr->default_val->value,
04752 -2, -2),
04753 flags);
04754 }
04755 else
04756 {
04757 if (flags & 2)
04758 printf ("attr_%s", attr->name);
04759 else
04760 printf ("get_attr_%s (insn)", attr->name);
04761 printf (" == ");
04762 write_attr_valueq (attr, XSTR (exp, 1));
04763 }
04764 break;
04765
04766
04767 case ATTR_FLAG:
04768 if (flags & 1)
04769 fatal ("ATTR_FLAG not valid inside comparison");
04770 printf ("(flags & ATTR_FLAG_%s) != 0", XSTR (exp, 0));
04771 break;
04772
04773
04774 case MATCH_OPERAND:
04775
04776
04777 if (XSTR (exp, 1) == NULL || *XSTR (exp, 1) == '\0')
04778 {
04779 if (GET_MODE (exp) == VOIDmode)
04780 fatal ("null MATCH_OPERAND specified as test");
04781 else
04782 printf ("GET_MODE (operands[%d]) == %smode",
04783 XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
04784 }
04785 else
04786 printf ("%s (operands[%d], %smode)",
04787 XSTR (exp, 1), XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
04788 break;
04789
04790 case MATCH_INSN:
04791 printf ("%s (insn)", XSTR (exp, 0));
04792 break;
04793
04794
04795 case CONST_INT:
04796 printf (HOST_WIDE_INT_PRINT_DEC, XWINT (exp, 0));
04797 break;
04798
04799
04800 case SYMBOL_REF:
04801 printf ("%s", XSTR (exp, 0));
04802 break;
04803
04804
04805 case MATCH_DUP:
04806 printf ("INSN_ADDRESSES_SET_P () ? INSN_ADDRESSES (INSN_UID (GET_CODE (operands[%d]) == LABEL_REF ? XEXP (operands[%d], 0) : operands[%d])) : 0",
04807 XINT (exp, 0), XINT (exp, 0), XINT (exp, 0));
04808 break;
04809
04810 case PC:
04811
04812
04813
04814
04815
04816 printf ("insn_current_reference_address (insn)");
04817 break;
04818
04819 case CONST_STRING:
04820 printf ("%s", XSTR (exp, 0));
04821 break;
04822
04823 case IF_THEN_ELSE:
04824 write_test_expr (XEXP (exp, 0), flags & 2);
04825 printf (" ? ");
04826 write_test_expr (XEXP (exp, 1), flags | 1);
04827 printf (" : ");
04828 write_test_expr (XEXP (exp, 2), flags | 1);
04829 break;
04830
04831 default:
04832 fatal ("bad RTX code `%s' in attribute calculation\n",
04833 GET_RTX_NAME (code));
04834 }
04835
04836 printf (")");
04837 }
04838
04839
04840
04841
04842 static int
04843 max_attr_value (exp, unknownp)
04844 rtx exp;
04845 int *unknownp;
04846 {
04847 int current_max;
04848 int i, n;
04849
04850 switch (GET_CODE (exp))
04851 {
04852 case CONST_STRING:
04853 current_max = atoi (XSTR (exp, 0));
04854 break;
04855
04856 case COND:
04857 current_max = max_attr_value (XEXP (exp, 1), unknownp);
04858 for (i = 0; i < XVECLEN (exp, 0); i += 2)
04859 {
04860 n = max_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
04861 if (n > current_max)
04862 current_max = n;
04863 }
04864 break;
04865
04866 case IF_THEN_ELSE:
04867 current_max = max_attr_value (XEXP (exp, 1), unknownp);
04868 n = max_attr_value (XEXP (exp, 2), unknownp);
04869 if (n > current_max)
04870 current_max = n;
04871 break;
04872
04873 default:
04874 *unknownp = 1;
04875 current_max = INT_MAX;
04876 break;
04877 }
04878
04879 return current_max;
04880 }
04881
04882
04883
04884
04885
04886 static int
04887 or_attr_value (exp, unknownp)
04888 rtx exp;
04889 int *unknownp;
04890 {
04891 int current_or;
04892 int i;
04893
04894 switch (GET_CODE (exp))
04895 {
04896 case CONST_STRING:
04897 current_or = atoi (XSTR (exp, 0));
04898 break;
04899
04900 case COND:
04901 current_or = or_attr_value (XEXP (exp, 1), unknownp);
04902 for (i = 0; i < XVECLEN (exp, 0); i += 2)
04903 current_or |= or_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
04904 break;
04905
04906 case IF_THEN_ELSE:
04907 current_or = or_attr_value (XEXP (exp, 1), unknownp);
04908 current_or |= or_attr_value (XEXP (exp, 2), unknownp);
04909 break;
04910
04911 default:
04912 *unknownp = 1;
04913 current_or = -1;
04914 break;
04915 }
04916
04917 return current_or;
04918 }
04919
04920
04921
04922
04923
04924
04925
04926
04927
04928
04929
04930 static void
04931 walk_attr_value (exp)
04932 rtx exp;
04933 {
04934 int i, j;
04935 const char *fmt;
04936 RTX_CODE code;
04937
04938 if (exp == NULL)
04939 return;
04940
04941 code = GET_CODE (exp);
04942 switch (code)
04943 {
04944 case SYMBOL_REF:
04945 if (! ATTR_IND_SIMPLIFIED_P (exp))
04946
04947
04948
04949 must_extract = must_constrain = 1;
04950 return;
04951
04952 case MATCH_OPERAND:
04953 must_extract = 1;
04954 return;
04955
04956 case EQ_ATTR:
04957 if (XSTR (exp, 0) == alternative_name)
04958 must_extract = must_constrain = 1;
04959 else if (strcmp (XSTR (exp, 0), "length") == 0)
04960 length_used = 1;
04961 return;
04962
04963 case MATCH_DUP:
04964 must_extract = 1;
04965 address_used = 1;
04966 return;
04967
04968 case PC:
04969 address_used = 1;
04970 return;
04971
04972 case ATTR_FLAG:
04973 return;
04974
04975 default:
04976 break;
04977 }
04978
04979 for (i = 0, fmt = GET_RTX_FORMAT (code); i < GET_RTX_LENGTH (code); i++)
04980 switch (*fmt++)
04981 {
04982 case 'e':
04983 case 'u':
04984 walk_attr_value (XEXP (exp, i));
04985 break;
04986
04987 case 'E':
04988 if (XVEC (exp, i) != NULL)
04989 for (j = 0; j < XVECLEN (exp, i); j++)
04990 walk_attr_value (XVECEXP (exp, i, j));
04991 break;
04992 }
04993 }
04994
04995
04996
04997 static void
04998 write_attr_get (attr)
04999 struct attr_desc *attr;
05000 {
05001 struct attr_value *av, *common_av;
05002
05003
05004
05005 common_av = find_most_used (attr);
05006
05007
05008 if (!attr->is_numeric)
05009 printf ("extern enum attr_%s ", attr->name);
05010 else if (attr->unsigned_p)
05011 printf ("extern unsigned int ");
05012 else
05013 printf ("extern int ");
05014
05015
05016 if (attr->name[0] == '*')
05017 printf ("%s PARAMS ((rtx));\n", &attr->name[1]);
05018 else
05019 printf ("get_attr_%s PARAMS ((%s));\n", attr->name,
05020 (attr->is_const ? "void" : "rtx"));
05021
05022
05023
05024 if (!attr->is_numeric)
05025 printf ("enum attr_%s\n", attr->name);
05026 else if (attr->unsigned_p)
05027 printf ("unsigned int\n");
05028 else
05029 printf ("int\n");
05030
05031
05032
05033 if (attr->name[0] == '*')
05034 printf ("%s (insn)\n", &attr->name[1]);
05035 else if (attr->is_const == 0)
05036 printf ("get_attr_%s (insn)\n", attr->name);
05037 else
05038 {
05039 printf ("get_attr_%s ()\n", attr->name);
05040 printf ("{\n");
05041
05042 for (av = attr->first_value; av; av = av->next)
05043 if (av->num_insns != 0)
05044 write_attr_set (attr, 2, av->value, "return", ";",
05045 true_rtx, av->first_insn->insn_code,
05046 av->first_insn->insn_index);
05047
05048 printf ("}\n\n");
05049 return;
05050 }
05051
05052 printf (" rtx insn;\n");
05053 printf ("{\n");
05054
05055 if (GET_CODE (common_av->value) == FFS)
05056 {
05057 rtx p = XEXP (common_av->value, 0);
05058
05059
05060
05061
05062 write_toplevel_expr (p);
05063
05064 printf ("\n if (accum && accum == (accum & -accum))\n");
05065 printf (" {\n");
05066 printf (" int i;\n");
05067 printf (" for (i = 0; accum >>= 1; ++i) continue;\n");
05068 printf (" accum = i;\n");
05069 printf (" }\n else\n");
05070 printf (" accum = ~accum;\n");
05071 printf (" return accum;\n}\n\n");
05072 }
05073 else
05074 {
05075 printf (" switch (recog_memoized (insn))\n");
05076 printf (" {\n");
05077
05078 for (av = attr->first_value; av; av = av->next)
05079 if (av != common_av)
05080 write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
05081
05082 write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
05083 printf (" }\n}\n\n");
05084 }
05085 }
05086
05087
05088
05089
05090
05091
05092 static rtx
05093 eliminate_known_true (known_true, exp, insn_code, insn_index)
05094 rtx known_true;
05095 rtx exp;
05096 int insn_code, insn_index;
05097 {
05098 rtx term;
05099
05100 known_true = SIMPLIFY_TEST_EXP (known_true, insn_code, insn_index);
05101
05102 if (GET_CODE (known_true) == AND)
05103 {
05104 exp = eliminate_known_true (XEXP (known_true, 0), exp,
05105 insn_code, insn_index);
05106 exp = eliminate_known_true (XEXP (known_true, 1), exp,
05107 insn_code, insn_index);
05108 }
05109 else
05110 {
05111 term = known_true;
05112 exp = simplify_and_tree (exp, &term, insn_code, insn_index);
05113 }
05114
05115 return exp;
05116 }
05117
05118
05119
05120
05121
05122
05123 static void
05124 write_attr_set (attr, indent, value, prefix, suffix, known_true,
05125 insn_code, insn_index)
05126 struct attr_desc *attr;
05127 int indent;
05128 rtx value;
05129 const char *prefix;
05130 const char *suffix;
05131 rtx known_true;
05132 int insn_code, insn_index;
05133 {
05134 if (GET_CODE (value) == COND)
05135 {
05136
05137
05138 rtx default_val = XEXP (value, 1);
05139 rtx our_known_true = known_true;
05140 rtx newexp;
05141 int first_if = 1;
05142 int i;
05143
05144 for (i = 0; i < XVECLEN (value, 0); i += 2)
05145 {
05146 rtx testexp;
05147 rtx inner_true;
05148
05149 testexp = eliminate_known_true (our_known_true,
05150 XVECEXP (value, 0, i),
05151 insn_code, insn_index);
05152 newexp = attr_rtx (NOT, testexp);
05153 newexp = insert_right_side (AND, our_known_true, newexp,
05154 insn_code, insn_index);
05155
05156
05157
05158
05159 if (testexp == true_rtx || newexp == false_rtx)
05160 {
05161 default_val = XVECEXP (value, 0, i + 1);
05162 break;
05163 }
05164
05165
05166
05167 inner_true = insert_right_side (AND, our_known_true,
05168 testexp, insn_code, insn_index);
05169
05170
05171 if (inner_true == false_rtx)
05172 continue;
05173
05174 write_indent (indent);
05175 printf ("%sif ", first_if ? "" : "else ");
05176 first_if = 0;
05177 write_test_expr (testexp, 0);
05178 printf ("\n");
05179 write_indent (indent + 2);
05180 printf ("{\n");
05181
05182 write_attr_set (attr, indent + 4,
05183 XVECEXP (value, 0, i + 1), prefix, suffix,
05184 inner_true, insn_code, insn_index);
05185 write_indent (indent + 2);
05186 printf ("}\n");
05187 our_known_true = newexp;
05188 }
05189
05190 if (! first_if)
05191 {
05192 write_indent (indent);
05193 printf ("else\n");
05194 write_indent (indent + 2);
05195 printf ("{\n");
05196 }
05197
05198 write_attr_set (attr, first_if ? indent : indent + 4, default_val,
05199 prefix, suffix, our_known_true, insn_code, insn_index);
05200
05201 if (! first_if)
05202 {
05203 write_indent (indent + 2);
05204 printf ("}\n");
05205 }
05206 }
05207 else
05208 {
05209 write_indent (indent);
05210 printf ("%s ", prefix);
05211 write_attr_value (attr, value);
05212 printf ("%s\n", suffix);
05213 }
05214 }
05215
05216
05217
05218 static void
05219 write_attr_case (attr, av, write_case_lines, prefix, suffix, indent,
05220 known_true)
05221 struct attr_desc *attr;
05222 struct attr_value *av;
05223 int write_case_lines;
05224 const char *prefix, *suffix;
05225 int indent;
05226 rtx known_true;
05227 {
05228 struct insn_ent *ie;
05229
05230 if (av->num_insns == 0)
05231 return;
05232
05233 if (av->has_asm_insn)
05234 {
05235 write_indent (indent);
05236 printf ("case -1:\n");
05237 write_indent (indent + 2);
05238 printf ("if (GET_CODE (PATTERN (insn)) != ASM_INPUT\n");
05239 write_indent (indent + 2);
05240 printf (" && asm_noperands (PATTERN (insn)) < 0)\n");
05241 write_indent (indent + 2);
05242 printf (" fatal_insn_not_found (insn);\n");
05243 }
05244
05245 if (write_case_lines)
05246 {
05247 for (ie = av->first_insn; ie; ie = ie->next)
05248 if (ie->insn_code != -1)
05249 {
05250 write_indent (indent);
05251 printf ("case %d:\n", ie->insn_code);
05252 }
05253 }
05254 else
05255 {
05256 write_indent (indent);
05257 printf ("default:\n");
05258 }
05259
05260
05261 must_extract = must_constrain = address_used = 0;
05262 walk_attr_value (av->value);
05263
05264 if (must_constrain)
05265 {
05266 write_indent (indent + 2);
05267 printf ("extract_constrain_insn_cached (insn);\n");
05268 }
05269 else if (must_extract)
05270 {
05271 write_indent (indent + 2);
05272 printf ("extract_insn_cached (insn);\n");
05273 }
05274
05275 write_attr_set (attr, indent + 2, av->value, prefix, suffix,
05276 known_true, av->first_insn->insn_code,
05277 av->first_insn->insn_index);
05278
05279 if (strncmp (prefix, "return", 6))
05280 {
05281 write_indent (indent + 2);
05282 printf ("break;\n");
05283 }
05284 printf ("\n");
05285 }
05286
05287
05288
05289 static int
05290 write_expr_attr_cache (p, attr)
05291 rtx p;
05292 struct attr_desc *attr;
05293 {
05294 const char *fmt;
05295 int i, ie, j, je;
05296
05297 if (GET_CODE (p) == EQ_ATTR)
05298 {
05299 if (XSTR (p, 0) != attr->name)
05300 return 0;
05301
05302 if (!attr->is_numeric)
05303 printf (" enum attr_%s ", attr->name);
05304 else if (attr->unsigned_p)
05305 printf (" unsigned int ");
05306 else
05307 printf (" int ");
05308
05309 printf ("attr_%s = get_attr_%s (insn);\n", attr->name, attr->name);
05310 return 1;
05311 }
05312
05313 fmt = GET_RTX_FORMAT (GET_CODE (p));
05314 ie = GET_RTX_LENGTH (GET_CODE (p));
05315 for (i = 0; i < ie; i++)
05316 {
05317 switch (*fmt++)
05318 {
05319 case 'e':
05320 if (write_expr_attr_cache (XEXP (p, i), attr))
05321 return 1;
05322 break;
05323
05324 case 'E':
05325 je = XVECLEN (p, i);
05326 for (j = 0; j < je; ++j)
05327 if (write_expr_attr_cache (XVECEXP (p, i, j), attr))
05328 return 1;
05329 break;
05330 }
05331 }
05332
05333 return 0;
05334 }
05335
05336
05337
05338
05339
05340 static void
05341 write_toplevel_expr (p)
05342 rtx p;
05343 {
05344 struct attr_desc *attr;
05345 int i;
05346
05347 for (i = 0; i < MAX_ATTRS_INDEX; ++i)
05348 for (attr = attrs[i]; attr; attr = attr->next)
05349 if (!attr->is_const)
05350 write_expr_attr_cache (p, attr);
05351
05352 printf (" unsigned long accum = 0;\n\n");
05353
05354 while (GET_CODE (p) == IOR)
05355 {
05356 rtx e;
05357 if (GET_CODE (XEXP (p, 0)) == IOR)
05358 e = XEXP (p, 1), p = XEXP (p, 0);
05359 else
05360 e = XEXP (p, 0), p = XEXP (p, 1);
05361
05362 printf (" accum |= ");
05363 write_test_expr (e, 3);
05364 printf (";\n");
05365 }
05366 printf (" accum |= ");
05367 write_test_expr (p, 3);
05368 printf (";\n");
05369 }
05370
05371
05372
05373 static void
05374 write_unit_name (prefix, num, suffix)
05375 const char *prefix;
05376 int num;
05377 const char *suffix;
05378 {
05379 struct function_unit *unit;
05380
05381 for (unit = units; unit; unit = unit->next)
05382 if (unit->num == num)
05383 {
05384 printf ("%s%s%s", prefix, unit->name, suffix);
05385 return;
05386 }
05387
05388 printf ("%s<unknown>%s", prefix, suffix);
05389 }
05390
05391 static void
05392 write_attr_valueq (attr, s)
05393 struct attr_desc *attr;
05394 const char *s;
05395 {
05396 if (attr->is_numeric)
05397 {
05398 int num = atoi (s);
05399
05400 printf ("%d", num);
05401
05402
05403
05404 if (attr->func_units_p)
05405 {
05406 if (num == -1)
05407 printf (" /* units: none */");
05408 else if (num >= 0)
05409 write_unit_name (" /* units: ", num, " */");
05410 else
05411 {
05412 int i;
05413 const char *sep = " /* units: ";
05414 for (i = 0, num = ~num; num; i++, num >>= 1)
05415 if (num & 1)
05416 {
05417 write_unit_name (sep, i, (num == 1) ? " */" : "");
05418 sep = ", ";
05419 }
05420 }
05421 }
05422
05423 else if (attr->blockage_p)
05424 printf (" /* min %d, max %d */", num >> (HOST_BITS_PER_INT / 2),
05425 num & ((1 << (HOST_BITS_PER_INT / 2)) - 1));
05426
05427 else if (num > 9 || num < 0)
05428 printf (" /* 0x%x */", num);
05429 }
05430 else
05431 {
05432 write_upcase (attr->name);
05433 printf ("_");
05434 write_upcase (s);
05435 }
05436 }
05437
05438 static void
05439 write_attr_value (attr, value)
05440 struct attr_desc *attr;
05441 rtx value;
05442 {
05443 int op;
05444
05445 switch (GET_CODE (value))
05446 {
05447 case CONST_STRING:
05448 write_attr_valueq (attr, XSTR (value, 0));
05449 break;
05450
05451 case CONST_INT:
05452 printf (HOST_WIDE_INT_PRINT_DEC, INTVAL (value));
05453 break;
05454
05455 case SYMBOL_REF:
05456 fputs (XSTR (value, 0), stdout);
05457 break;
05458
05459 case ATTR:
05460 {
05461 struct attr_desc *attr2 = find_attr (XSTR (value, 0), 0);
05462 printf ("get_attr_%s (%s)", attr2->name,
05463 (attr2->is_const ? "" : "insn"));
05464 }
05465 break;
05466
05467 case PLUS:
05468 op = '+';
05469 goto do_operator;
05470 case MINUS:
05471 op = '-';
05472 goto do_operator;
05473 case MULT:
05474 op = '*';
05475 goto do_operator;
05476 case DIV:
05477 op = '/';
05478 goto do_operator;
05479 case MOD:
05480 op = '%';
05481 goto do_operator;
05482
05483 do_operator:
05484 write_attr_value (attr, XEXP (value, 0));
05485 putchar (' ');
05486 putchar (op);
05487 putchar (' ');
05488 write_attr_value (attr, XEXP (value, 1));
05489 break;
05490
05491 default:
05492 abort ();
05493 }
05494 }
05495
05496 static void
05497 write_upcase (str)
05498 const char *str;
05499 {
05500 while (*str)
05501 {
05502
05503 putchar (TOUPPER(*str));
05504 str++;
05505 }
05506 }
05507
05508 static void
05509 write_indent (indent)
05510 int indent;
05511 {
05512 for (; indent > 8; indent -= 8)
05513 printf ("\t");
05514
05515 for (; indent; indent--)
05516 printf (" ");
05517 }
05518
05519
05520
05521
05522
05523
05524
05525
05526
05527
05528
05529
05530
05531 static void
05532 write_eligible_delay (kind)
05533 const char *kind;
05534 {
05535 struct delay_desc *delay;
05536 int max_slots;
05537 char str[50];
05538 struct attr_desc *attr;
05539 struct attr_value *av, *common_av;
05540 int i;
05541
05542
05543
05544
05545
05546 for (delay = delays, max_slots = 0; delay; delay = delay->next)
05547 if (XVECLEN (delay->def, 1) / 3 > max_slots)
05548 max_slots = XVECLEN (delay->def, 1) / 3;
05549
05550
05551
05552 printf ("int\n");
05553 printf ("eligible_for_%s (delay_insn, slot, candidate_insn, flags)\n",
05554 kind);
05555 printf (" rtx delay_insn ATTRIBUTE_UNUSED;\n");
05556 printf (" int slot;\n");
05557 printf (" rtx candidate_insn;\n");
05558 printf (" int flags ATTRIBUTE_UNUSED;\n");
05559 printf ("{\n");
05560 printf (" rtx insn;\n");
05561 printf ("\n");
05562 printf (" if (slot >= %d)\n", max_slots);
05563 printf (" abort ();\n");
05564 printf ("\n");
05565
05566
05567
05568 if (num_delays > 1)
05569 {
05570 attr = find_attr ("*delay_type", 0);
05571 if (! attr)
05572 abort ();
05573 common_av = find_most_used (attr);
05574
05575 printf (" insn = delay_insn;\n");
05576 printf (" switch (recog_memoized (insn))\n");
05577 printf (" {\n");
05578
05579 sprintf (str, " * %d;\n break;", max_slots);
05580 for (av = attr->first_value; av; av = av->next)
05581 if (av != common_av)
05582 write_attr_case (attr, av, 1, "slot +=", str, 4, true_rtx);
05583
05584 write_attr_case (attr, common_av, 0, "slot +=", str, 4, true_rtx);
05585 printf (" }\n\n");
05586
05587
05588 printf (" if (slot < %d)\n", max_slots);
05589 printf (" abort ();\n\n");
05590 }
05591
05592
05593 if (num_delays == 1 && max_slots == 1)
05594 {
05595 printf (" insn = candidate_insn;\n");
05596 printf (" switch (recog_memoized (insn))\n");
05597 printf (" {\n");
05598
05599 attr = find_attr ("*delay_1_0", 0);
05600 if (! attr)
05601 abort ();
05602 common_av = find_most_used (attr);
05603
05604 for (av = attr->first_value; av; av = av->next)
05605 if (av != common_av)
05606 write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
05607
05608 write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
05609 printf (" }\n");
05610 }
05611
05612 else
05613 {
05614
05615
05616 printf (" insn = candidate_insn;\n");
05617 printf (" switch (slot)\n");
05618 printf (" {\n");
05619
05620 for (delay = delays; delay; delay = delay->next)
05621 for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
05622 {
05623 printf (" case %d:\n",
05624 (i / 3) + (num_delays == 1 ? 0 : delay->num * max_slots));
05625 printf (" switch (recog_memoized (insn))\n");
05626 printf ("\t{\n");
05627
05628 sprintf (str, "*%s_%d_%d", kind, delay->num, i / 3);
05629 attr = find_attr (str, 0);
05630 if (! attr)
05631 abort ();
05632 common_av = find_most_used (attr);
05633
05634 for (av = attr->first_value; av; av = av->next)
05635 if (av != common_av)
05636 write_attr_case (attr, av, 1, "return", ";", 8, true_rtx);
05637
05638 write_attr_case (attr, common_av, 0, "return", ";", 8, true_rtx);
05639 printf (" }\n");
05640 }
05641
05642 printf (" default:\n");
05643 printf (" abort ();\n");
05644 printf (" }\n");
05645 }
05646
05647 printf ("}\n\n");
05648 }
05649
05650
05651
05652
05653 static void
05654 write_function_unit_info ()
05655 {
05656 struct function_unit *unit;
05657 int i;
05658
05659
05660
05661
05662 for (unit = units; unit; unit = unit->next)
05663 {
05664 if (unit->needs_blockage_function)
05665 write_complex_function (unit, "blockage", "block");
05666
05667
05668
05669 if (! unit->needs_conflict_function)
05670 {
05671 unit->default_cost = make_numeric_value (unit->issue_delay.max);
05672 continue;
05673 }
05674
05675
05676 unit->default_cost = make_numeric_value (0);
05677 write_complex_function (unit, "conflict_cost", "cost");
05678 }
05679
05680
05681
05682
05683
05684 printf ("const struct function_unit_desc function_units[] = {\n");
05685
05686
05687
05688 for (i = 0; i < num_units; i++)
05689 {
05690 for (unit = units; unit; unit = unit->next)
05691 if (unit->num == i)
05692 break;
05693
05694 printf (" {\"%s\", %d, %d, %d, %s, %d, %s_unit_ready_cost, ",
05695 unit->name, 1 << unit->num, unit->multiplicity,
05696 unit->simultaneity, XSTR (unit->default_cost, 0),
05697 unit->issue_delay.max, unit->name);
05698
05699 if (unit->needs_conflict_function)
05700 printf ("%s_unit_conflict_cost, ", unit->name);
05701 else
05702 printf ("0, ");
05703
05704 printf ("%d, ", unit->max_blockage);
05705
05706 if (unit->needs_range_function)
05707 printf ("%s_unit_blockage_range, ", unit->name);
05708 else
05709 printf ("0, ");
05710
05711 if (unit->needs_blockage_function)
05712 printf ("%s_unit_blockage", unit->name);
05713 else
05714 printf ("0");
05715
05716 printf ("}, \n");
05717 }
05718
05719 if (num_units == 0)
05720 printf ("{\"dummy\", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* a dummy element */");
05721 printf ("};\n\n");
05722 }
05723
05724 static void
05725 write_complex_function (unit, name, connection)
05726 struct function_unit *unit;
05727 const char *name, *connection;
05728 {
05729 struct attr_desc *case_attr, *attr;
05730 struct attr_value *av, *common_av;
05731 rtx value;
05732 char str[256];
05733 int using_case;
05734 int i;
05735
05736 printf ("static int %s_unit_%s PARAMS ((rtx, rtx));\n", unit->name, name);
05737 printf ("static int\n");
05738 printf ("%s_unit_%s (executing_insn, candidate_insn)\n", unit->name, name);
05739 printf (" rtx executing_insn;\n");
05740 printf (" rtx candidate_insn;\n");
05741 printf ("{\n");
05742 printf (" rtx insn;\n");
05743 printf (" int casenum;\n\n");
05744 printf (" insn = executing_insn;\n");
05745 printf (" switch (recog_memoized (insn))\n");
05746 printf (" {\n");
05747
05748
05749 if (strlen (unit->name) + sizeof "*_cases" > 256)
05750 abort ();
05751 sprintf (str, "*%s_cases", unit->name);
05752 case_attr = find_attr (str, 0);
05753 if (! case_attr)
05754 abort ();
05755 common_av = find_most_used (case_attr);
05756
05757 for (av = case_attr->first_value; av; av = av->next)
05758 if (av != common_av)
05759 write_attr_case (case_attr, av, 1,
05760 "casenum =", ";", 4, unit->condexp);
05761
05762 write_attr_case (case_attr, common_av, 0,
05763 "casenum =", ";", 4, unit->condexp);
05764 printf (" }\n\n");
05765
05766
05767
05768 printf (" insn = candidate_insn;\n");
05769 printf (" switch (casenum)\n");
05770 printf (" {\n");
05771
05772 for (i = 0; i < unit->num_opclasses; i++)
05773 {
05774
05775 using_case = 0;
05776 for (av = case_attr->first_value; av; av = av->next)
05777 if (av->num_insns
05778 && contained_in_p (make_numeric_value (i), av->value))
05779 using_case = 1;
05780
05781 if (! using_case)
05782 continue;
05783
05784 printf (" case %d:\n", i);
05785 sprintf (str, "*%s_%s_%d", unit->name, connection, i);
05786 attr = find_attr (str, 0);
05787 if (! attr)
05788 abort ();
05789
05790
05791 value = find_single_value (attr);
05792 if (value)
05793 write_attr_set (attr, 6, value, "return", ";\n", true_rtx, -2, -2);
05794 else
05795 {
05796 common_av = find_most_used (attr);
05797 printf (" switch (recog_memoized (insn))\n");
05798 printf ("\t{\n");
05799
05800 for (av = attr->first_value; av; av = av->next)
05801 if (av != common_av)
05802 write_attr_case (attr, av, 1,
05803 "return", ";", 8, unit->condexp);
05804
05805 write_attr_case (attr, common_av, 0,
05806 "return", ";", 8, unit->condexp);
05807 printf (" }\n\n");
05808 }
05809 }
05810
05811
05812
05813
05814 printf (" default:\n abort ();\n");
05815 printf (" }\n}\n\n");
05816 }
05817
05818
05819
05820
05821
05822
05823
05824 static char *
05825 next_comma_elt (pstr)
05826 const char **pstr;
05827 {
05828 const char *start;
05829
05830 start = scan_comma_elt (pstr);
05831
05832 if (start == NULL)
05833 return NULL;
05834
05835 return attr_string (start, *pstr - start);
05836 }
05837
05838
05839
05840
05841 static struct attr_desc *
05842 find_attr (name, create)
05843 const char *name;
05844 int create;
05845 {
05846 struct attr_desc *attr;
05847 int index;
05848
05849
05850
05851 if (name == alternative_name)
05852 return NULL;
05853
05854 index = name[0] & (MAX_ATTRS_INDEX - 1);
05855 for (attr = attrs[index]; attr; attr = attr->next)
05856 if (name == attr->name)
05857 return attr;
05858
05859
05860 for (attr = attrs[index]; attr; attr = attr->next)
05861 if (name[0] == attr->name[0] && ! strcmp (name, attr->name))
05862 return attr;
05863
05864 if (! create)
05865 return NULL;
05866
05867 attr = (struct attr_desc *) oballoc (sizeof (struct attr_desc));
05868 attr->name = attr_string (name, strlen (name));
05869 attr->first_value = attr->default_val = NULL;
05870 attr->is_numeric = attr->negative_ok = attr->is_const = attr->is_special = 0;
05871 attr->unsigned_p = attr->func_units_p = attr->blockage_p = 0;
05872 attr->next = attrs[index];
05873 attrs[index] = attr;
05874
05875 return attr;
05876 }
05877
05878
05879
05880 void
05881 make_internal_attr (name, value, special)
05882 const char *name;
05883 rtx value;
05884 int special;
05885 {
05886 struct attr_desc *attr;
05887
05888 attr = find_attr (name, 1);
05889 if (attr->default_val)
05890 abort ();
05891
05892 attr->is_numeric = 1;
05893 attr->is_const = 0;
05894 attr->is_special = (special & 1) != 0;
05895 attr->negative_ok = (special & 2) != 0;
05896 attr->unsigned_p = (special & 4) != 0;
05897 attr->func_units_p = (special & 8) != 0;
05898 attr->blockage_p = (special & 16) != 0;
05899 attr->default_val = get_attr_value (value, attr, -2);
05900 }
05901
05902
05903
05904 static struct attr_value *
05905 find_most_used (attr)
05906 struct attr_desc *attr;
05907 {
05908 struct attr_value *av;
05909 struct attr_value *most_used;
05910 int nuses;
05911
05912 most_used = NULL;
05913 nuses = -1;
05914
05915 for (av = attr->first_value; av; av = av->next)
05916 if (av->num_insns > nuses)
05917 nuses = av->num_insns, most_used = av;
05918
05919 return most_used;
05920 }
05921
05922
05923
05924
05925 static rtx
05926 find_single_value (attr)
05927 struct attr_desc *attr;
05928 {
05929 struct attr_value *av;
05930 rtx unique_value;
05931
05932 unique_value = NULL;
05933 for (av = attr->first_value; av; av = av->next)
05934 if (av->num_insns)
05935 {
05936 if (unique_value)
05937 return NULL;
05938 else
05939 unique_value = av->value;
05940 }
05941
05942 return unique_value;
05943 }
05944
05945
05946
05947 rtx
05948 make_numeric_value (n)
05949 int n;
05950 {
05951 static rtx int_values[20];
05952 rtx exp;
05953 char *p;
05954
05955 if (n < 0)
05956 abort ();
05957
05958 if (n < 20 && int_values[n])
05959 return int_values[n];
05960
05961 p = attr_printf (MAX_DIGITS, "%d", n);
05962 exp = attr_rtx (CONST_STRING, p);
05963
05964 if (n < 20)
05965 int_values[n] = exp;
05966
05967 return exp;
05968 }
05969
05970 static void
05971 extend_range (range, min, max)
05972 struct range *range;
05973 int min;
05974 int max;
05975 {
05976 if (range->min > min)
05977 range->min = min;
05978 if (range->max < max)
05979 range->max = max;
05980 }
05981
05982 static rtx
05983 copy_rtx_unchanging (orig)
05984 rtx orig;
05985 {
05986 #if 0
05987 rtx copy;
05988 RTX_CODE code;
05989 #endif
05990
05991 if (ATTR_IND_SIMPLIFIED_P (orig) || ATTR_CURR_SIMPLIFIED_P (orig))
05992 return orig;
05993
05994 ATTR_CURR_SIMPLIFIED_P (orig) = 1;
05995 return orig;
05996
05997 #if 0
05998 code = GET_CODE (orig);
05999 switch (code)
06000 {
06001 case CONST_INT:
06002 case CONST_DOUBLE:
06003 case SYMBOL_REF:
06004 case CODE_LABEL:
06005 return orig;
06006
06007 default:
06008 break;
06009 }
06010
06011 copy = rtx_alloc (code);
06012 PUT_MODE (copy, GET_MODE (orig));
06013 ATTR_IND_SIMPLIFIED_P (copy) = 1;
06014
06015 memcpy (&XEXP (copy, 0), &XEXP (orig, 0),
06016 GET_RTX_LENGTH (GET_CODE (copy)) * sizeof (rtx));
06017 return copy;
06018 #endif
06019 }
06020
06021
06022
06023
06024 static void
06025 write_const_num_delay_slots ()
06026 {
06027 struct attr_desc *attr = find_attr ("*num_delay_slots", 0);
06028 struct attr_value *av;
06029 struct insn_ent *ie;
06030
06031 if (attr)
06032 {
06033 printf ("int\nconst_num_delay_slots (insn)\n");
06034 printf (" rtx insn;\n");
06035 printf ("{\n");
06036 printf (" switch (recog_memoized (insn))\n");
06037 printf (" {\n");
06038
06039 for (av = attr->first_value; av; av = av->next)
06040 {
06041 length_used = 0;
06042 walk_attr_value (av->value);
06043 if (length_used)
06044 {
06045 for (ie = av->first_insn; ie; ie = ie->next)
06046 if (ie->insn_code != -1)
06047 printf (" case %d:\n", ie->insn_code);
06048 printf (" return 0;\n");
06049 }
06050 }
06051
06052 printf (" default:\n");
06053 printf (" return 1;\n");
06054 printf (" }\n}\n\n");
06055 }
06056 }
06057
06058 extern int main PARAMS ((int, char **));
06059
06060 int
06061 main (argc, argv)
06062 int argc;
06063 char **argv;
06064 {
06065 rtx desc;
06066 struct attr_desc *attr;
06067 struct insn_def *id;
06068 rtx tem;
06069 int i;
06070
06071 progname = "genattrtab";
06072
06073 if (argc <= 1)
06074 fatal ("no input file name");
06075
06076 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
06077 return (FATAL_EXIT_CODE);
06078
06079 obstack_init (hash_obstack);
06080 obstack_init (temp_obstack);
06081
06082
06083 true_rtx = rtx_alloc (CONST_INT);
06084 XWINT (true_rtx, 0) = 1;
06085 false_rtx = rtx_alloc (CONST_INT);
06086 XWINT (false_rtx, 0) = 0;
06087 ATTR_IND_SIMPLIFIED_P (true_rtx) = ATTR_IND_SIMPLIFIED_P (false_rtx) = 1;
06088 ATTR_PERMANENT_P (true_rtx) = ATTR_PERMANENT_P (false_rtx) = 1;
06089
06090 alternative_name = attr_string ("alternative", strlen ("alternative"));
06091
06092 printf ("/* Generated automatically by the program `genattrtab'\n\
06093 from the machine description file `md'. */\n\n");
06094
06095
06096
06097 initiate_automaton_gen (argc, argv);
06098 while (1)
06099 {
06100 int lineno;
06101
06102 desc = read_md_rtx (&lineno, &insn_code_number);
06103 if (desc == NULL)
06104 break;
06105
06106 switch (GET_CODE (desc))
06107 {
06108 case DEFINE_INSN:
06109 case DEFINE_PEEPHOLE:
06110 case DEFINE_ASM_ATTRIBUTES:
06111 gen_insn (desc, lineno);
06112 break;
06113
06114 case DEFINE_ATTR:
06115 gen_attr (desc, lineno);
06116 break;
06117
06118 case DEFINE_DELAY:
06119 gen_delay (desc, lineno);
06120 break;
06121
06122 case DEFINE_FUNCTION_UNIT:
06123 gen_unit (desc, lineno);
06124 break;
06125
06126 case DEFINE_CPU_UNIT:
06127 gen_cpu_unit (desc);
06128 break;
06129
06130 case DEFINE_QUERY_CPU_UNIT:
06131 gen_query_cpu_unit (desc);
06132 break;
06133
06134 case DEFINE_BYPASS:
06135 gen_bypass (desc);
06136 break;
06137
06138 case EXCLUSION_SET:
06139 gen_excl_set (desc);
06140 break;
06141
06142 case PRESENCE_SET:
06143 gen_presence_set (desc);
06144 break;
06145
06146 case ABSENCE_SET:
06147 gen_absence_set (desc);
06148 break;
06149
06150 case DEFINE_AUTOMATON:
06151 gen_automaton (desc);
06152 break;
06153
06154 case AUTOMATA_OPTION:
06155 gen_automata_option (desc);
06156 break;
06157
06158 case DEFINE_RESERVATION:
06159 gen_reserv (desc);
06160 break;
06161
06162 case DEFINE_INSN_RESERVATION:
06163 gen_insn_reserv (desc);
06164 break;
06165
06166 default:
06167 break;
06168 }
06169 if (GET_CODE (desc) != DEFINE_ASM_ATTRIBUTES)
06170 insn_index_number++;
06171 }
06172
06173 if (have_error)
06174 return FATAL_EXIT_CODE;
06175
06176 insn_code_number++;
06177
06178
06179 if (! got_define_asm_attributes)
06180 {
06181 tem = rtx_alloc (DEFINE_ASM_ATTRIBUTES);
06182 XVEC (tem, 0) = rtvec_alloc (0);
06183 gen_insn (tem, 0);
06184 }
06185
06186
06187 if (num_delays)
06188 expand_delays ();
06189
06190 if (num_units || num_dfa_decls)
06191 {
06192
06193 expand_units ();
06194
06195
06196 expand_automata ();
06197 }
06198
06199 printf ("#include \"config.h\"\n");
06200 printf ("#include \"system.h\"\n");
06201 printf ("#include \"rtl.h\"\n");
06202 printf ("#include \"tm_p.h\"\n");
06203 printf ("#include \"insn-config.h\"\n");
06204 printf ("#include \"recog.h\"\n");
06205 printf ("#include \"regs.h\"\n");
06206 printf ("#include \"real.h\"\n");
06207 printf ("#include \"output.h\"\n");
06208 printf ("#include \"insn-attr.h\"\n");
06209 printf ("#include \"toplev.h\"\n");
06210 printf ("#include \"flags.h\"\n");
06211 printf ("#include \"function.h\"\n");
06212 printf ("\n");
06213 printf ("#define operands recog_data.operand\n\n");
06214
06215
06216 insn_alternatives = (int *) oballoc (insn_code_number * sizeof (int));
06217 for (id = defs; id; id = id->next)
06218 if (id->insn_code >= 0)
06219 insn_alternatives[id->insn_code] = (1 << id->num_alternatives) - 1;
06220
06221
06222 insn_n_alternatives = (int *) oballoc (insn_code_number * sizeof (int));
06223 for (id = defs; id; id = id->next)
06224 if (id->insn_code >= 0)
06225 insn_n_alternatives[id->insn_code] = id->num_alternatives;
06226
06227
06228
06229
06230 check_defs ();
06231
06232 for (i = 0; i < MAX_ATTRS_INDEX; i++)
06233 for (attr = attrs[i]; attr; attr = attr->next)
06234 attr->default_val->value
06235 = check_attr_value (attr->default_val->value, attr);
06236
06237 if (have_error)
06238 return FATAL_EXIT_CODE;
06239
06240 for (i = 0; i < MAX_ATTRS_INDEX; i++)
06241 for (attr = attrs[i]; attr; attr = attr->next)
06242 fill_attr (attr);
06243
06244
06245 make_length_attrs ();
06246
06247
06248 #ifndef SGI_MONGOOSE
06249 optimize_attrs ();
06250 #endif
06251
06252
06253
06254
06255
06256 for (i = 0; i < MAX_ATTRS_INDEX; i++)
06257 for (attr = attrs[i]; attr; attr = attr->next)
06258 {
06259 if (! attr->is_special && ! attr->is_const)
06260 write_attr_get (attr);
06261 }
06262
06263
06264
06265
06266 if (num_delays)
06267 {
06268 write_eligible_delay ("delay");
06269 if (have_annul_true)
06270 write_eligible_delay ("annul_true");
06271 if (have_annul_false)
06272 write_eligible_delay ("annul_false");
06273 }
06274
06275 if (num_units || num_dfa_decls)
06276 {
06277
06278 write_function_unit_info ();
06279
06280
06281 write_automata ();
06282 }
06283
06284
06285 write_const_num_delay_slots ();
06286
06287 write_length_unit_log ();
06288
06289 fflush (stdout);
06290 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
06291 }
06292
06293
06294 const char *
06295 get_insn_name (code)
06296 int code ATTRIBUTE_UNUSED;
06297 {
06298 return NULL;
06299 }