This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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?

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)


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