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