xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/init-regs.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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