diff mbox series

[2/8] ipa: Rationalize IPA-VR computations across pass-through jump functions

Message ID ri6jzdiq6pf.fsf@virgil.suse.cz
State New
Headers show
Series [1/8] ipa: Fix jump function copying | expand

Commit Message

Martin Jambor Nov. 5, 2024, 11:07 a.m. UTC
Hi,

currently ipa_value_range_from_jfunc and
propagate_vr_across_jump_function contain similar but not same code
for dealing with pass-through jump functions.  This patch puts these
common bits into one function which can also handle comparison
operations.

Bootstrapped and tested on x86_64-linux, the whole patch series has
additionally passed LTO and profiled-LTO bootstrap on the same platform
and a bootstrap and testsuite on ppc64-linux.  Aarch64-linux bootstrap
and testing is in progress.  OK for master is that passes too?

Thanks,

Martin


gcc/ChangeLog:

2024-11-01  Martin Jambor  <mjambor@suse.cz>

	PR ipa/114985
	* ipa-cp.cc (ipa_vr_intersect_with_arith_jfunc): New function.
	(ipa_value_range_from_jfunc): Move the common functionality to the
	above new function, adjust the rest so that it works with it well.
	(propagate_vr_across_jump_function): Likewise.
---
 gcc/ipa-cp.cc | 181 +++++++++++++++++++-------------------------------
 1 file changed, 67 insertions(+), 114 deletions(-)

Comments

Aldy Hernandez Nov. 5, 2024, 11:54 a.m. UTC | #1
Martin Jambor <mjambor@suse.cz> writes:

> Hi,
>
> currently ipa_value_range_from_jfunc and
> propagate_vr_across_jump_function contain similar but not same code
> for dealing with pass-through jump functions.  This patch puts these
> common bits into one function which can also handle comparison
> operations.
>
> Bootstrapped and tested on x86_64-linux, the whole patch series has
> additionally passed LTO and profiled-LTO bootstrap on the same platform
> and a bootstrap and testsuite on ppc64-linux.  Aarch64-linux bootstrap
> and testing is in progress.  OK for master is that passes too?

The range bits LGTM.

Aldy
Jan Hubicka Nov. 5, 2024, 3:50 p.m. UTC | #2
> Hi,
> 
> currently ipa_value_range_from_jfunc and
> propagate_vr_across_jump_function contain similar but not same code
> for dealing with pass-through jump functions.  This patch puts these
> common bits into one function which can also handle comparison
> operations.
> 
> Bootstrapped and tested on x86_64-linux, the whole patch series has
> additionally passed LTO and profiled-LTO bootstrap on the same platform
> and a bootstrap and testsuite on ppc64-linux.  Aarch64-linux bootstrap
> and testing is in progress.  OK for master is that passes too?

OK.
I also think we want to extend aggregate jump functions to track value
ranges and other stuff and lookup the knowledge from value numbering
code like we do for aggregate constants.
There are practical examples of this in libstdc++.  

For example after we resize vector, some member functions contains
redundant check for size not being too large which can go away with
this.

