ifcvt.c (find_cond_trap): New.
authorRichard Henderson <rth@redhat.com>
Sat, 14 Jul 2001 18:39:16 +0000 (11:39 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Sat, 14 Jul 2001 18:39:16 +0000 (11:39 -0700)
        * 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

gcc/ChangeLog
gcc/ifcvt.c
gcc/jump.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/iftrap-1.c [new file with mode: 0644]

index 098ffcd..11aec12 100644 (file)
@@ -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
index 6cb2fab..6196522 100644 (file)
 #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.
index ffe958e..f98da2d 100644 (file)
@@ -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,
index d9e01b8..3075c3f 100644 (file)
@@ -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 (file)
index 0000000..a9f6a77
--- /dev/null
@@ -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();
+}