/* Gimple range inference implementation.
   Copyright (C) 2022-2025 Free Software Foundation, Inc.
   Contributed by Andrew MacLeod <amacleod@redhat.com>.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

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/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "insn-codes.h"
#include "tree.h"
#include "gimple.h"
#include "ssa.h"
#include "gimple-pretty-print.h"
#include "gimple-range.h"
#include "value-range-storage.h"
#include "tree-cfg.h"
#include "target.h"
#include "attribs.h"
#include "gimple-iterator.h"
#include "gimple-walk.h"
#include "cfganal.h"
#include "tree-dfa.h"

// Create the global oracle.

infer_range_oracle infer_oracle;

// This class is merely an accessor which is granted internals to
// gimple_infer_range such that non_null_loadstore as a static callback can
// call the protected add_nonzero ().
// Static functions ccannot be friends, so we do it through a class wrapper.

class non_null_wrapper
{
public:
  inline non_null_wrapper (gimple_infer_range *infer) : m_infer (infer) { }
  inline void add_nonzero (tree name) { m_infer->add_nonzero (name); }
  inline void add_range (tree t, vrange &r) { m_infer->add_range (t, r); }
private:
  gimple_infer_range *m_infer;
};

// Adapted from infer_nonnull_range_by_dereference and check_loadstore
// to process nonnull ssa_name OP in S.  DATA contains a pointer to a
// stmt range inference instance.

static bool
non_null_loadstore (gimple *, tree op, tree, void *data)
{
  if (TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
    {
      /* Some address spaces may legitimately dereference zero.  */
      addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (op));
      if (!targetm.addr_space.zero_address_valid (as))
	{
	  non_null_wrapper wrapper ((gimple_infer_range *)data);
	  wrapper.add_nonzero (TREE_OPERAND (op, 0));
	}
    }
  return false;
}

// Process an ASSUME call to see if there are any inferred ranges available.

void
gimple_infer_range::check_assume_func (gcall *call)
{
  tree arg;
  unsigned i;
  tree assume_id = TREE_OPERAND (gimple_call_arg (call, 0), 0);
  if (!assume_id)
    return;
  struct function *fun = DECL_STRUCT_FUNCTION (assume_id);
  if (!fun)
    return;
  // Loop over arguments, matching them to the assume parameters.
  for (arg = DECL_ARGUMENTS (assume_id), i = 1;
       arg && i < gimple_call_num_args (call);
       i++, arg = DECL_CHAIN (arg))
    {
      tree op = gimple_call_arg (call, i);
      tree type = TREE_TYPE (op);
      if (gimple_range_ssa_p (op) && value_range::supports_type_p (type))
	{
	  tree default_def = ssa_default_def (fun, arg);
	  if (!default_def || type != TREE_TYPE (default_def))
	    continue;
	  // Query the global range of the default def in the assume function.
	  value_range assume_range (type);
	  gimple_range_global (assume_range, default_def, fun);
	  // If there is a non-varying result, add it as an inferred range.
	  if (!assume_range.varying_p ())
	    {
	      add_range (op, assume_range);
	      if (dump_file)
		{
		  print_generic_expr (dump_file, assume_id, TDF_SLIM);
		  fprintf (dump_file, " assume inferred range of ");
		  print_generic_expr (dump_file, op, TDF_SLIM);
		  fprintf (dump_file, " (param ");
		  print_generic_expr (dump_file, arg, TDF_SLIM);
		  fprintf (dump_file, ") = ");
		  assume_range.dump (dump_file);
		  fputc ('\n', dump_file);
		}
	    }
	}
    }
}

// Add NAME and RANGE to the range inference summary.

void
gimple_infer_range::add_range (tree name, vrange &range)
{
  // Do not add an inferred range if it is VARYING.
  if (range.varying_p ())
    return;
  m_names[num_args] = name;
  m_ranges[num_args] = range;
  if (num_args < size_limit - 1)
    num_args++;
}

// Add a nonzero range for NAME to the range inference summary.

void
gimple_infer_range::add_nonzero (tree name)
{
  if (!gimple_range_ssa_p (name))
    return;
  prange nz;
  nz.set_nonzero (TREE_TYPE (name));
  add_range (name, nz);
}

