summaryrefslogtreecommitdiff
path: root/gcc/jump.c
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>1998-06-02 22:03:22 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>1998-06-02 22:03:22 +0000
commit18681e6f1fb343ce31a9ef19cb0d69ed2cbb1ebe (patch)
tree9401b2f6edacfc3678ca437b6dd73db6418527d7 /gcc/jump.c
parentc8477219ab9947a209d8e1b66ba76d4b96af4821 (diff)
downloadgcc-18681e6f1fb343ce31a9ef19cb0d69ed2cbb1ebe.tar.gz
* jump.c (rtx_unsafe_p): New function.
(jump_optimize): Use it on if/then/else transformations and conditional move transformations. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@20200 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/jump.c')
-rw-r--r--gcc/jump.c104
1 files changed, 93 insertions, 11 deletions
diff --git a/gcc/jump.c b/gcc/jump.c
index d5e33966a88..0a4fecdbb83 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -121,6 +121,7 @@ static void redirect_tablejump PROTO((rtx, rtx));
#ifndef HAVE_cc0
static rtx find_insert_position PROTO((rtx, rtx));
#endif
+static int rtx_unsafe_p PROTO((rtx));
/* Delete no-op jumps and optimize jumps to jumps
and jumps around jumps.
@@ -771,11 +772,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
&& GET_CODE (temp2) == INSN
&& (temp4 = single_set (temp2)) != 0
&& rtx_equal_p (SET_DEST (temp4), temp1)
- && (GET_CODE (SET_SRC (temp4)) == REG
- || GET_CODE (SET_SRC (temp4)) == SUBREG
- || (GET_CODE (SET_SRC (temp4)) == MEM
- && RTX_UNCHANGING_P (SET_SRC (temp4)))
- || CONSTANT_P (SET_SRC (temp4)))
+ && ! rtx_unsafe_p (SET_SRC (temp4))
&& (REG_NOTES (temp2) == 0
|| ((REG_NOTE_KIND (REG_NOTES (temp2)) == REG_EQUAL
|| REG_NOTE_KIND (REG_NOTES (temp2)) == REG_EQUIV)
@@ -807,6 +804,16 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
rtx q;
#endif
+ if (!(GET_CODE (SET_SRC (temp4)) == REG
+ || GET_CODE (SET_SRC (temp4)) == SUBREG
+ || (GET_CODE (SET_SRC (temp4)) == MEM
+ && RTX_UNCHANGING_P (SET_SRC (temp4)))
+ || CONSTANT_P (SET_SRC (temp4))))
+ {
+ fprintf(stderr, "\nxyzzy 1\n");
+ debug_rtx (temp4);
+ }
+
/* Set P to the first jump insn that goes around "x = a;". */
for (p = temp; nuses && p; p = prev_nonnote_insn (p))
{
@@ -846,7 +853,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
&& ! reg_referenced_between_p (temp1, p, NEXT_INSN (temp3))
&& ! reg_set_between_p (temp1, p, temp3)
&& (GET_CODE (SET_SRC (temp4)) == CONST_INT
- || ! reg_set_between_p (SET_SRC (temp4), p, temp2)))
+ || ! modified_between_p (SET_SRC (temp4), p, temp2)))
{
emit_insn_after_with_line_notes (PATTERN (temp2), p, temp2);
delete_insn (temp2);
@@ -1161,11 +1168,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
&& GET_CODE (temp1 = SET_DEST (PATTERN (temp))) == REG
&& (! SMALL_REGISTER_CLASSES
|| REGNO (temp1) >= FIRST_PSEUDO_REGISTER)
- && (GET_CODE (temp2 = SET_SRC (PATTERN (temp))) == REG
- || (GET_CODE (temp2) == MEM && RTX_UNCHANGING_P (temp2))
- || GET_CODE (temp2) == SUBREG
- /* ??? How about floating point constants? */
- || CONSTANT_P (temp2))
+ && ! rtx_unsafe_p (temp2 = SET_SRC (PATTERN (temp)))
/* Allow either form, but prefer the former if both apply.
There is no point in using the old value of TEMP1 if
it is a register, since cse will alias them. It can
@@ -1203,6 +1206,16 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
#endif
)
{
+ if (! (GET_CODE (temp2) == REG
+ || (GET_CODE (temp2) == MEM && RTX_UNCHANGING_P (temp2))
+ || GET_CODE (temp2) == SUBREG
+ /* ??? How about floating point constants? */
+ || CONSTANT_P (temp2)))
+ {
+ fprintf(stderr, "\nxyzzy 2\n");
+ debug_rtx (PATTERN (temp));
+ }
+
#ifdef HAVE_conditional_move
/* First try a conditional move. */
{
@@ -4783,4 +4796,73 @@ find_insert_position (insn, new)
return reg_mentioned_p (SET_DEST (single_set (new)), prev) ? 0 : prev;
}
+
+/* Return 1 if the value of X is unsafe to arbitrarily evaluate, i.e.
+ might fault on some arguments. This is used in connection with
+ conditional move optimization. */
+
+static int
+rtx_unsafe_p (x)
+ rtx x;
+{
+ register RTX_CODE code = GET_CODE (x);
+ register int i;
+ register char *fmt;
+
+ switch (code)
+ {
+ case MEM:
+ return ! RTX_UNCHANGING_P (x);
+
+ case QUEUED:
+ return 1;
+
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case CONST_STRING:
+ case CONST:
+ case PC:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ case ADDRESSOF:
+ case REG:
+ return 0;
+
+ case DIV:
+ case MOD:
+ case UDIV:
+ case UMOD:
+ case SQRT:
+ return 1;
+
+ default:
+ if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
+ && !flag_fast_math
+ && FLOAT_MODE_P (GET_MODE (x)))
+ return 1;
+
+ switch (GET_RTX_CLASS (code))
+ {
+ case '<':
+ case '1':
+ case '2':
+ case '3':
+ case 'c':
+ case 'b':
+ break;
+
+ default:
+ return 1;
+ }
+ break;
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ if (fmt[i] == 'e')
+ if (rtx_unsafe_p (XEXP (x, i)))
+ return 1;
+
+ return 0;
+}
#endif /* !HAVE_cc0 */