]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ipa-prop.h (ipa_pass_through_data): New field type_preserved.
authorMartin Jambor <mjambor@suse.cz>
Tue, 27 Aug 2013 21:41:15 +0000 (23:41 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Tue, 27 Aug 2013 21:41:15 +0000 (23:41 +0200)
2013-08-27  Martin Jambor  <mjambor@suse.cz>

* ipa-prop.h (ipa_pass_through_data): New field type_preserved.
(ipa_ancestor_jf_data): Likewise.
(ipa_get_jf_pass_through_agg_preserved): Fix comment typo.
(ipa_get_jf_pass_through_type_preserved): New function.
(ipa_get_jf_ancestor_agg_preserved): Fix comment typo.
(ipa_get_jf_ancestor_type_preserved): New function.
* ipa-cp.c (ipa_get_jf_pass_through_result): Honor type_preserved
flag.
(ipa_get_jf_ancestor_result): Likewise.
(propagate_vals_accross_pass_through): Use
ipa_get_jf_pass_through_result to do all the value mappings.
* ipa-prop.c (ipa_print_node_jump_functions_for_edge): Dump the
type_preserved flag.
(ipa_set_jf_cst_copy): New function.
(ipa_set_jf_simple_pass_through): Set the type_preserved flag.
(ipa_set_jf_arith_pass_through): Likewise.
(ipa_set_ancestor_jf): Likewise.
(compute_complex_assign_jump_func): Set type_preserved instead of
punting.
(ipa_compute_jump_functions_for_edge): Likewise.
(combine_known_type_and_ancestor_jfs): Honor type_preserved.
(update_jump_functions_after_inlining): Update type_preserved.
Explicitely create jump functions when combining one with
pass_through.
(ipa_write_jump_function): Stream the type_preserved flags.
(ipa_read_jump_function): Likewise.

From-SVN: r202036

gcc/ChangeLog
gcc/ipa-cp.c
gcc/ipa-prop.c
gcc/ipa-prop.h

index 9c043ccef7cfe497208ff710be12baaf0710173c..0903dc43ffdd987cd3bb810ac42abd7be32b27c1 100644 (file)
@@ -1,3 +1,32 @@
+2013-08-27  Martin Jambor  <mjambor@suse.cz>
+
+       * ipa-prop.h (ipa_pass_through_data): New field type_preserved.
+       (ipa_ancestor_jf_data): Likewise.
+       (ipa_get_jf_pass_through_agg_preserved): Fix comment typo.
+       (ipa_get_jf_pass_through_type_preserved): New function.
+       (ipa_get_jf_ancestor_agg_preserved): Fix comment typo.
+       (ipa_get_jf_ancestor_type_preserved): New function.
+       * ipa-cp.c (ipa_get_jf_pass_through_result): Honor type_preserved
+       flag.
+       (ipa_get_jf_ancestor_result): Likewise.
+       (propagate_vals_accross_pass_through): Use
+       ipa_get_jf_pass_through_result to do all the value mappings.
+       * ipa-prop.c (ipa_print_node_jump_functions_for_edge): Dump the
+       type_preserved flag.
+       (ipa_set_jf_cst_copy): New function.
+       (ipa_set_jf_simple_pass_through): Set the type_preserved flag.
+       (ipa_set_jf_arith_pass_through): Likewise.
+       (ipa_set_ancestor_jf): Likewise.
+       (compute_complex_assign_jump_func): Set type_preserved instead of
+       punting.
+       (ipa_compute_jump_functions_for_edge): Likewise.
+       (combine_known_type_and_ancestor_jfs): Honor type_preserved.
+       (update_jump_functions_after_inlining): Update type_preserved.
+       Explicitely create jump functions when combining one with
+       pass_through.
+       (ipa_write_jump_function): Stream the type_preserved flags.
+       (ipa_read_jump_function): Likewise.
+
 2013-08-27  Jakub Jelinek  <jakub@redhat.com>
            Aldy Hernandez  <aldyh@redhat.com>
 
index 93934e20de827ba675e25831d12dd753d16c6aa2..78dee15aad8e1aefd9de6ff323d16e0ab57c324f 100644 (file)
@@ -745,17 +745,26 @@ initialize_node_lattices (struct cgraph_node *node)
 
 /* Return the result of a (possibly arithmetic) pass through jump function
    JFUNC on the constant value INPUT.  Return NULL_TREE if that cannot be
-   determined or itself is considered an interprocedural invariant.  */
+   determined or be considered an interprocedural invariant.  */
 
 static tree
 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
 {
   tree restype, res;
 
+  if (TREE_CODE (input) == TREE_BINFO)
+    {
+      if (ipa_get_jf_pass_through_type_preserved (jfunc))
+       {
+         gcc_checking_assert (ipa_get_jf_pass_through_operation (jfunc)
+                              == NOP_EXPR);
+         return input;
+       }
+      return NULL_TREE;
+    }
+
   if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
     return input;
-  else if (TREE_CODE (input) == TREE_BINFO)
-    return NULL_TREE;
 
   gcc_checking_assert (is_gimple_ip_invariant (input));
   if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
@@ -779,9 +788,13 @@ static tree
 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
 {
   if (TREE_CODE (input) == TREE_BINFO)
-    return get_binfo_at_offset (input,
-                               ipa_get_jf_ancestor_offset (jfunc),
-                               ipa_get_jf_ancestor_type (jfunc));
+    {
+      if (!ipa_get_jf_ancestor_type_preserved (jfunc))
+       return NULL;
+      return get_binfo_at_offset (input,
+                                 ipa_get_jf_ancestor_offset (jfunc),
+                                 ipa_get_jf_ancestor_type (jfunc));
+    }
   else if (TREE_CODE (input) == ADDR_EXPR)
     {
       tree t = TREE_OPERAND (input, 0);
@@ -1013,26 +1026,16 @@ propagate_vals_accross_pass_through (struct cgraph_edge *cs,
   struct ipcp_value *src_val;
   bool ret = false;
 
-  if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
-    for (src_val = src_lat->values; src_val; src_val = src_val->next)
-      ret |= add_scalar_value_to_lattice (dest_lat, src_val->value, cs,
-                                         src_val, src_idx);
   /* Do not create new values when propagating within an SCC because if there
      are arithmetic functions with circular dependencies, there is infinite
      number of them and we would just make lattices bottom.  */
-  else if (edge_within_scc (cs))
+  if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
+      and edge_within_scc (cs))
     ret = set_lattice_contains_variable (dest_lat);
   else
     for (src_val = src_lat->values; src_val; src_val = src_val->next)
       {
-       tree cstval = src_val->value;
-
-       if (TREE_CODE (cstval) == TREE_BINFO)
-         {
-           ret |= set_lattice_contains_variable (dest_lat);
-           continue;
-         }
-       cstval = ipa_get_jf_pass_through_result (jfunc, cstval);
+       tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
 
        if (cstval)
          ret |= add_scalar_value_to_lattice (dest_lat, cstval, cs, src_val,
index 9074a63161e790b75546479e855f2445f1dba42f..ca133134d509e7e00469b5aa05b58fbb0811fa9e 100644 (file)
@@ -257,6 +257,8 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs)
            }
          if (jump_func->value.pass_through.agg_preserved)
            fprintf (f, ", agg_preserved");
+         if (jump_func->value.pass_through.type_preserved)
+           fprintf (f, ", type_preserved");
          fprintf (f, "\n");
        }
       else if (type == IPA_JF_ANCESTOR)
@@ -268,6 +270,8 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs)
          print_generic_expr (f, jump_func->value.ancestor.type, 0);
          if (jump_func->value.ancestor.agg_preserved)
            fprintf (f, ", agg_preserved");
+         if (jump_func->value.ancestor.type_preserved)
+           fprintf (f, ", type_preserved");
          fprintf (f, "\n");
        }
 
@@ -373,6 +377,19 @@ ipa_set_jf_known_type (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
   jfunc->value.known_type.component_type = component_type;
 }
 
+/* Set JFUNC to be a copy of another jmp (to be used by jump function
+   combination code).  The two functions will share their rdesc.  */
+
+static void
+ipa_set_jf_cst_copy (struct ipa_jump_func *dst,
+                    struct ipa_jump_func *src)
+
+{
+  gcc_checking_assert (src->type == IPA_JF_CONST);
+  dst->type = IPA_JF_CONST;
+  dst->value.constant = src->value.constant;
+}
+
 /* Set JFUNC to be a constant jmp function.  */
 
 static void
@@ -406,13 +423,14 @@ ipa_set_jf_constant (struct ipa_jump_func *jfunc, tree constant,
 /* Set JFUNC to be a simple pass-through jump function.  */
 static void
 ipa_set_jf_simple_pass_through (struct ipa_jump_func *jfunc, int formal_id,
-                               bool agg_preserved)
+                               bool agg_preserved, bool type_preserved)
 {
   jfunc->type = IPA_JF_PASS_THROUGH;
   jfunc->value.pass_through.operand = 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;
+  jfunc->value.pass_through.type_preserved = type_preserved;
 }
 
 /* Set JFUNC to be an arithmetic pass through jump function.  */
@@ -426,19 +444,22 @@ ipa_set_jf_arith_pass_through (struct ipa_jump_func *jfunc, int formal_id,
   jfunc->value.pass_through.formal_id = formal_id;
   jfunc->value.pass_through.operation = operation;
   jfunc->value.pass_through.agg_preserved = false;
+  jfunc->value.pass_through.type_preserved = false;
 }
 
 /* Set JFUNC to be an ancestor jump function.  */
 
 static void
 ipa_set_ancestor_jf (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
-                    tree type, int formal_id, bool agg_preserved)
+                    tree type, int formal_id, bool agg_preserved,
+                    bool type_preserved)
 {
   jfunc->type = IPA_JF_ANCESTOR;
   jfunc->value.ancestor.formal_id = formal_id;
   jfunc->value.ancestor.offset = offset;
   jfunc->value.ancestor.type = type;
   jfunc->value.ancestor.agg_preserved = agg_preserved;
+  jfunc->value.ancestor.type_preserved = type_preserved;
 }
 
 /* Extract the acual BINFO being described by JFUNC which must be a known type
@@ -1005,12 +1026,13 @@ compute_complex_assign_jump_func (struct ipa_node_params *info,
          ipa_set_jf_arith_pass_through (jfunc, index, op2,
                                         gimple_assign_rhs_code (stmt));
        }
-      else if (gimple_assign_single_p (stmt)
-              && !detect_type_change_ssa (tc_ssa, call, jfunc))
+      else if (gimple_assign_single_p (stmt))
        {
          bool agg_p = parm_ref_data_pass_through_p (&parms_ainfo[index],
                                                     call, tc_ssa);
-         ipa_set_jf_simple_pass_through (jfunc, index, agg_p);
+         bool type_p = !detect_type_change_ssa (tc_ssa, call, jfunc);
+         if (type_p || jfunc->type == IPA_JF_UNKNOWN)
+           ipa_set_jf_simple_pass_through (jfunc, index, agg_p, type_p);
        }
       return;
     }
@@ -1033,13 +1055,16 @@ compute_complex_assign_jump_func (struct ipa_node_params *info,
       || offset < 0)
     return;
 
-  /* Dynamic types are changed only in constructors and destructors and  */
+  /* Dynamic types are changed in constructors and destructors.  */
   index = ipa_get_param_decl_index (info, SSA_NAME_VAR (ssa));
