haifa-sched.c (haifa_classify_insn): TRAP_IF is risky.
authorJohn Carr <jfc@mit.edu>
Wed, 17 Jun 1998 16:14:09 +0000 (16:14 +0000)
committerJohn Carr <jfc@gcc.gnu.org>
Wed, 17 Jun 1998 16:14:09 +0000 (16:14 +0000)
* haifa-sched.c (haifa_classify_insn): TRAP_IF is risky.
(sched_analyze_2): Allow scheduling TRAP_IF.
* reorg.c (mark_referenced_resources): Examine operands of TRAP_IF.
* rtl.h (TRAP_CODE): New macro.
* rtl.def (TRAP_IF): Change second operand type to rtx.
* optabs.c (gen_cond_trap): New function.
(init_traps): New function.
(init_optabs): Call init_traps.
* expr.h: Declare gen_cond_trap.
* jump.c (jump_optimize): Optimize jumps to and around traps.
* sparc.md: Define trap instructions.
* rs6000.md: Define trap instructions.
* rs6000.c (print_operand): New code 'V' for trap condition.
(trap_comparison_operator): New function.
* m88k.md: Update use of TRAP_IF.
* tree.h (enum built_in_function): New function code BUILT_IN_TRAP.
* c-decl.c (init_decl_processing): New builtin __builtin_trap.
* expr.c (expand_builtin): Handle BUILT_IN_TRAP.
* expr.c (expand_builtin): Error if __builtin_longjmp second argument
is not 1.

From-SVN: r20543

15 files changed:
gcc/ChangeLog
gcc/c-decl.c
gcc/config/m88k/m88k.md
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md
gcc/config/sparc/sparc.md
gcc/expr.c
gcc/expr.h
gcc/haifa-sched.c
gcc/jump.c
gcc/optabs.c
gcc/reorg.c
gcc/rtl.def
gcc/rtl.h
gcc/tree.h

index 7bd21357269fa259cc744be92d30b44ebb06ae73..6f58a02765a6ff7364f54f5daeb3b3e215ba07dd 100644 (file)
@@ -1,3 +1,36 @@
+Wed Jun 17 19:05:03 1998  John Carr  <jfc@mit.edu>
+
+       * haifa-sched.c (haifa_classify_insn): TRAP_IF is risky.
+       (sched_analyze_2): Allow scheduling TRAP_IF.
+
+       * reorg.c (mark_referenced_resources): Examine operands of TRAP_IF.
+
+       * rtl.h (TRAP_CODE): New macro.
+
+       * rtl.def (TRAP_IF): Change second operand type to rtx.
+
+       * optabs.c (gen_cond_trap): New function.
+       (init_traps): New function.
+       (init_optabs): Call init_traps.
+       * expr.h: Declare gen_cond_trap.
+
+       * jump.c (jump_optimize): Optimize jumps to and around traps.
+
+       * sparc.md: Define trap instructions.
+
+       * rs6000.md: Define trap instructions.
+       * rs6000.c (print_operand): New code 'V' for trap condition.
+       (trap_comparison_operator): New function.
+
+       * m88k.md: Update use of TRAP_IF.
+
+       * tree.h (enum built_in_function): New function code BUILT_IN_TRAP.
+       * c-decl.c (init_decl_processing): New builtin __builtin_trap.
+       * expr.c (expand_builtin): Handle BUILT_IN_TRAP.
+
+       * expr.c (expand_builtin): Error if __builtin_longjmp second argument
+       is not 1.
+
 Wed Jun 17 15:20:00 PDT 1998  Catherine Moore  <clm@cygnus.com>
 
          * reload1.c (spill_hard_reg):  Check mode of register when
index 4fadf3b12a788f135846d7401faaf6ceec41b0e5..62768e3ef68be20423bcf9629cd56f2ab892e373 100644 (file)
@@ -3425,6 +3425,9 @@ init_decl_processing ()
                                           integer_type_node,
                                           endlink))),
                    BUILT_IN_LONGJMP, NULL_PTR);
+  builtin_function ("__builtin_trap",
+                   build_function_type (void_type_node, endlink),
+                   BUILT_IN_TRAP, NULL_PTR);
 
   /* In an ANSI C program, it is okay to supply built-in meanings
      for these functions, since applications cannot validly use them
index 54ec648677344325e47aa7e2d97107d8f64f1398..c94e6fd82ae867b6d5c33b14c40cc95ac75698cd 100644 (file)
 
 ;; Division by 0 trap
 (define_insn "trap_divide_by_zero"
-  [(trap_if (const_int 1) 503)]
+  [(trap_if (const_int 1) (const_int 503))]
   ""
   "tb0 0,%#r0,503"
   [(set_attr "type" "weird")])
                          (const_int 0))
                      (pc)
                      (match_operand 1 "" "")))
-   (trap_if (const_int 1) 503)]
+   (trap_if (const_int 1) (const_int 503))]
   ""
   "
 {
 (define_insn "tbnd"
   [(trap_if (gtu (match_operand:SI 0 "register_operand" "r")
                 (match_operand:SI 1 "arith_operand" "rI"))
-           7)]
+           (const_int 7))]
   ""
   "tbnd %r0,%1"
   [(set_attr "type" "weird")])
 
 ;; Just in case the optimizer decides to fold away the test.
 (define_insn ""
-  [(trap_if (const_int 1) 7)]
+  [(trap_if (const_int 1) (const_int 7))]
   ""
   "tbnd %#r31,0"
   [(set_attr "type" "weird")])
index 8e6598d43b982d8e0d0c90e86e499d5f0994aa57..464a5551b0bcfb25ed82bf40deae9732a5293a5f 100644 (file)
@@ -2046,6 +2046,17 @@ scc_comparison_operator (op, mode)
 
   return 1;
 }
+
+int
+trap_comparison_operator (op, mode)
+    rtx op;
+    enum machine_mode mode;
+{
+  if (mode != VOIDmode && mode != GET_MODE (op))
+    return 0;
+  return (GET_RTX_CLASS (GET_CODE (op)) == '<'
+          || GET_CODE (op) == EQ || GET_CODE (op) == NE);
+}
 \f
 /* Return 1 if ANDOP is a mask that has no bits on that are not in the
    mask required to convert the result of a rotate insn into a shift
@@ -2924,6 +2935,45 @@ print_operand (file, x, code)
        putc ('u', file);
       return;
 
+    case 'V':
+      /* Print the trap code for this operand.  */
+      switch (GET_CODE (x))
+       {
+       case EQ:
+         fputs ("eq", file);   /* 4 */
+         break;
+       case NE:
+         fputs ("ne", file);   /* 24 */
+         break;
+       case LT:
+         fputs ("lt", file);   /* 16 */
+         break;
+       case LE:
+         fputs ("le", file);   /* 20 */
+         break;
+       case GT:
+         fputs ("gt", file);   /* 8 */
+         break;
+       case GE:
+         fputs ("ge", file);   /* 12 */
+         break;
+       case LTU:
+         fputs ("llt", file);  /* 2 */
+         break;
+       case LEU:
+         fputs ("lle", file);  /* 6 */
+         break;
+       case GTU:
+         fputs ("lgt", file);  /* 1 */
+         break;
+       case GEU:
+         fputs ("lge", file);  /* 5 */
+         break;
+       default:
+         abort ();
+       }
+      break;
+
     case 'w':
       /* If constant, low-order 16 bits of constant, signed.  Otherwise, write
         normally.  */
index c83f9d5568f55294e9c732f4a54578820eb55440..05ee92f9efac17555785d0fd5ea8c7c8c4d4ead3 100644 (file)
   "
 { operands[7] = gen_rtx (GET_CODE (operands[2]), VOIDmode, operands[3],
                         const0_rtx); }")
