/* Subroutines used by or related to instruction recognition.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "rtl.h"
#include "tm_p.h"
#include "insn-config.h"
{
case PLUS:
/* If we have a PLUS whose second operand is now a CONST_INT, use
- plus_constant to try to simplify it.
+ simplify_gen_binary to try to simplify it.
??? We may want later to remove this, once simplification is
separated from this function. */
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT && XEXP (x, 1) == to)
validate_change (object, loc,
simplify_gen_binary
(PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1);
note_uses (&PATTERN (insn), validate_replace_src_1, &d);
}
-/* Same as validate_repalace_src_group, but validate by seeing if
+/* Same as validate_replace_src_group, but validate by seeing if
INSN is still valid. */
int
validate_replace_src (from, to, insn)
#ifdef CANNOT_CHANGE_MODE_CLASS
if (GET_CODE (sub) == REG
&& REGNO (sub) < FIRST_PSEUDO_REGISTER
- && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), mode, GET_MODE (sub))
+ && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
return 0;
#ifdef STACK_GROWS_DOWNWARD
|| INTVAL (XEXP (XEXP (op, 1), 1)) != - (int) rounded_size
#else
- || INTVAL (XEXP (XEXP (op, 1), 1)) != rounded_size
+ || INTVAL (XEXP (XEXP (op, 1), 1)) != (int) rounded_size
#endif
)
return 0;
while (*constraint)
{
- char c = *constraint++;
+ char c = *constraint;
+ int len;
switch (c)
{
+ case ',':
+ constraint++;
+ continue;
case '=':
case '+':
case '*':
case '%':
- case '?':
case '!':
case '#':
case '&':
- case ',':
+ case '?':
break;
case '0': case '1': case '2': case '3': case '4':
proper matching constraint, but we can't actually fail
the check if they didn't. Indicate that results are
inconclusive. */
- while (ISDIGIT (*constraint))
+ do
constraint++;
- result = -1;
- break;
+ while (ISDIGIT (*constraint));
+ if (! result)
+ result = -1;
+ continue;
case 'p':
if (address_operand (op, VOIDmode))
- return 1;
+ result = 1;
break;
case 'm':
case 'V': /* non-offsettable */
if (memory_operand (op, VOIDmode))
- return 1;
+ result = 1;
break;
case 'o': /* offsettable */
if (offsettable_nonstrict_memref_p (op))
- return 1;
+ result = 1;
break;
case '<':
&& (1
|| GET_CODE (XEXP (op, 0)) == PRE_DEC
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
- return 1;
+ result = 1;
break;
case '>':
&& (1
|| GET_CODE (XEXP (op, 0)) == PRE_INC
|| GET_CODE (XEXP (op, 0)) == POST_INC))
- return 1;
+ result = 1;
break;
case 'E':
if (GET_CODE (op) == CONST_DOUBLE
|| (GET_CODE (op) == CONST_VECTOR
&& GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
- return 1;
+ result = 1;
break;
case 'G':
if (GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_OK_FOR_LETTER_P (op, 'G'))
- return 1;
+ && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'G', constraint))
+ result = 1;
break;
case 'H':
if (GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_OK_FOR_LETTER_P (op, 'H'))
- return 1;
+ && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'H', constraint))
+ result = 1;
break;
case 's':
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
#endif
)
- return 1;
+ result = 1;
break;
case 'n':
if (GET_CODE (op) == CONST_INT
|| (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode))
- return 1;
+ result = 1;
break;
case 'I':
if (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'))
- return 1;
+ && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'I', constraint))
+ result = 1;
break;
case 'J':
if (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op), 'J'))
- return 1;
+ && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'J', constraint))
+ result = 1;
break;
case 'K':
if (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op), 'K'))
- return 1;
+ && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', constraint))
+ result = 1;
break;
case 'L':
if (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'))
- return 1;
+ && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'L', constraint))
+ result = 1;
break;
case 'M':
if (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op), 'M'))
- return 1;
+ && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'M', constraint))
+ result = 1;
break;
case 'N':
if (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op), 'N'))
- return 1;
+ && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'N', constraint))
+ result = 1;
break;
case 'O':
if (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'))
- return 1;
+ && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'O', constraint))
+ result = 1;
break;
case 'P':
if (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op), 'P'))
- return 1;
+ && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'P', constraint))
+ result = 1;
break;
case 'X':
- return 1;
+ result = 1;
case 'g':
if (general_operand (op, VOIDmode))
- return 1;
+ result = 1;
break;
default:
/* For all other letters, we first check for a register class,
otherwise it is an EXTRA_CONSTRAINT. */
- if (REG_CLASS_FROM_LETTER (c) != NO_REGS)
+ if (REG_CLASS_FROM_CONSTRAINT (c, constraint) != NO_REGS)
{
case 'r':
if (GET_MODE (op) == BLKmode)
break;
if (register_operand (op, VOIDmode))
- return 1;
+ result = 1;
}
-#ifdef EXTRA_CONSTRAINT
- if (EXTRA_CONSTRAINT (op, c))
- return 1;
- if (EXTRA_MEMORY_CONSTRAINT (c))
+#ifdef EXTRA_CONSTRAINT_STR
+ if (EXTRA_CONSTRAINT_STR (op, c, constraint))
+ result = 1;
+ if (EXTRA_MEMORY_CONSTRAINT (c, constraint))
{
/* Every memory operand can be reloaded to fit. */
if (memory_operand (op, VOIDmode))
- return 1;
+ result = 1;
}
- if (EXTRA_ADDRESS_CONSTRAINT (c))
+ if (EXTRA_ADDRESS_CONSTRAINT (c, constraint))
{
/* Every address operand can be reloaded to fit. */
if (address_operand (op, VOIDmode))
- return 1;
+ result = 1;
}
#endif
break;
}
+ len = CONSTRAINT_LEN (c, constraint);
+ do
+ constraint++;
+ while (--len && *constraint);
+ if (len)
+ return 0;
}
return result;
for (;;)
{
- char c = *p++;
+ char c = *p;
if (c == '#')
do
- c = *p++;
+ c = *++p;
while (c != ',' && c != '\0');
if (c == ',' || c == '\0')
- break;
+ {
+ p++;
+ break;
+ }
switch (c)
{
case '5': case '6': case '7': case '8': case '9':
{
char *end;
- op_alt[j].matches = strtoul (p - 1, &end, 10);
+ op_alt[j].matches = strtoul (p, &end, 10);
recog_op_alt[op_alt[j].matches][j].matched = i;
p = end;
}
- break;
+ continue;
case 'm':
op_alt[j].memory_ok = 1;
break;
default:
- if (EXTRA_MEMORY_CONSTRAINT (c))
+ if (EXTRA_MEMORY_CONSTRAINT (c, p))
{
op_alt[j].memory_ok = 1;
break;
}
- if (EXTRA_ADDRESS_CONSTRAINT (c))
+ if (EXTRA_ADDRESS_CONSTRAINT (c, p))
{
op_alt[j].is_address = 1;
- op_alt[j].class = reg_class_subunion[(int) op_alt[j].class]
- [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+ op_alt[j].class
+ = (reg_class_subunion
+ [(int) op_alt[j].class]
+ [(int) MODE_BASE_REG_CLASS (VOIDmode)]);
break;
}
- op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
+ op_alt[j].class
+ = (reg_class_subunion
+ [(int) op_alt[j].class]
+ [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
break;
}
+ p += CONSTRAINT_LEN (c, p);
}
}
}
alternative of constraints was matched: 0 for the first alternative,
1 for the next, etc.
- In addition, when two operands are match
+ In addition, when two operands are required to match
and it happens that the output operand is (reg) while the
input operand is --(reg) or ++(reg) (a pre-inc or pre-dec),
make the output operand look like the input.
int offset = 0;
int win = 0;
int val;
+ int len;
earlyclobber[opno] = 0;
if (*p == 0 || *p == ',')
win = 1;
- while (*p && (c = *p++) != ',')
- switch (c)
+ do
+ switch (c = *p, len = CONSTRAINT_LEN (c, p), c)
{
+ case '\0':
+ len = 0;
+ break;
+ case ',':
+ c = '\0';
+ break;
+
case '?': case '!': case '*': case '%':
case '=': case '+':
break;
case '#':
/* Ignore rest of this alternative as far as
constraint checking is concerned. */
- while (*p && *p != ',')
+ do
p++;
+ while (*p && *p != ',');
+ len = 0;
break;
case '&':
char *end;
int match;
- match = strtoul (p - 1, &end, 10);
+ match = strtoul (p, &end, 10);
p = end;
if (strict < 0)
funny_match[funny_match_index++].other = match;
}
}
+ len = 0;
break;
case 'p':
case 'G':
case 'H':
if (GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_OK_FOR_LETTER_P (op, c))
+ && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
win = 1;
break;
case 'O':
case 'P':
if (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op), c))
+ && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
win = 1;
break;
{
enum reg_class class;
- class = (c == 'r' ? GENERAL_REGS : REG_CLASS_FROM_LETTER (c));
+ class = (c == 'r'
+ ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
if (class != NO_REGS)
{
if (strict < 0
&& reg_fits_class_p (op, class, offset, mode)))
win = 1;
}
-#ifdef EXTRA_CONSTRAINT
- else if (EXTRA_CONSTRAINT (op, c))
+#ifdef EXTRA_CONSTRAINT_STR
+ else if (EXTRA_CONSTRAINT_STR (op, c, p))
win = 1;
- if (EXTRA_MEMORY_CONSTRAINT (c))
+ if (EXTRA_MEMORY_CONSTRAINT (c, p))
{
- /* Every memory operand can be reloaded to fit,
- so copy the condition from the 'm' case. */
- if (GET_CODE (op) == MEM
- /* Before reload, accept what reload can turn into mem. */
- || (strict < 0 && CONSTANT_P (op))
- /* During reload, accept a pseudo */
- || (reload_in_progress && GET_CODE (op) == REG
- && REGNO (op) >= FIRST_PSEUDO_REGISTER))
+ /* Every memory operand can be reloaded to fit. */
+ if (strict < 0 && GET_CODE (op) == MEM)
+ win = 1;
+
+ /* Before reload, accept what reload can turn into mem. */
+ if (strict < 0 && CONSTANT_P (op))
+ win = 1;
+
+ /* During reload, accept a pseudo */
+ if (reload_in_progress && GET_CODE (op) == REG
+ && REGNO (op) >= FIRST_PSEUDO_REGISTER)
win = 1;
}
- if (EXTRA_ADDRESS_CONSTRAINT (c))
+ if (EXTRA_ADDRESS_CONSTRAINT (c, p))
{
- /* Every address operand can be reloaded to fit,
- so copy the condition from the 'p' case. */
- if (strict <= 0
- || (strict_memory_address_p (recog_data.operand_mode[opno],
- op)))
+ /* Every address operand can be reloaded to fit. */
+ if (strict < 0)
win = 1;
}
#endif
break;
}
}
+ while (p += len, c);
constraints[opno] = p;
/* If this operand did not win somehow,
int upd_life;
{
sbitmap blocks;
- int changed;
+ bool changed;
basic_block bb;
blocks = sbitmap_alloc (last_basic_block);
sbitmap_zero (blocks);
- changed = 0;
+ changed = false;
FOR_EACH_BB_REVERSE (bb)
{
while (GET_CODE (last) == BARRIER)
last = PREV_INSN (last);
SET_BIT (blocks, bb->index);
- changed = 1;
+ changed = true;
insn = last;
}
}
if (changed)
{
+ int old_last_basic_block = last_basic_block;
+
find_many_sub_basic_blocks (blocks);
+
+ if (old_last_basic_block != last_basic_block && upd_life)
+ blocks = sbitmap_resize (blocks, last_basic_block, 1);
}
if (changed && upd_life)
- {
- count_or_remove_death_notes (blocks, 1);
- update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
- }
+ update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
+ PROP_DEATH_NOTES | PROP_REG_INFO);
+
#ifdef ENABLE_CHECKING
verify_flow_info ();
#endif
}
/* Same as split_all_insns, but do not expect CFG to be available.
- Used by machine depedent reorg passes. */
+ Used by machine dependent reorg passes. */
void
split_all_insns_noflow ()
}
class = (class_str[0] == 'r' ? GENERAL_REGS
- : REG_CLASS_FROM_LETTER (class_str[0]));
+ : REG_CLASS_FROM_CONSTRAINT (class_str[0], class_str));
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{