In order to replace the use of somewhat unweildy
expr_type_first_operand_type_p we need to record and stream the types
of results of operations recorded in arithmetic jump functions.  This
is necessary so that we can then simulate them at the IPA stage with
the corresponding precision and signedness.  This patch does the
recorsing and streaming, the following one adds the use of the date.

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
        PR ipa/118785
        PR ipa/119318
        * ipa-prop.h (ipa_pass_through_data): New field op_type.
        (ipa_get_jf_pass_through_op_type): New function.
        * ipa-prop.cc (ipa_dump_jump_function): Dump also pass-through
        operation types, if any.  Dump pass-through operands only if not NULL.
        (ipa_set_jf_simple_pass_through): Set op_type accordingly.
        (compute_complex_assign_jump_func): Set op_type of arithmetic
        pass-through jump_functions.
        (analyze_agg_content_value): Update lhs when walking assighment
        copies.  Set op_type of aggregate arithmetic pass-through
        jump_functions.
        (update_jump_functions_after_inlining): Also transfer the operation
        type from the source arithmentic pass-through jump function to the
        destination jump function.
        (ipa_write_jump_function): Stream also the op_type when necessary.
        (ipa_read_jump_function): Likewise.
        (ipa_agg_pass_through_jf_equivalent_p): Also compare operation types.
---
 gcc/ipa-prop.cc | 63 ++++++++++++++++++++++++++++++++++++++++---------
 gcc/ipa-prop.h  | 15 ++++++++++++
 2 files changed, 67 insertions(+), 11 deletions(-)

diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
index a120f942dc2..d882b997bf4 100644
--- a/gcc/ipa-prop.cc
+++ b/gcc/ipa-prop.cc
@@ -454,7 +454,11 @@ ipa_dump_jump_function (FILE *f, ipa_jump_func *jump_func,
       if (jump_func->value.pass_through.operation != NOP_EXPR)
        {
          fprintf (f, " ");
-         print_generic_expr (f, jump_func->value.pass_through.operand);
+         if (jump_func->value.pass_through.operand)
+           print_generic_expr (f, jump_func->value.pass_through.operand);
+         fprintf (f, " (in type ");
+         print_generic_expr (f, jump_func->value.pass_through.op_type);
+         fprintf (f, ")");
        }
       if (jump_func->value.pass_through.agg_preserved)
        fprintf (f, ", agg_preserved");
@@ -510,7 +514,11 @@ ipa_dump_jump_function (FILE *f, ipa_jump_func *jump_func,
              if (item->value.pass_through.operation != NOP_EXPR)
                {
                  fprintf (f, " ");
-                 print_generic_expr (f, item->value.pass_through.operand);
+                 if (item->value.pass_through.operand)
+                   print_generic_expr (f, item->value.pass_through.operand);
+                 fprintf (f, " (in type ");
+                 print_generic_expr (f, jump_func->value.pass_through.op_type);
+                 fprintf (f, ")");
                }
            }
          else if (item->jftype == IPA_JF_CONST)
@@ -682,6 +690,7 @@ ipa_set_jf_simple_pass_through (struct ipa_jump_func 
*jfunc, int formal_id,
 {
   jfunc->type = IPA_JF_PASS_THROUGH;
   jfunc->value.pass_through.operand = NULL_TREE;
+  jfunc->value.pass_through.op_type = NULL_TREE;
   jfunc->value.pass_through.formal_id = formal_id;
   jfunc->value.pass_through.operation = NOP_EXPR;
   jfunc->value.pass_through.agg_preserved = agg_preserved;
@@ -692,10 +701,11 @@ ipa_set_jf_simple_pass_through (struct ipa_jump_func 
*jfunc, int formal_id,
 
 static void
 ipa_set_jf_unary_pass_through (struct ipa_jump_func *jfunc, int formal_id,
-                              enum tree_code operation)
+                              enum tree_code operation, tree op_type)
 {
   jfunc->type = IPA_JF_PASS_THROUGH;
   jfunc->value.pass_through.operand = NULL_TREE;
+  jfunc->value.pass_through.op_type = op_type;
   jfunc->value.pass_through.formal_id = formal_id;
   jfunc->value.pass_through.operation = operation;
   jfunc->value.pass_through.agg_preserved = false;
@@ -705,10 +715,12 @@ ipa_set_jf_unary_pass_through (struct ipa_jump_func 
*jfunc, int formal_id,
 
 static void
 ipa_set_jf_arith_pass_through (struct ipa_jump_func *jfunc, int formal_id,
-                              tree operand, enum tree_code operation)
+                              tree operand, enum tree_code operation,
+                              tree op_type)
 {
   jfunc->type = IPA_JF_PASS_THROUGH;
   jfunc->value.pass_through.operand = unshare_expr_without_location (operand);
+  jfunc->value.pass_through.op_type = op_type;
   jfunc->value.pass_through.formal_id = formal_id;
   jfunc->value.pass_through.operation = operation;
   jfunc->value.pass_through.agg_preserved = false;
@@ -1526,7 +1538,8 @@ compute_complex_assign_jump_func (struct 
ipa_func_body_info *fbi,
              return;
 
            ipa_set_jf_arith_pass_through (jfunc, index, op2,
-                                          gimple_assign_rhs_code (stmt));
+                                          gimple_assign_rhs_code (stmt),
+                                          TREE_TYPE (name));
            break;
          }
        case GIMPLE_SINGLE_RHS:
@@ -1539,7 +1552,8 @@ compute_complex_assign_jump_func (struct 
ipa_func_body_info *fbi,
        case GIMPLE_UNARY_RHS:
          if (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt)))
            ipa_set_jf_unary_pass_through (jfunc, index,
-                                          gimple_assign_rhs_code (stmt));
+                                          gimple_assign_rhs_code (stmt),
+                                          TREE_TYPE (name));
        default:;
        }
       return;
@@ -1912,6 +1926,7 @@ analyze_agg_content_value (struct ipa_func_body_info *fbi,
       if (!is_gimple_assign (stmt))
        break;
 
+      lhs = gimple_assign_lhs (stmt);
       rhs1 = gimple_assign_rhs1 (stmt);
     }
 
@@ -1956,6 +1971,7 @@ analyze_agg_content_value (struct ipa_func_body_info *fbi,
 
       code = ASSERT_EXPR;
       agg_value->pass_through.operand = operand;
+      agg_value->pass_through.op_type = TREE_TYPE (lhs);
     }
   else if (is_gimple_assign (stmt))
     {
@@ -1984,6 +2000,7 @@ analyze_agg_content_value (struct ipa_func_body_info *fbi,
            return;
 
          rhs1 = get_ssa_def_if_simple_copy (rhs1, &stmt);
+         agg_value->pass_through.op_type = TREE_TYPE (lhs);
          break;
 
        case GIMPLE_BINARY_RHS:
@@ -1998,6 +2015,7 @@ analyze_agg_content_value (struct ipa_func_body_info *fbi,
            if (is_gimple_ip_invariant (rhs2))
              {
                agg_value->pass_through.operand = rhs2;
+               agg_value->pass_through.op_type = TREE_TYPE (lhs);
                stmt = rhs1_stmt;
              }
            else if (is_gimple_ip_invariant (rhs1))
@@ -2008,6 +2026,7 @@ analyze_agg_content_value (struct ipa_func_body_info *fbi,
                  return;
 
                agg_value->pass_through.operand = rhs1;
+               agg_value->pass_through.op_type = TREE_TYPE (lhs);
                stmt = rhs2_stmt;
                rhs1 = rhs2;
              }
@@ -3520,12 +3539,17 @@ update_jump_functions_after_inlining (struct 
cgraph_edge *cs,
                        ipa_set_jf_simple_pass_through (dst, formal_id, agg_p);
                      }
                    else if (TREE_CODE_CLASS (operation) == tcc_unary)
-                     ipa_set_jf_unary_pass_through (dst, formal_id, operation);
+                     {
+                       tree op_t = ipa_get_jf_pass_through_op_type (src);
+                       ipa_set_jf_unary_pass_through (dst, formal_id, 
operation,
+                                                      op_t);
+                     }
                    else
                      {
                        tree operand = ipa_get_jf_pass_through_operand (src);
+                       tree op_t = ipa_get_jf_pass_through_op_type (src);
                        ipa_set_jf_arith_pass_through (dst, formal_id, operand,
-                                                      operation);
+                                                      operation, op_t);
                      }
                    break;
                  }
@@ -4935,9 +4959,13 @@ ipa_write_jump_function (struct output_block *ob,
        }
       else if (TREE_CODE_CLASS (jump_func->value.pass_through.operation)
               == tcc_unary)
-       streamer_write_uhwi (ob, jump_func->value.pass_through.formal_id);
+       {
+         stream_write_tree (ob, jump_func->value.pass_through.op_type, true);
+         streamer_write_uhwi (ob, jump_func->value.pass_through.formal_id);
+       }
       else
        {
+         stream_write_tree (ob, jump_func->value.pass_through.op_type, true);
          stream_write_tree (ob, jump_func->value.pass_through.operand, true);
          streamer_write_uhwi (ob, jump_func->value.pass_through.formal_id);
        }
@@ -4979,6 +5007,8 @@ ipa_write_jump_function (struct output_block *ob,
        case IPA_JF_LOAD_AGG:
          streamer_write_uhwi (ob, item->value.pass_through.operation);
          streamer_write_uhwi (ob, item->value.pass_through.formal_id);
+         if (item->value.pass_through.operation != NOP_EXPR)
+           stream_write_tree (ob, item->value.pass_through.op_type, true);
          if (TREE_CODE_CLASS (item->value.pass_through.operation)
                                                        != tcc_unary)
            stream_write_tree (ob, item->value.pass_through.operand, true);
@@ -5047,15 +5077,18 @@ ipa_read_jump_function (class lto_input_block *ib,
        }
       else if (TREE_CODE_CLASS (operation) == tcc_unary)
        {
+         tree op_type = stream_read_tree (ib, data_in);
          int formal_id =  streamer_read_uhwi (ib);
-         ipa_set_jf_unary_pass_through (jump_func, formal_id, operation);
+         ipa_set_jf_unary_pass_through (jump_func, formal_id, operation,
+                                        op_type);
        }
       else
        {
+         tree op_type = stream_read_tree (ib, data_in);
          tree operand = stream_read_tree (ib, data_in);
          int formal_id =  streamer_read_uhwi (ib);
          ipa_set_jf_arith_pass_through (jump_func, formal_id, operand,
-                                        operation);
+                                        operation, op_type);
        }
       break;
     case IPA_JF_ANCESTOR:
@@ -5103,6 +5136,10 @@ ipa_read_jump_function (class lto_input_block *ib,
          operation = (enum tree_code) streamer_read_uhwi (ib);
          item.value.pass_through.operation = operation;
          item.value.pass_through.formal_id = streamer_read_uhwi (ib);
+         if (operation != NOP_EXPR)
+           item.value.pass_through.op_type = stream_read_tree (ib, data_in);
+         else
+           item.value.pass_through.op_type = NULL_TREE;
          if (TREE_CODE_CLASS (operation) == tcc_unary)
            item.value.pass_through.operand = NULL_TREE;
          else
@@ -6224,6 +6261,10 @@ ipa_agg_pass_through_jf_equivalent_p 
(ipa_pass_through_data *ipt1,
       || ipt1->formal_id != ipt2->formal_id
       || (!agg_jf && (ipt1->agg_preserved != ipt2->agg_preserved)))
     return false;
+  if (ipt1->operation != NOP_EXPR
+      && (TYPE_MAIN_VARIANT (ipt1->op_type)
+         != TYPE_MAIN_VARIANT (ipt2->op_type)))
+    return false;
   if (((ipt1->operand != NULL_TREE) != (ipt2->operand != NULL_TREE))
       || (ipt1->operand
          && !values_equal_for_ipcp_p (ipt1->operand, ipt2->operand)))
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 7735b573f03..3bd442fff39 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -96,6 +96,9 @@ struct GTY(()) ipa_pass_through_data
   /* If an operation is to be performed on the original parameter, this is the
      second (constant) operand.  */
   tree operand;
+  /* The result type of the operation.  In case of no operation (represented by
+     NOP_EXPR) it should be NULL_TREE.  */
+  tree op_type;
   /* Number of the caller's formal parameter being passed.  */
   int formal_id;
   /* Operation that is performed on the argument before it is passed on.
@@ -387,6 +390,18 @@ ipa_get_jf_pass_through_operand (struct ipa_jump_func 
*jfunc)
   return jfunc->value.pass_through.operand;
 }
 
+/* Return the type of the operation in a non-NOP pass through jmp function
+   JFUNC.  */
+
+inline tree
+ipa_get_jf_pass_through_op_type (struct ipa_jump_func *jfunc)
+{
+  gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH
+                      && jfunc->value.pass_through.operation != NOP_EXPR);
+
+  return jfunc->value.pass_through.op_type;
+}
+
 /* Return the number of the caller's formal parameter that a pass through jump
    function JFUNC refers to.  */
 
-- 
2.48.1

Reply via email to