diff options
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/df.c | 36 | ||||
-rw-r--r-- | gcc/df.h | 11 | ||||
-rw-r--r-- | gcc/ra-build.c | 17 | ||||
-rw-r--r-- | gcc/ra-colorize.c | 10 | ||||
-rw-r--r-- | gcc/ra.c | 20 | ||||
-rw-r--r-- | gcc/ra.h | 7 |
7 files changed, 79 insertions, 40 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4d90245bf0d..1debc6929a1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2003-03-07 Michael Matz <matz@suse.de> + + * df.h (enum df_ref_flags.DF_REF_STRIPPED): New. + (DF_FOR_REGALLOC): New. + * df.c (df_ref_record): Set DF_REF_STRIPPED. + (read_modify_subreg_p): Simplify. + (df_def_record_1, df_uses_record): Set DF_REF_MODE_CHANGE more often. + Use DF_FOR_REGALLOC. + * ra.h (struct web): New member subreg_stripped. + (invalid_mode_change_regs): Declare. + * ra.c (invalid_mode_change_regs): New. + (init_ra): Initialize it. + * ra-build.c (init_one_web_common, remember_web_was_spilled): Use it. + Use CANNOT_CHANGE_MODE_CLASS as ifdef guard. + (reinit_one_web, parts_to_web_1): Deal with subreg_stripped. + * ra-colorize.c (colorize_one_web): Use invalid_mode_change_regs. + Use CANNOT_CHANGE_MODE_CLASS as ifdef guard. + 2003-03-07 Richard Earnshaw <rearnsha@arm.com> * arm.md (addsf3, adddf3, subsf3, subdf3, mulsf3, muldf3, negsf2) @@ -849,6 +849,7 @@ df_ref_record (df, reg, loc, insn, ref_type, ref_flags) { loc = &SUBREG_REG (reg); reg = *loc; + ref_flags |= DF_REF_STRIPPED; } regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg); @@ -893,13 +894,8 @@ read_modify_subreg_p (x) return false; 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 (osize > UNITS_PER_WORD) - return false; - return true; + /* Paradoxical subreg writes don't leave a trace of the old content. */ + return (isize > osize && isize > UNITS_PER_WORD); } @@ -927,9 +923,7 @@ df_def_record_1 (df, x, bb, insn) } #ifdef CLASS_CANNOT_CHANGE_MODE - if (GET_CODE (dst) == SUBREG - && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (dst)), - GET_MODE (dst))) + if (GET_CODE (dst) == SUBREG) flags |= DF_REF_MODE_CHANGE; #endif @@ -938,7 +932,8 @@ df_def_record_1 (df, x, bb, insn) while (GET_CODE (dst) == STRICT_LOW_PART || GET_CODE (dst) == ZERO_EXTRACT || GET_CODE (dst) == SIGN_EXTRACT - || read_modify_subreg_p (dst)) + || ((df->flags & DF_FOR_REGALLOC) == 0 + && read_modify_subreg_p (dst))) { /* Strict low part always contains SUBREG, but we do not want to make it appear outside, as whole register is always considered. */ @@ -948,9 +943,7 @@ df_def_record_1 (df, x, bb, insn) dst = *loc; } #ifdef CLASS_CANNOT_CHANGE_MODE - if (GET_CODE (dst) == SUBREG - && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (dst)), - GET_MODE (dst))) + if (GET_CODE (dst) == SUBREG) flags |= DF_REF_MODE_CHANGE; #endif loc = &XEXP (dst, 0); @@ -1050,9 +1043,7 @@ 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; + flags |= DF_REF_MODE_CHANGE; #endif /* ... Fall through ... */ @@ -1072,13 +1063,12 @@ df_uses_record (df, loc, ref_type, bb, insn, flags) { enum df_ref_flags use_flags; case SUBREG: - if (read_modify_subreg_p (dst)) + if ((df->flags & DF_FOR_REGALLOC) == 0 + && 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; + use_flags |= DF_REF_MODE_CHANGE; #endif df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb, insn, use_flags); @@ -1102,9 +1092,7 @@ df_uses_record (df, loc, ref_type, bb, insn, flags) 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; + use_flags |= DF_REF_MODE_CHANGE; #endif df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb, insn, use_flags); @@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #define DF_ALL 255 #define DF_HARD_REGS 1024 /* Mark hard registers. */ #define DF_EQUIV_NOTES 2048 /* Mark uses present in EQUIV/EQUAL notes. */ +#define DF_FOR_REGALLOC 4096 /* If called for the register allocator. */ enum df_ref_type {DF_REF_REG_DEF, DF_REF_REG_USE, DF_REF_REG_MEM_LOAD, DF_REF_REG_MEM_STORE}; @@ -52,13 +53,17 @@ enum df_ref_flags DF_REF_READ_WRITE = 1, /* This flag is set on register references inside a subreg on - machines which have CLASS_CANNOT_CHANGE_MODE and where the mode - change of that subreg expression is invalid for this class. + machines which have CANNOT_CHANGE_MODE_CLASS. Note, that this flag can also be set on df_refs representing the REG itself (i.e., one might not see the subreg anyore). Also note, that this flag is set also for hardreg refs, i.e., you must check yourself if it's a pseudo. */ - DF_REF_MODE_CHANGE = 2 + DF_REF_MODE_CHANGE = 2, + + /* This flag is set, if we stripped the subreg from the reference. + In this case we must make conservative guesses, at what the + outer mode was. */ + DF_REF_STRIPPED = 4 }; diff --git a/gcc/ra-build.c b/gcc/ra-build.c index 4448065de0d..37ca30c7994 100644 --- a/gcc/ra-build.c +++ b/gcc/ra-build.c @@ -1305,10 +1305,9 @@ init_one_web_common (web, reg) AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors); prune_hardregs_for_mode (&web->usable_regs, PSEUDO_REGNO_MODE (web->regno)); -#ifdef CLASS_CANNOT_CHANGE_MODE +#ifdef CANNOT_CHANGE_MODE_CLASS if (web->mode_changed) - AND_COMPL_HARD_REG_SET (web->usable_regs, reg_class_contents[ - (int) CLASS_CANNOT_CHANGE_MODE]); + AND_COMPL_HARD_REG_SET (web->usable_regs, invalid_mode_change_regs); #endif web->num_freedom = hard_regs_count (web->usable_regs); web->num_freedom -= web->add_hardregs; @@ -1351,6 +1350,7 @@ reinit_one_web (web, reg) web->artificial = 0; web->live_over_abnormal = 0; web->mode_changed = 0; + web->subreg_stripped = 0; web->move_related = 0; web->in_load = 0; web->target_of_spilled_move = 0; @@ -1912,6 +1912,9 @@ parts_to_webs_1 (df, copy_webs, all_refs) if ((DF_REF_FLAGS (ref) & DF_REF_MODE_CHANGE) != 0 && web->regno >= FIRST_PSEUDO_REGISTER) web->mode_changed = 1; + if ((DF_REF_FLAGS (ref) & DF_REF_STRIPPED) != 0 + && web->regno >= FIRST_PSEUDO_REGISTER) + web->subreg_stripped = 1; if (i >= def_id && TEST_BIT (live_over_abnormal, ref_id)) web->live_over_abnormal = 1; @@ -1961,6 +1964,9 @@ parts_to_webs_1 (df, copy_webs, all_refs) if ((DF_REF_FLAGS (ref) & DF_REF_MODE_CHANGE) != 0 && web->regno >= FIRST_PSEUDO_REGISTER) web->mode_changed = 1; + if ((DF_REF_FLAGS (ref) & DF_REF_STRIPPED) != 0 + && web->regno >= FIRST_PSEUDO_REGISTER) + web->subreg_stripped = 1; /* Setup def2web, or use2web, and increment num_defs or num_uses. */ if (i < def_id) @@ -2364,10 +2370,9 @@ remember_web_was_spilled (web) reg_class_contents[(int) GENERAL_REGS]); AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors); prune_hardregs_for_mode (&web->usable_regs, PSEUDO_REGNO_MODE (web->regno)); -#ifdef CLASS_CANNOT_CHANGE_MODE +#ifdef CANNOT_CHANGE_MODE_CLASS if (web->mode_changed) - AND_COMPL_HARD_REG_SET (web->usable_regs, reg_class_contents[ - (int) CLASS_CANNOT_CHANGE_MODE]); + AND_COMPL_HARD_REG_SET (web->usable_regs, invalid_mode_change_regs); #endif web->num_freedom = hard_regs_count (web->usable_regs); if (!web->num_freedom) diff --git a/gcc/ra-colorize.c b/gcc/ra-colorize.c index 359dfd86126..6c514df1c4e 100644 --- a/gcc/ra-colorize.c +++ b/gcc/ra-colorize.c @@ -1370,10 +1370,9 @@ colorize_one_web (web, hard) else COPY_HARD_REG_SET (colors, usable_regs[reg_preferred_class (web->regno)]); -#ifdef CLASS_CANNOT_CHANGE_MODE +#ifdef CANNOT_CHANGE_MODE_CLASS if (web->mode_changed) - AND_COMPL_HARD_REG_SET (colors, reg_class_contents[ - (int) CLASS_CANNOT_CHANGE_MODE]); + AND_COMPL_HARD_REG_SET (colors, invalid_mode_change_regs); #endif COPY_HARD_REG_SET (call_clobbered, colors); AND_HARD_REG_SET (call_clobbered, call_used_reg_set); @@ -1404,10 +1403,9 @@ colorize_one_web (web, hard) else IOR_HARD_REG_SET (colors, usable_regs [reg_alternate_class (web->regno)]); -#ifdef CLASS_CANNOT_CHANGE_MODE +#ifdef CANNOT_CHANGE_MODE_CLASS if (web->mode_changed) - AND_COMPL_HARD_REG_SET (colors, reg_class_contents[ - (int) CLASS_CANNOT_CHANGE_MODE]); + AND_COMPL_HARD_REG_SET (colors, invalid_mode_change_regs); #endif COPY_HARD_REG_SET (call_clobbered, colors); AND_HARD_REG_SET (call_clobbered, call_used_reg_set); @@ -148,6 +148,7 @@ HARD_REG_SET never_use_colors; HARD_REG_SET usable_regs[N_REG_CLASSES]; unsigned int num_free_regs[N_REG_CLASSES]; HARD_REG_SET hardregs_for_mode[NUM_MACHINE_MODES]; +HARD_REG_SET invalid_mode_change_regs; unsigned char byte2bitcount[256]; unsigned int debug_new_regalloc = -1; @@ -555,6 +556,23 @@ init_ra () COPY_HARD_REG_SET (hardregs_for_mode[i], rs); } + CLEAR_HARD_REG_SET (invalid_mode_change_regs); +#ifdef CANNOT_CHANGE_MODE_CLASS + if (0) + for (i = 0; i < NUM_MACHINE_MODES; i++) + { + enum machine_mode from = (enum machine_mode) i; + enum machine_mode to; + for (to = VOIDmode; to < MAX_MACHINE_MODE; ++to) + { + int r; + for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) + if (REG_CANNOT_CHANGE_MODE_P (from, to, r)) + SET_HARD_REG_BIT (invalid_mode_change_regs, r); + } + } +#endif + for (an_unusable_color = 0; an_unusable_color < FIRST_PSEUDO_REGISTER; an_unusable_color++) if (TEST_HARD_REG_BIT (never_use_colors, an_unusable_color)) @@ -755,7 +773,7 @@ reg_alloc () chains per insn, and per regno. In later passes only update that info from the new and modified insns. */ df_analyse (df, (ra_pass == 1) ? 0 : (bitmap) -1, - DF_HARD_REGS | DF_RD_CHAIN | DF_RU_CHAIN); + DF_HARD_REGS | DF_RD_CHAIN | DF_RU_CHAIN | DF_FOR_REGALLOC); if ((debug_new_regalloc & DUMP_DF) != 0) { @@ -168,6 +168,11 @@ struct web was illegal for hardregs in CLASS_CANNOT_CHANGE_MODE. */ unsigned int mode_changed:1; + /* Nonzero if some references of this web, where in subreg context, + but the actual subreg is already stripped (i.e. we don't know the + outer mode of the actual reference). */ + unsigned int subreg_stripped:1; + /* Nonzero, when this web stems from the last pass of the allocator, and all info is still valid (i.e. it wasn't spilled). */ unsigned int old_web:1; @@ -497,6 +502,8 @@ extern unsigned int num_free_regs[N_REG_CLASSES]; represent the possible resources which could be taken away be a value in mode M. */ extern HARD_REG_SET hardregs_for_mode[NUM_MACHINE_MODES]; +/* The set of hardregs, for which _any_ mode change is invalid. */ +extern HARD_REG_SET invalid_mode_change_regs; /* For 0 <= I <= 255, the number of bits set in I. Used to calculate the number of set bits in a HARD_REG_SET. */ extern unsigned char byte2bitcount[256]; |