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. */
/* Middle-to-low level generation of rtx code and insns.
#include "bitmap.h"
#include "basic-block.h"
#include "ggc.h"
+#include "debug.h"
/* Commonly used modes. */
static int rtx_htab_mark_1 PARAMS ((void **, void *));
static void rtx_htab_mark PARAMS ((void *));
+/* Probability of the conditional branch currently proceeded by try_split.
+ Set to -1 otherwise. */
+int split_branch_probability = -1;
+
\f
/* Returns a hash code for X (which is a really a CONST_INT). */
/* Generate a SUBREG representing the least-significant part
* of REG if MODE is smaller than mode of REG, otherwise
- * paradoxical SUBREG. */
+ * paradoxical SUBREG. */
rtx
gen_lowpart_SUBREG (mode, reg)
enum machine_mode mode;
rtx
gen_rtx VPARAMS ((enum rtx_code code, enum machine_mode mode, ...))
{
-#ifndef ANSI_PROTOTYPES
- enum rtx_code code;
- enum machine_mode mode;
-#endif
- va_list p;
register int i; /* Array indices... */
register const char *fmt; /* Current rtx's format... */
register rtx rt_val; /* RTX to return to caller... */
- VA_START (p, mode);
-
-#ifndef ANSI_PROTOTYPES
- code = va_arg (p, enum rtx_code);
- mode = va_arg (p, enum machine_mode);
-#endif
+ VA_OPEN (p, mode);
+ VA_FIXEDARG (p, enum rtx_code, code);
+ VA_FIXEDARG (p, enum machine_mode, mode);
switch (code)
{
break;
}
- va_end (p);
+ VA_CLOSE (p);
return rt_val;
}
rtvec
gen_rtvec VPARAMS ((int n, ...))
{
-#ifndef ANSI_PROTOTYPES
- int n;
-#endif
- int i;
- va_list p;
+ int i, save_n;
rtx *vector;
- VA_START (p, n);
-
-#ifndef ANSI_PROTOTYPES
- n = va_arg (p, int);
-#endif
+ VA_OPEN (p, n);
+ VA_FIXEDARG (p, int, n);
if (n == 0)
return NULL_RTVEC; /* Don't allocate an empty rtvec... */
for (i = 0; i < n; i++)
vector[i] = va_arg (p, rtx);
- va_end (p);
- return gen_rtvec_v (n, vector);
+ /* The definition of VA_* in K&R C causes `n' to go out of scope. */
+ save_n = n;
+ VA_CLOSE (p);
+
+ return gen_rtvec_v (save_n, vector);
}
rtvec
if (mode == VOIDmode)
abort ();
- /* If OP is narrower than a word, fail. */
+ /* If OP is narrower than a word, fail. */
if (mode != BLKmode
&& (GET_MODE_SIZE (mode) < UNITS_PER_WORD))
return 0;
- /* If we want a word outside OP, return zero. */
+ /* If we want a word outside OP, return zero. */
if (mode != BLKmode
&& (offset + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
return const0_rtx;
will do memref tracking. */
rtx addr = XEXP (memref, 0);
+ /* ??? Prefer to create garbage instead of creating shared rtl. */
+ addr = copy_rtx (addr);
+
/* If MEMREF is a LO_SUM and the offset is within the alignment of the
object, we can merge it into the LO_SUM. */
if (GET_MODE (memref) != BLKmode && GET_CODE (addr) == LO_SUM
&& offset >= 0
- && offset < GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT)
+ && (unsigned HOST_WIDE_INT) offset
+ < GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT)
addr = gen_rtx_LO_SUM (mode, XEXP (addr, 0),
plus_constant (XEXP (addr, 1), offset));
else
object, we can merge it into the LO_SUM. */
if (GET_MODE (memref) != BLKmode && GET_CODE (addr) == LO_SUM
&& offset >= 0
- && offset < GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT)
+ && (unsigned HOST_WIDE_INT) offset
+ < GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT)
addr = gen_rtx_LO_SUM (mode, XEXP (addr, 0),
plus_constant (XEXP (addr, 1), offset));
else
}
/* Go through all virtual stack slots of a function and mark them as
- not shared. */
+ not shared. */
static void
reset_used_decls (blk)
tree blk;
{
rtx before = PREV_INSN (trial);
rtx after = NEXT_INSN (trial);
- rtx seq = split_insns (pat, trial);
int has_barrier = 0;
rtx tem;
+ rtx note, seq;
+ int probability;
+
+ if (any_condjump_p (trial)
+ && (note = find_reg_note (trial, REG_BR_PROB, 0)))
+ split_branch_probability = INTVAL (XEXP (note, 0));
+ probability = split_branch_probability;
+
+ seq = split_insns (pat, trial);
+
+ split_branch_probability = -1;
/* If we are splitting a JUMP_INSN, it might be followed by a BARRIER.
We may need to handle this specially. */
it, in turn, will be split (SFmode on the 29k is an example). */
if (GET_CODE (seq) == SEQUENCE)
{
- int i;
+ int i, njumps = 0;
rtx eh_note;
/* Avoid infinite loop if any insn of the result matches
/* Mark labels. */
for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
if (GET_CODE (XVECEXP (seq, 0, i)) == JUMP_INSN)
- mark_jump_label (PATTERN (XVECEXP (seq, 0, i)),
- XVECEXP (seq, 0, i), 0);
-
+ {
+ rtx insn = XVECEXP (seq, 0, i);
+ mark_jump_label (PATTERN (insn),
+ XVECEXP (seq, 0, i), 0);
+ njumps++;
+ if (probability != -1
+ && any_condjump_p (insn)
+ && !find_reg_note (insn, REG_BR_PROB, 0))
+ {
+ /* We can preserve the REG_BR_PROB notes only if exactly
+ one jump is created, otherwise the machinde description
+ is responsible for this step using
+ split_branch_probability variable. */
+ if (njumps != 1)
+ abort ();
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_BR_PROB,
+ GEN_INT (probability),
+ REG_NOTES (insn));
+ }
+ }
/* If we are splitting a CALL_INSN, look for the CALL_INSN
in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it. */
if (GET_CODE (trial) == CALL_INSN)
/* Return either the first or the last insn, depending on which was
requested. */
return last
- ? (after ? prev_active_insn (after) : last_insn)
- : next_active_insn (before);
+ ? (after ? PREV_INSN (after) : last_insn)
+ : NEXT_INSN (before);
}
return trial;
if (NOTE_LINE_NUMBER (tmp) == NOTE_INSN_BLOCK_BEG)
{
- /* We just verified that this BLOCK matches us
- with the block_stack check above. */
- if (debug_ignore_block (NOTE_BLOCK (insn)))
+ /* We just verified that this BLOCK matches us with
+ the block_stack check above. Never delete the
+ BLOCK for the outermost scope of the function; we
+ can refer to names from that scope even if the
+ block notes are messed up. */
+ if (! is_body_block (NOTE_BLOCK (insn))
+ && (*debug_hooks->ignore_block) (NOTE_BLOCK (insn)))
{
remove_insn (tmp);
remove_insn (insn);
}
/* Place a note of KIND on insn INSN with DATUM as the datum. If a
- note of this type already exists, remove it first. */
+ note of this type already exists, remove it first. */
void
set_unique_reg_note (insn, kind, datum)
if (len == 1
&& ! RTX_FRAME_RELATED_P (first_insn)
&& GET_CODE (first_insn) == INSN
- /* Don't throw away any reg notes. */
+ /* Don't throw away any reg notes. */
&& REG_NOTES (first_insn) == 0)
return PATTERN (first_insn);