diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/gimple-pretty-print.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/pr33738.C | 1 | ||||
-rw-r--r-- | gcc/tree-ssa-ccp.c | 80 | ||||
-rw-r--r-- | gcc/tree-ssanames.c | 60 | ||||
-rw-r--r-- | gcc/tree-ssanames.h | 9 |
7 files changed, 172 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e46ad1529a3..0e072c4725c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,20 @@ 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.h (assert_unreachable_fallthru_edge_p): New prototype. * tree-vrp.c (all_imm_uses_in_stmt_or_feed_cond): New function. diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 248dfea01af..6842213199a 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -1737,7 +1737,7 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc) if (!POINTER_TYPE_P (TREE_TYPE (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); if (range_type == VR_VARYING) @@ -1750,8 +1750,20 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc) pp_printf (buffer, ", "); pp_double_int (buffer, max, TYPE_UNSIGNED (TREE_TYPE (node))); 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); } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f663aca60eb..769209d795a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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> PR rtl-optimization/58934 diff --git a/gcc/testsuite/g++.dg/warn/pr33738.C b/gcc/testsuite/g++.dg/warn/pr33738.C index e84fece13f6..60ee0b48412 100644 --- a/gcc/testsuite/g++.dg/warn/pr33738.C +++ b/gcc/testsuite/g++.dg/warn/pr33738.C @@ -18,6 +18,7 @@ int main() { if (a2 == -1) { // { dg-warning "always false due" } link_error (); } + a2 = static_cast<Alpha>(GetM1()); if (-1 == a2) { // { dg-warning "always false due" } link_error (); } diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index d30bd8b2493..5b6c0dbea28 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -260,6 +260,19 @@ get_default_value (tree var) { val.lattice_val = VARYING; 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)) @@ -828,7 +841,8 @@ ccp_finalize (void) do_dbg_cnt (); /* 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) { tree name = ssa_name (i); @@ -836,7 +850,11 @@ ccp_finalize (void) unsigned int tem, align; 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; val = get_value (name); @@ -844,13 +862,24 @@ ccp_finalize (void) || TREE_CODE (val->value) != INTEGER_CST) continue; - /* Trailing constant bits specify the alignment, trailing value - bits the misalignment. */ - tem = val->mask.low; - align = (tem & -tem); - if (align > 1) - set_ptr_info_alignment (get_ptr_info (name), align, - TREE_INT_CST_LOW (val->value) & (align - 1)); + if (POINTER_TYPE_P (TREE_TYPE (name))) + { + /* Trailing mask bits specify the alignment, trailing value + bits the misalignment. */ + tem = val->mask.low; + align = (tem & -tem); + 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. */ @@ -1671,6 +1700,39 @@ evaluate_stmt (gimple stmt) 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) { /* The statement produced a nonconstant value. If the statement diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 435cdc78965..00bd436c008 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -189,11 +189,30 @@ set_range_info (tree name, double_int min, double_int max) { ri = ggc_alloc_cleared_range_info_def (); SSA_NAME_RANGE_INFO (name) = ri; + ri->nonzero_bits = double_int::mask (TYPE_PRECISION (TREE_TYPE (name))); } /* Set the values. */ ri->min = min; 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; } +/* 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 it may be reused. diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h index f80e0b2ce33..1d02d966fd7 100644 --- a/gcc/tree-ssanames.h +++ b/gcc/tree-ssanames.h @@ -52,6 +52,8 @@ struct GTY (()) range_info_def { double_int min; /* Maximum for value range. */ 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 }; /* 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. */ -extern enum value_range_type get_range_info (tree name, double_int *min, - double_int *max); +extern enum value_range_type get_range_info (tree, double_int *, double_int *); +extern void set_nonzero_bits (tree, double_int); +extern double_int get_nonzero_bits (tree); extern void init_ssanames (struct function *, int); extern void fini_ssanames (void); extern void ssanames_print_statistics (void); |