Propagate will_be_nonconstant in ipa-analysis

Jan Hubicka hubicka@ucw.cz
Thu Apr 28 12:42:00 GMT 2011


Hi,
tthis patch makes inliner to handle nested expressions when trying to figure out what
will be constant after inlining.  This is done by simple propagation across SSA names.
We can't really handle PHIs well, since we know name will be constant, but we don't know
what, so this is a lot weakter than SCCP, should be enough for cases inliner is interested in.

We would get better results running this in DFS order, but at the momemnt we don't have any
funcition computing it when cfun is not set.  I will do that incrementally.

Bootstrapped/regtested x86_64-linux, will commit it later today.

Honza

	* ipa-inline-analysis.c (will_be_nonconstant_predicate): Take nonconstant_names
	array.
	(estimate_function_body_sizes): Build nonconstant_names array; handle
	BUILT_IN_CONSTANT_P.
Index: ipa-inline-analysis.c
===================================================================
*** ipa-inline-analysis.c	(revision 173042)
--- ipa-inline-analysis.c	(working copy)
*************** edge_execution_predicate (struct ipa_nod
*** 931,940 ****
  			gimple_cond_rhs (last));
  }
  
  static struct predicate
  will_be_nonconstant_predicate (struct ipa_node_params *info,
  			       struct inline_summary *summary,
! 			       gimple stmt)
  {
    struct predicate p = true_predicate ();
    ssa_op_iter iter;
--- 931,953 ----
  			gimple_cond_rhs (last));
  }
  
+ 
+ /* We keep info about constantness of SSA names.  */
+ 
+ typedef struct predicate predicate_t;
+ DEF_VEC_O (predicate_t);
+ DEF_VEC_ALLOC_O (predicate_t, heap);
+ 
+ 
+ /* Return predicate specifying when the STMT might have result that is not a compile
+    time constant.  */
+ 
  static struct predicate
  will_be_nonconstant_predicate (struct ipa_node_params *info,
  			       struct inline_summary *summary,
! 			       gimple stmt,
! 			       VEC (predicate_t, heap) *nonconstant_names)
! 			      
  {
    struct predicate p = true_predicate ();
    ssa_op_iter iter;
*************** will_be_nonconstant_predicate (struct ip
*** 949,955 ****
        && gimple_code (stmt) != GIMPLE_SWITCH)
      return p;
  
!   /* Stores and loads will stay anyway.  */
    if (gimple_vuse (stmt))
      return p;
  
--- 962,969 ----
        && gimple_code (stmt) != GIMPLE_SWITCH)
      return p;
  
!   /* Stores and loads will stay anyway.
!      TODO: Constant memory accesses could be handled here, too.  */
    if (gimple_vuse (stmt))
      return p;
  
*************** will_be_nonconstant_predicate (struct ip
*** 957,977 ****
       adding conditionals.  */
    FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
      {
!       /* TODO: handle nested expressions and constant
! 	 array accesses.  */
!       if (TREE_CODE (use) != SSA_NAME
! 	  || !SSA_NAME_IS_DEFAULT_DEF (use)
! 	  || ipa_get_param_decl_index (info, SSA_NAME_VAR (use)) < 0)
  	return p;
      }
    op_non_const = false_predicate ();
    FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
      {
!       p = add_condition (summary,
! 			 ipa_get_param_decl_index (info, SSA_NAME_VAR (use)),
! 			 IS_NOT_CONSTANT, NULL);
        op_non_const = or_predicates (&p, &op_non_const);
      }
    return op_non_const;
  }
  
--- 971,1006 ----
       adding conditionals.  */
    FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
      {
!       if (TREE_CODE (use) != SSA_NAME)
  	return p;
+       /* For arguments we can build a condition.  */
+       if (SSA_NAME_IS_DEFAULT_DEF (use)
+ 	  && ipa_get_param_decl_index (info, SSA_NAME_VAR (use)) >= 0)
+ 	continue;
+       /* If we know when operand is constant,
+ 	 we still can say something useful.  */
+       if (!true_predicate_p (VEC_index (predicate_t, nonconstant_names,
+ 					SSA_NAME_VERSION (use))))
+ 	continue;
+       return p;
      }
    op_non_const = false_predicate ();
    FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
      {
!       if (SSA_NAME_IS_DEFAULT_DEF (use)
! 	  && ipa_get_param_decl_index (info, SSA_NAME_VAR (use)) >= 0)
! 	p = add_condition (summary,
! 			   ipa_get_param_decl_index (info, SSA_NAME_VAR (use)),
! 			   IS_NOT_CONSTANT, NULL);
!       else
! 	p = *VEC_index (predicate_t, nonconstant_names,
! 			SSA_NAME_VERSION (use));
        op_non_const = or_predicates (&p, &op_non_const);
      }
