The testcase from the PR at -O2 shows

    ((_277 == 2) AND (_79 == 0))
    OR ((NOT (_277 == 0)) AND (NOT (_277 > 2)) AND (NOT (_277 == 2)) AND (_79 
== 0))
    OR ((NOT (pretmp_300 == 255)) AND (_277 == 0) AND (NOT (_277 > 2)) AND (NOT 
(_277 == 2)) AND (_79 == 0))

which we fail to simplify.  The following patch makes us simplify
the relations on _277, producing

    ((_79 == 0) AND (_277 == 2))
    OR ((_79 == 0) AND (_277 <= 1) AND (NOT (_277 == 0)))
    OR ((_79 == 0) AND (_277 == 0) AND (NOT (pretmp_300 == 255)))

which might be an incremental step to resolve a bogus uninit
diagnostic at -O2.  The patch uses maybe_fold_and_comparison for this.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

        PR tree-optimization/107919
        * gimple-predicate-analysis.cc (simplify_1): Rename to ...
        (simplify_1a): .. this.
        (simplify_1b): New.
        (predicate::simplify): Call both simplify_1a and simplify_1b.
---
 gcc/gimple-predicate-analysis.cc | 83 +++++++++++++++++++++++++++++---
 1 file changed, 76 insertions(+), 7 deletions(-)

diff --git a/gcc/gimple-predicate-analysis.cc b/gcc/gimple-predicate-analysis.cc
index 23be4b69bab..ce2e1d10e43 100644
--- a/gcc/gimple-predicate-analysis.cc
+++ b/gcc/gimple-predicate-analysis.cc
@@ -42,6 +42,7 @@
 #include "value-query.h"
 #include "cfganal.h"
 #include "tree-eh.h"
+#include "gimple-fold.h"
 
 #include "gimple-predicate-analysis.h"
 
@@ -1174,7 +1175,9 @@ compute_control_dep_chain (basic_block dom_bb, 
const_basic_block dep_bb,
 
 /* Implemented simplifications:
 
-   1) ((x IOR y) != 0) AND (x != 0) is equivalent to (x != 0);
+   1a) ((x IOR y) != 0) AND (x != 0) is equivalent to (x != 0);
+   1b) [!](X rel y) AND [!](X rel y') where y == y' or both constant
+       can possibly be simplified
    2) (X AND Y) OR (!X AND Y) is equivalent to Y;
    3) X OR (!X AND Y) is equivalent to (X OR Y);
    4) ((x IAND y) != 0) || (x != 0 AND y != 0)) is equivalent to
@@ -1184,11 +1187,11 @@ compute_control_dep_chain (basic_block dom_bb, 
const_basic_block dep_bb,
 
    PREDS is the predicate chains, and N is the number of chains.  */
 
-/* Implement rule 1 above.  PREDS is the AND predicate to simplify
+/* Implement rule 1a above.  PREDS is the AND predicate to simplify
    in place.  */
 
 static void
-simplify_1 (pred_chain &chain)
+simplify_1a (pred_chain &chain)
 {
   bool simplified = false;
   pred_chain s_chain = vNULL;
@@ -1245,6 +1248,66 @@ simplify_1 (pred_chain &chain)
   chain = s_chain;
 }
 
+/* Implement rule 1b above.  PREDS is the AND predicate to simplify
+   in place.  Returns true if CHAIN simplifies to true.  */
+
+static bool
+simplify_1b (pred_chain &chain)
+{
+  for (unsigned i = 0; i < chain.length (); i++)
+    {
+      pred_info &a_pred = chain[i];
+
+      for (unsigned j = i + 1; j < chain.length (); ++j)
+       {
+         pred_info &b_pred = chain[j];
+
+         if (!operand_equal_p (a_pred.pred_lhs, b_pred.pred_lhs)
+             || (!operand_equal_p (a_pred.pred_rhs, b_pred.pred_rhs)
+                 && !(CONSTANT_CLASS_P (a_pred.pred_rhs)
+                      && CONSTANT_CLASS_P (b_pred.pred_rhs))))
+           continue;
+
+         tree_code a_code = a_pred.cond_code;
+         if (a_pred.invert)
+           a_code = invert_tree_comparison (a_code, false);
+         tree_code b_code = b_pred.cond_code;
+         if (b_pred.invert)
+           b_code = invert_tree_comparison (b_code, false);
+         /* Try to combine X a_code Y && X b_code Y'.  */
+         tree comb = maybe_fold_and_comparisons (boolean_type_node,
+                                                 a_code,
+                                                 a_pred.pred_lhs,
+                                                 a_pred.pred_rhs,
+                                                 b_code,
+                                                 b_pred.pred_lhs,
+                                                 b_pred.pred_rhs, NULL);
+         if (!comb)
+           ;
+         else if (integer_zerop (comb))
+           return true;
+         else if (integer_truep (comb))
+           {
+             chain.ordered_remove (j);
+             chain.ordered_remove (i);
+             i--;
+             break;
+           }
+         else if (COMPARISON_CLASS_P (comb)
+                  && operand_equal_p (a_pred.pred_lhs, TREE_OPERAND (comb, 0)))
+           {
+             chain.ordered_remove (j);
+             a_pred.cond_code = TREE_CODE (comb);
+             a_pred.pred_rhs = TREE_OPERAND (comb, 1);
+             a_pred.invert = false;
+             j--;
+           }
+       }
+    }
+
+  return false;
+}
+
 /* Implements rule 2 for the OR predicate PREDS:
 
    2) (X AND Y) OR (!X AND Y) is equivalent to Y.  */
@@ -1435,11 +1498,17 @@ predicate::simplify (gimple *use_or_def, bool is_use)
       dump (dump_file, use_or_def, is_use ? "[USE]:\n" : "[DEF]:\n");
     }
 
-  unsigned n = m_preds.length ();
-  for (unsigned i = 0; i < n; i++)
-    ::simplify_1 (m_preds[i]);
+  for (unsigned i = 0; i < m_preds.length (); i++)
+    {
+      ::simplify_1a (m_preds[i]);
+      if (::simplify_1b (m_preds[i]))
+       {
+         m_preds.ordered_remove (i);
+         i--;
+       }
+    }
 
-  if (n < 2)
+  if (m_preds.length () < 2)
     return;
 
   bool changed;
-- 
2.35.3

Reply via email to