/* Global common subexpression elimination/Partial redundancy elimination
and global constant/copy propagation for GNU compiler.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007 Free Software Foundation, Inc.
+ 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of GCC.
/* Number of cuids. */
static int max_cuid;
-/* Mapping of cuids to insns. */
-static rtx *cuid_insn;
-
-/* Get insn from cuid. */
-#define CUID_INSN(CUID) (cuid_insn[CUID])
-
/* Maximum register number in function prior to doing gcse + 1.
Registers created during this pass have regno >= max_gcse_regno.
This is named with "gcse" to not collide with global of same name. */
/* We do not construct an accurate cfg in functions which call
setjmp, so just punt to be safe. */
- if (current_function_calls_setjmp)
+ if (cfun->calls_setjmp)
return 0;
/* Assume that we do not need to run jump optimizations after gcse. */
/* Don't allow constant propagation to modify jumps
during this pass. */
- timevar_push (TV_CPROP1);
- changed = one_cprop_pass (pass + 1, false, false);
- timevar_pop (TV_CPROP1);
+ if (dbg_cnt (cprop1))
+ {
+ timevar_push (TV_CPROP1);
+ changed = one_cprop_pass (pass + 1, false, false);
+ timevar_pop (TV_CPROP1);
+ }
if (optimize_size)
/* Do nothing. */ ;
/* Do one last pass of copy propagation, including cprop into
conditional jumps. */
- max_gcse_regno = max_reg_num ();
- alloc_gcse_mem ();
- /* This time, go ahead and allow cprop to alter jumps. */
- timevar_push (TV_CPROP2);
- one_cprop_pass (pass + 1, true, true);
- timevar_pop (TV_CPROP2);
- free_gcse_mem ();
+ if (dbg_cnt (cprop2))
+ {
+ max_gcse_regno = max_reg_num ();
+ alloc_gcse_mem ();
+
+ /* This time, go ahead and allow cprop to alter jumps. */
+ timevar_push (TV_CPROP2);
+ one_cprop_pass (pass + 1, true, true);
+ timevar_pop (TV_CPROP2);
+ free_gcse_mem ();
+ }
if (dump_file)
{
uid_cuid[INSN_UID (insn)] = i;
}
- /* Create a table mapping cuids to insns. */
-
max_cuid = i;
- cuid_insn = gcalloc (max_cuid + 1, sizeof (rtx));
- i = 0;
- FOR_EACH_BB (bb)
- FOR_BB_INSNS (bb, insn)
- if (INSN_P (insn))
- CUID_INSN (i++) = insn;
/* Allocate vars to track sets of regs. */
reg_set_bitmap = BITMAP_ALLOC (NULL);
free_gcse_mem (void)
{
free (uid_cuid);
- free (cuid_insn);
BITMAP_FREE (reg_set_bitmap);
with our replacement. */
if (note != 0 && REG_NOTE_KIND (note) == REG_EQUAL)
set_unique_reg_note (insn, REG_EQUAL,
- simplify_replace_rtx (XEXP (note, 0), from, to));
+ simplify_replace_rtx (XEXP (note, 0), from,
+ copy_rtx (to)));
if (!success && set && reg_mentioned_p (from, SET_SRC (set)))
{
/* If above failed and this is a single set, try to simplify the source of
to one computed by setcc. */
if (setcc && modified_in_p (new, setcc))
return 0;
- if (! validate_change (jump, &SET_SRC (set), new, 0))
+ if (! validate_unshare_change (jump, &SET_SRC (set), new, 0))
{
/* When (some) constants are not valid in a comparison, and there
are two registers to be replaced by constants before the entire
expressions into. Get the mode for the new pseudo from
the mode of the original destination pseudo. */
if (expr->reaching_reg == NULL)
- expr->reaching_reg
- = gen_reg_rtx (GET_MODE (SET_DEST (set)));
+ expr->reaching_reg = gen_reg_rtx_and_attrs (SET_DEST (set));
gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
delete_insn (insn);
We no longer ignore such label references (see LABEL_REF handling in
mark_jump_label for additional information). */
- if (reg_mentioned_p (XEXP (x, 0), insn))
- {
- /* There's no reason for current users to emit jump-insns
- with such a LABEL_REF, so we don't have to handle
- REG_LABEL_TARGET notes. */
- gcc_assert (!JUMP_P (insn));
- REG_NOTES (insn)
- = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, XEXP (x, 0),
- REG_NOTES (insn));
- if (LABEL_P (XEXP (x, 0)))
- LABEL_NUSES (XEXP (x, 0))++;
- }
+ /* There's no reason for current users to emit jump-insns with
+ such a LABEL_REF, so we don't have to handle REG_LABEL_TARGET
+ notes. */
+ gcc_assert (!JUMP_P (insn));
+ REG_NOTES (insn)
+ = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, XEXP (x, 0),
+ REG_NOTES (insn));
+ if (LABEL_P (XEXP (x, 0)))
+ LABEL_NUSES (XEXP (x, 0))++;
+
return;
}
from the mode of the original destination pseudo. */
if (expr->reaching_reg == NULL)
expr->reaching_reg
- = gen_reg_rtx (GET_MODE (SET_DEST (set)));
+ = gen_reg_rtx_and_attrs (SET_DEST (set));
gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
delete_insn (insn);
are any side effects. */
if (TEST_BIT (ae_gen[bb->index], ptr->index))
{
- rtx r = gen_reg_rtx (GET_MODE (ptr->pattern));
+ rtx r = gen_reg_rtx_and_attrs (ptr->pattern);
if (dump_file)
fprintf (dump_file, "Removing redundant store:\n");
replace_store_insn (r, XEXP (st, 0), bb, ptr);
rtx reg, i, del;
if (expr->reaching_reg == NULL_RTX)
- expr->reaching_reg = gen_reg_rtx (GET_MODE (expr->pattern));
+ expr->reaching_reg = gen_reg_rtx_and_attrs (expr->pattern);
reg = expr->reaching_reg;
/* We do not construct an accurate cfg in functions which call
setjmp, so just punt to be safe. */
- if (current_function_calls_setjmp)
+ if (cfun->calls_setjmp)
return 0;
/* Identify the basic block information for this function, including
static bool
gate_handle_jump_bypass (void)
{
- return optimize > 0 && flag_gcse;
+ return optimize > 0 && flag_gcse
+ && dbg_cnt (jump_bypass);
}
/* Perform jump bypassing and control flow optimizations. */
return 0;
}
-struct tree_opt_pass pass_jump_bypass =
+struct rtl_opt_pass pass_jump_bypass =
{
+ {
+ RTL_PASS,
"bypass", /* name */
gate_handle_jump_bypass, /* gate */
rest_of_handle_jump_bypass, /* execute */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func |
- TODO_ggc_collect | TODO_verify_flow, /* todo_flags_finish */
- 'G' /* letter */
+ TODO_ggc_collect | TODO_verify_flow /* todo_flags_finish */
+ }
};
static bool
gate_handle_gcse (void)
{
- return optimize > 0 && flag_gcse;
+ return optimize > 0 && flag_gcse
+ && dbg_cnt (gcse);
}
/* If gcse or cse altered any jumps, rerun jump optimizations to clean
things up. */
- if (tem || tem2)
+ if (tem || tem2 == 2)
{
timevar_push (TV_JUMP);
rebuild_jump_labels (get_insns ());
cleanup_cfg (0);
timevar_pop (TV_JUMP);
}
+ else if (tem2 == 1)
+ cleanup_cfg (0);
flag_cse_skip_blocks = save_csb;
flag_cse_follow_jumps = save_cfj;
return 0;
}
-struct tree_opt_pass pass_gcse =
+struct rtl_opt_pass pass_gcse =
{
+ {
+ RTL_PASS,
"gcse1", /* name */
gate_handle_gcse, /* gate */
rest_of_handle_gcse, /* execute */
0, /* todo_flags_start */
TODO_df_finish | TODO_verify_rtl_sharing |
TODO_dump_func |
- TODO_verify_flow | TODO_ggc_collect, /* todo_flags_finish */
- 'G' /* letter */
+ TODO_verify_flow | TODO_ggc_collect /* todo_flags_finish */
+ }
};