[PATCH] Split tree-sra.c:scan_function into three separate functions

Richard Guenther rguenther@suse.de
Tue May 4 15:51:00 GMT 2010


On Tue, 4 May 2010, Martin Jambor wrote:

> Hi,
> 
> the patch below splits scan_function in tree-sra.c, which has become
> too generic for little benefit or purpose, making it unnecessary
> difficult to understand and maintain, let alone extend.  Currently it
> drives function body traversal of intra-SRA analysis and
> transformation and IPA-SRA analysis and transformation.  I have left
> the analyses in it and moved both transformations to separate
> functions.
> 
> The patch does not change the functionality in any way.
> 
> I'm now looking at how to solve the IPA-SRA function declaration
> problems, nevertheless all approaches are based on this patch so that
> I have the IPA-SRA transformation isolated.
> 
> Bootstrapped and regression tested on x86-64-linux.  OK for trunk?

Ok.

Thanks,
Richard.

> Thanks,
> 
> Martin
> 
> 
> 2010-04-28  Martin Jambor  <mjambor@suse.cz>
> 
> 	* tree-sra.c (build_access_from_expr_1): The first parameter type
> 	changed to simple tree.
> 	(build_access_from_expr): Likewise, gsi parameter was eliminated.
> 	(scan_assign_result): Renamed to assignment_mod_result, enum elements
> 	renamed as well.
> 	(build_accesses_from_assign): Removed all parameters except for a
> 	simple gimple statement.  Now returns a simple bool.
> 	(scan_function): All non-analysis parts moved to separate functions
> 	sra_modify_function_body and ipa_sra_modify_function_body.  Removed all
> 	parameters and updated both callers.
> 	(sra_modify_expr): Removed parameter data.
> 	(sra_modify_function_body): New function.
> 	(perform_intra_sra): Call sra_modify_function_body to modify the
> 	function body.
> 	(replace_removed_params_ssa_names): Parameter data changed into
> 	adjustments vector.
> 	(sra_ipa_modify_expr): Likewise.  Also removed unused parameter gsi and
> 	changed the parameter dont_convert to convert with the opposite
> 	meaning.
> 	(sra_ipa_modify_assign): Parameter data changed into adjustments
> 	vector, return value changed to bool.
> 	(ipa_sra_modify_function_body): New function.
> 	(sra_ipa_reset_debug_stmts): Updated a comment.
> 	(modify_function): Use ipa_sra_modify_function_body to modify function
> 	body.
> 
> Index: mine/gcc/tree-sra.c
> ===================================================================
> *** mine.orig/gcc/tree-sra.c
> --- mine/gcc/tree-sra.c
> *************** disqualify_base_of_expr (tree t, const c
> *** 903,912 ****
>      created.  */
>   
>   static struct access *
> ! build_access_from_expr_1 (tree *expr_ptr, gimple stmt, bool write)
>   {
>     struct access *ret = NULL;
> -   tree expr = *expr_ptr;
>     bool partial_ref;
>   
>     if (TREE_CODE (expr) == BIT_FIELD_REF
> --- 903,911 ----
>      created.  */
>   
>   static struct access *
> ! build_access_from_expr_1 (tree expr, gimple stmt, bool write)
>   {
>     struct access *ret = NULL;
>     bool partial_ref;
>   
>     if (TREE_CODE (expr) == BIT_FIELD_REF
> *************** build_access_from_expr_1 (tree *expr_ptr
> *** 958,975 ****
>     return ret;
>   }
>   
> ! /* Callback of scan_function.  Scan expression EXPR and create access
> !    structures for all accesses to candidates for scalarization.  Return true if
> !    any access has been inserted.  */
>   
>   static bool
> ! build_access_from_expr (tree *expr_ptr,
> ! 			gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED, bool write,
> ! 			void *data ATTRIBUTE_UNUSED)
>   {
>     struct access *access;
>   
> !   access = build_access_from_expr_1 (expr_ptr, gsi_stmt (*gsi), write);
>     if (access)
>       {
>         /* This means the aggregate is accesses as a whole in a way other than an
> --- 957,973 ----
>     return ret;
>   }
>   
> ! /* Scan expression EXPR and create access structures for all accesses to
> !    candidates for scalarization.  Return true if any access has been inserted.
> !    STMT must be the statement from which the expression is taken, WRITE must be
> !    true if the expression is a store and false otherwise. */
>   
>   static bool
> ! build_access_from_expr (tree expr, gimple stmt, bool write)
>   {
>     struct access *access;
>   
> !   access = build_access_from_expr_1 (expr, stmt, write);
>     if (access)
>       {
>         /* This means the aggregate is accesses as a whole in a way other than an
> *************** disqualify_ops_if_throwing_stmt (gimple
> *** 1001,1039 ****
>     return false;
>   }
>   
> ! 
> ! /* Result code for scan_assign callback for scan_function.  */
> ! enum scan_assign_result { SRA_SA_NONE,       /* nothing done for the stmt */
> ! 			  SRA_SA_PROCESSED,  /* stmt analyzed/changed */
> ! 			  SRA_SA_REMOVED };  /* stmt redundant and eliminated */
> ! 
> ! 
> ! /* Callback of scan_function.  Scan expressions occuring in the statement
> !    pointed to by STMT_EXPR, create access structures for all accesses to
> !    candidates for scalarization and remove those candidates which occur in
>      statements or expressions that prevent them from being split apart.  Return
>      true if any access has been inserted.  */
>   
> ! static enum scan_assign_result
> ! build_accesses_from_assign (gimple *stmt_ptr,
> ! 			    gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
> ! 			    void *data ATTRIBUTE_UNUSED)
>   {
> !   gimple stmt = *stmt_ptr;
> !   tree *lhs_ptr, *rhs_ptr;
>     struct access *lacc, *racc;
>   
>     if (!gimple_assign_single_p (stmt))
> !     return SRA_SA_NONE;
>   
> !   lhs_ptr = gimple_assign_lhs_ptr (stmt);
> !   rhs_ptr = gimple_assign_rhs1_ptr (stmt);
>   
> !   if (disqualify_ops_if_throwing_stmt (stmt, *lhs_ptr, *rhs_ptr))
> !     return SRA_SA_NONE;
>   
> !   racc = build_access_from_expr_1 (rhs_ptr, stmt, false);
> !   lacc = build_access_from_expr_1 (lhs_ptr, stmt, true);
>   
>     if (racc)
>       {
> --- 999,1026 ----
>     return false;
>   }
>   
> ! /* Scan expressions occuring in STMT, create access structures for all accesses
> !    to candidates for scalarization and remove those candidates which occur in
>      statements or expressions that prevent them from being split apart.  Return
>      true if any access has been inserted.  */
>   
> ! static bool
> ! build_accesses_from_assign (gimple stmt)
>   {
> !   tree lhs, rhs;
>     struct access *lacc, *racc;
>   
>     if (!gimple_assign_single_p (stmt))
> !     return false;
>   
> !   lhs = gimple_assign_lhs (stmt);
> !   rhs = gimple_assign_rhs1 (stmt);
>   
> !   if (disqualify_ops_if_throwing_stmt (stmt, lhs, rhs))
> !     return false;
>   
> !   racc = build_access_from_expr_1 (rhs, stmt, false);
> !   lacc = build_access_from_expr_1 (lhs, stmt, true);
>   
>     if (racc)
>       {
> *************** build_accesses_from_assign (gimple *stmt
> *** 1047,1053 ****
>         && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
>         && !lacc->grp_unscalarizable_region
>         && !racc->grp_unscalarizable_region
> !       && AGGREGATE_TYPE_P (TREE_TYPE (*lhs_ptr))
>         /* FIXME: Turn the following line into an assert after PR 40058 is
>   	 fixed.  */
>         && lacc->size == racc->size
> --- 1034,1040 ----
>         && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
>         && !lacc->grp_unscalarizable_region
>         && !racc->grp_unscalarizable_region
> !       && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
>         /* FIXME: Turn the following line into an assert after PR 40058 is
>   	 fixed.  */
>         && lacc->size == racc->size
> *************** build_accesses_from_assign (gimple *stmt
> *** 1064,1070 ****
>         add_link_to_rhs (racc, link);
>       }
>   
> !   return (lacc || racc) ? SRA_SA_PROCESSED : SRA_SA_NONE;
>   }
>   
>   /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
> --- 1051,1057 ----
>         add_link_to_rhs (racc, link);
>       }
>   
> !   return lacc || racc;
>   }
>   
>   /* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
> *************** callsite_has_enough_arguments_p (gimple
> *** 1091,1166 ****
>     return gimple_call_num_args (call) >= (unsigned) func_param_count;
>   }
>   
> ! /* Scan function and look for interesting statements. Return true if any has
> !    been found or processed, as indicated by callbacks.  SCAN_EXPR is a callback
> !    called on all expressions within statements except assign statements and
> !    those deemed entirely unsuitable for some reason (all operands in such
> !    statements and expression are removed from candidate_bitmap).  SCAN_ASSIGN
> !    is a callback called on all assign statements, HANDLE_SSA_DEFS is a callback
> !    called on assign statements and those call statements which have a lhs, it
> !    can be NULL.  ANALYSIS_STAGE is true when running in the analysis stage of a
> !    pass and thus no statement is being modified.  DATA is a pointer passed to
> !    all callbacks.  If any single callback returns true, this function also
> !    returns true, otherwise it returns false.  */
> ! 
> ! static bool
> ! scan_function (bool (*scan_expr) (tree *, gimple_stmt_iterator *, bool, void *),
> ! 	       enum scan_assign_result (*scan_assign) (gimple *,
> ! 						       gimple_stmt_iterator *,
> ! 						       void *),
> ! 	       bool (*handle_ssa_defs)(gimple, void *),
> ! 	       bool analysis_stage, void *data)
>   {
> -   gimple_stmt_iterator gsi;
>     basic_block bb;
> -   unsigned i;
> -   tree *t;
>     bool ret = false;
>   
>     FOR_EACH_BB (bb)
>       {
> !       bool bb_changed = false;
> ! 
> !       if (handle_ssa_defs)
> ! 	for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> ! 	  ret |= handle_ssa_defs (gsi_stmt (gsi), data);
> ! 
> !       gsi = gsi_start_bb (bb);
> !       while (!gsi_end_p (gsi))
>   	{
>   	  gimple stmt = gsi_stmt (gsi);
> ! 	  enum scan_assign_result assign_result;
> ! 	  bool any = false, deleted = false;
>   
> ! 	  if (analysis_stage && final_bbs && stmt_can_throw_external (stmt))
>   	    bitmap_set_bit (final_bbs, bb->index);
>   	  switch (gimple_code (stmt))
>   	    {
>   	    case GIMPLE_RETURN:
> ! 	      t = gimple_return_retval_ptr (stmt);
> ! 	      if (*t != NULL_TREE)
> ! 		any |= scan_expr (t, &gsi, false, data);
> ! 	      if (analysis_stage && final_bbs)
>   		bitmap_set_bit (final_bbs, bb->index);
>   	      break;
>   
>   	    case GIMPLE_ASSIGN:
> ! 	      assign_result = scan_assign (&stmt, &gsi, data);
> ! 	      any |= assign_result == SRA_SA_PROCESSED;
> ! 	      deleted = assign_result == SRA_SA_REMOVED;
> ! 	      if (handle_ssa_defs && assign_result != SRA_SA_REMOVED)
> ! 		any |= handle_ssa_defs (stmt, data);
>   	      break;
>   
>   	    case GIMPLE_CALL:
> - 	      /* Operands must be processed before the lhs.  */
>   	      for (i = 0; i < gimple_call_num_args (stmt); i++)
> ! 		{
> ! 		  tree *argp = gimple_call_arg_ptr (stmt, i);
> ! 		  any |= scan_expr (argp, &gsi, false, data);
> ! 		}
>   
> ! 	      if (analysis_stage && sra_mode == SRA_MODE_EARLY_IPA)
>   		{
>   		  tree dest = gimple_call_fndecl (stmt);
>   		  int flags = gimple_call_flags (stmt);
> --- 1078,1123 ----
>     return gimple_call_num_args (call) >= (unsigned) func_param_count;
>   }
>   
> ! /* Scan function and look for interesting expressions and create access
> !    structures for them.  Return true iff any access is created.  */
> ! 
> ! static bool
> ! scan_function (void)
>   {
>     basic_block bb;
>     bool ret = false;
>   
>     FOR_EACH_BB (bb)
>       {
> !       gimple_stmt_iterator gsi;
> !       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
>   	{
>   	  gimple stmt = gsi_stmt (gsi);
> ! 	  tree t;
> ! 	  unsigned i;
>   
> ! 	  if (final_bbs && stmt_can_throw_external (stmt))
>   	    bitmap_set_bit (final_bbs, bb->index);
>   	  switch (gimple_code (stmt))
>   	    {
>   	    case GIMPLE_RETURN:
> ! 	      t = gimple_return_retval (stmt);
> ! 	      if (t != NULL_TREE)
> ! 		ret |= build_access_from_expr (t, stmt, false);
> ! 	      if (final_bbs)
>   		bitmap_set_bit (final_bbs, bb->index);
>   	      break;
>   
>   	    case GIMPLE_ASSIGN:
> ! 	      ret |= build_accesses_from_assign (stmt);
>   	      break;
>   
>   	    case GIMPLE_CALL:
>   	      for (i = 0; i < gimple_call_num_args (stmt); i++)
> ! 		ret |= build_access_from_expr (gimple_call_arg (stmt, i),
> ! 					       stmt, false);
>   
> ! 	      if (sra_mode == SRA_MODE_EARLY_IPA)
>   		{
>   		  tree dest = gimple_call_fndecl (stmt);
>   		  int flags = gimple_call_flags (stmt);
> *************** scan_function (bool (*scan_expr) (tree *
> *** 1184,1248 ****
>   		    bitmap_set_bit (final_bbs, bb->index);
>   		}
>   
> ! 	      if (gimple_call_lhs (stmt))
> ! 		{
> ! 		  tree *lhs_ptr = gimple_call_lhs_ptr (stmt);
> ! 		  if (!analysis_stage
> ! 		      || !disqualify_ops_if_throwing_stmt (stmt,
> ! 							   *lhs_ptr, NULL))
> ! 		    {
> ! 		      any |= scan_expr (lhs_ptr, &gsi, true, data);
> ! 		      if (handle_ssa_defs)
> ! 			any |= handle_ssa_defs (stmt, data);
> ! 		    }
> ! 		}
>   	      break;
>   
>   	    case GIMPLE_ASM:
> ! 	      if (analysis_stage)
> ! 		{
> ! 		  walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL,
> ! 						 asm_visit_addr);
> ! 		  if (final_bbs)
> ! 		    bitmap_set_bit (final_bbs, bb->index);
> ! 		}
>   	      for (i = 0; i < gimple_asm_ninputs (stmt); i++)
>   		{
> ! 		  tree *op = &TREE_VALUE (gimple_asm_input_op (stmt, i));
> ! 		  any |= scan_expr (op, &gsi, false, data);
>   		}
>   	      for (i = 0; i < gimple_asm_noutputs (stmt); i++)
>   		{
> ! 		  tree *op = &TREE_VALUE (gimple_asm_output_op (stmt, i));
> ! 		  any |= scan_expr (op, &gsi, true, data);
>   		}
>   	      break;
>   
>   	    default:
>   	      break;
>   	    }
> - 
> - 	  if (any)
> - 	    {
> - 	      ret = true;
> - 
> - 	      if (!analysis_stage)
> - 		{
> - 		  bb_changed = true;
> - 		  update_stmt (stmt);
> - 		  maybe_clean_eh_stmt (stmt);
> - 		}
> - 	    }
> - 	  if (deleted)
> - 	    bb_changed = true;
> - 	  else
> - 	    {
> - 	      gsi_next (&gsi);
> - 	      ret = true;
> - 	    }
>   	}
> -       if (!analysis_stage && bb_changed && sra_mode == SRA_MODE_EARLY_IPA)
> - 	gimple_purge_dead_eh_edges (bb);
>       }
>   
>     return ret;
> --- 1141,1173 ----
>   		    bitmap_set_bit (final_bbs, bb->index);
>   		}
>   
> ! 	      t = gimple_call_lhs (stmt);
> ! 	      if (t && !disqualify_ops_if_throwing_stmt (stmt, t, NULL))
> ! 		ret |= build_access_from_expr (t, stmt, true);
>   	      break;
>   
>   	    case GIMPLE_ASM:
> ! 	      walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL,
> ! 					     asm_visit_addr);
> ! 	      if (final_bbs)
> ! 		bitmap_set_bit (final_bbs, bb->index);
> ! 
>   	      for (i = 0; i < gimple_asm_ninputs (stmt); i++)
>   		{
> ! 		  t = TREE_VALUE (gimple_asm_input_op (stmt, i));
> ! 		  ret |= build_access_from_expr (t, stmt, false);
>   		}
>   	      for (i = 0; i < gimple_asm_noutputs (stmt); i++)
>   		{
> ! 		  t = TREE_VALUE (gimple_asm_output_op (stmt, i));
> ! 		  ret |= build_access_from_expr (t, stmt, true);
>   		}
>   	      break;
>   
>   	    default:
>   	      break;
>   	    }
>   	}
>       }
>   
>     return ret;
> *************** get_access_for_expr (tree expr)
> *** 2300,2314 ****
>     return get_var_base_offset_size_access (base, offset, max_size);
>   }
>   
> ! /* Callback for scan_function.  Replace the expression EXPR with a scalar
> !    replacement if there is one and generate other statements to do type
> !    conversion or subtree copying if necessary.  GSI is used to place newly
> !    created statements, WRITE is true if the expression is being written to (it
> !    is on a LHS of a statement or output in an assembly statement).  */
>   
>   static bool
> ! sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write,
> ! 		 void *data ATTRIBUTE_UNUSED)
>   {
>     struct access *access;
>     tree type, bfr;
> --- 2225,2238 ----
>     return get_var_base_offset_size_access (base, offset, max_size);
>   }
>   
> ! /* Replace the expression EXPR with a scalar replacement if there is one and
> !    generate other statements to do type conversion or subtree copying if
> !    necessary.  GSI is used to place newly created statements, WRITE is true if
> !    the expression is being written to (it is on a LHS of a statement or output
> !    in an assembly statement).  */
>   
>   static bool
> ! sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
>   {
>     struct access *access;
>     tree type, bfr;
> *************** load_assign_lhs_subreplacements (struct
> *** 2510,2520 ****
>     while (lacc);
>   }
>   
>   /* Modify assignments with a CONSTRUCTOR on their RHS.  STMT contains a pointer
>      to the assignment and GSI is the statement iterator pointing at it.  Returns
>      the same values as sra_modify_assign.  */
>   
> ! static enum scan_assign_result
>   sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
>   {
>     tree lhs = gimple_assign_lhs (*stmt);
> --- 2434,2450 ----
>     while (lacc);
>   }
>   
> + /* Result code for SRA assignment modification.  */
> + enum assignment_mod_result { SRA_AM_NONE,       /* nothing done for the stmt */
> + 			     SRA_AM_MODIFIED,  /* stmt changed but not
> + 						  removed */
> + 			     SRA_AM_REMOVED };  /* stmt eliminated */
> + 
>   /* Modify assignments with a CONSTRUCTOR on their RHS.  STMT contains a pointer
>      to the assignment and GSI is the statement iterator pointing at it.  Returns
>      the same values as sra_modify_assign.  */
>   
> ! static enum assignment_mod_result
>   sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
>   {
>     tree lhs = gimple_assign_lhs (*stmt);
> *************** sra_modify_constructor_assign (gimple *s
> *** 2522,2528 ****
>   
>     acc = get_access_for_expr (lhs);
>     if (!acc)
> !     return SRA_SA_NONE;
>   
>     if (VEC_length (constructor_elt,
>   		  CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0)
> --- 2452,2458 ----
>   
>     acc = get_access_for_expr (lhs);
>     if (!acc)
> !     return SRA_AM_NONE;
>   
>     if (VEC_length (constructor_elt,
>   		  CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0)
> *************** sra_modify_constructor_assign (gimple *s
> *** 2532,2538 ****
>         if (access_has_children_p (acc))
>   	generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
>   				 true, true);
> !       return SRA_SA_PROCESSED;
>       }
>   
>     if (acc->grp_covered)
> --- 2462,2468 ----
>         if (access_has_children_p (acc))
>   	generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
>   				 true, true);
> !       return SRA_AM_MODIFIED;
>       }
>   
>     if (acc->grp_covered)
> *************** sra_modify_constructor_assign (gimple *s
> *** 2540,2551 ****
>         init_subtree_with_zero (acc, gsi, false);
>         unlink_stmt_vdef (*stmt);
>         gsi_remove (gsi, true);
> !       return SRA_SA_REMOVED;
>       }
>     else
>       {
>         init_subtree_with_zero (acc, gsi, true);
> !       return SRA_SA_PROCESSED;
>       }
>   }
>   
> --- 2470,2481 ----
>         init_subtree_with_zero (acc, gsi, false);
>         unlink_stmt_vdef (*stmt);
>         gsi_remove (gsi, true);
> !       return SRA_AM_REMOVED;
>       }
>     else
>       {
>         init_subtree_with_zero (acc, gsi, true);
> !       return SRA_AM_MODIFIED;
>       }
>   }
>   
> *************** replace_uses_with_default_def_ssa_name (
> *** 2578,2593 ****
>     replace_uses_by (ssa, repl);
>   }
>   
> ! /* Callback of scan_function to process assign statements.  It examines both
> !    sides of the statement, replaces them with a scalare replacement if there is
> !    one and generating copying of replacements if scalarized aggregates have been
> !    used in the assignment.  STMT is a pointer to the assign statement, GSI is
> !    used to hold generated statements for type conversions and subtree
>      copying.  */
>   
> ! static enum scan_assign_result
> ! sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
> ! 		   void *data ATTRIBUTE_UNUSED)
>   {
>     struct access *lacc, *racc;
>     tree lhs, rhs;
> --- 2508,2521 ----
>     replace_uses_by (ssa, repl);
>   }
>   
> ! /* Examine both sides of the assignment statement pointed to by STMT, replace
> !    them with a scalare replacement if there is one and generate copying of
> !    replacements if scalarized aggregates have been used in the assignment.  GSI
> !    is used to hold generated statements for type conversions and subtree
>      copying.  */
>   
> ! static enum assignment_mod_result
> ! sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
>   {
>     struct access *lacc, *racc;
>     tree lhs, rhs;
> *************** sra_modify_assign (gimple *stmt, gimple_
> *** 2597,2603 ****
>     gimple_stmt_iterator orig_gsi = *gsi;
>   
>     if (!gimple_assign_single_p (*stmt))
> !     return SRA_SA_NONE;
>     lhs = gimple_assign_lhs (*stmt);
>     rhs = gimple_assign_rhs1 (*stmt);
>   
> --- 2525,2531 ----
>     gimple_stmt_iterator orig_gsi = *gsi;
>   
>     if (!gimple_assign_single_p (*stmt))
> !     return SRA_AM_NONE;
>     lhs = gimple_assign_lhs (*stmt);
>     rhs = gimple_assign_rhs1 (*stmt);
>   
> *************** sra_modify_assign (gimple *stmt, gimple_
> *** 2609,2624 ****
>         || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
>       {
>         modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt),
> ! 					  gsi, false, data);
>         modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt),
> ! 					   gsi, true, data);
> !       return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
>       }
>   
>     lacc = get_access_for_expr (lhs);
>     racc = get_access_for_expr (rhs);
>     if (!lacc && !racc)
> !     return SRA_SA_NONE;
>   
>     if (lacc && lacc->grp_to_be_replaced)
>       {
> --- 2537,2552 ----
>         || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
>       {
>         modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt),
> ! 					  gsi, false);
>         modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt),
> ! 					   gsi, true);
> !       return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
>       }
>   
>     lacc = get_access_for_expr (lhs);
>     racc = get_access_for_expr (rhs);
>     if (!lacc && !racc)
> !     return SRA_AM_NONE;
>   
>     if (lacc && lacc->grp_to_be_replaced)
>       {
> *************** sra_modify_assign (gimple *stmt, gimple_
> *** 2747,2753 ****
>   	      unlink_stmt_vdef (*stmt);
>   	      gsi_remove (&orig_gsi, true);
>   	      sra_stats.deleted++;
> ! 	      return SRA_SA_REMOVED;
>   	    }
>   	}
>         else
> --- 2675,2681 ----
>   	      unlink_stmt_vdef (*stmt);
>   	      gsi_remove (&orig_gsi, true);
>   	      sra_stats.deleted++;
> ! 	      return SRA_AM_REMOVED;
>   	    }
>   	}
>         else
> *************** sra_modify_assign (gimple *stmt, gimple_
> *** 2767,2773 ****
>   		  unlink_stmt_vdef (*stmt);
>   		  gsi_remove (gsi, true);
>   		  sra_stats.deleted++;
> ! 		  return SRA_SA_REMOVED;
>   		}
>   	      else if (racc->first_child)
>   		generate_subtree_copies (racc->first_child, lhs,
> --- 2695,2701 ----
>   		  unlink_stmt_vdef (*stmt);
>   		  gsi_remove (gsi, true);
>   		  sra_stats.deleted++;
> ! 		  return SRA_AM_REMOVED;
>   		}
>   	      else if (racc->first_child)
>   		generate_subtree_copies (racc->first_child, lhs,
> *************** sra_modify_assign (gimple *stmt, gimple_
> *** 2790,2796 ****
>         gcc_assert (*stmt == gsi_stmt (orig_gsi));
>       }
>   
> !   return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
>   }
>   
>   /* Generate statements initializing scalar replacements of parts of function
> --- 2718,2800 ----
>         gcc_assert (*stmt == gsi_stmt (orig_gsi));
>       }
>   
> !   return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
> ! }
> ! 
> ! /* Traverse the function body and all modifications as decided in
> !    analyze_all_variable_accesses.  */
> ! 
> ! static void
> ! sra_modify_function_body (void)
> ! {
> !   basic_block bb;
> ! 
> !   FOR_EACH_BB (bb)
> !     {
> !       gimple_stmt_iterator gsi = gsi_start_bb (bb);
> !       while (!gsi_end_p (gsi))
> ! 	{
> ! 	  gimple stmt = gsi_stmt (gsi);
> ! 	  enum assignment_mod_result assign_result;
> ! 	  bool modified = false, deleted = false;
> ! 	  tree *t;
> ! 	  unsigned i;
> ! 
> ! 	  switch (gimple_code (stmt))
> ! 	    {
> ! 	    case GIMPLE_RETURN:
> ! 	      t = gimple_return_retval_ptr (stmt);
> ! 	      if (*t != NULL_TREE)
> ! 		modified |= sra_modify_expr (t, &gsi, false);
> ! 	      break;
> ! 
> ! 	    case GIMPLE_ASSIGN:
> ! 	      assign_result = sra_modify_assign (&stmt, &gsi);
> ! 	      modified |= assign_result == SRA_AM_MODIFIED;
> ! 	      deleted = assign_result == SRA_AM_REMOVED;
> ! 	      break;
> ! 
> ! 	    case GIMPLE_CALL:
> ! 	      /* Operands must be processed before the lhs.  */
> ! 	      for (i = 0; i < gimple_call_num_args (stmt); i++)
> ! 		{
> ! 		  t = gimple_call_arg_ptr (stmt, i);
> ! 		  modified |= sra_modify_expr (t, &gsi, false);
> ! 		}
> ! 
> ! 	      if (gimple_call_lhs (stmt))
> ! 		{
> ! 		  t = gimple_call_lhs_ptr (stmt);
> ! 		  modified |= sra_modify_expr (t, &gsi, true);
> ! 		}
> ! 	      break;
> ! 
> ! 	    case GIMPLE_ASM:
> ! 	      for (i = 0; i < gimple_asm_ninputs (stmt); i++)
> ! 		{
> ! 		  t = &TREE_VALUE (gimple_asm_input_op (stmt, i));
> ! 		  modified |= sra_modify_expr (t, &gsi, false);
> ! 		}
> ! 	      for (i = 0; i < gimple_asm_noutputs (stmt); i++)
> ! 		{
> ! 		  t = &TREE_VALUE (gimple_asm_output_op (stmt, i));
> ! 		  modified |= sra_modify_expr (t, &gsi, true);
> ! 		}
> ! 	      break;
> ! 
> ! 	    default:
> ! 	      break;
> ! 	    }
> ! 
> ! 	  if (modified)
> ! 	    {
> ! 	      update_stmt (stmt);
> ! 	      maybe_clean_eh_stmt (stmt);
> ! 	    }
> ! 	  if (!deleted)
> ! 	    gsi_next (&gsi);
> ! 	}
> !     }
>   }
>   
>   /* Generate statements initializing scalar replacements of parts of function
> *************** perform_intra_sra (void)
> *** 2844,2857 ****
>     if (!find_var_candidates ())
>       goto out;
>   
> !   if (!scan_function (build_access_from_expr, build_accesses_from_assign, NULL,
> ! 		      true, NULL))
>       goto out;
>   
>     if (!analyze_all_variable_accesses ())
>       goto out;
>   
> !   scan_function (sra_modify_expr, sra_modify_assign, NULL, false, NULL);
>     initialize_parameter_reductions ();
>   
>     statistics_counter_event (cfun, "Scalar replacements created",
> --- 2848,2860 ----
>     if (!find_var_candidates ())
>       goto out;
>   
> !   if (!scan_function ())
>       goto out;
>   
>     if (!analyze_all_variable_accesses ())
>       goto out;
>   
> !   sra_modify_function_body ();
>     initialize_parameter_reductions ();
>   
>     statistics_counter_event (cfun, "Scalar replacements created",
> *************** get_adjustment_for_base (ipa_parm_adjust
> *** 3786,3805 ****
>     return NULL;
>   }
>   
> ! /* Callback for scan_function.  If the statement STMT defines an SSA_NAME of a
> !    parameter which is to be removed because its value is not used, replace the
> !    SSA_NAME with a one relating to a created VAR_DECL and replace all of its
> !    uses too and return true (update_stmt is then issued for the statement by
> !    the caller).  DATA is a pointer to an adjustments vector.  */
>   
>   static bool
> ! replace_removed_params_ssa_names (gimple stmt, void *data)
>   {
> -   VEC (ipa_parm_adjustment_t, heap) *adjustments;
>     struct ipa_parm_adjustment *adj;
>     tree lhs, decl, repl, name;
>   
> -   adjustments = (VEC (ipa_parm_adjustment_t, heap) *) data;
>     if (gimple_code (stmt) == GIMPLE_PHI)
>       lhs = gimple_phi_result (stmt);
>     else if (is_gimple_assign (stmt))
> --- 3789,3806 ----
>     return NULL;
>   }
>   
> ! /* If the statement STMT defines an SSA_NAME of a parameter which is to be
> !    removed because its value is not used, replace the SSA_NAME with a one
> !    relating to a created VAR_DECL together all of its uses and return true.
> !    ADJUSTMENTS is a pointer to an adjustments vector.  */
>   
>   static bool
> ! replace_removed_params_ssa_names (gimple stmt,
> ! 				  ipa_parm_adjustment_vec adjustments)
>   {
>     struct ipa_parm_adjustment *adj;
>     tree lhs, decl, repl, name;
>   
>     if (gimple_code (stmt) == GIMPLE_PHI)
>       lhs = gimple_phi_result (stmt);
>     else if (is_gimple_assign (stmt))
> *************** replace_removed_params_ssa_names (gimple
> *** 3842,3868 ****
>     return true;
>   }
>   
> ! /* Callback for scan_function and helper to sra_ipa_modify_assign.  If the
> !    expression *EXPR should be replaced by a reduction of a parameter, do so.
> !    DATA is a pointer to a vector of adjustments.  DONT_CONVERT specifies
> !    whether the function should care about type incompatibility the current and
> !    new expressions.  If it is true, the function will leave incompatibility
> !    issues to the caller.
> ! 
> !    When called directly by scan_function, DONT_CONVERT is true when the EXPR is
> !    a write (LHS) expression.  */
>   
>   static bool
> ! sra_ipa_modify_expr (tree *expr, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
> ! 		     bool dont_convert, void *data)
>   {
> -   ipa_parm_adjustment_vec adjustments;
>     int i, len;
>     struct ipa_parm_adjustment *adj, *cand = NULL;
>     HOST_WIDE_INT offset, size, max_size;
>     tree base, src;
>   
> -   adjustments = (VEC (ipa_parm_adjustment_t, heap) *) data;
>     len = VEC_length (ipa_parm_adjustment_t, adjustments);
>   
>     if (TREE_CODE (*expr) == BIT_FIELD_REF
> --- 3843,3864 ----
>     return true;
>   }
>   
> ! /* If the expression *EXPR should be replaced by a reduction of a parameter, do
> !    so.  ADJUSTMENTS is a pointer to a vector of adjustments.  CONVERT
> !    specifies whether the function should care about type incompatibility the
> !    current and new expressions.  If it is false, the function will leave
> !    incompatibility issues to the caller.  Return true iff the expression
> !    was modified. */
>   
>   static bool
> ! sra_ipa_modify_expr (tree *expr, bool convert,
> ! 		     ipa_parm_adjustment_vec adjustments)
>   {
>     int i, len;
>     struct ipa_parm_adjustment *adj, *cand = NULL;
>     HOST_WIDE_INT offset, size, max_size;
>     tree base, src;
>   
>     len = VEC_length (ipa_parm_adjustment_t, adjustments);
>   
>     if (TREE_CODE (*expr) == BIT_FIELD_REF
> *************** sra_ipa_modify_expr (tree *expr, gimple_
> *** 3870,3876 ****
>         || TREE_CODE (*expr) == REALPART_EXPR)
>       {
>         expr = &TREE_OPERAND (*expr, 0);
> !       dont_convert = false;
>       }
>   
>     base = get_ref_base_and_extent (*expr, &offset, &size, &max_size);
> --- 3866,3872 ----
>         || TREE_CODE (*expr) == REALPART_EXPR)
>       {
>         expr = &TREE_OPERAND (*expr, 0);
> !       convert = true;
>       }
>   
>     base = get_ref_base_and_extent (*expr, &offset, &size, &max_size);
> *************** sra_ipa_modify_expr (tree *expr, gimple_
> *** 3919,3926 ****
>         fprintf (dump_file, "\n");
>       }
>   
> !   if (!dont_convert
> !       && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
>       {
>         tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src);
>         *expr = vce;
> --- 3915,3921 ----
>         fprintf (dump_file, "\n");
>       }
>   
> !   if (convert && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
>       {
>         tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src);
>         *expr = vce;
> *************** sra_ipa_modify_expr (tree *expr, gimple_
> *** 3930,3953 ****
>     return true;
>   }
>   
> ! /* Callback for scan_function to process assign statements.  Performs
> !    essentially the same function like sra_ipa_modify_expr.  */
>   
> ! static enum scan_assign_result
> ! sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi, void *data)
>   {
>     gimple stmt = *stmt_ptr;
>     tree *lhs_p, *rhs_p;
>     bool any;
>   
>     if (!gimple_assign_single_p (stmt))
> !     return SRA_SA_NONE;
>   
>     rhs_p = gimple_assign_rhs1_ptr (stmt);
>     lhs_p = gimple_assign_lhs_ptr (stmt);
>   
> !   any = sra_ipa_modify_expr (rhs_p, gsi, true, data);
> !   any |= sra_ipa_modify_expr (lhs_p, gsi, true, data);
>     if (any)
>       {
>         tree new_rhs = NULL_TREE;
> --- 3925,3952 ----
>     return true;
>   }
>   
> ! /* If the statement pointed to by STMT_PTR contains any expressions that need
> !    to replaced with a different one as noted by ADJUSTMENTS, do so.  Handle any
> !    potential type incompatibilities (GSI is used to accommodate conversion
> !    statements and must point to the statement).  Return true iff the statement
> !    was modified.  */
>   
> ! static bool
> ! sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi,
> ! 		       ipa_parm_adjustment_vec adjustments)
>   {
>     gimple stmt = *stmt_ptr;
>     tree *lhs_p, *rhs_p;
>     bool any;
>   
>     if (!gimple_assign_single_p (stmt))
> !     return false;
>   
>     rhs_p = gimple_assign_rhs1_ptr (stmt);
>     lhs_p = gimple_assign_lhs_ptr (stmt);
>   
> !   any = sra_ipa_modify_expr (rhs_p, false, adjustments);
> !   any |= sra_ipa_modify_expr (lhs_p, false, adjustments);
>     if (any)
>       {
>         tree new_rhs = NULL_TREE;
> *************** sra_ipa_modify_assign (gimple *stmt_ptr,
> *** 3983,3992 ****
>   	  gimple_assign_set_rhs_from_tree (gsi, tmp);
>   	}
>   
> !       return SRA_SA_PROCESSED;
>       }
>   
> !   return SRA_SA_NONE;
>   }
>   
>   /* Call gimple_debug_bind_reset_value on all debug statements describing
> --- 3982,4075 ----
>   	  gimple_assign_set_rhs_from_tree (gsi, tmp);
>   	}
>   
> !       return true;
>       }
>   
> !   return false;
> ! }
> ! 
> ! /* Traverse the function body and all modifications as described in
> !    ADJUSTMENTS.  */
> ! 
> ! static void
> ! ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
> ! {
> !   basic_block bb;
> ! 
> !   FOR_EACH_BB (bb)
> !     {
> !       gimple_stmt_iterator gsi;
> !       bool bb_changed = false;
> ! 
> !       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> ! 	replace_removed_params_ssa_names (gsi_stmt (gsi), adjustments);
> ! 
> !       gsi = gsi_start_bb (bb);
> !       while (!gsi_end_p (gsi))
> ! 	{
> ! 	  gimple stmt = gsi_stmt (gsi);
> ! 	  bool modified = false;
> ! 	  tree *t;
> ! 	  unsigned i;
> ! 
> ! 	  switch (gimple_code (stmt))
> ! 	    {
> ! 	    case GIMPLE_RETURN:
> ! 	      t = gimple_return_retval_ptr (stmt);
> ! 	      if (*t != NULL_TREE)
> ! 		modified |= sra_ipa_modify_expr (t, true, adjustments);
> ! 	      break;
> ! 
> ! 	    case GIMPLE_ASSIGN:
> ! 	      modified |= sra_ipa_modify_assign (&stmt, &gsi, adjustments);
> ! 	      modified |= replace_removed_params_ssa_names (stmt, adjustments);
> ! 	      break;
> ! 
> ! 	    case GIMPLE_CALL:
> ! 	      /* Operands must be processed before the lhs.  */
> ! 	      for (i = 0; i < gimple_call_num_args (stmt); i++)
> ! 		{
> ! 		  t = gimple_call_arg_ptr (stmt, i);
> ! 		  modified |= sra_ipa_modify_expr (t, true, adjustments);
> ! 		}
> ! 
> ! 	      if (gimple_call_lhs (stmt))
> ! 		{
> ! 		  t = gimple_call_lhs_ptr (stmt);
> ! 		  modified |= sra_ipa_modify_expr (t, false, adjustments);
> ! 		  modified |= replace_removed_params_ssa_names (stmt,
> ! 								adjustments);
> ! 		}
> ! 	      break;
> ! 
> ! 	    case GIMPLE_ASM:
> ! 	      for (i = 0; i < gimple_asm_ninputs (stmt); i++)
> ! 		{
> ! 		  t = &TREE_VALUE (gimple_asm_input_op (stmt, i));
> ! 		  modified |= sra_ipa_modify_expr (t, true, adjustments);
> ! 		}
> ! 	      for (i = 0; i < gimple_asm_noutputs (stmt); i++)
> ! 		{
> ! 		  t = &TREE_VALUE (gimple_asm_output_op (stmt, i));
> ! 		  modified |= sra_ipa_modify_expr (t, false, adjustments);
> ! 		}
> ! 	      break;
> ! 
> ! 	    default:
> ! 	      break;
> ! 	    }
> ! 
> ! 	  if (modified)
> ! 	    {
> ! 	      bb_changed = true;
> ! 	      update_stmt (stmt);
> ! 	      maybe_clean_eh_stmt (stmt);
> ! 	    }
> ! 	  gsi_next (&gsi);
> ! 	}
> !       if (bb_changed)
> ! 	gimple_purge_dead_eh_edges (bb);
> !     }
>   }
>   
>   /* Call gimple_debug_bind_reset_value on all debug statements describing
> *************** sra_ipa_reset_debug_stmts (ipa_parm_adju
> *** 4013,4019 ****
>   	continue;
>         FOR_EACH_IMM_USE_STMT (stmt, ui, name)
>   	{
> ! 	  /* All other users must have been removed by scan_function.  */
>   	  gcc_assert (is_gimple_debug (stmt));
>   	  gimple_debug_bind_reset_value (stmt);
>   	  update_stmt (stmt);
> --- 4096,4103 ----
>   	continue;
>         FOR_EACH_IMM_USE_STMT (stmt, ui, name)
>   	{
> ! 	  /* All other users must have been removed by
> ! 	     ipa_sra_modify_function_body.  */
>   	  gcc_assert (is_gimple_debug (stmt));
>   	  gimple_debug_bind_reset_value (stmt);
>   	  update_stmt (stmt);
> *************** modify_function (struct cgraph_node *nod
> *** 4131,4138 ****
>        as following functions will use what it computed.  */
>     create_abstract_origin (current_function_decl);
>     ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA");
> !   scan_function (sra_ipa_modify_expr, sra_ipa_modify_assign,
> ! 		 replace_removed_params_ssa_names, false, adjustments);
>     sra_ipa_reset_debug_stmts (adjustments);
>     convert_callers (node, adjustments);
>     cgraph_make_node_local (node);
> --- 4215,4221 ----
>        as following functions will use what it computed.  */
>     create_abstract_origin (current_function_decl);
>     ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA");
> !   ipa_sra_modify_function_body (adjustments);
>     sra_ipa_reset_debug_stmts (adjustments);
>     convert_callers (node, adjustments);
>     cgraph_make_node_local (node);
> *************** ipa_early_sra (void)
> *** 4224,4231 ****
>   				 * last_basic_block_for_function (cfun));
>     final_bbs = BITMAP_ALLOC (NULL);
>   
> !   scan_function (build_access_from_expr, build_accesses_from_assign,
> ! 		 NULL, true, NULL);
>     if (encountered_apply_args)
>       {
>         if (dump_file)
> --- 4307,4313 ----
>   				 * last_basic_block_for_function (cfun));
>     final_bbs = BITMAP_ALLOC (NULL);
>   
> !   scan_function ();
>     if (encountered_apply_args)
>       {
>         if (dump_file)
> 
> 

-- 
Richard Guenther <rguenther@suse.de>
Novell / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 - GF: Markus Rex



More information about the Gcc-patches mailing list