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