mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-24 12:19:35 +08:00
ddef6bc7a3
2001-04-03 Jakub Jelinek <jakub@redhat.com> David S. Miller <davem@pierdol.cobaltmicro.com> Andrew MacLeod <amacleod@redhat.com> Use byte offsets in SUBREGs instead of words. * alias.c (nonlocal_mentioned_p): Use subreg_regno function. * caller-save.c (mark_set_regs): Change callers of subreg_hard_regno to pass new argument. (add_stored_regs): Use subreg_regno_offset function. * calls.c (expand_call): For non-paradoxical SUBREG take endianess into account. (precompute_arguments): Use gen_lowpart_SUBREG. * combine.c (try_combine): Replace explicit XEXP with SUBREG_REG. (combine_simplify_rtx): Rework to use SUBREG_BYTE. (simplify_set): Rework to use SUBREG_BYTE. (expand_field_assignment): Use SUBREG_BYTE. (make_extraction): Use SUBREG_BYTE. (if_then_else_cond): Use SUBREG_BYTE. (apply_distributive_law): Use SUBREG_BYTE and fixup subreg comments. (gen_lowpart_for_combine): Compute full byte offset. * cse.c (mention_regs): Use SUBREG_BYTE. (remove_invalid_subreg_refs): Rework to use SUBREG_BYTE. (canon_hash): Use SUBREG_BYTE. (fold_rtx): Pass SUBREG_BYTE div UNITS_PER_WORD to operand_subword. (gen_lowpart_if_possible): Formatting. * dbxout.c (dbxout_symbol_location): Compute SUBREG hard regnos correctly. * dwarf2out.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG (mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG (loc_descriptor): Fixup explicit XEXP into SUBREG_REG * dwarfout.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG (output_mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG (output_loc_descriptor): Fixup explicit XEXP into SUBREG_REG * emit-rtl.c (gen_rtx_SUBREG): New function, used to verify certain invariants about SUBREGs the compiler creates. (gen_lowpart_SUBREG): New function. (subreg_hard_regno): New function to get the final register number. (gen_lowpart_common): Use SUBREG_BYTE. (gen_imagpart): Spacing nits. (subreg_realpart_p): Use SUBREG_BYTE. (gen_highpart): Use SUBREG_BYTE. (subreg_lowpart_p): Always compute endian corrected goal offset, even at the byte level, then compare against that. (constant_subword): New function, pulled out all constant cases from operand_subword and changed second argument name to offset. (operand_subword): Detect non REG/SUBREG/CONCAT/MEM cases early and call constant_subword to do the work. Return const0_rtx if looking for a word outside of OP. (operand_subword_force): Change second arg name to offset. * expmed.c (store_bit_field): Use SUBREG_BYTE. (store_split_bit_field): Use SUBREG_BYTE. (extract_bit_field): Use SUBREG_BYTE. (extract_split_bit_field): Use SUBREG_BYTE. (expand_shift): Use SUBREG_BYTE. * expr.c (store_expr, expand_expr): Use gen_lowpart_SUBREG. * final.c (alter_subreg) Use subreg_hard_regno and SUBREG_BYTE. * flow.c (set_noop_p): Use SUBREG_BYTE. (mark_set_1): Remove ALTER_HARD_SUBREG. Use subreg_regno_offset instead. * function.c (fixup_var_refs_1): Fixup explicit XEXP into a SUBREG_REG. (fixup_memory_subreg): Use SUBREG_BYTE and remove byte endian correction code. (optimize_bit_field): Use SUBREG_BYTE. (purge_addressof_1): Use SUBREG_BYTE. (purge_single_hard_subreg_set): Use subreg_regno_offset function. (assign_params): Mark arguments SUBREG_PROMOTED_VAR_P if they are actually promoted by the caller and PROMOTE_FOR_CALLS_ONLY is true. * gengenrtl.c (special_rtx): Add SUBREG. * global.c (mark_reg_store): Use SUBREG_BYTE. (set_preference): Rework to use subreg_regno_offset and SUBREG_BYTE. * ifcvt (noce_emit_move_insn): Use SUBREG_BYTE. * integrate.c (copy_rtx_and_substitute): Use SUBREG_BYTE and make sure final byte offset is congruent to subreg's mode size. (subst_constants): Use SUBREG_BYTE. (mark_stores): Use subreg_regno_offset function. * jump.c (rtx_renumbered_equal_p, true_regnum): Use subreg_regno_offset function and SUBREG_BYTE. * local-alloc.c (combine_regs): Use subreg_regno_offset function. (reg_is_born): Use subreg_hard_regno. * recog.c (valid_replace_rtx_1): Use SUBREG_BYTE and remove byte endian correction code. Don't combine subregs unless resulting offset aligns with type. Fix subreg constant extraction for DImode. Simplify SUBREG of VOIDmode CONST_DOUBLE. (general_operand): Remove dead mode_altering_drug code. (indirect_operand): Use SUBREG_BYTE. (constrain_operands): Use subreg_regno_offset function. * reg-stack.c (get_true_reg): Use subreg_regno_offset function. * regmove.c (regmove_optimize): Use SUBREG_BYTE. (optimize_reg_copy_3): Use gen_lowpart_SUBREG. * regs.h (REG_SIZE): Allow target to override. (REGMODE_NATURAL_SIZE): New macro which target can override. * reload.c (reload_inner_reg_of_subreg): subreg_regno should be used on the entire subreg rtx. (push_reload): Use SUBREG_BYTE in comments and code. (find_dummy_reload): Use subreg_regno_offset. Only adjust offsets for hard registers inside subregs. (operands_match_p): Use subreg_regno_offset. (find_reloads): Use SUBREG_BYTE and only advance offset for subregs containing hard regs. (find_reload_toplev): Use SUBREG_BYTE. Remove byte endian corrections when fixing up MEM subregs. (find_reloads_address_1): Use SUBREG_BYTE, subreg_regno, and subreg_regno_offset where appropriate. (find_reloads_subreg_address): Use SUBREG_BYTE. Remove byte endian corrections when fixing up MEM subregs. (subst_reloads): When combining two subregs, make sure final offset is congruent to subreg's mode size. (find_replacement): Use SUBREG_BYTE and subreg_regno_offset. (refers_to_regno_for_reload_p): Use subreg_regno. (reg_overlap_mentioned_for_reload_p): Use subreg_regno_offset. * reload1.c (eliminate_regs) Use SUBREG_BYTE. Remove byte endian correction code for memory subreg fixups. (forget_old_reload_1): Use subreg_regno_offset. (choose_reload_regs): Use subreg_regno. (emit_input_reload_insns): Use SUBREG_BYTE. (reload_combine_note_store): Use subreg_regno_offset. (move2add_note_store): Use subreg_regno_offset. * resource.c (update_live_status, mark_referenced_resources): Use subreg_regno function. (mark_set_resources): Use subreg_regno function. * rtl.h (SUBREG_WORD): Rename to SUBREG_BYTE. (subreg_regno_offset, subreg_regno): Define prototypes. (subreg_hard_regno, constant_subword, gen_rtx_SUBREG): Newi functions. (gen_lowpart_SUBREG): Add prototype. * rtl.texi (subreg): Update to reflect new byte offset representation. Add mentioning of the effect that BYTES_BIG_ENDIAN has on subregs now. * rtlanal.c (refers_to_regno_p): Use subreg_regno. (reg_overlap_mentioned_p): Use subreg_regno. (replace_regs); Make sure final offset of combined subreg is congruent to size of subreg's mode. (subreg_regno_offset): New function. (subreg_regno): New function. * sched-vis.c (print_value): Change SUBREG_WORD to SUBREG_BYTE. * sdbout.c (sdbout_symbol): Compute offset using alter_subreg. * stmt.c (expand_anon_union_decl): Use gen_lowpart_SUBREG. * tm.texi (ALTER_HARD_SUBREG): Remove, it is now dead. (SUBREG_REGNO_OFFSET): Describe SUBREG_REGNO_OFFSET overrides. * config/a29k/a29k.c (gpc_reg_operand): Use subreg_regno. (a29k_get_reloaded_address): Use SUBREG_BYTE. (print_operand): Use SUBREG_BYTE. * config/alpha/alpha.c (print_operand_address): Use SUBREG_BYTE. * config/arm/arm.c (arm_reload_in_hi): Use SUBREG_BYTE. (arm_reload_out_hi): Use SUBREG_BYTE. * config/d30v/d30v.c (d30v_split_double): Use subreg_regno_offset instead of SUBREG_WORD. (d30v_print_operand_memory_reference): Use subreg_regno_offset. * config/dsp16xx/dsp16xx.md (extendqihi2, zero_extendqihi2): Fix SUBREG creation to use byte offset. * config/h8300/h8300.md (Unnamed HImode zero extraction and 16bit inverted load insns): Fix explicit rtl subregs to use byte offsets. * config/i370/i370.md (cmpstrsi, movstrsi, mulsi3, divsi3, udivsi3, umodsi3): Generate SUBREGs with byte offsets. * config/i860/i860.c (single_insn_src_p): Use SUBREG_BYTE. * config/i860/i860.md (mulsi3_big): Fixup explicit SUBREGs in rtl to use byte offsets. (unnamed fmlow.dd insn): Fixup SUBREGS to use byte offsets. * config/i960/i960.md (extendhisi2): Generate SUBREGs with byte offsets, also make sure it is congruent to SUBREG's mode size. (extendqisi2, extendqihi2, zero_extendhisi2, zero_extendqisi2, unnamed ldob insn): Generate SUBREGs with byte offset. (zero_extendqihi2): SUBREG's are byte offsets. * config/m68hc11/m68hc11.c (m68hc11_gen_lowpart): Use SUBREG_BYTE. (m68hc11_gen_highpart): Use SUBREG_BYTE. * config/m68k/m68k.md (zero_extendhisi2, zero_extendqihi2, zero-extendqisi2): Generate SUBREGs with byte offset. (umulsidi3, mulsidi3, subreghi1ashrdi_const32, subregsi1ashrdi_const32, subreg1lshrdi_const32): Fixup explicit subregs in rtl to use byte offsets. * config/m88k/m88k.md (extendsidi2): fixup subregs to use byte offset. * config/mips/mips.c (mips_move_1word): Use subreg_regno_offset. (mips_move_2words): Use subreg_regno_offset. (mips_secondary_reload_class): Use subreg_regno_offset. * config/mips/mips.md (DImode plus, minus, move, and logical op splits): Fixup explicit subregs in rtl to use byte offsets. * config/mn10200/mn10200.c (print_operand): Use subreg_regno function. * config/mn10300/mn10300.c (print_operand): Use subreg_regno function. * config/ns32k/ns32k.md (udivmoddisi4): Fix explicit subregs in rtl to use byte offsets. * config/pa/pa.c (emit_move_sequence): Use SUBREG_BYTE. * config/pa/pa.md (floatunssisf2, floatunssidf2, mulsi3): fix explicit subregs to use byte offsets. * config/pdp11/pdp11.md (zero_extendhisi2, modhi3, modhi3+1): Fixup explicit subregs in rtl to use byte offsets. * config/romp/romp.c (memory_offset_in_range_p): Use SUBREG_BYTE and remove byte endian correction code. * config/sh/sh.c (output_movedouble): Use subreg_regno. (gen_ashift_hi): Use SUBREG_BYTE. (regs_used): Use subreg_regno_offset. (machine_dependent_reorg): Use subreg_regno_offset. * config/sh/sh.h (INDEX_REGISTER_RTX_P): Use SUBREG_BYTE. * config/sh/sh.md (DImode and DFmode move splits): Use subreg_regno. (movdf_i4): Subregs are byte offsets now. * config/sparc/sparc.c (ultra_find_type): Use SUBREG_BYTE. * config/sparc/sparc.h (ALTER_HARD_SUBREG): Removed. (REGMODE_NATURAL_SIZE): Override. (REG_SIZE): For SUBREG check float mode on SUBREG_REG's mode. * config/sparc/sparc.md (TFmode move splits): Generate SUBREGs with byte offsets. (zero_extendhisi2, zero_extendqidi2_insn, extendhisi2, extendqihi2, sign_extendqihi2_insn, sign_extendqisi2_insn, extendqidi2): Generate SUBREGs with byte offsets, also make sure it is congruent to SUBREG's mode size. (smulsi3_highpart_v8plus): Fix explicit subregs in rtl to use byte offsets. (cmp_siqi_trunc, cmp_siqi_trunc_set, cmp_diqi_trunc, cmp_diqi_trunc_set, lshrdi3_v8plus+1, lshrdi3_v8plus+2, lshrdi3_v8plus+3, lshrdi3_v8plus+4): Use proper SUBREG_BYTE offset for non-paradoxical subregs in patterns. * config/v850/v850.c (print_operand, output_move_double): Use subreg_regno function. Co-Authored-By: Andrew MacLeod <amacleod@redhat.com> Co-Authored-By: David S. Miller <davem@pierdol.cobaltmicro.com> From-SVN: r41058
223 lines
8.1 KiB
C
223 lines
8.1 KiB
C
/* Define per-register tables for data flow info and register allocation.
|
|
Copyright (C) 1987, 1993, 1994, 1995, 1996, 1997, 1998,
|
|
1999, 2000 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. */
|
|
|
|
|
|
#include "varray.h"
|
|
|
|
#define REG_BYTES(R) mode_size[(int) GET_MODE (R)]
|
|
|
|
/* Get the number of consecutive hard regs required to hold the REG or
|
|
SUBREG rtx R.
|
|
When something may be an explicit hard reg, REG_SIZE is the only
|
|
valid way to get this value. You cannot get it from the regno.
|
|
|
|
A target may override this definition, the case where you would do
|
|
this is where there are registers which are smaller than WORD_SIZE
|
|
such as the SFmode registers on sparc64. */
|
|
|
|
#ifndef REG_SIZE
|
|
#define REG_SIZE(R) \
|
|
((mode_size[(int) GET_MODE (R)] + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
|
|
#endif
|
|
|
|
/* When you only have the mode of a pseudo register before it has a hard
|
|
register chosen for it, this reports the size of each hard register
|
|
a pseudo in such a mode would get allocated to. Like REG_SIZE, a
|
|
target may override this. */
|
|
|
|
#ifndef REGMODE_NATURAL_SIZE
|
|
#define REGMODE_NATURAL_SIZE(MODE) UNITS_PER_WORD
|
|
#endif
|
|
|
|
#ifndef SMALL_REGISTER_CLASSES
|
|
#define SMALL_REGISTER_CLASSES 0
|
|
#endif
|
|
|
|
/* Maximum register number used in this function, plus one. */
|
|
|
|
extern int max_regno;
|
|
|
|
/* Register information indexed by register number */
|
|
typedef struct reg_info_def
|
|
{ /* fields set by reg_scan */
|
|
int first_uid; /* UID of first insn to use (REG n) */
|
|
int last_uid; /* UID of last insn to use (REG n) */
|
|
int last_note_uid; /* UID of last note to use (REG n) */
|
|
|
|
/* fields set by reg_scan & flow_analysis */
|
|
int sets; /* # of times (REG n) is set */
|
|
|
|
/* fields set by flow_analysis */
|
|
int refs; /* # of times (REG n) is used or set */
|
|
int deaths; /* # of times (REG n) dies */
|
|
int live_length; /* # of instructions (REG n) is live */
|
|
int calls_crossed; /* # of calls (REG n) is live across */
|
|
int basic_block; /* # of basic blocks (REG n) is used in */
|
|
char changes_mode; /* whether (SUBREG (REG n)) exists and
|
|
is illegal. */
|
|
} reg_info;
|
|
|
|
extern varray_type reg_n_info;
|
|
|
|
/* Indexed by n, gives number of times (REG n) is used or set.
|
|
References within loops may be counted more times. */
|
|
|
|
#define REG_N_REFS(N) (VARRAY_REG (reg_n_info, N)->refs)
|
|
|
|
/* Indexed by n, gives number of times (REG n) is set.
|
|
??? both regscan and flow allocate space for this. We should settle
|
|
on just copy. */
|
|
|
|
#define REG_N_SETS(N) (VARRAY_REG (reg_n_info, N)->sets)
|
|
|
|
/* Indexed by N, gives number of insns in which register N dies.
|
|
Note that if register N is live around loops, it can die
|
|
in transitions between basic blocks, and that is not counted here.
|
|
So this is only a reliable indicator of how many regions of life there are
|
|
for registers that are contained in one basic block. */
|
|
|
|
#define REG_N_DEATHS(N) (VARRAY_REG (reg_n_info, N)->deaths)
|
|
|
|
/* Indexed by N; says whether a pseudo register N was ever used
|
|
within a SUBREG that changes the mode of the reg in some way
|
|
that is illegal for a given class (usually floating-point)
|
|
of registers. */
|
|
|
|
#define REG_CHANGES_MODE(N) (VARRAY_REG (reg_n_info, N)->changes_mode)
|
|
|
|
/* Get the number of consecutive words required to hold pseudo-reg N. */
|
|
|
|
#define PSEUDO_REGNO_SIZE(N) \
|
|
((GET_MODE_SIZE (PSEUDO_REGNO_MODE (N)) + UNITS_PER_WORD - 1) \
|
|
/ UNITS_PER_WORD)
|
|
|
|
/* Get the number of bytes required to hold pseudo-reg N. */
|
|
|
|
#define PSEUDO_REGNO_BYTES(N) \
|
|
GET_MODE_SIZE (PSEUDO_REGNO_MODE (N))
|
|
|
|
/* Get the machine mode of pseudo-reg N. */
|
|
|
|
#define PSEUDO_REGNO_MODE(N) GET_MODE (regno_reg_rtx[N])
|
|
|
|
/* Indexed by N, gives number of CALL_INSNS across which (REG n) is live. */
|
|
|
|
#define REG_N_CALLS_CROSSED(N) (VARRAY_REG (reg_n_info, N)->calls_crossed)
|
|
|
|
/* Total number of instructions at which (REG n) is live.
|
|
The larger this is, the less priority (REG n) gets for
|
|
allocation in a hard register (in global-alloc).
|
|
This is set in flow.c and remains valid for the rest of the compilation
|
|
of the function; it is used to control register allocation.
|
|
|
|
local-alloc.c may alter this number to change the priority.
|
|
|
|
Negative values are special.
|
|
-1 is used to mark a pseudo reg which has a constant or memory equivalent
|
|
and is used infrequently enough that it should not get a hard register.
|
|
-2 is used to mark a pseudo reg for a parameter, when a frame pointer
|
|
is not required. global.c makes an allocno for this but does
|
|
not try to assign a hard register to it. */
|
|
|
|
#define REG_LIVE_LENGTH(N) (VARRAY_REG (reg_n_info, N)->live_length)
|
|
|
|
/* Vector of substitutions of register numbers,
|
|
used to map pseudo regs into hardware regs.
|
|
|
|
This can't be folded into reg_n_info without changing all of the
|
|
machine dependent directories, since the reload functions
|
|
in the machine dependent files access it. */
|
|
|
|
extern short *reg_renumber;
|
|
|
|
/* Vector indexed by hardware reg
|
|
saying whether that reg is ever used. */
|
|
|
|
extern char regs_ever_live[FIRST_PSEUDO_REGISTER];
|
|
|
|
/* Vector indexed by hardware reg giving its name. */
|
|
|
|
extern const char * reg_names[FIRST_PSEUDO_REGISTER];
|
|
|
|
/* 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. */
|
|
|
|
extern enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];
|
|
|
|
/* Vector indexed by regno; gives uid of first insn using that reg.
|
|
This is computed by reg_scan for use by cse and loop.
|
|
It is sometimes adjusted for subsequent changes during loop,
|
|
but not adjusted by cse even if cse invalidates it. */
|
|
|
|
#define REGNO_FIRST_UID(N) (VARRAY_REG (reg_n_info, N)->first_uid)
|
|
|
|
/* Vector indexed by regno; gives uid of last insn using that reg.
|
|
This is computed by reg_scan for use by cse and loop.
|
|
It is sometimes adjusted for subsequent changes during loop,
|
|
but not adjusted by cse even if cse invalidates it.
|
|
This is harmless since cse won't scan through a loop end. */
|
|
|
|
#define REGNO_LAST_UID(N) (VARRAY_REG (reg_n_info, N)->last_uid)
|
|
|
|
/* Similar, but includes insns that mention the reg in their notes. */
|
|
|
|
#define REGNO_LAST_NOTE_UID(N) (VARRAY_REG (reg_n_info, N)->last_note_uid)
|
|
|
|
/* List made of EXPR_LIST rtx's which gives pairs of pseudo registers
|
|
that have to go in the same hard reg. */
|
|
extern rtx regs_may_share;
|
|
|
|
/* Flag set by local-alloc or global-alloc if they decide to allocate
|
|
something in a call-clobbered register. */
|
|
|
|
extern int caller_save_needed;
|
|
|
|
/* Predicate to decide whether to give a hard reg to a pseudo which
|
|
is referenced REFS times and would need to be saved and restored
|
|
around a call CALLS times. */
|
|
|
|
#ifndef CALLER_SAVE_PROFITABLE
|
|
#define CALLER_SAVE_PROFITABLE(REFS, CALLS) (4 * (CALLS) < (REFS))
|
|
#endif
|
|
|
|
/* On most machines a register class is likely to be spilled if it
|
|
only has one register. */
|
|
#ifndef CLASS_LIKELY_SPILLED_P
|
|
#define CLASS_LIKELY_SPILLED_P(CLASS) (reg_class_size[(int) (CLASS)] == 1)
|
|
#endif
|
|
|
|
/* Select a register mode required for caller save of hard regno REGNO. */
|
|
#ifndef HARD_REGNO_CALLER_SAVE_MODE
|
|
#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
|
|
choose_hard_reg_mode (REGNO, NREGS)
|
|
#endif
|
|
|
|
/* Registers that get partially clobbered by a call in a given mode.
|
|
These must not be call used registers. */
|
|
#ifndef HARD_REGNO_CALL_PART_CLOBBERED
|
|
#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) 0
|
|
#endif
|
|
|
|
/* Allocate reg_n_info tables */
|
|
extern void allocate_reg_info PARAMS ((size_t, int, int));
|