deleted and recreated from scratch. REG_DEAD is never created for a
SET_DEST, only REG_UNUSED.
- Before life analysis, the mode of each insn is set based on whether
- or not any stack registers are mentioned within that insn. VOIDmode
- means that no regs are mentioned anyway, and QImode means that at
- least one pattern within the insn mentions stack registers. This
- information is valid until after reg_to_stack returns, and is used
- from jump_optimize.
-
* asm_operands:
There are several rules on the usage of stack-like regs in
#include "insn-flags.h"
#include "recog.h"
#include "toplev.h"
+#include "varray.h"
#ifdef STACK_REGS
add insns within a block. */
static int *block_number;
+/* We use this array to cache info about insns, because otherwise we
+ spend too much time in stack_regs_mentioned_p.
+
+ Indexed by insn UIDs. A value of zero is uninitialized, one indicates
+ the insn uses stack registers, two indicates the insn does not use
+ stack registers. */
+static varray_type stack_regs_mentioned_data;
+
/* This is the register file for all register after conversion */
static rtx
FP_mode_reg[LAST_STACK_REG+1-FIRST_STACK_REG][(int) MAX_MACHINE_MODE];
static void convert_regs PROTO((void));
static void print_blocks PROTO((FILE *, rtx, rtx));
static void dump_stack_info PROTO((FILE *));
+static int check_stack_regs_mentioned PROTO((rtx insn));
+\f
+/* Initialize stack_regs_mentioned_data for INSN (growing the virtual array
+ if needed. Return nonzero if INSN mentions stacked registers. */
+
+static int
+check_stack_regs_mentioned (insn)
+ rtx insn;
+{
+ unsigned int uid = INSN_UID (insn);
+ if (uid >= VARRAY_SIZE (stack_regs_mentioned_data))
+ {
+ unsigned int size = VARRAY_SIZE (stack_regs_mentioned_data);
+
+ /* Allocate some extra size to avoid too many reallocs, but
+ do not grow exponentially. */
+ size = uid + uid / 20;
+ VARRAY_GROW (stack_regs_mentioned_data, size);
+ }
+ if (stack_regs_mentioned_p (PATTERN (insn)))
+ {
+ VARRAY_CHAR (stack_regs_mentioned_data, uid) = 1;
+ return 1;
+ }
+ else
+ VARRAY_CHAR (stack_regs_mentioned_data, uid) = 2;
+ return 0;
+}
+
+/* Return nonzero if INSN mentions stacked registers, else return
+ zero. */
+
+int
+stack_regs_mentioned (insn)
+ rtx insn;
+{
+ unsigned int uid;
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ return 0;
+ uid = INSN_UID (insn);
+ if (uid >= VARRAY_SIZE (stack_regs_mentioned_data)
+ || ! VARRAY_CHAR (stack_regs_mentioned_data, uid))
+ return (check_stack_regs_mentioned (insn));
+ return VARRAY_CHAR (stack_regs_mentioned_data, uid) == 1;
+}
+
\f
/* Mark all registers needed for this pattern. */
enum machine_mode mode;
HARD_REG_SET stackentry;
+ max_uid = get_max_uid ();
+ VARRAY_CHAR_INIT (stack_regs_mentioned_data, max_uid + 1,
+ "stack_regs_mentioned cache");
+
CLEAR_HARD_REG_SET (stackentry);
{
&& stack_regs_mentioned_p (PATTERN (insn)))
{
stack_reg_seen = 1;
- PUT_MODE (insn, QImode);
+ VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 1;
/* Note any register passing parameters. */
&stackentry, 1);
}
else
- PUT_MODE (insn, VOIDmode);
+ VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 2;
if (code == CODE_LABEL)
LABEL_REFS (insn) = insn; /* delete old chain */
anything to convert. */
if (! stack_reg_seen)
- return;
+ {
+ VARRAY_FREE (stack_regs_mentioned_data);
+ return;
+ }
/* If there are stack registers, there must be at least one block. */
if (optimize)
jump_optimize (first, 2, 0, 0);
+
+ VARRAY_FREE (stack_regs_mentioned_data);
}
\f
/* Check PAT, which is in INSN, for LABEL_REFs. Add INSN to the
malformed_asm = 1;
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
- PUT_MODE (insn, VOIDmode);
+ VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 2;
return;
}
{
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
- PUT_MODE (insn, VOIDmode);
+ VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 2;
return;
}
pat = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, DFmode),
CONST0_RTX (DFmode));
init = emit_insn_after (pat, insn);
- PUT_MODE (init, QImode);
CLEAR_HARD_REG_BIT (regstack->reg_set, reg);
everything dies. But otherwise don't process unless there
are some stack regs present. */
- if (GET_MODE (insn) == QImode || GET_CODE (insn) == CALL_INSN)
+ if (stack_regs_mentioned (insn) || GET_CODE (insn) == CALL_INSN)
record_reg_life (insn, block, ®stack);
} while (insn != block_begin[block]);
init_rtx = gen_rtx_SET (VOIDmode, FP_MODE_REG(reg, DFmode),
CONST0_RTX (DFmode));
block_begin[0] = emit_insn_after (init_rtx, first);
- PUT_MODE (block_begin[0], QImode);
CLEAR_HARD_REG_BIT (block_stack_in[0].reg_set, reg);
}
FP_MODE_REG (FIRST_STACK_REG, DFmode));
pop_insn = (*when) (pop_rtx, insn);
- /* ??? This used to be VOIDmode, but that seems wrong. */
- PUT_MODE (pop_insn, QImode);
REG_NOTES (pop_insn) = gen_rtx_EXPR_LIST (REG_DEAD,
FP_MODE_REG (FIRST_STACK_REG, DFmode),
/* Find the previous insn involving stack regs, but don't go past
any labels, calls or jumps. */
i1 = prev_nonnote_insn (insn);
- while (i1 && GET_CODE (i1) == INSN && GET_MODE (i1) != QImode)
+ while (i1 && GET_CODE (i1) == INSN && !stack_regs_mentioned (i1))
i1 = prev_nonnote_insn (i1);
if (i1)
swap_rtx = gen_swapdf (FP_MODE_REG (hard_regno, DFmode),
FP_MODE_REG (FIRST_STACK_REG, DFmode));
swap_insn = emit_insn_after (swap_rtx, i1);
- /* ??? This used to be VOIDmode, but that seems wrong. */
- PUT_MODE (swap_insn, QImode);
}
\f
/* Handle a move to or from a stack register in PAT, which is in INSN.
push_rtx = gen_movxf (top_stack_reg, top_stack_reg);
push_insn = emit_insn_before (push_rtx, insn);
- PUT_MODE (push_insn, QImode);
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, top_stack_reg,
REG_NOTES (insn));
}
we must check each pattern in a parallel here. A call_value_pop could
fail otherwise. */
- if (GET_MODE (insn) == QImode)
+ if (stack_regs_mentioned (insn))
{
int n_operands = asm_noperands (PATTERN (insn));
if (n_operands >= 0)
mentioned or if it's a CALL_INSN (register passing of
floating point values). */
- if (GET_MODE (insn) == QImode || GET_CODE (insn) == CALL_INSN)
+ if (stack_regs_mentioned (insn) || GET_CODE (insn) == CALL_INSN)
subst_stack_regs (insn, ®stack);
} while (insn != block_end[block]);