+\f
+(define_insn "trap"
+  [(trap_if (const_int 1) (const_int 0))]
+  ""
+  "{t 31,0,0|trap}")
+
+(define_expand "conditional_trap"
+  [(trap_if (match_operator 0 "trap_comparison_operator"
+                           [(match_dup 2) (match_dup 3)])
+           (match_operand 1 "const_int_operand" ""))]
+  ""
+  "if (rs6000_compare_fp_p || operands[1] != const0_rtx) FAIL;
+   operands[2] = rs6000_compare_op0;
+   operands[3] = rs6000_compare_op1;")
+
+(define_insn ""
+  [(trap_if (match_operator 0 "trap_comparison_operator"
+                            [(match_operand:SI 1 "register_operand" "r")
+                             (match_operand:SI 2 "reg_or_short_operand" "rI")])
+           (const_int 0))]
+  ""
+  "t%V0%I2 %1,%2")
index 683bcfd55f8a41568efb1ec481ce8d3df9ee95e1..f4018492d963f8a8fd955d3486c11dc9c6f00ade 100644 (file)
@@ -6674,3 +6674,33 @@ if (! TARGET_ARCH64)
   [(unspec_volatile [(const_int 0)] 4)]
   "flag_pic"
   "")
+\f
+(define_insn "trap"
+  [(trap_if (const_int 1) (const_int 5))]
+  ""
+  "ta 5"
+  [(set_attr "type" "misc")])
+
+(define_expand "conditional_trap"
+  [(trap_if (match_operator 0 "noov_compare_op"
+                           [(match_dup 2) (match_dup 3)])
+           (match_operand:SI 1 "arith_operand" ""))]
+  ""
+  "operands[2] = gen_compare_reg (GET_CODE (operands[0]),
+                                 sparc_compare_op0, sparc_compare_op1);
+   operands[3] = const0_rtx;")
+
+(define_insn ""
+  [(trap_if (match_operator 0 "noov_compare_op" [(reg:CC 100) (const_int 0)])
+           (match_operand:SI 1 "arith_operand" "rM"))]
+  ""
+  "t%C0 %1"
+  [(set_attr "type" "misc")])
+
+(define_insn ""
+  [(trap_if (match_operator 0 "noov_compare_op" [(reg:CCX 100) (const_int 0)])
+           (match_operand:SI 1 "arith_operand" "rM"))]
+  "TARGET_V9"
+  "t%C0 %%xcc,%1"
+  [(set_attr "type" "misc")])
+
index aad427d1fa14a956462c871ec55617345bf934ec..aff3dd104c70397cccb0833bbc6af7dbe4f00efd 100644 (file)
@@ -8973,10 +8973,27 @@ expand_builtin (exp, target, subtarget, mode, ignore)
                                      VOIDmode, 0);
          rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
                                   NULL_RTX, VOIDmode, 0);
+
+         if (value != const1_rtx)
+           {
+             error ("__builtin_longjmp second argument must be 1");
+             return const0_rtx;
+           }
+
          expand_builtin_longjmp (buf_addr, value);
          return const0_rtx;
        }
 
+    case BUILT_IN_TRAP:
+#ifdef HAVE_trap
+      if (HAVE_trap)
+       emit_insn (gen_trap ());
+      else
+#endif
+       error ("__builtin_trap not supported by this target");
+      emit_barrier ();
+      return const0_rtx;
+
       /* Various hooks for the DWARF 2 __throw routine.  */
     case BUILT_IN_UNWIND_INIT:
       expand_builtin_unwind_init ();
