diff options
Diffstat (limited to 'gnu/gcc2/lib/regclass.c')
| -rw-r--r-- | gnu/gcc2/lib/regclass.c | 1673 |
1 files changed, 0 insertions, 1673 deletions
diff --git a/gnu/gcc2/lib/regclass.c b/gnu/gcc2/lib/regclass.c deleted file mode 100644 index 196035597246..000000000000 --- a/gnu/gcc2/lib/regclass.c +++ /dev/null @@ -1,1673 +0,0 @@ -/* 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 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, 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_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; - -/* 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 (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. */ - -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 - - 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. */ - -void -fix_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; - } - else - { - warning ("unknown register name: %s", name); - } -} - -/* 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 int copy_cost (); -static void record_reg_classes (); -static void record_address_regs (); - - -/* 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 (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 - ) - 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 (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. Don't bother doing anything if the - second operand is a constant since that is the case - for which the constraints should have been written. */ - - for (i = 0; i < noperands - 1; i++) - if (constraints[i][0] == '%' - && ! CONSTANT_P (recog_operand[i+1])) - { - 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; - - /* 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. */ - if (rtx_equal_p (ops[j], op)) - ; - - /* 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. */ - - 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 (! find_reg_note (insn, REG_DEAD, op)) - alt_cost += 2; - - /* This is in place of ordinary cost computation - for this operand. */ - 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': - /* 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; - 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); - } - } -} - -/* 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); - } - } -} -#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; - -/* 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 togetherm - and we want this to remain correct for all the remaining passes. */ - -int max_parallel; - -void reg_scan_mark_refs (); - -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)); - reg_n_sets - = (short *) oballoc (highest_regno_in_uid_map * sizeof (short)); - } - - bzero (regno_first_uid, highest_regno_in_uid_map * sizeof (int)); - bzero (regno_last_uid, highest_regno_in_uid_map * sizeof (int)); - bzero (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); - } -} - -void -reg_scan_mark_refs (x, insn) - rtx x; - rtx insn; -{ - 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_uid[regno] = INSN_UID (insn); - if (regno_first_uid[regno] == 0) - regno_first_uid[regno] = INSN_UID (insn); - } - 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); - 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); - } - } - } - } -} - -/* 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; -} - |
