mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-27 20:51:11 +08:00
2008-08-26 Vladimir Makarov <vmakarov@redhat.com> * ira-build.c, ira-color.c, ira-costs.c, ira.h, ira-lives.c, ira.c, ira-conflicts.c, ira-emit.c, ira-int.h: New files. * doc/passes.texi: Describe IRA. * doc/tm.texi (IRA_COVER_CLASSES, IRA_HARD_REGNO_ADD_COST_MULTIPLIER): Describe the new macros. * doc/invoke.texi (ira-max-loops-num): Describe the new parameter. (-fira, -fira-algorithm, -fira-coalesce, -fno-ira-move-spills, -fira-propagate-cost, -fno-ira-share-save-slots, -fno-ira-share-spill-slots, -fira-verbose): Describe new options. * flags.h (ira_algorithm): New enumeration. (flag_ira_algorithm, flag_ira_verbose): New external variable declarations. * postreload.c (gate_handle_postreload): Don't do post reload optimizations unless the reload is completed. * reload.c (push_reload, find_dummy_reload): Use DF_LR_OUT for IRA. * tree-pass.h (pass_ira): New external variable declaration. * reload.h: Add 2008 to the Copyright. * cfgloopanal.c: Include params.h. (estimate_reg_pressure_cost): Decrease cost for IRA optimization mode. * params.h (IRA_MAX_LOOPS_NUM): New macro. * toplev.c (ira.h): New include. (flag_ira_algorithm, flag_ira_verbose): New external variables. (backend_init_target): Call ira_init. (backend_init): Call ira_init_once. (finalize): Call finish_ira_once. * toplev.h (flag_ira, flag_ira_coalesce, flag_ira_move_spills, flag_ira_share_save_slots, flag_ira_share_spill_slots): New external variables. * regs.h (contains_reg_of_mode, move_cost, may_move_in_cost, may_move_out_cost): New external variable declarations. (move_table): New typedef. * caller-save.c: Include headers output.h and ira.h. (no_caller_save_reg_set): New global variable. (save_slots_num, save_slots): New variables. (reg_save_code, reg_restore_code, add_stored_regs): Add prototypes. (init_caller_save): Set up no_caller_save_reg_set. (init_save_areas): Reset save_slots_num. (saved_hard_reg): New structure. (hard_reg_map, saved_regs_num, all_saved_regs): New variables. (initiate_saved_hard_regs, new_saved_hard_reg, finish_saved_hard_regs, saved_hard_reg_compare_func): New functions. (setup_save_areas): Add code for sharing stack slots. (all_blocks): New variable. (save_call_clobbered_regs): Process pseudo-register too. (mark_set_regs): Process pseudo-register too. (insert_one_insn): Put the insn after bb note in a empty basic block. Add insn check. * global.c (eliminable_regset): Make it external. (mark_elimination): Use DF_LR_IN for IRA. (pseudo_for_reload_consideration_p): New. (build_insn_chain): Make it external. Don't ignore spilled pseudos for IRA. Use pseudo_for_reload_consideration_p. (gate_handle_global_alloc): New function. (pass_global_alloc): Add the gate function. * opts.c (decode_options): Set up flag_ira. Print the warning for -fira. (common_handle_option): Process -fira-algorithm and -fira-verbose. * timevar.def (TV_IRA, TV_RELOAD): New passes. * regmove.c (regmove_optimize): Don't do replacement of output for IRA. * hard-reg-set.h (no_caller_save_reg_set, reg_class_subclasses): New external variable declarations. * local-alloc.c (update_equiv_regs): Make it external. Return true if jump label rebuilding should be done. Rescan new_insn for notes. (gate_handle_local_alloc): New function. (pass_local_alloc): Add the gate function. * alias.c (value_addr_p, stack_addr_p): New functions. (nonoverlapping_memrefs_p): Use them for IRA. * common.opt (fira, fira-algorithm, fira-coalesce, fira-move-spills, fira-share-save-slots, fira-share-spill-slots, fira-verbose): New options. * regclass.c (reg_class_subclasses, contains_reg_of_mode, move_cost, may_move_in_cost, may_move_out_cost): Make the variables external. (move_table): Remove typedef. (init_move_cost): Make it external. (allocate_reg_info, resize_reg_info, setup_reg_classes): New functions. * rtl.h (init_move_cost, allocate_reg_info, resize_reg_info, setup_reg_classes): New function prototypes. (eliminable_regset): New external variable declaration. (build_insn_chain, update_equiv_regs): New function prototypes. * Makefile.in (IRA_INT_H): New definition. (OBJS-common): Add ira.o, ira-build.o, ira-costs.o, ira-conflicts.o, ira-color.o, ira-emit.o, and ira-lives.o. (reload1.o, toplev.o): Add dependence on ira.h. (cfgloopanal.o): Add PARAMS_H. (caller-save.o): Add dependence on output.h and ira.h. (ira.o, ira-build.o, ira-costs.o, ira-conflicts.o, ira-color.o, ira-emit.o, ira-lives.o): New entries. * passes.c (pass_ira): New pass. * params.def (PARAM_IRA_MAX_LOOPS_NUM): New parameter. * reload1.c (ira.h): Include the header. (changed_allocation_pseudos): New bitmap. (init_reload): Initiate the bitmap. (compute_use_by_pseudos): Permits spilled registers in FROM. (temp_pseudo_reg_arr): New variable. (reload): Allocate and free temp_pseudo_reg_arr. Sort pseudos for IRA. Call alter_reg with the additional parameter. Don't clear spilled_pseudos for IRA. Restore original insn chain for IRA. Clear changed_allocation_pseudos at the end of reload. (calculate_needs_all_insns): Call IRA's mark_memory_move_deletion. (hard_regno_to_pseudo_regno): New variable. (count_pseudo): Check spilled pseudos. Set up hard_regno_to_pseudo_regno. (count_spilled_pseudo): Check spilled pseudos. Update hard_regno_to_pseudo_regno. (find_reg): Use better_spill_reload_regno_p. Check hard_regno_to_pseudo_regno. (alter_reg): Set up spilled_pseudos. Add a new parameter. Add code for IRA. (eliminate_regs_1): Use additional parameter for alter_reg. (finish_spills): Set up pseudo_previous_regs only for spilled pseudos. Call reassign_pseudos once for all spilled pseudos, pass more arguments. Don't clear live_throughout and dead_or_set for spilled pseudos. Use additional parameter for alter_reg. Call mark_allocation_change. Set up changed_allocation_pseudos. Remove sanity check. (emit_input_reload_insns, delete_output_reload): Use additional parameter for alter_reg. Call mark_allocation_change. (substitute, gen_reload_chain_without_interm_reg_p): New functions. (reloads_conflict): Use gen_reload_chain_without_interm_reg_p. * testsuite/gcc.dg/20080410-1.c: New file. * config/s390/s390.h (IRA_COVER_CLASSES, IRA_HARD_REGNO_ADD_COST_MULTIPLIER): Define. * config/sparc/sparc.h (IRA_COVER_CLASSES): New macro. * config/i386/i386.h (IRA_COVER_CLASSES): Ditto. * config/ia64/ia64.h (IRA_COVER_CLASSES): Ditto. * config/rs6000/rs6000.h (IRA_COVER_CLASSES): Ditto. * config/arm/arm.h (IRA_COVER_CLASSES): Ditto. * config/alpha/alpha.h (IRA_COVER_CLASSES): Ditto. 2008-08-24 Jeff Law <law@redhat.com> * ira.c (setup_reg_class_intersect_union): Prefer smallest class when ignoring unavailable registers. 2008-08-24 Jeff Law <law@redhat.com> * ira-color.c (coalesced_pseudo_reg_slot_compare): Check FRAME_GROWS_DOWNWARD and STACK_GROWS_DOWNWARD. * ira.c (setup_eliminable_regset): Check stack_realign_needed. * config/mn10300/mn10300.h (IRA_COVER_CLASSES): New macro. 2008-06-03 Steve Chamberlain <steve.chamberlain@gmail.com> * ira-build.c (allocno_range_compare_func): Stabilize sort. 2008-05-29 Andy Hutchinson <hutchinsonandy@aim.com> * config/avr/avr.h (IRA_COVER_CLASSES): New macro. * reload1.c (find_reg): Process registers in register allocation order. 2008-05-10 Richard Sandiford <rsandifo@nildram.co.uk> * toplev.c (backend_init_target): Move ira_init call from here... (lang_dependent_init_target): ...to here. 2008-05-10 Richard Sandiford <rsandifo@nildram.co.uk> * ira.c (setup_class_subset_and_memory_move_costs): Don't calculate memory move costs for NO_REGS. 2008-05-05 Kaz Kojima <kkojima@gcc.gnu.org> * ira-color.c (ira_fast_allocation): Use no_stack_reg_p only if STACK_REGS is defined. 2008-04-08 Andrew Pinski <andrew_pinski@playstation.sony.com> * config/spu/spu.h (IRA_COVER_CLASSES): New macro. 2008-04-04 Bernd Schmidt <bernd.schmidt@analog.com> * config/bfin/bfin.h (IRA_COVER_CLASSES): New macro. 2008-04-04 Kaz Kojima <kkojima@gcc.gnu.org> * config/sh/sh.h (IRA_COVER_CLASSES): Define. * config/sh/sh.md (movsicc_true+3): Check if emit returns a barrier. From-SVN: r139590
371 lines
12 KiB
C
371 lines
12 KiB
C
/* Define per-register tables for data flow info and register allocation.
|
|
Copyright (C) 1987, 1993, 1994, 1995, 1996, 1997, 1998,
|
|
1999, 2000, 2003, 2004, 2005, 2006, 2007, 2008 Free Software
|
|
Foundation, Inc.
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 3, or (at your option) any later
|
|
version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef GCC_REGS_H
|
|
#define GCC_REGS_H
|
|
|
|
#include "varray.h"
|
|
#include "obstack.h"
|
|
#include "hard-reg-set.h"
|
|
#include "basic-block.h"
|
|
|
|
#define REG_BYTES(R) mode_size[(int) GET_MODE (R)]
|
|
|
|
/* When you only have the mode of a pseudo register before it has a hard
|
|
register chosen for it, this reports the size of each hard register
|
|
a pseudo in such a mode would get allocated to. A target may
|
|
override this. */
|
|
|
|
#ifndef REGMODE_NATURAL_SIZE
|
|
#define REGMODE_NATURAL_SIZE(MODE) UNITS_PER_WORD
|
|
#endif
|
|
|
|
#ifndef SMALL_REGISTER_CLASSES
|
|
#define SMALL_REGISTER_CLASSES 0
|
|
#endif
|
|
|
|
/* Maximum register number used in this function, plus one. */
|
|
|
|
extern int max_regno;
|
|
|
|
/* REG_N_REFS and REG_N_SETS are initialized by a call to
|
|
regstat_init_n_sets_and_refs from the current values of
|
|
DF_REG_DEF_COUNT and DF_REG_USE_COUNT. REG_N_REFS and REG_N_SETS
|
|
should only be used if a pass need to change these values in some
|
|
magical way or or the pass needs to have accurate values for these
|
|
and is not using incremental df scanning.
|
|
|
|
At the end of a pass that uses REG_N_REFS and REG_N_SETS, a call
|
|
should be made to regstat_free_n_sets_and_refs.
|
|
|
|
Local alloc seems to play pretty loose with these values.
|
|
REG_N_REFS is set to 0 if the register is used in an asm.
|
|
Furthermore, local_alloc calls regclass to hack both REG_N_REFS and
|
|
REG_N_SETS for three address insns. Other passes seem to have
|
|
other special values. */
|
|
|
|
|
|
|
|
/* Structure to hold values for REG_N_SETS (i) and REG_N_REFS (i). */
|
|
|
|
struct regstat_n_sets_and_refs_t
|
|
{
|
|
int sets; /* # of times (REG n) is set */
|
|
int refs; /* # of times (REG n) is used or set */
|
|
};
|
|
|
|
extern struct regstat_n_sets_and_refs_t *regstat_n_sets_and_refs;
|
|
|
|
/* Indexed by n, gives number of times (REG n) is used or set. */
|
|
static inline int
|
|
REG_N_REFS(int regno)
|
|
{
|
|
return regstat_n_sets_and_refs[regno].refs;
|
|
}
|
|
|
|
/* Indexed by n, gives number of times (REG n) is used or set. */
|
|
#define SET_REG_N_REFS(N,V) (regstat_n_sets_and_refs[N].refs = V)
|
|
#define INC_REG_N_REFS(N,V) (regstat_n_sets_and_refs[N].refs += V)
|
|
|
|
/* Indexed by n, gives number of times (REG n) is set. */
|
|
static inline int
|
|
REG_N_SETS (int regno)
|
|
{
|
|
return regstat_n_sets_and_refs[regno].sets;
|
|
}
|
|
|
|
/* Indexed by n, gives number of times (REG n) is set. */
|
|
#define SET_REG_N_SETS(N,V) (regstat_n_sets_and_refs[N].sets = V)
|
|
#define INC_REG_N_SETS(N,V) (regstat_n_sets_and_refs[N].sets += V)
|
|
|
|
|
|
/* Functions defined in reg-stat.c. */
|
|
extern void regstat_init_n_sets_and_refs (void);
|
|
extern void regstat_free_n_sets_and_refs (void);
|
|
extern void regstat_compute_ri (void);
|
|
extern void regstat_free_ri (void);
|
|
extern bitmap regstat_get_setjmp_crosses (void);
|
|
extern void regstat_compute_calls_crossed (void);
|
|
extern void regstat_free_calls_crossed (void);
|
|
|
|
|
|
/* Register information indexed by register number. This structure is
|
|
initialized by calling regstat_compute_ri and is destroyed by
|
|
calling regstat_free_ri. */
|
|
struct reg_info_t
|
|
{
|
|
int freq; /* # estimated frequency (REG n) is used or set */
|
|
int deaths; /* # of times (REG n) dies */
|
|
int live_length; /* # of instructions (REG n) is live */
|
|
int calls_crossed; /* # of calls (REG n) is live across */
|
|
int freq_calls_crossed; /* # estimated frequency (REG n) crosses call */
|
|
int throw_calls_crossed; /* # of calls that may throw (REG n) is live across */
|
|
int basic_block; /* # of basic blocks (REG n) is used in */
|
|
};
|
|
|
|
extern struct reg_info_t *reg_info_p;
|
|
|
|
/* The number allocated elements of reg_info_p. */
|
|
extern size_t reg_info_p_size;
|
|
|
|
/* Estimate frequency of references to register N. */
|
|
|
|
#define REG_FREQ(N) (reg_info_p[N].freq)
|
|
|
|
/* The weights for each insn varies from 0 to REG_FREQ_BASE.
|
|
This constant does not need to be high, as in infrequently executed
|
|
regions we want to count instructions equivalently to optimize for
|
|
size instead of speed. */
|
|
#define REG_FREQ_MAX 1000
|
|
|
|
/* Compute register frequency from the BB frequency. When optimizing for size,
|
|
or profile driven feedback is available and the function is never executed,
|
|
frequency is always equivalent. Otherwise rescale the basic block
|
|
frequency. */
|
|
#define REG_FREQ_FROM_BB(bb) (optimize_size \
|
|
|| (flag_branch_probabilities \
|
|
&& !ENTRY_BLOCK_PTR->count) \
|
|
? REG_FREQ_MAX \
|
|
: ((bb)->frequency * REG_FREQ_MAX / BB_FREQ_MAX)\
|
|
? ((bb)->frequency * REG_FREQ_MAX / BB_FREQ_MAX)\
|
|
: 1)
|
|
|
|
/* Indexed by N, gives number of insns in which register N dies.
|
|
Note that if register N is live around loops, it can die
|
|
in transitions between basic blocks, and that is not counted here.
|
|
So this is only a reliable indicator of how many regions of life there are
|
|
for registers that are contained in one basic block. */
|
|
|
|
#define REG_N_DEATHS(N) (reg_info_p[N].deaths)
|
|
|
|
/* Get the number of consecutive words required to hold pseudo-reg N. */
|
|
|
|
#define PSEUDO_REGNO_SIZE(N) \
|
|
((GET_MODE_SIZE (PSEUDO_REGNO_MODE (N)) + UNITS_PER_WORD - 1) \
|
|
/ UNITS_PER_WORD)
|
|
|
|
/* Get the number of bytes required to hold pseudo-reg N. */
|
|
|
|
#define PSEUDO_REGNO_BYTES(N) \
|
|
GET_MODE_SIZE (PSEUDO_REGNO_MODE (N))
|
|
|
|
/* Get the machine mode of pseudo-reg N. */
|
|
|
|
#define PSEUDO_REGNO_MODE(N) GET_MODE (regno_reg_rtx[N])
|
|
|
|
/* Indexed by N, gives number of CALL_INSNS across which (REG n) is live. */
|
|
|
|
#define REG_N_CALLS_CROSSED(N) (reg_info_p[N].calls_crossed)
|
|
#define REG_FREQ_CALLS_CROSSED(N) (reg_info_p[N].freq_calls_crossed)
|
|
|
|
/* Indexed by N, gives number of CALL_INSNS that may throw, across which
|
|
(REG n) is live. */
|
|
|
|
#define REG_N_THROWING_CALLS_CROSSED(N) (reg_info_p[N].throw_calls_crossed)
|
|
|
|
/* Total number of instructions at which (REG n) is live. The larger
|
|
this is, the less priority (REG n) gets for allocation in a hard
|
|
register (in global-alloc). This is set in df-problems.c whenever
|
|
register info is requested and remains valid for the rest of the
|
|
compilation of the function; it is used to control register
|
|
allocation.
|
|
|
|
local-alloc.c may alter this number to change the priority.
|
|
|
|
Negative values are special.
|
|
-1 is used to mark a pseudo reg which has a constant or memory equivalent
|
|
and is used infrequently enough that it should not get a hard register.
|
|
-2 is used to mark a pseudo reg for a parameter, when a frame pointer
|
|
is not required. global.c makes an allocno for this but does
|
|
not try to assign a hard register to it. */
|
|
|
|
#define REG_LIVE_LENGTH(N) (reg_info_p[N].live_length)
|
|
|
|
/* Indexed by n, gives number of basic block that (REG n) is used in.
|
|
If the value is REG_BLOCK_GLOBAL (-1),
|
|
it means (REG n) is used in more than one basic block.
|
|
REG_BLOCK_UNKNOWN (0) means it hasn't been seen yet so we don't know.
|
|
This information remains valid for the rest of the compilation
|
|
of the current function; it is used to control register allocation. */
|
|
|
|
#define REG_BLOCK_UNKNOWN 0
|
|
#define REG_BLOCK_GLOBAL -1
|
|
|
|
#define REG_BASIC_BLOCK(N) (reg_info_p[N].basic_block)
|
|
|
|
/* Vector of substitutions of register numbers,
|
|
used to map pseudo regs into hardware regs.
|
|
|
|
This can't be folded into reg_n_info without changing all of the
|
|
machine dependent directories, since the reload functions
|
|
in the machine dependent files access it. */
|
|
|
|
extern short *reg_renumber;
|
|
|
|
/* Vector indexed by machine mode saying whether there are regs of that mode. */
|
|
|
|
extern bool have_regs_of_mode [MAX_MACHINE_MODE];
|
|
|
|
/* For each hard register, the widest mode object that it can contain.
|
|
This will be a MODE_INT mode if the register can hold integers. Otherwise
|
|
it will be a MODE_FLOAT or a MODE_CC mode, whichever is valid for the
|
|
register. */
|
|
|
|
extern enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];
|
|
|
|
/* Flag set by local-alloc or global-alloc if they decide to allocate
|
|
something in a call-clobbered register. */
|
|
|
|
extern int caller_save_needed;
|
|
|
|
/* Predicate to decide whether to give a hard reg to a pseudo which
|
|
is referenced REFS times and would need to be saved and restored
|
|
around a call CALLS times. */
|
|
|
|
#ifndef CALLER_SAVE_PROFITABLE
|
|
#define CALLER_SAVE_PROFITABLE(REFS, CALLS) (4 * (CALLS) < (REFS))
|
|
#endif
|
|
|
|
/* On most machines a register class is likely to be spilled if it
|
|
only has one register. */
|
|
#ifndef CLASS_LIKELY_SPILLED_P
|
|
#define CLASS_LIKELY_SPILLED_P(CLASS) (reg_class_size[(int) (CLASS)] == 1)
|
|
#endif
|
|
|
|
/* Select a register mode required for caller save of hard regno REGNO. */
|
|
#ifndef HARD_REGNO_CALLER_SAVE_MODE
|
|
#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
|
|
choose_hard_reg_mode (REGNO, NREGS, false)
|
|
#endif
|
|
|
|
/* Registers that get partially clobbered by a call in a given mode.
|
|
These must not be call used registers. */
|
|
#ifndef HARD_REGNO_CALL_PART_CLOBBERED
|
|
#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) 0
|
|
#endif
|
|
|
|
/* 1 if the corresponding class does contain register of given
|
|
mode. */
|
|
extern char contains_reg_of_mode [N_REG_CLASSES] [MAX_MACHINE_MODE];
|
|
|
|
typedef unsigned short move_table[N_REG_CLASSES];
|
|
|
|
/* Maximum cost of moving from a register in one class to a register
|
|
in another class. */
|
|
extern move_table *move_cost[MAX_MACHINE_MODE];
|
|
|
|
/* Specify number of hard registers given machine mode occupy. */
|
|
extern unsigned char hard_regno_nregs[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
|
|
|
|
/* Similar, but here we don't have to move if the first index is a
|
|
subset of the second so in that case the cost is zero. */
|
|
extern move_table *may_move_in_cost[MAX_MACHINE_MODE];
|
|
|
|
/* Similar, but here we don't have to move if the first index is a
|
|
superset of the second so in that case the cost is zero. */
|
|
extern move_table *may_move_out_cost[MAX_MACHINE_MODE];
|
|
|
|
/* Return an exclusive upper bound on the registers occupied by hard
|
|
register (reg:MODE REGNO). */
|
|
|
|
static inline unsigned int
|
|
end_hard_regno (enum machine_mode mode, unsigned int regno)
|
|
{
|
|
return regno + hard_regno_nregs[regno][(int) mode];
|
|
}
|
|
|
|
/* Likewise for hard register X. */
|
|
|
|
#define END_HARD_REGNO(X) end_hard_regno (GET_MODE (X), REGNO (X))
|
|
|
|
/* Likewise for hard or pseudo register X. */
|
|
|
|
#define END_REGNO(X) (HARD_REGISTER_P (X) ? END_HARD_REGNO (X) : REGNO (X) + 1)
|
|
|
|
/* Add to REGS all the registers required to store a value of mode MODE
|
|
in register REGNO. */
|
|
|
|
static inline void
|
|
add_to_hard_reg_set (HARD_REG_SET *regs, enum machine_mode mode,
|
|
unsigned int regno)
|
|
{
|
|
unsigned int end_regno;
|
|
|
|
end_regno = end_hard_regno (mode, regno);
|
|
do
|
|
SET_HARD_REG_BIT (*regs, regno);
|
|
while (++regno < end_regno);
|
|
}
|
|
|
|
/* Likewise, but remove the registers. */
|
|
|
|
static inline void
|
|
remove_from_hard_reg_set (HARD_REG_SET *regs, enum machine_mode mode,
|
|
unsigned int regno)
|
|
{
|
|
unsigned int end_regno;
|
|
|
|
end_regno = end_hard_regno (mode, regno);
|
|
do
|
|
CLEAR_HARD_REG_BIT (*regs, regno);
|
|
while (++regno < end_regno);
|
|
}
|
|
|
|
/* Return true if REGS contains the whole of (reg:MODE REGNO). */
|
|
|
|
static inline bool
|
|
in_hard_reg_set_p (const HARD_REG_SET regs, enum machine_mode mode,
|
|
unsigned int regno)
|
|
{
|
|
unsigned int end_regno;
|
|
|
|
if (!TEST_HARD_REG_BIT (regs, regno))
|
|
return false;
|
|
|
|
end_regno = end_hard_regno (mode, regno);
|
|
while (++regno < end_regno)
|
|
if (!TEST_HARD_REG_BIT (regs, regno))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Return true if (reg:MODE REGNO) includes an element of REGS. */
|
|
|
|
static inline bool
|
|
overlaps_hard_reg_set_p (const HARD_REG_SET regs, enum machine_mode mode,
|
|
unsigned int regno)
|
|
{
|
|
unsigned int end_regno;
|
|
|
|
if (TEST_HARD_REG_BIT (regs, regno))
|
|
return true;
|
|
|
|
end_regno = end_hard_regno (mode, regno);
|
|
while (++regno < end_regno)
|
|
if (TEST_HARD_REG_BIT (regs, regno))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
#endif /* GCC_REGS_H */
|