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) \