a33927c9ab
The initialize_uninitialized_regs function emits (set (reg:) (CONST0_RTX)) for all uninitialized pseudo uses. However, some modes (eg, opaque modes) may not have a CONST0_RTX defined, leading to an ICE when we try and create the initialization insn. The fix is to skip emitting the initialization if there is no CONST0_RTX defined for the mode. 2021-02-15 Peter Bergner <bergner@linux.ibm.com> gcc/ PR rtl-optimization/98872 * init-regs.c (initialize_uninitialized_regs): Skip initialization if CONST0_RTX is NULL. gcc/testsuite/ PR rtl-optimization/98872 * gcc.target/powerpc/pr98872.c: New test.
172 lines
4.7 KiB
C
172 lines
4.7 KiB
C
/* Initialization of uninitialized regs.
|
|
Copyright (C) 2007-2021 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 3, 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 COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "coretypes.h"
|
|
#include "backend.h"
|
|
#include "rtl.h"
|
|
#include "tree.h"
|
|
#include "df.h"
|
|
#include "memmodel.h"
|
|
#include "emit-rtl.h"
|
|
#include "expr.h"
|
|
#include "tree-pass.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;
|
|
auto_bitmap already_genned;
|
|
|
|
if (optimize == 1)
|
|
{
|
|
df_live_add_problem ();
|
|
df_live_set_all_dirty ();
|
|
}
|
|
|
|
df_analyze ();
|
|
|
|
FOR_EACH_BB_FN (bb, cfun)
|
|
{
|
|
rtx_insn *insn;
|
|
bitmap lr = DF_LR_IN (bb);
|
|
bitmap ur = DF_LIVE_IN (bb);
|
|
bitmap_clear (already_genned);
|
|
|
|
FOR_BB_INSNS (bb, insn)
|
|
{
|
|
df_ref use;
|
|
if (!NONDEBUG_INSN_P (insn))
|
|
continue;
|
|
|
|
FOR_EACH_INSN_USE (use, insn)
|
|
{
|
|
unsigned int regno = DF_REF_REGNO (use);
|
|
|
|
/* Only do this for the pseudos. */
|
|
if (regno < FIRST_PSEUDO_REGISTER)
|
|
continue;
|
|
|
|
/* Ignore pseudo PIC register. */
|
|
if (pic_offset_table_rtx
|
|
&& regno == REGNO (pic_offset_table_rtx))
|
|
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_insn *move_insn;
|
|
rtx reg = DF_REF_REAL_REG (use);
|
|
|
|
bitmap_set_bit (already_genned, regno);
|
|
|
|
start_sequence ();
|
|
emit_clobber (reg);
|
|
/* PR98872: Only emit an initialization if MODE has a
|
|
CONST0_RTX defined. */
|
|
if (CONST0_RTX (GET_MODE (reg)))
|
|
emit_move_insn (reg, CONST0_RTX (GET_MODE (reg)));
|
|
move_insn = get_insns ();
|
|
end_sequence ();
|
|
emit_insn_before (move_insn, insn);
|
|
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,
|
|
INSN_UID (insn));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (optimize == 1)
|
|
{
|
|
if (dump_file)
|
|
df_dump (dump_file);
|
|
df_remove_problem (df_live);
|
|
}
|
|
}
|
|
|
|
namespace {
|
|
|
|
const pass_data pass_data_initialize_regs =
|
|
{
|
|
RTL_PASS, /* type */
|
|
"init-regs", /* name */
|
|
OPTGROUP_NONE, /* optinfo_flags */
|
|
TV_NONE, /* tv_id */
|
|
0, /* properties_required */
|
|
0, /* properties_provided */
|
|
0, /* properties_destroyed */
|
|
0, /* todo_flags_start */
|
|
TODO_df_finish, /* todo_flags_finish */
|
|
};
|
|
|
|
class pass_initialize_regs : public rtl_opt_pass
|
|
{
|
|
public:
|
|
pass_initialize_regs (gcc::context *ctxt)
|
|
: rtl_opt_pass (pass_data_initialize_regs, ctxt)
|
|
{}
|
|
|
|
/* opt_pass methods: */
|
|
virtual bool gate (function *) { return optimize > 0; }
|
|
virtual unsigned int execute (function *)
|
|
{
|
|
initialize_uninitialized_regs ();
|
|
return 0;
|
|
}
|
|
|
|
}; // class pass_initialize_regs
|
|
|
|
} // anon namespace
|
|
|
|
rtl_opt_pass *
|
|
make_pass_initialize_regs (gcc::context *ctxt)
|
|
{
|
|
return new pass_initialize_regs (ctxt);
|
|
}
|