From 53d5bfcd64e186f8b68d4e5bb0c2d3b9184acbcd Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 16 Jun 2020 15:44:43 -0400
Subject: [PATCH 231/237] FIXME: WIP on adding iterated binops

---
 gcc/analyzer/analyzer.h             |  2 ++
 gcc/analyzer/constraint-manager2.cc | 33 ++++++++++++++++++++----
 gcc/analyzer/constraint-manager2.h  |  4 +--
 gcc/analyzer/region-model2.cc       | 39 ++++++++++++++++++++++++++---
 gcc/analyzer/region-model2.h        | 15 ++++++++---
 5 files changed, 79 insertions(+), 14 deletions(-)

diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
index 5944d4127dd..b2d0a9c7e49 100644
--- a/gcc/analyzer/analyzer.h
+++ b/gcc/analyzer/analyzer.h
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_ANALYZER_H
 #define GCC_ANALYZER_ANALYZER_H
 
+#define ITERATED_BINOPS 0
+
 class graphviz_out;
 
 namespace ana {
diff --git a/gcc/analyzer/constraint-manager2.cc b/gcc/analyzer/constraint-manager2.cc
index d6708c191ba..bdc4d9819b5 100644
--- a/gcc/analyzer/constraint-manager2.cc
+++ b/gcc/analyzer/constraint-manager2.cc
@@ -1357,13 +1357,35 @@ class merger2_fact_visitor : public fact2_visitor
 {
 public:
   merger2_fact_visitor (constraint_manager2 *cm_b,
-			constraint_manager2 *out)
-  : m_cm_b (cm_b), m_out (out)
+			constraint_manager2 *out,
+			const model2_merger &merger)
+  : m_cm_b (cm_b), m_out (out), m_merger (merger)
   {}
 
   void on_fact (const svalue2 *lhs, enum tree_code code, const svalue2 *rhs)
     FINAL OVERRIDE
   {
+    /* If we merged (M BINOP X) with M
+       and A has fact (M RELOP Y),
+       then we should instead have fact (M RELOP (Y BINOP X)).
+       For example, if we merged (M + 1) with M
+       and we have fact M <= 255 then we should instead have M <= 256.  */
+    // TODO: we need to fix eval_condition for this to work.
+#if ITERATED_BINOPS
+    unsigned i;
+    const binop_svalue2 *binop;
+    FOR_EACH_VEC_ELT (m_merger.m_iterated_binops, i, binop)
+      {
+	if (binop->get_arg0 () == lhs)
+	  {
+	    region_model2_manager *mgr = m_merger.get_manager ();
+	    rhs = mgr->get_or_create_binop (rhs->get_type (),
+					    binop->get_op (),
+					    rhs, binop->get_arg1 ());
+	  }
+      }
+#endif
+
     /* Special-case for widening.  */
     /* FIXME: should only do this if LHS isn't mentioned anywhere in
        m_cm_b's model, rather than just in m_cb_b?  */
@@ -1387,6 +1409,7 @@ public:
 private:
   constraint_manager2 *m_cm_b;
   constraint_manager2 *m_out;
+  const model2_merger &m_merger;
 };
 
 // FIXME
@@ -1399,8 +1422,8 @@ private:
 void
 constraint_manager2::merge (const constraint_manager2 &cm_a,
 			    const constraint_manager2 &cm_b,
-			    constraint_manager2 *out/*,
-			    const model_merger &merger*/)
+			    constraint_manager2 *out,
+			    const model2_merger &merger)
 {
   /* FIXME: work with a copy, since eval_condition can mutate a cm.  */
   constraint_manager2 copy_cm_a (cm_a);
@@ -1410,7 +1433,7 @@ constraint_manager2::merge (const constraint_manager2 &cm_a,
      The easiest way to do this seems to be to enumerate all of the facts
      in cm_a, see which are also true in cm_b,
      and add those to *OUT.  */
-  merger2_fact_visitor v (&copy_cm_b, out);
+  merger2_fact_visitor v (&copy_cm_b, out, merger);
   copy_cm_a.for_each_fact (&v);
 
   /* FIXME and the other way around, since things could be implicit in one
diff --git a/gcc/analyzer/constraint-manager2.h b/gcc/analyzer/constraint-manager2.h
index 7c1fec5db6e..5425de08ab9 100644
--- a/gcc/analyzer/constraint-manager2.h
+++ b/gcc/analyzer/constraint-manager2.h
@@ -222,8 +222,8 @@ public:
 
   static void merge (const constraint_manager2 &cm_a,
 		     const constraint_manager2 &cm_b,
-		     constraint_manager2 *out/*,
-		     const model_merger &merger*/);
+		     constraint_manager2 *out,
+		     const model2_merger &merger);
 
   void for_each_fact (fact2_visitor *) const;
 
diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc
index d7736301829..9c7ae379b2a 100644
--- a/gcc/analyzer/region-model2.cc
+++ b/gcc/analyzer/region-model2.cc
@@ -295,9 +295,18 @@ svalue2::can_merge_p (const svalue2 *other,
 	/* Merger of : (Widen() BINOP X)
 	   and       : Widen()
 	   to        : Widen()
-	   e.g. merge of Widen(0, 1) + 1 and Widen(0, 1) to Widen(0, 1).  */
+	   e.g. merge of Widen(0, 1) + 1 and Widen(0, 1) to Widen(0, 1).
+	   However, we want to update constraints for this case, since we're
+	   considering another iteration.
+	   Presumably we also want to ensure that it converges; we don't want
+	   a descending chain of constraints.  */
 	if (other == widen_arg0)
-	  return widen_arg0;
+	  {
+#if ITERATED_BINOPS
+	    merger->add_iterating_widening_binop_thing (binop_sval);
+#endif
+	    return widen_arg0;
+	  }
       }
 #endif
 
@@ -7708,7 +7717,8 @@ region_model2::can_merge_with_p (const region_model2 &other_model,
   /* Merge constraints.  */
   constraint_manager2::merge (*m_constraints2,
 			      *other_model.m_constraints2,
-			      out_model->m_constraints2);
+			      out_model->m_constraints2,
+			      m);
 
   return true;
 }
@@ -8031,6 +8041,19 @@ model2_merger::dump_to_pp (pretty_printer *pp, bool simple) const
   pp_newline (pp);
   m_merged_model->dump_to_pp (pp, simple, true);
   pp_newline (pp);
+
+#if ITERATED_BINOPS
+  pp_string (pp, "iterated binops:");
+  pp_newline (pp);
+  unsigned i;
+  const binop_svalue2 *binop;
+  FOR_EACH_VEC_ELT (m_iterated_binops, i, binop)
+    {
+      pp_string (pp, "  ");
+      binop->dump_to_pp (pp, simple);
+      pp_newline (pp);
+    }
+#endif
 }
 
 /* Dump a multiline representation of this merger to FILE.  */
@@ -8054,6 +8077,16 @@ model2_merger::dump (bool simple) const
   dump (stderr, simple);
 }
 
+/* FIXME.  */
+#if ITERATED_BINOPS
+void
+model2_merger::add_iterating_widening_binop_thing (const binop_svalue2 *binop_sval)
+{
+  // TODO!
+  m_iterated_binops.safe_push (binop_sval);
+}
+#endif
+
 /* struct svalue2_id_merger_mapping.  */
 
 #if 0
diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h
index d5bcbe58b09..4a1f79cf007 100644
--- a/gcc/analyzer/region-model2.h
+++ b/gcc/analyzer/region-model2.h
@@ -2530,6 +2530,14 @@ struct model2_merger
   void dump (FILE *fp, bool simple) const;
   void dump (bool simple) const;
 
+#if ITERATED_BINOPS
+  void add_iterating_widening_binop_thing (const binop_svalue2 *binop_sval);
+#endif
+  region_model2_manager *get_manager () const
+  {
+    return m_model_a->get_manager ();
+  }
+
 #if 0
   template <typename Subclass>
   Subclass *get_region2_a (region2_id rid_a) const
@@ -2560,10 +2568,9 @@ struct model2_merger
   const region_model2 *m_model_b;
   const program_point &m_point;
   region_model2 *m_merged_model;
-#if 0
-  one_way_region2_id_map m_map_region2s_from_a_to_m;
-  one_way_region2_id_map m_map_region2s_from_b_to_m;
-  svalue2_id_merger_mapping *m_sid_mapping;
+#if ITERATED_BINOPS
+  /* FIXME: comment for this.  */
+  auto_vec<const binop_svalue2 *> m_iterated_binops;
 #endif
 };
 
-- 
2.26.2