// Process S for range inference and fill in the summary list.
// This is the routine where any new inferred ranges should be added.
// If USE_RANGEOPS is true, invoke range-ops on stmts with a single
// ssa-name a constant to reflect an inferred range. ie
// x_2 = y_3 + 1 will provide an inferred range for y_3 of [-INF, +INF - 1].
// This defaults to FALSE as it can be expensive.,

gimple_infer_range::gimple_infer_range (gimple *s, range_query *q,
					bool use_rangeops)
{
  num_args = 0;

  if (is_a<gphi *> (s))
    return;

  // Default to the global query if none provided.
  if (!q)
    q = get_global_range_query ();

  if (is_a<gcall *> (s) && flag_delete_null_pointer_checks)
    {
      tree fntype = gimple_call_fntype (s);
      bitmap nonnullargs = get_nonnull_args (fntype);
      // Process any non-null arguments
      if (nonnullargs)
	{
	  for (unsigned i = 0; i < gimple_call_num_args (s); i++)
	    {
	      if (bitmap_empty_p (nonnullargs)
		  || bitmap_bit_p (nonnullargs, i))
		{
		  tree op = gimple_call_arg (s, i);
		  if (POINTER_TYPE_P (TREE_TYPE (op)))
		    add_nonzero (op);
		}
	    }
	  BITMAP_FREE (nonnullargs);
	}
      if (fntype)
	for (tree attrs = TYPE_ATTRIBUTES (fntype);
	     (attrs = lookup_attribute ("nonnull_if_nonzero", attrs));
	     attrs = TREE_CHAIN (attrs))
	  {
	    tree args = TREE_VALUE (attrs);
	    unsigned int idx = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1;
	    unsigned int idx2
	      = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args))) - 1;
	    unsigned int idx3 = idx2;
	    if (tree chain2 = TREE_CHAIN (TREE_CHAIN (args)))
	      idx3 = TREE_INT_CST_LOW (TREE_VALUE (chain2)) - 1;
	    if (idx < gimple_call_num_args (s)
		&& idx2 < gimple_call_num_args (s)
		&& idx3 < gimple_call_num_args (s))
	      {
		tree arg = gimple_call_arg (s, idx);
		tree arg2 = gimple_call_arg (s, idx2);
		tree arg3 = gimple_call_arg (s, idx3);
		if (!POINTER_TYPE_P (TREE_TYPE (arg))
		    || !INTEGRAL_TYPE_P (TREE_TYPE (arg2))
		    || !INTEGRAL_TYPE_P (TREE_TYPE (arg3))
		    || integer_zerop (arg2)
		    || integer_zerop (arg3))
		  continue;
		if (integer_nonzerop (arg2) && integer_nonzerop (arg3))
		  add_nonzero (arg);
		else
		  {
		    value_range r (TREE_TYPE (arg2));
		    if (q->range_of_expr (r, arg2, s)
			&& !r.contains_p (build_zero_cst (TREE_TYPE (arg2))))
		      {
			if (idx2 == idx3)
			  add_nonzero (arg);
			else
			  {
			    value_range r2 (TREE_TYPE (arg3));
			    tree zero3 = build_zero_cst (TREE_TYPE (arg3));
			    if (q->range_of_expr (r2, arg3, s)
				&& !r2.contains_p (zero3))
			      add_nonzero (arg);
			  }
		      }
		  }
	      }
	  }
      // Fallthru and walk load/store ops now.
    }

  // Check for inferred ranges from ASSUME calls.
  if (is_a<gcall *> (s) && gimple_call_internal_p (s)
      && gimple_call_internal_fn (s) == IFN_ASSUME)
    check_assume_func (as_a<gcall *> (s));

  // Look for possible non-null values.
  if (flag_delete_null_pointer_checks && gimple_code (s) != GIMPLE_ASM
      && !gimple_clobber_p (s))
    walk_stmt_load_store_ops (s, (void *)this, non_null_loadstore,
			      non_null_loadstore);

  // Gated by flag.
  if (!use_rangeops)
    return;

  // Check if there are any inferred ranges from range-ops.
  gimple_range_op_handler handler (s);
  if (!handler)
    return;

  // Only proceed if ONE operand is an SSA_NAME,  This may provide an
  // inferred range for 'y + 3' , but will bypass expressions like
  // 'y + z' as it depends on symbolic values.
  tree ssa1 = gimple_range_ssa_p (handler.operand1 ());
  tree ssa2 = gimple_range_ssa_p (handler.operand2 ());
  if ((ssa1 != NULL) == (ssa2 != NULL))
    return;

  // The other operand should be a constant, so just use the global range
  // query to pick up any other values.
  if (ssa1)
    {
      value_range op1 (TREE_TYPE (ssa1));
      if (op1_range (op1, s, q) && !op1.varying_p ())
	add_range (ssa1, op1);
    }
  else
    {
      gcc_checking_assert (ssa2);
      value_range op2 (TREE_TYPE (ssa2));
      if (op2_range (op2, s, q) && !op2.varying_p ())
	add_range (ssa2, op2);
    }
}

