diff mbox

Set nonnull attribute to ptr_info_def based on VRP

Message ID c520d954-7c43-9eb0-d4a2-aae2736d6a72@linaro.org
State New
Headers show

Commit Message

Kugan Vivekanandarajah Oct. 12, 2016, 6:46 a.m. UTC
Hi Richard,


On 07/10/16 21:03, Richard Biener wrote:
> On Fri, Oct 7, 2016 at 2:53 AM, kugan <kugan.vivekanandarajah@linaro.org> wrote:
>> Hi Richard,
>>
>> Thanks for the review.
>>
>>
>> On 09/08/16 18:58, Richard Biener wrote:
>>>
>>> On Tue, Aug 9, 2016 at 12:58 AM, kugan
>>> <kugan.vivekanandarajah@linaro.org> wrote:
>>>>
>>>> Hi Jakub,
>>>>
>>>> Thanks for the review.
>>>>
>>>> On 08/08/16 16:40, Jakub Jelinek wrote:
>>>>>
>>>>>
>>>>> On Mon, Aug 08, 2016 at 01:36:51PM +1000, kugan wrote:
>>>>>>
>>>>>>
>>>>>> diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
>>>>>> index c81b1a1..6e34433 100644
>>>>>> --- a/gcc/tree-ssanames.h
>>>>>> +++ b/gcc/tree-ssanames.h
>>>>>> @@ -43,6 +43,9 @@ struct GTY(()) ptr_info_def
>>>>>>       above alignment.  Access only through the same helper functions
>>>>>> as
>>>>>> align
>>>>>>       above.  */
>>>>>>    unsigned int misalign;
>>>>>> +  /* When this pointer is knonw to be nnonnull this would be true
>>>>>> otherwise
>>>>>> +     false.  */
>>>>>> +  bool  nonnull_p;
>>>>>>  };
>>>>>
>>>>>
>>>>>
>>>>> Why do you need this?  Doesn't the pt.null bit represent that already?
>>>>
>>>>
>>>>
>>>> It looks like I can use this. As in gcc/tree-ssa-alias.h:
>>>>
>>>>   /* Nonzero if the points-to set includes 'nothing', the points-to set
>>>>      includes memory at address NULL.  */
>>>>   unsigned int null : 1;
>>>>
>>>> But in gcc/tree-ssa-alias.c, ptrs_compare_unequal has the following
>>>> comment
>>>> which says:
>>>>
>>>> /* ???  We'd like to handle ptr1 != NULL and ptr1 != ptr2
>>>>      but those require pt.null to be conservatively correct.  */
>>>>
>>>> Does that means it can be wrong at times? I haven't looked it in detail
>>>> yet
>>>> but if it is, it would be a problem.
>>>
>>>
>>> Yes, this bit is not correctly computed for all cases (well, it works
>>> for trivial
>>> ones but for example misses weaks and maybe some other corner-cases).
>>>
>>> Currently there are no consumers of this bit so the incorrectness
>>> doesn't matter.
>>>
>>> I suggest you simply use that bit but set it conservatively from PTA (to
>>> true)
>>> for now and adjust it from VRP only.
>>>
>>> I do have some patches for fixinig some of the .nonnull_p issues in PTA
>>> but
>>> they come at a cost of more constraints.
>>
>>
>> Here is a version of the patch that does this. I have a follow up patch to
>> use this in ipa-vrp. I will send it for review once this is OK.
>>
>> Bootstrapped and regression tested on x86_64-linux-gnu with no new
>> regressions. Is this OK for trunk?
>
> @@ -6359,7 +6361,7 @@ find_what_var_points_to (tree fndecl, varinfo_t orig_vi)
>        if (vi->is_artificial_var)
>         {
>           if (vi->id == nothing_id)
> -           pt->null = 1;
> +           ;
>
> please leave this here.
Done.

>
>  pt_solution_singleton_p (struct pt_solution *pt, unsigned *uid)
>  {
>    if (pt->anything || pt->nonlocal || pt->escaped || pt->ipa_escaped
> -      || pt->null || pt->vars == NULL
> +      || pt->vars == NULL
>        || !bitmap_single_bit_set_p (pt->vars))
>      return false;
>
> humm... this is a correctness problem I guess.  A latent one currently
> depending on who relies on it.
> There is a single use of the above predicate which looks for the
> points-to solution of a __builtin_alloca call.  We should somehow
> arrange for its solution to not include ->null.  Or, simpler, change
> the predicates name to pt_solution_singleton_or_null_p () as
> the use does not care for pt->null.

I have changed the name.

>
> +void
> +set_ptr_nonnull (tree name)
> +{
> +  gcc_assert (POINTER_TYPE_P (TREE_TYPE (name)));
> +  struct ptr_info_def *pi = get_ptr_info (name);
> +  pi->pt.null = 0;
>
>  = false;
>
> +}
>
> There is the question on how pt.null semantics should be
> with respect to pt.anything, pt.escaped and pt.nonlocal.
> I think get_ptr_nonnull needs to return false if any
> of those are set.

I have added pt.anything.

I am assuming if pt.escaped, it cannot become null?
My intention is to eliminate for pt.nonlocal too. Like in:

static __attribute__((noinline, noclone))
int foo (int *p)
{
   if (!p)
     return 0;
   *p = 1;
}

struct st
{
   int a;
   int b;
};

int bar (struct st *s)
{

   if (!s)
     return 0;
   foo (&s->a);
   foo (&s->b);
}

And also in find_what_p_points_to we can overwrite pt.null. So I have 
changed that too.

Please find the updated patch attached. Does this look better?

Thanks,
Kugan

> Richard.
>
>>
>> Thanks,
>> Kugan
>>
>> gcc/ChangeLog:
>>
>> 2016-10-07  Kugan Vivekanandarajah  <kuganv@linaro.org>
>>
>>         * tree-ssa-alias.c (dump_points_to_solution): Dump non null as it
>>           is set to null conservatively.
>>         * tree-ssa-structalias.c (find_what_var_points_to): Set to null
>>           conservatively.
>>         (pt_solution_singleton_p): Dont check null.
>>         * tree-ssanames.c (set_ptr_nonnull): New.
>>         (get_ptr_nonnull): Likewise.
>>         * tree-vrp.c (vrp_finalize): Set ptr that are nonnull.
>>         (evrp_dom_walker::before_dom_children): Likewise.
>>
>>>
>>> Richard.
>>>
>>>>> Also, formatting and spelling:
>>>>> s/knonw/known/
>>>>> s/nnon/non/
>>>>> s/bool  /bool /
>>>>
>>>>
>>>>
>>>> I will change this.
>>>>
>>>> Thanks,
>>>> Kugan
>>>>>
>>>>>
>>>>>
>>>>>         Jakub
>>>>>
>>>>
>>

Comments

Richard Biener Oct. 12, 2016, 12:20 p.m. UTC | #1
On Wed, Oct 12, 2016 at 8:46 AM, kugan
<kugan.vivekanandarajah@linaro.org> wrote:
> Hi Richard,
>
>
>
> On 07/10/16 21:03, Richard Biener wrote:
>>
>> On Fri, Oct 7, 2016 at 2:53 AM, kugan <kugan.vivekanandarajah@linaro.org>
>> wrote:
>>>
>>> Hi Richard,
>>>
>>> Thanks for the review.
>>>
>>>
>>> On 09/08/16 18:58, Richard Biener wrote:
>>>>
>>>>
>>>> On Tue, Aug 9, 2016 at 12:58 AM, kugan
>>>> <kugan.vivekanandarajah@linaro.org> wrote:
>>>>>
>>>>>
>>>>> Hi Jakub,
>>>>>
>>>>> Thanks for the review.
>>>>>
>>>>> On 08/08/16 16:40, Jakub Jelinek wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Mon, Aug 08, 2016 at 01:36:51PM +1000, kugan wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
>>>>>>> index c81b1a1..6e34433 100644
>>>>>>> --- a/gcc/tree-ssanames.h
>>>>>>> +++ b/gcc/tree-ssanames.h
>>>>>>> @@ -43,6 +43,9 @@ struct GTY(()) ptr_info_def
>>>>>>>       above alignment.  Access only through the same helper functions
>>>>>>> as
>>>>>>> align
>>>>>>>       above.  */
>>>>>>>    unsigned int misalign;
>>>>>>> +  /* When this pointer is knonw to be nnonnull this would be true
>>>>>>> otherwise
>>>>>>> +     false.  */
>>>>>>> +  bool  nonnull_p;
>>>>>>>  };
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Why do you need this?  Doesn't the pt.null bit represent that already?
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> It looks like I can use this. As in gcc/tree-ssa-alias.h:
>>>>>
>>>>>   /* Nonzero if the points-to set includes 'nothing', the points-to set
>>>>>      includes memory at address NULL.  */
>>>>>   unsigned int null : 1;
>>>>>
>>>>> But in gcc/tree-ssa-alias.c, ptrs_compare_unequal has the following
>>>>> comment
>>>>> which says:
>>>>>
>>>>> /* ???  We'd like to handle ptr1 != NULL and ptr1 != ptr2
>>>>>      but those require pt.null to be conservatively correct.  */
>>>>>
>>>>> Does that means it can be wrong at times? I haven't looked it in detail
>>>>> yet
>>>>> but if it is, it would be a problem.
>>>>
>>>>
>>>>
>>>> Yes, this bit is not correctly computed for all cases (well, it works
>>>> for trivial
>>>> ones but for example misses weaks and maybe some other corner-cases).
>>>>
>>>> Currently there are no consumers of this bit so the incorrectness
>>>> doesn't matter.
>>>>
>>>> I suggest you simply use that bit but set it conservatively from PTA (to
>>>> true)
>>>> for now and adjust it from VRP only.
>>>>
>>>> I do have some patches for fixinig some of the .nonnull_p issues in PTA
>>>> but
>>>> they come at a cost of more constraints.
>>>
>>>
>>>
>>> Here is a version of the patch that does this. I have a follow up patch
>>> to
>>> use this in ipa-vrp. I will send it for review once this is OK.
>>>
>>> Bootstrapped and regression tested on x86_64-linux-gnu with no new
>>> regressions. Is this OK for trunk?
>>
>>
>> @@ -6359,7 +6361,7 @@ find_what_var_points_to (tree fndecl, varinfo_t
>> orig_vi)
>>        if (vi->is_artificial_var)
>>         {
>>           if (vi->id == nothing_id)
>> -           pt->null = 1;
>> +           ;
>>
>> please leave this here.
>
> Done.
>
>>
>>  pt_solution_singleton_p (struct pt_solution *pt, unsigned *uid)
>>  {
>>    if (pt->anything || pt->nonlocal || pt->escaped || pt->ipa_escaped
>> -      || pt->null || pt->vars == NULL
>> +      || pt->vars == NULL
>>        || !bitmap_single_bit_set_p (pt->vars))
>>      return false;
>>
>> humm... this is a correctness problem I guess.  A latent one currently
>> depending on who relies on it.
>> There is a single use of the above predicate which looks for the
>> points-to solution of a __builtin_alloca call.  We should somehow
>> arrange for its solution to not include ->null.  Or, simpler, change
>> the predicates name to pt_solution_singleton_or_null_p () as
>> the use does not care for pt->null.
>
>
> I have changed the name.
>
>>
>> +void
>> +set_ptr_nonnull (tree name)
>> +{
>> +  gcc_assert (POINTER_TYPE_P (TREE_TYPE (name)));
>> +  struct ptr_info_def *pi = get_ptr_info (name);
>> +  pi->pt.null = 0;
>>
>>  = false;
>>
>> +}
>>
>> There is the question on how pt.null semantics should be
>> with respect to pt.anything, pt.escaped and pt.nonlocal.
>> I think get_ptr_nonnull needs to return false if any
>> of those are set.
>
>
> I have added pt.anything.
>
> I am assuming if pt.escaped, it cannot become null?

Sure can it become null.

> My intention is to eliminate for pt.nonlocal too. Like in:
>
> static __attribute__((noinline, noclone))
> int foo (int *p)
> {
>   if (!p)
>     return 0;
>   *p = 1;
> }
>
> struct st
> {
>   int a;
>   int b;
> };
>
> int bar (struct st *s)
> {
>
>   if (!s)
>     return 0;
>   foo (&s->a);
>   foo (&s->b);
> }

I don't think this is sth PTA handles.

> And also in find_what_p_points_to we can overwrite pt.null. So I have
> changed that too.
>
> Please find the updated patch attached. Does this look better?

@@ -515,8 +515,8 @@ dump_points_to_solution (FILE *file, struct pt_solution *pt)
   if (pt->ipa_escaped)
     fprintf (file, ", points-to unit escaped");

-  if (pt->null)
-    fprintf (file, ", points-to NULL");
+  if (!pt->null)
+    fprintf (file, ", points-to non NULL");

please keep the original dumping.  !pt->null doesn't mean it points to
sth not NULL.
It might point to nothing.  And as I said pt->nonlocal / pt->escaped
include NULL.

@@ -6391,9 +6393,7 @@ find_what_var_points_to (tree fndecl, varinfo_t orig_vi)

       if (vi->is_artificial_var)
        {
-         if (vi->id == nothing_id)
-           pt->null = 1;
-         else if (vi->id == escaped_id)
+         if (vi->id == escaped_id)
            {
              if (in_ipa_mode)
                pt->ipa_escaped = 1;

please keep this as well.

@@ -6451,6 +6451,7 @@ find_what_p_points_to (tree fndecl, tree p)
   struct ptr_info_def *pi;
   tree lookup_p = p;
   varinfo_t vi;
+  bool nonnull = get_ptr_nonnull (p);

   /* For parameters, get at the points-to set for the actual parm
      decl.  */
@@ -6466,6 +6467,8 @@ find_what_p_points_to (tree fndecl, tree p)

   pi = get_ptr_info (p);
   pi->pt = find_what_var_points_to (fndecl, vi);
+  if (nonnull)
+    set_ptr_nonnull (p);
 }

what does this try to do?  Preserve info VRP computed across PTA?

I think we didn't yet sort out the nonlocal/escaped vs. null handling properly
(or how PTA should handle get_ptr_nonnull).  The way you are using it
asks for pt.null to be orthogonal to nonlocal/escaped and thus having
nonlocal or escaped would also require setting ptr.null in PTA.  It then
would be also more canonical to set it for pt.anything as well.  Which
means conservatively handling it would be equivalent to flipping its
semantic and changing its name to pt.nonnull.

That said, you seem to be simply "reserving" the bit for VRP, keeping it
conservatively true when "not computed".  I guess I'm fine with this for now
but it should be documented in the header file that way.

Richard.

> Thanks,
> Kugan
>
>
>> Richard.
>>
>>>
>>> Thanks,
>>> Kugan
>>>
>>> gcc/ChangeLog:
>>>
>>> 2016-10-07  Kugan Vivekanandarajah  <kuganv@linaro.org>
>>>
>>>         * tree-ssa-alias.c (dump_points_to_solution): Dump non null as it
>>>           is set to null conservatively.
>>>         * tree-ssa-structalias.c (find_what_var_points_to): Set to null
>>>           conservatively.
>>>         (pt_solution_singleton_p): Dont check null.
>>>         * tree-ssanames.c (set_ptr_nonnull): New.
>>>         (get_ptr_nonnull): Likewise.
>>>         * tree-vrp.c (vrp_finalize): Set ptr that are nonnull.
>>>         (evrp_dom_walker::before_dom_children): Likewise.
>>>
>>>>
>>>> Richard.
>>>>
>>>>>> Also, formatting and spelling:
>>>>>> s/knonw/known/
>>>>>> s/nnon/non/
>>>>>> s/bool  /bool /
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> I will change this.
>>>>>
>>>>> Thanks,
>>>>> Kugan
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>         Jakub
>>>>>>
>>>>>
>>>
>
Kugan Vivekanandarajah Oct. 13, 2016, 4:49 a.m. UTC | #2
Hi Richard,

>
> what does this try to do?  Preserve info VRP computed across PTA?
>
> I think we didn't yet sort out the nonlocal/escaped vs. null handling properly
> (or how PTA should handle get_ptr_nonnull).  The way you are using it
> asks for pt.null to be orthogonal to nonlocal/escaped and thus having
> nonlocal or escaped would also require setting ptr.null in PTA.  It then
> would be also more canonical to set it for pt.anything as well.  Which
> means conservatively handling it would be equivalent to flipping its
> semantic and changing its name to pt.nonnull.
>
> That said, you seem to be simply "reserving" the bit for VRP, keeping it
> conservatively true when "not computed".  I guess I'm fine with this for now
> but it should be documented in the header file that way.
>

Thanks for the comments.

To summarize, currently I am not relying on PTA analysis at all. Just 
saving null from VRP (or rather nonnull) and preserving it across PTA. 
Primary intention is to pass it for PARM_DECL SSA names (from ipa-vrp).

In this case, using  pt.anything/nonlocal/escaped will only make the 
result more pessimistic.

Ideally, we should improve pt.null within PTA but for now as you said, I 
will document it.

When we start using pt.null from PTA analysis, we would also have to 
take into account pt.anything/nonlocal/escaped.

Does that make sense?

Thanks,
Kugan
Richard Biener Oct. 13, 2016, 9:44 a.m. UTC | #3
On Thu, Oct 13, 2016 at 6:49 AM, kugan
<kugan.vivekanandarajah@linaro.org> wrote:
> Hi Richard,
>
>>
>> what does this try to do?  Preserve info VRP computed across PTA?
>>
>> I think we didn't yet sort out the nonlocal/escaped vs. null handling
>> properly
>> (or how PTA should handle get_ptr_nonnull).  The way you are using it
>> asks for pt.null to be orthogonal to nonlocal/escaped and thus having
>> nonlocal or escaped would also require setting ptr.null in PTA.  It then
>> would be also more canonical to set it for pt.anything as well.  Which
>> means conservatively handling it would be equivalent to flipping its
>> semantic and changing its name to pt.nonnull.
>>
>> That said, you seem to be simply "reserving" the bit for VRP, keeping it
>> conservatively true when "not computed".  I guess I'm fine with this for
>> now
>> but it should be documented in the header file that way.
>>
>
> Thanks for the comments.
>
> To summarize, currently I am not relying on PTA analysis at all. Just saving
> null from VRP (or rather nonnull) and preserving it across PTA. Primary
> intention is to pass it for PARM_DECL SSA names (from ipa-vrp).
>
> In this case, using  pt.anything/nonlocal/escaped will only make the result
> more pessimistic.
>
> Ideally, we should improve pt.null within PTA but for now as you said, I
> will document it.
>
> When we start using pt.null from PTA analysis, we would also have to take
> into account pt.anything/nonlocal/escaped.
>
> Does that make sense?

Yes.

Thanks,
Richard.

> Thanks,
> Kugan
>
diff mbox

Patch

From a2c163ca9e7d3569cc2d58bc188fcd466dfe2ff7 Mon Sep 17 00:00:00 2001
From: Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
Date: Wed, 12 Oct 2016 13:48:07 +1100
Subject: [PATCH 1/3] Add-nonnull-to-pointer-from-VRP

---
 gcc/tree-ssa-alias.c       |  4 ++--
 gcc/tree-ssa-alias.h       |  2 +-
 gcc/tree-ssa-ccp.c         |  2 +-
 gcc/tree-ssa-structalias.c | 13 ++++++++-----
 gcc/tree-ssanames.c        | 22 ++++++++++++++++++++++
 gcc/tree-ssanames.h        |  2 ++
 gcc/tree-vrp.c             | 44 +++++++++++++++++++++++++++++---------------
 7 files changed, 65 insertions(+), 24 deletions(-)

diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 01bef17..dff11b1 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -515,8 +515,8 @@  dump_points_to_solution (FILE *file, struct pt_solution *pt)
   if (pt->ipa_escaped)
     fprintf (file, ", points-to unit escaped");
 
-  if (pt->null)
-    fprintf (file, ", points-to NULL");
+  if (!pt->null)
+    fprintf (file, ", points-to non NULL");
 
   if (pt->vars)
     {
diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h
index 6680cc0..27a06fc 100644
--- a/gcc/tree-ssa-alias.h
+++ b/gcc/tree-ssa-alias.h
@@ -146,7 +146,7 @@  extern void dump_alias_stats (FILE *);
 /* In tree-ssa-structalias.c  */
 extern unsigned int compute_may_aliases (void);
 extern bool pt_solution_empty_p (struct pt_solution *);
-extern bool pt_solution_singleton_p (struct pt_solution *, unsigned *);
+extern bool pt_solution_singleton_or_null_p (struct pt_solution *, unsigned *);
 extern bool pt_solution_includes_global (struct pt_solution *);
 extern bool pt_solution_includes (struct pt_solution *, const_tree);
 extern bool pt_solutions_intersect (struct pt_solution *, struct pt_solution *);
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index fe9a313..61754d8 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -2135,7 +2135,7 @@  fold_builtin_alloca_with_align (gimple *stmt)
       {
 	bool singleton_p;
 	unsigned uid;
-	singleton_p = pt_solution_singleton_p (&pi->pt, &uid);
+	singleton_p = pt_solution_singleton_or_null_p (&pi->pt, &uid);
 	gcc_assert (singleton_p);
 	SET_DECL_PT_UID (var, uid);
       }
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 2a4ab2f..d451ba2 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -6382,6 +6382,8 @@  find_what_var_points_to (tree fndecl, varinfo_t orig_vi)
 
   *slot = pt = XOBNEW (&final_solutions_obstack, struct pt_solution);
   memset (pt, 0, sizeof (struct pt_solution));
+  /* Conservatively set to NULL from PTA (to true). */
+  pt->null = 1;
 
   /* Translate artificial variables into SSA_NAME_PTR_INFO
      attributes.  */
@@ -6391,9 +6393,7 @@  find_what_var_points_to (tree fndecl, varinfo_t orig_vi)
 
       if (vi->is_artificial_var)
 	{
-	  if (vi->id == nothing_id)
-	    pt->null = 1;
-	  else if (vi->id == escaped_id)
+	  if (vi->id == escaped_id)
 	    {
 	      if (in_ipa_mode)
 		pt->ipa_escaped = 1;
@@ -6451,6 +6451,7 @@  find_what_p_points_to (tree fndecl, tree p)
   struct ptr_info_def *pi;
   tree lookup_p = p;
   varinfo_t vi;
+  bool nonnull = get_ptr_nonnull (p);
 
   /* For parameters, get at the points-to set for the actual parm
      decl.  */
@@ -6466,6 +6467,8 @@  find_what_p_points_to (tree fndecl, tree p)
 
   pi = get_ptr_info (p);
   pi->pt = find_what_var_points_to (fndecl, vi);
+  if (nonnull)
+    set_ptr_nonnull (p);
 }
 
 
@@ -6599,10 +6602,10 @@  pt_solution_empty_p (struct pt_solution *pt)
    return the var uid in *UID.  */
 
 bool
-pt_solution_singleton_p (struct pt_solution *pt, unsigned *uid)
+pt_solution_singleton_or_null_p (struct pt_solution *pt, unsigned *uid)
 {
   if (pt->anything || pt->nonlocal || pt->escaped || pt->ipa_escaped
-      || pt->null || pt->vars == NULL
+      || pt->vars == NULL
       || !bitmap_single_bit_set_p (pt->vars))
     return false;
 
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 64ab13a..1d2ec01 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -374,6 +374,28 @@  get_range_info (const_tree name, wide_int *min, wide_int *max)
   return SSA_NAME_RANGE_TYPE (name);
 }
 
+/* Set nonnull attribute to pointer NAME.  */
+
+void
+set_ptr_nonnull (tree name)
+{
+  gcc_assert (POINTER_TYPE_P (TREE_TYPE (name)));
+  struct ptr_info_def *pi = get_ptr_info (name);
+  pi->pt.null = 0;
+}
+
+/* Return nonnull attribute of pointer NAME.  */
+bool
+get_ptr_nonnull (const_tree name)
+{
+  gcc_assert (POINTER_TYPE_P (TREE_TYPE (name)));
+  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
+  if (pi == NULL
+      || pi->pt.anything)
+    return false;
+  return !pi->pt.null;
+}
+
 /* Change non-zero bits bitmask of NAME.  */
 
 void
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index 4496e1d..d39cc9d 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -88,6 +88,8 @@  extern void set_ptr_info_alignment (struct ptr_info_def *, unsigned int,
 extern void adjust_ptr_info_misalignment (struct ptr_info_def *,
 					  unsigned int);
 extern struct ptr_info_def *get_ptr_info (tree);
+extern void set_ptr_nonnull (tree);
+extern bool get_ptr_nonnull (const_tree);
 
 extern tree copy_ssa_name_fn (struct function *, tree, gimple *);
 extern void duplicate_ssa_name_ptr_info (tree, struct ptr_info_def *);
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 8a129c6..7e4f947 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -10603,18 +10603,24 @@  vrp_finalize (bool warn_array_bounds_p)
       {
 	tree name = ssa_name (i);
 
-      if (!name
-	  || POINTER_TYPE_P (TREE_TYPE (name))
-	  || (vr_value[i]->type == VR_VARYING)
-	  || (vr_value[i]->type == VR_UNDEFINED))
-	continue;
+	if (!name
+	    || (vr_value[i]->type == VR_VARYING)
+	    || (vr_value[i]->type == VR_UNDEFINED)
+	    || (TREE_CODE (vr_value[i]->min) != INTEGER_CST)
+	    || (TREE_CODE (vr_value[i]->max) != INTEGER_CST))
+	  continue;
 
-      if ((TREE_CODE (vr_value[i]->min) == INTEGER_CST)
-	  && (TREE_CODE (vr_value[i]->max) == INTEGER_CST)
-	  && (vr_value[i]->type == VR_RANGE
-	      || vr_value[i]->type == VR_ANTI_RANGE))
-	set_range_info (name, vr_value[i]->type, vr_value[i]->min,
-			vr_value[i]->max);
+	if (POINTER_TYPE_P (TREE_TYPE (name))
+	    && ((vr_value[i]->type == VR_RANGE
+		 && range_includes_zero_p (vr_value[i]->min,
+					   vr_value[i]->max) == 0)
+		|| (vr_value[i]->type == VR_ANTI_RANGE
+		    && range_includes_zero_p (vr_value[i]->min,
+					      vr_value[i]->max) == 1)))
+	  set_ptr_nonnull (name);
+	else if (!POINTER_TYPE_P (TREE_TYPE (name)))
+	  set_range_info (name, vr_value[i]->type, vr_value[i]->min,
+			  vr_value[i]->max);
       }
 
   substitute_and_fold (op_with_constant_singleton_value_range,
@@ -10817,17 +10823,25 @@  evrp_dom_walker::before_dom_children (basic_block bb)
 	  def_operand_p def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF);
 	  /* Set the SSA with the value range.  */
 	  if (def_p
-	      && TREE_CODE (DEF_FROM_PTR (def_p)) == SSA_NAME
-	      && INTEGRAL_TYPE_P (TREE_TYPE (DEF_FROM_PTR (def_p))))
+	      && TREE_CODE (DEF_FROM_PTR (def_p)) == SSA_NAME)
 	    {
 	      tree def = DEF_FROM_PTR (def_p);
 	      value_range *vr = get_value_range (def);
 
-	      if ((vr->type == VR_RANGE
-		   || vr->type == VR_ANTI_RANGE)
+	      if (INTEGRAL_TYPE_P (TREE_TYPE (DEF_FROM_PTR (def_p)))
+		  && (vr->type == VR_RANGE
+		      || vr->type == VR_ANTI_RANGE)
 		  && (TREE_CODE (vr->min) == INTEGER_CST)
 		  && (TREE_CODE (vr->max) == INTEGER_CST))
 		set_range_info (def, vr->type, vr->min, vr->max);
+	      else if (POINTER_TYPE_P (TREE_TYPE (DEF_FROM_PTR (def_p)))
+		       && ((vr->type == VR_RANGE
+			    && range_includes_zero_p (vr->min,
+						      vr->max) == 0)
+			   || (vr->type == VR_ANTI_RANGE
+			       && range_includes_zero_p (vr->min,
+							 vr->max) == 1)))
+		set_ptr_nonnull (def);
 	    }
 	}
       else
-- 
2.7.4