aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2012-03-01 16:58:11 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2012-03-01 16:58:11 +0000
commit0f68ba3ea390e3b71320cc3bf70deedbb9534223 (patch)
treec2c1bae2d077b418073a5806f3512ee632e4b466
parent2aceddd8fc0fa80fffd5a6eca0745895b95011e1 (diff)
downloadgcc-0f68ba3ea390e3b71320cc3bf70deedbb9534223.zip
gcc-0f68ba3ea390e3b71320cc3bf70deedbb9534223.tar.gz
gcc-0f68ba3ea390e3b71320cc3bf70deedbb9534223.tar.bz2
re PR debug/52001 (Huge compile-time regression with var-tracking)
PR debug/52001 PR rtl-optimization/52417 * cselib.c (cselib_any_perm_equivs): New variable. (cselib_reset_table): Check that it's not set when not preserving constants. (cselib_add_permanent_equiv): Set it. (cselib_have_permanent_equivalences): New. (cselib_init, cselib_finish): Reset it. * cselib.h (cselib_have_permanent_equivalences): Declare. * alias.c (get_addr): Restore earlier behavior when there aren't permanent equivalences. From-SVN: r184750
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/alias.c32
-rw-r--r--gcc/cselib.c18
-rw-r--r--gcc/cselib.h1
4 files changed, 55 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c18b261..805e359 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+2012-03-01 Alexandre Oliva <aoliva@redhat.com>
+
+ PR debug/52001
+ PR rtl-optimization/52417
+ * cselib.c (cselib_any_perm_equivs): New variable.
+ (cselib_reset_table): Check that it's not set when not
+ preserving constants.
+ (cselib_add_permanent_equiv): Set it.
+ (cselib_have_permanent_equivalences): New.
+ (cselib_init, cselib_finish): Reset it.
+ * cselib.h (cselib_have_permanent_equivalences): Declare.
+ * alias.c (get_addr): Restore earlier behavior when there
+ aren't permanent equivalences.
+
2012-03-01 Steven Bosscher <steven@gcc.gnu.org>
* config/mn10300/mn10300-modes.def: Fix copyright notice.
diff --git a/gcc/alias.c b/gcc/alias.c
index 4bda40d..e9d701f 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -1811,20 +1811,34 @@ get_addr (rtx x)
v = CSELIB_VAL_PTR (x);
if (v)
{
- v = canonical_cselib_val (v);
+ bool have_equivs = cselib_have_permanent_equivalences ();
+ if (have_equivs)
+ 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) && GET_CODE (l->loc) != VALUE
- && !refs_newer_value_p (l->loc, x))
+ if (!REG_P (l->loc) && !MEM_P (l->loc)
+ /* Avoid infinite recursion when potentially dealing with
+ var-tracking artificial equivalences, by skipping the
+ equivalences themselves, and not choosing expressions
+ that refer to newer VALUEs. */
+ && (!have_equivs
+ || (GET_CODE (l->loc) != VALUE
+ && !refs_newer_value_p (l->loc, x))))
return l->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;
+ if (have_equivs)
+ {
+ 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;
+ }
+ if (v->locs)
+ return v->locs->loc;
}
return x;
}
diff --git a/gcc/cselib.c b/gcc/cselib.c
index 4985357..56f2b7f 100644
--- a/gcc/cselib.c
+++ b/gcc/cselib.c
@@ -52,6 +52,7 @@ struct elt_list {
static bool cselib_record_memory;
static bool cselib_preserve_constants;
+static bool cselib_any_perm_equivs;
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 *);
@@ -477,7 +478,10 @@ cselib_reset_table (unsigned int num)
if (cselib_preserve_constants)
htab_traverse (cselib_hash_table, preserve_constants_and_equivs, NULL);
else
- htab_empty (cselib_hash_table);
+ {
+ htab_empty (cselib_hash_table);
+ gcc_checking_assert (!cselib_any_perm_equivs);
+ }
n_useless_values = 0;
n_useless_debug_values = 0;
@@ -2388,6 +2392,8 @@ cselib_add_permanent_equiv (cselib_val *elt, rtx x, rtx insn)
if (nelt != elt)
{
+ cselib_any_perm_equivs = true;
+
if (!PRESERVED_VALUE_P (nelt->val_rtx))
cselib_preserve_value (nelt);
@@ -2397,6 +2403,14 @@ cselib_add_permanent_equiv (cselib_val *elt, rtx x, rtx insn)
cselib_current_insn = save_cselib_current_insn;
}
+/* Return TRUE if any permanent equivalences have been recorded since
+ the table was last initialized. */
+bool
+cselib_have_permanent_equivalences (void)
+{
+ return cselib_any_perm_equivs;
+}
+
/* There is no good way to determine how many elements there can be
in a PARALLEL. Since it's fairly cheap, use a really large number. */
#define MAX_SETS (FIRST_PSEUDO_REGISTER * 2)
@@ -2651,6 +2665,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_any_perm_equivs = false;
/* (mem:BLK (scratch)) is a special mechanism to conflict with everything,
see canon_true_dependence. This is only created once. */
@@ -2684,6 +2699,7 @@ cselib_finish (void)
{
cselib_discard_hook = NULL;
cselib_preserve_constants = false;
+ cselib_any_perm_equivs = false;
cfa_base_preserved_val = NULL;
cfa_base_preserved_regno = INVALID_REGNUM;
free_alloc_pool (elt_list_pool);
diff --git a/gcc/cselib.h b/gcc/cselib.h
index 5b5fe23..96575f9 100644
--- a/gcc/cselib.h
+++ b/gcc/cselib.h
@@ -98,6 +98,7 @@ extern bool cselib_preserved_value_p (cselib_val *);
extern void cselib_preserve_only_values (void);
extern void cselib_preserve_cfa_base_value (cselib_val *, unsigned int);
extern void cselib_add_permanent_equiv (cselib_val *, rtx, rtx);
+extern bool cselib_have_permanent_equivalences (void);
extern void dump_cselib_table (FILE *);