From 0d732cca67aff483c9f31ef0385f141d0aea54e2 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Mon, 2 Jun 2014 13:12:08 -0600 Subject: [PATCH] re PR rtl-optimization/61094 (-O3 insn Internal compiler error in copyprop_hardreg_forward_1, at regcprop.c:775) PR rtl-optimization/61094 * ree.c (combine_reaching_defs): Do not reextend an insn if it was marked as do_no_reextend. If a copy is needed to eliminate an extension, then mark it as do_not_reextend. PR rtl-optimization/61094 * g++.dg/pr61094: New test. From-SVN: r211142 --- gcc/ChangeLog | 7 +++++ gcc/ree.c | 47 +++++++++++++++++++++++++++++----- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/g++.dg/pr61094.C | 31 ++++++++++++++++++++++ 4 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr61094.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cffab0b5694..acefcc0b400 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2014-06-02 Jeff Law + + PR rtl-optimization/61094 + * ree.c (combine_reaching_defs): Do not reextend an insn if it + was marked as do_no_reextend. If a copy is needed to eliminate + an extension, then mark it as do_not_reextend. + 2014-06-02 Marcus Shawcroft * config/aarch64/aarch64.md (set_fpcr): Drop ISB after FPCR write. diff --git a/gcc/ree.c b/gcc/ree.c index 77f13842a52..ade413e8bed 100644 --- a/gcc/ree.c +++ b/gcc/ree.c @@ -507,6 +507,8 @@ struct ATTRIBUTE_PACKED ext_modified /* Kind of modification of the insn. */ ENUM_BITFIELD(ext_modified_kind) kind : 2; + unsigned int do_not_reextend : 1; + /* True if the insn is scheduled to be deleted. */ unsigned int deleted : 1; }; @@ -712,8 +714,10 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) register than the source operand, then additional restrictions are needed. Note we have to handle cases where we have nested extensions in the source operand. */ - if (REGNO (SET_DEST (PATTERN (cand->insn))) - != REGNO (get_extended_src_reg (SET_SRC (PATTERN (cand->insn))))) + bool copy_needed + = (REGNO (SET_DEST (PATTERN (cand->insn))) + != REGNO (get_extended_src_reg (SET_SRC (PATTERN (cand->insn))))); + if (copy_needed) { /* In theory we could handle more than one reaching def, it just makes the code to update the insn stream more complex. */ @@ -722,7 +726,7 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) /* We require the candidate not already be modified. It may, for example have been changed from a (sign_extend (reg)) - into (zero_extend (sign_extend (reg)). + into (zero_extend (sign_extend (reg))). Handling that case shouldn't be terribly difficult, but the code here and the code to emit copies would need auditing. Until @@ -777,6 +781,31 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) || reg_set_between_p (SET_DEST (PATTERN (cand->insn)), def_insn, cand->insn)) return false; + + /* We must be able to copy between the two registers. Generate, + recognize and verify constraints of the copy. Also fail if this + generated more than one insn. + + This generates garbage since we throw away the insn when we're + done, only to recreate it later if this test was successful. */ + start_sequence (); + rtx sub_rtx = *get_sub_rtx (def_insn); + rtx pat = PATTERN (cand->insn); + rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)), + REGNO (XEXP (SET_SRC (pat), 0))); + rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)), + REGNO (SET_DEST (pat))); + emit_move_insn (new_dst, new_src); + + rtx insn = get_insns(); + end_sequence (); + if (NEXT_INSN (insn)) + return false; + if (recog_memoized (insn) == -1) + return false; + extract_insn (insn); + if (!constrain_operands (1)) + return false; } @@ -843,11 +872,15 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) fprintf (dump_file, "All merges were successful.\n"); FOR_EACH_VEC_ELT (state->modified_list, i, def_insn) - if (state->modified[INSN_UID (def_insn)].kind == EXT_MODIFIED_NONE) - state->modified[INSN_UID (def_insn)].kind - = (cand->code == ZERO_EXTEND - ? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT); + { + ext_modified *modified = &state->modified[INSN_UID (def_insn)]; + if (modified->kind == EXT_MODIFIED_NONE) + modified->kind = (cand->code == ZERO_EXTEND ? EXT_MODIFIED_ZEXT + : EXT_MODIFIED_SEXT); + if (copy_needed) + modified->do_not_reextend = 1; + } return true; } else diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a52af2b56cf..590969e82cc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-06-02 Jeff Law + + PR rtl-optimization/61094 + * g++.dg/pr61094: New test. + 2014-06-02 Uros Bizjak * gcc.target/i386/xop-rotate1-vector.c (dg-options): Add -mno-avx2. diff --git a/gcc/testsuite/g++.dg/pr61094.C b/gcc/testsuite/g++.dg/pr61094.C new file mode 100644 index 00000000000..35adc256c21 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr61094.C @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +template struct A { + unsigned _width, _height, _depth, _spectrum; + template A(t p1) { + int a = p1.size(); + if (a) { + _width = p1._width; + _depth = _height = _spectrum = p1._spectrum; + } + } + long size() { return (long)_width * _height * _depth * _spectrum; } +}; + +int d; +void fn1(void *); +A *fn2(); +void fn3() { + int b; + for (;;) { + A c(*fn2()); + fn1(&c); + if (d || !b) + throw; + } +} + + + +