compare-elim.c: Fix head comment.
* compare-elim.c: Fix head comment. (conforming_compare): Remove redundant test. (can_eliminate_compare): New function extracted from... (before_dom_children): ...here. Use it, replace direct uses of flag_non_call_exceptions and tidy up. (maybe_select_cc_mode): Tidy up. From-SVN: r218468
This commit is contained in:
parent
bbea402544
commit
6c6a593dc0
|
@ -1,3 +1,12 @@
|
||||||
|
2014-12-07 Eric Botcazou <ebotcazou@adacore.com>
|
||||||
|
|
||||||
|
* compare-elim.c: Fix head comment.
|
||||||
|
(conforming_compare): Remove redundant test.
|
||||||
|
(can_eliminate_compare): New function extracted from...
|
||||||
|
(before_dom_children): ...here. Use it, replace direct uses of
|
||||||
|
flag_non_call_exceptions and tidy up.
|
||||||
|
(maybe_select_cc_mode): Tidy up.
|
||||||
|
|
||||||
2014-12-07 Felix Yang <felix.yang@huawei.com>
|
2014-12-07 Felix Yang <felix.yang@huawei.com>
|
||||||
Shanyao Chen <chenshanyao@huawei.com>
|
Shanyao Chen <chenshanyao@huawei.com>
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ along with GCC; see the file COPYING3. If not see
|
||||||
|
|
||||||
(1) All comparison patterns are represented as
|
(1) All comparison patterns are represented as
|
||||||
|
|
||||||
[(set (reg:CC) (compare:CC (reg) (immediate)))]
|
[(set (reg:CC) (compare:CC (reg) (reg_or_immediate)))]
|
||||||
|
|
||||||
(2) All insn patterns that modify the flags are represented as
|
(2) All insn patterns that modify the flags are represented as
|
||||||
|
|
||||||
|
@ -157,7 +157,6 @@ conforming_compare (rtx_insn *insn)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (REG_P (XEXP (src, 0))
|
if (REG_P (XEXP (src, 0))
|
||||||
&& REG_P (XEXP (src, 0))
|
|
||||||
&& (REG_P (XEXP (src, 1)) || CONSTANT_P (XEXP (src, 1))))
|
&& (REG_P (XEXP (src, 1)) || CONSTANT_P (XEXP (src, 1))))
|
||||||
return src;
|
return src;
|
||||||
|
|
||||||
|
@ -266,6 +265,45 @@ public:
|
||||||
virtual void before_dom_children (basic_block);
|
virtual void before_dom_children (basic_block);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Return true if conforming COMPARE with EH_NOTE is redundant with comparison
|
||||||
|
CMP and can thus be eliminated. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
can_eliminate_compare (rtx compare, rtx eh_note, struct comparison *cmp)
|
||||||
|
{
|
||||||
|
/* Take care that it's in the same EH region. */
|
||||||
|
if (cfun->can_throw_non_call_exceptions
|
||||||
|
&& !rtx_equal_p (eh_note, cmp->eh_note))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Make sure the compare is redundant with the previous. */
|
||||||
|
if (!rtx_equal_p (XEXP (compare, 0), cmp->in_a)
|
||||||
|
|| !rtx_equal_p (XEXP (compare, 1), cmp->in_b))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* New mode must be compatible with the previous compare mode. */
|
||||||
|
enum machine_mode new_mode
|
||||||
|
= targetm.cc_modes_compatible (GET_MODE (compare), cmp->orig_mode);
|
||||||
|
|
||||||
|
if (new_mode == VOIDmode)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (cmp->orig_mode != new_mode)
|
||||||
|
{
|
||||||
|
/* Generate new comparison for substitution. */
|
||||||
|
rtx flags = gen_rtx_REG (new_mode, targetm.flags_regnum);
|
||||||
|
rtx x = gen_rtx_COMPARE (new_mode, cmp->in_a, cmp->in_b);
|
||||||
|
x = gen_rtx_SET (VOIDmode, flags, x);
|
||||||
|
|
||||||
|
if (!validate_change (cmp->insn, &PATTERN (cmp->insn), x, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
cmp->orig_mode = new_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Identify comparison instructions within BB. If the flags from the last
|
/* Identify comparison instructions within BB. If the flags from the last
|
||||||
compare in the BB is live at the end of the block, install the compare
|
compare in the BB is live at the end of the block, install the compare
|
||||||
in BB->AUX. Called via dom_walker.walk (). */
|
in BB->AUX. Called via dom_walker.walk (). */
|
||||||
|
@ -317,62 +355,26 @@ find_comparison_dom_walker::before_dom_children (basic_block bb)
|
||||||
src = conforming_compare (insn);
|
src = conforming_compare (insn);
|
||||||
if (src)
|
if (src)
|
||||||
{
|
{
|
||||||
machine_mode src_mode = GET_MODE (src);
|
|
||||||
rtx eh_note = NULL;
|
rtx eh_note = NULL;
|
||||||
|
|
||||||
if (flag_non_call_exceptions)
|
if (cfun->can_throw_non_call_exceptions)
|
||||||
eh_note = find_reg_note (insn, REG_EH_REGION, NULL);
|
eh_note = find_reg_note (insn, REG_EH_REGION, NULL);
|
||||||
|
|
||||||
if (!last_cmp_valid)
|
if (last_cmp_valid && can_eliminate_compare (src, eh_note, last_cmp))
|
||||||
goto dont_delete;
|
{
|
||||||
|
if (eh_note)
|
||||||
|
need_purge = true;
|
||||||
|
delete_insn (insn);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
/* New mode must be compatible with the previous compare mode. */
|
|
||||||
{
|
|
||||||
machine_mode new_mode
|
|
||||||
= targetm.cc_modes_compatible (last_cmp->orig_mode, src_mode);
|
|
||||||
if (new_mode == VOIDmode)
|
|
||||||
goto dont_delete;
|
|
||||||
|
|
||||||
if (new_mode != last_cmp->orig_mode)
|
|
||||||
{
|
|
||||||
rtx x, flags = gen_rtx_REG (src_mode, targetm.flags_regnum);
|
|
||||||
|
|
||||||
/* 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 = XCNEW (struct comparison);
|
||||||
last_cmp->insn = insn;
|
last_cmp->insn = insn;
|
||||||
last_cmp->prev_clobber = last_clobber;
|
last_cmp->prev_clobber = last_clobber;
|
||||||
last_cmp->in_a = XEXP (src, 0);
|
last_cmp->in_a = XEXP (src, 0);
|
||||||
last_cmp->in_b = XEXP (src, 1);
|
last_cmp->in_b = XEXP (src, 1);
|
||||||
last_cmp->eh_note = eh_note;
|
last_cmp->eh_note = eh_note;
|
||||||
last_cmp->orig_mode = src_mode;
|
last_cmp->orig_mode = GET_MODE (src);
|
||||||
all_compares.safe_push (last_cmp);
|
all_compares.safe_push (last_cmp);
|
||||||
|
|
||||||
/* It's unusual, but be prepared for comparison patterns that
|
/* It's unusual, but be prepared for comparison patterns that
|
||||||
|
@ -391,7 +393,6 @@ find_comparison_dom_walker::before_dom_children (basic_block bb)
|
||||||
/* In either case, the previous compare is no longer valid. */
|
/* In either case, the previous compare is no longer valid. */
|
||||||
last_cmp = NULL;
|
last_cmp = NULL;
|
||||||
last_cmp_valid = false;
|
last_cmp_valid = false;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notice if this instruction uses the flags register. */
|
/* Notice if this instruction uses the flags register. */
|
||||||
|
@ -425,8 +426,7 @@ find_comparison_dom_walker::before_dom_children (basic_block bb)
|
||||||
FOR_EACH_EDGE (e, ei, bb->succs)
|
FOR_EACH_EDGE (e, ei, bb->succs)
|
||||||
{
|
{
|
||||||
basic_block dest = e->dest;
|
basic_block dest = e->dest;
|
||||||
if (bitmap_bit_p (df_get_live_in (bb),
|
if (bitmap_bit_p (df_get_live_in (bb), targetm.flags_regnum)
|
||||||
targetm.flags_regnum)
|
|
||||||
&& !single_pred_p (dest))
|
&& !single_pred_p (dest))
|
||||||
{
|
{
|
||||||
last_cmp->missing_uses = true;
|
last_cmp->missing_uses = true;
|
||||||
|
@ -498,8 +498,7 @@ maybe_select_cc_mode (struct comparison *cmp, rtx a ATTRIBUTE_UNUSED,
|
||||||
sel_mode = SELECT_CC_MODE (cmp->uses[0].code, a, b);
|
sel_mode = SELECT_CC_MODE (cmp->uses[0].code, a, b);
|
||||||
for (i = 1; i < n; ++i)
|
for (i = 1; i < n; ++i)
|
||||||
{
|
{
|
||||||
machine_mode new_mode;
|
machine_mode new_mode = SELECT_CC_MODE (cmp->uses[i].code, a, b);
|
||||||
new_mode = SELECT_CC_MODE (cmp->uses[i].code, a, b);
|
|
||||||
if (new_mode != sel_mode)
|
if (new_mode != sel_mode)
|
||||||
{
|
{
|
||||||
sel_mode = targetm.cc_modes_compatible (sel_mode, new_mode);
|
sel_mode = targetm.cc_modes_compatible (sel_mode, new_mode);
|
||||||
|
@ -507,7 +506,7 @@ maybe_select_cc_mode (struct comparison *cmp, rtx a ATTRIBUTE_UNUSED,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sel_mode != cmp->orig_mode)
|
if (sel_mode != cmp->orig_mode)
|
||||||
{
|
{
|
||||||
flags = gen_rtx_REG (sel_mode, targetm.flags_regnum);
|
flags = gen_rtx_REG (sel_mode, targetm.flags_regnum);
|
||||||
|
@ -633,7 +632,7 @@ try_eliminate_compare (struct comparison *cmp)
|
||||||
validate_change (insn, &XVECEXP (PATTERN (insn), 0, 1), x, true);
|
validate_change (insn, &XVECEXP (PATTERN (insn), 0, 1), x, true);
|
||||||
if (!apply_change_group ())
|
if (!apply_change_group ())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Success. Delete the compare insn... */
|
/* Success. Delete the compare insn... */
|
||||||
delete_insn (cmp->insn);
|
delete_insn (cmp->insn);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue