aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2001-01-07 19:39:19 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2001-01-07 18:39:19 +0000
commitab94bc48842d18b6e44546303904656fa37777f2 (patch)
tree6257660a69c432d217093b6d999d5392a89e6f7b /gcc
parentf6a13bffbbae0b5cf9e74b8ee169c892d25faf0e (diff)
downloadgcc-ab94bc48842d18b6e44546303904656fa37777f2.zip
gcc-ab94bc48842d18b6e44546303904656fa37777f2.tar.gz
gcc-ab94bc48842d18b6e44546303904656fa37777f2.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/jump.c212
-rw-r--r--gcc/rtl.h3
3 files changed, 161 insertions, 63 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index de0d48c..f766766 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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/.
diff --git a/gcc/jump.c b/gcc/jump.c
index 2dae0e5..6fa1f33 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:
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 6e2aee6..9db7a37 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -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));