re PR bootstrap/61565 (ICE building libjava/interpret.cc)
PR target/61565 * compare-elim.c (struct comparison): Add eh_note. (find_comparison_dom_walker::before_dom_children): Don't eliminate a redundant comparison in a different EH region. Purge EH edges if necessary. From-SVN: r211881
This commit is contained in:
parent
37317a1fc0
commit
08281ce0fb
@ -1,3 +1,11 @@
|
||||
2014-06-22 Richard Henderson <rth@redhat.com>
|
||||
|
||||
PR target/61565
|
||||
* compare-elim.c (struct comparison): Add eh_note.
|
||||
(find_comparison_dom_walker::before_dom_children): Don't eliminate
|
||||
a redundant comparison in a different EH region. Purge EH edges if
|
||||
necessary.
|
||||
|
||||
2014-06-22 Segher Boessenkool <segher@kernel.crashing.org>
|
||||
|
||||
* config/rs6000/rs6000.md (maybe_var_shift): New define_attr.
|
||||
|
@ -100,6 +100,9 @@ struct comparison
|
||||
constants. */
|
||||
rtx in_a, in_b;
|
||||
|
||||
/* The REG_EH_REGION of the comparison. */
|
||||
rtx eh_note;
|
||||
|
||||
/* Information about how this comparison is used. */
|
||||
struct comparison_use uses[MAX_CMP_USE];
|
||||
|
||||
@ -262,6 +265,7 @@ find_comparison_dom_walker::before_dom_children (basic_block bb)
|
||||
struct comparison *last_cmp;
|
||||
rtx insn, next, last_clobber;
|
||||
bool last_cmp_valid;
|
||||
bool need_purge = false;
|
||||
bitmap killed;
|
||||
|
||||
killed = BITMAP_ALLOC (NULL);
|
||||
@ -303,44 +307,60 @@ find_comparison_dom_walker::before_dom_children (basic_block bb)
|
||||
if (src)
|
||||
{
|
||||
enum machine_mode src_mode = GET_MODE (src);
|
||||
rtx eh_note = NULL;
|
||||
|
||||
/* Eliminate a compare that's redundant with the previous. */
|
||||
if (last_cmp_valid
|
||||
&& rtx_equal_p (last_cmp->in_a, XEXP (src, 0))
|
||||
&& rtx_equal_p (last_cmp->in_b, XEXP (src, 1)))
|
||||
{
|
||||
rtx flags, x;
|
||||
enum machine_mode new_mode
|
||||
= targetm.cc_modes_compatible (last_cmp->orig_mode, src_mode);
|
||||
if (flag_non_call_exceptions)
|
||||
eh_note = find_reg_note (insn, REG_EH_REGION, NULL);
|
||||
|
||||
/* New mode is incompatible with the previous compare mode. */
|
||||
if (new_mode == VOIDmode)
|
||||
continue;
|
||||
if (!last_cmp_valid)
|
||||
goto dont_delete;
|
||||
|
||||
if (new_mode != last_cmp->orig_mode)
|
||||
{
|
||||
flags = gen_rtx_REG (src_mode, targetm.flags_regnum);
|
||||
/* Take care that it's in the same EH region. */
|
||||
if (flag_non_call_exceptions
|
||||
&& !rtx_equal_p (eh_note, last_cmp->eh_note))
|
||||
goto dont_delete;
|
||||
|
||||
/* Generate new comparison for substitution. */
|
||||
x = gen_rtx_COMPARE (new_mode, XEXP (src, 0), XEXP (src, 1));
|
||||
x = gen_rtx_SET (VOIDmode, flags, x);
|
||||
/* Make sure the compare is redundant with the previous. */
|
||||
if (!rtx_equal_p (last_cmp->in_a, XEXP (src, 0))
|
||||
|| !rtx_equal_p (last_cmp->in_b, XEXP (src, 1)))
|
||||
goto dont_delete;
|
||||
|
||||
if (!validate_change (last_cmp->insn,
|
||||
&PATTERN (last_cmp->insn), x, false))
|
||||
continue;
|
||||
/* New mode must be compatible with the previous compare mode. */
|
||||
{
|
||||
enum machine_mode new_mode
|
||||
= targetm.cc_modes_compatible (last_cmp->orig_mode, src_mode);
|
||||
if (new_mode == VOIDmode)
|
||||
goto dont_delete;
|
||||
|
||||
last_cmp->orig_mode = new_mode;
|
||||
}
|
||||
if (new_mode != last_cmp->orig_mode)
|
||||
{
|
||||
rtx x, flags = gen_rtx_REG (src_mode, targetm.flags_regnum);
|
||||
|
||||
delete_insn (insn);
|
||||
continue;
|
||||
}
|
||||
/* Generate new comparison for substitution. */
|
||||
x = gen_rtx_COMPARE (new_mode, XEXP (src, 0), XEXP (src, 1));
|
||||
x = gen_rtx_SET (VOIDmode, flags, x);
|
||||
|
||||
if (!validate_change (last_cmp->insn,
|
||||
&PATTERN (last_cmp->insn), x, false))
|
||||
goto dont_delete;
|
||||
|
||||
last_cmp->orig_mode = new_mode;
|
||||
}
|
||||
}
|
||||
|
||||
/* All tests and substitutions succeeded! */
|
||||
if (eh_note)
|
||||
need_purge = true;
|
||||
delete_insn (insn);
|
||||
continue;
|
||||
|
||||
dont_delete:
|
||||
last_cmp = XCNEW (struct comparison);
|
||||
last_cmp->insn = insn;
|
||||
last_cmp->prev_clobber = last_clobber;
|
||||
last_cmp->in_a = XEXP (src, 0);
|
||||
last_cmp->in_b = XEXP (src, 1);
|
||||
last_cmp->eh_note = eh_note;
|
||||
last_cmp->orig_mode = src_mode;
|
||||
all_compares.safe_push (last_cmp);
|
||||
|
||||
@ -404,6 +424,11 @@ find_comparison_dom_walker::before_dom_children (basic_block bb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we deleted a compare with a REG_EH_REGION note, we may need to
|
||||
remove EH edges. */
|
||||
if (need_purge)
|
||||
purge_dead_edges (bb);
|
||||
}
|
||||
|
||||
/* Find all comparisons in the function. */
|
||||
|
Loading…
Reference in New Issue
Block a user