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: [PATCH] Fix C++ strict-aliasing issues with memcpy folding


On Tue, 2 Feb 2010, Gabriel Dos Reis wrote:

> >> ah, but that transformation to plain assignment is middle-end
> >> gimmicks, not C++ source-level constructs. ?I think the middle-end
> >> should probably annotate that transformation (probably as
> >> a VIEW_CONVERT_EXPR?) since the standard explicitly says that one can
> >> move valid objects around with memcpy() (for objects of POD type.)
> >> And surely the library should use memcpy() to copy objects with
> >> statically ambiguous type.
> >>
> >> Does the annotation idea makes sense to the middle-end?
> >
> > Yes. ?I was playing with that during the weekend and have some
> > prototype patch that I need to clean up a bit.
> 
> That would be fantastic.

Current prototype attached.  It bootstraps and tests fine (well,
before some cleanup done) but still has some minor regressions.

The idea is to continue to fold memcpys into assignments (and thus
the frontends should use memcpy when they mean it).  To retain
the alias-set zeroness of the folded assignments we do the copy
in char[] type.  Encoding this using TARGET_MEM_REFs:

  MEM[symbol: j] = MEM[symbol: i];

where TREE_TYPE of the MEMs is char[4].  If later nothing takes
the address of j anymore we re-write the symbols into SSA form
like:

  j_7 = VIEW_CONVERT_EXPR<int>(MEM[symbol: i]);

I don't consider the patch appropriate for 4.5.
As the memcpy folding bug isn't a regression and we have a workaround
for libstdc++ in place I consider not fixing the bug for 4.5.

Thanks,
Richard.


FAIL: gcc.dg/memcpy-1.c scan-tree-dump-times optimized "nasty_local\\." 0

  SRA (and get_ref_base_and_extent) need to handle

    MEM[symbol: nasty_local] = MEM[symbol: a];
    D.1958_1 = nasty_local.a;

  but SRA build-ref-for-offset has to be careful to build alias-set
  zero references to a.

FAIL: gfortran.dg/array_memcpy_4.f90  -O  scan-tree-dump-times original "d = " 1

  The frontend should directly emit assignments with array type
  as it probably knows that using alias-set zero memcpy is not needed.
  As with Ada char_type_node doesn't have alias-set zero, so we do
  not fold.

FAIL: gcc.dg/tree-prof/stringop-1.c scan-tree-dump optimized "a.0. = "
FAIL: gcc.dg/tree-prof/stringop-1.c scan-tree-dump optimized "= b.0."

  Dump needs adjustment

FAIL: gcc.target/i386/memcpy-1.c scan-assembler-not test

FAIL: gfortran.dg/scalarize_parameter_array_1.f90  -O1  execution test
FAIL: libgomp.fortran/character1.f90  -O1  execution test


2010-01-31  Richard Guenther  <rguenther@suse.de>

	PR middle-end/42834
	* tree-ssa.c (execute_update_addresses_taken): Rewrite
	TARGET_MEM_REFs into plain assignments if we want to
	rename its symbol.
	* tree-flow.h (symbol_marked_for_renaming): Declare.
	* tree-into-ssa.c (symbol_marked_for_renaming): Export.
	* gimple.c (is_gimple_addressable): TARGET_MEM_REFs are
	addressable.
	(is_gimple_address): Likewise.
	* tree-ssa-sccvn.c (copy_reference_ops_from_ref): Handle
	wrapped TARGET_MEM_REFs.
	(visit_reference_op_store): Enter converted TARGET_MEM_REFs
	into the tables.
	* alias.c (get_alias_set): Use TMR_ORIGINAL only if it
	is available.
	* builtins.c (fold_builtin_memory_op): Make sure to use
	alias-set zero for copies by using TARGET_MEM_REFs of char[]
	type.
	* tree-ssa-operands.c (get_tmr_operands): Mark TMR_SYMBOL
	addressable only if it cannot be rewritten into SSA form.
	* tree-ssa-alias.c (refs_may_alias_p_1): Adjust bailout for
	TARGET_MEM_REFs.
	* tree-eh.c (tree_could_trap_p): Handle NULL TMR_ORIGINAL.
	* gimplify.c (gimplify_expr): Handle DECL_VALUE_EXPR
	modifications when gimplifying TARGET_MEM_REF.
	* tree-nested.c (convert_local_reference_op): Handle TARGET_MEM_REF.

	* gcc.dg/pr42834.c: New testcase.
	* gcc.c-torture/compile/20100131-1.c: Likewise.
	* g++.dg/torture/pr42834.C: Likewise.

