diff options
author | Jeff Law <law@redhat.com> | 2014-06-02 13:12:08 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2014-06-02 13:12:08 -0600 |
commit | 0d732cca67aff483c9f31ef0385f141d0aea54e2 (patch) | |
tree | 2bb3966093d33c4ba030af9dc89d13ceacc97766 /gcc | |
parent | a2adad8b0f7d079085a8771987ca0ff2a58958a7 (diff) | |
download | gcc-0d732cca67aff483c9f31ef0385f141d0aea54e2.zip gcc-0d732cca67aff483c9f31ef0385f141d0aea54e2.tar.gz gcc-0d732cca67aff483c9f31ef0385f141d0aea54e2.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/ree.c | 47 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/pr61094.C | 31 |
4 files changed, 83 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cffab0b..acefcc0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2014-06-02 Jeff Law <law@redhat.com> + + 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 <marcus.shawcroft@arm.com> * config/aarch64/aarch64.md (set_fpcr): Drop ISB after FPCR write. @@ -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 a52af2b..590969e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-06-02 Jeff Law <law@redhat.com> + + PR rtl-optimization/61094 + * g++.dg/pr61094: New test. + 2014-06-02 Uros Bizjak <ubizjak@gmail.com> * 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 0000000..35adc25 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr61094.C @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +template <typename> struct A { + unsigned _width, _height, _depth, _spectrum; + template <typename t> 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<int> *fn2(); +void fn3() { + int b; + for (;;) { + A<char> c(*fn2()); + fn1(&c); + if (d || !b) + throw; + } +} + + + + |