0
|
1 /* Initialization of uninitialized regs.
|
|
2 Copyright (C) 2007, 2008 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 "tm.h"
|
|
24 #include "tree.h"
|
|
25 #include "rtl.h"
|
|
26 #include "regs.h"
|
|
27 #include "expr.h"
|
|
28 #include "tree-pass.h"
|
|
29 #include "basic-block.h"
|
|
30 #include "flags.h"
|
|
31 #include "df.h"
|
|
32
|
|
33 /* Check all of the uses of pseudo variables. If any use that is MUST
|
|
34 uninitialized, add a store of 0 immediately before it. For
|
|
35 subregs, this makes combine happy. For full word regs, this makes
|
|
36 other optimizations, like the register allocator and the reg-stack
|
|
37 happy as well as papers over some problems on the arm and other
|
|
38 processors where certain isa constraints cannot be handled by gcc.
|
|
39 These are of the form where two operands to an insn my not be the
|
|
40 same. The ra will only make them the same if they do not
|
|
41 interfere, and this can only happen if one is not initialized.
|
|
42
|
|
43 There is also the unfortunate consequence that this may mask some
|
|
44 buggy programs where people forget to initialize stack variable.
|
|
45 Any programmer with half a brain would look at the uninitialized
|
|
46 variable warnings. */
|
|
47
|
|
48 static void
|
|
49 initialize_uninitialized_regs (void)
|
|
50 {
|
|
51 basic_block bb;
|
|
52 bitmap already_genned = BITMAP_ALLOC (NULL);
|
|
53
|
|
54 if (optimize == 1)
|
|
55 {
|
|
56 df_live_add_problem ();
|
|
57 df_live_set_all_dirty ();
|
|
58 }
|
|
59
|
|
60 df_analyze ();
|
|
61
|
|
62 FOR_EACH_BB (bb)
|
|
63 {
|
|
64 rtx insn;
|
|
65 bitmap lr = DF_LR_IN (bb);
|
|
66 bitmap ur = DF_LIVE_IN (bb);
|
|
67 bitmap_clear (already_genned);
|
|
68
|
|
69 FOR_BB_INSNS (bb, insn)
|
|
70 {
|
|
71 unsigned int uid = INSN_UID (insn);
|
|
72 df_ref *use_rec;
|
|
73 if (!INSN_P (insn))
|
|
74 continue;
|
|
75
|
|
76 for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
|
|
77 {
|
|
78 df_ref use = *use_rec;
|
|
79 unsigned int regno = DF_REF_REGNO (use);
|
|
80
|
|
81 /* Only do this for the pseudos. */
|
|
82 if (regno < FIRST_PSEUDO_REGISTER)
|
|
83 continue;
|
|
84
|
|
85 /* Do not generate multiple moves for the same regno.
|
|
86 This is common for sequences of subreg operations.
|
|
87 They would be deleted during combine but there is no
|
|
88 reason to churn the system. */
|
|
89 if (bitmap_bit_p (already_genned, regno))
|
|
90 continue;
|
|
91
|
|
92 /* A use is MUST uninitialized if it reaches the top of
|
|
93 the block from the inside of the block (the lr test)
|
|
94 and no def for it reaches the top of the block from
|
|
95 outside of the block (the ur test). */
|
|
96 if (bitmap_bit_p (lr, regno)
|
|
97 && (!bitmap_bit_p (ur, regno)))
|
|
98 {
|
|
99 rtx move_insn;
|
|
100 rtx reg = DF_REF_REAL_REG (use);
|
|
101
|
|
102 bitmap_set_bit (already_genned, regno);
|
|
103
|
|
104 start_sequence ();
|
|
105 emit_move_insn (reg, CONST0_RTX (GET_MODE (reg)));
|
|
106 move_insn = get_insns ();
|
|
107 end_sequence ();
|
|
108 emit_insn_before (move_insn, insn);
|
|
109 if (dump_file)
|
|
110 fprintf (dump_file,
|
|
111 "adding initialization in %s of reg %d at in block %d for insn %d.\n",
|
|
112 current_function_name (), regno, bb->index, uid);
|
|
113 }
|
|
114 }
|
|
115 }
|
|
116 }
|
|
117
|
|
118 if (optimize == 1)
|
|
119 {
|
|
120 if (dump_file)
|
|
121 df_dump (dump_file);
|
|
122 df_remove_problem (df_live);
|
|
123 }
|
|
124
|
|
125 BITMAP_FREE (already_genned);
|
|
126 }
|
|
127
|
|
128 static bool
|
|
129 gate_initialize_regs (void)
|
|
130 {
|
|
131 return optimize > 0;
|
|
132 }
|
|
133
|
|
134 static unsigned int
|
|
135 rest_of_handle_initialize_regs (void)
|
|
136 {
|
|
137 initialize_uninitialized_regs ();
|
|
138 return 0;
|
|
139 }
|
|
140
|
|
141 struct rtl_opt_pass pass_initialize_regs =
|
|
142 {
|
|
143 {
|
|
144 RTL_PASS,
|
|
145 "init-regs", /* name */
|
|
146 gate_initialize_regs, /* gate */
|
|
147 rest_of_handle_initialize_regs, /* execute */
|
|
148 NULL, /* sub */
|
|
149 NULL, /* next */
|
|
150 0, /* static_pass_number */
|
|
151 0, /* tv_id */
|
|
152 0, /* properties_required */
|
|
153 0, /* properties_provided */
|
|
154 0, /* properties_destroyed */
|
|
155 0, /* todo_flags_start */
|
|
156 TODO_dump_func |
|
|
157 TODO_df_finish /* todo_flags_finish */
|
|
158 }
|
|
159 };
|