This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][no-undefined-overflow] Fix compile torture
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 6 Mar 2009 10:36:32 +0100 (CET)
- Subject: [PATCH][no-undefined-overflow] Fix compile torture
This fixes the compile torture and most of the OMP ICEs.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to the
branch.
Richard.
2009-03-06 Richard Guenther <rguenther@suse.de>
* fold-const.c (fold_binary): Enable pointer re-association
for POINTER_PLUSNV_EXPR.
* gimplify.c (gimplify_expr): Handle POINTER_PLUSNV_EXPR.
(gimplify_omp_for): Handle *NV_EXPR.
* convert.c (convert_to_integer): Handle PLUSNV_EXPR and
MINUSNV_EXPR in narrowing properly. Remove use of
TYPE_OVERFLOW_WRAPS.
* omp-low.c (extract_omp_for_data): Handle *NV_EXPR.
Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c.orig 2009-03-05 17:30:39.000000000 +0100
--- gcc/fold-const.c 2009-03-05 17:30:41.000000000 +0100
*************** fold_binary (enum tree_code code, tree t
*** 10333,10348 ****
return non_lvalue (fold_convert (type, arg0));
}
- /* ??? Auditing required. */
- if (code == MINUSNV_EXPR)
- return NULL_TREE;
-
/* Pointer simplifications for subtraction, simple reassociations. */
if (POINTER_TYPE_P (TREE_TYPE (arg1)) && POINTER_TYPE_P (TREE_TYPE (arg0)))
{
/* (PTR0 p+ A) - (PTR1 p+ B) -> (PTR0 - PTR1) + (A - B) */
! if (TREE_CODE (arg0) == POINTER_PLUS_EXPR
! && TREE_CODE (arg1) == POINTER_PLUS_EXPR)
{
tree arg00 = fold_convert (type, TREE_OPERAND (arg0, 0));
tree arg01 = fold_convert (type, TREE_OPERAND (arg0, 1));
--- 10333,10344 ----
return non_lvalue (fold_convert (type, arg0));
}
/* Pointer simplifications for subtraction, simple reassociations. */
if (POINTER_TYPE_P (TREE_TYPE (arg1)) && POINTER_TYPE_P (TREE_TYPE (arg0)))
{
/* (PTR0 p+ A) - (PTR1 p+ B) -> (PTR0 - PTR1) + (A - B) */
! if (POINTER_PLUS_EXPR_P (arg0)
! && POINTER_PLUS_EXPR_P (arg1))
{
tree arg00 = fold_convert (type, TREE_OPERAND (arg0, 0));
tree arg01 = fold_convert (type, TREE_OPERAND (arg0, 1));
*************** fold_binary (enum tree_code code, tree t
*** 10352,10367 ****
fold_build2 (MINUS_EXPR, type, arg00, arg10),
fold_build2 (MINUS_EXPR, type, arg01, arg11));
}
! /* (PTR0 p+ A) - PTR1 -> (PTR0 - PTR1) + A, assuming PTR0 - PTR1 simplifies. */
! else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
{
tree arg00 = fold_convert (type, TREE_OPERAND (arg0, 0));
tree arg01 = fold_convert (type, TREE_OPERAND (arg0, 1));
! tree tmp = fold_binary (MINUS_EXPR, type, arg00, fold_convert (type, arg1));
if (tmp)
return fold_build2 (PLUS_EXPR, type, tmp, arg01);
}
}
/* A - (-B) -> A + B */
if (TREE_CODE (arg1) == NEGATE_EXPR)
return fold_build2 (PLUS_EXPR, type, op0,
--- 10348,10370 ----
fold_build2 (MINUS_EXPR, type, arg00, arg10),
fold_build2 (MINUS_EXPR, type, arg01, arg11));
}
! /* (PTR0 p+ A) - PTR1 -> (PTR0 - PTR1) + A, assuming
! PTR0 - PTR1 simplifies. */
! else if (POINTER_PLUS_EXPR_P (arg0))
{
tree arg00 = fold_convert (type, TREE_OPERAND (arg0, 0));
tree arg01 = fold_convert (type, TREE_OPERAND (arg0, 1));
! tree tmp = fold_binary (MINUS_EXPR, type, arg00,
! fold_convert (type, arg1));
if (tmp)
return fold_build2 (PLUS_EXPR, type, tmp, arg01);
}
}
+
+ /* ??? Auditing required. */
+ if (code == MINUSNV_EXPR)
+ return NULL_TREE;
+
/* A - (-B) -> A + B */
if (TREE_CODE (arg1) == NEGATE_EXPR)
return fold_build2 (PLUS_EXPR, type, op0,
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c.orig 2009-03-05 17:30:39.000000000 +0100
--- gcc/gimplify.c 2009-03-05 18:00:28.000000000 +0100
*************** gimplify_omp_for (tree *expr_p, gimple_s
*** 5885,5890 ****
--- 5885,5891 ----
switch (TREE_CODE (t))
{
case PLUS_EXPR:
+ case PLUSNV_EXPR:
if (TREE_OPERAND (t, 1) == decl)
{
TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
*************** gimplify_omp_for (tree *expr_p, gimple_s
*** 5894,5900 ****
--- 5895,5903 ----
/* Fallthru. */
case MINUS_EXPR:
+ case MINUSNV_EXPR:
case POINTER_PLUS_EXPR:
+ case POINTER_PLUSNV_EXPR:
gcc_assert (TREE_OPERAND (t, 0) == decl);
TREE_OPERAND (t, 0) = var;
break;
*************** gimplify_omp_for (tree *expr_p, gimple_s
*** 5922,5930 ****
gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
gcc_assert (TREE_OPERAND (t, 0) == var);
t = TREE_OPERAND (t, 1);
! gcc_assert (TREE_CODE (t) == PLUS_EXPR
! || TREE_CODE (t) == MINUS_EXPR
! || TREE_CODE (t) == POINTER_PLUS_EXPR);
gcc_assert (TREE_OPERAND (t, 0) == var);
t = build2 (TREE_CODE (t), TREE_TYPE (decl), decl,
TREE_OPERAND (t, 1));
--- 5925,5933 ----
gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
gcc_assert (TREE_OPERAND (t, 0) == var);
t = TREE_OPERAND (t, 1);
! gcc_assert (PLUS_EXPR_P (t)
! || MINUS_EXPR_P (t)
! || POINTER_PLUS_EXPR_P (t));
gcc_assert (TREE_OPERAND (t, 0) == var);
t = build2 (TREE_CODE (t), TREE_TYPE (decl), decl,
TREE_OPERAND (t, 1));
*************** gimplify_expr (tree *expr_p, gimple_seq
*** 6766,6771 ****
--- 6769,6775 ----
break;
case POINTER_PLUS_EXPR:
+ case POINTER_PLUSNV_EXPR:
/* Convert ((type *)A)+offset into &A->field_of_type_and_offset.
The second is gimple immediate saving a need for extra statement.
*/
Index: gcc/convert.c
===================================================================
*** gcc/convert.c.orig 2009-03-05 17:30:39.000000000 +0100
--- gcc/convert.c 2009-03-05 17:30:41.000000000 +0100
*************** convert_to_integer (tree type, tree expr
*** 639,645 ****
--- 639,647 ----
}
case PLUS_EXPR:
+ case PLUSNV_EXPR:
case MINUS_EXPR:
+ case MINUSNV_EXPR:
case BIT_AND_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
*************** convert_to_integer (tree type, tree expr
*** 686,704 ****
|| ex_form == RSHIFT_EXPR
|| ex_form == LROTATE_EXPR
|| ex_form == RROTATE_EXPR))
! || ex_form == LSHIFT_EXPR
! /* If we have !flag_wrapv, and either ARG0 or
! ARG1 is of a signed type, we have to do
! PLUS_EXPR or MINUS_EXPR in an unsigned
! type. Otherwise, we would introduce
! signed-overflow undefinedness. */
! || ((!TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))
! || !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg1)))
! && (ex_form == PLUS_EXPR
! || ex_form == MINUS_EXPR)))
typex = unsigned_type_for (typex);
else
typex = signed_type_for (typex);
return convert (type,
fold_build2 (ex_form, typex,
convert (typex, arg0),
--- 688,701 ----
|| ex_form == RSHIFT_EXPR
|| ex_form == LROTATE_EXPR
|| ex_form == RROTATE_EXPR))
! || ex_form == LSHIFT_EXPR)
typex = unsigned_type_for (typex);
else
typex = signed_type_for (typex);
+ /* Even if the original expression didn't overflow
+ the one in a different type might, so strip nv
+ qualification here. */
+ ex_form = strip_nv (ex_form);
return convert (type,
fold_build2 (ex_form, typex,
convert (typex, arg0),
Index: gcc/omp-low.c
===================================================================
*** gcc/omp-low.c.orig 2009-03-05 16:12:02.000000000 +0100
--- gcc/omp-low.c 2009-03-05 18:02:21.000000000 +0100
*************** extract_omp_for_data (gimple for_stmt, s
*** 334,343 ****
--- 334,346 ----
switch (TREE_CODE (t))
{
case PLUS_EXPR:
+ case PLUSNV_EXPR:
case POINTER_PLUS_EXPR:
+ case POINTER_PLUSNV_EXPR:
loop->step = TREE_OPERAND (t, 1);
break;
case MINUS_EXPR:
+ case MINUSNV_EXPR:
loop->step = TREE_OPERAND (t, 1);
loop->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (loop->step),
loop->step);