From patchwork Fri Sep 10 23:34:50 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Fix VTA sp (and fp) based MEM handling (PR debug/43051, PR debug/43092) From: Alexandre Oliva X-Patchwork-Id: 64478 Message-Id: To: Jakub Jelinek , bernds@codesourcery.com Cc: Richard Guenther , gcc-patches@gcc.gnu.org Date: Fri, 10 Sep 2010 20:34:50 -0300 On Mar 23, 2010, Alexandre Oliva wrote: > On Mar 15, 2010, Jakub Jelinek wrote: >> One is that cselib doesn't handle autoinc rtls well >> (Alex has a follow-up patch in which it teaches cselib about these; this >> final version of the patch doesn't need it for var-tracking though). > Here it is. Regstraped on x86_64-linux-gnu, i686-linux-gnu and > ia64-linux-gnu. Ok to install? In bug 43494, Bernd suggested us to track autoinc always, rather than only within VTA. I implemented that, splitting out the code needed to introduce the explicit selection into a separate patch. I also dropped the _addr renamed functions, and adjusted the few callers that didn't pass a mode for the enclosing MEM. I found out VTA, for reasons I didn't investigate, could somehow do without cselib_invalidate_rtx() for autoinc-modified parameters, but other passes failed without that. I ended up introducing a loop to explicitly invalidate dests of implicit autoinc sets. The first patch implements unconditional autoinc support in cselib. I have regstrapped it on x86_64-linux-gnu and i686-linux-gnu. Ok to install? The second patch makes autoinc support in cselib optional, making some code conditional and conditionally restoring special-case handling that could be removed if autoinc was unconditional. I have *not* completed its regstrap yet. Should I? for gcc/ChangeLog from Alexandre Oliva PR debug/43092 PR debug/43494 * cselib.h (CSELIB_RECORD_AUTOINC): New enumerator. * cselib.c (cselib_record_autoinc): New var. (rtx_equal_for_cselib_1): Test it. (cselib_hash_rtx): Likewise. (cselib_subst_to_values): Likewise. (cselib_record_sets): Likewise. Move autoinc data into conditional. (cselib_init): Initialize cselib_record_autoinc. * var-tracking.c (vt_initialize): Pass CSELIB_RECORD_AUTOINC to cselib_init. Index: gcc/cselib.h =================================================================== --- gcc/cselib.h.orig 2010-09-10 20:24:28.000000000 -0300 +++ gcc/cselib.h 2010-09-10 20:26:34.000000000 -0300 @@ -69,7 +69,8 @@ struct cselib_set enum cselib_record_what { CSELIB_RECORD_MEMORY = 1, - CSELIB_PRESERVE_CONSTANTS = 2 + CSELIB_PRESERVE_CONSTANTS = 2, + CSELIB_RECORD_AUTOINC = 4 }; extern void (*cselib_discard_hook) (cselib_val *); Index: gcc/cselib.c =================================================================== --- gcc/cselib.c.orig 2010-09-10 20:24:28.000000000 -0300 +++ gcc/cselib.c 2010-09-10 20:28:29.000000000 -0300 @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. static bool cselib_record_memory; static bool cselib_preserve_constants; +static bool cselib_record_autoinc; static int entry_and_rtx_equal_p (const void *, const void *); static hashval_t get_value_hash (const void *); static struct elt_list *new_elt_list (struct elt_list *, cselib_val *); @@ -764,6 +765,9 @@ rtx_equal_for_cselib_1 (rtx x, rtx y, en rtx xorig = x, yorig = y; rtx xoff = NULL, yoff = NULL; + if (!cselib_record_autoinc) + return 0; + x = autoinc_split (x, &xoff, memmode); y = autoinc_split (y, &yoff, memmode); @@ -988,6 +992,8 @@ cselib_hash_rtx (rtx x, int create, enum case PRE_DEC: case PRE_INC: /* We can't compute these without knowing the MEM mode. */ + if (!cselib_record_autoinc) + return 0; gcc_assert (memmode != VOIDmode); i = GET_MODE_SIZE (memmode); if (code == PRE_DEC) @@ -998,12 +1004,16 @@ cselib_hash_rtx (rtx x, int create, enum return hash ? hash : 1 + (unsigned) PLUS; case PRE_MODIFY: + if (!cselib_record_autoinc) + return 0; gcc_assert (memmode != VOIDmode); return cselib_hash_rtx (XEXP (x, 1), create, memmode); case POST_DEC: case POST_INC: case POST_MODIFY: + if (!cselib_record_autoinc) + return 0; gcc_assert (memmode != VOIDmode); return cselib_hash_rtx (XEXP (x, 0), create, memmode); @@ -1622,7 +1632,8 @@ cselib_expand_value_rtx_1 (rtx orig, str to registers and memory. X isn't actually modified; if modifications are needed, new rtl is allocated. However, the return value can share rtl with X. - If X is within a MEM, MEMMODE must be the mode of the MEM. */ + If X is within a MEM, MEMMODE must be the mode of the MEM if + cselib_record_autoinc holds. */ rtx cselib_subst_to_values (rtx x, enum machine_mode memmode) @@ -1664,6 +1675,12 @@ cselib_subst_to_values (rtx x, enum mach case PRE_DEC: case PRE_INC: + if (!cselib_record_autoinc) + { + no_autoinc: + e = new_cselib_val (next_uid, GET_MODE (x), x); + return e->val_rtx; + } gcc_assert (memmode != VOIDmode); i = GET_MODE_SIZE (memmode); if (code == PRE_DEC) @@ -1672,12 +1689,16 @@ cselib_subst_to_values (rtx x, enum mach memmode); case PRE_MODIFY: + if (!cselib_record_autoinc) + goto no_autoinc; gcc_assert (memmode != VOIDmode); return cselib_subst_to_values (XEXP (x, 1), memmode); case POST_DEC: case POST_INC: case POST_MODIFY: + if (!cselib_record_autoinc) + goto no_autoinc; gcc_assert (memmode != VOIDmode); return cselib_subst_to_values (XEXP (x, 0), memmode); @@ -2074,6 +2095,13 @@ cselib_invalidate_rtx (rtx dest) cselib_invalidate_regno (REGNO (dest), GET_MODE (dest)); else if (MEM_P (dest)) cselib_invalidate_mem (dest); + + /* Some machines don't define AUTO_INC_DEC, but they still use push + instructions. We need to catch that case here in order to + invalidate the stack pointer correctly. Note that invalidating + the stack pointer is different from invalidating DEST. */ + if (!cselib_record_autoinc && push_operand (dest, GET_MODE (dest))) + cselib_invalidate_rtx (stack_pointer_rtx); } /* A wrapper for cselib_invalidate_rtx to be called via note_stores. */ @@ -2176,7 +2204,6 @@ cselib_record_sets (rtx insn) rtx body = PATTERN (insn); rtx cond = 0; int n_sets_before_autoinc; - struct cselib_record_autoinc_data data; body = PATTERN (insn); if (GET_CODE (body) == COND_EXEC) @@ -2220,10 +2247,16 @@ cselib_record_sets (rtx insn) sets[0].src = XEXP (note, 0); } - data.sets = sets; - data.n_sets = n_sets_before_autoinc = n_sets; - for_each_inc_dec (&insn, cselib_record_autoinc_cb, &data); - n_sets = data.n_sets; + if (cselib_record_autoinc) + { + struct cselib_record_autoinc_data data; + data.sets = sets; + data.n_sets = n_sets_before_autoinc = n_sets; + for_each_inc_dec (&insn, cselib_record_autoinc_cb, &data); + n_sets = data.n_sets; + } + else + n_sets_before_autoinc = n_sets; /* Look up the values that are read. Do this before invalidating the locations that are written. */ @@ -2397,6 +2430,7 @@ cselib_init (int record_what) value_pool = create_alloc_pool ("value", RTX_CODE_SIZE (VALUE), 100); cselib_record_memory = record_what & CSELIB_RECORD_MEMORY; cselib_preserve_constants = record_what & CSELIB_PRESERVE_CONSTANTS; + cselib_record_autoinc = record_what & CSELIB_RECORD_AUTOINC; /* (mem:BLK (scratch)) is a special mechanism to conflict with everything, see canon_true_dependence. This is only created once. */ Index: gcc/var-tracking.c =================================================================== --- gcc/var-tracking.c.orig 2010-09-10 20:24:28.000000000 -0300 +++ gcc/var-tracking.c 2010-09-10 20:26:34.000000000 -0300 @@ -8297,7 +8297,8 @@ vt_initialize (void) if (MAY_HAVE_DEBUG_INSNS) { - cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS); + cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS + | CSELIB_RECORD_AUTOINC); scratch_regs = BITMAP_ALLOC (NULL); valvar_pool = create_alloc_pool ("small variable_def pool", sizeof (struct variable_def), 256);