Commit c853f62a by Jakub Jelinek Committed by Jakub Jelinek

gimple-pretty-print.c (dump_ssaname_info): Print newline also in case of VR_VARYING.

	* gimple-pretty-print.c (dump_ssaname_info): Print newline also
	in case of VR_VARYING.  Print get_nonzero_bits if not all ones.
	* tree-ssanames.h (struct range_info_def): Add nonzero_bits field.
	(set_nonzero_bits, get_nonzero_bits): New prototypes.
	* tree-ssa-ccp.c (get_default_value): Use get_range_info to see if
	a default def isn't partially constant.
	(ccp_finalize): If after IPA, set_range_info if integral SSA_NAME
	is known to be partially zero.
	(evaluate_stmt): If we'd return otherwise VARYING, use get_range_info
	to see if a default def isn't partially constant.
	* tree-ssanames.c (set_range_info): Initialize nonzero_bits upon
	creation of a range, if VR_RANGE, try to improve nonzero_bits from
	the range.
	(set_nonzero_bits, get_nonzero_bits): New functions.

	* g++.dg/warn/pr33738.C (main): Initialize a2 again to make sure
	we warn about it already during VRP1 pass.

From-SVN: r204256
parent d8202b84
2013-10-31 Jakub Jelinek <jakub@redhat.com> 2013-10-31 Jakub Jelinek <jakub@redhat.com>
* gimple-pretty-print.c (dump_ssaname_info): Print newline also
in case of VR_VARYING. Print get_nonzero_bits if not all ones.
* tree-ssanames.h (struct range_info_def): Add nonzero_bits field.
(set_nonzero_bits, get_nonzero_bits): New prototypes.
* tree-ssa-ccp.c (get_default_value): Use get_range_info to see if
a default def isn't partially constant.
(ccp_finalize): If after IPA, set_range_info if integral SSA_NAME
is known to be partially zero.
(evaluate_stmt): If we'd return otherwise VARYING, use get_range_info
to see if a default def isn't partially constant.
* tree-ssanames.c (set_range_info): Initialize nonzero_bits upon
creation of a range, if VR_RANGE, try to improve nonzero_bits from
the range.
(set_nonzero_bits, get_nonzero_bits): New functions.
* tree-cfg.c (assert_unreachable_fallthru_edge_p): New function. * tree-cfg.c (assert_unreachable_fallthru_edge_p): New function.
* tree-cfg.h (assert_unreachable_fallthru_edge_p): New prototype. * tree-cfg.h (assert_unreachable_fallthru_edge_p): New prototype.
* tree-vrp.c (all_imm_uses_in_stmt_or_feed_cond): New function. * tree-vrp.c (all_imm_uses_in_stmt_or_feed_cond): New function.
...@@ -1737,7 +1737,7 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc) ...@@ -1737,7 +1737,7 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc)
if (!POINTER_TYPE_P (TREE_TYPE (node)) if (!POINTER_TYPE_P (TREE_TYPE (node))
&& SSA_NAME_RANGE_INFO (node)) && SSA_NAME_RANGE_INFO (node))
{ {
double_int min, max; double_int min, max, nonzero_bits;
value_range_type range_type = get_range_info (node, &min, &max); value_range_type range_type = get_range_info (node, &min, &max);
if (range_type == VR_VARYING) if (range_type == VR_VARYING)
...@@ -1750,8 +1750,20 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc) ...@@ -1750,8 +1750,20 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc)
pp_printf (buffer, ", "); pp_printf (buffer, ", ");
pp_double_int (buffer, max, TYPE_UNSIGNED (TREE_TYPE (node))); pp_double_int (buffer, max, TYPE_UNSIGNED (TREE_TYPE (node)));
pp_printf (buffer, "]"); pp_printf (buffer, "]");
newline_and_indent (buffer, spc);
} }
nonzero_bits = get_nonzero_bits (node);
if (nonzero_bits != double_int_minus_one
&& (nonzero_bits
!= double_int::mask (TYPE_PRECISION (TREE_TYPE (node)))))
{
pp_string (buffer, " NONZERO ");
sprintf (pp_buffer (buffer)->digit_buffer,
HOST_WIDE_INT_PRINT_DOUBLE_HEX,
(unsigned HOST_WIDE_INT) nonzero_bits.high,
nonzero_bits.low);
pp_string (buffer, pp_buffer (buffer)->digit_buffer);
}
newline_and_indent (buffer, spc);
} }
} }
......
2013-10-31 Jakub Jelinek <jakub@redhat.com>
* g++.dg/warn/pr33738.C (main): Initialize a2 again to make sure
we warn about it already during VRP1 pass.
2013-10-31 Martin Jambor <mjambor@suse.cz> 2013-10-31 Martin Jambor <mjambor@suse.cz>
PR rtl-optimization/58934 PR rtl-optimization/58934
......
...@@ -18,6 +18,7 @@ int main() { ...@@ -18,6 +18,7 @@ int main() {
if (a2 == -1) { // { dg-warning "always false due" } if (a2 == -1) { // { dg-warning "always false due" }
link_error (); link_error ();
} }
a2 = static_cast<Alpha>(GetM1());
if (-1 == a2) { // { dg-warning "always false due" } if (-1 == a2) { // { dg-warning "always false due" }
link_error (); link_error ();
} }
......
...@@ -260,6 +260,19 @@ get_default_value (tree var) ...@@ -260,6 +260,19 @@ get_default_value (tree var)
{ {
val.lattice_val = VARYING; val.lattice_val = VARYING;
val.mask = double_int_minus_one; val.mask = double_int_minus_one;
if (flag_tree_bit_ccp)
{
double_int nonzero_bits = get_nonzero_bits (var);
double_int mask
= double_int::mask (TYPE_PRECISION (TREE_TYPE (var)));
if (nonzero_bits != double_int_minus_one && nonzero_bits != mask)
{
val.lattice_val = CONSTANT;
val.value = build_zero_cst (TREE_TYPE (var));
/* CCP wants the bits above precision set. */
val.mask = nonzero_bits | ~mask;
}
}
} }
} }
else if (is_gimple_assign (stmt)) else if (is_gimple_assign (stmt))
...@@ -828,7 +841,8 @@ ccp_finalize (void) ...@@ -828,7 +841,8 @@ ccp_finalize (void)
do_dbg_cnt (); do_dbg_cnt ();
/* Derive alignment and misalignment information from partially /* Derive alignment and misalignment information from partially
constant pointers in the lattice. */ constant pointers in the lattice or nonzero bits from partially
constant integers. */
for (i = 1; i < num_ssa_names; ++i) for (i = 1; i < num_ssa_names; ++i)
{ {
tree name = ssa_name (i); tree name = ssa_name (i);
...@@ -836,7 +850,11 @@ ccp_finalize (void) ...@@ -836,7 +850,11 @@ ccp_finalize (void)
unsigned int tem, align; unsigned int tem, align;
if (!name if (!name
|| !POINTER_TYPE_P (TREE_TYPE (name))) || (!POINTER_TYPE_P (TREE_TYPE (name))
&& (!INTEGRAL_TYPE_P (TREE_TYPE (name))
/* Don't record nonzero bits before IPA to avoid
using too much memory. */
|| first_pass_instance)))
continue; continue;
val = get_value (name); val = get_value (name);
...@@ -844,13 +862,24 @@ ccp_finalize (void) ...@@ -844,13 +862,24 @@ ccp_finalize (void)
|| TREE_CODE (val->value) != INTEGER_CST) || TREE_CODE (val->value) != INTEGER_CST)
continue; continue;
/* Trailing constant bits specify the alignment, trailing value if (POINTER_TYPE_P (TREE_TYPE (name)))
bits the misalignment. */ {
tem = val->mask.low; /* Trailing mask bits specify the alignment, trailing value
align = (tem & -tem); bits the misalignment. */
if (align > 1) tem = val->mask.low;
set_ptr_info_alignment (get_ptr_info (name), align, align = (tem & -tem);
TREE_INT_CST_LOW (val->value) & (align - 1)); if (align > 1)
set_ptr_info_alignment (get_ptr_info (name), align,
(TREE_INT_CST_LOW (val->value)
& (align - 1)));
}
else
{
double_int nonzero_bits = val->mask;
nonzero_bits = nonzero_bits | tree_to_double_int (val->value);
nonzero_bits &= get_nonzero_bits (name);
set_nonzero_bits (name, nonzero_bits);
}
} }
/* Perform substitutions based on the known constant values. */ /* Perform substitutions based on the known constant values. */
...@@ -1671,6 +1700,39 @@ evaluate_stmt (gimple stmt) ...@@ -1671,6 +1700,39 @@ evaluate_stmt (gimple stmt)
is_constant = (val.lattice_val == CONSTANT); is_constant = (val.lattice_val == CONSTANT);
} }
if (flag_tree_bit_ccp
&& ((is_constant && TREE_CODE (val.value) == INTEGER_CST)
|| (!is_constant && likelyvalue != UNDEFINED))
&& gimple_get_lhs (stmt)
&& TREE_CODE (gimple_get_lhs (stmt)) == SSA_NAME)
{
tree lhs = gimple_get_lhs (stmt);
double_int nonzero_bits = get_nonzero_bits (lhs);
double_int mask = double_int::mask (TYPE_PRECISION (TREE_TYPE (lhs)));
if (nonzero_bits != double_int_minus_one && nonzero_bits != mask)
{
if (!is_constant)
{
val.lattice_val = CONSTANT;
val.value = build_zero_cst (TREE_TYPE (lhs));
/* CCP wants the bits above precision set. */
val.mask = nonzero_bits | ~mask;
is_constant = true;
}
else
{
double_int valv = tree_to_double_int (val.value);
if (!(valv & ~nonzero_bits & mask).is_zero ())
val.value = double_int_to_tree (TREE_TYPE (lhs),
valv & nonzero_bits);
if (nonzero_bits.is_zero ())
val.mask = double_int_zero;
else
val.mask = val.mask & (nonzero_bits | ~mask);
}
}
}
if (!is_constant) if (!is_constant)
{ {
/* The statement produced a nonconstant value. If the statement /* The statement produced a nonconstant value. If the statement
......
...@@ -189,11 +189,30 @@ set_range_info (tree name, double_int min, double_int max) ...@@ -189,11 +189,30 @@ set_range_info (tree name, double_int min, double_int max)
{ {
ri = ggc_alloc_cleared_range_info_def (); ri = ggc_alloc_cleared_range_info_def ();
SSA_NAME_RANGE_INFO (name) = ri; SSA_NAME_RANGE_INFO (name) = ri;
ri->nonzero_bits = double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
} }
/* Set the values. */ /* Set the values. */
ri->min = min; ri->min = min;
ri->max = max; ri->max = max;
/* If it is a range, try to improve nonzero_bits from the min/max. */
if (min.cmp (max, TYPE_UNSIGNED (TREE_TYPE (name))) != 1)
{
int prec = TYPE_PRECISION (TREE_TYPE (name));
double_int xorv;
min = min.zext (prec);
max = max.zext (prec);
xorv = min ^ max;
if (xorv.high)
xorv = double_int::mask (2 * HOST_BITS_PER_WIDE_INT
- clz_hwi (xorv.high));
else if (xorv.low)
xorv = double_int::mask (HOST_BITS_PER_WIDE_INT
- clz_hwi (xorv.low));
ri->nonzero_bits = ri->nonzero_bits & (min | xorv);
}
} }
...@@ -233,6 +252,47 @@ get_range_info (tree name, double_int *min, double_int *max) ...@@ -233,6 +252,47 @@ get_range_info (tree name, double_int *min, double_int *max)
return range_type; return range_type;
} }
/* Change non-zero bits bitmask of NAME. */
void
set_nonzero_bits (tree name, double_int mask)
{
gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
if (SSA_NAME_RANGE_INFO (name) == NULL)
set_range_info (name,
tree_to_double_int (TYPE_MIN_VALUE (TREE_TYPE (name))),
tree_to_double_int (TYPE_MAX_VALUE (TREE_TYPE (name))));
range_info_def *ri = SSA_NAME_RANGE_INFO (name);
ri->nonzero_bits
= mask & double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
}
/* Return a double_int with potentially non-zero bits in SSA_NAME
NAME, or double_int_minus_one if unknown. */
double_int
get_nonzero_bits (tree name)
{
if (POINTER_TYPE_P (TREE_TYPE (name)))
{
struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
if (pi && pi->align)
{
double_int al = double_int::from_uhwi (pi->align - 1);
return ((double_int::mask (TYPE_PRECISION (TREE_TYPE (name))) & ~al)
| double_int::from_uhwi (pi->misalign));
}
return double_int_minus_one;
}
range_info_def *ri = SSA_NAME_RANGE_INFO (name);
if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name)))
> 2 * HOST_BITS_PER_WIDE_INT))
return double_int_minus_one;
return ri->nonzero_bits;
}
/* We no longer need the SSA_NAME expression VAR, release it so that /* We no longer need the SSA_NAME expression VAR, release it so that
it may be reused. it may be reused.
......
...@@ -52,6 +52,8 @@ struct GTY (()) range_info_def { ...@@ -52,6 +52,8 @@ struct GTY (()) range_info_def {
double_int min; double_int min;
/* Maximum for value range. */ /* Maximum for value range. */
double_int max; double_int max;
/* Non-zero bits - bits not set are guaranteed to be always zero. */
double_int nonzero_bits;
}; };
...@@ -68,10 +70,11 @@ struct GTY (()) range_info_def { ...@@ -68,10 +70,11 @@ struct GTY (()) range_info_def {
enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING }; enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING };
/* Sets the value range to SSA. */ /* Sets the value range to SSA. */
extern void set_range_info (tree ssa, double_int min, double_int max); extern void set_range_info (tree, double_int, double_int);
/* Gets the value range from SSA. */ /* Gets the value range from SSA. */
extern enum value_range_type get_range_info (tree name, double_int *min, extern enum value_range_type get_range_info (tree, double_int *, double_int *);
double_int *max); extern void set_nonzero_bits (tree, double_int);
extern double_int get_nonzero_bits (tree);
extern void init_ssanames (struct function *, int); extern void init_ssanames (struct function *, int);
extern void fini_ssanames (void); extern void fini_ssanames (void);
extern void ssanames_print_statistics (void); extern void ssanames_print_statistics (void);
......
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