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] Fix parts of PR41186


The alias-oracle doesn't look at the size argument of builtin
memory or string copy routines.  The following adds this
to deal with the C++ frontend often emitting memcpy for
base class assignments.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2009-08-30  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/41186
	* tree-ssa-alias.c (ptr_deref_may_alias_ref_p): Remove.
	(ao_ref_init_from_ptr_and_size): New function.
	(ref_maybe_used_by_call_p_1): Be more precise tracking
	used ranges for builtin functions.
	(ref_maybe_used_by_call_p): Adjust.
	(call_may_clobber_ref_p_1): Be more precise tracking clobbered
	ranges for builtin functions.
	* tree-ssa-alias.h (ao_ref_init_from_ptr_and_size): Declare.

	* g++.dg/torture/pr41186.C: New testcase.
	* g++.dg/tree-ssa/pr41186.C: Likewise.

Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c	(revision 151175)
--- gcc/tree-ssa-alias.c	(working copy)
*************** ptr_deref_may_alias_ref_p_1 (tree ptr, a
*** 302,315 ****
    return true;
  }
  
- static bool
- ptr_deref_may_alias_ref_p (tree ptr, tree ref)
- {
-   ao_ref r;
-   ao_ref_init (&r, ref);
-   return ptr_deref_may_alias_ref_p_1 (ptr, &r);
- }
- 
  
  /* Dump alias information on FILE.  */
  
--- 302,307 ----
*************** ao_ref_alias_set (ao_ref *ref)
*** 490,495 ****
--- 482,515 ----
    return ref->ref_alias_set;
  }
  
+ /* Init an alias-oracle reference representation from a gimple pointer
+    PTR and a gimple size SIZE in bytes.  If SIZE is NULL_TREE the the
+    size is assumed to be unknown.  The access is assumed to be only
+    to or after of the pointer target, not before it.  */
+ 
+ void
+ ao_ref_init_from_ptr_and_size (ao_ref *ref, tree ptr, tree size)
+ {
+   HOST_WIDE_INT t1, t2;
+   ref->ref = NULL_TREE;
+   if (TREE_CODE (ptr) == ADDR_EXPR)
+     ref->base = get_ref_base_and_extent (TREE_OPERAND (ptr, 0),
+ 					 &ref->offset, &t1, &t2);
+   else
+     {
+       ref->base = build1 (INDIRECT_REF, char_type_node, ptr);
+       ref->offset = 0;
+     }
+   if (size
+       && host_integerp (size, 0)
+       && TREE_INT_CST_LOW (size) * 8 / 8 == TREE_INT_CST_LOW (size))
+     ref->max_size = ref->size = TREE_INT_CST_LOW (size) * 8;
+   else
+     ref->max_size = ref->size = -1;
+   ref->ref_alias_set = 0;
+   ref->base_alias_set = 0;
+ }
+ 
  /* Return 1 if TYPE1 and TYPE2 are to be considered equivalent for the
     purpose of TBAA.  Return 0 if they are distinct and -1 if we cannot
     decide.  */
