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.
---
 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

Reply via email to