Honza
> 
> Thanks,
> 
> Martin
> 
> 
> gcc/ChangeLog:
> 
> 2024-11-01  Martin Jambor  <mjambor@suse.cz>
> 
> 	PR ipa/114985
> 	* ipa-cp.cc (ipa_vr_intersect_with_arith_jfunc): New function.
> 	(ipa_value_range_from_jfunc): Move the common functionality to the
> 	above new function, adjust the rest so that it works with it well.
> 	(propagate_vr_across_jump_function): Likewise.
> ---
>  gcc/ipa-cp.cc | 181 +++++++++++++++++++-------------------------------
>  1 file changed, 67 insertions(+), 114 deletions(-)
> 
> diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
> index 212d9ccbbfe..fa4f0feeb8d 100644
> --- a/gcc/ipa-cp.cc
> +++ b/gcc/ipa-cp.cc
> @@ -1682,6 +1682,55 @@ ipa_vr_operation_and_type_effects (vrange &dst_vr,
>  					    dst_type, src_type);
>  }
>  
> +/* Given a PASS_THROUGH jump function JFUNC that takes as its source SRC_VR of
> +   SRC_TYPE and the result needs to be DST_TYPE, if any value range information
> +   can be deduced at all, intersect VR with it.  */
> +
> +static void
> +ipa_vr_intersect_with_arith_jfunc (vrange &vr,
> +				   ipa_jump_func *jfunc,
> +				   const value_range &src_vr,
> +				   tree src_type,
> +				   tree dst_type)
> +{
> +  if (src_vr.undefined_p () || src_vr.varying_p ())
> +    return;
> +
> +  enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
> +  if (TREE_CODE_CLASS (operation) == tcc_unary)
> +    {
> +      value_range tmp_res (dst_type);
> +      if (ipa_vr_operation_and_type_effects (tmp_res, src_vr, operation,
> +					     dst_type, src_type))
> +	vr.intersect (tmp_res);
> +      return;
> +    }
> +
> +  tree operand = ipa_get_jf_pass_through_operand (jfunc);
> +  range_op_handler handler (operation);
> +  if (!handler)
> +    return;
> +  value_range op_vr (TREE_TYPE (operand));
> +  ipa_range_set_and_normalize (op_vr, operand);
> +
> +  tree operation_type;
> +  if (TREE_CODE_CLASS (operation) == tcc_comparison)
> +    operation_type = boolean_type_node;
> +  else
> +    operation_type = src_type;
> +
> +  value_range op_res (dst_type);
> +  if (!ipa_vr_supported_type_p (operation_type)
> +      || !handler.operand_check_p (operation_type, src_type, op_vr.type ())
> +      || !handler.fold_range (op_res, operation_type, src_vr, op_vr))
> +    return;
> +
> +  value_range tmp_res (dst_type);
> +  if (ipa_vr_operation_and_type_effects (tmp_res, op_res, NOP_EXPR, dst_type,
> +					 operation_type))
> +      vr.intersect (tmp_res);
> +}
> +
>  /* Determine range of JFUNC given that INFO describes the caller node or
>     the one it is inlined to, CS is the call graph edge corresponding to JFUNC
>     and PARM_TYPE of the parameter.  */
> @@ -1691,18 +1740,18 @@ ipa_value_range_from_jfunc (vrange &vr,
>  			    ipa_node_params *info, cgraph_edge *cs,
>  			    ipa_jump_func *jfunc, tree parm_type)
>  {
> -  vr.set_undefined ();
> +  vr.set_varying (parm_type);
>  
> -  if (jfunc->m_vr)
> +  if (jfunc->m_vr && jfunc->m_vr->known_p ())
>      ipa_vr_operation_and_type_effects (vr,
>  				       *jfunc->m_vr,
>  				       NOP_EXPR, parm_type,
>  				       jfunc->m_vr->type ());
>    if (vr.singleton_p ())
>      return;
> +
>    if (jfunc->type == IPA_JF_PASS_THROUGH)
>      {
> -      int idx;
>        ipcp_transformation *sum
>  	= ipcp_get_transformation_summary (cs->caller->inlined_to
>  					   ? cs->caller->inlined_to
> @@ -1710,54 +1759,15 @@ ipa_value_range_from_jfunc (vrange &vr,
>        if (!sum || !sum->m_vr)
>  	return;
>  
> -      idx = ipa_get_jf_pass_through_formal_id (jfunc);
> +      int idx = ipa_get_jf_pass_through_formal_id (jfunc);
>  
>        if (!(*sum->m_vr)[idx].known_p ())
>  	return;
> -      tree vr_type = ipa_get_type (info, idx);
> +      tree src_type = ipa_get_type (info, idx);
>        value_range srcvr;
>        (*sum->m_vr)[idx].get_vrange (srcvr);
>  
> -      enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
> -
> -      if (TREE_CODE_CLASS (operation) == tcc_unary)
> -	{
> -	  value_range res (parm_type);
> -
> -	  if (ipa_vr_operation_and_type_effects (res,
> -						 srcvr,
> -						 operation, parm_type,
> -						 vr_type))
> -	    vr.intersect (res);
> -	}
> -      else
> -	{
> -	  value_range op_res (vr_type);
> -	  value_range res (vr_type);
> -	  tree op = ipa_get_jf_pass_through_operand (jfunc);
> -	  value_range op_vr (TREE_TYPE (op));
> -	  range_op_handler handler (operation);
> -
> -	  ipa_range_set_and_normalize (op_vr, op);
> -
> -	  if (!handler
> -	      || !op_res.supports_type_p (vr_type)
> -	      /* Sometimes we try to fold comparison operators using a
> -		 pointer type to hold the result instead of a boolean
> -		 type.  Avoid trapping in the sanity check in
> -		 fold_range until this is fixed.  */
> -	      || srcvr.undefined_p ()
> -	      || op_vr.undefined_p ()
> -	      || !handler.operand_check_p (vr_type, srcvr.type (), op_vr.type ())
> -	      || !handler.fold_range (op_res, vr_type, srcvr, op_vr))
> -	    op_res.set_varying (vr_type);
> -
> -	  if (ipa_vr_operation_and_type_effects (res,
> -						 op_res,
> -						 NOP_EXPR, parm_type,
> -						 vr_type))
> -	    vr.intersect (res);
> -	}
> +      ipa_vr_intersect_with_arith_jfunc (vr, jfunc, srcvr, src_type, parm_type);
>      }
>  }
>  
> @@ -2523,9 +2533,15 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
>        || !ipa_vr_supported_type_p (param_type))
>      return dest_lat->set_to_bottom ();
>  
> +  value_range vr (param_type);
> +  vr.set_varying (param_type);
> +  if (jfunc->m_vr)
> +    ipa_vr_operation_and_type_effects (vr, *jfunc->m_vr, NOP_EXPR,
> +				       param_type,
> +				       jfunc->m_vr->type ());
> +
>    if (jfunc->type == IPA_JF_PASS_THROUGH)
>      {
> -      enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
>        ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
>        int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
>        class ipcp_param_lattices *src_lats
> @@ -2535,77 +2551,14 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
>        if (src_lats->m_value_range.bottom_p ())
>  	return dest_lat->set_to_bottom ();
>  
> -      value_range vr (param_type);
> -      if (TREE_CODE_CLASS (operation) == tcc_unary)
> -	ipa_vr_operation_and_type_effects (vr,
> +      if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR
> +	  || !ipa_edge_within_scc (cs))
> +	ipa_vr_intersect_with_arith_jfunc (vr, jfunc,
>  					   src_lats->m_value_range.m_vr,
> -					   operation, param_type,
> -					   operand_type);
> -      /* A crude way to prevent unbounded number of value range updates
> -	 in SCC components.  We should allow limited number of updates within
> -	 SCC, too.  */
> -      else if (!ipa_edge_within_scc (cs))
> -	{
> -	  tree op = ipa_get_jf_pass_through_operand (jfunc);
> -	  value_range op_vr (TREE_TYPE (op));
> -	  value_range op_res (param_type);
> -	  range_op_handler handler (operation);
> -
> -	  ipa_range_set_and_normalize (op_vr, op);
> -
> -	  if (!handler
> -	      || !ipa_vr_supported_type_p (operand_type)
> -	      /* Sometimes we try to fold comparison operators using a
> -		 pointer type to hold the result instead of a boolean
> -		 type.  Avoid trapping in the sanity check in
> -		 fold_range until this is fixed.  */
> -	      || src_lats->m_value_range.m_vr.undefined_p ()
> -	      || op_vr.undefined_p ()
> -	      || !handler.operand_check_p (operand_type,
> -					   src_lats->m_value_range.m_vr.type (),
> -					   op_vr.type ())
> -	      || !handler.fold_range (op_res, operand_type,
> -				      src_lats->m_value_range.m_vr, op_vr))
> -	    op_res.set_varying (param_type);
> -
> -	  ipa_vr_operation_and_type_effects (vr,
> -					     op_res,
> -					     NOP_EXPR, param_type,
> -					     operand_type);
> -	}
> -      if (!vr.undefined_p () && !vr.varying_p ())
> -	{
> -	  if (jfunc->m_vr)
> -	    {
> -	      value_range jvr (param_type);
> -	      if (ipa_vr_operation_and_type_effects (jvr, *jfunc->m_vr,
> -						     NOP_EXPR,
> -						     param_type,
> -						     jfunc->m_vr->type ()))
> -		vr.intersect (jvr);
> -	    }
> -	  return dest_lat->meet_with (vr);
> -	}
> -    }
> -  else if (jfunc->type == IPA_JF_CONST)
> -    {
> -      tree val = ipa_get_jf_constant (jfunc);
> -      if (TREE_CODE (val) == INTEGER_CST)
> -	{
> -	  val = fold_convert (param_type, val);
> -	  if (TREE_OVERFLOW_P (val))
> -	    val = drop_tree_overflow (val);
> -
> -	  value_range tmpvr (val, val);
> -	  return dest_lat->meet_with (tmpvr);
> -	}
> +					   operand_type, param_type);
>      }
>  
> -  value_range vr (param_type);
> -  if (jfunc->m_vr
> -      && ipa_vr_operation_and_type_effects (vr, *jfunc->m_vr, NOP_EXPR,
> -					    param_type,
> -					    jfunc->m_vr->type ()))
> +  if (!vr.undefined_p () && !vr.varying_p ())
>      return dest_lat->meet_with (vr);
>    else
>      return dest_lat->set_to_bottom ();
> -- 
> 2.47.0
>
diff mbox series

