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
This commit is contained in:
parent
a2adad8b0f
commit
0d732cca67
@ -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.
|
||||
|
47
gcc/ree.c
47
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
|
||||
|
@ -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.
|
||||
|
31
gcc/testsuite/g++.dg/pr61094.C
Normal file
31
gcc/testsuite/g++.dg/pr61094.C
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user