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