OSDN Git Service

Adding new option -ftrapv.
authorcchavva <cchavva@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 18 Oct 2000 21:33:41 +0000 (21:33 +0000)
committercchavva <cchavva@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 18 Oct 2000 21:33:41 +0000 (21:33 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@36942 138bc75d-0d04-0410-961f-82ee72b054a4

13 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/expmed.c
gcc/expr.c
gcc/expr.h
gcc/flags.h
gcc/genopinit.c
gcc/invoke.texi
gcc/libgcc2.c
gcc/loop.c
gcc/optabs.c
gcc/toplev.c
gcc/tree.h

index 605ab53..61cd3ae 100644 (file)
@@ -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>
 
index 7f9fcfe..595c62e 100644 (file)
@@ -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
index 69761b9..bdd9fa7 100644 (file)
@@ -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)
index 01c1fb6..84e574d 100644 (file)
@@ -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)
     {
index ffa7d86..8cb2836 100644 (file)
@@ -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));
index 7fec383..dec686d 100644 (file)
@@ -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).  */
 
index 993c347..9aeaee7 100644 (file)
@@ -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));
index 19ae2a0..73dd1d9 100644 (file)
@@ -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.
index 7e8eaf7..00a50e6 100644 (file)
@@ -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;
+} 
+\f
+#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
+\f
+#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
+\f
+#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
+\f
+#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
+\f
+#ifdef L_negvsi2
+SItype
+__negvsi2 (SItype a)
+{
+   SItype w;
+
+   w  = -a;
+
+  if (a >= 0 ? w > 0 : w < 0)
+    abort ();
+
+   return w;
+}
+#endif
+\f
+#ifdef L_negvdi2
+DItype
+__negvdi2 (DItype a)
+{
+   DItype w;
+
+   w  = -a;
+
+  if (a >= 0 ? w > 0 : w < 0)
+    abort ();
+
+   return w;
+}
+#endif
+\f
+#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
+\f
+#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
+\f
+#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
+\f
 DWtype
 __negdi2 (DWtype u)
 {
index 977bbd2..23ee292 100644 (file)
@@ -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 ();
 
index 5dbbcaa..16433a9 100644 (file)
@@ -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');
 
index 6613963..1dfa7f5 100644 (file)
@@ -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.  */
index 2ec1274..68ccbbf 100644 (file)
@@ -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