summaryrefslogtreecommitdiff
path: root/gcc/jump.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2001-01-07 18:39:19 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2001-01-07 18:39:19 +0000
commit8e98892d68c1098165edfdac2499157f788c7eac (patch)
tree6257660a69c432d217093b6d999d5392a89e6f7b /gcc/jump.c
parent36cf4ed6d51d1175d0cf5bbf9947f78937dcc237 (diff)
downloadgcc-8e98892d68c1098165edfdac2499157f788c7eac.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@38779 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/jump.c')
-rw-r--r--gcc/jump.c212
1 files changed, 149 insertions, 63 deletions
diff --git a/gcc/jump.c b/gcc/jump.c
index 2dae0e53333..6fa1f339187 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -1699,80 +1699,174 @@ jump_back_p (insn, target)
&& rtx_renumbered_equal_p (XEXP (cinsn, 1), XEXP (ctarget, 1)));
}
-/* 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. */
-
-int
-can_reverse_comparison_p (comparison, insn)
- rtx comparison;
- rtx insn;
+/* 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;
{
- rtx arg0;
+ enum machine_mode mode;
/* If this is not actually a comparison, we can't reverse it. */
- if (GET_RTX_CLASS (GET_CODE (comparison)) != '<')
- return 0;
+ if (GET_RTX_CLASS (code) != '<')
+ return UNKNOWN;
- 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;
+ mode = GET_MODE (arg0);
+ if (mode == VOIDmode)
+ mode = GET_MODE (arg1);
- arg0 = XEXP (comparison, 0);
+ /* 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
- /* 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.
+ /* 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);
- Handle cc0 and a MODE_CC register. */
- if ((GET_CODE (arg0) == REG && GET_MODE_CLASS (GET_MODE (arg0)) == MODE_CC)
+ if (GET_MODE_CLASS (mode) == 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
-
+ 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 0;
+ return UNKNOWN;
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);
+ {
+ 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 (arg0) == COMPARE)
- arg0 = XEXP (arg0, 0);
- break;
- }
+ 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;
+ }
}
- /* 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));
+ /* 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.
+
+ 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;
+{
+ 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;
+
+ code = reversed_comparison_code (comparison, insn);
+ if (code == UNKNOWN)
+ return 0;
+
+ /* 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: