/* Integrated Register Allocator (IRA) intercommunication header file.
   Copyright (C) 2006-2023 Free Software Foundation, Inc.
   Contributed by Vladimir Makarov <vmakarov@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/>.  */

#ifndef GCC_IRA_INT_H
#define GCC_IRA_INT_H

#include "recog.h"
#include "function-abi.h"

/* To provide consistency in naming, all IRA external variables,
   functions, common typedefs start with prefix ira_.  */

#if CHECKING_P
#define ENABLE_IRA_CHECKING
#endif

#ifdef ENABLE_IRA_CHECKING
#define ira_assert(c) gcc_assert (c)
#else
/* Always define and include C, so that warnings for empty body in an
  'if' statement and unused variable do not occur.  */
#define ira_assert(c) ((void)(0 && (c)))
#endif

/* Compute register frequency from edge frequency FREQ.  It is
   analogous to REG_FREQ_FROM_BB.  When optimizing for size, or
   profile driven feedback is available and the function is never
   executed, frequency is always equivalent.  Otherwise rescale the
   edge frequency.  */
#define REG_FREQ_FROM_EDGE_FREQ(freq)				   \
  (optimize_function_for_size_p (cfun)				   \
   ? REG_FREQ_MAX : (freq * REG_FREQ_MAX / BB_FREQ_MAX)		   \
   ? (freq * REG_FREQ_MAX / BB_FREQ_MAX) : 1)

/* A modified value of flag `-fira-verbose' used internally.  */
extern int internal_flag_ira_verbose;

/* Dump file of the allocator if it is not NULL.  */
extern FILE *ira_dump_file;

/* Typedefs for pointers to allocno live range, allocno, and copy of
   allocnos.  */
typedef struct live_range *live_range_t;
typedef struct ira_allocno *ira_allocno_t;
typedef struct ira_allocno_pref *ira_pref_t;
typedef struct ira_allocno_copy *ira_copy_t;
typedef struct ira_object *ira_object_t;

/* Definition of vector of allocnos and copies.  */

/* Typedef for pointer to the subsequent structure.  */
typedef struct ira_loop_tree_node *ira_loop_tree_node_t;

typedef unsigned short move_table[N_REG_CLASSES];

/* In general case, IRA is a regional allocator.  The regions are
   nested and form a tree.  Currently regions are natural loops.  The
   following structure describes loop tree node (representing basic
   block or loop).  We need such tree because the loop tree from
   cfgloop.h is not convenient for the optimization: basic blocks are
   not a part of the tree from cfgloop.h.  We also use the nodes for
   storing additional information about basic blocks/loops for the
   register allocation purposes.  */
struct ira_loop_tree_node
{
  /* The node represents basic block if children == NULL.  */
  basic_block bb;    /* NULL for loop.  */
  /* NULL for BB or for loop tree root if we did not build CFG loop tree.  */
  class loop *loop;
  /* NEXT/SUBLOOP_NEXT is the next node/loop-node of the same parent.
     SUBLOOP_NEXT is always NULL for BBs.  */
  ira_loop_tree_node_t subloop_next, next;
  /* CHILDREN/SUBLOOPS is the first node/loop-node immediately inside
     the node.  They are NULL for BBs.  */
  ira_loop_tree_node_t subloops, children;
  /* The node immediately containing given node.  */
  ira_loop_tree_node_t parent;

  /* Loop level in range [0, ira_loop_tree_height).  */
  int level;

  /* All the following members are defined only for nodes representing
     loops.  */

  /* The loop number from CFG loop tree.  The root number is 0.  */
  int loop_num;

  /* True if the loop was marked for removal from the register
     allocation.  */
  bool to_remove_p;

  /* Allocnos in the loop corresponding to their regnos.  If it is
     NULL the loop does not form a separate register allocation region
     (e.g. because it has abnormal enter/exit edges and we cannot put
     code for register shuffling on the edges if a different
     allocation is used for a pseudo-register on different sides of
     the edges).  Caps are not in the map (remember we can have more
     one cap with the same regno in a region).  */
  ira_allocno_t *regno_allocno_map;

  /* True if there is an entry to given loop not from its parent (or
     grandparent) basic block.  For example, it is possible for two
     adjacent loops inside another loop.  */
  bool entered_from_non_parent_p;

  /* Maximal register pressure inside loop for given register class
     (defined only for the pressure classes).  */
  int reg_pressure[N_REG_CLASSES];

  /* Numbers of allocnos referred or living in the loop node (except
     for its subloops).  */
  bitmap all_allocnos;

  /* Numbers of allocnos living at the loop borders.  */
  bitmap border_allocnos;

  /* Regnos of pseudos modified in the loop node (including its
     subloops).  */
  bitmap modified_regnos;

  /* Numbers of copies referred in the corresponding loop.  */
  bitmap local_copies;
};

/* The root of the loop tree corresponding to the all function.  */
extern ira_loop_tree_node_t ira_loop_tree_root;

/* Height of the loop tree.  */
extern int ira_loop_tree_height;

/* All nodes representing basic blocks are referred through the
   following array.  We cannot use basic block member `aux' for this
   because it is used for insertion of insns on edges.  */
extern ira_loop_tree_node_t ira_bb_nodes;

/* Two access macros to the nodes representing basic blocks.  */
#if defined ENABLE_IRA_CHECKING && (GCC_VERSION >= 2007)
#define IRA_BB_NODE_BY_INDEX(index) __extension__			\
(({ ira_loop_tree_node_t _node = (&ira_bb_nodes[index]);		\
     if (_node->children != NULL || _node->loop != NULL || _node->bb == NULL)\
       {								\
         fprintf (stderr,						\
                  "\n%s: %d: error in %s: it is not a block node\n",	\
                  __FILE__, __LINE__, __FUNCTION__);			\
         gcc_unreachable ();						\
       }								\
     _node; }))
#else
#define IRA_BB_NODE_BY_INDEX(index) (&ira_bb_nodes[index])
#endif

#define IRA_BB_NODE(bb) IRA_BB_NODE_BY_INDEX ((bb)->index)

/* All nodes representing loops are referred through the following
   array.  */
extern ira_loop_tree_node_t ira_loop_nodes;

/* Two access macros to the nodes representing loops.  */
#if defined ENABLE_IRA_CHECKING && (GCC_VERSION >= 2007)
#define IRA_LOOP_NODE_BY_INDEX(index) __extension__			\
(({ ira_loop_tree_node_t const _node = (&ira_loop_nodes[index]);	\
     if (_node->children == NULL || _node->bb != NULL			\
         || (_node->loop == NULL && current_loops != NULL))		\
       {								\
         fprintf (stderr,						\
                  "\n%s: %d: error in %s: it is not a loop node\n",	\
                  __FILE__, __LINE__, __FUNCTION__);			\
         gcc_unreachable ();						\
       }								\
     _node; }))
#else
#define IRA_LOOP_NODE_BY_INDEX(index) (&ira_loop_nodes[index])
#endif

#define IRA_LOOP_NODE(loop) IRA_LOOP_NODE_BY_INDEX ((loop)->num)

