diff options
author | dberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-06-11 18:02:15 +0000 |
---|---|---|
committer | dberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-06-11 18:02:15 +0000 |
commit | 3072d30e7983a3ca5ad030f1f98a5c39bcc2c07b (patch) | |
tree | fdb9e9f8a0700a2713dc690fed1a2cf20dae8392 /gcc/init-regs.c | |
parent | 8ceb1bfd33bc40bf0cbe1fab8903c2c31efd10ee (diff) | |
download | gcc-3072d30e7983a3ca5ad030f1f98a5c39bcc2c07b.tar.gz |
Merge dataflow branch into mainline
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125624 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/init-regs.c')
-rw-r--r-- | gcc/init-regs.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/gcc/init-regs.c b/gcc/init-regs.c new file mode 100644 index 00000000000..adde3fa2cd7 --- /dev/null +++ b/gcc/init-regs.c @@ -0,0 +1,148 @@ +/* Initialization of uninitialized regs. + Copyright (C) 2007 Free Software Foundation, + Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "rtl.h" +#include "regs.h" +#include "expr.h" +#include "tree-pass.h" +#include "basic-block.h" +#include "flags.h" +#include "df.h" + +/* Check all of the uses of pseudo variables. If any use that is MUST + uninitialized, add a store of 0 immediately before it. For + subregs, this makes combine happy. For full word regs, this makes + other optimizations, like the register allocator and the reg-stack + happy as well as papers over some problems on the arm and other + processors where certain isa constraints cannot be handled by gcc. + These are of the form where two operands to an insn my not be the + same. The ra will only make them the same if they do not + interfere, and this can only happen if one is not initialized. + + There is also the unfortunate consequence that this may mask some + buggy programs where people forget to initialize stack variable. + Any programmer with half a brain would look at the uninitialized + variable warnings. */ + +static void +initialize_uninitialized_regs (void) +{ + basic_block bb; + bitmap already_genned = BITMAP_ALLOC (NULL); + + df_analyze (); + + FOR_EACH_BB (bb) + { + rtx insn; + bitmap lr = DF_LR_IN (bb); + bitmap ur = DF_LIVE_IN (bb); + bitmap_clear (already_genned); + + FOR_BB_INSNS (bb, insn) + { + unsigned int uid = INSN_UID (insn); + struct df_ref **use_rec; + if (!INSN_P (insn)) + continue; + + for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) + { + struct df_ref *use = *use_rec; + unsigned int regno = DF_REF_REGNO (use); + + /* Only do this for the pseudos. */ + if (regno < FIRST_PSEUDO_REGISTER) + continue; + + /* Do not generate multiple moves for the same regno. + This is common for sequences of subreg operations. + They would be deleted during combine but there is no + reason to churn the system. */ + if (bitmap_bit_p (already_genned, regno)) + continue; + + /* A use is MUST uninitialized if it reaches the top of + the block from the inside of the block (the lr test) + and no def for it reaches the top of the block from + outside of the block (the ur test). */ + if (bitmap_bit_p (lr, regno) + && (!bitmap_bit_p (ur, regno))) + { + rtx move_insn; + rtx reg = DF_REF_REAL_REG (use); + + bitmap_set_bit (already_genned, regno); + + start_sequence (); + emit_move_insn (reg, CONST0_RTX (GET_MODE (reg))); + move_insn = get_insns (); + end_sequence (); + add_insn_before (move_insn, insn, bb); + if (dump_file) + fprintf (dump_file, + "adding initialization in %s of reg %d at in block %d for insn %d.\n", + current_function_name (), regno, bb->index, uid); + } + } + } + } + + BITMAP_FREE (already_genned); +} + +static bool +gate_initialize_regs (void) +{ + return optimize > 0; +} + +static unsigned int +rest_of_handle_initialize_regs (void) +{ + no_new_pseudos = 0; + initialize_uninitialized_regs (); + no_new_pseudos = 1; + return 0; +} + +struct tree_opt_pass pass_initialize_regs = +{ + "init-regs", /* name */ + gate_initialize_regs, /* gate */ + rest_of_handle_initialize_regs, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_df_finish, /* todo_flags_finish */ + 0 /* letter */ +}; |