// Create an single inferred range for NAMe using range R.

gimple_infer_range::gimple_infer_range (tree name, vrange &r)
{
  num_args = 0;
  add_range (name, r);
}

// -------------------------------------------------------------------------

// This class is an element in the list of inferred ranges.

class exit_range
{
public:
  tree name;
  gimple *stmt;
  vrange_storage *range;
  exit_range *next;
};


// If there is an element which matches SSA, return a pointer to the element.
// Otherwise return NULL.

exit_range *
infer_range_manager::exit_range_head::find_ptr (tree ssa)
{
  // Return NULL if SSA is not in this list.
  if (!m_names || !bitmap_bit_p (m_names, SSA_NAME_VERSION (ssa)))
    return NULL;
  for (exit_range *ptr = head; ptr != NULL; ptr = ptr->next)
    if (ptr->name == ssa)
      return ptr;
  // Should be unreachable.
  gcc_unreachable ();
  return NULL;
}

// Construct a range infer manager.  DO_SEARCH indicates whether an immediate
// use scan should be made the first time a name is processed.  This is for
// on-demand clients who may not visit every statement and may miss uses.
// Q is the range_query to use for any lookups.  Default is NULL which maps
// to the global_range_query.

infer_range_manager::infer_range_manager (bool do_search, range_query *q)
{
  // Set the range query to use.
  m_query = q ? q : get_global_range_query ();

  bitmap_obstack_initialize (&m_bitmaps);
  m_on_exit.create (0);
  m_on_exit.safe_grow_cleared (last_basic_block_for_fn (cfun) + 1);
  // m_seen == NULL indicates no scanning.  Otherwise the bit indicates a
  // scan has been performed on NAME.
  if (do_search)
    m_seen = BITMAP_ALLOC (&m_bitmaps);
  else
    m_seen = NULL;
  obstack_init (&m_list_obstack);
  // Non-zero elements are very common, so cache them for each ssa-name.
  m_nonzero.create (0);
  m_nonzero.safe_grow_cleared (num_ssa_names + 1);
  m_range_allocator = new vrange_allocator;
}

// Destruct a range infer manager.

infer_range_manager::~infer_range_manager ()
{
  m_nonzero.release ();
  obstack_free (&m_list_obstack, NULL);
  m_on_exit.release ();
  bitmap_obstack_release (&m_bitmaps);
  delete m_range_allocator;
}

// Return a non-zero range value of the appropriate type for NAME from
// the cache, creating it if necessary.

const vrange&
infer_range_manager::get_nonzero (tree name)
{
  unsigned v = SSA_NAME_VERSION (name);
  if (v >= m_nonzero.length ())
    m_nonzero.safe_grow_cleared (num_ssa_names + 20);
  if (!m_nonzero[v])
    {
      m_nonzero[v]
	= (irange *) m_range_allocator->alloc (sizeof (int_range <2>));
      m_nonzero[v]->set_nonzero (TREE_TYPE (name));
    }
  return *(m_nonzero[v]);
}

// Return TRUE if NAME has a range inference in block BB.  If NAME is NULL,
// return TRUE if there are any name sin BB.

bool
infer_range_manager::has_range_p (basic_block bb, tree name)
{
  // Check if this is an immediate use search model.
  if (name && m_seen && !bitmap_bit_p (m_seen, SSA_NAME_VERSION (name)))
    register_all_uses (name);

  if (bb->index >= (int)m_on_exit.length ())
    return false;

  bitmap b = m_on_exit[bb->index].m_names;
  if (!b)
    return false;

  if (name)
    return bitmap_bit_p (m_on_exit[bb->index].m_names, SSA_NAME_VERSION (name));
  return !bitmap_empty_p (b);
}

// Return TRUE if NAME has a range inference in block BB, and adjust range R
// to include it.

bool
infer_range_manager::maybe_adjust_range (vrange &r, tree name, basic_block bb)
{
  if (!has_range_p (bb, name))
    return false;
  exit_range *ptr = m_on_exit[bb->index].find_ptr (name);
  gcc_checking_assert (ptr);
  // Return true if this exit range changes R, otherwise false.
  tree type = TREE_TYPE (name);
  value_range tmp (type);
  ptr->range->get_vrange (tmp, type);
  return r.intersect (tmp);
}

// Add all inferred ranges in INFER at stmt S.

void
infer_range_manager::add_ranges (gimple *s, gimple_infer_range &infer)
{
  for (unsigned x = 0; x < infer.num (); x++)
    {
      tree arg = infer.name (x);
      value_range r (TREE_TYPE (arg));
      m_query->range_of_expr (r, arg, s);
      // Only add the inferred range if it changes the current range.
      if (r.intersect (infer.range (x)))
	add_range (arg, s, infer.range (x));
    }
}

// Add range R as an inferred range for NAME on stmt S.

void
infer_range_manager::add_range (tree name, gimple *s, const vrange &r)
{
  basic_block bb = gimple_bb (s);
  if (!bb)
    return;
  if (bb->index >= (int)m_on_exit.length ())
    m_on_exit.safe_grow_cleared (last_basic_block_for_fn (cfun) + 1);

  // Create the summary list bitmap if it doesn't exist.
  if (!m_on_exit[bb->index].m_names)
      m_on_exit[bb->index].m_names = BITMAP_ALLOC (&m_bitmaps);

  if (dump_file && (dump_flags & TDF_DETAILS))
   {
     fprintf (dump_file, "   on-exit update ");
     print_generic_expr (dump_file, name, TDF_SLIM);
     fprintf (dump_file, " in BB%d : ",bb->index);
     r.dump (dump_file);
     fprintf (dump_file, "\n");
   }

  // If NAME already has a range, intersect them and done.
  exit_range *ptr = m_on_exit[bb->index].find_ptr (name);
  if (ptr)
    {
      tree type = TREE_TYPE (name);
      value_range cur (r), name_range (type);
      ptr->range->get_vrange (name_range, type);
      // If no new info is added, just return.
      if (!cur.intersect (name_range))
	return;
      if (ptr->range->fits_p (cur))
	ptr->range->set_vrange (cur);
      else
	ptr->range = m_range_allocator->clone (cur);
      ptr->stmt = s;
      return;
    }

  // Otherwise create a record.
  bitmap_set_bit (m_on_exit[bb->index].m_names, SSA_NAME_VERSION (name));
  ptr = (exit_range *)obstack_alloc (&m_list_obstack, sizeof (exit_range));
  ptr->range = m_range_allocator->clone (r);
  ptr->name = name;
  ptr->stmt = s;
  ptr->next = m_on_exit[bb->index].head;
  m_on_exit[bb->index].head = ptr;
}

// Add a non-zero inferred range for NAME at stmt S.

void
infer_range_manager::add_nonzero (tree name, gimple *s)
{
  add_range (name, s, get_nonzero (name));
}

// Follow immediate use chains and find all inferred ranges for NAME.

void
infer_range_manager::register_all_uses (tree name)
{
  gcc_checking_assert (m_seen);

  // Check if we've already processed this name.
  unsigned v = SSA_NAME_VERSION (name);
  if (bitmap_bit_p (m_seen, v))
     return;
  bitmap_set_bit (m_seen, v);

  use_operand_p use_p;
  imm_use_iterator iter;

  // Loop over each immediate use and see if it has an inferred range.
  FOR_EACH_IMM_USE_FAST (use_p, iter, name)
    {
      gimple *s = USE_STMT (use_p);
      gimple_infer_range infer (s, m_query);
      for (unsigned x = 0; x < infer.num (); x++)
	{
	  if (name == infer.name (x))
	    add_range (name, s, infer.range (x));
	}
    }
}
