From: Richard Henderson Date: Sat, 4 Dec 2004 00:36:38 +0000 (-0800) Subject: re PR middle-end/17503 (quadratic behaviour in invalid_mode_change_p) X-Git-Tag: releases/gcc-3.3.6~206 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=38869d234b0db226dc1952909656d128e1e523f6;p=thirdparty%2Fgcc.git re PR middle-end/17503 (quadratic behaviour in invalid_mode_change_p) PR rtl-opt/17503 * regclass.c (subregs_of_mode): Turn into an htab. Make static. (som_hash, som_eq): New. (init_subregs_of_mode, record_subregs_of_mode): New. (cannot_change_mode_set_regs): Rewrite for htab implementation. (invalid_mode_change_p): Likewise. * combine.c (gen_lowpart_for_combine): Use record_subregs_of_mode. * flow.c (mark_used_regs): Likewise. (life_analysis): Use init_subregs_of_mode. * regs.h (subregs_of_mode): Remove. * rtl.h (init_subregs_of_mode, record_subregs_of_mode): Declare. From-SVN: r91714 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 81bd0c148ceb..49df8ee33992 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2004-12-03 Richard Henderson + + 2004-09-24 Richard Henderson + PR rtl-opt/17503 + * regclass.c (subregs_of_mode): Turn into an htab. Make static. + (som_hash, som_eq): New. + (init_subregs_of_mode, record_subregs_of_mode): New. + (cannot_change_mode_set_regs): Rewrite for htab implementation. + (invalid_mode_change_p): Likewise. + * combine.c (gen_lowpart_for_combine): Use record_subregs_of_mode. + * flow.c (mark_used_regs): Likewise. + (life_analysis): Use init_subregs_of_mode. + * regs.h (subregs_of_mode): Remove. + * rtl.h (init_subregs_of_mode, record_subregs_of_mode): Declare. + 2004-12-03 Roger Sayle PR target/9908 @@ -20,7 +35,7 @@ regs_invalidated_by_call. 2004-11-27 Falk Hueffner - Eric Botcazou + Eric Botcazou PR optimization/18577 * unroll.c (unroll_loop): Test both REGNO_LAST_UID and @@ -78,16 +93,16 @@ 2004-09-30 Richard Henderson - * config/alpha/qrnnd.asm: Mark for noexecstack. + * config/alpha/qrnnd.asm: Mark for noexecstack. 2004-09-30 Richard Henderson - * unwind-dw2.c (_Unwind_GetGR): Honor DWARF_ZERO_REG. - * doc/tm.texi (DWARF_ZERO_REG): New. + * unwind-dw2.c (_Unwind_GetGR): Honor DWARF_ZERO_REG. + * doc/tm.texi (DWARF_ZERO_REG): New. - * config/alpha/alpha.c (alpha_sa_mask, alpha_expand_prologue, - alpha_expand_epilogue): Revert 2003-09-30 change to store zero. - * config/alpha/alpha.h (DWARF_ZERO_REG): New. + * config/alpha/alpha.c (alpha_sa_mask, alpha_expand_prologue, + alpha_expand_epilogue): Revert 2003-09-30 change to store zero. + * config/alpha/alpha.h (DWARF_ZERO_REG): New. 2004-09-30 Release Manager @@ -110,12 +125,12 @@ 2004-09-13 Richard Henderson - PR inline-asm/6806 - * cselib.c (cselib_invalidate_rtx): Export. Remove unused args. - (cselib_invalidate_rtx_note_stores): New. - (cselib_record_sets, cselib_process_insn): Update to match. - * cselib.h (cselib_invalidate_rtx): Declare. - * reload1.c (reload_cse_simplify): Invalidate asm clobbers. + PR inline-asm/6806 + * cselib.c (cselib_invalidate_rtx): Export. Remove unused args. + (cselib_invalidate_rtx_note_stores): New. + (cselib_record_sets, cselib_process_insn): Update to match. + * cselib.h (cselib_invalidate_rtx): Declare. + * reload1.c (reload_cse_simplify): Invalidate asm clobbers. 2004-08-29 Jonathan Wakely @@ -174,7 +189,7 @@ 2004-07-25 Andreas Jaeger Backport from mainline: - * libgcc-std.ver: Add __unorddf2 and __unordsf2 with version 3.3.4. + * libgcc-std.ver: Add __unorddf2 and __unordsf2 with version 3.3.4. 2004-07-25 Kaz Kojima @@ -246,14 +261,14 @@ side-effect of having a length greater or equal to 3. 2004-07-13 Eric Botcazou - Lloyd Parkes + Lloyd Parkes PR target/15186 * config/sparc/sol2-bi.h (LINK_ARCH64_SPEC_BASE): Pass /usr/ucblib/sparcv9 as -R path when -compat-bsd is specified. 2004-07-13 Eric Botcazou - Martin Sebor + Martin Sebor PR target/12602 * doc/invoke.texi (SPARC options): Document -threads @@ -343,18 +358,18 @@ Backport from mainline: 2004-01-19 Richard Henderson - * alpha.md (UNSPEC_NT_LDA): Renumber. - (UNSPEC_CVTLQ, cvtlq): New. - (extendsidi2_1): Rename from extendsidi2_nofix; remove f/f. - (extendsidi2_fix): Remove. - (extendsidi2 splitter): Use cvtlq. - (extendsidi2 fp peepholes): Remove. - (cvtql): Use SFmode instead of SImode. - (fix_trunc?fsi): Update to match. - (floatsisf2_ieee, floatsisf2, floatsidf2_ieee, floatsidf2): New. - (movsi): Rename from movsi_nofix, remove f alternatives. - (movsi_nt_vms): Similarly. - (movsi_fix, movsi_nt_vms_fix): Remove. + * alpha.md (UNSPEC_NT_LDA): Renumber. + (UNSPEC_CVTLQ, cvtlq): New. + (extendsidi2_1): Rename from extendsidi2_nofix; remove f/f. + (extendsidi2_fix): Remove. + (extendsidi2 splitter): Use cvtlq. + (extendsidi2 fp peepholes): Remove. + (cvtql): Use SFmode instead of SImode. + (fix_trunc?fsi): Update to match. + (floatsisf2_ieee, floatsisf2, floatsidf2_ieee, floatsidf2): New. + (movsi): Rename from movsi_nofix, remove f alternatives. + (movsi_nt_vms): Similarly. + (movsi_fix, movsi_nt_vms_fix): Remove. 2004-05-26 Hans-Peter Nilsson diff --git a/gcc/combine.c b/gcc/combine.c index bc4ee639047c..c8b5987faab5 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -10138,13 +10138,8 @@ gen_lowpart_for_combine (mode, x) result = gen_lowpart_common (mode, x); #ifdef CANNOT_CHANGE_MODE_CLASS - if (result != 0 - && GET_CODE (result) == SUBREG - && GET_CODE (SUBREG_REG (result)) == REG - && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER) - bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (result)) - * MAX_MACHINE_MODE - + GET_MODE (result)); + if (result != 0 && GET_CODE (result) == SUBREG) + record_subregs_of_mode (result); #endif if (result) diff --git a/gcc/flow.c b/gcc/flow.c index 11b15dc0ce4d..9f5e1924e91a 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -431,9 +431,8 @@ life_analysis (f, file, flags) SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM); #endif - #ifdef CANNOT_CHANGE_MODE_CLASS - bitmap_initialize (&subregs_of_mode, 1); + init_subregs_of_mode (); #endif if (! optimize) @@ -3851,11 +3850,7 @@ mark_used_regs (pbi, x, cond, insn) case SUBREG: #ifdef CANNOT_CHANGE_MODE_CLASS - if (GET_CODE (SUBREG_REG (x)) == REG - && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER) - bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (x)) - * MAX_MACHINE_MODE - + GET_MODE (x)); + record_subregs_of_mode (x); #endif /* While we're here, optimize this case. */ @@ -3900,12 +3895,8 @@ mark_used_regs (pbi, x, cond, insn) || GET_CODE (testreg) == SUBREG) { #ifdef CANNOT_CHANGE_MODE_CLASS - if (GET_CODE (testreg) == SUBREG - && GET_CODE (SUBREG_REG (testreg)) == REG - && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER) - bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (testreg)) - * MAX_MACHINE_MODE - + GET_MODE (testreg)); + if (GET_CODE (testreg) == SUBREG) + record_subregs_of_mode (testreg); #endif /* Modifying a single register in an alternate mode diff --git a/gcc/regclass.c b/gcc/regclass.c index e3a8963a594a..999a0d61f46e 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -41,6 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "toplev.h" #include "output.h" #include "ggc.h" +#include "hashtab.h" #ifndef REGISTER_MOVE_COST #define REGISTER_MOVE_COST(m, x, y) 2 @@ -235,12 +236,6 @@ static char *in_inc_dec; #endif /* FORBIDDEN_INC_DEC_CLASSES */ -#ifdef CANNOT_CHANGE_MODE_CLASS -/* All registers that have been subreged. Indexed by regno * MAX_MACHINE_MODE - + mode. */ -bitmap_head subregs_of_mode; -#endif - /* Sample MEM values for use by memory_move_secondary_cost. */ static GTY(()) rtx top_of_stack[MAX_MACHINE_MODE]; @@ -2630,6 +2625,77 @@ regset_release_memory () } #ifdef CANNOT_CHANGE_MODE_CLASS + +struct subregs_of_mode_node +{ + unsigned int block; + unsigned char modes[MAX_MACHINE_MODE]; +}; + +static htab_t subregs_of_mode; + +static hashval_t som_hash PARAMS ((const void *)); +static int som_eq PARAMS ((const void *, const void *)); + +static hashval_t +som_hash (x) + const void *x; +{ + const struct subregs_of_mode_node *a = x; + return a->block; +} + +static int +som_eq (x, y) + const void *x; + const void *y; +{ + const struct subregs_of_mode_node *a = x; + const struct subregs_of_mode_node *b = y; + return a->block == b->block; +} + +void +init_subregs_of_mode () +{ + if (subregs_of_mode) + htab_empty (subregs_of_mode); + else + subregs_of_mode = htab_create (100, som_hash, som_eq, free); +} + +void +record_subregs_of_mode (subreg) + rtx subreg; +{ + struct subregs_of_mode_node dummy, *node; + enum machine_mode mode; + unsigned int regno; + void **slot; + + if (!REG_P (SUBREG_REG (subreg))) + return; + + regno = REGNO (SUBREG_REG (subreg)); + mode = GET_MODE (subreg); + + if (regno < FIRST_PSEUDO_REGISTER) + return; + + dummy.block = regno & -8; + slot = htab_find_slot_with_hash (subregs_of_mode, &dummy, + dummy.block, INSERT); + node = *slot; + if (node == NULL) + { + node = xcalloc (1, sizeof (*node)); + node->block = regno & -8; + *slot = node; + } + + node->modes[mode] |= 1 << (regno & 7); +} + /* Set bits in *USED which correspond to registers which can't change their mode from FROM to any mode in which REGNO was encountered. */ @@ -2639,42 +2705,50 @@ cannot_change_mode_set_regs (used, from, regno) enum machine_mode from; unsigned int regno; { + struct subregs_of_mode_node dummy, *node; enum machine_mode to; - int n, i; - int start = regno * MAX_MACHINE_MODE; + unsigned char mask; + unsigned int i; - EXECUTE_IF_SET_IN_BITMAP (&subregs_of_mode, start, n, - if (n >= MAX_MACHINE_MODE + start) - return; - to = n - start; - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (! TEST_HARD_REG_BIT (*used, i) - && REG_CANNOT_CHANGE_MODE_P (i, from, to)) - SET_HARD_REG_BIT (*used, i); - ); + dummy.block = regno & -8; + node = htab_find_with_hash (subregs_of_mode, &dummy, dummy.block); + if (node == NULL) + return; + + mask = 1 << (regno & 7); + for (to = VOIDmode; to < NUM_MACHINE_MODES; to++) + if (node->modes[to] & mask) + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (!TEST_HARD_REG_BIT (*used, i) + && REG_CANNOT_CHANGE_MODE_P (i, from, to)) + SET_HARD_REG_BIT (*used, i); } /* Return 1 if REGNO has had an invalid mode change in CLASS from FROM mode. */ bool -invalid_mode_change_p (regno, class, from_mode) +invalid_mode_change_p (regno, class, from) unsigned int regno; - enum reg_class class; - enum machine_mode from_mode; + enum reg_class class; + enum machine_mode from; { - enum machine_mode to_mode; - int n; - int start = regno * MAX_MACHINE_MODE; - - EXECUTE_IF_SET_IN_BITMAP (&subregs_of_mode, start, n, - if (n >= MAX_MACHINE_MODE + start) - return 0; - to_mode = n - start; - if (CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode, class)) - return 1; - ); - return 0; + struct subregs_of_mode_node dummy, *node; + enum machine_mode to; + unsigned char mask; + + dummy.block = regno & -8; + node = htab_find_with_hash (subregs_of_mode, &dummy, dummy.block); + if (node == NULL) + return false; + + mask = 1 << (regno & 7); + for (to = VOIDmode; to < NUM_MACHINE_MODES; to++) + if (node->modes[to] & mask) + if (CANNOT_CHANGE_MODE_CLASS (from, to, class)) + return true; + + return false; } #endif /* CANNOT_CHANGE_MODE_CLASS */ diff --git a/gcc/regs.h b/gcc/regs.h index e823298614de..1e7ba4419582 100644 --- a/gcc/regs.h +++ b/gcc/regs.h @@ -69,8 +69,6 @@ typedef struct reg_info_def extern varray_type reg_n_info; -extern bitmap_head subregs_of_mode; - /* Indexed by n, gives number of times (REG n) is used or set. */ #define REG_N_REFS(N) (VARRAY_REG (reg_n_info, N)->refs) diff --git a/gcc/rtl.h b/gcc/rtl.h index 715febfddd92..ded9c99d46bc 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2120,6 +2120,8 @@ extern void regclass PARAMS ((rtx, int, FILE *)); extern void reg_scan PARAMS ((rtx, unsigned int, int)); extern void reg_scan_update PARAMS ((rtx, rtx, unsigned int)); extern void fix_register PARAMS ((const char *, int, int)); +extern void init_subregs_of_mode PARAMS ((void)); +extern void record_subregs_of_mode PARAMS ((rtx)); #ifdef HARD_CONST extern void cannot_change_mode_set_regs PARAMS ((HARD_REG_SET *, enum machine_mode,