/* Discovery of auto-inc and auto-dec instructions.
- Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
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"
There are (4) basic forms that are matched:
+ (1) FORM_PRE_ADD
a <- b + c
...
*a
a <- b
...
*(a += c) pre
+
+
+ (2) FORM_PRE_INC
a += c
...
*a
becomes
*(a += c) pre
+
+
+ (3) FORM_POST_ADD
*a
...
b <- a + c
- for this case to be true, b must not be assigned or used between
- the *a and the assignment to b. B must also be a Pmode reg.
+ (For this case to be true, b must not be assigned or used between
+ the *a and the assignment to b. B must also be a Pmode reg.)
becomes
b <- a
...
*(b += c) post
+
+
+ (4) FORM_POST_INC
*a
...
a <- a + c
HAVE_PRE_INCREMENT, HAVE_POST_INCREMENT, HAVE_PRE_DECREMENT or
HAVE_POST_DECREMENT defined.
- 2) c is a contant not equal to the width of the value being accessed
+ 2) c is a constant not equal to the width of the value being accessed
by the pointer. This is useful for machines that have
HAVE_PRE_MODIFY_DISP, HAVE_POST_MODIFY_DISP defined.
The is one special case: if a already had an offset equal to it +-
its width and that offset is equal to -c when the increment was
before the ref or +c if the increment was after the ref, then if we
- can do the combination but switch the pre/post bit.
-
- (1) FORM_PRE_ADD
-
- a <- b + c
- ...
- *(a - c)
-
- becomes
-
- a <- b
- ...
- *(a += c) post
-
- (2) FORM_PRE_INC
-
- a += c
- ...
- *(a - c)
-
- becomes
-
- *(a += c) post
-
- (3) FORM_POST_ADD
-
- *(a + c)
- ...
- b <- a + c
-
- for this case to be true, b must not be assigned or used between
- the *a and the assignment to b. B must also be a Pmode reg.
-
- becomes
-
- b <- a
- ...
- *(b += c) pre
-
+ can do the combination but switch the pre/post bit. */
- (4) FORM_POST_INC
-
- *(a + c)
- ...
- a <- a + c
-
- becomes
-
- *(a += c) pre
-*/
#ifdef AUTO_INC_DEC
enum form
/* Move dead note that match PATTERN to TO_INSN from FROM_INSN. We do
not really care about moving any other notes from the inc or add
insn. Moving the REG_EQUAL and REG_EQUIV is clearly wrong and it
- does not appear that there are any other kinds of relavant notes. */
+ does not appear that there are any other kinds of relevant notes. */
static void
move_dead_notes (rtx to_insn, rtx from_insn, rtx pattern)
rtx new_mem;
int old_cost = 0;
int new_cost = 0;
+ bool speed = optimize_bb_for_speed_p (bb);
PUT_MODE (mem_tmp, mode);
XEXP (mem_tmp, 0) = new_addr;
- old_cost = rtx_cost (mem, 0)
- + rtx_cost (PATTERN (inc_insn.insn), 0);
- new_cost = rtx_cost (mem_tmp, 0);
-
+ old_cost = (rtx_cost (mem, SET, speed)
+ + rtx_cost (PATTERN (inc_insn.insn), SET, speed));
+ new_cost = rtx_cost (mem_tmp, SET, speed);
+
/* The first item of business is to see if this is profitable. */
if (old_cost < new_cost)
{
switch (inc_insn.form)
{
case FORM_PRE_ADD:
- mov_insn = insert_move_insn_before (mem_insn.insn,
+ /* Replace the addition with a move. Do it at the location of
+ the addition since the operand of the addition may change
+ before the memory reference. */
+ mov_insn = insert_move_insn_before (inc_insn.insn,
inc_insn.reg_res, inc_insn.reg0);
move_dead_notes (mov_insn, inc_insn.insn, inc_insn.reg0);
}
/* Record that this insn has an implicit side effect. */
- REG_NOTES (mem_insn.insn)
- = alloc_EXPR_LIST (REG_INC, inc_reg, REG_NOTES (mem_insn.insn));
+ add_reg_note (mem_insn.insn, REG_INC, inc_reg);
if (dump_file)
{
/* Try to combine the instruction in INC_INSN with the instruction in
MEM_INSN. First the form is determined using the DECISION_TABLE
- and and the results of parsing the INC_INSN and the MEM_INSN.
+ and the results of parsing the INC_INSN and the MEM_INSN.
Assuming the form is ok, a prototype new address is built which is
passed to ATTEMPT_CHANGE for final processing. */
}
/* Look to see if the inc register is dead after the memory
- reference. If it is do not do the combination. */
+ reference. If it is, do not do the combination. */
if (find_regno_note (last_insn, REG_DEAD, REGNO (inc_reg)))
{
if (dump_file)
else
inc_insn.form = before_mem ? FORM_PRE_ADD : FORM_POST_ADD;
- if (GET_CODE (XEXP (SET_SRC (pat), 1)) == CONST_INT)
+ if (CONST_INT_P (XEXP (SET_SRC (pat), 1)))
{
/* Process a = b + c where c is a const. */
inc_insn.reg1_is_const = true;
mem_insn.reg0 = inc_insn.reg_res;
mem_insn.reg1 = b;
mem_insn.reg1_is_const = inc_insn.reg1_is_const;
- if (GET_CODE (b) == CONST_INT)
+ if (CONST_INT_P (b))
{
/* Match with *(reg0 + reg1) where reg1 is a const. */
HOST_WIDE_INT val = INTVAL (b);
rtx insn;
basic_block bb = BASIC_BLOCK (BLOCK_NUM (mem_insn.insn));
rtx other_insn;
- struct df_ref **def_rec;
+ df_ref *def_rec;
/* Make sure this reg appears only once in this insn. */
if (count_occurrences (PATTERN (mem_insn.insn), mem_insn.reg0, 1) != 1)
assigned to by the mem insn. */
for (def_rec = DF_INSN_DEFS (mem_insn.insn); *def_rec; def_rec++)
{
- struct df_ref *def = *def_rec;
+ df_ref def = *def_rec;
unsigned int regno = DF_REF_REGNO (def);
if ((regno == REGNO (inc_insn.reg0))
|| (regno == REGNO (inc_insn.reg_res)))
return false;
}
- /* Need to check that there are no assignemnts to b
+ /* Need to check that there are no assignments to b
before the add insn. */
other_insn
= get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_def);
next add or inc, not the next insn that used the
reg. Because we are going to increment the reg
in this form, we need to make sure that there
- were no interveining uses of reg. */
+ were no intervening uses of reg. */
if (inc_insn.insn != other_insn)
return false;
}
mem_insn.mem_loc = address_of_x;
mem_insn.reg0 = XEXP (XEXP (x, 0), 0);
mem_insn.reg1 = reg1;
- if (GET_CODE (reg1) == CONST_INT)
+ if (CONST_INT_P (reg1))
{
mem_insn.reg1_is_const = true;
/* Match with *(reg0 + c) where c is a const. */
unsigned int uid = INSN_UID (insn);
bool insn_is_add_or_inc = true;
- if (!INSN_P (insn))
+ if (!NONDEBUG_INSN_P (insn))
continue;
/* This continue is deliberate. We do not want the uses of the
/* If the inc insn was merged with a mem, the inc insn is gone
and there is noting to update. */
- if (DF_INSN_UID_GET(uid))
+ if (DF_INSN_UID_GET (uid))
{
- struct df_ref **def_rec;
- struct df_ref **use_rec;
+ df_ref *def_rec;
+ df_ref *use_rec;
/* Need to update next use. */
for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
{
- struct df_ref *def = *def_rec;
+ df_ref def = *def_rec;
reg_next_use[DF_REF_REGNO (def)] = NULL;
reg_next_inc_use[DF_REF_REGNO (def)] = NULL;
reg_next_def[DF_REF_REGNO (def)] = insn;
for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
{
- struct df_ref *use = *use_rec;
+ df_ref use = *use_rec;
reg_next_use[DF_REF_REGNO (use)] = insn;
if (insn_is_add_or_inc)
reg_next_inc_use[DF_REF_REGNO (use)] = insn;
}
-struct tree_opt_pass pass_inc_dec =
+struct rtl_opt_pass pass_inc_dec =
{
- "auto-inc-dec", /* name */
+ {
+ RTL_PASS,
+ "auto_inc_dec", /* name */
gate_auto_inc_dec, /* gate */
rest_of_handle_auto_inc_dec, /* execute */
NULL, /* sub */
0, /* todo_flags_start */
TODO_dump_func |
TODO_df_finish, /* todo_flags_finish */
- 0 /* letter */
+ }
};
-