Patch

diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index 212d9ccbbfe..fa4f0feeb8d 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -1682,6 +1682,55 @@  ipa_vr_operation_and_type_effects (vrange &dst_vr,
 					    dst_type, src_type);
 }
 
+/* Given a PASS_THROUGH jump function JFUNC that takes as its source SRC_VR of
+   SRC_TYPE and the result needs to be DST_TYPE, if any value range information
+   can be deduced at all, intersect VR with it.  */
+
+static void
+ipa_vr_intersect_with_arith_jfunc (vrange &vr,
+				   ipa_jump_func *jfunc,
+				   const value_range &src_vr,
+				   tree src_type,
+				   tree dst_type)
+{
+  if (src_vr.undefined_p () || src_vr.varying_p ())
+    return;
+
+  enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
+  if (TREE_CODE_CLASS (operation) == tcc_unary)
+    {
+      value_range tmp_res (dst_type);
+      if (ipa_vr_operation_and_type_effects (tmp_res, src_vr, operation,
+					     dst_type, src_type))
+	vr.intersect (tmp_res);
+      return;
+    }
+
+  tree operand = ipa_get_jf_pass_through_operand (jfunc);
+  range_op_handler handler (operation);
+  if (!handler)
+    return;
+  value_range op_vr (TREE_TYPE (operand));
+  ipa_range_set_and_normalize (op_vr, operand);
+
+  tree operation_type;
+  if (TREE_CODE_CLASS (operation) == tcc_comparison)
+    operation_type = boolean_type_node;
+  else
+    operation_type = src_type;
+
+  value_range op_res (dst_type);
+  if (!ipa_vr_supported_type_p (operation_type)
+      || !handler.operand_check_p (operation_type, src_type, op_vr.type ())
+      || !handler.fold_range (op_res, operation_type, src_vr, op_vr))
+    return;
+
+  value_range tmp_res (dst_type);
+  if (ipa_vr_operation_and_type_effects (tmp_res, op_res, NOP_EXPR, dst_type,
+					 operation_type))
+      vr.intersect (tmp_res);
+}
+
 /* Determine range of JFUNC given that INFO describes the caller node or
    the one it is inlined to, CS is the call graph edge corresponding to JFUNC
    and PARM_TYPE of the parameter.  */
@@ -1691,18 +1740,18 @@  ipa_value_range_from_jfunc (vrange &vr,
 			    ipa_node_params *info, cgraph_edge *cs,
 			    ipa_jump_func *jfunc, tree parm_type)
 {
-  vr.set_undefined ();
+  vr.set_varying (parm_type);
 
-  if (jfunc->m_vr)
+  if (jfunc->m_vr && jfunc->m_vr->known_p ())
     ipa_vr_operation_and_type_effects (vr,
 				       *jfunc->m_vr,
 				       NOP_EXPR, parm_type,
 				       jfunc->m_vr->type ());
   if (vr.singleton_p ())
     return;
+
   if (jfunc->type == IPA_JF_PASS_THROUGH)
     {
-      int idx;
       ipcp_transformation *sum
 	= ipcp_get_transformation_summary (cs->caller->inlined_to
 					   ? cs->caller->inlined_to
@@ -1710,54 +1759,15 @@  ipa_value_range_from_jfunc (vrange &vr,
       if (!sum || !sum->m_vr)
 	return;
 
-      idx = ipa_get_jf_pass_through_formal_id (jfunc);
+      int idx = ipa_get_jf_pass_through_formal_id (jfunc);
 
       if (!(*sum->m_vr)[idx].known_p ())
 	return;
-      tree vr_type = ipa_get_type (info, idx);
+      tree src_type = ipa_get_type (info, idx);
       value_range srcvr;
       (*sum->m_vr)[idx].get_vrange (srcvr);
 
-      enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
-
-      if (TREE_CODE_CLASS (operation) == tcc_unary)
-	{
-	  value_range res (parm_type);
-
-	  if (ipa_vr_operation_and_type_effects (res,
-						 srcvr,
-						 operation, parm_type,
-						 vr_type))
-	    vr.intersect (res);
-	}
-      else
-	{
-	  value_range op_res (vr_type);
-	  value_range res (vr_type);
-	  tree op = ipa_get_jf_pass_through_operand (jfunc);
-	  value_range op_vr (TREE_TYPE (op));
-	  range_op_handler handler (operation);
-
-	  ipa_range_set_and_normalize (op_vr, op);
-
-	  if (!handler
-	      || !op_res.supports_type_p (vr_type)
-	      /* Sometimes we try to fold comparison operators using a
-		 pointer type to hold the result instead of a boolean
-		 type.  Avoid trapping in the sanity check in
-		 fold_range until this is fixed.  */
-	      || srcvr.undefined_p ()
-	      || op_vr.undefined_p ()
-	      || !handler.operand_check_p (vr_type, srcvr.type (), op_vr.type ())
-	      || !handler.fold_range (op_res, vr_type, srcvr, op_vr))
-	    op_res.set_varying (vr_type);
-
-	  if (ipa_vr_operation_and_type_effects (res,
-						 op_res,
-						 NOP_EXPR, parm_type,
-						 vr_type))
-	    vr.intersect (res);
-	}
+      ipa_vr_intersect_with_arith_jfunc (vr, jfunc, srcvr, src_type, parm_type);
     }
 }
 
@@ -2523,9 +2533,15 @@  propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
       || !ipa_vr_supported_type_p (param_type))
     return dest_lat->set_to_bottom ();
 
+  value_range vr (param_type);
+  vr.set_varying (param_type);
+  if (jfunc->m_vr)
+    ipa_vr_operation_and_type_effects (vr, *jfunc->m_vr, NOP_EXPR,
+				       param_type,
+				       jfunc->m_vr->type ());
+
   if (jfunc->type == IPA_JF_PASS_THROUGH)
     {
-      enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
       ipa_node_params *caller_info = ipa_node_params_sum->get (cs->caller);
       int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
       class ipcp_param_lattices *src_lats
@@ -2535,77 +2551,14 @@  propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
       if (src_lats->m_value_range.bottom_p ())
 	return dest_lat->set_to_bottom ();
 
-      value_range vr (param_type);
-      if (TREE_CODE_CLASS (operation) == tcc_unary)
-	ipa_vr_operation_and_type_effects (vr,
+      if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR
+	  || !ipa_edge_within_scc (cs))
+	ipa_vr_intersect_with_arith_jfunc (vr, jfunc,
 					   src_lats->m_value_range.m_vr,
-					   operation, param_type,
-					   operand_type);
-      /* A crude way to prevent unbounded number of value range updates
-	 in SCC components.  We should allow limited number of updates within
-	 SCC, too.  */
-      else if (!ipa_edge_within_scc (cs))
-	{
-	  tree op = ipa_get_jf_pass_through_operand (jfunc);
-	  value_range op_vr (TREE_TYPE (op));
-	  value_range op_res (param_type);
-	  range_op_handler handler (operation);
-
-	  ipa_range_set_and_normalize (op_vr, op);
-
-	  if (!handler
-	      || !ipa_vr_supported_type_p (operand_type)
-	      /* Sometimes we try to fold comparison operators using a
-		 pointer type to hold the result instead of a boolean
-		 type.  Avoid trapping in the sanity check in
-		 fold_range until this is fixed.  */
-	      || src_lats->m_value_range.m_vr.undefined_p ()
-	      || op_vr.undefined_p ()
-	      || !handler.operand_check_p (operand_type,
-					   src_lats->m_value_range.m_vr.type (),
-					   op_vr.type ())
-	      || !handler.fold_range (op_res, operand_type,
-				      src_lats->m_value_range.m_vr, op_vr))
-	    op_res.set_varying (param_type);
-
-	  ipa_vr_operation_and_type_effects (vr,
-					     op_res,
-					     NOP_EXPR, param_type,
-					     operand_type);
-	}
-      if (!vr.undefined_p () && !vr.varying_p ())
-	{
-	  if (jfunc->m_vr)
-	    {
-	      value_range jvr (param_type);
-	      if (ipa_vr_operation_and_type_effects (jvr, *jfunc->m_vr,
-						     NOP_EXPR,
-						     param_type,
-						     jfunc->m_vr->type ()))
-		vr.intersect (jvr);
-	    }
-	  return dest_lat->meet_with (vr);
-	}
-    }
-  else if (jfunc->type == IPA_JF_CONST)
-    {
-      tree val = ipa_get_jf_constant (jfunc);
-      if (TREE_CODE (val) == INTEGER_CST)
-	{
-	  val = fold_convert (param_type, val);
-	  if (TREE_OVERFLOW_P (val))
-	    val = drop_tree_overflow (val);
-
-	  value_range tmpvr (val, val);
-	  return dest_lat->meet_with (tmpvr);
-	}
+					   operand_type, param_type);
     }
 
-  value_range vr (param_type);
-  if (jfunc->m_vr
-      && ipa_vr_operation_and_type_effects (vr, *jfunc->m_vr, NOP_EXPR,
-					    param_type,
-					    jfunc->m_vr->type ()))
+  if (!vr.undefined_p () && !vr.varying_p ())
     return dest_lat->meet_with (vr);
   else
     return dest_lat->set_to_bottom ();