From a5628378163028b24ef0e4472f98becc5aa96731 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Sat, 25 Feb 2012 12:09:41 +0000 Subject: [PATCH] re PR debug/52001 (Huge compile-time regression with var-tracking) PR debug/52001 * alias.c (refs_newer_value_cb, refs_newer_value_p): New. (get_addr): Walk canonical value's locs. Avoid returning VALUEs and locs that reference values newer than the non-canonical value at hand. Return the canonical value as a worst case. (memrefs_conflict_p): Walk canonical value's locs. From-SVN: r184572 --- gcc/ChangeLog | 7 +++++++ gcc/alias.c | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4a2c9fb6c2f..5dfe71f3c2f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2012-02-25 Alexandre Oliva + PR debug/52001 + * alias.c (refs_newer_value_cb, refs_newer_value_p): New. + (get_addr): Walk canonical value's locs. Avoid returning VALUEs + and locs that reference values newer than the non-canonical value + at hand. Return the canonical value as a worst case. + (memrefs_conflict_p): Walk canonical value's locs. + PR debug/52001 * cselib.c (preserve_only_constants): Rename to... (preserve_constants_and_equivs): ... this. Split out... diff --git a/gcc/alias.c b/gcc/alias.c index b9b9676b173..4bda40d8836 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -1773,6 +1773,29 @@ base_alias_check (rtx x, rtx y, enum machine_mode x_mode, return 1; } +/* Callback for for_each_rtx, that returns 1 upon encountering a VALUE + whose UID is greater than the int uid that D points to. */ + +static int +refs_newer_value_cb (rtx *x, void *d) +{ + if (GET_CODE (*x) == VALUE && CSELIB_VAL_PTR (*x)->uid > *(int *)d) + return 1; + + return 0; +} + +/* Return TRUE if EXPR refers to a VALUE whose uid is greater than + that of V. */ + +static bool +refs_newer_value_p (rtx expr, rtx v) +{ + int minuid = CSELIB_VAL_PTR (v)->uid; + + return for_each_rtx (&expr, refs_newer_value_cb, &minuid); +} + /* Convert the address X into something we can use. This is done by returning it unchanged unless it is a value; in the latter case we call cselib to get a more useful rtx. */ @@ -1788,14 +1811,20 @@ get_addr (rtx x) v = CSELIB_VAL_PTR (x); if (v) { + v = canonical_cselib_val (v); for (l = v->locs; l; l = l->next) if (CONSTANT_P (l->loc)) return l->loc; for (l = v->locs; l; l = l->next) - if (!REG_P (l->loc) && !MEM_P (l->loc)) + if (!REG_P (l->loc) && !MEM_P (l->loc) && GET_CODE (l->loc) != VALUE + && !refs_newer_value_p (l->loc, x)) return l->loc; - if (v->locs) - return v->locs->loc; + for (l = v->locs; l; l = l->next) + if (REG_P (l->loc) || (GET_CODE (l->loc) != VALUE + && !refs_newer_value_p (l->loc, x))) + return l->loc; + /* Return the canonical value. */ + return v->val_rtx; } return x; } @@ -1873,7 +1902,8 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c) { struct elt_loc_list *l = NULL; if (CSELIB_VAL_PTR (x)) - for (l = CSELIB_VAL_PTR (x)->locs; l; l = l->next) + for (l = canonical_cselib_val (CSELIB_VAL_PTR (x))->locs; + l; l = l->next) if (REG_P (l->loc) && rtx_equal_for_memref_p (l->loc, y)) break; if (l) @@ -1891,7 +1921,8 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c) { struct elt_loc_list *l = NULL; if (CSELIB_VAL_PTR (y)) - for (l = CSELIB_VAL_PTR (y)->locs; l; l = l->next) + for (l = canonical_cselib_val (CSELIB_VAL_PTR (y))->locs; + l; l = l->next) if (REG_P (l->loc) && rtx_equal_for_memref_p (l->loc, x)) break; if (l)