On 19/01/16 04:10, Jan Hubicka wrote:
In general, given that we have existing VRP implementation I would suggest
first implementing the IPA propagation and profile estimation bits using
existing VRP pass and then try to compare the simple dominator based approach
with the VRP we have and see what are the compile time/code quality effects
of both. Based on that we can decide how complex VRP we really want.

It will be probably also more fun to implement it this way:)
I plan to collect some data on early VRP and firefox today or tomorrow.


Thanks. I started experimenting with it. Prototype patch is attached. I haven't tested it in any detailed way yet. This is just to understand the LTO and see how we can implement it.


I wanted to set the value range to parameter based on the ipa-vrp. For example:

extern void foo (int);

void bar (unsigned long l)
{
  foo(l == 0);
}

void bar2 (unsigned long l)
{
  foo(l & 0x2);
}


unsigned long x;

int main()
{
  x = 0;
  bar (x);
  x = 1;
  bar (x);
  x = 3;
  bar2 (x);
  x = 5;
  bar2 (x);
}


In the above case, I wanted value range of the ssa_name that gets initialized to [0,2]. As can be seen from the ipa-cp dump (attached), this is now happening. Any comments ? I also have some questions:


1.I think even if we are not going to use the tree-vrp for intra-procedural value range propagation, we can factor out some of the routines and share it. Any thoughts on this?


2. Is the DOM based intra-procedural prototype Richard Biener implemented available anywhere. Can you please point me to that.


Thanks,
Kugan


IPA structures before propagation:

Function parameters:
  function  foo/6 parameter descriptors:
    param #0 used undescribed_use
  function  main/3 parameter descriptors:
  function  bar2/1 parameter descriptors:
    param #0 used undescribed_use
  function  bar/0 parameter descriptors:
    param #0 used undescribed_use

Jump functions:
  Jump functions of caller  __builtin_puts/7:
  Jump functions of caller  foo/6:
    callsite  foo/6 -> __builtin_puts/7 : 
       param 0: CONST: &"test"[0]
         Alignment: 1, misalignment: 0
  Jump functions of caller  main/3:
    callsite  main/3 -> foo/6 : 
       param 0: CONST: 0
         Unknown alignment
    callsite  main/3 -> foo/6 : 
       param 0: CONST: 2
         Unknown alignment
    callsite  main/3 -> foo/6 : 
       param 0: CONST: 0
         Unknown alignment
    callsite  main/3 -> foo/6 : 
       param 0: CONST: 1
         Unknown alignment
  Jump functions of caller  bar2/1:
    callsite  bar2/1 -> foo/6 : 
       param 0: UNKNOWN
         Unknown alignment
  Jump functions of caller  bar/0:
    callsite  bar/0 -> foo/6 : 
       param 0: UNKNOWN
         Unknown alignment

 Propagating constants:

Not considering foo for cloning; -fipa-cp-clone disabled.
Marking all lattices of foo/6 as BOTTOM
Not considering main for cloning; -fipa-cp-clone disabled.
Marking all lattices of main/3 as BOTTOM
Not considering bar2 for cloning; -fipa-cp-clone disabled.
Marking all lattices of bar2/1 as BOTTOM
Not considering bar for cloning; -fipa-cp-clone disabled.
Marking all lattices of bar/0 as BOTTOM

overall_size: 34, max_new_size: 11001

Estimating effects for bar2/1, base_time: 14.

Estimating effects for bar/0, base_time: 14.
Meeting
  [0, 2]
and
  [0, 1]
to
  [0, 2]

Estimating effects for foo/6, base_time: 6.

IPA lattices after all propagation:

Lattices:
  Node: foo/6:
    param [0]: BOTTOM
         ctxs: BOTTOM
         Alignment unusable (BOTTOM)
[0, 2]        AGGS BOTTOM
  Node: main/3:
  Node: bar2/1:
    param [0]: BOTTOM
         ctxs: BOTTOM
         Alignment unusable (BOTTOM)
UNDEFINED        AGGS BOTTOM
  Node: bar/0:
    param [0]: BOTTOM
         ctxs: BOTTOM
         Alignment unusable (BOTTOM)
UNDEFINED        AGGS BOTTOM

IPA decision stage:


Evaluating opportunities for bar2/1.

Evaluating opportunities for bar/0.

Evaluating opportunities for foo/6.

IPA constant propagation end

Reclaiming functions:
Reclaiming variables:
Clearing address taken flags:
Symbol table:

puts/7 (__builtin_puts) @0x7ffa9ff50730
  Type: function
  Visibility: external public
  References: 
  Referring: 
  Availability: not_available
  First run: 0
  Function flags:
  Called by: foo/6 (0.19 per call) 
  Calls: 
foo/6 (foo) @0x7ffa9ff505c0
  Type: function definition analyzed
  Visibility: externally_visible public
  References: 
  Referring: 
  Read from file: t1.o
  Availability: available
  First run: 0
  Function flags:
  Called by: bar/0 (1.00 per call) bar2/1 (1.00 per call) main/3 (1.00 per 
call) main/3 (1.00 per call) main/3 (1.00 per call) main/3 (1.00 per call) 
  Calls: puts/7 (0.19 per call) 
x/2 (x) @0x7ffa9ff51000
  Type: variable definition analyzed
  Visibility: externally_visible public common
  References: 
  Referring: main/3 (write)main/3 (write)main/3 (write)main/3 (write)
  Read from file: t2.o
  Availability: overwritable
  Varpool flags:
main/3 (main) @0x7ffa9ff502e0
  Type: function definition analyzed
  Visibility: externally_visible public
  References: x/2 (write)x/2 (write)x/2 (write)x/2 (write)
  Referring: 
  Read from file: t2.o
  Availability: available
  First run: 0
  Function flags: only_called_at_startup executed_once only_called_at_startup
  Called by: 
  Calls: foo/6 (1.00 per call) foo/6 (1.00 per call) foo/6 (1.00 per call) 
foo/6 (1.00 per call) 
bar2/1 (bar2) @0x7ffa9ff50170
  Type: function definition analyzed
  Visibility: externally_visible public
  References: 
  Referring: 
  Read from file: t2.o
  Availability: available
  First run: 0
  Function flags:
  Called by: 
  Calls: foo/6 (1.00 per call) 
bar/0 (bar) @0x7ffa9ff50000
  Type: function definition analyzed
  Visibility: externally_visible public
  References: 
  Referring: 
  Read from file: t2.o
  Availability: available
  First run: 0
  Function flags:
  Called by: 
  Calls: foo/6 (1.00 per call) 

;; Function foo (foo, funcdef_no=0, decl_uid=3890, cgraph_uid=4, symbol_order=6)

Modification phase of node foo/6
Setting value range of param 0 [0,2]
__attribute__((noinline))
foo (int i)
{
  unsigned int _3;

  <bb 2>:
  _3 = (unsigned int) i_2(D);
  if (_3 > 1)
    goto <bb 4>;
  else
    goto <bb 3>;

  <bb 3>:
  __builtin_puts (&"test"[0]);

  <bb 4>:
  return;

}



;; Function main (main, funcdef_no=1, decl_uid=3884, cgraph_uid=2, 
symbol_order=3) (executed once)

Modification phase of node main/3
main ()
{
  <bb 2>:
  x = 0;
  foo (1);
  x = 1;
  foo (0);
  x = 3;
  foo (2);
  x = 5;
  foo (0);
  return 0;

}



;; Function bar2 (bar2, funcdef_no=2, decl_uid=3883, cgraph_uid=1, 
symbol_order=1)

Modification phase of node bar2/1
bar2 (long unsigned int l)
{
  int _2;
  int _3;

  <bb 2>:
  _2 = (int) l_1(D);
  _3 = _2 & 2;
  foo (_3);
  return;

}



;; Function bar (bar, funcdef_no=3, decl_uid=3882, cgraph_uid=0, symbol_order=0)

Modification phase of node bar/0
bar (long unsigned int l)
{
  _Bool _2;
  int _3;

  <bb 2>:
  _2 = l_1(D) == 0;
  _3 = (int) _2;
  foo (_3);
  return;

}


diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index ee28550..cb42a51 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -121,6 +121,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-inline.h"
 #include "ipa-utils.h"
 
+extern void set_range_info (tree, enum value_range_type, const wide_int_ref &,
+                           const wide_int_ref &);
 template <typename valtype> class ipcp_value;
 
 /* Describes a particular source for an IPA-CP value.  */
@@ -266,6 +268,33 @@ private:
   bool meet_with_1 (unsigned new_align, unsigned new_misalign);
 };
 
+/* Lattice of value ranges.  */
+
+class ipcp_vr_lattice
+{
+public:
+  value_range vr;
+
+  inline bool bottom_p () const;
+  inline bool top_p () const;
+  inline bool set_to_bottom ();
+  bool meet_with (const value_range *vr);
+  bool meet_with (const ipcp_vr_lattice &other);
+  void init () { vr.type = VR_UNDEFINED; }
+  void print (FILE * f);
+
+private:
+  bool meet_with_1 (const value_range *vr);
+  /* If set, this lattice is bottom and all other fields should be
+     disregarded.  */
+  bool bottom;
+  /* If bottom and not_top are false, the lattice is TOP.  If not_top is true,
+     the known alignment is stored in the fields align and misalign.  The field
+     is negated so that memset to zero initializes the lattice to TOP
+     state.  */
+  bool not_top;
+};
+
 /* Structure containing lattices for a parameter itself and for pieces of
    aggregates that are passed in the parameter or by a reference in a parameter
    plus some other useful flags.  */
@@ -281,6 +310,8 @@ public:
   ipcp_agg_lattice *aggs;
   /* Lattice describing known alignment.  */
   ipcp_alignment_lattice alignment;
+  /* Lattice describing value range.  */
+  ipcp_vr_lattice vr;
   /* Number of aggregate lattices */
   int aggs_count;
   /* True if aggregate data were passed by reference (as opposed to by
@@ -348,6 +379,15 @@ ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i)
   return &plats->ctxlat;
 }
 
+/* Return the lattice corresponding to the value range of the Ith formal
+   parameter of the function described by INFO.  */
+static inline ipcp_vr_lattice *
+ipa_get_vr_lat (struct ipa_node_params *info, int i)
+{
+  struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
+  return &plats->vr;
+}
+
 /* Return whether LAT is a lattice with a single constant and without an
    undefined value.  */
 
@@ -458,6 +498,14 @@ ipcp_alignment_lattice::print (FILE * f)
     fprintf (f, "         Alignment %u, misalignment %u\n", align, misalign);
 }
 
+/* Print vr lattice to F.  */
+
+void
+ipcp_vr_lattice::print (FILE * f)
+{
+  dump_value_range (f, &vr);
+}
+
 /* Print all ipcp_lattices of all functions to F.  */
 
 static void
@@ -484,6 +532,7 @@ print_all_lattices (FILE * f, bool dump_sources, bool 
dump_benefits)
          fprintf (f, "         ctxs: ");
          plats->ctxlat.print (f, dump_sources, dump_benefits);
          plats->alignment.print (f);
+         plats->vr.print (f);
          if (plats->virt_call)
            fprintf (f, "        virt_call flag set\n");
 
@@ -828,6 +877,98 @@ ipcp_alignment_lattice::set_to_bottom ()
   return true;
 }
 
+/* Meet the current value of the lattice with described by OTHER
+   lattice.  */
+
+bool
+ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other)
+{
+  return meet_with_1 (&other.vr);
+}
+
+/* Meet the current value of the lattice with value ranfge described by VR
+   lattice.  */
+
+bool
+ipcp_vr_lattice::meet_with (const value_range *vr)
+{
+  return meet_with_1 (vr);
+}
+
+/* Meet the current value of the lattice with value ranfge described by
+   OTHER_VR lattice.  */
+
+bool
+ipcp_vr_lattice::meet_with_1 (const value_range *other_vr)
+{
+  tree min = NULL_TREE, max = NULL_TREE;
+  value_range_type type = VR_LAST;
+
+  if (bottom_p ())
+    return false;
+
+  if (other_vr->type == VR_VARYING)
+    {
+      set_to_bottom ();
+      return (vr.type != VR_VARYING);
+    }
+  else if ( other_vr->type == VR_UNDEFINED)
+    return false;
+
+  if (top_p ())
+    {
+      vr.min = other_vr->min;
+      vr.max = other_vr->max;
+      vr.type = other_vr->type;
+      return true;
+    }
+
+  if (vr.type == VR_RANGE
+      || vr.type == VR_ANTI_RANGE)
+    {
+      min = vr.min;
+      max = vr.max;
+      type = vr.type;
+    }
+
+  vrp_meet (&vr, const_cast<value_range *> (other_vr));
+  if (type != vr.type
+      || min != vr.min
+      || max != vr.max)
+    return true;
+  else
+    return false;
+}
+
+/* Return true if alignment information in the lattice is yet unknown.  */
+
+bool
+ipcp_vr_lattice::top_p () const
+{
+  return vr.type == VR_UNDEFINED;
+}
+
+/* Return true if value range information in the lattice is known to be
+   unusable.  */
+
+bool
+ipcp_vr_lattice::bottom_p () const
+{
+  return vr.type == VR_VARYING;
+}
+
+/* Set value range information in the lattice to bottom.  Return true if it
+   previously was in a different state.  */
+
+bool
+ipcp_vr_lattice::set_to_bottom ()
+{
+  if (vr.type == VR_VARYING)
+    return false;
+  vr.type = VR_VARYING;
+  return true;
+}
+
 /* Meet the current value of the lattice with alignment described by NEW_ALIGN
    and NEW_MISALIGN, assuming that we know the current value is neither TOP nor
    BOTTOM.  Return true if the value of lattice has changed.  */
@@ -915,6 +1056,7 @@ set_all_contains_variable (struct ipcp_param_lattices 
*plats)
   ret |= plats->ctxlat.set_contains_variable ();
   ret |= set_agg_lats_contain_variable (plats);
   ret |= plats->alignment.set_to_bottom ();
+  ret |= plats->vr.set_to_bottom ();
   return ret;
 }
 
@@ -999,6 +1141,7 @@ initialize_node_lattices (struct cgraph_node *node)
            }
          else
            set_all_contains_variable (plats);
+         plats->vr.init ();
        }
       if (dump_file && (dump_flags & TDF_DETAILS)
          && !node->alias && !node->thunk.thunk_p)
@@ -1613,7 +1756,26 @@ propagate_alignment_accross_jump_function (cgraph_edge 
*cs,
     }
 }
 
-/* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
+/* Propagate alignments across jump function JFUNC that is associated with
+   edge CS and update DEST_LAT accordingly.  */
+static bool
+propagate_vr_accross_jump_function (ipa_jump_func *jfunc,
+                                   struct ipcp_param_lattices *dest_plats)
+{
+  ipcp_vr_lattice *dest_lat = &dest_plats->vr;
+  if (dest_lat->bottom_p ())
+    return false;
+
+  //if (!jfunc->vr_known)
+  //  return dest_lat->set_to_bottom ();
+
+  if (dest_lat->meet_with (&jfunc->vr))
+    return true;
+
+  return false;
+}
+
+/* If DEST_PLATS alvrhas aggregate items, check that aggs_by_ref matches
    NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all
    other cases, return false).  If there are no aggregate items, set
    aggs_by_ref to NEW_AGGS_BY_REF.  */
@@ -1953,6 +2115,7 @@ propagate_constants_accross_call (struct cgraph_edge *cs)
                                                         
&dest_plats->alignment);
          ret |= propagate_aggs_accross_jump_function (cs, jump_func,
                                                       dest_plats);
+         ret |= propagate_vr_accross_jump_function (jump_func, dest_plats);
        }
     }
   for (; i < parms_count; i++)
@@ -4479,7 +4642,7 @@ ipcp_decision_stage (struct ipa_topo_info *topo)
    to the transformation summary.  */
 
 static void
-ipcp_store_alignment_results (void)
+ipcp_store_alignment_and_vr_results (void)
 {
   cgraph_node *node;
 
@@ -4489,6 +4652,7 @@ ipcp_store_alignment_results (void)
     bool dumped_sth = false;
     bool found_useful_result = false;
 
+#if 0
     if (!opt_for_fn (node->decl, flag_ipa_cp_alignment))
       {
        if (dump_file)
@@ -4497,6 +4661,7 @@ ipcp_store_alignment_results (void)
                   node->name ());
        continue;
       }
+#endif
 
    if (info->ipcp_orig_node)
       info = IPA_NODE_REF (info->ipcp_orig_node);
@@ -4512,6 +4677,12 @@ ipcp_store_alignment_results (void)
           found_useful_result = true;
           break;
         }
+       if (!plats->vr.bottom_p ()
+          && !plats->vr.top_p ())
+        {
+          found_useful_result = true;
+          break;
+        }
      }
    if (!found_useful_result)
      continue;
@@ -4519,11 +4690,13 @@ ipcp_store_alignment_results (void)
    ipcp_grow_transformations_if_necessary ();
    ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
    vec_safe_reserve_exact (ts->alignments, count);
+   vec_safe_reserve_exact (ts->vr, count);
 
    for (unsigned i = 0; i < count ; i++)
      {
        ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
        ipa_alignment al;
+       ipa_vr vr;
 
        if (!plats->alignment.bottom_p ()
           && !plats->alignment.top_p ())
@@ -4535,7 +4708,19 @@ ipcp_store_alignment_results (void)
        else
         al.known = false;
 
+       if (!plats->vr.bottom_p ()
+          && !plats->vr.top_p ())
+        {
+          vr.known = true;
+          vr.type = plats->vr.vr.type;
+          vr.min = plats->vr.vr.min;
+          vr.max = plats->vr.vr.max;
+        }
+       else
+        vr.known = false;
+
        ts->alignments->quick_push (al);
+       ts->vr->quick_push (vr);
        if (!dump_file || !al.known)
         continue;
        if (!dumped_sth)
@@ -4582,7 +4767,7 @@ ipcp_driver (void)
   /* Decide what constant propagation and cloning should be performed.  */
   ipcp_decision_stage (&topo);
   /* Store results of alignment propagation. */
-  ipcp_store_alignment_results ();
+  ipcp_store_alignment_and_vr_results ();
 
   /* Free all IPCP structures.  */
   free_toporder_info (&topo);
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 72c2fed..0c4878b 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -1655,7 +1655,20 @@ ipa_compute_jump_functions_for_edge (struct 
ipa_func_body_info *fbi,
            gcc_assert (!jfunc->alignment.known);
        }
       else
-       gcc_assert (!jfunc->alignment.known);
+       {
+         wide_int min, max;
+         value_range_type type;
+         if (TREE_CODE (arg) == SSA_NAME
+             && (type = get_range_info (arg, &min, &max))
+             && (type == VR_RANGE || type == VR_ANTI_RANGE))
+           {
+             jfunc->vr_known = true;
+             jfunc->vr.type = type;
+             jfunc->vr.min = wide_int_to_tree (TREE_TYPE (arg), min);
+             jfunc->vr.max = wide_int_to_tree (TREE_TYPE (arg), max);
+           }
+         gcc_assert (!jfunc->alignment.known);
+       }
 
       if (is_gimple_ip_invariant (arg))
        ipa_set_jf_constant (jfunc, arg, cs);
@@ -3532,16 +3545,24 @@ ipa_node_params_t::duplicate(cgraph_node *src, 
cgraph_node *dst,
 
   ipcp_transformation_summary *src_trans = ipcp_get_transformation_summary 
(src);
 
-  if (src_trans && vec_safe_length (src_trans->alignments) > 0)
+  if (src_trans
+      && (vec_safe_length (src_trans->alignments) > 0
+         || vec_safe_length (src_trans->vr) > 0))
     {
       ipcp_grow_transformations_if_necessary ();
       src_trans = ipcp_get_transformation_summary (src);
       const vec<ipa_alignment, va_gc> *src_alignments = src_trans->alignments;
+      const vec<ipa_vr, va_gc> *src_vr = src_trans->vr;
       vec<ipa_alignment, va_gc> *&dst_alignments
        = ipcp_get_transformation_summary (dst)->alignments;
+      vec<ipa_vr, va_gc> *&dst_vr
+       = ipcp_get_transformation_summary (dst)->vr;
       vec_safe_reserve_exact (dst_alignments, src_alignments->length ());
+      vec_safe_reserve_exact (dst_vr, src_vr->length ());
       for (unsigned i = 0; i < src_alignments->length (); ++i)
        dst_alignments->quick_push ((*src_alignments)[i]);
+      for (unsigned i = 0; i < src_vr->length (); ++i)
+       dst_vr->quick_push ((*src_vr)[i]);
     }
 }
 
@@ -4462,6 +4483,14 @@ ipa_write_jump_function (struct output_block *ob,
       streamer_write_uhwi (ob, jump_func->alignment.align);
       streamer_write_uhwi (ob, jump_func->alignment.misalign);
     }
+  bp_pack_value (&bp, jump_func->vr_known, 1);
+  streamer_write_bitpack (&bp);
+  if (jump_func->vr_known)
+    {
+      streamer_write_enum (ob->main_stream, value_rang_type, VR_LAST, 
jump_func->vr.type);
+      stream_write_tree (ob, jump_func->vr.min, true);
+      stream_write_tree (ob, jump_func->vr.max, true);
+    }
 }
 
 /* Read in jump function JUMP_FUNC from IB.  */
@@ -4538,6 +4567,17 @@ ipa_read_jump_function (struct lto_input_block *ib,
     }
   else
     jump_func->alignment.known = false;
+  struct bitpack_d vr_bp = streamer_read_bitpack (ib);
+  bool vr_known = bp_unpack_value (&vr_bp, 1);
+  if (vr_known)
+    {
+      jump_func->vr_known = true;
+      jump_func->vr.type = streamer_read_enum (ib, value_range_type, VR_LAST);
+      jump_func->vr.min = stream_read_tree (ib, data_in);
+      jump_func->vr.max = stream_read_tree (ib, data_in);
+    }
+  else
+    jump_func->vr_known = false;
 }
 
 /* Stream out parts of cgraph_indirect_call_info corresponding to CS that are
@@ -4878,7 +4918,8 @@ write_ipcp_transformation_info (output_block *ob, 
cgraph_node *node)
     }
 
   ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
-  if (ts && vec_safe_length (ts->alignments) > 0)
+  if (ts && (vec_safe_length (ts->alignments) > 0
+            || vec_safe_length (ts->alignments) > 0))
     {
       count = ts->alignments->length ();
 
@@ -4886,6 +4927,7 @@ write_ipcp_transformation_info (output_block *ob, 
cgraph_node *node)
       for (unsigned i = 0; i < count; ++i)
        {
          ipa_alignment *parm_al = &(*ts->alignments)[i];
+         ipa_vr *parm_vr = &(*ts->vr)[i];
 
          struct bitpack_d bp;
          bp = bitpack_create (ob->main_stream);
@@ -4897,6 +4939,15 @@ write_ipcp_transformation_info (output_block *ob, 
cgraph_node *node)
              streamer_write_hwi_in_range (ob->main_stream, 0, parm_al->align,
                                           parm_al->misalign);
            }
+         bp = bitpack_create (ob->main_stream);
+         bp_pack_value (&bp, parm_vr->known, 1);
+         streamer_write_bitpack (&bp);
+         if (parm_vr->known)
+           {
+             streamer_write_enum (ob->main_stream, value_rang_type, VR_LAST, 
parm_vr->type);
+             stream_write_tree (ob, parm_vr->min, true);
+             stream_write_tree (ob, parm_vr->max, true);
+           }
        }
     }
   else
@@ -4936,11 +4987,14 @@ read_ipcp_transformation_info (lto_input_block *ib, 
cgraph_node *node,
 
       ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
       vec_safe_grow_cleared (ts->alignments, count);
+      vec_safe_grow_cleared (ts->vr, count);
 
       for (i = 0; i < count; i++)
        {
          ipa_alignment *parm_al;
+         ipa_vr *parm_vr;
          parm_al = &(*ts->alignments)[i];
+         parm_vr = &(*ts->vr)[i];
          struct bitpack_d bp;
          bp = streamer_read_bitpack (ib);
          parm_al->known = bp_unpack_value (&bp, 1);
@@ -4951,6 +5005,14 @@ read_ipcp_transformation_info (lto_input_block *ib, 
cgraph_node *node,
                = streamer_read_hwi_in_range (ib, "ipa-prop misalign",
                                              0, parm_al->align);
            }
+         bp = streamer_read_bitpack (ib);
+         parm_vr->known = bp_unpack_value (&bp, 1);
+         if (parm_vr->known)
+           {
+             parm_vr->type = streamer_read_enum (ib, value_range_type, 
VR_LAST);
+             parm_vr->min = stream_read_tree (ib, data_in);
+             parm_vr->max = stream_read_tree (ib, data_in);
+           }
        }
     }
 }
@@ -5207,15 +5269,17 @@ ipcp_modif_dom_walker::before_dom_children (basic_block 
bb)
    ipcp_transformation_summary.  */
 
 static void
-ipcp_update_alignments (struct cgraph_node *node)
+ipcp_update_vr_and_alignments (struct cgraph_node *node)
 {
   tree fndecl = node->decl;
   tree parm = DECL_ARGUMENTS (fndecl);
   tree next_parm = parm;
   ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
-  if (!ts || vec_safe_length (ts->alignments) == 0)
+  if (!ts || ((vec_safe_length (ts->alignments) == 0)
+             && (vec_safe_length (ts->vr) == 0)))
     return;
   const vec<ipa_alignment, va_gc> &alignments = *ts->alignments;
+  const vec<ipa_vr, va_gc> &vr = *ts->vr;
   unsigned count = alignments.length ();
 
   for (unsigned i = 0; i < count; ++i, parm = next_parm)
@@ -5225,13 +5289,32 @@ ipcp_update_alignments (struct cgraph_node *node)
        continue;
       gcc_checking_assert (parm);
       next_parm = DECL_CHAIN (parm);
-
-      if (!alignments[i].known || !is_gimple_reg (parm))
-       continue;
       tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->decl), parm);
       if (!ddef)
        continue;
 
+      if (vr[i].known
+         && TREE_CODE (vr[i].min) == INTEGER_CST
+         && TREE_CODE (vr[i].max) == INTEGER_CST)
+       {
+         if (dump_file)
+           {
+             fprintf (dump_file, "Setting value range of param %u ", i);
+             fprintf (dump_file, "%s[", (vr[i].type == VR_ANTI_RANGE) ? "~" : 
"");
+             print_generic_expr (dump_file, vr[i].min, 0);
+             fprintf (dump_file, ",");
+             print_generic_expr (dump_file, vr[i].max, 0);
+             fprintf (dump_file, "]\n");
+           }
+         set_range_info (ddef, vr[i].type,
+                         wide_int_to_tree (TREE_TYPE (ddef), vr[i].min),
+                         wide_int_to_tree (TREE_TYPE (ddef), vr[i].max));
+
+       }
+
+      if (!alignments[i].known || !is_gimple_reg (parm))
+       continue;
+
       if (dump_file)
        fprintf (dump_file, "  Adjusting alignment of param %u to %u, "
                 "misalignment to %u\n", i, alignments[i].align,
@@ -5273,7 +5356,7 @@ ipcp_transform_function (struct cgraph_node *node)
     fprintf (dump_file, "Modification phase of node %s/%i\n",
             node->name (), node->order);
 
-  ipcp_update_alignments (node);
+  ipcp_update_vr_and_alignments (node);
   aggval = ipa_get_agg_replacements_for_node (node);
   if (!aggval)
       return 0;
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 2fe824d..169ec97 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -154,6 +154,16 @@ struct GTY(()) ipa_alignment
   unsigned misalign;
 };
 
+/* Info about value ranges. */
+struct GTY(()) ipa_vr
+{
+  /* The data fields below are valid only if known is true.  */
+  bool known;
+  enum value_range_type type;
+  tree GTY ((skip)) min;
+  tree GTY ((skip)) max;
+};
+
 /* A jump function for a callsite represents the values passed as actual
    arguments of the callsite. See enum jump_func_type for the various
    types of jump functions supported.  */
@@ -166,6 +176,10 @@ struct GTY (()) ipa_jump_func
   /* Information about alignment of pointers. */
   struct ipa_alignment alignment;
 
+  /* Information about value range. */
+  bool vr_known;
+  value_range vr;
+
   enum jump_func_type type;
   /* Represents a value of a jump function.  pass_through is used only in jump
      function context.  constant represents the actual constant in constant 
jump
@@ -482,6 +496,8 @@ struct GTY(()) ipcp_transformation_summary
   ipa_agg_replacement_value *agg_values;
   /* Alignment information for pointers.  */
   vec<ipa_alignment, va_gc> *alignments;
+  /* Value range information.  */
+  vec<ipa_vr, va_gc> *vr;
 };
 
 void ipa_set_node_agg_value_chain (struct cgraph_node *node,
diff --git a/gcc/passes.def b/gcc/passes.def
index 43ce3d5..6d0dbec 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -119,6 +119,7 @@ along with GCC; see the file COPYING3.  If not see
             early optimizations again.  It is thus good idea to do this
              late.  */
          NEXT_PASS (pass_split_functions);
+      NEXT_PASS (pass_vrp, false /* warn_array_bounds_p */);
       POP_INSERT_PASSES ()
       NEXT_PASS (pass_release_ssa_names);
       NEXT_PASS (pass_rebuild_cgraph_edges);
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index 092ada1..73ff5f4 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -63,9 +63,7 @@ struct GTY ((variable_size)) range_info_def {
 #define ssa_name(i) ((*cfun->gimple_df->ssa_names)[(i)])
 
 
-/* Type of value ranges.  See value_range_d In tree-vrp.c for a
-   description of these types.  */
-enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING };
+#define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }
 
 /* Sets the value range to SSA.  */
 extern void set_range_info (tree, enum value_range_type, const wide_int_ref &,
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index acbb70b..ed92fda 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -59,33 +59,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "target.h"
 #include "case-cfn-macros.h"
 
-/* Range of values that can be associated with an SSA_NAME after VRP
-   has executed.  */
-struct value_range
-{
-  /* Lattice value represented by this range.  */
-  enum value_range_type type;
-
-  /* Minimum and maximum values represented by this range.  These
-     values should be interpreted as follows:
-
-       - If TYPE is VR_UNDEFINED or VR_VARYING then MIN and MAX must
-         be NULL.
-
-       - If TYPE == VR_RANGE then MIN holds the minimum value and
-         MAX holds the maximum value of the range [MIN, MAX].
-
-       - If TYPE == ANTI_RANGE the variable is known to NOT
-         take any values in the range [MIN, MAX].  */
-  tree min;
-  tree max;
-
-  /* Set of SSA names whose value ranges are equivalent to this one.
-     This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE.  */
-  bitmap equiv;
-};
-
-#define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }
 
 /* Set of SSA names found live during the RPO traversal of the function
    for still active basic-blocks.  */
@@ -103,7 +76,6 @@ live_on_edge (edge e, tree name)
 /* Local functions.  */
 static int compare_values (tree val1, tree val2);
 static int compare_values_warnv (tree val1, tree val2, bool *);
-static void vrp_meet (value_range *, value_range *);
 static void vrp_intersect_ranges (value_range *, value_range *);
 static tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
                                                     tree, tree, bool, bool *,
@@ -4629,7 +4601,6 @@ compare_range_with_value (enum tree_code comp, 
value_range *vr, tree val,
 
 /* Debugging dumps.  */
 
-void dump_value_range (FILE *, value_range *);
 void debug_value_range (value_range *);
 void dump_all_value_ranges (FILE *);
 void debug_all_value_ranges (void);
@@ -8623,7 +8594,7 @@ vrp_meet_1 (value_range *vr0, value_range *vr1)
     bitmap_clear (vr0->equiv);
 }
 
-static void
+void
 vrp_meet (value_range *vr0, value_range *vr1)
 {
   if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/tree.h b/gcc/tree.h
index 96ffa83..e1bbc27 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2696,6 +2696,40 @@ extern priority_type decl_fini_priority_lookup (tree);
 extern void decl_init_priority_insert (tree, priority_type);
 extern void decl_fini_priority_insert (tree, priority_type);
 
+/* Type of value ranges.  See value_range_d In tree-vrp.c for a
+   description of these types.  */
+enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING, 
VR_LAST };
+
+/* Range of values that can be associated with an SSA_NAME after VRP
+   has executed.  */
+struct GTY(()) value_range
+{
+  /* Lattice value represented by this range.  */
+  enum value_range_type type;
+
+  /* Minimum and maximum values represented by this range.  These
+     values should be interpreted as follows:
+
+       - If TYPE is VR_UNDEFINED or VR_VARYING then MIN and MAX must
+         be NULL.
+
+       - If TYPE == VR_RANGE then MIN holds the minimum value and
+         MAX holds the maximum value of the range [MIN, MAX].
+
+       - If TYPE == ANTI_RANGE the variable is known to NOT
+         take any values in the range [MIN, MAX].  */
+  tree min;
+  tree max;
+
+  /* Set of SSA names whose value ranges are equivalent to this one.
+     This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE.  */
+  bitmap equiv;
+};
+
+void vrp_meet (value_range *vr0, value_range *vr1);
+void dump_value_range (FILE *, value_range *);
+
+
 /* For a VAR_DECL or FUNCTION_DECL the initialization priority of
    NODE.  */
 #define DECL_INIT_PRIORITY(NODE) \

Reply via email to