File pr40141.diff of Package gcc43

2009-05-15  Richard Guenther  <rguenther@suse.de>

	Backport from gcc-4_4-branch

	2008-11-25  Richard Guenther  <rguenther@suse.de>

        PR middle-end/38151
        PR middle-end/38236
        * tree-ssa-alias.c (struct alias_info): Remove written_vars.
        Remove dereferenced_ptrs_store and dereferenced_ptrs_load
        in favor of dereferenced_ptrs.
        (init_alias_info): Adjust.
        (delete_alias_info): Likewise.
        (compute_flow_insensitive_aliasing): Properly
        include all aliased variables.
        (update_alias_info_1): Use dereferenced_ptrs.
        (setup_pointers_and_addressables): Likewise.
        (get_smt_for): Honor ref-all pointers and pointers with known alias
        set properly.
        * config/i386/i386.c (ix86_gimplify_va_arg): Use ref-all pointers.

	2008-11-20  Uros Bizjak  <ubizjak@gmail.com>

        PR target/38151
        * config/i386/i386.c (classify_argument) [integer mode size <= 64bit]:
        Handle cases when integer argument crosses argument register boundary.

	2008-04-29  Richard Guenther  <rguenther@suse.de>

        * tree-ssa-alias.c (finalize_ref_all_pointers): Remove.
        (compute_may_aliases): Do not call finalize_ref_all_pointers.
        (compute_flow_insensitive_aliasing): Do not treat
        PTR_IS_REF_ALL pointers special.
        (get_smt_for): Likewise.
        (may_alias_p): Re-structure.
        (is_escape_site): A ref-all pointer conversion is not an escape site.
        * tree-ssa-structalias.c (find_what_p_points_to): Do not treat
        PTR_IS_REF_ALL pointers special.
        * tree-ssa-structalias.h (struct alias_info): Remove
        ref_all_symbol_mem_tag field.
        (PTR_IS_REF_ALL): Remove.


Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c	(revision 147534)
--- gcc/tree-ssa-structalias.c	(working copy)
*************** update_alias_info (tree stmt, struct ali
*** 3536,3548 ****
  	     all the variables OP points to.  */
  	  pi->is_dereferenced = 1;
  
! 	  /* If this is a store operation, mark OP as being
! 	     dereferenced to store, otherwise mark it as being
! 	     dereferenced to load.  */
! 	  if (num_stores > 0)
! 	    pointer_set_insert (ai->dereferenced_ptrs_store, var);
! 	  else
! 	    pointer_set_insert (ai->dereferenced_ptrs_load, var);
  
  	  /* Update the frequency estimate for all the dereferences of
  	     pointer OP.  */
--- 3536,3543 ----
  	     all the variables OP points to.  */
  	  pi->is_dereferenced = 1;
  
! 	  /* Mark OP as being dereferenced.  */
! 	  pointer_set_insert (ai->dereferenced_ptrs, var);
  
  	  /* Update the frequency estimate for all the dereferences of
  	     pointer OP.  */
*************** update_alias_info (tree stmt, struct ali
*** 3567,3573 ****
  	  if (get_call_expr_in (stmt)
  	      || stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
  	    {
! 	      pointer_set_insert (ai->dereferenced_ptrs_store, var);
  	      pi->is_dereferenced = 1;
  	    }
  	}
--- 3562,3568 ----
  	  if (get_call_expr_in (stmt)
  	      || stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
  	    {
! 	      pointer_set_insert (ai->dereferenced_ptrs, var);
  	      pi->is_dereferenced = 1;
  	    }
  	}
*************** update_alias_info (tree stmt, struct ali
*** 3585,3613 ****
  
        mem_ref_stats->num_mem_stmts++;
  
-       /* Add all decls written to to the list of written variables.  */
-       if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
- 	  && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) != SSA_NAME)
- 	{
- 	  tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
- 	  while (handled_component_p (lhs))
- 	    lhs = TREE_OPERAND (lhs, 0);
- 	  if (DECL_P (lhs))
- 	    {
- 	      subvar_t svars;
- 	      if (var_can_have_subvars (lhs)
- 		  && (svars = get_subvars_for_var (lhs)))
- 		{
- 		  unsigned int i;
- 		  tree subvar;
- 		  for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
- 		    pointer_set_insert (ai->written_vars, subvar);
- 		}
- 	      else
- 		pointer_set_insert (ai->written_vars, lhs);
- 	    }
- 	}
- 
        /* Notice that we only update memory reference stats for symbols
  	 loaded and stored by the statement if the statement does not
  	 contain pointer dereferences and it is not a call/asm site.
--- 3580,3585 ----
*************** find_what_p_points_to (tree p)
*** 5026,5042 ****
  
  	  /* Instead of using pt_anything, we merge in the SMT aliases
  	     for the underlying SMT.  In addition, if they could have
! 	     pointed to anything, they could point to global memory.
! 	     But we cannot do that for ref-all pointers because these
! 	     aliases have not been computed yet.  */
  	  if (was_pt_anything)
  	    {
- 	      if (PTR_IS_REF_ALL (p))
- 		{
- 		  pi->pt_anything = 1;
- 		  return false;
- 		}
- 
  	      merge_smts_into (p, finished_solution);
  	      pi->pt_global_mem = 1;
  	    }
--- 4998,5006 ----
  
  	  /* Instead of using pt_anything, we merge in the SMT aliases
  	     for the underlying SMT.  In addition, if they could have
! 	     pointed to anything, they could point to global memory.  */
  	  if (was_pt_anything)
  	    {
  	      merge_smts_into (p, finished_solution);
  	      pi->pt_global_mem = 1;
  	    }
Index: gcc/tree-ssa-structalias.h
===================================================================
*** gcc/tree-ssa-structalias.h	(revision 147534)
--- gcc/tree-ssa-structalias.h	(working copy)
***************
*** 21,29 ****
  #ifndef TREE_SSA_STRUCTALIAS_H
  #define TREE_SSA_STRUCTALIAS_H
  
- /* True if the data pointed to by PTR can alias anything.  */
- #define PTR_IS_REF_ALL(PTR) TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (PTR))
- 
  struct constraint;
  typedef struct constraint *constraint_t;
  
--- 21,26 ----
*************** struct alias_info
*** 48,65 ****
    struct alias_map_d **pointers;
    size_t num_pointers;
  
!   /* Variables that have been written to directly (i.e., not through a
!      pointer dereference).  */
!   struct pointer_set_t *written_vars;
! 
!   /* Pointers that have been used in an indirect store operation.  */
!   struct pointer_set_t *dereferenced_ptrs_store;
! 
!   /* Pointers that have been used in an indirect load operation.  */
!   struct pointer_set_t *dereferenced_ptrs_load;
! 
!   /* Memory tag for all the PTR_IS_REF_ALL pointers.  */
!   tree ref_all_symbol_mem_tag;
  };
  
  /* In tree-ssa-alias.c.  */
