summaryrefslogtreecommitdiff
path: root/gcc/sched-deps.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2002-06-04 11:46:14 -0600
committerJeff Law <law@gcc.gnu.org>2002-06-04 11:46:14 -0600
commit85d692168905f7ccb3463f5b8a1fda54fe7ea22f (patch)
tree100d6f14c9cba9eedae456288118fc9c150d270b /gcc/sched-deps.c
parent63f4a88e2873b14f843f02a0aeb4c8de73c51f57 (diff)
downloadgcc-85d692168905f7ccb3463f5b8a1fda54fe7ea22f.tar.gz
sched-int.h (struct deps): New field libcall_block_tail_insn.
* sched-int.h (struct deps): New field libcall_block_tail_insn. * sched_deps.c (init_deps): Initialize libcall_block_tail_insn. * sched_deps.c (sched_analyze_insn): If libcall_block_tail_insn is set, then mark the current insn as being part of a libcall scheduling group. (sched_analyze): Set and clear libcall_block_tail_insn appropriately. * haifa-sched.c (schedule_block): Do not count USE or CLOBBER insns against the issue rate. From-SVN: r54251
Diffstat (limited to 'gcc/sched-deps.c')
-rw-r--r--gcc/sched-deps.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index 268f58e6cd1..ec18f9d1973 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -1163,6 +1163,16 @@ sched_analyze_insn (deps, x, insn, loop_notes)
CLEAR_REG_SET (reg_pending_clobbers);
CLEAR_REG_SET (reg_pending_sets);
+ /* If we are currently in a libcall scheduling group, then mark the
+ current insn as being in a scheduling group and that it can not
+ be moved into a different basic block. */
+
+ if (deps->libcall_block_tail_insn)
+ {
+ set_sched_group_p (insn);
+ CANT_MOVE (insn) = 1;
+ }
+
/* If a post-call group is still open, see if it should remain so.
This insn must be a simple move of a hard reg to a pseudo or
vice-versa.
@@ -1226,6 +1236,8 @@ sched_analyze (deps, head, tail)
for (insn = head;; insn = NEXT_INSN (insn))
{
+ rtx link, end_seq, r0, set, note;
+
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
{
/* Clear out the stale LOG_LINKS from flow. */
@@ -1340,6 +1352,46 @@ sched_analyze (deps, head, tail)
if (current_sched_info->use_cselib)
cselib_process_insn (insn);
+
+ /* Now that we have completed handling INSN, check and see if it is
+ a CLOBBER beginning a libcall block. If it is, record the
+ end of the libcall sequence.
+
+ We want to schedule libcall blocks as a unit before reload. While
+ this restricts scheduling, it preserves the meaning of a libcall
+ block.
+
+ As a side effect, we may get better code due to decreased register
+ pressure as well as less chance of a foreign insn appearing in
+ a libcall block. */
+ if (!reload_completed
+ /* Note we may have nested libcall sequences. We only care about
+ the outermost libcall sequence. */
+ && deps->libcall_block_tail_insn == 0
+ /* The sequence must start with a clobber of a register. */
+ && GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == CLOBBER
+ && (r0 = XEXP (PATTERN (insn), 0), GET_CODE (r0) == REG)
+ && GET_CODE (XEXP (PATTERN (insn), 0)) == REG
+ /* The CLOBBER must also have a REG_LIBCALL note attached. */
+ && (link = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0
+ && (end_seq = XEXP (link, 0)) != 0
+ /* The insn referenced by the REG_LIBCALL note must be a
+ simple nop copy with the same destination as the register
+ mentioned in the clobber. */
+ && (set = single_set (end_seq)) != 0
+ && SET_DEST (set) == r0 && SET_SRC (set) == r0
+ /* And finally the insn referenced by the REG_LIBCALL must
+ also contain a REG_EQUAL note and a REG_RETVAL note. */
+ && find_reg_note (end_seq, REG_EQUAL, NULL_RTX) != 0
+ && find_reg_note (end_seq, REG_RETVAL, NULL_RTX) != 0)
+ deps->libcall_block_tail_insn = XEXP (link, 0);
+
+ /* If we have reached the end of a libcall block, then close the
+ block. */
+ if (deps->libcall_block_tail_insn == insn)
+ deps->libcall_block_tail_insn = 0;
+
if (insn == tail)
{
if (current_sched_info->use_cselib)
@@ -1433,6 +1485,7 @@ init_deps (deps)
deps->last_function_call = 0;
deps->sched_before_next_call = 0;
deps->in_post_call_group_p = false;
+ deps->libcall_block_tail_insn = 0;
}
/* Free insn lists found in DEPS. */