This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] Making fold-const sane WRT symbol visibilities


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"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]