Hi,
this is variant of patch I comitted (the change is only testsuite compensation
for pr36902 and 44024) and updated predicate name to nonzero_address

Honza

        * cgraph.h (symtab_node): Add nonzero_address.
        (decl_in_symtab_p): Break out from ...
        (symtab_get_node): ... here.
        * fold-const.c: Include cgraph.h
        (tree_single_nonzero_warnv_p): Use symtab to determine
        if symbol is non-zero.
        * symtab.c (symtab_node::nonzero_address): New method.

        * gcc.dg/pr36901.h: Simplify because non-zero symbol folding no
        longer happens during parsing.
        * gcc.dg/pr44024.c: Update template.
        * g++.dg/tree-ssa/nonzero-2.C: New testcase.
        * g++.dg/tree-ssa/nonzero-1.C: New testcase.
        * gcc.dg/tree-ssa/nonzero-1.c: New testcase.
        
Index: cgraph.h
===================================================================
--- cgraph.h    (revision 212495)
+++ cgraph.h    (working copy)
@@ -282,6 +282,9 @@ public:
 
   void set_init_priority (priority_type priority);
   priority_type get_init_priority ();
+
+  /* Return true if symbol is known to be nonzero.  */
+  bool nonzero_address ();
 };
 
 /* Walk all aliases for NODE.  */
@@ -1148,6 +1151,17 @@ tree varpool_get_constructor (struct var
 /* In cgraph.c */
 extern void change_decl_assembler_name (tree, tree);
 
+/* Return true if DECL should have entry in symbol table if used.
+   Those are functions and static & external veriables*/
+
+static bool
+decl_in_symtab_p (const_tree decl)
+{
+  return (TREE_CODE (decl) == FUNCTION_DECL
+          || (TREE_CODE (decl) == VAR_DECL
+             && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))));
+}
+
 /* Return symbol table node associated with DECL, if any,
    and NULL otherwise.  */
 
@@ -1155,12 +1169,7 @@ static inline symtab_node *
 symtab_get_node (const_tree decl)
 {
 #ifdef ENABLE_CHECKING
-  /* Check that we are called for sane type of object - functions
-     and static or external variables.  */
-  gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL
-                      || (TREE_CODE (decl) == VAR_DECL
-                          && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
-                              || in_lto_p)));
+  gcc_checking_assert (decl_in_symtab_p (decl));
   /* Check that the mapping is sane - perhaps this check can go away,
      but at the moment frontends tends to corrupt the mapping by calling
      memcpy/memset on the tree nodes.  */
Index: fold-const.c
===================================================================
--- fold-const.c        (revision 212495)
+++ fold-const.c        (working copy)
@@ -69,6 +69,7 @@ along with GCC; see the file COPYING3.
 #include "tree-dfa.h"
 #include "hash-table.h"  /* Required for ENABLE_FOLD_CHECKING.  */
 #include "builtins.h"
+#include "cgraph.h"
 
 /* Nonzero if we are folding constants inside an initializer; zero
    otherwise.  */
@@ -16020,21 +16021,33 @@ tree_single_nonzero_warnv_p (tree t, boo
     case ADDR_EXPR:
       {
        tree base = TREE_OPERAND (t, 0);
+
        if (!DECL_P (base))
          base = get_base_address (base);
 
        if (!base)
          return false;
 
-       /* Weak declarations may link to NULL.  Other things may also be NULL
-          so protect with -fdelete-null-pointer-checks; but not variables
-          allocated on the stack.  */
+       /* For objects in symbol table check if we know they are non-zero.
+          Don't do anything for variables and functions before symtab is built;
+          it is quite possible that they will be declared weak later.  */
+       if (DECL_P (base) && decl_in_symtab_p (base))
+         {
+           struct symtab_node *symbol;
+
+           symbol = symtab_get_node (base);
+           if (symbol)
+             return symbol->nonzero_address ();
+           else
+             return false;
+         }
+
+       /* Function local objects are never NULL.  */
        if (DECL_P (base)
-           && (flag_delete_null_pointer_checks
-               || (DECL_CONTEXT (base)
-                   && TREE_CODE (DECL_CONTEXT (base)) == FUNCTION_DECL
-                   && auto_var_in_fn_p (base, DECL_CONTEXT (base)))))
-         return !VAR_OR_FUNCTION_DECL_P (base) || !DECL_WEAK (base);
+           && (DECL_CONTEXT (base)
+               && TREE_CODE (DECL_CONTEXT (base)) == FUNCTION_DECL
+               && auto_var_in_fn_p (base, DECL_CONTEXT (base))))
+         return true;
 
        /* Constants are never weak.  */
        if (CONSTANT_CLASS_P (base))
Index: testsuite/gcc.dg/pr36901.h
===================================================================
--- testsuite/gcc.dg/pr36901.h  (revision 212495)
+++ testsuite/gcc.dg/pr36901.h  (working copy)
@@ -1,6 +1,2 @@
-#if defined(AVR) /* flag_delete_null_pointer_checks = 0  */
 int sc = (&sc >= 0);
-#else
-int sc = (&sc > 0);
-#endif
 
Index: testsuite/gcc.dg/pr44024.c
===================================================================
--- testsuite/gcc.dg/pr44024.c  (revision 212495)
+++ testsuite/gcc.dg/pr44024.c  (working copy)
@@ -1,5 +1,5 @@
 /* { dg-do link } */
-/* { dg-options "-fdelete-null-pointer-checks -fdump-tree-original" } */
+/* { dg-options "-fdelete-null-pointer-checks -fdump-tree-ccp1" } */
 
 void foo();
 
@@ -10,5 +10,5 @@ int main()
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-not "foo" "original" { target { ! avr*-*-* } } 
} } */
-/* { dg-final { cleanup-tree-dump "original" } } */
+/* { dg-final { scan-tree-dump-not "foo" "ccp1" { target { ! avr*-*-* } } } } 
*/
+/* { dg-final { cleanup-tree-dump "ccp1" } } */
Index: testsuite/gcc.dg/tree-ssa/nonzero-1.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/nonzero-1.c       (revision 0)
+++ testsuite/gcc.dg/tree-ssa/nonzero-1.c       (revision 0)
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+extern int a;
+t()
+{
+  return &a!=0;
+}
+extern int a __attribute__ ((weak));
+
+/* { dg-final { scan-tree-dump-not "return 1" "optimized"} } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
Index: testsuite/g++.dg/tree-ssa/nonzero-1.C
===================================================================
--- testsuite/g++.dg/tree-ssa/nonzero-1.C       (revision 0)
+++ testsuite/g++.dg/tree-ssa/nonzero-1.C       (revision 0)
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ccp1" } */
+inline void t()
+{
+}
+int m()
+{
+  void *q = (void *)&t;
+  return q != 0;
+}
+/* { dg-final { scan-tree-dump "return 1" "ccp1"} } */
+/* { dg-final { cleanup-tree-dump "ccp1" } } */
Index: testsuite/g++.dg/tree-ssa/nonzero-2.C
===================================================================
--- testsuite/g++.dg/tree-ssa/nonzero-2.C       (revision 0)
+++ testsuite/g++.dg/tree-ssa/nonzero-2.C       (revision 0)
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ccp1 -fdelete-null-pointer-checks" } */
+struct t
+{
+  static inline void tt()
+  {
+  }
+  virtual void q();
+};
+int m()
+{
+  void *q = (void *)&t::tt;
+  return q != 0;
+}
+/* { dg-final { scan-tree-dump "return 1" "ccp1"} } */
+/* { dg-final { cleanup-tree-dump "ccp1" } } */
Index: symtab.c
===================================================================
--- symtab.c    (revision 212495)
+++ symtab.c    (working copy)
@@ -1890,4 +1890,67 @@ symtab_get_symbol_partitioning_class (sy
 
   return SYMBOL_PARTITION;
 }
+
+/* Return true when symbol is known to be non-zero.  */
+
+bool
+symtab_node::nonzero_address ()
+{
+  /* Weakrefs may be NULL when their target is not defined.  */
+  if (this->alias && this->weakref)
+    {
+      if (this->analyzed)
+       {
+         symtab_node *target = symtab_alias_ultimate_target (this);
+
+         if (target->alias && target->weakref)
+           return false;
+         /* We can not recurse to target::nonzero.  It is possible that the
+            target is used only via the alias.
+            We may walk references and look for strong use, but we do not know
+            if this strong use will survive to final binary, so be
+            conservative here.  
+            ??? Maybe we could do the lookup during late optimization that
+            could be useful to eliminate the NULL pointer checks in LTO
+            programs.  */
+         if (target->definition && !DECL_EXTERNAL (target->decl))
+           return true;
+         if (target->resolution != LDPR_UNKNOWN
+             && target->resolution != LDPR_UNDEF
+             && flag_delete_null_pointer_checks)
+           return true;
+         return false;
+       }
+      else
+        return false;
+    }
+
+  /* With !flag_delete_null_pointer_checks we assume that symbols may
+     bind to NULL. This is on by default on embedded targets only.
+
+     Otherwise all non-WEAK symbols must be defined and thus non-NULL or
+     linking fails.  Important case of WEAK we want to do well are comdats.
+     Those are handled by later check for definition.
+
+     When parsing, beware the cases when WEAK attribute is added later.  */
+  if (!DECL_WEAK (this->decl)
+      && flag_delete_null_pointer_checks
+      && cgraph_state > CGRAPH_STATE_PARSING)
+    return true;
+
+  /* If target is defined and not extern, we know it will be output and thus
+     it will bind to non-NULL.
+     Play safe for flag_delete_null_pointer_checks where weak definition maye
+     be re-defined by NULL.  */
+  if (this->definition && !DECL_EXTERNAL (this->decl)
+      && (flag_delete_null_pointer_checks || !DECL_WEAK (this->decl)))
+    return true;
+
+  /* As the last resort, check the resolution info.  */
+  if (this->resolution != LDPR_UNKNOWN
+      && this->resolution != LDPR_UNDEF
+      && flag_delete_null_pointer_checks)
+    return true;
+  return false;
+}
 #include "gt-symtab.h"

Reply via email to