From: Michael Matz Date: Tue, 16 Jul 2002 13:36:30 +0000 (+0000) Subject: Add a new register allocator. X-Git-Tag: releases/gcc-3.3.0~3822 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9406d60d5ea3a092d81e98a32330dd2158a09d38;p=thirdparty%2Fgcc.git Add a new register allocator. * ra.c: New file. * ra.h: New file. * ra-build.c: New file. * ra-colorize.c: New file. * ra-debug.c: New file. * ra-rewrite.c: New file. * Makefile.in (ra.o, ra-build.o, ra-colorize.o, ra-debug.o, (ra-rewrite.o): New .o files for libbackend.a. (GTFILES): Add basic-block.h. * toplev.c (flag_new_regalloc): New. (f_options): New option "new-ra". (rest_of_compilation): Call initialize_uninitialized_subregs() only for the old allocator. If flag_new_regalloc is set, call new allocator, instead of local_alloc(), global_alloc() and friends. * doc/invoke.texi: Document -fnew-ra. * basic-block.h (FOR_ALL_BB): New. * config/rs6000/rs6000.c (print_operand): Write small constants as @l+80. * df.c (read_modify_subreg_p): Narrow down cases for a rmw subreg. (df_reg_table_realloc): Make size at least as large as max_reg_num(). (df_insn_table_realloc): Size argument now is absolute, not relative. Changed all callers. * gengtype.c (main): Add the pseudo-type "HARD_REG_SET". * regclass.c (reg_scan_mark_refs): Ignore NULL rtx's. 2002-06-20 Michael Matz * df.h (struct ref.id): Make unsigned. * df.c (df_bb_reg_def_chain_create): Remove unsigned cast. 2002-06-13 Michael Matz * df.h (DF_REF_MODE_CHANGE): New flag. * df.c (df_def_record_1, df_uses_record): Set this flag for refs involving subregs with invalid mode changes, when CLASS_CANNOT_CHANGE_MODE is defined. 2002-05-07 Michael Matz * reload1.c (fixup_abnormal_edges): Don't insert on NULL edge. 2002-05-03 Michael Matz * sbitmap.c (sbitmap_difference): Accept sbitmaps of different size. Sat Feb 2 18:58:07 2002 Denis Chertykov * regclass.c (regclass): Work with all regs which have sets or refs. (reg_scan_mark_refs): Count regs inside (clobber ...). 2002-01-04 Michael Matz * df.c (df_ref_record): Correctly calculate SUBREGs of hardregs. (df_bb_reg_def_chain_create, df_bb_reg_use_chain_create): Only add new refs. (df_bb_refs_update): Don't clear insns_modified here, ... (df_analyse): ... but here. * sbitmap.c (dump_sbitmap_file): New. (debug_sbitmap): Use it. * sbitmap.h (dump_sbitmap_file): Add prototype. 2001-08-07 Daniel Berlin * df.c (df_insn_modify): Grow the UID table if necessary, rather than assume all emits go through df_insns_modify. 2001-07-26 Daniel Berlin * regclass.c (reg_scan_mark_refs): When we increase REG_N_SETS, increase REG_N_REFS (like flow does), so that regclass doesn't think a reg is useless, and thus, not calculate a class, when it really should have. 2001-01-28 Daniel Berlin * sbitmap.h (EXECUTE_IF_SET_IN_SBITMAP_REV): New macro, needed for dataflow analysis. From-SVN: r55485 --- diff --git a/gcc/df.c b/gcc/df.c index d7131683c48a..7b8b85e8fca1 100644 --- a/gcc/df.c +++ b/gcc/df.c @@ -311,17 +311,20 @@ static inline bool read_modify_subreg_p PARAMS ((rtx)); /* Local memory allocation/deallocation routines. */ -/* Increase the insn info table by SIZE more elements. */ +/* Increase the insn info table to have space for at least SIZE + 1 + elements. */ static void df_insn_table_realloc (df, size) struct df *df; int size; { - /* Make table 25 percent larger by default. */ - if (! size) - size = df->insn_size / 4; + size++; + if (size <= df->insn_size) + return; - size += df->insn_size; + /* Make the table a little larger than requested, so we don't need + to enlarge it so often. */ + size += df->insn_size / 4; df->insns = (struct insn_info *) xrealloc (df->insns, size * sizeof (struct insn_info)); @@ -350,6 +353,8 @@ df_reg_table_realloc (df, size) size = df->reg_size / 4; size += df->reg_size; + if (size < max_reg_num ()) + size = max_reg_num (); df->regs = (struct reg_info *) xrealloc (df->regs, size * sizeof (struct reg_info)); @@ -892,7 +897,11 @@ df_ref_record (df, reg, loc, insn, ref_type, ref_flags) are really referenced. E.g. a (subreg:SI (reg:DI 0) 0) does _not_ reference the whole reg 0 in DI mode (which would also include reg 1, at least, if 0 and 1 are SImode registers). */ - endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg)); + endregno = HARD_REGNO_NREGS (regno, GET_MODE (reg)); + if (GET_CODE (reg) == SUBREG) + regno += subreg_regno_offset (regno, GET_MODE (SUBREG_REG (reg)), + SUBREG_BYTE (reg), GET_MODE (reg)); + endregno += regno; for (i = regno; i < endregno; i++) df_ref_record_1 (df, regno_reg_rtx[i], @@ -904,18 +913,23 @@ df_ref_record (df, reg, loc, insn, ref_type, ref_flags) } } -/* Writes to SUBREG of inndermode wider than word and outermode shorter than - word are read-modify-write. */ +/* Writes to paradoxical subregs, or subregs which are too narrow + are read-modify-write. */ static inline bool read_modify_subreg_p (x) rtx x; { + unsigned int isize, osize; if (GET_CODE (x) != SUBREG) return false; - if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) <= UNITS_PER_WORD) + isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))); + osize = GET_MODE_SIZE (GET_MODE (x)); + if (isize <= osize) + return true; + if (isize <= UNITS_PER_WORD) return false; - if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) + if (osize >= UNITS_PER_WORD) return false; return true; } @@ -943,6 +957,13 @@ df_def_record_1 (df, x, bb, insn) return; } +#ifdef CLASS_CANNOT_CHANGE_MODE + if (GET_CODE (dst) == SUBREG + && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst), + GET_MODE (SUBREG_REG (dst)))) + flags |= DF_REF_MODE_CHANGE; +#endif + /* May be, we should flag the use of strict_low_part somehow. Might be handy for the reg allocator. */ while (GET_CODE (dst) == STRICT_LOW_PART @@ -957,6 +978,12 @@ df_def_record_1 (df, x, bb, insn) loc = &XEXP (dst, 0); dst = *loc; } +#ifdef CLASS_CANNOT_CHANGE_MODE + if (GET_CODE (dst) == SUBREG + && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst), + GET_MODE (SUBREG_REG (dst)))) + flags |= DF_REF_MODE_CHANGE; +#endif loc = &XEXP (dst, 0); dst = *loc; flags |= DF_REF_READ_WRITE; @@ -1052,6 +1079,11 @@ df_uses_record (df, loc, ref_type, bb, insn, flags) df_uses_record (df, loc, ref_type, bb, insn, flags); return; } +#ifdef CLASS_CANNOT_CHANGE_MODE + if (CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (x), + GET_MODE (SUBREG_REG (x)))) + flags |= DF_REF_MODE_CHANGE; +#endif /* ... Fall through ... */ @@ -1068,16 +1100,24 @@ df_uses_record (df, loc, ref_type, bb, insn, flags) switch (GET_CODE (dst)) { + enum df_ref_flags use_flags; case SUBREG: if (read_modify_subreg_p (dst)) { + use_flags = DF_REF_READ_WRITE; +#ifdef CLASS_CANNOT_CHANGE_MODE + if (CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst), + GET_MODE (SUBREG_REG (dst)))) + use_flags |= DF_REF_MODE_CHANGE; +#endif df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb, - insn, DF_REF_READ_WRITE); + insn, use_flags); break; } /* ... FALLTHRU ... */ case REG: case PC: + case PARALLEL: break; case MEM: df_uses_record (df, &XEXP (dst, 0), @@ -1089,8 +1129,14 @@ df_uses_record (df, loc, ref_type, bb, insn, flags) dst = XEXP (dst, 0); if (GET_CODE (dst) != SUBREG) abort (); + use_flags = DF_REF_READ_WRITE; +#ifdef CLASS_CANNOT_CHANGE_MODE + if (CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst), + GET_MODE (SUBREG_REG (dst)))) + use_flags |= DF_REF_MODE_CHANGE; +#endif df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb, - insn, DF_REF_READ_WRITE); + insn, use_flags); break; case ZERO_EXTRACT: case SIGN_EXTRACT: @@ -1345,6 +1391,11 @@ df_bb_reg_def_chain_create (df, bb) { struct ref *def = link->ref; unsigned int dregno = DF_REF_REGNO (def); + /* Don't add ref's to the chain two times. I.e. only add + new refs. XXX the same could be done by testing if the current + insn is a modified (or a new) one. This would be faster. */ + if (DF_REF_ID (def) < df->def_id_save) + continue; df->regs[dregno].defs = df_link_create (def, df->regs[dregno].defs); @@ -1394,6 +1445,11 @@ df_bb_reg_use_chain_create (df, bb) { struct ref *use = link->ref; unsigned int uregno = DF_REF_REGNO (use); + /* Don't add ref's to the chain two times. I.e. only add + new refs. XXX the same could be done by testing if the current + insn is a modified (or a new) one. This would be faster. */ + if (DF_REF_ID (use) < df->use_id_save) + continue; df->regs[uregno].uses = df_link_create (use, df->regs[uregno].uses); @@ -2218,8 +2274,6 @@ df_bb_refs_update (df, bb) /* Scan the insn for refs. */ df_insn_refs_record (df, bb, insn); - - bitmap_clear_bit (df->insns_modified, uid); count++; } if (insn == bb->end) @@ -2318,6 +2372,7 @@ df_analyse (df, blocks, flags) df_analyse_1 (df, blocks, flags, 1); bitmap_zero (df->bbs_modified); + bitmap_zero (df->insns_modified); } } return update; @@ -2445,9 +2500,8 @@ df_insn_modify (df, bb, insn) unsigned int uid; uid = INSN_UID (insn); - if (uid >= df->insn_size) - df_insn_table_realloc (df, 0); + df_insn_table_realloc (df, uid); bitmap_set_bit (df->bbs_modified, bb->index); bitmap_set_bit (df->insns_modified, uid); @@ -2734,7 +2788,7 @@ df_insns_modify (df, bb, first_insn, last_insn) uid = INSN_UID (insn); if (uid >= df->insn_size) - df_insn_table_realloc (df, 0); + df_insn_table_realloc (df, uid); df_insn_modify (df, bb, insn);