aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog33
-rw-r--r--gcc/c-decl.c3
-rw-r--r--gcc/config/m88k/m88k.md8
-rw-r--r--gcc/config/rs6000/rs6000.c50
-rw-r--r--gcc/config/rs6000/rs6000.md22
-rw-r--r--gcc/config/sparc/sparc.md30
-rw-r--r--gcc/expr.c17
-rw-r--r--gcc/expr.h3
-rw-r--r--gcc/haifa-sched.c14
-rw-r--r--gcc/jump.c74
-rw-r--r--gcc/optabs.c52
-rw-r--r--gcc/reorg.c5
-rw-r--r--gcc/rtl.def2
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/tree.h1
15 files changed, 308 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7bd2135..6f58a02 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 4fadf3b..62768e3 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -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
diff --git a/gcc/config/m88k/m88k.md b/gcc/config/m88k/m88k.md
index 54ec648..c94e6fd 100644
--- a/gcc/config/m88k/m88k.md
+++ b/gcc/config/m88k/m88k.md
@@ -2810,7 +2810,7 @@
;; 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")])
@@ -2822,7 +2822,7 @@
(const_int 0))
(pc)
(match_operand 1 "" "")))
- (trap_if (const_int 1) 503)]
+ (trap_if (const_int 1) (const_int 503))]
""
"
{
@@ -3451,14 +3451,14 @@
(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")])
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 8e6598d..464a555 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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);
+}
/* 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. */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index c83f9d5..05ee92f 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -9991,3 +9991,25 @@
"
{ operands[7] = gen_rtx (GET_CODE (operands[2]), VOIDmode, operands[3],
const0_rtx); }")
+
+(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")
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 683bcfd..f401849 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -6674,3 +6674,33 @@ if (! TARGET_ARCH64)
[(unspec_volatile [(const_int 0)] 4)]
"flag_pic"
"")
+
+(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")])
+
diff --git a/gcc/expr.c b/gcc/expr.c
index aad427d..aff3dd1 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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 ();
diff --git a/gcc/expr.h b/gcc/expr.h
index 30e8d8c..f75828f 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -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));
/* Functions from expr.c: */
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 8267170..2416a83 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -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;
diff --git a/gcc/jump.c b/gcc/jump.c
index 606fe28..9feb99e 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -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)
diff --git a/gcc/optabs.c b/gcc/optabs.c
index c00562f..8a2697b 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -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));
/* 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 */
+
+#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;
+}
diff --git a/gcc/reorg.c b/gcc/reorg.c
index f2ee5b8..7370a35 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -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);
diff --git a/gcc/rtl.def b/gcc/rtl.def
index 6d02c61..e219e87 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -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.
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 276ba6a..a9946ca 100644
--- 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)
diff --git a/gcc/tree.h b/gcc/tree.h
index 0407db2..62b3168 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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,