From: Richard Henderson Date: Fri, 24 Sep 2004 19:47:05 +0000 (-0700) Subject: re PR middle-end/17503 (quadratic behaviour in invalid_mode_change_p) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=41bf2a8b17267a42615392ad9da37081f59e428c;p=gcc.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: r88067 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 74b4a425f54..070d85c8254 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +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-09-24 Andrew Pinski * tree-ssa-phiopt.c (conditional_replacement): Use the correct diff --git a/gcc/combine.c b/gcc/combine.c index 24ebbc97147..f0b5b0698dd 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -9327,13 +9327,8 @@ gen_lowpart_for_combine (enum machine_mode mode, rtx x) result = gen_lowpart_common (mode, x); #ifdef CANNOT_CHANGE_MODE_CLASS - if (result != 0 - && GET_CODE (result) == SUBREG - && REG_P (SUBREG_REG (result)) - && 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 d1e7e2d61c4..02f7ff21505 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -377,7 +377,7 @@ life_analysis (FILE *file, int flags) #ifdef CANNOT_CHANGE_MODE_CLASS if (flags & PROP_REG_INFO) - bitmap_initialize (&subregs_of_mode, 1); + init_subregs_of_mode (); #endif if (! optimize) @@ -3773,12 +3773,8 @@ mark_used_regs (struct propagate_block_info *pbi, rtx x, rtx cond, rtx insn) case SUBREG: #ifdef CANNOT_CHANGE_MODE_CLASS - if ((flags & PROP_REG_INFO) - && REG_P (SUBREG_REG (x)) - && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER) - bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (x)) - * MAX_MACHINE_MODE - + GET_MODE (x)); + if (flags & PROP_REG_INFO) + record_subregs_of_mode (x); #endif /* While we're here, optimize this case. */ @@ -3823,13 +3819,8 @@ mark_used_regs (struct propagate_block_info *pbi, rtx x, rtx cond, rtx insn) || GET_CODE (testreg) == SUBREG) { #ifdef CANNOT_CHANGE_MODE_CLASS - if ((flags & PROP_REG_INFO) - && GET_CODE (testreg) == SUBREG - && REG_P (SUBREG_REG (testreg)) - && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER) - bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (testreg)) - * MAX_MACHINE_MODE - + GET_MODE (testreg)); + if ((flags & PROP_REG_INFO) && 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 1d33a0977b2..6d1d975f093 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -45,6 +45,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "output.h" #include "ggc.h" #include "timevar.h" +#include "hashtab.h" static void init_reg_sets_1 (void); static void init_reg_autoinc (void); @@ -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]; @@ -2594,6 +2589,70 @@ regset_release_memory (void) } #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 (const void *x) +{ + const struct subregs_of_mode_node *a = x; + return a->block; +} + +static int +som_eq (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 (void) +{ + 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 (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. */ @@ -2601,19 +2660,23 @@ void cannot_change_mode_set_regs (HARD_REG_SET *used, 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 @@ -2621,20 +2684,24 @@ cannot_change_mode_set_regs (HARD_REG_SET *used, enum machine_mode from, bool invalid_mode_change_p (unsigned int regno, enum reg_class class, - enum machine_mode from_mode) + 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 027b0e33c67..848c306a3ff 100644 --- a/gcc/regs.h +++ b/gcc/regs.h @@ -68,8 +68,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 d96b3d4c433..8f7274a3c1b 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2092,6 +2092,8 @@ extern void regclass (rtx, int, FILE *); extern void reg_scan (rtx, unsigned int, int); extern void reg_scan_update (rtx, rtx, unsigned int); extern void fix_register (const char *, int, int); +extern void init_subregs_of_mode (void); +extern void record_subregs_of_mode (rtx); #ifdef HARD_CONST extern void cannot_change_mode_set_regs (HARD_REG_SET *, enum machine_mode, unsigned int);