haifa-sched.c (haifa_classify_insn): TRAP_IF is risky.

* 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
This commit is contained in:
John Carr 1998-06-17 16:14:09 +00:00 committed by John Carr
parent 4fdf79cb67
commit e0cd077072
15 changed files with 308 additions and 7 deletions

View 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

View 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

View File

@ -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")])

View 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);
}
/* 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. */

View File

@ -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")

View File

@ -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")])

View 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 ();

View 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));
/* Functions from expr.c: */

View 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;

View 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)

View 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));
/* 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;
}

View 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);

View 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.

View File

@ -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)

View 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,