Branch data Line data Source code
1 : : /* Scanning of rtl for dataflow analysis.
2 : : Copyright (C) 2007-2025 Free Software Foundation, Inc.
3 : : Contributed by Kenneth Zadeck (zadeck@naturalbridge.com).
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify it under
8 : : the terms of the GNU General Public License as published by the Free
9 : : Software Foundation; either version 3, or (at your option) any later
10 : : version.
11 : :
12 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : : for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along with GCC; see the file COPYING3. If not see
19 : : <http://www.gnu.org/licenses/>. */
20 : :
21 : :
22 : : #include "config.h"
23 : : #include "system.h"
24 : : #include "coretypes.h"
25 : : #include "backend.h"
26 : : #include "rtl.h"
27 : : #include "predict.h"
28 : : #include "df.h"
29 : : #include "regs.h"
30 : :
31 : :
32 : : struct regstat_n_sets_and_refs_t *regstat_n_sets_and_refs;
33 : :
34 : : /*----------------------------------------------------------------------------
35 : : REG_N_SETS and REG_N_REFS.
36 : : ----------------------------------------------------------------------------*/
37 : :
38 : : /* If a pass need to change these values in some magical way or the
39 : : pass needs to have accurate values for these and is not using
40 : : incremental df scanning, then it should use REG_N_SETS and
41 : : REG_N_USES. If the pass is doing incremental scanning then it
42 : : should be getting the info from DF_REG_DEF_COUNT and
43 : : DF_REG_USE_COUNT. */
44 : :
45 : : void
46 : 3532644 : regstat_init_n_sets_and_refs (void)
47 : : {
48 : 3532644 : unsigned int i;
49 : 3532644 : unsigned int max_regno = max_reg_num ();
50 : :
51 : 3532644 : timevar_push (TV_REG_STATS);
52 : 3532644 : df_grow_reg_info ();
53 : 3532644 : gcc_assert (!regstat_n_sets_and_refs);
54 : :
55 : 3532644 : regstat_n_sets_and_refs = XNEWVEC (struct regstat_n_sets_and_refs_t, max_regno);
56 : :
57 : 3532644 : if (MAY_HAVE_DEBUG_BIND_INSNS)
58 : 232747619 : for (i = 0; i < max_regno; i++)
59 : : {
60 : 231258052 : int use_count;
61 : 231258052 : df_ref use;
62 : :
63 : 231258052 : use_count = DF_REG_USE_COUNT (i);
64 : 519639704 : for (use = DF_REG_USE_CHAIN (i); use; use = DF_REF_NEXT_REG (use))
65 : 288381652 : if (DF_REF_INSN_INFO (use) && DEBUG_INSN_P (DF_REF_INSN (use)))
66 : 30135250 : use_count--;
67 : :
68 : :
69 : 231258052 : SET_REG_N_SETS (i, DF_REG_DEF_COUNT (i));
70 : 231258052 : SET_REG_N_REFS (i, use_count + REG_N_SETS (i));
71 : : }
72 : : else
73 : 273217879 : for (i = 0; i < max_regno; i++)
74 : : {
75 : 271174802 : SET_REG_N_SETS (i, DF_REG_DEF_COUNT (i));
76 : 271174802 : SET_REG_N_REFS (i, DF_REG_USE_COUNT (i) + REG_N_SETS (i));
77 : : }
78 : 3532644 : timevar_pop (TV_REG_STATS);
79 : :
80 : 3532644 : }
81 : :
82 : :
83 : : /* Free the array that holds the REG_N_SETS and REG_N_REFS. */
84 : :
85 : : void
86 : 3532644 : regstat_free_n_sets_and_refs (void)
87 : : {
88 : 3532644 : gcc_assert (regstat_n_sets_and_refs);
89 : 3532644 : free (regstat_n_sets_and_refs);
90 : 3532644 : regstat_n_sets_and_refs = NULL;
91 : 3532644 : }
92 : :
93 : :
94 : : /*----------------------------------------------------------------------------
95 : : REGISTER INFORMATION
96 : :
97 : : Process REG_N_DEATHS, REG_N_CALLS_CROSSED, and REG_BASIC_BLOCK.
98 : :
99 : : ----------------------------------------------------------------------------*/
100 : :
101 : : static bitmap setjmp_crosses;
102 : : struct reg_info_t *reg_info_p;
103 : :
104 : : /* The number allocated elements of reg_info_p. */
105 : : size_t reg_info_p_size;
106 : :
107 : : /* Compute register info: lifetime, bb, and number of defs and uses
108 : : for basic block BB. LIVE is a scratch bitvector used here. */
109 : :
110 : : static void
111 : 28094892 : regstat_bb_compute_ri (basic_block bb, bitmap live)
112 : : {
113 : 28094892 : rtx_insn *insn;
114 : 28094892 : df_ref def, use;
115 : 28094892 : bitmap_iterator bi;
116 : 28094892 : unsigned int regno;
117 : :
118 : 28094892 : bitmap_copy (live, df_get_live_out (bb));
119 : :
120 : : /* Process the regs live at the end of the block. Mark them as
121 : : not local to any one basic block. */
122 : 400139470 : EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi)
123 : 372044578 : REG_BASIC_BLOCK (regno) = REG_BLOCK_GLOBAL;
124 : :
125 : : /* Process the artificial defs and uses at the bottom of the block
126 : : to begin processing. */
127 : 57118987 : FOR_EACH_ARTIFICIAL_DEF (def, bb->index)
128 : 929203 : if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
129 : 0 : bitmap_clear_bit (live, DF_REF_REGNO (def));
130 : :
131 : 168569352 : FOR_EACH_ARTIFICIAL_USE (use, bb->index)
132 : 112379568 : if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
133 : : {
134 : 112379568 : regno = DF_REF_REGNO (use);
135 : 112379568 : bitmap_set_bit (live, regno);
136 : : }
137 : :
138 : 339126974 : FOR_BB_INSNS_REVERSE (bb, insn)
139 : : {
140 : 311032082 : struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
141 : 311032082 : bitmap_iterator bi;
142 : 311032082 : rtx link;
143 : :
144 : 311032082 : if (!NONDEBUG_INSN_P (insn))
145 : 151847187 : continue;
146 : :
147 : 159184895 : link = REG_NOTES (insn);
148 : 328796715 : while (link)
149 : : {
150 : 169611820 : if (REG_NOTE_KIND (link) == REG_DEAD)
151 : 94387421 : REG_N_DEATHS (REGNO (XEXP (link, 0)))++;
152 : 169611820 : link = XEXP (link, 1);
153 : : }
154 : :
155 : : /* Process the defs. */
156 : 159184895 : if (CALL_P (insn))
157 : : {
158 : 11406734 : bool set_jump = (find_reg_note (insn, REG_SETJMP, NULL) != NULL);
159 : 200611942 : EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi)
160 : : {
161 : 189205208 : REG_N_CALLS_CROSSED (regno)++;
162 : :
163 : : /* We have a problem with any pseudoreg that lives
164 : : across the setjmp. ANSI says that if a user variable
165 : : does not change in value between the setjmp and the
166 : : longjmp, then the longjmp preserves it. This
167 : : includes longjmp from a place where the pseudo
168 : : appears dead. (In principle, the value still exists
169 : : if it is in scope.) If the pseudo goes in a hard
170 : : reg, some other value may occupy that hard reg where
171 : : this pseudo is dead, thus clobbering the pseudo.
172 : : Conclusion: such a pseudo must not go in a hard
173 : : reg. */
174 : 189205208 : if (set_jump)
175 : 10794 : bitmap_set_bit (setjmp_crosses, regno);
176 : : }
177 : : }
178 : :
179 : : /* All of the defs except the return value are some sort of
180 : : clobber. This code is for the return. */
181 : 1225202268 : FOR_EACH_INSN_INFO_DEF (def, insn_info)
182 : : {
183 : 1066017373 : if ((!CALL_P (insn))
184 : 935223586 : || (!(DF_REF_FLAGS (def)
185 : : & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))))
186 : : {
187 : 136112848 : unsigned int dregno = DF_REF_REGNO (def);
188 : :
189 : : /* Kill this register if it is not a subreg store or
190 : : conditional store.
191 : : ??? This means that any partial store is live from
192 : : the last use in a basic block to the start of this
193 : : basic block. */
194 : 136112848 : if (!(DF_REF_FLAGS (def)
195 : : & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
196 : 135415181 : bitmap_clear_bit (live, dregno);
197 : :
198 : 136112848 : if (dregno >= FIRST_PSEUDO_REGISTER)
199 : : {
200 : 65902503 : REG_FREQ (dregno) += REG_FREQ_FROM_BB (bb);
201 : 65902503 : REG_FREQ (dregno) =
202 : 65902503 : MIN (REG_FREQ (dregno), REG_FREQ_MAX);
203 : :
204 : 65902503 : if (REG_BASIC_BLOCK (dregno) == REG_BLOCK_UNKNOWN)
205 : 977511 : REG_BASIC_BLOCK (dregno) = bb->index;
206 : 64924992 : else if (REG_BASIC_BLOCK (dregno) != bb->index)
207 : 24239145 : REG_BASIC_BLOCK (dregno) = REG_BLOCK_GLOBAL;
208 : : }
209 : : }
210 : : }
211 : :
212 : 351947138 : FOR_EACH_INSN_INFO_USE (use, insn_info)
213 : : {
214 : 192762243 : unsigned int uregno = DF_REF_REGNO (use);
215 : :
216 : 192762243 : if (uregno >= FIRST_PSEUDO_REGISTER)
217 : : {
218 : 100180889 : REG_FREQ (uregno) += REG_FREQ_FROM_BB (bb);
219 : 100180889 : REG_FREQ (uregno) =
220 : 100180889 : MIN (REG_FREQ (uregno), REG_FREQ_MAX);
221 : :
222 : 100180889 : if (REG_BASIC_BLOCK (uregno) == REG_BLOCK_UNKNOWN)
223 : 39576938 : REG_BASIC_BLOCK (uregno) = bb->index;
224 : 60603951 : else if (REG_BASIC_BLOCK (uregno) != bb->index)
225 : 51502175 : REG_BASIC_BLOCK (uregno) = REG_BLOCK_GLOBAL;
226 : : }
227 : : }
228 : : }
229 : 28094892 : }
230 : :
231 : :
232 : : /* Compute register info: lifetime, bb, and number of defs and uses. */
233 : : void
234 : 2501673 : regstat_compute_ri (void)
235 : : {
236 : 2501673 : basic_block bb;
237 : 2501673 : bitmap live = BITMAP_ALLOC (&df_bitmap_obstack);
238 : 2501673 : unsigned int regno;
239 : 2501673 : bitmap_iterator bi;
240 : :
241 : : /* Initialize everything. */
242 : :
243 : 2501673 : gcc_assert (!reg_info_p);
244 : :
245 : 2501673 : timevar_push (TV_REG_STATS);
246 : 2501673 : setjmp_crosses = BITMAP_ALLOC (&df_bitmap_obstack);
247 : 2501673 : max_regno = max_reg_num ();
248 : 2501673 : reg_info_p_size = max_regno;
249 : 2501673 : reg_info_p = XCNEWVEC (struct reg_info_t, max_regno);
250 : :
251 : 30596565 : FOR_EACH_BB_FN (bb, cfun)
252 : : {
253 : 28094892 : regstat_bb_compute_ri (bb, live);
254 : : }
255 : :
256 : 2501673 : BITMAP_FREE (live);
257 : :
258 : : /* See the setjmp comment in regstat_bb_compute_ri. */
259 : 2502878 : EXECUTE_IF_SET_IN_BITMAP (setjmp_crosses, FIRST_PSEUDO_REGISTER, regno, bi)
260 : : {
261 : 1205 : REG_BASIC_BLOCK (regno) = REG_BLOCK_UNKNOWN;
262 : : }
263 : :
264 : 2501673 : timevar_pop (TV_REG_STATS);
265 : 2501673 : }
266 : :
267 : :
268 : : /* Free all storage associated with the problem. */
269 : :
270 : : void
271 : 2501673 : regstat_free_ri (void)
272 : : {
273 : 2501673 : gcc_assert (reg_info_p);
274 : 2501673 : reg_info_p_size = 0;
275 : 2501673 : free (reg_info_p);
276 : 2501673 : reg_info_p = NULL;
277 : :
278 : 2501673 : BITMAP_FREE (setjmp_crosses);
279 : 2501673 : }
280 : :
281 : :
282 : : /* Return a bitmap containing the set of registers that cross a setjmp.
283 : : The client should not change or delete this bitmap. */
284 : :
285 : : bitmap
286 : 1777008 : regstat_get_setjmp_crosses (void)
287 : : {
288 : 1777008 : return setjmp_crosses;
289 : : }
290 : :
291 : : /*----------------------------------------------------------------------------
292 : : Process REG_N_CALLS_CROSSED.
293 : :
294 : : This is used by sched_deps. A good implementation of sched-deps
295 : : would really process the blocks directly rather than going through
296 : : lists of insns. If it did this, it could use the exact regs that
297 : : cross an individual call rather than using this info that merges
298 : : the info for all calls.
299 : :
300 : : ----------------------------------------------------------------------------*/
301 : :
302 : :
303 : :
304 : : /* Compute calls crossed for BB. Live is a scratch bitvector. */
305 : :
306 : : static void
307 : 9554094 : regstat_bb_compute_calls_crossed (unsigned int bb_index, bitmap live)
308 : : {
309 : 9554094 : basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
310 : 9554094 : rtx_insn *insn;
311 : 9554094 : df_ref def, use;
312 : :
313 : 9554094 : bitmap_copy (live, df_get_live_out (bb));
314 : :
315 : : /* Process the artificial defs and uses at the bottom of the block
316 : : to begin processing. */
317 : 19476026 : FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
318 : 367838 : if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
319 : 0 : bitmap_clear_bit (live, DF_REF_REGNO (def));
320 : :
321 : 30032303 : FOR_EACH_ARTIFICIAL_USE (use, bb_index)
322 : 10924115 : if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
323 : 10924115 : bitmap_set_bit (live, DF_REF_REGNO (use));
324 : :
325 : 128430055 : FOR_BB_INSNS_REVERSE (bb, insn)
326 : : {
327 : 118875961 : if (!NONDEBUG_INSN_P (insn))
328 : 62201329 : continue;
329 : :
330 : 56674632 : gcc_assert (INSN_UID (insn) < (int) DF_INSN_SIZE ());
331 : 56674632 : struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
332 : 56674632 : unsigned int regno;
333 : :
334 : : /* Process the defs. */
335 : 56674632 : if (CALL_P (insn))
336 : : {
337 : 4257895 : bitmap_iterator bi;
338 : 17372222 : EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi)
339 : : {
340 : 13114327 : REG_N_CALLS_CROSSED (regno)++;
341 : : }
342 : : }
343 : :
344 : : /* All of the defs except the return value are some sort of
345 : : clobber. This code is for the return. */
346 : 448862664 : FOR_EACH_INSN_INFO_DEF (def, insn_info)
347 : : {
348 : 392188032 : if ((!CALL_P (insn))
349 : 347007662 : || (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))))
350 : : {
351 : : /* Kill this register if it is not a subreg store or conditional store. */
352 : 47203343 : if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
353 : 47155528 : bitmap_clear_bit (live, DF_REF_REGNO (def));
354 : : }
355 : : }
356 : :
357 : 127978144 : FOR_EACH_INSN_INFO_USE (use, insn_info)
358 : 71303512 : bitmap_set_bit (live, DF_REF_REGNO (use));
359 : : }
360 : 9554094 : }
361 : :
362 : :
363 : : /* Compute register info: lifetime, bb, and number of defs and uses. */
364 : : void
365 : 928180 : regstat_compute_calls_crossed (void)
366 : : {
367 : 928180 : basic_block bb;
368 : 928180 : bitmap live = BITMAP_ALLOC (&df_bitmap_obstack);
369 : :
370 : : /* Initialize everything. */
371 : 928180 : gcc_assert (!reg_info_p);
372 : :
373 : 928180 : timevar_push (TV_REG_STATS);
374 : 928180 : max_regno = max_reg_num ();
375 : 928180 : reg_info_p_size = max_regno;
376 : 928180 : reg_info_p = XCNEWVEC (struct reg_info_t, max_regno);
377 : :
378 : 10482274 : FOR_EACH_BB_FN (bb, cfun)
379 : : {
380 : 9554094 : regstat_bb_compute_calls_crossed (bb->index, live);
381 : : }
382 : :
383 : 928180 : BITMAP_FREE (live);
384 : 928180 : timevar_pop (TV_REG_STATS);
385 : 928180 : }
386 : :
387 : :
388 : : /* Free all storage associated with the problem. */
389 : :
390 : : void
391 : 928180 : regstat_free_calls_crossed (void)
392 : : {
393 : 928180 : gcc_assert (reg_info_p);
394 : 928180 : reg_info_p_size = 0;
395 : 928180 : free (reg_info_p);
396 : 928180 : reg_info_p = NULL;
397 : 928180 : }
398 : :
399 : : /* Dump the register info to FILE. */
400 : :
401 : : void
402 : 118 : dump_reg_info (FILE *file)
403 : : {
404 : 118 : unsigned int i, max = max_reg_num ();
405 : 118 : if (reload_completed)
406 : : return;
407 : :
408 : 85 : if (reg_info_p_size < max)
409 : 85 : max = reg_info_p_size;
410 : :
411 : 85 : fprintf (file, "%d registers.\n", max);
412 : 85 : for (i = FIRST_PSEUDO_REGISTER; i < max; i++)
413 : : {
414 : 0 : enum reg_class rclass, altclass;
415 : :
416 : 0 : if (regstat_n_sets_and_refs)
417 : 0 : fprintf (file, "\nRegister %d used %d times",
418 : : i, REG_N_REFS (i));
419 : 0 : else if (df)
420 : 0 : fprintf (file, "\nRegister %d used %d times",
421 : 0 : i, DF_REG_USE_COUNT (i) + DF_REG_DEF_COUNT (i));
422 : :
423 : 0 : if (REG_BASIC_BLOCK (i) >= NUM_FIXED_BLOCKS)
424 : 0 : fprintf (file, " in block %d", REG_BASIC_BLOCK (i));
425 : 0 : if (regstat_n_sets_and_refs)
426 : 0 : fprintf (file, "; set %d time%s", REG_N_SETS (i),
427 : 0 : (REG_N_SETS (i) == 1) ? "" : "s");
428 : 0 : else if (df)
429 : 0 : fprintf (file, "; set %d time%s", DF_REG_DEF_COUNT (i),
430 : 0 : (DF_REG_DEF_COUNT (i) == 1) ? "" : "s");
431 : 0 : if (regno_reg_rtx[i] != NULL && REG_USERVAR_P (regno_reg_rtx[i]))
432 : 0 : fputs ("; user var", file);
433 : 0 : if (REG_N_DEATHS (i) != 1)
434 : 0 : fprintf (file, "; dies in %d places", REG_N_DEATHS (i));
435 : 0 : if (REG_N_CALLS_CROSSED (i) == 1)
436 : 0 : fputs ("; crosses 1 call", file);
437 : 0 : else if (REG_N_CALLS_CROSSED (i))
438 : 0 : fprintf (file, "; crosses %d calls", REG_N_CALLS_CROSSED (i));
439 : 0 : if (regno_reg_rtx[i] != NULL
440 : 0 : && maybe_ne (PSEUDO_REGNO_BYTES (i), UNITS_PER_WORD))
441 : : {
442 : 0 : fprintf (file, "; ");
443 : 0 : print_dec (PSEUDO_REGNO_BYTES (i), file, SIGNED);
444 : 0 : fprintf (file, " bytes");
445 : : }
446 : :
447 : 0 : rclass = reg_preferred_class (i);
448 : 0 : altclass = reg_alternate_class (i);
449 : 0 : if (rclass != GENERAL_REGS || altclass != ALL_REGS)
450 : : {
451 : 0 : if (altclass == ALL_REGS || rclass == ALL_REGS)
452 : 0 : fprintf (file, "; pref %s", reg_class_names[(int) rclass]);
453 : 0 : else if (altclass == NO_REGS)
454 : 0 : fprintf (file, "; %s or none", reg_class_names[(int) rclass]);
455 : : else
456 : 0 : fprintf (file, "; pref %s, else %s",
457 : 0 : reg_class_names[(int) rclass],
458 : 0 : reg_class_names[(int) altclass]);
459 : : }
460 : :
461 : 0 : if (regno_reg_rtx[i] != NULL && REG_POINTER (regno_reg_rtx[i]))
462 : 0 : fputs ("; pointer", file);
463 : 0 : fputs (".\n", file);
464 : : }
465 : : }
466 : :
|