diff options
author | jfc <jfc@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-06-17 16:14:09 +0000 |
---|---|---|
committer | jfc <jfc@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-06-17 16:14:09 +0000 |
commit | 9e5192edc9f9b2d30b69ebbf775e59139d59a196 (patch) | |
tree | bc08309af18e3e3b81d9dde6d23a1abd41673ffe | |
parent | 3e82d236f23959133707525ad1176390394c56f4 (diff) | |
download | gcc-9e5192edc9f9b2d30b69ebbf775e59139d59a196.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@20543 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 33 | ||||
-rw-r--r-- | gcc/c-decl.c | 3 | ||||
-rw-r--r-- | gcc/config/m88k/m88k.md | 8 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 50 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 22 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.md | 30 | ||||
-rw-r--r-- | gcc/expr.c | 17 | ||||
-rw-r--r-- | gcc/expr.h | 3 | ||||
-rw-r--r-- | gcc/haifa-sched.c | 14 | ||||
-rw-r--r-- | gcc/jump.c | 74 | ||||
-rw-r--r-- | gcc/optabs.c | 52 | ||||
-rw-r--r-- | gcc/reorg.c | 5 | ||||
-rw-r--r-- | gcc/rtl.def | 2 | ||||
-rw-r--r-- | gcc/rtl.h | 1 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
15 files changed, 308 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7bd21357269..6f58a02765a 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 4fadf3b12a7..62768e3ef68 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 54ec6486773..c94e6fd82ae 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 8e6598d43b9..464a5551b0b 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 c83f9d5568f..05ee92f9efa 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 683bcfd55f8..f4018492d96 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 aad427d1fa1..aff3dd104c7 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 30e8d8c2c01..f75828f212a 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 82671700bfe..2416a83fc1d 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 606fe287998..9feb99efa28 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 c00562fbf88..8a2697b4fe9 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 f2ee5b8884b..7370a356dc4 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 6d02c61e29e..e219e87c042 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 276ba6a072e..a9946cacc82 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 0407db28bcb..62b31687490 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, |