+   if (gimple_code (stmt) == GIMPLE_ASSIGN
+       && TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME)
+     VEC_replace (predicate_t, nonconstant_names,
+ 		 SSA_NAME_VERSION (gimple_assign_lhs (stmt)), &op_non_const);
    return op_non_const;
  }
  
*************** estimate_function_body_sizes (struct cgr
*** 994,1002 ****
    int freq;
    struct inline_summary *info = inline_summary (node);
    struct predicate bb_predicate;
!   struct ipa_node_params *parms_info;
  
!   parms_info = ipa_node_params_vector && !early ? IPA_NODE_REF (node) : NULL;
  
    info->conds = 0;
    info->entry = 0;
--- 1023,1037 ----
    int freq;
    struct inline_summary *info = inline_summary (node);
    struct predicate bb_predicate;
!   struct ipa_node_params *parms_info = NULL;
!   VEC (predicate_t, heap) *nonconstant_names = NULL;
  
!   if (ipa_node_params_vector && !early && optimize)
!     {
!       parms_info = IPA_NODE_REF (node);
!       VEC_safe_grow_cleared (predicate_t, heap, nonconstant_names,
! 			     VEC_length (tree, SSANAMES (my_function)));
!     }
  
    info->conds = 0;
    info->entry = 0;
*************** estimate_function_body_sizes (struct cgr
*** 1014,1020 ****
    bb_predicate = not_inlined_predicate ();
    account_size_time (info, 2 * INLINE_SIZE_SCALE, 0, &bb_predicate);
  
- 
    gcc_assert (my_function && my_function->cfg);
    FOR_EACH_BB_FN (bb, my_function)
      {
--- 1049,1054 ----
*************** estimate_function_body_sizes (struct cgr
*** 1063,1068 ****
--- 1097,1115 ----
  	      struct cgraph_edge *edge = cgraph_edge (node, stmt);
  	      struct inline_edge_summary *es = inline_edge_summary (edge);
  
+ 	      /* Special case: results of BUILT_IN_CONSTANT_P will be always
+ 		 resolved as constant.  We however don't want to optimize
+ 		 out the cgraph edges.  */
+ 	      if (nonconstant_names
+ 		  && gimple_call_builtin_p (stmt, BUILT_IN_CONSTANT_P)
+ 		  && gimple_call_lhs (stmt)
+ 		  && TREE_CODE (gimple_call_lhs (stmt)) == SSA_NAME)
+ 		{
+ 		  struct predicate false_p = false_predicate ();
+ 		  VEC_replace (predicate_t, nonconstant_names,
+ 			       SSA_NAME_VERSION (gimple_call_lhs (stmt)), &false_p);
+ 		}
+ 
  	      es->call_stmt_size = this_size;
  	      es->call_stmt_time = this_time;
  	      es->loop_depth = bb->loop_depth;
*************** estimate_function_body_sizes (struct cgr
*** 1098,1104 ****
  	      if (parms_info)
  		{
  		  will_be_nonconstant
! 		     = will_be_nonconstant_predicate (parms_info, info, stmt);
  		  p = and_predicates (&bb_predicate, &will_be_nonconstant);
  		}
  	      else
--- 1145,1152 ----
  	      if (parms_info)
  		{
  		  will_be_nonconstant
! 		     = will_be_nonconstant_predicate (parms_info, info,
! 						      stmt, nonconstant_names);
  		  p = and_predicates (&bb_predicate, &will_be_nonconstant);
  		}
  	      else
*************** estimate_function_body_sizes (struct cgr
*** 1131,1136 ****
--- 1179,1185 ----
      time = MAX_TIME;
    inline_summary (node)->self_time = time;
    inline_summary (node)->self_size = size;
+   VEC_free (predicate_t, heap, nonconstant_names);
    if (dump_file)
      {
        fprintf (dump_file, "\n");



More information about the Gcc-patches mailing list