/* Register Transfer Language (RTL) definitions for GCC
Copyright (C) 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
#include "vecir.h"
#include "fixed-value.h"
#include "alias.h"
+#include "hashtab.h"
#undef FFS /* Some systems predefine this symbol; don't let it interfere. */
#undef FLOAT /* Likewise. */
#define NEXT_INSN(INSN) XEXP (INSN, 2)
#define BLOCK_FOR_INSN(INSN) XBBDEF (INSN, 3)
-#define INSN_LOCATOR(INSN) XINT (INSN, 4)
+
+/* The body of an insn. */
+#define PATTERN(INSN) XEXP (INSN, 4)
+
+#define INSN_LOCATOR(INSN) XINT (INSN, 5)
/* LOCATION of an RTX if relevant. */
#define RTL_LOCATION(X) (INSN_P (X) ? \
locator_location (INSN_LOCATOR (X)) \
: UNKNOWN_LOCATION)
/* LOCATION of current INSN. */
#define CURR_INSN_LOCATION (locator_location (curr_insn_locator ()))
-/* The body of an insn. */
-#define PATTERN(INSN) XEXP (INSN, 5)
/* Code number of instruction, from when it was recognized.
-1 means this instruction has not been recognized yet. */
but a value from enum reg_note. */
#define REG_NOTES(INSN) XEXP(INSN, 7)
+/* In an ENTRY_VALUE this is the DECL_INCOMING_RTL of the argument in
+ question. */
+#define ENTRY_VALUE_EXP(RTX) (RTL_CHECKC1 (RTX, 0, ENTRY_VALUE).rt_rtx)
+
enum reg_note
{
#define DEF_REG_NOTE(NAME) NAME,
/* DEBUG_EXPR_DECL corresponding to a DEBUG_EXPR RTX. */
#define DEBUG_EXPR_TREE_DECL(RTX) XCTREE (RTX, 0, DEBUG_EXPR)
+/* VAR_DECL/PARM_DECL DEBUG_IMPLICIT_PTR takes address of. */
+#define DEBUG_IMPLICIT_PTR_DECL(RTX) XCTREE (RTX, 0, DEBUG_IMPLICIT_PTR)
+
/* Possible initialization status of a variable. When requested
by the user, this information is tracked and recorded in the DWARF
debug information, along with the variable's location. */
/* In jump.c, each label contains a count of the number
of LABEL_REFs that point at it, so unused labels can be deleted. */
-#define LABEL_NUSES(RTX) XCINT (RTX, 4, CODE_LABEL)
+#define LABEL_NUSES(RTX) XCINT (RTX, 5, CODE_LABEL)
/* Labels carry a two-bit field composed of the ->jump and ->call
bits. This field indicates whether the label is an alternate
/* Once basic blocks are found, each CODE_LABEL starts a chain that
goes through all the LABEL_REFs that jump to that label. The chain
eventually winds up at the CODE_LABEL: it is circular. */
-#define LABEL_REFS(LABEL) XCEXP (LABEL, 5, CODE_LABEL)
+#define LABEL_REFS(LABEL) XCEXP (LABEL, 4, CODE_LABEL)
\f
/* For a REG rtx, REGNO extracts the register number. REGNO can only
be used on RHS. Use SET_REGNO to change the value. */
#define REGNO(RTX) (rhs_regno(RTX))
#define SET_REGNO(RTX,N) (df_ref_change_reg_with_loc (REGNO(RTX), N, RTX), XCUINT (RTX, 0, REG) = N)
+#define SET_REGNO_RAW(RTX,N) (XCUINT (RTX, 0, REG) = N)
/* ORIGINAL_REGNO holds the number the register originally had; for a
pseudo register turned into a hard reg this will hold the old pseudo
not to use an rtx with this cost under any circumstances. */
#define MAX_COST INT_MAX
+/* A structure to hold all available cost information about an rtl
+ expression. */
+struct full_rtx_costs
+{
+ int speed;
+ int size;
+};
+
+/* Initialize a full_rtx_costs structure C to the maximum cost. */
+static inline void
+init_costs_to_max (struct full_rtx_costs *c)
+{
+ c->speed = MAX_COST;
+ c->size = MAX_COST;
+}
+
+/* Initialize a full_rtx_costs structure C to zero cost. */
+static inline void
+init_costs_to_zero (struct full_rtx_costs *c)
+{
+ c->speed = 0;
+ c->size = 0;
+}
+
+/* Compare two full_rtx_costs structures A and B, returning true
+ if A < B when optimizing for speed. */
+static inline bool
+costs_lt_p (struct full_rtx_costs *a, struct full_rtx_costs *b,
+ bool speed)
+{
+ if (speed)
+ return (a->speed < b->speed
+ || (a->speed == b->speed && a->size < b->size));
+ else
+ return (a->size < b->size
+ || (a->size == b->size && a->speed < b->speed));
+}
+
+/* Increase both members of the full_rtx_costs structure C by the
+ cost of N insns. */
+static inline void
+costs_add_n_insns (struct full_rtx_costs *c, int n)
+{
+ c->speed += COSTS_N_INSNS (n);
+ c->size += COSTS_N_INSNS (n);
+}
+
extern void init_rtlanal (void);
extern int rtx_cost (rtx, enum rtx_code, bool);
extern int address_cost (rtx, enum machine_mode, addr_space_t, bool);
+extern void get_full_rtx_cost (rtx, enum rtx_code, struct full_rtx_costs *);
extern unsigned int subreg_lsb (const_rtx);
extern unsigned int subreg_lsb_1 (enum machine_mode, enum machine_mode,
unsigned int);
#define MEM_NOTRAP_P(RTX) \
(RTL_FLAG_CHECK1("MEM_NOTRAP_P", (RTX), MEM)->call)
-/* If VAL is nonzero, set MEM_IN_STRUCT_P and clear MEM_SCALAR_P in
- RTX. Otherwise, vice versa. Use this macro only when you are
- *sure* that you know that the MEM is in a structure, or is a
- scalar. VAL is evaluated only once. */
-#define MEM_SET_IN_STRUCT_P(RTX, VAL) \
-do { \
- if (VAL) \
- { \
- MEM_IN_STRUCT_P (RTX) = 1; \
- MEM_SCALAR_P (RTX) = 0; \
- } \
- else \
- { \
- MEM_IN_STRUCT_P (RTX) = 0; \
- MEM_SCALAR_P (RTX) = 1; \
- } \
-} while (0)
-
/* The memory attribute block. We provide access macros for each value
in the block and provide defaults if none specified. */
#define MEM_ATTRS(RTX) X0MEMATTR (RTX, 1)
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 int rtx_equal_p (const_rtx, const_rtx);
+extern hashval_t iterative_hash_rtx (const_rtx, hashval_t);
/* In emit-rtl.c */
extern rtvec gen_rtvec_v (int, rtx *);
extern rtx get_pool_constant_mark (rtx, bool *);
extern enum machine_mode get_pool_mode (const_rtx);
extern rtx simplify_subtraction (rtx);
+extern void decide_function_section (tree);
/* In function.c */
extern rtx assign_stack_local (enum machine_mode, HOST_WIDE_INT, int);
-extern rtx assign_stack_local_1 (enum machine_mode, HOST_WIDE_INT, int, bool);
+#define ASLK_REDUCE_ALIGN 1
+#define ASLK_RECORD_PAD 2
+extern rtx assign_stack_local_1 (enum machine_mode, HOST_WIDE_INT, int, int);
extern rtx assign_stack_temp (enum machine_mode, HOST_WIDE_INT, int);
extern rtx assign_stack_temp_for_type (enum machine_mode,
HOST_WIDE_INT, int, tree);
extern rtx next_nonnote_insn_bb (rtx);
extern rtx prev_nondebug_insn (rtx);
extern rtx next_nondebug_insn (rtx);
+extern rtx prev_nonnote_nondebug_insn (rtx);
+extern rtx next_nonnote_nondebug_insn (rtx);
extern rtx prev_real_insn (rtx);
extern rtx next_real_insn (rtx);
extern rtx prev_active_insn (rtx);
extern void add_reg_note (rtx, enum reg_note, rtx);
extern void remove_note (rtx, const_rtx);
extern void remove_reg_equal_equiv_notes (rtx);
+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 int volatile_insn_p (const_rtx);
typedef int (*rtx_function) (rtx *, void *);
extern int for_each_rtx (rtx *, rtx_function, void *);
+/* Callback for for_each_inc_dec, to process the autoinc operation OP
+ within MEM that sets DEST to SRC + SRCOFF, or SRC if SRCOFF is
+ NULL. The callback is passed the same opaque ARG passed to
+ for_each_inc_dec. Return zero to continue looking for other
+ autoinc operations, -1 to skip OP's operands, and any other value
+ to interrupt the traversal and return that value to the caller of
+ for_each_inc_dec. */
+typedef int (*for_each_inc_dec_fn) (rtx mem, rtx op, rtx dest, rtx src,
+ rtx srcoff, void *arg);
+extern int for_each_inc_dec (rtx *, for_each_inc_dec_fn, void *arg);
+
typedef int (*rtx_equal_p_callback_function) (const_rtx *, const_rtx *,
rtx *, rtx *);
extern int rtx_equal_p_cb (const_rtx, const_rtx,
extern enum reg_class reg_preferred_class (int);
extern enum reg_class reg_alternate_class (int);
-extern enum reg_class reg_cover_class (int);
+extern enum reg_class reg_allocno_class (int);
extern void setup_reg_classes (int, enum reg_class, enum reg_class,
enum reg_class);
#define HARD_FRAME_POINTER_REGNUM FRAME_POINTER_REGNUM
#endif
+#ifndef HARD_FRAME_POINTER_IS_FRAME_POINTER
+#define HARD_FRAME_POINTER_IS_FRAME_POINTER \
+ (HARD_FRAME_POINTER_REGNUM == FRAME_POINTER_REGNUM)
+#endif
+
+#ifndef HARD_FRAME_POINTER_IS_ARG_POINTER
+#define HARD_FRAME_POINTER_IS_ARG_POINTER \
+ (HARD_FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM)
+#endif
+
/* Index labels for global_rtl. */
enum global_rtl_index
{
GR_PC,
GR_CC0,
+ GR_RETURN,
GR_STACK_POINTER,
GR_FRAME_POINTER,
/* For register elimination to work properly these hard_frame_pointer_rtx,
#if FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM
GR_ARG_POINTER = GR_FRAME_POINTER,
#endif
-#if HARD_FRAME_POINTER_REGNUM == FRAME_POINTER_REGNUM
+#if HARD_FRAME_POINTER_IS_FRAME_POINTER
GR_HARD_FRAME_POINTER = GR_FRAME_POINTER,
#else
GR_HARD_FRAME_POINTER,
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
-#if HARD_FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM
+#if HARD_FRAME_POINTER_IS_ARG_POINTER
GR_ARG_POINTER = GR_HARD_FRAME_POINTER,
#else
GR_ARG_POINTER,
GR_VIRTUAL_STACK_DYNAMIC,
GR_VIRTUAL_OUTGOING_ARGS,
GR_VIRTUAL_CFA,
+ GR_VIRTUAL_PREFERRED_STACK_BOUNDARY,
GR_MAX
};
They are initialized once per compilation unit, then copied into
regno_reg_rtx at the beginning of each function. */
rtx x_initial_regno_reg_rtx[FIRST_PSEUDO_REGISTER];
+
+ /* A sample (mem:M stack_pointer_rtx) rtx for each mode M. */
+ rtx x_top_of_stack[MAX_MACHINE_MODE];
+
+ /* Static hunks of RTL used by the aliasing code; these are treated
+ as persistent to avoid unnecessary RTL allocations. */
+ rtx x_static_reg_base_value[FIRST_PSEUDO_REGISTER];
};
extern GTY(()) struct target_rtl default_target_rtl;
(this_target_rtl->x_pic_offset_table_rtx)
#define return_address_pointer_rtx \
(this_target_rtl->x_return_address_pointer_rtx)
+#define top_of_stack \
+ (this_target_rtl->x_top_of_stack)
/* Standard pieces of rtx, to be substituted directly into things. */
#define pc_rtx (global_rtl[GR_PC])
+#define ret_rtx (global_rtl[GR_RETURN])
#define cc0_rtx (global_rtl[GR_CC0])
/* All references to certain hard regs, except those created
#define VIRTUAL_CFA_REGNUM ((FIRST_VIRTUAL_REGISTER) + 4)
-#define LAST_VIRTUAL_REGISTER ((FIRST_VIRTUAL_REGISTER) + 4)
+#define LAST_VIRTUAL_POINTER_REGISTER ((FIRST_VIRTUAL_REGISTER) + 4)
+
+/* This is replaced by crtl->preferred_stack_boundary / BITS_PER_UNIT
+ when finalized. */
+
+#define virtual_preferred_stack_boundary_rtx \
+ (global_rtl[GR_VIRTUAL_PREFERRED_STACK_BOUNDARY])
+
+#define VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM \
+ ((FIRST_VIRTUAL_REGISTER) + 5)
+
+#define LAST_VIRTUAL_REGISTER ((FIRST_VIRTUAL_REGISTER) + 5)
/* Nonzero if REGNUM is a pointer into the stack frame. */
#define REGNO_PTR_FRAME_P(REGNUM) \
|| (REGNUM) == HARD_FRAME_POINTER_REGNUM \
|| (REGNUM) == ARG_POINTER_REGNUM \
|| ((REGNUM) >= FIRST_VIRTUAL_REGISTER \
- && (REGNUM) <= LAST_VIRTUAL_REGISTER))
+ && (REGNUM) <= LAST_VIRTUAL_POINTER_REGISTER))
/* REGNUM never really appearing in the INSN stream. */
#define INVALID_REGNUM (~(unsigned int) 0)
extern int exp_equiv_p (const_rtx, const_rtx, int, bool);
extern unsigned hash_rtx (const_rtx x, enum machine_mode, int *, int *, bool);
+/* In dse.c */
+extern void check_for_inc_dec (rtx insn);
+
/* In jump.c */
extern int comparison_dominates_p (enum rtx_code, enum rtx_code);
extern int condjump_p (const_rtx);
extern void redirect_jump_2 (rtx, rtx, rtx, int, int);
extern int redirect_jump (rtx, rtx, int);
extern void rebuild_jump_labels (rtx);
+extern void rebuild_jump_labels_chain (rtx);
extern rtx reversed_comparison (const_rtx, enum machine_mode);
extern enum rtx_code reversed_comparison_code (const_rtx, const_rtx);
extern enum rtx_code reversed_comparison_code_parts (enum rtx_code, const_rtx,
/* In sched-ebb.c. */
extern void schedule_ebbs (void);
-/* In haifa-sched.c. */
-extern void fix_sched_param (const char *, const char *);
-
/* In sel-sched-dump.c. */
extern void sel_sched_fix_param (const char *param, const char *val);
extern int sibcall_epilogue_contains (const_rtx);
extern void mark_temp_addr_taken (rtx);
extern void update_temp_slot_address (rtx, rtx);
-extern void maybe_copy_epilogue_insn (rtx, rtx);
+extern void maybe_copy_prologue_epilogue_insn (rtx, rtx);
/* In stmt.c */
extern void expand_null_return (void);
/* In reginfo.c */
extern int reg_classes_intersect_p (reg_class_t, reg_class_t);
-extern int reg_class_subset_p (enum reg_class, enum reg_class);
+extern int reg_class_subset_p (reg_class_t, reg_class_t);
extern void globalize_reg (int);
extern void init_reg_modes_target (void);
extern void init_regs (void);
extern void regclass (rtx, int);
extern void reg_scan (rtx, unsigned int);
extern void fix_register (const char *, int, int);
-extern bool invalid_mode_change_p (unsigned int, enum reg_class,
- enum machine_mode);
+extern bool invalid_mode_change_p (unsigned int, enum reg_class);
/* In reorg.c */
extern void dbr_schedule (rtx);
extern int read_dependence (const_rtx, const_rtx);
extern int anti_dependence (const_rtx, const_rtx);
extern int output_dependence (const_rtx, const_rtx);
+extern int may_alias_p (const_rtx, const_rtx);
extern void init_alias_target (void);
extern void init_alias_analysis (void);
extern void end_alias_analysis (void);
+extern void vt_equate_reg_base_value (const_rtx, const_rtx);
extern bool memory_modified_in_insn_p (const_rtx, const_rtx);
extern rtx find_base_term (rtx);
extern rtx gen_hard_reg_clobber (enum machine_mode, unsigned int);
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);
#ifdef STACK_REGS
extern int stack_regs_mentioned (const_rtx insn);