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]

[PATCH][1/n] Fix PR61034


The following fixes part of PR61034 - we are hindered by false
clobbering during FRE/PRE on paths we try to look through by
means of the alias walker.  The following makes us also
consider lattice-based disambiguation there and in particular
also try harder to disambiguate against builtins.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2014-05-07  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/61034
	* tree-ssa-alias.c (call_may_clobber_ref_p_1): Export.
	(maybe_skip_until): Use translate to take into account
	lattices when trying to do disambiguations.
	(get_continuation_for_phi_1): Likewise.
	(get_continuation_for_phi): Adjust for added translate
	arguments.
	(walk_non_aliased_vuses): Likewise.
	* tree-ssa-alias.h (get_continuation_for_phi): Adjust
	prototype.
	(walk_non_aliased_vuses): Likewise.
	(call_may_clobber_ref_p_1): Declare.
	* tree-ssa-sccvn.c (vn_reference_lookup_3): Also
	disambiguate against calls.  Stop early if we are
	only supposed to disambiguate.
	* tree-ssa-pre.c (translate_vuse_through_block): Adjust.

	* g++.dg/tree-ssa/pr61034.C: New testcase.

Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig	2014-05-07 13:53:47.015599960 +0200
--- gcc/tree-ssa-alias.c	2014-05-07 14:07:09.087544738 +0200
*************** ref_maybe_used_by_stmt_p (gimple stmt, t
*** 1835,1841 ****
  /* If the call in statement CALL may clobber the memory reference REF
     return true, otherwise return false.  */
  
! static bool
  call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
  {
    tree base;
--- 1835,1841 ----
  /* If the call in statement CALL may clobber the memory reference REF
     return true, otherwise return false.  */
  
! bool
  call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
  {
    tree base;
*************** stmt_kills_ref_p (gimple stmt, tree ref)
*** 2318,2324 ****
  static bool
  maybe_skip_until (gimple phi, tree target, ao_ref *ref,
  		  tree vuse, unsigned int *cnt, bitmap *visited,
! 		  bool abort_on_visited)
  {
    basic_block bb = gimple_bb (phi);
  
--- 2318,2326 ----
  static bool
  maybe_skip_until (gimple phi, tree target, ao_ref *ref,
  		  tree vuse, unsigned int *cnt, bitmap *visited,
! 		  bool abort_on_visited,
! 		  void *(*translate)(ao_ref *, tree, void *, bool),
! 		  void *data)
  {
    basic_block bb = gimple_bb (phi);
  
*************** maybe_skip_until (gimple phi, tree targe
*** 2338,2344 ****
  	  if (bitmap_bit_p (*visited, SSA_NAME_VERSION (PHI_RESULT (def_stmt))))
  	    return !abort_on_visited;
  	  vuse = get_continuation_for_phi (def_stmt, ref, cnt,
! 					   visited, abort_on_visited);
  	  if (!vuse)
  	    return false;
  	  continue;
--- 2340,2347 ----
  	  if (bitmap_bit_p (*visited, SSA_NAME_VERSION (PHI_RESULT (def_stmt))))
  	    return !abort_on_visited;
  	  vuse = get_continuation_for_phi (def_stmt, ref, cnt,
! 					   visited, abort_on_visited,
! 					   translate, data);
  	  if (!vuse)
  	    return false;
  	  continue;
*************** maybe_skip_until (gimple phi, tree targe
*** 2350,2356 ****
  	  /* A clobbering statement or the end of the IL ends it failing.  */
  	  ++*cnt;
  	  if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
! 	    return false;
  	}
        /* If we reach a new basic-block see if we already skipped it
           in a previous walk that ended successfully.  */
--- 2353,2365 ----
  	  /* A clobbering statement or the end of the IL ends it failing.  */
  	  ++*cnt;
  	  if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
! 	    {
! 	      if (translate
! 		  && (*translate) (ref, vuse, data, true) == NULL)
! 		;
! 	      else
! 		return false;
! 	    }
  	}
        /* If we reach a new basic-block see if we already skipped it
           in a previous walk that ended successfully.  */
*************** maybe_skip_until (gimple phi, tree targe
*** 2372,2378 ****
  static tree
  get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
  			    ao_ref *ref, unsigned int *cnt,
! 			    bitmap *visited, bool abort_on_visited)
  {
    gimple def0 = SSA_NAME_DEF_STMT (arg0);
    gimple def1 = SSA_NAME_DEF_STMT (arg1);
--- 2381,2389 ----
  static tree
  get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
  			    ao_ref *ref, unsigned int *cnt,
! 			    bitmap *visited, bool abort_on_visited,
! 			    void *(*translate)(ao_ref *, tree, void *, bool),
! 			    void *data)
  {
    gimple def0 = SSA_NAME_DEF_STMT (arg0);
    gimple def1 = SSA_NAME_DEF_STMT (arg1);
*************** get_continuation_for_phi_1 (gimple phi,
*** 2386,2392 ****
  				  gimple_bb (def1), gimple_bb (def0))))
      {
        if (maybe_skip_until (phi, arg0, ref, arg1, cnt,
! 			    visited, abort_on_visited))
  	return arg0;
      }
    else if (gimple_nop_p (def1)
--- 2397,2403 ----
  				  gimple_bb (def1), gimple_bb (def0))))
      {
        if (maybe_skip_until (phi, arg0, ref, arg1, cnt,
! 			    visited, abort_on_visited, translate, data))
  	return arg0;
      }
    else if (gimple_nop_p (def1)
*************** get_continuation_for_phi_1 (gimple phi,
*** 2394,2400 ****
  			      gimple_bb (def0), gimple_bb (def1)))
      {
        if (maybe_skip_until (phi, arg1, ref, arg0, cnt,
! 			    visited, abort_on_visited))
  	return arg1;
      }
    /* Special case of a diamond:
--- 2405,2411 ----
  			      gimple_bb (def0), gimple_bb (def1)))
      {
        if (maybe_skip_until (phi, arg1, ref, arg0, cnt,
! 			    visited, abort_on_visited, translate, data))
  	return arg1;
      }
    /* Special case of a diamond:
*************** get_continuation_for_phi_1 (gimple phi,
*** 2414,2421 ****
  	   && common_vuse == gimple_vuse (def1))
      {
        *cnt += 2;
!       if (!stmt_may_clobber_ref_p_1 (def0, ref)
! 	  && !stmt_may_clobber_ref_p_1 (def1, ref))
  	return common_vuse;
      }
  
--- 2425,2436 ----
  	   && common_vuse == gimple_vuse (def1))
      {
        *cnt += 2;
!       if ((!stmt_may_clobber_ref_p_1 (def0, ref)
! 	   || (translate
! 	       && (*translate) (ref, arg0, data, true) == NULL))
! 	  && (!stmt_may_clobber_ref_p_1 (def1, ref)
! 	      || (translate
! 		  && (*translate) (ref, arg1, data, true) == NULL)))
  	return common_vuse;
      }
  
*************** get_continuation_for_phi_1 (gimple phi,
*** 2432,2438 ****
  tree
  get_continuation_for_phi (gimple phi, ao_ref *ref,
  			  unsigned int *cnt, bitmap *visited,
! 			  bool abort_on_visited)
  {
    unsigned nargs = gimple_phi_num_args (phi);
  
--- 2447,2455 ----
  tree
  get_continuation_for_phi (gimple phi, ao_ref *ref,
  			  unsigned int *cnt, bitmap *visited,
! 			  bool abort_on_visited,
! 			  void *(*translate)(ao_ref *, tree, void *, bool),
! 			  void *data)
  {
    unsigned nargs = gimple_phi_num_args (phi);
  
*************** get_continuation_for_phi (gimple phi, ao
*** 2470,2476 ****
  	{
  	  arg1 = PHI_ARG_DEF (phi, i);
  	  arg0 = get_continuation_for_phi_1 (phi, arg0, arg1, ref,
! 					     cnt, visited, abort_on_visited);
  	  if (!arg0)
  	    return NULL_TREE;
  	}
--- 2487,2494 ----
  	{
  	  arg1 = PHI_ARG_DEF (phi, i);
  	  arg0 = get_continuation_for_phi_1 (phi, arg0, arg1, ref,
! 					     cnt, visited, abort_on_visited,
! 					     translate, data);
  	  if (!arg0)
  	    return NULL_TREE;
  	}
*************** get_continuation_for_phi (gimple phi, ao
*** 2502,2508 ****
  void *
  walk_non_aliased_vuses (ao_ref *ref, tree vuse,
  			void *(*walker)(ao_ref *, tree, unsigned int, void *),
! 			void *(*translate)(ao_ref *, tree, void *), void *data)
  {
    bitmap visited = NULL;
    void *res;
--- 2520,2527 ----
  void *
  walk_non_aliased_vuses (ao_ref *ref, tree vuse,
  			void *(*walker)(ao_ref *, tree, unsigned int, void *),
! 			void *(*translate)(ao_ref *, tree, void *, bool),
! 			void *data)
  {
    bitmap visited = NULL;
    void *res;
*************** walk_non_aliased_vuses (ao_ref *ref, tre
*** 2532,2538 ****
  	break;
        else if (gimple_code (def_stmt) == GIMPLE_PHI)
  	vuse = get_continuation_for_phi (def_stmt, ref, &cnt,
! 					 &visited, translated);
        else
  	{
  	  cnt++;
--- 2551,2557 ----
  	break;
        else if (gimple_code (def_stmt) == GIMPLE_PHI)
  	vuse = get_continuation_for_phi (def_stmt, ref, &cnt,
! 					 &visited, translated, translate, data);
        else
  	{
  	  cnt++;
*************** walk_non_aliased_vuses (ao_ref *ref, tre
*** 2540,2546 ****
  	    {
  	      if (!translate)
  		break;
! 	      res = (*translate) (ref, vuse, data);
  	      /* Failed lookup and translation.  */
  	      if (res == (void *)-1)
  		{
--- 2559,2565 ----
  	    {
  	      if (!translate)
  		break;
! 	      res = (*translate) (ref, vuse, data, false);
  	      /* Failed lookup and translation.  */
  	      if (res == (void *)-1)
  		{
Index: gcc/tree-ssa-alias.h
===================================================================
*** gcc/tree-ssa-alias.h.orig	2014-05-07 13:53:47.015599960 +0200
--- gcc/tree-ssa-alias.h	2014-05-07 14:07:09.088544738 +0200
*************** extern bool stmt_may_clobber_global_p (g
*** 110,122 ****
  extern bool stmt_may_clobber_ref_p (gimple, tree);
  extern bool stmt_may_clobber_ref_p_1 (gimple, ao_ref *);
  extern bool call_may_clobber_ref_p (gimple, tree);
  extern bool stmt_kills_ref_p (gimple, tree);
  extern tree get_continuation_for_phi (gimple, ao_ref *,
! 				      unsigned int *, bitmap *, bool);
  extern void *walk_non_aliased_vuses (ao_ref *, tree,
  				     void *(*)(ao_ref *, tree,
  					       unsigned int, void *),
! 				     void *(*)(ao_ref *, tree, void *), void *);
  extern unsigned int walk_aliased_vdefs (ao_ref *, tree,
  					bool (*)(ao_ref *, tree, void *),
  					void *, bitmap *);
--- 110,126 ----
  extern bool stmt_may_clobber_ref_p (gimple, tree);
  extern bool stmt_may_clobber_ref_p_1 (gimple, ao_ref *);
  extern bool call_may_clobber_ref_p (gimple, tree);
+ extern bool call_may_clobber_ref_p_1 (gimple, ao_ref *);
  extern bool stmt_kills_ref_p (gimple, tree);
  extern tree get_continuation_for_phi (gimple, ao_ref *,
! 				      unsigned int *, bitmap *, bool,
! 				      void *(*)(ao_ref *, tree, void *, bool),
! 				      void *);
  extern void *walk_non_aliased_vuses (ao_ref *, tree,
  				     void *(*)(ao_ref *, tree,
  					       unsigned int, void *),
! 				     void *(*)(ao_ref *, tree, void *, bool),
! 				     void *);
  extern unsigned int walk_aliased_vdefs (ao_ref *, tree,
  					bool (*)(ao_ref *, tree, void *),
  					void *, bitmap *);
Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c.orig	2014-05-07 13:53:47.015599960 +0200
--- gcc/tree-ssa-sccvn.c	2014-05-07 14:07:27.320543483 +0200
*************** vn_reference_lookup_or_insert_for_pieces
*** 1542,1548 ****
     of VUSE.  */
  
  static void *
! vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
  {
    vn_reference_t vr = (vn_reference_t)vr_;
    gimple def_stmt = SSA_NAME_DEF_STMT (vuse);
--- 1542,1549 ----
     of VUSE.  */
  
  static void *
! vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
! 		       bool disambiguate_only)
  {
    vn_reference_t vr = (vn_reference_t)vr_;
    gimple def_stmt = SSA_NAME_DEF_STMT (vuse);
*************** vn_reference_lookup_3 (ao_ref *ref, tree
*** 1580,1585 ****
--- 1581,1619 ----
  	  lhs_ref_ok = true;
  	}
      }
+   else if (gimple_call_builtin_p (def_stmt, BUILT_IN_NORMAL)
+ 	   && gimple_call_num_args (def_stmt) <= 4)
+     {
+       /* For builtin calls valueize its arguments and call the
+          alias oracle again.  Valueization may improve points-to
+ 	 info of pointers and constify size and position arguments.
+ 	 Originally this was motivated by PR61034 which has
+ 	 conditional calls to free falsely clobbering ref because
+ 	 of imprecise points-to info of the argument.  */
+       tree oldargs[4];
+       bool valueized_anything;
+       for (unsigned i = 0; i < gimple_call_num_args (def_stmt); ++i)
+ 	{
+ 	  oldargs[i] = gimple_call_arg (def_stmt, i);
+ 	  if (TREE_CODE (oldargs[i]) == SSA_NAME
+ 	      && VN_INFO (oldargs[i])->valnum != oldargs[i])
+ 	    {
+ 	      gimple_call_set_arg (def_stmt, i, VN_INFO (oldargs[i])->valnum);
+ 	      valueized_anything = true;
+ 	    }
+ 	}
+       if (valueized_anything)
+ 	{
+ 	  bool res = call_may_clobber_ref_p_1 (def_stmt, ref);
+ 	  for (unsigned i = 0; i < gimple_call_num_args (def_stmt); ++i)
+ 	    gimple_call_set_arg (def_stmt, i, oldargs[i]);
+ 	  if (!res)
+ 	    return NULL;
+ 	}
+     }
+ 
+   if (disambiguate_only)
+     return (void *)-1;
  
    base = ao_ref_base (ref);
    offset = ref->offset;
Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c.orig	2014-05-07 13:53:47.015599960 +0200
--- gcc/tree-ssa-pre.c	2014-05-07 14:07:09.091544738 +0200
*************** translate_vuse_through_block (vec<vn_ref
*** 1308,1314 ****
  	  unsigned int cnt;
  	  /* Try to find a vuse that dominates this phi node by skipping
  	     non-clobbering statements.  */
! 	  vuse = get_continuation_for_phi (phi, &ref, &cnt, &visited, false);
  	  if (visited)
  	    BITMAP_FREE (visited);
  	}
--- 1308,1315 ----
  	  unsigned int cnt;
  	  /* Try to find a vuse that dominates this phi node by skipping
  	     non-clobbering statements.  */
! 	  vuse = get_continuation_for_phi (phi, &ref, &cnt, &visited, false,
! 					   NULL, NULL);
  	  if (visited)
  	    BITMAP_FREE (visited);
  	}
Index: gcc/testsuite/g++.dg/tree-ssa/pr61034.C
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/g++.dg/tree-ssa/pr61034.C	2014-05-07 14:07:09.091544738 +0200
***************
*** 0 ****
--- 1,45 ----
+ // { dg-do compile }
+ // { dg-options "-O3 -fdump-tree-fre2" }
+ 
+ #define assume(x) if(!(x))__builtin_unreachable()
+ 
+ inline void* operator new(__SIZE_TYPE__ n){ return __builtin_malloc(n); }
+ inline void operator delete(void *p) { __builtin_free(p); }
+ struct O {
+     double num;
+     int count;
+ };
+ struct I {
+     O *o;
+     I(double d = 0) : o (new O) { o->num = d; o->count = 1; }
+     I(I const&i) { assume(i.o->count >= 1); o = i.o; ++o->count; }
+     I& operator=(I const&i) { I(i).swap(*this); return *this; }
+     ~I() { if (--o->count == 0) delete o; }
+     void swap(I& i) { O *tmp = o; o = i.o; i.o = tmp; }
+     I& operator*= (I const&i) {
+ 	if (o->count > 1) *this = I(o->num);
+ 	o->num *= i.o->num;
+ 	return *this;
+     }
+     I& operator-= (I const&i) {
+ 	if (o->count > 1) *this = I(o->num);
+ 	o->num -= i.o->num;
+ 	return *this;
+     }
+ };
+ inline I operator* (I a, I const&b) { return a *= b; }
+ inline I operator- (I a, I const&b) { return a -= b; }
+ inline bool operator< (I const&a, I const&b) { return a.o->num < b.o->num; }
+ 
+ bool f(I a, I b, I c, I d) {
+     return (a * d - b * c) * (a * b - c * d) < 42;
+ }
+ 
+ // We should be able to CSE most references to count and thus remove
+ // a bunch of conditional free()s and unreachable()s.
+ // This works only if everything is inlined into 'f'.
+ 
+ // { dg-final { scan-tree-dump-times ";; Function" 1 "fre2" } }
+ // { dg-final { scan-tree-dump-times "free" 19 "fre2" } }
+ // { dg-final { scan-tree-dump-times "unreachable" 11 "fre2" } }
+ // { dg-final { cleanup-tree-dump "fre2" } }


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