summaryrefslogtreecommitdiffstats
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/gimple-pretty-print.c16
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/warn/pr33738.C1
-rw-r--r--gcc/tree-ssa-ccp.c80
-rw-r--r--gcc/tree-ssanames.c60
-rw-r--r--gcc/tree-ssanames.h9
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);
OpenPOWER on IntegriCloud