Index: gcc/tree-ssa.c
===================================================================
*** gcc/tree-ssa.c.orig	2010-02-02 13:15:12.000000000 +0100
--- gcc/tree-ssa.c	2010-02-02 15:11:25.000000000 +0100
*************** execute_update_addresses_taken (bool do_
*** 1933,1945 ****
  	    {
                tree lhs = gimple_get_lhs (stmt);
  
-               /* We may not rewrite TMR_SYMBOL to SSA.  */
-               if (lhs && TREE_CODE (lhs) == TARGET_MEM_REF
-                   && TMR_SYMBOL (lhs))
-                 bitmap_set_bit (not_reg_needs, DECL_UID (TMR_SYMBOL (lhs)));
- 
                /* A plain decl does not need it set.  */
!               else if (lhs && handled_component_p (lhs))
                  {
                    var = get_base_address (lhs);
                    if (DECL_P (var))
--- 1933,1940 ----
  	    {
                tree lhs = gimple_get_lhs (stmt);
  
                /* A plain decl does not need it set.  */
!               if (lhs && handled_component_p (lhs))
                  {
                    var = get_base_address (lhs);
                    if (DECL_P (var))
*************** execute_update_addresses_taken (bool do_
*** 2021,2026 ****
--- 2016,2075 ----
  	    {
  	      gimple stmt = gsi_stmt (gsi);
  
+ 	      /* Re-write TARGET_MEM_REFs of symbols we want to
+ 		 rewrite into SSA form.  */
+ 	      if (gimple_assign_single_p (stmt))
+ 		{
+ 		  tree lhs = gimple_assign_lhs (stmt);
+ 		  tree rhs, *rhsp = gimple_assign_rhs1_ptr (stmt);
+ 		  tree sym;
+ 
+ 		  /* We shouldn't have any fancy wrapping of
+ 		     component-refs on the LHS, but look through
+ 		     VIEW_CONVERT_EXPRs as that is easy.  */
+ 		  while (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
+ 		    lhs = TREE_OPERAND (lhs, 0);
+ 		  if (TREE_CODE (lhs) == TARGET_MEM_REF
+ 		      && (sym = TMR_SYMBOL (lhs))
+ 		      && !TREE_ADDRESSABLE (sym)
+ 		      && symbol_marked_for_renaming (sym))
+ 		    lhs = sym;
+ 		  else
+ 		    lhs = gimple_assign_lhs (stmt);
+ 
+ 		  /* We can have fancy wrappings on the RHS though.  */
+ 		  while (handled_component_p (*rhsp))
+ 		    rhsp = &TREE_OPERAND (*rhsp, 0);
+ 		  if (TREE_CODE (*rhsp) == TARGET_MEM_REF
+ 		      && (sym = TMR_SYMBOL (*rhsp))
+ 		      && !TREE_ADDRESSABLE (sym)
+ 		      && symbol_marked_for_renaming (sym))
+ 		    {
+ 		      if (!useless_type_conversion_p (TREE_TYPE (*rhsp),
+ 						      TREE_TYPE (sym)))
+ 			*rhsp = build1 (VIEW_CONVERT_EXPR,
+ 					TREE_TYPE (*rhsp), sym);
+ 		      else
+ 			*rhsp = sym;
+ 		    }
+ 
+ 		  rhs = gimple_assign_rhs1 (stmt);
+ 		  if (gimple_assign_lhs (stmt) != lhs
+ 		      && !useless_type_conversion_p (TREE_TYPE (lhs),
+ 						     TREE_TYPE (rhs)))
+ 		    rhs = fold_build1 (VIEW_CONVERT_EXPR,
+ 				       TREE_TYPE (lhs), rhs);
+ 
+ 		  if (gimple_assign_lhs (stmt) != lhs)
+ 		    gimple_assign_set_lhs (stmt, lhs);
+ 
+ 		  if (gimple_assign_rhs1 (stmt) != rhs)
+ 		    {
+ 		      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ 		      gimple_assign_set_rhs_from_tree (&gsi, rhs);
+ 		    }
+ 		}
+ 
  	      if (gimple_references_memory_p (stmt)
  		  || is_gimple_debug (stmt))
  		update_stmt (stmt);
Index: gcc/tree-into-ssa.c
===================================================================
*** gcc/tree-into-ssa.c.orig	2010-02-02 13:15:10.000000000 +0100
--- gcc/tree-into-ssa.c	2010-02-02 14:12:45.000000000 +0100
*************** set_livein_block (tree var, basic_block
*** 561,567 ****
  
  /* Return true if symbol SYM is marked for renaming.  */
  
! static inline bool
  symbol_marked_for_renaming (tree sym)
  {
    return bitmap_bit_p (SYMS_TO_RENAME (cfun), DECL_UID (sym));
--- 561,567 ----
  
  /* Return true if symbol SYM is marked for renaming.  */
  
! bool
  symbol_marked_for_renaming (tree sym)
  {
    return bitmap_bit_p (SYMS_TO_RENAME (cfun), DECL_UID (sym));
Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c.orig	2010-02-02 13:15:12.000000000 +0100
--- gcc/gimple.c	2010-02-02 13:46:27.000000000 +0100
*************** is_gimple_condexpr (tree t)
*** 2523,2529 ****
  bool
  is_gimple_addressable (tree t)
  {
!   return (is_gimple_id (t) || handled_component_p (t) || INDIRECT_REF_P (t));
  }
  
  /* Return true if T is a valid gimple constant.  */
--- 2523,2530 ----
  bool
  is_gimple_addressable (tree t)
  {
!   return (is_gimple_id (t) || handled_component_p (t)
! 	  || INDIRECT_REF_P (t) || TREE_CODE (t) == TARGET_MEM_REF);
  }
  
  /* Return true if T is a valid gimple constant.  */
*************** is_gimple_address (const_tree t)
*** 2564,2569 ****
--- 2565,2571 ----
      return false;
  
    op = TREE_OPERAND (t, 0);
+   /* ???  Why does this not simpl return is_gimple_addressable (op)?  */
    while (handled_component_p (op))
      {
        if ((TREE_CODE (op) == ARRAY_REF
*************** is_gimple_address (const_tree t)
*** 2574,2580 ****
        op = TREE_OPERAND (op, 0);
      }
  
!   if (CONSTANT_CLASS_P (op) || INDIRECT_REF_P (op))
      return true;
  
    switch (TREE_CODE (op))
--- 2576,2583 ----
        op = TREE_OPERAND (op, 0);
      }
  
!   if (CONSTANT_CLASS_P (op) || INDIRECT_REF_P (op)
!       || TREE_CODE (op) == TARGET_MEM_REF)
      return true;
  
    switch (TREE_CODE (op))
Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c.orig	2010-02-02 12:43:58.000000000 +0100
--- gcc/tree-ssa-sccvn.c	2010-02-02 13:46:27.000000000 +0100
*************** copy_reference_ops_from_ref (tree ref, V
*** 597,602 ****
--- 597,622 ----
  	case REALPART_EXPR:
  	case VIEW_CONVERT_EXPR:
  	  break;
+ 	case TARGET_MEM_REF:
+ 	  {
+ 	    tree base;
+ 
+ 	    base = TMR_SYMBOL (ref) ? TMR_SYMBOL (ref) : TMR_BASE (ref);
+ 	    if (!base)
+ 	      base = build_int_cst (ptr_type_node, 0);
+ 
+ 	    temp.op0 = TMR_INDEX (ref);
+ 	    temp.op1 = TMR_STEP (ref);
+ 	    temp.op2 = TMR_OFFSET (ref);
+ 	    VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
+ 
+ 	    memset (&temp, 0, sizeof (temp));
+ 	    temp.type = NULL_TREE;
+ 	    temp.opcode = TREE_CODE (base);
+ 	    temp.op0 = base;
+ 	    temp.op1 = TMR_ORIGINAL (ref);
+ 	    break;
+ 	  }
  	default:
  	  gcc_unreachable ();
  	}
*************** visit_reference_op_store (tree lhs, tree
*** 2130,2136 ****
  	  changed |= set_ssa_val_to (vdef, vdef);
  	}
  
!       /* Do not insert structure copies into the tables.  */
        if (is_gimple_min_invariant (op)
  	  || is_gimple_reg (op))
          vn_reference_insert (lhs, op, vdef);
--- 2150,2159 ----
  	  changed |= set_ssa_val_to (vdef, vdef);
  	}
  
!       /* Do not insert structure copies into the tables, but record
!          aggregate VIEW_CONVERT_EXPRs of registers.  */
!       if (TREE_CODE (op) == VIEW_CONVERT_EXPR)
! 	op = TREE_OPERAND (op, 0);
        if (is_gimple_min_invariant (op)
  	  || is_gimple_reg (op))
          vn_reference_insert (lhs, op, vdef);
Index: gcc/alias.c
===================================================================
*** gcc/alias.c.orig	2010-02-02 12:43:58.000000000 +0100
--- gcc/alias.c	2010-02-02 13:46:27.000000000 +0100
*************** get_alias_set (tree t)
*** 649,656 ****
        if (set != -1)
  	return set;
  
!       /* Retrieve the original memory reference if needed.  */
!       if (TREE_CODE (t) == TARGET_MEM_REF)
  	t = TMR_ORIGINAL (t);
  
        /* First see if the actual object referenced is an INDIRECT_REF from a
--- 649,657 ----
        if (set != -1)
  	return set;
  
!       /* Retrieve the original memory reference if needed and available.  */
!       if (TREE_CODE (t) == TARGET_MEM_REF
! 	  && TMR_ORIGINAL (t))
  	t = TMR_ORIGINAL (t);
  
        /* First see if the actual object referenced is an INDIRECT_REF from a
Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c.orig	2010-02-02 12:43:58.000000000 +0100
--- gcc/builtins.c	2010-02-02 13:46:27.000000000 +0100
*************** fold_builtin_memory_op (location_t loc,
*** 8160,8165 ****
--- 8160,8166 ----
      {
        tree srctype, desttype;
        int src_align, dest_align;
+       tree cpytype;
  
        if (endp == 3)
  	{
*************** fold_builtin_memory_op (location_t loc,
*** 8303,8308 ****
--- 8304,8312 ----
        if (!ignore)
          dest = builtin_save_expr (dest);
  
+       /* ???  With the current code using TARGET_MEM_REF we can relax
+ 	 a lot of the following checks as we only need a valid
+ 	 base symbol and constant offset.  */
        srcvar = NULL_TREE;
        if (tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
  	{
*************** fold_builtin_memory_op (location_t loc,
*** 8336,8399 ****
        if (srcvar == NULL_TREE && destvar == NULL_TREE)
  	return NULL_TREE;
  
        if (srcvar == NULL_TREE)
  	{
  	  tree srcptype;
  	  if (TREE_ADDRESSABLE (TREE_TYPE (destvar)))
  	    return NULL_TREE;
  
! 	  srctype = build_qualified_type (desttype, 0);
! 	  if (src_align < (int) TYPE_ALIGN (srctype))
  	    {
! 	      if (AGGREGATE_TYPE_P (srctype)
! 		  || SLOW_UNALIGNED_ACCESS (TYPE_MODE (srctype), src_align))
! 		return NULL_TREE;
  
! 	      srctype = build_variant_type_copy (srctype);
! 	      TYPE_ALIGN (srctype) = src_align;
! 	      TYPE_USER_ALIGN (srctype) = 1;
! 	      TYPE_PACKED (srctype) = 1;
  	    }
! 	  srcptype = build_pointer_type_for_mode (srctype, ptr_mode, true);
! 	  src = fold_convert_loc (loc, srcptype, src);
! 	  srcvar = build_fold_indirect_ref_loc (loc, src);
  	}
!       else if (destvar == NULL_TREE)
  	{
  	  tree destptype;
  	  if (TREE_ADDRESSABLE (TREE_TYPE (srcvar)))
  	    return NULL_TREE;
  
! 	  desttype = build_qualified_type (srctype, 0);
! 	  if (dest_align < (int) TYPE_ALIGN (desttype))
  	    {
! 	      if (AGGREGATE_TYPE_P (desttype)
! 		  || SLOW_UNALIGNED_ACCESS (TYPE_MODE (desttype), dest_align))
! 		return NULL_TREE;
  
! 	      desttype = build_variant_type_copy (desttype);
! 	      TYPE_ALIGN (desttype) = dest_align;
! 	      TYPE_USER_ALIGN (desttype) = 1;
! 	      TYPE_PACKED (desttype) = 1;
  	    }
! 	  destptype = build_pointer_type_for_mode (desttype, ptr_mode, true);
! 	  dest = fold_convert_loc (loc, destptype, dest);
! 	  destvar = build_fold_indirect_ref_loc (loc, dest);
  	}
  
!       if (srctype == desttype
! 	  || (gimple_in_ssa_p (cfun)
! 	      && useless_type_conversion_p (desttype, srctype)))
! 	expr = srcvar;
!       else if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
! 	   || POINTER_TYPE_P (TREE_TYPE (srcvar)))
! 	  && (INTEGRAL_TYPE_P (TREE_TYPE (destvar))
! 	      || POINTER_TYPE_P (TREE_TYPE (destvar))))
! 	expr = fold_convert_loc (loc, TREE_TYPE (destvar), srcvar);
!       else
! 	expr = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
! 			    TREE_TYPE (destvar), srcvar);
!       expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr);
      }
  
    if (ignore)
--- 8340,8430 ----
        if (srcvar == NULL_TREE && destvar == NULL_TREE)
  	return NULL_TREE;
  
+       if (integer_onep (len))
+ 	cpytype = char_type_node;
+       else
+ 	{
+ 	  cpytype = build_index_type (size_int (TREE_INT_CST_LOW (len) - 1));
+ 	  cpytype = build_array_type (char_type_node, cpytype);
+ 	}
+       /* ???  Need a middle-end byte type with guaranteed alias-set zero.
+          Neither Fortran nor Ada currently pass the following check.  */
+       if (get_alias_set (cpytype) != 0)
+ 	return NULL_TREE;
+ 
        if (srcvar == NULL_TREE)
  	{
  	  tree srcptype;
  	  if (TREE_ADDRESSABLE (TREE_TYPE (destvar)))
  	    return NULL_TREE;
  
! 	  srcptype = build_pointer_type_for_mode (cpytype, ptr_mode, true);
! 	  src = fold_convert_loc (loc, srcptype, src);
! 	  srcvar = build_fold_indirect_ref_loc (loc, src);
! 	}
!       else
! 	{
! 	  HOST_WIDE_INT offset = 0;
! 	  HOST_WIDE_INT size = -1;
! 	  HOST_WIDE_INT maxsize = -1;
! 	  tree base = srcvar;
! 
! 	  if (handled_component_p (base))
  	    {
! 	      base = get_ref_base_and_extent (base, &offset, &size, &maxsize);
  
! 	      /* If the start address is variable bail out.
! 		 ???  We can use srcvar itself if len == 1 and srcvar is a
! 		 reference of the same size and with alias-set zero.
! 		 ???  We could also use get_inner_reference here and put
! 		 the variable offset into TMR_INDEX with a TMR_STEP of one.  */
! 	      if (size != maxsize
! 		  || maxsize == -1)
! 		return NULL_TREE;
  	    }
! 
! 	  srcvar = build6 (TARGET_MEM_REF, cpytype,
! 			   base, NULL_TREE, NULL_TREE, NULL_TREE,
! 			   offset != 0
! 			   ? size_int (offset / BITS_PER_UNIT) : NULL_TREE,
! 			   NULL_TREE);
  	}
! 
!       if (destvar == NULL_TREE)
  	{
  	  tree destptype;
  	  if (TREE_ADDRESSABLE (TREE_TYPE (srcvar)))
  	    return NULL_TREE;
  
! 	  destptype = build_pointer_type_for_mode (cpytype, ptr_mode, true);
! 	  dest = fold_convert_loc (loc, destptype, dest);
! 	  destvar = build_fold_indirect_ref_loc (loc, dest);
! 	}
!       else
! 	{
! 	  HOST_WIDE_INT offset = 0;
! 	  HOST_WIDE_INT size = -1;
! 	  HOST_WIDE_INT maxsize = -1;
! 	  tree base = destvar;
! 
! 	  if (handled_component_p (base))
  	    {
! 	      base = get_ref_base_and_extent (base, &offset, &size, &maxsize);
  
! 	      /* If the start address is variable bail out.  */
! 	      if (size != maxsize
! 		  || maxsize == -1)
! 		return NULL_TREE;
  	    }
! 
! 	  destvar = build6 (TARGET_MEM_REF, cpytype,
! 			    base, NULL_TREE, NULL_TREE, NULL_TREE,
! 			    offset != 0
! 			    ? size_int (offset / BITS_PER_UNIT) : NULL_TREE,
! 			    NULL_TREE);
  	}
  
!       expr = build2 (MODIFY_EXPR, void_type_node, destvar, srcvar);
      }
  
    if (ignore)
Index: gcc/tree-ssa-operands.c
===================================================================
*** gcc/tree-ssa-operands.c.orig	2010-02-02 12:43:58.000000000 +0100
--- gcc/tree-ssa-operands.c	2010-02-02 13:46:27.000000000 +0100
*************** get_tmr_operands (gimple stmt, tree expr
*** 736,742 ****
    get_expr_operands (stmt, &TMR_BASE (expr), opf_use | (flags & opf_no_vops));
    get_expr_operands (stmt, &TMR_INDEX (expr), opf_use | (flags & opf_no_vops));
  
!   if (TMR_SYMBOL (expr))
      mark_address_taken (TMR_SYMBOL (expr));
  
    add_virtual_operand (stmt, flags);
--- 736,747 ----
    get_expr_operands (stmt, &TMR_BASE (expr), opf_use | (flags & opf_no_vops));
    get_expr_operands (stmt, &TMR_INDEX (expr), opf_use | (flags & opf_no_vops));
  
!   if (TMR_SYMBOL (expr)
!       && !(is_gimple_reg_type (TREE_TYPE (TMR_SYMBOL (expr)))
! 	   && !TMR_INDEX (expr)
! 	   && !TMR_OFFSET (expr)
! 	   && tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (expr)),
! 				  DECL_SIZE (TMR_SYMBOL (expr)))))
      mark_address_taken (TMR_SYMBOL (expr));
  
    add_virtual_operand (stmt, flags);
Index: gcc/testsuite/gcc.dg/pr42834.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/pr42834.c	2010-02-02 13:46:27.000000000 +0100
***************
*** 0 ****
--- 1,21 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-optimized-vops" } */
+ 
+ void bar (int *);
+ int foo(int i)
+ {
+   int j, k, l;
+   __builtin_memcpy (&j, &i, 4);
+   __builtin_memcpy (&k, &i, 4);
+   __builtin_memcpy (&l, &k, 4);
+   bar (&k);
+   return j + k + l;
+ }
+ 
+ /* All memcpy calls should be folded away.  Two VDEFs should
+    remain, that for the store into k which has its address taken
+    and that for the call to bar.  */
+ 
+ /* { dg-final { scan-tree-dump-times "memcpy" 0 "optimized" } } */
+ /* { dg-final { scan-tree-dump-times "VDEF" 2 "optimized" } } */
+ /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig	2010-02-02 13:15:12.000000000 +0100
--- gcc/tree-ssa-alias.c	2010-02-02 13:46:27.000000000 +0100
*************** refs_may_alias_p_1 (ao_ref *ref1, ao_ref
*** 828,835 ****
    /* If one reference is a TARGET_MEM_REF weird things are allowed.  Still
       TBAA disambiguation based on the access type is possible, so bail
       out only after that check.  */
!   if ((ref1->ref && TREE_CODE (ref1->ref) == TARGET_MEM_REF)
!       || (ref2->ref && TREE_CODE (ref2->ref) == TARGET_MEM_REF))
      return true;
  
    /* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators.  */
--- 828,835 ----
    /* If one reference is a TARGET_MEM_REF weird things are allowed.  Still
       TBAA disambiguation based on the access type is possible, so bail
       out only after that check.  */
!   if (TREE_CODE (base1) == TARGET_MEM_REF
!       || TREE_CODE (base2) == TARGET_MEM_REF)
      return true;
  
    /* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators.  */
Index: gcc/testsuite/gcc.c-torture/compile/20100131-1.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.c-torture/compile/20100131-1.c	2010-02-02 13:46:27.000000000 +0100
***************
*** 0 ****
--- 1,16 ----
+ typedef struct rtx_def *rtx;
+ struct rtx_def {
+     int code;
+ };
+ struct obstack {
+     char *next_free;
+ };
+ static struct obstack obstack;
+ static void gen_insn (rtx insn)
+ {
+   __builtin_memcpy (obstack.next_free, &insn, sizeof (rtx));
+ }
+ void foo (rtx desc)
+ {
+   gen_insn (desc);
+ }
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c.orig	2010-02-02 12:43:58.000000000 +0100
--- gcc/gimplify.c	2010-02-02 13:46:27.000000000 +0100
*************** gimplify_expr (tree *expr_p, gimple_seq
*** 6732,6740 ****
  	    enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
  
  	    if (TMR_SYMBOL (*expr_p))
! 	      r0 = gimplify_expr (&TMR_SYMBOL (*expr_p), pre_p,
! 				  post_p, is_gimple_lvalue, fb_either);
! 	    else if (TMR_BASE (*expr_p))
  	      r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
  				  post_p, is_gimple_val, fb_either);
  	    if (TMR_INDEX (*expr_p))
--- 6732,6766 ----
  	    enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
  
  	    if (TMR_SYMBOL (*expr_p))
! 	      {
! 		r0 = gimplify_expr (&TMR_SYMBOL (*expr_p), pre_p,
! 				    post_p, is_gimple_lvalue, fb_either);
! 		/* Via DECL_VALUE_EXPR we can end up gimplifying
! 		   TMR_SYMBOL into a non-symbol.  Move it to TMR_BASE
! 		   or adjust the offset in that case.  */
! 		if (handled_component_p (TMR_SYMBOL (*expr_p)))
! 		  {
! 		    tree base;
! 		    HOST_WIDE_INT offset, size, max_size;
! 		    base = get_ref_base_and_extent (TMR_SYMBOL (*expr_p),
! 						    &offset, &size, &max_size);
! 		    TMR_SYMBOL (*expr_p) = base;
! 		    if (!TMR_OFFSET (*expr_p) && offset != 0)
! 		      TMR_OFFSET (*expr_p) = size_int (offset / BITS_PER_UNIT);
! 		    else if (offset != 0)
! 		      TMR_OFFSET (*expr_p)
! 			= size_binop_loc (UNKNOWN_LOCATION, PLUS_EXPR,
! 					  TMR_OFFSET (*expr_p),
! 					  size_int (offset / BITS_PER_UNIT));
! 		  }
! 		if (INDIRECT_REF_P (TMR_SYMBOL (*expr_p)))
! 		  {
! 		    gcc_assert (!TMR_BASE (*expr_p));
! 		    TMR_BASE (*expr_p) = TREE_OPERAND (TMR_SYMBOL (*expr_p), 0);
! 		    TMR_SYMBOL (*expr_p) = NULL_TREE;
! 		  }
! 	      }
! 	    if (TMR_BASE (*expr_p))
  	      r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
  				  post_p, is_gimple_val, fb_either);
  	    if (TMR_INDEX (*expr_p))
Index: gcc/tree-eh.c
===================================================================
*** gcc/tree-eh.c.orig	2010-02-02 12:43:58.000000000 +0100
--- gcc/tree-eh.c	2010-02-02 13:46:27.000000000 +0100
*************** tree_could_trap_p (tree expr)
*** 2371,2376 ****
--- 2371,2378 ----
        /* For TARGET_MEM_REFs use the information based on the original
  	 reference.  */
        expr = TMR_ORIGINAL (expr);
+       if (!expr)
+ 	return false;
        code = TREE_CODE (expr);
        goto restart;
  
Index: gcc/tree-nested.c
===================================================================
*** gcc/tree-nested.c.orig	2010-02-02 12:43:58.000000000 +0100
--- gcc/tree-nested.c	2010-02-02 13:46:27.000000000 +0100
*************** convert_local_reference_op (tree *tp, in
*** 1499,1504 ****
--- 1499,1535 ----
        wi->val_only = save_val_only;
        break;
  
+     case TARGET_MEM_REF:
+       save_val_only = wi->val_only;
+       wi->val_only = false;
+       if (TMR_SYMBOL (t))
+ 	{
+ 	  walk_tree (&TMR_SYMBOL (t), convert_local_reference_op, wi, NULL);
+ 	  if (handled_component_p (TMR_SYMBOL (t)))
+ 	    {
+ 	      tree base;
+ 	      HOST_WIDE_INT offset, size, max_size;
+ 	      base = get_ref_base_and_extent (TMR_SYMBOL (t),
+ 					      &offset, &size, &max_size);
+ 	      TMR_SYMBOL (t) = base;
+ 	      if (!TMR_OFFSET (t) && offset != 0)
+ 		TMR_OFFSET (t) = size_int (offset / BITS_PER_UNIT);
+ 	      else if (offset != 0)
+ 		TMR_OFFSET (t)
+ 		    = size_binop_loc (UNKNOWN_LOCATION, PLUS_EXPR,
+ 				      TMR_OFFSET (t),
+ 				      size_int (offset / BITS_PER_UNIT));
+ 	    }
+ 	}
+       wi->val_only = true;
+       wi->is_lhs = false;
+       if (TMR_BASE (t))
+ 	walk_tree (&TMR_BASE (t), convert_local_reference_op, wi, NULL);
+       if (TMR_INDEX (t))
+ 	walk_tree (&TMR_INDEX (t), convert_local_reference_op, wi, NULL);
+       wi->val_only = save_val_only;
+       break;
+ 
      case VIEW_CONVERT_EXPR:
        /* Just request to look at the subtrees, leaving val_only and lhs
  	 untouched.  This might actually be for !val_only + lhs, in which
Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h.orig	2010-02-02 13:15:12.000000000 +0100
--- gcc/tree-flow.h	2010-02-02 14:11:01.000000000 +0100
*************** void release_ssa_name_after_update_ssa (
*** 599,604 ****
--- 599,605 ----
  void compute_global_livein (bitmap, bitmap);
  void mark_sym_for_renaming (tree);
  void mark_set_for_renaming (bitmap);
+ bool symbol_marked_for_renaming (tree);
  tree get_current_def (tree);
  void set_current_def (tree, tree);
  
Index: gcc/testsuite/g++.dg/torture/pr42834.C
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/g++.dg/torture/pr42834.C	2010-02-02 14:22:56.000000000 +0100
***************
*** 0 ****
--- 1,16 ----
+ // { dg-do run }
+ 
+ int main()
+ {
+   if (sizeof(int) == sizeof(float))
+     {
+       int i = 0;
+       float f = 1.0;
+       int *p = (int *)&f;
+       __builtin_memcpy (&i, p, 4);
+       if (*(float *)&i != 1.0)
+ 	__builtin_abort ();
+     }
+   return 0;
+ }
+ 

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