Commit 8bc5448f by Kugan Vivekanandarajah Committed by Kugan Vivekanandarajah

Add IPA VRP

gcc/lto/ChangeLog:
2016-09-21  Kugan Vivekanandarajah  <kuganv@linaro.org>

	* lto-partition.c: Include tree-vrp.h.
	* lto.c: Likewise.

gcc/testsuite/ChangeLog:

2016-09-21  Kugan Vivekanandarajah  <kuganv@linaro.org>

	* g++.dg/ipa/pure-const-3.C: Add -fno-ipa-vrp. Else constant arguments
	will be optimized away.
	* gcc.dg/ipa/vrp1.c: New test.
	* gcc.dg/ipa/vrp2.c: New test.
	* gcc.dg/ipa/vrp3.c: New test.

gcc/ChangeLog:

2016-09-21  Kugan Vivekanandarajah  <kuganv@linaro.org>

	* common.opt: New option -fipa-vrp.
	* ipa-cp.c (ipa_get_vr_lat): New.
	(ipcp_vr_lattice::print): Likewise.
	(print_all_lattices): Call ipcp_vr_lattice::print.
	(ipcp_vr_lattice::meet_with): New.
	(ipcp_vr_lattice::meet_with_1): Likewise.
	(ipcp_vr_lattice::top_p): Likewise.
	(ipcp_vr_lattice::bottom_p): Likewsie.
	(ipcp_vr_lattice::set_to_bottom): Likewise.
	(set_all_contains_variable): Call VR set_to_bottom.
	(initialize_node_lattices): Init VR lattices.
	(propagate_vr_accross_jump_function): New.
	(propagate_constants_accross_call): Call
	propagate_vr_accross_jump_function.
	(ipcp_store_vr_results): New.
	(ipcp_driver): Handle VR.
	* ipa-prop.c (ipa_print_node_jump_functions_for_edge): Handle VR.
	(ipa_set_jf_unknown): Likewise.
	(ipa_compute_jump_functions_for_edge): Likewise.
	(ipa_node_params_t::duplicate): Likewise.
	(ipa_write_jump_function): Likewise.
	(ipa_read_jump_function): Likewise.
	(write_ipcp_transformation_info): Likewise.
	(read_ipcp_transformation_info): Likewise.
	(ipcp_update_vr): New.
	(ipcp_transform_function): Handle VR.
	* ipa-prop.h (struct ipa_vr): New.
	* cgraph.c: Include tree-vrp.h.
	* cgraphunit.c: Likewise.
	* ipa-utils.c: Likewise.
	* ipa.c: Likewise.

