mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-20 05:50:28 +08:00
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:
parent
4fdf79cb67
commit
e0cd077072
@ -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
|
||||
|
@ -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
|
||||
|
@ -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")])
|
||||
|
@ -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. */
|
||||
|
@ -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")
|
||||
|
@ -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")])
|
||||
|
||||
|
17
gcc/expr.c
17
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 ();
|
||||
|
@ -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: */
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
74
gcc/jump.c
74
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)
|
||||
|
52
gcc/optabs.c
52
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user