jump.c (reversed_comparison_code_parts, [...]): New.

* jump.c (reversed_comparison_code_parts, reversed_comparison_code):
	New.
	(can_reverse_comparison_p): Rewrite to use reversed_comparison_code.
	(reverse_condition_maybe_unordered): Abort on unsigned comparisons.
	* rtl.h (reversed_comparison_code_parts, reversed_comparison_code):
	Declare.

From-SVN: r38779
This commit is contained in:
Jan Hubicka 2001-01-07 19:39:19 +01:00 committed by Jan Hubicka
parent f6a13bffbb
commit ab94bc4884
3 changed files with 166 additions and 68 deletions

View File

@ -1,3 +1,12 @@
Sun Jan 7 19:37:48 MET 2001 Jan Hubicka <jh@suse.cz>
* jump.c (reversed_comparison_code_parts, reversed_comparison_code):
New.
(can_reverse_comparison_p): Rewrite to use reversed_comparison_code.
(reverse_condition_maybe_unordered): Abort on unsigned comparisons.
* rtl.h (reversed_comparison_code_parts, reversed_comparison_code):
Declare.
2001-01-07 Neil Booth <neil@daikokuya.demon.co.uk>
* fix-header.c (read_scan_file): s/pfile/scan_in/.

View File

@ -1699,80 +1699,174 @@ jump_back_p (insn, target)
&& rtx_renumbered_equal_p (XEXP (cinsn, 1), XEXP (ctarget, 1)));
}
/* Given a comparison (CODE ARG0 ARG1), inside a insn, INSN, return an code
of reversed comparison if it is possible to do so. Otherwise return UNKNOWN.
UNKNOWN may be returned in case we are having CC_MODE compare and we don't
know whether it's source is floating point or integer comparison. Machine
description should define REVERSIBLE_CC_MODE and REVERSE_CONDITION macros
to help this function avoid overhead in these cases. */
enum rtx_code
reversed_comparison_code_parts (code, arg0, arg1, insn)
rtx insn, arg0, arg1;
enum rtx_code code;
{
enum machine_mode mode;
/* If this is not actually a comparison, we can't reverse it. */
if (GET_RTX_CLASS (code) != '<')
return UNKNOWN;
mode = GET_MODE (arg0);
if (mode == VOIDmode)
mode = GET_MODE (arg1);
/* First see if machine description supply us way to reverse the comparison.
Give it priority over everything else to allow machine description to do
tricks. */
#ifdef REVERSIBLE_CC_MODE
if (GET_MODE_CLASS (mode) == MODE_CC)
&& REVERSIBLE_CC_MODE (mode))
{
#ifdef REVERSE_CONDITION
return REVERSE_CONDITION (code, mode);
#endif
return reverse_condition (code);
}
#endif
/* Try few special cases based on the comparison code. */
switch (code)
{
case GEU:
case GTU:
case LEU:
case LTU:
case NE:
case EQ:
/* It is always safe to reverse EQ and NE, even for the floating
point. Similary the unsigned comparisons are never used for
floating point so we can reverse them in the default way. */
return reverse_condition (code);
case ORDERED:
case UNORDERED:
case LTGT:
case UNEQ:
/* In case we already see unordered comparison, we can be sure to
be dealing with floating point so we don't need any more tests. */
return reverse_condition_maybe_unordered (code);
case UNLT:
case UNLE:
case UNGT:
case UNGE:
/* We don't have safe way to reverse these yet. */
return UNKNOWN;
default:
break;
}
/* In case we give up IEEE compatibility, all comparisons are reversible. */
if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|| flag_fast_math)
return reverse_condition (code);
if (GET_MODE_CLASS (mode) == MODE_CC
#ifdef HAVE_cc0
|| arg0 == cc0_rtx
#endif
)
{
rtx prev;
/* Try to search for the comparison to determine the real mode.
This code is expensive, but with sane machine description it
will be never used, since REVERSIBLE_CC_MODE will return true
in all cases. */
if (! insn)
return UNKNOWN;
for (prev = prev_nonnote_insn (insn);
prev != 0 && GET_CODE (prev) != CODE_LABEL;
prev = prev_nonnote_insn (prev))
{
rtx set = set_of (arg0, prev);
if (set && GET_CODE (set) == SET
&& rtx_equal_p (SET_DEST (set), arg0))
{
rtx src = SET_SRC (set);
if (GET_CODE (src) == COMPARE)
{
rtx comparison = src;
arg0 = XEXP (src, 0);
mode = GET_MODE (arg0);
if (mode == VOIDmode)
mode = GET_MODE (XEXP (comparison, 1));
break;
}
/* We can get past reg-reg moves. This may be usefull for model
of i387 comparisons that first move flag registers around. */
if (REG_P (src))
{
arg0 = src;
continue;
}
}
/* If register is clobbered in some ununderstandable way,
give up. */
if (set)
return UNKNOWN;
}
}
/* An integer condition. */
if (GET_CODE (arg0) == CONST_INT
|| (GET_MODE (arg0) != VOIDmode
&& GET_MODE_CLASS (mode) != MODE_CC
&& ! FLOAT_MODE_P (mode)))
return reverse_condition (code);
return UNKNOWN;
}
/* An wrapper around the previous function to take COMPARISON as rtx
expression. This simplifies many callers. */
enum rtx_code
reversed_comparison_code (comparison, insn)
rtx comparison, insn;
{
if (GET_RTX_CLASS (GET_CODE (comparison)) != '<')
return UNKNOWN;
return reversed_comparison_code_parts (GET_CODE (comparison),
XEXP (comparison, 0),
XEXP (comparison, 1), insn);
}
/* Given a comparison, COMPARISON, inside a conditional jump insn, INSN,
return non-zero if it is safe to reverse this comparison. It is if our
floating-point is not IEEE, if this is an NE or EQ comparison, or if
this is known to be an integer comparison. */
this is known to be an integer comparison.
Use of this function is depreached and you should use
REVERSED_COMPARISON_CODE bits instead.
*/
int
can_reverse_comparison_p (comparison, insn)
rtx comparison;
rtx insn;
{
rtx arg0;
enum rtx_code code;
/* If this is not actually a comparison, we can't reverse it. */
if (GET_RTX_CLASS (GET_CODE (comparison)) != '<')
return 0;
if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
/* If this is an NE comparison, it is safe to reverse it to an EQ
comparison and vice versa, even for floating point. If no operands
are NaNs, the reversal is valid. If some operand is a NaN, EQ is
always false and NE is always true, so the reversal is also valid. */
|| flag_fast_math
|| GET_CODE (comparison) == NE
|| GET_CODE (comparison) == EQ)
return 1;
code = reversed_comparison_code (comparison, insn);
if (code == UNKNOWN)
return 0;
arg0 = XEXP (comparison, 0);
/* Make sure ARG0 is one of the actual objects being compared. If we
can't do this, we can't be sure the comparison can be reversed.
Handle cc0 and a MODE_CC register. */
if ((GET_CODE (arg0) == REG && GET_MODE_CLASS (GET_MODE (arg0)) == MODE_CC)
#ifdef HAVE_cc0
|| arg0 == cc0_rtx
#endif
)
{
rtx prev, set;
/* First see if the condition code mode alone if enough to say we can
reverse the condition. If not, then search backwards for a set of
ARG0. We do not need to check for an insn clobbering it since valid
code will contain set a set with no intervening clobber. But
stop when we reach a label. */
#ifdef REVERSIBLE_CC_MODE
if (GET_MODE_CLASS (GET_MODE (arg0)) == MODE_CC
&& REVERSIBLE_CC_MODE (GET_MODE (arg0)))
return 1;
#endif
if (! insn)
return 0;
for (prev = prev_nonnote_insn (insn);
prev != 0 && GET_CODE (prev) != CODE_LABEL;
prev = prev_nonnote_insn (prev))
if ((set = single_set (prev)) != 0
&& rtx_equal_p (SET_DEST (set), arg0))
{
arg0 = SET_SRC (set);
if (GET_CODE (arg0) == COMPARE)
arg0 = XEXP (arg0, 0);
break;
}
}
/* We can reverse this if ARG0 is a CONST_INT or if its mode is
not VOIDmode and neither a MODE_CC nor MODE_FLOAT type. */
return (GET_CODE (arg0) == CONST_INT
|| (GET_MODE (arg0) != VOIDmode
&& GET_MODE_CLASS (GET_MODE (arg0)) != MODE_CC
&& GET_MODE_CLASS (GET_MODE (arg0)) != MODE_FLOAT));
/* The code will follow can_reverse_comparison_p with reverse_condition,
so see if it will get proper result. */
return (code == reverse_condition (GET_CODE (comparison)));
}
/* Given an rtx-code for a comparison, return the code for the negated
@ -1781,7 +1875,7 @@ can_reverse_comparison_p (comparison, insn)
WATCH OUT! reverse_condition is not safe to use on a jump that might
be acting on the results of an IEEE floating point comparison, because
of the special treatment of non-signaling nans in comparisons.
Use can_reverse_comparison_p to be sure. */
Use reversed_comparison_code instead. */
enum rtx_code
reverse_condition (code)
@ -1855,14 +1949,6 @@ reverse_condition_maybe_unordered (code)
return UNGT;
case LTGT:
return UNEQ;
case GTU:
return LEU;
case GEU:
return LTU;
case LTU:
return GEU;
case LEU:
return GTU;
case UNORDERED:
return ORDERED;
case ORDERED:

View File

@ -1701,6 +1701,9 @@ extern void rebuild_jump_labels PARAMS ((rtx));
extern void thread_jumps PARAMS ((rtx, int, int));
extern int rtx_equal_for_thread_p PARAMS ((rtx, rtx, rtx));
extern int can_reverse_comparison_p PARAMS ((rtx, rtx));
extern enum rtx_code reversed_comparison_code PARAMS ((rtx, rtx));
extern enum rtx_code reversed_comparison_code_parts PARAMS ((enum rtx_code,
rtx, rtx, rtx));
extern void delete_for_peephole PARAMS ((rtx, rtx));
extern int condjump_in_parallel_p PARAMS ((rtx));
extern void never_reached_warning PARAMS ((rtx));