Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC 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 version.
+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
+version.
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
/* This module is essentially the "combiner" phase of the U. of Arizona
Portable Optimizer, but redone to work on our list-structured
#include "hard-reg-set.h"
#include "basic-block.h"
#include "insn-config.h"
-#include "insn-codes.h"
#include "function.h"
/* Include expr.h after insn-config.h so we get HAVE_conditional_move. */
#include "expr.h"
rtx f;
unsigned int nregs;
{
- register rtx insn, next;
+ rtx insn, next;
#ifdef HAVE_cc0
- register rtx prev;
+ rtx prev;
#endif
- register int i;
- register rtx links, nextlinks;
+ int i;
+ rtx links, nextlinks;
int new_direct_jump_p = 0;
if (need_refresh)
{
- compute_bb_for_insn (get_max_uid ());
update_life_info (refresh_blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
PROP_DEATH_NOTES);
}
static rtx
try_combine (i3, i2, i1, new_direct_jump_p)
- register rtx i3, i2, i1;
- register int *new_direct_jump_p;
+ rtx i3, i2, i1;
+ int *new_direct_jump_p;
{
/* New patterns for I3 and I2, respectively. */
rtx newpat, newi2pat = 0;
int maxreg;
rtx temp;
- register rtx link;
+ rtx link;
int i;
/* Exit early if one of the insns involved can't be used for
}
}
+ /* If we've split a jump pattern, we'll wind up with a sequence even
+ with one instruction. We can handle that below, so extract it. */
+ if (m_split && GET_CODE (m_split) == SEQUENCE
+ && XVECLEN (m_split, 0) == 1)
+ m_split = PATTERN (XVECEXP (m_split, 0, 0));
+
if (m_split && GET_CODE (m_split) != SEQUENCE)
{
insn_code_number = recog_for_combine (&m_split, i3, &new_i3_notes);
static rtx
subst (x, from, to, in_dest, unique_copy)
- register rtx x, from, to;
+ rtx x, from, to;
int in_dest;
int unique_copy;
{
- register enum rtx_code code = GET_CODE (x);
+ enum rtx_code code = GET_CODE (x);
enum machine_mode op0_mode = VOIDmode;
- register const char *fmt;
- register int len, i;
+ const char *fmt;
+ int len, i;
rtx new;
/* Two expressions are equal if they are identical copies of a shared
{
if (fmt[i] == 'E')
{
- register int j;
+ int j;
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
{
if (COMBINE_RTX_EQUAL_P (XVECEXP (x, i, j), from))
just make the comparison operation. */
if (true_rtx == const_true_rtx && false_rtx == const0_rtx)
x = gen_binary (cond_code, mode, cond, cop1);
- else if (true_rtx == const0_rtx && false_rtx == const_true_rtx)
+ else if (true_rtx == const0_rtx && false_rtx == const_true_rtx
+ && reverse_condition (cond_code) != UNKNOWN)
x = gen_binary (reverse_condition (cond_code),
mode, cond, cop1);
/* Get the mode to use should INNER not be a MEM, the mode for the position,
and the mode for the result. */
-#ifdef HAVE_insv
- if (in_dest)
+ if (in_dest && mode_for_extraction(EP_insv, -1) != MAX_MACHINE_MODE)
{
- wanted_inner_reg_mode
- = insn_data[(int) CODE_FOR_insv].operand[0].mode;
- if (wanted_inner_reg_mode == VOIDmode)
- wanted_inner_reg_mode = word_mode;
-
- pos_mode = insn_data[(int) CODE_FOR_insv].operand[2].mode;
- if (pos_mode == VOIDmode)
- pos_mode = word_mode;
-
- extraction_mode = insn_data[(int) CODE_FOR_insv].operand[3].mode;
- if (extraction_mode == VOIDmode)
- extraction_mode = word_mode;
+ wanted_inner_reg_mode = mode_for_extraction (EP_insv, 0);
+ pos_mode = mode_for_extraction (EP_insv, 2);
+ extraction_mode = mode_for_extraction (EP_insv, 3);
}
-#endif
-#ifdef HAVE_extzv
- if (! in_dest && unsignedp)
+ if (! in_dest && unsignedp
+ && mode_for_extraction (EP_extzv, -1) != MAX_MACHINE_MODE)
{
- wanted_inner_reg_mode
- = insn_data[(int) CODE_FOR_extzv].operand[1].mode;
- if (wanted_inner_reg_mode == VOIDmode)
- wanted_inner_reg_mode = word_mode;
-
- pos_mode = insn_data[(int) CODE_FOR_extzv].operand[3].mode;
- if (pos_mode == VOIDmode)
- pos_mode = word_mode;
-
- extraction_mode = insn_data[(int) CODE_FOR_extzv].operand[0].mode;
- if (extraction_mode == VOIDmode)
- extraction_mode = word_mode;
+ wanted_inner_reg_mode = mode_for_extraction (EP_extzv, 1);
+ pos_mode = mode_for_extraction (EP_extzv, 3);
+ extraction_mode = mode_for_extraction (EP_extzv, 0);
}
-#endif
-#ifdef HAVE_extv
- if (! in_dest && ! unsignedp)
+ if (! in_dest && ! unsignedp
+ && mode_for_extraction (EP_extv, -1) != MAX_MACHINE_MODE)
{
- wanted_inner_reg_mode
- = insn_data[(int) CODE_FOR_extv].operand[1].mode;
- if (wanted_inner_reg_mode == VOIDmode)
- wanted_inner_reg_mode = word_mode;
-
- pos_mode = insn_data[(int) CODE_FOR_extv].operand[3].mode;
- if (pos_mode == VOIDmode)
- pos_mode = word_mode;
-
- extraction_mode = insn_data[(int) CODE_FOR_extv].operand[0].mode;
- if (extraction_mode == VOIDmode)
- extraction_mode = word_mode;
+ wanted_inner_reg_mode = mode_for_extraction (EP_extv, 1);
+ pos_mode = mode_for_extraction (EP_extv, 3);
+ extraction_mode = mode_for_extraction (EP_extv, 0);
}
-#endif
/* Never narrow an object, since that might not be safe. */
binop:
/* For most binary operations, just propagate into the operation and
- change the mode if we have an operation of that mode. */
+ change the mode if we have an operation of that mode. */
op0 = gen_lowpart_for_combine (op_mode,
force_to_mode (XEXP (x, 0), mode, mask,
/* If we were given an invalid count, don't do anything except exactly
what was requested. */
- if (input_count < 0 || input_count > (int) GET_MODE_BITSIZE (mode))
+ if (input_count < 0 || input_count >= (int) GET_MODE_BITSIZE (mode))
{
if (x)
return x;
rtx insn;
rtx *pnotes;
{
- register rtx pat = *pnewpat;
+ rtx pat = *pnewpat;
int insn_code_number;
int num_clobbers_to_add = 0;
int i;
static rtx
gen_lowpart_for_combine (mode, x)
enum machine_mode mode;
- register rtx x;
+ rtx x;
{
rtx result;
if (GET_CODE (x) == MEM)
{
- register int offset = 0;
+ int offset = 0;
/* Refuse to work on a volatile memory ref or one with a mode-dependent
address. */
{
if (BITS_BIG_ENDIAN)
{
-#ifdef HAVE_extzv
- mode = insn_data[(int) CODE_FOR_extzv].operand[1].mode;
- if (mode == VOIDmode)
- mode = word_mode;
- i = (GET_MODE_BITSIZE (mode) - 1 - i);
-#else
- i = BITS_PER_WORD - 1 - i;
-#endif
+ enum machine_mode new_mode
+ = mode_for_extraction (EP_extzv, 1);
+ if (new_mode == MAX_MACHINE_MODE)
+ i = BITS_PER_WORD - 1 - i;
+ else
+ {
+ mode = new_mode;
+ i = (GET_MODE_BITSIZE (mode) - 1 - i);
+ }
}
op0 = XEXP (op0, 2);
if (GET_CODE (op0) == SUBREG && subreg_lowpart_p (op0)
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
+ && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT
&& (code == NE || code == EQ)
&& ((GET_MODE_SIZE (GET_MODE (op0))
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))))))
else if (GET_CODE (op0) == SUBREG && subreg_lowpart_p (op0)
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
+ && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT
&& (code == NE || code == EQ)
&& (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
<= HOST_BITS_PER_WIDE_INT)
update_table_tick (x)
rtx x;
{
- register enum rtx_code code = GET_CODE (x);
- register const char *fmt = GET_RTX_FORMAT (code);
- register int i;
+ enum rtx_code code = GET_CODE (x);
+ const char *fmt = GET_RTX_FORMAT (code);
+ int i;
if (code == REG)
{
record_dead_and_set_regs (insn)
rtx insn;
{
- register rtx link;
+ rtx link;
unsigned int i;
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
static int
use_crosses_set_p (x, from_cuid)
- register rtx x;
+ rtx x;
int from_cuid;
{
- register const char *fmt;
- register int i;
- register enum rtx_code code = GET_CODE (x);
+ const char *fmt;
+ int i;
+ enum rtx_code code = GET_CODE (x);
if (code == REG)
{
{
if (fmt[i] == 'E')
{
- register int j;
+ int j;
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
if (use_crosses_set_p (XVECEXP (x, i, j), from_cuid))
return 1;
{
/* If setting a MEM, or a SUBREG of a MEM, then note any hard regs in
the address. */
- register rtx testreg = SET_DEST (x);
+ rtx testreg = SET_DEST (x);
while (GET_CODE (testreg) == SUBREG
|| GET_CODE (testreg) == ZERO_EXTRACT
/* Recursively scan the operands of this expression. */
{
- register const char *fmt = GET_RTX_FORMAT (code);
+ const char *fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
mark_used_regs_combine (XEXP (x, i));
else if (fmt[i] == 'E')
{
- register int j;
+ int j;
for (j = 0; j < XVECLEN (x, i); j++)
mark_used_regs_combine (XVECEXP (x, i, j));
unsigned int regno;
rtx insn;
{
- register rtx note = find_regno_note (insn, REG_DEAD, regno);
+ rtx note = find_regno_note (insn, REG_DEAD, regno);
if (note)
{
rtx to_insn;
rtx *pnotes;
{
- register const char *fmt;
- register int len, i;
- register enum rtx_code code = GET_CODE (x);
+ const char *fmt;
+ int len, i;
+ enum rtx_code code = GET_CODE (x);
if (code == REG)
{
unsigned int regno = REGNO (x);
- register rtx where_dead = reg_last_death[regno];
- register rtx before_dead, after_dead;
+ rtx where_dead = reg_last_death[regno];
+ rtx before_dead, after_dead;
/* Don't move the register if it gets killed in between from and to */
if (maybe_kill_insn && reg_set_p (x, maybe_kill_insn)
{
if (fmt[i] == 'E')
{
- register int j;
+ int j;
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
move_deaths (XVECEXP (x, i, j), maybe_kill_insn, from_cuid,
to_insn, pnotes);
place = i3;
break;
+ case REG_VTABLE_REF:
+ /* ??? Should remain with *a particular* memory load. Given the
+ nature of vtable data, the last insn seems relatively safe. */
+ place = i3;
+ break;
+
case REG_NON_LOCAL_GOTO:
if (GET_CODE (i3) == JUMP_INSN)
place = i3;