@@ -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 ();