/* Variable tracking routines for the GNU compiler.
- Copyright (C) 2002-2014 Free Software Foundation, Inc.
+ Copyright (C) 2002-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
+#include "cfghooks.h"
#include "rtl.h"
+#include "alias.h"
#include "tree.h"
#include "varasm.h"
#include "stor-layout.h"
-#include "hash-map.h"
-#include "hash-table.h"
-#include "basic-block.h"
+#include "cfgrtl.h"
+#include "cfganal.h"
#include "tm_p.h"
-#include "hard-reg-set.h"
#include "flags.h"
#include "insn-config.h"
#include "reload.h"
-#include "sbitmap.h"
#include "alloc-pool.h"
-#include "fibheap.h"
#include "regs.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "stmt.h"
#include "expr.h"
#include "tree-pass.h"
-#include "bitmap.h"
#include "tree-dfa.h"
#include "tree-ssa.h"
#include "cselib.h"
#include "diagnostic.h"
#include "tree-pretty-print.h"
#include "recog.h"
-#include "tm_p.h"
-#include "alias.h"
+#include "rtl-iter.h"
+#include "fibonacci_heap.h"
+
+typedef fibonacci_heap <long, basic_block_def> bb_heap_t;
+typedef fibonacci_node <long, basic_block_def> bb_heap_node_t;
/* var-tracking.c assumes that tree code with the same value as VALUE rtx code
has no chance to appear in REG_EXPR/MEM_EXPRs and isn't a decl.
};
/* Structure holding information about micro operation. */
-typedef struct micro_operation_def
+struct micro_operation
{
/* Type of micro operation. */
enum micro_operation_type type;
/* Stack adjustment. */
HOST_WIDE_INT adjust;
} u;
-} micro_operation;
+};
/* A declaration of a variable, or an RTL value being handled like a
register is described by a chain of these structures.
The chains are pretty short (usually 1 or 2 elements) and thus
chain is the best data structure. */
-typedef struct attrs_def
+struct attrs
{
/* Pointer to next member of the list. */
- struct attrs_def *next;
+ attrs *next;
/* The rtx of register. */
rtx loc;
/* Offset from start of DECL. */
HOST_WIDE_INT offset;
-} *attrs;
+};
/* Structure for chaining the locations. */
-typedef struct location_chain_def
+struct location_chain
{
/* Next element in the chain. */
- struct location_chain_def *next;
+ location_chain *next;
/* The location (REG, MEM or VALUE). */
rtx loc;
/* Initialized? */
enum var_init_status init;
-} *location_chain;
+};
/* A vector of loc_exp_dep holds the active dependencies of a one-part
DV on VALUEs, i.e., the VALUEs expanded so as to form the current
location of DV. Each entry is also part of VALUE' s linked-list of
backlinks back to DV. */
-typedef struct loc_exp_dep_s
+struct loc_exp_dep
{
/* The dependent DV. */
decl_or_value dv;
/* The dependency VALUE or DECL_DEBUG. */
rtx value;
/* The next entry in VALUE's backlinks list. */
- struct loc_exp_dep_s *next;
+ struct loc_exp_dep *next;
/* A pointer to the pointer to this entry (head or prev's next) in
the doubly-linked list. */
- struct loc_exp_dep_s **pprev;
-} loc_exp_dep;
+ struct loc_exp_dep **pprev;
+};
/* This data structure holds information about the depth of a variable
expansion. */
-typedef struct expand_depth_struct
+struct expand_depth
{
/* This measures the complexity of the expanded expression. It
grows by one for each level of expansion that adds more than one
/* This counts the number of ENTRY_VALUE expressions in an
expansion. We want to minimize their use. */
int entryvals;
-} expand_depth;
+};
/* This data structure is allocated for one-part variables at the time
of emitting notes. */
};
/* Structure describing one part of variable. */
-typedef struct variable_part_def
+struct variable_part
{
/* Chain of locations of the part. */
- location_chain loc_chain;
+ location_chain *loc_chain;
/* Location which was last emitted to location list. */
rtx cur_loc;
/* Pointer to auxiliary data, if var->onepart and emit_notes. */
struct onepart_aux *onepaux;
} aux;
-} variable_part;
+};
/* Maximum number of location parts. */
#define MAX_VAR_PARTS 16
/* Enumeration type used to discriminate various types of one-part
variables. */
-typedef enum onepart_enum
+enum onepart_enum
{
/* Not a one-part variable. */
NOT_ONEPART = 0,
ONEPART_DEXPR = 2,
/* A VALUE. */
ONEPART_VALUE = 3
-} onepart_enum_t;
+};
/* Structure describing where the variable is located. */
-typedef struct variable_def
+struct variable
{
/* The declaration of the variable, or an RTL value being handled
like a declaration. */
/* The variable parts. */
variable_part var_part[1];
-} *variable;
-typedef const struct variable_def *const_variable;
+};
/* Pointer to the BB's information specific to variable tracking pass. */
-#define VTI(BB) ((variable_tracking_info) (BB)->aux)
+#define VTI(BB) ((variable_tracking_info *) (BB)->aux)
/* Macro to access MEM_OFFSET as an HOST_WIDE_INT. Evaluates MEM twice. */
#define INT_MEM_OFFSET(mem) (MEM_OFFSET_KNOWN_P (mem) ? MEM_OFFSET (mem) : 0)
/* Access VAR's Ith part's offset, checking that it's not a one-part
variable. */
#define VAR_PART_OFFSET(var, i) __extension__ \
-(*({ variable const __v = (var); \
+(*({ variable *const __v = (var); \
gcc_checking_assert (!__v->onepart); \
&__v->var_part[(i)].aux.offset; }))
/* Access VAR's one-part auxiliary data, checking that it is a
one-part variable. */
#define VAR_LOC_1PAUX(var) __extension__ \
-(*({ variable const __v = (var); \
+(*({ variable *const __v = (var); \
gcc_checking_assert (__v->onepart); \
&__v->var_part[0].aux.onepaux; }))
/* Variable hashtable helpers. */
-struct variable_hasher
+struct variable_hasher : pointer_hash <variable>
{
- typedef variable_def value_type;
- typedef void compare_type;
- static inline hashval_t hash (const value_type *);
- static inline bool equal (const value_type *, const compare_type *);
- static inline void remove (value_type *);
+ typedef void *compare_type;
+ static inline hashval_t hash (const variable *);
+ static inline bool equal (const variable *, const void *);
+ static inline void remove (variable *);
};
/* The hash function for variable_htab, computes the hash value
from the declaration of variable X. */
inline hashval_t
-variable_hasher::hash (const value_type *v)
+variable_hasher::hash (const variable *v)
{
return dv_htab_hash (v->dv);
}
/* Compare the declaration of variable X with declaration Y. */
inline bool
-variable_hasher::equal (const value_type *v, const compare_type *y)
+variable_hasher::equal (const variable *v, const void *y)
{
decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
/* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
inline void
-variable_hasher::remove (value_type *var)
+variable_hasher::remove (variable *var)
{
variable_htab_free (var);
}
/* Structure for passing some other parameters to function
emit_note_insn_var_location. */
-typedef struct emit_note_data_def
+struct emit_note_data
{
/* The instruction which the note will be emitted before/after. */
rtx_insn *insn;
/* The variables and values active at this point. */
variable_table_type *vars;
-} emit_note_data;
+};
/* Structure holding a refcounted hash table. If refcount > 1,
it must be first unshared before modified. */
-typedef struct shared_hash_def
+struct shared_hash
{
/* Reference count. */
int refcount;
/* Actual hash table. */
variable_table_type *htab;
-} *shared_hash;
+};
/* Structure holding the IN or OUT set for a basic block. */
-typedef struct dataflow_set_def
+struct dataflow_set
{
/* Adjustment of stack offset. */
HOST_WIDE_INT stack_adjust;
/* Attributes for registers (lists of attrs). */
- attrs regs[FIRST_PSEUDO_REGISTER];
+ attrs *regs[FIRST_PSEUDO_REGISTER];
/* Variable locations. */
- shared_hash vars;
+ shared_hash *vars;
/* Vars that is being traversed. */
- shared_hash traversed_vars;
-} dataflow_set;
+ shared_hash *traversed_vars;
+};
/* The structure (one for each basic block) containing the information
needed for variable tracking. */
-typedef struct variable_tracking_info_def
+struct variable_tracking_info
{
/* The vector of micro operations. */
vec<micro_operation> mos;
/* Has the block been flooded in VTA? */
bool flooded;
-} *variable_tracking_info;
+};
/* Alloc pool for struct attrs_def. */
-static alloc_pool attrs_pool;
+object_allocator<attrs> attrs_pool ("attrs pool");
/* Alloc pool for struct variable_def with MAX_VAR_PARTS entries. */
-static alloc_pool var_pool;
+
+static pool_allocator var_pool
+ ("variable_def pool", sizeof (variable) +
+ (MAX_VAR_PARTS - 1) * sizeof (((variable *)NULL)->var_part[0]));
/* Alloc pool for struct variable_def with a single var_part entry. */
-static alloc_pool valvar_pool;
+static pool_allocator valvar_pool
+ ("small variable_def pool", sizeof (variable));
-/* Alloc pool for struct location_chain_def. */
-static alloc_pool loc_chain_pool;
+/* Alloc pool for struct location_chain. */
+static object_allocator<location_chain> location_chain_pool
+ ("location_chain pool");
-/* Alloc pool for struct shared_hash_def. */
-static alloc_pool shared_hash_pool;
+/* Alloc pool for struct shared_hash. */
+static object_allocator<shared_hash> shared_hash_pool ("shared_hash pool");
/* Alloc pool for struct loc_exp_dep_s for NOT_ONEPART variables. */
-static alloc_pool loc_exp_dep_pool;
+object_allocator<loc_exp_dep> loc_exp_dep_pool ("loc_exp_dep pool");
/* Changed variables, notes will be emitted for them. */
static variable_table_type *changed_variables;
static variable_table_type *dropped_values;
/* Empty shared hashtable. */
-static shared_hash empty_shared_hash;
+static shared_hash *empty_shared_hash;
/* Scratch register bitmap used by cselib_expand_value_rtx. */
static bitmap scratch_regs = NULL;
#ifdef HAVE_window_save
-typedef struct GTY(()) parm_reg {
+struct GTY(()) parm_reg {
rtx outgoing;
rtx incoming;
-} parm_reg_t;
+};
/* Vector of windowed parameter registers, if any. */
-static vec<parm_reg_t, va_gc> *windowed_parm_regs = NULL;
+static vec<parm_reg, va_gc> *windowed_parm_regs = NULL;
#endif
/* Variable used to tell whether cselib_process_insn called our hook. */
HOST_WIDE_INT *);
static bool vt_stack_adjustments (void);
-static void init_attrs_list_set (attrs *);
-static void attrs_list_clear (attrs *);
-static attrs attrs_list_member (attrs, decl_or_value, HOST_WIDE_INT);
-static void attrs_list_insert (attrs *, decl_or_value, HOST_WIDE_INT, rtx);
-static void attrs_list_copy (attrs *, attrs);
-static void attrs_list_union (attrs *, attrs);
+static void init_attrs_list_set (attrs **);
+static void attrs_list_clear (attrs **);
+static attrs *attrs_list_member (attrs *, decl_or_value, HOST_WIDE_INT);
+static void attrs_list_insert (attrs **, decl_or_value, HOST_WIDE_INT, rtx);
+static void attrs_list_copy (attrs **, attrs *);
+static void attrs_list_union (attrs **, attrs *);
-static variable_def **unshare_variable (dataflow_set *set, variable_def **slot,
- variable var, enum var_init_status);
+static variable **unshare_variable (dataflow_set *set, variable **slot,
+ variable *var, enum var_init_status);
static void vars_copy (variable_table_type *, variable_table_type *);
static tree var_debug_decl (tree);
static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
static void dataflow_set_copy (dataflow_set *, dataflow_set *);
static int variable_union_info_cmp_pos (const void *, const void *);
static void dataflow_set_union (dataflow_set *, dataflow_set *);
-static location_chain find_loc_in_1pdv (rtx, variable, variable_table_type *);
+static location_chain *find_loc_in_1pdv (rtx, variable *,
+ variable_table_type *);
static bool canon_value_cmp (rtx, rtx);
static int loc_cmp (rtx, rtx);
static bool variable_part_different_p (variable_part *, variable_part *);
-static bool onepart_variable_different_p (variable, variable);
-static bool variable_different_p (variable, variable);
+static bool onepart_variable_different_p (variable *, variable *);
+static bool variable_different_p (variable *, variable *);
static bool dataflow_set_different (dataflow_set *, dataflow_set *);
static void dataflow_set_destroy (dataflow_set *);
static bool contains_symbol_ref (rtx);
static bool track_expr_p (tree, bool);
static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT);
-static int add_uses (rtx *, void *);
static void add_uses_1 (rtx *, void *);
static void add_stores (rtx, const_rtx, void *);
static bool compute_bb_dataflow (basic_block);
static bool vt_find_locations (void);
-static void dump_attrs_list (attrs);
-static void dump_var (variable);
+static void dump_attrs_list (attrs *);
+static void dump_var (variable *);
static void dump_vars (variable_table_type *);
static void dump_dataflow_set (dataflow_set *);
static void dump_dataflow_sets (void);
static void set_dv_changed (decl_or_value, bool);
-static void variable_was_changed (variable, dataflow_set *);
-static variable_def **set_slot_part (dataflow_set *, rtx, variable_def **,
- decl_or_value, HOST_WIDE_INT,
- enum var_init_status, rtx);
+static void variable_was_changed (variable *, dataflow_set *);
+static variable **set_slot_part (dataflow_set *, rtx, variable **,
+ decl_or_value, HOST_WIDE_INT,
+ enum var_init_status, rtx);
static void set_variable_part (dataflow_set *, rtx,
decl_or_value, HOST_WIDE_INT,
enum var_init_status, rtx, enum insert_option);
-static variable_def **clobber_slot_part (dataflow_set *, rtx,
- variable_def **, HOST_WIDE_INT, rtx);
+static variable **clobber_slot_part (dataflow_set *, rtx,
+ variable **, HOST_WIDE_INT, rtx);
static void clobber_variable_part (dataflow_set *, rtx,
decl_or_value, HOST_WIDE_INT, rtx);
-static variable_def **delete_slot_part (dataflow_set *, rtx, variable_def **,
- HOST_WIDE_INT);
+static variable **delete_slot_part (dataflow_set *, rtx, variable **,
+ HOST_WIDE_INT);
static void delete_variable_part (dataflow_set *, rtx,
decl_or_value, HOST_WIDE_INT);
static void emit_notes_in_bb (basic_block, dataflow_set *);
static bool vt_initialize (void);
static void vt_finalize (void);
+/* Callback for stack_adjust_offset_pre_post, called via for_each_inc_dec. */
+
+static int
+stack_adjust_offset_pre_post_cb (rtx, rtx op, rtx dest, rtx src, rtx srcoff,
+ void *arg)
+{
+ if (dest != stack_pointer_rtx)
+ return 0;
+
+ switch (GET_CODE (op))
+ {
+ case PRE_INC:
+ case PRE_DEC:
+ ((HOST_WIDE_INT *)arg)[0] -= INTVAL (srcoff);
+ return 0;
+ case POST_INC:
+ case POST_DEC:
+ ((HOST_WIDE_INT *)arg)[1] -= INTVAL (srcoff);
+ return 0;
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ /* We handle only adjustments by constant amount. */
+ gcc_assert (GET_CODE (src) == PLUS
+ && CONST_INT_P (XEXP (src, 1))
+ && XEXP (src, 0) == stack_pointer_rtx);
+ ((HOST_WIDE_INT *)arg)[GET_CODE (op) == POST_MODIFY]
+ -= INTVAL (XEXP (src, 1));
+ return 0;
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* Given a SET, calculate the amount of stack adjustment it contains
PRE- and POST-modifying stack pointer.
This function is similar to stack_adjust_offset. */
*post += INTVAL (XEXP (src, 1));
else
*post -= INTVAL (XEXP (src, 1));
+ return;
}
- else if (MEM_P (dest))
- {
- /* (set (mem (pre_dec (reg sp))) (foo)) */
- src = XEXP (dest, 0);
- code = GET_CODE (src);
-
- switch (code)
- {
- case PRE_MODIFY:
- case POST_MODIFY:
- if (XEXP (src, 0) == stack_pointer_rtx)
- {
- rtx val = XEXP (XEXP (src, 1), 1);
- /* We handle only adjustments by constant amount. */
- gcc_assert (GET_CODE (XEXP (src, 1)) == PLUS &&
- CONST_INT_P (val));
-
- if (code == PRE_MODIFY)
- *pre -= INTVAL (val);
- else
- *post -= INTVAL (val);
- break;
- }
- return;
-
- case PRE_DEC:
- if (XEXP (src, 0) == stack_pointer_rtx)
- {
- *pre += GET_MODE_SIZE (GET_MODE (dest));
- break;
- }
- return;
-
- case POST_DEC:
- if (XEXP (src, 0) == stack_pointer_rtx)
- {
- *post += GET_MODE_SIZE (GET_MODE (dest));
- break;
- }
- return;
-
- case PRE_INC:
- if (XEXP (src, 0) == stack_pointer_rtx)
- {
- *pre -= GET_MODE_SIZE (GET_MODE (dest));
- break;
- }
- return;
-
- case POST_INC:
- if (XEXP (src, 0) == stack_pointer_rtx)
- {
- *post -= GET_MODE_SIZE (GET_MODE (dest));
- break;
- }
- return;
-
- default:
- return;
- }
- }
+ HOST_WIDE_INT res[2] = { 0, 0 };
+ for_each_inc_dec (pattern, stack_adjust_offset_pre_post_cb, res);
+ *pre += res[0];
+ *post += res[1];
}
/* Given an INSN, calculate the amount of stack adjustment it contains
/* Initialize entry block. */
VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->visited = true;
- VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->in.stack_adjust =
- INCOMING_FRAME_SP_OFFSET;
- VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->out.stack_adjust =
- INCOMING_FRAME_SP_OFFSET;
+ VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->in.stack_adjust
+ = INCOMING_FRAME_SP_OFFSET;
+ VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->out.stack_adjust
+ = INCOMING_FRAME_SP_OFFSET;
/* Allocate stack for back-tracking up CFG. */
stack = XNEWVEC (edge_iterator, n_basic_blocks_for_fn (cfun) + 1);
struct adjust_mem_data
{
bool store;
- enum machine_mode mem_mode;
+ machine_mode mem_mode;
HOST_WIDE_INT stack_adjust;
- rtx side_effects;
+ rtx_expr_list *side_effects;
};
-/* Helper for adjust_mems. Return 1 if *loc is unsuitable for
- transformation of wider mode arithmetics to narrower mode,
- -1 if it is suitable and subexpressions shouldn't be
- traversed and 0 if it is suitable and subexpressions should
- be traversed. Called through for_each_rtx. */
+/* Helper for adjust_mems. Return true if X is suitable for
+ transformation of wider mode arithmetics to narrower mode. */
-static int
-use_narrower_mode_test (rtx *loc, void *data)
+static bool
+use_narrower_mode_test (rtx x, const_rtx subreg)
{
- rtx subreg = (rtx) data;
-
- if (CONSTANT_P (*loc))
- return -1;
- switch (GET_CODE (*loc))
+ subrtx_var_iterator::array_type array;
+ FOR_EACH_SUBRTX_VAR (iter, array, x, NONCONST)
{
- case REG:
- if (cselib_lookup (*loc, GET_MODE (SUBREG_REG (subreg)), 0, VOIDmode))
- return 1;
- if (!validate_subreg (GET_MODE (subreg), GET_MODE (*loc),
- *loc, subreg_lowpart_offset (GET_MODE (subreg),
- GET_MODE (*loc))))
- return 1;
- return -1;
- case PLUS:
- case MINUS:
- case MULT:
- return 0;
- case ASHIFT:
- if (for_each_rtx (&XEXP (*loc, 0), use_narrower_mode_test, data))
- return 1;
+ rtx x = *iter;
+ if (CONSTANT_P (x))
+ iter.skip_subrtxes ();
else
- return -1;
- default:
- return 1;
+ switch (GET_CODE (x))
+ {
+ case REG:
+ if (cselib_lookup (x, GET_MODE (SUBREG_REG (subreg)), 0, VOIDmode))
+ return false;
+ if (!validate_subreg (GET_MODE (subreg), GET_MODE (x), x,
+ subreg_lowpart_offset (GET_MODE (subreg),
+ GET_MODE (x))))
+ return false;
+ break;
+ case PLUS:
+ case MINUS:
+ case MULT:
+ break;
+ case ASHIFT:
+ iter.substitute (XEXP (x, 0));
+ break;
+ default:
+ return false;
+ }
}
+ return true;
}
/* Transform X into narrower mode MODE from wider mode WMODE. */
static rtx
-use_narrower_mode (rtx x, enum machine_mode mode, enum machine_mode wmode)
+use_narrower_mode (rtx x, machine_mode mode, machine_mode wmode)
{
rtx op0, op1;
if (CONSTANT_P (x))
return simplify_gen_binary (GET_CODE (x), mode, op0, op1);
case ASHIFT:
op0 = use_narrower_mode (XEXP (x, 0), mode, wmode);
- return simplify_gen_binary (ASHIFT, mode, op0, XEXP (x, 1));
+ op1 = XEXP (x, 1);
+ /* Ensure shift amount is not wider than mode. */
+ if (GET_MODE (op1) == VOIDmode)
+ op1 = lowpart_subreg (mode, op1, wmode);
+ else if (GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (GET_MODE (op1)))
+ op1 = lowpart_subreg (mode, op1, GET_MODE (op1));
+ return simplify_gen_binary (ASHIFT, mode, op0, op1);
default:
gcc_unreachable ();
}
{
struct adjust_mem_data *amd = (struct adjust_mem_data *) data;
rtx mem, addr = loc, tem;
- enum machine_mode mem_mode_save;
+ machine_mode mem_mode_save;
bool store_save;
switch (GET_CODE (loc))
{
tem = simplify_replace_fn_rtx (tem, old_rtx, adjust_mems, data);
amd->store = store_save;
amd->side_effects = alloc_EXPR_LIST (0,
- gen_rtx_SET (VOIDmode,
- XEXP (loc, 0), tem),
+ gen_rtx_SET (XEXP (loc, 0), tem),
amd->side_effects);
return addr;
case PRE_MODIFY:
adjust_mems, data);
amd->store = store_save;
amd->side_effects = alloc_EXPR_LIST (0,
- gen_rtx_SET (VOIDmode,
- XEXP (loc, 0), tem),
+ gen_rtx_SET (XEXP (loc, 0), tem),
amd->side_effects);
return addr;
case SUBREG:
|| GET_CODE (SUBREG_REG (tem)) == MINUS
|| GET_CODE (SUBREG_REG (tem)) == MULT
|| GET_CODE (SUBREG_REG (tem)) == ASHIFT)
- && GET_MODE_CLASS (GET_MODE (tem)) == MODE_INT
- && GET_MODE_CLASS (GET_MODE (SUBREG_REG (tem))) == MODE_INT
- && GET_MODE_SIZE (GET_MODE (tem))
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (tem)))
+ && (GET_MODE_CLASS (GET_MODE (tem)) == MODE_INT
+ || GET_MODE_CLASS (GET_MODE (tem)) == MODE_PARTIAL_INT)
+ && (GET_MODE_CLASS (GET_MODE (SUBREG_REG (tem))) == MODE_INT
+ || GET_MODE_CLASS (GET_MODE (SUBREG_REG (tem))) == MODE_PARTIAL_INT)
+ && GET_MODE_PRECISION (GET_MODE (tem))
+ < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (tem)))
&& subreg_lowpart_p (tem)
- && !for_each_rtx (&SUBREG_REG (tem), use_narrower_mode_test, tem))
+ && use_narrower_mode_test (SUBREG_REG (tem), tem))
return use_narrower_mode (SUBREG_REG (tem), GET_MODE (tem),
GET_MODE (SUBREG_REG (tem)));
return tem;
{
unsigned int i, nregs = vec_safe_length (windowed_parm_regs);
rtx rtl = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nregs * 2));
- parm_reg_t *p;
+ parm_reg *p;
FOR_EACH_VEC_SAFE_ELT (windowed_parm_regs, i, p)
{
XVECEXP (rtl, 0, i * 2)
- = gen_rtx_SET (VOIDmode, p->incoming, p->outgoing);
+ = gen_rtx_SET (p->incoming, p->outgoing);
/* Do not clobber the attached DECL, but only the REG. */
XVECEXP (rtl, 0, i * 2 + 1)
= gen_rtx_CLOBBER (GET_MODE (p->outgoing),
amd.mem_mode = VOIDmode;
amd.stack_adjust = -VTI (bb)->out.stack_adjust;
- amd.side_effects = NULL_RTX;
+ amd.side_effects = NULL;
amd.store = true;
note_stores (PATTERN (insn), adjust_mem_stores, &amd);
/* Return nonzero if a decl_or_value must not have more than one
variable part. The returned value discriminates among various
kinds of one-part DVs ccording to enum onepart_enum. */
-static inline onepart_enum_t
+static inline onepart_enum
dv_onepart_p (decl_or_value dv)
{
tree decl;
}
/* Return the variable pool to be used for a dv of type ONEPART. */
-static inline alloc_pool
-onepart_pool (onepart_enum_t onepart)
+static inline pool_allocator &
+onepart_pool (onepart_enum onepart)
{
return onepart ? valvar_pool : var_pool;
}
+/* Allocate a variable_def from the corresponding variable pool. */
+static inline variable *
+onepart_pool_allocate (onepart_enum onepart)
+{
+ return (variable*) onepart_pool (onepart).allocate ();
+}
+
/* Build a decl_or_value out of a decl. */
static inline decl_or_value
dv_from_decl (tree decl)
debug_generic_stmt (dv_as_decl (dv));
}
-static void loc_exp_dep_clear (variable var);
+static void loc_exp_dep_clear (variable *var);
/* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
variable_htab_free (void *elem)
{
int i;
- variable var = (variable) elem;
- location_chain node, next;
+ variable *var = (variable *) elem;
+ location_chain *node, *next;
gcc_checking_assert (var->refcount > 0);
for (node = var->var_part[i].loc_chain; node; node = next)
{
next = node->next;
- pool_free (loc_chain_pool, node);
+ delete node;
}
var->var_part[i].loc_chain = NULL;
}
if (var->onepart == ONEPART_DEXPR)
set_dv_changed (var->dv, true);
}
- pool_free (onepart_pool (var->onepart), var);
+ onepart_pool (var->onepart).remove (var);
}
/* Initialize the set (array) SET of attrs to empty lists. */
static void
-init_attrs_list_set (attrs *set)
+init_attrs_list_set (attrs **set)
{
int i;
/* Make the list *LISTP empty. */
static void
-attrs_list_clear (attrs *listp)
+attrs_list_clear (attrs **listp)
{
- attrs list, next;
+ attrs *list, *next;
for (list = *listp; list; list = next)
{
next = list->next;
- pool_free (attrs_pool, list);
+ delete list;
}
*listp = NULL;
}
/* Return true if the pair of DECL and OFFSET is the member of the LIST. */
-static attrs
-attrs_list_member (attrs list, decl_or_value dv, HOST_WIDE_INT offset)
+static attrs *
+attrs_list_member (attrs *list, decl_or_value dv, HOST_WIDE_INT offset)
{
for (; list; list = list->next)
if (dv_as_opaque (list->dv) == dv_as_opaque (dv) && list->offset == offset)
/* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */
static void
-attrs_list_insert (attrs *listp, decl_or_value dv,
+attrs_list_insert (attrs **listp, decl_or_value dv,
HOST_WIDE_INT offset, rtx loc)
{
- attrs list;
-
- list = (attrs) pool_alloc (attrs_pool);
+ attrs *list = new attrs;
list->loc = loc;
list->dv = dv;
list->offset = offset;
/* Copy all nodes from SRC and create a list *DSTP of the copies. */
static void
-attrs_list_copy (attrs *dstp, attrs src)
+attrs_list_copy (attrs **dstp, attrs *src)
{
- attrs n;
-
attrs_list_clear (dstp);
for (; src; src = src->next)
{
- n = (attrs) pool_alloc (attrs_pool);
+ attrs *n = new attrs;
n->loc = src->loc;
n->dv = src->dv;
n->offset = src->offset;
/* Add all nodes from SRC which are not in *DSTP to *DSTP. */
static void
-attrs_list_union (attrs *dstp, attrs src)
+attrs_list_union (attrs **dstp, attrs *src)
{
for (; src; src = src->next)
{
*DSTP. */
static void
-attrs_list_mpdv_union (attrs *dstp, attrs src, attrs src2)
+attrs_list_mpdv_union (attrs **dstp, attrs *src, attrs *src2)
{
gcc_assert (!*dstp);
for (; src; src = src->next)
/* Return true if VARS is shared. */
static inline bool
-shared_hash_shared (shared_hash vars)
+shared_hash_shared (shared_hash *vars)
{
return vars->refcount > 1;
}
/* Return the hash table for VARS. */
static inline variable_table_type *
-shared_hash_htab (shared_hash vars)
+shared_hash_htab (shared_hash *vars)
{
return vars->htab;
}
/* Return true if VAR is shared, or maybe because VARS is shared. */
static inline bool
-shared_var_p (variable var, shared_hash vars)
+shared_var_p (variable *var, shared_hash *vars)
{
/* Don't count an entry in the changed_variables table as a duplicate. */
return ((var->refcount > 1 + (int) var->in_changed_variables)
/* Copy variables into a new hash table. */
-static shared_hash
-shared_hash_unshare (shared_hash vars)
+static shared_hash *
+shared_hash_unshare (shared_hash *vars)
{
- shared_hash new_vars = (shared_hash) pool_alloc (shared_hash_pool);
+ shared_hash *new_vars = new shared_hash;
gcc_assert (vars->refcount > 1);
new_vars->refcount = 1;
new_vars->htab = new variable_table_type (vars->htab->elements () + 3);
/* Increment reference counter on VARS and return it. */
-static inline shared_hash
-shared_hash_copy (shared_hash vars)
+static inline shared_hash *
+shared_hash_copy (shared_hash *vars)
{
vars->refcount++;
return vars;
anymore. */
static void
-shared_hash_destroy (shared_hash vars)
+shared_hash_destroy (shared_hash *vars)
{
gcc_checking_assert (vars->refcount > 0);
if (--vars->refcount == 0)
{
delete vars->htab;
- pool_free (shared_hash_pool, vars);
+ delete vars;
}
}
/* Unshare *PVARS if shared and return slot for DV. If INS is
INSERT, insert it if not already present. */
-static inline variable_def **
-shared_hash_find_slot_unshare_1 (shared_hash *pvars, decl_or_value dv,
+static inline variable **
+shared_hash_find_slot_unshare_1 (shared_hash **pvars, decl_or_value dv,
hashval_t dvhash, enum insert_option ins)
{
if (shared_hash_shared (*pvars))
return shared_hash_htab (*pvars)->find_slot_with_hash (dv, dvhash, ins);
}
-static inline variable_def **
-shared_hash_find_slot_unshare (shared_hash *pvars, decl_or_value dv,
+static inline variable **
+shared_hash_find_slot_unshare (shared_hash **pvars, decl_or_value dv,
enum insert_option ins)
{
return shared_hash_find_slot_unshare_1 (pvars, dv, dv_htab_hash (dv), ins);
If it is not present, insert it only VARS is not shared, otherwise
return NULL. */
-static inline variable_def **
-shared_hash_find_slot_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash)
+static inline variable **
+shared_hash_find_slot_1 (shared_hash *vars, decl_or_value dv, hashval_t dvhash)
{
return shared_hash_htab (vars)->find_slot_with_hash (dv, dvhash,
shared_hash_shared (vars)
? NO_INSERT : INSERT);
}
-static inline variable_def **
-shared_hash_find_slot (shared_hash vars, decl_or_value dv)
+static inline variable **
+shared_hash_find_slot (shared_hash *vars, decl_or_value dv)
{
return shared_hash_find_slot_1 (vars, dv, dv_htab_hash (dv));
}
/* Return slot for DV only if it is already present in the hash table. */
-static inline variable_def **
-shared_hash_find_slot_noinsert_1 (shared_hash vars, decl_or_value dv,
+static inline variable **
+shared_hash_find_slot_noinsert_1 (shared_hash *vars, decl_or_value dv,
hashval_t dvhash)
{
return shared_hash_htab (vars)->find_slot_with_hash (dv, dvhash, NO_INSERT);
}
-static inline variable_def **
-shared_hash_find_slot_noinsert (shared_hash vars, decl_or_value dv)
+static inline variable **
+shared_hash_find_slot_noinsert (shared_hash *vars, decl_or_value dv)
{
return shared_hash_find_slot_noinsert_1 (vars, dv, dv_htab_hash (dv));
}
/* Return variable for DV or NULL if not already present in the hash
table. */
-static inline variable
-shared_hash_find_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash)
+static inline variable *
+shared_hash_find_1 (shared_hash *vars, decl_or_value dv, hashval_t dvhash)
{
return shared_hash_htab (vars)->find_with_hash (dv, dvhash);
}
-static inline variable
-shared_hash_find (shared_hash vars, decl_or_value dv)
+static inline variable *
+shared_hash_find (shared_hash *vars, decl_or_value dv)
{
return shared_hash_find_1 (vars, dv, dv_htab_hash (dv));
}
/* Return a copy of a variable VAR and insert it to dataflow set SET. */
-static variable_def **
-unshare_variable (dataflow_set *set, variable_def **slot, variable var,
+static variable **
+unshare_variable (dataflow_set *set, variable **slot, variable *var,
enum var_init_status initialized)
{
- variable new_var;
+ variable *new_var;
int i;
- new_var = (variable) pool_alloc (onepart_pool (var->onepart));
+ new_var = onepart_pool_allocate (var->onepart);
new_var->dv = var->dv;
new_var->refcount = 1;
var->refcount--;
for (i = 0; i < var->n_var_parts; i++)
{
- location_chain node;
- location_chain *nextp;
+ location_chain *node;
+ location_chain **nextp;
if (i == 0 && var->onepart)
{
nextp = &new_var->var_part[i].loc_chain;
for (node = var->var_part[i].loc_chain; node; node = node->next)
{
- location_chain new_lc;
+ location_chain *new_lc;
- new_lc = (location_chain) pool_alloc (loc_chain_pool);
+ new_lc = new location_chain;
new_lc->next = NULL;
if (node->init > initialized)
new_lc->init = node->init;
*slot = new_var;
if (var->in_changed_variables)
{
- variable_def **cslot
+ variable **cslot
= changed_variables->find_slot_with_hash (var->dv,
dv_htab_hash (var->dv),
NO_INSERT);
vars_copy (variable_table_type *dst, variable_table_type *src)
{
variable_iterator_type hi;
- variable var;
+ variable *var;
FOR_EACH_HASH_TABLE_ELEMENT (*src, var, variable, hi)
{
- variable_def **dstp;
+ variable **dstp;
var->refcount++;
dstp = dst->find_slot_with_hash (var->dv, dv_htab_hash (var->dv),
INSERT);
decl_or_value dv, HOST_WIDE_INT offset, rtx set_src,
enum insert_option iopt)
{
- attrs node;
+ attrs *node;
bool decl_p = dv_is_decl_p (dv);
if (decl_p)
static enum var_init_status
get_init_value (dataflow_set *set, rtx loc, decl_or_value dv)
{
- variable var;
+ variable *var;
int i;
enum var_init_status ret_val = VAR_INIT_STATUS_UNKNOWN;
{
for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++)
{
- location_chain nextp;
+ location_chain *nextp;
for (nextp = var->var_part[i].loc_chain; nextp; nextp = nextp->next)
if (rtx_equal_p (nextp->loc, loc))
{
{
tree decl = REG_EXPR (loc);
HOST_WIDE_INT offset = REG_OFFSET (loc);
- attrs node, next;
- attrs *nextp;
+ attrs *node, *next;
+ attrs **nextp;
decl = var_debug_decl (decl);
if (dv_as_opaque (node->dv) != decl || node->offset != offset)
{
delete_variable_part (set, node->loc, node->dv, node->offset);
- pool_free (attrs_pool, node);
+ delete node;
*nextp = next;
}
else
static void
var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
{
- attrs *nextp = &set->regs[REGNO (loc)];
- attrs node, next;
+ attrs **nextp = &set->regs[REGNO (loc)];
+ attrs *node, *next;
if (clobber)
{
if (clobber || !dv_onepart_p (node->dv))
{
delete_variable_part (set, node->loc, node->dv, node->offset);
- pool_free (attrs_pool, node);
+ delete node;
*nextp = next;
}
else
static void
var_regno_delete (dataflow_set *set, int regno)
{
- attrs *reg = &set->regs[regno];
- attrs node, next;
+ attrs **reg = &set->regs[regno];
+ attrs *node, *next;
for (node = *reg; node; node = next)
{
next = node->next;
delete_variable_part (set, node->loc, node->dv, node->offset);
- pool_free (attrs_pool, node);
+ delete node;
}
*reg = NULL;
}
rtx x;
gcc_checking_assert (GET_CODE (loc) == VALUE);
-
+
bool existed;
rtx *slot = &global_get_addr_cache->get_or_insert (loc, &existed);
if (existed)
{
rtx x;
decl_or_value dv;
- variable var;
- location_chain l;
+ variable *var;
+ location_chain *l;
gcc_checking_assert (GET_CODE (loc) == VALUE);
-
+
bool existed;
rtx *slot = &local_get_addr_cache->get_or_insert (loc, &existed);
if (existed)
return *slot;
x = get_addr_from_global_cache (loc);
-
+
/* Tentative, avoiding infinite recursion. */
*slot = x;
vt_canonicalize_addr (dataflow_set *set, rtx oloc)
{
HOST_WIDE_INT ofst = 0;
- enum machine_mode mode = GET_MODE (oloc);
+ machine_mode mode = GET_MODE (oloc);
rtx loc = oloc;
rtx x;
bool retry = true;
canonicalized itself. */
int
-drop_overlapping_mem_locs (variable_def **slot, overlapping_mems *coms)
+drop_overlapping_mem_locs (variable **slot, overlapping_mems *coms)
{
dataflow_set *set = coms->set;
rtx mloc = coms->loc, addr = coms->addr;
- variable var = *slot;
+ variable *var = *slot;
if (var->onepart == ONEPART_VALUE)
{
- location_chain loc, *locp;
+ location_chain *loc, **locp;
bool changed = false;
rtx cur_loc;
if (VAR_LOC_1PAUX (var))
VAR_LOC_FROM (var) = NULL;
}
- pool_free (loc_chain_pool, loc);
+ delete loc;
}
if (!var->var_part[0].loc_chain)
static void
val_reset (dataflow_set *set, decl_or_value dv)
{
- variable var = shared_hash_find (set->vars, dv) ;
- location_chain node;
+ variable *var = shared_hash_find (set->vars, dv) ;
+ location_chain *node;
rtx cval;
if (!var || !var->n_var_parts)
if (var->onepart == ONEPART_VALUE)
{
rtx x = dv_as_value (dv);
-
+
/* Relationships in the global cache don't change, so reset the
local cache entry only. */
rtx *slot = local_get_addr_cache->get (x);
if (REG_P (loc))
{
- attrs node, found = NULL;
+ attrs *node, *found = NULL;
for (node = set->regs[REGNO (loc)]; node; node = node->next)
if (dv_is_value_p (node->dv)
struct variable_union_info
{
/* Node of the location chain. */
- location_chain lc;
+ location_chain *lc;
/* The sum of positions in the input chains. */
int pos;
we keep the newest locations in the beginning. */
static int
-variable_union (variable src, dataflow_set *set)
+variable_union (variable *src, dataflow_set *set)
{
- variable dst;
- variable_def **dstp;
+ variable *dst;
+ variable **dstp;
int i, j, k;
dstp = shared_hash_find_slot (set->vars, src->dv);
entries are in canonical order. */
if (src->onepart)
{
- location_chain *nodep, dnode, snode;
+ location_chain **nodep, *dnode, *snode;
gcc_assert (src->n_var_parts == 1
&& dst->n_var_parts == 1);
if (r > 0)
{
- location_chain nnode;
+ location_chain *nnode;
if (shared_var_p (dst, set->vars))
{
goto restart_onepart_unshared;
}
- *nodep = nnode = (location_chain) pool_alloc (loc_chain_pool);
+ *nodep = nnode = new location_chain;
nnode->loc = snode->loc;
nnode->init = snode->init;
if (!snode->set_src || MEM_P (snode->set_src))
for (k--; k >= 0; k--)
{
- location_chain node, node2;
+ location_chain *node, *node2;
if (i >= 0 && j >= 0
&& VAR_PART_OFFSET (src, i) == VAR_PART_OFFSET (dst, j))
{
dstp = unshare_variable (set, dstp, dst,
VAR_INIT_STATUS_UNKNOWN);
- dst = (variable)*dstp;
+ dst = (variable *)*dstp;
}
}
if (dst_l == 1)
{
/* The most common case, much simpler, no qsort is needed. */
- location_chain dstnode = dst->var_part[j].loc_chain;
+ location_chain *dstnode = dst->var_part[j].loc_chain;
dst->var_part[k].loc_chain = dstnode;
VAR_PART_OFFSET (dst, k) = VAR_PART_OFFSET (dst, j);
node2 = dstnode;
&& REGNO (dstnode->loc) == REGNO (node->loc))
|| rtx_equal_p (dstnode->loc, node->loc)))
{
- location_chain new_node;
+ location_chain *new_node;
/* Copy the location from SRC. */
- new_node = (location_chain) pool_alloc (loc_chain_pool);
+ new_node = new location_chain;
new_node->loc = node->loc;
new_node->init = node->init;
if (!node->set_src || MEM_P (node->set_src))
}
if (jj >= dst_l) /* The location has not been found. */
{
- location_chain new_node;
+ location_chain *new_node;
/* Copy the location from SRC. */
- new_node = (location_chain) pool_alloc (loc_chain_pool);
+ new_node = new location_chain;
new_node->loc = node->loc;
new_node->init = node->init;
if (!node->set_src || MEM_P (node->set_src))
&& VAR_PART_OFFSET (src, i) > VAR_PART_OFFSET (dst, j))
|| j < 0)
{
- location_chain *nextp;
+ location_chain **nextp;
/* Copy the chain from SRC. */
nextp = &dst->var_part[k].loc_chain;
for (node = src->var_part[i].loc_chain; node; node = node->next)
{
- location_chain new_lc;
+ location_chain *new_lc;
- new_lc = (location_chain) pool_alloc (loc_chain_pool);
+ new_lc = new location_chain;
new_lc->next = NULL;
new_lc->init = node->init;
if (!node->set_src || MEM_P (node->set_src))
if (flag_var_tracking_uninit)
for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
{
- location_chain node, node2;
+ location_chain *node, *node2;
for (node = src->var_part[i].loc_chain; node; node = node->next)
for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next)
if (rtx_equal_p (node->loc, node2->loc))
else
{
variable_iterator_type hi;
- variable var;
+ variable *var;
FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (src->vars),
var, variable, hi)
any values recursively mentioned in the location lists. VARS must
be in star-canonical form. */
-static location_chain
-find_loc_in_1pdv (rtx loc, variable var, variable_table_type *vars)
+static location_chain *
+find_loc_in_1pdv (rtx loc, variable *var, variable_table_type *vars)
{
- location_chain node;
+ location_chain *node;
enum rtx_code loc_code;
if (!var)
for (node = var->var_part[0].loc_chain; node; node = node->next)
{
decl_or_value dv;
- variable rvar;
+ variable *rvar;
if (GET_CODE (node->loc) != loc_code)
{
loc_cmp order, and it is maintained as such. */
static void
-insert_into_intersection (location_chain *nodep, rtx loc,
+insert_into_intersection (location_chain **nodep, rtx loc,
enum var_init_status status)
{
- location_chain node;
+ location_chain *node;
int r;
for (node = *nodep; node; nodep = &node->next, node = *nodep)
else if (r > 0)
break;
- node = (location_chain) pool_alloc (loc_chain_pool);
+ node = new location_chain;
node->loc = loc;
node->set_src = NULL;
DSM->dst. */
static void
-intersect_loc_chains (rtx val, location_chain *dest, struct dfset_merge *dsm,
- location_chain s1node, variable s2var)
+intersect_loc_chains (rtx val, location_chain **dest, struct dfset_merge *dsm,
+ location_chain *s1node, variable *s2var)
{
dataflow_set *s1set = dsm->cur;
dataflow_set *s2set = dsm->src;
- location_chain found;
+ location_chain *found;
if (s2var)
{
- location_chain s2node;
+ location_chain *s2node;
gcc_checking_assert (s2var->onepart);
&& !VALUE_RECURSED_INTO (s1node->loc))
{
decl_or_value dv = dv_from_value (s1node->loc);
- variable svar = shared_hash_find (s1set->vars, dv);
+ variable *svar = shared_hash_find (s1set->vars, dv);
if (svar)
{
if (svar->n_var_parts == 1)
/* Check the order of entries in one-part variables. */
int
-canonicalize_loc_order_check (variable_def **slot,
+canonicalize_loc_order_check (variable **slot,
dataflow_set *data ATTRIBUTE_UNUSED)
{
- variable var = *slot;
- location_chain node, next;
+ variable *var = *slot;
+ location_chain *node, *next;
#ifdef ENABLE_RTL_CHECKING
int i;
the connections bidirectional. */
int
-canonicalize_values_mark (variable_def **slot, dataflow_set *set)
+canonicalize_values_mark (variable **slot, dataflow_set *set)
{
- variable var = *slot;
+ variable *var = *slot;
decl_or_value dv = var->dv;
rtx val;
- location_chain node;
+ location_chain *node;
if (!dv_is_value_p (dv))
return 1;
else
{
decl_or_value odv = dv_from_value (node->loc);
- variable_def **oslot;
+ variable **oslot;
oslot = shared_hash_find_slot_noinsert (set->vars, odv);
set_slot_part (set, val, oslot, odv, 0,
variables, canonicalizing equivalence sets into star shapes. */
int
-canonicalize_values_star (variable_def **slot, dataflow_set *set)
+canonicalize_values_star (variable **slot, dataflow_set *set)
{
- variable var = *slot;
+ variable *var = *slot;
decl_or_value dv = var->dv;
- location_chain node;
+ location_chain *node;
decl_or_value cdv;
rtx val, cval;
- variable_def **cslot;
+ variable **cslot;
bool has_value;
bool has_marks;
}
else if (GET_CODE (node->loc) == REG)
{
- attrs list = set->regs[REGNO (node->loc)], *listp;
+ attrs *list = set->regs[REGNO (node->loc)], **listp;
/* Change an existing attribute referring to dv so that it
refers to cdv, removing any duplicate this might
if (dv_as_opaque (list->dv) == dv_as_opaque (cdv))
{
*listp = list->next;
- pool_free (attrs_pool, list);
+ delete list;
list = *listp;
break;
}
if (dv_as_opaque (list->dv) == dv_as_opaque (dv))
{
*listp = list->next;
- pool_free (attrs_pool, list);
+ delete list;
list = *listp;
break;
}
get to a variable that references another member of the set. */
int
-canonicalize_vars_star (variable_def **slot, dataflow_set *set)
+canonicalize_vars_star (variable **slot, dataflow_set *set)
{
- variable var = *slot;
+ variable *var = *slot;
decl_or_value dv = var->dv;
- location_chain node;
+ location_chain *node;
rtx cval;
decl_or_value cdv;
- variable_def **cslot;
- variable cvar;
- location_chain cnode;
+ variable **cslot;
+ variable *cvar;
+ location_chain *cnode;
if (!var->onepart || var->onepart == ONEPART_VALUE)
return 1;
intersection. */
static int
-variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
+variable_merge_over_cur (variable *s1var, struct dfset_merge *dsm)
{
dataflow_set *dst = dsm->dst;
- variable_def **dstslot;
- variable s2var, dvar = NULL;
+ variable **dstslot;
+ variable *s2var, *dvar = NULL;
decl_or_value dv = s1var->dv;
- onepart_enum_t onepart = s1var->onepart;
+ onepart_enum onepart = s1var->onepart;
rtx val;
hashval_t dvhash;
- location_chain node, *nodep;
+ location_chain *node, **nodep;
/* If the incoming onepart variable has an empty location list, then
the intersection will be just as empty. For other variables,
{
if (node)
{
- dvar = (variable) pool_alloc (onepart_pool (onepart));
+ dvar = onepart_pool_allocate (onepart);
dvar->dv = dv;
dvar->refcount = 1;
dvar->n_var_parts = 1;
nodep = &dvar->var_part[0].loc_chain;
while ((node = *nodep))
{
- location_chain *nextp = &node->next;
+ location_chain **nextp = &node->next;
if (GET_CODE (node->loc) == REG)
{
- attrs list;
+ attrs *list;
for (list = dst->regs[REGNO (node->loc)]; list; list = list->next)
if (GET_MODE (node->loc) == GET_MODE (list->loc)
if (GET_CODE (node->loc) == VALUE)
{
decl_or_value dv = dv_from_value (node->loc);
- variable_def **slot = NULL;
+ variable **slot = NULL;
if (shared_hash_shared (dst->vars))
slot = shared_hash_find_slot_noinsert (dst->vars, dv);
INSERT);
if (!*slot)
{
- variable var = (variable) pool_alloc (onepart_pool
- (ONEPART_VALUE));
+ variable *var = onepart_pool_allocate (ONEPART_VALUE);
var->dv = dv;
var->refcount = 1;
var->n_var_parts = 1;
variable_merge_over_cur(). */
static int
-variable_merge_over_src (variable s2var, struct dfset_merge *dsm)
+variable_merge_over_src (variable *s2var, struct dfset_merge *dsm)
{
dataflow_set *dst = dsm->dst;
decl_or_value dv = s2var->dv;
if (!s2var->onepart)
{
- variable_def **dstp = shared_hash_find_slot (dst->vars, dv);
+ variable **dstp = shared_hash_find_slot (dst->vars, dv);
*dstp = s2var;
s2var->refcount++;
return 1;
int i;
size_t src1_elems, src2_elems;
variable_iterator_type hi;
- variable var;
+ variable *var;
src1_elems = shared_hash_htab (src1->vars)->elements ();
src2_elems = shared_hash_htab (src2->vars)->elements ();
dataflow_set_init (dst);
dst->stack_adjust = cur.stack_adjust;
shared_hash_destroy (dst->vars);
- dst->vars = (shared_hash) pool_alloc (shared_hash_pool);
+ dst->vars = new shared_hash;
dst->vars->refcount = 1;
dst->vars->htab = new variable_table_type (MAX (src1_elems, src2_elems));
dataflow_set_equiv_regs (dataflow_set *set)
{
int i;
- attrs list, *listp;
+ attrs *list, **listp;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
if (list->offset == 0 && dv_onepart_p (list->dv))
{
rtx cval = canon[(int)GET_MODE (list->loc)];
- variable_def **slot;
+ variable **slot;
if (!cval)
continue;
be unshared and 1-part. */
static void
-remove_duplicate_values (variable var)
+remove_duplicate_values (variable *var)
{
- location_chain node, *nodep;
+ location_chain *node, **nodep;
gcc_assert (var->onepart);
gcc_assert (var->n_var_parts == 1);
{
/* Remove duplicate value node. */
*nodep = node->next;
- pool_free (loc_chain_pool, node);
+ delete node;
continue;
}
else
variables that don't have value numbers for them. */
int
-variable_post_merge_new_vals (variable_def **slot, dfset_post_merge *dfpm)
+variable_post_merge_new_vals (variable **slot, dfset_post_merge *dfpm)
{
dataflow_set *set = dfpm->set;
- variable var = *slot;
- location_chain node;
+ variable *var = *slot;
+ location_chain *node;
if (!var->onepart || !var->n_var_parts)
return 1;
gcc_assert (!VALUE_RECURSED_INTO (node->loc));
else if (GET_CODE (node->loc) == REG)
{
- attrs att, *attp, *curp = NULL;
+ attrs *att, **attp, **curp = NULL;
if (var->refcount != 1)
{
to be added when we bring perm in. */
att = *curp;
*curp = att->next;
- pool_free (attrs_pool, att);
+ delete att;
}
}
chosen expression. */
int
-variable_post_merge_perm_vals (variable_def **pslot, dfset_post_merge *dfpm)
+variable_post_merge_perm_vals (variable **pslot, dfset_post_merge *dfpm)
{
dataflow_set *set = dfpm->set;
- variable pvar = *pslot, var;
- location_chain pnode;
+ variable *pvar = *pslot, *var;
+ location_chain *pnode;
decl_or_value dv;
- attrs att;
+ attrs *att;
gcc_assert (dv_is_value_p (pvar->dv)
&& pvar->n_var_parts == 1);
location list of a one-part variable or value VAR, or in that of
any values recursively mentioned in the location lists. */
-static location_chain
+static location_chain *
find_mem_expr_in_1pdv (tree expr, rtx val, variable_table_type *vars)
{
- location_chain node;
+ location_chain *node;
decl_or_value dv;
- variable var;
- location_chain where = NULL;
+ variable *var;
+ location_chain *where = NULL;
if (!val)
return NULL;
the variable itself, directly or within a VALUE. */
int
-dataflow_set_preserve_mem_locs (variable_def **slot, dataflow_set *set)
+dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set)
{
- variable var = *slot;
+ variable *var = *slot;
if (var->onepart == ONEPART_VDECL || var->onepart == ONEPART_DEXPR)
{
tree decl = dv_as_decl (var->dv);
- location_chain loc, *locp;
+ location_chain *loc, **locp;
bool changed = false;
if (!var->n_var_parts)
rtx old_loc = loc->loc;
if (GET_CODE (old_loc) == VALUE)
{
- location_chain mem_node
+ location_chain *mem_node
= find_mem_expr_in_1pdv (decl, loc->loc,
shared_hash_htab (set->vars));
}
}
*locp = loc->next;
- pool_free (loc_chain_pool, loc);
+ delete loc;
}
if (!var->var_part[0].loc_chain)
value. */
int
-dataflow_set_remove_mem_locs (variable_def **slot, dataflow_set *set)
+dataflow_set_remove_mem_locs (variable **slot, dataflow_set *set)
{
- variable var = *slot;
+ variable *var = *slot;
if (var->onepart == ONEPART_VALUE)
{
- location_chain loc, *locp;
+ location_chain *loc, **locp;
bool changed = false;
rtx cur_loc;
if (VAR_LOC_1PAUX (var))
VAR_LOC_FROM (var) = NULL;
}
- pool_free (loc_chain_pool, loc);
+ delete loc;
}
if (!var->var_part[0].loc_chain)
registers, as well as associations between MEMs and VALUEs. */
static void
-dataflow_set_clear_at_call (dataflow_set *set)
+dataflow_set_clear_at_call (dataflow_set *set, rtx_insn *call_insn)
{
unsigned int r;
hard_reg_set_iterator hrsi;
+ HARD_REG_SET invalidated_regs;
- EXECUTE_IF_SET_IN_HARD_REG_SET (regs_invalidated_by_call, 0, r, hrsi)
+ get_call_reg_set_usage (call_insn, &invalidated_regs,
+ regs_invalidated_by_call);
+
+ EXECUTE_IF_SET_IN_HARD_REG_SET (invalidated_regs, 0, r, hrsi)
var_regno_delete (set, r);
if (MAY_HAVE_DEBUG_INSNS)
static bool
variable_part_different_p (variable_part *vp1, variable_part *vp2)
{
- location_chain lc1, lc2;
+ location_chain *lc1, *lc2;
for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next)
{
They must be in canonical order. */
static bool
-onepart_variable_different_p (variable var1, variable var2)
+onepart_variable_different_p (variable *var1, variable *var2)
{
- location_chain lc1, lc2;
+ location_chain *lc1, *lc2;
if (var1 == var2)
return false;
/* Return true if variables VAR1 and VAR2 are different. */
static bool
-variable_different_p (variable var1, variable var2)
+variable_different_p (variable *var1, variable *var2)
{
int i;
dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
{
variable_iterator_type hi;
- variable var1;
+ variable *var1;
if (old_set->vars == new_set->vars)
return false;
var1, variable, hi)
{
variable_table_type *htab = shared_hash_htab (new_set->vars);
- variable var2 = htab->find_with_hash (var1->dv, dv_htab_hash (var1->dv));
+ variable *var2 = htab->find_with_hash (var1->dv, dv_htab_hash (var1->dv));
if (!var2)
{
if (dump_file && (dump_flags & TDF_DETAILS))
static bool
track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
- enum machine_mode *mode_out, HOST_WIDE_INT *offset_out)
+ machine_mode *mode_out, HOST_WIDE_INT *offset_out)
{
- enum machine_mode mode;
+ machine_mode mode;
if (expr == NULL || !track_expr_p (expr, true))
return false;
mode = GET_MODE (loc);
if (REG_P (loc) && !HARD_REGISTER_NUM_P (ORIGINAL_REGNO (loc)))
{
- enum machine_mode pseudo_mode;
+ machine_mode pseudo_mode;
pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc));
if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (pseudo_mode))
on the returned value are updated. */
static rtx
-var_lowpart (enum machine_mode mode, rtx loc)
+var_lowpart (machine_mode mode, rtx loc)
{
unsigned int offset, reg_offset, regno;
/* Find a VALUE corresponding to X. */
static inline cselib_val *
-find_use_val (rtx x, enum machine_mode mode, struct count_use_info *cui)
+find_use_val (rtx x, machine_mode mode, struct count_use_info *cui)
{
int i;
return cselib_subst_to_values (loc, VOIDmode);
}
-/* Return true if *X is a DEBUG_EXPR. Usable as an argument to
- for_each_rtx to tell whether there are any DEBUG_EXPRs within
- RTX. */
+/* Return true if X contains a DEBUG_EXPR. */
-static int
-rtx_debug_expr_p (rtx *x, void *data ATTRIBUTE_UNUSED)
+static bool
+rtx_debug_expr_p (const_rtx x)
{
- rtx loc = *x;
-
- return GET_CODE (loc) == DEBUG_EXPR;
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, x, ALL)
+ if (GET_CODE (*iter) == DEBUG_EXPR)
+ return true;
+ return false;
}
/* Determine what kind of micro operation to choose for a USE. Return
MO_CLOBBER if no micro operation is to be generated. */
static enum micro_operation_type
-use_type (rtx loc, struct count_use_info *cui, enum machine_mode *modep)
+use_type (rtx loc, struct count_use_info *cui, machine_mode *modep)
{
tree expr;
DEBUG_EXPRs (only happens in the presence of debug
insns). */
&& (!MAY_HAVE_DEBUG_INSNS
- || !for_each_rtx (&XEXP (loc, 0), rtx_debug_expr_p, NULL)))
+ || !rtx_debug_expr_p (XEXP (loc, 0))))
return MO_USE;
else
return MO_CLOBBER;
any rtxes not suitable for CONST use not replaced by VALUEs
are discovered. */
-static int
-non_suitable_const (rtx *x, void *data ATTRIBUTE_UNUSED)
+static bool
+non_suitable_const (const_rtx x)
{
- if (*x == NULL_RTX)
- return 0;
-
- switch (GET_CODE (*x))
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, x, ALL)
{
- case REG:
- case DEBUG_EXPR:
- case PC:
- case SCRATCH:
- case CC0:
- case ASM_INPUT:
- case ASM_OPERANDS:
- return 1;
- case MEM:
- return !MEM_READONLY_P (*x);
- default:
- return 0;
+ const_rtx x = *iter;
+ switch (GET_CODE (x))
+ {
+ case REG:
+ case DEBUG_EXPR:
+ case PC:
+ case SCRATCH:
+ case CC0:
+ case ASM_INPUT:
+ case ASM_OPERANDS:
+ return true;
+ case MEM:
+ if (!MEM_READONLY_P (x))
+ return true;
+ break;
+ default:
+ break;
+ }
}
+ return false;
}
/* Add uses (register and memory references) LOC which will be tracked
- to VTI (bb)->mos. INSN is instruction which the LOC is part of. */
+ to VTI (bb)->mos. */
-static int
-add_uses (rtx *ploc, void *data)
+static void
+add_uses (rtx loc, struct count_use_info *cui)
{
- rtx loc = *ploc;
- enum machine_mode mode = VOIDmode;
- struct count_use_info *cui = (struct count_use_info *)data;
+ machine_mode mode = VOIDmode;
enum micro_operation_type type = use_type (loc, cui, &mode);
if (type != MO_CLOBBER)
&& !MEM_P (XEXP (vloc, 0)))
{
rtx mloc = vloc;
- enum machine_mode address_mode = get_address_mode (mloc);
+ machine_mode address_mode = get_address_mode (mloc);
cselib_val *val
= cselib_lookup (XEXP (mloc, 0), address_mode, 0,
GET_MODE (mloc));
}
if (CONSTANT_P (vloc)
- && (GET_CODE (vloc) != CONST
- || for_each_rtx (&vloc, non_suitable_const, NULL)))
+ && (GET_CODE (vloc) != CONST || non_suitable_const (vloc)))
/* For constants don't look up any value. */;
else if (!VAR_LOC_UNKNOWN_P (vloc) && !unsuitable_loc (vloc)
&& (val = find_use_val (vloc, GET_MODE (oloc), cui)))
{
- enum machine_mode mode2;
+ machine_mode mode2;
enum micro_operation_type type2;
rtx nloc = NULL;
bool resolvable = REG_P (vloc) || MEM_P (vloc);
}
else if (type == MO_VAL_USE)
{
- enum machine_mode mode2 = VOIDmode;
+ machine_mode mode2 = VOIDmode;
enum micro_operation_type type2;
cselib_val *val = find_use_val (loc, GET_MODE (loc), cui);
rtx vloc, oloc = loc, nloc;
&& !MEM_P (XEXP (oloc, 0)))
{
rtx mloc = oloc;
- enum machine_mode address_mode = get_address_mode (mloc);
+ machine_mode address_mode = get_address_mode (mloc);
cselib_val *val
= cselib_lookup (XEXP (mloc, 0), address_mode, 0,
GET_MODE (mloc));
log_op_type (mo.u.loc, cui->bb, cui->insn, mo.type, dump_file);
VTI (bb)->mos.safe_push (mo);
}
-
- return 0;
}
/* Helper function for finding all uses of REG/MEM in X in insn INSN. */
static void
add_uses_1 (rtx *x, void *cui)
{
- for_each_rtx (x, add_uses, cui);
+ subrtx_var_iterator::array_type array;
+ FOR_EACH_SUBRTX_VAR (iter, array, *x, NONCONST)
+ add_uses (*iter, (struct count_use_info *) cui);
}
/* This is the value used during expansion of locations. We want it
static void
add_stores (rtx loc, const_rtx expr, void *cuip)
{
- enum machine_mode mode = VOIDmode, mode2;
+ machine_mode mode = VOIDmode, mode2;
struct count_use_info *cui = (struct count_use_info *)cuip;
basic_block bb = cui->bb;
micro_operation mo;
&& find_use_val (loc, mode, cui))
{
gcc_checking_assert (type == MO_VAL_SET);
- mo.u.loc = gen_rtx_SET (VOIDmode, loc, SET_SRC (expr));
+ mo.u.loc = gen_rtx_SET (loc, SET_SRC (expr));
}
}
else
}
else
{
- rtx xexpr = gen_rtx_SET (VOIDmode, loc, src);
+ rtx xexpr = gen_rtx_SET (loc, src);
if (same_variable_part_p (src, REG_EXPR (loc), REG_OFFSET (loc)))
{
/* If this is an instruction copying (part of) a parameter
&& !MEM_P (XEXP (loc, 0)))
{
rtx mloc = loc;
- enum machine_mode address_mode = get_address_mode (mloc);
+ machine_mode address_mode = get_address_mode (mloc);
cselib_val *val = cselib_lookup (XEXP (mloc, 0),
address_mode, 0,
GET_MODE (mloc));
}
else
{
- rtx xexpr = gen_rtx_SET (VOIDmode, loc, src);
+ rtx xexpr = gen_rtx_SET (loc, src);
if (same_variable_part_p (SET_SRC (xexpr),
MEM_EXPR (loc),
INT_MEM_OFFSET (loc)))
}
if (nloc && nloc != SET_SRC (mo.u.loc))
- oloc = gen_rtx_SET (GET_MODE (mo.u.loc), oloc, nloc);
+ oloc = gen_rtx_SET (oloc, nloc);
else
{
if (oloc == SET_DEST (mo.u.loc))
&& targetm.calls.struct_value_rtx (type, 0) == 0)
{
tree struct_addr = build_pointer_type (TREE_TYPE (type));
- enum machine_mode mode = TYPE_MODE (struct_addr);
+ machine_mode mode = TYPE_MODE (struct_addr);
rtx reg;
INIT_CUMULATIVE_ARGS (args_so_far_v, type, NULL_RTX, fndecl,
nargs + 1);
nargs);
if (obj_type_ref && TYPE_ARG_TYPES (type) != void_list_node)
{
- enum machine_mode mode;
+ machine_mode mode;
t = TYPE_ARG_TYPES (type);
mode = TYPE_MODE (TREE_VALUE (t));
this_arg = targetm.calls.function_arg (args_so_far, mode,
if (GET_MODE (link) == VOIDmode
|| GET_MODE (link) == BLKmode
|| (GET_MODE (link) != GET_MODE (x)
- && (GET_MODE_CLASS (GET_MODE (link)) != MODE_INT
- || GET_MODE_CLASS (GET_MODE (x)) != MODE_INT)))
+ && ((GET_MODE_CLASS (GET_MODE (link)) != MODE_INT
+ && GET_MODE_CLASS (GET_MODE (link)) != MODE_PARTIAL_INT)
+ || (GET_MODE_CLASS (GET_MODE (x)) != MODE_INT
+ && GET_MODE_CLASS (GET_MODE (x)) != MODE_PARTIAL_INT))))
/* Can't do anything for these, if the original type mode
isn't known or can't be converted. */;
else if (REG_P (x))
cselib_val *val = cselib_lookup (x, GET_MODE (x), 0, VOIDmode);
if (val && cselib_preserved_value_p (val))
item = val->val_rtx;
- else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
+ else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
+ || GET_MODE_CLASS (GET_MODE (x)) == MODE_PARTIAL_INT)
{
- enum machine_mode mode = GET_MODE (x);
+ machine_mode mode = GET_MODE (x);
while ((mode = GET_MODE_WIDER_MODE (mode)) != VOIDmode
&& GET_MODE_BITSIZE (mode) <= BITS_PER_WORD)
struct adjust_mem_data amd;
amd.mem_mode = VOIDmode;
amd.stack_adjust = -VTI (bb)->out.stack_adjust;
- amd.side_effects = NULL_RTX;
+ amd.side_effects = NULL;
amd.store = true;
mem = simplify_replace_fn_rtx (mem, NULL_RTX, adjust_mems,
&amd);
val = cselib_lookup (mem, GET_MODE (mem), 0, VOIDmode);
if (val && cselib_preserved_value_p (val))
item = val->val_rtx;
- else if (GET_MODE_CLASS (GET_MODE (mem)) != MODE_INT)
+ else if (GET_MODE_CLASS (GET_MODE (mem)) != MODE_INT
+ && GET_MODE_CLASS (GET_MODE (mem)) != MODE_PARTIAL_INT)
{
/* For non-integer stack argument see also if they weren't
initialized by integers. */
- enum machine_mode imode = int_mode_for_mode (GET_MODE (mem));
+ machine_mode imode = int_mode_for_mode (GET_MODE (mem));
if (imode != GET_MODE (mem) && imode != BLKmode)
{
val = cselib_lookup (adjust_address_nv (mem, imode, 0),
if (t && t != void_list_node)
{
tree argtype = TREE_VALUE (t);
- enum machine_mode mode = TYPE_MODE (argtype);
+ machine_mode mode = TYPE_MODE (argtype);
rtx reg;
if (pass_by_reference (&args_so_far_v, mode, argtype, true))
{
&& reg
&& REG_P (reg)
&& GET_MODE (reg) == mode
- && GET_MODE_CLASS (mode) == MODE_INT
+ && (GET_MODE_CLASS (mode) == MODE_INT
+ || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
&& REG_P (x)
&& REGNO (x) == REGNO (reg)
&& GET_MODE (x) == mode
&& item)
{
- enum machine_mode indmode
+ machine_mode indmode
= TYPE_MODE (TREE_TYPE (argtype));
rtx mem = gen_rtx_MEM (indmode, x);
cselib_val *val = cselib_lookup (mem, indmode, 0, VOIDmode);
{
rtx item;
tree dtemp = (**debug_args)[ix + 1];
- enum machine_mode mode = DECL_MODE (dtemp);
+ machine_mode mode = DECL_MODE (dtemp);
item = gen_rtx_DEBUG_PARAMETER_REF (mode, param);
item = gen_rtx_CONCAT (mode, item, DECL_RTL_KNOWN_SET (dtemp));
call_arguments = gen_rtx_EXPR_LIST (VOIDmode, item,
}
if (this_arg)
{
- enum machine_mode mode
+ machine_mode mode
= TYPE_MODE (TREE_TYPE (OBJ_TYPE_REF_EXPR (obj_type_ref)));
rtx clobbered = gen_rtx_MEM (mode, this_arg);
HOST_WIDE_INT token
first place, in which case sets and n_sets will be 0). */
static void
-add_with_sets (rtx uncast_insn, struct cselib_set *sets, int n_sets)
+add_with_sets (rtx_insn *insn, struct cselib_set *sets, int n_sets)
{
- rtx_insn *insn = as_a <rtx_insn *> (uncast_insn);
basic_block bb = BLOCK_FOR_INSN (insn);
int n1, n2;
struct count_use_info cui;
while (n1 < n2 && mos[n2].type != MO_USE)
n2--;
if (n1 < n2)
- {
- micro_operation sw;
-
- sw = mos[n1];
- mos[n1] = mos[n2];
- mos[n2] = sw;
- }
+ std::swap (mos[n1], mos[n2]);
}
n2 = VTI (bb)->mos.length () - 1;
while (n1 < n2 && mos[n2].type == MO_VAL_LOC)
n2--;
if (n1 < n2)
- {
- micro_operation sw;
-
- sw = mos[n1];
- mos[n1] = mos[n2];
- mos[n2] = sw;
- }
+ std::swap (mos[n1], mos[n2]);
}
if (CALL_P (insn))
while (n1 < n2 && mos[n2].type != MO_VAL_USE)
n2--;
if (n1 < n2)
- {
- micro_operation sw;
-
- sw = mos[n1];
- mos[n1] = mos[n2];
- mos[n2] = sw;
- }
+ std::swap (mos[n1], mos[n2]);
}
n2 = VTI (bb)->mos.length () - 1;
while (n1 < n2 && mos[n2].type != MO_CLOBBER)
n2--;
if (n1 < n2)
- {
- micro_operation sw;
-
- sw = mos[n1];
- mos[n1] = mos[n2];
- mos[n2] = sw;
- }
+ std::swap (mos[n1], mos[n2]);
}
}
{
tree decl = NULL_TREE; /* The variable being copied around. */
rtx set_src = NULL_RTX; /* The value for "decl" stored in "src". */
- variable var;
- location_chain nextp;
+ variable *var;
+ location_chain *nextp;
int i;
bool found;
switch (mo->type)
{
case MO_CALL:
- dataflow_set_clear_at_call (out);
+ dataflow_set_clear_at_call (out, insn);
break;
case MO_USE:
static bool
vt_find_locations (void)
{
- fibheap_t worklist, pending, fibheap_swap;
- sbitmap visited, in_worklist, in_pending, sbitmap_swap;
+ bb_heap_t *worklist = new bb_heap_t (LONG_MIN);
+ bb_heap_t *pending = new bb_heap_t (LONG_MIN);
+ sbitmap visited, in_worklist, in_pending;
basic_block bb;
edge e;
int *bb_order;
bb_order[rc_order[i]] = i;
free (rc_order);
- worklist = fibheap_new ();
- pending = fibheap_new ();
visited = sbitmap_alloc (last_basic_block_for_fn (cfun));
in_worklist = sbitmap_alloc (last_basic_block_for_fn (cfun));
in_pending = sbitmap_alloc (last_basic_block_for_fn (cfun));
bitmap_clear (in_worklist);
FOR_EACH_BB_FN (bb, cfun)
- fibheap_insert (pending, bb_order[bb->index], bb);
+ pending->insert (bb_order[bb->index], bb);
bitmap_ones (in_pending);
- while (success && !fibheap_empty (pending))
+ while (success && !pending->empty ())
{
- fibheap_swap = pending;
- pending = worklist;
- worklist = fibheap_swap;
- sbitmap_swap = in_pending;
- in_pending = in_worklist;
- in_worklist = sbitmap_swap;
+ std::swap (worklist, pending);
+ std::swap (in_worklist, in_pending);
bitmap_clear (visited);
- while (!fibheap_empty (worklist))
+ while (!worklist->empty ())
{
- bb = (basic_block) fibheap_extract_min (worklist);
+ bb = worklist->extract_min ();
bitmap_clear_bit (in_worklist, bb->index);
gcc_assert (!bitmap_bit_p (visited, bb->index));
if (!bitmap_bit_p (visited, bb->index))
{
/* Send E->DEST to next round. */
bitmap_set_bit (in_pending, e->dest->index);
- fibheap_insert (pending,
- bb_order[e->dest->index],
- e->dest);
+ pending->insert (bb_order[e->dest->index],
+ e->dest);
}
}
else if (!bitmap_bit_p (in_worklist, e->dest->index))
{
/* Add E->DEST to current round. */
bitmap_set_bit (in_worklist, e->dest->index);
- fibheap_insert (worklist, bb_order[e->dest->index],
- e->dest);
+ worklist->insert (bb_order[e->dest->index],
+ e->dest);
}
}
}
oldinsz,
(int)shared_hash_htab (VTI (bb)->out.vars)->size (),
oldoutsz,
- (int)worklist->nodes, (int)pending->nodes, htabsz);
+ (int)worklist->nodes (), (int)pending->nodes (),
+ htabsz);
if (dump_file && (dump_flags & TDF_DETAILS))
{
gcc_assert (VTI (bb)->flooded);
free (bb_order);
- fibheap_delete (worklist);
- fibheap_delete (pending);
+ delete worklist;
+ delete pending;
sbitmap_free (visited);
sbitmap_free (in_worklist);
sbitmap_free (in_pending);
/* Print the content of the LIST to dump file. */
static void
-dump_attrs_list (attrs list)
+dump_attrs_list (attrs *list)
{
for (; list; list = list->next)
{
/* Print the information about variable *SLOT to dump file. */
int
-dump_var_tracking_slot (variable_def **slot, void *data ATTRIBUTE_UNUSED)
+dump_var_tracking_slot (variable **slot, void *data ATTRIBUTE_UNUSED)
{
- variable var = *slot;
+ variable *var = *slot;
dump_var (var);
/* Print the information about variable VAR to dump file. */
static void
-dump_var (variable var)
+dump_var (variable *var)
{
int i;
- location_chain node;
+ location_chain *node;
if (dv_is_decl_p (var->dv))
{
/* Return the variable for DV in dropped_values, inserting one if
requested with INSERT. */
-static inline variable
+static inline variable *
variable_from_dropped (decl_or_value dv, enum insert_option insert)
{
- variable_def **slot;
- variable empty_var;
- onepart_enum_t onepart;
+ variable **slot;
+ variable *empty_var;
+ onepart_enum onepart;
slot = dropped_values->find_slot_with_hash (dv, dv_htab_hash (dv), insert);
gcc_checking_assert (onepart == ONEPART_VALUE || onepart == ONEPART_DEXPR);
- empty_var = (variable) pool_alloc (onepart_pool (onepart));
+ empty_var = onepart_pool_allocate (onepart);
empty_var->dv = dv;
empty_var->refcount = 1;
empty_var->n_var_parts = 0;
/* Recover the one-part aux from dropped_values. */
static struct onepart_aux *
-recover_dropped_1paux (variable var)
+recover_dropped_1paux (variable *var)
{
- variable dvar;
+ variable *dvar;
gcc_checking_assert (var->onepart);
if it has no locations delete it from SET's hash table. */
static void
-variable_was_changed (variable var, dataflow_set *set)
+variable_was_changed (variable *var, dataflow_set *set)
{
hashval_t hash = dv_htab_hash (var->dv);
if (emit_notes)
{
- variable_def **slot;
+ variable **slot;
/* Remember this decl or VALUE has been added to changed_variables. */
set_dv_changed (var->dv, true);
if (*slot)
{
- variable old_var = *slot;
+ variable *old_var = *slot;
gcc_assert (old_var->in_changed_variables);
old_var->in_changed_variables = false;
if (var != old_var && var->onepart)
if (set && var->n_var_parts == 0)
{
- onepart_enum_t onepart = var->onepart;
- variable empty_var = NULL;
- variable_def **dslot = NULL;
+ onepart_enum onepart = var->onepart;
+ variable *empty_var = NULL;
+ variable **dslot = NULL;
if (onepart == ONEPART_VALUE || onepart == ONEPART_DEXPR)
{
if (!empty_var)
{
- empty_var = (variable) pool_alloc (onepart_pool (onepart));
+ empty_var = onepart_pool_allocate (onepart);
empty_var->dv = var->dv;
empty_var->refcount = 1;
empty_var->n_var_parts = 0;
gcc_assert (set);
if (var->n_var_parts == 0)
{
- variable_def **slot;
+ variable **slot;
drop_var:
slot = shared_hash_find_slot_noinsert (set->vars, var->dv);
have, if it should be inserted. */
static inline int
-find_variable_location_part (variable var, HOST_WIDE_INT offset,
+find_variable_location_part (variable *var, HOST_WIDE_INT offset,
int *insertion_point)
{
int pos, low, high;
return -1;
}
-static variable_def **
-set_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
+static variable **
+set_slot_part (dataflow_set *set, rtx loc, variable **slot,
decl_or_value dv, HOST_WIDE_INT offset,
enum var_init_status initialized, rtx set_src)
{
int pos;
- location_chain node, next;
- location_chain *nextp;
- variable var;
- onepart_enum_t onepart;
+ location_chain *node, *next;
+ location_chain **nextp;
+ variable *var;
+ onepart_enum onepart;
var = *slot;
if (!var)
{
/* Create new variable information. */
- var = (variable) pool_alloc (onepart_pool (onepart));
+ var = onepart_pool_allocate (onepart);
var->dv = dv;
var->refcount = 1;
var->n_var_parts = 1;
set_src = node->set_src;
if (var->var_part[pos].cur_loc == node->loc)
var->var_part[pos].cur_loc = NULL;
- pool_free (loc_chain_pool, node);
+ delete node;
*nextp = next;
break;
}
}
/* Add the location to the beginning. */
- node = (location_chain) pool_alloc (loc_chain_pool);
+ node = new location_chain;
node->loc = loc;
node->init = initialized;
node->set_src = set_src;
enum var_init_status initialized, rtx set_src,
enum insert_option iopt)
{
- variable_def **slot;
+ variable **slot;
if (iopt == NO_INSERT)
slot = shared_hash_find_slot_noinsert (set->vars, dv);
The variable part is specified by variable's declaration or value
DV and offset OFFSET. */
-static variable_def **
-clobber_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
+static variable **
+clobber_slot_part (dataflow_set *set, rtx loc, variable **slot,
HOST_WIDE_INT offset, rtx set_src)
{
- variable var = *slot;
+ variable *var = *slot;
int pos = find_variable_location_part (var, offset, NULL);
if (pos >= 0)
{
- location_chain node, next;
+ location_chain *node, *next;
/* Remove the register locations from the dataflow set. */
next = var->var_part[pos].loc_chain;
{
if (REG_P (node->loc))
{
- attrs anode, anext;
- attrs *anextp;
+ attrs *anode, *anext;
+ attrs **anextp;
/* Remove the variable part from the register's
list, but preserve any other variable parts
if (dv_as_opaque (anode->dv) == dv_as_opaque (var->dv)
&& anode->offset == offset)
{
- pool_free (attrs_pool, anode);
+ delete anode;
*anextp = anext;
}
else
clobber_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
HOST_WIDE_INT offset, rtx set_src)
{
- variable_def **slot;
+ variable **slot;
if (!dv_as_opaque (dv)
|| (!dv_is_value_p (dv) && ! DECL_P (dv_as_decl (dv))))
variable part is specified by its SET->vars slot SLOT and offset
OFFSET and the part's location by LOC. */
-static variable_def **
-delete_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
+static variable **
+delete_slot_part (dataflow_set *set, rtx loc, variable **slot,
HOST_WIDE_INT offset)
{
- variable var = *slot;
+ variable *var = *slot;
int pos = find_variable_location_part (var, offset, NULL);
if (pos >= 0)
{
- location_chain node, next;
- location_chain *nextp;
+ location_chain *node, *next;
+ location_chain **nextp;
bool changed;
rtx cur_loc;
if (pos == 0 && var->onepart && VAR_LOC_1PAUX (var))
VAR_LOC_FROM (var) = NULL;
}
- pool_free (loc_chain_pool, node);
+ delete node;
*nextp = next;
break;
}
delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
HOST_WIDE_INT offset)
{
- variable_def **slot = shared_hash_find_slot_noinsert (set->vars, dv);
+ variable **slot = shared_hash_find_slot_noinsert (set->vars, dv);
if (!slot)
return;
room for COUNT dependencies. */
static void
-loc_exp_dep_alloc (variable var, int count)
+loc_exp_dep_alloc (variable *var, int count)
{
size_t allocsize;
removing them from the back-links lists too. */
static void
-loc_exp_dep_clear (variable var)
+loc_exp_dep_clear (variable *var)
{
while (VAR_LOC_DEP_VEC (var) && !VAR_LOC_DEP_VEC (var)->is_empty ())
{
back-links in VARS. */
static void
-loc_exp_insert_dep (variable var, rtx x, variable_table_type *vars)
+loc_exp_insert_dep (variable *var, rtx x, variable_table_type *vars)
{
decl_or_value dv;
- variable xvar;
+ variable *xvar;
loc_exp_dep *led;
dv = dv_from_rtx (x);
return;
if (var->onepart == NOT_ONEPART)
- led = (loc_exp_dep *) pool_alloc (loc_exp_dep_pool);
+ led = new loc_exp_dep;
else
{
loc_exp_dep empty;
true if we found any pending-recursion results. */
static bool
-loc_exp_dep_set (variable var, rtx result, rtx *value, int count,
+loc_exp_dep_set (variable *var, rtx result, rtx *value, int count,
variable_table_type *vars)
{
bool pending_recursion = false;
attempt to compute a current location. */
static void
-notify_dependents_of_resolved_value (variable ivar, variable_table_type *vars)
+notify_dependents_of_resolved_value (variable *ivar, variable_table_type *vars)
{
loc_exp_dep *led, *next;
for (led = VAR_LOC_DEP_LST (ivar); led; led = next)
{
decl_or_value dv = led->dv;
- variable var;
+ variable *var;
next = led->next;
it is pending recursion resolution. */
static inline rtx
-vt_expand_var_loc_chain (variable var, bitmap regs, void *data, bool *pendrecp)
+vt_expand_var_loc_chain (variable *var, bitmap regs, void *data,
+ bool *pendrecp)
{
struct expand_loc_callback_data *elcd
= (struct expand_loc_callback_data *) data;
- location_chain loc, next;
+ location_chain *loc, *next;
rtx result = NULL;
int first_child, result_first_child, last_child;
bool pending_recursion;
struct expand_loc_callback_data *elcd
= (struct expand_loc_callback_data *) data;
decl_or_value dv;
- variable var;
+ variable *var;
rtx result, subreg;
bool pending_recursion = false;
bool from_empty = false;
in VARS, updating their CUR_LOCs in the process. */
static rtx
-vt_expand_1pvar (variable var, variable_table_type *vars)
+vt_expand_1pvar (variable *var, variable_table_type *vars)
{
struct expand_loc_callback_data data;
rtx loc;
before or after instruction INSN. */
int
-emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
+emit_note_insn_var_location (variable **varp, emit_note_data *data)
{
- variable var = *varp;
+ variable *var = *varp;
rtx_insn *insn = data->insn;
enum emit_note_where where = data->where;
variable_table_type *vars = data->vars;
HOST_WIDE_INT offsets[MAX_VAR_PARTS];
rtx loc[MAX_VAR_PARTS];
tree decl;
- location_chain lc;
+ location_chain *lc;
gcc_checking_assert (var->onepart == NOT_ONEPART
|| var->onepart == ONEPART_VDECL);
var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc;
for (i = 0; i < var->n_var_parts; i++)
{
- enum machine_mode mode, wider_mode;
+ machine_mode mode, wider_mode;
rtx loc2;
HOST_WIDE_INT offset;
values) entries that aren't user variables. */
int
-var_track_values_to_stack (variable_def **slot,
+var_track_values_to_stack (variable **slot,
vec<rtx, va_heap> *changed_values_stack)
{
- variable var = *slot;
+ variable *var = *slot;
if (var->onepart == ONEPART_VALUE)
changed_values_stack->safe_push (dv_as_value (var->dv));
remove_value_from_changed_variables (rtx val)
{
decl_or_value dv = dv_from_rtx (val);
- variable_def **slot;
- variable var;
+ variable **slot;
+ variable *var;
slot = changed_variables->find_slot_with_hash (dv, dv_htab_hash (dv),
NO_INSERT);
notify_dependents_of_changed_value (rtx val, variable_table_type *htab,
vec<rtx, va_heap> *changed_values_stack)
{
- variable_def **slot;
- variable var;
+ variable **slot;
+ variable *var;
loc_exp_dep *led;
decl_or_value dv = dv_from_rtx (val);
while ((led = VAR_LOC_DEP_LST (var)))
{
decl_or_value ldv = led->dv;
- variable ivar;
+ variable *ivar;
/* Deactivate and remove the backlink, as it was “used up”. It
makes no sense to attempt to notify the same entity again:
break;
case NOT_ONEPART:
- pool_free (loc_exp_dep_pool, led);
+ delete led;
ivar = htab->find_with_hash (ldv, dv_htab_hash (ldv));
if (ivar)
{
static void
emit_notes_for_changes (rtx_insn *insn, enum emit_note_where where,
- shared_hash vars)
+ shared_hash *vars)
{
emit_note_data data;
variable_table_type *htab = shared_hash_htab (vars);
same variable in hash table DATA or is not there at all. */
int
-emit_notes_for_differences_1 (variable_def **slot, variable_table_type *new_vars)
+emit_notes_for_differences_1 (variable **slot, variable_table_type *new_vars)
{
- variable old_var, new_var;
+ variable *old_var, *new_var;
old_var = *slot;
new_var = new_vars->find_with_hash (old_var->dv, dv_htab_hash (old_var->dv));
if (!new_var)
{
/* Variable has disappeared. */
- variable empty_var = NULL;
+ variable *empty_var = NULL;
if (old_var->onepart == ONEPART_VALUE
|| old_var->onepart == ONEPART_DEXPR)
if (!empty_var)
{
- empty_var = (variable) pool_alloc (onepart_pool (old_var->onepart));
+ empty_var = onepart_pool_allocate (old_var->onepart);
empty_var->dv = old_var->dv;
empty_var->refcount = 0;
empty_var->n_var_parts = 0;
table DATA. */
int
-emit_notes_for_differences_2 (variable_def **slot, variable_table_type *old_vars)
+emit_notes_for_differences_2 (variable **slot, variable_table_type *old_vars)
{
- variable old_var, new_var;
+ variable *old_var, *new_var;
new_var = *slot;
old_var = old_vars->find_with_hash (new_var->dv, dv_htab_hash (new_var->dv));
switch (mo->type)
{
case MO_CALL:
- dataflow_set_clear_at_call (set);
+ dataflow_set_clear_at_call (set, insn);
emit_notes_for_changes (insn, EMIT_NOTE_AFTER_CALL_INSN, set->vars);
{
rtx arguments = mo->u.loc, *p = &arguments;
if (MAY_HAVE_DEBUG_INSNS)
{
dropped_values = new variable_table_type (cselib_get_next_uid () * 2);
- loc_exp_dep_pool = create_alloc_pool ("loc_exp_dep pool",
- sizeof (loc_exp_dep), 64);
}
dataflow_set_init (&cur);
rtx decl_rtl = DECL_RTL_IF_SET (parm);
rtx incoming = DECL_INCOMING_RTL (parm);
tree decl;
- enum machine_mode mode;
+ machine_mode mode;
HOST_WIDE_INT offset;
dataflow_set *out;
decl_or_value dv;
&& HARD_REGISTER_P (incoming)
&& OUTGOING_REGNO (REGNO (incoming)) != REGNO (incoming))
{
- parm_reg_t p;
+ parm_reg p;
p.incoming = incoming;
incoming
= gen_rtx_REG_offset (incoming, GET_MODE (incoming),
for (i = 0; i < XVECLEN (incoming, 0); i++)
{
rtx reg = XEXP (XVECEXP (incoming, 0, i), 0);
- parm_reg_t p;
+ parm_reg p;
p.incoming = reg;
reg = gen_rtx_REG_offset (reg, GET_MODE (reg),
OUTGOING_REGNO (REGNO (reg)), 0);
rtx reg = XEXP (incoming, 0);
if (OUTGOING_REGNO (REGNO (reg)) != REGNO (reg))
{
- parm_reg_t p;
+ parm_reg p;
p.incoming = reg;
reg = gen_raw_REG (GET_MODE (reg), OUTGOING_REGNO (REGNO (reg)));
p.outgoing = reg;
if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE
&& INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (parm))))
{
- enum machine_mode indmode
+ machine_mode indmode
= TYPE_MODE (TREE_TYPE (TREE_TYPE (parm)));
rtx mem = gen_rtx_MEM (indmode, incoming);
cselib_val *val = cselib_lookup_from_insn (mem, indmode, true,
for (parm = DECL_ARGUMENTS (current_function_decl);
parm; parm = DECL_CHAIN (parm))
- vt_add_function_parameter (parm);
+ if (!POINTER_BOUNDS_P (parm))
+ vt_add_function_parameter (parm);
if (DECL_HAS_VALUE_EXPR_P (DECL_RESULT (current_function_decl)))
{
basic_block bb;
HOST_WIDE_INT fp_cfa_offset = -1;
- alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def));
-
- attrs_pool = create_alloc_pool ("attrs_def pool",
- sizeof (struct attrs_def), 1024);
- var_pool = create_alloc_pool ("variable_def pool",
- sizeof (struct variable_def)
- + (MAX_VAR_PARTS - 1)
- * sizeof (((variable)NULL)->var_part[0]), 64);
- loc_chain_pool = create_alloc_pool ("location_chain_def pool",
- sizeof (struct location_chain_def),
- 1024);
- shared_hash_pool = create_alloc_pool ("shared_hash_def pool",
- sizeof (struct shared_hash_def), 256);
- empty_shared_hash = (shared_hash) pool_alloc (shared_hash_pool);
+ alloc_aux_for_blocks (sizeof (variable_tracking_info));
+
+ empty_shared_hash = new shared_hash;
empty_shared_hash->refcount = 1;
empty_shared_hash->htab = new variable_table_type (1);
changed_variables = new variable_table_type (10);
{
cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS);
scratch_regs = BITMAP_ALLOC (NULL);
- valvar_pool = create_alloc_pool ("small variable_def pool",
- sizeof (struct variable_def), 256);
preserved_values.create (256);
global_get_addr_cache = new hash_map<rtx, rtx>;
}
else
{
scratch_regs = NULL;
- valvar_pool = NULL;
global_get_addr_cache = NULL;
}
empty_shared_hash->htab = NULL;
delete changed_variables;
changed_variables = NULL;
- free_alloc_pool (attrs_pool);
- free_alloc_pool (var_pool);
- free_alloc_pool (loc_chain_pool);
- free_alloc_pool (shared_hash_pool);
+ attrs_pool.release ();
+ var_pool.release ();
+ location_chain_pool.release ();
+ shared_hash_pool.release ();
if (MAY_HAVE_DEBUG_INSNS)
{
if (global_get_addr_cache)
delete global_get_addr_cache;
global_get_addr_cache = NULL;
- if (loc_exp_dep_pool)
- free_alloc_pool (loc_exp_dep_pool);
- loc_exp_dep_pool = NULL;
- free_alloc_pool (valvar_pool);
+ loc_exp_dep_pool.release ();
+ valvar_pool.release ();
preserved_values.release ();
cselib_finish ();
BITMAP_FREE (scratch_regs);
{
bool success;
- if (flag_var_tracking_assignments < 0)
+ if (flag_var_tracking_assignments < 0
+ /* Var-tracking right now assumes the IR doesn't contain
+ any pseudos at this point. */
+ || targetm.no_register_allocation)
{
delete_debug_insns ();
return 0;