sel-sched-dump.c 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073
  1. /* Instruction scheduling pass. Log dumping infrastructure.
  2. Copyright (C) 2006-2015 Free Software Foundation, Inc.
  3. This file is part of GCC.
  4. GCC is free software; you can redistribute it and/or modify it under
  5. the terms of the GNU General Public License as published by the Free
  6. Software Foundation; either version 3, or (at your option) any later
  7. version.
  8. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  9. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  11. for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GCC; see the file COPYING3. If not see
  14. <http://www.gnu.org/licenses/>. */
  15. #include "config.h"
  16. #include "system.h"
  17. #include "coretypes.h"
  18. #include "tm.h"
  19. #include "diagnostic-core.h"
  20. #include "rtl.h"
  21. #include "tm_p.h"
  22. #include "hard-reg-set.h"
  23. #include "regs.h"
  24. #include "hashtab.h"
  25. #include "hash-set.h"
  26. #include "vec.h"
  27. #include "machmode.h"
  28. #include "input.h"
  29. #include "function.h"
  30. #include "predict.h"
  31. #include "dominance.h"
  32. #include "cfg.h"
  33. #include "basic-block.h"
  34. #include "flags.h"
  35. #include "insn-config.h"
  36. #include "insn-attr.h"
  37. #include "params.h"
  38. #include "cselib.h"
  39. #include "target.h"
  40. #ifdef INSN_SCHEDULING
  41. #include "sel-sched-ir.h"
  42. #include "sel-sched-dump.h"
  43. /* These variables control high-level pretty printing. */
  44. static int sel_dump_cfg_flags = SEL_DUMP_CFG_FLAGS;
  45. static int sel_debug_cfg_flags = SEL_DUMP_CFG_FLAGS;
  46. /* True when a cfg should be dumped. */
  47. static bool sel_dump_cfg_p;
  48. /* Variables that are used to build the cfg dump file name. */
  49. static const char * const sel_debug_cfg_root = "./";
  50. static const char * const sel_debug_cfg_root_postfix_default = "";
  51. static const char *sel_debug_cfg_root_postfix = "";
  52. static int sel_dump_cfg_fileno = -1;
  53. static int sel_debug_cfg_fileno = -1;
  54. /* When this flag is on, we are dumping to the .dot file.
  55. When it is off, we are dumping to log.
  56. This is useful to differentiate formatting between log and .dot
  57. files. */
  58. bool sched_dump_to_dot_p = false;
  59. /* Controls how insns from a fence list should be dumped. */
  60. static int dump_flist_insn_flags = (DUMP_INSN_UID | DUMP_INSN_BBN
  61. | DUMP_INSN_SEQNO);
  62. /* The variable used to hold the value of sched_dump when temporarily
  63. switching dump output to the other source, e.g. the .dot file. */
  64. static FILE *saved_sched_dump = NULL;
  65. /* Switch sched_dump to TO. It must not be called twice. */
  66. static void
  67. switch_dump (FILE *to)
  68. {
  69. gcc_assert (saved_sched_dump == NULL);
  70. saved_sched_dump = sched_dump;
  71. sched_dump = to;
  72. }
  73. /* Restore previously switched dump. */
  74. static void
  75. restore_dump (void)
  76. {
  77. sched_dump = saved_sched_dump;
  78. saved_sched_dump = NULL;
  79. }
  80. /* Functions for dumping instructions, av sets, and exprs. */
  81. /* Default flags for dumping insns. */
  82. static int dump_insn_rtx_flags = DUMP_INSN_RTX_UID | DUMP_INSN_RTX_PATTERN;
  83. /* Default flags for dumping vinsns. */
  84. static int dump_vinsn_flags = (DUMP_VINSN_INSN_RTX | DUMP_VINSN_TYPE
  85. | DUMP_VINSN_COUNT);
  86. /* Default flags for dumping expressions. */
  87. static int dump_expr_flags = DUMP_EXPR_ALL;
  88. /* Default flags for dumping insns when debugging. */
  89. static int debug_insn_rtx_flags = DUMP_INSN_RTX_ALL;
  90. /* Default flags for dumping vinsns when debugging. */
  91. static int debug_vinsn_flags = DUMP_VINSN_ALL;
  92. /* Default flags for dumping expressions when debugging. */
  93. static int debug_expr_flags = DUMP_EXPR_ALL;
  94. /* Controls how an insn from stream should be dumped when debugging. */
  95. static int debug_insn_flags = DUMP_INSN_ALL;
  96. /* Print an rtx X. */
  97. void
  98. sel_print_rtl (rtx x)
  99. {
  100. print_rtl_single (sched_dump, x);
  101. }
  102. /* Dump insn INSN honoring FLAGS. */
  103. void
  104. dump_insn_rtx_1 (rtx insn, int flags)
  105. {
  106. int all;
  107. /* flags == -1 also means dumping all. */
  108. all = (flags & 1);;
  109. if (all)
  110. flags |= DUMP_INSN_RTX_ALL;
  111. sel_print ("(");
  112. if (flags & DUMP_INSN_RTX_UID)
  113. sel_print ("%d;", INSN_UID (insn));
  114. if (flags & DUMP_INSN_RTX_PATTERN)
  115. sel_print ("%s;", str_pattern_slim (PATTERN (insn)));
  116. if (flags & DUMP_INSN_RTX_BBN)
  117. {
  118. basic_block bb = BLOCK_FOR_INSN (insn);
  119. sel_print ("bb:%d;", bb != NULL ? bb->index : -1);
  120. }
  121. sel_print (")");
  122. }
  123. /* Dump INSN with default flags. */
  124. void
  125. dump_insn_rtx (rtx insn)
  126. {
  127. dump_insn_rtx_1 (insn, dump_insn_rtx_flags);
  128. }
  129. /* Dump INSN to stderr. */
  130. DEBUG_FUNCTION void
  131. debug_insn_rtx (rtx insn)
  132. {
  133. switch_dump (stderr);
  134. dump_insn_rtx_1 (insn, debug_insn_rtx_flags);
  135. sel_print ("\n");
  136. restore_dump ();
  137. }
  138. /* Dump vinsn VI honoring flags. */
  139. void
  140. dump_vinsn_1 (vinsn_t vi, int flags)
  141. {
  142. int all;
  143. /* flags == -1 also means dumping all. */
  144. all = flags & 1;
  145. if (all)
  146. flags |= DUMP_VINSN_ALL;
  147. sel_print ("(");
  148. if (flags & DUMP_VINSN_INSN_RTX)
  149. dump_insn_rtx_1 (VINSN_INSN_RTX (vi), dump_insn_rtx_flags | all);
  150. if (flags & DUMP_VINSN_TYPE)
  151. sel_print ("type:%s;", GET_RTX_NAME (VINSN_TYPE (vi)));
  152. if (flags & DUMP_VINSN_COUNT)
  153. sel_print ("count:%d;", VINSN_COUNT (vi));
  154. if (flags & DUMP_VINSN_COST)
  155. {
  156. int cost = vi->cost;
  157. if (cost != -1)
  158. sel_print ("cost:%d;", cost);
  159. }
  160. sel_print (")");
  161. }
  162. /* Dump vinsn VI with default flags. */
  163. void
  164. dump_vinsn (vinsn_t vi)
  165. {
  166. dump_vinsn_1 (vi, dump_vinsn_flags);
  167. }
  168. DEBUG_FUNCTION void
  169. debug (vinsn_def &ref)
  170. {
  171. switch_dump (stderr);
  172. dump_vinsn_1 (&ref, dump_vinsn_flags);
  173. sel_print ("\n");
  174. restore_dump ();
  175. }
  176. DEBUG_FUNCTION void
  177. debug (vinsn_def *ptr)
  178. {
  179. if (ptr)
  180. debug (*ptr);
  181. else
  182. fprintf (stderr, "<nil>\n");
  183. }
  184. DEBUG_FUNCTION void
  185. debug_verbose (vinsn_def &ref)
  186. {
  187. switch_dump (stderr);
  188. dump_vinsn_1 (&ref, debug_vinsn_flags);
  189. sel_print ("\n");
  190. restore_dump ();
  191. }
  192. DEBUG_FUNCTION void
  193. debug_verbose (vinsn_def *ptr)
  194. {
  195. if (ptr)
  196. debug (*ptr);
  197. else
  198. fprintf (stderr, "<nil>\n");
  199. }
  200. /* Dump vinsn VI to stderr. */
  201. DEBUG_FUNCTION void
  202. debug_vinsn (vinsn_t vi)
  203. {
  204. switch_dump (stderr);
  205. dump_vinsn_1 (vi, debug_vinsn_flags);
  206. sel_print ("\n");
  207. restore_dump ();
  208. }
  209. /* Dump EXPR honoring flags. */
  210. void
  211. dump_expr_1 (expr_t expr, int flags)
  212. {
  213. int all;
  214. /* flags == -1 also means dumping all. */
  215. all = flags & 1;
  216. if (all)
  217. flags |= DUMP_EXPR_ALL;
  218. sel_print ("[");
  219. if (flags & DUMP_EXPR_VINSN)
  220. dump_vinsn_1 (EXPR_VINSN (expr), dump_vinsn_flags | all);
  221. if (flags & DUMP_EXPR_SPEC)
  222. {
  223. int spec = EXPR_SPEC (expr);
  224. if (spec != 0)
  225. sel_print ("spec:%d;", spec);
  226. }
  227. if (flags & DUMP_EXPR_USEFULNESS)
  228. {
  229. int use = EXPR_USEFULNESS (expr);
  230. if (use != REG_BR_PROB_BASE)
  231. sel_print ("use:%d;", use);
  232. }
  233. if (flags & DUMP_EXPR_PRIORITY)
  234. sel_print ("prio:%d;", EXPR_PRIORITY (expr));
  235. if (flags & DUMP_EXPR_SCHED_TIMES)
  236. {
  237. int times = EXPR_SCHED_TIMES (expr);
  238. if (times != 0)
  239. sel_print ("times:%d;", times);
  240. }
  241. if (flags & DUMP_EXPR_SPEC_DONE_DS)
  242. {
  243. ds_t spec_done_ds = EXPR_SPEC_DONE_DS (expr);
  244. if (spec_done_ds != 0)
  245. sel_print ("ds:%d;", spec_done_ds);
  246. }
  247. if (flags & DUMP_EXPR_ORIG_BB)
  248. {
  249. int orig_bb = EXPR_ORIG_BB_INDEX (expr);
  250. if (orig_bb != 0)
  251. sel_print ("orig_bb:%d;", orig_bb);
  252. }
  253. if (EXPR_TARGET_AVAILABLE (expr) < 1)
  254. sel_print ("target:%d;", EXPR_TARGET_AVAILABLE (expr));
  255. sel_print ("]");
  256. }
  257. /* Dump expression EXPR with default flags. */
  258. void
  259. dump_expr (expr_t expr)
  260. {
  261. dump_expr_1 (expr, dump_expr_flags);
  262. }
  263. /* Dump expression EXPR to stderr. */
  264. DEBUG_FUNCTION void
  265. debug_expr (expr_t expr)
  266. {
  267. switch_dump (stderr);
  268. dump_expr_1 (expr, debug_expr_flags);
  269. sel_print ("\n");
  270. restore_dump ();
  271. }
  272. /* Dump expression REF. */
  273. DEBUG_FUNCTION void
  274. debug (expr_def &ref)
  275. {
  276. switch_dump (stderr);
  277. dump_expr_1 (&ref, 0);
  278. sel_print ("\n");
  279. restore_dump ();
  280. }
  281. DEBUG_FUNCTION void
  282. debug (expr_def *ptr)
  283. {
  284. if (ptr)
  285. debug (*ptr);
  286. else
  287. fprintf (stderr, "<nil>\n");
  288. }
  289. /* Dump expression REF verbosely. */
  290. DEBUG_FUNCTION void
  291. debug_verbose (expr_def &ref)
  292. {
  293. switch_dump (stderr);
  294. dump_expr_1 (&ref, DUMP_EXPR_ALL);
  295. sel_print ("\n");
  296. restore_dump ();
  297. }
  298. DEBUG_FUNCTION void
  299. debug_verbose (expr_def *ptr)
  300. {
  301. if (ptr)
  302. debug_verbose (*ptr);
  303. else
  304. fprintf (stderr, "<nil>\n");
  305. }
  306. /* Dump insn I honoring FLAGS. */
  307. void
  308. dump_insn_1 (insn_t i, int flags)
  309. {
  310. int all;
  311. all = flags & 1;
  312. if (all)
  313. flags |= DUMP_INSN_ALL;
  314. if (!sched_dump_to_dot_p)
  315. sel_print ("(");
  316. if (flags & DUMP_INSN_EXPR)
  317. {
  318. dump_expr_1 (INSN_EXPR (i), dump_expr_flags | all);
  319. sel_print (";");
  320. }
  321. else if (flags & DUMP_INSN_PATTERN)
  322. {
  323. dump_insn_rtx_1 (i, DUMP_INSN_RTX_PATTERN | all);
  324. sel_print (";");
  325. }
  326. else if (flags & DUMP_INSN_UID)
  327. sel_print ("uid:%d;", INSN_UID (i));
  328. if (flags & DUMP_INSN_SEQNO)
  329. sel_print ("seqno:%d;", INSN_SEQNO (i));
  330. if (flags & DUMP_INSN_SCHED_CYCLE)
  331. {
  332. int cycle = INSN_SCHED_CYCLE (i);
  333. if (cycle != 0)
  334. sel_print ("cycle:%d;", cycle);
  335. }
  336. if (!sched_dump_to_dot_p)
  337. sel_print (")");
  338. }
  339. /* Dump insn I with default flags. */
  340. void
  341. dump_insn (insn_t i)
  342. {
  343. dump_insn_1 (i, DUMP_INSN_EXPR | DUMP_INSN_SCHED_CYCLE);
  344. }
  345. /* Dump INSN to stderr. */
  346. DEBUG_FUNCTION void
  347. debug_insn (insn_t insn)
  348. {
  349. switch_dump (stderr);
  350. dump_insn_1 (insn, debug_insn_flags);
  351. sel_print ("\n");
  352. restore_dump ();
  353. }
  354. /* Dumps av_set AV. */
  355. void
  356. dump_av_set (av_set_t av)
  357. {
  358. av_set_iterator i;
  359. expr_t expr;
  360. if (!sched_dump_to_dot_p)
  361. sel_print ("{");
  362. FOR_EACH_EXPR (expr, i, av)
  363. {
  364. dump_expr (expr);
  365. if (!sched_dump_to_dot_p)
  366. sel_print (" ");
  367. else
  368. sel_print ("\n");
  369. }
  370. if (!sched_dump_to_dot_p)
  371. sel_print ("}");
  372. }
  373. /* Dumps lvset LV. */
  374. void
  375. dump_lv_set (regset lv)
  376. {
  377. sel_print ("{");
  378. /* This code was adapted from cfg.c: dump_regset (). */
  379. if (lv == NULL)
  380. sel_print ("nil");
  381. else
  382. {
  383. unsigned i;
  384. reg_set_iterator rsi;
  385. int count = 0;
  386. EXECUTE_IF_SET_IN_REG_SET (lv, 0, i, rsi)
  387. {
  388. sel_print (" %d", i);
  389. if (i < FIRST_PSEUDO_REGISTER)
  390. {
  391. sel_print (" [%s]", reg_names[i]);
  392. ++count;
  393. }
  394. ++count;
  395. if (sched_dump_to_dot_p && count == 12)
  396. {
  397. count = 0;
  398. sel_print ("\n");
  399. }
  400. }
  401. }
  402. sel_print ("}\n");
  403. }
  404. /* Dumps a list of instructions pointed to by P. */
  405. static void
  406. dump_ilist (ilist_t p)
  407. {
  408. while (p)
  409. {
  410. dump_insn (ILIST_INSN (p));
  411. p = ILIST_NEXT (p);
  412. }
  413. }
  414. /* Dumps a list of boundaries pointed to by BNDS. */
  415. void
  416. dump_blist (blist_t bnds)
  417. {
  418. for (; bnds; bnds = BLIST_NEXT (bnds))
  419. {
  420. bnd_t bnd = BLIST_BND (bnds);
  421. sel_print ("[to: %d; ptr: ", INSN_UID (BND_TO (bnd)));
  422. dump_ilist (BND_PTR (bnd));
  423. sel_print ("] ");
  424. }
  425. }
  426. /* Dumps a list of fences pointed to by L. */
  427. void
  428. dump_flist (flist_t l)
  429. {
  430. while (l)
  431. {
  432. dump_insn_1 (FENCE_INSN (FLIST_FENCE (l)), dump_flist_insn_flags);
  433. sel_print (" ");
  434. l = FLIST_NEXT (l);
  435. }
  436. }
  437. /* Dumps an insn vector SUCCS. */
  438. void
  439. dump_insn_vector (rtx_vec_t succs)
  440. {
  441. int i;
  442. rtx_insn *succ;
  443. FOR_EACH_VEC_ELT (succs, i, succ)
  444. if (succ)
  445. dump_insn (succ);
  446. else
  447. sel_print ("NULL ");
  448. }
  449. /* Dumps a hard reg set SET to FILE using PREFIX. */
  450. static void
  451. print_hard_reg_set (FILE *file, const char *prefix, HARD_REG_SET set)
  452. {
  453. int i;
  454. fprintf (file, "%s{ ", prefix);
  455. for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
  456. {
  457. if (TEST_HARD_REG_BIT (set, i))
  458. fprintf (file, "%d ", i);
  459. }
  460. fprintf (file, "}\n");
  461. }
  462. /* Dumps a hard reg set SET using PREFIX. */
  463. void
  464. dump_hard_reg_set (const char *prefix, HARD_REG_SET set)
  465. {
  466. print_hard_reg_set (sched_dump, prefix, set);
  467. }
  468. /* Pretty print INSN. This is used as a hook. */
  469. const char *
  470. sel_print_insn (const rtx_insn *insn, int aligned ATTRIBUTE_UNUSED)
  471. {
  472. static char buf[80];
  473. /* '+' before insn means it is a new cycle start and it's not been
  474. scheduled yet. '>' - has been scheduled. */
  475. if (s_i_d.exists () && INSN_LUID (insn) > 0)
  476. if (GET_MODE (insn) == TImode)
  477. sprintf (buf, "%s %4d",
  478. INSN_SCHED_TIMES (insn) > 0 ? "> " : "< ",
  479. INSN_UID (insn));
  480. else
  481. sprintf (buf, "%s %4d",
  482. INSN_SCHED_TIMES (insn) > 0 ? "! " : " ",
  483. INSN_UID (insn));
  484. else
  485. if (GET_MODE (insn) == TImode)
  486. sprintf (buf, "+ %4d", INSN_UID (insn));
  487. else
  488. sprintf (buf, " %4d", INSN_UID (insn));
  489. return buf;
  490. }
  491. /* Functions for pretty printing of CFG. */
  492. /* FIXME: Using pretty-print here could simplify this stuff. */
  493. /* Replace all occurencies of STR1 to STR2 in BUF.
  494. The BUF must be large enough to hold the result. */
  495. static void
  496. replace_str_in_buf (char *buf, const char *str1, const char *str2)
  497. {
  498. int buf_len = strlen (buf);
  499. int str1_len = strlen (str1);
  500. int str2_len = strlen (str2);
  501. int diff = str2_len - str1_len;
  502. char *p = buf;
  503. do
  504. {
  505. p = strstr (p, str1);
  506. if (p)
  507. {
  508. char *p1 = p + str1_len;
  509. /* Copy the rest of buf and '\0'. */
  510. int n = buf + buf_len - p1;
  511. int i;
  512. /* Shift str by DIFF chars. */
  513. if (diff > 0)
  514. for (i = n; i >= 0; i--)
  515. p1[i + diff] = p1[i];
  516. else
  517. for (i = 0; i <= n; i++)
  518. p1[i + diff] = p1[i];
  519. /* Copy str2. */
  520. for (i = 0; i < str2_len; i++)
  521. p[i] = str2[i];
  522. p += str2_len;
  523. buf_len += diff;
  524. }
  525. }
  526. while (p);
  527. }
  528. /* Replace characters in BUF that have special meaning in .dot file.
  529. Similar to pp_write_text_as_dot_label_to_stream. */
  530. static void
  531. sel_prepare_string_for_dot_label (char *buf)
  532. {
  533. static char specials_from[7][2] = { "<", ">", "{", "|", "}", "\"",
  534. "\n" };
  535. static char specials_to[7][3] = { "\\<", "\\>", "\\{", "\\|", "\\}",
  536. "\\\"", "\\l" };
  537. unsigned i;
  538. for (i = 0; i < 7; i++)
  539. replace_str_in_buf (buf, specials_from[i], specials_to[i]);
  540. }
  541. /* This function acts like printf but dumps to the sched_dump file. */
  542. void
  543. sel_print (const char *fmt, ...)
  544. {
  545. va_list ap;
  546. va_start (ap, fmt);
  547. if (sched_dump_to_dot_p)
  548. {
  549. char *message;
  550. if (vasprintf (&message, fmt, ap) >= 0 && message != NULL)
  551. {
  552. message = (char *) xrealloc (message, 2 * strlen (message) + 1);
  553. sel_prepare_string_for_dot_label (message);
  554. fprintf (sched_dump, "%s", message);
  555. free (message);
  556. }
  557. }
  558. else
  559. vfprintf (sched_dump, fmt, ap);
  560. va_end (ap);
  561. }
  562. /* Dump INSN with FLAGS. */
  563. static void
  564. sel_dump_cfg_insn (insn_t insn, int flags)
  565. {
  566. int insn_flags = DUMP_INSN_UID | DUMP_INSN_PATTERN;
  567. if (sched_luids.exists () && INSN_LUID (insn) > 0)
  568. {
  569. if (flags & SEL_DUMP_CFG_INSN_SEQNO)
  570. insn_flags |= DUMP_INSN_SEQNO | DUMP_INSN_SCHED_CYCLE | DUMP_INSN_EXPR;
  571. }
  572. dump_insn_1 (insn, insn_flags);
  573. }
  574. /* Dump E to the dot file F. */
  575. static void
  576. sel_dump_cfg_edge (FILE *f, edge e)
  577. {
  578. int w;
  579. const char *color;
  580. if (e->flags & EDGE_FALLTHRU)
  581. {
  582. w = 10;
  583. color = ", color = red";
  584. }
  585. else if (e->src->next_bb == e->dest)
  586. {
  587. w = 3;
  588. color = ", color = blue";
  589. }
  590. else
  591. {
  592. w = 1;
  593. color = "";
  594. }
  595. fprintf (f, "\tbb%d -> bb%d [weight = %d%s];\n",
  596. e->src->index, e->dest->index, w, color);
  597. }
  598. /* Return true if BB has a predesessor from current region.
  599. TODO: Either make this function to trace back through empty block
  600. or just remove those empty blocks. */
  601. static bool
  602. has_preds_in_current_region_p (basic_block bb)
  603. {
  604. edge e;
  605. edge_iterator ei;
  606. gcc_assert (!in_current_region_p (bb));
  607. FOR_EACH_EDGE (e, ei, bb->preds)
  608. if (in_current_region_p (e->src))
  609. return true;
  610. return false;
  611. }
  612. /* Dump a cfg region to the dot file F honoring FLAGS. */
  613. static void
  614. sel_dump_cfg_2 (FILE *f, int flags)
  615. {
  616. basic_block bb;
  617. sched_dump_to_dot_p = true;
  618. switch_dump (f);
  619. fprintf (f, "digraph G {\n"
  620. "\tratio = 2.25;\n"
  621. "\tnode [shape = record, fontsize = 9];\n");
  622. if (flags & SEL_DUMP_CFG_FUNCTION_NAME)
  623. fprintf (f, "function [label = \"%s\"];\n", current_function_name ());
  624. FOR_EACH_BB_FN (bb, cfun)
  625. {
  626. insn_t insn = BB_HEAD (bb);
  627. insn_t next_tail = NEXT_INSN (BB_END (bb));
  628. edge e;
  629. edge_iterator ei;
  630. bool in_region_p = ((flags & SEL_DUMP_CFG_CURRENT_REGION)
  631. && in_current_region_p (bb));
  632. bool full_p = (!(flags & SEL_DUMP_CFG_CURRENT_REGION)
  633. || in_region_p);
  634. bool some_p = full_p || has_preds_in_current_region_p (bb);
  635. const char *color;
  636. const char *style;
  637. if (!some_p)
  638. continue;
  639. if ((flags & SEL_DUMP_CFG_CURRENT_REGION)
  640. && in_current_region_p (bb)
  641. && BLOCK_TO_BB (bb->index) == 0)
  642. color = "color = green, ";
  643. else
  644. color = "";
  645. if ((flags & SEL_DUMP_CFG_FENCES)
  646. && in_region_p)
  647. {
  648. style = "";
  649. if (!sel_bb_empty_p (bb))
  650. {
  651. bool first_p = true;
  652. insn_t tail = BB_END (bb);
  653. insn_t cur_insn;
  654. cur_insn = bb_note (bb);
  655. do
  656. {
  657. fence_t fence;
  658. cur_insn = NEXT_INSN (cur_insn);
  659. fence = flist_lookup (fences, cur_insn);
  660. if (fence != NULL)
  661. {
  662. if (!FENCE_SCHEDULED_P (fence))
  663. {
  664. if (first_p)
  665. color = "color = red, ";
  666. else
  667. color = "color = yellow, ";
  668. }
  669. else
  670. color = "color = blue, ";
  671. }
  672. first_p = false;
  673. }
  674. while (cur_insn != tail);
  675. }
  676. }
  677. else if (!full_p)
  678. style = "style = dashed, ";
  679. else
  680. style = "";
  681. fprintf (f, "\tbb%d [%s%slabel = \"{Basic block %d", bb->index,
  682. style, color, bb->index);
  683. if ((flags & SEL_DUMP_CFG_BB_LOOP)
  684. && bb->loop_father != NULL)
  685. fprintf (f, ", loop %d", bb->loop_father->num);
  686. if (full_p
  687. && (flags & SEL_DUMP_CFG_BB_NOTES_LIST))
  688. {
  689. insn_t notes = BB_NOTE_LIST (bb);
  690. if (notes != NULL_RTX)
  691. {
  692. fprintf (f, "|");
  693. /* For simplicity, we dump notes from note_list in reversed order
  694. to that what they will appear in the code. */
  695. while (notes != NULL_RTX)
  696. {
  697. sel_dump_cfg_insn (notes, flags);
  698. fprintf (f, "\\l");
  699. notes = PREV_INSN (notes);
  700. }
  701. }
  702. }
  703. if (full_p
  704. && (flags & SEL_DUMP_CFG_AV_SET)
  705. && in_current_region_p (bb)
  706. && !sel_bb_empty_p (bb))
  707. {
  708. fprintf (f, "|");
  709. if (BB_AV_SET_VALID_P (bb))
  710. dump_av_set (BB_AV_SET (bb));
  711. else if (BB_AV_LEVEL (bb) == -1)
  712. fprintf (f, "AV_SET needs update");
  713. }
  714. if ((flags & SEL_DUMP_CFG_LV_SET)
  715. && !sel_bb_empty_p (bb))
  716. {
  717. fprintf (f, "|");
  718. if (BB_LV_SET_VALID_P (bb))
  719. dump_lv_set (BB_LV_SET (bb));
  720. else
  721. fprintf (f, "LV_SET needs update");
  722. }
  723. if (full_p
  724. && (flags & SEL_DUMP_CFG_BB_INSNS))
  725. {
  726. fprintf (f, "|");
  727. while (insn != next_tail)
  728. {
  729. sel_dump_cfg_insn (insn, flags);
  730. fprintf (f, "\\l");
  731. insn = NEXT_INSN (insn);
  732. }
  733. }
  734. fprintf (f, "}\"];\n");
  735. FOR_EACH_EDGE (e, ei, bb->succs)
  736. if (full_p || in_current_region_p (e->dest))
  737. sel_dump_cfg_edge (f, e);
  738. }
  739. fprintf (f, "}");
  740. restore_dump ();
  741. sched_dump_to_dot_p = false;
  742. }
  743. /* Dump a cfg region to the file specified by TAG honoring flags.
  744. The file is created by the function. */
  745. static void
  746. sel_dump_cfg_1 (const char *tag, int flags)
  747. {
  748. char *buf;
  749. int i;
  750. FILE *f;
  751. ++sel_dump_cfg_fileno;
  752. if (!sel_dump_cfg_p)
  753. return;
  754. i = 1 + snprintf (NULL, 0, "%s/%s%05d-%s.dot", sel_debug_cfg_root,
  755. sel_debug_cfg_root_postfix, sel_dump_cfg_fileno, tag);
  756. buf = XNEWVEC (char, i);
  757. snprintf (buf, i, "%s/%s%05d-%s.dot", sel_debug_cfg_root,
  758. sel_debug_cfg_root_postfix, sel_dump_cfg_fileno, tag);
  759. f = fopen (buf, "w");
  760. if (f == NULL)
  761. fprintf (stderr, "Can't create file: %s.\n", buf);
  762. else
  763. {
  764. sel_dump_cfg_2 (f, flags);
  765. fclose (f);
  766. }
  767. free (buf);
  768. }
  769. /* Setup cfg dumping flags. Used for debugging. */
  770. void
  771. setup_dump_cfg_params (void)
  772. {
  773. sel_dump_cfg_flags = SEL_DUMP_CFG_FLAGS;
  774. sel_dump_cfg_p = 0;
  775. sel_debug_cfg_root_postfix = sel_debug_cfg_root_postfix_default;
  776. }
  777. /* Debug a cfg region with FLAGS. */
  778. void
  779. sel_debug_cfg_1 (int flags)
  780. {
  781. bool t1 = sel_dump_cfg_p;
  782. int t2 = sel_dump_cfg_fileno;
  783. sel_dump_cfg_p = true;
  784. sel_dump_cfg_fileno = ++sel_debug_cfg_fileno;
  785. sel_dump_cfg_1 ("sel-debug-cfg", flags);
  786. sel_dump_cfg_fileno = t2;
  787. sel_dump_cfg_p = t1;
  788. }
  789. /* Dumps av_set AV to stderr. */
  790. DEBUG_FUNCTION void
  791. debug_av_set (av_set_t av)
  792. {
  793. switch_dump (stderr);
  794. dump_av_set (av);
  795. sel_print ("\n");
  796. restore_dump ();
  797. }
  798. /* Dump LV to stderr. */
  799. DEBUG_FUNCTION void
  800. debug_lv_set (regset lv)
  801. {
  802. switch_dump (stderr);
  803. dump_lv_set (lv);
  804. sel_print ("\n");
  805. restore_dump ();
  806. }
  807. /* Dump an instruction list P to stderr. */
  808. DEBUG_FUNCTION void
  809. debug_ilist (ilist_t p)
  810. {
  811. switch_dump (stderr);
  812. dump_ilist (p);
  813. sel_print ("\n");
  814. restore_dump ();
  815. }
  816. /* Dump a boundary list BNDS to stderr. */
  817. DEBUG_FUNCTION void
  818. debug_blist (blist_t bnds)
  819. {
  820. switch_dump (stderr);
  821. dump_blist (bnds);
  822. sel_print ("\n");
  823. restore_dump ();
  824. }
  825. /* Dump a rtx vector REF. */
  826. DEBUG_FUNCTION void
  827. debug (vec<rtx_insn *> &ref)
  828. {
  829. switch_dump (stderr);
  830. dump_insn_vector (ref);
  831. sel_print ("\n");
  832. restore_dump ();
  833. }
  834. DEBUG_FUNCTION void
  835. debug (vec<rtx_insn *> *ptr)
  836. {
  837. if (ptr)
  838. debug (*ptr);
  839. else
  840. fprintf (stderr, "<nil>\n");
  841. }
  842. /* Dump an insn vector SUCCS. */
  843. DEBUG_FUNCTION void
  844. debug_insn_vector (rtx_vec_t succs)
  845. {
  846. switch_dump (stderr);
  847. dump_insn_vector (succs);
  848. sel_print ("\n");
  849. restore_dump ();
  850. }
  851. /* Dump a hard reg set SET to stderr. */
  852. DEBUG_FUNCTION void
  853. debug_hard_reg_set (HARD_REG_SET set)
  854. {
  855. switch_dump (stderr);
  856. dump_hard_reg_set ("", set);
  857. sel_print ("\n");
  858. restore_dump ();
  859. }
  860. /* Debug a cfg region with default flags. */
  861. void
  862. sel_debug_cfg (void)
  863. {
  864. sel_debug_cfg_1 (sel_debug_cfg_flags);
  865. }
  866. /* Print a current cselib value for X's address to stderr. */
  867. DEBUG_FUNCTION rtx
  868. debug_mem_addr_value (rtx x)
  869. {
  870. rtx t, addr;
  871. machine_mode address_mode;
  872. gcc_assert (MEM_P (x));
  873. address_mode = get_address_mode (x);
  874. t = shallow_copy_rtx (x);
  875. if (cselib_lookup (XEXP (t, 0), address_mode, 0, GET_MODE (t)))
  876. XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0), GET_MODE (t));
  877. t = canon_rtx (t);
  878. addr = get_addr (XEXP (t, 0));
  879. debug_rtx (t);
  880. debug_rtx (addr);
  881. return t;
  882. }
  883. #endif