Adding new option -ftrapv.
From-SVN: r36942
This commit is contained in:
parent
4c2c5712af
commit
91ce572a07
@ -1,3 +1,47 @@
|
||||
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>
|
||||
David V. Henkel-Wallace <gumby@cygnus.com>
|
||||
|
||||
|
@ -754,6 +754,8 @@ LIB2FUNCS = _muldi3 _divdi3 _moddi3 _udivdi3 _umoddi3 _negdi2 \
|
||||
_fixtfdi _fixunstfdi _floatditf \
|
||||
__gcc_bcmp _varargs __dummy _eprintf \
|
||||
_bb _shtab _clear_cache _trampoline __main _exit \
|
||||
_absvsi2 _absvdi2 _addvsi3 _addvdi3 _subvsi3 _subvdi3 \
|
||||
_mulvsi3 _mulvdi3 _negvsi2 _negvdi2 \
|
||||
_ctors
|
||||
|
||||
LIB2FUNCS_EH = _eh
|
||||
|
46
gcc/expmed.c
46
gcc/expmed.c
@ -2358,7 +2358,8 @@ expand_mult (mode, op0, op1, target, unsignedp)
|
||||
But this causes such a terrible slowdown sometimes
|
||||
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 alg2;
|
||||
@ -2531,7 +2532,10 @@ expand_mult (mode, op0, op1, target, unsignedp)
|
||||
|
||||
/* This used to use umul_optab if unsigned, but for non-widening multiply
|
||||
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);
|
||||
if (op0 == 0)
|
||||
abort ();
|
||||
@ -2775,7 +2779,9 @@ expand_mult_highpart (mode, op0, cnst1, target, unsignedp, max_cost)
|
||||
multiply. Maybe change expand_binop to handle widening multiply? */
|
||||
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,
|
||||
build_int_2 (size, 0), NULL_RTX, 1);
|
||||
return convert_modes (mode, wider_mode, tem, unsignedp);
|
||||
@ -2968,6 +2974,16 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
|
||||
if (op1 == const1_rtx)
|
||||
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
|
||||
/* Don't use the function value register as a target
|
||||
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)
|
||||
{
|
||||
HOST_WIDE_INT d = INTVAL (op1);
|
||||
unsigned HOST_WIDE_INT ml;
|
||||
int post_shift;
|
||||
int pre_shift;
|
||||
rtx t1;
|
||||
|
||||
post_shift = floor_log2 (d & -d);
|
||||
ml = invert_mod2n (d >> post_shift, size);
|
||||
t1 = expand_mult (compute_mode, op0, GEN_INT (ml), NULL_RTX,
|
||||
unsignedp);
|
||||
quotient = expand_shift (RSHIFT_EXPR, compute_mode, t1,
|
||||
build_int_2 (post_shift, 0),
|
||||
NULL_RTX, unsignedp);
|
||||
pre_shift = floor_log2 (d & -d);
|
||||
ml = invert_mod2n (d >> pre_shift, size);
|
||||
t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
|
||||
build_int_2 (pre_shift, 0), NULL_RTX, unsignedp);
|
||||
quotient = expand_mult (compute_mode, t1, GEN_INT (ml), NULL_RTX,
|
||||
0);
|
||||
|
||||
insn = get_last_insn ();
|
||||
set_unique_reg_note (insn,
|
||||
@ -3826,8 +3841,8 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
|
||||
remainder = expand_binop (compute_mode, sub_optab, op0, tem,
|
||||
remainder, 0, OPTAB_LIB_WIDEN);
|
||||
}
|
||||
abs_rem = expand_abs (compute_mode, remainder, NULL_RTX, 0);
|
||||
abs_op1 = expand_abs (compute_mode, op1, NULL_RTX, 0);
|
||||
abs_rem = expand_abs (compute_mode, remainder, NULL_RTX, 1, 0);
|
||||
abs_op1 = expand_abs (compute_mode, op1, NULL_RTX, 1, 0);
|
||||
tem = expand_shift (LSHIFT_EXPR, compute_mode, abs_rem,
|
||||
build_int_2 (1, 0), NULL_RTX, 1);
|
||||
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)
|
||||
we can use zero-extension to the wider mode (an unsigned conversion)
|
||||
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)
|
||||
tem = expand_unop (mode, abs_optab, op0, subtarget, 1);
|
||||
else if (ffs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
|
||||
|
39
gcc/expr.c
39
gcc/expr.c
@ -5307,7 +5307,7 @@ force_operand (value, target)
|
||||
tmp = force_operand (XEXP (value, 0), subtarget);
|
||||
return expand_mult (GET_MODE (value), tmp,
|
||||
force_operand (op2, NULL_RTX),
|
||||
target, 0);
|
||||
target, 1);
|
||||
}
|
||||
|
||||
if (binoptab)
|
||||
@ -7248,7 +7248,9 @@ expand_expr (exp, target, tmode, modifier)
|
||||
/* We come here from MINUS_EXPR when the second operand is a
|
||||
constant. */
|
||||
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
|
||||
something else, make sure we add the register to the constant and
|
||||
@ -7283,7 +7285,7 @@ expand_expr (exp, target, tmode, modifier)
|
||||
|
||||
If this is an EXPAND_SUM call, always return the sum. */
|
||||
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
|
||||
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
|
||||
@ -7441,7 +7443,9 @@ expand_expr (exp, target, tmode, modifier)
|
||||
goto plus_expr;
|
||||
}
|
||||
}
|
||||
this_optab = sub_optab;
|
||||
this_optab = ! unsignedp && flag_trapv
|
||||
&& (GET_MODE_CLASS(mode) == MODE_INT)
|
||||
? subv_optab : sub_optab;
|
||||
goto binop;
|
||||
|
||||
case MULT_EXPR:
|
||||
@ -7624,7 +7628,10 @@ expand_expr (exp, target, tmode, modifier)
|
||||
|
||||
case NEGATE_EXPR:
|
||||
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)
|
||||
abort ();
|
||||
return temp;
|
||||
@ -7642,7 +7649,7 @@ expand_expr (exp, target, tmode, modifier)
|
||||
if (TREE_UNSIGNED (type))
|
||||
return op0;
|
||||
|
||||
return expand_abs (mode, op0, target,
|
||||
return expand_abs (mode, op0, target, unsignedp,
|
||||
safe_from_p (target, TREE_OPERAND (exp, 0), 1));
|
||||
|
||||
case MAX_EXPR:
|
||||
@ -7964,10 +7971,14 @@ expand_expr (exp, target, tmode, modifier)
|
||||
&& TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
|
||||
{
|
||||
rtx result;
|
||||
optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR ? add_optab
|
||||
: TREE_CODE (binary_op) == MINUS_EXPR ? sub_optab
|
||||
: TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab
|
||||
: xor_optab);
|
||||
optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR
|
||||
? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
|
||||
? addv_optab : add_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).
|
||||
|
||||
@ -8491,7 +8502,10 @@ expand_expr (exp, target, tmode, modifier)
|
||||
gen_realpart (partmode, op0));
|
||||
|
||||
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);
|
||||
if (temp != imag_t)
|
||||
emit_move_insn (imag_t, temp);
|
||||
@ -9045,6 +9059,9 @@ expand_increment (exp, post, ignore)
|
||||
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. */
|
||||
if (!post)
|
||||
{
|
||||
|
14
gcc/expr.h
14
gcc/expr.h
@ -298,10 +298,13 @@ typedef struct optab
|
||||
enum optab_index
|
||||
{
|
||||
OTI_add,
|
||||
OTI_addv,
|
||||
OTI_sub,
|
||||
OTI_subv,
|
||||
|
||||
/* Signed and fp multiply */
|
||||
OTI_smul,
|
||||
OTI_smulv,
|
||||
/* Signed multiply, return high word */
|
||||
OTI_smul_highpart,
|
||||
OTI_umul_highpart,
|
||||
@ -311,6 +314,7 @@ enum optab_index
|
||||
|
||||
/* Signed divide */
|
||||
OTI_sdiv,
|
||||
OTI_sdivv,
|
||||
/* Signed divide-and-remainder in one */
|
||||
OTI_sdivmod,
|
||||
OTI_udiv,
|
||||
@ -357,8 +361,10 @@ enum optab_index
|
||||
/* Unary operations */
|
||||
/* Negation */
|
||||
OTI_neg,
|
||||
OTI_negv,
|
||||
/* Abs value */
|
||||
OTI_abs,
|
||||
OTI_absv,
|
||||
/* Bitwise not */
|
||||
OTI_one_cmpl,
|
||||
/* Find first bit set */
|
||||
@ -393,11 +399,15 @@ extern optab optab_table[OTI_MAX];
|
||||
#define add_optab (optab_table[OTI_add])
|
||||
#define sub_optab (optab_table[OTI_sub])
|
||||
#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 umul_highpart_optab (optab_table[OTI_umul_highpart])
|
||||
#define smul_widen_optab (optab_table[OTI_smul_widen])
|
||||
#define umul_widen_optab (optab_table[OTI_umul_widen])
|
||||
#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 udiv_optab (optab_table[OTI_udiv])
|
||||
#define udivmod_optab (optab_table[OTI_udivmod])
|
||||
@ -422,7 +432,9 @@ extern optab optab_table[OTI_MAX];
|
||||
#define movstrict_optab (optab_table[OTI_movstrict])
|
||||
|
||||
#define neg_optab (optab_table[OTI_neg])
|
||||
#define negv_optab (optab_table[OTI_negv])
|
||||
#define abs_optab (optab_table[OTI_abs])
|
||||
#define absv_optab (optab_table[OTI_absv])
|
||||
#define one_cmpl_optab (optab_table[OTI_one_cmpl])
|
||||
#define ffs_optab (optab_table[OTI_ffs])
|
||||
#define sqrt_optab (optab_table[OTI_sqrt])
|
||||
@ -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));
|
||||
|
||||
/* 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. */
|
||||
extern rtx expand_complex_abs PARAMS ((enum machine_mode, rtx, rtx, int));
|
||||
|
@ -555,6 +555,10 @@ extern int frame_pointer_needed;
|
||||
|
||||
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
|
||||
flag_check_memory_usage). */
|
||||
|
||||
|
@ -46,8 +46,11 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
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
|
||||
only integer modes should be considered for the next mode, and $F means
|
||||
that only float modes should be considered.
|
||||
only full integer modes should be considered for the next mode, and $F
|
||||
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
|
||||
used for comparisons. In that case, $c and $C are the lower-case and
|
||||
@ -62,14 +65,24 @@ const char * const optabs[] =
|
||||
"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][1] = CODE_FOR_$(floatuns$I$a$F$b2$)",
|
||||
"add_optab->handlers[$A].insn_code = CODE_FOR_$(add$a3$)",
|
||||
"sub_optab->handlers[$A].insn_code = CODE_FOR_$(sub$a3$)",
|
||||
"smul_optab->handlers[$A].insn_code = CODE_FOR_$(mul$a3$)",
|
||||
"add_optab->handlers[$A].insn_code = CODE_FOR_$(add$P$a3$)",
|
||||
"addv_optab->handlers[(int) $A].insn_code =\n\
|
||||
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$)",
|
||||
"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",
|
||||
"umul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umul$a$b3$)$N",
|
||||
"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$)",
|
||||
"sdivmod_optab->handlers[$A].insn_code = CODE_FOR_$(divmod$a4$)",
|
||||
"udivmod_optab->handlers[$A].insn_code = CODE_FOR_$(udivmod$a4$)",
|
||||
@ -91,8 +104,14 @@ const char * const optabs[] =
|
||||
"smax_optab->handlers[$A].insn_code = CODE_FOR_$(max$F$a3$)",
|
||||
"umin_optab->handlers[$A].insn_code = CODE_FOR_$(umin$I$a3$)",
|
||||
"umax_optab->handlers[$A].insn_code = CODE_FOR_$(umax$I$a3$)",
|
||||
"neg_optab->handlers[$A].insn_code = CODE_FOR_$(neg$a2$)",
|
||||
"abs_optab->handlers[$A].insn_code = CODE_FOR_$(abs$a2$)",
|
||||
"neg_optab->handlers[$A].insn_code = CODE_FOR_$(neg$P$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$)",
|
||||
"sin_optab->handlers[$A].insn_code = CODE_FOR_$(sin$a2$)",
|
||||
"cos_optab->handlers[$A].insn_code = CODE_FOR_$(cos$a2$)",
|
||||
@ -136,7 +155,7 @@ gen_insn (insn)
|
||||
|
||||
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 matches = 1;
|
||||
|
||||
@ -160,9 +179,14 @@ gen_insn (insn)
|
||||
case 'I':
|
||||
force_int = 1;
|
||||
break;
|
||||
case 'P':
|
||||
force_partial_int = 1;
|
||||
break;
|
||||
case 'F':
|
||||
force_float = 1;
|
||||
break;
|
||||
case 'V':
|
||||
break;
|
||||
case 'c':
|
||||
for (op = 0; op < NUM_RTX_CODE; op++)
|
||||
{
|
||||
@ -196,6 +220,9 @@ gen_insn (insn)
|
||||
|
||||
if (*p == 0
|
||||
&& (! 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))
|
||||
break;
|
||||
}
|
||||
@ -207,7 +234,7 @@ gen_insn (insn)
|
||||
else
|
||||
m2 = i, np += strlen (GET_MODE_NAME(i));
|
||||
|
||||
force_int = force_float = 0;
|
||||
force_int = force_partial_int = force_float = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -243,6 +270,10 @@ gen_insn (insn)
|
||||
case '(': case ')':
|
||||
case 'I': case 'F': case 'N':
|
||||
break;
|
||||
case 'V':
|
||||
if (GET_MODE_CLASS (m1) == MODE_FLOAT)
|
||||
printf ("v");
|
||||
break;
|
||||
case 'a':
|
||||
for (np = GET_MODE_NAME(m1); *np; np++)
|
||||
putchar (TOLOWER (*np));
|
||||
|
@ -173,7 +173,7 @@ in the following sections.
|
||||
-fdata-sections -ffunction-sections -fgcse
|
||||
-finline-functions -finline-limit=@var{n} -fkeep-inline-functions
|
||||
-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
|
||||
-fregmove -frerun-cse-after-loop -frerun-loop-opt -freduce-all-givs
|
||||
-fschedule-insns -fschedule-insns2 -fssa -fstrength-reduce
|
||||
@ -2664,6 +2664,10 @@ Usage, gcc.info, Using and Porting GCC}.@refill
|
||||
@item -foptimize-sibling-calls
|
||||
Optimize sibling and tail recursive calls.
|
||||
|
||||
@item -ftrapv
|
||||
This option generates traps for signed overflow on addition, subtraction,
|
||||
multiplication operations.
|
||||
|
||||
@item -fno-inline
|
||||
Don't pay attention to the @code{inline} keyword. Normally this option
|
||||
is used to keep the compiler from expanding any functions inline.
|
||||
|
170
gcc/libgcc2.c
170
gcc/libgcc2.c
@ -50,6 +50,176 @@ Boston, MA 02111-1307, USA. */
|
||||
#if defined (L_divdi3) || defined (L_moddi3)
|
||||
static inline
|
||||
#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
|
||||
__negdi2 (DWtype u)
|
||||
{
|
||||
|
@ -6877,7 +6877,7 @@ emit_iv_add_mult (b, m, a, reg, insert_before)
|
||||
update_reg_last_use (m, insert_before);
|
||||
|
||||
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)
|
||||
emit_move_insn (reg, result);
|
||||
seq = gen_sequence ();
|
||||
@ -6961,7 +6961,7 @@ product_cheap_p (a, b)
|
||||
of insns is generated. */
|
||||
|
||||
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 ();
|
||||
end_sequence ();
|
||||
|
||||
|
167
gcc/optabs.c
167
gcc/optabs.c
@ -218,7 +218,19 @@ expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
|
||||
rtx real_t, imag_t;
|
||||
rtx temp1, temp2;
|
||||
rtx res;
|
||||
optab this_add_optab = add_optab;
|
||||
optab this_sub_optab = sub_optab;
|
||||
optab this_neg_optab = neg_optab;
|
||||
optab this_mul_optab = smul_optab;
|
||||
|
||||
if (binoptab == sdivv_optab)
|
||||
{
|
||||
this_add_optab = addv_optab;
|
||||
this_sub_optab = subv_optab;
|
||||
this_neg_optab = negv_optab;
|
||||
this_mul_optab = smulv_optab;
|
||||
}
|
||||
|
||||
/* Don't fetch these from memory more than once. */
|
||||
real0 = force_reg (submode, real0);
|
||||
real1 = force_reg (submode, real1);
|
||||
@ -229,16 +241,16 @@ expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
|
||||
imag1 = force_reg (submode, imag1);
|
||||
|
||||
/* Divisor: c*c + d*d. */
|
||||
temp1 = expand_binop (submode, smul_optab, real1, real1,
|
||||
temp1 = expand_binop (submode, this_mul_optab, real1, real1,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
temp2 = expand_binop (submode, smul_optab, imag1, imag1,
|
||||
temp2 = expand_binop (submode, this_mul_optab, imag1, imag1,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (temp1 == 0 || temp2 == 0)
|
||||
return 0;
|
||||
|
||||
divisor = expand_binop (submode, add_optab, temp1, temp2,
|
||||
divisor = expand_binop (submode, this_add_optab, temp1, temp2,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
if (divisor == 0)
|
||||
return 0;
|
||||
@ -249,44 +261,44 @@ expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
|
||||
/* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */
|
||||
|
||||
/* Calculate the dividend. */
|
||||
real_t = expand_binop (submode, smul_optab, real0, real1,
|
||||
real_t = expand_binop (submode, this_mul_optab, real0, real1,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
imag_t = expand_binop (submode, smul_optab, real0, imag1,
|
||||
imag_t = expand_binop (submode, this_mul_optab, real0, imag1,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (real_t == 0 || imag_t == 0)
|
||||
return 0;
|
||||
|
||||
imag_t = expand_unop (submode, neg_optab, imag_t,
|
||||
imag_t = expand_unop (submode, this_neg_optab, imag_t,
|
||||
NULL_RTX, unsignedp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Mathematically, ((a+ib)(c-id))/divider. */
|
||||
/* Calculate the dividend. */
|
||||
temp1 = expand_binop (submode, smul_optab, real0, real1,
|
||||
temp1 = expand_binop (submode, this_mul_optab, real0, real1,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
temp2 = expand_binop (submode, smul_optab, imag0, imag1,
|
||||
temp2 = expand_binop (submode, this_mul_optab, imag0, imag1,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (temp1 == 0 || temp2 == 0)
|
||||
return 0;
|
||||
|
||||
real_t = expand_binop (submode, add_optab, temp1, temp2,
|
||||
real_t = expand_binop (submode, this_add_optab, temp1, temp2,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
temp1 = expand_binop (submode, smul_optab, imag0, real1,
|
||||
temp1 = expand_binop (submode, this_mul_optab, imag0, real1,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
temp2 = expand_binop (submode, smul_optab, real0, imag1,
|
||||
temp2 = expand_binop (submode, this_mul_optab, real0, imag1,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (temp1 == 0 || temp2 == 0)
|
||||
return 0;
|
||||
|
||||
imag_t = expand_binop (submode, sub_optab, temp1, temp2,
|
||||
imag_t = expand_binop (submode, this_sub_optab, temp1, temp2,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (real_t == 0 || imag_t == 0)
|
||||
@ -340,6 +352,18 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
|
||||
enum machine_mode mode;
|
||||
int align;
|
||||
rtx res;
|
||||
optab this_add_optab = add_optab;
|
||||
optab this_sub_optab = sub_optab;
|
||||
optab this_neg_optab = neg_optab;
|
||||
optab this_mul_optab = smul_optab;
|
||||
|
||||
if (binoptab == sdivv_optab)
|
||||
{
|
||||
this_add_optab = addv_optab;
|
||||
this_sub_optab = subv_optab;
|
||||
this_neg_optab = negv_optab;
|
||||
this_mul_optab = smulv_optab;
|
||||
}
|
||||
|
||||
/* Don't fetch these from memory more than once. */
|
||||
real0 = force_reg (submode, real0);
|
||||
@ -358,8 +382,8 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
|
||||
}
|
||||
else
|
||||
{
|
||||
temp1 = expand_abs (submode, real1, NULL_RTX, 1);
|
||||
temp2 = expand_abs (submode, imag1, NULL_RTX, 1);
|
||||
temp1 = expand_abs (submode, real1, NULL_RTX, unsignedp, 1);
|
||||
temp2 = expand_abs (submode, imag1, NULL_RTX, unsignedp, 1);
|
||||
}
|
||||
|
||||
if (temp1 == 0 || temp2 == 0)
|
||||
@ -385,13 +409,13 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
|
||||
|
||||
/* Calculate divisor. */
|
||||
|
||||
temp1 = expand_binop (submode, smul_optab, imag1, ratio,
|
||||
temp1 = expand_binop (submode, this_mul_optab, imag1, ratio,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (temp1 == 0)
|
||||
return 0;
|
||||
|
||||
divisor = expand_binop (submode, add_optab, temp1, real1,
|
||||
divisor = expand_binop (submode, this_add_optab, temp1, real1,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (divisor == 0)
|
||||
@ -405,13 +429,13 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
|
||||
|
||||
/* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)). */
|
||||
|
||||
imag_t = expand_binop (submode, smul_optab, real0, ratio,
|
||||
imag_t = expand_binop (submode, this_mul_optab, real0, ratio,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (imag_t == 0)
|
||||
return 0;
|
||||
|
||||
imag_t = expand_unop (submode, neg_optab, imag_t,
|
||||
imag_t = expand_unop (submode, this_neg_optab, imag_t,
|
||||
NULL_RTX, unsignedp);
|
||||
|
||||
if (real_t == 0 || imag_t == 0)
|
||||
@ -422,22 +446,22 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
|
||||
/* Compute (a+ib)/(c+id) as
|
||||
(a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)). */
|
||||
|
||||
temp1 = expand_binop (submode, smul_optab, imag0, ratio,
|
||||
temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (temp1 == 0)
|
||||
return 0;
|
||||
|
||||
real_t = expand_binop (submode, add_optab, temp1, real0,
|
||||
real_t = expand_binop (submode, this_add_optab, temp1, real0,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
temp1 = expand_binop (submode, smul_optab, real0, ratio,
|
||||
temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (temp1 == 0)
|
||||
return 0;
|
||||
|
||||
imag_t = expand_binop (submode, sub_optab, imag0, temp1,
|
||||
imag_t = expand_binop (submode, this_sub_optab, imag0, temp1,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (real_t == 0 || imag_t == 0)
|
||||
@ -490,13 +514,13 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
|
||||
|
||||
/* Calculate divisor. */
|
||||
|
||||
temp1 = expand_binop (submode, smul_optab, real1, ratio,
|
||||
temp1 = expand_binop (submode, this_mul_optab, real1, ratio,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (temp1 == 0)
|
||||
return 0;
|
||||
|
||||
divisor = expand_binop (submode, add_optab, temp1, imag1,
|
||||
divisor = expand_binop (submode, this_add_optab, temp1, imag1,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (divisor == 0)
|
||||
@ -508,10 +532,10 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
|
||||
{
|
||||
/* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */
|
||||
|
||||
real_t = expand_binop (submode, smul_optab, real0, ratio,
|
||||
real_t = expand_binop (submode, this_mul_optab, real0, ratio,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
imag_t = expand_unop (submode, neg_optab, real0,
|
||||
imag_t = expand_unop (submode, this_neg_optab, real0,
|
||||
NULL_RTX, unsignedp);
|
||||
|
||||
if (real_t == 0 || imag_t == 0)
|
||||
@ -522,22 +546,22 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
|
||||
/* Compute (a+ib)/(c+id) as
|
||||
(a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d). */
|
||||
|
||||
temp1 = expand_binop (submode, smul_optab, real0, ratio,
|
||||
temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (temp1 == 0)
|
||||
return 0;
|
||||
|
||||
real_t = expand_binop (submode, add_optab, temp1, imag0,
|
||||
real_t = expand_binop (submode, this_add_optab, temp1, imag0,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
temp1 = expand_binop (submode, smul_optab, imag0, ratio,
|
||||
temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (temp1 == 0)
|
||||
return 0;
|
||||
|
||||
imag_t = expand_binop (submode, sub_optab, temp1, real0,
|
||||
imag_t = expand_binop (submode, this_sub_optab, temp1, real0,
|
||||
NULL_RTX, unsignedp, methods);
|
||||
|
||||
if (real_t == 0 || imag_t == 0)
|
||||
@ -1491,7 +1515,9 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
|
||||
else if (imag0)
|
||||
res = imag0;
|
||||
else if (binoptab->code == MINUS)
|
||||
res = expand_unop (submode, neg_optab, imag1, imagr, unsignedp);
|
||||
res = expand_unop (submode,
|
||||
binoptab == subv_optab ? negv_optab : neg_optab,
|
||||
imag1, imagr, unsignedp);
|
||||
else
|
||||
res = imag1;
|
||||
|
||||
@ -1525,8 +1551,10 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
|
||||
if (temp1 == 0 || temp2 == 0)
|
||||
break;
|
||||
|
||||
res = expand_binop (submode, sub_optab, temp1, temp2,
|
||||
realr, unsignedp, methods);
|
||||
res = (expand_binop
|
||||
(submode,
|
||||
binoptab == smulv_optab ? subv_optab : sub_optab,
|
||||
temp1, temp2, realr, unsignedp, methods));
|
||||
|
||||
if (res == 0)
|
||||
break;
|
||||
@ -1542,8 +1570,10 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
|
||||
if (temp1 == 0 || temp2 == 0)
|
||||
break;
|
||||
|
||||
res = expand_binop (submode, add_optab, temp1, temp2,
|
||||
imagr, unsignedp, methods);
|
||||
res = (expand_binop
|
||||
(submode,
|
||||
binoptab == smulv_optab ? addv_optab : add_optab,
|
||||
temp1, temp2, imagr, unsignedp, methods));
|
||||
|
||||
if (res == 0)
|
||||
break;
|
||||
@ -2120,7 +2150,7 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
|
||||
}
|
||||
|
||||
/* Open-code the complex negation operation. */
|
||||
else if (unoptab == neg_optab
|
||||
else if (unoptab->code == NEG
|
||||
&& (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
|
||||
{
|
||||
rtx target_piece;
|
||||
@ -2231,11 +2261,13 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
|
||||
|
||||
/* If there is no negate operation, try doing a subtract from zero.
|
||||
The US Software GOFAST library needs this. */
|
||||
if (unoptab == neg_optab)
|
||||
if (unoptab->code == NEG)
|
||||
{
|
||||
rtx temp;
|
||||
temp = expand_binop (mode, sub_optab, CONST0_RTX (mode), op0,
|
||||
target, unsignedp, OPTAB_LIB_WIDEN);
|
||||
temp = expand_binop (mode,
|
||||
unoptab == negv_optab ? subv_optab : sub_optab,
|
||||
CONST0_RTX (mode), op0,
|
||||
target, unsignedp, OPTAB_LIB_WIDEN);
|
||||
if (temp)
|
||||
return temp;
|
||||
}
|
||||
@ -2253,16 +2285,21 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
|
||||
*/
|
||||
|
||||
rtx
|
||||
expand_abs (mode, op0, target, safe)
|
||||
expand_abs (mode, op0, target, result_unsignedp, safe)
|
||||
enum machine_mode mode;
|
||||
rtx op0;
|
||||
rtx target;
|
||||
int result_unsignedp;
|
||||
int safe;
|
||||
{
|
||||
rtx temp, op1;
|
||||
|
||||
if (! flag_trapv)
|
||||
result_unsignedp = 1;
|
||||
|
||||
/* First try to do it with a special abs instruction. */
|
||||
temp = expand_unop (mode, abs_optab, op0, target, 0);
|
||||
temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
|
||||
op0, target, 0);
|
||||
if (temp != 0)
|
||||
return temp;
|
||||
|
||||
@ -2298,8 +2335,8 @@ expand_abs (mode, op0, target, safe)
|
||||
temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
|
||||
OPTAB_LIB_WIDEN);
|
||||
if (temp != 0)
|
||||
temp = expand_binop (mode, sub_optab, temp, extended, target, 0,
|
||||
OPTAB_LIB_WIDEN);
|
||||
temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
|
||||
temp, extended, target, 0, OPTAB_LIB_WIDEN);
|
||||
|
||||
if (temp != 0)
|
||||
return temp;
|
||||
@ -2335,7 +2372,8 @@ expand_abs (mode, op0, target, safe)
|
||||
do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
|
||||
NULL_RTX, 0, NULL_RTX, op1);
|
||||
|
||||
op0 = expand_unop (mode, neg_optab, target, target, 0);
|
||||
op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
|
||||
target, target, 0);
|
||||
if (op0 != target)
|
||||
emit_move_insn (target, op0);
|
||||
emit_label (op1);
|
||||
@ -2365,6 +2403,7 @@ expand_complex_abs (mode, op0, target, unsignedp)
|
||||
rtx entry_last = get_last_insn ();
|
||||
rtx last;
|
||||
rtx pat;
|
||||
optab this_abs_optab;
|
||||
|
||||
/* Find the correct mode for the real and imaginary parts. */
|
||||
enum machine_mode submode
|
||||
@ -2387,9 +2426,13 @@ expand_complex_abs (mode, op0, target, unsignedp)
|
||||
if (target)
|
||||
target = protect_from_queue (target, 1);
|
||||
|
||||
if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
|
||||
this_abs_optab = ! unsignedp && flag_trapv
|
||||
&& (GET_MODE_CLASS(mode) == MODE_INT)
|
||||
? absv_optab : abs_optab;
|
||||
|
||||
if (this_abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
|
||||
{
|
||||
int icode = (int) abs_optab->handlers[(int) mode].insn_code;
|
||||
int icode = (int) this_abs_optab->handlers[(int) mode].insn_code;
|
||||
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
|
||||
rtx xop0 = op0;
|
||||
|
||||
@ -2414,10 +2457,12 @@ expand_complex_abs (mode, op0, target, unsignedp)
|
||||
if (pat)
|
||||
{
|
||||
if (GET_CODE (pat) == SEQUENCE
|
||||
&& ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX))
|
||||
&& ! add_equal_note (pat, temp, this_abs_optab->code, xop0,
|
||||
NULL_RTX))
|
||||
{
|
||||
delete_insns_since (last);
|
||||
return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp);
|
||||
return expand_unop (mode, this_abs_optab, op0, NULL_RTX,
|
||||
unsignedp);
|
||||
}
|
||||
|
||||
emit_insn (pat);
|
||||
@ -2433,7 +2478,8 @@ expand_complex_abs (mode, op0, target, unsignedp)
|
||||
for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
|
||||
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
|
||||
{
|
||||
if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
|
||||
if (this_abs_optab->handlers[(int) wider_mode].insn_code
|
||||
!= CODE_FOR_nothing)
|
||||
{
|
||||
rtx xop0 = op0;
|
||||
|
||||
@ -2483,7 +2529,7 @@ expand_complex_abs (mode, op0, target, unsignedp)
|
||||
}
|
||||
|
||||
/* Now try a library call in this mode. */
|
||||
if (abs_optab->handlers[(int) mode].libfunc)
|
||||
if (this_abs_optab->handlers[(int) mode].libfunc)
|
||||
{
|
||||
rtx insns;
|
||||
rtx value;
|
||||
@ -2499,7 +2545,7 @@ expand_complex_abs (mode, op0, target, unsignedp)
|
||||
|
||||
target = gen_reg_rtx (submode);
|
||||
emit_libcall_block (insns, target, value,
|
||||
gen_rtx_fmt_e (abs_optab->code, mode, op0));
|
||||
gen_rtx_fmt_e (this_abs_optab->code, mode, op0));
|
||||
|
||||
return target;
|
||||
}
|
||||
@ -2509,9 +2555,9 @@ expand_complex_abs (mode, op0, target, unsignedp)
|
||||
for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
|
||||
wider_mode = GET_MODE_WIDER_MODE (wider_mode))
|
||||
{
|
||||
if ((abs_optab->handlers[(int) wider_mode].insn_code
|
||||
if ((this_abs_optab->handlers[(int) wider_mode].insn_code
|
||||
!= CODE_FOR_nothing)
|
||||
|| abs_optab->handlers[(int) wider_mode].libfunc)
|
||||
|| this_abs_optab->handlers[(int) wider_mode].libfunc)
|
||||
{
|
||||
rtx xop0 = op0;
|
||||
|
||||
@ -4528,13 +4574,17 @@ init_optabs ()
|
||||
#endif
|
||||
|
||||
add_optab = init_optab (PLUS);
|
||||
addv_optab = init_optab (PLUS);
|
||||
sub_optab = init_optab (MINUS);
|
||||
subv_optab = init_optab (MINUS);
|
||||
smul_optab = init_optab (MULT);
|
||||
smulv_optab = init_optab (MULT);
|
||||
smul_highpart_optab = init_optab (UNKNOWN);
|
||||
umul_highpart_optab = init_optab (UNKNOWN);
|
||||
smul_widen_optab = init_optab (UNKNOWN);
|
||||
umul_widen_optab = init_optab (UNKNOWN);
|
||||
sdiv_optab = init_optab (DIV);
|
||||
sdivv_optab = init_optab (DIV);
|
||||
sdivmod_optab = init_optab (UNKNOWN);
|
||||
udiv_optab = init_optab (UDIV);
|
||||
udivmod_optab = init_optab (UNKNOWN);
|
||||
@ -4560,7 +4610,9 @@ init_optabs ()
|
||||
ucmp_optab = init_optab (UNKNOWN);
|
||||
tst_optab = init_optab (UNKNOWN);
|
||||
neg_optab = init_optab (NEG);
|
||||
negv_optab = init_optab (NEG);
|
||||
abs_optab = init_optab (ABS);
|
||||
absv_optab = init_optab (ABS);
|
||||
one_cmpl_optab = init_optab (NOT);
|
||||
ffs_optab = init_optab (FFS);
|
||||
sqrt_optab = init_optab (SQRT);
|
||||
@ -4595,11 +4647,18 @@ init_optabs ()
|
||||
/* Initialize the optabs with the names of the library functions. */
|
||||
init_integral_libfuncs (add_optab, "add", '3');
|
||||
init_floating_libfuncs (add_optab, "add", '3');
|
||||
init_integral_libfuncs (addv_optab, "addv", '3');
|
||||
init_floating_libfuncs (addv_optab, "add", '3');
|
||||
init_integral_libfuncs (sub_optab, "sub", '3');
|
||||
init_floating_libfuncs (sub_optab, "sub", '3');
|
||||
init_integral_libfuncs (subv_optab, "subv", '3');
|
||||
init_floating_libfuncs (subv_optab, "sub", '3');
|
||||
init_integral_libfuncs (smul_optab, "mul", '3');
|
||||
init_floating_libfuncs (smul_optab, "mul", '3');
|
||||
init_integral_libfuncs (smulv_optab, "mulv", '3');
|
||||
init_floating_libfuncs (smulv_optab, "mul", '3');
|
||||
init_integral_libfuncs (sdiv_optab, "div", '3');
|
||||
init_integral_libfuncs (sdivv_optab, "divv", '3');
|
||||
init_integral_libfuncs (udiv_optab, "udiv", '3');
|
||||
init_integral_libfuncs (sdivmod_optab, "divmod", '4');
|
||||
init_integral_libfuncs (udivmod_optab, "udivmod", '4');
|
||||
@ -4621,6 +4680,8 @@ init_optabs ()
|
||||
init_integral_libfuncs (umax_optab, "umax", '3');
|
||||
init_integral_libfuncs (neg_optab, "neg", '2');
|
||||
init_floating_libfuncs (neg_optab, "neg", '2');
|
||||
init_integral_libfuncs (negv_optab, "negv", '2');
|
||||
init_floating_libfuncs (negv_optab, "neg", '2');
|
||||
init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
|
||||
init_integral_libfuncs (ffs_optab, "ffs", '2');
|
||||
|
||||
|
@ -947,6 +947,8 @@ typedef struct
|
||||
}
|
||||
lang_independent_options;
|
||||
|
||||
int flag_trapv = 0;
|
||||
|
||||
/* Add or remove a leading underscore from user symbols. */
|
||||
int flag_leading_underscore = -1;
|
||||
|
||||
@ -1145,6 +1147,8 @@ lang_independent_options f_options[] =
|
||||
"Report time taken by each compiler pass at end of run"},
|
||||
{"mem-report", &mem_report, 1,
|
||||
"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. */
|
||||
|
@ -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. */
|
||||
#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 FUNCTION_DECL means that the function has been compiled.
|
||||
This is interesting in an inline function, since it might not need
|
||||
|
Loading…
Reference in New Issue
Block a user