diff options
Diffstat (limited to 'contrib/gcc/regclass.c')
-rw-r--r-- | contrib/gcc/regclass.c | 1900 |
1 files changed, 1900 insertions, 0 deletions
diff --git a/contrib/gcc/regclass.c b/contrib/gcc/regclass.c new file mode 100644 index 000000000000..9b9a4d50ec77 --- /dev/null +++ b/contrib/gcc/regclass.c @@ -0,0 +1,1900 @@ +/* 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 modify +it under the terms of the GNU General Public License as published by +the 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 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 GNU CC; see the file COPYING. If not, write to +the 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_ORDER +int 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. */ + +void +init_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 = ®_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. */ + +static void +init_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 void +init_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. */ + +void +init_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_mode +choose_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. + It should be a fixed register if FIXED and a + call-used register if CALL_USED. */ + +void +fix_register (name, fixed, call_used) + char *name; + int fixed, call_used; +{ + int i; + + if (output_bytecode) + { + warning ("request to mark `%s' as %s ignored by bytecode compiler", + name, call_used ? "call-used" : "fixed"); + return; + } + + /* 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; + } + else + { + warning ("unknown register name: %s", name); + } +} + +/* Mark register number I as global. */ + +void +globalize_reg (i) + int i; +{ + if (global_regs[i]) + { + warning ("register used for two global register variables"); + return; + } + + if (call_used_regs[i] && ! fixed_regs[i]) + warning ("call-clobbered register used for global register variable"); + + global_regs[i] = 1; + + /* If already fixed, nothing else to do. */ + if (fixed_regs[i]) + return; + + fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1; + n_non_fixed_regs--; + + SET_HARD_REG_BIT (fixed_reg_set, i); + SET_HARD_REG_BIT (call_used_reg_set, i); + SET_HARD_REG_BIT (call_fixed_reg_set, i); +} + +/* Now the data and code for the `regclass' pass, which happens + just before local-alloc. */ + +/* The `costs' struct records the cost of using a hard register of each class + and of using memory for each pseudo. We use this data to set up + register class preferences. */ + +struct costs +{ + int cost[N_REG_CLASSES]; + int mem_cost; +}; + +/* Record the cost of each class for each pseudo. */ + +static struct costs *costs; + +/* Record the same data by operand number, accumulated for each alternative + in an insn. The contribution to a pseudo is that of the minimum-cost + alternative. */ + +static struct costs op_costs[MAX_RECOG_OPERANDS]; + +/* (enum reg_class) prefclass[R] is the preferred class for pseudo number R. + This is available after `regclass' is run. */ + +static char *prefclass; + +/* altclass[R] is a register class that we should use for allocating + pseudo number R if no register in the preferred class is available. + If no register in this class is available, memory is preferred. + + It might appear to be more general to have a bitmask of classes here, + but since it is recommended that there be a class corresponding to the + union of most major pair of classes, that generality is not required. + + This is available after `regclass' is run. */ + +static char *altclass; + +/* Record the depth of loops that we are in. */ + +static int loop_depth; + +/* Account for the fact that insns within a loop are executed very commonly, + but don't keep doing this as loops go too deep. */ + +static int loop_cost; + +static void record_reg_classes PROTO((int, int, rtx *, enum machine_mode *, + char **, rtx)); +static int copy_cost PROTO((rtx, enum machine_mode, + enum reg_class, int)); +static void record_address_regs PROTO((rtx, enum reg_class, int)); +static auto_inc_dec_reg_p PROTO((rtx, enum machine_mode)); +static void reg_scan_mark_refs PROTO((rtx, rtx, int)); + +/* Return the reg_class in which pseudo reg number REGNO is best allocated. + This function is sometimes called before the info has been computed. + When that happens, just return GENERAL_REGS, which is innocuous. */ + +enum reg_class +reg_preferred_class (regno) + int regno; +{ + if (prefclass == 0) + return GENERAL_REGS; + return (enum reg_class) prefclass[regno]; +} + +enum reg_class +reg_alternate_class (regno) +{ + if (prefclass == 0) + return ALL_REGS; + + return (enum reg_class) altclass[regno]; +} + +/* This prevents dump_flow_info from losing if called + before regclass is run. */ + +void +regclass_init () +{ + prefclass = 0; +} + +/* This is a pass of the compiler that scans all instructions + and calculates the preferred class for each pseudo-register. + This information can be accessed later by calling `reg_preferred_class'. + This pass comes just before local register allocation. */ + +void +regclass (f, nregs) + rtx f; + int nregs; +{ +#ifdef REGISTER_CONSTRAINTS + register rtx insn; + register int i, j; + struct costs init_cost; + rtx set; + int pass; + + init_recog (); + + costs = (struct costs *) alloca (nregs * sizeof (struct costs)); + +#ifdef FORBIDDEN_INC_DEC_CLASSES + + in_inc_dec = (char *) alloca (nregs); + + /* Initialize information about which register classes can be used for + pseudos that are auto-incremented or auto-decremented. It would + seem better to put this in init_reg_sets, but we need to be able + to allocate rtx, which we can't do that early. */ + + for (i = 0; i < N_REG_CLASSES; i++) + { + rtx r = gen_rtx (REG, VOIDmode, 0); + enum machine_mode m; + + for (j = 0; j < FIRST_PSEUDO_REGISTER; j++) + if (TEST_HARD_REG_BIT (reg_class_contents[i], j)) + { + REGNO (r) = j; + + for (m = VOIDmode; (int) m < (int) MAX_MACHINE_MODE; + m = (enum machine_mode) ((int) m + 1)) + if (HARD_REGNO_MODE_OK (j, m)) + { + PUT_MODE (r, m); + + /* If a register is not directly suitable for an + auto-increment or decrement addressing mode and + requires secondary reloads, disallow its class from + being used in such addresses. */ + + if ((0 +#ifdef SECONDARY_INPUT_RELOAD_CLASS + || (SECONDARY_INPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r) + != NO_REGS) +#endif +#ifdef SECONDARY_OUTPUT_RELOAD_CLASS + || (SECONDARY_OUTPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r) + != NO_REGS) +#endif + ) + && ! auto_inc_dec_reg_p (r, m)) + forbidden_inc_dec_class[i] = 1; + } + } + } +#endif /* FORBIDDEN_INC_DEC_CLASSES */ + + init_cost.mem_cost = 10000; + for (i = 0; i < N_REG_CLASSES; i++) + init_cost.cost[i] = 10000; + + /* Normally we scan the insns once and determine the best class to use for + each register. However, if -fexpensive_optimizations are on, we do so + twice, the second time using the tentative best classes to guide the + selection. */ + + for (pass = 0; pass <= flag_expensive_optimizations; pass++) + { + /* Zero out our accumulation of the cost of each class for each reg. */ + + bzero ((char *) costs, nregs * sizeof (struct costs)); + +#ifdef FORBIDDEN_INC_DEC_CLASSES + bzero (in_inc_dec, nregs); +#endif + + loop_depth = 0, loop_cost = 1; + + /* Scan the instructions and record each time it would + save code to put a certain register in a certain class. */ + + for (insn = f; insn; insn = NEXT_INSN (insn)) + { + char *constraints[MAX_RECOG_OPERANDS]; + enum machine_mode modes[MAX_RECOG_OPERANDS]; + int nalternatives; + int noperands; + + /* Show that an insn inside a loop is likely to be executed three + times more than insns outside a loop. This is much more aggressive + than the assumptions made elsewhere and is being tried as an + experiment. */ + + if (GET_CODE (insn) == NOTE + && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) + loop_depth++, loop_cost = 1 << (2 * MIN (loop_depth, 5)); + else if (GET_CODE (insn) == NOTE + && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) + loop_depth--, loop_cost = 1 << (2 * MIN (loop_depth, 5)); + + else if ((GET_CODE (insn) == INSN + && GET_CODE (PATTERN (insn)) != USE + && GET_CODE (PATTERN (insn)) != CLOBBER + && GET_CODE (PATTERN (insn)) != ASM_INPUT) + || (GET_CODE (insn) == JUMP_INSN + && GET_CODE (PATTERN (insn)) != ADDR_VEC + && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC) + || GET_CODE (insn) == CALL_INSN) + { + if (GET_CODE (insn) == INSN + && (noperands = asm_noperands (PATTERN (insn))) >= 0) + { + decode_asm_operands (PATTERN (insn), recog_operand, NULL_PTR, + constraints, modes); + nalternatives = (noperands == 0 ? 0 + : n_occurrences (',', constraints[0]) + 1); + } + else + { + int insn_code_number = recog_memoized (insn); + rtx note; + + set = single_set (insn); + insn_extract (insn); + + nalternatives = insn_n_alternatives[insn_code_number]; + noperands = insn_n_operands[insn_code_number]; + + /* If this insn loads a parameter from its stack slot, then + it represents a savings, rather than a cost, if the + parameter is stored in memory. Record this fact. */ + + if (set != 0 && GET_CODE (SET_DEST (set)) == REG + && GET_CODE (SET_SRC (set)) == MEM + && (note = find_reg_note (insn, REG_EQUIV, + NULL_RTX)) != 0 + && GET_CODE (XEXP (note, 0)) == MEM) + { + costs[REGNO (SET_DEST (set))].mem_cost + -= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set))) + * loop_cost); + record_address_regs (XEXP (SET_SRC (set), 0), + BASE_REG_CLASS, loop_cost * 2); + continue; + } + + /* Improve handling of two-address insns such as + (set X (ashift CONST Y)) where CONST must be made to + match X. Change it into two insns: (set X CONST) + (set X (ashift X Y)). If we left this for reloading, it + would probably get three insns because X and Y might go + in the same place. This prevents X and Y from receiving + the same hard reg. + + We can only do this if the modes of operands 0 and 1 + (which might not be the same) are tieable and we only need + do this during our first pass. */ + + if (pass == 0 && optimize + && noperands >= 3 + && insn_operand_constraint[insn_code_number][1][0] == '0' + && insn_operand_constraint[insn_code_number][1][1] == 0 + && CONSTANT_P (recog_operand[1]) + && ! rtx_equal_p (recog_operand[0], recog_operand[1]) + && ! rtx_equal_p (recog_operand[0], recog_operand[2]) + && GET_CODE (recog_operand[0]) == REG + && MODES_TIEABLE_P (GET_MODE (recog_operand[0]), + insn_operand_mode[insn_code_number][1])) + { + rtx previnsn = prev_real_insn (insn); + rtx dest + = gen_lowpart (insn_operand_mode[insn_code_number][1], + recog_operand[0]); + rtx newinsn + = emit_insn_before (gen_move_insn (dest, + recog_operand[1]), + insn); + + /* If this insn was the start of a basic block, + include the new insn in that block. + We need not check for code_label here; + while a basic block can start with a code_label, + INSN could not be at the beginning of that block. */ + if (previnsn == 0 || GET_CODE (previnsn) == JUMP_INSN) + { + int b; + for (b = 0; b < n_basic_blocks; b++) + if (insn == basic_block_head[b]) + basic_block_head[b] = newinsn; + } + + /* This makes one more setting of new insns's dest. */ + reg_n_sets[REGNO (recog_operand[0])]++; + + *recog_operand_loc[1] = recog_operand[0]; + for (i = insn_n_dups[insn_code_number] - 1; i >= 0; i--) + if (recog_dup_num[i] == 1) + *recog_dup_loc[i] = recog_operand[0]; + + insn = PREV_INSN (newinsn); + continue; + } + + for (i = 0; i < noperands; i++) + { + constraints[i] + = insn_operand_constraint[insn_code_number][i]; + modes[i] = insn_operand_mode[insn_code_number][i]; + } + } + + /* If we get here, we are set up to record the costs of all the + operands for this insn. Start by initializing the costs. + Then handle any address registers. Finally record the desired + classes for any pseudos, doing it twice if some pair of + operands are commutative. */ + + for (i = 0; i < noperands; i++) + { + op_costs[i] = init_cost; + + if (GET_CODE (recog_operand[i]) == SUBREG) + recog_operand[i] = SUBREG_REG (recog_operand[i]); + + if (GET_CODE (recog_operand[i]) == MEM) + record_address_regs (XEXP (recog_operand[i], 0), + BASE_REG_CLASS, loop_cost * 2); + else if (constraints[i][0] == 'p') + record_address_regs (recog_operand[i], + BASE_REG_CLASS, loop_cost * 2); + } + + /* Check for commutative in a separate loop so everything will + have been initialized. We must do this even if one operand + is a constant--see addsi3 in m68k.md. */ + + for (i = 0; i < noperands - 1; i++) + if (constraints[i][0] == '%') + { + char *xconstraints[MAX_RECOG_OPERANDS]; + int j; + + /* Handle commutative operands by swapping the constraints. + We assume the modes are the same. */ + + for (j = 0; j < noperands; j++) + xconstraints[j] = constraints[j]; + + xconstraints[i] = constraints[i+1]; + xconstraints[i+1] = constraints[i]; + record_reg_classes (nalternatives, noperands, + recog_operand, modes, xconstraints, + insn); + } + + record_reg_classes (nalternatives, noperands, recog_operand, + modes, constraints, insn); + + /* Now add the cost for each operand to the total costs for + its register. */ + + for (i = 0; i < noperands; i++) + if (GET_CODE (recog_operand[i]) == REG + && REGNO (recog_operand[i]) >= FIRST_PSEUDO_REGISTER) + { + int regno = REGNO (recog_operand[i]); + struct costs *p = &costs[regno], *q = &op_costs[i]; + + p->mem_cost += q->mem_cost * loop_cost; + for (j = 0; j < N_REG_CLASSES; j++) + p->cost[j] += q->cost[j] * loop_cost; + } + } + } + + /* Now for each register look at how desirable each class is + and find which class is preferred. Store that in + `prefclass[REGNO]'. Record in `altclass[REGNO]' the largest register + class any of whose registers is better than memory. */ + + if (pass == 0) + { + prefclass = (char *) oballoc (nregs); + altclass = (char *) oballoc (nregs); + } + + for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++) + { + register int best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1; + enum reg_class best = ALL_REGS, alt = NO_REGS; + /* This is an enum reg_class, but we call it an int + to save lots of casts. */ + register int class; + register struct costs *p = &costs[i]; + + for (class = (int) ALL_REGS - 1; class > 0; class--) + { + /* Ignore classes that are too small for this operand or + invalid for a operand that was auto-incremented. */ + if (CLASS_MAX_NREGS (class, PSEUDO_REGNO_MODE (i)) + > reg_class_size[class] +#ifdef FORBIDDEN_INC_DEC_CLASSES + || (in_inc_dec[i] && forbidden_inc_dec_class[class]) +#endif + ) + ; + else if (p->cost[class] < best_cost) + { + best_cost = p->cost[class]; + best = (enum reg_class) class; + } + else if (p->cost[class] == best_cost) + best = reg_class_subunion[(int)best][class]; + } + + /* Record the alternate register class; i.e., a class for which + every register in it is better than using memory. If adding a + class would make a smaller class (i.e., no union of just those + classes exists), skip that class. The major unions of classes + should be provided as a register class. Don't do this if we + will be doing it again later. */ + + if (pass == 1 || ! flag_expensive_optimizations) + for (class = 0; class < N_REG_CLASSES; class++) + if (p->cost[class] < p->mem_cost + && (reg_class_size[(int) reg_class_subunion[(int) alt][class]] + > reg_class_size[(int) alt]) +#ifdef FORBIDDEN_INC_DEC_CLASSES + && ! (in_inc_dec[i] && forbidden_inc_dec_class[class]) +#endif + ) + alt = reg_class_subunion[(int) alt][class]; + + /* If we don't add any classes, nothing to try. */ + if (alt == best) + alt = (int) NO_REGS; + + /* We cast to (int) because (char) hits bugs in some compilers. */ + prefclass[i] = (int) best; + altclass[i] = (int) alt; + } + } +#endif /* REGISTER_CONSTRAINTS */ +} + +#ifdef REGISTER_CONSTRAINTS + +/* Record the cost of using memory or registers of various classes for + the operands in INSN. + + N_ALTS is the number of alternatives. + + N_OPS is the number of operands. + + OPS is an array of the operands. + + MODES are the modes of the operands, in case any are VOIDmode. + + CONSTRAINTS are the constraints to use for the operands. This array + is modified by this procedure. + + This procedure works alternative by alternative. For each alternative + we assume that we will be able to allocate all pseudos to their ideal + register class and calculate the cost of using that alternative. Then + we compute for each operand that is a pseudo-register, the cost of + having the pseudo allocated to each register class and using it in that + alternative. To this cost is added the cost of the alternative. + + The cost of each class for this insn is its lowest cost among all the + alternatives. */ + +static void +record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) + int n_alts; + int n_ops; + rtx *ops; + enum machine_mode *modes; + char **constraints; + rtx insn; +{ + int alt; + enum op_type {OP_READ, OP_WRITE, OP_READ_WRITE} op_types[MAX_RECOG_OPERANDS]; + int i, j; + rtx set; + + /* By default, each operand is an input operand. */ + + for (i = 0; i < n_ops; i++) + op_types[i] = OP_READ; + + /* Process each alternative, each time minimizing an operand's cost with + the cost for each operand in that alternative. */ + + for (alt = 0; alt < n_alts; alt++) + { + struct costs this_op_costs[MAX_RECOG_OPERANDS]; + int alt_fail = 0; + int alt_cost = 0; + enum reg_class classes[MAX_RECOG_OPERANDS]; + int class; + + for (i = 0; i < n_ops; i++) + { + char *p = constraints[i]; + rtx op = ops[i]; + enum machine_mode mode = modes[i]; + int allows_mem = 0; + int win = 0; + char c; + + /* If this operand has no constraints at all, we can conclude + nothing about it since anything is valid. */ + + if (*p == 0) + { + if (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER) + bzero ((char *) &this_op_costs[i], sizeof this_op_costs[i]); + + continue; + } + + if (*p == '%') + p++; + + /* If this alternative is only relevant when this operand + matches a previous operand, we do different things depending + on whether this operand is a pseudo-reg or not. */ + + if (p[0] >= '0' && p[0] <= '0' + i && (p[1] == ',' || p[1] == 0)) + { + j = p[0] - '0'; + classes[i] = classes[j]; + + if (GET_CODE (op) != REG || REGNO (op) < FIRST_PSEUDO_REGISTER) + { + /* If this matches the other operand, we have no added + cost and we win. */ + if (rtx_equal_p (ops[j], op)) + win = 1; + + /* If we can put the other operand into a register, add to + the cost of this alternative the cost to copy this + operand to the register used for the other operand. */ + + else if (classes[j] != NO_REGS) + alt_cost += copy_cost (op, mode, classes[j], 1), win = 1; + } + else if (GET_CODE (ops[j]) != REG + || REGNO (ops[j]) < FIRST_PSEUDO_REGISTER) + { + /* This op is a pseudo but the one it matches is not. */ + + /* If we can't put the other operand into a register, this + alternative can't be used. */ + + if (classes[j] == NO_REGS) + alt_fail = 1; + + /* Otherwise, add to the cost of this alternative the cost + to copy the other operand to the register used for this + operand. */ + + else + alt_cost += copy_cost (ops[j], mode, classes[j], 1); + } + else + { + /* The costs of this operand are the same as that of the + other operand. However, if we cannot tie them, this + alternative needs to do a copy, which is one + instruction. */ + + this_op_costs[i] = this_op_costs[j]; + if (REGNO (ops[i]) != REGNO (ops[j]) + && ! find_reg_note (insn, REG_DEAD, op)) + alt_cost += 2; + + /* This is in place of ordinary cost computation + for this operand, so skip to the end of the + alternative (should be just one character). */ + while (*p && *p++ != ',') + ; + + constraints[i] = p; + continue; + } + } + + /* Scan all the constraint letters. See if the operand matches + any of the constraints. Collect the valid register classes + and see if this operand accepts memory. */ + + classes[i] = NO_REGS; + while (*p && (c = *p++) != ',') + switch (c) + { + case '=': + op_types[i] = OP_WRITE; + break; + + case '+': + op_types[i] = OP_READ_WRITE; + break; + + case '*': + /* Ignore the next letter for this pass. */ + p++; + break; + + case '%': + case '?': case '!': case '#': + case '&': + case '0': case '1': case '2': case '3': case '4': + case 'p': + break; + + case 'm': case 'o': case 'V': + /* It doesn't seem worth distinguishing between offsettable + and non-offsettable addresses here. */ + allows_mem = 1; + if (GET_CODE (op) == MEM) + win = 1; + break; + + case '<': + if (GET_CODE (op) == MEM + && (GET_CODE (XEXP (op, 0)) == PRE_DEC + || GET_CODE (XEXP (op, 0)) == POST_DEC)) + win = 1; + break; + + case '>': + if (GET_CODE (op) == MEM + && (GET_CODE (XEXP (op, 0)) == PRE_INC + || GET_CODE (XEXP (op, 0)) == POST_INC)) + win = 1; + break; + + case 'E': +#ifndef REAL_ARITHMETIC + /* Match any floating double constant, but only if + we can examine the bits of it reliably. */ + if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT + || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD) + && GET_MODE (op) != VOIDmode && ! flag_pretend_float) + break; +#endif + if (GET_CODE (op) == CONST_DOUBLE) + win = 1; + break; + + case 'F': + if (GET_CODE (op) == CONST_DOUBLE) + win = 1; + break; + + case 'G': + case 'H': + if (GET_CODE (op) == CONST_DOUBLE + && CONST_DOUBLE_OK_FOR_LETTER_P (op, c)) + win = 1; + break; + + case 's': + if (GET_CODE (op) == CONST_INT + || (GET_CODE (op) == CONST_DOUBLE + && GET_MODE (op) == VOIDmode)) + break; + case 'i': + if (CONSTANT_P (op) +#ifdef LEGITIMATE_PIC_OPERAND_P + && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op)) +#endif + ) + win = 1; + break; + + case 'n': + if (GET_CODE (op) == CONST_INT + || (GET_CODE (op) == CONST_DOUBLE + && GET_MODE (op) == VOIDmode)) + win = 1; + break; + + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + if (GET_CODE (op) == CONST_INT + && CONST_OK_FOR_LETTER_P (INTVAL (op), c)) + win = 1; + break; + + case 'X': + win = 1; + break; + +#ifdef EXTRA_CONSTRAINT + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + if (EXTRA_CONSTRAINT (op, c)) + win = 1; + break; +#endif + + case 'g': + if (GET_CODE (op) == MEM + || (CONSTANT_P (op) +#ifdef LEGITIMATE_PIC_OPERAND_P + && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op)) +#endif + )) + win = 1; + allows_mem = 1; + case 'r': + classes[i] + = reg_class_subunion[(int) classes[i]][(int) GENERAL_REGS]; + break; + + default: + classes[i] + = reg_class_subunion[(int) classes[i]] + [(int) REG_CLASS_FROM_LETTER (c)]; + } + + constraints[i] = p; + + /* How we account for this operand now depends on whether it is a + pseudo register or not. If it is, we first check if any + register classes are valid. If not, we ignore this alternative, + since we want to assume that all pseudos get allocated for + register preferencing. If some register class is valid, compute + the costs of moving the pseudo into that class. */ + + if (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER) + { + if (classes[i] == NO_REGS) + alt_fail = 1; + else + { + struct costs *pp = &this_op_costs[i]; + + for (class = 0; class < N_REG_CLASSES; class++) + pp->cost[class] = may_move_cost[class][(int) classes[i]]; + + /* If the alternative actually allows memory, make things + a bit cheaper since we won't need an extra insn to + load it. */ + + pp->mem_cost = MEMORY_MOVE_COST (mode) - allows_mem; + + /* If we have assigned a class to this register in our + first pass, add a cost to this alternative corresponding + to what we would add if this register were not in the + appropriate class. */ + + if (prefclass) + alt_cost + += may_move_cost[prefclass[REGNO (op)]][(int) classes[i]]; + } + } + + /* Otherwise, if this alternative wins, either because we + have already determined that or if we have a hard register of + the proper class, there is no cost for this alternative. */ + + else if (win + || (GET_CODE (op) == REG + && reg_fits_class_p (op, classes[i], 0, GET_MODE (op)))) + ; + + /* If registers are valid, the cost of this alternative includes + copying the object to and/or from a register. */ + + else if (classes[i] != NO_REGS) + { + if (op_types[i] != OP_WRITE) + alt_cost += copy_cost (op, mode, classes[i], 1); + + if (op_types[i] != OP_READ) + alt_cost += copy_cost (op, mode, classes[i], 0); + } + + /* The only other way this alternative can be used is if this is a + constant that could be placed into memory. */ + + else if (CONSTANT_P (op) && allows_mem) + alt_cost += MEMORY_MOVE_COST (mode); + else + alt_fail = 1; + } + + if (alt_fail) + continue; + + /* Finally, update the costs with the information we've calculated + about this alternative. */ + + for (i = 0; i < n_ops; i++) + if (GET_CODE (ops[i]) == REG + && REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER) + { + struct costs *pp = &op_costs[i], *qq = &this_op_costs[i]; + int scale = 1 + (op_types[i] == OP_READ_WRITE); + + pp->mem_cost = MIN (pp->mem_cost, + (qq->mem_cost + alt_cost) * scale); + + for (class = 0; class < N_REG_CLASSES; class++) + pp->cost[class] = MIN (pp->cost[class], + (qq->cost[class] + alt_cost) * scale); + } + } + + /* If this insn is a single set copying operand 1 to operand 0 + and one is a pseudo with the other a hard reg that is in its + own register class, set the cost of that register class to -1. */ + + if ((set = single_set (insn)) != 0 + && ops[0] == SET_DEST (set) && ops[1] == SET_SRC (set) + && GET_CODE (ops[0]) == REG && GET_CODE (ops[1]) == REG) + for (i = 0; i <= 1; i++) + if (REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER) + { + int regno = REGNO (ops[!i]); + enum machine_mode mode = GET_MODE (ops[!i]); + int class; + int nr; + + if (regno >= FIRST_PSEUDO_REGISTER && prefclass != 0 + && (reg_class_size[prefclass[regno]] + == CLASS_MAX_NREGS (prefclass[regno], mode))) + op_costs[i].cost[prefclass[regno]] = -1; + else if (regno < FIRST_PSEUDO_REGISTER) + for (class = 0; class < N_REG_CLASSES; class++) + if (TEST_HARD_REG_BIT (reg_class_contents[class], regno) + && reg_class_size[class] == CLASS_MAX_NREGS (class, mode)) + { + if (reg_class_size[class] == 1) + op_costs[i].cost[class] = -1; + else + { + for (nr = 0; nr < HARD_REGNO_NREGS(regno, mode); nr++) + { + if (!TEST_HARD_REG_BIT (reg_class_contents[class], regno + nr)) + break; + } + + if (nr == HARD_REGNO_NREGS(regno,mode)) + op_costs[i].cost[class] = -1; + } + } + } +} + +/* Compute the cost of loading X into (if TO_P is non-zero) or from (if + TO_P is zero) a register of class CLASS in mode MODE. + + X must not be a pseudo. */ + +static int +copy_cost (x, mode, class, to_p) + rtx x; + enum machine_mode mode; + enum reg_class class; + int to_p; +{ + enum reg_class secondary_class = NO_REGS; + + /* If X is a SCRATCH, there is actually nothing to move since we are + assuming optimal allocation. */ + + if (GET_CODE (x) == SCRATCH) + return 0; + + /* Get the class we will actually use for a reload. */ + class = PREFERRED_RELOAD_CLASS (x, class); + +#ifdef HAVE_SECONDARY_RELOADS + /* If we need a secondary reload (we assume here that we are using + the secondary reload as an intermediate, not a scratch register), the + cost is that to load the input into the intermediate register, then + to copy them. We use a special value of TO_P to avoid recursion. */ + +#ifdef SECONDARY_INPUT_RELOAD_CLASS + if (to_p == 1) + secondary_class = SECONDARY_INPUT_RELOAD_CLASS (class, mode, x); +#endif + +#ifdef SECONDARY_OUTPUT_RELOAD_CLASS + if (! to_p) + secondary_class = SECONDARY_OUTPUT_RELOAD_CLASS (class, mode, x); +#endif + + if (secondary_class != NO_REGS) + return (move_cost[(int) secondary_class][(int) class] + + copy_cost (x, mode, secondary_class, 2)); +#endif /* HAVE_SECONDARY_RELOADS */ + + /* For memory, use the memory move cost, for (hard) registers, use the + cost to move between the register classes, and use 2 for everything + else (constants). */ + + if (GET_CODE (x) == MEM || class == NO_REGS) + return MEMORY_MOVE_COST (mode); + + else if (GET_CODE (x) == REG) + return move_cost[(int) REGNO_REG_CLASS (REGNO (x))][(int) class]; + + else + /* If this is a constant, we may eventually want to call rtx_cost here. */ + return 2; +} + +/* Record the pseudo registers we must reload into hard registers + in a subexpression of a memory address, X. + + CLASS is the class that the register needs to be in and is either + BASE_REG_CLASS or INDEX_REG_CLASS. + + SCALE is twice the amount to multiply the cost by (it is twice so we + can represent half-cost adjustments). */ + +static void +record_address_regs (x, class, scale) + rtx x; + enum reg_class class; + int scale; +{ + register enum rtx_code code = GET_CODE (x); + + switch (code) + { + case CONST_INT: + case CONST: + case CC0: + case PC: + case SYMBOL_REF: + case LABEL_REF: + return; + + case PLUS: + /* When we have an address that is a sum, + we must determine whether registers are "base" or "index" regs. + If there is a sum of two registers, we must choose one to be + the "base". Luckily, we can use the REGNO_POINTER_FLAG + to make a good choice most of the time. We only need to do this + on machines that can have two registers in an address and where + the base and index register classes are different. + + ??? This code used to set REGNO_POINTER_FLAG in some cases, but + that seems bogus since it should only be set when we are sure + the register is being used as a pointer. */ + + { + rtx arg0 = XEXP (x, 0); + rtx arg1 = XEXP (x, 1); + register enum rtx_code code0 = GET_CODE (arg0); + register enum rtx_code code1 = GET_CODE (arg1); + + /* Look inside subregs. */ + if (code0 == SUBREG) + arg0 = SUBREG_REG (arg0), code0 = GET_CODE (arg0); + if (code1 == SUBREG) + arg1 = SUBREG_REG (arg1), code1 = GET_CODE (arg1); + + /* If this machine only allows one register per address, it must + be in the first operand. */ + + if (MAX_REGS_PER_ADDRESS == 1) + record_address_regs (arg0, class, scale); + + /* If index and base registers are the same on this machine, just + record registers in any non-constant operands. We assume here, + as well as in the tests below, that all addresses are in + canonical form. */ + + else if (INDEX_REG_CLASS == BASE_REG_CLASS) + { + record_address_regs (arg0, class, scale); + if (! CONSTANT_P (arg1)) + record_address_regs (arg1, class, scale); + } + + /* If the second operand is a constant integer, it doesn't change + what class the first operand must be. */ + + else if (code1 == CONST_INT || code1 == CONST_DOUBLE) + record_address_regs (arg0, class, scale); + + /* If the second operand is a symbolic constant, the first operand + must be an index register. */ + + else if (code1 == SYMBOL_REF || code1 == CONST || code1 == LABEL_REF) + record_address_regs (arg0, INDEX_REG_CLASS, scale); + + /* If this the sum of two registers where the first is known to be a + pointer, it must be a base register with the second an index. */ + + else if (code0 == REG && code1 == REG + && REGNO_POINTER_FLAG (REGNO (arg0))) + { + record_address_regs (arg0, BASE_REG_CLASS, scale); + record_address_regs (arg1, INDEX_REG_CLASS, scale); + } + + /* If this is the sum of two registers and neither is known to + be a pointer, count equal chances that each might be a base + or index register. This case should be rare. */ + + else if (code0 == REG && code1 == REG + && ! REGNO_POINTER_FLAG (REGNO (arg0)) + && ! REGNO_POINTER_FLAG (REGNO (arg1))) + { + record_address_regs (arg0, BASE_REG_CLASS, scale / 2); + record_address_regs (arg0, INDEX_REG_CLASS, scale / 2); + record_address_regs (arg1, BASE_REG_CLASS, scale / 2); + record_address_regs (arg1, INDEX_REG_CLASS, scale / 2); + } + + /* In all other cases, the first operand is an index and the + second is the base. */ + + else + { + record_address_regs (arg0, INDEX_REG_CLASS, scale); + record_address_regs (arg1, BASE_REG_CLASS, scale); + } + } + break; + + case POST_INC: + case PRE_INC: + case POST_DEC: + case PRE_DEC: + /* Double the importance of a pseudo register that is incremented + or decremented, since it would take two extra insns + if it ends up in the wrong place. If the operand is a pseudo, + show it is being used in an INC_DEC context. */ + +#ifdef FORBIDDEN_INC_DEC_CLASSES + if (GET_CODE (XEXP (x, 0)) == REG + && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER) + in_inc_dec[REGNO (XEXP (x, 0))] = 1; +#endif + + record_address_regs (XEXP (x, 0), class, 2 * scale); + break; + + case REG: + { + register struct costs *pp = &costs[REGNO (x)]; + register int i; + + pp->mem_cost += (MEMORY_MOVE_COST (Pmode) * scale) / 2; + + for (i = 0; i < N_REG_CLASSES; i++) + pp->cost[i] += (may_move_cost[i][(int) class] * scale) / 2; + } + break; + + default: + { + register char *fmt = GET_RTX_FORMAT (code); + register int i; + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + if (fmt[i] == 'e') + record_address_regs (XEXP (x, i), class, scale); + } + } +} + +#ifdef FORBIDDEN_INC_DEC_CLASSES + +/* Return 1 if REG is valid as an auto-increment memory reference + to an object of MODE. */ + +static +auto_inc_dec_reg_p (reg, mode) + rtx reg; + enum machine_mode mode; +{ +#ifdef HAVE_POST_INCREMENT + if (memory_address_p (mode, gen_rtx (POST_INC, Pmode, reg))) + return 1; +#endif + +#ifdef HAVE_POST_DECREMENT + if (memory_address_p (mode, gen_rtx (POST_DEC, Pmode, reg))) + return 1; +#endif + +#ifdef HAVE_PRE_INCREMENT + if (memory_address_p (mode, gen_rtx (PRE_INC, Pmode, reg))) + return 1; +#endif + +#ifdef HAVE_PRE_DECREMENT + if (memory_address_p (mode, gen_rtx (PRE_DEC, Pmode, reg))) + return 1; +#endif + + return 0; +} +#endif + +#endif /* REGISTER_CONSTRAINTS */ + +/* This is the `regscan' pass of the compiler, run just before cse + and again just before loop. + + It finds the first and last use of each pseudo-register + and records them in the vectors regno_first_uid, regno_last_uid + and counts the number of sets in the vector reg_n_sets. + + REPEAT is nonzero the second time this is called. */ + +/* Indexed by pseudo register number, gives uid of first insn using the reg + (as of the time reg_scan is called). */ + +int *regno_first_uid; + +/* Indexed by pseudo register number, gives uid of last insn using the reg + (as of the time reg_scan is called). */ + +int *regno_last_uid; + +/* Indexed by pseudo register number, gives uid of last insn using the reg + or mentioning it in a note (as of the time reg_scan is called). */ + +int *regno_last_note_uid; + +/* Record the number of registers we used when we allocated the above two + tables. If we are called again with more than this, we must re-allocate + the tables. */ + +static int highest_regno_in_uid_map; + +/* Maximum number of parallel sets and clobbers in any insn in this fn. + Always at least 3, since the combiner could put that many together + and we want this to remain correct for all the remaining passes. */ + +int max_parallel; + +void +reg_scan (f, nregs, repeat) + rtx f; + int nregs; + int repeat; +{ + register rtx insn; + + if (!repeat || nregs > highest_regno_in_uid_map) + { + /* Leave some spare space in case more regs are allocated. */ + highest_regno_in_uid_map = nregs + nregs / 20; + regno_first_uid + = (int *) oballoc (highest_regno_in_uid_map * sizeof (int)); + regno_last_uid + = (int *) oballoc (highest_regno_in_uid_map * sizeof (int)); + regno_last_note_uid + = (int *) oballoc (highest_regno_in_uid_map * sizeof (int)); + reg_n_sets + = (short *) oballoc (highest_regno_in_uid_map * sizeof (short)); + } + + bzero ((char *) regno_first_uid, highest_regno_in_uid_map * sizeof (int)); + bzero ((char *) regno_last_uid, highest_regno_in_uid_map * sizeof (int)); + bzero ((char *) regno_last_note_uid, + highest_regno_in_uid_map * sizeof (int)); + bzero ((char *) reg_n_sets, highest_regno_in_uid_map * sizeof (short)); + + max_parallel = 3; + + for (insn = f; insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == INSN + || GET_CODE (insn) == CALL_INSN + || GET_CODE (insn) == JUMP_INSN) + { + if (GET_CODE (PATTERN (insn)) == PARALLEL + && XVECLEN (PATTERN (insn), 0) > max_parallel) + max_parallel = XVECLEN (PATTERN (insn), 0); + reg_scan_mark_refs (PATTERN (insn), insn, 0); + + if (REG_NOTES (insn)) + reg_scan_mark_refs (REG_NOTES (insn), insn, 1); + } +} + +/* X is the expression to scan. INSN is the insn it appears in. + NOTE_FLAG is nonzero if X is from INSN's notes rather than its body. */ + +static void +reg_scan_mark_refs (x, insn, note_flag) + rtx x; + rtx insn; + int note_flag; +{ + register enum rtx_code code = GET_CODE (x); + register rtx dest; + register rtx note; + + switch (code) + { + case CONST_INT: + case CONST: + case CONST_DOUBLE: + case CC0: + case PC: + case SYMBOL_REF: + case LABEL_REF: + case ADDR_VEC: + case ADDR_DIFF_VEC: + return; + + case REG: + { + register int regno = REGNO (x); + + regno_last_note_uid[regno] = INSN_UID (insn); + if (!note_flag) + regno_last_uid[regno] = INSN_UID (insn); + if (regno_first_uid[regno] == 0) + regno_first_uid[regno] = INSN_UID (insn); + } + break; + + case EXPR_LIST: + if (XEXP (x, 0)) + reg_scan_mark_refs (XEXP (x, 0), insn, note_flag); + if (XEXP (x, 1)) + reg_scan_mark_refs (XEXP (x, 1), insn, note_flag); + break; + + case INSN_LIST: + if (XEXP (x, 1)) + reg_scan_mark_refs (XEXP (x, 1), insn, note_flag); + break; + + case SET: + /* Count a set of the destination if it is a register. */ + for (dest = SET_DEST (x); + GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART + || GET_CODE (dest) == ZERO_EXTEND; + dest = XEXP (dest, 0)) + ; + + if (GET_CODE (dest) == REG) + reg_n_sets[REGNO (dest)]++; + + /* If this is setting a pseudo from another pseudo or the sum of a + pseudo and a constant integer and the other pseudo is known to be + a pointer, set the destination to be a pointer as well. + + Likewise if it is setting the destination from an address or from a + value equivalent to an address or to the sum of an address and + something else. + + But don't do any of this if the pseudo corresponds to a user + variable since it should have already been set as a pointer based + on the type. */ + + if (GET_CODE (SET_DEST (x)) == REG + && REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER + && ! REG_USERVAR_P (SET_DEST (x)) + && ! REGNO_POINTER_FLAG (REGNO (SET_DEST (x))) + && ((GET_CODE (SET_SRC (x)) == REG + && REGNO_POINTER_FLAG (REGNO (SET_SRC (x)))) + || ((GET_CODE (SET_SRC (x)) == PLUS + || GET_CODE (SET_SRC (x)) == LO_SUM) + && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT + && GET_CODE (XEXP (SET_SRC (x), 0)) == REG + && REGNO_POINTER_FLAG (REGNO (XEXP (SET_SRC (x), 0)))) + || GET_CODE (SET_SRC (x)) == CONST + || GET_CODE (SET_SRC (x)) == SYMBOL_REF + || GET_CODE (SET_SRC (x)) == LABEL_REF + || (GET_CODE (SET_SRC (x)) == HIGH + && (GET_CODE (XEXP (SET_SRC (x), 0)) == CONST + || GET_CODE (XEXP (SET_SRC (x), 0)) == SYMBOL_REF + || GET_CODE (XEXP (SET_SRC (x), 0)) == LABEL_REF)) + || ((GET_CODE (SET_SRC (x)) == PLUS + || GET_CODE (SET_SRC (x)) == LO_SUM) + && (GET_CODE (XEXP (SET_SRC (x), 1)) == CONST + || GET_CODE (XEXP (SET_SRC (x), 1)) == SYMBOL_REF + || GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF)) + || ((note = find_reg_note (insn, REG_EQUAL, 0)) != 0 + && (GET_CODE (XEXP (note, 0)) == CONST + || GET_CODE (XEXP (note, 0)) == SYMBOL_REF + || GET_CODE (XEXP (note, 0)) == LABEL_REF)))) + REGNO_POINTER_FLAG (REGNO (SET_DEST (x))) = 1; + + /* ... fall through ... */ + + default: + { + register char *fmt = GET_RTX_FORMAT (code); + register int i; + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'e') + reg_scan_mark_refs (XEXP (x, i), insn, note_flag); + else if (fmt[i] == 'E' && XVEC (x, i) != 0) + { + register int j; + for (j = XVECLEN (x, i) - 1; j >= 0; j--) + reg_scan_mark_refs (XVECEXP (x, i, j), insn, note_flag); + } + } + } + } +} + +/* Return nonzero if C1 is a subset of C2, i.e., if every register in C1 + is also in C2. */ + +int +reg_class_subset_p (c1, c2) + register enum reg_class c1; + register enum reg_class c2; +{ + if (c1 == c2) return 1; + + if (c2 == ALL_REGS) + win: + return 1; + GO_IF_HARD_REG_SUBSET (reg_class_contents[(int)c1], + reg_class_contents[(int)c2], + win); + return 0; +} + +/* Return nonzero if there is a register that is in both C1 and C2. */ + +int +reg_classes_intersect_p (c1, c2) + register enum reg_class c1; + register enum reg_class c2; +{ +#ifdef HARD_REG_SET + register +#endif + HARD_REG_SET c; + + if (c1 == c2) return 1; + + if (c1 == ALL_REGS || c2 == ALL_REGS) + return 1; + + COPY_HARD_REG_SET (c, reg_class_contents[(int) c1]); + AND_HARD_REG_SET (c, reg_class_contents[(int) c2]); + + GO_IF_HARD_REG_SUBSET (c, reg_class_contents[(int) NO_REGS], lose); + return 1; + + lose: + return 0; +} + |