From bab8d9625f4cdeaf9bb45e28ab62abe47c3827f9 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 4 Apr 2020 10:32:41 +0200 Subject: [PATCH] cselib: Don't consider SP_DERIVED_VALUE_P values as useless [PR94468] The following testcase ICEs, because at one point we see the SP_DERIVED_VALUE_P VALUE as useless (not PRESERVED_VALUE_P and no locs) and so expect it to be discarded as useless. But, later on we are adding some new VALUE that is equivalent to it, and when adding the equivalency that that new VALUE is equal to this SP_DERIVED_VALUE_P, new_elt_loc_list has code for VALUE canonicalization and reverses addition if uid is smaller, and at that point a new loc is added to the SP_DERIVED_VALUE_P VALUE and it isn't discarded as useless anymore. Now, I think we don't want to discard the SP_DERIVED_VALUE_P values even if they have no locs, because they still have the special behaviour that they then force other new VALUEs to be canonicalized against them, which is what this patch implements. I've not set PRESERVED_VALUE_P on the SP_DERIVED_VALUE_P at the creation time, because whether a VALUE is preserved or not is something that affects var-tracking decisions quite a lot and we shouldn't set it blindly on other VALUEs. Or, to avoid the repetitive code, should I introduce static bool cselib_useless_value_p (cselib_val *v) { return (v->locs == 0 && !PRESERVED_VALUE_P (v->val_rtx) && !SP_DERIVED_VALUE_P (v->val_rtx))); } predicate and use it in those 6 spots? 2020-04-04 Jakub Jelinek PR rtl-optimization/94468 * cselib.c (references_value_p): Formatting fix. (cselib_useless_value_p): New function. (discard_useless_locs, discard_useless_values, cselib_invalidate_regno_val, cselib_invalidate_mem, cselib_record_set): Use it instead of v->locs == 0 && !PRESERVED_VALUE_P (v->val_rtx). * g++.dg/opt/pr94468.C: New test. --- gcc/ChangeLog | 8 +++++ gcc/cselib.c | 26 +++++++++----- gcc/testsuite/ChangeLog | 3 ++ gcc/testsuite/g++.dg/opt/pr94468.C | 57 ++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr94468.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fdb685a99d1..0221945fe6c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2020-04-04 Jakub Jelinek + PR rtl-optimization/94468 + * cselib.c (references_value_p): Formatting fix. + (cselib_useless_value_p): New function. + (discard_useless_locs, discard_useless_values, + cselib_invalidate_regno_val, cselib_invalidate_mem, + cselib_record_set): Use it instead of + v->locs == 0 && !PRESERVED_VALUE_P (v->val_rtx). + PR debug/94441 * tree-iterator.h (expr_single): Declare. * tree-iterator.c (expr_single): New function. diff --git a/gcc/cselib.c b/gcc/cselib.c index 507898ed1e8..256bd785207 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -629,8 +629,8 @@ references_value_p (const_rtx x, int only_useless) int i, j; if (GET_CODE (x) == VALUE - && (! only_useless || - (CSELIB_VAL_PTR (x)->locs == 0 && !PRESERVED_VALUE_P (x)))) + && (! only_useless + || (CSELIB_VAL_PTR (x)->locs == 0 && !PRESERVED_VALUE_P (x)))) return 1; for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) @@ -646,6 +646,16 @@ references_value_p (const_rtx x, int only_useless) return 0; } +/* Return true if V is a useless VALUE and can be discarded as such. */ + +static bool +cselib_useless_value_p (cselib_val *v) +{ + return (v->locs == 0 + && !PRESERVED_VALUE_P (v->val_rtx) + && !SP_DERIVED_VALUE_P (v->val_rtx)); +} + /* For all locations found in X, delete locations that reference useless values (i.e. values without any location). Called through htab_traverse. */ @@ -666,7 +676,7 @@ discard_useless_locs (cselib_val **x, void *info ATTRIBUTE_UNUSED) p = &(*p)->next; } - if (had_locs && v->locs == 0 && !PRESERVED_VALUE_P (v->val_rtx)) + if (had_locs && cselib_useless_value_p (v)) { if (setting_insn && DEBUG_INSN_P (setting_insn)) n_useless_debug_values++; @@ -684,7 +694,7 @@ discard_useless_values (cselib_val **x, void *info ATTRIBUTE_UNUSED) { cselib_val *v = *x; - if (v->locs == 0 && !PRESERVED_VALUE_P (v->val_rtx)) + if (v->locs == 0 && cselib_useless_value_p (v)) { if (cselib_discard_hook) cselib_discard_hook (v); @@ -2370,7 +2380,7 @@ cselib_invalidate_regno_val (unsigned int regno, struct elt_list **l) } } - if (had_locs && v->locs == 0 && !PRESERVED_VALUE_P (v->val_rtx)) + if (had_locs && cselib_useless_value_p (v)) { if (setting_insn && DEBUG_INSN_P (setting_insn)) n_useless_debug_values++; @@ -2515,7 +2525,7 @@ cselib_invalidate_mem (rtx mem_rtx) unchain_one_elt_loc_list (p); } - if (had_locs && v->locs == 0 && !PRESERVED_VALUE_P (v->val_rtx)) + if (had_locs && cselib_useless_value_p (v)) { if (setting_insn && DEBUG_INSN_P (setting_insn)) n_useless_debug_values++; @@ -2593,14 +2603,14 @@ cselib_record_set (rtx dest, cselib_val *src_elt, cselib_val *dest_addr_elt) REG_VALUES (dreg)->elt = src_elt; } - if (src_elt->locs == 0 && !PRESERVED_VALUE_P (src_elt->val_rtx)) + if (cselib_useless_value_p (src_elt)) n_useless_values--; new_elt_loc_list (src_elt, dest); } else if (MEM_P (dest) && dest_addr_elt != 0 && cselib_record_memory) { - if (src_elt->locs == 0 && !PRESERVED_VALUE_P (src_elt->val_rtx)) + if (cselib_useless_value_p (src_elt)) n_useless_values--; add_mem_for_addr (dest_addr_elt, src_elt, dest); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c08bc0d68f7..427266a877f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2020-04-04 Jakub Jelinek + PR rtl-optimization/94468 + * g++.dg/opt/pr94468.C: New test. + PR debug/94441 * g++.dg/opt/pr94441.C: New test. diff --git a/gcc/testsuite/g++.dg/opt/pr94468.C b/gcc/testsuite/g++.dg/opt/pr94468.C new file mode 100644 index 00000000000..bd3f0b5a2e9 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr94468.C @@ -0,0 +1,57 @@ +// PR rtl-optimization/94468 +// { dg-do compile { target c++11 } } +// { dg-options "-O2" } +// { dg-additional-options "-fPIC" { target fpic } } + +bool a(); +enum b {}; +class c; +template struct d; +template struct d { + typedef e i; +}; +struct j { j(void(int, j *, c *, void **, bool *)) {} }; +template struct m : public j { + l ab; + static void ac(int, j *, c *, void **, bool *); + m(l f) : j(ac), ab(f) {} +}; +b ad; +struct c { + template + void ae(typename d::i *p, n af, typename d::i *ag, o ah) { + ai(p, &af, ag, &ah, new m(ah), ad, &d::i::aj); + } + void ai(c *, void *, c *, void *, j *, b, int *); +}; +struct r : public c { static int aj; void t(); }; +struct al : public c { + static int aj; + void am(); + void ao(); + void ap(); +}; +struct aq { aq(const int &, const int & = int()); }; +struct ar : public c { ~ar(); }; +struct as : public ar { + as(); + void at(); + void au(); + void av(); +}; +struct u : public c { void ax(); }; +struct ay { int az(); }; +struct ba : public c { static int aj; void bb(); }; +struct bc : public al { bc() { if (a()) am(); } }; +as::as() { + al *bd = new bc; + ae(bd, &al::ao, this, &as::au); + ae(bd, &al::ap, this, &as::av); + r be; + u bf; + ae(&be, &r::t, &bf, &u::ax); + c bg = *bd; + ae(static_cast(&bg), &ba::bb, this, &as::at); + ay bh; + aq am(bh.az()); +} -- 2.30.2