Fix logical_combine OR operation. Again.
authorAndrew MacLeod <amacleod@redhat.com>
Tue, 10 Nov 2020 00:38:22 +0000 (19:38 -0500)
committerAndrew MacLeod <amacleod@redhat.com>
Tue, 10 Nov 2020 00:41:05 +0000 (19:41 -0500)
The original fix was incorrect and results in loss of opportunities.
Revert the original fix. When processing logical chains, do not
follow chains outside of the current basic block.  Use the import
value instead.

gcc/
PR tree-optimization/97567
* gimple-range-gori.cc: (gori_compute::logical_combine): False
OR operations should intersect the 2 results.
(gori_compute::compute_logical_operands_in_chain): If def chains
are outside the current basic block, don't follow them.
gcc/testsuite/
* gcc.dg/pr97567-2.c: New.

gcc/gimple-range-gori.cc
gcc/testsuite/gcc.dg/pr97567-2.c [new file with mode: 0644]

index 54385baa62919d3e845a58d64a6e2610fd3f795a..af3609e414e89ba383cf05804700f31da869beba 100644 (file)
@@ -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 (file)
index 0000000..dee31c6
--- /dev/null
@@ -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" } }  */