Alright, the following patch was tested and it works diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 3b9500d..0d82018 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -13199,6 +13199,9 @@ tree_binary_nonzero_warnv_p (enum tree_code code, switch (code) { case POINTER_PLUS_EXPR: + return flag_delete_null_pointer_checks + && (tree_expr_nonzero_warnv_p (op0, strict_overflow_p) + || tree_expr_nonzero_warnv_p (op1, strict_overflow_p)); case PLUS_EXPR: if (ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type)) { -- 2.8.3
-Manish On Thu, Jun 30, 2016 at 6:45 PM, Richard Biener <richard.guent...@gmail.com> wrote: > On Thu, Jun 30, 2016 at 2:03 PM, Manish Goregaokar <man...@mozilla.com> wrote: >> What about ptr + intptr_t? I guess we should check nonnegative for op1 then? > > op1 will always be nonnegative as it is forced to sizetype type (which > is unsigned). > > Richard. > >> -Manish >> >> >> On Thu, Jun 30, 2016 at 5:25 PM, Richard Biener >> <richard.guent...@gmail.com> wrote: >>> On Thu, Jun 30, 2016 at 1:17 PM, Manish Goregaokar <man...@mozilla.com> >>> wrote: >>>> gcc/ChangeLog: >>>> PR c/71699 >>>> * fold-const.c (tree_binary_nonzero_warnv_p): Allow >>>> pointer addition to also be considered nonzero. >>>> --- >>>> gcc/fold-const.c | 20 +++++++++++++------- >>>> 1 file changed, 13 insertions(+), 7 deletions(-) >>>> >>>> diff --git a/gcc/fold-const.c b/gcc/fold-const.c >>>> index 3b9500d..eda713e 100644 >>>> --- a/gcc/fold-const.c >>>> +++ b/gcc/fold-const.c >>>> @@ -13200,16 +13200,22 @@ tree_binary_nonzero_warnv_p (enum tree_code code, >>>> { >>>> case POINTER_PLUS_EXPR: >>>> case PLUS_EXPR: >>>> - if (ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type)) >>>> + if ((ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type)) >>>> + || POINTER_TYPE_P (type)) >>>> { >>>> + /* Pointers are always nonnegative, check integers. */ >>>> + if (ANY_INTEGRAL_TYPE_P (type)) >>>> + { >>>> + sub_strict_overflow_p = false; >>>> + if (!tree_expr_nonnegative_warnv_p (op0, >>>> + &sub_strict_overflow_p) >>>> + || !tree_expr_nonnegative_warnv_p (op1, >>>> + &sub_strict_overflow_p)) >>>> + return false; >>>> + } >>>> /* With the presence of negative values it is hard >>>> to say something. */ >>>> - sub_strict_overflow_p = false; >>>> - if (!tree_expr_nonnegative_warnv_p (op0, >>>> - &sub_strict_overflow_p) >>>> - || !tree_expr_nonnegative_warnv_p (op1, >>>> - &sub_strict_overflow_p)) >>>> - return false; >>>> + >>> >>> Hmm, note that op1 of POINTER_PLUS_EXPR _is_ an integer that needs to be >>> treated >>> as signed. >>> >>> POINTER_PLUS_EXPR is special in other ways in that iff >>> flag_delete_null_pointer_checks >>> is set we can assume that ptr + non-zero is never zero. Thus simply do >>> >>> case POINTER_PLUS_EXPR: >>> return flag_delete_null_pointer_checks >>> && (tree_expr_nonzero_warnv_p (op0, strict_overflow_p) >>> || tree_expr_nonzero_warnv_p (op1, strict_overflow_p)); >>> >>> OTOH ptr + -(uintptr_t)ptr is valid from a POINTER_PLUS_EXPR >>> perspective as GCC does >>> not have a special tree code for pointer subtraction (but IIRC it uses >>> MINUS_EXPR on integers >>> for this). >>> >>> Richard. >>> >>> >>>> /* One of operands must be positive and the other non-negative. */ >>>> /* We don't set *STRICT_OVERFLOW_P here: even if this value >>>> overflows, on a twos-complement machine the sum of two >>>> -- >>>> 2.8.3