Commit 4b4de898 by Joern Rennecke Committed by Joern Rennecke

re PR rtl-optimization/38449 (delay branch scheduling follows REG_CROSSING_JUMP…

re PR rtl-optimization/38449 (delay branch scheduling follows REG_CROSSING_JUMP jumps indiscriminately)

        PR rtl-optimization/38449:
        * hooks.c (hook_bool_const_rtx_const_rtx_true): New function.
        * hooks.h (hook_bool_const_rtx_const_rtx_true): Declare.
        * target.def: Merge in definitions and documentation for
        TARGET_CAN_FOLLOW_JUMP.
        * doc/tm.texi.in: Add documentation locations for the above.
        * doc/tm.texi: Regenerate.
        * reorg.c (follow_jumps): New parameters jump and crossing.
        Changed all callers.

From-SVN: r191878
parent f84992b0
2012-09-30 Joern Rennecke <joern.rennecke@embecosm.com>
PR rtl-optimization/38449:
* hooks.c (hook_bool_const_rtx_const_rtx_true): New function.
* hooks.h (hook_bool_const_rtx_const_rtx_true): Declare.
* target.def: Merge in definitions and documentation for
TARGET_CAN_FOLLOW_JUMP.
* doc/tm.texi.in: Add documentation locations for the above.
* doc/tm.texi: Regenerate.
* reorg.c (follow_jumps): New parameters jump and crossing.
Changed all callers.
2012-09-30 Eric Botcazou <ebotcazou@adacore.com> 2012-09-30 Eric Botcazou <ebotcazou@adacore.com>
* reorg.c (relax_delay_slots): Use delay_insn consistently. * reorg.c (relax_delay_slots): Use delay_insn consistently.
......
...@@ -10958,6 +10958,10 @@ filling of delay slots can result in branches being redirected, and this ...@@ -10958,6 +10958,10 @@ filling of delay slots can result in branches being redirected, and this
may in turn cause a branch offset to overflow. may in turn cause a branch offset to overflow.
@end defmac @end defmac
@deftypefn {Target Hook} bool TARGET_CAN_FOLLOW_JUMP (const_rtx @var{follower}, const_rtx @var{followee})
FOLLOWER and FOLLOWEE are JUMP_INSN instructions; return true if FOLLOWER may be modified to follow FOLLOWEE; false, if it can't. For example, on some targets, certain kinds of branches can't be made to follow through a hot/cold partitioning.
@end deftypefn
@deftypefn {Target Hook} bool TARGET_COMMUTATIVE_P (const_rtx @var{x}, int @var{outer_code}) @deftypefn {Target Hook} bool TARGET_COMMUTATIVE_P (const_rtx @var{x}, int @var{outer_code})
This target hook returns @code{true} if @var{x} is considered to be commutative. This target hook returns @code{true} if @var{x} is considered to be commutative.
Usually, this is just COMMUTATIVE_P (@var{x}), but the HP PA doesn't consider Usually, this is just COMMUTATIVE_P (@var{x}), but the HP PA doesn't consider
......
...@@ -10814,6 +10814,8 @@ filling of delay slots can result in branches being redirected, and this ...@@ -10814,6 +10814,8 @@ filling of delay slots can result in branches being redirected, and this
may in turn cause a branch offset to overflow. may in turn cause a branch offset to overflow.
@end defmac @end defmac
@hook TARGET_CAN_FOLLOW_JUMP
@hook TARGET_COMMUTATIVE_P @hook TARGET_COMMUTATIVE_P
This target hook returns @code{true} if @var{x} is considered to be commutative. This target hook returns @code{true} if @var{x} is considered to be commutative.
Usually, this is just COMMUTATIVE_P (@var{x}), but the HP PA doesn't consider Usually, this is just COMMUTATIVE_P (@var{x}), but the HP PA doesn't consider
......
...@@ -117,6 +117,14 @@ hook_bool_mode_rtx_true (enum machine_mode mode ATTRIBUTE_UNUSED, ...@@ -117,6 +117,14 @@ hook_bool_mode_rtx_true (enum machine_mode mode ATTRIBUTE_UNUSED,
return true; return true;
} }
/* Generic hook that takes (rtx, rtx) and returns true. */
bool
hook_bool_const_rtx_const_rtx_true (const_rtx follower ATTRIBUTE_UNUSED,
const_rtx followee ATTRIBUTE_UNUSED)
{
return true;
}
/* Generic hook that takes (enum machine_mode, unsigned HOST_WIDE_INT) /* Generic hook that takes (enum machine_mode, unsigned HOST_WIDE_INT)
and returns false. */ and returns false. */
bool bool
......
...@@ -36,6 +36,7 @@ extern bool hook_bool_mode_const_rtx_false (enum machine_mode, const_rtx); ...@@ -36,6 +36,7 @@ extern bool hook_bool_mode_const_rtx_false (enum machine_mode, const_rtx);
extern bool hook_bool_mode_const_rtx_true (enum machine_mode, const_rtx); extern bool hook_bool_mode_const_rtx_true (enum machine_mode, const_rtx);
extern bool hook_bool_mode_rtx_false (enum machine_mode, rtx); extern bool hook_bool_mode_rtx_false (enum machine_mode, rtx);
extern bool hook_bool_mode_rtx_true (enum machine_mode, rtx); extern bool hook_bool_mode_rtx_true (enum machine_mode, rtx);
extern bool hook_bool_const_rtx_const_rtx_true (const_rtx, const_rtx);
extern bool hook_bool_mode_uhwi_false (enum machine_mode, extern bool hook_bool_mode_uhwi_false (enum machine_mode,
unsigned HOST_WIDE_INT); unsigned HOST_WIDE_INT);
extern bool hook_bool_tree_false (tree); extern bool hook_bool_tree_false (tree);
......
...@@ -2494,22 +2494,25 @@ fill_simple_delay_slots (int non_jumps_p) ...@@ -2494,22 +2494,25 @@ fill_simple_delay_slots (int non_jumps_p)
#endif #endif
} }
/* Follow any unconditional jump at LABEL; /* Follow any unconditional jump at LABEL, for the purpose of redirecting JUMP;
return the ultimate label reached by any such chain of jumps. return the ultimate label reached by any such chain of jumps.
Return a suitable return rtx if the chain ultimately leads to a Return a suitable return rtx if the chain ultimately leads to a
return instruction. return instruction.
If LABEL is not followed by a jump, return LABEL. If LABEL is not followed by a jump, return LABEL.
If the chain loops or we can't find end, return LABEL, If the chain loops or we can't find end, return LABEL,
since that tells caller to avoid changing the insn. */ since that tells caller to avoid changing the insn.
If the returned label is obtained by following a REG_CROSSING_JUMP
jump, set *CROSSING to true, otherwise set it to false. */
static rtx static rtx
follow_jumps (rtx label) follow_jumps (rtx label, rtx jump, bool *crossing)
{ {
rtx insn; rtx insn;
rtx next; rtx next;
rtx value = label; rtx value = label;
int depth; int depth;
*crossing = false;
if (ANY_RETURN_P (label)) if (ANY_RETURN_P (label))
return label; return label;
for (depth = 0; for (depth = 0;
...@@ -2537,6 +2540,11 @@ follow_jumps (rtx label) ...@@ -2537,6 +2540,11 @@ follow_jumps (rtx label)
|| GET_CODE (PATTERN (tem)) == ADDR_DIFF_VEC)) || GET_CODE (PATTERN (tem)) == ADDR_DIFF_VEC))
break; break;
if (!targetm.can_follow_jump (jump, insn))
break;
if (!*crossing)
*crossing
= find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX) != NULL_RTX;
value = this_label; value = this_label;
} }
if (depth == 10) if (depth == 10)
...@@ -2984,6 +2992,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread, ...@@ -2984,6 +2992,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
if (new_thread != thread) if (new_thread != thread)
{ {
rtx label; rtx label;
bool crossing = false;
gcc_assert (thread_if_true); gcc_assert (thread_if_true);
...@@ -2991,7 +3000,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread, ...@@ -2991,7 +3000,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
&& redirect_with_delay_list_safe_p (insn, && redirect_with_delay_list_safe_p (insn,
JUMP_LABEL (new_thread), JUMP_LABEL (new_thread),
delay_list)) delay_list))
new_thread = follow_jumps (JUMP_LABEL (new_thread)); new_thread = follow_jumps (JUMP_LABEL (new_thread), insn, &crossing);
if (ANY_RETURN_P (new_thread)) if (ANY_RETURN_P (new_thread))
label = find_end_label (new_thread); label = find_end_label (new_thread);
...@@ -3001,7 +3010,11 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread, ...@@ -3001,7 +3010,11 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
label = get_label_before (new_thread); label = get_label_before (new_thread);
if (label) if (label)
reorg_redirect_jump (insn, label); {
reorg_redirect_jump (insn, label);
if (crossing)
set_unique_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX);
}
} }
return delay_list; return delay_list;
...@@ -3347,6 +3360,7 @@ relax_delay_slots (rtx first) ...@@ -3347,6 +3360,7 @@ relax_delay_slots (rtx first)
for (insn = first; insn; insn = next) for (insn = first; insn; insn = next)
{ {
rtx other; rtx other;
bool crossing;
next = next_active_insn (insn); next = next_active_insn (insn);
...@@ -3357,7 +3371,9 @@ relax_delay_slots (rtx first) ...@@ -3357,7 +3371,9 @@ relax_delay_slots (rtx first)
&& (condjump_p (insn) || condjump_in_parallel_p (insn)) && (condjump_p (insn) || condjump_in_parallel_p (insn))
&& !ANY_RETURN_P (target_label = JUMP_LABEL (insn))) && !ANY_RETURN_P (target_label = JUMP_LABEL (insn)))
{ {
target_label = skip_consecutive_labels (follow_jumps (target_label)); target_label
= skip_consecutive_labels (follow_jumps (target_label, insn,
&crossing));
if (ANY_RETURN_P (target_label)) if (ANY_RETURN_P (target_label))
target_label = find_end_label (target_label); target_label = find_end_label (target_label);
...@@ -3369,7 +3385,11 @@ relax_delay_slots (rtx first) ...@@ -3369,7 +3385,11 @@ relax_delay_slots (rtx first)
} }
if (target_label && target_label != JUMP_LABEL (insn)) if (target_label && target_label != JUMP_LABEL (insn))
reorg_redirect_jump (insn, target_label); {
reorg_redirect_jump (insn, target_label);
if (crossing)
set_unique_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX);
}
/* See if this jump conditionally branches around an unconditional /* See if this jump conditionally branches around an unconditional
jump. If so, invert this jump and point it to the target of the jump. If so, invert this jump and point it to the target of the
...@@ -3503,7 +3523,8 @@ relax_delay_slots (rtx first) ...@@ -3503,7 +3523,8 @@ relax_delay_slots (rtx first)
/* If this jump goes to another unconditional jump, thread it, but /* If this jump goes to another unconditional jump, thread it, but
don't convert a jump into a RETURN here. */ don't convert a jump into a RETURN here. */
trial = skip_consecutive_labels (follow_jumps (target_label)); trial = skip_consecutive_labels (follow_jumps (target_label, delay_insn,
&crossing));
if (ANY_RETURN_P (trial)) if (ANY_RETURN_P (trial))
trial = find_end_label (trial); trial = find_end_label (trial);
...@@ -3512,6 +3533,8 @@ relax_delay_slots (rtx first) ...@@ -3512,6 +3533,8 @@ relax_delay_slots (rtx first)
{ {
reorg_redirect_jump (delay_insn, trial); reorg_redirect_jump (delay_insn, trial);
target_label = trial; target_label = trial;
if (crossing)
set_unique_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX);
} }
/* If the first insn at TARGET_LABEL is redundant with a previous /* If the first insn at TARGET_LABEL is redundant with a previous
......
...@@ -1350,6 +1350,17 @@ DEFHOOK ...@@ -1350,6 +1350,17 @@ DEFHOOK
bool, (void), bool, (void),
hook_bool_void_false) hook_bool_void_false)
/* True if FOLLOWER may be modified to follow FOLLOWEE. */
DEFHOOK
(can_follow_jump,
"FOLLOWER and FOLLOWEE are JUMP_INSN instructions;\
return true if FOLLOWER may be modified to follow FOLLOWEE;\
false, if it can't.\
For example, on some targets, certain kinds of branches can't be made to\
follow through a hot/cold partitioning.",
bool, (const_rtx follower, const_rtx followee),
hook_bool_const_rtx_const_rtx_true)
/* Return a register class for which branch target register /* Return a register class for which branch target register
optimizations should be applied. */ optimizations should be applied. */
DEFHOOK DEFHOOK
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment