diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2007-02-01 01:09:35 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2007-02-01 01:09:35 +0000 |
commit | e53a16e75f3cbaaa46e5ce2fc1ed449a18eef7d9 (patch) | |
tree | ef18ae23759d8cebf30524fd23a40023979adb9e /gcc/regclass.c | |
parent | 15c48c45f552564d65a3cc869b2a8f896492f05f (diff) | |
download | gcc-e53a16e75f3cbaaa46e5ce2fc1ed449a18eef7d9.zip gcc-e53a16e75f3cbaaa46e5ce2fc1ed449a18eef7d9.tar.gz gcc-e53a16e75f3cbaaa46e5ce2fc1ed449a18eef7d9.tar.bz2 |
lower-subreg.c: New file.
gcc/:
* lower-subreg.c: New file.
* rtl.def (CONCATN): Define.
* passes.c (init_optimization_passes): Add pass_lower_subreg and
pass_lower_subreg2.
* emit-rtl.c (update_reg_offset): New static function, broken out
of gen_rtx_REG_offset.
(gen_rtx_REG_offset): Call update_reg_offset.
(gen_reg_rtx_offset): New function.
* regclass.c: Revert patch of 2006-03-05, restoring
reg_scan_update.
(clear_reg_info_regno): New function.
* dwarf2out.c (concatn_loc_descriptor): New static function.
(loc_descriptor): Handle CONCATN.
* common.opt (fsplit_wide_types): New option.
* opts.c (decode_options): Set flag_split_wide_types when
optimizing.
* timevar.def (TV_LOWER_SUBREG): Define.
* rtl.h (gen_reg_rtx_offset): Declare.
(reg_scan_update): Declare.
* regs.h (clear_reg_info_regno): Declare.
* tree-pass.h (pass_lower_subreg): Declare.
(pass_lower_subreg2): Declare.
* doc/invoke.texi (Option Summary): List -fno-split-wide-types.
(Optimize Options): Add -fsplit-wide-types to -O1 list. Document
-fsplit-wide-types.
* doc/rtl.texi (Regs and Memory): Document concat and concatn.
* Makefile.in (OBJS-common): Add lower-subreg.o.
(lower-subreg.o): New target.
gcc/testsuite/:
* gcc.dg/lower-subreg-1.c (test): New test.
From-SVN: r121453
Diffstat (limited to 'gcc/regclass.c')
-rw-r--r-- | gcc/regclass.c | 82 |
1 files changed, 64 insertions, 18 deletions
diff --git a/gcc/regclass.c b/gcc/regclass.c index 7726ea1..0a1114d 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -1,6 +1,6 @@ /* Compute register class preferences for pseudo-registers. Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996 - 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GCC. @@ -859,7 +859,7 @@ static void record_address_regs (enum machine_mode, rtx, int, enum rtx_code, #ifdef FORBIDDEN_INC_DEC_CLASSES static int auto_inc_dec_reg_p (rtx, enum machine_mode); #endif -static void reg_scan_mark_refs (rtx, rtx, int); +static void reg_scan_mark_refs (rtx, rtx, int, unsigned int); /* Wrapper around REGNO_OK_FOR_INDEX_P, to allow pseudo registers. */ @@ -2292,6 +2292,14 @@ free_reg_info (void) regno_allocated = 0; reg_n_max = 0; } + +/* Clear the information stored for REGNO. */ +void +clear_reg_info_regno (unsigned int regno) +{ + if (regno < regno_allocated) + memset (VEC_index (reg_info_p, reg_n_info, regno), 0, sizeof (reg_info)); +} /* This is the `regscan' pass of the compiler, run just before cse and again just before loop. @@ -2333,10 +2341,10 @@ reg_scan (rtx f, unsigned int nregs) if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) > max_parallel) max_parallel = XVECLEN (pat, 0); - reg_scan_mark_refs (pat, insn, 0); + reg_scan_mark_refs (pat, insn, 0, 0); if (REG_NOTES (insn)) - reg_scan_mark_refs (REG_NOTES (insn), insn, 1); + reg_scan_mark_refs (REG_NOTES (insn), insn, 1, 0); } max_parallel += max_set_parallel; @@ -2344,11 +2352,39 @@ reg_scan (rtx f, unsigned int nregs) timevar_pop (TV_REG_SCAN); } +/* Update 'regscan' information by looking at the insns + from FIRST to LAST. Some new REGs have been created, + and any REG with number greater than OLD_MAX_REGNO is + such a REG. We only update information for those. */ + +void +reg_scan_update (rtx first, rtx last, unsigned int old_max_regno) +{ + rtx insn; + + allocate_reg_info (max_reg_num (), FALSE, FALSE); + + for (insn = first; insn != last; insn = NEXT_INSN (insn)) + if (INSN_P (insn)) + { + rtx pat = PATTERN (insn); + if (GET_CODE (pat) == PARALLEL + && XVECLEN (pat, 0) > max_parallel) + max_parallel = XVECLEN (pat, 0); + reg_scan_mark_refs (pat, insn, 0, old_max_regno); + + if (REG_NOTES (insn)) + reg_scan_mark_refs (REG_NOTES (insn), insn, 1, old_max_regno); + } +} + /* X is the expression to scan. INSN is the insn it appears in. - NOTE_FLAG is nonzero if X is from INSN's notes rather than its body. */ + NOTE_FLAG is nonzero if X is from INSN's notes rather than its body. + We should only record information for REGs with numbers + greater than or equal to MIN_REGNO. */ static void -reg_scan_mark_refs (rtx x, rtx insn, int note_flag) +reg_scan_mark_refs (rtx x, rtx insn, int note_flag, unsigned int min_regno) { enum rtx_code code; rtx dest; @@ -2375,35 +2411,43 @@ reg_scan_mark_refs (rtx x, rtx insn, int note_flag) { unsigned int regno = REGNO (x); - if (!note_flag) - REGNO_LAST_UID (regno) = INSN_UID (insn); - if (REGNO_FIRST_UID (regno) == 0) - REGNO_FIRST_UID (regno) = INSN_UID (insn); + if (regno >= min_regno) + { + if (!note_flag) + REGNO_LAST_UID (regno) = INSN_UID (insn); + if (REGNO_FIRST_UID (regno) == 0) + REGNO_FIRST_UID (regno) = INSN_UID (insn); + /* If we are called by reg_scan_update() (indicated by min_regno + being set), we also need to update the reference count. */ + if (min_regno) + REG_N_REFS (regno)++; + } } break; case EXPR_LIST: if (XEXP (x, 0)) - reg_scan_mark_refs (XEXP (x, 0), insn, note_flag); + reg_scan_mark_refs (XEXP (x, 0), insn, note_flag, min_regno); if (XEXP (x, 1)) - reg_scan_mark_refs (XEXP (x, 1), insn, note_flag); + reg_scan_mark_refs (XEXP (x, 1), insn, note_flag, min_regno); break; case INSN_LIST: if (XEXP (x, 1)) - reg_scan_mark_refs (XEXP (x, 1), insn, note_flag); + reg_scan_mark_refs (XEXP (x, 1), insn, note_flag, min_regno); break; case CLOBBER: { rtx reg = XEXP (x, 0); - if (REG_P (reg)) + if (REG_P (reg) + && REGNO (reg) >= min_regno) { REG_N_SETS (REGNO (reg))++; REG_N_REFS (REGNO (reg))++; } else if (MEM_P (reg)) - reg_scan_mark_refs (XEXP (reg, 0), insn, note_flag); + reg_scan_mark_refs (XEXP (reg, 0), insn, note_flag, min_regno); } break; @@ -2420,7 +2464,8 @@ reg_scan_mark_refs (rtx x, rtx insn, int note_flag) if (GET_CODE (dest) == PARALLEL) max_set_parallel = MAX (max_set_parallel, XVECLEN (dest, 0) - 1); - if (REG_P (dest)) + if (REG_P (dest) + && REGNO (dest) >= min_regno) { REG_N_SETS (REGNO (dest))++; REG_N_REFS (REGNO (dest))++; @@ -2440,6 +2485,7 @@ reg_scan_mark_refs (rtx x, rtx insn, int note_flag) if (REG_P (SET_DEST (x)) && REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER + && REGNO (SET_DEST (x)) >= min_regno /* If the destination pseudo is set more than once, then other sets might not be to a pointer value (consider access to a union in two threads of control in the presence of global @@ -2500,12 +2546,12 @@ reg_scan_mark_refs (rtx x, rtx insn, int note_flag) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') - reg_scan_mark_refs (XEXP (x, i), insn, note_flag); + reg_scan_mark_refs (XEXP (x, i), insn, note_flag, min_regno); else if (fmt[i] == 'E' && XVEC (x, i) != 0) { int j; for (j = XVECLEN (x, i) - 1; j >= 0; j--) - reg_scan_mark_refs (XVECEXP (x, i, j), insn, note_flag); + reg_scan_mark_refs (XVECEXP (x, i, j), insn, note_flag, min_regno); } } } |