> This patch revisits the fix for PR 118097 and instead of deducing the
> necessary operation type it just uses the value collected and streamed
> by an earlier patch.
>
> It is bigger than the ones for propagating value ranges and known bits
> because we track constants both in parameters themselves and also in
> memory they point to or within aggregates, we clone functions for them
> and we do fancy things for some types of recursive calls.
>
> In the case of constants in aggregates or passed by reference, the
> situation should not change because the code creating jump functions
> for them does not allow type-casts, unlike for the plain ones.
> However, this patch changes how we handle them for the sake of
> consistency and also so that we can try and eliminate this limitation
> in the next stage 1.
>
> Bootstrapped and tested and LTO bootstrapped on x86_64-linux. OK for
> master?
>
> Thanks,
>
> Martin
>
>
> gcc/ChangeLog:
>
> 2025-03-20 Martin Jambor <mjam...@suse.cz>
>
> PR ipa/118097
> * ipa-cp.cc (ipa_get_jf_arith_result): Require res_operand for
> anything except NOP_EXPR or ADDR_EXPR, document it and remove the code
> trying to deduce it.
> (ipa_value_from_jfunc): Use the stored and streamed type of arithmetic
> pass-through functions.
> (ipa_agg_value_from_jfunc): Use the stored and streamed type of
> arithmetic pass-through functions, convert to the type used to store
> the value if necessary.
> (get_val_across_arith_op): New parameter op_type, pass it to
> ipa_get_jf_arith_result.
> (propagate_vals_across_arith_jfunc): New parameter op_type, pass it to
> get_val_across_arith_op.
> (propagate_vals_across_pass_through): Use the stored and streamed type
> of arithmetic pass-through functions.
> (propagate_aggregate_lattice): Likewise.
> (push_agg_values_for_index_from_edge): Use the stored and streamed
> type of arithmetic pass-through functions, convert to the type used to
> store the value if necessary.
OK,
thanks!
Honza
> ---
> gcc/ipa-cp.cc | 94 ++++++++++++++++++++++++++++-----------------------
> 1 file changed, 52 insertions(+), 42 deletions(-)
>
> diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
> index e39a9e144ad..7aa17d083d3 100644
> --- a/gcc/ipa-cp.cc
> +++ b/gcc/ipa-cp.cc
> @@ -1478,10 +1478,12 @@ ipacp_value_safe_for_type (tree param_type, tree
> value)
> return NULL_TREE;
> }
>
> -/* Return the result of a (possibly arithmetic) operation on the constant
> value
> - INPUT. OPERAND is 2nd operand for binary operation. RES_TYPE is the type
> - in which any operation is to be performed. Return NULL_TREE if that
> cannot
> - be determined or be considered an interprocedural invariant. */
> +/* Return the result of a (possibly arithmetic) operation determined by
> OPCODE
> + on the constant value INPUT. OPERAND is 2nd operand for binary operation
> + and is required for binary operations. RES_TYPE, required when opcode is
> + not NOP_EXPR, is the type in which any operation is to be performed.
> Return
> + NULL_TREE if that cannot be determined or be considered an interprocedural
> + invariant. */
>
> static tree
> ipa_get_jf_arith_result (enum tree_code opcode, tree input, tree operand,
> @@ -1502,16 +1504,6 @@ ipa_get_jf_arith_result (enum tree_code opcode, tree
> input, tree operand,
> return NULL_TREE;
> }
>
> - if (!res_type)
> - {
> - if (TREE_CODE_CLASS (opcode) == tcc_comparison)
> - res_type = boolean_type_node;
> - else if (expr_type_first_operand_type_p (opcode))
> - res_type = TREE_TYPE (input);
> - else
> - return NULL_TREE;
> - }
> -
> if (TREE_CODE_CLASS (opcode) == tcc_unary)
> res = fold_unary (opcode, res_type, input);
> else
> @@ -1595,7 +1587,10 @@ ipa_value_from_jfunc (class ipa_node_params *info,
> struct ipa_jump_func *jfunc,
> return NULL_TREE;
> enum tree_code opcode = ipa_get_jf_pass_through_operation (jfunc);
> tree op2 = ipa_get_jf_pass_through_operand (jfunc);
> - tree cstval = ipa_get_jf_arith_result (opcode, input, op2, NULL_TREE);
> + tree op_type
> + = (opcode == NOP_EXPR) ? NULL_TREE
> + : ipa_get_jf_pass_through_op_type (jfunc);
> + tree cstval = ipa_get_jf_arith_result (opcode, input, op2, op_type);
> return ipacp_value_safe_for_type (parm_type, cstval);
> }
> else
> @@ -1905,10 +1900,11 @@ ipa_agg_value_from_jfunc (ipa_node_params *info,
> cgraph_node *node,
> return NULL_TREE;
> }
>
> - return ipa_get_jf_arith_result (item->value.pass_through.operation,
> - value,
> - item->value.pass_through.operand,
> - item->type);
> + tree cstval = ipa_get_jf_arith_result (item->value.pass_through.operation,
> + value,
> + item->value.pass_through.operand,
> + item->value.pass_through.op_type);
> + return ipacp_value_safe_for_type (item->type, cstval);
> }
>
> /* Process all items in AGG_JFUNC relative to caller (or the node the
> original
> @@ -2137,13 +2133,15 @@ ipcp_lattice<valtype>::add_value (valtype newval,
> cgraph_edge *cs,
> /* A helper function that returns result of operation specified by OPCODE on
> the value of SRC_VAL. If non-NULL, OPND1_TYPE is expected type for the
> value of SRC_VAL. If the operation is binary, OPND2 is a constant value
> - acting as its second operand. */
> + acting as its second operand. OP_TYPE is the type in which the operation
> is
> + performed. */
>
> static tree
> get_val_across_arith_op (enum tree_code opcode,
> tree opnd1_type,
> tree opnd2,
> - ipcp_value<tree> *src_val)
> + ipcp_value<tree> *src_val,
> + tree op_type)
> {
> tree opnd1 = src_val->value;
>
> @@ -2152,17 +2150,19 @@ get_val_across_arith_op (enum tree_code opcode,
> && !useless_type_conversion_p (opnd1_type, TREE_TYPE (opnd1)))
> return NULL_TREE;
>
> - return ipa_get_jf_arith_result (opcode, opnd1, opnd2, NULL_TREE);
> + return ipa_get_jf_arith_result (opcode, opnd1, opnd2, op_type);
> }
>
> /* Propagate values through an arithmetic transformation described by a jump
> function associated with edge CS, taking values from SRC_LAT and putting
> - them into DEST_LAT. OPND1_TYPE is expected type for the values in
> SRC_LAT.
> - OPND2 is a constant value if transformation is a binary operation.
> - SRC_OFFSET specifies offset in an aggregate if SRC_LAT describes lattice
> of
> - a part of the aggregate. SRC_IDX is the index of the source parameter.
> - RES_TYPE is the value type of result being propagated into. Return true
> if
> - DEST_LAT changed. */
> + them into DEST_LAT. OPND1_TYPE, if non-NULL, is the expected type for the
> + values in SRC_LAT. OPND2 is a constant value if transformation is a
> binary
> + operation. SRC_OFFSET specifies offset in an aggregate if SRC_LAT
> describes
> + lattice of a part of an aggregate, otherwise it should be -1. SRC_IDX is
> + the index of the source parameter. OP_TYPE is the type in which the
> + operation is performed and can be NULL when OPCODE is NOP_EXPR. RES_TYPE
> is
> + the value type of result being propagated into. Return true if DEST_LAT
> + changed. */
>
> static bool
> propagate_vals_across_arith_jfunc (cgraph_edge *cs,
> @@ -2173,6 +2173,7 @@ propagate_vals_across_arith_jfunc (cgraph_edge *cs,
> ipcp_lattice<tree> *dest_lat,
> HOST_WIDE_INT src_offset,
> int src_idx,
> + tree op_type,
> tree res_type)
> {
> ipcp_value<tree> *src_val;
> @@ -2228,7 +2229,7 @@ propagate_vals_across_arith_jfunc (cgraph_edge *cs,
> for (int j = 1; j < max_recursive_depth; j++)
> {
> tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
> - src_val);
> + src_val, op_type);
> cstval = ipacp_value_safe_for_type (res_type, cstval);
> if (!cstval)
> break;
> @@ -2253,7 +2254,7 @@ propagate_vals_across_arith_jfunc (cgraph_edge *cs,
> }
>
> tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
> - src_val);
> + src_val, op_type);
> cstval = ipacp_value_safe_for_type (res_type, cstval);
> if (cstval)
> ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
> @@ -2277,11 +2278,13 @@ propagate_vals_across_pass_through (cgraph_edge *cs,
> ipa_jump_func *jfunc,
> tree parm_type)
> {
> gcc_checking_assert (parm_type);
> - return propagate_vals_across_arith_jfunc (cs,
> - ipa_get_jf_pass_through_operation (jfunc),
> - NULL_TREE,
> + enum tree_code opcode = ipa_get_jf_pass_through_operation (jfunc);
> + tree op_type = (opcode == NOP_EXPR) ? NULL_TREE
> + : ipa_get_jf_pass_through_op_type (jfunc);
> + return propagate_vals_across_arith_jfunc (cs, opcode, NULL_TREE,
> ipa_get_jf_pass_through_operand (jfunc),
> - src_lat, dest_lat, -1, src_idx, parm_type);
> + src_lat, dest_lat, -1, src_idx, op_type,
> + parm_type);
> }
>
> /* Propagate values through an ancestor jump function JFUNC associated with
> @@ -2874,6 +2877,7 @@ propagate_aggregate_lattice (struct cgraph_edge *cs,
> src_lat, aglat,
> src_offset,
> src_idx,
> + item->value.pass_through.op_type,
> item->type);
>
> if (src_lat->contains_variable)
> @@ -5399,11 +5403,14 @@ find_more_scalar_values_for_callers_subset (struct
> cgraph_node *node,
> if (self_recursive_pass_through_p (cs, jump_func, i, false))
> {
> gcc_assert (newval);
> - t = ipa_get_jf_arith_result (
> - ipa_get_jf_pass_through_operation (jump_func),
> - newval,
> + enum tree_code opcode
> + = ipa_get_jf_pass_through_operation (jump_func);
> + tree op_type = (opcode == NOP_EXPR) ? NULL_TREE
> + : ipa_get_jf_pass_through_op_type (jump_func);
> + t = ipa_get_jf_arith_result (opcode, newval,
> ipa_get_jf_pass_through_operand (jump_func),
> - type);
> + op_type);
> + t = ipacp_value_safe_for_type (type, t);
> }
> else
> t = ipa_value_from_jfunc (ipa_node_params_sum->get (cs->caller),
> @@ -5608,10 +5615,13 @@ push_agg_values_for_index_from_edge (struct
> cgraph_edge *cs, int index,
> && self_recursive_agg_pass_through_p (cs, &agg_jf, index, false)
> && (srcvalue = interim->get_value(index,
> agg_jf.offset / BITS_PER_UNIT)))
> - value = ipa_get_jf_arith_result (agg_jf.value.pass_through.operation,
> - srcvalue,
> - agg_jf.value.pass_through.operand,
> - agg_jf.type);
> + {
> + value = ipa_get_jf_arith_result (agg_jf.value.pass_through.operation,
> + srcvalue,
> + agg_jf.value.pass_through.operand,
> + agg_jf.value.pass_through.op_type);
> + value = ipacp_value_safe_for_type (agg_jf.type, value);
> + }
> else
> value = ipa_agg_value_from_jfunc (caller_info, cs->caller,
> &agg_jf);
> --
> 2.48.1
>