/* Register Transfer Language (RTL) definitions for GCC
- Copyright (C) 1987-2017 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GCC.
#include "hard-reg-set.h"
+class predefined_function_abi;
+
/* Value used by some passes to "recognize" noop moves as valid
instructions. */
#define NOOP_MOVE_INSN_CODE INT_MAX
/* Structure used to describe the attributes of a MEM. These are hashed
so MEMs that the same attributes share a data structure. This means
they cannot be modified in place. */
-struct GTY(()) mem_attrs
+class GTY(()) mem_attrs
{
+public:
mem_attrs ();
/* The expression that the MEM accesses, or null if not known.
object in the low part of a 4-byte register, the OFFSET field
will be -3 rather than 0. */
-struct GTY((for_user)) reg_attrs {
+class GTY((for_user)) reg_attrs {
+public:
tree decl; /* decl corresponding to REG. */
poly_int64 offset; /* Offset from start of DECL. */
};
tree rt_tree;
basic_block rt_bb;
mem_attrs *rt_mem;
- struct constant_descriptor_rtx *rt_constant;
+ class constant_descriptor_rtx *rt_constant;
struct dw_cfi_node *rt_cfi;
};
1 in a VALUE is SP_BASED_VALUE_P in cselib.c.
1 in a SUBREG generated by LRA for reload insns.
1 in a REG if this is a static chain register.
- 1 in a CALL for calls instrumented by Pointer Bounds Checker.
Dumped as "/j" in RTL dumps. */
unsigned int jump : 1;
/* In a CODE_LABEL, part of the two-bit alternate entry field.
1 in a MEM if it cannot trap.
1 in a CALL_INSN logically equivalent to
ECF_LOOPING_CONST_OR_PURE and DECL_LOOPING_CONST_OR_PURE_P.
+ 1 in a VALUE is SP_DERIVED_VALUE_P in cselib.c.
Dumped as "/c" in RTL dumps. */
unsigned int call : 1;
/* 1 in a REG, MEM, or CONCAT if the value is set at most once, anywhere.
/* A node for constructing singly-linked lists of rtx. */
-class GTY(()) rtx_expr_list : public rtx_def
+struct GTY(()) rtx_expr_list : public rtx_def
{
+private:
/* No extra fields, but adds invariant: (GET_CODE (X) == EXPR_LIST). */
public:
return rt->code == EXPR_LIST;
}
-class GTY(()) rtx_insn_list : public rtx_def
+struct GTY(()) rtx_insn_list : public rtx_def
{
+private:
/* No extra fields, but adds invariant: (GET_CODE (X) == INSN_LIST).
This is an instance of:
/* A node with invariant GET_CODE (X) == SEQUENCE i.e. a vector of rtx,
typically (but not always) of rtx_insn *, used in the late passes. */
-class GTY(()) rtx_sequence : public rtx_def
+struct GTY(()) rtx_sequence : public rtx_def
{
+private:
/* No extra fields, but adds invariant: (GET_CODE (X) == SEQUENCE). */
public:
return rt->code == SEQUENCE;
}
-class GTY(()) rtx_insn : public rtx_def
+struct GTY(()) rtx_insn : public rtx_def
{
public:
/* No extra fields, but adds the invariant:
/* Subclasses of rtx_insn. */
-class GTY(()) rtx_debug_insn : public rtx_insn
+struct GTY(()) rtx_debug_insn : public rtx_insn
{
/* No extra fields, but adds the invariant:
DEBUG_INSN_P (X) aka (GET_CODE (X) == DEBUG_INSN)
from rtl.def. */
};
-class GTY(()) rtx_nonjump_insn : public rtx_insn
+struct GTY(()) rtx_nonjump_insn : public rtx_insn
{
/* No extra fields, but adds the invariant:
NONJUMP_INSN_P (X) aka (GET_CODE (X) == INSN)
from rtl.def. */
};
-class GTY(()) rtx_jump_insn : public rtx_insn
+struct GTY(()) rtx_jump_insn : public rtx_insn
{
public:
/* No extra fields, but adds the invariant:
inline void set_jump_target (rtx_code_label *);
};
-class GTY(()) rtx_call_insn : public rtx_insn
+struct GTY(()) rtx_call_insn : public rtx_insn
{
/* No extra fields, but adds the invariant:
CALL_P (X) aka (GET_CODE (X) == CALL_INSN)
from rtl.def. */
};
-class GTY(()) rtx_jump_table_data : public rtx_insn
+struct GTY(()) rtx_jump_table_data : public rtx_insn
{
/* No extra fields, but adds the invariant:
JUMP_TABLE_DATA_P (X) aka (GET_CODE (INSN) == JUMP_TABLE_DATA)
DEF_RTL_EXPR(JUMP_TABLE_DATA, "jump_table_data", "uuBe0000", RTX_INSN)
from rtl.def. */
-public:
-
/* This can be either:
(a) a table of absolute jumps, in which case PATTERN (this) is an
inline scalar_int_mode get_data_mode () const;
};
-class GTY(()) rtx_barrier : public rtx_insn
+struct GTY(()) rtx_barrier : public rtx_insn
{
/* No extra fields, but adds the invariant:
BARRIER_P (X) aka (GET_CODE (X) == BARRIER)
from rtl.def. */
};
-class GTY(()) rtx_code_label : public rtx_insn
+struct GTY(()) rtx_code_label : public rtx_insn
{
/* No extra fields, but adds the invariant:
LABEL_P (X) aka (GET_CODE (X) == CODE_LABEL)
from rtl.def. */
};
-class GTY(()) rtx_note : public rtx_insn
+struct GTY(()) rtx_note : public rtx_insn
{
/* No extra fields, but adds the invariant:
NOTE_P(X) aka (GET_CODE (X) == NOTE)
#define DEBUG_INSN_P(X) (GET_CODE (X) == DEBUG_INSN)
/* Predicate yielding nonzero iff X is an insn that is not a debug insn. */
-#define NONDEBUG_INSN_P(X) (INSN_P (X) && !DEBUG_INSN_P (X))
+#define NONDEBUG_INSN_P(X) (NONJUMP_INSN_P (X) || JUMP_P (X) || CALL_P (X))
/* Nonzero if DEBUG_MARKER_INSN_P may possibly hold. */
#define MAY_HAVE_DEBUG_MARKER_INSNS debug_nonbind_markers_p
(MAY_HAVE_DEBUG_MARKER_INSNS || MAY_HAVE_DEBUG_BIND_INSNS)
/* Predicate yielding nonzero iff X is a real insn. */
-#define INSN_P(X) \
- (NONJUMP_INSN_P (X) || DEBUG_INSN_P (X) || JUMP_P (X) || CALL_P (X))
+#define INSN_P(X) (NONDEBUG_INSN_P (X) || DEBUG_INSN_P (X))
/* Predicate yielding nonzero iff X is a note insn. */
#define NOTE_P(X) (GET_CODE (X) == NOTE)
#define CONSTANT_P(X) \
(GET_RTX_CLASS (GET_CODE (X)) == RTX_CONST_OBJ)
+/* 1 if X is a LABEL_REF. */
+#define LABEL_REF_P(X) \
+ (GET_CODE (X) == LABEL_REF)
+
/* 1 if X can be used to represent an object. */
#define OBJECT_P(X) \
((GET_RTX_CLASS (GET_CODE (X)) & RTX_OBJ_MASK) == RTX_OBJ_RESULT)
__FUNCTION__); \
&_rtx->u.fld[_n]; }))
+#define RTL_CHECKC3(RTX, N, C1, C2, C3) __extension__ \
+(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N); \
+ const enum rtx_code _code = GET_CODE (_rtx); \
+ if (_code != (C1) && _code != (C2) && _code != (C3)) \
+ rtl_check_failed_code3 (_rtx, (C1), (C2), (C3), __FILE__, \
+ __LINE__, __FUNCTION__); \
+ &_rtx->u.fld[_n]; }))
+
#define RTVEC_ELT(RTVEC, I) __extension__ \
(*({ __typeof (RTVEC) const _rtvec = (RTVEC); const int _i = (I); \
if (_i < 0 || _i >= GET_NUM_ELEM (_rtvec)) \
extern void rtl_check_failed_code2 (const_rtx, enum rtx_code, enum rtx_code,
const char *, int, const char *)
ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void rtl_check_failed_code3 (const_rtx, enum rtx_code, enum rtx_code,
+ enum rtx_code, const char *, int,
+ const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
extern void rtl_check_failed_code_mode (const_rtx, enum rtx_code, machine_mode,
bool, const char *, int, const char *)
ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
#define RTL_CHECK2(RTX, N, C1, C2) ((RTX)->u.fld[N])
#define RTL_CHECKC1(RTX, N, C) ((RTX)->u.fld[N])
#define RTL_CHECKC2(RTX, N, C1, C2) ((RTX)->u.fld[N])
+#define RTL_CHECKC3(RTX, N, C1, C2, C3) ((RTX)->u.fld[N])
#define RTVEC_ELT(RTVEC, I) ((RTVEC)->elem[I])
#define XWINT(RTX, N) ((RTX)->u.hwint[N])
#define CWI_ELT(RTX, I) ((RTX)->u.hwiv.elem[I])
#define XCVECLEN(RTX, N, C) GET_NUM_ELEM (XCVEC (RTX, N, C))
#define XC2EXP(RTX, N, C1, C2) (RTL_CHECKC2 (RTX, N, C1, C2).rt_rtx)
+#define XC3EXP(RTX, N, C1, C2, C3) (RTL_CHECKC3 (RTX, N, C1, C2, C3).rt_rtx)
\f
/* Methods of rtx_expr_list. */
#define GET_REG_NOTE_NAME(MODE) (reg_note_name[(int) (MODE)])
/* This field is only present on CALL_INSNs. It holds a chain of EXPR_LIST of
- USE and CLOBBER expressions.
+ USE, CLOBBER and SET expressions.
USE expressions list the registers filled with arguments that
are passed to the function.
CLOBBER expressions document the registers explicitly clobbered
by this CALL_INSN.
- Pseudo registers can not be mentioned in this list. */
+ SET expressions say that the return value of the call (the SET_DEST)
+ is equivalent to a value available before the call (the SET_SRC).
+ This kind of SET is used when the return value is predictable in
+ advance. It is purely an optimisation hint; unlike USEs and CLOBBERs,
+ it does not affect register liveness.
+
+ Pseudo registers cannot be mentioned in this list. */
#define CALL_INSN_FUNCTION_USAGE(INSN) XEXP(INSN, 7)
/* The label-number of a code-label. The assembler label
for which NOTE_MARKER_LOCATION can be used. */
#define NOTE_MARKER_P(INSN) \
(NOTE_P (INSN) && \
- (NOTE_KIND (INSN) == NOTE_INSN_BEGIN_STMT))
+ (NOTE_KIND (INSN) == NOTE_INSN_BEGIN_STMT \
+ || NOTE_KIND (INSN) == NOTE_INSN_INLINE_ENTRY))
/* Variable declaration and the location of a variable. */
#define PAT_VAR_LOCATION_DECL(PAT) (XCTREE ((PAT), 0, VAR_LOCATION))
(GET_CODE (PATTERN (INSN)) == DEBUG_MARKER \
? (GET_MODE (PATTERN (INSN)) == VOIDmode \
? NOTE_INSN_BEGIN_STMT \
+ : GET_MODE (PATTERN (INSN)) == BLKmode \
+ ? NOTE_INSN_INLINE_ENTRY \
: (enum insn_note)-1) \
: (enum insn_note)-1)
/* Create patterns for debug markers. These and the above abstract
wouldn't be a problem. */
#define GEN_RTX_DEBUG_MARKER_BEGIN_STMT_PAT() \
gen_rtx_DEBUG_MARKER (VOIDmode)
+#define GEN_RTX_DEBUG_MARKER_INLINE_ENTRY_PAT() \
+ gen_rtx_DEBUG_MARKER (BLKmode)
/* The VAR_LOCATION rtx in a DEBUG_INSN. */
#define INSN_VAR_LOCATION(INSN) \
((HOST_WIDE_INT) (CONST_FIXED_VALUE (r)->data.low))
/* For a CONST_VECTOR, return element #n. */
-#define CONST_VECTOR_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
+#define CONST_VECTOR_ELT(RTX, N) const_vector_elt (RTX, N)
/* See rtl.texi for a description of these macros. */
#define CONST_VECTOR_NPATTERNS(RTX) \
#define CONST_VECTOR_ENCODED_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
+/* Return the number of elements encoded directly in a CONST_VECTOR. */
+
+inline unsigned int
+const_vector_encoded_nelts (const_rtx x)
+{
+ return CONST_VECTOR_NPATTERNS (x) * CONST_VECTOR_NELTS_PER_PATTERN (x);
+}
+
/* For a CONST_VECTOR, return the number of elements in a vector. */
-#define CONST_VECTOR_NUNITS(RTX) XCVECLEN (RTX, 0, CONST_VECTOR)
+#define CONST_VECTOR_NUNITS(RTX) GET_MODE_NUNITS (GET_MODE (RTX))
/* For a SUBREG rtx, SUBREG_REG extracts the value we want a subreg of.
SUBREG_BYTE extracts the byte-number. */
inner_mode == the mode of the SUBREG_REG
offset == the SUBREG_BYTE
outer_mode == the mode of the SUBREG itself. */
-struct subreg_shape {
+class subreg_shape {
+public:
subreg_shape (machine_mode, poly_uint16, machine_mode);
bool operator == (const subreg_shape &) const;
bool operator != (const subreg_shape &) const;
extern int address_cost (rtx, machine_mode, addr_space_t, bool);
extern void get_full_rtx_cost (rtx, machine_mode, enum rtx_code, int,
struct full_rtx_costs *);
+extern bool native_encode_rtx (machine_mode, rtx, vec<target_unit> &,
+ unsigned int, unsigned int);
+extern rtx native_decode_rtx (machine_mode, vec<target_unit>,
+ unsigned int);
+extern rtx native_decode_vector_rtx (machine_mode, vec<target_unit>,
+ unsigned int, unsigned int, unsigned int);
extern poly_uint64 subreg_lsb (const_rtx);
-extern poly_uint64 subreg_lsb_1 (machine_mode, machine_mode, poly_uint64);
+extern poly_uint64 subreg_size_lsb (poly_uint64, poly_uint64, poly_uint64);
extern poly_uint64 subreg_size_offset_from_lsb (poly_uint64, poly_uint64,
poly_uint64);
extern bool read_modify_subreg_p (const_rtx);
+/* Given a subreg's OUTER_MODE, INNER_MODE, and SUBREG_BYTE, return the
+ bit offset at which the subreg begins (counting from the least significant
+ bit of the operand). */
+
+inline poly_uint64
+subreg_lsb_1 (machine_mode outer_mode, machine_mode inner_mode,
+ poly_uint64 subreg_byte)
+{
+ return subreg_size_lsb (GET_MODE_SIZE (outer_mode),
+ GET_MODE_SIZE (inner_mode), subreg_byte);
+}
+
/* Return the subreg byte offset for a subreg whose outer mode is
OUTER_MODE, whose inner mode is INNER_MODE, and where there are
LSB_SHIFT *bits* between the lsb of the outer value and the lsb of
#define LRA_SUBREG_P(RTX) \
(RTL_FLAG_CHECK1 ("LRA_SUBREG_P", (RTX), SUBREG)->jump)
-/* True if call is instrumented by Pointer Bounds Checker. */
-#define CALL_EXPR_WITH_BOUNDS_P(RTX) \
- (RTL_FLAG_CHECK1 ("CALL_EXPR_WITH_BOUNDS_P", (RTX), CALL)->jump)
-
/* Access various components of an ASM_OPERANDS rtx. */
#define ASM_OPERANDS_TEMPLATE(RTX) XCSTR (RTX, 0, ASM_OPERANDS)
/* In rtl.c */
extern rtx rtx_alloc (RTX_CODE CXX_MEM_STAT_INFO);
+inline rtx
+rtx_init (rtx rt, RTX_CODE code)
+{
+ memset (rt, 0, RTX_HDR_SIZE);
+ PUT_CODE (rt, code);
+ return rt;
+}
+#define rtx_alloca(code) \
+ rtx_init ((rtx) alloca (RTX_CODE_SIZE ((code))), (code))
extern rtx rtx_alloc_stat_v (RTX_CODE MEM_STAT_DECL, int);
#define rtx_alloc_v(c, SZ) rtx_alloc_stat_v (c MEM_STAT_INFO, SZ)
#define const_wide_int_alloc(NWORDS) \
extern int rtx_equal_p (const_rtx, const_rtx);
extern bool rtvec_all_equal_p (const_rtvec);
-/* Return true if X is some form of vector constant. */
-
-inline bool
-const_vec_p (const_rtx x)
-{
- return VECTOR_MODE_P (GET_MODE (x)) && CONSTANT_P (x);
-}
-
/* Return true if X is a vector constant with a duplicated element value. */
inline bool
const_vec_duplicate_p (const_rtx x)
{
- return ((GET_CODE (x) == CONST_VECTOR
- && CONST_VECTOR_NPATTERNS (x) == 1
- && CONST_VECTOR_DUPLICATE_P (x))
- || (GET_CODE (x) == CONST
- && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE));
+ return (GET_CODE (x) == CONST_VECTOR
+ && CONST_VECTOR_NPATTERNS (x) == 1
+ && CONST_VECTOR_DUPLICATE_P (x));
}
/* Return true if X is a vector constant with a duplicated element value.
inline bool
const_vec_duplicate_p (T x, T *elt)
{
- if (GET_CODE (x) == CONST_VECTOR
- && CONST_VECTOR_NPATTERNS (x) == 1
- && CONST_VECTOR_DUPLICATE_P (x))
+ if (const_vec_duplicate_p (x))
{
*elt = CONST_VECTOR_ENCODED_ELT (x, 0);
return true;
}
- if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE)
- {
- *elt = XEXP (XEXP (x, 0), 0);
- return true;
- }
return false;
}
inline bool
vec_duplicate_p (T x, T *elt)
{
- if (GET_CODE (x) == VEC_DUPLICATE)
+ if (GET_CODE (x) == VEC_DUPLICATE
+ && !VECTOR_MODE_P (GET_MODE (XEXP (x, 0))))
{
*elt = XEXP (x, 0);
return true;
inline T
unwrap_const_vec_duplicate (T x)
{
- if (GET_CODE (x) == CONST_VECTOR
- && CONST_VECTOR_NPATTERNS (x) == 1
- && CONST_VECTOR_DUPLICATE_P (x))
- return CONST_VECTOR_ENCODED_ELT (x, 0);
- if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE)
- return XEXP (XEXP (x, 0), 0);
+ if (const_vec_duplicate_p (x))
+ x = CONST_VECTOR_ELT (x, 0);
return x;
}
/* In emit-rtl.c. */
+extern wide_int const_vector_int_elt (const_rtx, unsigned int);
+extern rtx const_vector_elt (const_rtx, unsigned int);
extern bool const_vec_series_p_1 (const_rtx, rtx *, rtx *);
/* Return true if X is an integer constant vector that contains a linear
&& CONST_VECTOR_NPATTERNS (x) == 1
&& !CONST_VECTOR_DUPLICATE_P (x))
return const_vec_series_p_1 (x, base_out, step_out);
- if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == VEC_SERIES)
- {
- *base_out = XEXP (XEXP (x, 0), 0);
- *step_out = XEXP (XEXP (x, 0), 1);
- return true;
- }
return false;
}
inline bool
partial_subreg_p (machine_mode outermode, machine_mode innermode)
{
- return GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode);
+ /* Modes involved in a subreg must be ordered. In particular, we must
+ always know at compile time whether the subreg is paradoxical. */
+ poly_int64 outer_prec = GET_MODE_PRECISION (outermode);
+ poly_int64 inner_prec = GET_MODE_PRECISION (innermode);
+ gcc_checking_assert (ordered_p (outer_prec, inner_prec));
+ return maybe_lt (outer_prec, inner_prec);
}
/* Likewise return true if X is a subreg that is smaller than the inner
inline bool
paradoxical_subreg_p (machine_mode outermode, machine_mode innermode)
{
- return GET_MODE_PRECISION (outermode) > GET_MODE_PRECISION (innermode);
+ /* Modes involved in a subreg must be ordered. In particular, we must
+ always know at compile time whether the subreg is paradoxical. */
+ poly_int64 outer_prec = GET_MODE_PRECISION (outermode);
+ poly_int64 inner_prec = GET_MODE_PRECISION (innermode);
+ gcc_checking_assert (ordered_p (outer_prec, inner_prec));
+ return maybe_gt (outer_prec, inner_prec);
}
/* Return true if X is a paradoxical subreg, false otherwise. */
extern void decide_function_section (tree);
/* In emit-rtl.c */
-extern rtx_insn *emit_insn_before (rtx, rtx);
+extern rtx_insn *emit_insn_before (rtx, rtx_insn *);
extern rtx_insn *emit_insn_before_noloc (rtx, rtx_insn *, basic_block);
-extern rtx_insn *emit_insn_before_setloc (rtx, rtx_insn *, int);
-extern rtx_jump_insn *emit_jump_insn_before (rtx, rtx);
+extern rtx_insn *emit_insn_before_setloc (rtx, rtx_insn *, location_t);
+extern rtx_jump_insn *emit_jump_insn_before (rtx, rtx_insn *);
extern rtx_jump_insn *emit_jump_insn_before_noloc (rtx, rtx_insn *);
-extern rtx_jump_insn *emit_jump_insn_before_setloc (rtx, rtx_insn *, int);
+extern rtx_jump_insn *emit_jump_insn_before_setloc (rtx, rtx_insn *,
+ location_t);
extern rtx_insn *emit_call_insn_before (rtx, rtx_insn *);
extern rtx_insn *emit_call_insn_before_noloc (rtx, rtx_insn *);
-extern rtx_insn *emit_call_insn_before_setloc (rtx, rtx_insn *, int);
+extern rtx_insn *emit_call_insn_before_setloc (rtx, rtx_insn *, location_t);
extern rtx_insn *emit_debug_insn_before (rtx, rtx_insn *);
-extern rtx_insn *emit_debug_insn_before_noloc (rtx, rtx);
-extern rtx_insn *emit_debug_insn_before_setloc (rtx, rtx, int);
-extern rtx_barrier *emit_barrier_before (rtx);
-extern rtx_code_label *emit_label_before (rtx, rtx_insn *);
+extern rtx_insn *emit_debug_insn_before_noloc (rtx, rtx_insn *);
+extern rtx_insn *emit_debug_insn_before_setloc (rtx, rtx_insn *, location_t);
+extern rtx_barrier *emit_barrier_before (rtx_insn *);
+extern rtx_code_label *emit_label_before (rtx_code_label *, rtx_insn *);
extern rtx_note *emit_note_before (enum insn_note, rtx_insn *);
-extern rtx_insn *emit_insn_after (rtx, rtx);
-extern rtx_insn *emit_insn_after_noloc (rtx, rtx, basic_block);
-extern rtx_insn *emit_insn_after_setloc (rtx, rtx, int);
-extern rtx_jump_insn *emit_jump_insn_after (rtx, rtx);
-extern rtx_jump_insn *emit_jump_insn_after_noloc (rtx, rtx);
-extern rtx_jump_insn *emit_jump_insn_after_setloc (rtx, rtx, int);
-extern rtx_insn *emit_call_insn_after (rtx, rtx);
-extern rtx_insn *emit_call_insn_after_noloc (rtx, rtx);
-extern rtx_insn *emit_call_insn_after_setloc (rtx, rtx, int);
-extern rtx_insn *emit_debug_insn_after (rtx, rtx);
-extern rtx_insn *emit_debug_insn_after_noloc (rtx, rtx);
-extern rtx_insn *emit_debug_insn_after_setloc (rtx, rtx, int);
-extern rtx_barrier *emit_barrier_after (rtx);
-extern rtx_insn *emit_label_after (rtx, rtx_insn *);
+extern rtx_insn *emit_insn_after (rtx, rtx_insn *);
+extern rtx_insn *emit_insn_after_noloc (rtx, rtx_insn *, basic_block);
+extern rtx_insn *emit_insn_after_setloc (rtx, rtx_insn *, location_t);
+extern rtx_jump_insn *emit_jump_insn_after (rtx, rtx_insn *);
+extern rtx_jump_insn *emit_jump_insn_after_noloc (rtx, rtx_insn *);
+extern rtx_jump_insn *emit_jump_insn_after_setloc (rtx, rtx_insn *, location_t);
+extern rtx_insn *emit_call_insn_after (rtx, rtx_insn *);
+extern rtx_insn *emit_call_insn_after_noloc (rtx, rtx_insn *);
+extern rtx_insn *emit_call_insn_after_setloc (rtx, rtx_insn *, location_t);
+extern rtx_insn *emit_debug_insn_after (rtx, rtx_insn *);
+extern rtx_insn *emit_debug_insn_after_noloc (rtx, rtx_insn *);
+extern rtx_insn *emit_debug_insn_after_setloc (rtx, rtx_insn *, location_t);
+extern rtx_barrier *emit_barrier_after (rtx_insn *);
+extern rtx_insn *emit_label_after (rtx_insn *, rtx_insn *);
extern rtx_note *emit_note_after (enum insn_note, rtx_insn *);
extern rtx_insn *emit_insn (rtx);
extern rtx_insn *emit_debug_insn (rtx);
extern rtx_insn *next_nonnote_nondebug_insn (rtx_insn *);
extern rtx_insn *next_nonnote_nondebug_insn_bb (rtx_insn *);
extern rtx_insn *prev_real_insn (rtx_insn *);
-extern rtx_insn *next_real_insn (rtx);
+extern rtx_insn *next_real_insn (rtx_insn *);
+extern rtx_insn *prev_real_nondebug_insn (rtx_insn *);
+extern rtx_insn *next_real_nondebug_insn (rtx);
extern rtx_insn *prev_active_insn (rtx_insn *);
extern rtx_insn *next_active_insn (rtx_insn *);
extern int active_insn_p (const rtx_insn *);
extern enum rtx_code signed_condition (enum rtx_code);
extern void mark_jump_label (rtx, rtx_insn *, int);
+/* Return true if integer comparison operator CODE interprets its operands
+ as unsigned. */
+
+inline bool
+unsigned_condition_p (enum rtx_code code)
+{
+ return unsigned_condition (code) == code;
+}
+
/* In jump.c */
extern rtx_insn *delete_related_insns (rtx);
/* In reginfo.c */
extern machine_mode choose_hard_reg_mode (unsigned int, unsigned int,
- bool);
+ const predefined_function_abi *);
extern const HARD_REG_SET &simplifiable_subregs (const subreg_shape &);
/* In emit-rtl.c */
extern rtx set_for_reg_notes (rtx);
extern rtx set_unique_reg_note (rtx, enum reg_note, rtx);
extern rtx set_dst_reg_note (rtx, enum reg_note, rtx, rtx);
-extern void set_insn_deleted (rtx);
+extern void set_insn_deleted (rtx_insn *);
/* Functions in rtlanal.c */
extern rtx single_set_2 (const rtx_insn *, const_rtx);
extern bool contains_symbol_ref_p (const_rtx);
extern bool contains_symbolic_reference_p (const_rtx);
+extern bool contains_constant_pool_address_p (const_rtx);
+extern void add_auto_inc_notes (rtx_insn *, rtx);
/* Handle the cheap and common cases inline for performance. */
extern int rtx_unstable_p (const_rtx);
extern bool rtx_varies_p (const_rtx, bool);
extern bool rtx_addr_varies_p (const_rtx, bool);
-extern rtx get_call_rtx_from (rtx);
+extern rtx get_call_rtx_from (const rtx_insn *);
+extern tree get_call_fndecl (const rtx_insn *);
extern HOST_WIDE_INT get_integer_term (const_rtx);
extern rtx get_related_value (const_rtx);
extern bool offset_within_block_p (const_rtx, HOST_WIDE_INT);
extern void record_hard_reg_uses (rtx *, void *);
extern void find_all_hard_regs (const_rtx, HARD_REG_SET *);
extern void find_all_hard_reg_sets (const rtx_insn *, HARD_REG_SET *, bool);
-extern void note_stores (const_rtx, void (*) (rtx, const_rtx, void *), void *);
+extern void note_pattern_stores (const_rtx,
+ void (*) (rtx, const_rtx, void *), void *);
+extern void note_stores (const rtx_insn *,
+ void (*) (rtx, const_rtx, void *), void *);
extern void note_uses (rtx *, void (*) (rtx *, void *), void *);
extern int dead_or_set_p (const rtx_insn *, const_rtx);
extern int dead_or_set_regno_p (const rtx_insn *, unsigned int);
extern void add_shallow_copy_of_reg_note (rtx_insn *, rtx);
extern rtx duplicate_reg_note (rtx);
extern void remove_note (rtx_insn *, const_rtx);
-extern bool remove_reg_equal_equiv_notes (rtx_insn *);
+extern bool remove_reg_equal_equiv_notes (rtx_insn *, bool = false);
extern void remove_reg_equal_equiv_notes_for_regno (unsigned int);
extern int side_effects_p (const_rtx);
extern int volatile_refs_p (const_rtx);
extern bool can_nonlocal_goto (const rtx_insn *);
extern void copy_reg_eh_region_note_forward (rtx, rtx_insn *, rtx);
extern void copy_reg_eh_region_note_backward (rtx, rtx_insn *, rtx);
-extern int inequality_comparisons_p (const_rtx);
extern rtx replace_rtx (rtx, rtx, rtx, bool = false);
extern void replace_label (rtx *, rtx, rtx, bool);
extern void replace_label_in_insn (rtx_insn *, rtx_insn *, rtx_insn *, bool);
extern bool rtx_referenced_p (const_rtx, const_rtx);
extern bool tablejump_p (const rtx_insn *, rtx_insn **, rtx_jump_table_data **);
+extern rtx tablejump_casesi_pattern (const rtx_insn *insn);
extern int computed_jump_p (const rtx_insn *);
extern bool tls_referenced_p (const_rtx);
extern bool contains_mem_rtx_p (rtx x);
rtx x_static_reg_base_value[FIRST_PSEUDO_REGISTER];
/* The default memory attributes for each mode. */
- struct mem_attrs *x_mode_mem_attrs[(int) MAX_MACHINE_MODE];
+ class mem_attrs *x_mode_mem_attrs[(int) MAX_MACHINE_MODE];
/* Track if RTL has been initialized. */
bool target_specific_initialized;
#ifndef GENERATOR_FILE
/* Return the attributes of a MEM rtx. */
-static inline const struct mem_attrs *
+static inline const class mem_attrs *
get_mem_attrs (const_rtx x)
{
- struct mem_attrs *attrs;
+ class mem_attrs *attrs;
attrs = MEM_ATTRS (x);
if (!attrs)
extern rtx gen_rtx_CONST_INT (machine_mode, HOST_WIDE_INT);
extern rtx gen_rtx_CONST_VECTOR (machine_mode, rtvec);
extern void set_mode_and_regno (rtx, machine_mode, unsigned int);
+extern rtx init_raw_REG (rtx, machine_mode, unsigned int);
extern rtx gen_raw_REG (machine_mode, unsigned int);
+#define alloca_raw_REG(mode, regno) \
+ init_raw_REG (rtx_alloca (REG), (mode), (regno))
extern rtx gen_rtx_REG (machine_mode, unsigned int);
extern rtx gen_rtx_SUBREG (machine_mode, rtx, poly_uint64);
extern rtx gen_rtx_MEM (machine_mode, rtx);
extern void unshare_all_rtl_in_chain (rtx_insn *);
extern void verify_rtl_sharing (void);
extern void add_insn (rtx_insn *);
-extern void add_insn_before (rtx, rtx, basic_block);
-extern void add_insn_after (rtx, rtx, basic_block);
-extern void remove_insn (rtx);
+extern void add_insn_before (rtx_insn *, rtx_insn *, basic_block);
+extern void add_insn_after (rtx_insn *, rtx_insn *, basic_block);
+extern void remove_insn (rtx_insn *);
extern rtx_insn *emit (rtx, bool = true);
extern void emit_insn_at_entry (rtx);
extern rtx gen_lowpart_SUBREG (machine_mode, rtx);
extern void expand_naked_return (void);
extern void emit_jump (rtx);
+/* Memory operation built-ins differ by return value. Mapping
+ of the enum values is following:
+ - RETURN_BEGIN - return destination, e.g. memcpy
+ - RETURN_END - return destination + n, e.g. mempcpy
+ - RETURN_END_MINUS_ONE - return a pointer to the terminating
+ null byte of the string, e.g. strcpy
+*/
+
+enum memop_ret
+{
+ RETURN_BEGIN,
+ RETURN_END,
+ RETURN_END_MINUS_ONE
+};
+
/* In expr.c */
extern rtx move_by_pieces (rtx, rtx, unsigned HOST_WIDE_INT,
- unsigned int, int);
+ unsigned int, memop_ret);
extern poly_int64 find_args_size_adjust (rtx_insn *);
extern poly_int64 fixup_args_size_notes (rtx_insn *, rtx_insn *, poly_int64);
/* In gcse.c */
extern bool can_copy_p (machine_mode);
extern bool can_assign_to_reg_without_clobbers_p (rtx, machine_mode);
+extern rtx_insn *prepare_copy_insn (rtx, rtx);
+
+/* In cprop.c */
extern rtx fis_get_condition (rtx_insn *);
/* In ira.c */
/* In var-tracking.c */
extern unsigned int variable_tracking_main (void);
+extern void delete_vta_debug_insns (bool);
/* In stor-layout.c. */
extern void get_mode_bounds (scalar_int_mode, int,
extern void insn_locations_finalize (void);
extern void set_curr_insn_location (location_t);
extern location_t curr_insn_location (void);
+extern void set_insn_locations (rtx_insn *, location_t);
/* rtl-error.c */
extern void _fatal_insn_not_found (const_rtx, const char *, int, const char *)
Available only for functions that has been already assembled. */
struct GTY(()) cgraph_rtl_info {
- unsigned int preferred_incoming_stack_boundary;
+ unsigned int preferred_incoming_stack_boundary;
- /* Call unsaved hard registers really used by the corresponding
- function (including ones used by functions called by the
- function). */
+ /* Which registers the function clobbers, either directly or by
+ calling another function. */
HARD_REG_SET function_used_regs;
- /* Set if function_used_regs is valid. */
- unsigned function_used_regs_valid: 1;
};
/* If loads from memories of mode MODE always sign or zero extend,
{
poly_int64 suboffset;
x = strip_offset (x, &suboffset);
- *offset += suboffset;
+ *offset = poly_uint64 (*offset) + suboffset;
}
return x;
}
+/* Return true if X is an operation that always operates on the full
+ registers for WORD_REGISTER_OPERATIONS architectures. */
+
+inline bool
+word_register_operation_p (const_rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case CONST_INT:
+ case ROTATE:
+ case ROTATERT:
+ case SIGN_EXTRACT:
+ case ZERO_EXTRACT:
+ return false;
+
+ default:
+ return true;
+ }
+}
+
/* gtype-desc.c. */
extern void gt_ggc_mx (rtx &);
extern void gt_pch_nx (rtx &);