ipa: Check that scalar types that IPA-CP comes up with are sane (PR99122)
authorMartin Jambor <mjambor@suse.cz>
Wed, 24 Mar 2021 19:27:27 +0000 (20:27 +0100)
committerMartin Jambor <mjambor@suse.cz>
Wed, 24 Mar 2021 19:27:27 +0000 (20:27 +0100)
This patch fixes the last bit of PR 99122 where various bits of IPA
infrastructure are presented with a program with type mismatches that
make it have undefined behavior, and when inlining or performing
IPA-CP, and encountering such mismatch, we basically try to
VIEW_CONVERT_EXPR whatever the caller has into whatever the callee has
or simply use an empty constructor if that cannot be done.  This
however does not work when the callee has VLA parameters because we
ICE in the process.

Richi has already disabled inlining for such cases, this patch avoids
the issue in IPA-CP.  It adds checks that whatever constant the
propagation arrived at is actually compatible or fold_convertible to
the callees formal parameer type.  Unlike in the past, we now have
types of all parameters of functions that we have analyzed, even with
LTO, and so can do it.

This should prevent only bogus propagations.  I have looked at the
effect of the patch on WPA of Firefox and did not have any.

I have bootstrapped and LTO bootstrapped and tested the patch on
x86_64-linux.  OK for trunk?  And perhaps later for GCC 10 too?

Thanks

gcc/ChangeLog:

2021-02-26  Martin Jambor  <mjambor@suse.cz>

PR ipa/99122
* ipa-cp.c (initialize_node_lattices): Mark as bottom all
parameters with unknown type.
(ipacp_value_safe_for_type): New function.
(propagate_vals_across_arith_jfunc): Verify that the constant type
can be used for a type of the formal parameter.
(propagate_vals_across_ancestor): Likewise.
(propagate_scalar_across_jump_function): Likewise.  Pass the type
also to propagate_vals_across_ancestor.

gcc/testsuite/ChangeLog:

2021-02-26  Martin Jambor  <mjambor@suse.cz>

PR ipa/99122
* gcc.dg/pr99122-3.c: Remove -fno-ipa-cp from options.

gcc/ipa-cp.c
gcc/testsuite/gcc.dg/pr99122-3.c

index 167913c..6041f75 100644 (file)
@@ -1276,6 +1276,7 @@ initialize_node_lattices (struct cgraph_node *node)
     {
       ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
       if (disable
+         || !ipa_get_type (info, i)
          || (pre_modified && (surviving_params.length () <= (unsigned) i
                               || !surviving_params[i])))
        {
@@ -1304,6 +1305,21 @@ initialize_node_lattices (struct cgraph_node *node)
       }
 }
 
+/* Return true if VALUE can be safely IPA-CP propagated to a parameter of type
+   PARAM_TYPE.  */
+
+static bool
+ipacp_value_safe_for_type (tree param_type, tree value)
+{
+  tree val_type = TREE_TYPE (value);
+  if (param_type == val_type
+      || useless_type_conversion_p (param_type, val_type)
+      || fold_convertible_p (param_type, value))
+    return true;
+  else
+    return false;
+}
+
 /* Return true iff X and Y should be considered equal values by IPA-CP.  */
 
 static bool
@@ -2072,7 +2088,8 @@ propagate_vals_across_arith_jfunc (cgraph_edge *cs,
            {
              tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
                                                     src_val, res_type);
-             if (!cstval)
+             if (!cstval
+                 || !ipacp_value_safe_for_type (res_type, cstval))
                break;
 
              ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
@@ -2096,7 +2113,8 @@ propagate_vals_across_arith_jfunc (cgraph_edge *cs,
 
        tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
                                               src_val, res_type);
-       if (cstval)
+       if (cstval
+           && ipacp_value_safe_for_type (res_type, cstval))
          ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
                                      src_offset);
        else
@@ -2132,7 +2150,8 @@ static bool
 propagate_vals_across_ancestor (struct cgraph_edge *cs,
                                struct ipa_jump_func *jfunc,
                                ipcp_lattice<tree> *src_lat,
-                               ipcp_lattice<tree> *dest_lat, int src_idx)
+                               ipcp_lattice<tree> *dest_lat, int src_idx,
+                               tree param_type)
 {
   ipcp_value<tree> *src_val;
   bool ret = false;
@@ -2144,7 +2163,7 @@ propagate_vals_across_ancestor (struct cgraph_edge *cs,
     {
       tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
 
-      if (t)
+      if (t && ipacp_value_safe_for_type (param_type, t))
        ret |= dest_lat->add_value (t, cs, src_val, src_idx);
       else
        ret |= dest_lat->set_contains_variable ();
@@ -2169,7 +2188,10 @@ propagate_scalar_across_jump_function (struct cgraph_edge *cs,
   if (jfunc->type == IPA_JF_CONST)
     {
       tree val = ipa_get_jf_constant (jfunc);
-      return dest_lat->add_value (val, cs, NULL, 0);
+      if (ipacp_value_safe_for_type (param_type, val))
+       return dest_lat->add_value (val, cs, NULL, 0);
+      else
+       return dest_lat->set_contains_variable ();
     }
   else if (jfunc->type == IPA_JF_PASS_THROUGH
           || jfunc->type == IPA_JF_ANCESTOR)
@@ -2196,10 +2218,11 @@ propagate_scalar_across_jump_function (struct cgraph_edge *cs,
 
       if (jfunc->type == IPA_JF_PASS_THROUGH)
        ret = propagate_vals_across_pass_through (cs, jfunc, src_lat,
-                                                 dest_lat, src_idx, param_type);
+                                                 dest_lat, src_idx,
+                                                 param_type);
       else
        ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat,
-                                             src_idx);
+                                             src_idx, param_type);
 
       if (src_lat->contains_variable)
        ret |= dest_lat->set_contains_variable ();
index 6aa5b29..6a908ad 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -g -fno-ipa-cp -w" } */
+/* { dg-options "-O2 -g -w" } */
 
 static int foo ();