]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cgraph.h (symtab_node): Add nonzero_address.
authorJan Hubicka <hubicka@ucw.cz>
Sun, 13 Jul 2014 22:12:54 +0000 (00:12 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 13 Jul 2014 22:12:54 +0000 (22:12 +0000)
* 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.

From-SVN: r212499

gcc/ChangeLog
gcc/c-family/cilk.c
gcc/cgraph.h
gcc/fold-const.c
gcc/symtab.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/nonzero-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tree-ssa/nonzero-2.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr36901.h
gcc/testsuite/gcc.dg/pr44024.c
gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c [new file with mode: 0644]

index 6c639436eb45e2f5ab34bab359b64bbb1f4c5215..6017987531abb1baff7ae15547362e75c615a1c7 100644 (file)
@@ -1,3 +1,13 @@
+2014-07-13  Jan Hubicka  <hubicka@ucw.cz>
+
+       * 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.
+
 2014-07-12  Jan Hubicka  <hubicka@ucw.cz>
 
        * ipa-devirt.c (odr_subtypes_equivalent_p): Disable temporary hack
index 8bdcdcfaad577298ff3a70c29c886e2bc74d8d89..e7332203978a4b9e7ffd40ffb8815fdd4ae70823 100644 (file)
@@ -314,6 +314,7 @@ create_cilk_helper_decl (struct wrapper_data *wd)
   tree block = make_node (BLOCK);
   DECL_INITIAL (fndecl) = block;
   TREE_USED (block) = 1;
+  BLOCK_SUPERCONTEXT (block) = fndecl;
   gcc_assert (!DECL_SAVED_TREE (fndecl));
 
   /* Inlining would defeat the purpose of this wrapper.
index 9ef7bdfe1242aeb8713e25a9318ca70fffd9e93c..b40769a0f44c0a5125df369e764e518579747f01 100644 (file)
@@ -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 varpool_node *node);
 /* 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 d51bda728012c572f33cbdf93007acfd91a21358..6a1c50204bbeca262e5eedb12e7e44ed61a0ed87 100644 (file)
@@ -69,6 +69,7 @@ along with GCC; see the file COPYING3.  If not see
 #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, bool *strict_overflow_p)
     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 deb317d1fb399f5f169f4c58e9b49f1a2d2ffa0b..3a59935d132e20811b40b341ccca970cf59a604c 100644 (file)
@@ -1890,4 +1890,67 @@ symtab_get_symbol_partitioning_class (symtab_node *node)
 
   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"
index 43adb4719edc0e522a0ab4057cab1a263f28c697..be579b6de971da9d71a630a7b964da69e3048801 100644 (file)
@@ -1,3 +1,12 @@
+2014-07-13  Jan Hubicka  <hubicka@ucw.cz>
+
+       * 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.
+
 2014-07-13  Tom de Vries  <tom@codesourcery.com>
 
        * gcc.target/i386/fuse-caller-save-xmm-run.c: New test.
diff --git a/gcc/testsuite/g++.dg/tree-ssa/nonzero-1.C b/gcc/testsuite/g++.dg/tree-ssa/nonzero-1.C
new file mode 100644 (file)
index 0000000..60da49d
--- /dev/null
@@ -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" } } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/nonzero-2.C b/gcc/testsuite/g++.dg/tree-ssa/nonzero-2.C
new file mode 100644 (file)
index 0000000..fdf4114
--- /dev/null
@@ -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 6022732aa13fcb0bc6352cc1ec4a233dcbbddcc2..cf61c993935d9cd73e327482d184b248cdfd020e 100644 (file)
@@ -1,6 +1,2 @@
-#if defined(AVR) /* flag_delete_null_pointer_checks = 0  */
 int sc = (&sc >= 0);
-#else
-int sc = (&sc > 0);
-#endif
 
index f5d72d55f544fc1c907707c861a250d27a663c4f..740d04d48e02217803d511aef94c39b9b294979a 100644 (file)
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c b/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c
new file mode 100644 (file)
index 0000000..c79811b
--- /dev/null
@@ -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" } } */