aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2001-07-14 11:39:16 -0700
committerRichard Henderson <rth@gcc.gnu.org>2001-07-14 11:39:16 -0700
commit999c066978f30fa90fb38b35017db4aec97f8c2b (patch)
tree4e62c7a3872a1090591940a36b0d9134005d4e78
parent386eda2e22ce6fa01bef774257be8c3e4f426ec0 (diff)
downloadgcc-999c066978f30fa90fb38b35017db4aec97f8c2b.zip
gcc-999c066978f30fa90fb38b35017db4aec97f8c2b.tar.gz
gcc-999c066978f30fa90fb38b35017db4aec97f8c2b.tar.bz2
ifcvt.c (find_cond_trap): New.
* ifcvt.c (find_cond_trap): New. (find_if_header): Call it. (merge_if_block): Relax existing jump sanity check. * jump.c (jump_optimize_1): Remove conditional trap handling. * gcc.dg/iftrap-1.c: New. From-SVN: r44006
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/ifcvt.c134
-rw-r--r--gcc/jump.c79
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/iftrap-1.c38
5 files changed, 180 insertions, 82 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 098ffcd..11aec12 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2001-07-14 Richard Henderson <rth@redhat.com>
+
+ * ifcvt.c (find_cond_trap): New.
+ (find_if_header): Call it.
+ (merge_if_block): Relax existing jump sanity check.
+ * jump.c (jump_optimize_1): Remove conditional trap handling.
+
2001-07-14 Alan Modra <amodra@bigpond.net.au>
* config/pa/pa.c (emit_hpdiv_const): Return reg is r2 for 64-bit
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 6cb2fab..6196522 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -48,6 +48,12 @@
#ifndef HAVE_decscc
#define HAVE_decscc 0
#endif
+#ifndef HAVE_trap
+#define HAVE_trap 0
+#endif
+#ifndef HAVE_conditional_trap
+#define HAVE_conditional_trap 0
+#endif
#ifndef MAX_CONDITIONAL_EXECUTE
#define MAX_CONDITIONAL_EXECUTE (BRANCH_COST + 1)
@@ -97,6 +103,7 @@ static int find_if_header PARAMS ((basic_block));
static int find_if_block PARAMS ((basic_block, edge, edge));
static int find_if_case_1 PARAMS ((basic_block, edge, edge));
static int find_if_case_2 PARAMS ((basic_block, edge, edge));
+static int find_cond_trap PARAMS ((basic_block, edge, edge));
static int find_memory PARAMS ((rtx *, void *));
static int dead_or_predicable PARAMS ((basic_block, basic_block,
basic_block, rtx, int));
@@ -1757,10 +1764,9 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
if (combo_bb->succ == NULL_EDGE)
abort ();
- /* There should sill be a branch at the end of the THEN or ELSE
+ /* There should still be a branch at the end of the THEN or ELSE
blocks taking us to our final destination. */
- if (! any_uncondjump_p (combo_bb->end)
- && ! returnjump_p (combo_bb->end))
+ if (GET_CODE (combo_bb->end) != JUMP_INSN)
abort ();
}
@@ -1835,6 +1841,9 @@ find_if_header (test_bb)
if (find_if_block (test_bb, then_edge, else_edge))
goto success;
+ if (HAVE_trap && HAVE_conditional_trap
+ && find_cond_trap (test_bb, then_edge, else_edge))
+ goto success;
if (post_dominators
&& (! HAVE_conditional_execution || reload_completed))
{
@@ -1965,6 +1974,125 @@ find_if_block (test_bb, then_edge, else_edge)
return process_if_block (test_bb, then_bb, else_bb, join_bb);
}
+/* Convert a branch over a trap, or a branch to a trap,
+ into a conditional trap. */
+
+static int
+find_cond_trap (test_bb, then_edge, else_edge)
+ basic_block test_bb;
+ edge then_edge, else_edge;
+{
+ basic_block then_bb, else_bb, join_bb, trap_bb;
+ rtx trap, jump, cond, cond_earliest, seq;
+ enum rtx_code code;
+
+ then_bb = then_edge->dest;
+ else_bb = else_edge->dest;
+ join_bb = NULL;
+
+ /* Locate the block with the trap instruction. */
+ /* ??? While we look for no successors, we really ought to allow
+ EH successors. Need to fix merge_if_block for that to work. */
+ /* ??? We can't currently handle merging the blocks if they are not
+ already adjacent. Prevent losage in merge_if_block by detecting
+ this now. */
+ if (then_bb->succ == NULL)
+ {
+ trap_bb = then_bb;
+ if (else_bb->index != then_bb->index + 1)
+ return FALSE;
+ join_bb = else_bb;
+ else_bb = NULL;
+ }
+ else if (else_bb->succ == NULL)
+ {
+ trap_bb = else_bb;
+ if (else_bb->index != then_bb->index + 1)
+ else_bb = NULL;
+ else if (then_bb->succ
+ && ! then_bb->succ->succ_next
+ && ! (then_bb->succ->flags & EDGE_COMPLEX)
+ && then_bb->succ->dest->index == else_bb->index + 1)
+ join_bb = then_bb->succ->dest;
+ }
+ else
+ return FALSE;
+
+ /* The only instruction in the THEN block must be the trap. */
+ trap = first_active_insn (trap_bb);
+ if (! (trap == trap_bb->end
+ && GET_CODE (PATTERN (trap)) == TRAP_IF
+ && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx))
+ return FALSE;
+
+ if (rtl_dump_file)
+ {
+ if (trap_bb == then_bb)
+ fprintf (rtl_dump_file,
+ "\nTRAP-IF block found, start %d, trap %d",
+ test_bb->index, then_bb->index);
+ else
+ fprintf (rtl_dump_file,
+ "\nTRAP-IF block found, start %d, then %d, trap %d",
+ test_bb->index, then_bb->index, trap_bb->index);
+ if (join_bb)
+ fprintf (rtl_dump_file, ", join %d\n", join_bb->index);
+ else
+ fputc ('\n', rtl_dump_file);
+ }
+
+ /* If this is not a standard conditional jump, we can't parse it. */
+ jump = test_bb->end;
+ cond = noce_get_condition (jump, &cond_earliest);
+ if (! cond)
+ return FALSE;
+
+ /* If the conditional jump is more than just a conditional jump,
+ then we can not do if-conversion on this block. */
+ if (! onlyjump_p (jump))
+ return FALSE;
+
+ /* We must be comparing objects whose modes imply the size. */
+ if (GET_MODE (XEXP (cond, 0)) == BLKmode)
+ return FALSE;
+
+ /* Reverse the comparison code, if necessary. */
+ code = GET_CODE (cond);
+ if (then_bb == trap_bb)
+ {
+ code = reversed_comparison_code (cond, jump);
+ if (code == UNKNOWN)
+ return FALSE;
+ }
+
+ /* Attempt to generate the conditional trap. */
+ seq = gen_cond_trap (code, XEXP (cond, 0), XEXP (cond, 1),
+ TRAP_CODE (PATTERN (trap)));
+ if (seq == NULL)
+ return FALSE;
+
+ /* Emit the new insns before cond_earliest; delete the old jump
+ and trap insns. */
+
+ emit_insn_before (seq, cond_earliest);
+
+ test_bb->end = PREV_INSN (jump);
+ flow_delete_insn (jump);
+
+ trap_bb->end = PREV_INSN (trap);
+ flow_delete_insn (trap);
+
+ /* Merge the blocks! */
+ if (trap_bb != then_bb && ! else_bb)
+ {
+ flow_delete_block (trap_bb);
+ num_removed_blocks++;
+ }
+ merge_if_block (test_bb, then_bb, else_bb, join_bb);
+
+ return TRUE;
+}
+
/* Look for IF-THEN-ELSE cases in which one of THEN or ELSE is
transformable, but not necessarily the other. There need be no
JOIN block.
diff --git a/gcc/jump.c b/gcc/jump.c
index ffe958e..f98da2d 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -208,9 +208,6 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
int first = 1;
int max_uid = 0;
rtx last_insn;
-#ifdef HAVE_trap
- enum rtx_code reversed_code;
-#endif
cross_jump_death_matters = (cross_jump == 2);
max_uid = init_label_info (f) + 1;
@@ -498,82 +495,6 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan,
changed = 1;
next = NEXT_INSN (insn);
}
-
-#ifdef HAVE_trap
- /* Detect a conditional jump jumping over an unconditional trap. */
- if (HAVE_trap
- && this_is_any_condjump && this_is_onlyjump
- && reallabelprev != 0
- && GET_CODE (reallabelprev) == INSN
- && GET_CODE (PATTERN (reallabelprev)) == TRAP_IF
- && TRAP_CONDITION (PATTERN (reallabelprev)) == const_true_rtx
- && prev_active_insn (reallabelprev) == insn
- && no_labels_between_p (insn, reallabelprev)
- && (temp2 = get_condition (insn, &temp4))
- && ((reversed_code = reversed_comparison_code (temp2, insn))
- != UNKNOWN))
- {
- rtx new = gen_cond_trap (reversed_code,
- XEXP (temp2, 0), XEXP (temp2, 1),
- TRAP_CODE (PATTERN (reallabelprev)));
-
- if (new)
- {
- emit_insn_before (new, temp4);
- delete_insn (reallabelprev);
- delete_jump (insn);
- changed = 1;
- continue;
- }
- }
- /* Detect a jump jumping to an unconditional trap. */
- else if (HAVE_trap && this_is_onlyjump
- && (temp = next_active_insn (JUMP_LABEL (insn)))
- && GET_CODE (temp) == INSN
- && GET_CODE (PATTERN (temp)) == TRAP_IF
- && (this_is_any_uncondjump
- || (this_is_any_condjump
- && (temp2 = get_condition (insn, &temp4)))))
- {
- rtx tc = TRAP_CONDITION (PATTERN (temp));
-
- if (tc == const_true_rtx
- || (! this_is_any_uncondjump && rtx_equal_p (temp2, tc)))
- {
- rtx new;
- /* Replace an unconditional jump to a trap with a trap. */
- if (this_is_any_uncondjump)
- {
- emit_barrier_after (emit_insn_before (gen_trap (), insn));
- delete_jump (insn);
- changed = 1;
- continue;
- }
- new = gen_cond_trap (GET_CODE (temp2), XEXP (temp2, 0),
- XEXP (temp2, 1),
- TRAP_CODE (PATTERN (temp)));
- if (new)
- {
- emit_insn_before (new, temp4);
- delete_jump (insn);
- changed = 1;
- continue;
- }
- }
- /* If the trap condition and jump condition are mutually
- exclusive, redirect the jump to the following insn. */
- else if (GET_RTX_CLASS (GET_CODE (tc)) == '<'
- && this_is_any_condjump
- && swap_condition (GET_CODE (temp2)) == GET_CODE (tc)
- && rtx_equal_p (XEXP (tc, 0), XEXP (temp2, 0))
- && rtx_equal_p (XEXP (tc, 1), XEXP (temp2, 1))
- && redirect_jump (insn, get_label_after (temp), 1))
- {
- changed = 1;
- continue;
- }
- }
-#endif
else
{
/* Now that the jump has been tensioned,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d9e01b8..3075c3f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2001-07-14 Richard Henderson <rth@redhat.com>
+
+ * gcc.dg/iftrap-1.c: New.
+
2001-07-11 David Billinghurst <David.Billinghurst@riotinto.com>
* g77.f-torture/execute/intrinsic77.f: New test.
diff --git a/gcc/testsuite/gcc.dg/iftrap-1.c b/gcc/testsuite/gcc.dg/iftrap-1.c
new file mode 100644
index 0000000..a9f6a77
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/iftrap-1.c
@@ -0,0 +1,38 @@
+/* Verify that we optimize to conditional traps. */
+/* { dg-options "-O" } */
+/* { dg-do compile { target rs6000-* powerpc-* sparc*-* } } */
+/* { dg-final { scan-assembler-not iftrap-1.c "^\t(trap|ta)\[ \t\]" } } */
+
+void f1(int p)
+{
+ if (p)
+ __builtin_trap();
+}
+
+void f2(int p)
+{
+ if (p)
+ __builtin_trap();
+ else
+ bar();
+}
+
+void f3(int p)
+{
+ if (p)
+ bar();
+ else
+ __builtin_trap();
+}
+
+void f4(int p, int q)
+{
+ if (p)
+ {
+ bar();
+ if (q)
+ bar();
+ }
+ else
+ __builtin_trap();
+}