Line data Source code
1 : /* Initialization of uninitialized regs.
2 : Copyright (C) 2007-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation; either version 3, or (at your option) any later
9 : version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along 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 "backend.h"
24 : #include "rtl.h"
25 : #include "tree.h"
26 : #include "df.h"
27 : #include "memmodel.h"
28 : #include "emit-rtl.h"
29 : #include "expr.h"
30 : #include "tree-pass.h"
31 :
32 : /* Check all of the uses of pseudo variables. If any use that is MUST
33 : uninitialized, add a store of 0 immediately before it. For
34 : subregs, this makes combine happy. For full word regs, this makes
35 : other optimizations, like the register allocator and the reg-stack
36 : happy as well as papers over some problems on the arm and other
37 : processors where certain isa constraints cannot be handled by gcc.
38 : These are of the form where two operands to an insn my not be the
39 : same. The ra will only make them the same if they do not
40 : interfere, and this can only happen if one is not initialized.
41 :
42 : There is also the unfortunate consequence that this may mask some
43 : buggy programs where people forget to initialize stack variable.
44 : Any programmer with half a brain would look at the uninitialized
45 : variable warnings. */
46 :
47 : static void
48 1043678 : initialize_uninitialized_regs (void)
49 : {
50 1043678 : basic_block bb;
51 1043678 : auto_bitmap already_genned;
52 :
53 1043678 : if (optimize == 1)
54 : {
55 79703 : df_live_add_problem ();
56 79703 : df_live_set_all_dirty ();
57 : }
58 :
59 1043678 : df_analyze ();
60 :
61 11447150 : FOR_EACH_BB_FN (bb, cfun)
62 : {
63 10403472 : rtx_insn *insn;
64 10403472 : bitmap lr = DF_LR_IN (bb);
65 10403472 : bitmap ur = DF_LIVE_IN (bb);
66 10403472 : bitmap_clear (already_genned);
67 :
68 134245280 : FOR_BB_INSNS (bb, insn)
69 : {
70 123841808 : df_ref use;
71 123841808 : if (!NONDEBUG_INSN_P (insn))
72 65385867 : continue;
73 :
74 132956796 : FOR_EACH_INSN_USE (use, insn)
75 : {
76 74500855 : unsigned int regno = DF_REF_REGNO (use);
77 :
78 : /* Only do this for the pseudos. */
79 74500855 : if (regno < FIRST_PSEUDO_REGISTER)
80 35614353 : continue;
81 :
82 : /* Ignore pseudo PIC register. */
83 39192878 : if (pic_offset_table_rtx
84 38886502 : && regno == REGNO (pic_offset_table_rtx))
85 306376 : continue;
86 :
87 : /* Do not generate multiple moves for the same regno.
88 : This is common for sequences of subreg operations.
89 : They would be deleted during combine but there is no
90 : reason to churn the system. */
91 38580126 : if (bitmap_bit_p (already_genned, regno))
92 307361 : continue;
93 :
94 : /* A use is MUST uninitialized if it reaches the top of
95 : the block from the inside of the block (the lr test)
96 : and no def for it reaches the top of the block from
97 : outside of the block (the ur test). */
98 38272765 : if (bitmap_bit_p (lr, regno)
99 38272765 : && (!bitmap_bit_p (ur, regno)))
100 : {
101 182404 : rtx_insn *move_insn;
102 182404 : rtx reg = DF_REF_REAL_REG (use);
103 :
104 182404 : bitmap_set_bit (already_genned, regno);
105 :
106 182404 : start_sequence ();
107 182404 : emit_clobber (reg);
108 : /* PR98872: Only emit an initialization if MODE has a
109 : CONST0_RTX defined. */
110 182404 : if (CONST0_RTX (GET_MODE (reg)))
111 182404 : emit_move_insn (reg, CONST0_RTX (GET_MODE (reg)));
112 182404 : move_insn = end_sequence ();
113 182404 : emit_insn_before (move_insn, insn);
114 182404 : if (dump_file)
115 0 : fprintf (dump_file,
116 : "adding initialization in %s of reg %d at in block %d for insn %d.\n",
117 : current_function_name (), regno, bb->index,
118 0 : INSN_UID (insn));
119 : }
120 : }
121 : }
122 : }
123 :
124 1043678 : if (optimize == 1)
125 : {
126 79703 : if (dump_file)
127 8 : df_dump (dump_file);
128 79703 : df_remove_problem (df_live);
129 : }
130 1043678 : }
131 :
132 : namespace {
133 :
134 : const pass_data pass_data_initialize_regs =
135 : {
136 : RTL_PASS, /* type */
137 : "init-regs", /* name */
138 : OPTGROUP_NONE, /* optinfo_flags */
139 : TV_NONE, /* tv_id */
140 : 0, /* properties_required */
141 : 0, /* properties_provided */
142 : 0, /* properties_destroyed */
143 : 0, /* todo_flags_start */
144 : TODO_df_finish, /* todo_flags_finish */
145 : };
146 :
147 : class pass_initialize_regs : public rtl_opt_pass
148 : {
149 : public:
150 285722 : pass_initialize_regs (gcc::context *ctxt)
151 571444 : : rtl_opt_pass (pass_data_initialize_regs, ctxt)
152 : {}
153 :
154 : /* opt_pass methods: */
155 1471370 : bool gate (function *) final override { return optimize > 0; }
156 1043678 : unsigned int execute (function *) final override
157 : {
158 1043678 : initialize_uninitialized_regs ();
159 1043678 : return 0;
160 : }
161 :
162 : }; // class pass_initialize_regs
163 :
164 : } // anon namespace
165 :
166 : rtl_opt_pass *
167 285722 : make_pass_initialize_regs (gcc::context *ctxt)
168 : {
169 285722 : return new pass_initialize_regs (ctxt);
170 : }
|