genattr.c 14 KB

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