11debfc3dSmrg /* Initialization of uninitialized regs.
2*8feb0f0bSmrg Copyright (C) 2007-2020 Free Software Foundation, Inc.
31debfc3dSmrg
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
71debfc3dSmrg the terms of the GNU General Public License as published by the Free
81debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
91debfc3dSmrg version.
101debfc3dSmrg
111debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
121debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
141debfc3dSmrg for more details.
151debfc3dSmrg
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3. If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>. */
191debfc3dSmrg
201debfc3dSmrg #include "config.h"
211debfc3dSmrg #include "system.h"
221debfc3dSmrg #include "coretypes.h"
231debfc3dSmrg #include "backend.h"
241debfc3dSmrg #include "rtl.h"
251debfc3dSmrg #include "tree.h"
261debfc3dSmrg #include "df.h"
271debfc3dSmrg #include "memmodel.h"
281debfc3dSmrg #include "emit-rtl.h"
291debfc3dSmrg #include "expr.h"
301debfc3dSmrg #include "tree-pass.h"
311debfc3dSmrg
321debfc3dSmrg /* Check all of the uses of pseudo variables. If any use that is MUST
331debfc3dSmrg uninitialized, add a store of 0 immediately before it. For
341debfc3dSmrg subregs, this makes combine happy. For full word regs, this makes
351debfc3dSmrg other optimizations, like the register allocator and the reg-stack
361debfc3dSmrg happy as well as papers over some problems on the arm and other
371debfc3dSmrg processors where certain isa constraints cannot be handled by gcc.
381debfc3dSmrg These are of the form where two operands to an insn my not be the
391debfc3dSmrg same. The ra will only make them the same if they do not
401debfc3dSmrg interfere, and this can only happen if one is not initialized.
411debfc3dSmrg
421debfc3dSmrg There is also the unfortunate consequence that this may mask some
431debfc3dSmrg buggy programs where people forget to initialize stack variable.
441debfc3dSmrg Any programmer with half a brain would look at the uninitialized
451debfc3dSmrg variable warnings. */
461debfc3dSmrg
471debfc3dSmrg static void
initialize_uninitialized_regs(void)481debfc3dSmrg initialize_uninitialized_regs (void)
491debfc3dSmrg {
501debfc3dSmrg basic_block bb;
51a2dc1f3fSmrg auto_bitmap already_genned;
521debfc3dSmrg
531debfc3dSmrg if (optimize == 1)
541debfc3dSmrg {
551debfc3dSmrg df_live_add_problem ();
561debfc3dSmrg df_live_set_all_dirty ();
571debfc3dSmrg }
581debfc3dSmrg
591debfc3dSmrg df_analyze ();
601debfc3dSmrg
611debfc3dSmrg FOR_EACH_BB_FN (bb, cfun)
621debfc3dSmrg {
631debfc3dSmrg rtx_insn *insn;
641debfc3dSmrg bitmap lr = DF_LR_IN (bb);
651debfc3dSmrg bitmap ur = DF_LIVE_IN (bb);
661debfc3dSmrg bitmap_clear (already_genned);
671debfc3dSmrg
681debfc3dSmrg FOR_BB_INSNS (bb, insn)
691debfc3dSmrg {
701debfc3dSmrg df_ref use;
711debfc3dSmrg if (!NONDEBUG_INSN_P (insn))
721debfc3dSmrg continue;
731debfc3dSmrg
741debfc3dSmrg FOR_EACH_INSN_USE (use, insn)
751debfc3dSmrg {
761debfc3dSmrg unsigned int regno = DF_REF_REGNO (use);
771debfc3dSmrg
781debfc3dSmrg /* Only do this for the pseudos. */
791debfc3dSmrg if (regno < FIRST_PSEUDO_REGISTER)
801debfc3dSmrg continue;
811debfc3dSmrg
821debfc3dSmrg /* Ignore pseudo PIC register. */
831debfc3dSmrg if (pic_offset_table_rtx
841debfc3dSmrg && regno == REGNO (pic_offset_table_rtx))
851debfc3dSmrg continue;
861debfc3dSmrg
871debfc3dSmrg /* Do not generate multiple moves for the same regno.
881debfc3dSmrg This is common for sequences of subreg operations.
891debfc3dSmrg They would be deleted during combine but there is no
901debfc3dSmrg reason to churn the system. */
911debfc3dSmrg if (bitmap_bit_p (already_genned, regno))
921debfc3dSmrg continue;
931debfc3dSmrg
941debfc3dSmrg /* A use is MUST uninitialized if it reaches the top of
951debfc3dSmrg the block from the inside of the block (the lr test)
961debfc3dSmrg and no def for it reaches the top of the block from
971debfc3dSmrg outside of the block (the ur test). */
981debfc3dSmrg if (bitmap_bit_p (lr, regno)
991debfc3dSmrg && (!bitmap_bit_p (ur, regno)))
1001debfc3dSmrg {
1011debfc3dSmrg rtx_insn *move_insn;
1021debfc3dSmrg rtx reg = DF_REF_REAL_REG (use);
1031debfc3dSmrg
1041debfc3dSmrg bitmap_set_bit (already_genned, regno);
1051debfc3dSmrg
1061debfc3dSmrg start_sequence ();
1071debfc3dSmrg emit_clobber (reg);
1081debfc3dSmrg emit_move_insn (reg, CONST0_RTX (GET_MODE (reg)));
1091debfc3dSmrg move_insn = get_insns ();
1101debfc3dSmrg end_sequence ();
1111debfc3dSmrg emit_insn_before (move_insn, insn);
1121debfc3dSmrg if (dump_file)
1131debfc3dSmrg fprintf (dump_file,
1141debfc3dSmrg "adding initialization in %s of reg %d at in block %d for insn %d.\n",
1151debfc3dSmrg current_function_name (), regno, bb->index,
1161debfc3dSmrg INSN_UID (insn));
1171debfc3dSmrg }
1181debfc3dSmrg }
1191debfc3dSmrg }
1201debfc3dSmrg }
1211debfc3dSmrg
1221debfc3dSmrg if (optimize == 1)
1231debfc3dSmrg {
1241debfc3dSmrg if (dump_file)
1251debfc3dSmrg df_dump (dump_file);
1261debfc3dSmrg df_remove_problem (df_live);
1271debfc3dSmrg }
1281debfc3dSmrg }
1291debfc3dSmrg
1301debfc3dSmrg namespace {
1311debfc3dSmrg
1321debfc3dSmrg const pass_data pass_data_initialize_regs =
1331debfc3dSmrg {
1341debfc3dSmrg RTL_PASS, /* type */
1351debfc3dSmrg "init-regs", /* name */
1361debfc3dSmrg OPTGROUP_NONE, /* optinfo_flags */
1371debfc3dSmrg TV_NONE, /* tv_id */
1381debfc3dSmrg 0, /* properties_required */
1391debfc3dSmrg 0, /* properties_provided */
1401debfc3dSmrg 0, /* properties_destroyed */
1411debfc3dSmrg 0, /* todo_flags_start */
1421debfc3dSmrg TODO_df_finish, /* todo_flags_finish */
1431debfc3dSmrg };
1441debfc3dSmrg
1451debfc3dSmrg class pass_initialize_regs : public rtl_opt_pass
1461debfc3dSmrg {
1471debfc3dSmrg public:
pass_initialize_regs(gcc::context * ctxt)1481debfc3dSmrg pass_initialize_regs (gcc::context *ctxt)
1491debfc3dSmrg : rtl_opt_pass (pass_data_initialize_regs, ctxt)
1501debfc3dSmrg {}
1511debfc3dSmrg
1521debfc3dSmrg /* opt_pass methods: */
gate(function *)1531debfc3dSmrg virtual bool gate (function *) { return optimize > 0; }
execute(function *)1541debfc3dSmrg virtual unsigned int execute (function *)
1551debfc3dSmrg {
1561debfc3dSmrg initialize_uninitialized_regs ();
1571debfc3dSmrg return 0;
1581debfc3dSmrg }
1591debfc3dSmrg
1601debfc3dSmrg }; // class pass_initialize_regs
1611debfc3dSmrg
1621debfc3dSmrg } // anon namespace
1631debfc3dSmrg
1641debfc3dSmrg rtl_opt_pass *
make_pass_initialize_regs(gcc::context * ctxt)1651debfc3dSmrg make_pass_initialize_regs (gcc::context *ctxt)
1661debfc3dSmrg {
1671debfc3dSmrg return new pass_initialize_regs (ctxt);
1681debfc3dSmrg }
169