From cb29234501cd27d2d78a4a3040cc6a0890c96b32 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 23 Dec 2005 10:43:36 +0100 Subject: [PATCH] re PR target/25005 (ICE in extract_constrain_insn_cached, at recog.c:2002) PR target/25005 * regrename.c (replace_oldest_value_reg): Use validate_change with IN_GROUP set to 1 instead of doing direct modifications. (copyprop_hardreg_forward_1): Likewise. If any replace_oldest_* replacements have been performed on an instruction, use apply_change_group (). * g++.dg/opt/pr25005.C: New test. From-SVN: r109013 --- gcc/ChangeLog | 9 ++++++ gcc/regrename.c | 49 ++++++++++++++++++++++-------- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/opt/pr25005.C | 34 +++++++++++++++++++++ 4 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr25005.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1b64d262c5e..524b84ae668 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2005-12-23 Jakub Jelinek + + PR target/25005 + * regrename.c (replace_oldest_value_reg): Use validate_change with + IN_GROUP set to 1 instead of doing direct modifications. + (copyprop_hardreg_forward_1): Likewise. If any replace_oldest_* + replacements have been performed on an instruction, use + apply_change_group (). + 2005-12-23 Hans-Peter Nilsson * config/cris/arit.c (do_31div): Clarify what "31" refers to. diff --git a/gcc/regrename.c b/gcc/regrename.c index c9e1ac51406..a73e5f7d316 100644 --- a/gcc/regrename.c +++ b/gcc/regrename.c @@ -1408,7 +1408,7 @@ replace_oldest_value_reg (rtx *loc, enum reg_class cl, rtx insn, fprintf (dump_file, "insn %u: replaced reg %u with %u\n", INSN_UID (insn), REGNO (*loc), REGNO (new)); - *loc = new; + validate_change (insn, loc, new, 1); return true; } return false; @@ -1574,8 +1574,9 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd) for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn)) { int n_ops, i, alt, predicated; - bool is_asm; + bool is_asm, any_replacements; rtx set; + bool replaced[MAX_RECOG_OPERANDS]; if (! INSN_P (insn)) { @@ -1687,11 +1688,13 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd) } no_move_special_case: + any_replacements = false; + /* For each input operand, replace a hard register with the eldest live copy that's in an appropriate register class. */ for (i = 0; i < n_ops; i++) { - bool replaced = false; + replaced[i] = false; /* Don't scan match_operand here, since we've no reg class information to pass down. Any operands that we could @@ -1708,39 +1711,59 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd) if (recog_data.operand_type[i] == OP_IN) { if (recog_op_alt[i][alt].is_address) - replaced + replaced[i] = replace_oldest_value_addr (recog_data.operand_loc[i], recog_op_alt[i][alt].cl, VOIDmode, insn, vd); else if (REG_P (recog_data.operand[i])) - replaced + replaced[i] = replace_oldest_value_reg (recog_data.operand_loc[i], recog_op_alt[i][alt].cl, insn, vd); else if (MEM_P (recog_data.operand[i])) - replaced = replace_oldest_value_mem (recog_data.operand[i], - insn, vd); + replaced[i] = replace_oldest_value_mem (recog_data.operand[i], + insn, vd); } else if (MEM_P (recog_data.operand[i])) - replaced = replace_oldest_value_mem (recog_data.operand[i], - insn, vd); + replaced[i] = replace_oldest_value_mem (recog_data.operand[i], + insn, vd); /* If we performed any replacement, update match_dups. */ - if (replaced) + if (replaced[i]) { int j; rtx new; - changed = true; - new = *recog_data.operand_loc[i]; recog_data.operand[i] = new; for (j = 0; j < recog_data.n_dups; j++) if (recog_data.dup_num[j] == i) - *recog_data.dup_loc[j] = new; + validate_change (insn, recog_data.dup_loc[j], new, 1); + + any_replacements = true; } } + if (any_replacements) + { + if (! apply_change_group ()) + { + for (i = 0; i < n_ops; i++) + if (replaced[i]) + { + rtx old = *recog_data.operand_loc[i]; + recog_data.operand[i] = old; + } + + if (dump_file) + fprintf (dump_file, + "insn %u: reg replacements not verified\n", + INSN_UID (insn)); + } + else + changed = true; + } + did_replacement: /* Clobber call-clobbered registers. */ if (CALL_P (insn)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 87557d863a7..a61ab6f185d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-12-23 Jakub Jelinek + + PR target/25005 + * g++.dg/opt/pr25005.C: New test. + 2005-12-22 Mark Mitchell PR c++/25369 diff --git a/gcc/testsuite/g++.dg/opt/pr25005.C b/gcc/testsuite/g++.dg/opt/pr25005.C new file mode 100644 index 00000000000..f62f8a2bcee --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr25005.C @@ -0,0 +1,34 @@ +// PR target/25005 +// { dg-options "-O2 -funroll-loops" } +// { dg-do compile } + +inline void *operator new (__SIZE_TYPE__, void *__p) throw() { return __p; } + +struct M { ~M() { } }; + +struct P +{ + P () { v[0] = 0; v[1] = 0; v[2] = 0; } + P (const P &x) { for (int i = 0; i < 3; ++i) v[i] = x.v[i]; } + double v[3]; +}; + +struct V : public M +{ + V (const P *x, const P *y) + { + P *b = this->a = ::new P[2]; + for (; x != y; ++x, ++b) + ::new (b) P(*x); + } + P *a; +}; + +void bar (const V &); + +void +foo () +{ + const P d[2] = { P(), P() }; + bar (V (&d[0], &d[2])); +}