1 1.1 mrg /* Code for GIMPLE range trace and debugging related routines. 2 1.1 mrg Copyright (C) 2019-2022 Free Software Foundation, Inc. 3 1.1 mrg Contributed by Andrew MacLeod <amacleod (at) redhat.com> 4 1.1 mrg and Aldy Hernandez <aldyh (at) redhat.com>. 5 1.1 mrg 6 1.1 mrg This file is part of GCC. 7 1.1 mrg 8 1.1 mrg GCC is free software; you can redistribute it and/or modify 9 1.1 mrg it under the terms of the GNU General Public License as published by 10 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 11 1.1 mrg any later version. 12 1.1 mrg 13 1.1 mrg GCC is distributed in the hope that it will be useful, 14 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of 15 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 1.1 mrg GNU General Public License for more details. 17 1.1 mrg 18 1.1 mrg You should have received a copy of the GNU General Public License 19 1.1 mrg along with GCC; see the file COPYING3. If not see 20 1.1 mrg <http://www.gnu.org/licenses/>. */ 21 1.1 mrg 22 1.1 mrg #include "config.h" 23 1.1 mrg #include "system.h" 24 1.1 mrg #include "coretypes.h" 25 1.1 mrg #include "backend.h" 26 1.1 mrg #include "tree.h" 27 1.1 mrg #include "gimple.h" 28 1.1 mrg #include "ssa.h" 29 1.1 mrg #include "gimple-pretty-print.h" 30 1.1 mrg #include "gimple-iterator.h" 31 1.1 mrg #include "tree-cfg.h" 32 1.1 mrg #include "fold-const.h" 33 1.1 mrg #include "tree-cfg.h" 34 1.1 mrg #include "cfgloop.h" 35 1.1 mrg #include "tree-scalar-evolution.h" 36 1.1 mrg #include "gimple-range.h" 37 1.1 mrg 38 1.1 mrg 39 1.1 mrg // Breakpoint to trap at a specific index. From GDB, this provides a simple 40 1.1 mrg // place to put a breakpoint to stop at a given trace line. 41 1.1 mrg // ie. b range_tracer::breakpoint if index == 45678 42 1.1 mrg 43 1.1 mrg void 44 1.1 mrg range_tracer::breakpoint (unsigned index ATTRIBUTE_UNUSED) 45 1.1 mrg { 46 1.1 mrg } 47 1.1 mrg 48 1.1 mrg // Construct a range_tracer with component NAME. 49 1.1 mrg 50 1.1 mrg range_tracer::range_tracer (const char *name) 51 1.1 mrg { 52 1.1 mrg gcc_checking_assert (strlen(name) < name_len -1); 53 1.1 mrg strcpy (component, name); 54 1.1 mrg indent = 0; 55 1.1 mrg tracing = false; 56 1.1 mrg } 57 1.1 mrg 58 1.1 mrg // This routine does the initial line spacing/indenting for a trace. 59 1.1 mrg // If BLANKS is false, then IDX is printed, otherwise spaces. 60 1.1 mrg 61 1.1 mrg void 62 1.1 mrg range_tracer::print_prefix (unsigned idx, bool blanks) 63 1.1 mrg { 64 1.1 mrg // Print counter index as well as INDENT spaces. 65 1.1 mrg if (!blanks) 66 1.1 mrg fprintf (dump_file, "%-7u ", idx); 67 1.1 mrg else 68 1.1 mrg fprintf (dump_file, " "); 69 1.1 mrg fprintf (dump_file, "%s ", component); 70 1.1 mrg unsigned x; 71 1.1 mrg for (x = 0; x< indent; x++) 72 1.1 mrg fputc (' ', dump_file); 73 1.1 mrg 74 1.1 mrg } 75 1.1 mrg // If dumping, return the next call index and print the prefix for the next 76 1.1 mrg // output line. If not, retrurn 0. 77 1.1 mrg // Counter is static to monotonically increase across the compilation unit. 78 1.1 mrg 79 1.1 mrg unsigned 80 1.1 mrg range_tracer::do_header (const char *str) 81 1.1 mrg { 82 1.1 mrg static unsigned trace_count = 0; 83 1.1 mrg 84 1.1 mrg unsigned idx = ++trace_count; 85 1.1 mrg print_prefix (idx, false); 86 1.1 mrg fprintf (dump_file, "%s", str); 87 1.1 mrg indent += bump; 88 1.1 mrg breakpoint (idx); 89 1.1 mrg return idx; 90 1.1 mrg } 91 1.1 mrg 92 1.1 mrg // Print a line without starting or ending a trace. 93 1.1 mrg 94 1.1 mrg void 95 1.1 mrg range_tracer::print (unsigned counter, const char *str) 96 1.1 mrg { 97 1.1 mrg print_prefix (counter, true); 98 1.1 mrg fprintf (dump_file, "%s", str); 99 1.1 mrg } 100 1.1 mrg 101 1.1 mrg // End a trace and print the CALLER, NAME, and RESULT and range R, 102 1.1 mrg 103 1.1 mrg void 104 1.1 mrg range_tracer::trailer (unsigned counter, const char *caller, bool result, 105 1.1 mrg tree name, const irange &r) 106 1.1 mrg { 107 1.1 mrg gcc_checking_assert (tracing && counter != 0); 108 1.1 mrg 109 1.1 mrg indent -= bump; 110 1.1 mrg print_prefix (counter, true); 111 1.1 mrg fputs(result ? "TRUE : " : "FALSE : ", dump_file); 112 1.1 mrg fprintf (dump_file, "(%u) ", counter); 113 1.1 mrg fputs (caller, dump_file); 114 1.1 mrg fputs (" (",dump_file); 115 1.1 mrg if (name) 116 1.1 mrg print_generic_expr (dump_file, name, TDF_SLIM); 117 1.1 mrg fputs (") ",dump_file); 118 1.1 mrg if (result) 119 1.1 mrg { 120 1.1 mrg r.dump (dump_file); 121 1.1 mrg fputc('\n', dump_file); 122 1.1 mrg } 123 1.1 mrg else 124 1.1 mrg fputc('\n', dump_file); 125 1.1 mrg } 126 1.1 mrg 127 1.1 mrg // ========================================= 128 1.1 mrg // Debugging helpers. 129 1.1 mrg // ========================================= 130 1.1 mrg 131 1.1 mrg // Query all statements in the IL to precalculate computable ranges in RANGER. 132 1.1 mrg 133 1.1 mrg DEBUG_FUNCTION void 134 1.1 mrg debug_seed_ranger (gimple_ranger &ranger) 135 1.1 mrg { 136 1.1 mrg // Recalculate SCEV to make sure the dump lists everything. 137 1.1 mrg if (scev_initialized_p ()) 138 1.1 mrg { 139 1.1 mrg scev_finalize (); 140 1.1 mrg scev_initialize (); 141 1.1 mrg } 142 1.1 mrg 143 1.1 mrg basic_block bb; 144 1.1 mrg int_range_max r; 145 1.1 mrg gimple_stmt_iterator gsi; 146 1.1 mrg FOR_EACH_BB_FN (bb, cfun) 147 1.1 mrg for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 148 1.1 mrg { 149 1.1 mrg gimple *stmt = gsi_stmt (gsi); 150 1.1 mrg 151 1.1 mrg if (is_gimple_debug (stmt)) 152 1.1 mrg continue; 153 1.1 mrg 154 1.1 mrg ranger.range_of_stmt (r, stmt); 155 1.1 mrg } 156 1.1 mrg } 157 1.1 mrg 158 1.1 mrg // Change the current dump_file and dump_flags to F and FLAGS while 159 1.1 mrg // saving them for later restoring. 160 1.1 mrg 161 1.1 mrg push_dump_file::push_dump_file (FILE *f, dump_flags_t flags) 162 1.1 mrg { 163 1.1 mrg old_dump_file = dump_file; 164 1.1 mrg old_dump_flags = dump_flags; 165 1.1 mrg dump_file = f; 166 1.1 mrg dump_flags = flags; 167 1.1 mrg } 168 1.1 mrg 169 1.1 mrg // Restore saved dump_file and dump_flags. 170 1.1 mrg 171 1.1 mrg push_dump_file::~push_dump_file () 172 1.1 mrg { 173 1.1 mrg dump_file = old_dump_file; 174 1.1 mrg dump_flags = old_dump_flags; 175 1.1 mrg } 176 1.1 mrg 177 1.1 mrg // Dump all that ranger knows for the current function. 178 1.1 mrg 179 1.1 mrg void 180 1.1 mrg dump_ranger (FILE *out) 181 1.1 mrg { 182 1.1 mrg push_dump_file save (out, dump_flags); 183 1.1 mrg gimple_ranger ranger; 184 1.1 mrg 185 1.1 mrg fprintf (out, ";; Function "); 186 1.1 mrg print_generic_expr (out, current_function_decl); 187 1.1 mrg fprintf (out, "\n"); 188 1.1 mrg 189 1.1 mrg debug_seed_ranger (ranger); 190 1.1 mrg ranger.dump (out); 191 1.1 mrg } 192 1.1 mrg 193 1.1 mrg DEBUG_FUNCTION void 194 1.1 mrg debug_ranger () 195 1.1 mrg { 196 1.1 mrg dump_ranger (stderr); 197 1.1 mrg } 198 1.1 mrg 199 1.1 mrg // Dump all that ranger knows on a path of BBs. 200 1.1 mrg // 201 1.1 mrg // Note that the blocks are in reverse order, thus the exit block is 202 1.1 mrg // path[0]. 203 1.1 mrg 204 1.1 mrg void 205 1.1 mrg dump_ranger (FILE *dump_file, const vec<basic_block> &path) 206 1.1 mrg { 207 1.1 mrg if (path.length () == 0) 208 1.1 mrg { 209 1.1 mrg fprintf (dump_file, "empty\n"); 210 1.1 mrg return; 211 1.1 mrg } 212 1.1 mrg 213 1.1 mrg gimple_ranger ranger; 214 1.1 mrg debug_seed_ranger (ranger); 215 1.1 mrg 216 1.1 mrg unsigned i = path.length (); 217 1.1 mrg do 218 1.1 mrg { 219 1.1 mrg i--; 220 1.1 mrg ranger.dump_bb (dump_file, path[i]); 221 1.1 mrg } 222 1.1 mrg while (i > 0); 223 1.1 mrg } 224 1.1 mrg 225 1.1 mrg DEBUG_FUNCTION void 226 1.1 mrg debug_ranger (const vec<basic_block> &path) 227 1.1 mrg { 228 1.1 mrg dump_ranger (stderr, path); 229 1.1 mrg } 230 1.1 mrg 231 1.1 mrg #include "gimple-range-tests.cc" 232