/* Register Transfer Language (RTL) definitions for GCC
- Copyright (C) 1987-2016 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GCC.
machmode.h and other files to exist and would not normally have been
included by coretypes.h. */
#ifdef GENERATOR_FILE
-#include "machmode.h"
-#include "signop.h"
-#include "wide-int.h"
-#include "double-int.h"
#include "real.h"
#include "fixed-value.h"
#include "statistics.h"
#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.
This expression might be larger than the memory reference itself.
(In other words, the MEM might access only part of the object.) */
/* The offset of the memory reference from the start of EXPR.
Only valid if OFFSET_KNOWN_P. */
- HOST_WIDE_INT offset;
+ poly_int64 offset;
/* The size of the memory reference in bytes. Only valid if
SIZE_KNOWN_P. */
- HOST_WIDE_INT size;
+ poly_int64 size;
/* The alias set of the memory reference. */
alias_set_type alias;
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. */
- HOST_WIDE_INT offset; /* Offset from start of DECL. */
+ poly_int64 offset; /* Offset from start of DECL. */
};
/* Common union for an element of an rtx. */
{
int rt_int;
unsigned int rt_uint;
+ poly_uint16_pod rt_subreg;
const char *rt_str;
rtx rt_rtx;
rtvec rt_rtvec;
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;
};
#define CWI_PUT_NUM_ELEM(RTX, NUM) \
(RTL_FLAG_CHECK1("CWI_PUT_NUM_ELEM", (RTX), CONST_WIDE_INT)->u2.num_elem = (NUM))
+struct GTY((variable_size)) const_poly_int_def {
+ trailing_wide_ints<NUM_POLY_INT_COEFFS> coeffs;
+};
+
/* RTL expression ("rtx"). */
/* The GTY "desc" and "tag" options below are a kludge: we need a desc
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.
/* In a CONST_WIDE_INT (aka hwivec_def), this is the number of
HOST_WIDE_INTs in the hwivec_def. */
unsigned int num_elem;
+
+ /* Information about a CONST_VECTOR. */
+ struct
+ {
+ /* The value of CONST_VECTOR_NPATTERNS. */
+ unsigned int npatterns : 16;
+
+ /* The value of CONST_VECTOR_NELTS_PER_PATTERN. */
+ unsigned int nelts_per_pattern : 8;
+
+ /* For future expansion. */
+ unsigned int unused : 8;
+ } const_vector;
} GTY ((skip)) u2;
/* The first element of the operands of this rtx.
struct real_value rv;
struct fixed_value fv;
struct hwivec_def hwiv;
+ struct const_poly_int_def cpi;
} GTY ((special ("rtx_def"), desc ("GET_CODE (&%0)"))) u;
};
/* 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
This method gets the underlying vec. */
inline rtvec get_labels () const;
+ 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 CASE_CONST_UNIQUE \
case CONST_INT: \
case CONST_WIDE_INT: \
+ case CONST_POLY_INT: \
case CONST_DOUBLE: \
case CONST_FIXED
#define CASE_CONST_ANY \
case CONST_INT: \
case CONST_WIDE_INT: \
+ case CONST_POLY_INT: \
case CONST_DOUBLE: \
case CONST_FIXED: \
case CONST_VECTOR
/* Predicate yielding nonzero iff X is an rtx for a constant integer. */
#define CONST_WIDE_INT_P(X) (GET_CODE (X) == CONST_WIDE_INT)
+/* Predicate yielding nonzero iff X is an rtx for a polynomial constant
+ integer. */
+#define CONST_POLY_INT_P(X) \
+ (NUM_POLY_INT_COEFFS > 1 && GET_CODE (X) == CONST_POLY_INT)
+
/* Predicate yielding nonzero iff X is an rtx for a constant fixed-point. */
#define CONST_FIXED_P(X) (GET_CODE (X) == CONST_FIXED)
#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
+/* Nonzero if DEBUG_BIND_INSN_P may possibly hold. */
+#define MAY_HAVE_DEBUG_BIND_INSNS flag_var_tracking_assignments
/* Nonzero if DEBUG_INSN_P may possibly hold. */
-#define MAY_HAVE_DEBUG_INSNS (flag_var_tracking_assignments)
+#define MAY_HAVE_DEBUG_INSNS \
+ (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_bounds (const_rtx, int, const char *, int,
const char *)
- ATTRIBUTE_NORETURN;
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
extern void rtl_check_failed_type1 (const_rtx, int, int, const char *, int,
const char *)
- ATTRIBUTE_NORETURN;
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
extern void rtl_check_failed_type2 (const_rtx, int, int, int, const char *,
int, const char *)
- ATTRIBUTE_NORETURN;
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
extern void rtl_check_failed_code1 (const_rtx, enum rtx_code, const char *,
int, const char *)
- ATTRIBUTE_NORETURN;
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
extern void rtl_check_failed_code2 (const_rtx, enum rtx_code, enum rtx_code,
const char *, int, const char *)
- ATTRIBUTE_NORETURN;
+ 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_NORETURN ATTRIBUTE_COLD;
extern void rtl_check_failed_block_symbol (const char *, int, const char *)
- ATTRIBUTE_NORETURN;
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
extern void cwi_check_failed_bounds (const_rtx, int, const char *, int,
const char *)
- ATTRIBUTE_NORETURN;
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
extern void rtvec_check_failed_bounds (const_rtvec, int, const char *, int,
const char *)
- ATTRIBUTE_NORETURN;
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
#else /* not ENABLE_RTL_CHECKING */
#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])
extern void rtl_check_failed_flag (const char *, const_rtx, const char *,
int, const char *)
- ATTRIBUTE_NORETURN
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD
;
#else /* not ENABLE_RTL_FLAG_CHECKING */
#define XCINT(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_int)
#define XCUINT(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_uint)
+#define XCSUBREG(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_subreg)
#define XCSTR(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_str)
#define XCEXP(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_rtx)
#define XCVEC(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_rtvec)
#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. */
return XVEC (pat, 1); /* presumably an ADDR_DIFF_VEC */
}
+/* Return the mode of the data in the table, which is always a scalar
+ integer. */
+
+inline scalar_int_mode
+rtx_jump_table_data::get_data_mode () const
+{
+ return as_a <scalar_int_mode> (GET_MODE (PATTERN (this)));
+}
+
+/* If LABEL is followed by a jump table, return the table, otherwise
+ return null. */
+
+inline rtx_jump_table_data *
+jump_table_for_label (const rtx_code_label *label)
+{
+ return safe_dyn_cast <rtx_jump_table_data *> (NEXT_INSN (label));
+}
+
#define RTX_FRAME_RELATED_P(RTX) \
(RTL_FLAG_CHECK6 ("RTX_FRAME_RELATED_P", (RTX), DEBUG_INSN, INSN, \
CALL_INSN, JUMP_INSN, BARRIER, SET)->frame_related)
#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
#define NOTE_EH_HANDLER(INSN) XCINT (INSN, 3, NOTE)
#define NOTE_BASIC_BLOCK(INSN) XCBBDEF (INSN, 3, NOTE)
#define NOTE_VAR_LOCATION(INSN) XCEXP (INSN, 3, NOTE)
+#define NOTE_MARKER_LOCATION(INSN) XCUINT (INSN, 3, NOTE)
#define NOTE_CFI(INSN) XCCFI (INSN, 3, NOTE)
#define NOTE_LABEL_NUMBER(INSN) XCINT (INSN, 3, NOTE)
#define NOTE_INSN_BASIC_BLOCK_P(INSN) \
(NOTE_P (INSN) && NOTE_KIND (INSN) == NOTE_INSN_BASIC_BLOCK)
+/* Nonzero if INSN is a debug nonbind marker note,
+ 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_INLINE_ENTRY))
+
/* Variable declaration and the location of a variable. */
#define PAT_VAR_LOCATION_DECL(PAT) (XCTREE ((PAT), 0, VAR_LOCATION))
#define PAT_VAR_LOCATION_LOC(PAT) (XCEXP ((PAT), 1, VAR_LOCATION))
#define NOTE_VAR_LOCATION_STATUS(NOTE) \
PAT_VAR_LOCATION_STATUS (NOTE_VAR_LOCATION (NOTE))
+/* Evaluate to TRUE if INSN is a debug insn that denotes a variable
+ location/value tracking annotation. */
+#define DEBUG_BIND_INSN_P(INSN) \
+ (DEBUG_INSN_P (INSN) \
+ && (GET_CODE (PATTERN (INSN)) \
+ == VAR_LOCATION))
+/* Evaluate to TRUE if INSN is a debug insn that denotes a program
+ source location marker. */
+#define DEBUG_MARKER_INSN_P(INSN) \
+ (DEBUG_INSN_P (INSN) \
+ && (GET_CODE (PATTERN (INSN)) \
+ != VAR_LOCATION))
+/* Evaluate to the marker kind. */
+#define INSN_DEBUG_MARKER_KIND(INSN) \
+ (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
+ the representation, so that it's easier to get rid of the abuse of
+ the mode to hold the marker kind. Other marker types are
+ envisioned, so a single bit flag won't do; maybe separate RTL codes
+ 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) PATTERN (INSN)
+#define INSN_VAR_LOCATION(INSN) \
+ (RTL_FLAG_CHECK1 ("INSN_VAR_LOCATION", PATTERN (INSN), VAR_LOCATION))
+/* A pointer to the VAR_LOCATION rtx in a DEBUG_INSN. */
+#define INSN_VAR_LOCATION_PTR(INSN) \
+ (&PATTERN (INSN))
/* Accessors for a tree-expanded var location debug insn. */
#define INSN_VAR_LOCATION_DECL(INSN) \
#define SET_REGNO(RTX, N) (df_ref_change_reg_with_loc (RTX, N))
/* Return the number of consecutive registers in a REG. This is always
- 1 for pseudo registers and is determined by HARD_REGNO_NREGS for
+ 1 for pseudo registers and is determined by TARGET_HARD_REGNO_NREGS for
hard registers. */
#define REG_NREGS(RTX) (REG_CHECK (RTX)->nregs)
#define CONST_WIDE_INT_NUNITS(RTX) CWI_GET_NUM_ELEM (RTX)
#define CONST_WIDE_INT_ELT(RTX, N) CWI_ELT (RTX, N)
+/* For a CONST_POLY_INT, CONST_POLY_INT_COEFFS gives access to the
+ individual coefficients, in the form of a trailing_wide_ints structure. */
+#define CONST_POLY_INT_COEFFS(RTX) \
+ (RTL_FLAG_CHECK1("CONST_POLY_INT_COEFFS", (RTX), \
+ CONST_POLY_INT)->u.cpi.coeffs)
+
/* For a CONST_DOUBLE:
#if TARGET_SUPPORTS_WIDE_INT == 0
For a VOIDmode, there are two integers CONST_DOUBLE_LOW is the
((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) \
+ (RTL_FLAG_CHECK1 ("CONST_VECTOR_NPATTERNS", (RTX), CONST_VECTOR) \
+ ->u2.const_vector.npatterns)
+
+#define CONST_VECTOR_NELTS_PER_PATTERN(RTX) \
+ (RTL_FLAG_CHECK1 ("CONST_VECTOR_NELTS_PER_PATTERN", (RTX), CONST_VECTOR) \
+ ->u2.const_vector.nelts_per_pattern)
+
+#define CONST_VECTOR_DUPLICATE_P(RTX) \
+ (CONST_VECTOR_NELTS_PER_PATTERN (RTX) == 1)
+
+#define CONST_VECTOR_STEPPED_P(RTX) \
+ (CONST_VECTOR_NELTS_PER_PATTERN (RTX) == 3)
+
+#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. */
#define SUBREG_REG(RTX) XCEXP (RTX, 0, SUBREG)
-#define SUBREG_BYTE(RTX) XCUINT (RTX, 1, SUBREG)
+#define SUBREG_BYTE(RTX) XCSUBREG (RTX, 1, SUBREG)
/* in rtlanal.c */
/* Return the right cost to give to an operation
inner_mode == the mode of the SUBREG_REG
offset == the SUBREG_BYTE
outer_mode == the mode of the SUBREG itself. */
-struct subreg_shape {
- subreg_shape (machine_mode, unsigned int, machine_mode);
+class subreg_shape {
+public:
+ subreg_shape (machine_mode, poly_uint16, machine_mode);
bool operator == (const subreg_shape &) const;
bool operator != (const subreg_shape &) const;
- unsigned int unique_id () const;
+ unsigned HOST_WIDE_INT unique_id () const;
machine_mode inner_mode;
- unsigned int offset;
+ poly_uint16 offset;
machine_mode outer_mode;
};
inline
subreg_shape::subreg_shape (machine_mode inner_mode_in,
- unsigned int offset_in,
+ poly_uint16 offset_in,
machine_mode outer_mode_in)
: inner_mode (inner_mode_in), offset (offset_in), outer_mode (outer_mode_in)
{}
subreg_shape::operator == (const subreg_shape &other) const
{
return (inner_mode == other.inner_mode
- && offset == other.offset
+ && known_eq (offset, other.offset)
&& outer_mode == other.outer_mode);
}
current mode is anywhere near being 65536 bytes in size, so the
id comfortably fits in an int. */
-inline unsigned int
+inline unsigned HOST_WIDE_INT
subreg_shape::unique_id () const
{
- STATIC_ASSERT (MAX_MACHINE_MODE <= 256);
- return (int) inner_mode + ((int) outer_mode << 8) + (offset << 16);
+ { STATIC_ASSERT (MAX_MACHINE_MODE <= 256); }
+ { STATIC_ASSERT (NUM_POLY_INT_COEFFS <= 3); }
+ { STATIC_ASSERT (sizeof (offset.coeffs[0]) <= 2); }
+ int res = (int) inner_mode + ((int) outer_mode << 8);
+ for (int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ res += (HOST_WIDE_INT) offset.coeffs[i] << ((1 + i) * 16);
+ return res;
}
/* Return the shape of a SUBREG rtx. */
/* The address space. */
addr_space_t as;
+ /* True if this is an RTX_AUTOINC address. */
+ bool autoinc_p;
+
/* A pointer to the top-level address. */
rtx *outer;
/* If BASE is nonnull, this is the code of the rtx that contains it. */
enum rtx_code base_outer_code;
-
- /* True if this is an RTX_AUTOINC address. */
- bool autoinc_p;
};
/* This is used to bundle an rtx and a mode together so that the pair
inline unsigned int
wi::int_traits <rtx_mode_t>::get_precision (const rtx_mode_t &x)
{
- gcc_checking_assert (x.second != BLKmode && x.second != VOIDmode);
- return GET_MODE_PRECISION (x.second);
+ return GET_MODE_PRECISION (as_a <scalar_mode> (x.second));
}
inline wi::storage_ref
inline wi::hwi_with_prec
wi::shwi (HOST_WIDE_INT val, machine_mode mode)
{
- return shwi (val, GET_MODE_PRECISION (mode));
+ return shwi (val, GET_MODE_PRECISION (as_a <scalar_mode> (mode)));
}
/* Produce the smallest number that is represented in MODE. The precision
inline wide_int
wi::min_value (machine_mode mode, signop sgn)
{
- return min_value (GET_MODE_PRECISION (mode), sgn);
+ return min_value (GET_MODE_PRECISION (as_a <scalar_mode> (mode)), sgn);
}
/* Produce the largest number that is represented in MODE. The precision
inline wide_int
wi::max_value (machine_mode mode, signop sgn)
{
- return max_value (GET_MODE_PRECISION (mode), sgn);
+ return max_value (GET_MODE_PRECISION (as_a <scalar_mode> (mode)), sgn);
+}
+
+namespace wi
+{
+ typedef poly_int<NUM_POLY_INT_COEFFS,
+ generic_wide_int <wide_int_ref_storage <false, false> > >
+ rtx_to_poly_wide_ref;
+ rtx_to_poly_wide_ref to_poly_wide (const_rtx, machine_mode);
+}
+
+/* Return the value of a CONST_POLY_INT in its native precision. */
+
+inline wi::rtx_to_poly_wide_ref
+const_poly_int_value (const_rtx x)
+{
+ poly_int<NUM_POLY_INT_COEFFS, WIDE_INT_REF_FOR (wide_int)> res;
+ for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ res.coeffs[i] = CONST_POLY_INT_COEFFS (x)[i];
+ return res;
+}
+
+/* Return true if X is a scalar integer or a CONST_POLY_INT. The value
+ can then be extracted using wi::to_poly_wide. */
+
+inline bool
+poly_int_rtx_p (const_rtx x)
+{
+ return CONST_SCALAR_INT_P (x) || CONST_POLY_INT_P (x);
+}
+
+/* Access X (which satisfies poly_int_rtx_p) as a poly_wide_int.
+ MODE is the mode of X. */
+
+inline wi::rtx_to_poly_wide_ref
+wi::to_poly_wide (const_rtx x, machine_mode mode)
+{
+ if (CONST_POLY_INT_P (x))
+ return const_poly_int_value (x);
+ return rtx_mode_t (const_cast<rtx> (x), mode);
+}
+
+/* Return the value of X as a poly_int64. */
+
+inline poly_int64
+rtx_to_poly_int64 (const_rtx x)
+{
+ if (CONST_POLY_INT_P (x))
+ {
+ poly_int64 res;
+ for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ res.coeffs[i] = CONST_POLY_INT_COEFFS (x)[i].to_shwi ();
+ return res;
+ }
+ return INTVAL (x);
+}
+
+/* Return true if arbitrary value X is an integer constant that can
+ be represented as a poly_int64. Store the value in *RES if so,
+ otherwise leave it unmodified. */
+
+inline bool
+poly_int_rtx_p (const_rtx x, poly_int64_pod *res)
+{
+ if (CONST_INT_P (x))
+ {
+ *res = INTVAL (x);
+ return true;
+ }
+ if (CONST_POLY_INT_P (x))
+ {
+ for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ if (!wi::fits_shwi_p (CONST_POLY_INT_COEFFS (x)[i]))
+ return false;
+ for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ res->coeffs[i] = CONST_POLY_INT_COEFFS (x)[i].to_shwi ();
+ return true;
+ }
+ return false;
}
extern void init_rtlanal (void);
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 unsigned int subreg_lsb (const_rtx);
-extern unsigned int subreg_lsb_1 (machine_mode, machine_mode,
- unsigned int);
-extern unsigned int subreg_regno_offset (unsigned int, machine_mode,
- unsigned int, machine_mode);
+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_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
+ the inner value. This is the inverse of subreg_lsb_1 (which converts
+ byte offsets to bit shifts). */
+
+inline poly_uint64
+subreg_offset_from_lsb (machine_mode outer_mode,
+ machine_mode inner_mode,
+ poly_uint64 lsb_shift)
+{
+ return subreg_size_offset_from_lsb (GET_MODE_SIZE (outer_mode),
+ GET_MODE_SIZE (inner_mode), lsb_shift);
+}
+
+extern unsigned int subreg_regno_offset (unsigned int, machine_mode,
+ poly_uint64, machine_mode);
extern bool subreg_offset_representable_p (unsigned int, machine_mode,
- unsigned int, machine_mode);
+ poly_uint64, machine_mode);
extern unsigned int subreg_regno (const_rtx);
extern int simplify_subreg_regno (unsigned int, machine_mode,
- unsigned int, machine_mode);
+ poly_uint64, machine_mode);
extern unsigned int subreg_nregs (const_rtx);
extern unsigned int subreg_nregs_with_regno (unsigned int, const_rtx);
extern unsigned HOST_WIDE_INT nonzero_bits (const_rtx, machine_mode);
#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)
}
#endif
+/* A convenience macro to validate the arguments of a zero_extract
+ expression. It determines whether SIZE lies inclusively within
+ [1, RANGE], POS lies inclusively within between [0, RANGE - 1]
+ and the sum lies inclusively within [1, RANGE]. RANGE must be
+ >= 1, but SIZE and POS may be negative. */
+#define EXTRACT_ARGS_IN_RANGE(SIZE, POS, RANGE) \
+ (IN_RANGE ((POS), 0, (unsigned HOST_WIDE_INT) (RANGE) - 1) \
+ && IN_RANGE ((SIZE), 1, (unsigned HOST_WIDE_INT) (RANGE) \
+ - (unsigned HOST_WIDE_INT)(POS)))
+
/* In explow.c */
extern HOST_WIDE_INT trunc_int_for_mode (HOST_WIDE_INT, machine_mode);
-extern rtx plus_constant (machine_mode, rtx, HOST_WIDE_INT, bool = false);
+extern poly_int64 trunc_int_for_mode (poly_int64, machine_mode);
+extern rtx plus_constant (machine_mode, rtx, poly_int64, bool = false);
+extern HOST_WIDE_INT get_stack_check_protect (void);
/* In rtl.c */
-extern rtx rtx_alloc_stat (RTX_CODE MEM_STAT_DECL);
-#define rtx_alloc(c) rtx_alloc_stat (c MEM_STAT_INFO)
+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) \
/* In rtl.c */
extern unsigned int rtx_size (const_rtx);
-extern rtx shallow_copy_rtx_stat (const_rtx MEM_STAT_DECL);
-#define shallow_copy_rtx(a) shallow_copy_rtx_stat (a MEM_STAT_INFO)
+extern rtx shallow_copy_rtx (const_rtx CXX_MEM_STAT_INFO);
extern int rtx_equal_p (const_rtx, const_rtx);
extern bool rtvec_all_equal_p (const_rtvec);
inline bool
const_vec_duplicate_p (const_rtx x)
{
- return GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0));
+ 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.
{
if (const_vec_duplicate_p (x))
{
- *elt = CONST_VECTOR_ELT (x, 0);
+ *elt = CONST_VECTOR_ENCODED_ELT (x, 0);
return true;
}
return false;
}
+/* Return true if X is a vector with a duplicated element value, either
+ constant or nonconstant. Store the duplicated element in *ELT if so. */
+
+template <typename T>
+inline bool
+vec_duplicate_p (T x, T *elt)
+{
+ if (GET_CODE (x) == VEC_DUPLICATE
+ && !VECTOR_MODE_P (GET_MODE (XEXP (x, 0))))
+ {
+ *elt = XEXP (x, 0);
+ return true;
+ }
+ return const_vec_duplicate_p (x, elt);
+}
+
/* If X is a vector constant with a duplicated element value, return that
element value, otherwise return X. */
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
+ series of the form:
+
+ { B, B + S, B + 2 * S, B + 3 * S, ... }
+
+ for a nonzero S. Store B and S in *BASE_OUT and *STEP_OUT on sucess. */
+
+inline bool
+const_vec_series_p (const_rtx x, rtx *base_out, rtx *step_out)
+{
+ if (GET_CODE (x) == CONST_VECTOR
+ && CONST_VECTOR_NPATTERNS (x) == 1
+ && !CONST_VECTOR_DUPLICATE_P (x))
+ return const_vec_series_p_1 (x, base_out, step_out);
+ return false;
+}
+
+/* Return true if X is a vector that contains a linear series of the
+ form:
+
+ { B, B + S, B + 2 * S, B + 3 * S, ... }
+
+ where B and S are constant or nonconstant. Store B and S in
+ *BASE_OUT and *STEP_OUT on sucess. */
+
+inline bool
+vec_series_p (const_rtx x, rtx *base_out, rtx *step_out)
+{
+ if (GET_CODE (x) == VEC_SERIES)
+ {
+ *base_out = XEXP (x, 0);
+ *step_out = XEXP (x, 1);
+ return true;
+ }
+ return const_vec_series_p (x, base_out, step_out);
+}
+
+/* Return the unpromoted (outer) mode of SUBREG_PROMOTED_VAR_P subreg X. */
+
+inline scalar_int_mode
+subreg_unpromoted_mode (rtx x)
+{
+ gcc_checking_assert (SUBREG_PROMOTED_VAR_P (x));
+ return as_a <scalar_int_mode> (GET_MODE (x));
+}
+
+/* Return the promoted (inner) mode of SUBREG_PROMOTED_VAR_P subreg X. */
+
+inline scalar_int_mode
+subreg_promoted_mode (rtx x)
+{
+ gcc_checking_assert (SUBREG_PROMOTED_VAR_P (x));
+ return as_a <scalar_int_mode> (GET_MODE (SUBREG_REG (x)));
+}
+
/* In emit-rtl.c */
extern rtvec gen_rtvec_v (int, rtx *);
extern rtvec gen_rtvec_v (int, rtx_insn **);
extern rtx gen_reg_rtx (machine_mode);
-extern rtx gen_rtx_REG_offset (rtx, machine_mode, unsigned int, int);
+extern rtx gen_rtx_REG_offset (rtx, machine_mode, unsigned int, poly_int64);
extern rtx gen_reg_rtx_offset (rtx, machine_mode, int);
extern rtx gen_reg_rtx_and_attrs (rtx);
extern rtx_code_label *gen_label_rtx (void);
/* In emit-rtl.c */
extern rtx gen_highpart (machine_mode, rtx);
extern rtx gen_highpart_mode (machine_mode, machine_mode, rtx);
-extern rtx operand_subword (rtx, unsigned int, int, machine_mode);
+extern rtx operand_subword (rtx, poly_uint64, int, machine_mode);
/* In emit-rtl.c */
-extern rtx operand_subword_force (rtx, unsigned int, machine_mode);
-extern bool paradoxical_subreg_p (const_rtx);
+extern rtx operand_subword_force (rtx, poly_uint64, machine_mode);
extern int subreg_lowpart_p (const_rtx);
-extern unsigned int subreg_lowpart_offset (machine_mode,
- machine_mode);
-extern unsigned int subreg_highpart_offset (machine_mode,
- machine_mode);
-extern int byte_lowpart_offset (machine_mode, machine_mode);
+extern poly_uint64 subreg_size_lowpart_offset (poly_uint64, poly_uint64);
+
+/* Return true if a subreg of mode OUTERMODE would only access part of
+ an inner register with mode INNERMODE. The other bits of the inner
+ register would then be "don't care" on read. The behavior for writes
+ depends on REGMODE_NATURAL_SIZE; bits in the same REGMODE_NATURAL_SIZE-d
+ chunk would be clobbered but other bits would be preserved. */
+
+inline bool
+partial_subreg_p (machine_mode outermode, machine_mode 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
+ register. Use read_modify_subreg_p to test whether writing to such
+ a subreg preserves any part of the inner register. */
+
+inline bool
+partial_subreg_p (const_rtx x)
+{
+ if (GET_CODE (x) != SUBREG)
+ return false;
+ return partial_subreg_p (GET_MODE (x), GET_MODE (SUBREG_REG (x)));
+}
+
+/* Return true if a subreg with the given outer and inner modes is
+ paradoxical. */
+
+inline bool
+paradoxical_subreg_p (machine_mode outermode, machine_mode 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. */
+
+inline bool
+paradoxical_subreg_p (const_rtx x)
+{
+ if (GET_CODE (x) != SUBREG)
+ return false;
+ return paradoxical_subreg_p (GET_MODE (x), GET_MODE (SUBREG_REG (x)));
+}
+
+/* Return the SUBREG_BYTE for an OUTERMODE lowpart of an INNERMODE value. */
+
+inline poly_uint64
+subreg_lowpart_offset (machine_mode outermode, machine_mode innermode)
+{
+ return subreg_size_lowpart_offset (GET_MODE_SIZE (outermode),
+ GET_MODE_SIZE (innermode));
+}
+
+/* Given that a subreg has outer mode OUTERMODE and inner mode INNERMODE,
+ return the smaller of the two modes if they are different sizes,
+ otherwise return the outer mode. */
+
+inline machine_mode
+narrower_subreg_mode (machine_mode outermode, machine_mode innermode)
+{
+ return paradoxical_subreg_p (outermode, innermode) ? innermode : outermode;
+}
+
+/* Given that a subreg has outer mode OUTERMODE and inner mode INNERMODE,
+ return the mode that is big enough to hold both the outer and inner
+ values. Prefer the outer mode in the event of a tie. */
+
+inline machine_mode
+wider_subreg_mode (machine_mode outermode, machine_mode innermode)
+{
+ return partial_subreg_p (outermode, innermode) ? innermode : outermode;
+}
+
+/* Likewise for subreg X. */
+
+inline machine_mode
+wider_subreg_mode (const_rtx x)
+{
+ return wider_subreg_mode (GET_MODE (x), GET_MODE (SUBREG_REG (x)));
+}
+
+extern poly_uint64 subreg_size_highpart_offset (poly_uint64, poly_uint64);
+
+/* Return the SUBREG_BYTE for an OUTERMODE highpart of an INNERMODE value. */
+
+inline poly_uint64
+subreg_highpart_offset (machine_mode outermode, machine_mode innermode)
+{
+ return subreg_size_highpart_offset (GET_MODE_SIZE (outermode),
+ GET_MODE_SIZE (innermode));
+}
+
+extern poly_int64 byte_lowpart_offset (machine_mode, machine_mode);
+extern poly_int64 subreg_memory_offset (machine_mode, machine_mode,
+ poly_uint64);
+extern poly_int64 subreg_memory_offset (const_rtx);
extern rtx make_safe_from (rtx, rtx);
-extern rtx convert_memory_address_addr_space_1 (machine_mode, rtx,
+extern rtx convert_memory_address_addr_space_1 (scalar_int_mode, rtx,
addr_space_t, bool, bool);
-extern rtx convert_memory_address_addr_space (machine_mode, rtx,
+extern rtx convert_memory_address_addr_space (scalar_int_mode, rtx,
addr_space_t);
#define convert_memory_address(to_mode,x) \
convert_memory_address_addr_space ((to_mode), (x), ADDR_SPACE_GENERIC)
extern double_int rtx_to_double_int (const_rtx);
#endif
extern void cwi_output_hex (FILE *, const_rtx);
-#ifndef GENERATOR_FILE
-extern rtx immed_wide_int_const (const wide_int_ref &, machine_mode);
-#endif
#if TARGET_SUPPORTS_WIDE_INT == 0
extern rtx immed_double_const (HOST_WIDE_INT, HOST_WIDE_INT,
machine_mode);
#endif
+extern rtx immed_wide_int_const (const poly_wide_int_ref &, machine_mode);
/* In varasm.c */
extern rtx force_const_mem (machine_mode, rtx);
struct function;
extern rtx get_pool_constant (const_rtx);
extern rtx get_pool_constant_mark (rtx, bool *);
-extern machine_mode get_pool_mode (const_rtx);
+extern fixed_size_mode get_pool_mode (const_rtx);
extern rtx simplify_subtraction (rtx);
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 *previous_insn (rtx_insn *);
extern rtx_insn *next_insn (rtx_insn *);
extern rtx_insn *prev_nonnote_insn (rtx_insn *);
-extern rtx_insn *prev_nonnote_insn_bb (rtx_insn *);
extern rtx_insn *next_nonnote_insn (rtx_insn *);
-extern rtx_insn *next_nonnote_insn_bb (rtx_insn *);
extern rtx_insn *prev_nondebug_insn (rtx_insn *);
extern rtx_insn *next_nondebug_insn (rtx_insn *);
extern rtx_insn *prev_nonnote_nondebug_insn (rtx_insn *);
+extern rtx_insn *prev_nonnote_nondebug_insn_bb (rtx_insn *);
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 emit-rtl.c */
extern rtx_insn *try_split (rtx, rtx_insn *, int);
-extern int split_branch_probability;
/* In insn-recog.c (generated by genrecog). */
extern rtx_insn *split_insns (rtx, rtx_insn *);
/* In simplify-rtx.c */
+
+/* A class that records the context in which a simplification
+ is being mode. */
+class simplify_context
+{
+public:
+ rtx simplify_unary_operation (rtx_code, machine_mode, rtx, machine_mode);
+ rtx simplify_binary_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_ternary_operation (rtx_code, machine_mode, machine_mode,
+ rtx, rtx, rtx);
+ rtx simplify_relational_operation (rtx_code, machine_mode, machine_mode,
+ rtx, rtx);
+ rtx simplify_subreg (machine_mode, rtx, machine_mode, poly_uint64);
+
+ rtx lowpart_subreg (machine_mode, rtx, machine_mode);
+
+ rtx simplify_merge_mask (rtx, rtx, int);
+
+ rtx simplify_gen_unary (rtx_code, machine_mode, rtx, machine_mode);
+ rtx simplify_gen_binary (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_gen_ternary (rtx_code, machine_mode, machine_mode,
+ rtx, rtx, rtx);
+ rtx simplify_gen_relational (rtx_code, machine_mode, machine_mode, rtx, rtx);
+ rtx simplify_gen_subreg (machine_mode, rtx, machine_mode, poly_uint64);
+
+ /* Tracks the level of MEM nesting for the value being simplified:
+ 0 means the value is not in a MEM, >0 means it is. This is needed
+ because the canonical representation of multiplication is different
+ inside a MEM than outside. */
+ unsigned int mem_depth = 0;
+
+private:
+ rtx simplify_truncation (machine_mode, rtx, machine_mode);
+ rtx simplify_byte_swapping_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_associative_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_distributive_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_logical_relational_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_binary_operation_series (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_distribute_over_subregs (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_shift_const_int (rtx_code, machine_mode, rtx, unsigned int);
+ rtx simplify_plus_minus (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_cond_clz_ctz (rtx, rtx_code, rtx, rtx);
+
+ rtx simplify_unary_operation_1 (rtx_code, machine_mode, rtx);
+ rtx simplify_binary_operation_1 (rtx_code, machine_mode, rtx, rtx, rtx, rtx);
+ rtx simplify_ternary_operation_1 (rtx_code, machine_mode, machine_mode,
+ rtx, rtx, rtx);
+ rtx simplify_relational_operation_1 (rtx_code, machine_mode, machine_mode,
+ rtx, rtx);
+};
+
+inline rtx
+simplify_unary_operation (rtx_code code, machine_mode mode, rtx op,
+ machine_mode op_mode)
+{
+ return simplify_context ().simplify_unary_operation (code, mode, op,
+ op_mode);
+}
+
+inline rtx
+simplify_binary_operation (rtx_code code, machine_mode mode, rtx op0, rtx op1)
+{
+ return simplify_context ().simplify_binary_operation (code, mode, op0, op1);
+}
+
+inline rtx
+simplify_ternary_operation (rtx_code code, machine_mode mode,
+ machine_mode op0_mode, rtx op0, rtx op1, rtx op2)
+{
+ return simplify_context ().simplify_ternary_operation (code, mode, op0_mode,
+ op0, op1, op2);
+}
+
+inline rtx
+simplify_relational_operation (rtx_code code, machine_mode mode,
+ machine_mode op_mode, rtx op0, rtx op1)
+{
+ return simplify_context ().simplify_relational_operation (code, mode,
+ op_mode, op0, op1);
+}
+
+inline rtx
+simplify_subreg (machine_mode outermode, rtx op, machine_mode innermode,
+ poly_uint64 byte)
+{
+ return simplify_context ().simplify_subreg (outermode, op, innermode, byte);
+}
+
+inline rtx
+simplify_gen_unary (rtx_code code, machine_mode mode, rtx op,
+ machine_mode op_mode)
+{
+ return simplify_context ().simplify_gen_unary (code, mode, op, op_mode);
+}
+
+inline rtx
+simplify_gen_binary (rtx_code code, machine_mode mode, rtx op0, rtx op1)
+{
+ return simplify_context ().simplify_gen_binary (code, mode, op0, op1);
+}
+
+inline rtx
+simplify_gen_ternary (rtx_code code, machine_mode mode, machine_mode op0_mode,
+ rtx op0, rtx op1, rtx op2)
+{
+ return simplify_context ().simplify_gen_ternary (code, mode, op0_mode,
+ op0, op1, op2);
+}
+
+inline rtx
+simplify_gen_relational (rtx_code code, machine_mode mode,
+ machine_mode op_mode, rtx op0, rtx op1)
+{
+ return simplify_context ().simplify_gen_relational (code, mode, op_mode,
+ op0, op1);
+}
+
+inline rtx
+simplify_gen_subreg (machine_mode outermode, rtx op, machine_mode innermode,
+ poly_uint64 byte)
+{
+ return simplify_context ().simplify_gen_subreg (outermode, op,
+ innermode, byte);
+}
+
+inline rtx
+lowpart_subreg (machine_mode outermode, rtx op, machine_mode innermode)
+{
+ return simplify_context ().lowpart_subreg (outermode, op, innermode);
+}
+
extern rtx simplify_const_unary_operation (enum rtx_code, machine_mode,
rtx, machine_mode);
-extern rtx simplify_unary_operation (enum rtx_code, machine_mode, rtx,
- machine_mode);
extern rtx simplify_const_binary_operation (enum rtx_code, machine_mode,
rtx, rtx);
-extern rtx simplify_binary_operation (enum rtx_code, machine_mode, rtx,
- rtx);
-extern rtx simplify_ternary_operation (enum rtx_code, machine_mode,
- machine_mode, rtx, rtx, rtx);
extern rtx simplify_const_relational_operation (enum rtx_code,
machine_mode, rtx, rtx);
-extern rtx simplify_relational_operation (enum rtx_code, machine_mode,
- machine_mode, rtx, rtx);
-extern rtx simplify_gen_binary (enum rtx_code, machine_mode, rtx, rtx);
-extern rtx simplify_gen_unary (enum rtx_code, machine_mode, rtx,
- machine_mode);
-extern rtx simplify_gen_ternary (enum rtx_code, machine_mode,
- machine_mode, rtx, rtx, rtx);
-extern rtx simplify_gen_relational (enum rtx_code, machine_mode,
- machine_mode, rtx, rtx);
-extern rtx simplify_subreg (machine_mode, rtx, machine_mode,
- unsigned int);
-extern rtx simplify_gen_subreg (machine_mode, rtx, machine_mode,
- unsigned int);
-extern rtx lowpart_subreg (machine_mode, rtx, machine_mode);
extern rtx simplify_replace_fn_rtx (rtx, const_rtx,
rtx (*fn) (rtx, const_rtx, void *), void *);
extern rtx simplify_replace_rtx (rtx, const_rtx, 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 rtx simple_regno_set (rtx, unsigned int);
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. */
return single_set_2 (insn, PATTERN (insn));
}
-extern machine_mode get_address_mode (rtx mem);
+extern scalar_int_mode get_address_mode (rtx mem);
extern int rtx_addr_can_trap_p (const_rtx);
extern bool nonzero_address_p (const_rtx);
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 split_const (rtx, rtx *, rtx *);
+extern rtx strip_offset (rtx, poly_int64_pod *);
+extern poly_int64 get_args_size (const_rtx);
extern bool unsigned_reg_p (rtx);
extern int reg_mentioned_p (const_rtx, const_rtx);
extern int count_occurrences (const_rtx, const_rtx, 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, const_rtx);
-extern int dead_or_set_regno_p (const_rtx, unsigned int);
+extern int dead_or_set_p (const rtx_insn *, const_rtx);
+extern int dead_or_set_regno_p (const rtx_insn *, unsigned int);
extern rtx find_reg_note (const_rtx, enum reg_note, const_rtx);
extern rtx find_regno_note (const_rtx, enum reg_note, unsigned int);
extern rtx find_reg_equal_equiv_note (const_rtx);
extern int find_regno_fusage (const_rtx, enum rtx_code, unsigned int);
extern rtx alloc_reg_note (enum reg_note, rtx, rtx);
extern void add_reg_note (rtx, enum reg_note, rtx);
-extern void add_int_reg_note (rtx, enum reg_note, int);
+extern void add_int_reg_note (rtx_insn *, enum reg_note, int);
+extern void add_args_size_note (rtx_insn *, poly_int64);
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 void 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, 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);
+extern bool register_asm_p (const_rtx);
/* Overload for refers_to_regno_p for checking a single register. */
inline bool
extern rtx_insn *find_first_parameter_load (rtx_insn *, rtx_insn *);
extern bool keep_with_call_p (const rtx_insn *);
extern bool label_is_jump_target_p (const_rtx, const rtx_insn *);
-extern int insn_rtx_cost (rtx, bool);
+extern int pattern_cost (rtx, bool);
+extern int insn_cost (rtx_insn *, bool);
extern unsigned seq_cost (const rtx_insn *, bool);
/* Given an insn and condition, return a canonical description of
};
extern void subreg_get_info (unsigned int, machine_mode,
- unsigned int, machine_mode,
+ poly_uint64, machine_mode,
struct subreg_info *);
/* lists.c */
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 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, int);
+extern rtx gen_rtx_SUBREG (machine_mode, rtx, poly_uint64);
extern rtx gen_rtx_MEM (machine_mode, rtx);
extern rtx gen_rtx_VAR_LOCATION (machine_mode, tree, rtx,
enum var_init_status);
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 rtx gen_frame_mem (machine_mode, rtx);
extern rtx gen_tmp_stack_mem (machine_mode, rtx);
extern bool validate_subreg (machine_mode, machine_mode,
- const_rtx, unsigned int);
+ const_rtx, poly_uint64);
/* In combine.c */
extern unsigned int extended_count (const_rtx, machine_mode, int);
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);
-extern HOST_WIDE_INT find_args_size_adjust (rtx_insn *);
-extern int fixup_args_size_notes (rtx_insn *, rtx_insn *, 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 expmed.c */
extern void init_expmed (void);
/* 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 */
LCT_RETURNS_TWICE = 5
};
-extern void emit_library_call (rtx, enum libcall_type, machine_mode, int,
- ...);
-extern rtx emit_library_call_value (rtx, rtx, enum libcall_type,
- machine_mode, int, ...);
+extern rtx emit_library_call_value_1 (int, rtx, rtx, enum libcall_type,
+ machine_mode, int, rtx_mode_t *);
+
+/* Output a library call and discard the returned value. FUN is the
+ address of the function, as a SYMBOL_REF rtx, and OUTMODE is the mode
+ of the (discarded) return value. FN_TYPE is LCT_NORMAL for `normal'
+ calls, LCT_CONST for `const' calls, LCT_PURE for `pure' calls, or
+ another LCT_ value for other types of library calls.
+
+ There are different overloads of this function for different numbers
+ of arguments. In each case the argument value is followed by its mode. */
+
+inline void
+emit_library_call (rtx fun, libcall_type fn_type, machine_mode outmode)
+{
+ emit_library_call_value_1 (0, fun, NULL_RTX, fn_type, outmode, 0, NULL);
+}
+
+inline void
+emit_library_call (rtx fun, libcall_type fn_type, machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode)
+{
+ rtx_mode_t args[] = { rtx_mode_t (arg1, arg1_mode) };
+ emit_library_call_value_1 (0, fun, NULL_RTX, fn_type, outmode, 1, args);
+}
+
+inline void
+emit_library_call (rtx fun, libcall_type fn_type, machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode,
+ rtx arg2, machine_mode arg2_mode)
+{
+ rtx_mode_t args[] = {
+ rtx_mode_t (arg1, arg1_mode),
+ rtx_mode_t (arg2, arg2_mode)
+ };
+ emit_library_call_value_1 (0, fun, NULL_RTX, fn_type, outmode, 2, args);
+}
+
+inline void
+emit_library_call (rtx fun, libcall_type fn_type, machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode,
+ rtx arg2, machine_mode arg2_mode,
+ rtx arg3, machine_mode arg3_mode)
+{
+ rtx_mode_t args[] = {
+ rtx_mode_t (arg1, arg1_mode),
+ rtx_mode_t (arg2, arg2_mode),
+ rtx_mode_t (arg3, arg3_mode)
+ };
+ emit_library_call_value_1 (0, fun, NULL_RTX, fn_type, outmode, 3, args);
+}
+
+inline void
+emit_library_call (rtx fun, libcall_type fn_type, machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode,
+ rtx arg2, machine_mode arg2_mode,
+ rtx arg3, machine_mode arg3_mode,
+ rtx arg4, machine_mode arg4_mode)
+{
+ rtx_mode_t args[] = {
+ rtx_mode_t (arg1, arg1_mode),
+ rtx_mode_t (arg2, arg2_mode),
+ rtx_mode_t (arg3, arg3_mode),
+ rtx_mode_t (arg4, arg4_mode)
+ };
+ emit_library_call_value_1 (0, fun, NULL_RTX, fn_type, outmode, 4, args);
+}
+
+/* Like emit_library_call, but return the value produced by the call.
+ Use VALUE to store the result if it is nonnull, otherwise pick a
+ convenient location. */
+
+inline rtx
+emit_library_call_value (rtx fun, rtx value, libcall_type fn_type,
+ machine_mode outmode)
+{
+ return emit_library_call_value_1 (1, fun, value, fn_type, outmode, 0, NULL);
+}
+
+inline rtx
+emit_library_call_value (rtx fun, rtx value, libcall_type fn_type,
+ machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode)
+{
+ rtx_mode_t args[] = { rtx_mode_t (arg1, arg1_mode) };
+ return emit_library_call_value_1 (1, fun, value, fn_type, outmode, 1, args);
+}
+
+inline rtx
+emit_library_call_value (rtx fun, rtx value, libcall_type fn_type,
+ machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode,
+ rtx arg2, machine_mode arg2_mode)
+{
+ rtx_mode_t args[] = {
+ rtx_mode_t (arg1, arg1_mode),
+ rtx_mode_t (arg2, arg2_mode)
+ };
+ return emit_library_call_value_1 (1, fun, value, fn_type, outmode, 2, args);
+}
+
+inline rtx
+emit_library_call_value (rtx fun, rtx value, libcall_type fn_type,
+ machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode,
+ rtx arg2, machine_mode arg2_mode,
+ rtx arg3, machine_mode arg3_mode)
+{
+ rtx_mode_t args[] = {
+ rtx_mode_t (arg1, arg1_mode),
+ rtx_mode_t (arg2, arg2_mode),
+ rtx_mode_t (arg3, arg3_mode)
+ };
+ return emit_library_call_value_1 (1, fun, value, fn_type, outmode, 3, args);
+}
+
+inline rtx
+emit_library_call_value (rtx fun, rtx value, libcall_type fn_type,
+ machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode,
+ rtx arg2, machine_mode arg2_mode,
+ rtx arg3, machine_mode arg3_mode,
+ rtx arg4, machine_mode arg4_mode)
+{
+ rtx_mode_t args[] = {
+ rtx_mode_t (arg1, arg1_mode),
+ rtx_mode_t (arg2, arg2_mode),
+ rtx_mode_t (arg3, arg3_mode),
+ rtx_mode_t (arg4, arg4_mode)
+ };
+ return emit_library_call_value_1 (1, fun, value, fn_type, outmode, 4, args);
+}
/* In varasm.c */
extern void init_varasm_once (void);
extern rtx make_debug_expr_from_rtl (const_rtx);
/* In read-rtl.c */
+#ifdef GENERATOR_FILE
extern bool read_rtx (const char *, vec<rtx> *);
+#endif
/* In alias.c */
extern rtx canon_rtx (rtx);
extern rtx get_reg_known_value (unsigned int);
extern bool get_reg_known_equiv_p (unsigned int);
extern rtx get_reg_base_value (unsigned int);
+extern rtx extract_mem_from_operand (rtx);
#ifdef STACK_REGS
extern int stack_regs_mentioned (const_rtx insn);
/* 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 (machine_mode, int, machine_mode,
- rtx *, rtx *);
+extern void get_mode_bounds (scalar_int_mode, int,
+ scalar_int_mode, rtx *, rtx *);
/* In loop-iv.c */
extern rtx canon_condition (rtx);
{
rtx (*gen_lowpart) (machine_mode, rtx);
rtx (*gen_lowpart_no_emit) (machine_mode, rtx);
- rtx (*reg_nonzero_bits) (const_rtx, machine_mode, const_rtx, machine_mode,
- unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT *);
- rtx (*reg_num_sign_bit_copies) (const_rtx, machine_mode, const_rtx, machine_mode,
- unsigned int, unsigned int *);
+ rtx (*reg_nonzero_bits) (const_rtx, scalar_int_mode, scalar_int_mode,
+ unsigned HOST_WIDE_INT *);
+ rtx (*reg_num_sign_bit_copies) (const_rtx, scalar_int_mode, scalar_int_mode,
+ unsigned int *);
bool (*reg_truncated_to_mode) (machine_mode, const_rtx);
/* Whenever you add entries here, make sure you adjust rtlhooks-def.h. */
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 *)
- ATTRIBUTE_NORETURN;
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
extern void _fatal_insn (const char *, const_rtx, const char *, int, const char *)
- ATTRIBUTE_NORETURN;
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
#define fatal_insn(msgid, insn) \
_fatal_insn (msgid, insn, __FILE__, __LINE__, __FUNCTION__)
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,
inline rtx_code
load_extend_op (machine_mode mode)
{
- if (SCALAR_INT_MODE_P (mode)
- && GET_MODE_PRECISION (mode) < BITS_PER_WORD)
- return LOAD_EXTEND_OP (mode);
+ scalar_int_mode int_mode;
+ if (is_a <scalar_int_mode> (mode, &int_mode)
+ && GET_MODE_PRECISION (int_mode) < BITS_PER_WORD)
+ return LOAD_EXTEND_OP (int_mode);
return UNKNOWN;
}
+/* If X is a PLUS of a base and a constant offset, add the constant to *OFFSET
+ and return the base. Return X otherwise. */
+
+inline rtx
+strip_offset_and_add (rtx x, poly_int64_pod *offset)
+{
+ if (GET_CODE (x) == PLUS)
+ {
+ poly_int64 suboffset;
+ x = strip_offset (x, &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 &);