Message ID | CAFOnWk=xveuB-LNHHz4rE9+8vZK5yNfRPCTt5DUQs4ALdPKdtQ@mail.gmail.com |
---|---|
State | New |
Headers | show |
On Thu, Jun 30, 2016 at 1:17 PM, Manish Goregaokar <manish@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
What about ptr + intptr_t? I guess we should check nonnegative for op1 then? -Manish On Thu, Jun 30, 2016 at 5:25 PM, Richard Biener <richard.guenther@gmail.com> wrote: > On Thu, Jun 30, 2016 at 1:17 PM, Manish Goregaokar <manish@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
On Thu, Jun 30, 2016 at 2:03 PM, Manish Goregaokar <manish@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.guenther@gmail.com> wrote: >> On Thu, Jun 30, 2016 at 1:17 PM, Manish Goregaokar <manish@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
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; + /* 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