📄 regclass.c
字号:
/* Compute register class preferences for pseudo-registers. Copyright (C) 1987, 1988, 1991, 1992 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, 675 Mass Ave, Cambridge, MA 02139, 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"#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 psuedos 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 ints. We copy from these ints to the table above. This is done so that 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 int 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;/* 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] & (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 (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 = ®_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 = ®_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 = ®_class_subclasses[j][0]; *p2 != LIM_REG_CLASSES; p2++) if (*p2 != i) cost = MAX (cost, REGISTER_MOVE_COST (i, *p2)); for (p1 = ®_class_subclasses[i][0]; *p1 != LIM_REG_CLASSES; p1++) { if (*p1 != j) cost = MAX (cost, REGISTER_MOVE_COST (*p1, j)); for (p2 = ®_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. */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 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (global_regs[i]) { if (call_used_regs[i] && ! fixed_regs[i]) warning ("call-clobbered register used for global register variable"); fixed_regs[i] = 1; /* Prevent saving/restoring of this reg. */ call_used_regs[i] = 1; } /* 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);#ifdef STRUCT_VALUE_REGNUM call_fixed_regs[STRUCT_VALUE_REGNUM] = 1;#endif#ifdef STATIC_CHAIN_REGNUM call_fixed_regs[STATIC_CHAIN_REGNUM] = 1;#endif n_non_fixed_regs = 0; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { if (FUNCTION_VALUE_REGNO_P (i)) call_fixed_regs[i] = 1; 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); }}/* Specify the usage characteristics of the register named NAME. It should be a fixed register if FIXED and a call-used register if CALL_USED. */voidfix_register (name, fixed, call_used) char *name; int fixed, call_used;{ int i; /* Decode the name and update the primary form of the register info. */ if ((i = decode_reg_name (name)) >= 0) { fixed_regs[i] = fixed; call_used_regs[i] = call_used;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -