This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][no-undefined-overflow][1/2] Basic middle-end support
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 5 Mar 2009 15:53:06 +0100 (CET)
- Subject: [PATCH][no-undefined-overflow][1/2] Basic middle-end support
It took me quite a while to dissect my work-in progress patch back
to a state that still bootstraps ...
So here is the initial enabling middle-end part. It introduces
NEGATENV_EXPR, PLUSNV_EXPR, MINUSNV_EXPR, MULTNV_EXPR and
POINTER_PLUSNV_EXPR and updates places to support constant-folding
and expansion. It also makes the middle-end macros
TYPE_OVERFLOW_WRAPS, TYPE_OVERFLOW_UNDEFINED and
POINTER_TYPE_OVERFLOW_UNDEFINED to always true, false, false
according to the general plan of no-undefined-overflow branch.
Bootstrapped and tested on x86_64-unknown-linux-gnu (C only) together
with patch [2/2] that enables C frontend support.
Some fun in the testresults, we have some vectorizer miscompiles
because of missed memory-reference re-construction... that'll go
away with re-instantiating the foldings.
Branched and applied there (branches/no-undefined-overflow).
Richard.
2009-03-05 Richard Guenther <rguenther@suse.de>
* expr.c (expand_expr_real_1): Handle POINTER_PLUSNV_EXPR,
PLUSNV_EXPR, MINUSNV_EXPR, MULTNV_EXPR and NEGATENV_EXPR.
* flags.h (TYPE_OVERFLOW_WRAPS): Define to always true.
(TYPE_OVERFLOW_UNDEFINED): Define to always false.
(POINTER_TYPE_OVERFLOW_UNDEFINED): Define to always false.
* optabs.c (optab_for_tree_code): Handle *NV_EXPR.
* tree-cfg.c (verify_gimple_assign_unary): Likewise.
(verify_gimple_assign_binary): Likewise.
* tree-inline.c (estimate_operator_cost): Likewise.
* tree-pretty-print.c (dump_generic_node): Likewise.
(op_code_prio): Likewise.
(op_symbol_code): Likewise.
* tree-ssa-structalias.c (find_func_aliases): Handle
POINTER_PLUSNV_EXPR.
* tree.c (build2_stat): Adjust checks.
(associative_tree_code): Add PLUSNV_EXPR and MULTNV_EXPR.
(commutative_tree_code): Add PLUSNV_EXPR and MULTNV_EXPR.
(undefined_overflow_used_p_1): New function.
* tree.def (PLUSNV_EXPR, MINUSNV_EXPR, MULTNV_EXPR,
POINTER_PLUSNV_EXPR, NEGATENV_EXPR): New tree codes for
operations that are known to not overflow.
* tree.h (NEGATE_EXPR_CODE_P, PLUS_EXPR_CODE_P,
POINTER_PLUS_EXPR_CODE_P, MINUS_EXPR_CODE_P, MULT_EXPR_CODE_P): New.
(NEGATE_EXPR_P, PLUS_EXPR_P, POINTER_PLUS_EXPR_P, MINUS_EXPR_P,
MULT_EXPR_P): Likewise.
(strip_nv): New inline function.
(undefined_overflow_used_p_1): Declare.
(undefined_overflow_used_p): New inline function.
* varasm.c (narrowing_initializer_constant_valid_p): Handle
MINUSNV_EXPR.
(initializer_constant_valid_p): Handle *NV_EXPR.
* omp-low.c (omp_reduction_init): Likewise.
* gimple-pretty-print.c (dump_unary_rhs): Handle NEGATENV_EXPR.
* fold-const.c (fold_negate_expr): Likewise.
(int_const_binop): Handle *NV_EXPR.
(fold_unary): Handle NEGATENV_EXPR.
(tree_binary_nonzero_warnv_p): The type argument is unused.
(fold_binary): Handle simple cases for POINTER_PLUSNV_EXPR,
PLUSNV_EXPR, MINUSNV_EXPR and MULTNV_EXPR.
Index: trunk/gcc/expr.c
===================================================================
*** trunk.orig/gcc/expr.c 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/expr.c 2009-03-05 12:34:00.000000000 +0100
*************** expand_expr_real_1 (tree exp, rtx target
*** 8331,8337 ****
return op0;
! case POINTER_PLUS_EXPR:
/* Even though the sizetype mode and the pointer's mode can be different
expand is able to handle this correctly and get the correct result out
of the PLUS_EXPR code. */
--- 8331,8338 ----
return op0;
! case POINTER_PLUS_EXPR:
! case POINTER_PLUSNV_EXPR:
/* Even though the sizetype mode and the pointer's mode can be different
expand is able to handle this correctly and get the correct result out
of the PLUS_EXPR code. */
*************** expand_expr_real_1 (tree exp, rtx target
*** 8344,8354 ****
fold_convert (ssizetype,
TREE_OPERAND (exp, 1))));
case PLUS_EXPR:
/* Check if this is a case for multiplication and addition. */
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == FIXED_POINT_TYPE)
! && TREE_CODE (TREE_OPERAND (exp, 0)) == MULT_EXPR)
{
tree subsubexp0, subsubexp1;
enum tree_code code0, code1, this_code;
--- 8345,8356 ----
fold_convert (ssizetype,
TREE_OPERAND (exp, 1))));
case PLUS_EXPR:
+ case PLUSNV_EXPR:
/* Check if this is a case for multiplication and addition. */
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == FIXED_POINT_TYPE)
! && MULT_EXPR_P (TREE_OPERAND (exp, 0)))
{
tree subsubexp0, subsubexp1;
enum tree_code code0, code1, this_code;
*************** expand_expr_real_1 (tree exp, rtx target
*** 8405,8411 ****
sp, ap, or fp is our second argument, in which case we must swap
the innermost first argument and our second argument. */
! if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (exp, 1)) == VAR_DECL
&& (DECL_RTL (TREE_OPERAND (exp, 1)) == frame_pointer_rtx
--- 8407,8413 ----
sp, ap, or fp is our second argument, in which case we must swap
the innermost first argument and our second argument. */
! if (PLUS_EXPR_P (TREE_OPERAND (exp, 0))
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (exp, 1)) == VAR_DECL
&& (DECL_RTL (TREE_OPERAND (exp, 1)) == frame_pointer_rtx
*************** expand_expr_real_1 (tree exp, rtx target
*** 8508,8513 ****
--- 8510,8516 ----
return REDUCE_BIT_FIELD (simplify_gen_binary (PLUS, mode, op0, op1));
case MINUS_EXPR:
+ case MINUSNV_EXPR:
/* Check if this is a case for multiplication and subtraction. */
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == FIXED_POINT_TYPE)
*************** expand_expr_real_1 (tree exp, rtx target
*** 8598,8603 ****
--- 8601,8607 ----
goto binop2;
case MULT_EXPR:
+ case MULTNV_EXPR:
/* If this is a fixed-point operation, then we cannot use the code
below because "expand_mult" doesn't support sat/no-sat fixed-point
multiplications. */
*************** expand_expr_real_1 (tree exp, rtx target
*** 8818,8823 ****
--- 8822,8828 ----
return target;
case NEGATE_EXPR:
+ case NEGATENV_EXPR:
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget,
VOIDmode, EXPAND_NORMAL);
if (modifier == EXPAND_STACK_PARM)
Index: trunk/gcc/flags.h
===================================================================
*** trunk.orig/gcc/flags.h 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/flags.h 2009-03-05 12:34:00.000000000 +0100
*************** extern bool warn_disallowed_functions;
*** 345,352 ****
/* True if overflow wraps around for the given integral type. That
is, TYPE_MAX + 1 == TYPE_MIN. */
! #define TYPE_OVERFLOW_WRAPS(TYPE) \
! (TYPE_UNSIGNED (TYPE) || flag_wrapv)
/* True if overflow is undefined for the given integral type. We may
optimize on the assumption that values in the type never overflow.
--- 345,351 ----
/* True if overflow wraps around for the given integral type. That
is, TYPE_MAX + 1 == TYPE_MIN. */
! #define TYPE_OVERFLOW_WRAPS(TYPE) true
/* True if overflow is undefined for the given integral type. We may
optimize on the assumption that values in the type never overflow.
*************** extern bool warn_disallowed_functions;
*** 356,363 ****
it will be appropriate to issue the warning immediately, and in
other cases it will be appropriate to simply set a flag and let the
caller decide whether a warning is appropriate or not. */
! #define TYPE_OVERFLOW_UNDEFINED(TYPE) \
! (!TYPE_UNSIGNED (TYPE) && !flag_wrapv && !flag_trapv && flag_strict_overflow)
/* True if overflow for the given integral type should issue a
trap. */
--- 355,361 ----
it will be appropriate to issue the warning immediately, and in
other cases it will be appropriate to simply set a flag and let the
caller decide whether a warning is appropriate or not. */
! #define TYPE_OVERFLOW_UNDEFINED(TYPE) false
/* True if overflow for the given integral type should issue a
trap. */
*************** extern bool warn_disallowed_functions;
*** 365,371 ****
(!TYPE_UNSIGNED (TYPE) && flag_trapv)
/* True if pointer types have undefined overflow. */
! #define POINTER_TYPE_OVERFLOW_UNDEFINED (flag_strict_overflow)
/* Names for the different levels of -Wstrict-overflow=N. The numeric
values here correspond to N. */
--- 363,369 ----
(!TYPE_UNSIGNED (TYPE) && flag_trapv)
/* True if pointer types have undefined overflow. */
! #define POINTER_TYPE_OVERFLOW_UNDEFINED false
/* Names for the different levels of -Wstrict-overflow=N. The numeric
values here correspond to N. */
Index: trunk/gcc/optabs.c
===================================================================
*** trunk.orig/gcc/optabs.c 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/optabs.c 2009-03-05 12:34:00.000000000 +0100
*************** optab_for_tree_code (enum tree_code code
*** 490,511 ****
--- 490,516 ----
switch (code)
{
case POINTER_PLUS_EXPR:
+ case POINTER_PLUSNV_EXPR:
case PLUS_EXPR:
+ case PLUSNV_EXPR:
if (TYPE_SATURATING(type))
return TYPE_UNSIGNED(type) ? usadd_optab : ssadd_optab;
return trapv ? addv_optab : add_optab;
case MINUS_EXPR:
+ case MINUSNV_EXPR:
if (TYPE_SATURATING(type))
return TYPE_UNSIGNED(type) ? ussub_optab : sssub_optab;
return trapv ? subv_optab : sub_optab;
case MULT_EXPR:
+ case MULTNV_EXPR:
if (TYPE_SATURATING(type))
return TYPE_UNSIGNED(type) ? usmul_optab : ssmul_optab;
return trapv ? smulv_optab : smul_optab;
case NEGATE_EXPR:
+ case NEGATENV_EXPR:
if (TYPE_SATURATING(type))
return TYPE_UNSIGNED(type) ? usneg_optab : ssneg_optab;
return trapv ? negv_optab : neg_optab;
Index: trunk/gcc/tree-cfg.c
===================================================================
*** trunk.orig/gcc/tree-cfg.c 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/tree-cfg.c 2009-03-05 12:34:00.000000000 +0100
*************** verify_gimple_assign_unary (gimple stmt)
*** 3397,3402 ****
--- 3397,3403 ----
}
case NEGATE_EXPR:
+ case NEGATENV_EXPR:
case ABS_EXPR:
case BIT_NOT_EXPR:
case PAREN_EXPR:
*************** verify_gimple_assign_binary (gimple stmt
*** 3524,3529 ****
--- 3525,3531 ----
}
case POINTER_PLUS_EXPR:
+ case POINTER_PLUSNV_EXPR:
{
if (!POINTER_TYPE_P (rhs1_type)
|| !useless_type_conversion_p (lhs_type, rhs1_type)
*************** verify_gimple_assign_binary (gimple stmt
*** 3581,3587 ****
--- 3583,3591 ----
return verify_gimple_comparison (lhs_type, rhs1, rhs2);
case PLUS_EXPR:
+ case PLUSNV_EXPR:
case MINUS_EXPR:
+ case MINUSNV_EXPR:
{
if (POINTER_TYPE_P (lhs_type)
|| POINTER_TYPE_P (rhs1_type)
*************** verify_gimple_assign_binary (gimple stmt
*** 3596,3601 ****
--- 3600,3606 ----
}
case MULT_EXPR:
+ case MULTNV_EXPR:
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
Index: trunk/gcc/tree-inline.c
===================================================================
*** trunk.orig/gcc/tree-inline.c 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/tree-inline.c 2009-03-05 12:34:00.000000000 +0100
*************** estimate_operator_cost (enum tree_code c
*** 2753,2766 ****
--- 2753,2771 ----
case VEC_COND_EXPR:
case PLUS_EXPR:
+ case PLUSNV_EXPR:
case POINTER_PLUS_EXPR:
+ case POINTER_PLUSNV_EXPR:
case MINUS_EXPR:
+ case MINUSNV_EXPR:
case MULT_EXPR:
+ case MULTNV_EXPR:
case FIXED_CONVERT_EXPR:
case FIX_TRUNC_EXPR:
case NEGATE_EXPR:
+ case NEGATENV_EXPR:
case FLOAT_EXPR:
case MIN_EXPR:
case MAX_EXPR:
Index: trunk/gcc/tree-pretty-print.c
===================================================================
*** trunk.orig/gcc/tree-pretty-print.c 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/tree-pretty-print.c 2009-03-05 12:34:00.000000000 +0100
*************** dump_generic_node (pretty_printer *buffe
*** 1261,1269 ****
--- 1261,1273 ----
case WIDEN_SUM_EXPR:
case WIDEN_MULT_EXPR:
case MULT_EXPR:
+ case MULTNV_EXPR:
case PLUS_EXPR:
+ case PLUSNV_EXPR:
case POINTER_PLUS_EXPR:
+ case POINTER_PLUSNV_EXPR:
case MINUS_EXPR:
+ case MINUSNV_EXPR:
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
*************** dump_generic_node (pretty_printer *buffe
*** 1337,1342 ****
--- 1341,1347 ----
/* Unary arithmetic and logic expressions. */
case NEGATE_EXPR:
+ case NEGATENV_EXPR:
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
case ADDR_EXPR:
*************** op_code_prio (enum tree_code code)
*** 2332,2339 ****
--- 2337,2347 ----
case WIDEN_SUM_EXPR:
case PLUS_EXPR:
+ case PLUSNV_EXPR:
case POINTER_PLUS_EXPR:
+ case POINTER_PLUSNV_EXPR:
case MINUS_EXPR:
+ case MINUSNV_EXPR:
return 12;
case VEC_WIDEN_MULT_HI_EXPR:
*************** op_code_prio (enum tree_code code)
*** 2341,2346 ****
--- 2349,2355 ----
case WIDEN_MULT_EXPR:
case DOT_PROD_EXPR:
case MULT_EXPR:
+ case MULTNV_EXPR:
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
*************** op_code_prio (enum tree_code code)
*** 2360,2365 ****
--- 2369,2375 ----
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case NEGATE_EXPR:
+ case NEGATENV_EXPR:
case ALIGN_INDIRECT_REF:
case MISALIGNED_INDIRECT_REF:
case INDIRECT_REF:
*************** op_symbol_code (enum tree_code code)
*** 2504,2513 ****
--- 2514,2529 ----
case POINTER_PLUS_EXPR:
return "+";
+
+ case POINTER_PLUSNV_EXPR:
+ return "+/nv";
case PLUS_EXPR:
return "+";
+ case PLUSNV_EXPR:
+ return "+/nv";
+
case REDUC_PLUS_EXPR:
return "r+";
*************** op_symbol_code (enum tree_code code)
*** 2521,2526 ****
--- 2537,2546 ----
case MINUS_EXPR:
return "-";
+ case NEGATENV_EXPR:
+ case MINUSNV_EXPR:
+ return "-/nv";
+
case BIT_NOT_EXPR:
return "~";
*************** op_symbol_code (enum tree_code code)
*** 2531,2536 ****
--- 2551,2559 ----
case INDIRECT_REF:
return "*";
+ case MULTNV_EXPR:
+ return "*/nv";
+
case ALIGN_INDIRECT_REF:
return "A*";
Index: trunk/gcc/tree-ssa-structalias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-structalias.c 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/tree-ssa-structalias.c 2009-03-05 12:34:00.000000000 +0100
*************** find_func_aliases (gimple origt)
*** 3866,3872 ****
struct constraint_expr temp;
get_constraint_for (lhsop, &lhsc);
! if (gimple_assign_rhs_code (t) == POINTER_PLUS_EXPR)
get_constraint_for_ptr_offset (gimple_assign_rhs1 (t),
gimple_assign_rhs2 (t), &rhsc);
else if ((CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (t))
--- 3866,3872 ----
struct constraint_expr temp;
get_constraint_for (lhsop, &lhsc);
! if (POINTER_PLUS_EXPR_CODE_P (gimple_assign_rhs_code (t)))
get_constraint_for_ptr_offset (gimple_assign_rhs1 (t),
gimple_assign_rhs2 (t), &rhsc);
else if ((CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (t))
Index: trunk/gcc/tree.c
===================================================================
*** trunk.orig/gcc/tree.c 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/tree.c 2009-03-05 12:48:13.000000000 +0100
*************** build2_stat (enum tree_code code, tree t
*** 3288,3294 ****
gcc_assert (TREE_CODE_LENGTH (code) == 2);
! if ((code == MINUS_EXPR || code == PLUS_EXPR || code == MULT_EXPR)
&& arg0 && arg1 && tt && POINTER_TYPE_P (tt)
/* When sizetype precision doesn't match that of pointers
we need to be able to build explicit extensions or truncations
--- 3288,3296 ----
gcc_assert (TREE_CODE_LENGTH (code) == 2);
! if ((MINUS_EXPR_CODE_P (code)
! || PLUS_EXPR_CODE_P (code)
! || MULT_EXPR_CODE_P (code))
&& arg0 && arg1 && tt && POINTER_TYPE_P (tt)
/* When sizetype precision doesn't match that of pointers
we need to be able to build explicit extensions or truncations
*************** build2_stat (enum tree_code code, tree t
*** 3297,3303 ****
gcc_assert (TREE_CODE (arg0) == INTEGER_CST
&& TREE_CODE (arg1) == INTEGER_CST);
! if (code == POINTER_PLUS_EXPR && arg0 && arg1 && tt)
gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0))
&& INTEGRAL_TYPE_P (TREE_TYPE (arg1))
&& useless_type_conversion_p (sizetype, TREE_TYPE (arg1)));
--- 3299,3305 ----
gcc_assert (TREE_CODE (arg0) == INTEGER_CST
&& TREE_CODE (arg1) == INTEGER_CST);
! if (POINTER_PLUS_EXPR_CODE_P (code) && arg0 && arg1 && tt)
gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0))
&& INTEGRAL_TYPE_P (TREE_TYPE (arg1))
&& useless_type_conversion_p (sizetype, TREE_TYPE (arg1)));
*************** associative_tree_code (enum tree_code co
*** 5284,5290 ****
--- 5286,5294 ----
case BIT_AND_EXPR:
case BIT_XOR_EXPR:
case PLUS_EXPR:
+ case PLUSNV_EXPR:
case MULT_EXPR:
+ case MULTNV_EXPR:
case MIN_EXPR:
case MAX_EXPR:
return true;
*************** commutative_tree_code (enum tree_code co
*** 5303,5309 ****
--- 5307,5315 ----
switch (code)
{
case PLUS_EXPR:
+ case PLUSNV_EXPR:
case MULT_EXPR:
+ case MULTNV_EXPR:
case MIN_EXPR:
case MAX_EXPR:
case BIT_IOR_EXPR:
*************** block_ultimate_origin (const_tree block)
*** 9280,9283 ****
--- 9286,9316 ----
}
}
+
+ /* Returns true if operation CODE on type TYPE does not overflow because
+ overflow might have been undefined. */
+
+ bool
+ undefined_overflow_used_p_1 (enum tree_code code, tree type)
+ {
+ if (flag_strict_overflow
+ && ((!flag_wrapv
+ && INTEGRAL_TYPE_P (type)
+ && !TYPE_UNSIGNED (type))
+ || POINTER_TYPE_P (type)))
+ {
+ switch (code)
+ {
+ case NEGATENV_EXPR:
+ case PLUSNV_EXPR:
+ case MINUSNV_EXPR:
+ case MULTNV_EXPR:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+ }
+
#include "gt-tree.h"
Index: trunk/gcc/tree.def
===================================================================
*** trunk.orig/gcc/tree.def 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/tree.def 2009-03-05 12:34:00.000000000 +0100
*************** DEFTREECODE (PLACEHOLDER_EXPR, "placehol
*** 632,643 ****
--- 632,647 ----
/* Simple arithmetic. */
DEFTREECODE (PLUS_EXPR, "plus_expr", tcc_binary, 2)
+ DEFTREECODE (PLUSNV_EXPR, "plusv_expr", tcc_binary, 2)
DEFTREECODE (MINUS_EXPR, "minus_expr", tcc_binary, 2)
+ DEFTREECODE (MINUSNV_EXPR, "minusv_expr", tcc_binary, 2)
DEFTREECODE (MULT_EXPR, "mult_expr", tcc_binary, 2)
+ DEFTREECODE (MULTNV_EXPR, "multv_expr", tcc_binary, 2)
/* Pointer addition. The first operand is always a pointer and the
second operand is an integer of type sizetype. */
DEFTREECODE (POINTER_PLUS_EXPR, "pointer_plus_expr", tcc_binary, 2)
+ DEFTREECODE (POINTER_PLUSNV_EXPR, "pointer_plusv_expr", tcc_binary, 2)
/* Division for integer result that rounds the quotient toward zero. */
DEFTREECODE (TRUNC_DIV_EXPR, "trunc_div_expr", tcc_binary, 2)
*************** DEFTREECODE (FLOAT_EXPR, "float_expr", t
*** 672,677 ****
--- 676,682 ----
/* Unary negation. */
DEFTREECODE (NEGATE_EXPR, "negate_expr", tcc_unary, 1)
+ DEFTREECODE (NEGATENV_EXPR, "negatev_expr", tcc_unary, 1)
/* Minimum and maximum values. When used with floating point, if both
operands are zeros, or if either operand is NaN, then it is unspecified
Index: trunk/gcc/tree.h
===================================================================
*** trunk.orig/gcc/tree.h 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/tree.h 2009-03-05 12:48:42.000000000 +0100
*************** extern const enum tree_code_class tree_c
*** 177,182 ****
--- 177,223 ----
#define EXPR_P(NODE) IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (NODE)))
+ /* Returns true if the tree code is of a plain or non-overflowing kind. */
+
+ #define NEGATE_EXPR_CODE_P(CODE) \
+ ((CODE) == NEGATE_EXPR || (CODE) == NEGATENV_EXPR)
+ #define PLUS_EXPR_CODE_P(CODE) \
+ ((CODE) == PLUS_EXPR || (CODE) == PLUSNV_EXPR)
+ #define POINTER_PLUS_EXPR_CODE_P(CODE) \
+ ((CODE) == POINTER_PLUS_EXPR \
+ || (CODE) == POINTER_PLUSNV_EXPR)
+ #define MINUS_EXPR_CODE_P(CODE) \
+ ((CODE) == MINUS_EXPR || (CODE) == MINUSNV_EXPR)
+ #define MULT_EXPR_CODE_P(CODE) \
+ ((CODE) == MULT_EXPR || (CODE) == MULTNV_EXPR)
+
+ /* Returns true if the expression is of a plain or non-overflowing kind. */
+
+ #define NEGATE_EXPR_P(NODE) NEGATE_EXPR_CODE_P (TREE_CODE (NODE))
+ #define PLUS_EXPR_P(NODE) PLUS_EXPR_CODE_P (TREE_CODE (NODE))
+ #define POINTER_PLUS_EXPR_P(NODE) POINTER_PLUS_EXPR_CODE_P (TREE_CODE (NODE))
+ #define MINUS_EXPR_P(NODE) MINUS_EXPR_CODE_P (TREE_CODE (NODE))
+ #define MULT_EXPR_P(NODE) MULT_EXPR_CODE_P (TREE_CODE (NODE))
+
+ /* Returns an equivalent non-NV tree code for CODE. */
+ static inline enum tree_code
+ strip_nv (enum tree_code code)
+ {
+ switch (code)
+ {
+ case NEGATENV_EXPR:
+ return NEGATE_EXPR;
+ case PLUSNV_EXPR:
+ return PLUS_EXPR;
+ case MINUSNV_EXPR:
+ return MINUS_EXPR;
+ case MULTNV_EXPR:
+ return MULT_EXPR;
+ default:
+ return code;
+ }
+ }
+
/* Number of argument-words in each kind of tree-node. */
extern const unsigned char tree_code_length[];
*************** more_const_call_expr_args_p (const const
*** 5371,5374 ****
--- 5412,5425 ----
for ((arg) = first_const_call_expr_arg ((call), &(iter)); (arg); \
(arg) = next_const_call_expr_arg (&(iter)))
+ bool undefined_overflow_used_p_1 (enum tree_code, tree);
+
+ /* Returns true if EXP does not overflow because overflow is undefined. */
+ static inline bool
+ undefined_overflow_used_p (tree exp)
+ {
+ return (!TREE_NO_WARNING (exp)
+ && undefined_overflow_used_p_1 (TREE_CODE (exp), TREE_TYPE (exp)));
+ }
+
#endif /* GCC_TREE_H */
Index: trunk/gcc/varasm.c
===================================================================
*** trunk.orig/gcc/varasm.c 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/varasm.c 2009-03-05 12:34:00.000000000 +0100
*************** narrowing_initializer_constant_valid_p (
*** 4126,4132 ****
{
if (op0 == op1
&& (op0 == null_pointer_node
! || TREE_CODE (value) == MINUS_EXPR))
return null_pointer_node;
/* Support differences between labels. */
--- 4126,4132 ----
{
if (op0 == op1
&& (op0 == null_pointer_node
! || MINUS_EXPR_P (value)))
return null_pointer_node;
/* Support differences between labels. */
*************** initializer_constant_valid_p (tree value
*** 4301,4307 ****
--- 4301,4309 ----
break;
case POINTER_PLUS_EXPR:
+ case POINTER_PLUSNV_EXPR:
case PLUS_EXPR:
+ case PLUSNV_EXPR:
if (! INTEGRAL_TYPE_P (endtype)
|| TYPE_PRECISION (endtype) >= POINTER_SIZE)
{
*************** initializer_constant_valid_p (tree value
*** 4324,4329 ****
--- 4326,4332 ----
break;
case MINUS_EXPR:
+ case MINUSNV_EXPR:
if (! INTEGRAL_TYPE_P (endtype)
|| TYPE_PRECISION (endtype) >= POINTER_SIZE)
{
Index: trunk/gcc/omp-low.c
===================================================================
*** trunk.orig/gcc/omp-low.c 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/omp-low.c 2009-03-05 12:34:00.000000000 +0100
*************** omp_reduction_init (tree clause, tree ty
*** 2130,2136 ****
--- 2130,2138 ----
switch (OMP_CLAUSE_REDUCTION_CODE (clause))
{
case PLUS_EXPR:
+ case PLUSNV_EXPR:
case MINUS_EXPR:
+ case MINUSNV_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case TRUTH_OR_EXPR:
*************** omp_reduction_init (tree clause, tree ty
*** 2140,2145 ****
--- 2142,2148 ----
return fold_convert (type, integer_zero_node);
case MULT_EXPR:
+ case MULTNV_EXPR:
case TRUTH_AND_EXPR:
case TRUTH_ANDIF_EXPR:
case EQ_EXPR:
Index: trunk/gcc/gimple-pretty-print.c
===================================================================
*** trunk.orig/gcc/gimple-pretty-print.c 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/gimple-pretty-print.c 2009-03-05 12:34:00.000000000 +0100
*************** dump_unary_rhs (pretty_printer *buffer,
*** 299,304 ****
--- 299,306 ----
pp_character (buffer, '!');
else if (rhs_code == NEGATE_EXPR)
pp_character (buffer, '-');
+ else if (rhs_code == NEGATENV_EXPR)
+ pp_string (buffer, "-/nv");
else
{
pp_character (buffer, '[');
Index: trunk/gcc/fold-const.c
===================================================================
*** trunk.orig/gcc/fold-const.c 2009-03-05 12:28:32.000000000 +0100
--- trunk/gcc/fold-const.c 2009-03-05 13:48:19.000000000 +0100
*************** fold_negate_expr (tree t)
*** 1292,1297 ****
--- 1292,1298 ----
break;
case NEGATE_EXPR:
+ case NEGATENV_EXPR:
return TREE_OPERAND (t, 0);
case PLUS_EXPR:
*************** int_const_binop (enum tree_code code, co
*** 1684,1699 ****
--- 1685,1703 ----
break;
case PLUS_EXPR:
+ case PLUSNV_EXPR:
overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi);
break;
case MINUS_EXPR:
+ case MINUSNV_EXPR:
neg_double (int2l, int2h, &low, &hi);
add_double (int1l, int1h, low, hi, &low, &hi);
overflow = OVERFLOW_SUM_SIGN (hi, int2h, int1h);
break;
case MULT_EXPR:
+ case MULTNV_EXPR:
overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi);
break;
*************** fold_unary (enum tree_code code, tree ty
*** 8412,8417 ****
--- 8416,8422 ----
return fold_view_convert_expr (type, op0);
case NEGATE_EXPR:
+ case NEGATENV_EXPR:
tem = fold_negate_expr (arg0);
if (tem)
return fold_convert (type, tem);
*************** tree_unary_nonzero_warnv_p (enum tree_co
*** 14887,14893 ****
bool
tree_binary_nonzero_warnv_p (enum tree_code code,
! tree type,
tree op0,
tree op1, bool *strict_overflow_p)
{
--- 14892,14898 ----
bool
tree_binary_nonzero_warnv_p (enum tree_code code,
! tree type ATTRIBUTE_UNUSED,
tree op0,
tree op1, bool *strict_overflow_p)
{