*************** refs_output_dependent_p (tree store1, tr
*** 854,860 ****
     otherwise return false.  */
  
  static bool
! ref_maybe_used_by_call_p_1 (gimple call, tree ref)
  {
    tree base, callee;
    unsigned i;
--- 874,880 ----
     otherwise return false.  */
  
  static bool
! ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
  {
    tree base, callee;
    unsigned i;
*************** ref_maybe_used_by_call_p_1 (gimple call,
*** 865,871 ****
        && (flags & (ECF_CONST|ECF_NOVOPS)))
      goto process_args;
  
!   base = get_base_address (ref);
    if (!base)
      return true;
  
--- 885,891 ----
        && (flags & (ECF_CONST|ECF_NOVOPS)))
      goto process_args;
  
!   base = ao_ref_base (ref);
    if (!base)
      return true;
  
*************** ref_maybe_used_by_call_p_1 (gimple call,
*** 899,906 ****
  	case BUILT_IN_STRCAT:
  	case BUILT_IN_STRNCAT:
  	  {
! 	    tree src = gimple_call_arg (call, 1);
! 	    return ptr_deref_may_alias_ref_p (src, ref);
  	  }
  	/* The following builtins do not read from memory.  */
  	case BUILT_IN_FREE:
--- 919,932 ----
  	case BUILT_IN_STRCAT:
  	case BUILT_IN_STRNCAT:
  	  {
! 	    ao_ref dref;
! 	    tree size = NULL_TREE;
! 	    if (gimple_call_num_args (call) == 3)
! 	      size = gimple_call_arg (call, 2);
! 	    ao_ref_init_from_ptr_and_size (&dref,
! 					   gimple_call_arg (call, 1),
! 					   size);
! 	    return refs_may_alias_p_1 (&dref, ref, false);
  	  }
  	/* The following builtins do not read from memory.  */
  	case BUILT_IN_FREE:
*************** process_args:
*** 1004,1012 ****
  	op = TREE_OPERAND (op, 0);
  
        if (TREE_CODE (op) != SSA_NAME
! 	  && !is_gimple_min_invariant (op)
! 	  && refs_may_alias_p (op, ref))
! 	return true;
      }
  
    return false;
--- 1030,1042 ----
  	op = TREE_OPERAND (op, 0);
  
        if (TREE_CODE (op) != SSA_NAME
! 	  && !is_gimple_min_invariant (op))
! 	{
! 	  ao_ref r;
! 	  ao_ref_init (&r, op);
! 	  if (refs_may_alias_p_1 (&r, ref, true))
! 	    return true;
! 	}
      }
  
    return false;
*************** process_args:
*** 1015,1021 ****
  static bool
  ref_maybe_used_by_call_p (gimple call, tree ref)
  {
!   bool res = ref_maybe_used_by_call_p_1 (call, ref);
    if (res)
      ++alias_stats.ref_maybe_used_by_call_p_may_alias;
    else
--- 1045,1054 ----
  static bool
  ref_maybe_used_by_call_p (gimple call, tree ref)
  {
!   ao_ref r;
!   bool res;
!   ao_ref_init (&r, ref);
!   res = ref_maybe_used_by_call_p_1 (call, &r);
    if (res)
      ++alias_stats.ref_maybe_used_by_call_p_may_alias;
    else
*************** call_may_clobber_ref_p_1 (gimple call, a
*** 1106,1120 ****
  	case BUILT_IN_STPNCPY:
  	case BUILT_IN_STRCAT:
  	case BUILT_IN_STRNCAT:
  	  {
! 	    tree dest = gimple_call_arg (call, 0);
! 	    return ptr_deref_may_alias_ref_p_1 (dest, ref);
  	  }
  	/* Freeing memory kills the pointed-to memory.  More importantly
  	   the call has to serve as a barrier for moving loads and stores
! 	   across it.  Same is true for memset.  */
  	case BUILT_IN_FREE:
- 	case BUILT_IN_MEMSET:
  	  {
  	    tree ptr = gimple_call_arg (call, 0);
  	    return ptr_deref_may_alias_ref_p_1 (ptr, ref);
--- 1139,1159 ----
  	case BUILT_IN_STPNCPY:
  	case BUILT_IN_STRCAT:
  	case BUILT_IN_STRNCAT:
+ 	case BUILT_IN_MEMSET:
  	  {
! 	    ao_ref dref;
! 	    tree size = NULL_TREE;
! 	    if (gimple_call_num_args (call) == 3)
! 	      size = gimple_call_arg (call, 2);
! 	    ao_ref_init_from_ptr_and_size (&dref,
! 					   gimple_call_arg (call, 0),
! 					   size);
! 	    return refs_may_alias_p_1 (&dref, ref, false);
  	  }
  	/* Freeing memory kills the pointed-to memory.  More importantly
  	   the call has to serve as a barrier for moving loads and stores
! 	   across it.  */
  	case BUILT_IN_FREE:
  	  {
  	    tree ptr = gimple_call_arg (call, 0);
  	    return ptr_deref_may_alias_ref_p_1 (ptr, ref);
Index: gcc/tree-ssa-alias.h
===================================================================
*** gcc/tree-ssa-alias.h	(revision 151175)
--- gcc/tree-ssa-alias.h	(working copy)
*************** typedef struct ao_ref_s
*** 88,93 ****
--- 88,94 ----
  
  /* In tree-ssa-alias.c  */
  extern void ao_ref_init (ao_ref *, tree);
+ extern void ao_ref_init_from_ptr_and_size (ao_ref *, tree, tree);
  extern tree ao_ref_base (ao_ref *);
  extern alias_set_type ao_ref_alias_set (ao_ref *);
  extern bool ptr_deref_may_alias_global_p (tree);
Index: gcc/testsuite/g++.dg/torture/pr41186.C
===================================================================
*** gcc/testsuite/g++.dg/torture/pr41186.C	(revision 0)
--- gcc/testsuite/g++.dg/torture/pr41186.C	(revision 0)
***************
*** 0 ****
--- 1,29 ----
+ /* { dg-do run } */
+ 
+ struct Foo {
+   Foo() {};
+   int i;
+   short f;
+ };
+ struct Bar : public Foo {
+   Bar() {};
+   short b;
+ };
+ 
+ extern "C" void abort(void);
+ 
+ int main()
+ {
+   Bar b1, b2;
+   b2.i = 0;
+   b1.f = 0;
+   b1.b = 1;
+   b2.f = 1;
+   b2.b = 2;
+   static_cast<Foo&>(b1) = static_cast<Foo&>(b2);
+   if (b1.i != 0 || b1.b != 1)
+     abort ();
+   if (b1.f != 1)
+     abort ();
+   return 0;
+ }
Index: gcc/testsuite/g++.dg/tree-ssa/pr41186.C
===================================================================
*** gcc/testsuite/g++.dg/tree-ssa/pr41186.C	(revision 0)
--- gcc/testsuite/g++.dg/tree-ssa/pr41186.C	(revision 0)
***************
*** 0 ****
--- 1,35 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre-details" } */
+ 
+ struct Foo {
+   Foo() {};
+   int i;
+   short f;
+ };
+ struct Bar : public Foo {
+   Bar() {};
+   short b;
+ };
+ 
+ extern "C" void abort(void);
+ 
+ int main()
+ {
+   Bar b1, b2;
+   b2.i = 0;
+   b1.f = 0;
+   b1.b = 1;
+   b2.f = 1;
+   b2.b = 2;
+   static_cast<Foo&>(b1) = static_cast<Foo&>(b2);
+   if (b1.i != 0 || b1.b != 1)
+     abort ();
+   if (b1.f != 1)
+     abort ();
+   return 0;
+ }
+ 
+ /* { dg-final { scan-tree-dump "Replaced b1.b with 1" "fre" } } */
+ /* { dg-final { scan-tree-dump "Replaced b1.i with 0" "fre" { xfail *-*-* } } } */
+ /* { dg-final { scan-tree-dump "Replaced b1.f with 1" "fre" { xfail *-*-* } } } */
+ /* { dg-final { cleanup-tree-dump "fre" } } */


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