⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reload1.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Reload pseudo regs into hard regs for insns that require hard regs.   Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include <stdio.h>#include "config.h"#include "rtl.h"#include "obstack.h"#include "insn-config.h"#include "insn-flags.h"#include "insn-codes.h"#include "flags.h"#include "expr.h"#include "regs.h"#include "hard-reg-set.h"#include "reload.h"#include "recog.h"#include "basic-block.h"#include "output.h"#include "real.h"/* This file contains the reload pass of the compiler, which is   run after register allocation has been done.  It checks that   each insn is valid (operands required to be in registers really   are in registers of the proper class) and fixes up invalid ones   by copying values temporarily into registers for the insns   that need them.   The results of register allocation are described by the vector   reg_renumber; the insns still contain pseudo regs, but reg_renumber   can be used to find which hard reg, if any, a pseudo reg is in.   The technique we always use is to free up a few hard regs that are   called ``reload regs'', and for each place where a pseudo reg   must be in a hard reg, copy it temporarily into one of the reload regs.   All the pseudos that were formerly allocated to the hard regs that   are now in use as reload regs must be ``spilled''.  This means   that they go to other hard regs, or to stack slots if no other   available hard regs can be found.  Spilling can invalidate more   insns, requiring additional need for reloads, so we must keep checking   until the process stabilizes.   For machines with different classes of registers, we must keep track   of the register class needed for each reload, and make sure that   we allocate enough reload registers of each class.   The file reload.c contains the code that checks one insn for   validity and reports the reloads that it needs.  This file   is in charge of scanning the entire rtl code, accumulating the   reload needs, spilling, assigning reload registers to use for   fixing up each insn, and generating the new insns to copy values   into the reload registers.  */#ifndef REGISTER_MOVE_COST#define REGISTER_MOVE_COST(x, y) 2#endif#ifndef MEMORY_MOVE_COST#define MEMORY_MOVE_COST(x) 4#endif/* During reload_as_needed, element N contains a REG rtx for the hard reg   into which reg N has been reloaded (perhaps for a previous insn). */static rtx *reg_last_reload_reg;/* Elt N nonzero if reg_last_reload_reg[N] has been set in this insn   for an output reload that stores into reg N.  */static char *reg_has_output_reload;/* Indicates which hard regs are reload-registers for an output reload   in the current insn.  */static HARD_REG_SET reg_is_output_reload;/* Element N is the constant value to which pseudo reg N is equivalent,   or zero if pseudo reg N is not equivalent to a constant.   find_reloads looks at this in order to replace pseudo reg N   with the constant it stands for.  */rtx *reg_equiv_constant;/* Element N is a memory location to which pseudo reg N is equivalent,   prior to any register elimination (such as frame pointer to stack   pointer).  Depending on whether or not it is a valid address, this value   is transferred to either reg_equiv_address or reg_equiv_mem.  */rtx *reg_equiv_memory_loc;/* Element N is the address of stack slot to which pseudo reg N is equivalent.   This is used when the address is not valid as a memory address   (because its displacement is too big for the machine.)  */rtx *reg_equiv_address;/* Element N is the memory slot to which pseudo reg N is equivalent,   or zero if pseudo reg N is not equivalent to a memory slot.  */rtx *reg_equiv_mem;/* Widest width in which each pseudo reg is referred to (via subreg).  */static int *reg_max_ref_width;/* Element N is the insn that initialized reg N from its equivalent   constant or memory slot.  */static rtx *reg_equiv_init;/* During reload_as_needed, element N contains the last pseudo regno   reloaded into the Nth reload register.  This vector is in parallel   with spill_regs.  If that pseudo reg occupied more than one register,   reg_reloaded_contents points to that pseudo for each spill register in   use; all of these must remain set for an inheritance to occur.  */static int reg_reloaded_contents[FIRST_PSEUDO_REGISTER];/* During reload_as_needed, element N contains the insn for which   the Nth reload register was last used.  This vector is in parallel   with spill_regs, and its contents are significant only when   reg_reloaded_contents is significant.  */static rtx reg_reloaded_insn[FIRST_PSEUDO_REGISTER];/* Number of spill-regs so far; number of valid elements of spill_regs.  */static int n_spills;/* In parallel with spill_regs, contains REG rtx's for those regs.   Holds the last rtx used for any given reg, or 0 if it has never   been used for spilling yet.  This rtx is reused, provided it has   the proper mode.  */static rtx spill_reg_rtx[FIRST_PSEUDO_REGISTER];/* In parallel with spill_regs, contains nonzero for a spill reg   that was stored after the last time it was used.   The precise value is the insn generated to do the store.  */static rtx spill_reg_store[FIRST_PSEUDO_REGISTER];/* This table is the inverse mapping of spill_regs:   indexed by hard reg number,   it contains the position of that reg in spill_regs,   or -1 for something that is not in spill_regs.  */static short spill_reg_order[FIRST_PSEUDO_REGISTER];/* This reg set indicates registers that may not be used for retrying global   allocation.  The registers that may not be used include all spill registers   and the frame pointer (if we are using one).  */HARD_REG_SET forbidden_regs;/* This reg set indicates registers that are not good for spill registers.   They will not be used to complete groups of spill registers.  This includes   all fixed registers, registers that may be eliminated, and, if   SMALL_REGISTER_CLASSES is not defined, registers explicitly used in the rtl.   (spill_reg_order prevents these registers from being used to start a   group.)  */static HARD_REG_SET bad_spill_regs;/* Describes order of use of registers for reloading   of spilled pseudo-registers.  `spills' is the number of   elements that are actually valid; new ones are added at the end.  */static short spill_regs[FIRST_PSEUDO_REGISTER];/* Index of last register assigned as a spill register.  We allocate in   a round-robin fashion.  */static int last_spill_reg;/* Describes order of preference for putting regs into spill_regs.   Contains the numbers of all the hard regs, in order most preferred first.   This order is different for each function.   It is set up by order_regs_for_reload.   Empty elements at the end contain -1.  */static short potential_reload_regs[FIRST_PSEUDO_REGISTER];/* 1 for a hard register that appears explicitly in the rtl   (for example, function value registers, special registers   used by insns, structure value pointer registers).  */static char regs_explicitly_used[FIRST_PSEUDO_REGISTER];/* Indicates if a register was counted against the need for   groups.  0 means it can count against max_nongroup instead.  */static HARD_REG_SET counted_for_groups;/* Indicates if a register was counted against the need for   non-groups.  0 means it can become part of a new group.   During choose_reload_regs, 1 here means don't use this reg   as part of a group, even if it seems to be otherwise ok.  */static HARD_REG_SET counted_for_nongroups;/* Indexed by pseudo reg number N,   says may not delete stores into the real (memory) home of pseudo N.   This is set if we already substituted a memory equivalent in some uses,   which happens when we have to eliminate the fp from it.  */static char *cannot_omit_stores;/* Nonzero if indirect addressing is supported on the machine; this means   that spilling (REG n) does not require reloading it into a register in   order to do (MEM (REG n)) or (MEM (PLUS (REG n) (CONST_INT c))).  The   value indicates the level of indirect addressing supported, e.g., two   means that (MEM (MEM (REG n))) is also valid if (REG n) does not get   a hard register.  */static char spill_indirect_levels;/* Nonzero if indirect addressing is supported when the innermost MEM is   of the form (MEM (SYMBOL_REF sym)).  It is assumed that the level to   which these are valid is the same as spill_indirect_levels, above.   */char indirect_symref_ok;/* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid.  */char double_reg_address_ok;/* Record the stack slot for each spilled hard register.  */static rtx spill_stack_slot[FIRST_PSEUDO_REGISTER];/* Width allocated so far for that stack slot.  */static int spill_stack_slot_width[FIRST_PSEUDO_REGISTER];/* Indexed by register class and basic block number, nonzero if there is   any need for a spill register of that class in that basic block.   The pointer is 0 if we did stupid allocation and don't know   the structure of basic blocks.  */char *basic_block_needs[N_REG_CLASSES];/* First uid used by insns created by reload in this function.   Used in find_equiv_reg.  */int reload_first_uid;/* Flag set by local-alloc or global-alloc if anything is live in   a call-clobbered reg across calls.  */int caller_save_needed;/* Set to 1 while reload_as_needed is operating.   Required by some machines to handle any generated moves differently.  */int reload_in_progress = 0;/* These arrays record the insn_code of insns that may be needed to   perform input and output reloads of special objects.  They provide a   place to pass a scratch register.  */enum insn_code reload_in_optab[NUM_MACHINE_MODES];enum insn_code reload_out_optab[NUM_MACHINE_MODES];/* This obstack is used for allocation of rtl during register elimination.   The allocated storage can be freed once find_reloads has processed the   insn.  */struct obstack reload_obstack;char *reload_firstobj;#define obstack_chunk_alloc xmalloc#define obstack_chunk_free free/* List of labels that must never be deleted.  */extern rtx forced_labels;/* This structure is used to record information about register eliminations.   Each array entry describes one possible way of eliminating a register   in favor of another.   If there is more than one way of eliminating a   particular register, the most preferred should be specified first.  */static struct elim_table{  int from;			/* Register number to be eliminated. */  int to;			/* Register number used as replacement. */  int initial_offset;		/* Initial difference between values. */  int can_eliminate;		/* Non-zero if this elimination can be done. */  int can_eliminate_previous;	/* Value of CAN_ELIMINATE in previous scan over				   insns made by reload. */  int offset;			/* Current offset between the two regs. */  int max_offset;		/* Maximum offset between the two regs. */  int previous_offset;		/* Offset at end of previous insn. */  int ref_outside_mem;		/* "to" has been referenced outside a MEM. */  rtx from_rtx;			/* REG rtx for the register to be eliminated.				   We cannot simply compare the number since				   we might then spuriously replace a hard				   register corresponding to a pseudo				   assigned to the reg to be eliminated. */  rtx to_rtx;			/* REG rtx for the replacement. */} reg_eliminate[] =/* If a set of eliminable registers was specified, define the table from it.   Otherwise, default to the normal case of the frame pointer being   replaced by the stack pointer.  */#ifdef ELIMINABLE_REGS  ELIMINABLE_REGS;#else  {{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}};#endif#define NUM_ELIMINABLE_REGS (sizeof reg_eliminate / sizeof reg_eliminate[0])/* Record the number of pending eliminations that have an offset not equal   to their initial offset.  If non-zero, we use a new copy of each   replacement result in any insns encountered.  */static int num_not_at_initial_offset;/* Count the number of registers that we may be able to eliminate.  */static int num_eliminable;/* For each label, we record the offset of each elimination.  If we reach   a label by more than one path and an offset differs, we cannot do the   elimination.  This information is indexed by the number of the label.   The first table is an array of flags that records whether we have yet   encountered a label and the second table is an array of arrays, one   entry in the latter array for each elimination.  */static char *offsets_known_at;static int (*offsets_at)[NUM_ELIMINABLE_REGS];/* Number of labels in the current function.  */static int num_labels;struct hard_reg_n_uses { int regno; int uses; };static int possible_group_p		PROTO((int, int *));static void count_possible_groups	PROTO((int *, enum machine_mode *,					       int *, int));static int modes_equiv_for_class_p	PROTO((enum machine_mode,					       enum machine_mode,					       enum reg_class));static void spill_failure		PROTO((rtx));static int new_spill_reg		PROTO((int, int, int *, int *, int,					       FILE *));static void delete_dead_insn		PROTO((rtx));static void alter_reg  			PROTO((int, int));static void mark_scratch_live		PROTO((rtx));static void set_label_offsets		PROTO((rtx, rtx, int));static int eliminate_regs_in_insn	PROTO((rtx, int));static void mark_not_eliminable		PROTO((rtx, rtx));static int spill_hard_reg		PROTO((int, int, FILE *, int));static void scan_paradoxical_subregs	PROTO((rtx));static int hard_reg_use_compare		PROTO((struct hard_reg_n_uses *,					       struct hard_reg_n_uses *));static void order_regs_for_reload	PROTO((void));static int compare_spill_regs		PROTO((short *, short *));static void reload_as_needed		PROTO((rtx, int));static void forget_old_reloads_1	PROTO((rtx, rtx));static int reload_reg_class_lower	PROTO((short *, short *));static void mark_reload_reg_in_use	PROTO((int, int, enum reload_type,					       enum machine_mode));static void clear_reload_reg_in_use	PROTO((int, int, enum reload_type,					       enum machine_mode));static int reload_reg_free_p		PROTO((int, int, enum reload_type));static int reload_reg_free_before_p	PROTO((int, int, enum reload_type));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -