aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2014-06-02 13:12:08 -0600
committerJeff Law <law@gcc.gnu.org>2014-06-02 13:12:08 -0600
commit0d732cca67aff483c9f31ef0385f141d0aea54e2 (patch)
tree2bb3966093d33c4ba030af9dc89d13ceacc97766 /gcc
parenta2adad8b0f7d079085a8771987ca0ff2a58958a7 (diff)
downloadgcc-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/ChangeLog7
-rw-r--r--gcc/ree.c47
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/pr61094.C31
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.
diff --git a/gcc/ree.c b/gcc/ree.c
index 77f1384..ade413e 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 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;
+ }
+}
+
+
+
+