This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] New command line option -fwrapv (take 2)


This is an update of my earlier patch to add the "-fwrapv" command
line option to GCC, to specify wrap-around two's complement semantics
on signed arithmetic overflow.

Now that extract_muldiv_1 has been fixed to re-enable one of GCC's
optimizations that rely on undefined arithmetic overflow, its possible
to come up with a testcase to check that "-fwrapv" is actually working.


Rather than just post a test case, I've also updated the patch against
current CVS, and confirmed that it still bootstraps on i686-pc-linux-gnu,
all languages except Ada and treelang, and introduces no new failures
in the test suite.


Ok for mainline?  Would it be worthwhile to also add an almost identical
"-fno-wrapv" testcase, that just replaces " == " with " != " to check
that this optimization gets applied with undefined overflow semantics?
This would have caught the recent patch that accidentally disabled it.



2003-03-24  Roger Sayle  <roger at eyesopen dot com>

	* flags.h (flag_wrapv): New flag controlling overflow semantics.
	* toplev.c (flag_wrapv): Declare the variable with default false.
	(lang_independent_options): New option "-fwrapv" to set the above.

	* fold-const.c (extract_muldiv_1): Disable optimization of (2*x)/2
	as x, when signed arithmetic overflow wraps around.
	(fold): Optimize "-A - B" as "-B - A" if overflow wraps around.
	* loop.c (basic_induction_var): Ignore BIVs that rely on undefined
	overflow when flag_wrapv is true.

	* java/lang.c (java_init_options): Prescribe wrap-around two's
	complement arithmetic overflow by setting flag_wrapv.

	* doc/invoke.texi: Document new -fwrapv command line option.
	* doc/c-tree.texi: Mention that the overflow semantics of
	NEGATE_EXPR, PLUS_EXPR, MINUS_EXPR and MULT_EXPR is dependent
	upon both flag_wrapv and flag_trapv.

	* gcc.dg/fwrapv.c: New test case.


Index: flags.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flags.h,v
retrieving revision 1.102
diff -c -3 -p -r1.102 flags.h
*** flags.h	9 Mar 2003 00:31:00 -0000	1.102
--- flags.h	24 Mar 2003 18:34:17 -0000
*************** extern int frame_pointer_needed;
*** 586,591 ****
--- 586,594 ----
     for PLUS / SUB / MULT.  */
  extern int flag_trapv;

+ /* Nonzero if the signed arithmetic overflow should wrap around.  */
+ extern int flag_wrapv;
+
  /* Value of the -G xx switch, and whether it was passed or not.  */
  extern int g_switch_value;
  extern int g_switch_set;
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.736
diff -c -3 -p -r1.736 toplev.c
*** toplev.c	20 Mar 2003 16:43:18 -0000	1.736
--- toplev.c	24 Mar 2003 18:34:18 -0000
*************** typedef struct
*** 981,988 ****
--- 981,992 ----
  }
  lang_independent_options;

+ /* Nonzero if signed arithmetic overflow should trap.  */
  int flag_trapv = 0;

+ /* Nonzero if signed arithmetic overflow should wrap around.  */
+ int flag_wrapv = 0;
+
  /* Add or remove a leading underscore from user symbols.  */
  int flag_leading_underscore = -1;

*************** static const lang_independent_options f_
*** 1224,1229 ****
--- 1228,1235 ----
     N_("Report on permanent memory allocation at end of run") },
    { "trapv", &flag_trapv, 1,
     N_("Trap for signed overflow in addition / subtraction / multiplication") },
+   { "wrapv", &flag_wrapv, 1,
+    N_("Assume signed arithmetic overflow wraps around") },
    { "new-ra", &flag_new_regalloc, 1,
     N_("Use graph coloring register allocation.") },
  };
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.241
diff -c -3 -p -r1.241 fold-const.c
*** fold-const.c	21 Mar 2003 00:03:24 -0000	1.241
--- fold-const.c	24 Mar 2003 18:34:19 -0000
*************** extract_muldiv_1 (t, c, code, wide_type)
*** 4367,4372 ****
--- 4367,4373 ----
  	 overflowed.  */
        if ((! TREE_UNSIGNED (ctype)
  	   || (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype)))
