mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
d8202b848c
commit
c853f62af3
|
|
@ -1,5 +1,20 @@
|
||||||
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)
|
||||||
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)
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
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() {
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|| 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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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 {
|
||||||
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 {
|
||||||
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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue