aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2018-01-15 10:05:59 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2018-01-15 10:05:59 +0100
commit3fccbb9ecec7daa3b6468f72379c0bd1fb5bb8d9 (patch)
tree08c17fa7abe77e42e46b0fdf6d49c9bdf48fc9a0 /gcc/fold-const.c
parent2aa89839f557b7467704ddffa4dc43a130e8d027 (diff)
downloadgcc-3fccbb9ecec7daa3b6468f72379c0bd1fb5bb8d9.zip
gcc-3fccbb9ecec7daa3b6468f72379c0bd1fb5bb8d9.tar.gz
gcc-3fccbb9ecec7daa3b6468f72379c0bd1fb5bb8d9.tar.bz2
re PR middle-end/82694 (Linux kernel miscompiled since r250765)
PR middle-end/82694 * common.opt (fstrict-overflow): No longer an alias. (fwrapv-pointer): New option. * tree.h (TYPE_OVERFLOW_WRAPS, TYPE_OVERFLOW_UNDEFINED): Define also for pointer types based on flag_wrapv_pointer. * opts.c (common_handle_option) <case OPT_fstrict_overflow>: Set opts->x_flag_wrap[pv] to !value, clear opts->x_flag_trapv if opts->x_flag_wrapv got set. * fold-const.c (fold_comparison, fold_binary_loc): Revert 2017-08-01 changes, just use TYPE_OVERFLOW_UNDEFINED on pointer type instead of POINTER_TYPE_OVERFLOW_UNDEFINED. * match.pd: Likewise in address comparison pattern. * doc/invoke.texi: Document -fwrapv and -fstrict-overflow. * gcc.dg/no-strict-overflow-7.c: Revert 2017-08-01 changes. * gcc.dg/tree-ssa/pr81388-1.c: Likewise. From-SVN: r256686
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index cfb1b3d..f3749db 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -8551,9 +8551,13 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
{
/* We can fold this expression to a constant if the non-constant
offset parts are equal. */
- if (offset0 == offset1
- || (offset0 && offset1
- && operand_equal_p (offset0, offset1, 0)))
+ if ((offset0 == offset1
+ || (offset0 && offset1
+ && operand_equal_p (offset0, offset1, 0)))
+ && (equality_code
+ || (indirect_base0
+ && (DECL_P (base0) || CONSTANT_CLASS_P (base0)))
+ || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))))
{
if (!equality_code
&& maybe_ne (bitpos0, bitpos1)
@@ -8612,7 +8616,11 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
because pointer arithmetic is restricted to retain within an
object and overflow on pointer differences is undefined as of
6.5.6/8 and /9 with respect to the signed ptrdiff_t. */
- else if (known_eq (bitpos0, bitpos1))
+ else if (known_eq (bitpos0, bitpos1)
+ && (equality_code
+ || (indirect_base0
+ && (DECL_P (base0) || CONSTANT_CLASS_P (base0)))
+ || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))))
{
/* By converting to signed sizetype we cover middle-end pointer
arithmetic which operates on unsigned pointer types of size
@@ -9721,8 +9729,8 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type,
/* With undefined overflow prefer doing association in a type
which wraps on overflow, if that is one of the operand types. */
- if (POINTER_TYPE_P (type)
- || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type)))
+ if ((POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
+ && !TYPE_OVERFLOW_WRAPS (type))
{
if (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
&& TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0)))
@@ -9735,8 +9743,8 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type,
/* With undefined overflow we can only associate constants with one
variable, and constants whose association doesn't overflow. */
- if (POINTER_TYPE_P (atype)
- || (INTEGRAL_TYPE_P (atype) && !TYPE_OVERFLOW_WRAPS (atype)))
+ if ((POINTER_TYPE_P (atype) || INTEGRAL_TYPE_P (atype))
+ && !TYPE_OVERFLOW_WRAPS (atype))
{
if ((var0 && var1) || (minus_var0 && minus_var1))
{