Remove CC0
This removes CC0 and all directly related infrastructure. CC_STATUS, CC_STATUS_MDEP, CC_STATUS_MDEP_INIT, and NOTICE_UPDATE_CC are deleted and poisoned. CC0 is only deleted (some targets use that name for something else). HAVE_cc0 is automatically generated, and we no longer will do that after this patch. CC_STATUS_INIT is suggested in final.c to also be useful for ports that are not CC0, and at least arm seems to use it for something. So I am leaving that alone, but most targets that have it could remove it. 2021-05-04 Segher Boessenkool <segher@kernel.crashing.org> * caller-save.c: Remove CC0. * cfgcleanup.c: Remove CC0. * cfgrtl.c: Remove CC0. * combine.c: Remove CC0. * compare-elim.c: Remove CC0. * conditions.h: Remove CC0. * config/h8300/h8300.h: Remove CC0. * config/h8300/h8300-protos.h: Remove CC0. * config/h8300/peepholes.md: Remove CC0. * config/i386/x86-tune-sched.c: Remove CC0. * config/m68k/m68k.c: Remove CC0. * config/rl78/rl78.c: Remove CC0. * config/sparc/sparc.c: Remove CC0. * config/xtensa/xtensa.c: Remove CC0. (gen_conditional_move): Use pc_rtx instead of cc0_rtx in a piece of RTL where that is used as a placeholder only. * cprop.c: Remove CC0. * cse.c: Remove CC0. * cselib.c: Remove CC0. * df-problems.c: Remove CC0. * df-scan.c: Remove CC0. * doc/md.texi: Remove CC0. Adjust an example. * doc/rtl.texi: Remove CC0. Adjust an example. * doc/tm.texi: Regenerate. * doc/tm.texi.in: Remove CC0. * emit-rtl.c: Remove CC0. * final.c: Remove CC0. * fwprop.c: Remove CC0. * gcse-common.c: Remove CC0. * gcse.c: Remove CC0. * genattrtab.c: Remove CC0. * genconfig.c: Remove CC0. * genemit.c: Remove CC0. * genextract.c: Remove CC0. * gengenrtl.c: Remove CC0. * genrecog.c: Remove CC0. * haifa-sched.c: Remove CC0. * ifcvt.c: Remove CC0. * ira-costs.c: Remove CC0. * ira.c: Remove CC0. * jump.c: Remove CC0. * loop-invariant.c: Remove CC0. * lra-constraints.c: Remove CC0. * lra-eliminations.c: Remove CC0. * optabs.c: Remove CC0. * postreload-gcse.c: Remove CC0. * postreload.c: Remove CC0. * print-rtl.c: Remove CC0. * read-rtl-function.c: Remove CC0. * reg-notes.def: Remove CC0. * reg-stack.c: Remove CC0. * reginfo.c: Remove CC0. * regrename.c: Remove CC0. * reload.c: Remove CC0. * reload1.c: Remove CC0. * reorg.c: Remove CC0. * resource.c: Remove CC0. * rtl.c: Remove CC0. * rtl.def: Remove CC0. * rtl.h: Remove CC0. * rtlanal.c: Remove CC0. * sched-deps.c: Remove CC0. * sched-rgn.c: Remove CC0. * shrink-wrap.c: Remove CC0. * simplify-rtx.c: Remove CC0. * system.h: Remove CC0. Poison NOTICE_UPDATE_CC, CC_STATUS_MDEP_INIT, CC_STATUS_MDEP, and CC_STATUS. * target.def: Remove CC0. * valtrack.c: Remove CC0. * var-tracking.c: Remove CC0.
This commit is contained in:
parent
7a38976611
commit
bd1cd0d0e0
67 changed files with 155 additions and 2702 deletions
|
@ -1012,7 +1012,7 @@ mark_referenced_regs (rtx *loc, refmarker_fn *mark, void *arg)
|
|||
loc = &SET_DEST (*loc);
|
||||
code = GET_CODE (*loc);
|
||||
if ((code == REG && REGNO (*loc) < FIRST_PSEUDO_REGISTER)
|
||||
|| code == PC || code == CC0
|
||||
|| code == PC
|
||||
|| (code == SUBREG && REG_P (SUBREG_REG (*loc))
|
||||
&& REGNO (SUBREG_REG (*loc)) < FIRST_PSEUDO_REGISTER
|
||||
/* If we're setting only part of a multi-word register,
|
||||
|
@ -1340,17 +1340,6 @@ insert_one_insn (class insn_chain *chain, int before_p, int code, rtx pat)
|
|||
rtx_insn *insn = chain->insn;
|
||||
class insn_chain *new_chain;
|
||||
|
||||
/* If INSN references CC0, put our insns in front of the insn that sets
|
||||
CC0. This is always safe, since the only way we could be passed an
|
||||
insn that references CC0 is for a restore, and doing a restore earlier
|
||||
isn't a problem. We do, however, assume here that CALL_INSNs don't
|
||||
reference CC0. Guard against non-INSN's like CODE_LABEL. */
|
||||
|
||||
if (HAVE_cc0 && (NONJUMP_INSN_P (insn) || JUMP_P (insn))
|
||||
&& before_p
|
||||
&& reg_referenced_p (cc0_rtx, PATTERN (insn)))
|
||||
chain = chain->prev, insn = chain->insn;
|
||||
|
||||
new_chain = new_insn_chain ();
|
||||
if (before_p)
|
||||
{
|
||||
|
|
|
@ -1449,12 +1449,6 @@ flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx_insn **f1,
|
|||
i2 = PREV_INSN (i2);
|
||||
}
|
||||
|
||||
/* Don't allow the insn after a compare to be shared by
|
||||
cross-jumping unless the compare is also shared. */
|
||||
if (HAVE_cc0 && ninsns && reg_mentioned_p (cc0_rtx, last1)
|
||||
&& ! sets_cc0_p (last1))
|
||||
last1 = afterlast1, last2 = afterlast2, last_dir = afterlast_dir, ninsns--;
|
||||
|
||||
/* Include preceding notes and labels in the cross-jump. One,
|
||||
this may bring us to the head of the blocks as requested above.
|
||||
Two, it keeps line number notes as matched as may be. */
|
||||
|
@ -1571,12 +1565,6 @@ flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx_insn **f
|
|||
i2 = NEXT_INSN (i2);
|
||||
}
|
||||
|
||||
/* Don't allow a compare to be shared by cross-jumping unless the insn
|
||||
after the compare is also shared. */
|
||||
if (HAVE_cc0 && ninsns && reg_mentioned_p (cc0_rtx, last1)
|
||||
&& sets_cc0_p (last1))
|
||||
last1 = beforelast1, last2 = beforelast2, ninsns--;
|
||||
|
||||
if (ninsns)
|
||||
{
|
||||
*f1 = last1;
|
||||
|
@ -2340,12 +2328,7 @@ try_head_merge_bb (basic_block bb)
|
|||
|
||||
cond = get_condition (jump, &move_before, true, false);
|
||||
if (cond == NULL_RTX)
|
||||
{
|
||||
if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, jump))
|
||||
move_before = prev_nonnote_nondebug_insn (jump);
|
||||
else
|
||||
move_before = jump;
|
||||
}
|
||||
move_before = jump;
|
||||
|
||||
for (ix = 0; ix < nedges; ix++)
|
||||
if (EDGE_SUCC (bb, ix)->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
|
||||
|
@ -2505,12 +2488,7 @@ try_head_merge_bb (basic_block bb)
|
|||
jump = BB_END (final_dest_bb);
|
||||
cond = get_condition (jump, &move_before, true, false);
|
||||
if (cond == NULL_RTX)
|
||||
{
|
||||
if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, jump))
|
||||
move_before = prev_nonnote_nondebug_insn (jump);
|
||||
else
|
||||
move_before = jump;
|
||||
}
|
||||
move_before = jump;
|
||||
}
|
||||
|
||||
do
|
||||
|
@ -2527,11 +2505,6 @@ try_head_merge_bb (basic_block bb)
|
|||
/* Try again, using a different insertion point. */
|
||||
move_before = jump;
|
||||
|
||||
/* Don't try moving before a cc0 user, as that may invalidate
|
||||
the cc0. */
|
||||
if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, jump))
|
||||
break;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2585,11 +2558,6 @@ try_head_merge_bb (basic_block bb)
|
|||
/* For the unmerged insns, try a different insertion point. */
|
||||
move_before = jump;
|
||||
|
||||
/* Don't try moving before a cc0 user, as that may invalidate
|
||||
the cc0. */
|
||||
if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, jump))
|
||||
break;
|
||||
|
||||
for (ix = 0; ix < nedges; ix++)
|
||||
currptr[ix] = headptr[ix] = nextptr[ix];
|
||||
}
|
||||
|
|
33
gcc/cfgrtl.c
33
gcc/cfgrtl.c
|
@ -887,18 +887,6 @@ rtl_merge_blocks (basic_block a, basic_block b)
|
|||
|
||||
del_first = a_end;
|
||||
|
||||
/* If this was a conditional jump, we need to also delete
|
||||
the insn that set cc0. */
|
||||
if (HAVE_cc0 && only_sets_cc0_p (prev))
|
||||
{
|
||||
rtx_insn *tmp = prev;
|
||||
|
||||
prev = prev_nonnote_insn (prev);
|
||||
if (!prev)
|
||||
prev = BB_HEAD (a);
|
||||
del_first = tmp;
|
||||
}
|
||||
|
||||
a_end = PREV_INSN (del_first);
|
||||
}
|
||||
else if (BARRIER_P (NEXT_INSN (a_end)))
|
||||
|
@ -1041,7 +1029,7 @@ edge
|
|||
try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
|
||||
{
|
||||
basic_block src = e->src;
|
||||
rtx_insn *insn = BB_END (src), *kill_from;
|
||||
rtx_insn *insn = BB_END (src);
|
||||
rtx set;
|
||||
int fallthru = 0;
|
||||
|
||||
|
@ -1078,13 +1066,6 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
|
|||
if (!set || side_effects_p (set))
|
||||
return NULL;
|
||||
|
||||
/* In case we zap a conditional jump, we'll need to kill
|
||||
the cc0 setter too. */
|
||||
kill_from = insn;
|
||||
if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, PATTERN (insn))
|
||||
&& only_sets_cc0_p (PREV_INSN (insn)))
|
||||
kill_from = PREV_INSN (insn);
|
||||
|
||||
/* See if we can create the fallthru edge. */
|
||||
if (in_cfglayout || can_fallthru (src, target))
|
||||
{
|
||||
|
@ -1095,12 +1076,11 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
|
|||
/* Selectively unlink whole insn chain. */
|
||||
if (in_cfglayout)
|
||||
{
|
||||
delete_insn_chain (kill_from, BB_END (src), false);
|
||||
delete_insn_chain (insn, BB_END (src), false);
|
||||
remove_barriers_from_footer (src);
|
||||
}
|
||||
else
|
||||
delete_insn_chain (kill_from, PREV_INSN (BB_HEAD (target)),
|
||||
false);
|
||||
delete_insn_chain (insn, PREV_INSN (BB_HEAD (target)), false);
|
||||
}
|
||||
|
||||
/* If this already is simplejump, redirect it. */
|
||||
|
@ -1139,7 +1119,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
|
|||
INSN_UID (insn), INSN_UID (BB_END (src)));
|
||||
|
||||
|
||||
delete_insn_chain (kill_from, insn, false);
|
||||
delete_insn_chain (insn, insn, false);
|
||||
|
||||
/* Recognize a tablejump that we are converting to a
|
||||
simple jump and remove its associated CODE_LABEL
|
||||
|
@ -1806,11 +1786,6 @@ rtl_tidy_fallthru_edge (edge e)
|
|||
delete_insn (table);
|
||||
}
|
||||
|
||||
/* If this was a conditional jump, we need to also delete
|
||||
the insn that set cc0. */
|
||||
if (HAVE_cc0 && any_condjump_p (q) && only_sets_cc0_p (PREV_INSN (q)))
|
||||
q = PREV_INSN (q);
|
||||
|
||||
q = PREV_INSN (q);
|
||||
}
|
||||
/* Unconditional jumps with side-effects (i.e. which we can't just delete
|
||||
|
|
264
gcc/combine.c
264
gcc/combine.c
|
@ -33,12 +33,6 @@ along with GCC; see the file COPYING3. If not see
|
|||
small number of quadruplets of insns A, B, C and D for which
|
||||
there's high likelihood of success.
|
||||
|
||||
LOG_LINKS does not have links for use of the CC0. They don't
|
||||
need to, because the insn that sets the CC0 is always immediately
|
||||
before the insn that tests it. So we always regard a branch
|
||||
insn as having a logical link to the preceding insn. The same is true
|
||||
for an insn explicitly using CC0.
|
||||
|
||||
We check (with modified_between_p) to avoid combining in such a way
|
||||
as to move a computation to a place where its value would be different.
|
||||
|
||||
|
@ -64,16 +58,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
||||
To simplify substitution, we combine only when the earlier insn(s)
|
||||
consist of only a single assignment. To simplify updating afterward,
|
||||
we never combine when a subroutine call appears in the middle.
|
||||
|
||||
Since we do not represent assignments to CC0 explicitly except when that
|
||||
is all an insn does, there is no LOG_LINKS entry in an insn that uses
|
||||
the condition code for the insn that set the condition code.
|
||||
Fortunately, these two insns must be consecutive.
|
||||
Therefore, every JUMP_INSN is taken to have an implicit logical link
|
||||
to the preceding insn. This is not quite right, since non-jumps can
|
||||
also use the condition code; but in practice such insns would not
|
||||
combine anyway. */
|
||||
we never combine when a subroutine call appears in the middle. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
|
@ -549,8 +534,8 @@ combine_split_insns (rtx pattern, rtx_insn *insn)
|
|||
}
|
||||
|
||||
/* This is used by find_single_use to locate an rtx in LOC that
|
||||
contains exactly one use of DEST, which is typically either a REG
|
||||
or CC0. It returns a pointer to the innermost rtx expression
|
||||
contains exactly one use of DEST, which is typically a REG.
|
||||
It returns a pointer to the innermost rtx expression
|
||||
containing DEST. Appearances of DEST that are being used to
|
||||
totally replace it are not counted. */
|
||||
|
||||
|
@ -574,12 +559,11 @@ find_single_use_1 (rtx dest, rtx *loc)
|
|||
return 0;
|
||||
|
||||
case SET:
|
||||
/* If the destination is anything other than CC0, PC, a REG or a SUBREG
|
||||
/* If the destination is anything other than PC, a REG or a SUBREG
|
||||
of a REG that occupies all of the REG, the insn uses DEST if
|
||||
it is mentioned in the destination or the source. Otherwise, we
|
||||
need just check the source. */
|
||||
if (GET_CODE (SET_DEST (x)) != CC0
|
||||
&& GET_CODE (SET_DEST (x)) != PC
|
||||
if (GET_CODE (SET_DEST (x)) != PC
|
||||
&& !REG_P (SET_DEST (x))
|
||||
&& ! (GET_CODE (SET_DEST (x)) == SUBREG
|
||||
&& REG_P (SUBREG_REG (SET_DEST (x)))
|
||||
|
@ -649,9 +633,6 @@ find_single_use_1 (rtx dest, rtx *loc)
|
|||
|
||||
If PLOC is nonzero, *PLOC is set to the insn containing the single use.
|
||||
|
||||
If DEST is cc0_rtx, we look only at the next insn. In that case, we don't
|
||||
care about REG_DEAD notes or LOG_LINKS.
|
||||
|
||||
Otherwise, we find the single use by finding an insn that has a
|
||||
LOG_LINKS pointing at INSN and has a REG_DEAD note for DEST. If DEST is
|
||||
only referenced once in that insn, we know that it must be the first
|
||||
|
@ -665,19 +646,6 @@ find_single_use (rtx dest, rtx_insn *insn, rtx_insn **ploc)
|
|||
rtx *result;
|
||||
struct insn_link *link;
|
||||
|
||||
if (dest == cc0_rtx)
|
||||
{
|
||||
next = NEXT_INSN (insn);
|
||||
if (next == 0
|
||||
|| (!NONJUMP_INSN_P (next) && !JUMP_P (next)))
|
||||
return 0;
|
||||
|
||||
result = find_single_use_1 (dest, &PATTERN (next));
|
||||
if (result && ploc)
|
||||
*ploc = next;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!REG_P (dest))
|
||||
return 0;
|
||||
|
||||
|
@ -1128,9 +1096,7 @@ create_log_links (void)
|
|||
/* Walk the LOG_LINKS of insn B to see if we find a reference to A. Return
|
||||
true if we found a LOG_LINK that proves that A feeds B. This only works
|
||||
if there are no instructions between A and B which could have a link
|
||||
depending on A, since in that case we would not record a link for B.
|
||||
We also check the implicit dependency created by a cc0 setter/user
|
||||
pair. */
|
||||
depending on A, since in that case we would not record a link for B. */
|
||||
|
||||
static bool
|
||||
insn_a_feeds_b (rtx_insn *a, rtx_insn *b)
|
||||
|
@ -1139,8 +1105,6 @@ insn_a_feeds_b (rtx_insn *a, rtx_insn *b)
|
|||
FOR_EACH_LOG_LINK (links, b)
|
||||
if (links->insn == a)
|
||||
return true;
|
||||
if (HAVE_cc0 && sets_cc0_p (a))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1153,7 +1117,6 @@ static int
|
|||
combine_instructions (rtx_insn *f, unsigned int nregs)
|
||||
{
|
||||
rtx_insn *insn, *next;
|
||||
rtx_insn *prev;
|
||||
struct insn_link *links, *nextlinks;
|
||||
rtx_insn *first;
|
||||
basic_block last_bb;
|
||||
|
@ -1330,69 +1293,6 @@ combine_instructions (rtx_insn *f, unsigned int nregs)
|
|||
}
|
||||
}
|
||||
|
||||
/* Try to combine a jump insn that uses CC0
|
||||
with a preceding insn that sets CC0, and maybe with its
|
||||
logical predecessor as well.
|
||||
This is how we make decrement-and-branch insns.
|
||||
We need this special code because data flow connections
|
||||
via CC0 do not get entered in LOG_LINKS. */
|
||||
|
||||
if (HAVE_cc0
|
||||
&& JUMP_P (insn)
|
||||
&& (prev = prev_nonnote_insn (insn)) != 0
|
||||
&& NONJUMP_INSN_P (prev)
|
||||
&& sets_cc0_p (PATTERN (prev)))
|
||||
{
|
||||
if ((next = try_combine (insn, prev, NULL, NULL,
|
||||
&new_direct_jump_p,
|
||||
last_combined_insn)) != 0)
|
||||
goto retry;
|
||||
|
||||
FOR_EACH_LOG_LINK (nextlinks, prev)
|
||||
if ((next = try_combine (insn, prev, nextlinks->insn,
|
||||
NULL, &new_direct_jump_p,
|
||||
last_combined_insn)) != 0)
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Do the same for an insn that explicitly references CC0. */
|
||||
if (HAVE_cc0 && NONJUMP_INSN_P (insn)
|
||||
&& (prev = prev_nonnote_insn (insn)) != 0
|
||||
&& NONJUMP_INSN_P (prev)
|
||||
&& sets_cc0_p (PATTERN (prev))
|
||||
&& GET_CODE (PATTERN (insn)) == SET
|
||||
&& reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn))))
|
||||
{
|
||||
if ((next = try_combine (insn, prev, NULL, NULL,
|
||||
&new_direct_jump_p,
|
||||
last_combined_insn)) != 0)
|
||||
goto retry;
|
||||
|
||||
FOR_EACH_LOG_LINK (nextlinks, prev)
|
||||
if ((next = try_combine (insn, prev, nextlinks->insn,
|
||||
NULL, &new_direct_jump_p,
|
||||
last_combined_insn)) != 0)
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Finally, see if any of the insns that this insn links to
|
||||
explicitly references CC0. If so, try this insn, that insn,
|
||||
and its predecessor if it sets CC0. */
|
||||
if (HAVE_cc0)
|
||||
{
|
||||
FOR_EACH_LOG_LINK (links, insn)
|
||||
if (NONJUMP_INSN_P (links->insn)
|
||||
&& GET_CODE (PATTERN (links->insn)) == SET
|
||||
&& reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (links->insn)))
|
||||
&& (prev = prev_nonnote_insn (links->insn)) != 0
|
||||
&& NONJUMP_INSN_P (prev)
|
||||
&& sets_cc0_p (PATTERN (prev))
|
||||
&& (next = try_combine (insn, links->insn,
|
||||
prev, NULL, &new_direct_jump_p,
|
||||
last_combined_insn)) != 0)
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Try combining an insn with two different insns whose results it
|
||||
uses. */
|
||||
if (max_combine >= 3)
|
||||
|
@ -1853,7 +1753,7 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED,
|
|||
else if (next_active_insn (insn) != i3)
|
||||
all_adjacent = false;
|
||||
|
||||
/* Can combine only if previous insn is a SET of a REG, a SUBREG or CC0.
|
||||
/* Can combine only if previous insn is a SET of a REG or a SUBREG,
|
||||
or a PARALLEL consisting of such a SET and CLOBBERs.
|
||||
|
||||
If INSN has CLOBBER parallel parts, ignore them for our processing.
|
||||
|
@ -2032,7 +1932,7 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED,
|
|||
|| (DF_INSN_LUID (insn) < last_call_luid && ! CONSTANT_P (src)))
|
||||
return 0;
|
||||
|
||||
/* DEST must either be a REG or CC0. */
|
||||
/* DEST must be a REG. */
|
||||
if (REG_P (dest))
|
||||
{
|
||||
/* If register alignment is being enforced for multi-word items in all
|
||||
|
@ -2059,7 +1959,7 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED,
|
|||
GET_MODE (src)))))
|
||||
return 0;
|
||||
}
|
||||
else if (GET_CODE (dest) != CC0)
|
||||
else
|
||||
return 0;
|
||||
|
||||
|
||||
|
@ -2139,23 +2039,6 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED,
|
|||
|| reg_overlap_mentioned_p (XEXP (link, 0), PATTERN (i3))))
|
||||
return 0;
|
||||
|
||||
/* Don't combine an insn that follows a CC0-setting insn.
|
||||
An insn that uses CC0 must not be separated from the one that sets it.
|
||||
We do, however, allow I2 to follow a CC0-setting insn if that insn
|
||||
is passed as I1; in that case it will be deleted also.
|
||||
We also allow combining in this case if all the insns are adjacent
|
||||
because that would leave the two CC0 insns adjacent as well.
|
||||
It would be more logical to test whether CC0 occurs inside I1 or I2,
|
||||
but that would be much slower, and this ought to be equivalent. */
|
||||
|
||||
if (HAVE_cc0)
|
||||
{
|
||||
p = prev_nonnote_insn (insn);
|
||||
if (p && p != pred && NONJUMP_INSN_P (p) && sets_cc0_p (PATTERN (p))
|
||||
&& ! all_adjacent)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If we get here, we have passed all the tests and the combination is
|
||||
to be allowed. */
|
||||
|
||||
|
@ -2988,7 +2871,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
|
|||
This undoes a previous combination and allows us to match a branch-and-
|
||||
decrement insn. */
|
||||
|
||||
if (!HAVE_cc0 && i1 == 0
|
||||
if (i1 == 0
|
||||
&& is_parallel_of_n_reg_sets (PATTERN (i2), 2)
|
||||
&& (GET_MODE_CLASS (GET_MODE (SET_DEST (XVECEXP (PATTERN (i2), 0, 0))))
|
||||
== MODE_CC)
|
||||
|
@ -3020,7 +2903,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
|
|||
/* If I2 is a PARALLEL of two SETs of REGs (and perhaps some CLOBBERs),
|
||||
make those two SETs separate I1 and I2 insns, and make an I0 that is
|
||||
the original I1. */
|
||||
if (!HAVE_cc0 && i0 == 0
|
||||
if (i0 == 0
|
||||
&& is_parallel_of_n_reg_sets (PATTERN (i2), 2)
|
||||
&& can_split_parallel_of_n_reg_sets (i2, 2)
|
||||
&& !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 0)), i2, i3)
|
||||
|
@ -3228,7 +3111,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
|
|||
|
||||
subst_insn = i3;
|
||||
|
||||
/* Many machines that don't use CC0 have insns that can both perform an
|
||||
/* Many machines have insns that can both perform an
|
||||
arithmetic operation and set the condition code. These operations will
|
||||
be represented as a PARALLEL with the first element of the vector
|
||||
being a COMPARE of an arithmetic operation with the constant zero.
|
||||
|
@ -3239,7 +3122,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
|
|||
needed, and make the PARALLEL by just replacing I2DEST in I3SRC with
|
||||
I2SRC. Later we will make the PARALLEL that contains I2. */
|
||||
|
||||
if (!HAVE_cc0 && i1 == 0 && added_sets_2 && GET_CODE (PATTERN (i3)) == SET
|
||||
if (i1 == 0 && added_sets_2 && GET_CODE (PATTERN (i3)) == SET
|
||||
&& GET_CODE (SET_SRC (PATTERN (i3))) == COMPARE
|
||||
&& CONST_INT_P (XEXP (SET_SRC (PATTERN (i3)), 1))
|
||||
&& rtx_equal_p (XEXP (SET_SRC (PATTERN (i3)), 0), i2dest))
|
||||
|
@ -3779,7 +3662,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
|
|||
are set between I2 and I3. */
|
||||
if (insn_code_number < 0
|
||||
&& (split = find_split_point (&newpat, i3, false)) != 0
|
||||
&& (!HAVE_cc0 || REG_P (i2dest))
|
||||
/* We need I2DEST in the proper mode. If it is a hard register
|
||||
or the only use of a pseudo, we can change its mode.
|
||||
Make sure we don't change a hard register to have a mode that
|
||||
|
@ -3966,7 +3848,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
|
|||
eliminate the copy.
|
||||
|
||||
We cannot do this if the destination of the first assignment is a
|
||||
condition code register or cc0. We eliminate this case by making sure
|
||||
condition code register. We eliminate this case by making sure
|
||||
the SET_DEST and SET_SRC have the same mode.
|
||||
|
||||
We cannot do this if the destination of the second assignment is
|
||||
|
@ -4060,8 +3942,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
|
|||
rtx set0 = XVECEXP (newpat, 0, 0);
|
||||
rtx set1 = XVECEXP (newpat, 0, 1);
|
||||
|
||||
/* Normally, it doesn't matter which of the two is done first,
|
||||
but the one that references cc0 can't be the second, and
|
||||
/* Normally, it doesn't matter which of the two is done first, but
|
||||
one which uses any regs/memory set in between i2 and i3 can't
|
||||
be first. The PARALLEL might also have been pre-existing in i3,
|
||||
so we need to make sure that we won't wrongly hoist a SET to i2
|
||||
|
@ -4074,7 +3955,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
|
|||
&& find_reg_note (i2, REG_DEAD,
|
||||
SUBREG_REG (SET_DEST (set1))))
|
||||
&& !modified_between_p (SET_DEST (set1), i2, i3)
|
||||
&& (!HAVE_cc0 || !reg_referenced_p (cc0_rtx, set0))
|
||||
/* If I3 is a jump, ensure that set0 is a jump so that
|
||||
we do not create invalid RTL. */
|
||||
&& (!JUMP_P (i3) || SET_DEST (set0) == pc_rtx)
|
||||
|
@ -4090,7 +3970,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
|
|||
&& find_reg_note (i2, REG_DEAD,
|
||||
SUBREG_REG (SET_DEST (set0))))
|
||||
&& !modified_between_p (SET_DEST (set0), i2, i3)
|
||||
&& (!HAVE_cc0 || !reg_referenced_p (cc0_rtx, set1))
|
||||
/* If I3 is a jump, ensure that set1 is a jump so that
|
||||
we do not create invalid RTL. */
|
||||
&& (!JUMP_P (i3) || SET_DEST (set1) == pc_rtx)
|
||||
|
@ -4158,19 +4037,6 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
|
|||
}
|
||||
}
|
||||
|
||||
/* If I2 is the CC0 setter and I3 is the CC0 user then check whether
|
||||
they are adjacent to each other or not. */
|
||||
if (HAVE_cc0)
|
||||
{
|
||||
rtx_insn *p = prev_nonnote_insn (i3);
|
||||
if (p && p != i2 && NONJUMP_INSN_P (p) && newi2pat
|
||||
&& sets_cc0_p (newi2pat))
|
||||
{
|
||||
undo_all ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only allow this combination if insn_cost reports that the
|
||||
replacement instructions are cheaper than the originals. */
|
||||
if (!combine_validate_cost (i0, i1, i2, i3, newpat, newi2pat, other_pat))
|
||||
|
@ -5061,19 +4927,6 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src)
|
|||
break;
|
||||
|
||||
case SET:
|
||||
/* If SET_DEST is CC0 and SET_SRC is not an operand, a COMPARE, or a
|
||||
ZERO_EXTRACT, the most likely reason why this doesn't match is that
|
||||
we need to put the operand into a register. So split at that
|
||||
point. */
|
||||
|
||||
if (SET_DEST (x) == cc0_rtx
|
||||
&& GET_CODE (SET_SRC (x)) != COMPARE
|
||||
&& GET_CODE (SET_SRC (x)) != ZERO_EXTRACT
|
||||
&& !OBJECT_P (SET_SRC (x))
|
||||
&& ! (GET_CODE (SET_SRC (x)) == SUBREG
|
||||
&& OBJECT_P (SUBREG_REG (SET_SRC (x)))))
|
||||
return &SET_SRC (x);
|
||||
|
||||
/* See if we can split SET_SRC as it stands. */
|
||||
split = find_split_point (&SET_SRC (x), insn, true);
|
||||
if (split && split != &SET_SRC (x))
|
||||
|
@ -5485,9 +5338,7 @@ subst (rtx x, rtx from, rtx to, int in_dest, int in_cond, int unique_copy)
|
|||
{
|
||||
rtx dest = SET_DEST (XVECEXP (x, 0, i));
|
||||
|
||||
if (!REG_P (dest)
|
||||
&& GET_CODE (dest) != CC0
|
||||
&& GET_CODE (dest) != PC)
|
||||
if (!REG_P (dest) && GET_CODE (dest) != PC)
|
||||
{
|
||||
new_rtx = subst (dest, from, to, 0, 0, unique_copy);
|
||||
|
||||
|
@ -5505,13 +5356,12 @@ subst (rtx x, rtx from, rtx to, int in_dest, int in_cond, int unique_copy)
|
|||
len = GET_RTX_LENGTH (code);
|
||||
fmt = GET_RTX_FORMAT (code);
|
||||
|
||||
/* We don't need to process a SET_DEST that is a register, CC0,
|
||||
or PC, so set up to skip this common case. All other cases
|
||||
where we want to suppress replacing something inside a
|
||||
SET_SRC are handled via the IN_DEST operand. */
|
||||
/* We don't need to process a SET_DEST that is a register or PC, so
|
||||
set up to skip this common case. All other cases where we want
|
||||
to suppress replacing something inside a SET_SRC are handled via
|
||||
the IN_DEST operand. */
|
||||
if (code == SET
|
||||
&& (REG_P (SET_DEST (x))
|
||||
|| GET_CODE (SET_DEST (x)) == CC0
|
||||
|| GET_CODE (SET_DEST (x)) == PC))
|
||||
fmt = "ie";
|
||||
|
||||
|
@ -5581,22 +5431,17 @@ subst (rtx x, rtx from, rtx to, int in_dest, int in_cond, int unique_copy)
|
|||
from in the outside mode, and that may be invalid
|
||||
if it is an fp reg copied in integer mode.
|
||||
|
||||
We allow two exceptions to this: It is valid if
|
||||
We allow an exception to this: It is valid if
|
||||
it is inside another SUBREG and the mode of that
|
||||
SUBREG and the mode of the inside of TO is
|
||||
tieable and it is valid if X is a SET that copies
|
||||
FROM to CC0. */
|
||||
tieable. */
|
||||
|
||||
if (GET_CODE (to) == SUBREG
|
||||
&& !targetm.modes_tieable_p (GET_MODE (to),
|
||||
GET_MODE (SUBREG_REG (to)))
|
||||
&& ! (code == SUBREG
|
||||
&& (targetm.modes_tieable_p
|
||||
(GET_MODE (x), GET_MODE (SUBREG_REG (to)))))
|
||||
&& (!HAVE_cc0
|
||||
|| (! (code == SET
|
||||
&& i == 1
|
||||
&& XEXP (x, 0) == cc0_rtx))))
|
||||
(GET_MODE (x), GET_MODE (SUBREG_REG (to))))))
|
||||
return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
|
||||
|
||||
if (code == SUBREG
|
||||
|
@ -6219,8 +6064,7 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
|
|||
/* If the first operand is a condition code, we can't do anything
|
||||
with it. */
|
||||
if (GET_CODE (XEXP (x, 0)) == COMPARE
|
||||
|| (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) != MODE_CC
|
||||
&& ! CC0_P (XEXP (x, 0))))
|
||||
|| GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) != MODE_CC)
|
||||
{
|
||||
rtx op0 = XEXP (x, 0);
|
||||
rtx op1 = XEXP (x, 1);
|
||||
|
@ -6833,12 +6677,9 @@ simplify_set (rtx x)
|
|||
SUBST (SET_SRC (x), src);
|
||||
}
|
||||
|
||||
/* If we are setting CC0 or if the source is a COMPARE, look for the use of
|
||||
the comparison result and try to simplify it unless we already have used
|
||||
undobuf.other_insn. */
|
||||
if ((GET_MODE_CLASS (mode) == MODE_CC
|
||||
|| GET_CODE (src) == COMPARE
|
||||
|| CC0_P (dest))
|
||||
/* If the source is a COMPARE, look for the use of the comparison result
|
||||
and try to simplify it unless we already have used undobuf.other_insn. */
|
||||
if ((GET_MODE_CLASS (mode) == MODE_CC || GET_CODE (src) == COMPARE)
|
||||
&& (cc_use = find_single_use (dest, subst_insn, &other_insn)) != 0
|
||||
&& (undobuf.other_insn == 0 || other_insn == undobuf.other_insn)
|
||||
&& COMPARISON_P (*cc_use)
|
||||
|
@ -6915,7 +6756,7 @@ simplify_set (rtx x)
|
|||
a hard register, just build new versions with the proper mode. If it
|
||||
is a pseudo, we lose unless it is only time we set the pseudo, in
|
||||
which case we can safely change its mode. */
|
||||
if (!HAVE_cc0 && compare_mode != GET_MODE (dest))
|
||||
if (compare_mode != GET_MODE (dest))
|
||||
{
|
||||
if (can_change_dest_mode (dest, 0, compare_mode))
|
||||
{
|
||||
|
@ -7039,24 +6880,6 @@ simplify_set (rtx x)
|
|||
src = SET_SRC (x), dest = SET_DEST (x);
|
||||
}
|
||||
|
||||
/* If we have (set (cc0) (subreg ...)), we try to remove the subreg
|
||||
in SRC. */
|
||||
if (dest == cc0_rtx
|
||||
&& partial_subreg_p (src)
|
||||
&& subreg_lowpart_p (src))
|
||||
{
|
||||
rtx inner = SUBREG_REG (src);
|
||||
machine_mode inner_mode = GET_MODE (inner);
|
||||
|
||||
/* Here we make sure that we don't have a sign bit on. */
|
||||
if (val_signbit_known_clear_p (GET_MODE (src),
|
||||
nonzero_bits (inner, inner_mode)))
|
||||
{
|
||||
SUBST (SET_SRC (x), inner);
|
||||
src = SET_SRC (x);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have (set FOO (subreg:M (mem:N BAR) 0)) with M wider than N, this
|
||||
would require a paradoxical subreg. Replace the subreg with a
|
||||
zero_extend to avoid the reload that would otherwise be required.
|
||||
|
@ -12250,7 +12073,6 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
|
|||
/* We can't do anything if OP0 is a condition code value, rather
|
||||
than an actual data value. */
|
||||
if (const_op != 0
|
||||
|| CC0_P (XEXP (op0, 0))
|
||||
|| GET_MODE_CLASS (GET_MODE (XEXP (op0, 0))) == MODE_CC)
|
||||
break;
|
||||
|
||||
|
@ -13935,9 +13757,6 @@ mark_used_regs_combine (rtx x)
|
|||
case ADDR_VEC:
|
||||
case ADDR_DIFF_VEC:
|
||||
case ASM_INPUT:
|
||||
/* CC0 must die in the insn after it is set, so we don't need to take
|
||||
special note of it here. */
|
||||
case CC0:
|
||||
return;
|
||||
|
||||
case CLOBBER:
|
||||
|
@ -14615,7 +14434,6 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2,
|
|||
{
|
||||
rtx set = single_set (tem_insn);
|
||||
rtx inner_dest = 0;
|
||||
rtx_insn *cc0_setter = NULL;
|
||||
|
||||
if (set != 0)
|
||||
for (inner_dest = SET_DEST (set);
|
||||
|
@ -14628,17 +14446,12 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2,
|
|||
/* Verify that it was the set, and not a clobber that
|
||||
modified the register.
|
||||
|
||||
CC0 targets must be careful to maintain setter/user
|
||||
pairs. If we cannot delete the setter due to side
|
||||
If we cannot delete the setter due to side
|
||||
effects, mark the user with an UNUSED note instead
|
||||
of deleting it. */
|
||||
|
||||
if (set != 0 && ! side_effects_p (SET_SRC (set))
|
||||
&& rtx_equal_p (XEXP (note, 0), inner_dest)
|
||||
&& (!HAVE_cc0
|
||||
|| (! reg_mentioned_p (cc0_rtx, SET_SRC (set))
|
||||
|| ((cc0_setter = prev_cc0_setter (tem_insn)) != NULL
|
||||
&& sets_cc0_p (PATTERN (cc0_setter)) > 0))))
|
||||
&& rtx_equal_p (XEXP (note, 0), inner_dest))
|
||||
{
|
||||
/* Move the notes and links of TEM_INSN elsewhere.
|
||||
This might delete other dead insns recursively.
|
||||
|
@ -14661,23 +14474,6 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2,
|
|||
SET_INSN_DELETED (tem_insn);
|
||||
if (tem_insn == i2)
|
||||
i2 = NULL;
|
||||
|
||||
/* Delete the setter too. */
|
||||
if (cc0_setter)
|
||||
{
|
||||
PATTERN (cc0_setter) = pc_rtx;
|
||||
old_notes = REG_NOTES (cc0_setter);
|
||||
REG_NOTES (cc0_setter) = NULL;
|
||||
|
||||
distribute_notes (old_notes, cc0_setter,
|
||||
cc0_setter, NULL,
|
||||
NULL_RTX, NULL_RTX, NULL_RTX);
|
||||
distribute_links (LOG_LINKS (cc0_setter));
|
||||
|
||||
SET_INSN_DELETED (cc0_setter);
|
||||
if (cc0_setter == i2)
|
||||
i2 = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -25,9 +25,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
cannot make use of the comparison elimination offered by the combine pass.
|
||||
|
||||
This is a small pass intended to provide comparison elimination similar to
|
||||
what is available via NOTICE_UPDATE_CC for cc0 targets. This should help
|
||||
encourage cc0 targets to convert to an explicit post-reload representation
|
||||
of the flags.
|
||||
what was available via NOTICE_UPDATE_CC for cc0 targets.
|
||||
|
||||
This pass assumes:
|
||||
|
||||
|
|
|
@ -20,46 +20,6 @@ along with GCC; see the file COPYING3. If not see
|
|||
#ifndef GCC_CONDITIONS_H
|
||||
#define GCC_CONDITIONS_H
|
||||
|
||||
/* The variable cc_status says how to interpret the condition code.
|
||||
It is set by output routines for an instruction that sets the cc's
|
||||
and examined by output routines for jump instructions.
|
||||
|
||||
cc_status contains two components named `value1' and `value2'
|
||||
that record two equivalent expressions for the values that the
|
||||
condition codes were set from. (Either or both may be null if
|
||||
there is no useful expression to record.) These fields are
|
||||
used for eliminating redundant test and compare instructions
|
||||
in the cases where the condition codes were already set by the
|
||||
previous instruction.
|
||||
|
||||
cc_status.flags contains flags which say that the condition codes
|
||||
were set in a nonstandard manner. The output of jump instructions
|
||||
uses these flags to compensate and produce the standard result
|
||||
with the nonstandard condition codes. Standard flags are defined here.
|
||||
The tm.h file can also define other machine-dependent flags.
|
||||
|
||||
cc_status also contains a machine-dependent component `mdep'
|
||||
whose type, `CC_STATUS_MDEP', may be defined as a macro in the
|
||||
tm.h file. */
|
||||
|
||||
#ifndef CC_STATUS_MDEP
|
||||
#define CC_STATUS_MDEP int
|
||||
#endif
|
||||
|
||||
#ifndef CC_STATUS_MDEP_INIT
|
||||
#define CC_STATUS_MDEP_INIT 0
|
||||
#endif
|
||||
|
||||
struct CC_STATUS {int flags; rtx value1, value2; CC_STATUS_MDEP mdep;};
|
||||
|
||||
/* While outputting an insn as assembler code,
|
||||
this is the status BEFORE that insn. */
|
||||
extern CC_STATUS cc_prev_status;
|
||||
|
||||
/* While outputting an insn as assembler code,
|
||||
this is being altered to the status AFTER that insn. */
|
||||
extern CC_STATUS cc_status;
|
||||
|
||||
/* These are the machine-independent flags: */
|
||||
|
||||
/* Set if the sign of the cc value is inverted:
|
||||
|
@ -106,13 +66,4 @@ extern CC_STATUS cc_status;
|
|||
This is only used by machine description files. */
|
||||
#define CC_NOT_SIGNED 0200
|
||||
|
||||
/* This is how to initialize the variable cc_status.
|
||||
final does this at appropriate moments. */
|
||||
|
||||
/* FIXME: We want to get rid of these ifndefs. */
|
||||
#ifndef CC_STATUS_INIT
|
||||
#define CC_STATUS_INIT \
|
||||
(cc_status.flags = 0, cc_status.value1 = 0, cc_status.value2 = 0, \
|
||||
CC_STATUS_MDEP_INIT)
|
||||
#endif
|
||||
#endif /* GCC_CONDITIONS_H */
|
||||
|
|
|
@ -36,7 +36,6 @@ extern const char *output_simode_bld (int, rtx[]);
|
|||
extern void final_prescan_insn (rtx_insn *, rtx *, int);
|
||||
extern int h8300_expand_movsi (rtx[]);
|
||||
extern machine_mode h8300_select_cc_mode (RTX_CODE, rtx, rtx);
|
||||
extern void notice_update_cc (rtx, rtx_insn *);
|
||||
extern const char *output_logical_op (machine_mode, rtx *);
|
||||
extern unsigned int compute_logical_op_length (machine_mode,
|
||||
rtx *);
|
||||
|
|
|
@ -569,13 +569,6 @@ struct cum_arg
|
|||
/* Here we define machine-dependent flags and fields in cc_status
|
||||
(see `conditions.h'). No extra ones are needed for the h8300. */
|
||||
|
||||
/* Store in cc_status the expressions
|
||||
that the condition codes will describe
|
||||
after execution of an instruction whose pattern is EXP.
|
||||
Do not alter them if the instruction would not alter the cc's. */
|
||||
|
||||
#define NOTICE_UPDATE_CC(EXP, INSN) notice_update_cc (EXP, INSN)
|
||||
|
||||
/* The add insns don't set overflow in a usable way. */
|
||||
#define CC_OVERFLOW_UNUSABLE 01000
|
||||
/* The mov,and,or,xor insns don't set carry. That's OK though as the
|
||||
|
|
|
@ -349,90 +349,6 @@
|
|||
(match_dup 1)))]
|
||||
"")
|
||||
|
||||
;; Turn
|
||||
;;
|
||||
;; subs #1,er4
|
||||
;; mov.w r4,r4
|
||||
;; bne .L2028
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; dec.w #1,r4
|
||||
;; bne .L2028
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand:HI 0 "register_operand" "")
|
||||
(plus:HI (match_dup 0)
|
||||
(match_operand 1 "incdec_operand" "")))
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "eqne_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
""
|
||||
[(set (match_operand:HI 0 "register_operand" "")
|
||||
(unspec:HI [(match_dup 0)
|
||||
(match_dup 1)]
|
||||
UNSPEC_INCDEC))
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_op_dup 4 [(cc0) (const_int 0)])
|
||||
(match_dup 2)
|
||||
(match_dup 3)))])
|
||||
|
||||
;; The SImode version of the previous pattern.
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand:SI 0 "register_operand" "")
|
||||
(plus:SI (match_dup 0)
|
||||
(match_operand 1 "incdec_operand" "")))
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "eqne_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
""
|
||||
[(set (match_operand:SI 0 "register_operand" "")
|
||||
(unspec:SI [(match_dup 0)
|
||||
(match_dup 1)]
|
||||
UNSPEC_INCDEC))
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_op_dup 4 [(cc0) (const_int 0)])
|
||||
(match_dup 2)
|
||||
(match_dup 3)))])
|
||||
|
||||
(define_peephole2
|
||||
[(parallel [(set (cc0)
|
||||
(compare (zero_extract:SI (match_operand:QI 0 "register_operand" "")
|
||||
(const_int 1)
|
||||
(const_int 7))
|
||||
(const_int 0)))
|
||||
(clobber (scratch:QI))])
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "eqne_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
""
|
||||
[(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_op_dup 4 [(cc0) (const_int 0)])
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[4] = ((GET_CODE (operands[4]) == EQ)
|
||||
? gen_rtx_GE (VOIDmode, cc0_rtx, const0_rtx)
|
||||
: gen_rtx_LT (VOIDmode, cc0_rtx, const0_rtx));
|
||||
})
|
||||
|
||||
;; If a load of mem:SI is followed by an AND that turns off the upper
|
||||
;; half, then we can load mem:HI instead.
|
||||
|
||||
|
@ -456,829 +372,6 @@
|
|||
operands[4] = gen_lowpart (HImode, operands[1]);
|
||||
})
|
||||
|
||||
;; (compare (reg:HI) (const_int)) takes 4 bytes, so we try to achieve
|
||||
;; the equivalent with shorter sequences. Here is the summary. Cases
|
||||
;; are grouped for each define_peephole2.
|
||||
;;
|
||||
;; reg const_int use insn
|
||||
;; --------------------------------------------------------
|
||||
;; dead -2 eq/ne inc.l
|
||||
;; dead -1 eq/ne inc.l
|
||||
;; dead 1 eq/ne dec.l
|
||||
;; dead 2 eq/ne dec.l
|
||||
;;
|
||||
;; dead 1 ge/lt shar.l
|
||||
;; dead 3 (H8S) ge/lt shar.l
|
||||
;;
|
||||
;; dead 1 geu/ltu shar.l
|
||||
;; dead 3 (H8S) geu/ltu shar.l
|
||||
;;
|
||||
;; ---- 255 ge/lt mov.b
|
||||
;;
|
||||
;; ---- 255 geu/ltu mov.b
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.w #1,r0
|
||||
;; bne .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; dec.w #1,r0
|
||||
;; bne .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:HI 0 "register_operand" "")
|
||||
(match_operand:HI 1 "incdec_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "eqne_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"INTVAL (operands[1]) != 0 && peep2_reg_dead_p (1, operands[0])"
|
||||
[(set (match_dup 0)
|
||||
(unspec:HI [(match_dup 0)
|
||||
(match_dup 5)]
|
||||
UNSPEC_INCDEC))
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_op_dup 4 [(cc0) (const_int 0)])
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[5] = GEN_INT (- INTVAL (operands[1]));
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.w #1,r0
|
||||
;; bgt .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; shar.w r0
|
||||
;; bgt .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:HI 0 "register_operand" "")
|
||||
(match_operand:HI 1 "const_int_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "gtle_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"peep2_reg_dead_p (1, operands[0])
|
||||
&& (INTVAL (operands[1]) == 1
|
||||
|| (TARGET_H8300S && INTVAL (operands[1]) == 3))"
|
||||
[(parallel [(set (match_dup 0)
|
||||
(ashiftrt:HI (match_dup 0)
|
||||
(match_dup 5)))
|
||||
(clobber (scratch:QI))])
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_dup 4)
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[5] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.w #1,r0
|
||||
;; bhi .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; shar.w r0
|
||||
;; bne .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:HI 0 "register_operand" "")
|
||||
(match_operand:HI 1 "const_int_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "gtuleu_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"peep2_reg_dead_p (1, operands[0])
|
||||
&& (INTVAL (operands[1]) == 1
|
||||
|| (TARGET_H8300S && INTVAL (operands[1]) == 3))"
|
||||
[(parallel [(set (match_dup 0)
|
||||
(ashiftrt:HI (match_dup 0)
|
||||
(match_dup 5)))
|
||||
(clobber (scratch:QI))])
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_dup 6)
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[5] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
|
||||
operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == GTU ? NE : EQ,
|
||||
VOIDmode, cc0_rtx, const0_rtx);
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.w #255,r0
|
||||
;; bgt .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; mov.b r0h,r0h
|
||||
;; bgt .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:HI 0 "register_operand" "")
|
||||
(const_int 255)))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 1 "gtle_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
""
|
||||
[(set (cc0) (compare (and:HI (match_dup 0)
|
||||
(const_int -256))
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_dup 1)
|
||||
(match_dup 2)
|
||||
(match_dup 3)))])
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.w #255,r0
|
||||
;; bhi .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; mov.b r0h,r0h
|
||||
;; bne .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:HI 0 "register_operand" "")
|
||||
(const_int 255)))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 1 "gtuleu_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
""
|
||||
[(set (cc0) (compare (and:HI (match_dup 0)
|
||||
(const_int -256))
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_dup 4)
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[1]) == GTU ? NE : EQ,
|
||||
VOIDmode, cc0_rtx, const0_rtx);
|
||||
})
|
||||
|
||||
;; (compare (reg:SI) (const_int)) takes 6 bytes, so we try to achieve
|
||||
;; the equivalent with shorter sequences. Here is the summary. Cases
|
||||
;; are grouped for each define_peephole2.
|
||||
;;
|
||||
;; reg const_int use insn
|
||||
;; --------------------------------------------------------
|
||||
;; live -2 eq/ne copy and inc.l
|
||||
;; live -1 eq/ne copy and inc.l
|
||||
;; live 1 eq/ne copy and dec.l
|
||||
;; live 2 eq/ne copy and dec.l
|
||||
;;
|
||||
;; dead -2 eq/ne inc.l
|
||||
;; dead -1 eq/ne inc.l
|
||||
;; dead 1 eq/ne dec.l
|
||||
;; dead 2 eq/ne dec.l
|
||||
;;
|
||||
;; dead -131072 eq/ne inc.w and test
|
||||
;; dead -65536 eq/ne inc.w and test
|
||||
;; dead 65536 eq/ne dec.w and test
|
||||
;; dead 131072 eq/ne dec.w and test
|
||||
;;
|
||||
;; dead 0x000000?? except 1 and 2 eq/ne xor.b and test
|
||||
;; dead 0x0000??00 eq/ne xor.b and test
|
||||
;; dead 0x0000ffff eq/ne not.w and test
|
||||
;;
|
||||
;; dead 0xffffff?? except -1 and -2 eq/ne xor.b and not.l
|
||||
;; dead 0xffff??ff eq/ne xor.b and not.l
|
||||
;; dead 0x40000000 (H8S) eq/ne rotl.l and dec.l
|
||||
;; dead 0x80000000 eq/ne rotl.l and dec.l
|
||||
;;
|
||||
;; live 1 ge/lt copy and shar.l
|
||||
;; live 3 (H8S) ge/lt copy and shar.l
|
||||
;;
|
||||
;; live 1 geu/ltu copy and shar.l
|
||||
;; live 3 (H8S) geu/ltu copy and shar.l
|
||||
;;
|
||||
;; dead 1 ge/lt shar.l
|
||||
;; dead 3 (H8S) ge/lt shar.l
|
||||
;;
|
||||
;; dead 1 geu/ltu shar.l
|
||||
;; dead 3 (H8S) geu/ltu shar.l
|
||||
;;
|
||||
;; dead 3 (H8/300H) ge/lt and.b and test
|
||||
;; dead 7 ge/lt and.b and test
|
||||
;; dead 15 ge/lt and.b and test
|
||||
;; dead 31 ge/lt and.b and test
|
||||
;; dead 63 ge/lt and.b and test
|
||||
;; dead 127 ge/lt and.b and test
|
||||
;; dead 255 ge/lt and.b and test
|
||||
;;
|
||||
;; dead 3 (H8/300H) geu/ltu and.b and test
|
||||
;; dead 7 geu/ltu and.b and test
|
||||
;; dead 15 geu/ltu and.b and test
|
||||
;; dead 31 geu/ltu and.b and test
|
||||
;; dead 63 geu/ltu and.b and test
|
||||
;; dead 127 geu/ltu and.b and test
|
||||
;; dead 255 geu/ltu and.b and test
|
||||
;;
|
||||
;; ---- 65535 ge/lt mov.w
|
||||
;;
|
||||
;; ---- 65535 geu/ltu mov.w
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #1,er0
|
||||
;; beq .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; dec.l #1,er0
|
||||
;; beq .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "incdec_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "eqne_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"INTVAL (operands[1]) != 0 && peep2_reg_dead_p (1, operands[0])"
|
||||
[(set (match_dup 0)
|
||||
(unspec:SI [(match_dup 0)
|
||||
(match_dup 5)]
|
||||
UNSPEC_INCDEC))
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_op_dup 4 [(cc0) (const_int 0)])
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[5] = GEN_INT (- INTVAL (operands[1]));
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #65536,er0
|
||||
;; beq .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; dec.l #1,e0
|
||||
;; beq .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "const_int_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "eqne_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"peep2_reg_dead_p (1, operands[0])
|
||||
&& (INTVAL (operands[1]) == -131072
|
||||
|| INTVAL (operands[1]) == -65536
|
||||
|| INTVAL (operands[1]) == 65536
|
||||
|| INTVAL (operands[1]) == 131072)"
|
||||
[(set (match_dup 0)
|
||||
(plus:SI (match_dup 0)
|
||||
(match_dup 5)))
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_op_dup 4 [(cc0) (const_int 0)])
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[5] = GEN_INT (- INTVAL (operands[1]));
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #100,er0
|
||||
;; beq .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; xor.b #100,er0
|
||||
;; mov.l er0,er0
|
||||
;; beq .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "const_int_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "eqne_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"peep2_reg_dead_p (1, operands[0])
|
||||
&& ((INTVAL (operands[1]) & 0x00ff) == INTVAL (operands[1])
|
||||
|| (INTVAL (operands[1]) & 0xff00) == INTVAL (operands[1])
|
||||
|| INTVAL (operands[1]) == 0x0000ffff)
|
||||
&& INTVAL (operands[1]) != 0
|
||||
&& INTVAL (operands[1]) != 1
|
||||
&& INTVAL (operands[1]) != 2"
|
||||
[(set (match_dup 0)
|
||||
(xor:SI (match_dup 0)
|
||||
(match_dup 1)))
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_op_dup 4 [(cc0) (const_int 0)])
|
||||
(match_dup 2)
|
||||
(match_dup 3)))])
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #-100,er0
|
||||
;; beq .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; xor.b #99,er0
|
||||
;; not.l er0
|
||||
;; beq .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "const_int_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "eqne_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"peep2_reg_dead_p (1, operands[0])
|
||||
&& ((INTVAL (operands[1]) | 0x00ff) == -1
|
||||
|| (INTVAL (operands[1]) | 0xff00) == -1)
|
||||
&& INTVAL (operands[1]) != -1
|
||||
&& INTVAL (operands[1]) != -2"
|
||||
[(set (match_dup 0)
|
||||
(xor:SI (match_dup 0)
|
||||
(match_dup 5)))
|
||||
(set (match_dup 0)
|
||||
(not:SI (match_dup 0)))
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_op_dup 4 [(cc0) (const_int 0)])
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[5] = GEN_INT (INTVAL (operands[1]) ^ -1);
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #-2147483648,er0
|
||||
;; beq .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; rotl.l er0
|
||||
;; dec.l #1,er0
|
||||
;; beq .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "const_int_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "eqne_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"peep2_reg_dead_p (1, operands[0])
|
||||
&& (INTVAL (operands[1]) == -2147483647 - 1
|
||||
|| (TARGET_H8300S && INTVAL (operands[1]) == 1073741824))"
|
||||
[(set (match_dup 0)
|
||||
(rotate:SI (match_dup 0)
|
||||
(match_dup 5)))
|
||||
(set (match_dup 0)
|
||||
(unspec:SI [(match_dup 0)
|
||||
(const_int -1)]
|
||||
UNSPEC_INCDEC))
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_op_dup 4 [(cc0) (const_int 0)])
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[5] = GEN_INT (INTVAL (operands[1]) == -2147483647 - 1 ? 1 : 2);
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #1,er0
|
||||
;; bgt .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; mov.l er0,er1
|
||||
;; shar.l er1
|
||||
;; bgt .L1
|
||||
|
||||
;; We avoid this transformation if we see more than one copy of the
|
||||
;; same compare insn immediately before this one.
|
||||
|
||||
(define_peephole2
|
||||
[(match_scratch:SI 5 "r")
|
||||
(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "const_int_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "gtle_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"!peep2_reg_dead_p (1, operands[0])
|
||||
&& (INTVAL (operands[1]) == 1
|
||||
|| (TARGET_H8300S && INTVAL (operands[1]) == 3))
|
||||
&& !same_cmp_preceding_p (insn)"
|
||||
[(set (match_dup 5)
|
||||
(match_dup 0))
|
||||
(parallel [(set (match_dup 5)
|
||||
(ashiftrt:SI (match_dup 5)
|
||||
(match_dup 6)))
|
||||
(clobber (scratch:QI))])
|
||||
(set (cc0) (compare (match_dup 5)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_dup 4)
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[6] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #1,er0
|
||||
;; bhi .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; mov.l er0,er1
|
||||
;; shar.l er1
|
||||
;; bne .L1
|
||||
|
||||
;; We avoid this transformation if we see more than one copy of the
|
||||
;; same compare insn immediately before this one.
|
||||
|
||||
(define_peephole2
|
||||
[(match_scratch:SI 5 "r")
|
||||
(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "const_int_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "gtuleu_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"!peep2_reg_dead_p (1, operands[0])
|
||||
&& (INTVAL (operands[1]) == 1
|
||||
|| (TARGET_H8300S && INTVAL (operands[1]) == 3))
|
||||
&& !same_cmp_preceding_p (insn)"
|
||||
[(set (match_dup 5)
|
||||
(match_dup 0))
|
||||
(parallel [(set (match_dup 5)
|
||||
(ashiftrt:SI (match_dup 5)
|
||||
(match_dup 6)))
|
||||
(clobber (scratch:QI))])
|
||||
(set (cc0) (compare (match_dup 5)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_dup 7)
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[6] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
|
||||
operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == GTU ? NE : EQ,
|
||||
VOIDmode, cc0_rtx, const0_rtx);
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #1,er0
|
||||
;; bgt .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; shar.l er0
|
||||
;; bgt .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "const_int_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "gtle_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"peep2_reg_dead_p (1, operands[0])
|
||||
&& (INTVAL (operands[1]) == 1
|
||||
|| (TARGET_H8300S && INTVAL (operands[1]) == 3))"
|
||||
[(parallel [(set (match_dup 0)
|
||||
(ashiftrt:SI (match_dup 0)
|
||||
(match_dup 5)))
|
||||
(clobber (scratch:QI))])
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_dup 4)
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[5] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #1,er0
|
||||
;; bhi .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; shar.l er0
|
||||
;; bne .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "const_int_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "gtuleu_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"peep2_reg_dead_p (1, operands[0])
|
||||
&& (INTVAL (operands[1]) == 1
|
||||
|| (TARGET_H8300S && INTVAL (operands[1]) == 3))"
|
||||
[(parallel [(set (match_dup 0)
|
||||
(ashiftrt:SI (match_dup 0)
|
||||
(match_dup 5)))
|
||||
(clobber (scratch:QI))])
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_dup 6)
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[5] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
|
||||
operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == GTU ? NE : EQ,
|
||||
VOIDmode, cc0_rtx, const0_rtx);
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #15,er0
|
||||
;; bgt .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; and #240,r0l
|
||||
;; mov.l er0,er0
|
||||
;; bgt .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "const_int_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "gtle_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"peep2_reg_dead_p (1, operands[0])
|
||||
&& (INTVAL (operands[1]) == 3
|
||||
|| INTVAL (operands[1]) == 7
|
||||
|| INTVAL (operands[1]) == 15
|
||||
|| INTVAL (operands[1]) == 31
|
||||
|| INTVAL (operands[1]) == 63
|
||||
|| INTVAL (operands[1]) == 127
|
||||
|| INTVAL (operands[1]) == 255)"
|
||||
[(set (match_dup 0)
|
||||
(and:SI (match_dup 0)
|
||||
(match_dup 5)))
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_dup 4)
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[5] = GEN_INT (~INTVAL (operands[1]));
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #15,er0
|
||||
;; bhi .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; and #240,r0l
|
||||
;; mov.l er0,er0
|
||||
;; bne .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "const_int_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "gtuleu_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"peep2_reg_dead_p (1, operands[0])
|
||||
&& ((TARGET_H8300H && INTVAL (operands[1]) == 3)
|
||||
|| INTVAL (operands[1]) == 7
|
||||
|| INTVAL (operands[1]) == 15
|
||||
|| INTVAL (operands[1]) == 31
|
||||
|| INTVAL (operands[1]) == 63
|
||||
|| INTVAL (operands[1]) == 127
|
||||
|| INTVAL (operands[1]) == 255)"
|
||||
[(set (match_dup 0)
|
||||
(and:SI (match_dup 0)
|
||||
(match_dup 5)))
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_dup 6)
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[5] = GEN_INT (~INTVAL (operands[1]));
|
||||
operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == GTU ? NE : EQ,
|
||||
VOIDmode, cc0_rtx, const0_rtx);
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #65535,er0
|
||||
;; bgt .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; mov.l e0,e0
|
||||
;; bgt .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(const_int 65535)))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 1 "gtle_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
""
|
||||
[(set (cc0) (compare (and:SI (match_dup 0)
|
||||
(const_int -65536))
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_dup 1)
|
||||
(match_dup 2)
|
||||
(match_dup 3)))])
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #65535,er0
|
||||
;; bhi .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; mov.l e0,e0
|
||||
;; bne .L1
|
||||
|
||||
(define_peephole2
|
||||
[(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(const_int 65535)))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 1 "gtuleu_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
""
|
||||
[(set (cc0) (compare (and:SI (match_dup 0)
|
||||
(const_int -65536))
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_dup 4)
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[1]) == GTU ? NE : EQ,
|
||||
VOIDmode, cc0_rtx, const0_rtx);
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; cmp.l #1,er0
|
||||
;; beq .L1
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; mov.l er0,er1
|
||||
;; dec.l #1,er1
|
||||
;; beq .L1
|
||||
|
||||
;; We avoid this transformation if we see more than one copy of the
|
||||
;; same compare insn.
|
||||
|
||||
(define_peephole2
|
||||
[(match_scratch:SI 5 "r")
|
||||
(set (cc0)
|
||||
(compare (match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "incdec_operand" "")))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "eqne_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"INTVAL (operands[1]) != 0
|
||||
&& !peep2_reg_dead_p (1, operands[0])
|
||||
&& !same_cmp_following_p (insn)"
|
||||
[(set (match_dup 5)
|
||||
(match_dup 0))
|
||||
(set (match_dup 5)
|
||||
(unspec:SI [(match_dup 5)
|
||||
(match_dup 6)]
|
||||
UNSPEC_INCDEC))
|
||||
(set (cc0) (compare (match_dup 5)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_op_dup 4 [(cc0) (const_int 0)])
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
operands[6] = GEN_INT (- INTVAL (operands[1]));
|
||||
})
|
||||
|
||||
;; Narrow the mode of testing if possible.
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand:HSI 0 "register_operand" "")
|
||||
(and:HSI (match_dup 0)
|
||||
(match_operand:HSI 1 "const_int_operand" "")))
|
||||
(set (cc0) (compare (match_dup 0)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_operator 4 "eqne_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
(match_operand 2 "pc_or_label_operand" "")
|
||||
(match_operand 3 "pc_or_label_operand" "")))]
|
||||
"((const_int_qi_operand (operands[1], QImode)
|
||||
|| (GET_MODE (operands[0]) == SImode
|
||||
&& const_int_hi_operand (operands[1], HImode)))
|
||||
&& peep2_reg_dead_p (2, operands[0]))"
|
||||
[(set (match_dup 5) (match_dup 7))
|
||||
(set (cc0) (compare (match_dup 5)
|
||||
(const_int 0)))
|
||||
(set (pc)
|
||||
(if_then_else (match_op_dup 4 [(cc0) (const_int 0)])
|
||||
(match_dup 2)
|
||||
(match_dup 3)))]
|
||||
{
|
||||
enum machine_mode mode;
|
||||
|
||||
mode = const_int_qi_operand (operands[1], QImode) ? QImode : HImode;
|
||||
operands[5] = gen_rtx_REG (mode, REGNO (operands[0]));
|
||||
operands[6] = gen_int_mode (INTVAL (operands[1]), mode);
|
||||
operands[7] = gen_rtx_AND (mode, operands[5], operands[6]);
|
||||
})
|
||||
|
||||
;; These triggers right at the end of allocation of locals in the
|
||||
;; prologue (and possibly at other places).
|
||||
|
||||
|
@ -1367,46 +460,6 @@
|
|||
XEXP (operands[4], 0) = operands[1];
|
||||
})
|
||||
|
||||
;; Transform
|
||||
;;
|
||||
;; mov src1,reg
|
||||
;; cmp reg,src2
|
||||
;;
|
||||
;; into
|
||||
;;
|
||||
;; cmp src1,src2
|
||||
;;
|
||||
;; if "reg" dies in the comparison.
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand 0 "register_operand" "")
|
||||
(match_operand 1 "h8300_dst_operand" ""))
|
||||
(set (cc0)
|
||||
(compare (match_dup 0)
|
||||
(match_operand 2 "h8300_src_operand" "")))]
|
||||
"TARGET_H8300SX
|
||||
&& peep2_reg_dead_p (2, operands[0])
|
||||
&& !reg_overlap_mentioned_p (operands[0], operands[2])
|
||||
&& operands[2] != const0_rtx"
|
||||
[(set (cc0)
|
||||
(compare (match_dup 1)
|
||||
(match_dup 2)))])
|
||||
|
||||
;; Likewise for the second operand.
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand 0 "register_operand" "")
|
||||
(match_operand 1 "h8300_src_operand" ""))
|
||||
(set (cc0)
|
||||
(compare (match_operand 2 "h8300_dst_operand" "")
|
||||
(match_dup 0)))]
|
||||
"TARGET_H8300SX
|
||||
&& peep2_reg_dead_p (2, operands[0])
|
||||
&& !reg_overlap_mentioned_p (operands[0], operands[2])"
|
||||
[(set (cc0)
|
||||
(compare (match_dup 2)
|
||||
(match_dup 1)))])
|
||||
|
||||
;; Combine two moves.
|
||||
|
||||
(define_peephole2
|
||||
|
|
|
@ -181,7 +181,6 @@ exact_dependency_1 (rtx addr, rtx insn)
|
|||
case SYMBOL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
case EXPR_LIST:
|
||||
return false;
|
||||
default:
|
||||
|
|
|
@ -1993,8 +1993,6 @@ m68k_output_btst (rtx countop, rtx dataop, rtx_code code, int signpos)
|
|||
count == 0 followed by bcc/bcs are also possible, but need
|
||||
m68k-specific CC_Z_IN_NOT_V and CC_Z_IN_NOT_C flags. */
|
||||
}
|
||||
|
||||
cc_status.flags = CC_NOT_NEGATIVE;
|
||||
}
|
||||
output_asm_insn ("btst %0,%1", ops);
|
||||
return code;
|
||||
|
|
|
@ -3854,7 +3854,6 @@ rl78_note_reg_uses (char *dead, rtx s, rtx insn)
|
|||
/* These codes have no constituent expressions
|
||||
and are unique. */
|
||||
case SCRATCH:
|
||||
case CC0:
|
||||
case PC:
|
||||
return;
|
||||
|
||||
|
|
|
@ -8809,7 +8809,6 @@ epilogue_renumber (rtx *where, int test)
|
|||
*where = gen_rtx_REG (GET_MODE (*where), OUTGOING_REGNO (REGNO(*where)));
|
||||
/* fallthrough */
|
||||
case SCRATCH:
|
||||
case CC0:
|
||||
case PC:
|
||||
case CONST_INT:
|
||||
case CONST_WIDE_INT:
|
||||
|
|
|
@ -898,7 +898,7 @@ gen_conditional_move (enum rtx_code code, machine_mode mode,
|
|||
code = GE;
|
||||
op1 = const0_rtx;
|
||||
}
|
||||
cmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
|
||||
cmp = gen_rtx_fmt_ee (code, VOIDmode, pc_rtx, const0_rtx);
|
||||
|
||||
if (boolean_operator (cmp, VOIDmode))
|
||||
{
|
||||
|
|
21
gcc/cprop.c
21
gcc/cprop.c
|
@ -963,10 +963,6 @@ cprop_jump (basic_block bb, rtx_insn *setcc, rtx_insn *jump, rtx from, rtx src)
|
|||
remove_note (jump, note);
|
||||
}
|
||||
|
||||
/* Delete the cc0 setter. */
|
||||
if (HAVE_cc0 && setcc != NULL && CC0_P (SET_DEST (single_set (setcc))))
|
||||
delete_insn (setcc);
|
||||
|
||||
global_const_prop_count++;
|
||||
if (dump_file != NULL)
|
||||
{
|
||||
|
@ -1009,15 +1005,15 @@ constprop_register (rtx from, rtx src, rtx_insn *insn)
|
|||
rtx sset;
|
||||
rtx_insn *next_insn;
|
||||
|
||||
/* Check for reg or cc0 setting instructions followed by
|
||||
conditional branch instructions first. */
|
||||
/* Check for reg setting instructions followed by conditional branch
|
||||
instructions first. */
|
||||
if ((sset = single_set (insn)) != NULL
|
||||
&& (next_insn = next_nondebug_insn (insn)) != NULL
|
||||
&& any_condjump_p (next_insn)
|
||||
&& onlyjump_p (next_insn))
|
||||
{
|
||||
rtx dest = SET_DEST (sset);
|
||||
if ((REG_P (dest) || CC0_P (dest))
|
||||
if (REG_P (dest)
|
||||
&& cprop_jump (BLOCK_FOR_INSN (insn), insn, next_insn,
|
||||
from, src))
|
||||
return 1;
|
||||
|
@ -1636,8 +1632,7 @@ bypass_block (basic_block bb, rtx_insn *setcc, rtx_insn *jump)
|
|||
/* Avoid unification of the edge with other edges from original
|
||||
branch. We would end up emitting the instruction on "both"
|
||||
edges. */
|
||||
if (dest && setcc && !CC0_P (SET_DEST (PATTERN (setcc)))
|
||||
&& find_edge (e->src, dest))
|
||||
if (dest && setcc && find_edge (e->src, dest))
|
||||
dest = NULL;
|
||||
|
||||
old_dest = e->dest;
|
||||
|
@ -1647,13 +1642,11 @@ bypass_block (basic_block bb, rtx_insn *setcc, rtx_insn *jump)
|
|||
{
|
||||
redirect_edge_and_branch_force (e, dest);
|
||||
|
||||
/* Copy the register setter to the redirected edge.
|
||||
Don't copy CC0 setters, as CC0 is dead after jump. */
|
||||
/* Copy the register setter to the redirected edge. */
|
||||
if (setcc)
|
||||
{
|
||||
rtx pat = PATTERN (setcc);
|
||||
if (!CC0_P (SET_DEST (pat)))
|
||||
insert_insn_on_edge (copy_insn (pat), e);
|
||||
insert_insn_on_edge (copy_insn (pat), e);
|
||||
}
|
||||
|
||||
if (dump_file != NULL)
|
||||
|
@ -1719,7 +1712,7 @@ bypass_conditional_jumps (void)
|
|||
break;
|
||||
|
||||
dest = SET_DEST (PATTERN (insn));
|
||||
if (REG_P (dest) || CC0_P (dest))
|
||||
if (REG_P (dest))
|
||||
setcc = insn;
|
||||
else
|
||||
break;
|
||||
|
|
140
gcc/cse.c
140
gcc/cse.c
|
@ -255,18 +255,6 @@ struct qty_table_elem
|
|||
/* The table of all qtys, indexed by qty number. */
|
||||
static struct qty_table_elem *qty_table;
|
||||
|
||||
/* For machines that have a CC0, we do not record its value in the hash
|
||||
table since its use is guaranteed to be the insn immediately following
|
||||
its definition and any other insn is presumed to invalidate it.
|
||||
|
||||
Instead, we store below the current and last value assigned to CC0.
|
||||
If it should happen to be a constant, it is stored in preference
|
||||
to the actual assigned value. In case it is a constant, we store
|
||||
the mode in which the constant should be interpreted. */
|
||||
|
||||
static rtx this_insn_cc0, prev_insn_cc0;
|
||||
static machine_mode this_insn_cc0_mode, prev_insn_cc0_mode;
|
||||
|
||||
/* Insn being scanned. */
|
||||
|
||||
static rtx_insn *this_insn;
|
||||
|
@ -348,9 +336,8 @@ static bool cse_jumps_altered;
|
|||
to put in the note. */
|
||||
static bool recorded_label_ref;
|
||||
|
||||
/* canon_hash stores 1 in do_not_record
|
||||
if it notices a reference to CC0, PC, or some other volatile
|
||||
subexpression. */
|
||||
/* canon_hash stores 1 in do_not_record if it notices a reference to PC or
|
||||
some other volatile subexpression. */
|
||||
|
||||
static int do_not_record;
|
||||
|
||||
|
@ -592,7 +579,7 @@ static struct cse_reg_info * get_cse_reg_info (unsigned int regno);
|
|||
|
||||
static void flush_hash_table (void);
|
||||
static bool insn_live_p (rtx_insn *, int *);
|
||||
static bool set_live_p (rtx, rtx_insn *, int *);
|
||||
static bool set_live_p (rtx, int *);
|
||||
static void cse_change_cc_mode_insn (rtx_insn *, rtx);
|
||||
static void cse_change_cc_mode_insns (rtx_insn *, rtx_insn *, rtx);
|
||||
static machine_mode cse_cc_succs (basic_block, basic_block, rtx, rtx,
|
||||
|
@ -854,8 +841,6 @@ new_basic_block (void)
|
|||
free_element_chain = first;
|
||||
}
|
||||
}
|
||||
|
||||
prev_insn_cc0 = 0;
|
||||
}
|
||||
|
||||
/* Say that register REG contains a quantity in mode MODE not in any
|
||||
|
@ -2448,7 +2433,6 @@ hash_rtx_cb (const_rtx x, machine_mode mode,
|
|||
case PRE_MODIFY:
|
||||
case POST_MODIFY:
|
||||
case PC:
|
||||
case CC0:
|
||||
case CALL:
|
||||
case UNSPEC_VOLATILE:
|
||||
if (do_not_record_p) {
|
||||
|
@ -2633,7 +2617,6 @@ exp_equiv_p (const_rtx x, const_rtx y, int validate, bool for_gcse)
|
|||
switch (code)
|
||||
{
|
||||
case PC:
|
||||
case CC0:
|
||||
CASE_CONST_UNIQUE:
|
||||
return x == y;
|
||||
|
||||
|
@ -2853,7 +2836,6 @@ canon_reg (rtx x, rtx_insn *insn)
|
|||
switch (code)
|
||||
{
|
||||
case PC:
|
||||
case CC0:
|
||||
case CONST:
|
||||
CASE_CONST_ANY:
|
||||
case SYMBOL_REF:
|
||||
|
@ -2909,9 +2891,9 @@ canon_reg (rtx x, rtx_insn *insn)
|
|||
what values are being compared.
|
||||
|
||||
*PARG1 and *PARG2 are updated to contain the rtx representing the values
|
||||
actually being compared. For example, if *PARG1 was (cc0) and *PARG2
|
||||
was (const_int 0), *PARG1 and *PARG2 will be set to the objects that were
|
||||
compared to produce cc0.
|
||||
actually being compared. For example, if *PARG1 was (reg:CC CC_REG) and
|
||||
*PARG2 was (const_int 0), *PARG1 and *PARG2 will be set to the objects that
|
||||
were compared to produce (reg:CC CC_REG).
|
||||
|
||||
The return value is the comparison operator and is either the code of
|
||||
A or the code corresponding to the inverse of the comparison. */
|
||||
|
@ -2943,10 +2925,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
|
|||
x = 0;
|
||||
}
|
||||
|
||||
/* If arg1 is a COMPARE, extract the comparison arguments from it.
|
||||
On machines with CC0, this is the only case that can occur, since
|
||||
fold_rtx will return the COMPARE or item being compared with zero
|
||||
when given CC0. */
|
||||
/* If arg1 is a COMPARE, extract the comparison arguments from it. */
|
||||
|
||||
if (GET_CODE (arg1) == COMPARE && arg2 == const0_rtx)
|
||||
x = arg1;
|
||||
|
@ -3179,9 +3158,6 @@ fold_rtx (rtx x, rtx_insn *insn)
|
|||
case EXPR_LIST:
|
||||
return x;
|
||||
|
||||
case CC0:
|
||||
return prev_insn_cc0;
|
||||
|
||||
case ASM_OPERANDS:
|
||||
if (insn)
|
||||
{
|
||||
|
@ -3232,30 +3208,6 @@ fold_rtx (rtx x, rtx_insn *insn)
|
|||
const_arg = folded_arg;
|
||||
break;
|
||||
|
||||
case CC0:
|
||||
/* The cc0-user and cc0-setter may be in different blocks if
|
||||
the cc0-setter potentially traps. In that case PREV_INSN_CC0
|
||||
will have been cleared as we exited the block with the
|
||||
setter.
|
||||
|
||||
While we could potentially track cc0 in this case, it just
|
||||
doesn't seem to be worth it given that cc0 targets are not
|
||||
terribly common or important these days and trapping math
|
||||
is rarely used. The combination of those two conditions
|
||||
necessary to trip this situation is exceedingly rare in the
|
||||
real world. */
|
||||
if (!prev_insn_cc0)
|
||||
{
|
||||
const_arg = NULL_RTX;
|
||||
}
|
||||
else
|
||||
{
|
||||
folded_arg = prev_insn_cc0;
|
||||
mode_arg = prev_insn_cc0_mode;
|
||||
const_arg = equiv_constant (folded_arg);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
folded_arg = fold_rtx (folded_arg, insn);
|
||||
const_arg = equiv_constant (folded_arg);
|
||||
|
@ -3910,10 +3862,7 @@ record_jump_equiv (rtx_insn *insn, bool taken)
|
|||
op0 = fold_rtx (XEXP (XEXP (SET_SRC (set), 0), 0), insn);
|
||||
op1 = fold_rtx (XEXP (XEXP (SET_SRC (set), 0), 1), insn);
|
||||
|
||||
/* On a cc0 target the cc0-setter and cc0-user may end up in different
|
||||
blocks. When that happens the tracking of the cc0-setter via
|
||||
PREV_INSN_CC0 is spoiled. That means that fold_rtx may return
|
||||
NULL_RTX. In those cases, there's nothing to record. */
|
||||
/* If fold_rtx returns NULL_RTX, there's nothing to record. */
|
||||
if (op0 == NULL_RTX || op1 == NULL_RTX)
|
||||
return;
|
||||
|
||||
|
@ -4555,9 +4504,6 @@ cse_insn (rtx_insn *insn)
|
|||
sets = XALLOCAVEC (struct set, XVECLEN (x, 0));
|
||||
|
||||
this_insn = insn;
|
||||
/* Records what this insn does to set CC0. */
|
||||
this_insn_cc0 = 0;
|
||||
this_insn_cc0_mode = VOIDmode;
|
||||
|
||||
/* Find all regs explicitly clobbered in this insn,
|
||||
to ensure they are not replaced with any other regs
|
||||
|
@ -5658,21 +5604,6 @@ cse_insn (rtx_insn *insn)
|
|||
sets[i].rtl = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If setting CC0, record what it was set to, or a constant, if it
|
||||
is equivalent to a constant. If it is being set to a floating-point
|
||||
value, make a COMPARE with the appropriate constant of 0. If we
|
||||
don't do this, later code can interpret this as a test against
|
||||
const0_rtx, which can cause problems if we try to put it into an
|
||||
insn as a floating-point operand. */
|
||||
if (dest == cc0_rtx)
|
||||
{
|
||||
this_insn_cc0 = src_const && mode != VOIDmode ? src_const : src;
|
||||
this_insn_cc0_mode = mode;
|
||||
if (FLOAT_MODE_P (mode))
|
||||
this_insn_cc0 = gen_rtx_COMPARE (VOIDmode, this_insn_cc0,
|
||||
CONST0_RTX (mode));
|
||||
}
|
||||
}
|
||||
|
||||
/* Now enter all non-volatile source expressions in the hash table
|
||||
|
@ -6594,34 +6525,6 @@ cse_extended_basic_block (struct cse_basic_block_data *ebb_data)
|
|||
if (INSN_P (insn) && !recorded_label_ref
|
||||
&& check_for_label_ref (insn))
|
||||
recorded_label_ref = true;
|
||||
|
||||
if (HAVE_cc0 && NONDEBUG_INSN_P (insn))
|
||||
{
|
||||
/* If the previous insn sets CC0 and this insn no
|
||||
longer references CC0, delete the previous insn.
|
||||
Here we use fact that nothing expects CC0 to be
|
||||
valid over an insn, which is true until the final
|
||||
pass. */
|
||||
rtx_insn *prev_insn;
|
||||
rtx tem;
|
||||
|
||||
prev_insn = prev_nonnote_nondebug_insn (insn);
|
||||
if (prev_insn && NONJUMP_INSN_P (prev_insn)
|
||||
&& (tem = single_set (prev_insn)) != NULL_RTX
|
||||
&& SET_DEST (tem) == cc0_rtx
|
||||
&& ! reg_mentioned_p (cc0_rtx, PATTERN (insn)))
|
||||
delete_insn (prev_insn);
|
||||
|
||||
/* If this insn is not the last insn in the basic
|
||||
block, it will be PREV_INSN(insn) in the next
|
||||
iteration. If we recorded any CC0-related
|
||||
information for this insn, remember it. */
|
||||
if (insn != BB_END (bb))
|
||||
{
|
||||
prev_insn_cc0 = this_insn_cc0;
|
||||
prev_insn_cc0_mode = this_insn_cc0_mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6670,10 +6573,6 @@ cse_extended_basic_block (struct cse_basic_block_data *ebb_data)
|
|||
bool taken = (next_bb == BRANCH_EDGE (bb)->dest);
|
||||
record_jump_equiv (insn, taken);
|
||||
}
|
||||
|
||||
/* Clear the CC0-tracking related insns, they can't provide
|
||||
useful information across basic block boundaries. */
|
||||
prev_insn_cc0 = 0;
|
||||
}
|
||||
|
||||
gcc_assert (next_qty <= max_qty);
|
||||
|
@ -6816,7 +6715,6 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
|
|||
return;
|
||||
|
||||
case PC:
|
||||
case CC0:
|
||||
case CONST:
|
||||
CASE_CONST_ANY:
|
||||
case SYMBOL_REF:
|
||||
|
@ -6925,23 +6823,15 @@ is_dead_reg (const_rtx x, int *counts)
|
|||
|
||||
/* Return true if set is live. */
|
||||
static bool
|
||||
set_live_p (rtx set, rtx_insn *insn ATTRIBUTE_UNUSED, /* Only used with HAVE_cc0. */
|
||||
int *counts)
|
||||
set_live_p (rtx set, int *counts)
|
||||
{
|
||||
rtx_insn *tem;
|
||||
|
||||
if (set_noop_p (set))
|
||||
;
|
||||
|
||||
else if (GET_CODE (SET_DEST (set)) == CC0
|
||||
&& !side_effects_p (SET_SRC (set))
|
||||
&& ((tem = next_nonnote_nondebug_insn (insn)) == NULL_RTX
|
||||
|| !INSN_P (tem)
|
||||
|| !reg_referenced_p (cc0_rtx, PATTERN (tem))))
|
||||
return false;
|
||||
else if (!is_dead_reg (SET_DEST (set), counts)
|
||||
|| side_effects_p (SET_SRC (set)))
|
||||
|
||||
if (!is_dead_reg (SET_DEST (set), counts)
|
||||
|| side_effects_p (SET_SRC (set)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -6954,7 +6844,7 @@ insn_live_p (rtx_insn *insn, int *counts)
|
|||
if (!cfun->can_delete_dead_exceptions && !insn_nothrow_p (insn))
|
||||
return true;
|
||||
else if (GET_CODE (PATTERN (insn)) == SET)
|
||||
return set_live_p (PATTERN (insn), insn, counts);
|
||||
return set_live_p (PATTERN (insn), counts);
|
||||
else if (GET_CODE (PATTERN (insn)) == PARALLEL)
|
||||
{
|
||||
for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
|
||||
|
@ -6963,7 +6853,7 @@ insn_live_p (rtx_insn *insn, int *counts)
|
|||
|
||||
if (GET_CODE (elt) == SET)
|
||||
{
|
||||
if (set_live_p (elt, insn, counts))
|
||||
if (set_live_p (elt, counts))
|
||||
return true;
|
||||
}
|
||||
else if (GET_CODE (elt) != CLOBBER && GET_CODE (elt) != USE)
|
||||
|
|
|
@ -1387,7 +1387,6 @@ cselib_hash_rtx (rtx x, int create, machine_mode memmode)
|
|||
return cselib_hash_rtx (XEXP (x, 0), create, memmode);
|
||||
|
||||
case PC:
|
||||
case CC0:
|
||||
case CALL:
|
||||
case UNSPEC_VOLATILE:
|
||||
return 0;
|
||||
|
@ -1827,7 +1826,6 @@ cselib_expand_value_rtx_1 (rtx orig, struct expand_value_data *evd,
|
|||
case SYMBOL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
case SCRATCH:
|
||||
/* SCRATCH must be shared because they represent distinct values. */
|
||||
return orig;
|
||||
|
|
|
@ -4255,8 +4255,7 @@ can_move_insns_across (rtx_insn *from, rtx_insn *to,
|
|||
if (bitmap_intersect_p (merge_set, test_use)
|
||||
|| bitmap_intersect_p (merge_use, test_set))
|
||||
break;
|
||||
if (!HAVE_cc0 || !sets_cc0_p (insn))
|
||||
max_to = insn;
|
||||
max_to = insn;
|
||||
}
|
||||
next = NEXT_INSN (insn);
|
||||
if (insn == to)
|
||||
|
@ -4293,8 +4292,7 @@ can_move_insns_across (rtx_insn *from, rtx_insn *to,
|
|||
{
|
||||
if (NONDEBUG_INSN_P (insn))
|
||||
{
|
||||
if (!bitmap_intersect_p (test_set, local_merge_live)
|
||||
&& (!HAVE_cc0 || !sets_cc0_p (insn)))
|
||||
if (!bitmap_intersect_p (test_set, local_merge_live))
|
||||
{
|
||||
max_to = insn;
|
||||
break;
|
||||
|
|
|
@ -2816,7 +2816,6 @@ df_uses_record (class df_collection_rec *collection_rec,
|
|||
case CONST:
|
||||
CASE_CONST_ANY:
|
||||
case PC:
|
||||
case CC0:
|
||||
case ADDR_VEC:
|
||||
case ADDR_DIFF_VEC:
|
||||
return;
|
||||
|
@ -2902,7 +2901,6 @@ df_uses_record (class df_collection_rec *collection_rec,
|
|||
case PARALLEL:
|
||||
case SCRATCH:
|
||||
case PC:
|
||||
case CC0:
|
||||
break;
|
||||
case MEM:
|
||||
df_uses_record (collection_rec, &XEXP (dst, 0),
|
||||
|
|
|
@ -7071,7 +7071,7 @@ such as
|
|||
[(set (pc)
|
||||
(if_then_else (match_operator
|
||||
0 "comparison_operator"
|
||||
[(cc0) (const_int 0)])
|
||||
[(reg:CC CC_REG) (const_int 0)])
|
||||
(return)
|
||||
(pc)))]
|
||||
"@var{condition}"
|
||||
|
@ -7989,15 +7989,8 @@ works better when different sets of comparison operators are supported
|
|||
by different kinds of conditional branches (e.g.@: integer vs.@:
|
||||
floating-point), or by conditional branches with respect to conditional stores.
|
||||
|
||||
Two separate insns are always used if the machine description represents
|
||||
a condition code register using the legacy RTL expression @code{(cc0)},
|
||||
and on most machines that use a separate condition code register
|
||||
(@pxref{Condition Code}). For machines that use @code{(cc0)}, in
|
||||
fact, the set and use of the condition code must be separate and
|
||||
adjacent@footnote{@code{note} insns can separate them, though.}, thus
|
||||
allowing flags in @code{cc_status} to be used (@pxref{Condition Code}) and
|
||||
so that the comparison and branch insns could be located from each other
|
||||
by using the functions @code{prev_cc0_setter} and @code{next_cc0_user}.
|
||||
Two separate insns are always used on most machines that use a separate
|
||||
condition code register (@pxref{Condition Code}).
|
||||
|
||||
Even in this case having a single entry point for conditional branches
|
||||
is advantageous, because it handles equally well the case where a single
|
||||
|
@ -8191,7 +8184,7 @@ the operations as far as possible. For instance,
|
|||
@cindex @code{compare}, canonicalization of
|
||||
@item
|
||||
For the @code{compare} operator, a constant is always the second operand
|
||||
if the first argument is a condition code register or @code{(cc0)}.
|
||||
if the first argument is a condition code register.
|
||||
|
||||
@item
|
||||
For instructions that inherently set a condition code register, the
|
||||
|
@ -9330,8 +9323,7 @@ In addition to describing the instruction supported by the target machine,
|
|||
the @file{md} file also defines a group of @dfn{attributes} and a set of
|
||||
values for each. Every generated insn is assigned a value for each attribute.
|
||||
One possible attribute would be the effect that the insn has on the machine's
|
||||
condition code. This attribute can then be used by @code{NOTICE_UPDATE_CC}
|
||||
to track the condition codes.
|
||||
condition code.
|
||||
|
||||
@menu
|
||||
* Defining Attributes:: Specifying attributes and their values.
|
||||
|
|
152
gcc/doc/rtl.texi
152
gcc/doc/rtl.texi
|
@ -1271,8 +1271,7 @@ accumulator. The default format is ``64.64''.
|
|||
``Condition Code'' mode represents the value of a condition code, which
|
||||
is a machine-specific set of bits used to represent the result of a
|
||||
comparison operation. Other machine-specific modes may also be used for
|
||||
the condition code. These modes are not used on machines that use
|
||||
@code{cc0} (@pxref{Condition Code}).
|
||||
the condition code. (@pxref{Condition Code}).
|
||||
|
||||
@findex BLKmode
|
||||
@item BLKmode
|
||||
|
@ -2324,60 +2323,17 @@ the reload pass.
|
|||
@code{scratch} is usually present inside a @code{clobber} operation
|
||||
(@pxref{Side Effects}).
|
||||
|
||||
@findex cc0
|
||||
@cindex condition code register
|
||||
@item (cc0)
|
||||
This refers to the machine's condition code register. It has no
|
||||
operands and may not have a machine mode. There are two ways to use it:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
To stand for a complete set of condition code flags. This is best on
|
||||
most machines, where each comparison sets the entire series of flags.
|
||||
|
||||
With this technique, @code{(cc0)} may be validly used in only two
|
||||
contexts: as the destination of an assignment (in test and compare
|
||||
instructions) and in comparison operators comparing against zero
|
||||
(@code{const_int} with value zero; that is to say, @code{const0_rtx}).
|
||||
|
||||
@item
|
||||
To stand for a single flag that is the result of a single condition.
|
||||
This is useful on machines that have only a single flag bit, and in
|
||||
which comparison instructions must specify the condition to test.
|
||||
|
||||
With this technique, @code{(cc0)} may be validly used in only two
|
||||
contexts: as the destination of an assignment (in test and compare
|
||||
instructions) where the source is a comparison operator, and as the
|
||||
first operand of @code{if_then_else} (in a conditional branch).
|
||||
@end itemize
|
||||
|
||||
@findex cc0_rtx
|
||||
There is only one expression object of code @code{cc0}; it is the
|
||||
value of the variable @code{cc0_rtx}. Any attempt to create an
|
||||
expression of code @code{cc0} will return @code{cc0_rtx}.
|
||||
|
||||
Instructions can set the condition code implicitly. On many machines,
|
||||
nearly all instructions set the condition code based on the value that
|
||||
they compute or store. It is not necessary to record these actions
|
||||
explicitly in the RTL because the machine description includes a
|
||||
prescription for recognizing the instructions that do so (by means of
|
||||
the macro @code{NOTICE_UPDATE_CC}). @xref{Condition Code}. Only
|
||||
instructions whose sole purpose is to set the condition code, and
|
||||
instructions that use the condition code, need mention @code{(cc0)}.
|
||||
|
||||
On some machines, the condition code register is given a register number
|
||||
and a @code{reg} is used instead of @code{(cc0)}. This is usually the
|
||||
preferable approach if only a small subset of instructions modify the
|
||||
condition code. Other machines store condition codes in general
|
||||
and a @code{reg} is used.
|
||||
Other machines store condition codes in general
|
||||
registers; in such cases a pseudo register should be used.
|
||||
|
||||
Some machines, such as the SPARC and RS/6000, have two sets of
|
||||
arithmetic instructions, one that sets and one that does not set the
|
||||
condition code. This is best handled by normally generating the
|
||||
instruction that does not set the condition code, and making a pattern
|
||||
that both performs the arithmetic and sets the condition code register
|
||||
(which would not be @code{(cc0)} in this case). For examples, search
|
||||
for @samp{addcc} and @samp{andcc} in @file{sparc.md}.
|
||||
that both performs the arithmetic and sets the condition code register.
|
||||
For examples, search for @samp{addcc} and @samp{andcc} in @file{sparc.md}.
|
||||
|
||||
@findex pc
|
||||
@item (pc)
|
||||
|
@ -2495,14 +2451,13 @@ Of course, machines cannot really subtract with infinite precision.
|
|||
However, they can pretend to do so when only the sign of the result will
|
||||
be used, which is the case when the result is stored in the condition
|
||||
code. And that is the @emph{only} way this kind of expression may
|
||||
validly be used: as a value to be stored in the condition codes, either
|
||||
@code{(cc0)} or a register. @xref{Comparisons}.
|
||||
validly be used: as a value to be stored in the condition codes, in a
|
||||
register. @xref{Comparisons}.
|
||||
|
||||
The mode @var{m} is not related to the modes of @var{x} and @var{y}, but
|
||||
instead is the mode of the condition code value. If @code{(cc0)} is
|
||||
used, it is @code{VOIDmode}. Otherwise it is some mode in class
|
||||
instead is the mode of the condition code value. It is some mode in class
|
||||
@code{MODE_CC}, often @code{CCmode}. @xref{Condition Code}. If @var{m}
|
||||
is @code{VOIDmode} or @code{CCmode}, the operation returns sufficient
|
||||
is @code{CCmode}, the operation returns sufficient
|
||||
information (in an unspecified format) so that any comparison operator
|
||||
can be applied to the result of the @code{COMPARE} operation. For other
|
||||
modes in class @code{MODE_CC}, the operation only returns a subset of
|
||||
|
@ -2797,26 +2752,17 @@ of the data being compared. If the comparison operation is being tested
|
|||
@code{VOIDmode}.
|
||||
|
||||
@cindex condition codes
|
||||
There are two ways that comparison operations may be used. The
|
||||
comparison operators may be used to compare the condition codes
|
||||
@code{(cc0)} against zero, as in @code{(eq (cc0) (const_int 0))}. Such
|
||||
a construct actually refers to the result of the preceding instruction
|
||||
in which the condition codes were set. The instruction setting the
|
||||
condition code must be adjacent to the instruction using the condition
|
||||
code; only @code{note} insns may separate them.
|
||||
|
||||
Alternatively, a comparison operation may directly compare two data
|
||||
A comparison operation compares two data
|
||||
objects. The mode of the comparison is determined by the operands; they
|
||||
must both be valid for a common machine mode. A comparison with both
|
||||
operands constant would be invalid as the machine mode could not be
|
||||
deduced from it, but such a comparison should never exist in RTL due to
|
||||
constant folding.
|
||||
|
||||
In the example above, if @code{(cc0)} were last set to
|
||||
@code{(compare @var{x} @var{y})}, the comparison operation is
|
||||
identical to @code{(eq @var{x} @var{y})}. Usually only one style
|
||||
Usually only one style
|
||||
of comparisons is supported on a particular machine, but the combine
|
||||
pass will try to merge the operations to produce the @code{eq} shown
|
||||
pass will try to merge operations to produce code like
|
||||
@code{(eq @var{x} @var{y})},
|
||||
in case it exists in the context of the particular insn involved.
|
||||
|
||||
Inequality comparisons come in two flavors, signed and unsigned. Thus,
|
||||
|
@ -3168,7 +3114,7 @@ Represents the action of storing the value of @var{x} into the place
|
|||
represented by @var{lval}. @var{lval} must be an expression
|
||||
representing a place that can be stored in: @code{reg} (or @code{subreg},
|
||||
@code{strict_low_part} or @code{zero_extract}), @code{mem}, @code{pc},
|
||||
@code{parallel}, or @code{cc0}.
|
||||
or @code{parallel}.
|
||||
|
||||
If @var{lval} is a @code{reg}, @code{subreg} or @code{mem}, it has a
|
||||
machine mode; then @var{x} must be valid for that mode.
|
||||
|
@ -3191,13 +3137,6 @@ the bit-field (a memory or register reference) specified by the
|
|||
bit-field is not changed. Note that @code{sign_extract} cannot
|
||||
appear in @var{lval}.
|
||||
|
||||
If @var{lval} is @code{(cc0)}, it has no machine mode, and @var{x} may
|
||||
be either a @code{compare} expression or a value that may have any mode.
|
||||
The latter case represents a ``test'' instruction. The expression
|
||||
@code{(set (cc0) (reg:@var{m} @var{n}))} is equivalent to
|
||||
@code{(set (cc0) (compare (reg:@var{m} @var{n}) (const_int 0)))}.
|
||||
Use the former expression to save space during the compilation.
|
||||
|
||||
If @var{lval} is a @code{parallel}, it is used to represent the case of
|
||||
a function returning a structure in multiple registers. Each element
|
||||
of the @code{parallel} is an @code{expr_list} whose first operand is a
|
||||
|
@ -3219,7 +3158,7 @@ does not jump) and the other of the two must be a @code{label_ref}
|
|||
@code{mem}; these unusual patterns are used to represent jumps through
|
||||
branch tables.
|
||||
|
||||
If @var{lval} is neither @code{(cc0)} nor @code{(pc)}, the mode of
|
||||
If @var{lval} is not @code{(pc)}, the mode of
|
||||
@var{lval} must not be @code{VOIDmode} and the mode of @var{x} must be
|
||||
valid for the mode of @var{lval}.
|
||||
|
||||
|
@ -3402,9 +3341,9 @@ For example, people sometimes attempt to represent a jump-if-zero
|
|||
instruction this way:
|
||||
|
||||
@smallexample
|
||||
(parallel [(set (cc0) (reg:SI 34))
|
||||
(parallel [(set (reg:CC CC_REG) (reg:SI 34))
|
||||
(set (pc) (if_then_else
|
||||
(eq (cc0) (const_int 0))
|
||||
(eq (reg:CC CC_REG) (const_int 0))
|
||||
(label_ref @dots{})
|
||||
(pc)))])
|
||||
@end smallexample
|
||||
|
@ -3421,8 +3360,6 @@ whose elements are the operands needed to output the resulting
|
|||
assembler code---often @code{reg}, @code{mem} or constant expressions.
|
||||
This would not be well-formed RTL at any other stage in compilation,
|
||||
but it is OK then because no further optimization remains to be done.
|
||||
However, the definition of the macro @code{NOTICE_UPDATE_CC}, if
|
||||
any, must deal with such insns if you define any peephole optimizations.
|
||||
|
||||
@findex cond_exec
|
||||
@item (cond_exec [@var{cond} @var{expr}])
|
||||
|
@ -4101,14 +4038,6 @@ In the debugging output, this field is printed as a number followed by
|
|||
a symbolic representation that locates the pattern in the @file{md}
|
||||
file as some small positive or negative offset from a named pattern.
|
||||
|
||||
@findex LOG_LINKS
|
||||
@item LOG_LINKS (@var{i})
|
||||
A list (chain of @code{insn_list} expressions) giving information about
|
||||
dependencies between instructions within a basic block. Neither a jump
|
||||
nor a label may come between the related insns. These are only used by
|
||||
the schedulers and by combine. This is a deprecated data structure.
|
||||
Def-use and use-def chains are now preferred.
|
||||
|
||||
@findex REG_NOTES
|
||||
@item REG_NOTES (@var{i})
|
||||
A list (chain of @code{expr_list}, @code{insn_list} and @code{int_list}
|
||||
|
@ -4116,23 +4045,9 @@ expressions) giving miscellaneous information about the insn. It is often
|
|||
information pertaining to the registers used in this insn.
|
||||
@end table
|
||||
|
||||
The @code{LOG_LINKS} field of an insn is a chain of @code{insn_list}
|
||||
expressions. Each of these has two operands: the first is an insn,
|
||||
and the second is another @code{insn_list} expression (the next one in
|
||||
the chain). The last @code{insn_list} in the chain has a null pointer
|
||||
as second operand. The significant thing about the chain is which
|
||||
insns appear in it (as first operands of @code{insn_list}
|
||||
expressions). Their order is not significant.
|
||||
|
||||
This list is originally set up by the flow analysis pass; it is a null
|
||||
pointer until then. Flow only adds links for those data dependencies
|
||||
which can be used for instruction combination. For each insn, the flow
|
||||
analysis pass adds a link to insns which store into registers values
|
||||
that are used for the first time in this insn.
|
||||
|
||||
The @code{REG_NOTES} field of an insn is a chain similar to the
|
||||
@code{LOG_LINKS} field but it includes @code{expr_list} and @code{int_list}
|
||||
expressions in addition to @code{insn_list} expressions. There are several
|
||||
The @code{REG_NOTES} field of an insn is a chain that includes
|
||||
@code{expr_list} and @code{int_list} expressions as well as @code{insn_list}
|
||||
expressions. There are several
|
||||
kinds of register notes, which are distinguished by the machine mode, which
|
||||
in a register note is really understood as being an @code{enum reg_note}.
|
||||
The first operand @var{op} of the note is data whose meaning depends on
|
||||
|
@ -4147,8 +4062,7 @@ register note. Its counterpart, the macro @code{PUT_REG_NOTE_KIND
|
|||
|
||||
Register notes are of three classes: They may say something about an
|
||||
input to an insn, they may say something about an output of an insn, or
|
||||
they may create a linkage between two insns. There are also a set
|
||||
of values that are only used in @code{LOG_LINKS}.
|
||||
they may create a linkage between two insns.
|
||||
|
||||
These register notes annotate inputs to an insn:
|
||||
|
||||
|
@ -4289,26 +4203,6 @@ These notes describe linkages between insns. They occur in pairs: one
|
|||
insn has one of a pair of notes that points to a second insn, which has
|
||||
the inverse note pointing back to the first insn.
|
||||
|
||||
@table @code
|
||||
@findex REG_CC_SETTER
|
||||
@findex REG_CC_USER
|
||||
@item REG_CC_SETTER
|
||||
@itemx REG_CC_USER
|
||||
On machines that use @code{cc0}, the insns which set and use @code{cc0}
|
||||
set and use @code{cc0} are adjacent. However, when branch delay slot
|
||||
filling is done, this may no longer be true. In this case a
|
||||
@code{REG_CC_USER} note will be placed on the insn setting @code{cc0} to
|
||||
point to the insn using @code{cc0} and a @code{REG_CC_SETTER} note will
|
||||
be placed on the insn using @code{cc0} to point to the insn setting
|
||||
@code{cc0}.
|
||||
@end table
|
||||
|
||||
These values are only used in the @code{LOG_LINKS} field, and indicate
|
||||
the type of dependency that each link represents. Links which indicate
|
||||
a data dependence (a read after write dependence) do not use any code,
|
||||
they simply have mode @code{VOIDmode}, and are printed without any
|
||||
descriptive text.
|
||||
|
||||
@table @code
|
||||
@findex REG_DEP_TRUE
|
||||
@item REG_DEP_TRUE
|
||||
|
@ -5272,10 +5166,6 @@ are shared.
|
|||
@item
|
||||
There is only one @code{pc} expression.
|
||||
|
||||
@cindex @code{cc0}, RTL sharing
|
||||
@item
|
||||
There is only one @code{cc0} expression.
|
||||
|
||||
@cindex @code{const_double}, RTL sharing
|
||||
@item
|
||||
There is only one @code{const_double} expression with value 0 for
|
||||
|
|
|
@ -6310,21 +6310,16 @@ or target-specific sections.
|
|||
@section Condition Code Status
|
||||
@cindex condition code status
|
||||
|
||||
The macros in this section can be split in two families, according to the
|
||||
two ways of representing condition codes in GCC.
|
||||
|
||||
The first representation is the so called @code{(cc0)} representation
|
||||
(@pxref{Jump Patterns}), where all instructions can have an implicit
|
||||
clobber of the condition codes. The second is the condition code
|
||||
register representation, which provides better schedulability for
|
||||
Condition codes in GCC are represented as registers,
|
||||
which provides better schedulability for
|
||||
architectures that do have a condition code register, but on which
|
||||
most instructions do not affect it. The latter category includes
|
||||
most RISC machines.
|
||||
|
||||
The implicit clobbering poses a strong restriction on the placement of
|
||||
Implicit clobbering would pose a strong restriction on the placement of
|
||||
the definition and use of the condition code. In the past the definition
|
||||
and use were always adjacent. However, recent changes to support trapping
|
||||
arithmatic may result in the definition and user being in different blocks.
|
||||
arithmetic may result in the definition and user being in different blocks.
|
||||
Thus, there may be a @code{NOTE_INSN_BASIC_BLOCK} between them. Additionally,
|
||||
the definition may be the source of exception handling edges.
|
||||
|
||||
|
@ -6335,8 +6330,7 @@ three instructions earlier than the conditional branch. The instruction
|
|||
scheduler cannot perform this optimization if it is not permitted to
|
||||
separate the definition and use of the condition code register.
|
||||
|
||||
For this reason, it is possible and suggested to use a register to
|
||||
represent the condition code for new ports. If there is a specific
|
||||
If there is a specific
|
||||
condition code register in the machine, use a hard register. If the
|
||||
condition code or comparison result can be placed in any general register,
|
||||
or if there are multiple condition registers, use a pseudo register.
|
||||
|
@ -6348,78 +6342,9 @@ specified already in the compare instruction. In this case, you are not
|
|||
interested in most macros in this section.
|
||||
|
||||
@menu
|
||||
* CC0 Condition Codes:: Old style representation of condition codes.
|
||||
* MODE_CC Condition Codes:: Modern representation of condition codes.
|
||||
@end menu
|
||||
|
||||
@node CC0 Condition Codes
|
||||
@subsection Representation of condition codes using @code{(cc0)}
|
||||
@findex cc0
|
||||
|
||||
@findex cc_status
|
||||
The file @file{conditions.h} defines a variable @code{cc_status} to
|
||||
describe how the condition code was computed (in case the interpretation of
|
||||
the condition code depends on the instruction that it was set by). This
|
||||
variable contains the RTL expressions on which the condition code is
|
||||
currently based, and several standard flags.
|
||||
|
||||
Sometimes additional machine-specific flags must be defined in the machine
|
||||
description header file. It can also add additional machine-specific
|
||||
information by defining @code{CC_STATUS_MDEP}.
|
||||
|
||||
@defmac CC_STATUS_MDEP
|
||||
C code for a data type which is used for declaring the @code{mdep}
|
||||
component of @code{cc_status}. It defaults to @code{int}.
|
||||
|
||||
This macro is not used on machines that do not use @code{cc0}.
|
||||
@end defmac
|
||||
|
||||
@defmac CC_STATUS_MDEP_INIT
|
||||
A C expression to initialize the @code{mdep} field to ``empty''.
|
||||
The default definition does nothing, since most machines don't use
|
||||
the field anyway. If you want to use the field, you should probably
|
||||
define this macro to initialize it.
|
||||
|
||||
This macro is not used on machines that do not use @code{cc0}.
|
||||
@end defmac
|
||||
|
||||
@defmac NOTICE_UPDATE_CC (@var{exp}, @var{insn})
|
||||
A C compound statement to set the components of @code{cc_status}
|
||||
appropriately for an insn @var{insn} whose body is @var{exp}. It is
|
||||
this macro's responsibility to recognize insns that set the condition
|
||||
code as a byproduct of other activity as well as those that explicitly
|
||||
set @code{(cc0)}.
|
||||
|
||||
This macro is not used on machines that do not use @code{cc0}.
|
||||
|
||||
If there are insns that do not set the condition code but do alter
|
||||
other machine registers, this macro must check to see whether they
|
||||
invalidate the expressions that the condition code is recorded as
|
||||
reflecting. For example, on the 68000, insns that store in address
|
||||
registers do not set the condition code, which means that usually
|
||||
@code{NOTICE_UPDATE_CC} can leave @code{cc_status} unaltered for such
|
||||
insns. But suppose that the previous insn set the condition code
|
||||
based on location @samp{a4@@(102)} and the current insn stores a new
|
||||
value in @samp{a4}. Although the condition code is not changed by
|
||||
this, it will no longer be true that it reflects the contents of
|
||||
@samp{a4@@(102)}. Therefore, @code{NOTICE_UPDATE_CC} must alter
|
||||
@code{cc_status} in this case to say that nothing is known about the
|
||||
condition code value.
|
||||
|
||||
The definition of @code{NOTICE_UPDATE_CC} must be prepared to deal
|
||||
with the results of peephole optimization: insns whose patterns are
|
||||
@code{parallel} RTXs containing various @code{reg}, @code{mem} or
|
||||
constants which are just the operands. The RTL structure of these
|
||||
insns is not sufficient to indicate what the insns actually do. What
|
||||
@code{NOTICE_UPDATE_CC} should do when it sees one is just to run
|
||||
@code{CC_STATUS_INIT}.
|
||||
|
||||
A possible definition of @code{NOTICE_UPDATE_CC} is to call a function
|
||||
that looks at an attribute (@pxref{Insn Attributes}) named, for example,
|
||||
@samp{cc}. This avoids having detailed information about patterns in
|
||||
two places, the @file{md} file and in @code{NOTICE_UPDATE_CC}.
|
||||
@end defmac
|
||||
|
||||
@node MODE_CC Condition Codes
|
||||
@subsection Representation of condition codes using registers
|
||||
@findex CCmode
|
||||
|
@ -6534,7 +6459,7 @@ like:
|
|||
@end defmac
|
||||
|
||||
@deftypefn {Target Hook} bool TARGET_FIXED_CONDITION_CODE_REGS (unsigned int *@var{p1}, unsigned int *@var{p2})
|
||||
On targets which do not use @code{(cc0)}, and which use a hard
|
||||
On targets which use a hard
|
||||
register rather than a pseudo-register to hold condition codes, the
|
||||
regular CSE passes are often not able to identify cases in which the
|
||||
hard register is set to a common value. Use this hook to enable a
|
||||
|
@ -11578,8 +11503,7 @@ for cross-profiling.
|
|||
|
||||
A C expression for the maximum number of instructions to execute via
|
||||
conditional execution instructions instead of a branch. A value of
|
||||
@code{BRANCH_COST}+1 is the default if the machine does not use cc0, and
|
||||
1 if it does use cc0.
|
||||
@code{BRANCH_COST}+1 is the default.
|
||||
@end defmac
|
||||
|
||||
@defmac IFCVT_MODIFY_TESTS (@var{ce_info}, @var{true_expr}, @var{false_expr})
|
||||
|
|
|
@ -4268,21 +4268,16 @@ or @code{TARGET_MAX_ANCHOR_OFFSET} is set to a nonzero value.
|
|||
@section Condition Code Status
|
||||
@cindex condition code status
|
||||
|
||||
The macros in this section can be split in two families, according to the
|
||||
two ways of representing condition codes in GCC.
|
||||
|
||||
The first representation is the so called @code{(cc0)} representation
|
||||
(@pxref{Jump Patterns}), where all instructions can have an implicit
|
||||
clobber of the condition codes. The second is the condition code
|
||||
register representation, which provides better schedulability for
|
||||
Condition codes in GCC are represented as registers,
|
||||
which provides better schedulability for
|
||||
architectures that do have a condition code register, but on which
|
||||
most instructions do not affect it. The latter category includes
|
||||
most RISC machines.
|
||||
|
||||
The implicit clobbering poses a strong restriction on the placement of
|
||||
Implicit clobbering would pose a strong restriction on the placement of
|
||||
the definition and use of the condition code. In the past the definition
|
||||
and use were always adjacent. However, recent changes to support trapping
|
||||
arithmatic may result in the definition and user being in different blocks.
|
||||
arithmetic may result in the definition and user being in different blocks.
|
||||
Thus, there may be a @code{NOTE_INSN_BASIC_BLOCK} between them. Additionally,
|
||||
the definition may be the source of exception handling edges.
|
||||
|
||||
|
@ -4293,8 +4288,7 @@ three instructions earlier than the conditional branch. The instruction
|
|||
scheduler cannot perform this optimization if it is not permitted to
|
||||
separate the definition and use of the condition code register.
|
||||
|
||||
For this reason, it is possible and suggested to use a register to
|
||||
represent the condition code for new ports. If there is a specific
|
||||
If there is a specific
|
||||
condition code register in the machine, use a hard register. If the
|
||||
condition code or comparison result can be placed in any general register,
|
||||
or if there are multiple condition registers, use a pseudo register.
|
||||
|
@ -4306,78 +4300,9 @@ specified already in the compare instruction. In this case, you are not
|
|||
interested in most macros in this section.
|
||||
|
||||
@menu
|
||||
* CC0 Condition Codes:: Old style representation of condition codes.
|
||||
* MODE_CC Condition Codes:: Modern representation of condition codes.
|
||||
@end menu
|
||||
|
||||
@node CC0 Condition Codes
|
||||
@subsection Representation of condition codes using @code{(cc0)}
|
||||
@findex cc0
|
||||
|
||||
@findex cc_status
|
||||
The file @file{conditions.h} defines a variable @code{cc_status} to
|
||||
describe how the condition code was computed (in case the interpretation of
|
||||
the condition code depends on the instruction that it was set by). This
|
||||
variable contains the RTL expressions on which the condition code is
|
||||
currently based, and several standard flags.
|
||||
|
||||
Sometimes additional machine-specific flags must be defined in the machine
|
||||
description header file. It can also add additional machine-specific
|
||||
information by defining @code{CC_STATUS_MDEP}.
|
||||
|
||||
@defmac CC_STATUS_MDEP
|
||||
C code for a data type which is used for declaring the @code{mdep}
|
||||
component of @code{cc_status}. It defaults to @code{int}.
|
||||
|
||||
This macro is not used on machines that do not use @code{cc0}.
|
||||
@end defmac
|
||||
|
||||
@defmac CC_STATUS_MDEP_INIT
|
||||
A C expression to initialize the @code{mdep} field to ``empty''.
|
||||
The default definition does nothing, since most machines don't use
|
||||
the field anyway. If you want to use the field, you should probably
|
||||
define this macro to initialize it.
|
||||
|
||||
This macro is not used on machines that do not use @code{cc0}.
|
||||
@end defmac
|
||||
|
||||
@defmac NOTICE_UPDATE_CC (@var{exp}, @var{insn})
|
||||
A C compound statement to set the components of @code{cc_status}
|
||||
appropriately for an insn @var{insn} whose body is @var{exp}. It is
|
||||
this macro's responsibility to recognize insns that set the condition
|
||||
code as a byproduct of other activity as well as those that explicitly
|
||||
set @code{(cc0)}.
|
||||
|
||||
This macro is not used on machines that do not use @code{cc0}.
|
||||
|
||||
If there are insns that do not set the condition code but do alter
|
||||
other machine registers, this macro must check to see whether they
|
||||
invalidate the expressions that the condition code is recorded as
|
||||
reflecting. For example, on the 68000, insns that store in address
|
||||
registers do not set the condition code, which means that usually
|
||||
@code{NOTICE_UPDATE_CC} can leave @code{cc_status} unaltered for such
|
||||
insns. But suppose that the previous insn set the condition code
|
||||
based on location @samp{a4@@(102)} and the current insn stores a new
|
||||
value in @samp{a4}. Although the condition code is not changed by
|
||||
this, it will no longer be true that it reflects the contents of
|
||||
@samp{a4@@(102)}. Therefore, @code{NOTICE_UPDATE_CC} must alter
|
||||
@code{cc_status} in this case to say that nothing is known about the
|
||||
condition code value.
|
||||
|
||||
The definition of @code{NOTICE_UPDATE_CC} must be prepared to deal
|
||||
with the results of peephole optimization: insns whose patterns are
|
||||
@code{parallel} RTXs containing various @code{reg}, @code{mem} or
|
||||
constants which are just the operands. The RTL structure of these
|
||||
insns is not sufficient to indicate what the insns actually do. What
|
||||
@code{NOTICE_UPDATE_CC} should do when it sees one is just to run
|
||||
@code{CC_STATUS_INIT}.
|
||||
|
||||
A possible definition of @code{NOTICE_UPDATE_CC} is to call a function
|
||||
that looks at an attribute (@pxref{Insn Attributes}) named, for example,
|
||||
@samp{cc}. This avoids having detailed information about patterns in
|
||||
two places, the @file{md} file and in @code{NOTICE_UPDATE_CC}.
|
||||
@end defmac
|
||||
|
||||
@node MODE_CC Condition Codes
|
||||
@subsection Representation of condition codes using registers
|
||||
@findex CCmode
|
||||
|
@ -7909,8 +7834,7 @@ for cross-profiling.
|
|||
|
||||
A C expression for the maximum number of instructions to execute via
|
||||
conditional execution instructions instead of a branch. A value of
|
||||
@code{BRANCH_COST}+1 is the default if the machine does not use cc0, and
|
||||
1 if it does use cc0.
|
||||
@code{BRANCH_COST}+1 is the default.
|
||||
@end defmac
|
||||
|
||||
@defmac IFCVT_MODIFY_TESTS (@var{ce_info}, @var{true_expr}, @var{false_expr})
|
||||
|
|
|
@ -123,7 +123,6 @@ rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
|
|||
rtx pc_rtx;
|
||||
rtx ret_rtx;
|
||||
rtx simple_return_rtx;
|
||||
rtx cc0_rtx;
|
||||
|
||||
/* Marker used for denoting an INSN, which should never be accessed (i.e.,
|
||||
this pointer should normally never be dereferenced), but is required to be
|
||||
|
@ -2847,14 +2846,13 @@ verify_rtx_sharing (rtx orig, rtx insn)
|
|||
case LABEL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
case RETURN:
|
||||
case SIMPLE_RETURN:
|
||||
case SCRATCH:
|
||||
/* SCRATCH must be shared because they represent distinct values. */
|
||||
return;
|
||||
case CLOBBER:
|
||||
/* Share clobbers of hard registers (like cc0), but do not share pseudo reg
|
||||
/* Share clobbers of hard registers, but do not share pseudo reg
|
||||
clobbers or clobbers of hard registers that originated as pseudos.
|
||||
This is needed to allow safe register renaming. */
|
||||
if (REG_P (XEXP (x, 0))
|
||||
|
@ -3100,14 +3098,13 @@ repeat:
|
|||
case LABEL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
case RETURN:
|
||||
case SIMPLE_RETURN:
|
||||
case SCRATCH:
|
||||
/* SCRATCH must be shared because they represent distinct values. */
|
||||
return;
|
||||
case CLOBBER:
|
||||
/* Share clobbers of hard registers (like cc0), but do not share pseudo reg
|
||||
/* Share clobbers of hard registers, but do not share pseudo reg
|
||||
clobbers or clobbers of hard registers that originated as pseudos.
|
||||
This is needed to allow safe register renaming. */
|
||||
if (REG_P (XEXP (x, 0))
|
||||
|
@ -3223,7 +3220,6 @@ repeat:
|
|||
case SYMBOL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
case RETURN:
|
||||
case SIMPLE_RETURN:
|
||||
return;
|
||||
|
@ -3717,50 +3713,6 @@ prev_active_insn (rtx_insn *insn)
|
|||
return insn;
|
||||
}
|
||||
|
||||
/* Return the next insn that uses CC0 after INSN, which is assumed to
|
||||
set it. This is the inverse of prev_cc0_setter (i.e., prev_cc0_setter
|
||||
applied to the result of this function should yield INSN).
|
||||
|
||||
Normally, this is simply the next insn. However, if a REG_CC_USER note
|
||||
is present, it contains the insn that uses CC0.
|
||||
|
||||
Return 0 if we can't find the insn. */
|
||||
|
||||
rtx_insn *
|
||||
next_cc0_user (rtx_insn *insn)
|
||||
{
|
||||
rtx note = find_reg_note (insn, REG_CC_USER, NULL_RTX);
|
||||
|
||||
if (note)
|
||||
return safe_as_a <rtx_insn *> (XEXP (note, 0));
|
||||
|
||||
insn = next_nonnote_insn (insn);
|
||||
if (insn && NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
|
||||
insn = as_a <rtx_sequence *> (PATTERN (insn))->insn (0);
|
||||
|
||||
if (insn && INSN_P (insn) && reg_mentioned_p (cc0_rtx, PATTERN (insn)))
|
||||
return insn;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find the insn that set CC0 for INSN. Unless INSN has a REG_CC_SETTER
|
||||
note, it is the previous insn. */
|
||||
|
||||
rtx_insn *
|
||||
prev_cc0_setter (rtx_insn *insn)
|
||||
{
|
||||
rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
|
||||
|
||||
if (note)
|
||||
return safe_as_a <rtx_insn *> (XEXP (note, 0));
|
||||
|
||||
insn = prev_nonnote_insn (insn);
|
||||
gcc_assert (sets_cc0_p (PATTERN (insn)));
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
/* Find a RTX_AUTOINC class rtx which matches DATA. */
|
||||
|
||||
static int
|
||||
|
@ -5687,12 +5639,11 @@ copy_insn_1 (rtx orig)
|
|||
case SYMBOL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
case RETURN:
|
||||
case SIMPLE_RETURN:
|
||||
return orig;
|
||||
case CLOBBER:
|
||||
/* Share clobbers of hard registers (like cc0), but do not share pseudo reg
|
||||
/* Share clobbers of hard registers, but do not share pseudo reg
|
||||
clobbers or clobbers of hard registers that originated as pseudos.
|
||||
This is needed to allow safe register renaming. */
|
||||
if (REG_P (XEXP (orig, 0))
|
||||
|
@ -6413,7 +6364,6 @@ init_emit_once (void)
|
|||
pc_rtx = gen_rtx_fmt_ (PC, VOIDmode);
|
||||
ret_rtx = gen_rtx_fmt_ (RETURN, VOIDmode);
|
||||
simple_return_rtx = gen_rtx_fmt_ (SIMPLE_RETURN, VOIDmode);
|
||||
cc0_rtx = gen_rtx_fmt_ (CC0, VOIDmode);
|
||||
invalid_insn_rtx = gen_rtx_INSN (VOIDmode,
|
||||
/*prev_insn=*/NULL,
|
||||
/*next_insn=*/NULL,
|
||||
|
|
399
gcc/final.c
399
gcc/final.c
|
@ -93,7 +93,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "dbxout.h"
|
||||
#endif
|
||||
|
||||
/* Most ports that aren't using cc0 don't need to define CC_STATUS_INIT.
|
||||
/* Most ports don't need to define CC_STATUS_INIT.
|
||||
So define a null default for it to save conditionalization later. */
|
||||
#ifndef CC_STATUS_INIT
|
||||
#define CC_STATUS_INIT
|
||||
|
@ -175,17 +175,6 @@ static rtx last_ignored_compare = 0;
|
|||
|
||||
static int insn_counter = 0;
|
||||
|
||||
/* This variable contains machine-dependent flags (defined in tm.h)
|
||||
set and examined by output routines
|
||||
that describe how to interpret the condition codes properly. */
|
||||
|
||||
CC_STATUS cc_status;
|
||||
|
||||
/* During output of an insn, this contains a copy of cc_status
|
||||
from before the insn. */
|
||||
|
||||
CC_STATUS cc_prev_status;
|
||||
|
||||
/* Number of unmatched NOTE_INSN_BLOCK_BEG notes we have seen. */
|
||||
|
||||
static int block_depth;
|
||||
|
@ -226,9 +215,6 @@ static void output_asm_operand_names (rtx *, int *, int);
|
|||
#ifdef LEAF_REGISTERS
|
||||
static void leaf_renumber_regs (rtx_insn *);
|
||||
#endif
|
||||
#if HAVE_cc0
|
||||
static int alter_cond (rtx);
|
||||
#endif
|
||||
static int align_fuzz (rtx, rtx, int, unsigned);
|
||||
static void collect_fn_hard_reg_usage (void);
|
||||
|
||||
|
@ -1962,21 +1948,6 @@ final_1 (rtx_insn *first, FILE *file, int seen, int optimize_p)
|
|||
|
||||
last_ignored_compare = 0;
|
||||
|
||||
if (HAVE_cc0)
|
||||
for (insn = first; insn; insn = NEXT_INSN (insn))
|
||||
{
|
||||
/* If CC tracking across branches is enabled, record the insn which
|
||||
jumps to each branch only reached from one place. */
|
||||
if (optimize_p && JUMP_P (insn))
|
||||
{
|
||||
rtx lab = JUMP_LABEL (insn);
|
||||
if (lab && LABEL_P (lab) && LABEL_NUSES (lab) == 1)
|
||||
{
|
||||
LABEL_REFS (lab) = insn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init_recog ();
|
||||
|
||||
CC_STATUS_INIT;
|
||||
|
@ -2187,9 +2158,6 @@ static rtx_insn *
|
|||
final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
|
||||
int nopeepholes ATTRIBUTE_UNUSED, int *seen)
|
||||
{
|
||||
#if HAVE_cc0
|
||||
rtx set;
|
||||
#endif
|
||||
rtx_insn *next;
|
||||
rtx_jump_table_data *table;
|
||||
|
||||
|
@ -2562,23 +2530,6 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
|
|||
|| GET_CODE (body) == CLOBBER)
|
||||
break;
|
||||
|
||||
#if HAVE_cc0
|
||||
{
|
||||
/* If there is a REG_CC_SETTER note on this insn, it means that
|
||||
the setting of the condition code was done in the delay slot
|
||||
of the insn that branched here. So recover the cc status
|
||||
from the insn that set it. */
|
||||
|
||||
rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
|
||||
if (note)
|
||||
{
|
||||
rtx_insn *other = as_a <rtx_insn *> (XEXP (note, 0));
|
||||
NOTICE_UPDATE_CC (PATTERN (other), other);
|
||||
cc_prev_status = cc_status;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Detect insns that are really jump-tables
|
||||
and output them as such. */
|
||||
|
||||
|
@ -2798,182 +2749,6 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
|
|||
|
||||
body = PATTERN (insn);
|
||||
|
||||
#if HAVE_cc0
|
||||
set = single_set (insn);
|
||||
|
||||
/* Check for redundant test and compare instructions
|
||||
(when the condition codes are already set up as desired).
|
||||
This is done only when optimizing; if not optimizing,
|
||||
it should be possible for the user to alter a variable
|
||||
with the debugger in between statements
|
||||
and the next statement should reexamine the variable
|
||||
to compute the condition codes. */
|
||||
|
||||
if (optimize_p)
|
||||
{
|
||||
if (set
|
||||
&& GET_CODE (SET_DEST (set)) == CC0
|
||||
&& insn != last_ignored_compare)
|
||||
{
|
||||
rtx src1, src2;
|
||||
if (GET_CODE (SET_SRC (set)) == SUBREG)
|
||||
SET_SRC (set) = alter_subreg (&SET_SRC (set), true);
|
||||
|
||||
src1 = SET_SRC (set);
|
||||
src2 = NULL_RTX;
|
||||
if (GET_CODE (SET_SRC (set)) == COMPARE)
|
||||
{
|
||||
if (GET_CODE (XEXP (SET_SRC (set), 0)) == SUBREG)
|
||||
XEXP (SET_SRC (set), 0)
|
||||
= alter_subreg (&XEXP (SET_SRC (set), 0), true);
|
||||
if (GET_CODE (XEXP (SET_SRC (set), 1)) == SUBREG)
|
||||
XEXP (SET_SRC (set), 1)
|
||||
= alter_subreg (&XEXP (SET_SRC (set), 1), true);
|
||||
if (XEXP (SET_SRC (set), 1)
|
||||
== CONST0_RTX (GET_MODE (XEXP (SET_SRC (set), 0))))
|
||||
src2 = XEXP (SET_SRC (set), 0);
|
||||
}
|
||||
if ((cc_status.value1 != 0
|
||||
&& rtx_equal_p (src1, cc_status.value1))
|
||||
|| (cc_status.value2 != 0
|
||||
&& rtx_equal_p (src1, cc_status.value2))
|
||||
|| (src2 != 0 && cc_status.value1 != 0
|
||||
&& rtx_equal_p (src2, cc_status.value1))
|
||||
|| (src2 != 0 && cc_status.value2 != 0
|
||||
&& rtx_equal_p (src2, cc_status.value2)))
|
||||
{
|
||||
/* Don't delete insn if it has an addressing side-effect. */
|
||||
if (! FIND_REG_INC_NOTE (insn, NULL_RTX)
|
||||
/* or if anything in it is volatile. */
|
||||
&& ! volatile_refs_p (PATTERN (insn)))
|
||||
{
|
||||
/* We don't really delete the insn; just ignore it. */
|
||||
last_ignored_compare = insn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is a conditional branch, maybe modify it
|
||||
if the cc's are in a nonstandard state
|
||||
so that it accomplishes the same thing that it would
|
||||
do straightforwardly if the cc's were set up normally. */
|
||||
|
||||
if (cc_status.flags != 0
|
||||
&& JUMP_P (insn)
|
||||
&& GET_CODE (body) == SET
|
||||
&& SET_DEST (body) == pc_rtx
|
||||
&& GET_CODE (SET_SRC (body)) == IF_THEN_ELSE
|
||||
&& COMPARISON_P (XEXP (SET_SRC (body), 0))
|
||||
&& XEXP (XEXP (SET_SRC (body), 0), 0) == cc0_rtx)
|
||||
{
|
||||
/* This function may alter the contents of its argument
|
||||
and clear some of the cc_status.flags bits.
|
||||
It may also return 1 meaning condition now always true
|
||||
or -1 meaning condition now always false
|
||||
or 2 meaning condition nontrivial but altered. */
|
||||
int result = alter_cond (XEXP (SET_SRC (body), 0));
|
||||
/* If condition now has fixed value, replace the IF_THEN_ELSE
|
||||
with its then-operand or its else-operand. */
|
||||
if (result == 1)
|
||||
SET_SRC (body) = XEXP (SET_SRC (body), 1);
|
||||
if (result == -1)
|
||||
SET_SRC (body) = XEXP (SET_SRC (body), 2);
|
||||
|
||||
/* The jump is now either unconditional or a no-op.
|
||||
If it has become a no-op, don't try to output it.
|
||||
(It would not be recognized.) */
|
||||
if (SET_SRC (body) == pc_rtx)
|
||||
{
|
||||
delete_insn (insn);
|
||||
break;
|
||||
}
|
||||
else if (ANY_RETURN_P (SET_SRC (body)))
|
||||
/* Replace (set (pc) (return)) with (return). */
|
||||
PATTERN (insn) = body = SET_SRC (body);
|
||||
|
||||
/* Rerecognize the instruction if it has changed. */
|
||||
if (result != 0)
|
||||
INSN_CODE (insn) = -1;
|
||||
}
|
||||
|
||||
/* If this is a conditional trap, maybe modify it if the cc's
|
||||
are in a nonstandard state so that it accomplishes the same
|
||||
thing that it would do straightforwardly if the cc's were
|
||||
set up normally. */
|
||||
if (cc_status.flags != 0
|
||||
&& NONJUMP_INSN_P (insn)
|
||||
&& GET_CODE (body) == TRAP_IF
|
||||
&& COMPARISON_P (TRAP_CONDITION (body))
|
||||
&& XEXP (TRAP_CONDITION (body), 0) == cc0_rtx)
|
||||
{
|
||||
/* This function may alter the contents of its argument
|
||||
and clear some of the cc_status.flags bits.
|
||||
It may also return 1 meaning condition now always true
|
||||
or -1 meaning condition now always false
|
||||
or 2 meaning condition nontrivial but altered. */
|
||||
int result = alter_cond (TRAP_CONDITION (body));
|
||||
|
||||
/* If TRAP_CONDITION has become always false, delete the
|
||||
instruction. */
|
||||
if (result == -1)
|
||||
{
|
||||
delete_insn (insn);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If TRAP_CONDITION has become always true, replace
|
||||
TRAP_CONDITION with const_true_rtx. */
|
||||
if (result == 1)
|
||||
TRAP_CONDITION (body) = const_true_rtx;
|
||||
|
||||
/* Rerecognize the instruction if it has changed. */
|
||||
if (result != 0)
|
||||
INSN_CODE (insn) = -1;
|
||||
}
|
||||
|
||||
/* Make same adjustments to instructions that examine the
|
||||
condition codes without jumping and instructions that
|
||||
handle conditional moves (if this machine has either one). */
|
||||
|
||||
if (cc_status.flags != 0
|
||||
&& set != 0)
|
||||
{
|
||||
rtx cond_rtx, then_rtx, else_rtx;
|
||||
|
||||
if (!JUMP_P (insn)
|
||||
&& GET_CODE (SET_SRC (set)) == IF_THEN_ELSE)
|
||||
{
|
||||
cond_rtx = XEXP (SET_SRC (set), 0);
|
||||
then_rtx = XEXP (SET_SRC (set), 1);
|
||||
else_rtx = XEXP (SET_SRC (set), 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
cond_rtx = SET_SRC (set);
|
||||
then_rtx = const_true_rtx;
|
||||
else_rtx = const0_rtx;
|
||||
}
|
||||
|
||||
if (COMPARISON_P (cond_rtx)
|
||||
&& XEXP (cond_rtx, 0) == cc0_rtx)
|
||||
{
|
||||
int result;
|
||||
result = alter_cond (cond_rtx);
|
||||
if (result == 1)
|
||||
validate_change (insn, &SET_SRC (set), then_rtx, 0);
|
||||
else if (result == -1)
|
||||
validate_change (insn, &SET_SRC (set), else_rtx, 0);
|
||||
else if (result == 2)
|
||||
INSN_CODE (insn) = -1;
|
||||
if (SET_DEST (set) == SET_SRC (set))
|
||||
delete_insn (insn);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Do machine-specific peephole optimizations if desired. */
|
||||
|
||||
if (HAVE_peephole && optimize_p && !flag_no_peephole && !nopeepholes)
|
||||
|
@ -3041,17 +2816,6 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
|
|||
&& GET_CODE (PATTERN (insn)) == COND_EXEC)
|
||||
current_insn_predicate = COND_EXEC_TEST (PATTERN (insn));
|
||||
|
||||
#if HAVE_cc0
|
||||
cc_prev_status = cc_status;
|
||||
|
||||
/* Update `cc_status' for this instruction.
|
||||
The instruction's output routine may change it further.
|
||||
If the output routine for a jump insn needs to depend
|
||||
on the cc status, it should look at cc_prev_status. */
|
||||
|
||||
NOTICE_UPDATE_CC (body, insn);
|
||||
#endif
|
||||
|
||||
current_output_insn = debug_insn = insn;
|
||||
|
||||
/* Find the proper template for this insn. */
|
||||
|
@ -3443,167 +3207,6 @@ walk_alter_subreg (rtx *xp, bool *changed)
|
|||
return *xp;
|
||||
}
|
||||
|
||||
#if HAVE_cc0
|
||||
|
||||
/* Given BODY, the body of a jump instruction, alter the jump condition
|
||||
as required by the bits that are set in cc_status.flags.
|
||||
Not all of the bits there can be handled at this level in all cases.
|
||||
|
||||
The value is normally 0.
|
||||
1 means that the condition has become always true.
|
||||
-1 means that the condition has become always false.
|
||||
2 means that COND has been altered. */
|
||||
|
||||
static int
|
||||
alter_cond (rtx cond)
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
if (cc_status.flags & CC_REVERSED)
|
||||
{
|
||||
value = 2;
|
||||
PUT_CODE (cond, swap_condition (GET_CODE (cond)));
|
||||
}
|
||||
|
||||
if (cc_status.flags & CC_INVERTED)
|
||||
{
|
||||
value = 2;
|
||||
PUT_CODE (cond, reverse_condition (GET_CODE (cond)));
|
||||
}
|
||||
|
||||
if (cc_status.flags & CC_NOT_POSITIVE)
|
||||
switch (GET_CODE (cond))
|
||||
{
|
||||
case LE:
|
||||
case LEU:
|
||||
case GEU:
|
||||
/* Jump becomes unconditional. */
|
||||
return 1;
|
||||
|
||||
case GT:
|
||||
case GTU:
|
||||
case LTU:
|
||||
/* Jump becomes no-op. */
|
||||
return -1;
|
||||
|
||||
case GE:
|
||||
PUT_CODE (cond, EQ);
|
||||
value = 2;
|
||||
break;
|
||||
|
||||
case LT:
|
||||
PUT_CODE (cond, NE);
|
||||
value = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cc_status.flags & CC_NOT_NEGATIVE)
|
||||
switch (GET_CODE (cond))
|
||||
{
|
||||
case GE:
|
||||
case GEU:
|
||||
/* Jump becomes unconditional. */
|
||||
return 1;
|
||||
|
||||
case LT:
|
||||
case LTU:
|
||||
/* Jump becomes no-op. */
|
||||
return -1;
|
||||
|
||||
case LE:
|
||||
case LEU:
|
||||
PUT_CODE (cond, EQ);
|
||||
value = 2;
|
||||
break;
|
||||
|
||||
case GT:
|
||||
case GTU:
|
||||
PUT_CODE (cond, NE);
|
||||
value = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cc_status.flags & CC_NO_OVERFLOW)
|
||||
switch (GET_CODE (cond))
|
||||
{
|
||||
case GEU:
|
||||
/* Jump becomes unconditional. */
|
||||
return 1;
|
||||
|
||||
case LEU:
|
||||
PUT_CODE (cond, EQ);
|
||||
value = 2;
|
||||
break;
|
||||
|
||||
case GTU:
|
||||
PUT_CODE (cond, NE);
|
||||
value = 2;
|
||||
break;
|
||||
|
||||
case LTU:
|
||||
/* Jump becomes no-op. */
|
||||
return -1;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N))
|
||||
switch (GET_CODE (cond))
|
||||
{
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
|
||||
case NE:
|
||||
PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT);
|
||||
value = 2;
|
||||
break;
|
||||
|
||||
case EQ:
|
||||
PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? LT : GE);
|
||||
value = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cc_status.flags & CC_NOT_SIGNED)
|
||||
/* The flags are valid if signed condition operators are converted
|
||||
to unsigned. */
|
||||
switch (GET_CODE (cond))
|
||||
{
|
||||
case LE:
|
||||
PUT_CODE (cond, LEU);
|
||||
value = 2;
|
||||
break;
|
||||
|
||||
case LT:
|
||||
PUT_CODE (cond, LTU);
|
||||
value = 2;
|
||||
break;
|
||||
|
||||
case GT:
|
||||
PUT_CODE (cond, GTU);
|
||||
value = 2;
|
||||
break;
|
||||
|
||||
case GE:
|
||||
PUT_CODE (cond, GEU);
|
||||
value = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Report inconsistency between the assembler template and the operands.
|
||||
In an `asm', it's the user's fault; otherwise, the compiler's fault. */
|
||||
|
||||
|
|
|
@ -784,7 +784,7 @@ forward_propagate_and_simplify (use_info *use, set_info *def,
|
|||
if (need_single_set && !use_set)
|
||||
return false;
|
||||
|
||||
/* Do not propagate into PC, CC0, etc.
|
||||
/* Do not propagate into PC etc.
|
||||
|
||||
??? This too seems unnecessary. The current code should work correctly
|
||||
without it, including cases where jumps become unconditional. */
|
||||
|
|
|
@ -186,7 +186,6 @@ compute_transp (const_rtx x, int indx, sbitmap *bmap,
|
|||
goto repeat;
|
||||
|
||||
case PC:
|
||||
case CC0: /*FIXME*/
|
||||
case CONST:
|
||||
CASE_CONST_ANY:
|
||||
case SYMBOL_REF:
|
||||
|
|
25
gcc/gcse.c
25
gcc/gcse.c
|
@ -926,7 +926,6 @@ oprs_unchanged_p (const_rtx x, const rtx_insn *insn, int avail_p)
|
|||
return 0;
|
||||
|
||||
case PC:
|
||||
case CC0: /*FIXME*/
|
||||
case CONST:
|
||||
CASE_CONST_ANY:
|
||||
case SYMBOL_REF:
|
||||
|
@ -2031,33 +2030,15 @@ insert_insn_end_basic_block (struct gcse_expr *expr, basic_block bb)
|
|||
while (NEXT_INSN (pat_end) != NULL_RTX)
|
||||
pat_end = NEXT_INSN (pat_end);
|
||||
|
||||
/* If the last insn is a jump, insert EXPR in front [taking care to
|
||||
handle cc0, etc. properly]. Similarly we need to care trapping
|
||||
instructions in presence of non-call exceptions. */
|
||||
/* If the last insn is a jump, insert EXPR in front. Similarly we need to
|
||||
take care of trapping instructions in presence of non-call exceptions. */
|
||||
|
||||
if (JUMP_P (insn)
|
||||
|| (NONJUMP_INSN_P (insn)
|
||||
&& (!single_succ_p (bb)
|
||||
|| single_succ_edge (bb)->flags & EDGE_ABNORMAL)))
|
||||
{
|
||||
/* FIXME: 'twould be nice to call prev_cc0_setter here but it aborts
|
||||
if cc0 isn't set. */
|
||||
if (HAVE_cc0)
|
||||
{
|
||||
rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
|
||||
if (note)
|
||||
insn = safe_as_a <rtx_insn *> (XEXP (note, 0));
|
||||
else
|
||||
{
|
||||
rtx_insn *maybe_cc0_setter = prev_nonnote_insn (insn);
|
||||
if (maybe_cc0_setter
|
||||
&& INSN_P (maybe_cc0_setter)
|
||||
&& sets_cc0_p (PATTERN (maybe_cc0_setter)))
|
||||
insn = maybe_cc0_setter;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: What if something in cc0/jump uses value set in new insn? */
|
||||
/* FIXME: What if something in jump uses value set in new insn? */
|
||||
new_insn = emit_insn_before_noloc (pat, insn, bb);
|
||||
}
|
||||
|
||||
|
|
|
@ -3011,7 +3011,6 @@ clear_struct_flag (rtx x)
|
|||
case SYMBOL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
case EQ_ATTR:
|
||||
case ATTR_FLAG:
|
||||
return;
|
||||
|
|
|
@ -32,7 +32,6 @@ along with GCC; see the file COPYING3. If not see
|
|||
static int max_recog_operands; /* Largest operand number seen. */
|
||||
static int max_dup_operands; /* Largest number of match_dup in any insn. */
|
||||
static int max_clobbers_per_insn;
|
||||
static int have_cc0_flag;
|
||||
static int have_cmove_flag;
|
||||
static int have_cond_exec_flag;
|
||||
static int have_lo_sum_flag;
|
||||
|
@ -105,11 +104,6 @@ walk_insn_part (rtx part, int recog_p, int non_pc_set_src)
|
|||
max_recog_operands = XINT (part, 0);
|
||||
return;
|
||||
|
||||
case CC0:
|
||||
if (recog_p)
|
||||
have_cc0_flag = 1;
|
||||
return;
|
||||
|
||||
case LO_SUM:
|
||||
if (recog_p)
|
||||
have_lo_sum_flag = 1;
|
||||
|
@ -329,19 +323,6 @@ main (int argc, const char **argv)
|
|||
printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split);
|
||||
printf ("#endif\n");
|
||||
|
||||
if (have_cc0_flag)
|
||||
{
|
||||
printf ("#define HAVE_cc0 1\n");
|
||||
printf ("#define CC0_P(X) ((X) == cc0_rtx)\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We output CC0_P this way to make sure that X is declared
|
||||
somewhere. */
|
||||
printf ("#define HAVE_cc0 0\n");
|
||||
printf ("#define CC0_P(X) ((X) ? 0 : 0)\n");
|
||||
}
|
||||
|
||||
if (have_cmove_flag)
|
||||
printf ("#define HAVE_conditional_move 1\n");
|
||||
else
|
||||
|
|
|
@ -169,9 +169,6 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info)
|
|||
return;
|
||||
}
|
||||
break;
|
||||
case CC0:
|
||||
printf ("cc0_rtx");
|
||||
return;
|
||||
|
||||
case CONST_INT:
|
||||
if (INTVAL (x) == 0)
|
||||
|
|
|
@ -237,7 +237,6 @@ walk_rtx (md_rtx_info *info, rtx x, class accum_extract *acc)
|
|||
switch (code)
|
||||
{
|
||||
case PC:
|
||||
case CC0:
|
||||
case CONST_INT:
|
||||
case SYMBOL_REF:
|
||||
return;
|
||||
|
|
|
@ -143,7 +143,6 @@ special_rtx (int idx)
|
|||
|| strcmp (defs[idx].enumname, "SUBREG") == 0
|
||||
|| strcmp (defs[idx].enumname, "MEM") == 0
|
||||
|| strcmp (defs[idx].enumname, "PC") == 0
|
||||
|| strcmp (defs[idx].enumname, "CC0") == 0
|
||||
|| strcmp (defs[idx].enumname, "RETURN") == 0
|
||||
|| strcmp (defs[idx].enumname, "SIMPLE_RETURN") == 0
|
||||
|| strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
|
||||
|
|
|
@ -694,13 +694,11 @@ validate_pattern (rtx pattern, md_rtx_info *info, rtx set, int set_code)
|
|||
error_at (info->loc, "mode mismatch in set: %smode vs %smode",
|
||||
GET_MODE_NAME (dmode), GET_MODE_NAME (smode));
|
||||
|
||||
/* If only one of the operands is VOIDmode, and PC or CC0 is
|
||||
not involved, it's probably a mistake. */
|
||||
/* If only one of the operands is VOIDmode, and PC is not involved,
|
||||
it's probably a mistake. */
|
||||
else if (dmode != smode
|
||||
&& GET_CODE (dest) != PC
|
||||
&& GET_CODE (dest) != CC0
|
||||
&& GET_CODE (src) != PC
|
||||
&& GET_CODE (src) != CC0
|
||||
&& !CONST_INT_P (src)
|
||||
&& !CONST_WIDE_INT_P (src)
|
||||
&& GET_CODE (src) != CALL)
|
||||
|
|
|
@ -7255,10 +7255,6 @@ free_global_sched_pressure_data (void)
|
|||
void
|
||||
sched_init (void)
|
||||
{
|
||||
/* Disable speculative loads in their presence if cc0 defined. */
|
||||
if (HAVE_cc0)
|
||||
flag_schedule_speculative_load = 0;
|
||||
|
||||
if (targetm.sched.dispatch (NULL, IS_DISPATCH_ON))
|
||||
targetm.sched.dispatch_do (NULL, DISPATCH_INIT);
|
||||
|
||||
|
|
|
@ -3458,7 +3458,6 @@ noce_process_if_block (struct noce_if_info *if_info)
|
|||
/* First look for multiple SETS. */
|
||||
if (!else_bb
|
||||
&& HAVE_conditional_move
|
||||
&& !HAVE_cc0
|
||||
&& bb_ok_for_noce_convert_multiple_sets (then_bb))
|
||||
{
|
||||
if (noce_convert_multiple_sets (if_info))
|
||||
|
|
|
@ -1105,7 +1105,6 @@ record_address_regs (machine_mode mode, addr_space_t as, rtx x,
|
|||
{
|
||||
case CONST_INT:
|
||||
case CONST:
|
||||
case CC0:
|
||||
case PC:
|
||||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
|
|
15
gcc/ira.c
15
gcc/ira.c
|
@ -3085,7 +3085,6 @@ equiv_init_movable_p (rtx x, int regno)
|
|||
case SET:
|
||||
return equiv_init_movable_p (SET_SRC (x), regno);
|
||||
|
||||
case CC0:
|
||||
case CLOBBER:
|
||||
return 0;
|
||||
|
||||
|
@ -3170,7 +3169,6 @@ memref_referenced_p (rtx memref, rtx x, bool read_p)
|
|||
case SYMBOL_REF:
|
||||
CASE_CONST_ANY:
|
||||
case PC:
|
||||
case CC0:
|
||||
case HIGH:
|
||||
case LO_SUM:
|
||||
return false;
|
||||
|
@ -4448,9 +4446,6 @@ rtx_moveable_p (rtx *loc, enum op_type type)
|
|||
case PC:
|
||||
return type == OP_IN;
|
||||
|
||||
case CC0:
|
||||
return false;
|
||||
|
||||
case REG:
|
||||
if (x == frame_pointer_rtx)
|
||||
return true;
|
||||
|
@ -4741,13 +4736,6 @@ find_moveable_pseudos (void)
|
|||
? " (no unique first use)" : "");
|
||||
continue;
|
||||
}
|
||||
if (HAVE_cc0 && reg_referenced_p (cc0_rtx, PATTERN (closest_use)))
|
||||
{
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Reg %d: closest user uses cc0\n",
|
||||
regno);
|
||||
continue;
|
||||
}
|
||||
|
||||
bitmap_set_bit (interesting, regno);
|
||||
/* If we get here, we know closest_use is a non-NULL insn
|
||||
|
@ -4822,8 +4810,7 @@ find_moveable_pseudos (void)
|
|||
if (!bitmap_bit_p (def_bb_transp, regno))
|
||||
{
|
||||
if (bitmap_bit_p (def_bb_moveable, regno)
|
||||
&& !control_flow_insn_p (use_insn)
|
||||
&& (!HAVE_cc0 || !sets_cc0_p (use_insn)))
|
||||
&& !control_flow_insn_p (use_insn))
|
||||
{
|
||||
if (modified_between_p (DF_REF_REG (use), def_insn, use_insn))
|
||||
{
|
||||
|
|
53
gcc/jump.c
53
gcc/jump.c
|
@ -400,7 +400,7 @@ reversed_comparison_code_parts (enum rtx_code code, const_rtx arg0,
|
|||
break;
|
||||
}
|
||||
|
||||
if (GET_MODE_CLASS (mode) == MODE_CC || CC0_P (arg0))
|
||||
if (GET_MODE_CLASS (mode) == MODE_CC)
|
||||
{
|
||||
/* Try to search for the comparison to determine the real mode.
|
||||
This code is expensive, but with sane machine description it
|
||||
|
@ -1008,55 +1008,6 @@ jump_to_label_p (const rtx_insn *insn)
|
|||
return (JUMP_P (insn)
|
||||
&& JUMP_LABEL (insn) != NULL && !ANY_RETURN_P (JUMP_LABEL (insn)));
|
||||
}
|
||||
|
||||
/* Return nonzero if X is an RTX that only sets the condition codes
|
||||
and has no side effects. */
|
||||
|
||||
int
|
||||
only_sets_cc0_p (const_rtx x)
|
||||
{
|
||||
if (! x)
|
||||
return 0;
|
||||
|
||||
if (INSN_P (x))
|
||||
x = PATTERN (x);
|
||||
|
||||
return sets_cc0_p (x) == 1 && ! side_effects_p (x);
|
||||
}
|
||||
|
||||
/* Return 1 if X is an RTX that does nothing but set the condition codes
|
||||
and CLOBBER or USE registers.
|
||||
Return -1 if X does explicitly set the condition codes,
|
||||
but also does other things. */
|
||||
|
||||
int
|
||||
sets_cc0_p (const_rtx x)
|
||||
{
|
||||
if (! x)
|
||||
return 0;
|
||||
|
||||
if (INSN_P (x))
|
||||
x = PATTERN (x);
|
||||
|
||||
if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx)
|
||||
return 1;
|
||||
if (GET_CODE (x) == PARALLEL)
|
||||
{
|
||||
int i;
|
||||
int sets_cc0 = 0;
|
||||
int other_things = 0;
|
||||
for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
|
||||
{
|
||||
if (GET_CODE (XVECEXP (x, 0, i)) == SET
|
||||
&& SET_DEST (XVECEXP (x, 0, i)) == cc0_rtx)
|
||||
sets_cc0 = 1;
|
||||
else if (GET_CODE (XVECEXP (x, 0, i)) == SET)
|
||||
other_things = 1;
|
||||
}
|
||||
return ! sets_cc0 ? 0 : other_things ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find all CODE_LABELs referred to in X, and increment their use
|
||||
counts. If INSN is a JUMP_INSN and there is at least one
|
||||
|
@ -1101,7 +1052,6 @@ mark_jump_label_1 (rtx x, rtx_insn *insn, bool in_mem, bool is_target)
|
|||
switch (code)
|
||||
{
|
||||
case PC:
|
||||
case CC0:
|
||||
case REG:
|
||||
case CLOBBER:
|
||||
case CALL:
|
||||
|
@ -1771,7 +1721,6 @@ rtx_renumbered_equal_p (const_rtx x, const_rtx y)
|
|||
switch (code)
|
||||
{
|
||||
case PC:
|
||||
case CC0:
|
||||
case ADDR_VEC:
|
||||
case ADDR_DIFF_VEC:
|
||||
CASE_CONST_UNIQUE:
|
||||
|
|
|
@ -212,7 +212,6 @@ check_maybe_invariant (rtx x)
|
|||
return true;
|
||||
|
||||
case PC:
|
||||
case CC0:
|
||||
case UNSPEC_VOLATILE:
|
||||
case CALL:
|
||||
return false;
|
||||
|
@ -1095,10 +1094,6 @@ find_invariant_insn (rtx_insn *insn, bool always_reached, bool always_executed)
|
|||
bool simple = true;
|
||||
struct invariant *inv;
|
||||
|
||||
/* We can't move a CC0 setter without the user. */
|
||||
if (HAVE_cc0 && sets_cc0_p (insn))
|
||||
return;
|
||||
|
||||
/* Jumps have control flow side-effects. */
|
||||
if (JUMP_P (insn))
|
||||
return;
|
||||
|
|
|
@ -3989,15 +3989,9 @@ curr_insn_transform (bool check_only_p)
|
|||
no_input_reloads_p = no_output_reloads_p = false;
|
||||
goal_alt_number = -1;
|
||||
change_p = sec_mem_p = false;
|
||||
/* CALL_INSNs are not allowed to have any output reloads; neither
|
||||
are insns that SET cc0. Insns that use CC0 are not allowed to
|
||||
have any input reloads. */
|
||||
if (CALL_P (curr_insn))
|
||||
no_output_reloads_p = true;
|
||||
|
||||
if (HAVE_cc0 && reg_referenced_p (cc0_rtx, PATTERN (curr_insn)))
|
||||
no_input_reloads_p = true;
|
||||
if (HAVE_cc0 && reg_set_p (cc0_rtx, PATTERN (curr_insn)))
|
||||
/* CALL_INSNs are not allowed to have any output reloads. */
|
||||
if (CALL_P (curr_insn))
|
||||
no_output_reloads_p = true;
|
||||
|
||||
n_operands = curr_static_id->n_operands;
|
||||
|
|
|
@ -353,7 +353,6 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
|
|||
case SYMBOL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
case ASM_INPUT:
|
||||
case ADDR_VEC:
|
||||
case ADDR_DIFF_VEC:
|
||||
|
|
|
@ -4294,13 +4294,6 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
|
|||
> COSTS_N_INSNS (1)))
|
||||
y = force_reg (mode, y);
|
||||
|
||||
#if HAVE_cc0
|
||||
/* Make sure if we have a canonical comparison. The RTL
|
||||
documentation states that canonical comparisons are required only
|
||||
for targets which have cc0. */
|
||||
gcc_assert (!CONSTANT_P (x) || CONSTANT_P (y));
|
||||
#endif
|
||||
|
||||
/* Don't let both operands fail to indicate the mode. */
|
||||
if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
|
||||
x = force_reg (mode, x);
|
||||
|
|
|
@ -549,7 +549,6 @@ oprs_unchanged_p (rtx x, rtx_insn *insn, bool after_insn)
|
|||
return oprs_unchanged_p (XEXP (x, 0), insn, after_insn);
|
||||
|
||||
case PC:
|
||||
case CC0: /*FIXME*/
|
||||
case CONST:
|
||||
CASE_CONST_ANY:
|
||||
case SYMBOL_REF:
|
||||
|
|
|
@ -1013,10 +1013,6 @@ reload_combine_recognize_const_pattern (rtx_insn *insn)
|
|||
&& reg_state[clobbered_regno].real_store_ruid >= use_ruid)
|
||||
break;
|
||||
|
||||
/* Do not separate cc0 setter and cc0 user on HAVE_cc0 targets. */
|
||||
if (HAVE_cc0 && must_move_add && sets_cc0_p (PATTERN (use_insn)))
|
||||
break;
|
||||
|
||||
gcc_assert (reg_state[regno].store_ruid <= use_ruid);
|
||||
/* Avoid moving a use of ADDREG past a point where it is stored. */
|
||||
if (reg_state[REGNO (addreg)].store_ruid > use_ruid)
|
||||
|
|
|
@ -1748,7 +1748,6 @@ print_value (pretty_printer *pp, const_rtx x, int verbose)
|
|||
pp_wide_integer (pp, SUBREG_BYTE (x));
|
||||
break;
|
||||
case SCRATCH:
|
||||
case CC0:
|
||||
case PC:
|
||||
pp_string (pp, GET_RTX_NAME (GET_CODE (x)));
|
||||
break;
|
||||
|
|
|
@ -1491,7 +1491,6 @@ function_reader::consolidate_singletons (rtx x)
|
|||
case PC: return pc_rtx;
|
||||
case RETURN: return ret_rtx;
|
||||
case SIMPLE_RETURN: return simple_return_rtx;
|
||||
case CC0: return cc0_rtx;
|
||||
|
||||
case REG:
|
||||
return consolidate_reg (x);
|
||||
|
|
|
@ -71,16 +71,6 @@ REG_NOTE (NONNEG)
|
|||
/* Identifies a register set in this insn and never used. */
|
||||
REG_NOTE (UNUSED)
|
||||
|
||||
/* REG_CC_SETTER and REG_CC_USER link a pair of insns that set and use
|
||||
CC0, respectively. Normally, these are required to be consecutive
|
||||
insns, but we permit putting a cc0-setting insn in the delay slot
|
||||
of a branch as long as only one copy of the insn exists. In that
|
||||
case, these notes point from one to the other to allow code
|
||||
generation to determine what any require information and to
|
||||
properly update CC_STATUS. These notes are INSN_LISTs. */
|
||||
REG_NOTE (CC_SETTER)
|
||||
REG_NOTE (CC_USER)
|
||||
|
||||
/* Points to a CODE_LABEL. Used by JUMP_INSNs to say that the CODE_LABEL
|
||||
contained in the REG_LABEL_TARGET note is a possible jump target of
|
||||
this insn. This note is an INSN_LIST. */
|
||||
|
|
|
@ -1251,7 +1251,7 @@ swap_rtx_condition (rtx_insn *insn)
|
|||
{
|
||||
rtx pat = PATTERN (insn);
|
||||
|
||||
/* We're looking for a single set to cc0 or an HImode temporary. */
|
||||
/* We're looking for a single set to an HImode temporary. */
|
||||
|
||||
if (GET_CODE (pat) == SET
|
||||
&& REG_P (SET_DEST (pat))
|
||||
|
@ -1298,7 +1298,7 @@ swap_rtx_condition (rtx_insn *insn)
|
|||
|| ! dead_or_set_p (insn, dest))
|
||||
return 0;
|
||||
|
||||
/* Now we are prepared to handle this as a normal cc0 setter. */
|
||||
/* Now we are prepared to handle this. */
|
||||
insn = next_flags_user (insn);
|
||||
if (insn == NULL_RTX)
|
||||
return 0;
|
||||
|
@ -1586,9 +1586,7 @@ subst_stack_regs_pat (rtx_insn *insn, stack_ptr regstack, rtx pat)
|
|||
break;
|
||||
|
||||
case REG:
|
||||
/* This is a `tstM2' case. */
|
||||
gcc_assert (*dest == cc0_rtx);
|
||||
src1 = src;
|
||||
gcc_unreachable ();
|
||||
|
||||
/* Fall through. */
|
||||
|
||||
|
@ -1596,8 +1594,7 @@ subst_stack_regs_pat (rtx_insn *insn, stack_ptr regstack, rtx pat)
|
|||
case SQRT:
|
||||
case ABS:
|
||||
case NEG:
|
||||
/* These insns only operate on the top of the stack. DEST might
|
||||
be cc0_rtx if we're processing a tstM pattern. Also, it's
|
||||
/* These insns only operate on the top of the stack. It's
|
||||
possible that the tstM case results in a REG_DEAD note on the
|
||||
source. */
|
||||
|
||||
|
|
|
@ -1003,7 +1003,6 @@ reg_scan_mark_refs (rtx x, rtx_insn *insn)
|
|||
{
|
||||
case CONST:
|
||||
CASE_CONST_ANY:
|
||||
case CC0:
|
||||
case PC:
|
||||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
|
|
|
@ -1456,7 +1456,6 @@ scan_rtx (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions action,
|
|||
CASE_CONST_ANY:
|
||||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
case CC0:
|
||||
case PC:
|
||||
return;
|
||||
|
||||
|
|
48
gcc/reload.c
48
gcc/reload.c
|
@ -1500,27 +1500,6 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
|
|||
if (in != 0 && in != *inloc)
|
||||
rld[i].nocombine = 1;
|
||||
|
||||
#if 0
|
||||
/* This was replaced by changes in find_reloads_address_1 and the new
|
||||
function inc_for_reload, which go with a new meaning of reload_inc. */
|
||||
|
||||
/* If this is an IN/OUT reload in an insn that sets the CC,
|
||||
it must be for an autoincrement. It doesn't work to store
|
||||
the incremented value after the insn because that would clobber the CC.
|
||||
So we must do the increment of the value reloaded from,
|
||||
increment it, store it back, then decrement again. */
|
||||
if (out != 0 && sets_cc0_p (PATTERN (this_insn)))
|
||||
{
|
||||
out = 0;
|
||||
rld[i].out = 0;
|
||||
rld[i].inc = find_inc_amount (PATTERN (this_insn), in);
|
||||
/* If we did not find a nonzero amount-to-increment-by,
|
||||
that contradicts the belief that IN is being incremented
|
||||
in an address in this insn. */
|
||||
gcc_assert (rld[i].inc != 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we will replace IN and OUT with the reload-reg,
|
||||
record where they are located so that substitution need
|
||||
not do a tree walk. */
|
||||
|
@ -2696,17 +2675,10 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
|
|||
}
|
||||
}
|
||||
|
||||
/* JUMP_INSNs and CALL_INSNs are not allowed to have any output reloads;
|
||||
neither are insns that SET cc0. Insns that use CC0 are not allowed
|
||||
to have any input reloads. */
|
||||
/* JUMP_INSNs and CALL_INSNs are not allowed to have any output reloads. */
|
||||
if (JUMP_P (insn) || CALL_P (insn))
|
||||
no_output_reloads = 1;
|
||||
|
||||
if (HAVE_cc0 && reg_referenced_p (cc0_rtx, PATTERN (insn)))
|
||||
no_input_reloads = 1;
|
||||
if (HAVE_cc0 && reg_set_p (cc0_rtx, PATTERN (insn)))
|
||||
no_output_reloads = 1;
|
||||
|
||||
/* The eliminated forms of any secondary memory locations are per-insn, so
|
||||
clear them out here. */
|
||||
|
||||
|
@ -4585,15 +4557,6 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
|
|||
rld[j].in = 0;
|
||||
}
|
||||
|
||||
/* If we made any reloads for addresses, see if they violate a
|
||||
"no input reloads" requirement for this insn. But loads that we
|
||||
do after the insn (such as for output addresses) are fine. */
|
||||
if (HAVE_cc0 && no_input_reloads)
|
||||
for (i = 0; i < n_reloads; i++)
|
||||
gcc_assert (rld[i].in == 0
|
||||
|| rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS
|
||||
|| rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS);
|
||||
|
||||
/* Compute reload_mode and reload_nregs. */
|
||||
for (i = 0; i < n_reloads; i++)
|
||||
{
|
||||
|
@ -5323,7 +5286,6 @@ subst_reg_equivs (rtx ad, rtx_insn *insn)
|
|||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
case PC:
|
||||
case CC0:
|
||||
return ad;
|
||||
|
||||
case REG:
|
||||
|
@ -5862,7 +5824,7 @@ find_reloads_address_1 (machine_mode mode, addr_space_t as,
|
|||
/* If we can output the register afterwards, do so, this
|
||||
saves the extra update.
|
||||
We can do so if we have an INSN - i.e. no JUMP_INSN nor
|
||||
CALL_INSN - and it does not set CC0.
|
||||
CALL_INSN.
|
||||
But don't do this if we cannot directly address the
|
||||
memory location, since this will make it harder to
|
||||
reuse address reloads, and increases register pressure.
|
||||
|
@ -5872,9 +5834,6 @@ find_reloads_address_1 (machine_mode mode, addr_space_t as,
|
|||
: reg_equiv_mem (regno));
|
||||
enum insn_code icode = optab_handler (add_optab, GET_MODE (x));
|
||||
if (insn && NONJUMP_INSN_P (insn)
|
||||
#if HAVE_cc0
|
||||
&& ! sets_cc0_p (PATTERN (insn))
|
||||
#endif
|
||||
&& (regno < FIRST_PSEUDO_REGISTER
|
||||
|| (equiv
|
||||
&& memory_operand (equiv, GET_MODE (equiv))
|
||||
|
@ -6621,8 +6580,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
|
|||
}
|
||||
else if (MEM_P (x))
|
||||
return refers_to_mem_for_reload_p (in);
|
||||
else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
|
||||
|| GET_CODE (x) == CC0)
|
||||
else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC)
|
||||
return reg_mentioned_p (x, in);
|
||||
else
|
||||
{
|
||||
|
|
|
@ -2539,7 +2539,6 @@ eliminate_regs_1 (rtx x, machine_mode mem_mode, rtx insn,
|
|||
case SYMBOL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
case ASM_INPUT:
|
||||
case ADDR_VEC:
|
||||
case ADDR_DIFF_VEC:
|
||||
|
@ -2962,7 +2961,6 @@ elimination_effects (rtx x, machine_mode mem_mode)
|
|||
case SYMBOL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
case ASM_INPUT:
|
||||
case ADDR_VEC:
|
||||
case ADDR_DIFF_VEC:
|
||||
|
@ -4341,7 +4339,6 @@ scan_paradoxical_subregs (rtx x)
|
|||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
CASE_CONST_ANY:
|
||||
case CC0:
|
||||
case PC:
|
||||
case USE:
|
||||
case CLOBBER:
|
||||
|
@ -7852,7 +7849,7 @@ do_input_reload (class insn_chain *chain, struct reload *rl, int j)
|
|||
/* Do output reloading for reload RL, which is for the insn described by
|
||||
CHAIN and has the number J.
|
||||
??? At some point we need to support handling output reloads of
|
||||
JUMP_INSNs or insns that set cc0. */
|
||||
JUMP_INSNs. */
|
||||
static void
|
||||
do_output_reload (class insn_chain *chain, struct reload *rl, int j)
|
||||
{
|
||||
|
|
146
gcc/reorg.c
146
gcc/reorg.c
|
@ -88,17 +88,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
making the various individual schedules work well together. It is
|
||||
especially tuned to handle the control flow interactions of branch
|
||||
insns. It does nothing for insns with delay slots that do not
|
||||
branch.
|
||||
|
||||
On machines that use CC0, we are very conservative. We will not make
|
||||
a copy of an insn involving CC0 since we want to maintain a 1-1
|
||||
correspondence between the insn that sets and uses CC0. The insns are
|
||||
allowed to be separated by placing an insn that sets CC0 (but not an insn
|
||||
that uses CC0; we could do this, but it doesn't seem worthwhile) in a
|
||||
delay slot. In that case, we point each insn at the other with REG_CC_USER
|
||||
and REG_CC_SETTER notes. Note that these restrictions affect very few
|
||||
machines because most RISC machines with delay slots will not use CC0
|
||||
(the RT is the only known exception at this point). */
|
||||
branch. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
|
@ -155,21 +145,6 @@ skip_consecutive_labels (rtx label_or_return)
|
|||
|
||||
return label;
|
||||
}
|
||||
|
||||
/* INSN uses CC0 and is being moved into a delay slot. Set up REG_CC_SETTER
|
||||
and REG_CC_USER notes so we can find it. */
|
||||
|
||||
static void
|
||||
link_cc0_insns (rtx_insn *insn)
|
||||
{
|
||||
rtx user = next_nonnote_insn (insn);
|
||||
|
||||
if (NONJUMP_INSN_P (user) && GET_CODE (PATTERN (user)) == SEQUENCE)
|
||||
user = XVECEXP (PATTERN (user), 0, 0);
|
||||
|
||||
add_reg_note (user, REG_CC_SETTER, insn);
|
||||
add_reg_note (insn, REG_CC_USER, user);
|
||||
}
|
||||
|
||||
/* Insns which have delay slots that have not yet been filled. */
|
||||
|
||||
|
@ -345,8 +320,7 @@ insn_references_resource_p (rtx insn, struct resources *res,
|
|||
|
||||
/* Return TRUE if INSN modifies resources that are marked in RES.
|
||||
INCLUDE_DELAYED_EFFECTS is set if the actions of that routine should be
|
||||
included. CC0 is only modified if it is explicitly set; see comments
|
||||
in front of mark_set_resources for details. */
|
||||
included. */
|
||||
|
||||
static int
|
||||
insn_sets_resource_p (rtx insn, struct resources *res,
|
||||
|
@ -640,49 +614,11 @@ delete_from_delay_slot (rtx_insn *insn)
|
|||
return trial;
|
||||
}
|
||||
|
||||
/* Delete INSN, a JUMP_INSN. If it is a conditional jump, we must track down
|
||||
the insn that sets CC0 for it and delete it too. */
|
||||
/* Delete INSN, a JUMP_INSN. */
|
||||
|
||||
static void
|
||||
delete_scheduled_jump (rtx_insn *insn)
|
||||
{
|
||||
/* Delete the insn that sets cc0 for us. On machines without cc0, we could
|
||||
delete the insn that sets the condition code, but it is hard to find it.
|
||||
Since this case is rare anyway, don't bother trying; there would likely
|
||||
be other insns that became dead anyway, which we wouldn't know to
|
||||
delete. */
|
||||
|
||||
if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, insn))
|
||||
{
|
||||
rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
|
||||
|
||||
/* If a reg-note was found, it points to an insn to set CC0. This
|
||||
insn is in the delay list of some other insn. So delete it from
|
||||
the delay list it was in. */
|
||||
if (note)
|
||||
{
|
||||
if (! FIND_REG_INC_NOTE (XEXP (note, 0), NULL_RTX)
|
||||
&& sets_cc0_p (PATTERN (XEXP (note, 0))) == 1)
|
||||
delete_from_delay_slot (as_a <rtx_insn *> (XEXP (note, 0)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The insn setting CC0 is our previous insn, but it may be in
|
||||
a delay slot. It will be the last insn in the delay slot, if
|
||||
it is. */
|
||||
rtx_insn *trial = previous_insn (insn);
|
||||
if (NOTE_P (trial))
|
||||
trial = prev_nonnote_insn (trial);
|
||||
if (sets_cc0_p (PATTERN (trial)) != 1
|
||||
|| FIND_REG_INC_NOTE (trial, NULL_RTX))
|
||||
return;
|
||||
if (PREV_INSN (NEXT_INSN (trial)) == trial)
|
||||
delete_related_insns (trial);
|
||||
else
|
||||
delete_from_delay_slot (trial);
|
||||
}
|
||||
}
|
||||
|
||||
delete_related_insns (insn);
|
||||
}
|
||||
|
||||
|
@ -1112,9 +1048,6 @@ steal_delay_list_from_target (rtx_insn *insn, rtx condition, rtx_sequence *seq,
|
|||
if (insn_references_resource_p (trial, sets, false)
|
||||
|| insn_sets_resource_p (trial, needed, false)
|
||||
|| insn_sets_resource_p (trial, sets, false)
|
||||
/* If TRIAL sets CC0, we can't copy it, so we can't steal this
|
||||
delay list. */
|
||||
|| (HAVE_cc0 && find_reg_note (trial, REG_CC_USER, NULL_RTX))
|
||||
/* If TRIAL is from the fallthrough code of an annulled branch insn
|
||||
in SEQ, we cannot use it. */
|
||||
|| (INSN_ANNULLED_BRANCH_P (seq->insn (0))
|
||||
|
@ -1219,13 +1152,9 @@ steal_delay_list_from_fallthrough (rtx_insn *insn, rtx condition,
|
|||
rtx_insn *trial = seq->insn (i);
|
||||
rtx_insn *prior_insn;
|
||||
|
||||
/* If TRIAL sets CC0, stealing it will move it too far from the use
|
||||
of CC0. */
|
||||
if (insn_references_resource_p (trial, sets, false)
|
||||
|| insn_sets_resource_p (trial, needed, false)
|
||||
|| insn_sets_resource_p (trial, sets, false)
|
||||
|| (HAVE_cc0 && sets_cc0_p (PATTERN (trial))))
|
||||
|
||||
|| insn_sets_resource_p (trial, sets, false))
|
||||
break;
|
||||
|
||||
/* If this insn was already done, we don't need it. */
|
||||
|
@ -1314,8 +1243,6 @@ try_merge_delay_insns (rtx_insn *insn, rtx_insn *thread)
|
|||
continue;
|
||||
|
||||
if (GET_CODE (next_to_match) == GET_CODE (trial)
|
||||
/* We can't share an insn that sets cc0. */
|
||||
&& (!HAVE_cc0 || ! sets_cc0_p (pat))
|
||||
&& ! insn_references_resource_p (trial, &set, true)
|
||||
&& ! insn_sets_resource_p (trial, &set, true)
|
||||
&& ! insn_sets_resource_p (trial, &needed, true)
|
||||
|
@ -1385,7 +1312,6 @@ try_merge_delay_insns (rtx_insn *insn, rtx_insn *thread)
|
|||
if (! insn_references_resource_p (dtrial, &set, true)
|
||||
&& ! insn_sets_resource_p (dtrial, &set, true)
|
||||
&& ! insn_sets_resource_p (dtrial, &needed, true)
|
||||
&& (!HAVE_cc0 || ! sets_cc0_p (PATTERN (dtrial)))
|
||||
&& rtx_equal_p (PATTERN (next_to_match), PATTERN (dtrial))
|
||||
/* Check that DTRIAL and NEXT_TO_MATCH does not reference a
|
||||
resource modified between them (only dtrial is checked because
|
||||
|
@ -1549,8 +1475,8 @@ redundant_insn (rtx insn, rtx_insn *target, const vec<rtx_insn *> &delay_list)
|
|||
if (trial == 0)
|
||||
return 0;
|
||||
|
||||
/* See what resources this insn sets and needs. If they overlap, or
|
||||
if this insn references CC0, it can't be redundant. */
|
||||
/* See what resources this insn sets and needs. If they overlap, it
|
||||
can't be redundant. */
|
||||
|
||||
CLEAR_RESOURCE (&needed);
|
||||
CLEAR_RESOURCE (&set);
|
||||
|
@ -1562,7 +1488,6 @@ redundant_insn (rtx insn, rtx_insn *target, const vec<rtx_insn *> &delay_list)
|
|||
target_main = XVECEXP (PATTERN (target), 0, 0);
|
||||
|
||||
if (resource_conflicts_p (&needed, &set)
|
||||
|| (HAVE_cc0 && reg_mentioned_p (cc0_rtx, ipat))
|
||||
/* The insn requiring the delay may not set anything needed or set by
|
||||
INSN. */
|
||||
|| insn_sets_resource_p (target_main, &needed, true)
|
||||
|
@ -2051,8 +1976,6 @@ fill_simple_delay_slots (int non_jumps_p)
|
|||
filter_flags ? &fset : &set,
|
||||
true)
|
||||
&& ! insn_sets_resource_p (trial, &needed, true)
|
||||
/* Can't separate set of cc0 from its use. */
|
||||
&& (!HAVE_cc0 || ! (reg_mentioned_p (cc0_rtx, pat) && ! sets_cc0_p (pat)))
|
||||
&& ! can_throw_internal (trial))
|
||||
{
|
||||
trial = try_split (pat, trial, 1);
|
||||
|
@ -2186,7 +2109,6 @@ fill_simple_delay_slots (int non_jumps_p)
|
|||
&& ! insn_references_resource_p (trial, &set, true)
|
||||
&& ! insn_sets_resource_p (trial, &set, true)
|
||||
&& ! insn_sets_resource_p (trial, &needed, true)
|
||||
&& (!HAVE_cc0 && ! (reg_mentioned_p (cc0_rtx, pat) && ! sets_cc0_p (pat)))
|
||||
&& ! (maybe_never && may_trap_or_fault_p (pat))
|
||||
&& (trial = try_split (pat, trial, 0))
|
||||
&& eligible_for_delay (insn, slots_filled, trial, flags)
|
||||
|
@ -2194,8 +2116,6 @@ fill_simple_delay_slots (int non_jumps_p)
|
|||
{
|
||||
next_trial = next_nonnote_insn (trial);
|
||||
add_to_delay_list (trial, &delay_list);
|
||||
if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, pat))
|
||||
link_cc0_insns (trial);
|
||||
|
||||
delete_related_insns (trial);
|
||||
if (slots_to_fill == ++slots_filled)
|
||||
|
@ -2232,7 +2152,6 @@ fill_simple_delay_slots (int non_jumps_p)
|
|||
&& ! insn_references_resource_p (next_trial, &set, true)
|
||||
&& ! insn_sets_resource_p (next_trial, &set, true)
|
||||
&& ! insn_sets_resource_p (next_trial, &needed, true)
|
||||
&& (!HAVE_cc0 || ! reg_mentioned_p (cc0_rtx, PATTERN (next_trial)))
|
||||
&& ! (maybe_never && may_trap_or_fault_p (PATTERN (next_trial)))
|
||||
&& (next_trial = try_split (PATTERN (next_trial), next_trial, 0))
|
||||
&& eligible_for_delay (insn, slots_filled, next_trial, flags)
|
||||
|
@ -2452,23 +2371,10 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
|
|||
if (GET_CODE (trial) == DEBUG_INSN)
|
||||
continue;
|
||||
|
||||
/* If TRIAL conflicts with the insns ahead of it, we lose. Also,
|
||||
don't separate or copy insns that set and use CC0. */
|
||||
/* If TRIAL conflicts with the insns ahead of it, we lose. */
|
||||
if (! insn_references_resource_p (trial, &set, true)
|
||||
&& ! insn_sets_resource_p (trial, filter_flags ? &fset : &set, true)
|
||||
&& ! insn_sets_resource_p (trial, &needed, true)
|
||||
/* If we're handling sets to the flags register specially, we
|
||||
only allow an insn into a delay-slot, if it either:
|
||||
- doesn't set the flags register,
|
||||
- the "set" of the flags register isn't used (clobbered),
|
||||
- insns between the delay-slot insn and the trial-insn
|
||||
as accounted in "set", have not affected the flags register. */
|
||||
&& (! filter_flags
|
||||
|| ! insn_sets_resource_p (trial, &flags_res, true)
|
||||
|| find_regno_note (trial, REG_UNUSED, targetm.flags_regnum)
|
||||
|| ! TEST_HARD_REG_BIT (set.regs, targetm.flags_regnum))
|
||||
&& (!HAVE_cc0 || (! (reg_mentioned_p (cc0_rtx, pat)
|
||||
&& (! own_thread || ! sets_cc0_p (pat)))))
|
||||
&& ! can_throw_internal (trial))
|
||||
{
|
||||
rtx_insn *prior_insn;
|
||||
|
@ -2543,9 +2449,6 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
|
|||
must_annul = 1;
|
||||
winner:
|
||||
|
||||
if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, pat))
|
||||
link_cc0_insns (trial);
|
||||
|
||||
/* If we own this thread, delete the insn. If this is the
|
||||
destination of a branch, show that a basic block status
|
||||
may have been updated. In any case, mark the new
|
||||
|
@ -3083,37 +2986,13 @@ delete_prior_computation (rtx note, rtx_insn *insn)
|
|||
|
||||
Look at all our REG_DEAD notes. If a previous insn does nothing other
|
||||
than set a register that dies in this insn, we can delete that insn
|
||||
as well.
|
||||
|
||||
On machines with CC0, if CC0 is used in this insn, we may be able to
|
||||
delete the insn that set it. */
|
||||
as well. */
|
||||
|
||||
static void
|
||||
delete_computation (rtx_insn *insn)
|
||||
{
|
||||
rtx note, next;
|
||||
|
||||
if (HAVE_cc0 && reg_referenced_p (cc0_rtx, PATTERN (insn)))
|
||||
{
|
||||
rtx_insn *prev = prev_nonnote_insn (insn);
|
||||
/* We assume that at this stage
|
||||
CC's are always set explicitly
|
||||
and always immediately before the jump that
|
||||
will use them. So if the previous insn
|
||||
exists to set the CC's, delete it
|
||||
(unless it performs auto-increments, etc.). */
|
||||
if (prev && NONJUMP_INSN_P (prev)
|
||||
&& sets_cc0_p (PATTERN (prev)))
|
||||
{
|
||||
if (sets_cc0_p (PATTERN (prev)) > 0
|
||||
&& ! side_effects_p (PATTERN (prev)))
|
||||
delete_computation (prev);
|
||||
else
|
||||
/* Otherwise, show that cc0 won't be used. */
|
||||
add_reg_note (prev, REG_UNUSED, cc0_rtx);
|
||||
}
|
||||
}
|
||||
|
||||
for (note = REG_NOTES (insn); note; note = next)
|
||||
{
|
||||
next = XEXP (note, 1);
|
||||
|
@ -3458,14 +3337,7 @@ relax_delay_slots (rtx_insn *first)
|
|||
&& !INSN_ANNULLED_BRANCH_P (delay_jump_insn)
|
||||
&& !condjump_in_parallel_p (delay_jump_insn)
|
||||
&& prev_active_insn (as_a<rtx_insn *> (target_label)) == insn
|
||||
&& !BARRIER_P (prev_nonnote_insn (as_a<rtx_insn *> (target_label)))
|
||||
/* If the last insn in the delay slot sets CC0 for some insn,
|
||||
various code assumes that it is in a delay slot. We could
|
||||
put it back where it belonged and delete the register notes,
|
||||
but it doesn't seem worthwhile in this uncommon case. */
|
||||
&& (!HAVE_cc0
|
||||
|| ! find_reg_note (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1),
|
||||
REG_CC_USER, NULL_RTX)))
|
||||
&& !BARRIER_P (prev_nonnote_insn (as_a<rtx_insn *> (target_label))))
|
||||
{
|
||||
rtx_insn *after;
|
||||
int i;
|
||||
|
|
|
@ -246,10 +246,6 @@ mark_referenced_resources (rtx x, struct resources *res,
|
|||
mark_referenced_resources (XEXP (x, 0), res, false);
|
||||
return;
|
||||
|
||||
case CC0:
|
||||
res->cc = 1;
|
||||
return;
|
||||
|
||||
case UNSPEC_VOLATILE:
|
||||
case TRAP_IF:
|
||||
case ASM_INPUT:
|
||||
|
@ -607,13 +603,7 @@ find_dead_or_set_registers (rtx_insn *target, struct resources *res,
|
|||
set by the called routine.
|
||||
|
||||
If IN_DEST is nonzero, it means we are inside a SET. Otherwise,
|
||||
objects are being referenced instead of set.
|
||||
|
||||
We never mark the insn as modifying the condition code unless it explicitly
|
||||
SETs CC0 even though this is not totally correct. The reason for this is
|
||||
that we require a SET of CC0 to immediately precede the reference to CC0.
|
||||
So if some other insn sets CC0 as a side-effect, we know it cannot affect
|
||||
our computation and thus may be placed in a delay slot. */
|
||||
objects are being referenced instead of set. */
|
||||
|
||||
void
|
||||
mark_set_resources (rtx x, struct resources *res, int in_dest,
|
||||
|
@ -643,11 +633,6 @@ mark_set_resources (rtx x, struct resources *res, int in_dest,
|
|||
/* These don't set any resources. */
|
||||
return;
|
||||
|
||||
case CC0:
|
||||
if (in_dest)
|
||||
res->cc = 1;
|
||||
return;
|
||||
|
||||
case CALL_INSN:
|
||||
/* Called routine modifies the condition code, memory, any registers
|
||||
that aren't saved across calls, global registers and anything
|
||||
|
|
|
@ -295,14 +295,13 @@ copy_rtx (rtx orig)
|
|||
case SYMBOL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
case RETURN:
|
||||
case SIMPLE_RETURN:
|
||||
case SCRATCH:
|
||||
/* SCRATCH must be shared because they represent distinct values. */
|
||||
return orig;
|
||||
case CLOBBER:
|
||||
/* Share clobbers of hard registers (like cc0), but do not share pseudo reg
|
||||
/* Share clobbers of hard registers, but do not share pseudo reg
|
||||
clobbers or clobbers of hard registers that originated as pseudos.
|
||||
This is needed to allow safe register renaming. */
|
||||
if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER
|
||||
|
@ -388,7 +387,6 @@ shallow_copy_rtx (const_rtx orig MEM_STAT_DECL)
|
|||
case SYMBOL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
case RETURN:
|
||||
case SIMPLE_RETURN:
|
||||
case SCRATCH:
|
||||
|
|
|
@ -287,7 +287,7 @@ DEF_RTL_EXPR(PREFETCH, "prefetch", "eee", RTX_EXTRA)
|
|||
---------------------------------------------------------------------- */
|
||||
|
||||
/* Assignment.
|
||||
Operand 1 is the location (REG, MEM, PC, CC0 or whatever) assigned to.
|
||||
Operand 1 is the location (REG, MEM, PC or whatever) assigned to.
|
||||
Operand 2 is the value stored there.
|
||||
ALL assignment must use SET.
|
||||
Instructions that do multiple assignments must use multiple SET,
|
||||
|
@ -436,13 +436,6 @@ DEF_RTL_EXPR(LABEL_REF, "label_ref", "u", RTX_CONST_OBJ)
|
|||
This is either a DECL node, or some kind of constant. */
|
||||
DEF_RTL_EXPR(SYMBOL_REF, "symbol_ref", "s0", RTX_CONST_OBJ)
|
||||
|
||||
/* The condition code register is represented, in our imagination,
|
||||
as a register holding a value that can be compared to zero.
|
||||
In fact, the machine has already compared them and recorded the
|
||||
results; but instructions that look at the condition code
|
||||
pretend to be looking at the entire value and comparing it. */
|
||||
DEF_RTL_EXPR(CC0, "cc0", "", RTX_OBJ)
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Expressions for operators in an rtl pattern
|
||||
---------------------------------------------------------------------- */
|
||||
|
|
|
@ -3352,8 +3352,6 @@ extern rtx_insn *next_real_nondebug_insn (rtx);
|
|||
extern rtx_insn *prev_active_insn (rtx_insn *);
|
||||
extern rtx_insn *next_active_insn (rtx_insn *);
|
||||
extern int active_insn_p (const rtx_insn *);
|
||||
extern rtx_insn *next_cc0_user (rtx_insn *);
|
||||
extern rtx_insn *prev_cc0_setter (rtx_insn *);
|
||||
|
||||
/* In emit-rtl.c */
|
||||
extern int insn_line (const rtx_insn *);
|
||||
|
@ -3790,7 +3788,6 @@ extern GTY(()) rtx const_tiny_rtx[4][(int) MAX_MACHINE_MODE];
|
|||
#define CONSTM1_RTX(MODE) (const_tiny_rtx[3][(int) (MODE)])
|
||||
|
||||
extern GTY(()) rtx pc_rtx;
|
||||
extern GTY(()) rtx cc0_rtx;
|
||||
extern GTY(()) rtx ret_rtx;
|
||||
extern GTY(()) rtx simple_return_rtx;
|
||||
extern GTY(()) rtx_insn *invalid_insn_rtx;
|
||||
|
@ -4126,8 +4123,6 @@ extern int simplejump_p (const rtx_insn *);
|
|||
extern int returnjump_p (const rtx_insn *);
|
||||
extern int eh_returnjump_p (rtx_insn *);
|
||||
extern int onlyjump_p (const rtx_insn *);
|
||||
extern int only_sets_cc0_p (const_rtx);
|
||||
extern int sets_cc0_p (const_rtx);
|
||||
extern int invert_jump_1 (rtx_jump_insn *, rtx);
|
||||
extern int invert_jump (rtx_jump_insn *, rtx, int);
|
||||
extern int rtx_renumbered_equal_p (const_rtx, const_rtx);
|
||||
|
|
|
@ -996,7 +996,6 @@ count_occurrences (const_rtx x, const_rtx find, int count_dest)
|
|||
case SYMBOL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
return 0;
|
||||
|
||||
case EXPR_LIST:
|
||||
|
@ -1090,7 +1089,6 @@ reg_mentioned_p (const_rtx reg, const_rtx in)
|
|||
/* These codes have no constituent expressions
|
||||
and are unique. */
|
||||
case SCRATCH:
|
||||
case CC0:
|
||||
case PC:
|
||||
return 0;
|
||||
|
||||
|
@ -1173,11 +1171,10 @@ reg_referenced_p (const_rtx x, const_rtx body)
|
|||
if (reg_overlap_mentioned_p (x, SET_SRC (body)))
|
||||
return 1;
|
||||
|
||||
/* If the destination is anything other than CC0, PC, a REG or a SUBREG
|
||||
/* If the destination is anything other than PC, a REG or a SUBREG
|
||||
of a REG that occupies all of the REG, the insn references X if
|
||||
it is mentioned in the destination. */
|
||||
if (GET_CODE (SET_DEST (body)) != CC0
|
||||
&& GET_CODE (SET_DEST (body)) != PC
|
||||
if (GET_CODE (SET_DEST (body)) != PC
|
||||
&& !REG_P (SET_DEST (body))
|
||||
&& ! (GET_CODE (SET_DEST (body)) == SUBREG
|
||||
&& REG_P (SUBREG_REG (SET_DEST (body)))
|
||||
|
@ -1324,7 +1321,6 @@ modified_between_p (const_rtx x, const rtx_insn *start, const rtx_insn *end)
|
|||
return 0;
|
||||
|
||||
case PC:
|
||||
case CC0:
|
||||
return 1;
|
||||
|
||||
case MEM:
|
||||
|
@ -1379,7 +1375,6 @@ modified_in_p (const_rtx x, const_rtx insn)
|
|||
return 0;
|
||||
|
||||
case PC:
|
||||
case CC0:
|
||||
return 1;
|
||||
|
||||
case MEM:
|
||||
|
@ -1917,7 +1912,6 @@ reg_overlap_mentioned_p (const_rtx x, const_rtx in)
|
|||
|
||||
case SCRATCH:
|
||||
case PC:
|
||||
case CC0:
|
||||
return reg_mentioned_p (x, in);
|
||||
|
||||
case PARALLEL:
|
||||
|
@ -1943,7 +1937,7 @@ reg_overlap_mentioned_p (const_rtx x, const_rtx in)
|
|||
ignored by note_stores, but passed to FUN.
|
||||
|
||||
FUN receives three arguments:
|
||||
1. the REG, MEM, CC0 or PC being stored in or clobbered,
|
||||
1. the REG, MEM or PC being stored in or clobbered,
|
||||
2. the SET or CLOBBER rtx that does the store,
|
||||
3. the pointer DATA provided to note_stores.
|
||||
|
||||
|
@ -2392,8 +2386,8 @@ vec_rtx_properties_base::grow (ptrdiff_t start)
|
|||
}
|
||||
|
||||
/* Return nonzero if X's old contents don't survive after INSN.
|
||||
This will be true if X is (cc0) or if X is a register and
|
||||
X dies in INSN or because INSN entirely sets X.
|
||||
This will be true if X is a register and X dies in INSN or because
|
||||
INSN entirely sets X.
|
||||
|
||||
"Entirely set" means set directly and not through a SUBREG, or
|
||||
ZERO_EXTRACT, so no trace of the old contents remains.
|
||||
|
@ -2414,10 +2408,6 @@ dead_or_set_p (const rtx_insn *insn, const_rtx x)
|
|||
unsigned int regno, end_regno;
|
||||
unsigned int i;
|
||||
|
||||
/* Can't use cc0_rtx below since this file is used by genattrtab.c. */
|
||||
if (GET_CODE (x) == CC0)
|
||||
return 1;
|
||||
|
||||
gcc_assert (REG_P (x));
|
||||
|
||||
regno = REGNO (x);
|
||||
|
@ -2717,8 +2707,6 @@ alloc_reg_note (enum reg_note kind, rtx datum, rtx list)
|
|||
gcc_checking_assert (!int_reg_note_p (kind));
|
||||
switch (kind)
|
||||
{
|
||||
case REG_CC_SETTER:
|
||||
case REG_CC_USER:
|
||||
case REG_LABEL_TARGET:
|
||||
case REG_LABEL_OPERAND:
|
||||
case REG_TM:
|
||||
|
@ -2963,7 +2951,6 @@ volatile_insn_p (const_rtx x)
|
|||
case SYMBOL_REF:
|
||||
case CONST:
|
||||
CASE_CONST_ANY:
|
||||
case CC0:
|
||||
case PC:
|
||||
case REG:
|
||||
case SCRATCH:
|
||||
|
@ -3024,7 +3011,6 @@ volatile_refs_p (const_rtx x)
|
|||
case SYMBOL_REF:
|
||||
case CONST:
|
||||
CASE_CONST_ANY:
|
||||
case CC0:
|
||||
case PC:
|
||||
case REG:
|
||||
case SCRATCH:
|
||||
|
@ -3084,7 +3070,6 @@ side_effects_p (const_rtx x)
|
|||
case SYMBOL_REF:
|
||||
case CONST:
|
||||
CASE_CONST_ANY:
|
||||
case CC0:
|
||||
case PC:
|
||||
case REG:
|
||||
case SCRATCH:
|
||||
|
@ -3172,7 +3157,6 @@ may_trap_p_1 (const_rtx x, unsigned flags)
|
|||
case LABEL_REF:
|
||||
case CONST:
|
||||
case PC:
|
||||
case CC0:
|
||||
case REG:
|
||||
case SCRATCH:
|
||||
return 0;
|
||||
|
@ -5828,7 +5812,7 @@ seq_cost (const rtx_insn *seq, bool speed)
|
|||
canonical form to simplify testing by callers. Specifically:
|
||||
|
||||
(1) The code will always be a comparison operation (EQ, NE, GT, etc.).
|
||||
(2) Both operands will be machine operands; (cc0) will have been replaced.
|
||||
(2) Both operands will be machine operands.
|
||||
(3) If an operand is a constant, it will be the second operand.
|
||||
(4) (LE x const) will be replaced with (LT x <const+1>) and similarly
|
||||
for GE, GEU, and LEU.
|
||||
|
@ -5891,22 +5875,6 @@ canonicalize_condition (rtx_insn *insn, rtx cond, int reverse,
|
|||
/* Set nonzero when we find something of interest. */
|
||||
rtx x = 0;
|
||||
|
||||
/* If comparison with cc0, import actual comparison from compare
|
||||
insn. */
|
||||
if (op0 == cc0_rtx)
|
||||
{
|
||||
if ((prev = prev_nonnote_insn (prev)) == 0
|
||||
|| !NONJUMP_INSN_P (prev)
|
||||
|| (set = single_set (prev)) == 0
|
||||
|| SET_DEST (set) != cc0_rtx)
|
||||
return 0;
|
||||
|
||||
op0 = SET_SRC (set);
|
||||
op1 = CONST0_RTX (GET_MODE (op0));
|
||||
if (earliest)
|
||||
*earliest = prev;
|
||||
}
|
||||
|
||||
/* If this is a COMPARE, pick up the two things being compared. */
|
||||
if (GET_CODE (op0) == COMPARE)
|
||||
{
|
||||
|
@ -6095,10 +6063,6 @@ canonicalize_condition (rtx_insn *insn, rtx cond, int reverse,
|
|||
}
|
||||
}
|
||||
|
||||
/* Never return CC0; return zero instead. */
|
||||
if (CC0_P (op0))
|
||||
return 0;
|
||||
|
||||
/* We promised to return a comparison. */
|
||||
rtx ret = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
|
||||
if (COMPARISON_P (ret))
|
||||
|
|
|
@ -2579,21 +2579,6 @@ sched_analyze_2 (class deps_desc *deps, rtx x, rtx_insn *insn)
|
|||
|
||||
return;
|
||||
|
||||
case CC0:
|
||||
if (!HAVE_cc0)
|
||||
gcc_unreachable ();
|
||||
|
||||
/* User of CC0 depends on immediately preceding insn. */
|
||||
SCHED_GROUP_P (insn) = 1;
|
||||
/* Don't move CC0 setter to another block (it can set up the
|
||||
same flag for previous CC0 users which is safe). */
|
||||
CANT_MOVE (prev_nonnote_insn (insn)) = 1;
|
||||
|
||||
if (cslr_p && sched_deps_info->finish_rhs)
|
||||
sched_deps_info->finish_rhs ();
|
||||
|
||||
return;
|
||||
|
||||
case REG:
|
||||
{
|
||||
int regno = REGNO (x);
|
||||
|
|
|
@ -2442,7 +2442,7 @@ add_branch_dependences (rtx_insn *head, rtx_insn *tail)
|
|||
{
|
||||
rtx_insn *insn, *last;
|
||||
|
||||
/* For all branches, calls, uses, clobbers, cc0 setters, and instructions
|
||||
/* For all branches, calls, uses, clobbers, and instructions
|
||||
that can throw exceptions, force them to remain in order at the end of
|
||||
the block by adding dependencies and giving the last a high priority.
|
||||
There may be notes present, and prev_head may also be a note.
|
||||
|
@ -2451,9 +2451,6 @@ add_branch_dependences (rtx_insn *head, rtx_insn *tail)
|
|||
end since moving them results in worse register allocation. Uses remain
|
||||
at the end to ensure proper register allocation.
|
||||
|
||||
cc0 setters remain at the end because they can't be moved away from
|
||||
their cc0 user.
|
||||
|
||||
Predecessors of SCHED_GROUP_P instructions at the end remain at the end.
|
||||
|
||||
COND_EXEC insns cannot be moved past a branch (see e.g. PR17808).
|
||||
|
@ -2473,7 +2470,6 @@ add_branch_dependences (rtx_insn *head, rtx_insn *tail)
|
|||
&& (GET_CODE (PATTERN (insn)) == USE
|
||||
|| GET_CODE (PATTERN (insn)) == CLOBBER
|
||||
|| can_throw_internal (insn)
|
||||
|| (HAVE_cc0 && sets_cc0_p (PATTERN (insn)))
|
||||
|| (!reload_completed
|
||||
&& sets_likely_spilled (PATTERN (insn)))))
|
||||
|| NOTE_P (insn)
|
||||
|
|
|
@ -1772,9 +1772,6 @@ insert_prologue_epilogue_for_components (sbitmap components)
|
|||
void
|
||||
try_shrink_wrapping_separate (basic_block first_bb)
|
||||
{
|
||||
if (HAVE_cc0)
|
||||
return;
|
||||
|
||||
if (!(SHRINK_WRAPPING_ENABLED
|
||||
&& flag_shrink_wrap_separate
|
||||
&& optimize_function_for_speed_p (cfun)
|
||||
|
|
|
@ -2713,15 +2713,12 @@ simplify_context::simplify_binary_operation_1 (rtx_code code,
|
|||
rtx xop00 = XEXP (op0, 0);
|
||||
rtx xop10 = XEXP (op1, 0);
|
||||
|
||||
if (GET_CODE (xop00) == CC0 && GET_CODE (xop10) == CC0)
|
||||
return xop00;
|
||||
|
||||
if (REG_P (xop00) && REG_P (xop10)
|
||||
&& REGNO (xop00) == REGNO (xop10)
|
||||
&& GET_MODE (xop00) == mode
|
||||
&& GET_MODE (xop10) == mode
|
||||
&& GET_MODE_CLASS (mode) == MODE_CC)
|
||||
return xop00;
|
||||
if (REG_P (xop00) && REG_P (xop10)
|
||||
&& REGNO (xop00) == REGNO (xop10)
|
||||
&& GET_MODE (xop00) == mode
|
||||
&& GET_MODE (xop10) == mode
|
||||
&& GET_MODE_CLASS (mode) == MODE_CC)
|
||||
return xop00;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -5374,8 +5371,7 @@ simplify_context::simplify_relational_operation (rtx_code code,
|
|||
return simplify_gen_relational (code, mode, VOIDmode,
|
||||
XEXP (op0, 0), XEXP (op0, 1));
|
||||
|
||||
if (GET_MODE_CLASS (cmp_mode) == MODE_CC
|
||||
|| CC0_P (op0))
|
||||
if (GET_MODE_CLASS (cmp_mode) == MODE_CC)
|
||||
return NULL_RTX;
|
||||
|
||||
trueop0 = avoid_constant_pool_reference (op0);
|
||||
|
@ -5742,7 +5738,7 @@ simplify_const_relational_operation (enum rtx_code code,
|
|||
|
||||
/* We can't simplify MODE_CC values since we don't know what the
|
||||
actual comparison is. */
|
||||
if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC || CC0_P (op0))
|
||||
if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
|
||||
return 0;
|
||||
|
||||
/* Make sure the constant is second. */
|
||||
|
|
|
@ -1069,7 +1069,8 @@ extern void fancy_abort (const char *, int, const char *)
|
|||
LIBGCC2_LONG_DOUBLE_TYPE_SIZE STRUCT_VALUE \
|
||||
EH_FRAME_IN_DATA_SECTION TARGET_FLT_EVAL_METHOD_NON_DEFAULT \
|
||||
JCR_SECTION_NAME TARGET_USE_JCR_SECTION SDB_DEBUGGING_INFO \
|
||||
SDB_DEBUG NO_IMPLICIT_EXTERN_C
|
||||
SDB_DEBUG NO_IMPLICIT_EXTERN_C NOTICE_UPDATE_CC \
|
||||
CC_STATUS_MDEP_INIT CC_STATUS_MDEP CC_STATUS
|
||||
|
||||
/* Hooks that are no longer used. */
|
||||
#pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE \
|
||||
|
|
|
@ -3996,7 +3996,7 @@ filling in a single size corresponding to each hard register;\n\
|
|||
at by the second argument should be set to -1. */
|
||||
DEFHOOK
|
||||
(fixed_condition_code_regs,
|
||||
"On targets which do not use @code{(cc0)}, and which use a hard\n\
|
||||
"On targets which use a hard\n\
|
||||
register rather than a pseudo-register to hold condition codes, the\n\
|
||||
regular CSE passes are often not able to identify cases in which the\n\
|
||||
hard register is set to a common value. Use this hook to enable a\n\
|
||||
|
|
|
@ -68,12 +68,11 @@ cleanup_auto_inc_dec (rtx src, machine_mode mem_mode ATTRIBUTE_UNUSED)
|
|||
case SYMBOL_REF:
|
||||
case CODE_LABEL:
|
||||
case PC:
|
||||
case CC0:
|
||||
case SCRATCH:
|
||||
/* SCRATCH must be shared because they represent distinct values. */
|
||||
return x;
|
||||
case CLOBBER:
|
||||
/* Share clobbers of hard registers (like cc0), but do not share pseudo reg
|
||||
/* Share clobbers of hard registers, but do not share pseudo reg
|
||||
clobbers or clobbers of hard registers that originated as pseudos.
|
||||
This is needed to allow safe register renaming. */
|
||||
if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
|
||||
|
|
|
@ -2450,7 +2450,6 @@ unsuitable_loc (rtx loc)
|
|||
{
|
||||
case PC:
|
||||
case SCRATCH:
|
||||
case CC0:
|
||||
case ASM_INPUT:
|
||||
case ASM_OPERANDS:
|
||||
return true;
|
||||
|
@ -5661,7 +5660,6 @@ non_suitable_const (const_rtx x)
|
|||
case DEBUG_EXPR:
|
||||
case PC:
|
||||
case SCRATCH:
|
||||
case CC0:
|
||||
case ASM_INPUT:
|
||||
case ASM_OPERANDS:
|
||||
return true;
|
||||
|
|
Loading…
Add table
Reference in a new issue