+ 	  && ! flag_wrapv
  	  && ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR)
  	      || (tcode == MULT_EXPR
  		  && code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR
*************** fold (expr)
*** 5666,5672 ****
  	return fold (build (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
        /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
        if (TREE_CODE (arg0) == NEGATE_EXPR
! 	  && FLOAT_TYPE_P (type)
  	  && negate_expr_p (arg1)
  	  && (! TREE_SIDE_EFFECTS (arg0) || TREE_CONSTANT (arg1))
  	  && (! TREE_SIDE_EFFECTS (arg1) || TREE_CONSTANT (arg0)))
--- 5667,5674 ----
  	return fold (build (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
        /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
        if (TREE_CODE (arg0) == NEGATE_EXPR
! 	  && (FLOAT_TYPE_P (type)
! 	      || (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv))
  	  && negate_expr_p (arg1)
  	  && (! TREE_SIDE_EFFECTS (arg0) || TREE_CONSTANT (arg1))
  	  && (! TREE_SIDE_EFFECTS (arg1) || TREE_CONSTANT (arg0)))
Index: loop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop.c,v
retrieving revision 1.448
diff -c -3 -p -r1.448 loop.c
*** loop.c	15 Mar 2003 22:51:33 -0000	1.448
--- loop.c	24 Mar 2003 18:34:21 -0000
*************** basic_induction_var (loop, x, mode, dest
*** 6413,6418 ****
--- 6413,6421 ----
  	return 0;

      case SIGN_EXTEND:
+       /* Ignore this BIV if signed arithmetic overflow is defined.  */
+       if (flag_wrapv)
+ 	return 0;
        return basic_induction_var (loop, XEXP (x, 0), GET_MODE (XEXP (x, 0)),
  				  dest_reg, p, inc_val, mult_val, location);

Index: java/lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/lang.c,v
retrieving revision 1.123
diff -c -3 -p -r1.123 lang.c
*** java/lang.c	19 Mar 2003 20:34:09 -0000	1.123
--- java/lang.c	24 Mar 2003 18:34:21 -0000
*************** java_init_options (void)
*** 740,745 ****
--- 740,748 ----

    /* In Java floating point operations never trap.  */
    flag_trapping_math = 0;
+
+   /* In Java arithmetic overflow always wraps around.  */
+   flag_wrapv = 1;
  }

  static bool
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.255
diff -c -3 -p -r1.255 invoke.texi
*** doc/invoke.texi	11 Mar 2003 06:42:20 -0000	1.255
--- doc/invoke.texi	24 Mar 2003 18:34:24 -0000
*************** in the following sections.
*** 716,722 ****
  -fargument-alias  -fargument-noalias @gol
  -fargument-noalias-global  -fleading-underscore @gol
  -ftls-model= at var{model} @gol
! -ftrapv -fbounds-check}
  @end table

  @menu
--- 716,722 ----
  -fargument-alias  -fargument-noalias @gol
  -fargument-noalias-global  -fleading-underscore @gol
  -ftls-model= at var{model} @gol
! -ftrapv -fwrapv -fbounds-check}
  @end table

  @menu
*************** this option defaults to true and false r
*** 10819,10824 ****
--- 10819,10832 ----
  @opindex ftrapv
  This option generates traps for signed overflow on addition, subtraction,
  multiplication operations.
+
+ @item -fwrapv
+ @opindex fwrapv
+ This option instructs the compiler to assume that signed arithmetic
+ overflow of addition, subtraction and multiplication wraps around
+ using twos-complement representation.  This flag enables some optimzations
+ and disables other.  This option is enabled by default for the Java
+ front-end, as required by the Java language specification.

  @item -fexceptions
  @opindex fexceptions
Index: doc/c-tree.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/c-tree.texi,v
retrieving revision 1.40
diff -c -3 -p -r1.40 c-tree.texi
*** doc/c-tree.texi	7 Feb 2003 14:44:19 -0000	1.40
--- doc/c-tree.texi	24 Mar 2003 18:34:24 -0000
*************** These nodes represent unary negation of
*** 1913,1918 ****
--- 1913,1921 ----
  integer and floating-point types.  The type of negation can be
  determined by looking at the type of the expression.

+ The behavior of this operation on signed arithmetic overflow is
+ controlled by the @code{flag_wrapv} and @code{flag_trapv} variables.
+
  @item BIT_NOT_EXPR
  These nodes represent bitwise complement, and will always have integral
  type.  The only operand is the value to be complemented.
*************** The result of a @code{TRUNC_DIV_EXPR} is
*** 2065,2070 ****
--- 2068,2076 ----
  The @code{TRUNC_MOD_EXPR} of two operands @code{a} and @code{b} is
  always @code{a - (a/b)*b} where the division is as if computed by a
  @code{TRUNC_DIV_EXPR}.
+
+ The behavior of these operations on signed arithmetic overflow is
+ controlled by the @code{flag_wrapv} and @code{flag_trapv} variables.

  @item ARRAY_REF
  These nodes represent array accesses.  The first operand is the array;


/* Copyright (C) 2003 Free Software Foundation.

   Test that the -fwrapv command line option is accepted and disables
   "unsafe" optimizations that rely on undefined arithmetic overflow.

   Written by Roger Sayle, 24th March 2003.  */

/* { dg-do run } */
/* { dg-options "-O2 -fwrapv" } */

#include <limits.h>

extern void abort ();

int test(int x)
{
  return (2*x)/2;
}

main()
{
  int x = INT_MAX;

  if (test(x) == x)
    abort ();
  return 0;
}


Roger
--
Roger Sayle,                         E-mail: roger at eyesopen dot com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]