1*38fd1498Szrj /* Generate attribute information (insn-attr.h) from machine description.
2*38fd1498Szrj Copyright (C) 1991-2018 Free Software Foundation, Inc.
3*38fd1498Szrj Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
4*38fd1498Szrj
5*38fd1498Szrj This file is part of GCC.
6*38fd1498Szrj
7*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
8*38fd1498Szrj the terms of the GNU General Public License as published by the Free
9*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
10*38fd1498Szrj version.
11*38fd1498Szrj
12*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15*38fd1498Szrj for more details.
16*38fd1498Szrj
17*38fd1498Szrj You should have received a copy of the GNU General Public License
18*38fd1498Szrj along with GCC; see the file COPYING3. If not see
19*38fd1498Szrj <http://www.gnu.org/licenses/>. */
20*38fd1498Szrj
21*38fd1498Szrj
22*38fd1498Szrj #include "bconfig.h"
23*38fd1498Szrj #include "system.h"
24*38fd1498Szrj #include "coretypes.h"
25*38fd1498Szrj #include "tm.h"
26*38fd1498Szrj #include "rtl.h"
27*38fd1498Szrj #include "errors.h"
28*38fd1498Szrj #include "read-md.h"
29*38fd1498Szrj #include "gensupport.h"
30*38fd1498Szrj
31*38fd1498Szrj
32*38fd1498Szrj static vec<rtx> const_attrs, reservations;
33*38fd1498Szrj
34*38fd1498Szrj
35*38fd1498Szrj static void
gen_attr(md_rtx_info * info)36*38fd1498Szrj gen_attr (md_rtx_info *info)
37*38fd1498Szrj {
38*38fd1498Szrj const char *p;
39*38fd1498Szrj rtx attr = info->def;
40*38fd1498Szrj int is_const = GET_CODE (XEXP (attr, 2)) == CONST;
41*38fd1498Szrj
42*38fd1498Szrj if (is_const)
43*38fd1498Szrj const_attrs.safe_push (attr);
44*38fd1498Szrj
45*38fd1498Szrj printf ("#define HAVE_ATTR_%s 1\n", XSTR (attr, 0));
46*38fd1498Szrj
47*38fd1498Szrj /* If numeric attribute, don't need to write an enum. */
48*38fd1498Szrj if (GET_CODE (attr) == DEFINE_ENUM_ATTR)
49*38fd1498Szrj printf ("extern enum %s get_attr_%s (%s);\n\n",
50*38fd1498Szrj XSTR (attr, 1), XSTR (attr, 0),
51*38fd1498Szrj (is_const ? "void" : "rtx_insn *"));
52*38fd1498Szrj else
53*38fd1498Szrj {
54*38fd1498Szrj p = XSTR (attr, 1);
55*38fd1498Szrj if (*p == '\0')
56*38fd1498Szrj printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0),
57*38fd1498Szrj (is_const ? "void" : "rtx_insn *"));
58*38fd1498Szrj else
59*38fd1498Szrj printf ("extern enum attr_%s get_attr_%s (%s);\n\n",
60*38fd1498Szrj XSTR (attr, 0), XSTR (attr, 0),
61*38fd1498Szrj (is_const ? "void" : "rtx_insn *"));
62*38fd1498Szrj }
63*38fd1498Szrj
64*38fd1498Szrj /* If `length' attribute, write additional function definitions and define
65*38fd1498Szrj variables used by `insn_current_length'. */
66*38fd1498Szrj if (! strcmp (XSTR (attr, 0), "length"))
67*38fd1498Szrj {
68*38fd1498Szrj puts ("\
69*38fd1498Szrj extern void shorten_branches (rtx_insn *);\n\
70*38fd1498Szrj extern int insn_default_length (rtx_insn *);\n\
71*38fd1498Szrj extern int insn_min_length (rtx_insn *);\n\
72*38fd1498Szrj extern int insn_variable_length_p (rtx_insn *);\n\
73*38fd1498Szrj extern int insn_current_length (rtx_insn *);\n\n\
74*38fd1498Szrj #include \"insn-addr.h\"\n");
75*38fd1498Szrj }
76*38fd1498Szrj }
77*38fd1498Szrj
78*38fd1498Szrj /* Check that attribute NAME is used in define_insn_reservation condition
79*38fd1498Szrj EXP. Return true if it is. */
80*38fd1498Szrj static bool
check_tune_attr(const char * name,rtx exp)81*38fd1498Szrj check_tune_attr (const char *name, rtx exp)
82*38fd1498Szrj {
83*38fd1498Szrj switch (GET_CODE (exp))
84*38fd1498Szrj {
85*38fd1498Szrj case AND:
86*38fd1498Szrj if (check_tune_attr (name, XEXP (exp, 0)))
87*38fd1498Szrj return true;
88*38fd1498Szrj return check_tune_attr (name, XEXP (exp, 1));
89*38fd1498Szrj
90*38fd1498Szrj case IOR:
91*38fd1498Szrj return (check_tune_attr (name, XEXP (exp, 0))
92*38fd1498Szrj && check_tune_attr (name, XEXP (exp, 1)));
93*38fd1498Szrj
94*38fd1498Szrj case EQ_ATTR:
95*38fd1498Szrj return strcmp (XSTR (exp, 0), name) == 0;
96*38fd1498Szrj
97*38fd1498Szrj default:
98*38fd1498Szrj return false;
99*38fd1498Szrj }
100*38fd1498Szrj }
101*38fd1498Szrj
102*38fd1498Szrj /* Try to find a const attribute (usually cpu or tune) that is used
103*38fd1498Szrj in all define_insn_reservation conditions. */
104*38fd1498Szrj static bool
find_tune_attr(rtx exp)105*38fd1498Szrj find_tune_attr (rtx exp)
106*38fd1498Szrj {
107*38fd1498Szrj unsigned int i;
108*38fd1498Szrj rtx attr;
109*38fd1498Szrj
110*38fd1498Szrj switch (GET_CODE (exp))
111*38fd1498Szrj {
112*38fd1498Szrj case AND:
113*38fd1498Szrj case IOR:
114*38fd1498Szrj if (find_tune_attr (XEXP (exp, 0)))
115*38fd1498Szrj return true;
116*38fd1498Szrj return find_tune_attr (XEXP (exp, 1));
117*38fd1498Szrj
118*38fd1498Szrj case EQ_ATTR:
119*38fd1498Szrj if (strcmp (XSTR (exp, 0), "alternative") == 0)
120*38fd1498Szrj return false;
121*38fd1498Szrj
122*38fd1498Szrj FOR_EACH_VEC_ELT (const_attrs, i, attr)
123*38fd1498Szrj if (strcmp (XSTR (attr, 0), XSTR (exp, 0)) == 0)
124*38fd1498Szrj {
125*38fd1498Szrj unsigned int j;
126*38fd1498Szrj rtx resv;
127*38fd1498Szrj
128*38fd1498Szrj FOR_EACH_VEC_ELT (reservations, j, resv)
129*38fd1498Szrj if (! check_tune_attr (XSTR (attr, 0), XEXP (resv, 2)))
130*38fd1498Szrj return false;
131*38fd1498Szrj return true;
132*38fd1498Szrj }
133*38fd1498Szrj return false;
134*38fd1498Szrj
135*38fd1498Szrj default:
136*38fd1498Szrj return false;
137*38fd1498Szrj }
138*38fd1498Szrj }
139*38fd1498Szrj
140*38fd1498Szrj int
main(int argc,const char ** argv)141*38fd1498Szrj main (int argc, const char **argv)
142*38fd1498Szrj {
143*38fd1498Szrj bool have_annul_true = false;
144*38fd1498Szrj bool have_annul_false = false;
145*38fd1498Szrj int num_insn_reservations = 0;
146*38fd1498Szrj int i;
147*38fd1498Szrj
148*38fd1498Szrj progname = "genattr";
149*38fd1498Szrj
150*38fd1498Szrj if (!init_rtx_reader_args (argc, argv))
151*38fd1498Szrj return (FATAL_EXIT_CODE);
152*38fd1498Szrj
153*38fd1498Szrj puts ("/* Generated automatically by the program `genattr'");
154*38fd1498Szrj puts (" from the machine description file `md'. */\n");
155*38fd1498Szrj puts ("#ifndef GCC_INSN_ATTR_H");
156*38fd1498Szrj puts ("#define GCC_INSN_ATTR_H\n");
157*38fd1498Szrj
158*38fd1498Szrj puts ("#include \"insn-attr-common.h\"\n");
159*38fd1498Szrj
160*38fd1498Szrj /* Read the machine description. */
161*38fd1498Szrj
162*38fd1498Szrj md_rtx_info info;
163*38fd1498Szrj while (read_md_rtx (&info))
164*38fd1498Szrj {
165*38fd1498Szrj rtx def = info.def;
166*38fd1498Szrj switch (GET_CODE (def))
167*38fd1498Szrj {
168*38fd1498Szrj case DEFINE_ATTR:
169*38fd1498Szrj case DEFINE_ENUM_ATTR:
170*38fd1498Szrj gen_attr (&info);
171*38fd1498Szrj break;
172*38fd1498Szrj
173*38fd1498Szrj case DEFINE_DELAY:
174*38fd1498Szrj for (i = 0; i < XVECLEN (def, 1); i += 3)
175*38fd1498Szrj {
176*38fd1498Szrj if (XVECEXP (def, 1, i + 1))
177*38fd1498Szrj have_annul_true = true;
178*38fd1498Szrj
179*38fd1498Szrj if (XVECEXP (def, 1, i + 2))
180*38fd1498Szrj have_annul_false = true;
181*38fd1498Szrj }
182*38fd1498Szrj break;
183*38fd1498Szrj
184*38fd1498Szrj case DEFINE_INSN_RESERVATION:
185*38fd1498Szrj num_insn_reservations++;
186*38fd1498Szrj reservations.safe_push (def);
187*38fd1498Szrj break;
188*38fd1498Szrj
189*38fd1498Szrj default:
190*38fd1498Szrj break;
191*38fd1498Szrj }
192*38fd1498Szrj }
193*38fd1498Szrj
194*38fd1498Szrj printf ("extern int num_delay_slots (rtx_insn *);\n");
195*38fd1498Szrj printf ("extern int eligible_for_delay (rtx_insn *, int, rtx_insn *, int);\n\n");
196*38fd1498Szrj printf ("extern int const_num_delay_slots (rtx_insn *);\n\n");
197*38fd1498Szrj printf ("#define ANNUL_IFTRUE_SLOTS %d\n", have_annul_true);
198*38fd1498Szrj printf ("extern int eligible_for_annul_true (rtx_insn *, int, rtx_insn *, int);\n");
199*38fd1498Szrj printf ("#define ANNUL_IFFALSE_SLOTS %d\n", have_annul_false);
200*38fd1498Szrj printf ("extern int eligible_for_annul_false (rtx_insn *, int, rtx_insn *, int);\n");
201*38fd1498Szrj
202*38fd1498Szrj if (num_insn_reservations > 0)
203*38fd1498Szrj {
204*38fd1498Szrj bool has_tune_attr
205*38fd1498Szrj = find_tune_attr (XEXP (reservations[0], 2));
206*38fd1498Szrj /* Output interface for pipeline hazards recognition based on
207*38fd1498Szrj DFA (deterministic finite state automata. */
208*38fd1498Szrj printf ("\n/* DFA based pipeline interface. */");
209*38fd1498Szrj printf ("\n#ifndef AUTOMATON_ALTS\n");
210*38fd1498Szrj printf ("#define AUTOMATON_ALTS 0\n");
211*38fd1498Szrj printf ("#endif\n\n");
212*38fd1498Szrj printf ("\n#ifndef AUTOMATON_STATE_ALTS\n");
213*38fd1498Szrj printf ("#define AUTOMATON_STATE_ALTS 0\n");
214*38fd1498Szrj printf ("#endif\n\n");
215*38fd1498Szrj printf ("#ifndef CPU_UNITS_QUERY\n");
216*38fd1498Szrj printf ("#define CPU_UNITS_QUERY 0\n");
217*38fd1498Szrj printf ("#endif\n\n");
218*38fd1498Szrj /* Interface itself: */
219*38fd1498Szrj if (has_tune_attr)
220*38fd1498Szrj {
221*38fd1498Szrj printf ("/* Initialize fn pointers for internal_dfa_insn_code\n");
222*38fd1498Szrj printf (" and insn_default_latency. */\n");
223*38fd1498Szrj printf ("extern void init_sched_attrs (void);\n\n");
224*38fd1498Szrj printf ("/* Internal insn code number used by automata. */\n");
225*38fd1498Szrj printf ("extern int (*internal_dfa_insn_code) (rtx_insn *);\n\n");
226*38fd1498Szrj printf ("/* Insn latency time defined in define_insn_reservation. */\n");
227*38fd1498Szrj printf ("extern int (*insn_default_latency) (rtx_insn *);\n\n");
228*38fd1498Szrj }
229*38fd1498Szrj else
230*38fd1498Szrj {
231*38fd1498Szrj printf ("#define init_sched_attrs() do { } while (0)\n\n");
232*38fd1498Szrj printf ("/* Internal insn code number used by automata. */\n");
233*38fd1498Szrj printf ("extern int internal_dfa_insn_code (rtx_insn *);\n\n");
234*38fd1498Szrj printf ("/* Insn latency time defined in define_insn_reservation. */\n");
235*38fd1498Szrj printf ("extern int insn_default_latency (rtx_insn *);\n\n");
236*38fd1498Szrj }
237*38fd1498Szrj printf ("/* Return nonzero if there is a bypass for given insn\n");
238*38fd1498Szrj printf (" which is a data producer. */\n");
239*38fd1498Szrj printf ("extern int bypass_p (rtx_insn *);\n\n");
240*38fd1498Szrj printf ("/* Insn latency time on data consumed by the 2nd insn.\n");
241*38fd1498Szrj printf (" Use the function if bypass_p returns nonzero for\n");
242*38fd1498Szrj printf (" the 1st insn. */\n");
243*38fd1498Szrj printf ("extern int insn_latency (rtx_insn *, rtx_insn *);\n\n");
244*38fd1498Szrj printf ("/* Maximal insn latency time possible of all bypasses for this insn.\n");
245*38fd1498Szrj printf (" Use the function if bypass_p returns nonzero for\n");
246*38fd1498Szrj printf (" the 1st insn. */\n");
247*38fd1498Szrj printf ("extern int maximal_insn_latency (rtx_insn *);\n\n");
248*38fd1498Szrj printf ("\n#if AUTOMATON_ALTS\n");
249*38fd1498Szrj printf ("/* The following function returns number of alternative\n");
250*38fd1498Szrj printf (" reservations of given insn. It may be used for better\n");
251*38fd1498Szrj printf (" insns scheduling heuristics. */\n");
252*38fd1498Szrj printf ("extern int insn_alts (rtx);\n\n");
253*38fd1498Szrj printf ("#endif\n\n");
254*38fd1498Szrj printf ("/* Maximal possible number of insns waiting results being\n");
255*38fd1498Szrj printf (" produced by insns whose execution is not finished. */\n");
256*38fd1498Szrj printf ("extern const int max_insn_queue_index;\n\n");
257*38fd1498Szrj printf ("/* Pointer to data describing current state of DFA. */\n");
258*38fd1498Szrj printf ("typedef void *state_t;\n\n");
259*38fd1498Szrj printf ("/* Size of the data in bytes. */\n");
260*38fd1498Szrj printf ("extern int state_size (void);\n\n");
261*38fd1498Szrj printf ("/* Initiate given DFA state, i.e. Set up the state\n");
262*38fd1498Szrj printf (" as all functional units were not reserved. */\n");
263*38fd1498Szrj printf ("extern void state_reset (state_t);\n");
264*38fd1498Szrj printf ("/* The following function returns negative value if given\n");
265*38fd1498Szrj printf (" insn can be issued in processor state described by given\n");
266*38fd1498Szrj printf (" DFA state. In this case, the DFA state is changed to\n");
267*38fd1498Szrj printf (" reflect the current and future reservations by given\n");
268*38fd1498Szrj printf (" insn. Otherwise the function returns minimal time\n");
269*38fd1498Szrj printf (" delay to issue the insn. This delay may be zero\n");
270*38fd1498Szrj printf (" for superscalar or VLIW processors. If the second\n");
271*38fd1498Szrj printf (" parameter is NULL the function changes given DFA state\n");
272*38fd1498Szrj printf (" as new processor cycle started. */\n");
273*38fd1498Szrj printf ("extern int state_transition (state_t, rtx);\n");
274*38fd1498Szrj printf ("\n#if AUTOMATON_STATE_ALTS\n");
275*38fd1498Szrj printf ("/* The following function returns number of possible\n");
276*38fd1498Szrj printf (" alternative reservations of given insn in given\n");
277*38fd1498Szrj printf (" DFA state. It may be used for better insns scheduling\n");
278*38fd1498Szrj printf (" heuristics. By default the function is defined if\n");
279*38fd1498Szrj printf (" macro AUTOMATON_STATE_ALTS is defined because its\n");
280*38fd1498Szrj printf (" implementation may require much memory. */\n");
281*38fd1498Szrj printf ("extern int state_alts (state_t, rtx);\n");
282*38fd1498Szrj printf ("#endif\n\n");
283*38fd1498Szrj printf ("extern int min_issue_delay (state_t, rtx_insn *);\n");
284*38fd1498Szrj printf ("/* The following function returns nonzero if no one insn\n");
285*38fd1498Szrj printf (" can be issued in current DFA state. */\n");
286*38fd1498Szrj printf ("extern int state_dead_lock_p (state_t);\n");
287*38fd1498Szrj printf ("/* The function returns minimal delay of issue of the 2nd\n");
288*38fd1498Szrj printf (" insn after issuing the 1st insn in given DFA state.\n");
289*38fd1498Szrj printf (" The 1st insn should be issued in given state (i.e.\n");
290*38fd1498Szrj printf (" state_transition should return negative value for\n");
291*38fd1498Szrj printf (" the insn and the state). Data dependencies between\n");
292*38fd1498Szrj printf (" the insns are ignored by the function. */\n");
293*38fd1498Szrj printf ("extern int "
294*38fd1498Szrj "min_insn_conflict_delay (state_t, rtx_insn *, rtx_insn *);\n");
295*38fd1498Szrj printf ("/* The following function outputs reservations for given\n");
296*38fd1498Szrj printf (" insn as they are described in the corresponding\n");
297*38fd1498Szrj printf (" define_insn_reservation. */\n");
298*38fd1498Szrj printf ("extern void print_reservation (FILE *, rtx_insn *);\n");
299*38fd1498Szrj printf ("\n#if CPU_UNITS_QUERY\n");
300*38fd1498Szrj printf ("/* The following function returns code of functional unit\n");
301*38fd1498Szrj printf (" with given name (see define_cpu_unit). */\n");
302*38fd1498Szrj printf ("extern int get_cpu_unit_code (const char *);\n");
303*38fd1498Szrj printf ("/* The following function returns nonzero if functional\n");
304*38fd1498Szrj printf (" unit with given code is currently reserved in given\n");
305*38fd1498Szrj printf (" DFA state. */\n");
306*38fd1498Szrj printf ("extern int cpu_unit_reservation_p (state_t, int);\n");
307*38fd1498Szrj printf ("#endif\n\n");
308*38fd1498Szrj printf ("/* The following function returns true if insn\n");
309*38fd1498Szrj printf (" has a dfa reservation. */\n");
310*38fd1498Szrj printf ("extern bool insn_has_dfa_reservation_p (rtx_insn *);\n\n");
311*38fd1498Szrj printf ("/* Clean insn code cache. It should be called if there\n");
312*38fd1498Szrj printf (" is a chance that condition value in a\n");
313*38fd1498Szrj printf (" define_insn_reservation will be changed after\n");
314*38fd1498Szrj printf (" last call of dfa_start. */\n");
315*38fd1498Szrj printf ("extern void dfa_clean_insn_cache (void);\n\n");
316*38fd1498Szrj printf ("extern void dfa_clear_single_insn_cache (rtx_insn *);\n\n");
317*38fd1498Szrj printf ("/* Initiate and finish work with DFA. They should be\n");
318*38fd1498Szrj printf (" called as the first and the last interface\n");
319*38fd1498Szrj printf (" functions. */\n");
320*38fd1498Szrj printf ("extern void dfa_start (void);\n");
321*38fd1498Szrj printf ("extern void dfa_finish (void);\n");
322*38fd1498Szrj }
323*38fd1498Szrj else
324*38fd1498Szrj {
325*38fd1498Szrj /* Otherwise we do no scheduling, but we need these typedefs
326*38fd1498Szrj in order to avoid uglifying other code with more ifdefs. */
327*38fd1498Szrj printf ("typedef void *state_t;\n\n");
328*38fd1498Szrj }
329*38fd1498Szrj
330*38fd1498Szrj /* Special-purpose attributes should be tested with if, not #ifdef. */
331*38fd1498Szrj const char * const special_attrs[] = { "length", "enabled",
332*38fd1498Szrj "preferred_for_size",
333*38fd1498Szrj "preferred_for_speed", 0 };
334*38fd1498Szrj for (const char * const *p = special_attrs; *p; p++)
335*38fd1498Szrj {
336*38fd1498Szrj printf ("#ifndef HAVE_ATTR_%s\n"
337*38fd1498Szrj "#define HAVE_ATTR_%s 0\n"
338*38fd1498Szrj "#endif\n", *p, *p);
339*38fd1498Szrj }
340*38fd1498Szrj /* We make an exception here to provide stub definitions for
341*38fd1498Szrj insn_*_length* / get_attr_enabled functions. */
342*38fd1498Szrj puts ("#if !HAVE_ATTR_length\n"
343*38fd1498Szrj "extern int hook_int_rtx_insn_unreachable (rtx_insn *);\n"
344*38fd1498Szrj "#define insn_default_length hook_int_rtx_insn_unreachable\n"
345*38fd1498Szrj "#define insn_min_length hook_int_rtx_insn_unreachable\n"
346*38fd1498Szrj "#define insn_variable_length_p hook_int_rtx_insn_unreachable\n"
347*38fd1498Szrj "#define insn_current_length hook_int_rtx_insn_unreachable\n"
348*38fd1498Szrj "#include \"insn-addr.h\"\n"
349*38fd1498Szrj "#endif\n"
350*38fd1498Szrj "extern int hook_int_rtx_1 (rtx);\n"
351*38fd1498Szrj "#if !HAVE_ATTR_enabled\n"
352*38fd1498Szrj "#define get_attr_enabled hook_int_rtx_1\n"
353*38fd1498Szrj "#endif\n"
354*38fd1498Szrj "#if !HAVE_ATTR_preferred_for_size\n"
355*38fd1498Szrj "#define get_attr_preferred_for_size hook_int_rtx_1\n"
356*38fd1498Szrj "#endif\n"
357*38fd1498Szrj "#if !HAVE_ATTR_preferred_for_speed\n"
358*38fd1498Szrj "#define get_attr_preferred_for_speed hook_int_rtx_1\n"
359*38fd1498Szrj "#endif\n");
360*38fd1498Szrj
361*38fd1498Szrj /* Output flag masks for use by reorg.
362*38fd1498Szrj
363*38fd1498Szrj Flags are used to hold branch direction for use by eligible_for_... */
364*38fd1498Szrj printf ("\n#define ATTR_FLAG_forward\t0x1\n");
365*38fd1498Szrj printf ("#define ATTR_FLAG_backward\t0x2\n");
366*38fd1498Szrj
367*38fd1498Szrj puts ("\n#endif /* GCC_INSN_ATTR_H */");
368*38fd1498Szrj
369*38fd1498Szrj if (ferror (stdout) || fflush (stdout) || fclose (stdout))
370*38fd1498Szrj return FATAL_EXIT_CODE;
371*38fd1498Szrj
372*38fd1498Szrj return SUCCESS_EXIT_CODE;
373*38fd1498Szrj }
374