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

📄 regclass.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Compute register class preferences for pseudo-registers.   Copyright (C) 1987, 88, 91, 92, 93, 1994 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.  *//* This file contains two passes of the compiler: reg_scan and reg_class.   It also defines some tables of information about the hardware registers   and a function init_reg_sets to initialize the tables.  */#include "config.h"#include "rtl.h"#include "hard-reg-set.h"#include "flags.h"#include "basic-block.h"#include "regs.h"#include "insn-config.h"#include "recog.h"#include "reload.h"#include "real.h"#include "bytecode.h"#ifndef REGISTER_MOVE_COST#define REGISTER_MOVE_COST(x, y) 2#endif#ifndef MEMORY_MOVE_COST#define MEMORY_MOVE_COST(x) 4#endif/* If we have auto-increment or auto-decrement and we can have secondary   reloads, we are not allowed to use classes requiring secondary   reloads for pseudos auto-incremented since reload can't handle it.  */#ifdef AUTO_INC_DEC#if defined(SECONDARY_INPUT_RELOAD_CLASS) || defined(SECONDARY_OUTPUT_RELOAD_CLASS)#define FORBIDDEN_INC_DEC_CLASSES#endif#endif/* Register tables used by many passes.  *//* Indexed by hard register number, contains 1 for registers   that are fixed use (stack pointer, pc, frame pointer, etc.).   These are the registers that cannot be used to allocate   a pseudo reg whose life does not cross calls.  */char fixed_regs[FIRST_PSEUDO_REGISTER];/* Same info as a HARD_REG_SET.  */HARD_REG_SET fixed_reg_set;/* Data for initializing the above.  */static char initial_fixed_regs[] = FIXED_REGISTERS;/* Indexed by hard register number, contains 1 for registers   that are fixed use or are clobbered by function calls.   These are the registers that cannot be used to allocate   a pseudo reg whose life crosses calls.  */char call_used_regs[FIRST_PSEUDO_REGISTER];/* Same info as a HARD_REG_SET.  */HARD_REG_SET call_used_reg_set;/* Data for initializing the above.  */static char initial_call_used_regs[] = CALL_USED_REGISTERS;  /* Indexed by hard register number, contains 1 for registers that are   fixed use -- i.e. in fixed_regs -- or a function value return register   or STRUCT_VALUE_REGNUM or STATIC_CHAIN_REGNUM.  These are the   registers that cannot hold quantities across calls even if we are   willing to save and restore them.  */char call_fixed_regs[FIRST_PSEUDO_REGISTER];/* The same info as a HARD_REG_SET.  */HARD_REG_SET call_fixed_reg_set;/* Number of non-fixed registers.  */int n_non_fixed_regs;/* Indexed by hard register number, contains 1 for registers   that are being used for global register decls.   These must be exempt from ordinary flow analysis   and are also considered fixed.  */char global_regs[FIRST_PSEUDO_REGISTER];  /* Table of register numbers in the order in which to try to use them.  */#ifdef REG_ALLOC_ORDERint reg_alloc_order[FIRST_PSEUDO_REGISTER] = REG_ALLOC_ORDER;#endif/* For each reg class, a HARD_REG_SET saying which registers are in it.  */HARD_REG_SET reg_class_contents[N_REG_CLASSES];/* The same information, but as an array of unsigned ints.  We copy from   these unsigned ints to the table above.  We do this so the tm.h files   do not have to be aware of the wordsize for machines with <= 64 regs.  */#define N_REG_INTS  \  ((FIRST_PSEUDO_REGISTER + (HOST_BITS_PER_INT - 1)) / HOST_BITS_PER_INT)static unsigned int_reg_class_contents[N_REG_CLASSES][N_REG_INTS]   = REG_CLASS_CONTENTS;/* For each reg class, number of regs it contains.  */int reg_class_size[N_REG_CLASSES];/* For each reg class, table listing all the containing classes.  */enum reg_class reg_class_superclasses[N_REG_CLASSES][N_REG_CLASSES];/* For each reg class, table listing all the classes contained in it.  */enum reg_class reg_class_subclasses[N_REG_CLASSES][N_REG_CLASSES];/* For each pair of reg classes,   a largest reg class contained in their union.  */enum reg_class reg_class_subunion[N_REG_CLASSES][N_REG_CLASSES];/* For each pair of reg classes,   the smallest reg class containing their union.  */enum reg_class reg_class_superunion[N_REG_CLASSES][N_REG_CLASSES];/* Array containing all of the register names */char *reg_names[] = REGISTER_NAMES;/* 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.  */enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];/* Indexed by n, gives number of times (REG n) is set or clobbered.   This information remains valid for the rest of the compilation   of the current function; it is used to control register allocation.   This information applies to both hard registers and pseudo registers,   unlike much of the information above.  */short *reg_n_sets;/* Maximum cost of moving from a register in one class to a register in   another class.  Based on REGISTER_MOVE_COST.  */static int move_cost[N_REG_CLASSES][N_REG_CLASSES];/* 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.  */static int may_move_cost[N_REG_CLASSES][N_REG_CLASSES];#ifdef FORBIDDEN_INC_DEC_CLASSES/* These are the classes that regs which are auto-incremented or decremented   cannot be put in.  */static int forbidden_inc_dec_class[N_REG_CLASSES];/* Indexed by n, is non-zero if (REG n) is used in an auto-inc or auto-dec   context.  */static char *in_inc_dec;#endif /* FORBIDDEN_INC_DEC_CLASSES *//* Function called only once to initialize the above data on reg usage.   Once this is done, various switches may override.  */voidinit_reg_sets (){  register int i, j;  /* First copy the register information from the initial int form into     the regsets.  */  for (i = 0; i < N_REG_CLASSES; i++)    {      CLEAR_HARD_REG_SET (reg_class_contents[i]);      for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)	if (int_reg_class_contents[i][j / HOST_BITS_PER_INT]	    & ((unsigned) 1 << (j % HOST_BITS_PER_INT)))	  SET_HARD_REG_BIT (reg_class_contents[i], j);    }  bcopy (initial_fixed_regs, fixed_regs, sizeof fixed_regs);  bcopy (initial_call_used_regs, call_used_regs, sizeof call_used_regs);  bzero (global_regs, sizeof global_regs);  /* Compute number of hard regs in each class.  */  bzero ((char *) reg_class_size, sizeof reg_class_size);  for (i = 0; i < N_REG_CLASSES; i++)    for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)      if (TEST_HARD_REG_BIT (reg_class_contents[i], j))	reg_class_size[i]++;  /* Initialize the table of subunions.     reg_class_subunion[I][J] gets the largest-numbered reg-class     that is contained in the union of classes I and J.  */  for (i = 0; i < N_REG_CLASSES; i++)    {      for (j = 0; j < N_REG_CLASSES; j++)	{#ifdef HARD_REG_SET	  register		/* Declare it register if it's a scalar.  */#endif	    HARD_REG_SET c;	  register int k;	  COPY_HARD_REG_SET (c, reg_class_contents[i]);	  IOR_HARD_REG_SET (c, reg_class_contents[j]);	  for (k = 0; k < N_REG_CLASSES; k++)	    {	      GO_IF_HARD_REG_SUBSET (reg_class_contents[k], c,				     subclass1);	      continue;	    subclass1:	      /* keep the largest subclass */		/* SPEE 900308 */	      GO_IF_HARD_REG_SUBSET (reg_class_contents[k],				     reg_class_contents[(int) reg_class_subunion[i][j]],				     subclass2);	      reg_class_subunion[i][j] = (enum reg_class) k;	    subclass2:	      ;	    }	}    }  /* Initialize the table of superunions.     reg_class_superunion[I][J] gets the smallest-numbered reg-class     containing the union of classes I and J.  */  for (i = 0; i < N_REG_CLASSES; i++)    {      for (j = 0; j < N_REG_CLASSES; j++)	{#ifdef HARD_REG_SET	  register		/* Declare it register if it's a scalar.  */#endif	    HARD_REG_SET c;	  register int k;	  COPY_HARD_REG_SET (c, reg_class_contents[i]);	  IOR_HARD_REG_SET (c, reg_class_contents[j]);	  for (k = 0; k < N_REG_CLASSES; k++)	    GO_IF_HARD_REG_SUBSET (c, reg_class_contents[k], superclass);	superclass:	  reg_class_superunion[i][j] = (enum reg_class) k;	}    }  /* Initialize the tables of subclasses and superclasses of each reg class.     First clear the whole table, then add the elements as they are found.  */  for (i = 0; i < N_REG_CLASSES; i++)    {      for (j = 0; j < N_REG_CLASSES; j++)	{	  reg_class_superclasses[i][j] = LIM_REG_CLASSES;	  reg_class_subclasses[i][j] = LIM_REG_CLASSES;	}    }  for (i = 0; i < N_REG_CLASSES; i++)    {      if (i == (int) NO_REGS)	continue;      for (j = i + 1; j < N_REG_CLASSES; j++)	{	  enum reg_class *p;	  GO_IF_HARD_REG_SUBSET (reg_class_contents[i], reg_class_contents[j],				 subclass);	  continue;	subclass:	  /* Reg class I is a subclass of J.	     Add J to the table of superclasses of I.  */	  p = &reg_class_superclasses[i][0];	  while (*p != LIM_REG_CLASSES) p++;	  *p = (enum reg_class) j;	  /* Add I to the table of superclasses of J.  */	  p = &reg_class_subclasses[j][0];	  while (*p != LIM_REG_CLASSES) p++;	  *p = (enum reg_class) i;	}    }  /* Initialize the move cost table.  Find every subset of each class     and take the maximum cost of moving any subset to any other.  */  for (i = 0; i < N_REG_CLASSES; i++)    for (j = 0; j < N_REG_CLASSES; j++)      {	int cost = i == j ? 2 : REGISTER_MOVE_COST (i, j);	enum reg_class *p1, *p2;	for (p2 = &reg_class_subclasses[j][0]; *p2 != LIM_REG_CLASSES; p2++)	  if (*p2 != i)	    cost = MAX (cost, REGISTER_MOVE_COST (i, *p2));	for (p1 = &reg_class_subclasses[i][0]; *p1 != LIM_REG_CLASSES; p1++)	  {	    if (*p1 != j)	      cost = MAX (cost, REGISTER_MOVE_COST (*p1, j));	    for (p2 = &reg_class_subclasses[j][0];		 *p2 != LIM_REG_CLASSES; p2++)	      if (*p1 != *p2)		cost = MAX (cost, REGISTER_MOVE_COST (*p1, *p2));	  }	move_cost[i][j] = cost;	if (reg_class_subset_p (i, j))	  cost = 0;	may_move_cost[i][j] = cost;      }}/* After switches have been processed, which perhaps alter   `fixed_regs' and `call_used_regs', convert them to HARD_REG_SETs.  */static voidinit_reg_sets_1 (){  register int i;  /* This macro allows the fixed or call-used registers     to depend on target flags.  */#ifdef CONDITIONAL_REGISTER_USAGE  CONDITIONAL_REGISTER_USAGE;#endif  /* Initialize "constant" tables.  */  CLEAR_HARD_REG_SET (fixed_reg_set);  CLEAR_HARD_REG_SET (call_used_reg_set);  CLEAR_HARD_REG_SET (call_fixed_reg_set);  bcopy (fixed_regs, call_fixed_regs, sizeof call_fixed_regs);  n_non_fixed_regs = 0;  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)    {      if (fixed_regs[i])	SET_HARD_REG_BIT (fixed_reg_set, i);      else	n_non_fixed_regs++;      if (call_used_regs[i])	SET_HARD_REG_BIT (call_used_reg_set, i);      if (call_fixed_regs[i])	SET_HARD_REG_BIT (call_fixed_reg_set, i);    }}/* Compute the table of register modes.   These values are used to record death information for individual registers   (as opposed to a multi-register mode).  */static voidinit_reg_modes (){  register int i;  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)    {      reg_raw_mode[i] = choose_hard_reg_mode (i, 1);      /* If we couldn't find a valid mode, fall back to `word_mode'.	 ??? We assume `word_mode' has already been initialized.         ??? One situation in which we need to do this is on the mips where	 HARD_REGNO_NREGS (fpreg, [SD]Fmode) returns 2.  Ideally we'd like	 to use DF mode for the even registers and VOIDmode for the odd	 (for the cpu models where the odd ones are inaccessible).  */      if (reg_raw_mode[i] == VOIDmode)	reg_raw_mode[i] = word_mode;    }}/* Finish initializing the register sets and   initialize the register modes.  */voidinit_regs (){  /* This finishes what was started by init_reg_sets, but couldn't be done     until after register usage was specified.  */  if (!output_bytecode)    init_reg_sets_1 ();  init_reg_modes ();}/* Return a machine mode that is legitimate for hard reg REGNO and large   enough to save nregs.  If we can't find one, return VOIDmode.  */enum machine_modechoose_hard_reg_mode (regno, nregs)     int regno;     int nregs;{  enum machine_mode found_mode = VOIDmode, mode;  /* We first look for the largest integer mode that can be validly     held in REGNO.  If none, we look for the largest floating-point mode.     If we still didn't find a valid mode, try CCmode.  */  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);       mode != VOIDmode;       mode = GET_MODE_WIDER_MODE (mode))    if (HARD_REGNO_NREGS (regno, mode) == nregs	&& HARD_REGNO_MODE_OK (regno, mode))      found_mode = mode;  if (found_mode != VOIDmode)    return found_mode;  for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);       mode != VOIDmode;       mode = GET_MODE_WIDER_MODE (mode))    if (HARD_REGNO_NREGS (regno, mode) == nregs	&& HARD_REGNO_MODE_OK (regno, mode))      found_mode = mode;  if (found_mode != VOIDmode)    return found_mode;  if (HARD_REGNO_NREGS (regno, CCmode) == nregs      && HARD_REGNO_MODE_OK (regno, CCmode))    return CCmode;  /* We can't find a mode valid for this register.  */  return VOIDmode;}/* Specify the usage characteristics of the register named NAME.

⌨️ 快捷键说明

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