-  if (index >= 0
-      && !detect_type_change (op1, base, call, jfunc, offset))
-    ipa_set_ancestor_jf (jfunc, offset, TREE_TYPE (op1), index,
-                        parm_ref_data_pass_through_p (&parms_ainfo[index],
-                                                      call, ssa));
+  if (index >= 0)
+    {
+      bool type_p = !detect_type_change (op1, base, call, jfunc, offset);
+      if (type_p || jfunc->type == IPA_JF_UNKNOWN)
+       ipa_set_ancestor_jf (jfunc, offset, TREE_TYPE (op1), index,
+                            parm_ref_data_pass_through_p (&parms_ainfo[index],
+                                                          call, ssa), type_p);
+    }
 }
 
 /* Extract the base, offset and MEM_REF expression from a statement ASSIGN if
@@ -1163,10 +1188,11 @@ compute_complex_ancestor_jump_func (struct ipa_node_params *info,
        return;
     }
 
-  if (!detect_type_change (obj, expr, call, jfunc, offset))
+  bool type_p = !detect_type_change (obj, expr, call, jfunc, offset);
+  if (type_p || jfunc->type == IPA_JF_UNKNOWN)
     ipa_set_ancestor_jf (jfunc, offset, TREE_TYPE (obj), index,
                         parm_ref_data_pass_through_p (&parms_ainfo[index],
-                                                      call, parm));
+                                                      call, parm), type_p);
 }
 
 /* Given OP which is passed as an actual argument to a called function,
@@ -1507,7 +1533,7 @@ ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_ainfo,
             for cycle.  */
          if (parm_preserved_before_stmt_p (&parms_ainfo[index], call, arg))
            {
-             ipa_set_jf_simple_pass_through (jfunc, index, false);
+             ipa_set_jf_simple_pass_through (jfunc, index, false, false);
              continue;
            }
        }
@@ -1516,13 +1542,14 @@ ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_ainfo,
          if (SSA_NAME_IS_DEFAULT_DEF (arg))
            {
              int index = ipa_get_param_decl_index (info, SSA_NAME_VAR (arg));
-             if (index >= 0
-                 && !detect_type_change_ssa (arg, call, jfunc))
+             if (index >= 0)
                {
-                 bool agg_p;
+                 bool agg_p, type_p;
                  agg_p = parm_ref_data_pass_through_p (&parms_ainfo[index],
                                                        call, arg);
-                 ipa_set_jf_simple_pass_through (jfunc, index, agg_p);
+                 type_p = !detect_type_change_ssa (arg, call, jfunc);
+                 if (type_p || jfunc->type == IPA_JF_UNKNOWN)
+                   ipa_set_jf_simple_pass_through (jfunc, index, agg_p,                                                    type_p);
                }
            }
          else
@@ -2130,6 +2157,12 @@ combine_known_type_and_ancestor_jfs (struct ipa_jump_func *src,
   HOST_WIDE_INT combined_offset;
   tree combined_type;
 
+  if (!ipa_get_jf_ancestor_type_preserved (dst))
+    {
+      dst->type = IPA_JF_UNKNOWN;
+      return;
+    }
+
   combined_offset = ipa_get_jf_known_type_offset (src)
     + ipa_get_jf_ancestor_offset (dst);
   combined_type = ipa_get_jf_ancestor_type (dst);
@@ -2196,6 +2229,8 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
              dst->value.ancestor.formal_id = src->value.pass_through.formal_id;
              dst->value.ancestor.agg_preserved &=
                src->value.pass_through.agg_preserved;
+             dst->value.ancestor.type_preserved &=
+               src->value.pass_through.type_preserved;
            }
          else if (src->type == IPA_JF_ANCESTOR)
            {
@@ -2203,6 +2238,8 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
              dst->value.ancestor.offset += src->value.ancestor.offset;
              dst->value.ancestor.agg_preserved &=
                src->value.ancestor.agg_preserved;
+             dst->value.ancestor.type_preserved &=
+               src->value.ancestor.type_preserved;
            }
          else
            dst->type = IPA_JF_UNKNOWN;
@@ -2216,16 +2253,69 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
              && (dst->value.pass_through.formal_id
                  < ipa_get_cs_argument_count (top)))
            {
-             bool agg_p;
              int dst_fid = dst->value.pass_through.formal_id;
              src = ipa_get_ith_jump_func (top, dst_fid);
-             agg_p = dst->value.pass_through.agg_preserved;
+             bool dst_agg_p = ipa_get_jf_pass_through_agg_preserved (dst);
 
-             dst->type = src->type;
-             dst->value = src->value;
+             switch (src->type)
+               {
+               case IPA_JF_UNKNOWN:
+                 dst->type = IPA_JF_UNKNOWN;
+                 break;
+               case IPA_JF_KNOWN_TYPE:
+                 ipa_set_jf_known_type (dst,
+                                        ipa_get_jf_known_type_offset (src),
+                                        ipa_get_jf_known_type_base_type (src),
+                                        ipa_get_jf_known_type_base_type (src));
+                 break;
+               case IPA_JF_CONST:
+                 ipa_set_jf_cst_copy (dst, src);
+                 break;
+
+               case IPA_JF_PASS_THROUGH:
+                 {
+                   int formal_id = ipa_get_jf_pass_through_formal_id (src);
+                   enum tree_code operation;
+                   operation = ipa_get_jf_pass_through_operation (src);
+
+                   if (operation == NOP_EXPR)
+                     {
+                       bool agg_p, type_p;
+                       agg_p = dst_agg_p
+                         && ipa_get_jf_pass_through_agg_preserved (src);
+                       type_p = ipa_get_jf_pass_through_type_preserved (src)
+                         && ipa_get_jf_pass_through_type_preserved (dst);
+                       ipa_set_jf_simple_pass_through (dst, formal_id,
+                                                       agg_p, type_p);
+                     }
+                   else
+                     {
+                       tree operand = ipa_get_jf_pass_through_operand (src);
+                       ipa_set_jf_arith_pass_through (dst, formal_id, operand,
+                                                      operation);
+                     }
+                   break;
+                 }
+               case IPA_JF_ANCESTOR:
+                 {
+                   bool agg_p, type_p;
+                   agg_p = dst_agg_p
+                     && ipa_get_jf_ancestor_agg_preserved (src);
+                   type_p = ipa_get_jf_ancestor_type_preserved (src)
+                     && ipa_get_jf_pass_through_type_preserved (dst);
+                   ipa_set_ancestor_jf (dst,
+                                        ipa_get_jf_ancestor_offset (src),
+                                        ipa_get_jf_ancestor_type (src),
+                                        ipa_get_jf_ancestor_formal_id (src),
+                                        agg_p, type_p);
+                   break;
+                 }
+               default:
+                 gcc_unreachable ();
+               }
 
              if (src->agg.items
-                 && (agg_p || !src->agg.by_ref))
+                 && (dst_agg_p || !src->agg.by_ref))
                {
                  /* Currently we do not produce clobber aggregate jump
                     functions, replace with merging when we do.  */
@@ -2234,14 +2324,6 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
                  dst->agg.by_ref = src->agg.by_ref;
                  dst->agg.items = vec_safe_copy (src->agg.items);
                }
