Mercurial > hg > CbC > CbC_gcc
diff gcc/df-problems.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
line wrap: on
line diff
--- a/gcc/df-problems.c Fri Feb 12 23:41:23 2010 +0900 +++ b/gcc/df-problems.c Mon May 24 12:47:05 2010 +0900 @@ -1,6 +1,6 @@ /* Standard problems for dataflow support routines. Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009 Free Software Foundation, Inc. + 2008, 2009, 2010 Free Software Foundation, Inc. Originally contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz, mhayes@redhat.com) Major rewrite contributed by Danny Berlin (dberlin@dberlin.org) @@ -3403,6 +3403,158 @@ return old; } +/* Node of a linked list of uses of dead REGs in debug insns. */ +struct dead_debug_use +{ + df_ref use; + struct dead_debug_use *next; +}; + +/* Linked list of the above, with a bitmap of the REGs in the + list. */ +struct dead_debug +{ + struct dead_debug_use *head; + bitmap used; + bitmap to_rescan; +}; + +/* Initialize DEBUG to an empty list, and clear USED, if given. */ +static inline void +dead_debug_init (struct dead_debug *debug, bitmap used) +{ + debug->head = NULL; + debug->used = used; + debug->to_rescan = NULL; + if (used) + bitmap_clear (used); +} + +/* Reset all debug insns with pending uses. Release the bitmap in it, + unless it is USED. USED must be the same bitmap passed to + dead_debug_init. */ +static inline void +dead_debug_finish (struct dead_debug *debug, bitmap used) +{ + struct dead_debug_use *head; + rtx insn = NULL; + + if (debug->used != used) + BITMAP_FREE (debug->used); + + while ((head = debug->head)) + { + insn = DF_REF_INSN (head->use); + if (!head->next || DF_REF_INSN (head->next->use) != insn) + { + INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC (); + df_insn_rescan_debug_internal (insn); + if (debug->to_rescan) + bitmap_clear_bit (debug->to_rescan, INSN_UID (insn)); + } + debug->head = head->next; + XDELETE (head); + } + + if (debug->to_rescan) + { + bitmap_iterator bi; + unsigned int uid; + + EXECUTE_IF_SET_IN_BITMAP (debug->to_rescan, 0, uid, bi) + { + struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid); + if (insn_info) + df_insn_rescan (insn_info->insn); + } + BITMAP_FREE (debug->to_rescan); + } +} + +/* Add USE to DEBUG. It must be a dead reference to UREGNO in a debug + insn. Create a bitmap for DEBUG as needed. */ +static inline void +dead_debug_add (struct dead_debug *debug, df_ref use, unsigned int uregno) +{ + struct dead_debug_use *newddu = XNEW (struct dead_debug_use); + + newddu->use = use; + newddu->next = debug->head; + debug->head = newddu; + + if (!debug->used) + debug->used = BITMAP_ALLOC (NULL); + + bitmap_set_bit (debug->used, uregno); +} + +/* If UREGNO is referenced by any entry in DEBUG, emit a debug insn + before INSN that binds the REG to a debug temp, and replace all + uses of UREGNO in DEBUG with uses of the debug temp. INSN must be + the insn where UREGNO dies. */ +static inline void +dead_debug_insert_before (struct dead_debug *debug, unsigned int uregno, + rtx insn) +{ + struct dead_debug_use **tailp = &debug->head; + struct dead_debug_use *cur; + struct dead_debug_use *uses = NULL; + struct dead_debug_use **usesp = &uses; + rtx reg = NULL; + rtx dval; + rtx bind; + + if (!debug->used || !bitmap_clear_bit (debug->used, uregno)) + return; + + /* Move all uses of uregno from debug->head to uses, setting mode to + the widest referenced mode. */ + while ((cur = *tailp)) + { + if (DF_REF_REGNO (cur->use) == uregno) + { + *usesp = cur; + usesp = &cur->next; + *tailp = cur->next; + cur->next = NULL; + if (!reg + || (GET_MODE_BITSIZE (GET_MODE (reg)) + < GET_MODE_BITSIZE (GET_MODE (*DF_REF_REAL_LOC (cur->use))))) + reg = *DF_REF_REAL_LOC (cur->use); + } + else + tailp = &(*tailp)->next; + } + + gcc_assert (reg); + + /* Create DEBUG_EXPR (and DEBUG_EXPR_DECL). */ + dval = make_debug_expr_from_rtl (reg); + + /* Emit a debug bind insn before the insn in which reg dies. */ + bind = gen_rtx_VAR_LOCATION (GET_MODE (reg), + DEBUG_EXPR_TREE_DECL (dval), reg, + VAR_INIT_STATUS_INITIALIZED); + + bind = emit_debug_insn_before (bind, insn); + df_insn_rescan (bind); + + /* Adjust all uses. */ + while ((cur = uses)) + { + if (GET_MODE (*DF_REF_REAL_LOC (cur->use)) == GET_MODE (reg)) + *DF_REF_REAL_LOC (cur->use) = dval; + else + *DF_REF_REAL_LOC (cur->use) + = gen_lowpart_SUBREG (GET_MODE (*DF_REF_REAL_LOC (cur->use)), dval); + /* ??? Should we simplify subreg of subreg? */ + if (debug->to_rescan == NULL) + debug->to_rescan = BITMAP_ALLOC (NULL); + bitmap_set_bit (debug->to_rescan, INSN_UID (DF_REF_INSN (cur->use))); + uses = cur->next; + XDELETE (cur); + } +} /* Recompute the REG_DEAD and REG_UNUSED notes and compute register info: lifetime, bb, and number of defs and uses for basic block @@ -3416,6 +3568,9 @@ rtx insn; df_ref *def_rec; df_ref *use_rec; + struct dead_debug debug; + + dead_debug_init (&debug, NULL); bitmap_copy (live, df_get_live_out (bb)); bitmap_clear (artificial_uses); @@ -3592,9 +3747,15 @@ { if (debug_insn) { - debug_insn = -1; + if (debug_insn > 0) + { + dead_debug_add (&debug, use, uregno); + continue; + } break; } + else + dead_debug_insert_before (&debug, uregno, insn); if ( (!(DF_REF_FLAGS (use) & DF_REF_MW_HARDREG)) && (!bitmap_bit_p (do_not_gen, uregno)) @@ -3636,6 +3797,8 @@ df_insn_rescan_debug_internal (insn); } } + + dead_debug_finish (&debug, NULL); } @@ -3745,9 +3908,22 @@ for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) { df_ref def = *def_rec; - /* If the def is to only part of the reg, it does - not kill the other defs that reach here. */ - if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL))) + bitmap_set_bit (defs, DF_REF_REGNO (def)); + } +} + +/* Find the set of real DEFs, which are not clobbers, for INSN. */ + +void +df_simulate_find_noclobber_defs (rtx insn, bitmap defs) +{ + df_ref *def_rec; + unsigned int uid = INSN_UID (insn); + + for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) + { + df_ref def = *def_rec; + if (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))) bitmap_set_bit (defs, DF_REF_REGNO (def)); } } @@ -3900,13 +4076,9 @@ the block, starting with the first one. ----------------------------------------------------------------------------*/ -/* Apply the artificial uses and defs at the top of BB in a forwards - direction. ??? This is wrong; defs mark the point where a pseudo - becomes live when scanning forwards (unless a def is unused). Since - there are no REG_UNUSED notes for artificial defs, passes that - require artificial defs probably should not call this function - unless (as is the case for fwprop) they are correct when liveness - bitmaps are *under*estimated. */ +/* Initialize the LIVE bitmap, which should be copied from DF_LIVE_IN or + DF_LR_IN for basic block BB, for forward scanning by marking artificial + defs live. */ void df_simulate_initialize_forwards (basic_block bb, bitmap live) @@ -3918,7 +4090,7 @@ { df_ref def = *def_rec; if (DF_REF_FLAGS (def) & DF_REF_AT_TOP) - bitmap_clear_bit (live, DF_REF_REGNO (def)); + bitmap_set_bit (live, DF_REF_REGNO (def)); } } @@ -3939,7 +4111,7 @@ while here the scan is performed forwards! So, first assume that the def is live, and if this is not true REG_UNUSED notes will rectify the situation. */ - df_simulate_find_defs (insn, live); + df_simulate_find_noclobber_defs (insn, live); /* Clear all of the registers that go dead. */ for (link = REG_NOTES (insn); link; link = XEXP (link, 1))