From 53cfcb2e281f62ed8ea272846cf4971f2b0df229 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 14 Dec 2016 20:40:05 +0100 Subject: [PATCH] re PR debug/77844 (Compilation of simple C++ example exhaust memory) PR debug/77844 * valtrack.c: Include rtl-iter.h. (struct rtx_subst_pair): Add insn field. (propagate_for_debug_subst): If pair->to contains at least 2 regs, create a DEBUG_INSN with a debug temp before pair->insn and replace from with the debug temp instead of pair->to. (propagate_for_debug): Initialize p.insn. * combine.c (insn_uid_check): New inline function. (INSN_COST, LOG_LINKS): Use it instead of INSN_UID. (find_single_use, combine_instructions, cant_combine_insn_p, try_combine): Use NONDEBUG_INSN_P instead of INSN_P. * g++.dg/opt/pr77844.C: New test. From-SVN: r243662 --- gcc/ChangeLog | 15 ++++++++++++++ gcc/combine.c | 25 +++++++++++++++-------- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/opt/pr77844.C | 32 ++++++++++++++++++++++++++++++ gcc/valtrack.c | 20 +++++++++++++++++++ 5 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr77844.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b52d9b41a28..259389ee69e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2016-12-14 Jakub Jelinek + + PR debug/77844 + * valtrack.c: Include rtl-iter.h. + (struct rtx_subst_pair): Add insn field. + (propagate_for_debug_subst): If pair->to contains at least 2 + regs, create a DEBUG_INSN with a debug temp before pair->insn + and replace from with the debug temp instead of pair->to. + (propagate_for_debug): Initialize p.insn. + * combine.c (insn_uid_check): New inline function. + (INSN_COST, LOG_LINKS): Use it instead of INSN_UID. + (find_single_use, combine_instructions, + cant_combine_insn_p, try_combine): Use NONDEBUG_INSN_P instead of + INSN_P. + 2016-12-14 Martin Sebor PR c/17308 diff --git a/gcc/combine.c b/gcc/combine.c index 19851a2f64c..473ffc4a132 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -327,8 +327,16 @@ struct insn_link { static struct insn_link **uid_log_links; -#define INSN_COST(INSN) (uid_insn_cost[INSN_UID (INSN)]) -#define LOG_LINKS(INSN) (uid_log_links[INSN_UID (INSN)]) +static inline int +insn_uid_check (const_rtx insn) +{ + int uid = INSN_UID (insn); + gcc_checking_assert (uid <= max_uid_known); + return uid; +} + +#define INSN_COST(INSN) (uid_insn_cost[insn_uid_check (INSN)]) +#define LOG_LINKS(INSN) (uid_log_links[insn_uid_check (INSN)]) #define FOR_EACH_LOG_LINK(L, INSN) \ for ((L) = LOG_LINKS (INSN); (L); (L) = (L)->next) @@ -676,7 +684,7 @@ find_single_use (rtx dest, rtx_insn *insn, rtx_insn **ploc) for (next = NEXT_INSN (insn); next && BLOCK_FOR_INSN (next) == bb; next = NEXT_INSN (next)) - if (INSN_P (next) && dead_or_set_p (next, dest)) + if (NONDEBUG_INSN_P (next) && dead_or_set_p (next, dest)) { FOR_EACH_LOG_LINK (link, next) if (link->insn == insn && link->regno == REGNO (dest)) @@ -1127,7 +1135,7 @@ combine_instructions (rtx_insn *f, unsigned int nregs) int new_direct_jump_p = 0; - for (first = f; first && !INSN_P (first); ) + for (first = f; first && !NONDEBUG_INSN_P (first); ) first = NEXT_INSN (first); if (!first) return 0; @@ -2275,7 +2283,7 @@ cant_combine_insn_p (rtx_insn *insn) /* If this isn't really an insn, we can't do anything. This can occur when flow deletes an insn that it has merged into an auto-increment address. */ - if (! INSN_P (insn)) + if (!NONDEBUG_INSN_P (insn)) return 1; /* Never combine loads and stores involving hard regs that are likely @@ -4178,7 +4186,8 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, || insn != BB_HEAD (this_basic_block->next_bb)); insn = NEXT_INSN (insn)) { - if (INSN_P (insn) && reg_referenced_p (ni2dest, PATTERN (insn))) + if (NONDEBUG_INSN_P (insn) + && reg_referenced_p (ni2dest, PATTERN (insn))) { FOR_EACH_LOG_LINK (link, insn) if (link->insn == i3) @@ -4319,9 +4328,9 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, for (temp_insn = NEXT_INSN (i2); temp_insn && (this_basic_block->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun) - || BB_HEAD (this_basic_block) != temp_insn); + || BB_HEAD (this_basic_block) != temp_insn); temp_insn = NEXT_INSN (temp_insn)) - if (temp_insn != i3 && INSN_P (temp_insn)) + if (temp_insn != i3 && NONDEBUG_INSN_P (temp_insn)) FOR_EACH_LOG_LINK (link, temp_insn) if (link->insn == i2) link->insn = i3; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 64d7839c375..25779c50a7a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-12-14 Jakub Jelinek + + PR debug/77844 + * g++.dg/opt/pr77844.C: New test. + 2016-12-14 Martin Sebor PR c/17308 diff --git a/gcc/testsuite/g++.dg/opt/pr77844.C b/gcc/testsuite/g++.dg/opt/pr77844.C new file mode 100644 index 00000000000..66eb978ddb7 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr77844.C @@ -0,0 +1,32 @@ +// PR debug/77844 +// { dg-do compile } +// { dg-options "-O3 -g" } + +#include + +void +foo (std::vector& v, int i, int j) +{ + for (int k = 0; k < 5; ++k) + v[5 * i + k] = v[5 * i + k] | v[5 * j + k]; +} + +void +bar (std::vector& v, int i, int j) +{ + for (int k = 0; k < 5; ++k) + v[5 * i + k] = v[5 * i + k] ^ v[5 * j + k]; +} + +void +baz (std::vector& v) +{ + foo (v, 4, 1); + foo (v, 4, 2); + foo (v, 4, 3); + foo (v, 4, 4); + bar (v, 4, 1); + bar (v, 4, 2); + bar (v, 4, 3); + bar (v, 4, 4); +} diff --git a/gcc/valtrack.c b/gcc/valtrack.c index 002f49fa6ee..ae53faa8108 100644 --- a/gcc/valtrack.c +++ b/gcc/valtrack.c @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see #include "regs.h" #include "memmodel.h" #include "emit-rtl.h" +#include "rtl-iter.h" /* gen_lowpart_no_emit hook implementation for DEBUG_INSNs. In DEBUG_INSNs, all lowpart SUBREGs are valid, despite what the machine requires for @@ -145,6 +146,7 @@ struct rtx_subst_pair { rtx to; bool adjusted; + rtx_insn *insn; }; /* DATA points to an rtx_subst_pair. Return the value that should be @@ -162,6 +164,23 @@ propagate_for_debug_subst (rtx from, const_rtx old_rtx, void *data) pair->adjusted = true; pair->to = cleanup_auto_inc_dec (pair->to, VOIDmode); pair->to = make_compound_operation (pair->to, SET); + /* Avoid propagation from growing DEBUG_INSN expressions too much. */ + int cnt = 0; + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, pair->to, ALL) + if (REG_P (*iter) && ++cnt > 1) + { + rtx dval = make_debug_expr_from_rtl (old_rtx); + /* Emit a debug bind insn. */ + rtx bind + = gen_rtx_VAR_LOCATION (GET_MODE (old_rtx), + DEBUG_EXPR_TREE_DECL (dval), pair->to, + VAR_INIT_STATUS_INITIALIZED); + rtx_insn *bind_insn = emit_debug_insn_before (bind, pair->insn); + df_insn_rescan (bind_insn); + pair->to = dval; + break; + } return pair->to; } return copy_rtx (pair->to); @@ -182,6 +201,7 @@ propagate_for_debug (rtx_insn *insn, rtx_insn *last, rtx dest, rtx src, struct rtx_subst_pair p; p.to = src; p.adjusted = false; + p.insn = NEXT_INSN (insn); next = NEXT_INSN (insn); last = NEXT_INSN (last); -- 2.30.2