--- 45,52 ----
    struct alias_map_d **pointers;
    size_t num_pointers;
  
!   /* Pointers that have been used in an indirect load/store operation.  */
!   struct pointer_set_t *dereferenced_ptrs;
  };
  
  /* In tree-ssa-alias.c.  */
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c	(revision 147534)
--- gcc/tree-ssa-alias.c	(working copy)
*************** static bitmap_obstack alias_bitmap_obsta
*** 196,202 ****
  
  /* Local functions.  */
  static void compute_flow_insensitive_aliasing (struct alias_info *);
- static void finalize_ref_all_pointers (struct alias_info *);
  static void dump_alias_stats (FILE *);
  static bool may_alias_p (tree, alias_set_type, tree, alias_set_type, bool);
  static tree create_memory_tag (tree type, bool is_type_tag);
--- 196,201 ----
*************** compute_may_aliases (void)
*** 1894,1905 ****
       avoid invalid transformations on them.  */
    maybe_create_global_var ();
  
-   /* If the program contains ref-all pointers, finalize may-alias information
-      for them.  This pass needs to be run after call-clobbering information
-      has been computed.  */
-   if (ai->ref_all_symbol_mem_tag)
-     finalize_ref_all_pointers (ai);
- 
    /* Compute memory partitions for every memory variable.  */
    compute_memory_partitions ();
  
