aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gimple-range-gori.cc25
-rw-r--r--gcc/testsuite/gcc.dg/pr97567-2.c24
2 files changed, 37 insertions, 12 deletions
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 54385ba..af3609e 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -730,10 +730,10 @@ gori_compute::logical_combine (irange &r, enum tree_code code,
if (lhs.zero_p ())
{
// An OR operation will only take the FALSE path if both
- // operands are false, so either [20, 255] or [0, 5] is the
- // union: [0,5][20,255].
+ // operands are false simlulateously, which means they should
+ // be intersected. !(x || y) == !x && !y
r = op1.false_range;
- r.union_ (op2.false_range);
+ r.intersect (op2.false_range);
}
else
{
@@ -804,9 +804,12 @@ gori_compute::compute_logical_operands_in_chain (tf_range &range,
tree name,
tree op, bool op_in_chain)
{
- if (!op_in_chain)
+ gimple *src_stmt = gimple_range_ssa_p (op) ? SSA_NAME_DEF_STMT (op) : NULL;
+ basic_block bb = gimple_bb (stmt);
+ if (!op_in_chain || (src_stmt != NULL && bb != gimple_bb (src_stmt)))
{
- // If op is not in chain, use its known value.
+ // If op is not in the def chain, or defined in this block,
+ // use its known value on entry to the block.
expr_range_in_bb (range.true_range, name, gimple_bb (stmt));
range.false_range = range.true_range;
return;
@@ -814,14 +817,12 @@ gori_compute::compute_logical_operands_in_chain (tf_range &range,
if (optimize_logical_operands (range, stmt, lhs, name, op))
return;
- // Calulate ranges for true and false on both sides, since the false
+ // Calculate ranges for true and false on both sides, since the false
// path is not always a simple inversion of the true side.
- if (!compute_operand_range (range.true_range, SSA_NAME_DEF_STMT (op),
- m_bool_one, name))
- expr_range_in_bb (range.true_range, name, gimple_bb (stmt));
- if (!compute_operand_range (range.false_range, SSA_NAME_DEF_STMT (op),
- m_bool_zero, name))
- expr_range_in_bb (range.false_range, name, gimple_bb (stmt));
+ if (!compute_operand_range (range.true_range, src_stmt, m_bool_one, name))
+ expr_range_in_bb (range.true_range, name, bb);
+ if (!compute_operand_range (range.false_range, src_stmt, m_bool_zero, name))
+ expr_range_in_bb (range.false_range, name, bb);
}
// Given a logical STMT, calculate true and false for each potential
diff --git a/gcc/testsuite/gcc.dg/pr97567-2.c b/gcc/testsuite/gcc.dg/pr97567-2.c
new file mode 100644
index 0000000..dee31c6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97567-2.c
@@ -0,0 +1,24 @@
+/* { dg-do compile} */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+char a[2];
+
+extern int x;
+
+void foo(void);
+
+signed char g (signed char min, signed char max)
+{
+ signed char i = x;
+ return i < min || max < i ? min : i;
+}
+
+void gg (void)
+{
+ signed char t = g (0, 9);
+ /* Ranger should be able to remove the call to foo (). */
+ if (t > 9 || t < 0)
+ foo ();
+}
+
+/* { dg-final { scan-tree-dump-not "foo" "evrp" } } */