/* Subroutines used by or related to instruction recognition.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GCC.
#include "expr.h"
#include "function.h"
#include "flags.h"
-#include "real.h"
#include "toplev.h"
#include "basic-block.h"
#include "output.h"
else
return false;
}
-
+
/* This subroutine of apply_change_group verifies whether the changes to INSN
were valid; i.e. whether INSN can still be recognized. */
if (MEM_P (object))
{
- if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
+ if (! memory_address_addr_space_p (GET_MODE (object),
+ XEXP (object, 0),
+ MEM_ADDR_SPACE (object)))
break;
}
else if (REG_P (changes[i].old)
rtx. */
static void
-simplify_while_replacing (rtx *loc, rtx to, rtx object,
+simplify_while_replacing (rtx *loc, rtx to, rtx object,
enum machine_mode op0_mode)
{
rtx x = *loc;
validate_change passing OBJECT. */
static void
-validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object,
+validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object,
bool simplify)
{
int i, j;
from, to, object, simplify);
}
else
- validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object,
+ validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object,
simplify);
}
}
validate_replace_rtx_1 (&XEXP (x, i), from, to, object, simplify);
else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object,
+ validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object,
simplify);
}
}
/* Try replacing every occurrence of FROM in WHERE with TO. Assume that WHERE
- is a part of INSN. After all changes have been made, validate by seeing if
- INSN is still valid.
- validate_replace_rtx (from, to, insn) is equivalent to
+ is a part of INSN. After all changes have been made, validate by seeing if
+ INSN is still valid.
+ validate_replace_rtx (from, to, insn) is equivalent to
validate_replace_rtx_part (from, to, &PATTERN (insn), insn). */
int
}
/* Same as above, but do not simplify rtx afterwards. */
-int
-validate_replace_rtx_part_nosimplify (rtx from, rtx to, rtx *where,
+int
+validate_replace_rtx_part_nosimplify (rtx from, rtx to, rtx *where,
rtx insn)
{
validate_replace_rtx_1 (where, from, to, insn, false);
}
-/* Try replacing every occurrence of FROM in INSN with TO. */
+/* Try replacing every occurrence of FROM in INSN with TO. This also
+ will replace in REG_EQUAL and REG_EQUIV notes. */
void
validate_replace_rtx_group (rtx from, rtx to, rtx insn)
{
+ rtx note;
validate_replace_rtx_1 (&PATTERN (insn), from, to, insn, true);
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_EQUAL
+ || REG_NOTE_KIND (note) == REG_EQUIV)
+ validate_replace_rtx_1 (&XEXP (note, 0), from, to, insn, true);
}
/* Function called by note_uses to replace used subexpressions. */
return 0;
/* Use the mem's mode, since it will be reloaded thus. */
- if (memory_address_p (GET_MODE (op), y))
+ if (memory_address_addr_space_p (GET_MODE (op), y, MEM_ADDR_SPACE (op)))
return 1;
}
return XEXP (op, 0) == stack_pointer_rtx;
}
-/* Return 1 if ADDR is a valid memory address for mode MODE. */
+/* Return 1 if ADDR is a valid memory address
+ for mode MODE in address space AS. */
int
-memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
+memory_address_addr_space_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx addr, addr_space_t as)
{
#ifdef GO_IF_LEGITIMATE_ADDRESS
+ gcc_assert (ADDR_SPACE_GENERIC_P (as));
GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
return 0;
win:
return 1;
#else
- return targetm.legitimate_address_p (mode, addr, 0);
+ return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
#endif
}
if (GET_CODE (XVECEXP (body, 0, 0)) == SET)
{
/* Multiple output operands, or 1 output plus some clobbers:
- body is
+ body is
[(set OUTPUT (asm_operands ...))... (clobber (reg ...))...]. */
/* Count backwards through CLOBBERs to determine number of SETs. */
for (i = XVECLEN (body, 0); i > 0; i--)
const char **constraints, enum machine_mode *modes,
location_t *loc)
{
- int noperands, nbase = 0, n, i;
+ int nbase = 0, n, i;
rtx asmop;
switch (GET_CODE (body))
gcc_unreachable ();
}
- noperands = (ASM_OPERANDS_INPUT_LENGTH (asmop)
- + ASM_OPERANDS_LABEL_LENGTH (asmop) + nbase);
-
n = ASM_OPERANDS_INPUT_LENGTH (asmop);
for (i = 0; i < n; i++)
{
offsettable_memref_p (rtx op)
{
return ((MEM_P (op))
- && offsettable_address_p (1, GET_MODE (op), XEXP (op, 0)));
+ && offsettable_address_addr_space_p (1, GET_MODE (op), XEXP (op, 0),
+ MEM_ADDR_SPACE (op)));
}
/* Similar, but don't require a strictly valid mem ref:
offsettable_nonstrict_memref_p (rtx op)
{
return ((MEM_P (op))
- && offsettable_address_p (0, GET_MODE (op), XEXP (op, 0)));
+ && offsettable_address_addr_space_p (0, GET_MODE (op), XEXP (op, 0),
+ MEM_ADDR_SPACE (op)));
}
/* Return 1 if Y is a memory address which contains no side effects
- and would remain valid after the addition of a positive integer
- less than the size of that mode.
+ and would remain valid for address space AS after the addition of
+ a positive integer less than the size of that mode.
We assume that the original address is valid and do not check it.
We do check that it is valid for narrower modes.
for the sake of use in reload.c. */
int
-offsettable_address_p (int strictp, enum machine_mode mode, rtx y)
+offsettable_address_addr_space_p (int strictp, enum machine_mode mode, rtx y,
+ addr_space_t as)
{
enum rtx_code ycode = GET_CODE (y);
rtx z;
rtx y1 = y;
rtx *y2;
- int (*addressp) (enum machine_mode, rtx) =
- (strictp ? strict_memory_address_p : memory_address_p);
+ int (*addressp) (enum machine_mode, rtx, addr_space_t) =
+ (strictp ? strict_memory_address_addr_space_p
+ : memory_address_addr_space_p);
unsigned int mode_sz = GET_MODE_SIZE (mode);
if (CONSTANT_ADDRESS_P (y))
*y2 = plus_constant (*y2, mode_sz - 1);
/* Use QImode because an odd displacement may be automatically invalid
for any wider mode. But it should be valid for a single byte. */
- good = (*addressp) (QImode, y);
+ good = (*addressp) (QImode, y, as);
/* In any case, restore old contents of memory. */
*y2 = y1;
/* Use QImode because an odd displacement may be automatically invalid
for any wider mode. But it should be valid for a single byte. */
- return (*addressp) (QImode, z);
+ return (*addressp) (QImode, z, as);
}
/* Return 1 if ADDR is an address-expression whose effect depends
Autoincrement addressing is a typical example of mode-dependence
because the amount of the increment depends on the mode. */
-int
+bool
mode_dependent_address_p (rtx addr)
{
/* Auto-increment addressing with anything other than post_modify
|| GET_CODE (addr) == POST_INC
|| GET_CODE (addr) == PRE_DEC
|| GET_CODE (addr) == POST_DEC)
- return 1;
+ return true;
- GO_IF_MODE_DEPENDENT_ADDRESS (addr, win);
- return 0;
- /* Label `win' might (not) be used via GO_IF_MODE_DEPENDENT_ADDRESS. */
- win: ATTRIBUTE_UNUSED_LABEL
- return 1;
+ return targetm.mode_dependent_address_p (addr);
}
\f
/* Like extract_insn, but save insn extracted and don't extract again, when
recog_data.operand_loc,
recog_data.constraints,
recog_data.operand_mode, NULL);
+ memset (recog_data.is_operator, 0, sizeof recog_data.is_operator);
if (noperands > 0)
{
const char *p = recog_data.constraints[0];
for (i = 0; i < noperands; i++)
{
recog_data.constraints[i] = insn_data[icode].operand[i].constraint;
+ recog_data.is_operator[i] = insn_data[icode].operand[i].is_operator;
recog_data.operand_mode[i] = insn_data[icode].operand[i].mode;
/* VOIDmode match_operands gets mode from their real operand. */
if (recog_data.operand_mode[i] == VOIDmode)
if (MEM_P (op))
{
if (strict > 0
- && !strict_memory_address_p (GET_MODE (op),
- XEXP (op, 0)))
+ && !strict_memory_address_addr_space_p
+ (GET_MODE (op), XEXP (op, 0),
+ MEM_ADDR_SPACE (op)))
break;
if (strict == 0
- && !memory_address_p (GET_MODE (op), XEXP (op, 0)))
+ && !memory_address_addr_space_p
+ (GET_MODE (op), XEXP (op, 0),
+ MEM_ADDR_SPACE (op)))
break;
win = 1;
}
do_cleanup_cfg |= purge_dead_edges (bb);
}
-#ifdef HAVE_conditional_execution
- for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
- peep2_insn_data[i].insn = NULL_RTX;
- peep2_insn_data[peep2_current].insn = PEEP2_EOB;
- peep2_current_count = 0;
-#else
- /* Back up lifetime information past the end of the
- newly created sequence. */
- if (++i >= MAX_INSNS_PER_PEEP2 + 1)
- i = 0;
- bitmap_copy (live, peep2_insn_data[i].live_before);
-
- /* Update life information for the new sequence. */
- x = attempt;
- do
+ if (targetm.have_conditional_execution ())
{
- if (INSN_P (x))
+ for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
+ peep2_insn_data[i].insn = NULL_RTX;
+ peep2_insn_data[peep2_current].insn = PEEP2_EOB;
+ peep2_current_count = 0;
+ }
+ else
+ {
+ /* Back up lifetime information past the end of the
+ newly created sequence. */
+ if (++i >= MAX_INSNS_PER_PEEP2 + 1)
+ i = 0;
+ bitmap_copy (live, peep2_insn_data[i].live_before);
+
+ /* Update life information for the new sequence. */
+ x = attempt;
+ do
{
- if (--i < 0)
- i = MAX_INSNS_PER_PEEP2;
- if (peep2_current_count < MAX_INSNS_PER_PEEP2
- && peep2_insn_data[i].insn == NULL_RTX)
- peep2_current_count++;
- peep2_insn_data[i].insn = x;
- df_insn_rescan (x);
- df_simulate_one_insn_backwards (bb, x, live);
- bitmap_copy (peep2_insn_data[i].live_before, live);
+ if (INSN_P (x))
+ {
+ if (--i < 0)
+ i = MAX_INSNS_PER_PEEP2;
+ if (peep2_current_count < MAX_INSNS_PER_PEEP2
+ && peep2_insn_data[i].insn == NULL_RTX)
+ peep2_current_count++;
+ peep2_insn_data[i].insn = x;
+ df_insn_rescan (x);
+ df_simulate_one_insn_backwards (bb, x, live);
+ bitmap_copy (peep2_insn_data[i].live_before,
+ live);
+ }
+ x = PREV_INSN (x);
}
- x = PREV_INSN (x);
- }
- while (x != prev);
+ while (x != prev);
- peep2_current = i;
-#endif
+ peep2_current = i;
+ }
/* If we generated a jump instruction, it won't have
JUMP_LABEL set. Recompute after we're done. */
return 1;
#else
return 0;
-#endif
+#endif
}
struct rtl_opt_pass pass_split_for_shorten_branches =