-
-             if (!agg_p)
-               {
-                 if (dst->type == IPA_JF_PASS_THROUGH)
-                   dst->value.pass_through.agg_preserved = false;
-                 else if (dst->type == IPA_JF_ANCESTOR)
-                   dst->value.ancestor.agg_preserved = false;
-               }
            }
          else
            dst->type = IPA_JF_UNKNOWN;
@@ -3703,6 +3785,7 @@ ipa_write_jump_function (struct output_block *ob,
          streamer_write_uhwi (ob, jump_func->value.pass_through.formal_id);
          bp = bitpack_create (ob->main_stream);
          bp_pack_value (&bp, jump_func->value.pass_through.agg_preserved, 1);
+         bp_pack_value (&bp, jump_func->value.pass_through.type_preserved, 1);
          streamer_write_bitpack (&bp);
        }
       else
@@ -3717,6 +3800,7 @@ ipa_write_jump_function (struct output_block *ob,
       streamer_write_uhwi (ob, jump_func->value.ancestor.formal_id);
       bp = bitpack_create (ob->main_stream);
       bp_pack_value (&bp, jump_func->value.ancestor.agg_preserved, 1);
+      bp_pack_value (&bp, jump_func->value.ancestor.type_preserved, 1);
       streamer_write_bitpack (&bp);
       break;
     }
@@ -3774,7 +3858,9 @@ ipa_read_jump_function (struct lto_input_block *ib,
          int formal_id =  streamer_read_uhwi (ib);
          struct bitpack_d bp = streamer_read_bitpack (ib);
          bool agg_preserved = bp_unpack_value (&bp, 1);
-         ipa_set_jf_simple_pass_through (jump_func, formal_id, agg_preserved);
+         bool type_preserved = bp_unpack_value (&bp, 1);
+         ipa_set_jf_simple_pass_through (jump_func, formal_id, agg_preserved,
+                                         type_preserved);
        }
       else
        {
@@ -3791,8 +3877,10 @@ ipa_read_jump_function (struct lto_input_block *ib,
        int formal_id = streamer_read_uhwi (ib);
        struct bitpack_d bp = streamer_read_bitpack (ib);
        bool agg_preserved = bp_unpack_value (&bp, 1);
+       bool type_preserved = bp_unpack_value (&bp, 1);
 
-       ipa_set_ancestor_jf (jump_func, offset, type, formal_id, agg_preserved);
+       ipa_set_ancestor_jf (jump_func, offset, type, formal_id, agg_preserved,
+                            type_preserved);
        break;
       }
     }
index 2ccac2f3edec01afb8e1ab9577f4b23c747d1a1b..48634d2e172a33f845e770270c4bd33b5a158782 100644 (file)
@@ -117,7 +117,12 @@ struct GTY(()) ipa_pass_through_data
      aggregate part of the jump function (see description of
      ipa_agg_jump_function).  The flag is used only when the operation is
      NOP_EXPR.  */
-  bool agg_preserved;
+  unsigned agg_preserved : 1;
+
+  /* When set to true, we guarantee that, if there is a C++ object pointed to
+     by this object, it does not undergo dynamic type change in the course of
+     functions decribed by this jump function.  */
+  unsigned type_preserved : 1;
 };
 
 /* Structure holding data required to describe an ancestor pass-through
@@ -132,7 +137,11 @@ struct GTY(()) ipa_ancestor_jf_data
   /* Number of the caller's formal parameter being passed.  */
   int formal_id;
   /* Flag with the same meaning like agg_preserve in ipa_pass_through_data.  */
-  bool agg_preserved;
+  unsigned agg_preserved : 1;
+  /* When set to true, we guarantee that, if there is a C++ object pointed to
+     by this object, it does not undergo dynamic type change in the course of
+     functions decribed by this jump function.  */
+  unsigned type_preserved : 1;
 };
 
 /* An element in an aggegate part of a jump function describing a known value
@@ -264,7 +273,7 @@ ipa_get_jf_pass_through_operation (struct ipa_jump_func *jfunc)
   return jfunc->value.pass_through.operation;
 }
 
-/* Return the agg_preserved flag of a pass through jump functin JFUNC.  */
+/* Return the agg_preserved flag of a pass through jump function JFUNC.  */
 
 static inline bool
 ipa_get_jf_pass_through_agg_preserved (struct ipa_jump_func *jfunc)
@@ -273,6 +282,15 @@ ipa_get_jf_pass_through_agg_preserved (struct ipa_jump_func *jfunc)
   return jfunc->value.pass_through.agg_preserved;
 }
 
+/* Return the type_preserved flag of a pass through jump function JFUNC.  */
+
+static inline bool
+ipa_get_jf_pass_through_type_preserved (struct ipa_jump_func *jfunc)
+{
+  gcc_checking_assert (jfunc->type == IPA_JF_PASS_THROUGH);
+  return jfunc->value.pass_through.type_preserved;
+}
+
 /* Return the offset of an ancestor jump function JFUNC.  */
 
 static inline HOST_WIDE_INT
@@ -301,7 +319,7 @@ ipa_get_jf_ancestor_formal_id (struct ipa_jump_func *jfunc)
   return jfunc->value.ancestor.formal_id;
 }
 
-/* Return the agg_preserved flag of an ancestor jump functin JFUNC.  */
+/* Return the agg_preserved flag of an ancestor jump function JFUNC.  */
 
 static inline bool
 ipa_get_jf_ancestor_agg_preserved (struct ipa_jump_func *jfunc)
@@ -310,6 +328,15 @@ ipa_get_jf_ancestor_agg_preserved (struct ipa_jump_func *jfunc)
   return jfunc->value.ancestor.agg_preserved;
 }
 
+/* Return the type_preserved flag of an ancestor jump function JFUNC.  */
+
+static inline bool
+ipa_get_jf_ancestor_type_preserved (struct ipa_jump_func *jfunc)
+{
+  gcc_checking_assert (jfunc->type == IPA_JF_ANCESTOR);
+  return jfunc->value.ancestor.type_preserved;
+}
+
 /* Summary describing a single formal parameter.  */
 
 struct ipa_param_descriptor