/* Post reload partially redundant load elimination
- Copyright (C) 2004, 2005, 2006, 2007
+ Copyright (C) 2004, 2005, 2006, 2007, 2008
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
+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
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. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
/* Support for hash table construction and transformations. */
static bool oprs_unchanged_p (rtx, rtx, bool);
-static void record_last_reg_set_info (rtx, int);
+static void record_last_reg_set_info (rtx, rtx);
+static void record_last_reg_set_info_regno (rtx, int);
static void record_last_mem_set_info (rtx);
-static void record_last_set_info (rtx, rtx, void *);
+static void record_last_set_info (rtx, const_rtx, void *);
static void record_opr_changes (rtx);
-static void find_mem_conflicts (rtx, rtx, void *);
+static void find_mem_conflicts (rtx, const_rtx, void *);
static int load_killed_in_block_p (int, rtx, bool);
static void reset_opr_set_tables (void);
static hashval_t
hash_expr_for_htab (const void *expp)
{
- struct expr *exp = (struct expr *) expp;
+ const struct expr *const exp = (const struct expr *) expp;
return exp->hash;
}
static int
expr_equiv_p (const void *exp1p, const void *exp2p)
{
- struct expr *exp1 = (struct expr *) exp1p;
- struct expr *exp2 = (struct expr *) exp2p;
+ const struct expr *const exp1 = (const struct expr *) exp1p;
+ const struct expr *const exp2 = (const struct expr *) exp2p;
int equiv_p = exp_equiv_p (exp1->expr, exp2->expr, 0, true);
-
+
gcc_assert (!equiv_p || exp1->hash == exp2->hash);
return equiv_p;
}
slot = (struct expr **) htab_find_slot_with_hash (expr_table, cur_expr,
hash, INSERT);
-
+
if (! (*slot))
/* The expression isn't found, so insert it. */
*slot = cur_expr;
/* Search for another occurrence in the same basic block. */
avail_occr = cur_expr->avail_occr;
- while (avail_occr && BLOCK_NUM (avail_occr->insn) != BLOCK_NUM (insn))
+ while (avail_occr
+ && BLOCK_FOR_INSN (avail_occr->insn) != BLOCK_FOR_INSN (insn))
{
/* If an occurrence isn't found, save a pointer to the end of
the list. */
case CONST:
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_FIXED:
case CONST_VECTOR:
case SYMBOL_REF:
case LABEL_REF:
to a nonzero value. */
static void
-find_mem_conflicts (rtx dest, rtx setter ATTRIBUTE_UNUSED,
+find_mem_conflicts (rtx dest, const_rtx setter ATTRIBUTE_UNUSED,
void *data)
{
rtx mem_op = (rtx) data;
/* Record register first/last/block set information for REGNO in INSN. */
static inline void
-record_last_reg_set_info (rtx insn, int regno)
+record_last_reg_set_info (rtx insn, rtx reg)
+{
+ unsigned int regno, end_regno;
+
+ regno = REGNO (reg);
+ end_regno = END_HARD_REGNO (reg);
+ do
+ reg_avail_info[regno] = INSN_CUID (insn);
+ while (++regno < end_regno);
+}
+
+static inline void
+record_last_reg_set_info_regno (rtx insn, int regno)
{
reg_avail_info[regno] = INSN_CUID (insn);
}
the SET is taking place. */
static void
-record_last_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED, void *data)
+record_last_set_info (rtx dest, const_rtx setter ATTRIBUTE_UNUSED, void *data)
{
rtx last_set_insn = (rtx) data;
dest = SUBREG_REG (dest);
if (REG_P (dest))
- record_last_reg_set_info (last_set_insn, REGNO (dest));
+ record_last_reg_set_info (last_set_insn, dest);
else if (MEM_P (dest))
{
/* Ignore pushes, they don't clobber memory. They may still
if (! push_operand (dest, GET_MODE (dest)))
record_last_mem_set_info (last_set_insn);
else
- record_last_reg_set_info (last_set_insn, STACK_POINTER_REGNUM);
+ record_last_reg_set_info_regno (last_set_insn, STACK_POINTER_REGNUM);
}
}
/* Also record autoincremented REGs for this insn as changed. */
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_INC)
- record_last_reg_set_info (insn, REGNO (XEXP (note, 0)));
+ record_last_reg_set_info (insn, XEXP (note, 0));
/* Finally, if this is a call, record all call clobbers. */
if (CALL_P (insn))
{
- unsigned int regno, end_regno;
+ unsigned int regno;
rtx link, x;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
- record_last_reg_set_info (insn, regno);
+ record_last_reg_set_info_regno (insn, regno);
for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
if (GET_CODE (XEXP (link, 0)) == CLOBBER)
if (REG_P (x))
{
gcc_assert (HARD_REGISTER_P (x));
- regno = REGNO (x);
- end_regno = END_HARD_REGNO (x);
- do
- record_last_reg_set_info (insn, regno);
- while (++regno < end_regno);
+ record_last_reg_set_info (insn, x);
}
}
- if (! CONST_OR_PURE_CALL_P (insn))
+ if (! RTL_CONST_OR_PURE_CALL_P (insn))
record_last_mem_set_info (insn);
}
}
avail_insn = a_occr->insn;
avail_reg = get_avail_load_store_reg (avail_insn);
gcc_assert (avail_reg);
-
+
/* Make sure we can generate a move from register avail_reg to
dest. */
extract_insn (gen_move_insn (copy_rtx (dest),
if (/* No load can be replaced by copy. */
npred_ok == 0
- /* Prevent exploding the code. */
- || (optimize_size && npred_ok > 1)
- /* If we don't have profile information we cannot tell if splitting
+ /* Prevent exploding the code. */
+ || (optimize_bb_for_size_p (bb) && npred_ok > 1)
+ /* If we don't have profile information we cannot tell if splitting
a critical edge is profitable or not so don't do it. */
|| ((! profile_info || ! flag_branch_probabilities
|| targetm.cannot_modify_jumps_p ())
continue;
/* Do not try anything on cold basic blocks. */
- if (probably_cold_bb_p (bb))
+ if (optimize_bb_for_size_p (bb))
continue;
/* Reset the table of things changed since the start of the current
memset (&stats, 0, sizeof (stats));
- /* Allocate ememory for this pass.
+ /* Allocate memory for this pass.
Also computes and initializes the insns' CUIDs. */
alloc_mem ();
fprintf (dump_file, "\n\n");
}
}
-
+
/* We are finished with alias. */
end_alias_analysis ();
static bool
gate_handle_gcse2 (void)
{
- return (optimize > 0 && flag_gcse_after_reload);
+ return (optimize > 0 && flag_gcse_after_reload
+ && optimize_function_for_speed_p (cfun));
}
return 0;
}
-struct tree_opt_pass pass_gcse2 =
+struct rtl_opt_pass pass_gcse2 =
{
+ {
+ RTL_PASS,
"gcse2", /* name */
gate_handle_gcse2, /* gate */
rest_of_handle_gcse2, /* execute */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func |
- TODO_verify_flow | TODO_ggc_collect, /* todo_flags_finish */
- 'J' /* letter */
+ TODO_dump_func | TODO_verify_rtl_sharing
+ | TODO_verify_flow | TODO_ggc_collect /* todo_flags_finish */
+ }
};