11debfc3dSmrg /* Generate attribute information (insn-attr.h) from machine description.
2*8feb0f0bSmrg Copyright (C) 1991-2020 Free Software Foundation, Inc.
31debfc3dSmrg Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
41debfc3dSmrg
51debfc3dSmrg This file is part of GCC.
61debfc3dSmrg
71debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
81debfc3dSmrg the terms of the GNU General Public License as published by the Free
91debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
101debfc3dSmrg version.
111debfc3dSmrg
121debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
131debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
141debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
151debfc3dSmrg for more details.
161debfc3dSmrg
171debfc3dSmrg You should have received a copy of the GNU General Public License
181debfc3dSmrg along with GCC; see the file COPYING3. If not see
191debfc3dSmrg <http://www.gnu.org/licenses/>. */
201debfc3dSmrg
211debfc3dSmrg
221debfc3dSmrg #include "bconfig.h"
231debfc3dSmrg #include "system.h"
241debfc3dSmrg #include "coretypes.h"
251debfc3dSmrg #include "tm.h"
261debfc3dSmrg #include "rtl.h"
271debfc3dSmrg #include "errors.h"
281debfc3dSmrg #include "read-md.h"
291debfc3dSmrg #include "gensupport.h"
301debfc3dSmrg
311debfc3dSmrg
321debfc3dSmrg static vec<rtx> const_attrs, reservations;
331debfc3dSmrg
341debfc3dSmrg
351debfc3dSmrg static void
gen_attr(md_rtx_info * info)361debfc3dSmrg gen_attr (md_rtx_info *info)
371debfc3dSmrg {
381debfc3dSmrg const char *p;
391debfc3dSmrg rtx attr = info->def;
401debfc3dSmrg int is_const = GET_CODE (XEXP (attr, 2)) == CONST;
411debfc3dSmrg
421debfc3dSmrg if (is_const)
431debfc3dSmrg const_attrs.safe_push (attr);
441debfc3dSmrg
451debfc3dSmrg printf ("#define HAVE_ATTR_%s 1\n", XSTR (attr, 0));
461debfc3dSmrg
471debfc3dSmrg /* If numeric attribute, don't need to write an enum. */
481debfc3dSmrg if (GET_CODE (attr) == DEFINE_ENUM_ATTR)
491debfc3dSmrg printf ("extern enum %s get_attr_%s (%s);\n\n",
501debfc3dSmrg XSTR (attr, 1), XSTR (attr, 0),
511debfc3dSmrg (is_const ? "void" : "rtx_insn *"));
521debfc3dSmrg else
531debfc3dSmrg {
541debfc3dSmrg p = XSTR (attr, 1);
551debfc3dSmrg if (*p == '\0')
561debfc3dSmrg printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0),
571debfc3dSmrg (is_const ? "void" : "rtx_insn *"));
581debfc3dSmrg else
591debfc3dSmrg printf ("extern enum attr_%s get_attr_%s (%s);\n\n",
601debfc3dSmrg XSTR (attr, 0), XSTR (attr, 0),
611debfc3dSmrg (is_const ? "void" : "rtx_insn *"));
621debfc3dSmrg }
631debfc3dSmrg
641debfc3dSmrg /* If `length' attribute, write additional function definitions and define
651debfc3dSmrg variables used by `insn_current_length'. */
661debfc3dSmrg if (! strcmp (XSTR (attr, 0), "length"))
671debfc3dSmrg {
681debfc3dSmrg puts ("\
691debfc3dSmrg extern void shorten_branches (rtx_insn *);\n\
701debfc3dSmrg extern int insn_default_length (rtx_insn *);\n\
711debfc3dSmrg extern int insn_min_length (rtx_insn *);\n\
721debfc3dSmrg extern int insn_variable_length_p (rtx_insn *);\n\
731debfc3dSmrg extern int insn_current_length (rtx_insn *);\n\n\
741debfc3dSmrg #include \"insn-addr.h\"\n");
751debfc3dSmrg }
761debfc3dSmrg }
771debfc3dSmrg
781debfc3dSmrg /* Check that attribute NAME is used in define_insn_reservation condition
791debfc3dSmrg EXP. Return true if it is. */
801debfc3dSmrg static bool
check_tune_attr(const char * name,rtx exp)811debfc3dSmrg check_tune_attr (const char *name, rtx exp)
821debfc3dSmrg {
831debfc3dSmrg switch (GET_CODE (exp))
841debfc3dSmrg {
851debfc3dSmrg case AND:
861debfc3dSmrg if (check_tune_attr (name, XEXP (exp, 0)))
871debfc3dSmrg return true;
881debfc3dSmrg return check_tune_attr (name, XEXP (exp, 1));
891debfc3dSmrg
901debfc3dSmrg case IOR:
911debfc3dSmrg return (check_tune_attr (name, XEXP (exp, 0))
921debfc3dSmrg && check_tune_attr (name, XEXP (exp, 1)));
931debfc3dSmrg
941debfc3dSmrg case EQ_ATTR:
951debfc3dSmrg return strcmp (XSTR (exp, 0), name) == 0;
961debfc3dSmrg
971debfc3dSmrg default:
981debfc3dSmrg return false;
991debfc3dSmrg }
1001debfc3dSmrg }
1011debfc3dSmrg
1021debfc3dSmrg /* Try to find a const attribute (usually cpu or tune) that is used
1031debfc3dSmrg in all define_insn_reservation conditions. */
1041debfc3dSmrg static bool
find_tune_attr(rtx exp)1051debfc3dSmrg find_tune_attr (rtx exp)
1061debfc3dSmrg {
1071debfc3dSmrg unsigned int i;
1081debfc3dSmrg rtx attr;
1091debfc3dSmrg
1101debfc3dSmrg switch (GET_CODE (exp))
1111debfc3dSmrg {
1121debfc3dSmrg case AND:
1131debfc3dSmrg case IOR:
1141debfc3dSmrg if (find_tune_attr (XEXP (exp, 0)))
1151debfc3dSmrg return true;
1161debfc3dSmrg return find_tune_attr (XEXP (exp, 1));
1171debfc3dSmrg
1181debfc3dSmrg case EQ_ATTR:
1191debfc3dSmrg if (strcmp (XSTR (exp, 0), "alternative") == 0)
1201debfc3dSmrg return false;
1211debfc3dSmrg
1221debfc3dSmrg FOR_EACH_VEC_ELT (const_attrs, i, attr)
1231debfc3dSmrg if (strcmp (XSTR (attr, 0), XSTR (exp, 0)) == 0)
1241debfc3dSmrg {
1251debfc3dSmrg unsigned int j;
1261debfc3dSmrg rtx resv;
1271debfc3dSmrg
1281debfc3dSmrg FOR_EACH_VEC_ELT (reservations, j, resv)
1291debfc3dSmrg if (! check_tune_attr (XSTR (attr, 0), XEXP (resv, 2)))
1301debfc3dSmrg return false;
1311debfc3dSmrg return true;
1321debfc3dSmrg }
1331debfc3dSmrg return false;
1341debfc3dSmrg
1351debfc3dSmrg default:
1361debfc3dSmrg return false;
1371debfc3dSmrg }
1381debfc3dSmrg }
1391debfc3dSmrg
1401debfc3dSmrg int
main(int argc,const char ** argv)1411debfc3dSmrg main (int argc, const char **argv)
1421debfc3dSmrg {
1431debfc3dSmrg bool have_annul_true = false;
1441debfc3dSmrg bool have_annul_false = false;
1451debfc3dSmrg int num_insn_reservations = 0;
1461debfc3dSmrg int i;
1471debfc3dSmrg
1481debfc3dSmrg progname = "genattr";
1491debfc3dSmrg
1501debfc3dSmrg if (!init_rtx_reader_args (argc, argv))
1511debfc3dSmrg return (FATAL_EXIT_CODE);
1521debfc3dSmrg
1531debfc3dSmrg puts ("/* Generated automatically by the program `genattr'");
1541debfc3dSmrg puts (" from the machine description file `md'. */\n");
1551debfc3dSmrg puts ("#ifndef GCC_INSN_ATTR_H");
1561debfc3dSmrg puts ("#define GCC_INSN_ATTR_H\n");
1571debfc3dSmrg
1581debfc3dSmrg puts ("#include \"insn-attr-common.h\"\n");
1591debfc3dSmrg
1601debfc3dSmrg /* Read the machine description. */
1611debfc3dSmrg
1621debfc3dSmrg md_rtx_info info;
1631debfc3dSmrg while (read_md_rtx (&info))
1641debfc3dSmrg {
1651debfc3dSmrg rtx def = info.def;
1661debfc3dSmrg switch (GET_CODE (def))
1671debfc3dSmrg {
1681debfc3dSmrg case DEFINE_ATTR:
1691debfc3dSmrg case DEFINE_ENUM_ATTR:
1701debfc3dSmrg gen_attr (&info);
1711debfc3dSmrg break;
1721debfc3dSmrg
1731debfc3dSmrg case DEFINE_DELAY:
1741debfc3dSmrg for (i = 0; i < XVECLEN (def, 1); i += 3)
1751debfc3dSmrg {
1761debfc3dSmrg if (XVECEXP (def, 1, i + 1))
1771debfc3dSmrg have_annul_true = true;
1781debfc3dSmrg
1791debfc3dSmrg if (XVECEXP (def, 1, i + 2))
1801debfc3dSmrg have_annul_false = true;
1811debfc3dSmrg }
1821debfc3dSmrg break;
1831debfc3dSmrg
1841debfc3dSmrg case DEFINE_INSN_RESERVATION:
1851debfc3dSmrg num_insn_reservations++;
1861debfc3dSmrg reservations.safe_push (def);
1871debfc3dSmrg break;
1881debfc3dSmrg
1891debfc3dSmrg default:
1901debfc3dSmrg break;
1911debfc3dSmrg }
1921debfc3dSmrg }
1931debfc3dSmrg
1941debfc3dSmrg printf ("extern int num_delay_slots (rtx_insn *);\n");
1951debfc3dSmrg printf ("extern int eligible_for_delay (rtx_insn *, int, rtx_insn *, int);\n\n");
1961debfc3dSmrg printf ("extern int const_num_delay_slots (rtx_insn *);\n\n");
1971debfc3dSmrg printf ("#define ANNUL_IFTRUE_SLOTS %d\n", have_annul_true);
1981debfc3dSmrg printf ("extern int eligible_for_annul_true (rtx_insn *, int, rtx_insn *, int);\n");
1991debfc3dSmrg printf ("#define ANNUL_IFFALSE_SLOTS %d\n", have_annul_false);
2001debfc3dSmrg printf ("extern int eligible_for_annul_false (rtx_insn *, int, rtx_insn *, int);\n");
2011debfc3dSmrg
2021debfc3dSmrg if (num_insn_reservations > 0)
2031debfc3dSmrg {
2041debfc3dSmrg bool has_tune_attr
2051debfc3dSmrg = find_tune_attr (XEXP (reservations[0], 2));
2061debfc3dSmrg /* Output interface for pipeline hazards recognition based on
2071debfc3dSmrg DFA (deterministic finite state automata. */
2081debfc3dSmrg printf ("\n/* DFA based pipeline interface. */");
2091debfc3dSmrg printf ("\n#ifndef AUTOMATON_ALTS\n");
2101debfc3dSmrg printf ("#define AUTOMATON_ALTS 0\n");
2111debfc3dSmrg printf ("#endif\n\n");
2121debfc3dSmrg printf ("\n#ifndef AUTOMATON_STATE_ALTS\n");
2131debfc3dSmrg printf ("#define AUTOMATON_STATE_ALTS 0\n");
2141debfc3dSmrg printf ("#endif\n\n");
2151debfc3dSmrg printf ("#ifndef CPU_UNITS_QUERY\n");
2161debfc3dSmrg printf ("#define CPU_UNITS_QUERY 0\n");
2171debfc3dSmrg printf ("#endif\n\n");
2181debfc3dSmrg /* Interface itself: */
2191debfc3dSmrg if (has_tune_attr)
2201debfc3dSmrg {
2211debfc3dSmrg printf ("/* Initialize fn pointers for internal_dfa_insn_code\n");
2221debfc3dSmrg printf (" and insn_default_latency. */\n");
2231debfc3dSmrg printf ("extern void init_sched_attrs (void);\n\n");
2241debfc3dSmrg printf ("/* Internal insn code number used by automata. */\n");
2251debfc3dSmrg printf ("extern int (*internal_dfa_insn_code) (rtx_insn *);\n\n");
2261debfc3dSmrg printf ("/* Insn latency time defined in define_insn_reservation. */\n");
2271debfc3dSmrg printf ("extern int (*insn_default_latency) (rtx_insn *);\n\n");
2281debfc3dSmrg }
2291debfc3dSmrg else
2301debfc3dSmrg {
2311debfc3dSmrg printf ("#define init_sched_attrs() do { } while (0)\n\n");
2321debfc3dSmrg printf ("/* Internal insn code number used by automata. */\n");
2331debfc3dSmrg printf ("extern int internal_dfa_insn_code (rtx_insn *);\n\n");
2341debfc3dSmrg printf ("/* Insn latency time defined in define_insn_reservation. */\n");
2351debfc3dSmrg printf ("extern int insn_default_latency (rtx_insn *);\n\n");
2361debfc3dSmrg }
2371debfc3dSmrg printf ("/* Return nonzero if there is a bypass for given insn\n");
2381debfc3dSmrg printf (" which is a data producer. */\n");
2391debfc3dSmrg printf ("extern int bypass_p (rtx_insn *);\n\n");
2401debfc3dSmrg printf ("/* Insn latency time on data consumed by the 2nd insn.\n");
2411debfc3dSmrg printf (" Use the function if bypass_p returns nonzero for\n");
2421debfc3dSmrg printf (" the 1st insn. */\n");
2431debfc3dSmrg printf ("extern int insn_latency (rtx_insn *, rtx_insn *);\n\n");
2441debfc3dSmrg printf ("/* Maximal insn latency time possible of all bypasses for this insn.\n");
2451debfc3dSmrg printf (" Use the function if bypass_p returns nonzero for\n");
2461debfc3dSmrg printf (" the 1st insn. */\n");
2471debfc3dSmrg printf ("extern int maximal_insn_latency (rtx_insn *);\n\n");
2481debfc3dSmrg printf ("\n#if AUTOMATON_ALTS\n");
2491debfc3dSmrg printf ("/* The following function returns number of alternative\n");
2501debfc3dSmrg printf (" reservations of given insn. It may be used for better\n");
2511debfc3dSmrg printf (" insns scheduling heuristics. */\n");
2521debfc3dSmrg printf ("extern int insn_alts (rtx);\n\n");
2531debfc3dSmrg printf ("#endif\n\n");
2541debfc3dSmrg printf ("/* Maximal possible number of insns waiting results being\n");
2551debfc3dSmrg printf (" produced by insns whose execution is not finished. */\n");
2561debfc3dSmrg printf ("extern const int max_insn_queue_index;\n\n");
2571debfc3dSmrg printf ("/* Pointer to data describing current state of DFA. */\n");
2581debfc3dSmrg printf ("typedef void *state_t;\n\n");
2591debfc3dSmrg printf ("/* Size of the data in bytes. */\n");
2601debfc3dSmrg printf ("extern int state_size (void);\n\n");
2611debfc3dSmrg printf ("/* Initiate given DFA state, i.e. Set up the state\n");
2621debfc3dSmrg printf (" as all functional units were not reserved. */\n");
2631debfc3dSmrg printf ("extern void state_reset (state_t);\n");
2641debfc3dSmrg printf ("/* The following function returns negative value if given\n");
2651debfc3dSmrg printf (" insn can be issued in processor state described by given\n");
2661debfc3dSmrg printf (" DFA state. In this case, the DFA state is changed to\n");
2671debfc3dSmrg printf (" reflect the current and future reservations by given\n");
2681debfc3dSmrg printf (" insn. Otherwise the function returns minimal time\n");
2691debfc3dSmrg printf (" delay to issue the insn. This delay may be zero\n");
2701debfc3dSmrg printf (" for superscalar or VLIW processors. If the second\n");
2711debfc3dSmrg printf (" parameter is NULL the function changes given DFA state\n");
2721debfc3dSmrg printf (" as new processor cycle started. */\n");
2731debfc3dSmrg printf ("extern int state_transition (state_t, rtx);\n");
2741debfc3dSmrg printf ("\n#if AUTOMATON_STATE_ALTS\n");
2751debfc3dSmrg printf ("/* The following function returns number of possible\n");
2761debfc3dSmrg printf (" alternative reservations of given insn in given\n");
2771debfc3dSmrg printf (" DFA state. It may be used for better insns scheduling\n");
2781debfc3dSmrg printf (" heuristics. By default the function is defined if\n");
2791debfc3dSmrg printf (" macro AUTOMATON_STATE_ALTS is defined because its\n");
2801debfc3dSmrg printf (" implementation may require much memory. */\n");
2811debfc3dSmrg printf ("extern int state_alts (state_t, rtx);\n");
2821debfc3dSmrg printf ("#endif\n\n");
2831debfc3dSmrg printf ("extern int min_issue_delay (state_t, rtx_insn *);\n");
2841debfc3dSmrg printf ("/* The following function returns nonzero if no one insn\n");
2851debfc3dSmrg printf (" can be issued in current DFA state. */\n");
2861debfc3dSmrg printf ("extern int state_dead_lock_p (state_t);\n");
2871debfc3dSmrg printf ("/* The function returns minimal delay of issue of the 2nd\n");
2881debfc3dSmrg printf (" insn after issuing the 1st insn in given DFA state.\n");
2891debfc3dSmrg printf (" The 1st insn should be issued in given state (i.e.\n");
2901debfc3dSmrg printf (" state_transition should return negative value for\n");
2911debfc3dSmrg printf (" the insn and the state). Data dependencies between\n");
2921debfc3dSmrg printf (" the insns are ignored by the function. */\n");
2931debfc3dSmrg printf ("extern int "
2941debfc3dSmrg "min_insn_conflict_delay (state_t, rtx_insn *, rtx_insn *);\n");
2951debfc3dSmrg printf ("/* The following function outputs reservations for given\n");
2961debfc3dSmrg printf (" insn as they are described in the corresponding\n");
2971debfc3dSmrg printf (" define_insn_reservation. */\n");
2981debfc3dSmrg printf ("extern void print_reservation (FILE *, rtx_insn *);\n");
2991debfc3dSmrg printf ("\n#if CPU_UNITS_QUERY\n");
3001debfc3dSmrg printf ("/* The following function returns code of functional unit\n");
3011debfc3dSmrg printf (" with given name (see define_cpu_unit). */\n");
3021debfc3dSmrg printf ("extern int get_cpu_unit_code (const char *);\n");
3031debfc3dSmrg printf ("/* The following function returns nonzero if functional\n");
3041debfc3dSmrg printf (" unit with given code is currently reserved in given\n");
3051debfc3dSmrg printf (" DFA state. */\n");
3061debfc3dSmrg printf ("extern int cpu_unit_reservation_p (state_t, int);\n");
3071debfc3dSmrg printf ("#endif\n\n");
3081debfc3dSmrg printf ("/* The following function returns true if insn\n");
3091debfc3dSmrg printf (" has a dfa reservation. */\n");
3101debfc3dSmrg printf ("extern bool insn_has_dfa_reservation_p (rtx_insn *);\n\n");
3111debfc3dSmrg printf ("/* Clean insn code cache. It should be called if there\n");
3121debfc3dSmrg printf (" is a chance that condition value in a\n");
3131debfc3dSmrg printf (" define_insn_reservation will be changed after\n");
3141debfc3dSmrg printf (" last call of dfa_start. */\n");
3151debfc3dSmrg printf ("extern void dfa_clean_insn_cache (void);\n\n");
3161debfc3dSmrg printf ("extern void dfa_clear_single_insn_cache (rtx_insn *);\n\n");
3171debfc3dSmrg printf ("/* Initiate and finish work with DFA. They should be\n");
3181debfc3dSmrg printf (" called as the first and the last interface\n");
3191debfc3dSmrg printf (" functions. */\n");
3201debfc3dSmrg printf ("extern void dfa_start (void);\n");
3211debfc3dSmrg printf ("extern void dfa_finish (void);\n");
3221debfc3dSmrg }
3231debfc3dSmrg else
3241debfc3dSmrg {
3251debfc3dSmrg /* Otherwise we do no scheduling, but we need these typedefs
3261debfc3dSmrg in order to avoid uglifying other code with more ifdefs. */
3271debfc3dSmrg printf ("typedef void *state_t;\n\n");
3281debfc3dSmrg }
3291debfc3dSmrg
3301debfc3dSmrg /* Special-purpose attributes should be tested with if, not #ifdef. */
3311debfc3dSmrg const char * const special_attrs[] = { "length", "enabled",
3321debfc3dSmrg "preferred_for_size",
3331debfc3dSmrg "preferred_for_speed", 0 };
3341debfc3dSmrg for (const char * const *p = special_attrs; *p; p++)
3351debfc3dSmrg {
3361debfc3dSmrg printf ("#ifndef HAVE_ATTR_%s\n"
3371debfc3dSmrg "#define HAVE_ATTR_%s 0\n"
3381debfc3dSmrg "#endif\n", *p, *p);
3391debfc3dSmrg }
3401debfc3dSmrg /* We make an exception here to provide stub definitions for
3411debfc3dSmrg insn_*_length* / get_attr_enabled functions. */
3421debfc3dSmrg puts ("#if !HAVE_ATTR_length\n"
3431debfc3dSmrg "extern int hook_int_rtx_insn_unreachable (rtx_insn *);\n"
3441debfc3dSmrg "#define insn_default_length hook_int_rtx_insn_unreachable\n"
3451debfc3dSmrg "#define insn_min_length hook_int_rtx_insn_unreachable\n"
3461debfc3dSmrg "#define insn_variable_length_p hook_int_rtx_insn_unreachable\n"
3471debfc3dSmrg "#define insn_current_length hook_int_rtx_insn_unreachable\n"
3481debfc3dSmrg "#include \"insn-addr.h\"\n"
3491debfc3dSmrg "#endif\n"
3501debfc3dSmrg "extern int hook_int_rtx_1 (rtx);\n"
3511debfc3dSmrg "#if !HAVE_ATTR_enabled\n"
3521debfc3dSmrg "#define get_attr_enabled hook_int_rtx_1\n"
3531debfc3dSmrg "#endif\n"
3541debfc3dSmrg "#if !HAVE_ATTR_preferred_for_size\n"
3551debfc3dSmrg "#define get_attr_preferred_for_size hook_int_rtx_1\n"
3561debfc3dSmrg "#endif\n"
3571debfc3dSmrg "#if !HAVE_ATTR_preferred_for_speed\n"
3581debfc3dSmrg "#define get_attr_preferred_for_speed hook_int_rtx_1\n"
3591debfc3dSmrg "#endif\n");
3601debfc3dSmrg
3611debfc3dSmrg /* Output flag masks for use by reorg.
3621debfc3dSmrg
3631debfc3dSmrg Flags are used to hold branch direction for use by eligible_for_... */
3641debfc3dSmrg printf ("\n#define ATTR_FLAG_forward\t0x1\n");
3651debfc3dSmrg printf ("#define ATTR_FLAG_backward\t0x2\n");
3661debfc3dSmrg
3671debfc3dSmrg puts ("\n#endif /* GCC_INSN_ATTR_H */");
3681debfc3dSmrg
3691debfc3dSmrg if (ferror (stdout) || fflush (stdout) || fclose (stdout))
3701debfc3dSmrg return FATAL_EXIT_CODE;
3711debfc3dSmrg
3721debfc3dSmrg return SUCCESS_EXIT_CODE;
3731debfc3dSmrg }
374