--- 1893,1898 ----
*************** init_alias_info (void)
*** 2220,2228 ****
    ai->ssa_names_visited = sbitmap_alloc (num_ssa_names);
    sbitmap_zero (ai->ssa_names_visited);
    ai->processed_ptrs = VEC_alloc (tree, heap, 50);
!   ai->written_vars = pointer_set_create ();
!   ai->dereferenced_ptrs_store = pointer_set_create ();
!   ai->dereferenced_ptrs_load = pointer_set_create ();
  
    /* Clear out all memory reference stats.  */
    init_mem_ref_stats ();
--- 2213,2219 ----
    ai->ssa_names_visited = sbitmap_alloc (num_ssa_names);
    sbitmap_zero (ai->ssa_names_visited);
    ai->processed_ptrs = VEC_alloc (tree, heap, 50);
!   ai->dereferenced_ptrs = pointer_set_create ();
  
    /* Clear out all memory reference stats.  */
    init_mem_ref_stats ();
*************** delete_alias_info (struct alias_info *ai
*** 2269,2277 ****
      free (ai->pointers[i]);
    free (ai->pointers);
  
!   pointer_set_destroy (ai->written_vars);
!   pointer_set_destroy (ai->dereferenced_ptrs_store);
!   pointer_set_destroy (ai->dereferenced_ptrs_load);
    free (ai);
  
    delete_mem_ref_stats (cfun);
--- 2260,2266 ----
      free (ai->pointers[i]);
    free (ai->pointers);
  
!   pointer_set_destroy (ai->dereferenced_ptrs);
    free (ai);
  
    delete_mem_ref_stats (cfun);
*************** compute_flow_insensitive_aliasing (struc
*** 2518,2548 ****
        tree tag = symbol_mem_tag (p_map->var);
        tree var;
  
-       /* Call-clobbering information is not finalized yet at this point.  */
-       if (PTR_IS_REF_ALL (p_map->var))
- 	continue;
- 
        for (j = 0; j < ai->num_addressable_vars; j++)
  	{
  	  struct alias_map_d *v_map;
  	  var_ann_t v_ann;
- 	  bool tag_stored_p, var_stored_p;
  	  
  	  v_map = ai->addressable_vars[j];
  	  var = v_map->var;
  	  v_ann = var_ann (var);
  
! 	  /* Skip memory tags and variables that have never been
! 	     written to.  We also need to check if the variables are
! 	     call-clobbered because they may be overwritten by
! 	     function calls.  */
! 	  tag_stored_p = pointer_set_contains (ai->written_vars, tag)
! 	                 || is_call_clobbered (tag);
! 	  var_stored_p = pointer_set_contains (ai->written_vars, var)
! 	                 || is_call_clobbered (var);
! 	  if (!tag_stored_p && !var_stored_p)
! 	    continue;
! 	     
  	  if (may_alias_p (p_map->var, p_map->set, var, v_map->set, false))
  	    {
  	      /* We should never have a var with subvars here, because
--- 2507,2528 ----
        tree tag = symbol_mem_tag (p_map->var);
        tree var;
  
        for (j = 0; j < ai->num_addressable_vars; j++)
  	{
  	  struct alias_map_d *v_map;
  	  var_ann_t v_ann;
  	  
  	  v_map = ai->addressable_vars[j];
  	  var = v_map->var;
  	  v_ann = var_ann (var);
  
! 	  /* We used to skip variables that have never been written to
! 	     if the memory tag has been never written to directly (or
! 	     either of them were call clobbered).  This is not enough
! 	     though, as this misses writes through the tags aliases.
! 	     So, for correctness we need to include any aliased
! 	     variable here.  */
! 
  	  if (may_alias_p (p_map->var, p_map->set, var, v_map->set, false))
  	    {
  	      /* We should never have a var with subvars here, because
*************** compute_flow_insensitive_aliasing (struc
*** 2583,2600 ****
        tree tag1 = symbol_mem_tag (p_map1->var);
        bitmap may_aliases1 = MTAG_ALIASES (tag1);
  
-       if (PTR_IS_REF_ALL (p_map1->var))
- 	continue;
- 
        for (j = i + 1; j < ai->num_pointers; j++)
  	{
  	  struct alias_map_d *p_map2 = ai->pointers[j];
  	  tree tag2 = symbol_mem_tag (p_map2->var);
  	  bitmap may_aliases2 = may_aliases (tag2);
  
- 	  if (PTR_IS_REF_ALL (p_map2->var))
- 	    continue;
- 
  	  /* If the pointers may not point to each other, do nothing.  */
  	  if (!may_alias_p (p_map1->var, p_map1->set, tag2, p_map2->set, true))
  	    continue;
--- 2563,2574 ----
*************** compute_flow_insensitive_aliasing (struc
*** 2639,2687 ****
  }
  
  
- /* Finalize may-alias information for ref-all pointers.  Traverse all
-    the addressable variables found in setup_pointers_and_addressables.
- 
-    If flow-sensitive alias analysis has attached a name memory tag to
-    a ref-all pointer, we will use it for the dereferences because that
-    will have more precise aliasing information.  But if there is no
-    name tag, we will use a special symbol tag that aliases all the
-    call-clobbered addressable variables.  */
- 
- static void
- finalize_ref_all_pointers (struct alias_info *ai)
- {
-   size_t i;
- 
-   /* First add the real call-clobbered variables.  */
-   for (i = 0; i < ai->num_addressable_vars; i++)
-     {
-       tree var = ai->addressable_vars[i]->var;
-       if (is_call_clobbered (var))
- 	add_may_alias (ai->ref_all_symbol_mem_tag, var);
-     }
- 
-   /* Then add the call-clobbered pointer memory tags.  See
-      compute_flow_insensitive_aliasing for the rationale.  */
-   for (i = 0; i < ai->num_pointers; i++)
-     {
-       tree ptr = ai->pointers[i]->var, tag;
-       /* Avoid adding to self and clean up.  */
-       if (PTR_IS_REF_ALL (ptr))
- 	{
- 	  struct ptr_info_def *pi = get_ptr_info (ptr);
- 	  if (pi->is_dereferenced)
- 	    pi->pt_anything = 0;
- 	  continue;
- 	}
-       tag = symbol_mem_tag (ptr);
-       if (is_call_clobbered (tag))
- 	add_may_alias (ai->ref_all_symbol_mem_tag, tag);
-     }
- 
- }
- 
- 
  /* Create a new alias set entry for VAR in AI->ADDRESSABLE_VARS.  */
  
  static void
--- 2613,2618 ----
*************** setup_pointers_and_addressables (struct
*** 2723,2729 ****
  	  /* Since we don't keep track of volatile variables, assume that
  	     these pointers are used in indirect store operations.  */
  	  if (TREE_THIS_VOLATILE (var))
! 	    pointer_set_insert (ai->dereferenced_ptrs_store, var);
  
  	  num_pointers++;
  	}
--- 2654,2660 ----
  	  /* Since we don't keep track of volatile variables, assume that
  	     these pointers are used in indirect store operations.  */
  	  if (TREE_THIS_VOLATILE (var))
! 	    pointer_set_insert (ai->dereferenced_ptrs, var);
  
  	  num_pointers++;
  	}
*************** setup_pointers_and_addressables (struct
*** 2821,2828 ****
           array and create a symbol memory tag for them.  */
        if (POINTER_TYPE_P (TREE_TYPE (var)))
  	{
! 	  if ((pointer_set_contains (ai->dereferenced_ptrs_store, var)
! 	       || pointer_set_contains (ai->dereferenced_ptrs_load, var)))
  	    {
  	      tree tag, old_tag;
  	      var_ann_t t_ann;
--- 2752,2758 ----
           array and create a symbol memory tag for them.  */
        if (POINTER_TYPE_P (TREE_TYPE (var)))
  	{
! 	  if (pointer_set_contains (ai->dereferenced_ptrs, var))
  	    {
  	      tree tag, old_tag;
  	      var_ann_t t_ann;
*************** setup_pointers_and_addressables (struct
*** 2848,2858 ****
  
  	      /* Associate the tag with pointer VAR.  */
  	      set_symbol_mem_tag (var, tag);
- 
- 	      /* If pointer VAR has been used in a store operation,
- 		 then its memory tag must be marked as written-to.  */
- 	      if (pointer_set_contains (ai->dereferenced_ptrs_store, var))
- 		pointer_set_insert (ai->written_vars, tag);
  	    }
  	  else
  	    {
--- 2778,2783 ----
*************** may_alias_p (tree ptr, alias_set_type me
*** 2966,3039 ****
        return false;
      }
  
    gcc_assert (TREE_CODE (mem) == SYMBOL_MEMORY_TAG);
  
!   if (!DECL_NO_TBAA_P (ptr))
      {
!       alias_stats.tbaa_queries++;
  
!       /* If the alias sets don't conflict then MEM cannot alias VAR.  */
!       if (!alias_sets_conflict_p (mem_alias_set, var_alias_set))
! 	{
! 	  alias_stats.alias_noalias++;
! 	  alias_stats.tbaa_resolved++;
! 	  return false;
! 	}
  
!       /* If VAR is a record or union type, PTR cannot point into VAR
! 	 unless there is some explicit address operation in the
! 	 program that can reference a field of the type pointed-to by
! 	 PTR.  This also assumes that the types of both VAR and PTR
! 	 are contained within the compilation unit, and that there is
! 	 no fancy addressing arithmetic associated with any of the
! 	 types involved.  */
!       if (mem_alias_set != 0 && var_alias_set != 0)
! 	{
! 	  tree ptr_type = TREE_TYPE (ptr);
! 	  tree var_type = TREE_TYPE (var);
!       
! 	  /* The star count is -1 if the type at the end of the
! 	     pointer_to chain is not a record or union type. */ 
! 	  if ((!alias_set_only) && 
! 	      ipa_type_escape_star_count_of_interesting_type (var_type) >= 0)
  	    {
! 	      int ptr_star_count = 0;
! 	  
! 	      /* ipa_type_escape_star_count_of_interesting_type is a
! 		 little too restrictive for the pointer type, need to
! 		 allow pointers to primitive types as long as those
! 		 types cannot be pointers to everything.  */
! 	      while (POINTER_TYPE_P (ptr_type))
! 		{
! 		  /* Strip the *s off.  */ 
! 		  ptr_type = TREE_TYPE (ptr_type);
! 		  ptr_star_count++;
! 		}
! 	  
! 	      /* There does not appear to be a better test to see if
! 		 the pointer type was one of the pointer to everything
! 		 types.  */
! 	      if (ptr_star_count > 0)
! 		{
! 		  alias_stats.structnoaddress_queries++;
! 		  if (ipa_type_escape_field_does_not_clobber_p (var_type, 
! 								TREE_TYPE (ptr)))
! 		    {
! 		      alias_stats.structnoaddress_resolved++;
! 		      alias_stats.alias_noalias++;
! 		      return false;
! 		    }
! 		}
! 	      else if (ptr_star_count == 0)
  		{
- 		  /* If PTR_TYPE was not really a pointer to type, it cannot 
- 		     alias.  */ 
- 		  alias_stats.structnoaddress_queries++;
  		  alias_stats.structnoaddress_resolved++;
  		  alias_stats.alias_noalias++;
  		  return false;
  		}
  	    }
  	}
      }
  
--- 2891,2974 ----
        return false;
      }
  
+   /* If the pointed to memory has alias set zero, or the pointer
+      is ref-all, or the pointer decl is marked that no TBAA is to
+      be applied, the MEM can alias VAR.  */
+   if (mem_alias_set == 0
+       || DECL_POINTER_ALIAS_SET (ptr) == 0
+       || TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (ptr))
+       || DECL_NO_TBAA_P (ptr))
+     {
+       alias_stats.alias_mayalias++;
+       alias_stats.simple_resolved++;
+       return true;
+     }
+ 
    gcc_assert (TREE_CODE (mem) == SYMBOL_MEMORY_TAG);
  
!   alias_stats.tbaa_queries++;
! 
!   /* If the alias sets don't conflict then MEM cannot alias VAR.  */
!   if (!alias_sets_conflict_p (mem_alias_set, var_alias_set))
      {
!       alias_stats.alias_noalias++;
!       alias_stats.tbaa_resolved++;
!       return false;
!     }
  
!   /* If VAR is a record or union type, PTR cannot point into VAR
!      unless there is some explicit address operation in the
!      program that can reference a field of the type pointed-to by
!      PTR.  This also assumes that the types of both VAR and PTR
!      are contained within the compilation unit, and that there is
!      no fancy addressing arithmetic associated with any of the
!      types involved.  */
!   if (mem_alias_set != 0 && var_alias_set != 0)
!     {
!       tree ptr_type = TREE_TYPE (ptr);
!       tree var_type = TREE_TYPE (var);
! 
!       /* The star count is -1 if the type at the end of the
! 	 pointer_to chain is not a record or union type. */ 
!       if (!alias_set_only
! 	  && ipa_type_escape_star_count_of_interesting_type (var_type) >= 0)
! 	{
! 	  int ptr_star_count = 0;
! 
! 	  /* ipa_type_escape_star_count_of_interesting_type is a
! 	     little too restrictive for the pointer type, need to
! 	     allow pointers to primitive types as long as those
! 	     types cannot be pointers to everything.  */
! 	  while (POINTER_TYPE_P (ptr_type))
! 	    {
! 	      /* Strip the *s off.  */ 
! 	      ptr_type = TREE_TYPE (ptr_type);
! 	      ptr_star_count++;
! 	    }
  
! 	  /* There does not appear to be a better test to see if
! 	     the pointer type was one of the pointer to everything
! 	     types.  */
! 	  if (ptr_star_count > 0)
  	    {
! 	      alias_stats.structnoaddress_queries++;
! 	      if (ipa_type_escape_field_does_not_clobber_p (var_type, 
! 							    TREE_TYPE (ptr)))
  		{
  		  alias_stats.structnoaddress_resolved++;
  		  alias_stats.alias_noalias++;
  		  return false;
  		}
  	    }
+ 	  else if (ptr_star_count == 0)
+ 	    {
+ 	      /* If PTR_TYPE was not really a pointer to type, it cannot 
+ 		 alias.  */ 
+ 	      alias_stats.structnoaddress_queries++;
+ 	      alias_stats.structnoaddress_resolved++;
+ 	      alias_stats.alias_noalias++;
+ 	      return false;
+ 	    }
  	}
      }
  
*************** is_escape_site (tree stmt)
*** 3139,3150 ****
  	     pointer escapes since we can't track the integer.  */
  	  if (POINTER_TYPE_P (from) && !POINTER_TYPE_P (to))
  	    return ESCAPE_BAD_CAST;
- 
- 	  /* Same if the RHS is a conversion between a regular pointer and a
- 	     ref-all pointer since we can't track the SMT of the former.  */
- 	  if (POINTER_TYPE_P (from) && !TYPE_REF_CAN_ALIAS_ALL (from)
- 	      && POINTER_TYPE_P (to) && TYPE_REF_CAN_ALIAS_ALL (to))
- 	    return ESCAPE_BAD_CAST;
  	}
  
        /* If the LHS is an SSA name, it can't possibly represent a non-local
--- 3074,3079 ----
*************** get_smt_for (tree ptr, struct alias_info
*** 3248,3261 ****
    size_t i;
    tree tag;
    tree tag_type = TREE_TYPE (TREE_TYPE (ptr));
!   alias_set_type tag_set = get_alias_set (tag_type);
  
!   /* We use a unique memory tag for all the ref-all pointers.  */
!   if (PTR_IS_REF_ALL (ptr))
      {
!       if (!ai->ref_all_symbol_mem_tag)
! 	ai->ref_all_symbol_mem_tag = create_memory_tag (void_type_node, true);
!       return ai->ref_all_symbol_mem_tag;
      }
  
    /* To avoid creating unnecessary memory tags, only create one memory tag
--- 3177,3197 ----
    size_t i;
    tree tag;
    tree tag_type = TREE_TYPE (TREE_TYPE (ptr));
!   alias_set_type tag_set;
  
!   /* Get the alias set to be used for the pointed-to memory.  If that
!      differs from what we would get from looking at the type adjust
!      the tag_type to void to make sure we get a proper alias set from
!      just looking at the SMT we create.  */
!   tag_set = get_alias_set (tag_type);
!   if (TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (ptr))
!       /* This is overly conservative but we do not want to assign
!          restrict alias sets here (which if they are not assigned
!          are -2 but still "known").  */
!       || DECL_POINTER_ALIAS_SET_KNOWN_P (ptr))
      {
!       tag_set = 0;
!       tag_type = void_type_node;
      }
  
    /* To avoid creating unnecessary memory tags, only create one memory tag
*************** get_smt_for (tree ptr, struct alias_info
*** 3287,3293 ****
  	 artificial variable representing the memory location
  	 pointed-to by PTR.  */
        tag = symbol_mem_tag (ptr);
!       if (tag == NULL_TREE)
  	tag = create_memory_tag (tag_type, true);
  
        /* Add PTR to the POINTERS array.  Note that we are not interested in
--- 3223,3230 ----
  	 artificial variable representing the memory location
  	 pointed-to by PTR.  */
        tag = symbol_mem_tag (ptr);
!       if (tag == NULL_TREE
! 	  || tag_set != get_alias_set (tag))
  	tag = create_memory_tag (tag_type, true);
  
        /* Add PTR to the POINTERS array.  Note that we are not interested in
Index: gcc/config/i386/i386.c
===================================================================
*** gcc/config/i386/i386.c	(revision 147534)
--- gcc/config/i386/i386.c	(working copy)
*************** ix86_gimplify_va_arg (tree valist, tree
*** 5336,5341 ****
--- 5336,5343 ----
  	      enum machine_mode mode = GET_MODE (reg);
  	      tree piece_type = lang_hooks.types.type_for_mode (mode, 1);
  	      tree addr_type = build_pointer_type (piece_type);
+ 	      tree daddr_type = build_pointer_type_for_mode (piece_type,
+ 							     ptr_mode, true);
  	      tree src_addr, src;
  	      int src_offset;
  	      tree dest_addr, dest;
*************** ix86_gimplify_va_arg (tree valist, tree
*** 5355,5362 ****
  				      size_int (src_offset));
  	      src = build_va_arg_indirect_ref (src_addr);
  
! 	      dest_addr = fold_convert (addr_type, addr);
! 	      dest_addr = fold_build2 (POINTER_PLUS_EXPR, addr_type, dest_addr,
  				       size_int (INTVAL (XEXP (slot, 1))));
  	      dest = build_va_arg_indirect_ref (dest_addr);
  
--- 5357,5364 ----
  				      size_int (src_offset));
  	      src = build_va_arg_indirect_ref (src_addr);
  
! 	      dest_addr = fold_convert (daddr_type, addr);
! 	      dest_addr = fold_build2 (POINTER_PLUS_EXPR, daddr_type, dest_addr,
  				       size_int (INTVAL (XEXP (slot, 1))));
  	      dest = build_va_arg_indirect_ref (dest_addr);
  
Index: gcc/testsuite/gcc.c-torture/execute/pr38151.c
===================================================================
*** gcc/testsuite/gcc.c-torture/execute/pr38151.c	(revision 0)
--- gcc/testsuite/gcc.c-torture/execute/pr38151.c	(revision 0)
***************
*** 0 ****
--- 1,46 ----
+ void abort (void);
+ 
+ struct S2848
+ {
+   unsigned int a;
+   _Complex int b;
+   struct
+   {
+   } __attribute__ ((aligned)) c;
+ };
+ 
+ struct S2848 s2848;
+ 
+ int fails;
+ 
+ void  __attribute__((noinline))
+ check2848va (int z, ...)
+ {
+   struct S2848 arg;
+   __builtin_va_list ap;
+ 
+   __builtin_va_start (ap, z);
+ 
+   arg = __builtin_va_arg (ap, struct S2848);
+ 
+   if (s2848.a != arg.a)
+     ++fails;
+   if (s2848.b != arg.b)
+     ++fails;
+ 
+   __builtin_va_end (ap);
+ }
+ 
+ int main (void)
+ {
+   s2848.a = 4027477739U;
+   s2848.b = (723419448 + -218144346 * __extension__ 1i);
+ 
+   check2848va (1, s2848);
+ 
+   if (fails)
+     abort ();
+ 
+   return 0;
+ }
+ 
Index: gcc/testsuite/gcc.c-torture/execute/pr38236.c
===================================================================
*** gcc/testsuite/gcc.c-torture/execute/pr38236.c	(revision 0)
--- gcc/testsuite/gcc.c-torture/execute/pr38236.c	(revision 0)
***************
*** 0 ****
--- 1,22 ----
+ struct X { int i; };
+ 
+ int __attribute__((noinline))
+ foo (struct X *p, int *q, int a, int b)
+ {
+   struct X x, y;
+   if (a)
+     p = &x;
+   if (b)
+     q = &x.i;
+   else
+     q = &y.i;
+   *q = 1;
+   return p->i; 
+ }
+ extern void abort (void);
+ int main()
+ {
+   if (foo((void *)0, (void *)0, 1, 1) != 1)
+     abort ();
+   return 0;
+ }
Index: gcc/testsuite/gcc.c-torture/execute/pr40141.c
===================================================================
*** gcc/testsuite/gcc.c-torture/execute/pr40141.c	(revision 0)
--- gcc/testsuite/gcc.c-torture/execute/pr40141.c	(revision 0)
***************
*** 0 ****
--- 1,16 ----
+ extern void abort (void);
+ typedef int __m128 __attribute__((vector_size(16),may_alias));
+ typedef float floatA __attribute__((may_alias));
+ 
+ int main()
+ {
+   __m128 x = { 0, 0, 0, 0 };
+   int i;
+   for (i = 0; i < 4; ++i) {
+       const float xx = ((floatA*)&x)[i];
+       if (xx != 0.f)
+ 	abort ();
+   }
+   return 0;
+ }
+ 
Index: gcc/testsuite/gcc.target/i386/pr38151-1.c
===================================================================
--- gcc/testsuite/gcc.target/i386/pr38151-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr38151-1.c	(revision 142059)
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+void abort (void);
+
+struct S2848
+{
+  unsigned int a;
+  _Complex int b;
+};
+
+struct S2848 s2848;
+
+void __attribute__((noinline))
+check2848 (struct S2848 arg0)
+{
+  if (arg0.b != s2848.b)
+    abort ();
+}
+
+int main()
+{
+  s2848.a = 4027477739U;
+  s2848.b = (723419448 + -218144346 * __extension__ 1i);
+
+  check2848 (s2848);
+
+  return 0;
+}
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 142058)
+++ gcc/config/i386/i386.c	(revision 142059)
@@ -5029,11 +5029,33 @@ classify_argument (enum machine_mode mod
     case CSImode:
     case CHImode:
     case CQImode:
-      if (bit_offset + GET_MODE_BITSIZE (mode) <= 32)
-	classes[0] = X86_64_INTEGERSI_CLASS;
-      else
-	classes[0] = X86_64_INTEGER_CLASS;
-      return 1;
+      {
+	int size = (bit_offset % 64)+ (int) GET_MODE_BITSIZE (mode);
+
+	if (size <= 32)
+	  {
+	    classes[0] = X86_64_INTEGERSI_CLASS;
+	    return 1;
+	  }
+	else if (size <= 64)
+	  {
+	    classes[0] = X86_64_INTEGER_CLASS;
+	    return 1;
+	  }
+	else if (size <= 64+32)
+	  {
+	    classes[0] = X86_64_INTEGER_CLASS;
+	    classes[1] = X86_64_INTEGERSI_CLASS;
+	    return 2;
+	  }
+	else if (size <= 64+64)
+	  {
+	    classes[0] = classes[1] = X86_64_INTEGER_CLASS;
+	    return 2;
+	  }
+	else
+	  gcc_unreachable ();
+      }
     case CDImode:
     case TImode:
       classes[0] = classes[1] = X86_64_INTEGER_CLASS;
openSUSE Build Service is sponsored by