[PR 78365] Prudent type handling in IPA VR-prop
authorMartin Jambor <mjambor@suse.cz>
Mon, 9 Jan 2017 18:26:37 +0000 (19:26 +0100)
committerMartin Jambor <jamborm@gcc.gnu.org>
Mon, 9 Jan 2017 18:26:37 +0000 (19:26 +0100)
2017-01-09  Martin Jambor  <mjambor@suse.cz>

PR ipa/78365
PR ipa/78599
* ipa-prop.h (ipa_jump_func): Swap positions of vr_known and m_vr.
* ipa-cp.c (ipa_vr_operation_and_type_effects): New function.
(propagate_vr_accross_jump_function): Use the above function for all
value range computations for pass-through jump functions and type
converasion from explicit value range values.
        (ipcp_propagate_stage): Do not attempt to deduce types of formal
        parameters from TYPE_ARG_TYPES.
* ipa-prop.c (ipa_write_jump_function): Remove trailing whitespace.
(ipa_write_node_info): Stream type of the actual argument.
(ipa_read_node_info): Likewise. Also remove trailing whitespace.

testsuite/
* gcc.dg/torture/pr78365.c: New test.

From-SVN: r244232

gcc/ChangeLog
gcc/ipa-cp.c
gcc/ipa-prop.c
gcc/ipa-prop.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr78365.c [new file with mode: 0644]

index 320121097d36e4ffb193e6481b01743bb973bf49..3d7b7ddd0d27eaee7f37651d2e409bcc17d5fcde 100644 (file)
@@ -1,3 +1,18 @@
+2017-01-09  Martin Jambor  <mjambor@suse.cz>
+
+       PR ipa/78365
+       PR ipa/78599
+       * ipa-prop.h (ipa_jump_func): Swap positions of vr_known and m_vr.
+       * ipa-cp.c (ipa_vr_operation_and_type_effects): New function.
+       (propagate_vr_accross_jump_function): Use the above function for all
+       value range computations for pass-through jump functions and type
+       converasion from explicit value range values.
+        (ipcp_propagate_stage): Do not attempt to deduce types of formal
+        parameters from TYPE_ARG_TYPES.
+       * ipa-prop.c (ipa_write_jump_function): Remove trailing whitespace.
+       (ipa_write_node_info): Stream type of the actual argument.
+       (ipa_read_node_info): Likewise. Also remove trailing whitespace.
+
 2017-01-09  Martin Liska  <mliska@suse.cz>
 
        PR pch/78970
index 82bf35084b637fa37c02022ebfd260f12cd14591..9cc903769e8182f5e7c4aa66c193f6a775d19e2a 100644 (file)
@@ -1837,6 +1837,23 @@ propagate_bits_across_jump_function (cgraph_edge *cs, int idx,
     return dest_lattice->set_to_bottom ();
 }
 
+/* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to
+   DST_TYPE on value range in SRC_VR and store it to DST_VR.  Return true if
+   the result is a range or an anti-range.  */
+
+static bool
+ipa_vr_operation_and_type_effects (value_range *dst_vr, value_range *src_vr,
+                                  enum tree_code operation,
+                                  tree dst_type, tree src_type)
+{
+  memset (dst_vr, 0, sizeof (*dst_vr));
+  extract_range_from_unary_expr (dst_vr, operation, dst_type, src_vr, src_type);
+  if (dst_vr->type == VR_RANGE || dst_vr->type == VR_ANTI_RANGE)
+    return true;
+  else
+    return false;
+}
+
 /* Propagate value range across jump function JFUNC that is associated with
    edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
    accordingly.  */
@@ -1846,7 +1863,6 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
                                   struct ipcp_param_lattices *dest_plats,
                                   tree param_type)
 {
-  struct ipcp_param_lattices *src_lats;
   ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
 
   if (dest_lat->bottom_p ())
@@ -1859,31 +1875,23 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
 
   if (jfunc->type == IPA_JF_PASS_THROUGH)
     {
-      struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
-      int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
-      src_lats = ipa_get_parm_lattices (caller_info, src_idx);
+      enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
 
-      if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
-       return dest_lat->meet_with (src_lats->m_value_range);
-      else if (param_type
-              && (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
-                  == tcc_unary))
+      if (TREE_CODE_CLASS (operation) == tcc_unary)
        {
-         value_range vr;
-         memset (&vr, 0, sizeof (vr));
+         struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
+         int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
          tree operand_type = ipa_get_type (caller_info, src_idx);
-         enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
+         struct ipcp_param_lattices *src_lats
+           = ipa_get_parm_lattices (caller_info, src_idx);
 
          if (src_lats->m_value_range.bottom_p ())
            return dest_lat->set_to_bottom ();
-
-         extract_range_from_unary_expr (&vr,
-                                        operation,
-                                        param_type,
-                                        &src_lats->m_value_range.m_vr,
-                                        operand_type);
-         if (vr.type == VR_RANGE
-             || vr.type == VR_ANTI_RANGE)
+         value_range vr;
+         if (ipa_vr_operation_and_type_effects (&vr,
+                                                &src_lats->m_value_range.m_vr,
+                                                operation, param_type,
+                                                operand_type))
            return dest_lat->meet_with (&vr);
        }
     }
@@ -1903,8 +1911,12 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
        }
     }
 
-  if (jfunc->vr_known)
-    return dest_lat->meet_with (&jfunc->m_vr);
+  value_range vr;
+  if (jfunc->vr_known
+      && ipa_vr_operation_and_type_effects (&vr, &jfunc->m_vr, NOP_EXPR,
+                                           param_type,
+                                           TREE_TYPE (jfunc->m_vr.min)))
+    return dest_lat->meet_with (&vr);
   else
     return dest_lat->set_to_bottom ();
 }
@@ -2244,7 +2256,7 @@ propagate_constants_across_call (struct cgraph_edge *cs)
     {
       struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
       struct ipcp_param_lattices *dest_plats;
-      tree param_type = ipa_get_callee_param_type (cs, i);
+      tree param_type = ipa_get_type (callee_info, i);
 
       dest_plats = ipa_get_parm_lattices (callee_info, i);
       if (availability == AVAIL_INTERPOSABLE)
@@ -3230,19 +3242,6 @@ ipcp_propagate_stage (struct ipa_topo_info *topo)
   {
     struct ipa_node_params *info = IPA_NODE_REF (node);
 
-    /* In LTO we do not have PARM_DECLs but we would still like to be able to
-       look at types of parameters.  */
-    if (in_lto_p)
-      {
-       tree t = TYPE_ARG_TYPES (TREE_TYPE (node->decl));
-       for (int k = 0; k < ipa_get_param_count (info) && t; k++)
-         {
-           gcc_assert (t != void_list_node);
-           info->descriptors[k].decl_or_type = TREE_VALUE (t);
-           t = t ? TREE_CHAIN (t) : NULL;
-         }
-      }
-
     determine_versionability (node, info);
     if (node->has_gimple_body_p ())
       {
index 1afa8fc7a0524d506c03a3fb2598f72b0689b1b6..1f68f736e465994ede277fc655cf7f4b3b120095 100644 (file)
@@ -4775,7 +4775,7 @@ ipa_write_jump_function (struct output_block *ob,
     {
       streamer_write_widest_int (ob, jump_func->bits.value);
       streamer_write_widest_int (ob, jump_func->bits.mask);
-    }   
+    }
   bp_pack_value (&bp, jump_func->vr_known, 1);
   streamer_write_bitpack (&bp);
   if (jump_func->vr_known)
@@ -4973,7 +4973,10 @@ ipa_write_node_info (struct output_block *ob, struct cgraph_node *node)
     bp_pack_value (&bp, ipa_is_param_used (info, j), 1);
   streamer_write_bitpack (&bp);
   for (j = 0; j < ipa_get_param_count (info); j++)
-    streamer_write_hwi (ob, ipa_get_controlled_uses (info, j));
+    {
+      streamer_write_hwi (ob, ipa_get_controlled_uses (info, j));
+      stream_write_tree (ob, ipa_get_type (info, j), true);
+    }
   for (e = node->callees; e; e = e->next_callee)
     {
       struct ipa_edge_args *args = IPA_EDGE_REF (e);
@@ -5020,7 +5023,7 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node,
 
   for (k = 0; k < ipa_get_param_count (info); k++)
     info->descriptors[k].move_cost = streamer_read_uhwi (ib);
-    
+
   bp = streamer_read_bitpack (ib);
   if (ipa_get_param_count (info) != 0)
     info->analysis_done = true;
@@ -5028,7 +5031,10 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node,
   for (k = 0; k < ipa_get_param_count (info); k++)
     ipa_set_param_used (info, k, bp_unpack_value (&bp, 1));
   for (k = 0; k < ipa_get_param_count (info); k++)
-    ipa_set_controlled_uses (info, k, streamer_read_hwi (ib));
+    {
+      ipa_set_controlled_uses (info, k, streamer_read_hwi (ib));
+      info->descriptors[k].decl_or_type = stream_read_tree (ib, data_in);
+    }
   for (e = node->callees; e; e = e->next_callee)
     {
       struct ipa_edge_args *args = IPA_EDGE_REF (e);
index 341d9db6c63f83d515639d49b429073dda8b4a80..c9a69ab1f53cc9acdb389edf3b8040d417f0b082 100644 (file)
@@ -178,9 +178,10 @@ struct GTY (()) ipa_jump_func
   /* Information about zero/non-zero bits.  */
   struct ipa_bits bits;
 
-  /* Information about value range.  */
-  bool vr_known;
+  /* Information about value range, containing valid data only when vr_known is
+     true.  */
   value_range m_vr;
+  bool vr_known;
 
   enum jump_func_type type;
   /* Represents a value of a jump function.  pass_through is used only in jump
index f89841ad5ace4547063f6ac16bc596f943e08eb4..31b7a2c6d403d2b987e95ba1a397d8bf3b56e7a0 100644 (file)
@@ -1,3 +1,9 @@
+2017-01-09  Martin Jambor  <mjambor@suse.cz>
+
+       PR ipa/78365
+       PR ipa/78599
+       * gcc.dg/torture/pr78365.c: New test.
+
 2017-01-09  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/78948
diff --git a/gcc/testsuite/gcc.dg/torture/pr78365.c b/gcc/testsuite/gcc.dg/torture/pr78365.c
new file mode 100644 (file)
index 0000000..5180a01
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+int a, b, c;
+char d;
+static void fn1 (void *, int);
+int fn2 (int);
+
+void fn1 (cc, yh) void *cc;
+char yh;
+{
+  char y;
+  a = fn2(c - b + 1);
+  for (; y <= yh; y++)
+    ;
+}
+
+void fn3()
+{
+    fn1((void *)fn3, 1);
+    fn1((void *)fn3, d - 1);
+}