/* 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.
#include "tree-pass.h"
#include "df.h"
#include "dbgcnt.h"
+#include "target.h"
/* This pass was originally removed from flow.c. However there is
almost nothing that remains of that code.
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
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
+ can do the combination but switch the pre/post bit. */
- 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
-
-
- (4) FORM_POST_INC
-
- *(a + c)
- ...
- a <- a + c
-
- becomes
-
- *(a += c) pre
-*/
#ifdef AUTO_INC_DEC
enum form
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)
{
}
/* 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. */
/* The width of the mem being accessed. */
int size = GET_MODE_SIZE (GET_MODE (mem));
rtx last_insn = NULL;
+ enum machine_mode reg_mode = GET_MODE (inc_reg);
switch (inc_insn.form)
{
case SIMPLE_PRE_INC: /* ++size */
if (dump_file)
fprintf (dump_file, "trying SIMPLE_PRE_INC\n");
- return attempt_change (gen_rtx_PRE_INC (Pmode, inc_reg), inc_reg);
+ return attempt_change (gen_rtx_PRE_INC (reg_mode, inc_reg), inc_reg);
break;
case SIMPLE_POST_INC: /* size++ */
if (dump_file)
fprintf (dump_file, "trying SIMPLE_POST_INC\n");
- return attempt_change (gen_rtx_POST_INC (Pmode, inc_reg), inc_reg);
+ return attempt_change (gen_rtx_POST_INC (reg_mode, inc_reg), inc_reg);
break;
case SIMPLE_PRE_DEC: /* --size */
if (dump_file)
fprintf (dump_file, "trying SIMPLE_PRE_DEC\n");
- return attempt_change (gen_rtx_PRE_DEC (Pmode, inc_reg), inc_reg);
+ return attempt_change (gen_rtx_PRE_DEC (reg_mode, inc_reg), inc_reg);
break;
case SIMPLE_POST_DEC: /* size-- */
if (dump_file)
fprintf (dump_file, "trying SIMPLE_POST_DEC\n");
- return attempt_change (gen_rtx_POST_DEC (Pmode, inc_reg), inc_reg);
+ return attempt_change (gen_rtx_POST_DEC (reg_mode, inc_reg), inc_reg);
break;
case DISP_PRE: /* ++con */
if (dump_file)
fprintf (dump_file, "trying DISP_PRE\n");
- return attempt_change (gen_rtx_PRE_MODIFY (Pmode,
+ return attempt_change (gen_rtx_PRE_MODIFY (reg_mode,
inc_reg,
- gen_rtx_PLUS (Pmode,
+ gen_rtx_PLUS (reg_mode,
inc_reg,
inc_insn.reg1)),
inc_reg);
case DISP_POST: /* con++ */
if (dump_file)
fprintf (dump_file, "trying POST_DISP\n");
- return attempt_change (gen_rtx_POST_MODIFY (Pmode,
+ return attempt_change (gen_rtx_POST_MODIFY (reg_mode,
inc_reg,
- gen_rtx_PLUS (Pmode,
+ gen_rtx_PLUS (reg_mode,
inc_reg,
inc_insn.reg1)),
inc_reg);
case REG_PRE: /* ++reg */
if (dump_file)
fprintf (dump_file, "trying PRE_REG\n");
- return attempt_change (gen_rtx_PRE_MODIFY (Pmode,
+ return attempt_change (gen_rtx_PRE_MODIFY (reg_mode,
inc_reg,
- gen_rtx_PLUS (Pmode,
+ gen_rtx_PLUS (reg_mode,
inc_reg,
inc_insn.reg1)),
inc_reg);
case REG_POST: /* reg++ */
if (dump_file)
fprintf (dump_file, "trying POST_REG\n");
- return attempt_change (gen_rtx_POST_MODIFY (Pmode,
+ return attempt_change (gen_rtx_POST_MODIFY (reg_mode,
inc_reg,
- gen_rtx_PLUS (Pmode,
+ gen_rtx_PLUS (reg_mode,
inc_reg,
inc_insn.reg1)),
inc_reg);
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)))
we are going to increment the result of the add insn.
For this trick to be correct, the result reg of
the inc must be a valid addressing reg. */
- if (GET_MODE (inc_insn.reg_res) != Pmode)
+ addr_space_t as = MEM_ADDR_SPACE (*mem_insn.mem_loc);
+ if (GET_MODE (inc_insn.reg_res)
+ != targetm.addr_space.address_mode (as))
{
if (dump_file)
fprintf (dump_file, "base reg mode failure.\n");
{
/* For this trick to be correct, the result reg of the inc
must be a valid addressing reg. */
- if (GET_MODE (inc_insn.reg_res) != Pmode)
+ addr_space_t as = MEM_ADDR_SPACE (*mem_insn.mem_loc);
+ if (GET_MODE (inc_insn.reg_res)
+ != targetm.addr_space.address_mode (as))
{
if (dump_file)
fprintf (dump_file, "base reg mode failure.\n");
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;
{
{
RTL_PASS,
- "auto-inc-dec", /* name */
+ "auto_inc_dec", /* name */
gate_auto_inc_dec, /* gate */
rest_of_handle_auto_inc_dec, /* execute */
NULL, /* sub */
TODO_df_finish, /* todo_flags_finish */
}
};
-