aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2002-04-18 13:02:18 -0700
committerRichard Henderson <rth@gcc.gnu.org>2002-04-18 13:02:18 -0700
commit96b453dc817b2af01b88e22f4e57394b79342339 (patch)
tree14f600f23fb352e68da7b61ad3f6ac0326cad42c
parent26406018509b6c8884453317d30e01c987fe9977 (diff)
downloadgcc-96b453dc817b2af01b88e22f4e57394b79342339.zip
gcc-96b453dc817b2af01b88e22f4e57394b79342339.tar.gz
gcc-96b453dc817b2af01b88e22f4e57394b79342339.tar.bz2
ifcvt.c: Include except.h.
* ifcvt.c: Include except.h. (block_has_only_trap): Break out from find_cond_trap. (find_cond_trap): Use it. Always delete the trap block. (merge_if_block): Allow then block null. Be less simplistic about what insns can end a block. * Makefile.in (ifcvt.o): Depend on except.h. * gcc.c-torture/compile/iftrap-1.c: New. * gcc.dg/iftrap-1.c: Adjust for ia64. * gcc.dg/iftrap-2.c: New. From-SVN: r52489
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/ifcvt.c108
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/iftrap-1.c99
-rw-r--r--gcc/testsuite/gcc.dg/iftrap-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/iftrap-2.c20
7 files changed, 210 insertions, 36 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 05a5f09..137640d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2002-04-18 Richard Henderson <rth@redhat.com>
+ * ifcvt.c: Include except.h.
+ (block_has_only_trap): Break out from find_cond_trap.
+ (find_cond_trap): Use it. Always delete the trap block.
+ (merge_if_block): Allow then block null. Be less simplistic about
+ what insns can end a block.
+ * Makefile.in (ifcvt.o): Depend on except.h.
+
* config/ia64/ia64.md (trap, conditional_trap): New.
2002-04-18 Jakub Jelinek <jakub@redhat.com>
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 1f7ad81..5a386ea 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1589,7 +1589,7 @@ regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) insn-config.h \
resource.h $(OBSTACK_H) flags.h $(TM_P_H)
ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) toplev.h \
flags.h insn-config.h function.h $(RECOG_H) $(BASIC_BLOCK_H) $(EXPR_H) \
- output.h $(TM_P_H)
+ output.h except.h $(TM_P_H)
dependence.o : dependence.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
$(C_COMMON_H) flags.h varray.h $(EXPR_H)
params.o : params.c $(CONFIG_H) $(SYSTEM_H) $(PARAMS_H) toplev.h
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 207ff5c..880f94a 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -27,6 +27,7 @@
#include "flags.h"
#include "insn-config.h"
#include "recog.h"
+#include "except.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "expr.h"
@@ -104,6 +105,7 @@ 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 rtx block_has_only_trap PARAMS ((basic_block));
static int find_memory PARAMS ((rtx *, void *));
static int dead_or_predicable PARAMS ((basic_block, basic_block,
basic_block, basic_block, int));
@@ -1812,11 +1814,14 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
/* First merge TEST block into THEN block. This is a no-brainer since
the THEN block did not have a code label to begin with. */
-
- if (combo_bb->global_live_at_end)
- COPY_REG_SET (combo_bb->global_live_at_end, then_bb->global_live_at_end);
- merge_blocks_nomove (combo_bb, then_bb);
- num_removed_blocks++;
+ if (then_bb)
+ {
+ if (combo_bb->global_live_at_end)
+ COPY_REG_SET (combo_bb->global_live_at_end,
+ then_bb->global_live_at_end);
+ merge_blocks_nomove (combo_bb, then_bb);
+ num_removed_blocks++;
+ }
/* The ELSE block, if it existed, had a label. That label count
will almost always be zero, but odd things can happen when labels
@@ -1832,14 +1837,34 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
if (! join_bb)
{
+ rtx last = combo_bb->end;
+
/* The outgoing edge for the current COMBO block should already
be correct. Verify this. */
if (combo_bb->succ == NULL_EDGE)
- abort ();
+ {
+ if (find_reg_note (last, REG_NORETURN, NULL))
+ ;
+ else if (GET_CODE (last) == INSN
+ && GET_CODE (PATTERN (last)) == TRAP_IF
+ && TRAP_CONDITION (PATTERN (last)) == const_true_rtx)
+ ;
+ else
+ abort ();
+ }
- /* There should still be a branch at the end of the THEN or ELSE
+ /* There should still be something at the end of the THEN or ELSE
blocks taking us to our final destination. */
- if (GET_CODE (combo_bb->end) != JUMP_INSN)
+ else if (GET_CODE (last) == JUMP_INSN)
+ ;
+ else if (combo_bb->succ->dest == EXIT_BLOCK_PTR
+ && GET_CODE (last) == CALL_INSN
+ && SIBLING_CALL_P (last))
+ ;
+ else if ((combo_bb->succ->flags & EDGE_EH)
+ && can_throw_internal (last))
+ ;
+ else
abort ();
}
@@ -2069,7 +2094,7 @@ find_cond_trap (test_bb, then_edge, else_edge)
/* ??? 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)
+ if ((trap = block_has_only_trap (then_bb)) != NULL)
{
trap_bb = then_bb;
if (else_bb->index != then_bb->index + 1)
@@ -2077,7 +2102,7 @@ find_cond_trap (test_bb, then_edge, else_edge)
join_bb = else_bb;
else_bb = NULL;
}
- else if (else_bb->succ == NULL)
+ else if ((trap = block_has_only_trap (else_bb)) != NULL)
{
trap_bb = else_bb;
if (else_bb->index != then_bb->index + 1)
@@ -2091,18 +2116,6 @@ find_cond_trap (test_bb, then_edge, else_edge)
else
return FALSE;
- /* Don't confuse a conditional return with something we want to
- optimize here. */
- if (trap_bb == EXIT_BLOCK_PTR)
- 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)
@@ -2149,26 +2162,55 @@ find_cond_trap (test_bb, then_edge, else_edge)
if (seq == NULL)
return FALSE;
- /* Emit the new insns before cond_earliest; delete the old jump
- and trap insns. */
-
+ /* Emit the new insns before cond_earliest; delete the old jump. */
emit_insn_before (seq, cond_earliest);
-
delete_insn (jump);
- delete_insn (trap);
+ /* Delete the trap block together with its insn. */
+ if (trap_bb == then_bb)
+ then_bb = NULL;
+ else if (else_bb == NULL)
+ ;
+ else if (trap_bb == else_bb)
+ else_bb = NULL;
+ else
+ abort ();
+ flow_delete_block (trap_bb);
+ num_removed_blocks++;
- /* Merge the blocks! */
- if (trap_bb != then_bb && ! else_bb)
- {
- flow_delete_block (trap_bb);
- num_removed_blocks++;
- }
+ /* Merge what's left. */
merge_if_block (test_bb, then_bb, else_bb, join_bb);
return TRUE;
}
+/* Subroutine of find_cond_trap: if BB contains only a trap insn,
+ return it. */
+
+static rtx
+block_has_only_trap (bb)
+ basic_block bb;
+{
+ rtx trap;
+
+ /* We're not the exit block. */
+ if (bb == EXIT_BLOCK_PTR)
+ return NULL_RTX;
+
+ /* The block must have no successors. */
+ if (bb->succ)
+ return NULL_RTX;
+
+ /* The only instruction in the THEN block must be the trap. */
+ trap = first_active_insn (bb);
+ if (! (trap == bb->end
+ && GET_CODE (PATTERN (trap)) == TRAP_IF
+ && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx))
+ return NULL_RTX;
+
+ return trap;
+}
+
/* 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/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9c6bd86..2a2aeda 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2002-04-18 Richard Henderson <rth@redhat.com>
+
+ * gcc.c-torture/compile/iftrap-1.c: New.
+ * gcc.dg/iftrap-1.c: Adjust for ia64.
+ * gcc.dg/iftrap-2.c: New.
+
2002-04-18 Jakub Jelinek <jakub@redhat.com>
* gcc.c-torture/compile/20020418-1.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/compile/iftrap-1.c b/gcc/testsuite/gcc.c-torture/compile/iftrap-1.c
new file mode 100644
index 0000000..a0adc78
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/iftrap-1.c
@@ -0,0 +1,99 @@
+/* Verify that ifcvt doesn't crash under a number of interesting conditions. */
+
+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();
+}
+
+void f5(int p)
+{
+ if (p)
+ __builtin_trap();
+ else
+ abort();
+}
+
+void f6(int p)
+{
+ if (p)
+ abort();
+ else
+ __builtin_trap();
+}
+
+void f7(int p)
+{
+ if (p)
+ __builtin_trap();
+ else
+ __builtin_trap();
+}
+
+void f8(int p)
+{
+ if (p)
+ __builtin_trap();
+ else
+ {
+ bar();
+ __builtin_trap();
+ }
+}
+
+void f9(int p)
+{
+ if (p)
+ {
+ bar();
+ __builtin_trap();
+ }
+ else
+ __builtin_trap();
+}
+
+void f10(int p)
+{
+ if (p)
+ __builtin_trap();
+ while (1)
+ bar();
+}
+
+void f11(int p)
+{
+ if (p)
+ __builtin_trap();
+ else
+ bar();
+ while (1)
+ baz();
+}
diff --git a/gcc/testsuite/gcc.dg/iftrap-1.c b/gcc/testsuite/gcc.dg/iftrap-1.c
index b6abfc4..69d754d 100644
--- a/gcc/testsuite/gcc.dg/iftrap-1.c
+++ b/gcc/testsuite/gcc.dg/iftrap-1.c
@@ -1,7 +1,7 @@
/* Verify that we optimize to conditional traps. */
/* { dg-options "-O" } */
-/* { dg-do compile { target rs6000-*-* powerpc-*-* sparc*-*-* } } */
-/* { dg-final { scan-assembler-not "^\t(trap|ta)\[ \t\]" } } */
+/* { dg-do compile { target rs6000-*-* powerpc-*-* sparc*-*-* ia64-*-* } } */
+/* { dg-final { scan-assembler-not "^\t(trap|ta|break)\[ \t\]" } } */
void f1(int p)
{
diff --git a/gcc/testsuite/gcc.dg/iftrap-2.c b/gcc/testsuite/gcc.dg/iftrap-2.c
new file mode 100644
index 0000000..909a85f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/iftrap-2.c
@@ -0,0 +1,20 @@
+/* Verify that we optimize to conditional traps. */
+/* { dg-options "-O" } */
+/* { dg-do compile { target rs6000-*-* powerpc-*-* sparc*-*-* ia64-*-* } } */
+/* { dg-final { scan-assembler-not "^\t(trap|ta|break)\[ \t\]" } } */
+
+void f1(int p)
+{
+ if (p)
+ __builtin_trap();
+ else
+ abort();
+}
+
+void f2(int p)
+{
+ if (p)
+ abort();
+ else
+ __builtin_trap();
+}