From-SVN: r240292
parent 973625a0
2016-09-21 Kugan Vivekanandarajah <kuganv@linaro.org> 2016-09-21 Kugan Vivekanandarajah <kuganv@linaro.org>
* common.opt: New option -fipa-vrp.
* ipa-cp.c (ipa_get_vr_lat): New.
(ipcp_vr_lattice::print): Likewise.
(print_all_lattices): Call ipcp_vr_lattice::print.
(ipcp_vr_lattice::meet_with): New.
(ipcp_vr_lattice::meet_with_1): Likewise.
(ipcp_vr_lattice::top_p): Likewise.
(ipcp_vr_lattice::bottom_p): Likewsie.
(ipcp_vr_lattice::set_to_bottom): Likewise.
(set_all_contains_variable): Call VR set_to_bottom.
(initialize_node_lattices): Init VR lattices.
(propagate_vr_accross_jump_function): New.
(propagate_constants_accross_call): Call
propagate_vr_accross_jump_function.
(ipcp_store_vr_results): New.
(ipcp_driver): Handle VR.
* ipa-prop.c (ipa_print_node_jump_functions_for_edge): Handle VR.
(ipa_set_jf_unknown): Likewise.
(ipa_compute_jump_functions_for_edge): Likewise.
(ipa_node_params_t::duplicate): Likewise.
(ipa_write_jump_function): Likewise.
(ipa_read_jump_function): Likewise.
(write_ipcp_transformation_info): Likewise.
(read_ipcp_transformation_info): Likewise.
(ipcp_update_vr): New.
(ipcp_transform_function): Handle VR.
* ipa-prop.h (struct ipa_vr): New.
* cgraph.c: Include tree-vrp.h.
* cgraphunit.c: Likewise.
* ipa-utils.c: Likewise.
* ipa.c: Likewise.
* opts.c: Likewise.
* toplev.c: Likewise.
* ipa-devirt.c: Likewise.
* ipa-inline-transform.c: Likewise.
* ipa-inline.c: Likewise.
* ipa-profile.c: Likewise.
2016-09-21 Kugan Vivekanandarajah <kuganv@linaro.org>
* doc/invoke.texi: Document -fdump-tree-evrp. * doc/invoke.texi: Document -fdump-tree-evrp.
* passes.def: Define new pass_early_vrp. * passes.def: Define new pass_early_vrp.
* timevar.def: Define new TV_TREE_EARLY_VRP. * timevar.def: Define new TV_TREE_EARLY_VRP.
......
...@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see
#include "value-prof.h" #include "value-prof.h"
#include "ipa-utils.h" #include "ipa-utils.h"
#include "symbol-summary.h" #include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h" #include "ipa-prop.h"
#include "ipa-inline.h" #include "ipa-inline.h"
#include "cfgloop.h" #include "cfgloop.h"
......
...@@ -190,6 +190,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -190,6 +190,7 @@ along with GCC; see the file COPYING3. If not see
#include "toplev.h" #include "toplev.h"
#include "debug.h" #include "debug.h"
#include "symbol-summary.h" #include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h" #include "ipa-prop.h"
#include "gimple-pretty-print.h" #include "gimple-pretty-print.h"
#include "plugin.h" #include "plugin.h"
......
...@@ -1605,6 +1605,10 @@ fipa-struct-reorg ...@@ -1605,6 +1605,10 @@ fipa-struct-reorg
Common Ignore Common Ignore
Does nothing. Preserved for backward compatibility. Does nothing. Preserved for backward compatibility.
fipa-vrp
Common Report Var(flag_ipa_vrp) Optimization
Perform IPA Value Range Propagation.
fira-algorithm= fira-algorithm=
Common Joined RejectNegative Enum(ira_algorithm) Var(flag_ira_algorithm) Init(IRA_ALGORITHM_CB) Optimization Common Joined RejectNegative Enum(ira_algorithm) Var(flag_ira_algorithm) Init(IRA_ALGORITHM_CB) Optimization
-fira-algorithm=[CB|priority] Set the used IRA algorithm. -fira-algorithm=[CB|priority] Set the used IRA algorithm.
......
...@@ -114,6 +114,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -114,6 +114,7 @@ along with GCC; see the file COPYING3. If not see
#include "fold-const.h" #include "fold-const.h"
#include "gimple-fold.h" #include "gimple-fold.h"
#include "symbol-summary.h" #include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h" #include "ipa-prop.h"
#include "tree-pretty-print.h" #include "tree-pretty-print.h"
#include "tree-inline.h" #include "tree-inline.h"
...@@ -321,6 +322,25 @@ private: ...@@ -321,6 +322,25 @@ private:
void get_value_and_mask (tree, widest_int *, widest_int *); void get_value_and_mask (tree, widest_int *, widest_int *);
}; };
/* Lattice of value ranges. */
class ipcp_vr_lattice
{
public:
value_range m_vr;
inline bool bottom_p () const;
inline bool top_p () const;
inline bool set_to_bottom ();
bool meet_with (const value_range *p_vr);
bool meet_with (const ipcp_vr_lattice &other);
void init () { m_vr.type = VR_UNDEFINED; }
void print (FILE * f);
private:
bool meet_with_1 (const value_range *other_vr);
};
/* Structure containing lattices for a parameter itself and for pieces of /* 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 aggregates that are passed in the parameter or by a reference in a parameter
plus some other useful flags. */ plus some other useful flags. */
...@@ -338,6 +358,8 @@ public: ...@@ -338,6 +358,8 @@ public:
ipcp_alignment_lattice alignment; ipcp_alignment_lattice alignment;
/* Lattice describing known bits. */ /* Lattice describing known bits. */
ipcp_bits_lattice bits_lattice; ipcp_bits_lattice bits_lattice;
/* Lattice describing value range. */
ipcp_vr_lattice m_value_range;
/* Number of aggregate lattices */ /* Number of aggregate lattices */
int aggs_count; int aggs_count;
/* True if aggregate data were passed by reference (as opposed to by /* True if aggregate data were passed by reference (as opposed to by
...@@ -405,6 +427,16 @@ ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i) ...@@ -405,6 +427,16 @@ ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i)
return &plats->ctxlat; 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->m_value_range;
}
/* Return whether LAT is a lattice with a single constant and without an /* Return whether LAT is a lattice with a single constant and without an
undefined value. */ undefined value. */
...@@ -530,6 +562,14 @@ ipcp_bits_lattice::print (FILE *f) ...@@ -530,6 +562,14 @@ ipcp_bits_lattice::print (FILE *f)
} }
} }
/* Print value range lattice to F. */
void
ipcp_vr_lattice::print (FILE * f)
{
dump_value_range (f, &m_vr);
}
/* Print all ipcp_lattices of all functions to F. */ /* Print all ipcp_lattices of all functions to F. */
static void static void
...@@ -557,6 +597,9 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits) ...@@ -557,6 +597,9 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
plats->ctxlat.print (f, dump_sources, dump_benefits); plats->ctxlat.print (f, dump_sources, dump_benefits);
plats->alignment.print (f); plats->alignment.print (f);
plats->bits_lattice.print (f); plats->bits_lattice.print (f);
fprintf (f, " ");
plats->m_value_range.print (f);
fprintf (f, "\n");
if (plats->virt_call) if (plats->virt_call)
fprintf (f, " virt_call flag set\n"); fprintf (f, " virt_call flag set\n");
...@@ -908,6 +951,77 @@ ipcp_alignment_lattice::set_to_bottom () ...@@ -908,6 +951,77 @@ ipcp_alignment_lattice::set_to_bottom ()
return true; 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.m_vr);
}
/* Meet the current value of the lattice with value ranfge described by VR
lattice. */
bool
ipcp_vr_lattice::meet_with (const value_range *p_vr)
{
return meet_with_1 (p_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 = m_vr.min, max = m_vr.max;
value_range_type type = m_vr.type;
if (bottom_p ())
return false;
if (other_vr->type == VR_VARYING)
return set_to_bottom ();
vrp_meet (&m_vr, other_vr);
if (type != m_vr.type
|| min != m_vr.min
|| max != m_vr.max)
return true;
else
return false;
}
/* Return true if value range information in the lattice is yet unknown. */
bool
ipcp_vr_lattice::top_p () const
{
return m_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 m_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 (m_vr.type == VR_VARYING)
return false;
m_vr.type = VR_VARYING;
return true;
}
/* Meet the current value of the lattice with alignment described by NEW_ALIGN /* 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 and NEW_MISALIGN, assuming that we know the current value is neither TOP nor
BOTTOM. Return true if the value of lattice has changed. */ BOTTOM. Return true if the value of lattice has changed. */
...@@ -1141,6 +1255,7 @@ set_all_contains_variable (struct ipcp_param_lattices *plats) ...@@ -1141,6 +1255,7 @@ set_all_contains_variable (struct ipcp_param_lattices *plats)
ret |= set_agg_lats_contain_variable (plats); ret |= set_agg_lats_contain_variable (plats);
ret |= plats->alignment.set_to_bottom (); ret |= plats->alignment.set_to_bottom ();
ret |= plats->bits_lattice.set_to_bottom (); ret |= plats->bits_lattice.set_to_bottom ();
ret |= plats->m_value_range.set_to_bottom ();
return ret; return ret;
} }
...@@ -1211,6 +1326,12 @@ initialize_node_lattices (struct cgraph_node *node) ...@@ -1211,6 +1326,12 @@ initialize_node_lattices (struct cgraph_node *node)
disable = true; disable = true;
} }
for (i = 0; i < ipa_get_param_count (info) ; i++)
{
struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
plats->m_value_range.init ();
}
if (disable || variable) if (disable || variable)
{ {
for (i = 0; i < ipa_get_param_count (info) ; i++) for (i = 0; i < ipa_get_param_count (info) ; i++)
...@@ -1223,6 +1344,7 @@ initialize_node_lattices (struct cgraph_node *node) ...@@ -1223,6 +1344,7 @@ initialize_node_lattices (struct cgraph_node *node)
set_agg_lats_to_bottom (plats); set_agg_lats_to_bottom (plats);
plats->alignment.set_to_bottom (); plats->alignment.set_to_bottom ();
plats->bits_lattice.set_to_bottom (); plats->bits_lattice.set_to_bottom ();
plats->m_value_range.set_to_bottom ();
} }
else else
set_all_contains_variable (plats); set_all_contains_variable (plats);
...@@ -1913,6 +2035,50 @@ propagate_bits_accross_jump_function (cgraph_edge *cs, int idx, ipa_jump_func *j ...@@ -1913,6 +2035,50 @@ propagate_bits_accross_jump_function (cgraph_edge *cs, int idx, ipa_jump_func *j
return dest_lattice->set_to_bottom (); return dest_lattice->set_to_bottom ();
} }
/* Propagate value range across jump function JFUNC that is associated with
edge CS and update DEST_PLATS accordingly. */
static bool
propagate_vr_accross_jump_function (cgraph_edge *cs,
ipa_jump_func *jfunc,
struct ipcp_param_lattices *dest_plats)
{
struct ipcp_param_lattices *src_lats;
ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
if (dest_lat->bottom_p ())
return false;
if (jfunc->type == IPA_JF_PASS_THROUGH)
{
struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
if (dest_lat->bottom_p ())
return false;
int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
src_lats = ipa_get_parm_lattices (caller_info, src_idx);
if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
return dest_lat->meet_with (src_lats->m_value_range);
}
else if (jfunc->type == IPA_JF_CONST)
{
tree val = ipa_get_jf_constant (jfunc);
if (TREE_CODE (val) == INTEGER_CST)
{
jfunc->vr_known = true;
jfunc->m_vr.type = VR_RANGE;
jfunc->m_vr.min = val;
jfunc->m_vr.max = val;
return dest_lat->meet_with (&jfunc->m_vr);
}
}
if (jfunc->vr_known)
return dest_lat->meet_with (&jfunc->m_vr);
else
return dest_lat->set_to_bottom ();
}
/* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches /* If DEST_PLATS already has 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 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 other cases, return false). If there are no aggregate items, set
...@@ -2264,6 +2430,11 @@ propagate_constants_accross_call (struct cgraph_edge *cs) ...@@ -2264,6 +2430,11 @@ propagate_constants_accross_call (struct cgraph_edge *cs)
&dest_plats->bits_lattice); &dest_plats->bits_lattice);
ret |= propagate_aggs_accross_jump_function (cs, jump_func, ret |= propagate_aggs_accross_jump_function (cs, jump_func,
dest_plats); dest_plats);
if (opt_for_fn (callee->decl, flag_ipa_vrp))
ret |= propagate_vr_accross_jump_function (cs,
jump_func, dest_plats);
else
ret |= dest_plats->m_value_range.set_to_bottom ();
} }
} }
for (; i < parms_count; i++) for (; i < parms_count; i++)
...@@ -4974,6 +5145,76 @@ ipcp_store_bits_results (void) ...@@ -4974,6 +5145,76 @@ ipcp_store_bits_results (void)
} }
} }
} }
/* Look up all VR information that we have discovered and copy it over
to the transformation summary. */
static void
ipcp_store_vr_results (void)
{
cgraph_node *node;
FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
{
ipa_node_params *info = IPA_NODE_REF (node);
bool found_useful_result = false;
if (!opt_for_fn (node->decl, flag_ipa_vrp))
{
if (dump_file)
fprintf (dump_file, "Not considering %s for VR discovery "
"and propagate; -fipa-ipa-vrp: disabled.\n",
node->name ());
continue;
}
if (info->ipcp_orig_node)
info = IPA_NODE_REF (info->ipcp_orig_node);
unsigned count = ipa_get_param_count (info);
for (unsigned i = 0; i < count ; i++)
{
ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
if (!plats->m_value_range.bottom_p ()
&& !plats->m_value_range.top_p ())
{
found_useful_result = true;
break;
}
}
if (!found_useful_result)
continue;
ipcp_grow_transformations_if_necessary ();
ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
vec_safe_reserve_exact (ts->m_vr, count);
for (unsigned i = 0; i < count ; i++)
{
ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
ipa_vr vr;
if (!plats->m_value_range.bottom_p ()
&& !plats->m_value_range.top_p ())
{
vr.known = true;
vr.type = plats->m_value_range.m_vr.type;
vr.min = plats->m_value_range.m_vr.min;
vr.max = plats->m_value_range.m_vr.max;
}
else
{
static wide_int zero = integer_zero_node;
vr.known = false;
vr.type = VR_VARYING;
vr.min = zero;
vr.max = zero;
}
ts->m_vr->quick_push (vr);
}
}
}
/* The IPCP driver. */ /* The IPCP driver. */
static unsigned int static unsigned int
...@@ -5009,6 +5250,8 @@ ipcp_driver (void) ...@@ -5009,6 +5250,8 @@ ipcp_driver (void)
ipcp_store_alignment_results (); ipcp_store_alignment_results ();
/* Store results of bits propagation. */ /* Store results of bits propagation. */
ipcp_store_bits_results (); ipcp_store_bits_results ();
/* Store results of value range propagation. */
ipcp_store_vr_results ();
/* Free all IPCP structures. */ /* Free all IPCP structures. */
free_toporder_info (&topo); free_toporder_info (&topo);
......
...@@ -122,6 +122,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -122,6 +122,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-utils.h" #include "ipa-utils.h"
#include "gimple-fold.h" #include "gimple-fold.h"
#include "symbol-summary.h" #include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h" #include "ipa-prop.h"
#include "ipa-inline.h" #include "ipa-inline.h"
#include "demangle.h" #include "demangle.h"
......
...@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h" #include "cgraph.h"
#include "tree-cfg.h" #include "tree-cfg.h"
#include "symbol-summary.h" #include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h" #include "ipa-prop.h"
#include "ipa-inline.h" #include "ipa-inline.h"
#include "tree-inline.h" #include "tree-inline.h"
......
...@@ -108,6 +108,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -108,6 +108,7 @@ along with GCC; see the file COPYING3. If not see
#include "params.h" #include "params.h"
#include "profile.h" #include "profile.h"
#include "symbol-summary.h" #include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h" #include "ipa-prop.h"
#include "ipa-inline.h" #include "ipa-inline.h"
#include "ipa-utils.h" #include "ipa-utils.h"
......
...@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see
#include "value-prof.h" #include "value-prof.h"
#include "tree-inline.h" #include "tree-inline.h"
#include "symbol-summary.h" #include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h" #include "ipa-prop.h"
#include "ipa-inline.h" #include "ipa-inline.h"
......
...@@ -311,6 +311,19 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs) ...@@ -311,6 +311,19 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs)
} }
else else
fprintf (f, " Unknown bits\n"); fprintf (f, " Unknown bits\n");
if (jump_func->vr_known)
{
fprintf (f, " VR ");
fprintf (f, "%s[",
(jump_func->m_vr.type == VR_ANTI_RANGE) ? "~" : "");
print_decs (jump_func->m_vr.min, f);
fprintf (f, ", ");
print_decs (jump_func->m_vr.max, f);
fprintf (f, "]\n");
}
else
fprintf (f, " Unknown VR\n");
} }
} }
...@@ -391,6 +404,7 @@ ipa_set_jf_unknown (struct ipa_jump_func *jfunc) ...@@ -391,6 +404,7 @@ ipa_set_jf_unknown (struct ipa_jump_func *jfunc)
jfunc->type = IPA_JF_UNKNOWN; jfunc->type = IPA_JF_UNKNOWN;
jfunc->alignment.known = false; jfunc->alignment.known = false;
jfunc->bits.known = false; jfunc->bits.known = false;
jfunc->vr_known = false;
} }
/* Set JFUNC to be a copy of another jmp (to be used by jump function /* Set JFUNC to be a copy of another jmp (to be used by jump function
...@@ -1680,9 +1694,27 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, ...@@ -1680,9 +1694,27 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
} }
else else
gcc_assert (!jfunc->alignment.known); gcc_assert (!jfunc->alignment.known);
gcc_assert (!jfunc->vr_known);
} }
else else
gcc_assert (!jfunc->alignment.known); {
wide_int min, max;
value_range_type type;
if (TREE_CODE (arg) == SSA_NAME
&& param_type
&& (type = get_range_info (arg, &min, &max))
&& (type == VR_RANGE || type == VR_ANTI_RANGE)
&& (min.get_precision () <= TYPE_PRECISION (param_type)))
{
jfunc->vr_known = true;
jfunc->m_vr.type = type;
jfunc->m_vr.min = wide_int_to_tree (param_type, min);
jfunc->m_vr.max = wide_int_to_tree (param_type, max);
}
else
gcc_assert (!jfunc->vr_known);
gcc_assert (!jfunc->alignment.known);
}
if (INTEGRAL_TYPE_P (TREE_TYPE (arg)) if (INTEGRAL_TYPE_P (TREE_TYPE (arg))
&& (TREE_CODE (arg) == SSA_NAME || TREE_CODE (arg) == INTEGER_CST)) && (TREE_CODE (arg) == SSA_NAME || TREE_CODE (arg) == INTEGER_CST))
...@@ -3709,16 +3741,28 @@ ipa_node_params_t::duplicate(cgraph_node *src, cgraph_node *dst, ...@@ -3709,16 +3741,28 @@ ipa_node_params_t::duplicate(cgraph_node *src, cgraph_node *dst,
ipcp_transformation_summary *src_trans = ipcp_get_transformation_summary (src); ipcp_transformation_summary *src_trans = ipcp_get_transformation_summary (src);
if (src_trans && vec_safe_length (src_trans->alignments) > 0) if (src_trans)
{ {
ipcp_grow_transformations_if_necessary (); ipcp_grow_transformations_if_necessary ();
src_trans = ipcp_get_transformation_summary (src); src_trans = ipcp_get_transformation_summary (src);
const vec<ipa_alignment, va_gc> *src_alignments = src_trans->alignments; const vec<ipa_alignment, va_gc> *src_alignments = src_trans->alignments;
const vec<ipa_vr, va_gc> *src_vr = src_trans->m_vr;
vec<ipa_alignment, va_gc> *&dst_alignments vec<ipa_alignment, va_gc> *&dst_alignments
= ipcp_get_transformation_summary (dst)->alignments; = ipcp_get_transformation_summary (dst)->alignments;
vec_safe_reserve_exact (dst_alignments, src_alignments->length ()); vec<ipa_vr, va_gc> *&dst_vr
for (unsigned i = 0; i < src_alignments->length (); ++i) = ipcp_get_transformation_summary (dst)->m_vr;
dst_alignments->quick_push ((*src_alignments)[i]); if (vec_safe_length (src_trans->alignments) > 0)
{
vec_safe_reserve_exact (dst_alignments, src_alignments->length ());
for (unsigned i = 0; i < src_alignments->length (); ++i)
dst_alignments->quick_push ((*src_alignments)[i]);
}
if (vec_safe_length (src_trans->m_vr) > 0)
{
vec_safe_reserve_exact (dst_vr, src_vr->length ());
for (unsigned i = 0; i < src_vr->length (); ++i)
dst_vr->quick_push ((*src_vr)[i]);
}
} }
if (src_trans && vec_safe_length (src_trans->bits) > 0) if (src_trans && vec_safe_length (src_trans->bits) > 0)
...@@ -4660,6 +4704,15 @@ ipa_write_jump_function (struct output_block *ob, ...@@ -4660,6 +4704,15 @@ 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.value);
streamer_write_widest_int (ob, jump_func->bits.mask); 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)
{
streamer_write_enum (ob->main_stream, value_rang_type,
VR_LAST, jump_func->m_vr.type);
stream_write_tree (ob, jump_func->m_vr.min, true);
stream_write_tree (ob, jump_func->m_vr.max, true);
}
} }
/* Read in jump function JUMP_FUNC from IB. */ /* Read in jump function JUMP_FUNC from IB. */
...@@ -4747,6 +4800,20 @@ ipa_read_jump_function (struct lto_input_block *ib, ...@@ -4747,6 +4800,20 @@ ipa_read_jump_function (struct lto_input_block *ib,
} }
else else
jump_func->bits.known = false; jump_func->bits.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->m_vr.type = streamer_read_enum (ib,
value_range_type,
VR_LAST);
jump_func->m_vr.min = stream_read_tree (ib, data_in);
jump_func->m_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 /* Stream out parts of cgraph_indirect_call_info corresponding to CS that are
...@@ -5113,7 +5180,29 @@ write_ipcp_transformation_info (output_block *ob, cgraph_node *node) ...@@ -5113,7 +5180,29 @@ write_ipcp_transformation_info (output_block *ob, cgraph_node *node)
else else
streamer_write_uhwi (ob, 0); streamer_write_uhwi (ob, 0);
ts = ipcp_get_transformation_summary (node); if (ts && vec_safe_length (ts->m_vr) > 0)
{
count = ts->m_vr->length ();
streamer_write_uhwi (ob, count);
for (unsigned i = 0; i < count; ++i)
{
struct bitpack_d bp;
ipa_vr *parm_vr = &(*ts->m_vr)[i];
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);
streamer_write_wide_int (ob, parm_vr->min);
streamer_write_wide_int (ob, parm_vr->max);
}
}
}
else
streamer_write_uhwi (ob, 0);
if (ts && vec_safe_length (ts->bits) > 0) if (ts && vec_safe_length (ts->bits) > 0)
{ {
count = ts->bits->length (); count = ts->bits->length ();
...@@ -5191,6 +5280,30 @@ read_ipcp_transformation_info (lto_input_block *ib, cgraph_node *node, ...@@ -5191,6 +5280,30 @@ read_ipcp_transformation_info (lto_input_block *ib, cgraph_node *node,
if (count > 0) if (count > 0)
{ {
ipcp_grow_transformations_if_necessary (); ipcp_grow_transformations_if_necessary ();
ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
vec_safe_grow_cleared (ts->m_vr, count);
for (i = 0; i < count; i++)
{
ipa_vr *parm_vr;
parm_vr = &(*ts->m_vr)[i];
struct bitpack_d bp;
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 = streamer_read_wide_int (ib);
parm_vr->max = streamer_read_wide_int (ib);
}
}
}
count = streamer_read_uhwi (ib);
if (count > 0)
{
ipcp_grow_transformations_if_necessary ();
ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node); ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
vec_safe_grow_cleared (ts->bits, count); vec_safe_grow_cleared (ts->bits, count);
...@@ -5558,6 +5671,59 @@ ipcp_update_bits (struct cgraph_node *node) ...@@ -5558,6 +5671,59 @@ ipcp_update_bits (struct cgraph_node *node)
} }
} }
/* Update value range of formal parameters as described in
ipcp_transformation_summary. */
static void
ipcp_update_vr (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->m_vr) == 0)
return;
const vec<ipa_vr, va_gc> &vr = *ts->m_vr;
unsigned count = vr.length ();
for (unsigned i = 0; i < count; ++i, parm = next_parm)
{
if (node->clone.combined_args_to_skip
&& bitmap_bit_p (node->clone.combined_args_to_skip, i))
continue;
gcc_checking_assert (parm);
next_parm = DECL_CHAIN (parm);
tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->decl), parm);
if (!ddef || !is_gimple_reg (parm))
continue;
if (vr[i].known
&& INTEGRAL_TYPE_P (TREE_TYPE (ddef))
&& !POINTER_TYPE_P (TREE_TYPE (ddef))
&& (vr[i].type == VR_RANGE || vr[i].type == VR_ANTI_RANGE))
{
tree type = TREE_TYPE (ddef);
unsigned prec = TYPE_PRECISION (type);
if (dump_file)
{
fprintf (dump_file, "Setting value range of param %u ", i);
fprintf (dump_file, "%s[",
(vr[i].type == VR_ANTI_RANGE) ? "~" : "");
print_decs (vr[i].min, dump_file);
fprintf (dump_file, ", ");
print_decs (vr[i].max, dump_file);
fprintf (dump_file, "]\n");
}
set_range_info (ddef, vr[i].type,
wide_int_storage::from (vr[i].min, prec,
TYPE_SIGN (type)),
wide_int_storage::from (vr[i].max, prec,
TYPE_SIGN (type)));
}
}
}
/* IPCP transformation phase doing propagation of aggregate values. */ /* IPCP transformation phase doing propagation of aggregate values. */
unsigned int unsigned int
...@@ -5578,6 +5744,7 @@ ipcp_transform_function (struct cgraph_node *node) ...@@ -5578,6 +5744,7 @@ ipcp_transform_function (struct cgraph_node *node)
ipcp_update_alignments (node); ipcp_update_alignments (node);
ipcp_update_bits (node); ipcp_update_bits (node);
ipcp_update_vr (node);
aggval = ipa_get_agg_replacements_for_node (node); aggval = ipa_get_agg_replacements_for_node (node);
if (!aggval) if (!aggval)
return 0; return 0;
......
...@@ -167,6 +167,16 @@ struct GTY(()) ipa_bits ...@@ -167,6 +167,16 @@ struct GTY(()) ipa_bits
bool known; bool known;
}; };
/* 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;
wide_int min;
wide_int max;
};
/* A jump function for a callsite represents the values passed as actual /* A jump function for a callsite represents the values passed as actual
arguments of the callsite. See enum jump_func_type for the various arguments of the callsite. See enum jump_func_type for the various
types of jump functions supported. */ types of jump functions supported. */
...@@ -182,6 +192,10 @@ struct GTY (()) ipa_jump_func ...@@ -182,6 +192,10 @@ struct GTY (()) ipa_jump_func
/* Information about zero/non-zero bits. */ /* Information about zero/non-zero bits. */
struct ipa_bits bits; struct ipa_bits bits;
/* Information about value range. */
bool vr_known;
value_range m_vr;
enum jump_func_type type; enum jump_func_type type;
/* Represents a value of a jump function. pass_through is used only in jump /* Represents a value of a jump function. pass_through is used only in jump
function context. constant represents the actual constant in constant jump function context. constant represents the actual constant in constant jump
...@@ -521,6 +535,8 @@ struct GTY(()) ipcp_transformation_summary ...@@ -521,6 +535,8 @@ struct GTY(()) ipcp_transformation_summary
vec<ipa_alignment, va_gc> *alignments; vec<ipa_alignment, va_gc> *alignments;
/* Known bits information. */ /* Known bits information. */
vec<ipa_bits, va_gc> *bits; vec<ipa_bits, va_gc> *bits;
/* Value range information. */
vec<ipa_vr, va_gc> *m_vr;
}; };
void ipa_set_node_agg_value_chain (struct cgraph_node *node, void ipa_set_node_agg_value_chain (struct cgraph_node *node,
......
...@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
#include "splay-tree.h" #include "splay-tree.h"
#include "ipa-utils.h" #include "ipa-utils.h"
#include "symbol-summary.h" #include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h" #include "ipa-prop.h"
#include "ipa-inline.h" #include "ipa-inline.h"
......
...@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-iterator.h" #include "tree-iterator.h"
#include "ipa-utils.h" #include "ipa-utils.h"
#include "symbol-summary.h" #include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h" #include "ipa-prop.h"
#include "ipa-inline.h" #include "ipa-inline.h"
#include "dbgcnt.h" #include "dbgcnt.h"
......
2016-09-21 Kugan Vivekanandarajah <kuganv@linaro.org>
* lto-partition.c: Include tree-vrp.h.
* lto.c: Likewise.
2016-09-20 Richard Biener <rguenther@suse.de> 2016-09-20 Richard Biener <rguenther@suse.de>
* lto.c (lto_main): Call early_finish with "<artificial>" as * lto.c (lto_main): Call early_finish with "<artificial>" as
......
...@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "lto-streamer.h" #include "lto-streamer.h"
#include "params.h" #include "params.h"
#include "symbol-summary.h" #include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h" #include "ipa-prop.h"
#include "ipa-inline.h" #include "ipa-inline.h"
#include "lto-partition.h" #include "lto-partition.h"
......
...@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see
#include "toplev.h" #include "toplev.h"
#include "stor-layout.h" #include "stor-layout.h"
#include "symbol-summary.h" #include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h" #include "ipa-prop.h"
#include "common.h" #include "common.h"
#include "debug.h" #include "debug.h"
......
...@@ -506,6 +506,7 @@ static const struct default_options default_options_table[] = ...@@ -506,6 +506,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_2_PLUS, OPT_fipa_cp, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fipa_cp, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fipa_cp_alignment, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fipa_cp_alignment, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fipa_bit_cp, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fipa_bit_cp, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fipa_vrp, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fdevirtualize_speculatively, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fdevirtualize_speculatively, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fipa_sra, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fipa_sra, NULL, 1 },
......
2016-09-21 Kugan Vivekanandarajah <kuganv@linaro.org> 2016-09-21 Kugan Vivekanandarajah <kuganv@linaro.org>
* g++.dg/ipa/pure-const-3.C: Add -fno-ipa-vrp. Else constant arguments
will be optimized away.
* gcc.dg/ipa/vrp1.c: New test.
* gcc.dg/ipa/vrp2.c: New test.
* gcc.dg/ipa/vrp3.c: New test.
2016-09-21 Kugan Vivekanandarajah <kuganv@linaro.org>
* g++.dg/tree-ssa/pr31146-2.C: Run with -fno-tree-evrp as evrp also * g++.dg/tree-ssa/pr31146-2.C: Run with -fno-tree-evrp as evrp also
does the same transformation. does the same transformation.
* g++.dg/warn/pr33738.C: XFAIL as optimization now happens in ccp. * g++.dg/warn/pr33738.C: XFAIL as optimization now happens in ccp.
......
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */ /* { dg-options "-O2 -fno-ipa-vrp -fdump-tree-optimized" } */
int *ptr; int *ptr;
static int barvar; static int barvar;
static int b(int a); static int b(int a);
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-ipa-cp-details" } */
static __attribute__((noinline, noclone))
int foo (int i)
{
if (i < 5)
__builtin_abort ();
return 0;
}
static __attribute__((noinline, noclone))
int bar (int j)
{
if (j > 8)
return foo (j + 2);
else if (j > 2)
return foo (j + 3);
return 0;
}
int main ()
{
for (unsigned int i =0; i < 1000; ++i)
bar (i);
return 0;
}
/* { dg-final { scan-ipa-dump "Setting value range of param 0 \\\[6," "cp" } } */
/* { dg-final { scan-ipa-dump "Setting value range of param 0 \\\[0, 999\\\]" "cp" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-ipa-cp-details" } */
static __attribute__((noinline, noclone))
int foo (int i)
{
if (i < 4)
__builtin_abort ();
return 0;
}
static __attribute__((noinline, noclone))
int bar (int j)
{
if (j > 8)
return foo (j + 2);
else if (j > 2)
return foo (j + 3);
return 0;
}
int main ()
{
foo (100);
for (unsigned int i = 0; i < 12; ++i)
{
bar (i);
}
foo (4);
return 0;
}
/* { dg-final { scan-ipa-dump "Setting value range of param 0 \\\[4," "cp" } } */
/* { dg-final { scan-ipa-dump "Setting value range of param 0 \\\[0, 11\\\]" "cp" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-ipa-cp-details" } */
volatile int cond;
static __attribute__((noinline, noclone))
int foo (int i)
{
if (i < 5)
__builtin_abort ();
return 0;
}
static __attribute__((noinline, noclone))
int bar (int j)
{
if (cond)
foo (j);
return 0;
}
int main ()
{
for (unsigned int i = 0; i < 10; ++i)
bar (i);
return 0;
}
/* { dg-final { scan-ipa-dump-times "Setting value range of param 0 \\\[0, 9\\\]" 2 "cp" } } */
...@@ -71,6 +71,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -71,6 +71,7 @@ along with GCC; see the file COPYING3. If not see
#include "dwarf2out.h" #include "dwarf2out.h"
#include "ipa-reference.h" #include "ipa-reference.h"
#include "symbol-summary.h" #include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h" #include "ipa-prop.h"
#include "gcse.h" #include "gcse.h"
#include "tree-chkp.h" #include "tree-chkp.h"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment