diff options
author | Jakub Jelinek <jakub@redhat.com> | 2018-01-15 10:05:59 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2018-01-15 10:05:59 +0100 |
commit | 3fccbb9ecec7daa3b6468f72379c0bd1fb5bb8d9 (patch) | |
tree | 08c17fa7abe77e42e46b0fdf6d49c9bdf48fc9a0 /gcc/fold-const.c | |
parent | 2aa89839f557b7467704ddffa4dc43a130e8d027 (diff) | |
download | gcc-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.c | 24 |
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)) { |