From 137b26412f681bb1f8b3eb52b8f9efd79e6bda2a Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 5 Nov 2024 12:52:51 -0500
Subject: [PATCH] Add details output for assume processing.

The Assume pass simply produces results, with no indication of how it
arrived as the results it gets.  Add some output to the details listing.

The only functional change is when gori is used to calculate a range
more than once (ie, multiple uses), we now load the merged range rather
than just using the last calculated one.

	* tree-assume.cc (assume_query::assume_query): Add debug output.
	(assume_query::update_parms): Likewise.
	(assume_query::calculate_phi): Likewise.
	(assume_query::calculate_op): Likewise.  Also pick up any
	merged path values.
	(assume_query::calculate_stmt): Likewise.
---
 gcc/tree-assume.cc | 134 ++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 115 insertions(+), 19 deletions(-)

diff --git a/gcc/tree-assume.cc b/gcc/tree-assume.cc
index dd279f58179..5c6e0832028 100644
--- a/gcc/tree-assume.cc
+++ b/gcc/tree-assume.cc
@@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
+#define INCLUDE_MEMORY
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -33,6 +34,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-iterator.h"
 #include "gimple-range.h"
 #include "tree-dfa.h"
+#include "tree-cfg.h"
+#include "gimple-pretty-print.h"
 
 // An assume query utilizes the current range query to implelemtn the assume
 // keyword.
@@ -145,7 +148,7 @@ assume_query::assume_query (function *f, bitmap p) : m_parm_list (p),
     process_stmts (def, lhs_range);
 
   if (dump_file)
-    fprintf (dump_file, "Assumptions :\n--------------\n");
+    fprintf (dump_file, "\n\nAssumptions :\n--------------\n");
 
   // Now export any interesting values that were found.
   bitmap_iterator bi;
@@ -159,6 +162,12 @@ assume_query::assume_query (function *f, bitmap p) : m_parm_list (p),
       if (m_parms.get_range (assume_range, name) && !assume_range.varying_p ())
 	set_range_info (name, assume_range);
     }
+
+  if (dump_file)
+   {
+     fputc ('\n', dump_file);
+     gimple_dump_cfg (dump_file, dump_flags & ~TDF_DETAILS);
+   }
 }
 
 // This function Will update all the current value of interesting parameters.
@@ -172,6 +181,9 @@ assume_query::assume_query (function *f, bitmap p) : m_parm_list (p),
 void
 assume_query::update_parms (fur_source &src)
 {
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "\nupdate parameters\n");
+
   // Merge any parameter values.
   bitmap_iterator bi;
   unsigned x;
@@ -180,40 +192,85 @@ assume_query::update_parms (fur_source &src)
       tree name = ssa_name (x);
       tree type = TREE_TYPE (name);
 
-      // Find a valu efrom calculations.
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	{
+	  fprintf (dump_file, "PARAMETER ");
+	  print_generic_expr (dump_file, name, TDF_SLIM);
+	}
       value_range glob_range (type);
-      if (!m_path.get_range (glob_range, name)
-	  && !src.get_operand (glob_range, name))
+      // Find a value from calculations.
+      // There will be a value in m_path if GORI calculated an operand value.
+      if (m_path.get_range (glob_range, name))
+	{
+	  if (dump_file && (dump_flags & TDF_DETAILS))
+	    {
+	      fprintf (dump_file, "\n  Calculated path range:");
+	      glob_range.dump (dump_file);
+	    }
+	}
+      // Otherwise, let ranger determine the range at the SRC location.
+      else if (src.get_operand (glob_range, name))
+	{
+	  if (dump_file && (dump_flags & TDF_DETAILS))
+	    {
+	      fprintf (dump_file, "\n  Ranger Computes path range:");
+	      glob_range.dump (dump_file);
+	    }
+	}
+      else
 	glob_range.set_varying (type);
 
-      // Find any current value of parm, and combine them.
+      // Find any current saved value of parm, and combine them.
       value_range parm_range (type);
       if (m_parms.get_range (parm_range, name))
 	glob_range.union_ (parm_range);
 
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	{
+	  fprintf (dump_file, "\n  Combine with previous range:");
+	  parm_range.dump (dump_file);
+	  fputc ('\n', dump_file);
+	  print_generic_expr (dump_file, name, TDF_SLIM);
+	  fprintf (dump_file, " = ");
+	  glob_range.dump (dump_file);
+	  fputc ('\n', dump_file);
+	}
       // Set this new value.
       m_parms.set_range (name, glob_range);
     }
   // Now reset the path values for the next path.
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "---------------------\n");
   m_path.clear ();
 }
 
 
 // Evaluate PHI statement, using the provided LHS range.
-// Only process edge that are both taken and returns the LHS of the PHI.
+// Only process edge that are taken and return the LHS of the PHI.
 
 void
 assume_query::calculate_phi (gphi *phi, vrange &lhs_range)
 {
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "Processing PHI feeding return value:\n");
+      print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
+    }
   for (unsigned x= 0; x < gimple_phi_num_args (phi); x++)
     {
       tree arg = gimple_phi_arg_def (phi, x);
       value_range arg_range (TREE_TYPE (arg));
       edge e = gimple_phi_arg_edge (phi, x);
       value_range edge_range (TREE_TYPE (arg));
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	{
+	  fprintf (dump_file, "\nArgument %d (bb%d->bb%d): ", x, e->src->index,
+		   e->dest->index);
+	  print_generic_expr (dump_file, arg, TDF_SLIM);
+	  fputc ('\n', dump_file);
+	}
       // If we can't get an edge range, be conservative and assume the
       // edge can be taken.
-      // NOte this can be either an ssa_name or a constant.
       if (get_range_query (m_func)->range_on_edge (edge_range, e, arg))
 	{
 	  if (gimple_range_ssa_p (arg))
@@ -224,15 +281,25 @@ assume_query::calculate_phi (gphi *phi, vrange &lhs_range)
 	      // An SSA_NAME arg will start with the LHS value.
 	      // Check the range of ARG on the edge leading here.  If that range
 	      // cannot be any value from the LHS of the PHI, then this branch
-	      // will not  be taken to return the LHS value and can be ignored.
+	      // will not be taken to return the LHS value and can be ignored.
 	      arg_range.intersect (edge_range);
 	      if (arg_range.undefined_p ())
-		continue;
+		{
+		  if (dump_file && (dump_flags & TDF_DETAILS))
+		    {
+		      fprintf (dump_file, "  IGNORE edge :  LHS range :");
+		      lhs_range.dump (dump_file);
+		      fprintf (dump_file, " Edge produces : ");
+		      edge_range.dump (dump_file);
+		      fputc ('\n', dump_file);
+		    }
+		  continue;
+		}
 
 	      // If the def is in the immediate preceeding block, process it
 	      // with GORI to determine what values can produce this
-	      // argument value.  Otherwise there is more flow, so just query
-	      // the edge for parm ranges and be conservative.
+	      // argument value.  Otherwise there is more CFG flow, so query
+	      // the edge for parm ranges.  This is conservative.
 	      gimple *def_stmt = SSA_NAME_DEF_STMT (arg);
 	      if (def_stmt && gimple_get_lhs (def_stmt) == arg
 		  && gimple_bb (def_stmt) == e->src)
@@ -240,19 +307,27 @@ assume_query::calculate_phi (gphi *phi, vrange &lhs_range)
 		  process_stmts (def_stmt, arg_range);
 		  continue;
 		}
-	      // Fall through to process the edge.
+	      // Fall through to process the parameter values on the edge.
 	    }
 	  else
 	    {
 	      // If this is a constant value that differs from LHS, this
 	      // edge cannot be taken and we can ignore it. Otherwise fall
-	      // thorugh and process the edge.
+	      // thorugh and process the parameters on the edge.
 	      edge_range.intersect (lhs_range);
 	      if (edge_range.undefined_p ())
-		continue;
+		{
+		  if (dump_file && (dump_flags & TDF_DETAILS))
+		    fprintf (dump_file, "  IGNORE : const edge not taken\n");
+		  continue;
+		}
+	      if (dump_file && (dump_flags & TDF_DETAILS))
+		fprintf (dump_file,
+			 "  Const edge executed, compute incoming ranges.\n");
+
 	    }
 	}
-      // If this point is reached the edge needs processing.
+      // The parameters on the edge now need calculating.
       fur_edge src (e, get_range_query (m_func));
       update_parms (src);
     }
@@ -271,18 +346,31 @@ assume_query::calculate_op (tree op, gimple *s, vrange &lhs, fur_source &src)
       src.gori ()->compute_operand_range (op_range, s, lhs, op, src)
       && !op_range.varying_p ())
     {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	{
+	  fprintf (dump_file, "  Operand ");
+	  print_generic_expr (dump_file, op, TDF_SLIM);
+	  fprintf (dump_file, " calculated as ");
+	  op_range.dump (dump_file);
+	}
       // Set the global range, merging if there is already a range.
       m_path.merge_range (op, op_range);
+      m_path.get_range (op_range, op);
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	{
+	  fprintf (dump_file, "  New path range :");
+	  op_range.dump (dump_file);
+	  fputc ('\n', dump_file);
+	}
       gimple *def_stmt = SSA_NAME_DEF_STMT (op);
-      // Terminate if the patway leads to a different block as we
-      // are not analyzing flow.
+      // Terminate if the pathway leads to a different block as we
+      // are not dealing with flow. Ranger will make those queries.
       if (def_stmt && gimple_get_lhs (def_stmt) == op
 	  && gimple_bb (def_stmt) == bb)
 	calculate_stmt (def_stmt, op_range, src);
     }
 }
 
-
 // Evaluate statement S which produces range LHS_RANGE.  Use GORI to
 // determine what values the operands can have to produce the LHS,
 // and set these in the M_PATH table.
@@ -290,6 +378,13 @@ assume_query::calculate_op (tree op, gimple *s, vrange &lhs, fur_source &src)
 void
 assume_query::calculate_stmt (gimple *s, vrange &lhs_range, fur_source &src)
 {
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "  Processing stmt with LHS = ");
+      lhs_range.dump (dump_file);
+      fprintf (dump_file, " : ");
+      print_gimple_stmt (dump_file, s, 0, TDF_SLIM);
+    }
   gimple_range_op_handler handler (s);
   if (handler)
     {
@@ -333,7 +428,8 @@ public:
       // Invoke the assume_query to detemine what values these parameters
       // have when the function returns TRUE, and set the globals value of
       // those parameters in this function based on that.  This will later be
-      // utilized by ranger when prcessing the builtin_assumer function.
+      // utilized by ranger when processing builtin IFN_ASSUME function calls.
+      // See gimple-range-infer.cc::check_assume_func ().
       auto_bitmap decls;
       for (tree arg = DECL_ARGUMENTS (fun->decl); arg; arg = DECL_CHAIN (arg))
 	{
-- 
2.45.0

