+2007-03-08 Ian Lance Taylor <iant@google.com>
+
+ * tree-vrp.c: Include "intl.h".
+ (usable_range_p): New static function.
+ (compare_values_warnv): Don't test TYPE_OVERFLOW_UNDEFINED for
+ overflowed values, juts set *strict_overflow_p.
+ (compare_values): Only return -2 if one of the operands is not a
+ constant.
+ (compare_ranges): Call usable_range_p.
+ (compare_range_with_value): Likewise.
+ (vrp_evaluate_conditional_warnv): Rename from
+ vrp_evaluate_conditional. Make static. Change all callers.
+ (vrp_evaluate_conditional): New function.
+ (simplify_div_or_mod_using_ranges): Issue warning about reliance
+ on signed overflow.
+ (simplify_abs_using_ranges): Likewise.
+ (simplify_stmt_for_jump_threading): Add within_stmt parameter.
+ * tree-ssa-dom.c (simplify_stmt_for_jump_threading): Add
+ within_stmt parameter.
+ * tree-ssa-propagate.c (fold_predicate_in): Update call to
+ vrp_evaluate_conditional.
+ * tree-ssa-threadedge.c
+ (record_temporary_equivalences_from_stmts_at_dest): Change
+ simplify parameter to take a second tree parameter.
+ (simplify_control_stmt_condition): Likewise.
+ (thread_across_edge): Likewise.
+ * tree-flow.h (vrp_evaluate_conditional): Update declaration.
+ (thread_across_edge): Likewise.
+ * gcc/Makefile.in (tree-vrp.o): Depend upon intl.h.
+
2007-03-08 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.h (TARGET_SAHF): New define.
static tree
record_temporary_equivalences_from_stmts_at_dest (edge e,
VEC(tree, heap) **stack,
- tree (*simplify) (tree))
+ tree (*simplify) (tree,
+ tree))
{
block_stmt_iterator bsi;
tree stmt = NULL;
cached_lhs = fold (pre_fold_expr);
if (TREE_CODE (cached_lhs) != SSA_NAME
&& !is_gimple_min_invariant (cached_lhs))
- cached_lhs = (*simplify) (stmt);
+ cached_lhs = (*simplify) (stmt, stmt);
}
/* Restore the statement's original uses/defs. */
simplify_control_stmt_condition (edge e,
tree stmt,
tree dummy_cond,
- tree (*simplify) (tree),
+ tree (*simplify) (tree, tree),
bool handle_dominating_asserts)
{
tree cond, cached_lhs;
/* If we have not simplified the condition down to an invariant,
then use the pass specific callback to simplify the condition. */
if (! is_gimple_min_invariant (cached_lhs))
- cached_lhs = (*simplify) (dummy_cond);
+ cached_lhs = (*simplify) (dummy_cond, stmt);
}
/* We can have conditionals which just test the state of a variable
/* If we haven't simplified to an invariant yet, then use the
pass specific callback to try and simplify it further. */
if (cached_lhs && ! is_gimple_min_invariant (cached_lhs))
- cached_lhs = (*simplify) (stmt);
+ cached_lhs = (*simplify) (stmt, stmt);
}
else
cached_lhs = NULL;
edge e,
bool handle_dominating_asserts,
VEC(tree, heap) **stack,
- tree (*simplify) (tree))
+ tree (*simplify) (tree, tree))
{
tree stmt;
#include "timevar.h"
#include "diagnostic.h"
#include "toplev.h"
+#include "intl.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
#include "tree-ssa-propagate.h"
static int compare_values (tree val1, tree val2);
static int compare_values_warnv (tree val1, tree val2, bool *);
static void vrp_meet (value_range_t *, value_range_t *);
+static tree vrp_evaluate_conditional_warnv (tree, bool, bool *);
/* Location information for ASSERT_EXPRs. Each instance of this
structure describes an ASSERT_EXPR for an SSA name. Since a single
|| is_overflow_infinity (vr->max)));
}
+/* Return false if we can not make a valid comparison based on VR;
+ this will be the case if it uses an overflow infinity and overflow
+ is not undefined (i.e., -fno-strict-overflow is in effect).
+ Otherwise return true, and set *STRICT_OVERFLOW_P to true if VR
+ uses an overflow infinity. */
+
+static bool
+usable_range_p (value_range_t *vr, bool *strict_overflow_p)
+{
+ gcc_assert (vr->type == VR_RANGE);
+ if (is_overflow_infinity (vr->min))
+ {
+ *strict_overflow_p = true;
+ if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (vr->min)))
+ return false;
+ }
+ if (is_overflow_infinity (vr->max))
+ {
+ *strict_overflow_p = true;
+ if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (vr->max)))
+ return false;
+ }
+ return true;
+}
+
+
/* Like tree_expr_nonnegative_warnv_p, but this function uses value
ranges obtained so far. */
infinities. */
if (TREE_OVERFLOW (val1) || TREE_OVERFLOW (val2))
{
- if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (val1)))
- return -2;
-
+ if (strict_overflow_p != NULL)
+ *strict_overflow_p = true;
if (is_negative_overflow_infinity (val1))
return is_negative_overflow_infinity (val2) ? 0 : -1;
else if (is_negative_overflow_infinity (val2))
}
}
-/* Compare values like compare_values_warnv, but treat comparisons
- which rely on undefined overflow as incomparable. */
+/* Compare values like compare_values_warnv, but treat comparisons of
+ nonconstants which rely on undefined overflow as incomparable. */
static int
compare_values (tree val1, tree val2)
sop = false;
ret = compare_values_warnv (val1, val2, &sop);
- if (sop)
+ if (sop
+ && (!is_gimple_min_invariant (val1) || !is_gimple_min_invariant (val2)))
ret = -2;
return ret;
}
extract_range_from_comparison (value_range_t *vr, tree expr)
{
bool sop = false;
- tree val = vrp_evaluate_conditional (expr, false, &sop);
+ tree val = vrp_evaluate_conditional_warnv (expr, false, &sop);
/* A disadvantage of using a special infinity as an overflow
representation is that we lose the ability to record overflow
return NULL_TREE;
}
+ if (!usable_range_p (vr0, strict_overflow_p)
+ || !usable_range_p (vr1, strict_overflow_p))
+ return NULL_TREE;
+
/* Simplify processing. If COMP is GT_EXPR or GE_EXPR, switch the
operands around and change the comparison code. */
if (comp == GT_EXPR || comp == GE_EXPR)
return NULL_TREE;
}
+ if (!usable_range_p (vr, strict_overflow_p))
+ return NULL_TREE;
+
if (comp == EQ_EXPR)
{
/* EQ_EXPR may only be computed if VR represents exactly
Set *STRICT_OVERFLOW_P to indicate whether we relied on an overflow
infinity to produce the result. */
-tree
-vrp_evaluate_conditional (tree cond, bool use_equiv_p, bool *strict_overflow_p)
+static tree
+vrp_evaluate_conditional_warnv (tree cond, bool use_equiv_p,
+ bool *strict_overflow_p)
{
gcc_assert (TREE_CODE (cond) == SSA_NAME
|| TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison);
return NULL_TREE;
}
+/* Given COND within STMT, try to simplify it based on value range
+ information. Return NULL if the conditional can not be evaluated.
+ The ranges of all the names equivalent with the operands in COND
+ will be used when trying to compute the value. If the result is
+ based on undefined signed overflow, issue a warning if
+ appropriate. */
+
+tree
+vrp_evaluate_conditional (tree cond, tree stmt)
+{
+ bool sop;
+ tree ret;
+
+ sop = false;
+ ret = vrp_evaluate_conditional_warnv (cond, true, &sop);
+
+ if (ret && sop)
+ {
+ enum warn_strict_overflow_code wc;
+ const char* warnmsg;
+
+ if (is_gimple_min_invariant (ret))
+ {
+ wc = WARN_STRICT_OVERFLOW_CONDITIONAL;
+ warnmsg = G_("assuming signed overflow does not occur when "
+ "simplifying conditional to constant");
+ }
+ else
+ {
+ wc = WARN_STRICT_OVERFLOW_COMPARISON;
+ warnmsg = G_("assuming signed overflow does not occur when "
+ "simplifying conditional");
+ }
+
+ if (issue_strict_overflow_warning (wc))
+ {
+ location_t locus;
+
+ if (!EXPR_HAS_LOCATION (stmt))
+ locus = input_location;
+ else
+ locus = EXPR_LOCATION (stmt);
+ warning (OPT_Wstrict_overflow, "%H%s", &locus, warnmsg);
+ }
+ }
+
+ return ret;
+}
+
/* Visit conditional statement STMT. If we can determine which edge
will be taken out of STMT's basic block, record it in
MICO, TRAMP3D and SPEC2000) showed that doing this results in
4 more predicates folded in SPEC. */
sop = false;
- val = vrp_evaluate_conditional (cond, false, &sop);
+ val = vrp_evaluate_conditional_warnv (cond, false, &sop);
if (val)
{
if (!sop)
bool sop = false;
val = compare_range_with_value (GT_EXPR, vr, integer_zero_node, &sop);
+
+ if (val
+ && sop
+ && integer_onep (val)
+ && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
+ {
+ location_t locus;
+
+ if (!EXPR_HAS_LOCATION (stmt))
+ locus = input_location;
+ else
+ locus = EXPR_LOCATION (stmt);
+ warning (OPT_Wstrict_overflow,
+ ("%Hassuming signed overflow does not occur when "
+ "simplifying / or %% to >> or &"),
+ &locus);
+ }
}
if (val && integer_onep (val))
{
tree t;
+ if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
+ {
+ location_t locus;
+
+ if (!EXPR_HAS_LOCATION (stmt))
+ locus = input_location;
+ else
+ locus = EXPR_LOCATION (stmt);
+ warning (OPT_Wstrict_overflow,
+ ("%Hassuming signed overflow does not occur when "
+ "simplifying abs (X) to X or -X"),
+ &locus);
+ }
+
if (integer_onep (val))
t = build1 (NEGATE_EXPR, TREE_TYPE (op), op);
else
restored. */
static VEC(tree,heap) *stack;
-/* A trivial wrapper so that we can present the generic jump
- threading code with a simple API for simplifying statements. */
+/* A trivial wrapper so that we can present the generic jump threading
+ code with a simple API for simplifying statements. STMT is the
+ statement we want to simplify, WITHIN_STMT provides the location
+ for any overflow warnings. */
+
static tree
-simplify_stmt_for_jump_threading (tree stmt)
+simplify_stmt_for_jump_threading (tree stmt, tree within_stmt)
{
- bool sop;
-
/* We only use VRP information to simplify conditionals. This is
overly conservative, but it's unclear if doing more would be
worth the compile time cost. */
if (TREE_CODE (stmt) != COND_EXPR)
return NULL;
- sop = false;
- return vrp_evaluate_conditional (COND_EXPR_COND (stmt), true, &sop);
+ return vrp_evaluate_conditional (COND_EXPR_COND (stmt), within_stmt);
}
/* Blocks which have more than one predecessor and more than