index 30e8d8c2c019d8537684b11f37df2bb5a86c5349..f75828f212aab7a28a6f29e3e525eada693ffcf0 100644 (file)
@@ -671,6 +671,9 @@ extern rtx emit_store_flag_force PROTO((rtx, enum rtx_code, rtx, rtx,
 
 /* Given a JUMP_INSN, return a description of the test being made.  */
 extern rtx get_condition PROTO((rtx, rtx *));
+
+/* Generate a conditional trap instruction.  */
+extern rtx gen_cond_trap PROTO((enum rtx_code, rtx, rtx, rtx));
 \f
 /* Functions from expr.c:  */
 
index 82671700bfe2967ab641b519dc0ac9a340d5e914..2416a83fc1dcc6d32c3971c1becac299eeeb9483 100644 (file)
@@ -2629,6 +2629,10 @@ haifa_classify_insn (insn)
              tmp_class =
                WORST_CLASS (tmp_class,
                           may_trap_exp (SET_SRC (XVECEXP (pat, 0, i)), 0));
+             break;
+           case TRAP_IF:
+             tmp_class = TRAP_RISKY;
+             break;
            default:;
            }
          insn_class = WORST_CLASS (insn_class, tmp_class);
@@ -2654,6 +2658,10 @@ haifa_classify_insn (insn)
          tmp_class =
            WORST_CLASS (tmp_class,
                         may_trap_exp (SET_SRC (pat), 0));
+         break;
+       case TRAP_IF:
+         tmp_class = TRAP_RISKY;
+         break;
        default:;
        }
       insn_class = tmp_class;
@@ -3560,10 +3568,14 @@ sched_analyze_2 (x, insn)
        return;
       }
 
+    /* Force pending stores to memory in case a trap handler needs them.  */
+    case TRAP_IF:
+      flush_pending_lists (insn, 1);
+      break;
+
     case ASM_OPERANDS:
     case ASM_INPUT:
     case UNSPEC_VOLATILE:
-    case TRAP_IF:
       {
        rtx u;
 
index 606fe2879989d65fcac0a84ca8cc58e39a0eafdb..9feb99efa289dc14b961f894b3784ea0960d6a61 100644 (file)
@@ -1892,6 +1892,80 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
                  continue;
                }
            }
+#ifdef HAVE_trap
+         /* Detect a conditional jump jumping over an unconditional trap.  */
+         else if (HAVE_trap
+                  && this_is_condjump && ! this_is_simplejump
+                  && 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))
+                  && can_reverse_comparison_p (temp2, insn))
+           {
+             rtx new = gen_cond_trap (reverse_condition (GET_CODE (temp2)),
+                                      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_condjump
+                  && (temp = next_active_insn (JUMP_LABEL (insn)))
+                  && GET_CODE (temp) == INSN
+                  && GET_CODE (PATTERN (temp)) == TRAP_IF
+                  && (this_is_simplejump
+                      || (temp2 = get_condition (insn, &temp4))))
+           {
+             rtx tc = TRAP_CONDITION (PATTERN (temp));
+
+             if (tc == const_true_rtx
+                 || (! this_is_simplejump && rtx_equal_p (temp2, tc)))
+               {
+                 rtx new;
+                 /* Replace an unconditional jump to a trap with a trap.  */
+                 if (this_is_simplejump)
+                   {
+                     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_simplejump
+                      && 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)))
+               {
+                 changed = 1;
+                 continue;
+               }
+           }
+#endif
+
          /* Detect a conditional jump jumping over an unconditional jump.  */
 
          else if ((this_is_condjump || this_is_condjump_in_parallel)
index c00562fbf88e4f22d791f1efd263a90055e0debb..8a2697b4fe951cde8f4aa3e6c89e951f0ae0b35c 100644 (file)
@@ -246,6 +246,7 @@ static optab init_optab     PROTO((enum rtx_code));
 static void init_libfuncs PROTO((optab, int, int, char *, int));
 static void init_integral_libfuncs PROTO((optab, char *, int));
 static void init_floating_libfuncs PROTO((optab, char *, int));
+static void init_traps PROTO((void));
 \f
 /* Add a REG_EQUAL note to the last insn in SEQ.  TARGET is being set to
    the result of operation CODE applied to OP0 (and OP1 if it is a binary
@@ -4380,6 +4381,10 @@ init_optabs ()
   chkr_check_exec_libfunc = gen_rtx (SYMBOL_REF, VOIDmode, "chkr_check_exec");
   chkr_check_str_libfunc = gen_rtx (SYMBOL_REF, VOIDmode, "chkr_check_str");
 
+#ifdef HAVE_conditional_trap
+  init_traps ();
+#endif
+
 #ifdef INIT_TARGET_OPTABS
   /* Allow the target to add more libcalls or rename some, etc.  */
   INIT_TARGET_OPTABS;
@@ -4402,3 +4407,50 @@ ldexp(x,n)
   return x;
 }
 #endif /* BROKEN_LDEXP */
+\f
+#ifdef HAVE_conditional_trap
+/* The insn generating function can not take an rtx_code argument.
+   TRAP_RTX is used as an rtx argument.  Its code is replaced with
+   the code to be used in the trap insn and all other fields are
+   ignored.
+
+   ??? Will need to change to support garbage collection.  */
+static rtx trap_rtx;
+
+static void
+init_traps ()
+{
+  if (HAVE_conditional_trap)
+    trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
+}
+#endif
+
+/* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
+   CODE.  Return 0 on failure.  */
+
+rtx
+gen_cond_trap (code, op1, op2, tcode)
+     enum rtx_code code;
+     rtx op1, op2, tcode;
+{
+  enum machine_mode mode = GET_MODE (op1);
+  enum insn_code icode;
+
+  if (mode == VOIDmode)
+    return 0;
+
+#ifdef HAVE_conditional_trap
+  if (HAVE_conditional_trap
+      && cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+    {
+      rtx insn;
+      emit_insn (GEN_FCN (cmp_optab->handlers[(int) mode].insn_code) (op1, op2));
+      PUT_CODE (trap_rtx, code);
+      insn = gen_conditional_trap (trap_rtx, tcode);
+      if (insn)
+       return insn;
+    }
+#endif
+
+  return 0;
+}
index f2ee5b8884bb0f568b77948ef2627cd4757acc62..7370a356dc4e80ce80183ea567a93d6be0242bf9 100644 (file)
@@ -340,11 +340,14 @@ mark_referenced_resources (x, res, include_delayed_effects)
 
     case UNSPEC_VOLATILE:
     case ASM_INPUT:
-    case TRAP_IF:
       /* Traditional asm's are always volatile.  */
       res->volatil = 1;
       return;
 
+    case TRAP_IF:
+      res->volatil = 1;
+      break;
+
     case ASM_OPERANDS:
       res->volatil = MEM_VOLATILE_P (x);
 
index 6d02c61e29eef293d6ecee3c1b39b9ea74e12603..e219e87c0422a21384aafe671b21f36f9a78a348 100644 (file)
@@ -506,7 +506,7 @@ DEF_RTL_EXPR(RETURN, "return", "", 'x')
    Operand 1 is the condition.
    Operand 2 is the trap code.
    For an unconditional trap, make the condition (const_int 1).  */
-DEF_RTL_EXPR(TRAP_IF, "trap_if", "ei", 'x')
+DEF_RTL_EXPR(TRAP_IF, "trap_if", "ee", 'x')
 
 /* ----------------------------------------------------------------------
    Primitive values for use in expressions.
index 276ba6a072eb9f4fe0355ae77b65435d50acf20f..a9946cacc8247749f0446ac481bd96b7c987187b 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -596,6 +596,7 @@ extern char *note_insn_name[];
 
 /* For a TRAP_IF rtx, TRAP_CONDITION is an expression.  */
 #define TRAP_CONDITION(RTX) ((RTX)->fld[0].rtx)
+#define TRAP_CODE(RTX) (RTX)->fld[1].rtx
 
 /* 1 in a SYMBOL_REF if it addresses this function's constants pool.  */
 #define CONSTANT_POOL_ADDRESS_P(RTX) ((RTX)->unchanging)
index 0407db28bcb11e1e52fb8bbb3f1053b8e0bdc3c5..62b316874907eca05c446ea5fe8d9f13027c8fdc 100644 (file)
@@ -107,6 +107,7 @@ enum built_in_function
   BUILT_IN_RETURN,
   BUILT_IN_SETJMP,
   BUILT_IN_LONGJMP,
+  BUILT_IN_TRAP,
 
   /* Various hooks for the DWARF 2 __throw routine.  */
   BUILT_IN_FP, BUILT_IN_SP,