re PR target/89399 (ICE: RTL check: expected code 'set', 'clobber' or 'clobber_high', have 'parallel' in combine_reaching_defs, at ree.c:783)
PR rtl-optimization/89399 * ree.c (combine_set_extension): Use single_set rather than digging into PATTERN for items on the candidate list. (combine_reaching_defs): Likewise. PR rtl-optimization/89399 * gcc.c-torture/compile/pr89399.c: New test. From-SVN: r270151
This commit is contained in:
parent
aace91e285
commit
c2457887ea
@ -1,3 +1,10 @@
|
|||||||
|
2019-04-04 Jeff Law <law@redhat.com>
|
||||||
|
|
||||||
|
PR rtl-optimization/89399
|
||||||
|
* ree.c (combine_set_extension): Use single_set rather than
|
||||||
|
digging into PATTERN for items on the candidate list.
|
||||||
|
(combine_reaching_defs): Likewise.
|
||||||
|
|
||||||
2019-04-04 Richard Sandiford <richard.sandiford@arm.com>
|
2019-04-04 Richard Sandiford <richard.sandiford@arm.com>
|
||||||
|
|
||||||
PR rtl-optimization/46590
|
PR rtl-optimization/46590
|
||||||
|
64
gcc/ree.c
64
gcc/ree.c
@ -320,7 +320,7 @@ combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set)
|
|||||||
rtx orig_src = SET_SRC (*orig_set);
|
rtx orig_src = SET_SRC (*orig_set);
|
||||||
machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set));
|
machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set));
|
||||||
rtx new_set;
|
rtx new_set;
|
||||||
rtx cand_pat = PATTERN (cand->insn);
|
rtx cand_pat = single_set (cand->insn);
|
||||||
|
|
||||||
/* If the extension's source/destination registers are not the same
|
/* If the extension's source/destination registers are not the same
|
||||||
then we need to change the original load to reference the destination
|
then we need to change the original load to reference the destination
|
||||||
@ -778,10 +778,14 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
|
|||||||
/* If the destination operand of the extension is a different
|
/* If the destination operand of the extension is a different
|
||||||
register than the source operand, then additional restrictions
|
register than the source operand, then additional restrictions
|
||||||
are needed. Note we have to handle cases where we have nested
|
are needed. Note we have to handle cases where we have nested
|
||||||
extensions in the source operand. */
|
extensions in the source operand.
|
||||||
|
|
||||||
|
Candidate insns are known to be single_sets, via the test in
|
||||||
|
find_removable_extensions. So we continue to use single_set here
|
||||||
|
rather than get_sub_rtx. */
|
||||||
|
rtx set = single_set (cand->insn);
|
||||||
bool copy_needed
|
bool copy_needed
|
||||||
= (REGNO (SET_DEST (PATTERN (cand->insn)))
|
= (REGNO (SET_DEST (set)) != REGNO (get_extended_src_reg (SET_SRC (set))));
|
||||||
!= REGNO (get_extended_src_reg (SET_SRC (PATTERN (cand->insn)))));
|
|
||||||
if (copy_needed)
|
if (copy_needed)
|
||||||
{
|
{
|
||||||
/* Considering transformation of
|
/* Considering transformation of
|
||||||
@ -816,8 +820,8 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
|
|||||||
if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE)
|
if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
machine_mode dst_mode = GET_MODE (SET_DEST (PATTERN (cand->insn)));
|
machine_mode dst_mode = GET_MODE (SET_DEST (set));
|
||||||
rtx src_reg = get_extended_src_reg (SET_SRC (PATTERN (cand->insn)));
|
rtx src_reg = get_extended_src_reg (SET_SRC (set));
|
||||||
|
|
||||||
/* Ensure we can use the src_reg in dst_mode (needed for
|
/* Ensure we can use the src_reg in dst_mode (needed for
|
||||||
the (set (reg1) (reg2)) insn mentioned above). */
|
the (set (reg1) (reg2)) insn mentioned above). */
|
||||||
@ -852,9 +856,9 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
|
|||||||
|| !REG_P (SET_DEST (*dest_sub_rtx)))
|
|| !REG_P (SET_DEST (*dest_sub_rtx)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
rtx tmp_reg = gen_rtx_REG (GET_MODE (SET_DEST (PATTERN (cand->insn))),
|
rtx tmp_reg = gen_rtx_REG (GET_MODE (SET_DEST (set)),
|
||||||
REGNO (SET_DEST (*dest_sub_rtx)));
|
REGNO (SET_DEST (*dest_sub_rtx)));
|
||||||
if (reg_overlap_mentioned_p (tmp_reg, SET_DEST (PATTERN (cand->insn))))
|
if (reg_overlap_mentioned_p (tmp_reg, SET_DEST (set)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* On RISC machines we must make sure that changing the mode of SRC_REG
|
/* On RISC machines we must make sure that changing the mode of SRC_REG
|
||||||
@ -877,10 +881,8 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
|
|||||||
|
|
||||||
/* The destination register of the extension insn must not be
|
/* The destination register of the extension insn must not be
|
||||||
used or set between the def_insn and cand->insn exclusive. */
|
used or set between the def_insn and cand->insn exclusive. */
|
||||||
if (reg_used_between_p (SET_DEST (PATTERN (cand->insn)),
|
if (reg_used_between_p (SET_DEST (set), def_insn, cand->insn)
|
||||||
def_insn, cand->insn)
|
|| reg_set_between_p (SET_DEST (set), def_insn, cand->insn))
|
||||||
|| reg_set_between_p (SET_DEST (PATTERN (cand->insn)),
|
|
||||||
def_insn, cand->insn))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* We must be able to copy between the two registers. Generate,
|
/* We must be able to copy between the two registers. Generate,
|
||||||
@ -894,11 +896,10 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
|
|||||||
is different than in the code to emit the copy as we have not
|
is different than in the code to emit the copy as we have not
|
||||||
modified the defining insn yet. */
|
modified the defining insn yet. */
|
||||||
start_sequence ();
|
start_sequence ();
|
||||||
rtx pat = PATTERN (cand->insn);
|
rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (set)),
|
||||||
rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (pat)),
|
REGNO (get_extended_src_reg (SET_SRC (set))));
|
||||||
REGNO (get_extended_src_reg (SET_SRC (pat))));
|
rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (set)),
|
||||||
rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (pat)),
|
REGNO (SET_DEST (set)));
|
||||||
REGNO (SET_DEST (pat)));
|
|
||||||
emit_move_insn (new_dst, new_src);
|
emit_move_insn (new_dst, new_src);
|
||||||
|
|
||||||
rtx_insn *insn = get_insns ();
|
rtx_insn *insn = get_insns ();
|
||||||
@ -912,7 +913,7 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (REG_P (SET_SRC (*dest_sub_rtx))
|
while (REG_P (SET_SRC (*dest_sub_rtx))
|
||||||
&& (REGNO (SET_SRC (*dest_sub_rtx)) == REGNO (SET_DEST (pat))))
|
&& (REGNO (SET_SRC (*dest_sub_rtx)) == REGNO (SET_DEST (set))))
|
||||||
{
|
{
|
||||||
/* Considering transformation of
|
/* Considering transformation of
|
||||||
(set (reg2) (expression))
|
(set (reg2) (expression))
|
||||||
@ -955,7 +956,7 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
|
|||||||
implicitly sets it in word mode. */
|
implicitly sets it in word mode. */
|
||||||
if (WORD_REGISTER_OPERATIONS && known_lt (prec, BITS_PER_WORD))
|
if (WORD_REGISTER_OPERATIONS && known_lt (prec, BITS_PER_WORD))
|
||||||
{
|
{
|
||||||
struct df_link *uses = get_uses (def_insn2, SET_DEST (pat));
|
struct df_link *uses = get_uses (def_insn2, SET_DEST (set));
|
||||||
if (!uses)
|
if (!uses)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -973,10 +974,8 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
|
|||||||
used or set between the def_insn2 and def_insn exclusive.
|
used or set between the def_insn2 and def_insn exclusive.
|
||||||
Likewise for the other reg, i.e. check both reg1 and reg2
|
Likewise for the other reg, i.e. check both reg1 and reg2
|
||||||
in the above comment. */
|
in the above comment. */
|
||||||
if (reg_used_between_p (SET_DEST (PATTERN (cand->insn)),
|
if (reg_used_between_p (SET_DEST (set), def_insn2, def_insn)
|
||||||
def_insn2, def_insn)
|
|| reg_set_between_p (SET_DEST (set), def_insn2, def_insn)
|
||||||
|| reg_set_between_p (SET_DEST (PATTERN (cand->insn)),
|
|
||||||
def_insn2, def_insn)
|
|
||||||
|| reg_used_between_p (src_reg, def_insn2, def_insn)
|
|| reg_used_between_p (src_reg, def_insn2, def_insn)
|
||||||
|| reg_set_between_p (src_reg, def_insn2, def_insn))
|
|| reg_set_between_p (src_reg, def_insn2, def_insn))
|
||||||
break;
|
break;
|
||||||
@ -991,13 +990,12 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
|
|||||||
if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE)
|
if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE)
|
||||||
{
|
{
|
||||||
machine_mode mode;
|
machine_mode mode;
|
||||||
rtx set;
|
|
||||||
|
|
||||||
if (state->modified[INSN_UID (cand->insn)].kind
|
if (state->modified[INSN_UID (cand->insn)].kind
|
||||||
!= (cand->code == ZERO_EXTEND
|
!= (cand->code == ZERO_EXTEND
|
||||||
? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT)
|
? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT)
|
||||||
|| state->modified[INSN_UID (cand->insn)].mode != cand->mode
|
|| state->modified[INSN_UID (cand->insn)].mode != cand->mode
|
||||||
|| (set = single_set (cand->insn)) == NULL_RTX)
|
|| (set == NULL_RTX))
|
||||||
return false;
|
return false;
|
||||||
mode = GET_MODE (SET_DEST (set));
|
mode = GET_MODE (SET_DEST (set));
|
||||||
gcc_assert (GET_MODE_UNIT_SIZE (mode)
|
gcc_assert (GET_MODE_UNIT_SIZE (mode)
|
||||||
@ -1320,9 +1318,9 @@ find_and_remove_re (void)
|
|||||||
we do not allow the optimization of extensions where
|
we do not allow the optimization of extensions where
|
||||||
the source and destination registers do not match. Thus
|
the source and destination registers do not match. Thus
|
||||||
checking REG_P here is correct. */
|
checking REG_P here is correct. */
|
||||||
if (REG_P (XEXP (SET_SRC (PATTERN (curr_cand->insn)), 0))
|
rtx set = single_set (curr_cand->insn);
|
||||||
&& (REGNO (SET_DEST (PATTERN (curr_cand->insn)))
|
if (REG_P (XEXP (SET_SRC (set), 0))
|
||||||
!= REGNO (XEXP (SET_SRC (PATTERN (curr_cand->insn)), 0))))
|
&& (REGNO (SET_DEST (set)) != REGNO (XEXP (SET_SRC (set), 0))))
|
||||||
{
|
{
|
||||||
reinsn_copy_list.safe_push (curr_cand->insn);
|
reinsn_copy_list.safe_push (curr_cand->insn);
|
||||||
reinsn_copy_list.safe_push (state.defs_list[0]);
|
reinsn_copy_list.safe_push (state.defs_list[0]);
|
||||||
@ -1356,13 +1354,13 @@ find_and_remove_re (void)
|
|||||||
defining insn was used to eliminate a second extension
|
defining insn was used to eliminate a second extension
|
||||||
that was wider than the first. */
|
that was wider than the first. */
|
||||||
rtx sub_rtx = *get_sub_rtx (def_insn);
|
rtx sub_rtx = *get_sub_rtx (def_insn);
|
||||||
rtx pat = PATTERN (curr_insn);
|
rtx set = single_set (curr_insn);
|
||||||
rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
|
rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
|
||||||
REGNO (XEXP (SET_SRC (pat), 0)));
|
REGNO (XEXP (SET_SRC (set), 0)));
|
||||||
rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
|
rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
|
||||||
REGNO (SET_DEST (pat)));
|
REGNO (SET_DEST (set)));
|
||||||
rtx set = gen_rtx_SET (new_dst, new_src);
|
rtx new_set = gen_rtx_SET (new_dst, new_src);
|
||||||
emit_insn_after (set, def_insn);
|
emit_insn_after (new_set, def_insn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete all useless extensions here in one sweep. */
|
/* Delete all useless extensions here in one sweep. */
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2019-04-04 Jeff Law <law@redhat.com>
|
||||||
|
|
||||||
|
PR rtl-optimization/89399
|
||||||
|
* gcc.c-torture/compile/pr89399.c: New test.
|
||||||
|
|
||||||
2019-04-04 Harald Anlauf <anlauf@gmx.de>
|
2019-04-04 Harald Anlauf <anlauf@gmx.de>
|
||||||
|
|
||||||
PR fortran/89004
|
PR fortran/89004
|
||||||
|
10
gcc/testsuite/gcc.c-torture/compile/pr89399.c
Normal file
10
gcc/testsuite/gcc.c-torture/compile/pr89399.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
extern int bar(void);
|
||||||
|
|
||||||
|
short s;
|
||||||
|
|
||||||
|
int foo(void)
|
||||||
|
{
|
||||||
|
s = bar();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user