Commit 91ce572a by Chandrakala Chavva Committed by Chandra Chavva

Adding new option -ftrapv.

From-SVN: r36942
parent 4c2c5712
2000-10-18 Chandrakala Chavva <cchavva@redhat.com>
* expmed.c (expand_mult): Don't do synth_mult optimization for -ftrapv.
Use smulv_optab for -ftrapv.
(expand_mult_highpart): Use unsigned multiply.
(expand_divmod): Special-case division by -1.
For EXACT_DIV_EXPR, do right shift first, then the multiply.
For complex divide, use abs with unsigned result.
* expr.c (force_operand): Use unsigned multiply.
(expand_expr): Use overflow-trapping optabs for signed types if
flag_trapv.
If flag_trapv, don't generate a recursive call with EXPAND_SUM
if the type is signed and the original call wasn't EXPAND_SUM or
EXPAND_INITIALIZER.
* expr.h (addv_optab, subv_optab, smulv_optab, sdivv_optab): Declare.
(negv_optab, absv_optab): Declare.
* flags.h (flag_trapv): Declare.
* genopinit.c (optabs): Add entries for addv_optab, subv_optab,
smulv_optab, sdivv_optab, negv_optab and absv_optab.
(gen_insn): Interpret '$P' as requiring an integer mode,
including partial integer modes.
* loop.c (emit_iv_add_mult): Use unsigned expand_mult_add.
(product_cheap_p): Use unsigned expand_mult.
* optabs.c (addv_optab, subv_optab, smulv_optab, sdivv_optab): Define.
(negv_optab, absv_optab): Define.
(expand_binop): Use overflow-trapping optabs for signed types if
flag_trapv.
Handle negv_optab libe neg_optab.
(expand_abs): Take result_unsignedp argument instead of unsignedp one.
Use overflow-trapping optabs for signed result if flag_trapv.
(expand_complex_abs): Use overflow-trapping optabs for signed types if
flag_trapv.
Don't open-code complex absolute-value operation for flag_trapv.
(init_optabs): Initialize addv_optab, subv_optab, smulv_optab,
sdivv_optab, negv_optab and absv_optab.
* toplev.c (flag_trapv): Define.
(lang_independent_options f_options): Include flag_trapv.
* tree.h (TYPE_TRAP_SIGNED): Define.
* libgcc2.c (__addvsi3, __addvdi3, __subvsi3,__subvsi3, __subvdi3,
__mulvsi3, __negvsi2, __negvdi2, __absvsi2, __absvdi2, __mulvdi3):
New functions.
* Makefile.in: add _absvsi2 _absvdi2 _addvsi3 _addvdi3 _subvsi3
_subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2.
2000-10-18 Geoffrey Keating <geoffk@cygnus.com> 2000-10-18 Geoffrey Keating <geoffk@cygnus.com>
David V. Henkel-Wallace <gumby@cygnus.com> David V. Henkel-Wallace <gumby@cygnus.com>
......
...@@ -754,6 +754,8 @@ LIB2FUNCS = _muldi3 _divdi3 _moddi3 _udivdi3 _umoddi3 _negdi2 \ ...@@ -754,6 +754,8 @@ LIB2FUNCS = _muldi3 _divdi3 _moddi3 _udivdi3 _umoddi3 _negdi2 \
_fixtfdi _fixunstfdi _floatditf \ _fixtfdi _fixunstfdi _floatditf \
__gcc_bcmp _varargs __dummy _eprintf \ __gcc_bcmp _varargs __dummy _eprintf \
_bb _shtab _clear_cache _trampoline __main _exit \ _bb _shtab _clear_cache _trampoline __main _exit \
_absvsi2 _absvdi2 _addvsi3 _addvdi3 _subvsi3 _subvdi3 \
_mulvsi3 _mulvdi3 _negvsi2 _negvdi2 \
_ctors _ctors
LIB2FUNCS_EH = _eh LIB2FUNCS_EH = _eh
......
...@@ -2358,7 +2358,8 @@ expand_mult (mode, op0, op1, target, unsignedp) ...@@ -2358,7 +2358,8 @@ expand_mult (mode, op0, op1, target, unsignedp)
But this causes such a terrible slowdown sometimes But this causes such a terrible slowdown sometimes
that it seems better to use synth_mult always. */ that it seems better to use synth_mult always. */
if (const_op1 && GET_CODE (const_op1) == CONST_INT) if (const_op1 && GET_CODE (const_op1) == CONST_INT
&& (unsignedp || ! flag_trapv))
{ {
struct algorithm alg; struct algorithm alg;
struct algorithm alg2; struct algorithm alg2;
...@@ -2531,7 +2532,10 @@ expand_mult (mode, op0, op1, target, unsignedp) ...@@ -2531,7 +2532,10 @@ expand_mult (mode, op0, op1, target, unsignedp)
/* This used to use umul_optab if unsigned, but for non-widening multiply /* This used to use umul_optab if unsigned, but for non-widening multiply
there is no difference between signed and unsigned. */ there is no difference between signed and unsigned. */
op0 = expand_binop (mode, smul_optab, op0 = expand_binop (mode,
! unsignedp
&& flag_trapv && (GET_MODE_CLASS(mode) == MODE_INT)
? smulv_optab : smul_optab,
op0, op1, target, unsignedp, OPTAB_LIB_WIDEN); op0, op1, target, unsignedp, OPTAB_LIB_WIDEN);
if (op0 == 0) if (op0 == 0)
abort (); abort ();
...@@ -2775,7 +2779,9 @@ expand_mult_highpart (mode, op0, cnst1, target, unsignedp, max_cost) ...@@ -2775,7 +2779,9 @@ expand_mult_highpart (mode, op0, cnst1, target, unsignedp, max_cost)
multiply. Maybe change expand_binop to handle widening multiply? */ multiply. Maybe change expand_binop to handle widening multiply? */
op0 = convert_to_mode (wider_mode, op0, unsignedp); op0 = convert_to_mode (wider_mode, op0, unsignedp);
tem = expand_mult (wider_mode, op0, wide_op1, NULL_RTX, unsignedp); /* We know that this can't have signed overflow, so pretend this is
an unsigned multiply. */
tem = expand_mult (wider_mode, op0, wide_op1, NULL_RTX, 0);
tem = expand_shift (RSHIFT_EXPR, wider_mode, tem, tem = expand_shift (RSHIFT_EXPR, wider_mode, tem,
build_int_2 (size, 0), NULL_RTX, 1); build_int_2 (size, 0), NULL_RTX, 1);
return convert_modes (mode, wider_mode, tem, unsignedp); return convert_modes (mode, wider_mode, tem, unsignedp);
...@@ -2968,6 +2974,16 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp) ...@@ -2968,6 +2974,16 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
if (op1 == const1_rtx) if (op1 == const1_rtx)
return rem_flag ? const0_rtx : op0; return rem_flag ? const0_rtx : op0;
/* When dividing by -1, we could get an overflow.
negv_optab can handle overflows. */
if (! unsignedp && op1 == constm1_rtx)
{
if (rem_flag)
return const0_rtx;
return expand_unop (mode, flag_trapv && GET_MODE_CLASS(mode) == MODE_INT
? negv_optab : neg_optab, op0, target, 0);
}
if (target if (target
/* Don't use the function value register as a target /* Don't use the function value register as a target
since we have to read it as well as write it, since we have to read it as well as write it,
...@@ -3764,16 +3780,15 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp) ...@@ -3764,16 +3780,15 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
{ {
HOST_WIDE_INT d = INTVAL (op1); HOST_WIDE_INT d = INTVAL (op1);
unsigned HOST_WIDE_INT ml; unsigned HOST_WIDE_INT ml;
int post_shift; int pre_shift;
rtx t1; rtx t1;
post_shift = floor_log2 (d & -d); pre_shift = floor_log2 (d & -d);
ml = invert_mod2n (d >> post_shift, size); ml = invert_mod2n (d >> pre_shift, size);
t1 = expand_mult (compute_mode, op0, GEN_INT (ml), NULL_RTX, t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
unsignedp); build_int_2 (pre_shift, 0), NULL_RTX, unsignedp);
quotient = expand_shift (RSHIFT_EXPR, compute_mode, t1, quotient = expand_mult (compute_mode, t1, GEN_INT (ml), NULL_RTX,
build_int_2 (post_shift, 0), 0);
NULL_RTX, unsignedp);
insn = get_last_insn (); insn = get_last_insn ();
set_unique_reg_note (insn, set_unique_reg_note (insn,
...@@ -3826,8 +3841,8 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp) ...@@ -3826,8 +3841,8 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
remainder = expand_binop (compute_mode, sub_optab, op0, tem, remainder = expand_binop (compute_mode, sub_optab, op0, tem,
remainder, 0, OPTAB_LIB_WIDEN); remainder, 0, OPTAB_LIB_WIDEN);
} }
abs_rem = expand_abs (compute_mode, remainder, NULL_RTX, 0); abs_rem = expand_abs (compute_mode, remainder, NULL_RTX, 1, 0);
abs_op1 = expand_abs (compute_mode, op1, NULL_RTX, 0); abs_op1 = expand_abs (compute_mode, op1, NULL_RTX, 1, 0);
tem = expand_shift (LSHIFT_EXPR, compute_mode, abs_rem, tem = expand_shift (LSHIFT_EXPR, compute_mode, abs_rem,
build_int_2 (1, 0), NULL_RTX, 1); build_int_2 (1, 0), NULL_RTX, 1);
do_cmp_and_jump (tem, abs_op1, LTU, compute_mode, label); do_cmp_and_jump (tem, abs_op1, LTU, compute_mode, label);
...@@ -4477,6 +4492,11 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep) ...@@ -4477,6 +4492,11 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
we can use zero-extension to the wider mode (an unsigned conversion) we can use zero-extension to the wider mode (an unsigned conversion)
as the operation. */ as the operation. */
/* CYGNUS LOCAL - amylaar/-ftrapv: Note that ABS doesn't yield a
positive number for INT_MIN, but that is compensated by the
subsequent overflow when subtracting one / negating.
END CYGNUS LOCAL */
if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
tem = expand_unop (mode, abs_optab, op0, subtarget, 1); tem = expand_unop (mode, abs_optab, op0, subtarget, 1);
else if (ffs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) else if (ffs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
......
...@@ -5307,7 +5307,7 @@ force_operand (value, target) ...@@ -5307,7 +5307,7 @@ force_operand (value, target)
tmp = force_operand (XEXP (value, 0), subtarget); tmp = force_operand (XEXP (value, 0), subtarget);
return expand_mult (GET_MODE (value), tmp, return expand_mult (GET_MODE (value), tmp,
force_operand (op2, NULL_RTX), force_operand (op2, NULL_RTX),
target, 0); target, 1);
} }
if (binoptab) if (binoptab)
...@@ -7248,7 +7248,9 @@ expand_expr (exp, target, tmode, modifier) ...@@ -7248,7 +7248,9 @@ expand_expr (exp, target, tmode, modifier)
/* We come here from MINUS_EXPR when the second operand is a /* We come here from MINUS_EXPR when the second operand is a
constant. */ constant. */
plus_expr: plus_expr:
this_optab = add_optab; this_optab = ! unsignedp && flag_trapv
&& (GET_MODE_CLASS(mode) == MODE_INT)
? addv_optab : add_optab;
/* If we are adding a constant, an RTL_EXPR that is sp, fp, or ap, and /* If we are adding a constant, an RTL_EXPR that is sp, fp, or ap, and
something else, make sure we add the register to the constant and something else, make sure we add the register to the constant and
...@@ -7283,7 +7285,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -7283,7 +7285,7 @@ expand_expr (exp, target, tmode, modifier)
If this is an EXPAND_SUM call, always return the sum. */ If this is an EXPAND_SUM call, always return the sum. */
if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER
|| mode == ptr_mode) || (mode == ptr_mode && (unsignedp || ! flag_trapv)))
{ {
if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
...@@ -7441,7 +7443,9 @@ expand_expr (exp, target, tmode, modifier) ...@@ -7441,7 +7443,9 @@ expand_expr (exp, target, tmode, modifier)
goto plus_expr; goto plus_expr;
} }
} }
this_optab = sub_optab; this_optab = ! unsignedp && flag_trapv
&& (GET_MODE_CLASS(mode) == MODE_INT)
? subv_optab : sub_optab;
goto binop; goto binop;
case MULT_EXPR: case MULT_EXPR:
...@@ -7624,7 +7628,10 @@ expand_expr (exp, target, tmode, modifier) ...@@ -7624,7 +7628,10 @@ expand_expr (exp, target, tmode, modifier)
case NEGATE_EXPR: case NEGATE_EXPR:
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
temp = expand_unop (mode, neg_optab, op0, target, 0); temp = expand_unop (mode,
! unsignedp && flag_trapv
&& (GET_MODE_CLASS(mode) == MODE_INT)
? negv_optab : neg_optab, op0, target, 0);
if (temp == 0) if (temp == 0)
abort (); abort ();
return temp; return temp;
...@@ -7642,7 +7649,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -7642,7 +7649,7 @@ expand_expr (exp, target, tmode, modifier)
if (TREE_UNSIGNED (type)) if (TREE_UNSIGNED (type))
return op0; return op0;
return expand_abs (mode, op0, target, return expand_abs (mode, op0, target, unsignedp,
safe_from_p (target, TREE_OPERAND (exp, 0), 1)); safe_from_p (target, TREE_OPERAND (exp, 0), 1));
case MAX_EXPR: case MAX_EXPR:
...@@ -7964,10 +7971,14 @@ expand_expr (exp, target, tmode, modifier) ...@@ -7964,10 +7971,14 @@ expand_expr (exp, target, tmode, modifier)
&& TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<') && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
{ {
rtx result; rtx result;
optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR ? add_optab optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR
: TREE_CODE (binary_op) == MINUS_EXPR ? sub_optab ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
: TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab ? addv_optab : add_optab)
: xor_optab); : TREE_CODE (binary_op) == MINUS_EXPR
? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
? subv_optab : sub_optab)
: TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab
: xor_optab);
/* If we had X ? A : A + 1, do this as A + (X == 0). /* If we had X ? A : A + 1, do this as A + (X == 0).
...@@ -8491,7 +8502,10 @@ expand_expr (exp, target, tmode, modifier) ...@@ -8491,7 +8502,10 @@ expand_expr (exp, target, tmode, modifier)
gen_realpart (partmode, op0)); gen_realpart (partmode, op0));
imag_t = gen_imagpart (partmode, target); imag_t = gen_imagpart (partmode, target);
temp = expand_unop (partmode, neg_optab, temp = expand_unop (partmode,
! unsignedp && flag_trapv
&& (GET_MODE_CLASS(partmode) == MODE_INT)
? negv_optab : neg_optab,
gen_imagpart (partmode, op0), imag_t, 0); gen_imagpart (partmode, op0), imag_t, 0);
if (temp != imag_t) if (temp != imag_t)
emit_move_insn (imag_t, temp); emit_move_insn (imag_t, temp);
...@@ -9045,6 +9059,9 @@ expand_increment (exp, post, ignore) ...@@ -9045,6 +9059,9 @@ expand_increment (exp, post, ignore)
this_optab = add_optab; this_optab = add_optab;
} }
if (TYPE_TRAP_SIGNED (TREE_TYPE (exp)))
this_optab = this_optab == add_optab ? addv_optab : subv_optab;
/* For a preincrement, see if we can do this with a single instruction. */ /* For a preincrement, see if we can do this with a single instruction. */
if (!post) if (!post)
{ {
......
...@@ -298,10 +298,13 @@ typedef struct optab ...@@ -298,10 +298,13 @@ typedef struct optab
enum optab_index enum optab_index
{ {
OTI_add, OTI_add,
OTI_addv,
OTI_sub, OTI_sub,
OTI_subv,
/* Signed and fp multiply */ /* Signed and fp multiply */
OTI_smul, OTI_smul,
OTI_smulv,
/* Signed multiply, return high word */ /* Signed multiply, return high word */
OTI_smul_highpart, OTI_smul_highpart,
OTI_umul_highpart, OTI_umul_highpart,
...@@ -311,6 +314,7 @@ enum optab_index ...@@ -311,6 +314,7 @@ enum optab_index
/* Signed divide */ /* Signed divide */
OTI_sdiv, OTI_sdiv,
OTI_sdivv,
/* Signed divide-and-remainder in one */ /* Signed divide-and-remainder in one */
OTI_sdivmod, OTI_sdivmod,
OTI_udiv, OTI_udiv,
...@@ -357,8 +361,10 @@ enum optab_index ...@@ -357,8 +361,10 @@ enum optab_index
/* Unary operations */ /* Unary operations */
/* Negation */ /* Negation */
OTI_neg, OTI_neg,
OTI_negv,
/* Abs value */ /* Abs value */
OTI_abs, OTI_abs,
OTI_absv,
/* Bitwise not */ /* Bitwise not */
OTI_one_cmpl, OTI_one_cmpl,
/* Find first bit set */ /* Find first bit set */
...@@ -393,11 +399,15 @@ extern optab optab_table[OTI_MAX]; ...@@ -393,11 +399,15 @@ extern optab optab_table[OTI_MAX];
#define add_optab (optab_table[OTI_add]) #define add_optab (optab_table[OTI_add])
#define sub_optab (optab_table[OTI_sub]) #define sub_optab (optab_table[OTI_sub])
#define smul_optab (optab_table[OTI_smul]) #define smul_optab (optab_table[OTI_smul])
#define addv_optab (optab_table[OTI_addv])
#define subv_optab (optab_table[OTI_subv])
#define smul_highpart_optab (optab_table[OTI_smul_highpart]) #define smul_highpart_optab (optab_table[OTI_smul_highpart])
#define umul_highpart_optab (optab_table[OTI_umul_highpart]) #define umul_highpart_optab (optab_table[OTI_umul_highpart])
#define smul_widen_optab (optab_table[OTI_smul_widen]) #define smul_widen_optab (optab_table[OTI_smul_widen])
#define umul_widen_optab (optab_table[OTI_umul_widen]) #define umul_widen_optab (optab_table[OTI_umul_widen])
#define sdiv_optab (optab_table[OTI_sdiv]) #define sdiv_optab (optab_table[OTI_sdiv])
#define smulv_optab (optab_table[OTI_smulv])
#define sdivv_optab (optab_table[OTI_sdivv])
#define sdivmod_optab (optab_table[OTI_sdivmod]) #define sdivmod_optab (optab_table[OTI_sdivmod])
#define udiv_optab (optab_table[OTI_udiv]) #define udiv_optab (optab_table[OTI_udiv])
#define udivmod_optab (optab_table[OTI_udivmod]) #define udivmod_optab (optab_table[OTI_udivmod])
...@@ -422,7 +432,9 @@ extern optab optab_table[OTI_MAX]; ...@@ -422,7 +432,9 @@ extern optab optab_table[OTI_MAX];
#define movstrict_optab (optab_table[OTI_movstrict]) #define movstrict_optab (optab_table[OTI_movstrict])
#define neg_optab (optab_table[OTI_neg]) #define neg_optab (optab_table[OTI_neg])
#define negv_optab (optab_table[OTI_negv])
#define abs_optab (optab_table[OTI_abs]) #define abs_optab (optab_table[OTI_abs])
#define absv_optab (optab_table[OTI_absv])
#define one_cmpl_optab (optab_table[OTI_one_cmpl]) #define one_cmpl_optab (optab_table[OTI_one_cmpl])
#define ffs_optab (optab_table[OTI_ffs]) #define ffs_optab (optab_table[OTI_ffs])
#define sqrt_optab (optab_table[OTI_sqrt]) #define sqrt_optab (optab_table[OTI_sqrt])
...@@ -769,7 +781,7 @@ extern int expand_twoval_binop PARAMS ((optab, rtx, rtx, rtx, rtx, int)); ...@@ -769,7 +781,7 @@ extern int expand_twoval_binop PARAMS ((optab, rtx, rtx, rtx, rtx, int));
extern rtx expand_unop PARAMS ((enum machine_mode, optab, rtx, rtx, int)); extern rtx expand_unop PARAMS ((enum machine_mode, optab, rtx, rtx, int));
/* Expand the absolute value operation. */ /* Expand the absolute value operation. */
extern rtx expand_abs PARAMS ((enum machine_mode, rtx, rtx, int)); extern rtx expand_abs PARAMS ((enum machine_mode, rtx, rtx, int, int));
/* Expand the complex absolute value operation. */ /* Expand the complex absolute value operation. */
extern rtx expand_complex_abs PARAMS ((enum machine_mode, rtx, rtx, int)); extern rtx expand_complex_abs PARAMS ((enum machine_mode, rtx, rtx, int));
......
...@@ -555,6 +555,10 @@ extern int frame_pointer_needed; ...@@ -555,6 +555,10 @@ extern int frame_pointer_needed;
extern int flag_check_memory_usage; extern int flag_check_memory_usage;
/* Nonzero if the generated code should trap on signed overflow
for PLUS / SUB / MULT. */
extern int flag_trapv;
/* Nonzero if GCC must prefix function names (used with /* Nonzero if GCC must prefix function names (used with
flag_check_memory_usage). */ flag_check_memory_usage). */
......
...@@ -46,8 +46,11 @@ Boston, MA 02111-1307, USA. */ ...@@ -46,8 +46,11 @@ Boston, MA 02111-1307, USA. */
If $N is present in the pattern, it means the two modes must be consecutive If $N is present in the pattern, it means the two modes must be consecutive
widths in the same mode class (e.g, QImode and HImode). $I means that widths in the same mode class (e.g, QImode and HImode). $I means that
only integer modes should be considered for the next mode, and $F means only full integer modes should be considered for the next mode, and $F
that only float modes should be considered. means that only float modes should be considered.
$P means that both full and partial integer modes should be considered.
$V means to emit 'v' if the first mode is a MODE_FLOAT mode.
For some optabs, we store the operation by RTL codes. These are only For some optabs, we store the operation by RTL codes. These are only
used for comparisons. In that case, $c and $C are the lower-case and used for comparisons. In that case, $c and $C are the lower-case and
...@@ -62,14 +65,24 @@ const char * const optabs[] = ...@@ -62,14 +65,24 @@ const char * const optabs[] =
"fixtrunctab[$A][$B][1] = CODE_FOR_$(fixuns_trunc$F$a$I$b2$)", "fixtrunctab[$A][$B][1] = CODE_FOR_$(fixuns_trunc$F$a$I$b2$)",
"floattab[$B][$A][0] = CODE_FOR_$(float$I$a$F$b2$)", "floattab[$B][$A][0] = CODE_FOR_$(float$I$a$F$b2$)",
"floattab[$B][$A][1] = CODE_FOR_$(floatuns$I$a$F$b2$)", "floattab[$B][$A][1] = CODE_FOR_$(floatuns$I$a$F$b2$)",
"add_optab->handlers[$A].insn_code = CODE_FOR_$(add$a3$)", "add_optab->handlers[$A].insn_code = CODE_FOR_$(add$P$a3$)",
"sub_optab->handlers[$A].insn_code = CODE_FOR_$(sub$a3$)", "addv_optab->handlers[(int) $A].insn_code =\n\
"smul_optab->handlers[$A].insn_code = CODE_FOR_$(mul$a3$)", add_optab->handlers[(int) $A].insn_code = CODE_FOR_$(add$F$a3$)",
"addv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(addv$I$a3$)",
"sub_optab->handlers[$A].insn_code = CODE_FOR_$(sub$P$a3$)",
"subv_optab->handlers[(int) $A].insn_code =\n\
sub_optab->handlers[(int) $A].insn_code = CODE_FOR_$(sub$F$a3$)",
"subv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(subv$I$a3$)",
"smul_optab->handlers[$A].insn_code = CODE_FOR_$(mul$P$a3$)",
"smulv_optab->handlers[(int) $A].insn_code =\n\
smul_optab->handlers[(int) $A].insn_code = CODE_FOR_$(mul$F$a3$)",
"smulv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(mulv$I$a3$)",
"umul_highpart_optab->handlers[$A].insn_code = CODE_FOR_$(umul$a3_highpart$)", "umul_highpart_optab->handlers[$A].insn_code = CODE_FOR_$(umul$a3_highpart$)",
"smul_highpart_optab->handlers[$A].insn_code = CODE_FOR_$(smul$a3_highpart$)", "smul_highpart_optab->handlers[$A].insn_code = CODE_FOR_$(smul$a3_highpart$)",
"smul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(mul$a$b3$)$N", "smul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(mul$a$b3$)$N",
"umul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umul$a$b3$)$N", "umul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umul$a$b3$)$N",
"sdiv_optab->handlers[$A].insn_code = CODE_FOR_$(div$I$a3$)", "sdiv_optab->handlers[$A].insn_code = CODE_FOR_$(div$I$a3$)",
"sdivv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(div$V$I$a3$)",
"udiv_optab->handlers[$A].insn_code = CODE_FOR_$(udiv$I$a3$)", "udiv_optab->handlers[$A].insn_code = CODE_FOR_$(udiv$I$a3$)",
"sdivmod_optab->handlers[$A].insn_code = CODE_FOR_$(divmod$a4$)", "sdivmod_optab->handlers[$A].insn_code = CODE_FOR_$(divmod$a4$)",
"udivmod_optab->handlers[$A].insn_code = CODE_FOR_$(udivmod$a4$)", "udivmod_optab->handlers[$A].insn_code = CODE_FOR_$(udivmod$a4$)",
...@@ -91,8 +104,14 @@ const char * const optabs[] = ...@@ -91,8 +104,14 @@ const char * const optabs[] =
"smax_optab->handlers[$A].insn_code = CODE_FOR_$(max$F$a3$)", "smax_optab->handlers[$A].insn_code = CODE_FOR_$(max$F$a3$)",
"umin_optab->handlers[$A].insn_code = CODE_FOR_$(umin$I$a3$)", "umin_optab->handlers[$A].insn_code = CODE_FOR_$(umin$I$a3$)",
"umax_optab->handlers[$A].insn_code = CODE_FOR_$(umax$I$a3$)", "umax_optab->handlers[$A].insn_code = CODE_FOR_$(umax$I$a3$)",
"neg_optab->handlers[$A].insn_code = CODE_FOR_$(neg$a2$)", "neg_optab->handlers[$A].insn_code = CODE_FOR_$(neg$P$a2$)",
"abs_optab->handlers[$A].insn_code = CODE_FOR_$(abs$a2$)", "negv_optab->handlers[(int) $A].insn_code =\n\
neg_optab->handlers[(int) $A].insn_code = CODE_FOR_$(neg$F$a2$)",
"negv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(negv$I$a2$)",
"abs_optab->handlers[$A].insn_code = CODE_FOR_$(abs$P$a2$)",
"absv_optab->handlers[(int) $A].insn_code =\n\
abs_optab->handlers[(int) $A].insn_code = CODE_FOR_$(abs$F$a2$)",
"absv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(absv$I$a2$)",
"sqrt_optab->handlers[$A].insn_code = CODE_FOR_$(sqrt$a2$)", "sqrt_optab->handlers[$A].insn_code = CODE_FOR_$(sqrt$a2$)",
"sin_optab->handlers[$A].insn_code = CODE_FOR_$(sin$a2$)", "sin_optab->handlers[$A].insn_code = CODE_FOR_$(sin$a2$)",
"cos_optab->handlers[$A].insn_code = CODE_FOR_$(cos$a2$)", "cos_optab->handlers[$A].insn_code = CODE_FOR_$(cos$a2$)",
...@@ -136,7 +155,7 @@ gen_insn (insn) ...@@ -136,7 +155,7 @@ gen_insn (insn)
for (pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++) for (pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++)
{ {
int force_float = 0, force_int = 0; int force_float = 0, force_int = 0, force_partial_int = 0;
int force_consec = 0; int force_consec = 0;
int matches = 1; int matches = 1;
...@@ -160,9 +179,14 @@ gen_insn (insn) ...@@ -160,9 +179,14 @@ gen_insn (insn)
case 'I': case 'I':
force_int = 1; force_int = 1;
break; break;
case 'P':
force_partial_int = 1;
break;
case 'F': case 'F':
force_float = 1; force_float = 1;
break; break;
case 'V':
break;
case 'c': case 'c':
for (op = 0; op < NUM_RTX_CODE; op++) for (op = 0; op < NUM_RTX_CODE; op++)
{ {
...@@ -196,6 +220,9 @@ gen_insn (insn) ...@@ -196,6 +220,9 @@ gen_insn (insn)
if (*p == 0 if (*p == 0
&& (! force_int || mode_class[i] == MODE_INT) && (! force_int || mode_class[i] == MODE_INT)
&& (! force_partial_int
|| mode_class[i] == MODE_INT
|| mode_class[i] == MODE_PARTIAL_INT)
&& (! force_float || mode_class[i] == MODE_FLOAT)) && (! force_float || mode_class[i] == MODE_FLOAT))
break; break;
} }
...@@ -207,7 +234,7 @@ gen_insn (insn) ...@@ -207,7 +234,7 @@ gen_insn (insn)
else else
m2 = i, np += strlen (GET_MODE_NAME(i)); m2 = i, np += strlen (GET_MODE_NAME(i));
force_int = force_float = 0; force_int = force_partial_int = force_float = 0;
break; break;
default: default:
...@@ -243,6 +270,10 @@ gen_insn (insn) ...@@ -243,6 +270,10 @@ gen_insn (insn)
case '(': case ')': case '(': case ')':
case 'I': case 'F': case 'N': case 'I': case 'F': case 'N':
break; break;
case 'V':
if (GET_MODE_CLASS (m1) == MODE_FLOAT)
printf ("v");
break;
case 'a': case 'a':
for (np = GET_MODE_NAME(m1); *np; np++) for (np = GET_MODE_NAME(m1); *np; np++)
putchar (TOLOWER (*np)); putchar (TOLOWER (*np));
......
...@@ -173,7 +173,7 @@ in the following sections. ...@@ -173,7 +173,7 @@ in the following sections.
-fdata-sections -ffunction-sections -fgcse -fdata-sections -ffunction-sections -fgcse
-finline-functions -finline-limit=@var{n} -fkeep-inline-functions -finline-functions -finline-limit=@var{n} -fkeep-inline-functions
-fmove-all-movables -fno-default-inline -fno-defer-pop -fmove-all-movables -fno-default-inline -fno-defer-pop
-fno-function-cse -fno-inline -fno-peephole -fno-function-cse -fno-inline -fno-peephole -ftrapv
-fomit-frame-pointer -foptimize-register-moves -foptimize-sibling-calls -fomit-frame-pointer -foptimize-register-moves -foptimize-sibling-calls
-fregmove -frerun-cse-after-loop -frerun-loop-opt -freduce-all-givs -fregmove -frerun-cse-after-loop -frerun-loop-opt -freduce-all-givs
-fschedule-insns -fschedule-insns2 -fssa -fstrength-reduce -fschedule-insns -fschedule-insns2 -fssa -fstrength-reduce
...@@ -2664,6 +2664,10 @@ Usage, gcc.info, Using and Porting GCC}.@refill ...@@ -2664,6 +2664,10 @@ Usage, gcc.info, Using and Porting GCC}.@refill
@item -foptimize-sibling-calls @item -foptimize-sibling-calls
Optimize sibling and tail recursive calls. Optimize sibling and tail recursive calls.
@item -ftrapv
This option generates traps for signed overflow on addition, subtraction,
multiplication operations.
@item -fno-inline @item -fno-inline
Don't pay attention to the @code{inline} keyword. Normally this option Don't pay attention to the @code{inline} keyword. Normally this option
is used to keep the compiler from expanding any functions inline. is used to keep the compiler from expanding any functions inline.
......
...@@ -50,6 +50,176 @@ Boston, MA 02111-1307, USA. */ ...@@ -50,6 +50,176 @@ Boston, MA 02111-1307, USA. */
#if defined (L_divdi3) || defined (L_moddi3) #if defined (L_divdi3) || defined (L_moddi3)
static inline static inline
#endif #endif
#ifdef L_addvsi3
SItype
__addvsi3 (SItype a, SItype b)
{
SItype w, w1;
w = a + b;
if (b >= 0 ? w < a : w > a)
abort ();
return w;
}
#ifdef L_addvdi3
DItype
__addvdi3 (DItype a, DItype b)
{
DItype w;
w = a + b;
if (b >= 0 ? w < a : w > a)
abort ();
return w;
}
#endif
#ifdef L_subvsi3
SItype
__subvsi3 (SItype a, SItype b)
{
#ifdef L_addvsi3
return __addvsi3 (a, (-b));
#else
DItype w;
w = a - b;
if (b >= 0 ? w > a : w < a)
abort ();
return w;
#endif
}
#endif
#ifdef L_subvdi3
DItype
__subvdi3 (DItype a, DItype b)
{
#ifdef L_addvdi3
return (a, (-b));
#else
DItype w;
w = a - b;
if (b >= 0 ? w > a : w < a)
abort ();
return w;
#endif
}
#endif
#ifdef L_mulvsi3
SItype
__mulvsi3 (SItype a, SItype b)
{
DItype w;
w = a * b;
if ((a >= 0 && b >= 0) ? w < 0
: (a >= 0 || b >= 0) ? w > 0 : w < 0)
abort ();
return w;
}
#endif
#ifdef L_negvsi2
SItype
__negvsi2 (SItype a)
{
SItype w;
w = -a;
if (a >= 0 ? w > 0 : w < 0)
abort ();
return w;
}
#endif
#ifdef L_negvdi2
DItype
__negvdi2 (DItype a)
{
DItype w;
w = -a;
if (a >= 0 ? w > 0 : w < 0)
abort ();
return w;
}
#endif
#ifdef L_absvsi2
SItype
__absvsi2 (SItype a)
{
SItype w = a;
if (a < 0)
#ifdef L_negvsi2
w = __negvsi2 (a);
#else
w = -a;
if (w < 0)
abort ();
#endif
return w;
}
#endif
#ifdef L_absvdi2
DItype
__absvdi2 (DItype a)
{
DItype w = a;
if (a < 0)
#ifdef L_negvsi2
w = __negvsi2 (a);
#else
w = -a;
if (w < 0)
abort ();
#endif
return w;
}
#endif
#ifdef L_mulvdi3
DItype
__mulvdi3 (DItype u, DItype v)
{
DItype w;
w = u * v;
if ((u >= 0 && v >= 0) ? w < 0
: (u >= 0 || v >= 0) ? w > 0 : w < 0)
abort ();
return w;
}
#endif
DWtype DWtype
__negdi2 (DWtype u) __negdi2 (DWtype u)
{ {
......
...@@ -6877,7 +6877,7 @@ emit_iv_add_mult (b, m, a, reg, insert_before) ...@@ -6877,7 +6877,7 @@ emit_iv_add_mult (b, m, a, reg, insert_before)
update_reg_last_use (m, insert_before); update_reg_last_use (m, insert_before);
start_sequence (); start_sequence ();
result = expand_mult_add (b, reg, m, a, GET_MODE (reg), 0); result = expand_mult_add (b, reg, m, a, GET_MODE (reg), 1);
if (reg != result) if (reg != result)
emit_move_insn (reg, result); emit_move_insn (reg, result);
seq = gen_sequence (); seq = gen_sequence ();
...@@ -6961,7 +6961,7 @@ product_cheap_p (a, b) ...@@ -6961,7 +6961,7 @@ product_cheap_p (a, b)
of insns is generated. */ of insns is generated. */
start_sequence (); start_sequence ();
expand_mult (GET_MODE (a), a, b, NULL_RTX, 0); expand_mult (GET_MODE (a), a, b, NULL_RTX, 1);
tmp = gen_sequence (); tmp = gen_sequence ();
end_sequence (); end_sequence ();
......
...@@ -947,6 +947,8 @@ typedef struct ...@@ -947,6 +947,8 @@ typedef struct
} }
lang_independent_options; lang_independent_options;
int flag_trapv = 0;
/* Add or remove a leading underscore from user symbols. */ /* Add or remove a leading underscore from user symbols. */
int flag_leading_underscore = -1; int flag_leading_underscore = -1;
...@@ -1145,6 +1147,8 @@ lang_independent_options f_options[] = ...@@ -1145,6 +1147,8 @@ lang_independent_options f_options[] =
"Report time taken by each compiler pass at end of run"}, "Report time taken by each compiler pass at end of run"},
{"mem-report", &mem_report, 1, {"mem-report", &mem_report, 1,
"Report on permanent memory allocation at end of run"}, "Report on permanent memory allocation at end of run"},
{ "trapv", &flag_trapv, 1,
"Trap for signed overflow in addition / subtraction / multiplication." },
}; };
/* Table of language-specific options. */ /* Table of language-specific options. */
......
...@@ -574,6 +574,8 @@ extern void tree_class_check_failed PARAMS ((const tree, int, ...@@ -574,6 +574,8 @@ extern void tree_class_check_failed PARAMS ((const tree, int,
The same bit is used in functions as DECL_BUILT_IN_NONANSI. */ The same bit is used in functions as DECL_BUILT_IN_NONANSI. */
#define TREE_UNSIGNED(NODE) ((NODE)->common.unsigned_flag) #define TREE_UNSIGNED(NODE) ((NODE)->common.unsigned_flag)
#define TYPE_TRAP_SIGNED(NODE) (flag_trapv && ! TREE_UNSIGNED (NODE))
/* Nonzero in a VAR_DECL means assembler code has been written. /* Nonzero in a VAR_DECL means assembler code has been written.
Nonzero in a FUNCTION_DECL means that the function has been compiled. Nonzero in a FUNCTION_DECL means that the function has been compiled.
This is interesting in an inline function, since it might not need This is interesting in an inline function, since it might not need
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment