ipa vrp implementation in gcc
kugan
kugan.vivekanandarajah@linaro.org
Wed Feb 10 03:49:00 GMT 2016
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
-------------- next part --------------
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;
}
-------------- next part --------------
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) \
More information about the Gcc
mailing list