This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][no-undefined-overflow][2/2] Basic C frontend support
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 5 Mar 2009 15:55:24 +0100 (CET)
- Subject: [PATCH][no-undefined-overflow][2/2] Basic C frontend support
This enables the C frontend to generate the *NV_EXPR variants for
arithmetic involving undefined overflow (thus, signed and not flag_wrapv).
For pointer arithmetic flag_wrapv doesn't apply (does it?) and I'm not
sure about flag_strict_overflow (what's the difference to flag_wrapv
again?).
Anyway - I expect that this patch gets reverted later and replaced by
proper C frontend support from the frontend maintainers.
Bootstrapped and tested on x86_64-unknown-linux-gnu (C only), applied
to the branch.
Richard.
2009-03-05 Richard Guenther <rguenther@suse.de>
* c-common.c (pointer_int_sum): Use *NV_EXPR codes for
pointer arithmetic.
* c-typeck.c (build_unary_op): Use NEGATENV_EXPR if
signed arithmetic has undefined overflow.
(build_binary_op): Handle *NV_EXPR for recursive invocations.
If signed arithmetic has undefined overflow use
PLUSNV_EXPR, MINUSNV_EXPR and MULTNV_EXPR.
* c-omp.c (c_finish_omp_for): Deal with *NV_EXPR for increments.
Index: trunk/gcc/c-common.c
===================================================================
*** trunk.orig/gcc/c-common.c 2009-03-05 14:58:05.000000000 +0100
--- trunk/gcc/c-common.c 2009-03-05 15:42:12.000000000 +0100
*************** pointer_int_sum (enum tree_code resultco
*** 3287,3300 ****
type for the pointer operation. */
intop = convert (sizetype,
build_binary_op (EXPR_LOCATION (intop),
! MULT_EXPR, intop,
convert (TREE_TYPE (intop), size_exp), 1));
/* Create the sum or difference. */
if (resultcode == MINUS_EXPR)
! intop = fold_build1 (NEGATE_EXPR, sizetype, intop);
! ret = fold_build2 (POINTER_PLUS_EXPR, result_type, ptrop, intop);
fold_undefer_and_ignore_overflow_warnings ();
--- 3287,3300 ----
type for the pointer operation. */
intop = convert (sizetype,
build_binary_op (EXPR_LOCATION (intop),
! MULTNV_EXPR, intop,
convert (TREE_TYPE (intop), size_exp), 1));
/* Create the sum or difference. */
if (resultcode == MINUS_EXPR)
! intop = fold_build1 (NEGATENV_EXPR, sizetype, intop);
! ret = fold_build2 (POINTER_PLUSNV_EXPR, result_type, ptrop, intop);
fold_undefer_and_ignore_overflow_warnings ();
Index: trunk/gcc/c-typeck.c
===================================================================
*** trunk.orig/gcc/c-typeck.c 2009-03-05 14:58:05.000000000 +0100
--- trunk/gcc/c-typeck.c 2009-03-05 15:42:12.000000000 +0100
*************** build_unary_op (location_t location,
*** 3260,3265 ****
--- 3260,3272 ----
if (argtype == 0)
argtype = TREE_TYPE (arg);
+
+ if (!flag_wrapv
+ && TREE_CODE (argtype) == INTEGER_TYPE
+ && !TYPE_UNSIGNED (argtype)
+ && code == NEGATE_EXPR)
+ code = NEGATENV_EXPR;
+
ret = require_constant_value ? fold_build1_initializer (code, argtype, arg)
: fold_build1 (code, argtype, arg);
return_build_unary_op:
*************** build_binary_op (location_t location, en
*** 8104,8109 ****
--- 8111,8117 ----
switch (code)
{
case PLUS_EXPR:
+ case PLUSNV_EXPR:
/* Handle the pointer + int case. */
if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
*************** build_binary_op (location_t location, en
*** 8120,8125 ****
--- 8128,8134 ----
break;
case MINUS_EXPR:
+ case MINUSNV_EXPR:
/* Subtraction of two similar pointers.
We must subtract them as integers, then divide by object size. */
if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
*************** build_binary_op (location_t location, en
*** 8139,8144 ****
--- 8148,8154 ----
break;
case MULT_EXPR:
+ case MULTNV_EXPR:
common = 1;
break;
*************** build_binary_op (location_t location, en
*** 8563,8568 ****
--- 8573,8590 ----
if (build_type == NULL_TREE)
build_type = result_type;
+ if (TREE_CODE (build_type) == INTEGER_TYPE
+ && !TYPE_UNSIGNED (build_type)
+ && !flag_wrapv)
+ {
+ if (resultcode == PLUS_EXPR)
+ resultcode = PLUSNV_EXPR;
+ else if (resultcode == MINUS_EXPR)
+ resultcode = MINUSNV_EXPR;
+ else if (resultcode == MULT_EXPR)
+ resultcode = MULTNV_EXPR;
+ }
+
/* Treat expressions in initializers specially as they can't trap. */
ret = require_constant_value ? fold_build2_initializer (resultcode,
build_type,
Index: trunk/gcc/c-omp.c
===================================================================
*** trunk.orig/gcc/c-omp.c 2009-01-29 17:14:52.000000000 +0100
--- trunk/gcc/c-omp.c 2009-03-05 15:44:09.000000000 +0100
*************** c_finish_omp_for (location_t locus, tree
*** 375,387 ****
break;
if (TREE_OPERAND (incr, 1) == decl)
break;
! if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
&& (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
|| TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
incr_ok = true;
! else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
! || (TREE_CODE (TREE_OPERAND (incr, 1))
! == POINTER_PLUS_EXPR))
&& TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
incr_ok = true;
else
--- 375,386 ----
break;
if (TREE_OPERAND (incr, 1) == decl)
break;
! if (PLUS_EXPR_P (TREE_OPERAND (incr, 1))
&& (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
|| TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
incr_ok = true;
! else if ((MINUS_EXPR_P (TREE_OPERAND (incr, 1))
! || POINTER_PLUS_EXPR_P (TREE_OPERAND (incr, 1)))
&& TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
incr_ok = true;
else