/* Emit RTL for the GCC expander.
- Copyright (C) 1987-2014 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "tm.h"
#include "diagnostic-core.h"
#include "rtl.h"
+#include "alias.h"
+#include "symtab.h"
#include "tree.h"
+#include "fold-const.h"
#include "varasm.h"
+#include "predict.h"
+#include "hard-reg-set.h"
+#include "function.h"
+#include "cfgrtl.h"
#include "basic-block.h"
#include "tree-eh.h"
#include "tm_p.h"
#include "flags.h"
-#include "function.h"
#include "stringpool.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "stmt.h"
#include "expr.h"
#include "regs.h"
-#include "hard-reg-set.h"
-#include "hashtab.h"
-#include "insn-config.h"
#include "recog.h"
#include "bitmap.h"
#include "debug.h"
#include "params.h"
#include "target.h"
#include "builtins.h"
+#include "rtl-iter.h"
struct target_rtl default_target_rtl;
#if SWITCHABLE_TARGET
/* Commonly used modes. */
-enum machine_mode byte_mode; /* Mode whose width is BITS_PER_UNIT. */
-enum machine_mode word_mode; /* Mode whose width is BITS_PER_WORD. */
-enum machine_mode double_mode; /* Mode whose width is DOUBLE_TYPE_SIZE. */
-enum machine_mode ptr_mode; /* Mode whose width is POINTER_SIZE. */
+machine_mode byte_mode; /* Mode whose width is BITS_PER_UNIT. */
+machine_mode word_mode; /* Mode whose width is BITS_PER_WORD. */
+machine_mode double_mode; /* Mode whose width is DOUBLE_TYPE_SIZE. */
+machine_mode ptr_mode; /* Mode whose width is POINTER_SIZE. */
/* Datastructures maintained for currently processed function in RTL form. */
rtx simple_return_rtx;
rtx cc0_rtx;
+/* Marker used for denoting an INSN, which should never be accessed (i.e.,
+ this pointer should normally never be dereferenced), but is required to be
+ distinct from NULL_RTX. Currently used by peephole2 pass. */
+rtx_insn *invalid_insn_rtx;
+
/* A hash table storing CONST_INTs whose absolute value is greater
than MAX_SAVED_CONST_INT. */
-static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
- htab_t const_int_htab;
+struct const_int_hasher : ggc_cache_ptr_hash<rtx_def>
+{
+ typedef HOST_WIDE_INT compare_type;
+
+ static hashval_t hash (rtx i);
+ static bool equal (rtx i, HOST_WIDE_INT h);
+};
+
+static GTY ((cache)) hash_table<const_int_hasher> *const_int_htab;
+
+struct const_wide_int_hasher : ggc_cache_ptr_hash<rtx_def>
+{
+ static hashval_t hash (rtx x);
+ static bool equal (rtx x, rtx y);
+};
-static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
- htab_t const_wide_int_htab;
+static GTY ((cache)) hash_table<const_wide_int_hasher> *const_wide_int_htab;
/* A hash table storing register attribute structures. */
-static GTY ((if_marked ("ggc_marked_p"), param_is (struct reg_attrs)))
- htab_t reg_attrs_htab;
+struct reg_attr_hasher : ggc_cache_ptr_hash<reg_attrs>
+{
+ static hashval_t hash (reg_attrs *x);
+ static bool equal (reg_attrs *a, reg_attrs *b);
+};
+
+static GTY ((cache)) hash_table<reg_attr_hasher> *reg_attrs_htab;
/* A hash table storing all CONST_DOUBLEs. */
-static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
- htab_t const_double_htab;
+struct const_double_hasher : ggc_cache_ptr_hash<rtx_def>
+{
+ static hashval_t hash (rtx x);
+ static bool equal (rtx x, rtx y);
+};
+
+static GTY ((cache)) hash_table<const_double_hasher> *const_double_htab;
/* A hash table storing all CONST_FIXEDs. */
-static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
- htab_t const_fixed_htab;
+struct const_fixed_hasher : ggc_cache_ptr_hash<rtx_def>
+{
+ static hashval_t hash (rtx x);
+ static bool equal (rtx x, rtx y);
+};
+
+static GTY ((cache)) hash_table<const_fixed_hasher> *const_fixed_htab;
#define cur_insn_uid (crtl->emit.x_cur_insn_uid)
#define cur_debug_insn_uid (crtl->emit.x_cur_debug_insn_uid)
static void set_used_decls (tree);
static void mark_label_nuses (rtx);
-static hashval_t const_int_htab_hash (const void *);
-static int const_int_htab_eq (const void *, const void *);
#if TARGET_SUPPORTS_WIDE_INT
-static hashval_t const_wide_int_htab_hash (const void *);
-static int const_wide_int_htab_eq (const void *, const void *);
static rtx lookup_const_wide_int (rtx);
#endif
-static hashval_t const_double_htab_hash (const void *);
-static int const_double_htab_eq (const void *, const void *);
static rtx lookup_const_double (rtx);
-static hashval_t const_fixed_htab_hash (const void *);
-static int const_fixed_htab_eq (const void *, const void *);
static rtx lookup_const_fixed (rtx);
-static hashval_t reg_attrs_htab_hash (const void *);
-static int reg_attrs_htab_eq (const void *, const void *);
static reg_attrs *get_reg_attrs (tree, int);
-static rtx gen_const_vector (enum machine_mode, int);
+static rtx gen_const_vector (machine_mode, int);
static void copy_rtx_if_shared_1 (rtx *orig);
/* Probability of the conditional branch currently proceeded by try_split.
\f
/* Returns a hash code for X (which is a really a CONST_INT). */
-static hashval_t
-const_int_htab_hash (const void *x)
+hashval_t
+const_int_hasher::hash (rtx x)
{
- return (hashval_t) INTVAL ((const_rtx) x);
+ return (hashval_t) INTVAL (x);
}
/* Returns nonzero if the value represented by X (which is really a
CONST_INT) is the same as that given by Y (which is really a
HOST_WIDE_INT *). */
-static int
-const_int_htab_eq (const void *x, const void *y)
+bool
+const_int_hasher::equal (rtx x, HOST_WIDE_INT y)
{
- return (INTVAL ((const_rtx) x) == *((const HOST_WIDE_INT *) y));
+ return (INTVAL (x) == y);
}
#if TARGET_SUPPORTS_WIDE_INT
/* Returns a hash code for X (which is a really a CONST_WIDE_INT). */
-static hashval_t
-const_wide_int_htab_hash (const void *x)
+hashval_t
+const_wide_int_hasher::hash (rtx x)
{
int i;
- HOST_WIDE_INT hash = 0;
- const_rtx xr = (const_rtx) x;
+ unsigned HOST_WIDE_INT hash = 0;
+ const_rtx xr = x;
for (i = 0; i < CONST_WIDE_INT_NUNITS (xr); i++)
hash += CONST_WIDE_INT_ELT (xr, i);
CONST_WIDE_INT) is the same as that given by Y (which is really a
CONST_WIDE_INT). */
-static int
-const_wide_int_htab_eq (const void *x, const void *y)
+bool
+const_wide_int_hasher::equal (rtx x, rtx y)
{
int i;
- const_rtx xr = (const_rtx) x;
- const_rtx yr = (const_rtx) y;
+ const_rtx xr = x;
+ const_rtx yr = y;
if (CONST_WIDE_INT_NUNITS (xr) != CONST_WIDE_INT_NUNITS (yr))
- return 0;
+ return false;
for (i = 0; i < CONST_WIDE_INT_NUNITS (xr); i++)
if (CONST_WIDE_INT_ELT (xr, i) != CONST_WIDE_INT_ELT (yr, i))
- return 0;
+ return false;
- return 1;
+ return true;
}
#endif
/* Returns a hash code for X (which is really a CONST_DOUBLE). */
-static hashval_t
-const_double_htab_hash (const void *x)
+hashval_t
+const_double_hasher::hash (rtx x)
{
- const_rtx const value = (const_rtx) x;
+ const_rtx const value = x;
hashval_t h;
if (TARGET_SUPPORTS_WIDE_INT == 0 && GET_MODE (value) == VOIDmode)
/* Returns nonzero if the value represented by X (really a ...)
is the same as that represented by Y (really a ...) */
-static int
-const_double_htab_eq (const void *x, const void *y)
+bool
+const_double_hasher::equal (rtx x, rtx y)
{
- const_rtx const a = (const_rtx)x, b = (const_rtx)y;
+ const_rtx const a = x, b = y;
if (GET_MODE (a) != GET_MODE (b))
return 0;
/* Returns a hash code for X (which is really a CONST_FIXED). */
-static hashval_t
-const_fixed_htab_hash (const void *x)
+hashval_t
+const_fixed_hasher::hash (rtx x)
{
- const_rtx const value = (const_rtx) x;
+ const_rtx const value = x;
hashval_t h;
h = fixed_hash (CONST_FIXED_VALUE (value));
return h;
}
-/* Returns nonzero if the value represented by X (really a ...)
- is the same as that represented by Y (really a ...). */
+/* Returns nonzero if the value represented by X is the same as that
+ represented by Y. */
-static int
-const_fixed_htab_eq (const void *x, const void *y)
+bool
+const_fixed_hasher::equal (rtx x, rtx y)
{
- const_rtx const a = (const_rtx) x, b = (const_rtx) y;
+ const_rtx const a = x, b = y;
if (GET_MODE (a) != GET_MODE (b))
return 0;
/* Return true if the given memory attributes are equal. */
-static bool
+bool
mem_attrs_eq_p (const struct mem_attrs *p, const struct mem_attrs *q)
{
+ if (p == q)
+ return true;
+ if (!p || !q)
+ return false;
return (p->alias == q->alias
&& p->offset_known_p == q->offset_known_p
&& (!p->offset_known_p || p->offset == q->offset)
/* Returns a hash code for X (which is a really a reg_attrs *). */
-static hashval_t
-reg_attrs_htab_hash (const void *x)
+hashval_t
+reg_attr_hasher::hash (reg_attrs *x)
{
- const reg_attrs *const p = (const reg_attrs *) x;
+ const reg_attrs *const p = x;
return ((p->offset * 1000) ^ (intptr_t) p->decl);
}
-/* Returns nonzero if the value represented by X (which is really a
- reg_attrs *) is the same as that given by Y (which is also really a
- reg_attrs *). */
+/* Returns nonzero if the value represented by X is the same as that given by
+ Y. */
-static int
-reg_attrs_htab_eq (const void *x, const void *y)
+bool
+reg_attr_hasher::equal (reg_attrs *x, reg_attrs *y)
{
- const reg_attrs *const p = (const reg_attrs *) x;
- const reg_attrs *const q = (const reg_attrs *) y;
+ const reg_attrs *const p = x;
+ const reg_attrs *const q = y;
return (p->decl == q->decl && p->offset == q->offset);
}
get_reg_attrs (tree decl, int offset)
{
reg_attrs attrs;
- void **slot;
/* If everything is the default, we can just return zero. */
if (decl == 0 && offset == 0)
attrs.decl = decl;
attrs.offset = offset;
- slot = htab_find_slot (reg_attrs_htab, &attrs, INSERT);
+ reg_attrs **slot = reg_attrs_htab->find_slot (&attrs, INSERT);
if (*slot == 0)
{
*slot = ggc_alloc<reg_attrs> ();
memcpy (*slot, &attrs, sizeof (reg_attrs));
}
- return (reg_attrs *) *slot;
+ return *slot;
}
#endif
+/* Set the mode and register number of X to MODE and REGNO. */
+
+void
+set_mode_and_regno (rtx x, machine_mode mode, unsigned int regno)
+{
+ unsigned int nregs = (HARD_REGISTER_NUM_P (regno)
+ ? hard_regno_nregs[regno][mode]
+ : 1);
+ PUT_MODE_RAW (x, mode);
+ set_regno_raw (x, regno, nregs);
+}
+
/* Generate a new REG rtx. Make sure ORIGINAL_REGNO is set properly, and
don't attempt to share with the various global pieces of rtl (such as
frame_pointer_rtx). */
rtx
-gen_raw_REG (enum machine_mode mode, int regno)
+gen_raw_REG (machine_mode mode, unsigned int regno)
{
- rtx x = gen_rtx_raw_REG (mode, regno);
+ rtx x = rtx_alloc_stat (REG MEM_STAT_INFO);
+ set_mode_and_regno (x, mode, regno);
+ REG_ATTRS (x) = NULL;
ORIGINAL_REGNO (x) = regno;
return x;
}
functions do the raw handling. If you add to this list, modify
special_rtx in gengenrtl.c as well. */
-rtx
-gen_rtx_CONST_INT (enum machine_mode mode ATTRIBUTE_UNUSED, HOST_WIDE_INT arg)
+rtx_expr_list *
+gen_rtx_EXPR_LIST (machine_mode mode, rtx expr, rtx expr_list)
+{
+ return as_a <rtx_expr_list *> (gen_rtx_fmt_ee (EXPR_LIST, mode, expr,
+ expr_list));
+}
+
+rtx_insn_list *
+gen_rtx_INSN_LIST (machine_mode mode, rtx insn, rtx insn_list)
{
- void **slot;
+ return as_a <rtx_insn_list *> (gen_rtx_fmt_ue (INSN_LIST, mode, insn,
+ insn_list));
+}
+
+rtx_insn *
+gen_rtx_INSN (machine_mode mode, rtx_insn *prev_insn, rtx_insn *next_insn,
+ basic_block bb, rtx pattern, int location, int code,
+ rtx reg_notes)
+{
+ return as_a <rtx_insn *> (gen_rtx_fmt_uuBeiie (INSN, mode,
+ prev_insn, next_insn,
+ bb, pattern, location, code,
+ reg_notes));
+}
+rtx
+gen_rtx_CONST_INT (machine_mode mode ATTRIBUTE_UNUSED, HOST_WIDE_INT arg)
+{
if (arg >= - MAX_SAVED_CONST_INT && arg <= MAX_SAVED_CONST_INT)
return const_int_rtx[arg + MAX_SAVED_CONST_INT];
#endif
/* Look up the CONST_INT in the hash table. */
- slot = htab_find_slot_with_hash (const_int_htab, &arg,
- (hashval_t) arg, INSERT);
+ rtx *slot = const_int_htab->find_slot_with_hash (arg, (hashval_t) arg,
+ INSERT);
if (*slot == 0)
*slot = gen_rtx_raw_CONST_INT (VOIDmode, arg);
- return (rtx) *slot;
+ return *slot;
}
rtx
-gen_int_mode (HOST_WIDE_INT c, enum machine_mode mode)
+gen_int_mode (HOST_WIDE_INT c, machine_mode mode)
{
return GEN_INT (trunc_int_for_mode (c, mode));
}
static rtx
lookup_const_double (rtx real)
{
- void **slot = htab_find_slot (const_double_htab, real, INSERT);
+ rtx *slot = const_double_htab->find_slot (real, INSERT);
if (*slot == 0)
*slot = real;
- return (rtx) *slot;
+ return *slot;
}
/* Return a CONST_DOUBLE rtx for a floating-point value specified by
VALUE in mode MODE. */
rtx
-const_double_from_real_value (REAL_VALUE_TYPE value, enum machine_mode mode)
+const_double_from_real_value (REAL_VALUE_TYPE value, machine_mode mode)
{
rtx real = rtx_alloc (CONST_DOUBLE);
PUT_MODE (real, mode);
static rtx
lookup_const_fixed (rtx fixed)
{
- void **slot = htab_find_slot (const_fixed_htab, fixed, INSERT);
+ rtx *slot = const_fixed_htab->find_slot (fixed, INSERT);
if (*slot == 0)
*slot = fixed;
- return (rtx) *slot;
+ return *slot;
}
/* Return a CONST_FIXED rtx for a fixed-point value specified by
VALUE in mode MODE. */
rtx
-const_fixed_from_fixed_value (FIXED_VALUE_TYPE value, enum machine_mode mode)
+const_fixed_from_fixed_value (FIXED_VALUE_TYPE value, machine_mode mode)
{
rtx fixed = rtx_alloc (CONST_FIXED);
PUT_MODE (fixed, mode);
static rtx
lookup_const_wide_int (rtx wint)
{
- void **slot = htab_find_slot (const_wide_int_htab, wint, INSERT);
+ rtx *slot = const_wide_int_htab->find_slot (wint, INSERT);
if (*slot == 0)
*slot = wint;
- return (rtx) *slot;
+ return *slot;
}
#endif
(if TARGET_SUPPORTS_WIDE_INT). */
rtx
-immed_wide_int_const (const wide_int_ref &v, enum machine_mode mode)
+immed_wide_int_const (const wide_int_ref &v, machine_mode mode)
{
unsigned int len = v.get_len ();
unsigned int prec = GET_MODE_PRECISION (mode);
CONST_DOUBLE_FROM_REAL_VALUE. */
rtx
-immed_double_const (HOST_WIDE_INT i0, HOST_WIDE_INT i1, enum machine_mode mode)
+immed_double_const (HOST_WIDE_INT i0, HOST_WIDE_INT i1, machine_mode mode)
{
rtx value;
unsigned int i;
|| GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
/* We can get a 0 for an error mark. */
|| GET_MODE_CLASS (mode) == MODE_VECTOR_INT
- || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT);
+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
+ || GET_MODE_CLASS (mode) == MODE_POINTER_BOUNDS);
if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
return gen_int_mode (i0, mode);
#endif
rtx
-gen_rtx_REG (enum machine_mode mode, unsigned int regno)
+gen_rtx_REG (machine_mode mode, unsigned int regno)
{
/* In case the MD file explicitly references the frame pointer, have
all such references point to the same frame pointer. This is
if (regno == FRAME_POINTER_REGNUM
&& (!reload_completed || frame_pointer_needed))
return frame_pointer_rtx;
-#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
- if (regno == HARD_FRAME_POINTER_REGNUM
+
+ if (!HARD_FRAME_POINTER_IS_FRAME_POINTER
+ && regno == HARD_FRAME_POINTER_REGNUM
&& (!reload_completed || frame_pointer_needed))
return hard_frame_pointer_rtx;
-#endif
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM && !HARD_FRAME_POINTER_IS_ARG_POINTER
- if (regno == ARG_POINTER_REGNUM)
+#if !HARD_FRAME_POINTER_IS_ARG_POINTER
+ if (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+ && regno == ARG_POINTER_REGNUM)
return arg_pointer_rtx;
#endif
#ifdef RETURN_ADDRESS_POINTER_REGNUM
}
rtx
-gen_rtx_MEM (enum machine_mode mode, rtx addr)
+gen_rtx_MEM (machine_mode mode, rtx addr)
{
rtx rt = gen_rtx_raw_MEM (mode, addr);
/* Generate a memory referring to non-trapping constant memory. */
rtx
-gen_const_mem (enum machine_mode mode, rtx addr)
+gen_const_mem (machine_mode mode, rtx addr)
{
rtx mem = gen_rtx_MEM (mode, addr);
MEM_READONLY_P (mem) = 1;
save areas. */
rtx
-gen_frame_mem (enum machine_mode mode, rtx addr)
+gen_frame_mem (machine_mode mode, rtx addr)
{
rtx mem = gen_rtx_MEM (mode, addr);
MEM_NOTRAP_P (mem) = 1;
of the fixed stack frame. For example, something which is pushed
by a target splitter. */
rtx
-gen_tmp_stack_mem (enum machine_mode mode, rtx addr)
+gen_tmp_stack_mem (machine_mode mode, rtx addr)
{
rtx mem = gen_rtx_MEM (mode, addr);
MEM_NOTRAP_P (mem) = 1;
this construct would be valid, and false otherwise. */
bool
-validate_subreg (enum machine_mode omode, enum machine_mode imode,
+validate_subreg (machine_mode omode, machine_mode imode,
const_rtx reg, unsigned int offset)
{
unsigned int isize = GET_MODE_SIZE (imode);
if (osize < UNITS_PER_WORD
&& ! (lra_in_progress && (FLOAT_MODE_P (imode) || FLOAT_MODE_P (omode))))
{
- enum machine_mode wmode = isize > UNITS_PER_WORD ? word_mode : imode;
+ machine_mode wmode = isize > UNITS_PER_WORD ? word_mode : imode;
unsigned int low_off = subreg_lowpart_offset (omode, wmode);
if (offset % UNITS_PER_WORD != low_off)
return false;
}
rtx
-gen_rtx_SUBREG (enum machine_mode mode, rtx reg, int offset)
+gen_rtx_SUBREG (machine_mode mode, rtx reg, int offset)
{
gcc_assert (validate_subreg (mode, GET_MODE (reg), reg, offset));
return gen_rtx_raw_SUBREG (mode, reg, offset);
is smaller than mode of REG, otherwise paradoxical SUBREG. */
rtx
-gen_lowpart_SUBREG (enum machine_mode mode, rtx reg)
+gen_lowpart_SUBREG (machine_mode mode, rtx reg)
{
- enum machine_mode inmode;
+ machine_mode inmode;
inmode = GET_MODE (reg);
if (inmode == VOIDmode)
}
rtx
-gen_rtx_VAR_LOCATION (enum machine_mode mode, tree decl, rtx loc,
+gen_rtx_VAR_LOCATION (machine_mode mode, tree decl, rtx loc,
enum var_init_status status)
{
rtx x = gen_rtx_fmt_te (VAR_LOCATION, mode, decl, loc);
return rt_val;
}
+
+rtvec
+gen_rtvec_v (int n, rtx_insn **argp)
+{
+ int i;
+ rtvec rt_val;
+
+ /* Don't allocate an empty rtvec... */
+ if (n == 0)
+ return NULL_RTVEC;
+
+ rt_val = rtvec_alloc (n);
+
+ for (i = 0; i < n; i++)
+ rt_val->elem[i] = *argp++;
+
+ return rt_val;
+}
+
\f
/* Return the number of bytes between the start of an OUTER_MODE
in-memory value and the start of an INNER_MODE in-memory value,
on big-endian targets. */
int
-byte_lowpart_offset (enum machine_mode outer_mode,
- enum machine_mode inner_mode)
+byte_lowpart_offset (machine_mode outer_mode,
+ machine_mode inner_mode)
{
if (GET_MODE_SIZE (outer_mode) < GET_MODE_SIZE (inner_mode))
return subreg_lowpart_offset (outer_mode, inner_mode);
This pseudo is assigned the next sequential register number. */
rtx
-gen_reg_rtx (enum machine_mode mode)
+gen_reg_rtx (machine_mode mode)
{
rtx val;
unsigned int align = GET_MODE_ALIGNMENT (mode);
which makes much better code. Besides, allocating DCmode
pseudos overstrains reload on some machines like the 386. */
rtx realpart, imagpart;
- enum machine_mode partmode = GET_MODE_INNER (mode);
+ machine_mode partmode = GET_MODE_INNER (mode);
realpart = gen_reg_rtx (partmode);
imagpart = gen_reg_rtx (partmode);
added to the REG_OFFSET. */
rtx
-gen_rtx_REG_offset (rtx reg, enum machine_mode mode, unsigned int regno,
+gen_rtx_REG_offset (rtx reg, machine_mode mode, unsigned int regno,
int offset)
{
rtx new_rtx = gen_rtx_REG (mode, regno);
with OFFSET added to the REG_OFFSET. */
rtx
-gen_reg_rtx_offset (rtx reg, enum machine_mode mode, int offset)
+gen_reg_rtx_offset (rtx reg, machine_mode mode, int offset)
{
rtx new_rtx = gen_reg_rtx (mode);
new register is a (possibly paradoxical) lowpart of the old one. */
void
-adjust_reg_mode (rtx reg, enum machine_mode mode)
+adjust_reg_mode (rtx reg, machine_mode mode)
{
update_reg_offset (reg, reg, byte_lowpart_offset (mode, GET_MODE (reg)));
PUT_MODE (reg, mode);
If this is not a case we can handle, return 0. */
rtx
-gen_lowpart_common (enum machine_mode mode, rtx x)
+gen_lowpart_common (machine_mode mode, rtx x)
{
int msize = GET_MODE_SIZE (mode);
int xsize;
int offset = 0;
- enum machine_mode innermode;
+ machine_mode innermode;
/* Unfortunately, this routine doesn't take a parameter for the mode of X,
so we have to make one up. Yuk. */
}
\f
rtx
-gen_highpart (enum machine_mode mode, rtx x)
+gen_highpart (machine_mode mode, rtx x)
{
unsigned int msize = GET_MODE_SIZE (mode);
rtx result;
/* Like gen_highpart, but accept mode of EXP operand in case EXP can
be VOIDmode constant. */
rtx
-gen_highpart_mode (enum machine_mode outermode, enum machine_mode innermode, rtx exp)
+gen_highpart_mode (machine_mode outermode, machine_mode innermode, rtx exp)
{
if (GET_MODE (exp) != VOIDmode)
{
/* Return the SUBREG_BYTE for an OUTERMODE lowpart of an INNERMODE value. */
unsigned int
-subreg_lowpart_offset (enum machine_mode outermode, enum machine_mode innermode)
+subreg_lowpart_offset (machine_mode outermode, machine_mode innermode)
{
unsigned int offset = 0;
int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode));
/* Return offset in bytes to get OUTERMODE high part
of the value in mode INNERMODE stored in memory in target format. */
unsigned int
-subreg_highpart_offset (enum machine_mode outermode, enum machine_mode innermode)
+subreg_highpart_offset (machine_mode outermode, machine_mode innermode)
{
unsigned int offset = 0;
int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode));
*/
rtx
-operand_subword (rtx op, unsigned int offset, int validate_address, enum machine_mode mode)
+operand_subword (rtx op, unsigned int offset, int validate_address, machine_mode mode)
{
if (mode == VOIDmode)
mode = GET_MODE (op);
MODE is the mode of OP, in case it is CONST_INT. */
rtx
-operand_subword_force (rtx op, unsigned int offset, enum machine_mode mode)
+operand_subword_force (rtx op, unsigned int offset, machine_mode mode)
{
rtx result = operand_subword (op, offset, 1, mode);
The memory attributes are not changed. */
static rtx
-change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate,
+change_address_1 (rtx memref, machine_mode mode, rtx addr, int validate,
bool inplace)
{
addr_space_t as;
way we are changing MEMREF, so we only preserve the alias set. */
rtx
-change_address (rtx memref, enum machine_mode mode, rtx addr)
+change_address (rtx memref, machine_mode mode, rtx addr)
{
rtx new_rtx = change_address_1 (memref, mode, addr, 1, false);
- enum machine_mode mmode = GET_MODE (new_rtx);
+ machine_mode mmode = GET_MODE (new_rtx);
struct mem_attrs attrs, *defattrs;
attrs = *get_mem_attrs (memref);
has no inherent size. */
rtx
-adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset,
+adjust_address_1 (rtx memref, machine_mode mode, HOST_WIDE_INT offset,
int validate, int adjust_address, int adjust_object,
HOST_WIDE_INT size)
{
rtx addr = XEXP (memref, 0);
rtx new_rtx;
- enum machine_mode address_mode;
+ machine_mode address_mode;
int pbits;
struct mem_attrs attrs = *get_mem_attrs (memref), *defattrs;
unsigned HOST_WIDE_INT max_align;
#ifdef POINTERS_EXTEND_UNSIGNED
- enum machine_mode pointer_mode
+ machine_mode pointer_mode
= targetm.addr_space.pointer_mode (attrs.addrspace);
#endif
nonzero, the memory address is forced to be valid. */
rtx
-adjust_automodify_address_1 (rtx memref, enum machine_mode mode, rtx addr,
+adjust_automodify_address_1 (rtx memref, machine_mode mode, rtx addr,
HOST_WIDE_INT offset, int validate)
{
memref = change_address_1 (memref, VOIDmode, addr, validate, false);
offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2)
{
rtx new_rtx, addr = XEXP (memref, 0);
- enum machine_mode address_mode;
+ machine_mode address_mode;
struct mem_attrs attrs, *defattrs;
attrs = *get_mem_attrs (memref);
operations plus masking logic. */
rtx
-widen_memory_access (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset)
+widen_memory_access (rtx memref, machine_mode mode, HOST_WIDE_INT offset)
{
rtx new_rtx = adjust_address_1 (memref, mode, offset, 1, 1, 0, 0);
struct mem_attrs attrs;
\f
/* Return a newly created CODE_LABEL rtx with a unique label number. */
-rtx
+rtx_code_label *
gen_label_rtx (void)
{
- return gen_rtx_CODE_LABEL (VOIDmode, NULL_RTX, NULL_RTX,
- NULL, label_num++, NULL);
+ return as_a <rtx_code_label *> (
+ gen_rtx_CODE_LABEL (VOIDmode, NULL_RTX, NULL_RTX,
+ NULL, label_num++, NULL));
}
\f
/* For procedure integration. */
Used for an inline-procedure after copying the insn chain. */
void
-set_new_first_and_last_insn (rtx first, rtx last)
+set_new_first_and_last_insn (rtx_insn *first, rtx_insn *last)
{
- rtx insn;
+ rtx_insn *insn;
set_first_insn (first);
set_last_insn (last);
structure. This routine should only be called once. */
static void
-unshare_all_rtl_1 (rtx insn)
+unshare_all_rtl_1 (rtx_insn *insn)
{
/* Unshare just about everything else. */
unshare_all_rtl_in_chain (insn);
This special care is necessary when the stack slot MEM does not
actually appear in the insn chain. If it does appear, its address
is unshared from all else at that point. */
- stack_slot_list = copy_rtx_if_shared (stack_slot_list);
+ stack_slot_list = safe_as_a <rtx_expr_list *> (
+ copy_rtx_if_shared (stack_slot_list));
}
/* Go through all the RTL insn bodies and copy any invalid shared
should be done sparingly. */
void
-unshare_all_rtl_again (rtx insn)
+unshare_all_rtl_again (rtx_insn *insn)
{
- rtx p;
+ rtx_insn *p;
tree decl;
for (p = insn; p; p = NEXT_INSN (p))
static void
reset_all_used_flags (void)
{
- rtx p;
+ rtx_insn *p;
for (p = get_insns (); p; p = NEXT_INSN (p))
if (INSN_P (p))
{
gcc_assert (REG_NOTES (p) == NULL);
for (int i = 0; i < XVECLEN (pat, 0); i++)
- reset_insn_used_flags (XVECEXP (pat, 0, i));
+ {
+ rtx insn = XVECEXP (pat, 0, i);
+ if (INSN_P (insn))
+ reset_insn_used_flags (insn);
+ }
}
}
}
DEBUG_FUNCTION void
verify_rtl_sharing (void)
{
- rtx p;
+ rtx_insn *p;
timevar_push (TV_VERIFY_RTL_SHARING);
verify_insn_sharing (p);
else
for (int i = 0; i < XVECLEN (pat, 0); i++)
- verify_insn_sharing (XVECEXP (pat, 0, i));
+ {
+ rtx insn = XVECEXP (pat, 0, i);
+ if (INSN_P (insn))
+ verify_insn_sharing (insn);
+ }
}
reset_all_used_flags ();
Assumes the mark bits are cleared at entry. */
void
-unshare_all_rtl_in_chain (rtx insn)
+unshare_all_rtl_in_chain (rtx_insn *insn)
{
for (; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn))
/* Return the last insn emitted, even if it is in a sequence now pushed. */
-rtx
+rtx_insn *
get_last_insn_anywhere (void)
{
- struct sequence_stack *stack;
- if (get_last_insn ())
- return get_last_insn ();
- for (stack = seq_stack; stack; stack = stack->next)
- if (stack->last != 0)
- return stack->last;
+ struct sequence_stack *seq;
+ for (seq = get_current_sequence (); seq; seq = seq->next)
+ if (seq->last != 0)
+ return seq->last;
return 0;
}
/* Return the first nonnote insn emitted in current sequence or current
function. This routine looks inside SEQUENCEs. */
-rtx
+rtx_insn *
get_first_nonnote_insn (void)
{
- rtx insn = get_insns ();
+ rtx_insn *insn = get_insns ();
if (insn)
{
{
if (NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
- insn = XVECEXP (PATTERN (insn), 0, 0);
+ insn = as_a <rtx_sequence *> (PATTERN (insn))->insn (0);
}
}
/* Return the last nonnote insn emitted in current sequence or current
function. This routine looks inside SEQUENCEs. */
-rtx
+rtx_insn *
get_last_nonnote_insn (void)
{
- rtx insn = get_last_insn ();
+ rtx_insn *insn = get_last_insn ();
if (insn)
{
continue;
else
{
- if (NONJUMP_INSN_P (insn)
- && GET_CODE (PATTERN (insn)) == SEQUENCE)
- insn = XVECEXP (PATTERN (insn), 0,
- XVECLEN (PATTERN (insn), 0) - 1);
+ if (NONJUMP_INSN_P (insn))
+ if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn)))
+ insn = seq->insn (seq->len () - 1);
}
}
/* Return the next insn. If it is a SEQUENCE, return the first insn
of the sequence. */
-rtx
-next_insn (rtx insn)
+rtx_insn *
+next_insn (rtx_insn *insn)
{
if (insn)
{
insn = NEXT_INSN (insn);
if (insn && NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
- insn = XVECEXP (PATTERN (insn), 0, 0);
+ insn = as_a <rtx_sequence *> (PATTERN (insn))->insn (0);
}
return insn;
/* Return the previous insn. If it is a SEQUENCE, return the last insn
of the sequence. */
-rtx
-previous_insn (rtx insn)
+rtx_insn *
+previous_insn (rtx_insn *insn)
{
if (insn)
{
insn = PREV_INSN (insn);
- if (insn && NONJUMP_INSN_P (insn)
- && GET_CODE (PATTERN (insn)) == SEQUENCE)
- insn = XVECEXP (PATTERN (insn), 0, XVECLEN (PATTERN (insn), 0) - 1);
+ if (insn && NONJUMP_INSN_P (insn))
+ if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn)))
+ insn = seq->insn (seq->len () - 1);
}
return insn;
/* Return the next insn after INSN that is not a NOTE. This routine does not
look inside SEQUENCEs. */
-rtx
-next_nonnote_insn (rtx insn)
+rtx_insn *
+next_nonnote_insn (rtx uncast_insn)
{
+ rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
while (insn)
{
insn = NEXT_INSN (insn);
search before we enter another basic block. This routine does not
look inside SEQUENCEs. */
-rtx
-next_nonnote_insn_bb (rtx insn)
+rtx_insn *
+next_nonnote_insn_bb (rtx_insn *insn)
{
while (insn)
{
if (insn == 0 || !NOTE_P (insn))
break;
if (NOTE_INSN_BASIC_BLOCK_P (insn))
- return NULL_RTX;
+ return NULL;
}
return insn;
/* Return the previous insn before INSN that is not a NOTE. This routine does
not look inside SEQUENCEs. */
-rtx
-prev_nonnote_insn (rtx insn)
+rtx_insn *
+prev_nonnote_insn (rtx uncast_insn)
{
+ rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
+
while (insn)
{
insn = PREV_INSN (insn);
the search before we enter another basic block. This routine does
not look inside SEQUENCEs. */
-rtx
-prev_nonnote_insn_bb (rtx insn)
+rtx_insn *
+prev_nonnote_insn_bb (rtx uncast_insn)
{
+ rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
+
while (insn)
{
insn = PREV_INSN (insn);
if (insn == 0 || !NOTE_P (insn))
break;
if (NOTE_INSN_BASIC_BLOCK_P (insn))
- return NULL_RTX;
+ return NULL;
}
return insn;
/* Return the next insn after INSN that is not a DEBUG_INSN. This
routine does not look inside SEQUENCEs. */
-rtx
-next_nondebug_insn (rtx insn)
+rtx_insn *
+next_nondebug_insn (rtx uncast_insn)
{
+ rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
+
while (insn)
{
insn = NEXT_INSN (insn);
/* Return the previous insn before INSN that is not a DEBUG_INSN.
This routine does not look inside SEQUENCEs. */
-rtx
-prev_nondebug_insn (rtx insn)
+rtx_insn *
+prev_nondebug_insn (rtx uncast_insn)
{
+ rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
+
while (insn)
{
insn = PREV_INSN (insn);
/* Return the next insn after INSN that is not a NOTE nor DEBUG_INSN.
This routine does not look inside SEQUENCEs. */
-rtx
-next_nonnote_nondebug_insn (rtx insn)
+rtx_insn *
+next_nonnote_nondebug_insn (rtx uncast_insn)
{
+ rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
+
while (insn)
{
insn = NEXT_INSN (insn);
/* Return the previous insn before INSN that is not a NOTE nor DEBUG_INSN.
This routine does not look inside SEQUENCEs. */
-rtx
-prev_nonnote_nondebug_insn (rtx insn)
+rtx_insn *
+prev_nonnote_nondebug_insn (rtx uncast_insn)
{
+ rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
+
while (insn)
{
insn = PREV_INSN (insn);
or 0, if there is none. This routine does not look inside
SEQUENCEs. */
-rtx
-next_real_insn (rtx insn)
+rtx_insn *
+next_real_insn (rtx uncast_insn)
{
+ rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
+
while (insn)
{
insn = NEXT_INSN (insn);
or 0, if there is none. This routine does not look inside
SEQUENCEs. */
-rtx
-prev_real_insn (rtx insn)
+rtx_insn *
+prev_real_insn (rtx uncast_insn)
{
+ rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
+
while (insn)
{
insn = PREV_INSN (insn);
/* Return the last CALL_INSN in the current list, or 0 if there is none.
This routine does not look inside SEQUENCEs. */
-rtx
+rtx_call_insn *
last_call_insn (void)
{
- rtx insn;
+ rtx_insn *insn;
for (insn = get_last_insn ();
insn && !CALL_P (insn);
insn = PREV_INSN (insn))
;
- return insn;
+ return safe_as_a <rtx_call_insn *> (insn);
}
/* Find the next insn after INSN that really does something. This routine
&& GET_CODE (PATTERN (insn)) != CLOBBER))));
}
-rtx
-next_active_insn (rtx insn)
+rtx_insn *
+next_active_insn (rtx uncast_insn)
{
+ rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
+
while (insn)
{
insn = NEXT_INSN (insn);
does not look inside SEQUENCEs. After reload this also skips over
standalone USE and CLOBBER insn. */
-rtx
-prev_active_insn (rtx insn)
+rtx_insn *
+prev_active_insn (rtx uncast_insn)
{
+ rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
+
while (insn)
{
insn = PREV_INSN (insn);
return insn;
}
\f
-#ifdef HAVE_cc0
/* Return the next insn that uses CC0 after INSN, which is assumed to
set it. This is the inverse of prev_cc0_setter (i.e., prev_cc0_setter
applied to the result of this function should yield INSN).
Return 0 if we can't find the insn. */
-rtx
-next_cc0_user (rtx insn)
+rtx_insn *
+next_cc0_user (rtx uncast_insn)
{
+ rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
+
rtx note = find_reg_note (insn, REG_CC_USER, NULL_RTX);
if (note)
- return XEXP (note, 0);
+ return safe_as_a <rtx_insn *> (XEXP (note, 0));
insn = next_nonnote_insn (insn);
if (insn && NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
- insn = XVECEXP (PATTERN (insn), 0, 0);
+ insn = as_a <rtx_sequence *> (PATTERN (insn))->insn (0);
if (insn && INSN_P (insn) && reg_mentioned_p (cc0_rtx, PATTERN (insn)))
return insn;
/* Find the insn that set CC0 for INSN. Unless INSN has a REG_CC_SETTER
note, it is the previous insn. */
-rtx
-prev_cc0_setter (rtx insn)
+rtx_insn *
+prev_cc0_setter (rtx_insn *insn)
{
rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
if (note)
- return XEXP (note, 0);
+ return safe_as_a <rtx_insn *> (XEXP (note, 0));
insn = prev_nonnote_insn (insn);
gcc_assert (sets_cc0_p (PATTERN (insn)));
return insn;
}
-#endif
#ifdef AUTO_INC_DEC
/* Find a RTX_AUTOINC class rtx which matches DATA. */
static int
-find_auto_inc (rtx *xp, void *data)
+find_auto_inc (const_rtx x, const_rtx reg)
{
- rtx x = *xp;
- rtx reg = (rtx) data;
-
- if (GET_RTX_CLASS (GET_CODE (x)) != RTX_AUTOINC)
- return 0;
-
- switch (GET_CODE (x))
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, x, NONCONST)
{
- case PRE_DEC:
- case PRE_INC:
- case POST_DEC:
- case POST_INC:
- case PRE_MODIFY:
- case POST_MODIFY:
- if (rtx_equal_p (reg, XEXP (x, 0)))
- return 1;
- break;
-
- default:
- gcc_unreachable ();
+ const_rtx x = *iter;
+ if (GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC
+ && rtx_equal_p (reg, XEXP (x, 0)))
+ return true;
}
- return -1;
+ return false;
}
#endif
const char *fmt;
code = GET_CODE (x);
- if (code == LABEL_REF && LABEL_P (XEXP (x, 0)))
- LABEL_NUSES (XEXP (x, 0))++;
+ if (code == LABEL_REF && LABEL_P (LABEL_REF_LABEL (x)))
+ LABEL_NUSES (LABEL_REF_LABEL (x))++;
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
replacement insn depending on the value of LAST. Otherwise, it
returns TRIAL. If the insn to be returned can be split, it will be. */
-rtx
-try_split (rtx pat, rtx trial, int last)
+rtx_insn *
+try_split (rtx pat, rtx_insn *trial, int last)
{
- rtx before = PREV_INSN (trial);
- rtx after = NEXT_INSN (trial);
- int has_barrier = 0;
- rtx note, seq, tem;
+ rtx_insn *before = PREV_INSN (trial);
+ rtx_insn *after = NEXT_INSN (trial);
+ rtx note;
+ rtx_insn *seq, *tem;
int probability;
- rtx insn_last, insn;
+ rtx_insn *insn_last, *insn;
int njumps = 0;
- rtx call_insn = NULL_RTX;
+ rtx_insn *call_insn = NULL;
/* We're not good at redistributing frame information. */
if (RTX_FRAME_RELATED_P (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. */
- if (after && BARRIER_P (after))
- {
- has_barrier = 1;
- after = NEXT_INSN (after);
- }
-
if (!seq)
return trial;
for (insn = insn_last; insn ; insn = PREV_INSN (insn))
if (CALL_P (insn))
{
- rtx next, *p;
+ rtx_insn *next;
+ rtx *p;
gcc_assert (call_insn == NULL_RTX);
call_insn = insn;
{
rtx reg = XEXP (note, 0);
if (!FIND_REG_INC_NOTE (insn, reg)
- && for_each_rtx (&PATTERN (insn), find_auto_inc, reg) > 0)
+ && find_auto_inc (PATTERN (insn), reg))
add_reg_note (insn, REG_INC, reg);
}
break;
#endif
case REG_ARGS_SIZE:
- fixup_args_size_notes (NULL_RTX, insn_last, INTVAL (XEXP (note, 0)));
+ fixup_args_size_notes (NULL, insn_last, INTVAL (XEXP (note, 0)));
break;
case REG_CALL_DECL:
tem = emit_insn_after_setloc (seq, trial, INSN_LOCATION (trial));
delete_insn (trial);
- if (has_barrier)
- emit_barrier_after (tem);
/* Recursively call try_split for each new insn created; by the
time control returns here that insn will be fully split, so
We can't use next_active_insn here since AFTER may be a note.
Ignore deleted insns, which can be occur if not optimizing. */
for (tem = NEXT_INSN (before); tem != after; tem = NEXT_INSN (tem))
- if (! INSN_DELETED_P (tem) && INSN_P (tem))
+ if (! tem->deleted () && INSN_P (tem))
tem = try_split (PATTERN (tem), tem, 1);
/* Return either the first or the last insn, depending on which was
/* Make and return an INSN rtx, initializing all its slots.
Store PATTERN in the pattern slots. */
-rtx
+rtx_insn *
make_insn_raw (rtx pattern)
{
- rtx insn;
+ rtx_insn *insn;
- insn = rtx_alloc (INSN);
+ insn = as_a <rtx_insn *> (rtx_alloc (INSN));
INSN_UID (insn) = cur_insn_uid++;
PATTERN (insn) = pattern;
/* Like `make_insn_raw' but make a DEBUG_INSN instead of an insn. */
-static rtx
+static rtx_insn *
make_debug_insn_raw (rtx pattern)
{
- rtx insn;
+ rtx_debug_insn *insn;
- insn = rtx_alloc (DEBUG_INSN);
+ insn = as_a <rtx_debug_insn *> (rtx_alloc (DEBUG_INSN));
INSN_UID (insn) = cur_debug_insn_uid++;
if (cur_debug_insn_uid > MIN_NONDEBUG_INSN_UID)
INSN_UID (insn) = cur_insn_uid++;
/* Like `make_insn_raw' but make a JUMP_INSN instead of an insn. */
-static rtx
+static rtx_insn *
make_jump_insn_raw (rtx pattern)
{
- rtx insn;
+ rtx_jump_insn *insn;
- insn = rtx_alloc (JUMP_INSN);
+ insn = as_a <rtx_jump_insn *> (rtx_alloc (JUMP_INSN));
INSN_UID (insn) = cur_insn_uid++;
PATTERN (insn) = pattern;
/* Like `make_insn_raw' but make a CALL_INSN instead of an insn. */
-static rtx
+static rtx_insn *
make_call_insn_raw (rtx pattern)
{
- rtx insn;
+ rtx_call_insn *insn;
- insn = rtx_alloc (CALL_INSN);
+ insn = as_a <rtx_call_insn *> (rtx_alloc (CALL_INSN));
INSN_UID (insn) = cur_insn_uid++;
PATTERN (insn) = pattern;
/* Like `make_insn_raw' but make a NOTE instead of an insn. */
-static rtx
+static rtx_note *
make_note_raw (enum insn_note subtype)
{
/* Some notes are never created this way at all. These notes are
gcc_assert (subtype != NOTE_INSN_DELETED_LABEL
&& subtype != NOTE_INSN_DELETED_DEBUG_LABEL);
- rtx note = rtx_alloc (NOTE);
+ rtx_note *note = as_a <rtx_note *> (rtx_alloc (NOTE));
INSN_UID (note) = cur_insn_uid++;
NOTE_KIND (note) = subtype;
BLOCK_FOR_INSN (note) = NULL;
but also BARRIERs and JUMP_TABLE_DATAs. PREV and NEXT may be NULL. */
static inline void
-link_insn_into_chain (rtx insn, rtx prev, rtx next)
+link_insn_into_chain (rtx_insn *insn, rtx_insn *prev, rtx_insn *next)
{
- PREV_INSN (insn) = prev;
- NEXT_INSN (insn) = next;
+ SET_PREV_INSN (insn) = prev;
+ SET_NEXT_INSN (insn) = next;
if (prev != NULL)
{
- NEXT_INSN (prev) = insn;
+ SET_NEXT_INSN (prev) = insn;
if (NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
{
- rtx sequence = PATTERN (prev);
- NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn;
+ rtx_sequence *sequence = as_a <rtx_sequence *> (PATTERN (prev));
+ SET_NEXT_INSN (sequence->insn (sequence->len () - 1)) = insn;
}
}
if (next != NULL)
{
- PREV_INSN (next) = insn;
+ SET_PREV_INSN (next) = insn;
if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
- PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = insn;
+ {
+ rtx_sequence *sequence = as_a <rtx_sequence *> (PATTERN (next));
+ SET_PREV_INSN (sequence->insn (0)) = insn;
+ }
}
if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
{
- rtx sequence = PATTERN (insn);
- PREV_INSN (XVECEXP (sequence, 0, 0)) = prev;
- NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = next;
+ rtx_sequence *sequence = as_a <rtx_sequence *> (PATTERN (insn));
+ SET_PREV_INSN (sequence->insn (0)) = prev;
+ SET_NEXT_INSN (sequence->insn (sequence->len () - 1)) = next;
}
}
INSN may be an INSN, JUMP_INSN, CALL_INSN, CODE_LABEL, BARRIER or NOTE. */
void
-add_insn (rtx insn)
+add_insn (rtx_insn *insn)
{
- rtx prev = get_last_insn ();
+ rtx_insn *prev = get_last_insn ();
link_insn_into_chain (insn, prev, NULL);
if (NULL == get_insns ())
set_first_insn (insn);
/* Add INSN into the doubly-linked list after insn AFTER. */
static void
-add_insn_after_nobb (rtx insn, rtx after)
+add_insn_after_nobb (rtx_insn *insn, rtx_insn *after)
{
- rtx next = NEXT_INSN (after);
+ rtx_insn *next = NEXT_INSN (after);
- gcc_assert (!optimize || !INSN_DELETED_P (after));
+ gcc_assert (!optimize || !after->deleted ());
link_insn_into_chain (insn, after, next);
if (next == NULL)
{
- if (get_last_insn () == after)
- set_last_insn (insn);
- else
- {
- struct sequence_stack *stack = seq_stack;
- /* Scan all pending sequences too. */
- for (; stack; stack = stack->next)
- if (after == stack->last)
- {
- stack->last = insn;
- break;
- }
- }
+ struct sequence_stack *seq;
+
+ for (seq = get_current_sequence (); seq; seq = seq->next)
+ if (after == seq->last)
+ {
+ seq->last = insn;
+ break;
+ }
}
}
/* Add INSN into the doubly-linked list before insn BEFORE. */
static void
-add_insn_before_nobb (rtx insn, rtx before)
+add_insn_before_nobb (rtx_insn *insn, rtx_insn *before)
{
- rtx prev = PREV_INSN (before);
+ rtx_insn *prev = PREV_INSN (before);
- gcc_assert (!optimize || !INSN_DELETED_P (before));
+ gcc_assert (!optimize || !before->deleted ());
link_insn_into_chain (insn, prev, before);
if (prev == NULL)
{
- if (get_insns () == before)
- set_first_insn (insn);
- else
- {
- struct sequence_stack *stack = seq_stack;
- /* Scan all pending sequences too. */
- for (; stack; stack = stack->next)
- if (before == stack->first)
- {
- stack->first = insn;
- break;
- }
+ struct sequence_stack *seq;
- gcc_assert (stack);
- }
+ for (seq = get_current_sequence (); seq; seq = seq->next)
+ if (before == seq->first)
+ {
+ seq->first = insn;
+ break;
+ }
+
+ gcc_assert (seq);
}
}
they know how to update a SEQUENCE. */
void
-add_insn_after (rtx insn, rtx after, basic_block bb)
+add_insn_after (rtx uncast_insn, rtx uncast_after, basic_block bb)
{
+ rtx_insn *insn = as_a <rtx_insn *> (uncast_insn);
+ rtx_insn *after = as_a <rtx_insn *> (uncast_after);
add_insn_after_nobb (insn, after);
if (!BARRIER_P (after)
&& !BARRIER_P (insn)
they know how to update a SEQUENCE. */
void
-add_insn_before (rtx insn, rtx before, basic_block bb)
+add_insn_before (rtx uncast_insn, rtx uncast_before, basic_block bb)
{
+ rtx_insn *insn = as_a <rtx_insn *> (uncast_insn);
+ rtx_insn *before = as_a <rtx_insn *> (uncast_before);
add_insn_before_nobb (insn, before);
if (!bb
set_insn_deleted (rtx insn)
{
if (INSN_P (insn))
- df_insn_delete (insn);
+ df_insn_delete (as_a <rtx_insn *> (insn));
PUT_CODE (insn, NOTE);
NOTE_KIND (insn) = NOTE_INSN_DELETED;
}
To really delete an insn and related DF information, use delete_insn. */
void
-remove_insn (rtx insn)
+remove_insn (rtx uncast_insn)
{
- rtx next = NEXT_INSN (insn);
- rtx prev = PREV_INSN (insn);
+ rtx_insn *insn = as_a <rtx_insn *> (uncast_insn);
+ rtx_insn *next = NEXT_INSN (insn);
+ rtx_insn *prev = PREV_INSN (insn);
basic_block bb;
if (prev)
{
- NEXT_INSN (prev) = next;
+ SET_NEXT_INSN (prev) = next;
if (NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
{
- rtx sequence = PATTERN (prev);
- NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = next;
+ rtx_sequence *sequence = as_a <rtx_sequence *> (PATTERN (prev));
+ SET_NEXT_INSN (sequence->insn (sequence->len () - 1)) = next;
}
}
- else if (get_insns () == insn)
- {
- if (next)
- PREV_INSN (next) = NULL;
- set_first_insn (next);
- }
else
{
- struct sequence_stack *stack = seq_stack;
- /* Scan all pending sequences too. */
- for (; stack; stack = stack->next)
- if (insn == stack->first)
+ struct sequence_stack *seq;
+
+ for (seq = get_current_sequence (); seq; seq = seq->next)
+ if (insn == seq->first)
{
- stack->first = next;
+ seq->first = next;
break;
}
- gcc_assert (stack);
+ gcc_assert (seq);
}
if (next)
{
- PREV_INSN (next) = prev;
+ SET_PREV_INSN (next) = prev;
if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
- PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = prev;
+ {
+ rtx_sequence *sequence = as_a <rtx_sequence *> (PATTERN (next));
+ SET_PREV_INSN (sequence->insn (0)) = prev;
+ }
}
- else if (get_last_insn () == insn)
- set_last_insn (prev);
else
{
- struct sequence_stack *stack = seq_stack;
- /* Scan all pending sequences too. */
- for (; stack; stack = stack->next)
- if (insn == stack->last)
+ struct sequence_stack *seq;
+
+ for (seq = get_current_sequence (); seq; seq = seq->next)
+ if (insn == seq->last)
{
- stack->last = prev;
+ seq->last = prev;
break;
}
- gcc_assert (stack);
+ gcc_assert (seq);
}
/* Fix up basic block boundaries, if necessary. */
FROM becomes the new last instruction. */
void
-delete_insns_since (rtx from)
+delete_insns_since (rtx_insn *from)
{
if (from == 0)
set_first_insn (0);
else
- NEXT_INSN (from) = 0;
+ SET_NEXT_INSN (from) = 0;
set_last_insn (from);
}
called after delay-slot filling has been done. */
void
-reorder_insns_nobb (rtx from, rtx to, rtx after)
+reorder_insns_nobb (rtx_insn *from, rtx_insn *to, rtx_insn *after)
{
#ifdef ENABLE_CHECKING
- rtx x;
+ rtx_insn *x;
for (x = from; x != to; x = NEXT_INSN (x))
gcc_assert (after != x);
gcc_assert (after != to);
/* Splice this bunch out of where it is now. */
if (PREV_INSN (from))
- NEXT_INSN (PREV_INSN (from)) = NEXT_INSN (to);
+ SET_NEXT_INSN (PREV_INSN (from)) = NEXT_INSN (to);
if (NEXT_INSN (to))
- PREV_INSN (NEXT_INSN (to)) = PREV_INSN (from);
+ SET_PREV_INSN (NEXT_INSN (to)) = PREV_INSN (from);
if (get_last_insn () == to)
set_last_insn (PREV_INSN (from));
if (get_insns () == from)
/* Make the new neighbors point to it and it to them. */
if (NEXT_INSN (after))
- PREV_INSN (NEXT_INSN (after)) = to;
+ SET_PREV_INSN (NEXT_INSN (after)) = to;
- NEXT_INSN (to) = NEXT_INSN (after);
- PREV_INSN (from) = after;
- NEXT_INSN (after) = from;
+ SET_NEXT_INSN (to) = NEXT_INSN (after);
+ SET_PREV_INSN (from) = after;
+ SET_NEXT_INSN (after) = from;
if (after == get_last_insn ())
set_last_insn (to);
}
/* Same as function above, but take care to update BB boundaries. */
void
-reorder_insns (rtx from, rtx to, rtx after)
+reorder_insns (rtx_insn *from, rtx_insn *to, rtx_insn *after)
{
- rtx prev = PREV_INSN (from);
+ rtx_insn *prev = PREV_INSN (from);
basic_block bb, bb2;
reorder_insns_nobb (from, to, after);
if (!BARRIER_P (after)
&& (bb = BLOCK_FOR_INSN (after)))
{
- rtx x;
+ rtx_insn *x;
df_set_bb_dirty (bb);
if (!BARRIER_P (from)
SEQUENCE rtl results in much fragmented RTL memory since the SEQUENCE
generated would almost certainly die right after it was created. */
-static rtx
+static rtx_insn *
emit_pattern_before_noloc (rtx x, rtx before, rtx last, basic_block bb,
- rtx (*make_raw) (rtx))
+ rtx_insn *(*make_raw) (rtx))
{
- rtx insn;
+ rtx_insn *insn;
gcc_assert (before);
if (x == NULL_RTX)
- return last;
+ return safe_as_a <rtx_insn *> (last);
switch (GET_CODE (x))
{
case CODE_LABEL:
case BARRIER:
case NOTE:
- insn = x;
+ insn = as_a <rtx_insn *> (x);
while (insn)
{
- rtx next = NEXT_INSN (insn);
+ rtx_insn *next = NEXT_INSN (insn);
add_insn_before (insn, before, bb);
last = insn;
insn = next;
break;
}
- return last;
+ return safe_as_a <rtx_insn *> (last);
}
/* Make X be output before the instruction BEFORE. */
-rtx
-emit_insn_before_noloc (rtx x, rtx before, basic_block bb)
+rtx_insn *
+emit_insn_before_noloc (rtx x, rtx_insn *before, basic_block bb)
{
return emit_pattern_before_noloc (x, before, before, bb, make_insn_raw);
}
/* Make an instruction with body X and code JUMP_INSN
and output it before the instruction BEFORE. */
-rtx
-emit_jump_insn_before_noloc (rtx x, rtx before)
+rtx_jump_insn *
+emit_jump_insn_before_noloc (rtx x, rtx_insn *before)
{
- return emit_pattern_before_noloc (x, before, NULL_RTX, NULL,
- make_jump_insn_raw);
+ return as_a <rtx_jump_insn *> (
+ emit_pattern_before_noloc (x, before, NULL_RTX, NULL,
+ make_jump_insn_raw));
}
/* Make an instruction with body X and code CALL_INSN
and output it before the instruction BEFORE. */
-rtx
-emit_call_insn_before_noloc (rtx x, rtx before)
+rtx_insn *
+emit_call_insn_before_noloc (rtx x, rtx_insn *before)
{
return emit_pattern_before_noloc (x, before, NULL_RTX, NULL,
make_call_insn_raw);
/* Make an instruction with body X and code DEBUG_INSN
and output it before the instruction BEFORE. */
-rtx
+rtx_insn *
emit_debug_insn_before_noloc (rtx x, rtx before)
{
return emit_pattern_before_noloc (x, before, NULL_RTX, NULL,
/* Make an insn of code BARRIER
and output it before the insn BEFORE. */
-rtx
+rtx_barrier *
emit_barrier_before (rtx before)
{
- rtx insn = rtx_alloc (BARRIER);
+ rtx_barrier *insn = as_a <rtx_barrier *> (rtx_alloc (BARRIER));
INSN_UID (insn) = cur_insn_uid++;
/* Emit the label LABEL before the insn BEFORE. */
-rtx
-emit_label_before (rtx label, rtx before)
+rtx_code_label *
+emit_label_before (rtx label, rtx_insn *before)
{
gcc_checking_assert (INSN_UID (label) == 0);
INSN_UID (label) = cur_insn_uid++;
add_insn_before (label, before, NULL);
- return label;
+ return as_a <rtx_code_label *> (label);
}
\f
/* Helper for emit_insn_after, handles lists of instructions
efficiently. */
-static rtx
-emit_insn_after_1 (rtx first, rtx after, basic_block bb)
+static rtx_insn *
+emit_insn_after_1 (rtx_insn *first, rtx uncast_after, basic_block bb)
{
- rtx last;
- rtx after_after;
+ rtx_insn *after = safe_as_a <rtx_insn *> (uncast_after);
+ rtx_insn *last;
+ rtx_insn *after_after;
if (!bb && !BARRIER_P (after))
bb = BLOCK_FOR_INSN (after);
after_after = NEXT_INSN (after);
- NEXT_INSN (after) = first;
- PREV_INSN (first) = after;
- NEXT_INSN (last) = after_after;
+ SET_NEXT_INSN (after) = first;
+ SET_PREV_INSN (first) = after;
+ SET_NEXT_INSN (last) = after_after;
if (after_after)
- PREV_INSN (after_after) = last;
+ SET_PREV_INSN (after_after) = last;
if (after == get_last_insn ())
set_last_insn (last);
return last;
}
-static rtx
-emit_pattern_after_noloc (rtx x, rtx after, basic_block bb,
- rtx (*make_raw)(rtx))
+static rtx_insn *
+emit_pattern_after_noloc (rtx x, rtx uncast_after, basic_block bb,
+ rtx_insn *(*make_raw)(rtx))
{
- rtx last = after;
+ rtx_insn *after = safe_as_a <rtx_insn *> (uncast_after);
+ rtx_insn *last = after;
gcc_assert (after);
case CODE_LABEL:
case BARRIER:
case NOTE:
- last = emit_insn_after_1 (x, after, bb);
+ last = emit_insn_after_1 (as_a <rtx_insn *> (x), after, bb);
break;
#ifdef ENABLE_RTL_CHECKING
/* Make X be output after the insn AFTER and set the BB of insn. If
BB is NULL, an attempt is made to infer the BB from AFTER. */
-rtx
+rtx_insn *
emit_insn_after_noloc (rtx x, rtx after, basic_block bb)
{
return emit_pattern_after_noloc (x, after, bb, make_insn_raw);
/* Make an insn of code JUMP_INSN with body X
and output it after the insn AFTER. */
-rtx
+rtx_jump_insn *
emit_jump_insn_after_noloc (rtx x, rtx after)
{
- return emit_pattern_after_noloc (x, after, NULL, make_jump_insn_raw);
+ return as_a <rtx_jump_insn *> (
+ emit_pattern_after_noloc (x, after, NULL, make_jump_insn_raw));
}
/* Make an instruction with body X and code CALL_INSN
and output it after the instruction AFTER. */
-rtx
+rtx_insn *
emit_call_insn_after_noloc (rtx x, rtx after)
{
return emit_pattern_after_noloc (x, after, NULL, make_call_insn_raw);
/* Make an instruction with body X and code CALL_INSN
and output it after the instruction AFTER. */
-rtx
+rtx_insn *
emit_debug_insn_after_noloc (rtx x, rtx after)
{
return emit_pattern_after_noloc (x, after, NULL, make_debug_insn_raw);
/* Make an insn of code BARRIER
and output it after the insn AFTER. */
-rtx
+rtx_barrier *
emit_barrier_after (rtx after)
{
- rtx insn = rtx_alloc (BARRIER);
+ rtx_barrier *insn = as_a <rtx_barrier *> (rtx_alloc (BARRIER));
INSN_UID (insn) = cur_insn_uid++;
/* Emit the label LABEL after the insn AFTER. */
-rtx
-emit_label_after (rtx label, rtx after)
+rtx_insn *
+emit_label_after (rtx label, rtx_insn *after)
{
gcc_checking_assert (INSN_UID (label) == 0);
INSN_UID (label) = cur_insn_uid++;
add_insn_after (label, after, NULL);
- return label;
+ return as_a <rtx_insn *> (label);
}
\f
/* Notes require a bit of special handling: Some notes need to have their
/* Emit a note of subtype SUBTYPE after the insn AFTER. */
-rtx
-emit_note_after (enum insn_note subtype, rtx after)
+rtx_note *
+emit_note_after (enum insn_note subtype, rtx_insn *after)
{
- rtx note = make_note_raw (subtype);
+ rtx_note *note = make_note_raw (subtype);
basic_block bb = BARRIER_P (after) ? NULL : BLOCK_FOR_INSN (after);
bool on_bb_boundary_p = (bb != NULL && BB_END (bb) == after);
/* Emit a note of subtype SUBTYPE before the insn BEFORE. */
-rtx
-emit_note_before (enum insn_note subtype, rtx before)
+rtx_note *
+emit_note_before (enum insn_note subtype, rtx_insn *before)
{
- rtx note = make_note_raw (subtype);
+ rtx_note *note = make_note_raw (subtype);
basic_block bb = BARRIER_P (before) ? NULL : BLOCK_FOR_INSN (before);
bool on_bb_boundary_p = (bb != NULL && BB_HEAD (bb) == before);
/* Insert PATTERN after AFTER, setting its INSN_LOCATION to LOC.
MAKE_RAW indicates how to turn PATTERN into a real insn. */
-static rtx
-emit_pattern_after_setloc (rtx pattern, rtx after, int loc,
- rtx (*make_raw) (rtx))
+static rtx_insn *
+emit_pattern_after_setloc (rtx pattern, rtx uncast_after, int loc,
+ rtx_insn *(*make_raw) (rtx))
{
- rtx last = emit_pattern_after_noloc (pattern, after, NULL, make_raw);
+ rtx_insn *after = safe_as_a <rtx_insn *> (uncast_after);
+ rtx_insn *last = emit_pattern_after_noloc (pattern, after, NULL, make_raw);
if (pattern == NULL_RTX || !loc)
return last;
after = NEXT_INSN (after);
while (1)
{
- if (active_insn_p (after) && !INSN_LOCATION (after))
+ if (active_insn_p (after)
+ && !JUMP_TABLE_DATA_P (after) /* FIXME */
+ && !INSN_LOCATION (after))
INSN_LOCATION (after) = loc;
if (after == last)
break;
into a real insn. SKIP_DEBUG_INSNS indicates whether to insert after
any DEBUG_INSNs. */
-static rtx
-emit_pattern_after (rtx pattern, rtx after, bool skip_debug_insns,
- rtx (*make_raw) (rtx))
+static rtx_insn *
+emit_pattern_after (rtx pattern, rtx uncast_after, bool skip_debug_insns,
+ rtx_insn *(*make_raw) (rtx))
{
- rtx prev = after;
+ rtx_insn *after = safe_as_a <rtx_insn *> (uncast_after);
+ rtx_insn *prev = after;
if (skip_debug_insns)
while (DEBUG_INSN_P (prev))
}
/* Like emit_insn_after_noloc, but set INSN_LOCATION according to LOC. */
-rtx
+rtx_insn *
emit_insn_after_setloc (rtx pattern, rtx after, int loc)
{
return emit_pattern_after_setloc (pattern, after, loc, make_insn_raw);
}
/* Like emit_insn_after_noloc, but set INSN_LOCATION according to AFTER. */
-rtx
+rtx_insn *
emit_insn_after (rtx pattern, rtx after)
{
return emit_pattern_after (pattern, after, true, make_insn_raw);
}
/* Like emit_jump_insn_after_noloc, but set INSN_LOCATION according to LOC. */
-rtx
+rtx_jump_insn *
emit_jump_insn_after_setloc (rtx pattern, rtx after, int loc)
{
- return emit_pattern_after_setloc (pattern, after, loc, make_jump_insn_raw);
+ return as_a <rtx_jump_insn *> (
+ emit_pattern_after_setloc (pattern, after, loc, make_jump_insn_raw));
}
/* Like emit_jump_insn_after_noloc, but set INSN_LOCATION according to AFTER. */
-rtx
+rtx_jump_insn *
emit_jump_insn_after (rtx pattern, rtx after)
{
- return emit_pattern_after (pattern, after, true, make_jump_insn_raw);
+ return as_a <rtx_jump_insn *> (
+ emit_pattern_after (pattern, after, true, make_jump_insn_raw));
}
/* Like emit_call_insn_after_noloc, but set INSN_LOCATION according to LOC. */
-rtx
+rtx_insn *
emit_call_insn_after_setloc (rtx pattern, rtx after, int loc)
{
return emit_pattern_after_setloc (pattern, after, loc, make_call_insn_raw);
}
/* Like emit_call_insn_after_noloc, but set INSN_LOCATION according to AFTER. */
-rtx
+rtx_insn *
emit_call_insn_after (rtx pattern, rtx after)
{
return emit_pattern_after (pattern, after, true, make_call_insn_raw);
}
/* Like emit_debug_insn_after_noloc, but set INSN_LOCATION according to LOC. */
-rtx
+rtx_insn *
emit_debug_insn_after_setloc (rtx pattern, rtx after, int loc)
{
return emit_pattern_after_setloc (pattern, after, loc, make_debug_insn_raw);
}
/* Like emit_debug_insn_after_noloc, but set INSN_LOCATION according to AFTER. */
-rtx
+rtx_insn *
emit_debug_insn_after (rtx pattern, rtx after)
{
return emit_pattern_after (pattern, after, false, make_debug_insn_raw);
indicates if PATTERN is meant for an INSN as opposed to a JUMP_INSN,
CALL_INSN, etc. */
-static rtx
-emit_pattern_before_setloc (rtx pattern, rtx before, int loc, bool insnp,
- rtx (*make_raw) (rtx))
+static rtx_insn *
+emit_pattern_before_setloc (rtx pattern, rtx uncast_before, int loc, bool insnp,
+ rtx_insn *(*make_raw) (rtx))
{
- rtx first = PREV_INSN (before);
- rtx last = emit_pattern_before_noloc (pattern, before,
- insnp ? before : NULL_RTX,
- NULL, make_raw);
+ rtx_insn *before = as_a <rtx_insn *> (uncast_before);
+ rtx_insn *first = PREV_INSN (before);
+ rtx_insn *last = emit_pattern_before_noloc (pattern, before,
+ insnp ? before : NULL_RTX,
+ NULL, make_raw);
if (pattern == NULL_RTX || !loc)
return last;
first = NEXT_INSN (first);
while (1)
{
- if (active_insn_p (first) && !INSN_LOCATION (first))
+ if (active_insn_p (first)
+ && !JUMP_TABLE_DATA_P (first) /* FIXME */
+ && !INSN_LOCATION (first))
INSN_LOCATION (first) = loc;
if (first == last)
break;
before any DEBUG_INSNs. INSNP indicates if PATTERN is meant for an
INSN as opposed to a JUMP_INSN, CALL_INSN, etc. */
-static rtx
-emit_pattern_before (rtx pattern, rtx before, bool skip_debug_insns,
- bool insnp, rtx (*make_raw) (rtx))
+static rtx_insn *
+emit_pattern_before (rtx pattern, rtx uncast_before, bool skip_debug_insns,
+ bool insnp, rtx_insn *(*make_raw) (rtx))
{
- rtx next = before;
+ rtx_insn *before = safe_as_a <rtx_insn *> (uncast_before);
+ rtx_insn *next = before;
if (skip_debug_insns)
while (DEBUG_INSN_P (next))
}
/* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC. */
-rtx
-emit_insn_before_setloc (rtx pattern, rtx before, int loc)
+rtx_insn *
+emit_insn_before_setloc (rtx pattern, rtx_insn *before, int loc)
{
return emit_pattern_before_setloc (pattern, before, loc, true,
make_insn_raw);
}
/* Like emit_insn_before_noloc, but set INSN_LOCATION according to BEFORE. */
-rtx
+rtx_insn *
emit_insn_before (rtx pattern, rtx before)
{
return emit_pattern_before (pattern, before, true, true, make_insn_raw);
}
/* like emit_insn_before_noloc, but set INSN_LOCATION according to LOC. */
-rtx
-emit_jump_insn_before_setloc (rtx pattern, rtx before, int loc)
+rtx_jump_insn *
+emit_jump_insn_before_setloc (rtx pattern, rtx_insn *before, int loc)
{
- return emit_pattern_before_setloc (pattern, before, loc, false,
- make_jump_insn_raw);
+ return as_a <rtx_jump_insn *> (
+ emit_pattern_before_setloc (pattern, before, loc, false,
+ make_jump_insn_raw));
}
/* Like emit_jump_insn_before_noloc, but set INSN_LOCATION according to BEFORE. */
-rtx
+rtx_jump_insn *
emit_jump_insn_before (rtx pattern, rtx before)
{
- return emit_pattern_before (pattern, before, true, false,
- make_jump_insn_raw);
+ return as_a <rtx_jump_insn *> (
+ emit_pattern_before (pattern, before, true, false,
+ make_jump_insn_raw));
}
/* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC. */
-rtx
-emit_call_insn_before_setloc (rtx pattern, rtx before, int loc)
+rtx_insn *
+emit_call_insn_before_setloc (rtx pattern, rtx_insn *before, int loc)
{
return emit_pattern_before_setloc (pattern, before, loc, false,
make_call_insn_raw);
/* Like emit_call_insn_before_noloc,
but set insn_location according to BEFORE. */
-rtx
-emit_call_insn_before (rtx pattern, rtx before)
+rtx_insn *
+emit_call_insn_before (rtx pattern, rtx_insn *before)
{
return emit_pattern_before (pattern, before, true, false,
make_call_insn_raw);
}
/* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC. */
-rtx
+rtx_insn *
emit_debug_insn_before_setloc (rtx pattern, rtx before, int loc)
{
return emit_pattern_before_setloc (pattern, before, loc, false,
/* Like emit_debug_insn_before_noloc,
but set insn_location according to BEFORE. */
-rtx
-emit_debug_insn_before (rtx pattern, rtx before)
+rtx_insn *
+emit_debug_insn_before (rtx pattern, rtx_insn *before)
{
return emit_pattern_before (pattern, before, false, false,
make_debug_insn_raw);
Returns the last insn emitted. */
-rtx
+rtx_insn *
emit_insn (rtx x)
{
- rtx last = get_last_insn ();
- rtx insn;
+ rtx_insn *last = get_last_insn ();
+ rtx_insn *insn;
if (x == NULL_RTX)
return last;
case CODE_LABEL:
case BARRIER:
case NOTE:
- insn = x;
+ insn = as_a <rtx_insn *> (x);
while (insn)
{
- rtx next = NEXT_INSN (insn);
+ rtx_insn *next = NEXT_INSN (insn);
add_insn (insn);
last = insn;
insn = next;
/* Make an insn of code DEBUG_INSN with pattern X
and add it to the end of the doubly-linked list. */
-rtx
+rtx_insn *
emit_debug_insn (rtx x)
{
- rtx last = get_last_insn ();
- rtx insn;
+ rtx_insn *last = get_last_insn ();
+ rtx_insn *insn;
if (x == NULL_RTX)
return last;
case CODE_LABEL:
case BARRIER:
case NOTE:
- insn = x;
+ insn = as_a <rtx_insn *> (x);
while (insn)
{
- rtx next = NEXT_INSN (insn);
+ rtx_insn *next = NEXT_INSN (insn);
add_insn (insn);
last = insn;
insn = next;
/* Make an insn of code JUMP_INSN with pattern X
and add it to the end of the doubly-linked list. */
-rtx
+rtx_insn *
emit_jump_insn (rtx x)
{
- rtx last = NULL_RTX, insn;
+ rtx_insn *last = NULL;
+ rtx_insn *insn;
switch (GET_CODE (x))
{
case CODE_LABEL:
case BARRIER:
case NOTE:
- insn = x;
+ insn = as_a <rtx_insn *> (x);
while (insn)
{
- rtx next = NEXT_INSN (insn);
+ rtx_insn *next = NEXT_INSN (insn);
add_insn (insn);
last = insn;
insn = next;
/* Make an insn of code CALL_INSN with pattern X
and add it to the end of the doubly-linked list. */
-rtx
+rtx_insn *
emit_call_insn (rtx x)
{
- rtx insn;
+ rtx_insn *insn;
switch (GET_CODE (x))
{
/* Add the label LABEL to the end of the doubly-linked list. */
-rtx
-emit_label (rtx label)
+rtx_code_label *
+emit_label (rtx uncast_label)
{
+ rtx_code_label *label = as_a <rtx_code_label *> (uncast_label);
+
gcc_checking_assert (INSN_UID (label) == 0);
INSN_UID (label) = cur_insn_uid++;
add_insn (label);
/* Make an insn of code JUMP_TABLE_DATA
and add it to the end of the doubly-linked list. */
-rtx
+rtx_jump_table_data *
emit_jump_table_data (rtx table)
{
- rtx jump_table_data = rtx_alloc (JUMP_TABLE_DATA);
+ rtx_jump_table_data *jump_table_data =
+ as_a <rtx_jump_table_data *> (rtx_alloc (JUMP_TABLE_DATA));
INSN_UID (jump_table_data) = cur_insn_uid++;
PATTERN (jump_table_data) = table;
BLOCK_FOR_INSN (jump_table_data) = NULL;
/* Make an insn of code BARRIER
and add it to the end of the doubly-linked list. */
-rtx
+rtx_barrier *
emit_barrier (void)
{
- rtx barrier = rtx_alloc (BARRIER);
+ rtx_barrier *barrier = as_a <rtx_barrier *> (rtx_alloc (BARRIER));
INSN_UID (barrier) = cur_insn_uid++;
add_insn (barrier);
return barrier;
/* Emit a copy of note ORIG. */
-rtx
-emit_note_copy (rtx orig)
+rtx_note *
+emit_note_copy (rtx_note *orig)
{
enum insn_note kind = (enum insn_note) NOTE_KIND (orig);
- rtx note = make_note_raw (kind);
+ rtx_note *note = make_note_raw (kind);
NOTE_DATA (note) = NOTE_DATA (orig);
add_insn (note);
return note;
/* Make an insn of code NOTE or type NOTE_NO
and add it to the end of the doubly-linked list. */
-rtx
+rtx_note *
emit_note (enum insn_note kind)
{
- rtx note = make_note_raw (kind);
+ rtx_note *note = make_note_raw (kind);
add_insn (note);
return note;
}
/* Emit a clobber of lvalue X. */
-rtx
+rtx_insn *
emit_clobber (rtx x)
{
/* CONCATs should not appear in the insn stream. */
/* Return a sequence of insns to clobber lvalue X. */
-rtx
+rtx_insn *
gen_clobber (rtx x)
{
- rtx seq;
+ rtx_insn *seq;
start_sequence ();
emit_clobber (x);
/* Emit a use of rvalue X. */
-rtx
+rtx_insn *
emit_use (rtx x)
{
/* CONCATs should not appear in the insn stream. */
/* Return a sequence of insns to use rvalue X. */
-rtx
+rtx_insn *
gen_use (rtx x)
{
- rtx seq;
+ rtx_insn *seq;
start_sequence ();
emit_use (x);
It serves no useful purpose and breaks eliminate_regs. */
if (GET_CODE (datum) == ASM_OPERANDS)
return NULL_RTX;
+
+ /* Notes with side effects are dangerous. Even if the side-effect
+ initially mirrors one in PATTERN (INSN), later optimizations
+ might alter the way that the final register value is calculated
+ and so move or alter the side-effect in some way. The note would
+ then no longer be a valid substitution for SET_SRC. */
+ if (side_effects_p (datum))
+ return NULL_RTX;
break;
default:
{
case REG_EQUAL:
case REG_EQUIV:
- df_notes_rescan (insn);
+ df_notes_rescan (as_a <rtx_insn *> (insn));
break;
default:
break;
return NULL_RTX;
}
\f
-/* Return an indication of which type of insn should have X as a body.
- The value is CODE_LABEL, INSN, CALL_INSN or JUMP_INSN. */
-
-static enum rtx_code
-classify_insn (rtx x)
-{
- if (LABEL_P (x))
- return CODE_LABEL;
- if (GET_CODE (x) == CALL)
- return CALL_INSN;
- if (ANY_RETURN_P (x))
- return JUMP_INSN;
- if (GET_CODE (x) == SET)
- {
- if (SET_DEST (x) == pc_rtx)
- return JUMP_INSN;
- else if (GET_CODE (SET_SRC (x)) == CALL)
- return CALL_INSN;
- else
- return INSN;
- }
- if (GET_CODE (x) == PARALLEL)
- {
- int j;
- for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
- if (GET_CODE (XVECEXP (x, 0, j)) == CALL)
- return CALL_INSN;
- else if (GET_CODE (XVECEXP (x, 0, j)) == SET
- && SET_DEST (XVECEXP (x, 0, j)) == pc_rtx)
- return JUMP_INSN;
- else if (GET_CODE (XVECEXP (x, 0, j)) == SET
- && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL)
- return CALL_INSN;
- }
- return INSN;
-}
+/* Emit the rtl pattern X as an appropriate kind of insn. Also emit a
+ following barrier if the instruction needs one and if ALLOW_BARRIER_P
+ is true.
-/* Emit the rtl pattern X as an appropriate kind of insn.
If X is a label, it is simply added into the insn chain. */
-rtx
-emit (rtx x)
+rtx_insn *
+emit (rtx x, bool allow_barrier_p)
{
enum rtx_code code = classify_insn (x);
return emit_insn (x);
case JUMP_INSN:
{
- rtx insn = emit_jump_insn (x);
- if (any_uncondjump_p (insn) || GET_CODE (x) == RETURN)
+ rtx_insn *insn = emit_jump_insn (x);
+ if (allow_barrier_p
+ && (any_uncondjump_p (insn) || GET_CODE (x) == RETURN))
return emit_barrier ();
return insn;
}
else
tem = ggc_alloc<sequence_stack> ();
- tem->next = seq_stack;
+ tem->next = get_current_sequence ()->next;
tem->first = get_insns ();
tem->last = get_last_insn ();
-
- seq_stack = tem;
+ get_current_sequence ()->next = tem;
set_first_insn (0);
set_last_insn (0);
start_sequence for more information about how to use this function. */
void
-push_to_sequence (rtx first)
+push_to_sequence (rtx_insn *first)
{
- rtx last;
+ rtx_insn *last;
start_sequence ();
looping through the list. */
void
-push_to_sequence2 (rtx first, rtx last)
+push_to_sequence2 (rtx_insn *first, rtx_insn *last)
{
start_sequence ();
void
push_topmost_sequence (void)
{
- struct sequence_stack *stack, *top = NULL;
+ struct sequence_stack *top;
start_sequence ();
- for (stack = seq_stack; stack; stack = stack->next)
- top = stack;
-
+ top = get_topmost_sequence ();
set_first_insn (top->first);
set_last_insn (top->last);
}
void
pop_topmost_sequence (void)
{
- struct sequence_stack *stack, *top = NULL;
-
- for (stack = seq_stack; stack; stack = stack->next)
- top = stack;
+ struct sequence_stack *top;
+ top = get_topmost_sequence ();
top->first = get_insns ();
top->last = get_last_insn ();
void
end_sequence (void)
{
- struct sequence_stack *tem = seq_stack;
+ struct sequence_stack *tem = get_current_sequence ()->next;
set_first_insn (tem->first);
set_last_insn (tem->last);
- seq_stack = tem->next;
+ get_current_sequence ()->next = tem->next;
memset (tem, 0, sizeof (*tem));
tem->next = free_sequence_stack;
int
in_sequence_p (void)
{
- return seq_stack != 0;
+ return get_current_sequence ()->next != 0;
}
\f
/* Put the various virtual registers into REGNO_REG_RTX. */
/* Return a copy of INSN that can be used in a SEQUENCE delay slot,
on that assumption that INSN itself remains in its original place. */
-rtx
-copy_delay_slot_insn (rtx insn)
+rtx_insn *
+copy_delay_slot_insn (rtx_insn *insn)
{
/* Copy INSN with its rtx_code, all its notes, location etc. */
- insn = copy_rtx (insn);
+ insn = as_a <rtx_insn *> (copy_rtx (insn));
INSN_UID (insn) = cur_insn_uid++;
return insn;
}
cur_debug_insn_uid = 1;
reg_rtx_no = LAST_VIRTUAL_REGISTER + 1;
first_label_num = label_num;
- seq_stack = NULL;
+ get_current_sequence ()->next = NULL;
/* Init the tables that describe all the pseudo regs. */
/* Generate a vector constant for mode MODE and constant value CONSTANT. */
static rtx
-gen_const_vector (enum machine_mode mode, int constant)
+gen_const_vector (machine_mode mode, int constant)
{
rtx tem;
rtvec v;
int units, i;
- enum machine_mode inner;
+ machine_mode inner;
units = GET_MODE_NUNITS (mode);
inner = GET_MODE_INNER (mode);
/* Generate a vector like gen_rtx_raw_CONST_VEC, but use the zero vector when
all elements are zero, and the one vector when all elements are one. */
rtx
-gen_rtx_CONST_VECTOR (enum machine_mode mode, rtvec v)
+gen_rtx_CONST_VECTOR (machine_mode mode, rtvec v)
{
- enum machine_mode inner = GET_MODE_INNER (mode);
+ machine_mode inner = GET_MODE_INNER (mode);
int nunits = GET_MODE_NUNITS (mode);
rtx x;
int i;
init_emit_regs (void)
{
int i;
- enum machine_mode mode;
+ machine_mode mode;
mem_attrs *attrs;
/* Reset register attributes */
- htab_empty (reg_attrs_htab);
+ reg_attrs_htab->empty ();
/* We need reg_raw_mode, so initialize the modes now. */
init_reg_modes_target ();
= gen_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM);
#endif
+ pic_offset_table_rtx = NULL_RTX;
if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
- else
- pic_offset_table_rtx = NULL_RTX;
for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
{
- mode = (enum machine_mode) i;
+ mode = (machine_mode) i;
attrs = ggc_cleared_alloc<mem_attrs> ();
attrs->align = BITS_PER_UNIT;
attrs->addrspace = ADDR_SPACE_GENERIC;
byte_mode = VOIDmode;
word_mode = VOIDmode;
- for (enum machine_mode mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+ for (machine_mode mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
init_emit_once (void)
{
int i;
- enum machine_mode mode;
- enum machine_mode double_mode;
+ machine_mode mode;
+ machine_mode double_mode;
/* Initialize the CONST_INT, CONST_WIDE_INT, CONST_DOUBLE,
CONST_FIXED, and memory attribute hash tables. */
- const_int_htab = htab_create_ggc (37, const_int_htab_hash,
- const_int_htab_eq, NULL);
+ const_int_htab = hash_table<const_int_hasher>::create_ggc (37);
#if TARGET_SUPPORTS_WIDE_INT
- const_wide_int_htab = htab_create_ggc (37, const_wide_int_htab_hash,
- const_wide_int_htab_eq, NULL);
+ const_wide_int_htab = hash_table<const_wide_int_hasher>::create_ggc (37);
#endif
- const_double_htab = htab_create_ggc (37, const_double_htab_hash,
- const_double_htab_eq, NULL);
+ const_double_htab = hash_table<const_double_hasher>::create_ggc (37);
- const_fixed_htab = htab_create_ggc (37, const_fixed_htab_hash,
- const_fixed_htab_eq, NULL);
+ const_fixed_htab = hash_table<const_fixed_hasher>::create_ggc (37);
- reg_attrs_htab = htab_create_ggc (37, reg_attrs_htab_hash,
- reg_attrs_htab_eq, NULL);
+ reg_attrs_htab = hash_table<reg_attr_hasher>::create_ggc (37);
#ifdef INIT_EXPANDERS
/* This is to initialize {init|mark|free}_machine_status before the first
for (mode = MIN_MODE_PARTIAL_INT;
mode <= MAX_MODE_PARTIAL_INT;
- mode = (enum machine_mode)((int)(mode) + 1))
+ mode = (machine_mode)((int)(mode) + 1))
const_tiny_rtx[i][(int) mode] = GEN_INT (i);
}
for (mode = MIN_MODE_PARTIAL_INT;
mode <= MAX_MODE_PARTIAL_INT;
- mode = (enum machine_mode)((int)(mode) + 1))
+ mode = (machine_mode)((int)(mode) + 1))
const_tiny_rtx[3][(int) mode] = constm1_rtx;
for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_INT);
}
for (i = (int) CCmode; i < (int) MAX_MACHINE_MODE; ++i)
- if (GET_MODE_CLASS ((enum machine_mode) i) == MODE_CC)
+ if (GET_MODE_CLASS ((machine_mode) i) == MODE_CC)
const_tiny_rtx[0][i] = const0_rtx;
const_tiny_rtx[0][(int) BImode] = const0_rtx;
if (STORE_FLAG_VALUE == 1)
const_tiny_rtx[1][(int) BImode] = const1_rtx;
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_POINTER_BOUNDS);
+ mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ {
+ wide_int wi_zero = wi::zero (GET_MODE_PRECISION (mode));
+ const_tiny_rtx[0][mode] = immed_wide_int_const (wi_zero, mode);
+ }
+
pc_rtx = gen_rtx_fmt_ (PC, VOIDmode);
ret_rtx = gen_rtx_fmt_ (RETURN, VOIDmode);
simple_return_rtx = gen_rtx_fmt_ (SIMPLE_RETURN, VOIDmode);
cc0_rtx = gen_rtx_fmt_ (CC0, VOIDmode);
+ invalid_insn_rtx = gen_rtx_INSN (VOIDmode,
+ /*prev_insn=*/NULL,
+ /*next_insn=*/NULL,
+ /*bb=*/NULL,
+ /*pattern=*/NULL_RTX,
+ /*location=*/-1,
+ CODE_FOR_nothing,
+ /*reg_notes=*/NULL_RTX);
}
\f
/* Produce exact duplicate of insn INSN after AFTER.
Care updating of libcall regions if present. */
-rtx
-emit_copy_of_insn_after (rtx insn, rtx after)
+rtx_insn *
+emit_copy_of_insn_after (rtx_insn *insn, rtx_insn *after)
{
- rtx new_rtx, link;
+ rtx_insn *new_rtx;
+ rtx link;
switch (GET_CODE (insn))
{
static GTY((deletable)) rtx hard_reg_clobbers [NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
rtx
-gen_hard_reg_clobber (enum machine_mode mode, unsigned int regno)
+gen_hard_reg_clobber (machine_mode mode, unsigned int regno)
{
if (hard_reg_clobbers[mode][regno])
return hard_reg_clobbers[mode][regno];
/* Return lexical scope block insn belongs to. */
tree
-insn_scope (const_rtx insn)
+insn_scope (const rtx_insn *insn)
{
return LOCATION_BLOCK (INSN_LOCATION (insn));
}
/* Return line number of the statement that produced this insn. */
int
-insn_line (const_rtx insn)
+insn_line (const rtx_insn *insn)
{
return LOCATION_LINE (INSN_LOCATION (insn));
}
/* Return source file of the statement that produced this insn. */
const char *
-insn_file (const_rtx insn)
+insn_file (const rtx_insn *insn)
{
return LOCATION_FILE (INSN_LOCATION (insn));
}
+/* Return expanded location of the statement that produced this insn. */
+expanded_location
+insn_location (const rtx_insn *insn)
+{
+ return expand_location (INSN_LOCATION (insn));
+}
+
/* Return true if memory model MODEL requires a pre-operation (release-style)
barrier or a post-operation (acquire-style) barrier. While not universal,
this function matches behavior of several targets. */
bool
need_atomic_barrier_p (enum memmodel model, bool pre)
{
- switch (model & MEMMODEL_MASK)
+ switch (model & MEMMODEL_BASE_MASK)
{
case MEMMODEL_RELAXED:
case MEMMODEL_CONSUME: