// Implementation of public inline member functions for RTL SSA     -*- C++ -*-
// Copyright (C) 2020-2021 Free Software Foundation, Inc.
//
// 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/>.

// This file contains inline implementations of public member functions that
// are too large to be written in the class definition.  It also contains
// some non-inline template definitions of public member functions.
// See the comments above the function declarations for details.
//
// The file also contains the bare minimum of private and protected inline
// member functions that are needed to make the public functions compile.
namespace rtl_ssa {

inline void
access_array_builder::reserve (unsigned int num_accesses)
{
  obstack_make_room (m_obstack, num_accesses * sizeof (access_info *));
}

inline void
access_array_builder::quick_push (access_info *access)
{
  obstack_ptr_grow_fast (m_obstack, access);
}

inline array_slice<access_info *>
access_array_builder::finish ()
{
  auto num_accesses = obstack_object_size (m_obstack) / sizeof (access_info *);
  if (num_accesses == 0)
    return {};

  auto **base = static_cast<access_info **> (obstack_finish (m_obstack));
  keep ();
  return { base, num_accesses };
}

inline bool
access_info::is_set_with_nondebug_insn_uses () const
{
  return m_is_set_with_nondebug_insn_uses;
}

inline bool
use_info::is_in_debug_insn () const
{
  return m_insn_or_phi.is_first () && m_is_in_debug_insn_or_phi;
}

inline bb_info *
use_info::bb () const
{
  if (m_insn_or_phi.is_first ())
    return m_insn_or_phi.known_first ()->bb ();
  return m_insn_or_phi.known_second ()->bb ();
}

inline ebb_info *
use_info::ebb () const
{
  return bb ()->ebb ();
}

inline use_info *
use_info::prev_use () const
{
  return m_last_use_or_prev_use.second_or_null ();
}

inline use_info *
use_info::next_use () const
{
  return m_last_nondebug_insn_use_or_next_use.second_or_null ();
}

inline bool
use_info::is_first_use () const
{
  return m_last_use_or_prev_use.is_first ();
}

inline bool
use_info::is_last_use () const
{
  return m_last_nondebug_insn_use_or_next_use.is_first ();
}

inline use_info *
use_info::next_nondebug_insn_use () const
{
  if (m_is_last_nondebug_insn_use)
    return nullptr;
  return m_last_nondebug_insn_use_or_next_use.known_second ();
}

inline use_info *
use_info::next_any_insn_use () const
{
  // This is used less often than next_nondebug_insn_use, so it doesn't
  // seem worth having an m_is_last_nondebug_insn_use-style end marker.
  if (use_info *use = next_use ())
    if (use->is_in_any_insn ())
      return use;
  return nullptr;
}

inline use_info *
use_info::prev_phi_use () const
{
  // This is used less often than next_nondebug_insn_use, so it doesn't
  // seem worth having an m_is_last_nondebug_insn_use-style end marker.
  if (use_info *use = prev_use ())
    if (use->is_in_phi ())
      return use;
  return nullptr;
}

// Return the last use of any kind in the list.  Only valid when is_first ()
// is true.
inline use_info *
use_info::last_use () const
{
  return m_last_use_or_prev_use.known_first ();
}

// Return the last nondebug insn use in the list, or null if none.  Only valid
// when is_last_use () is true.
inline use_info *
use_info::last_nondebug_insn_use () const
{
  return m_last_nondebug_insn_use_or_next_use.known_first ();
}

inline def_info *
def_info::prev_def () const
{
  return m_last_def_or_prev_def.second_or_null ();
}

inline def_info *
def_info::next_def () const
{
  return m_splay_root_or_next_def.second_or_null ();
}

inline bool
def_info::is_first_def () const
{
  return m_last_def_or_prev_def.is_first ();
}

inline bool
def_info::is_last_def () const
{
  return m_splay_root_or_next_def.is_first ();
}

inline bb_info *
def_info::bb () const
{
  return m_insn->bb ();
}

inline ebb_info *
def_info::ebb () const
{
  return m_insn->ebb ();
}

inline clobber_group *
clobber_info::group () const
{
  if (!m_group || !m_group->has_been_superceded ())
    return m_group;
  return const_cast<clobber_info *> (this)->recompute_group ();
}

inline use_info *
set_info::last_use () const
{
  return m_first_use ? m_first_use->last_use () : nullptr;
}

inline use_info *
set_info::first_nondebug_insn_use () const
{
  if (m_is_set_with_nondebug_insn_uses)
    return m_first_use;
  return nullptr;
}

inline use_info *
set_info::last_nondebug_insn_use () const
{
  if (m_is_set_with_nondebug_insn_uses)
    return m_first_use->last_use ()->last_nondebug_insn_use ();
  return nullptr;
}

inline use_info *
set_info::first_any_insn_use () const
{
  if (m_first_use->is_in_any_insn ())
    return m_first_use;
  return nullptr;
}

inline use_info *
set_info::last_phi_use () const
{
  if (m_first_use)
    {
      use_info *last = m_first_use->last_use ();
      if (last->is_in_phi ())
	return last;
    }
  return nullptr;
}

inline bool
set_info::has_nondebug_uses () const
{
  return has_nondebug_insn_uses () || has_phi_uses ();
}

inline bool
set_info::has_nondebug_insn_uses () const
{
  return m_is_set_with_nondebug_insn_uses;
}

inline bool
set_info::has_phi_uses () const
{
  return m_first_use && m_first_use->last_use ()->is_in_phi ();
}

inline use_info *
set_info::single_nondebug_use () const
{
  if (!has_phi_uses ())
    return single_nondebug_insn_use ();
  if (!has_nondebug_insn_uses ())
    return single_phi_use ();
  return nullptr;
}

inline use_info *
set_info::single_nondebug_insn_use () const
{
  use_info *first = first_nondebug_insn_use ();
  if (first && !first->next_nondebug_insn_use ())
    return first;
  return nullptr;
}

inline use_info *
set_info::single_phi_use () const
{
  use_info *last = last_phi_use ();
  if (last && !last->prev_phi_use ())
    return last;
  return nullptr;
}

inline bool
set_info::is_local_to_ebb () const
{
  if (!m_first_use)
    return true;

  use_info *last = m_first_use->last_use ();
  if (last->is_in_phi ())
    return false;

  last = last->last_nondebug_insn_use ();
  return !last || last->ebb () == ebb ();
}

inline iterator_range<use_iterator>
set_info::all_uses () const
{
  return { m_first_use, nullptr };
}

inline iterator_range<reverse_use_iterator>
set_info::reverse_all_uses () const
{
  return { last_use (), nullptr };
}

inline iterator_range<nondebug_insn_use_iterator>
set_info::nondebug_insn_uses () const
{
  return { first_nondebug_insn_use (), nullptr };
}

inline iterator_range<reverse_use_iterator>
set_info::reverse_nondebug_insn_uses () const
{
  return { last_nondebug_insn_use (), nullptr };
}

inline iterator_range<any_insn_use_iterator>
set_info::all_insn_uses () const
{
  return { first_any_insn_use (), nullptr };
}

inline iterator_range<phi_use_iterator>
set_info::phi_uses () const
{
  return { last_phi_use (), nullptr };
}

inline use_array
phi_info::inputs () const
{
  if (m_num_inputs == 1)
    return use_array (&m_single_input, 1);
  return use_array (m_inputs, m_num_inputs);
}

inline use_info *
phi_info::input_use (unsigned int i) const
{
  if (m_num_inputs == 1)
    return as_a<use_info *> (m_single_input);
  return as_a<use_info *> (m_inputs[i]);
}

inline set_info *
phi_info::input_value (unsigned int i) const
{
  return input_use (i)->def ();
}

inline def_info *
def_node::first_def () const
{
  // This should get optimized into an AND with -2.
  if (m_clobber_or_set.is_first ())
    return m_clobber_or_set.known_first ();
  return m_clobber_or_set.known_second ();
}

inline clobber_info *
clobber_group::first_clobber () const
{
  return m_clobber_or_set.known_first ();
}

inline iterator_range<def_iterator>
clobber_group::clobbers () const
{
  return { first_clobber (), m_last_clobber->next_def () };
}

inline def_info *
def_mux::first_def () const
{
  if (is_first ())
    return known_first ();
  return known_second ()->first_def ();
}

inline def_info *
def_mux::last_def () const
{
  if (is_first ())
    return known_first ();

  def_node *node = known_second ();
  if (auto *clobber = ::dyn_cast<clobber_group *> (node))
    return clobber->last_clobber ();

  return node->first_def ();
}

inline set_info *
def_mux::set () const
{
  if (is_first ())
    return ::safe_dyn_cast<set_info *> (known_first ());
  return ::dyn_cast<set_info *> (known_second ()->first_def ());
}

inline def_info *
def_lookup::prev_def () const
{
  if (!mux)
    return nullptr;

  if (comparison > 0)
    return mux.last_def ();

  return mux.first_def ()->prev_def ();
}

inline def_info *
def_lookup::next_def () const
{
  if (!mux)
    return nullptr;

  if (comparison < 0)
    return mux.first_def ();

  return mux.last_def ()->next_def ();
}

inline set_info *
def_lookup::matching_set () const
{
  if (comparison == 0)
    return mux.set ();
  return nullptr;
}

inline def_info *
def_lookup::matching_or_prev_def () const
{
  if (set_info *set = matching_set ())
    return set;
  return prev_def ();
}

inline def_info *
def_lookup::matching_or_next_def () const
{
  if (set_info *set = matching_set ())
    return set;
  return next_def ();
}

inline insn_note::insn_note (insn_note_kind kind)
  : m_next_note (nullptr),
    m_kind (kind),
    m_data8 (0),
    m_data16 (0),
    m_data32 (0)
{
}

template<typename T>
inline T
insn_note::as_a ()
{
  using deref_type = decltype (*std::declval<T> ());
  using derived = typename std::remove_reference<deref_type>::type;
  gcc_checking_assert (m_kind == derived::kind);
  return static_cast<T> (this);
}

template<typename T>
inline T
insn_note::dyn_cast ()
{
  using deref_type = decltype (*std::declval<T> ());
  using derived = typename std::remove_reference<deref_type>::type;
  if (m_kind == derived::kind)
    return static_cast<T> (this);
  return nullptr;
}

inline bool
insn_info::operator< (const insn_info &other) const
{
  if (this == &other)
    return false;

  if (__builtin_expect (m_point != other.m_point, 1))
    return m_point < other.m_point;

  return slow_compare_with (other) < 0;
}

inline bool
insn_info::operator> (const insn_info &other) const
{
  return other < *this;
}

inline bool
insn_info::operator<= (const insn_info &other) const
{
  return !(other < *this);
}

inline bool
insn_info::operator>= (const insn_info &other) const
{
  return !(*this < other);
}

inline int
insn_info::compare_with (const insn_info *other) const
{
  if (this == other)
    return 0;

  if (__builtin_expect (m_point != other->m_point, 1))
    // Assume that points remain in [0, INT_MAX].
    return m_point - other->m_point;

  return slow_compare_with (*other);
}

inline insn_info *
insn_info::prev_nondebug_insn () const
{
  gcc_checking_assert (!is_debug_insn ());
  return m_prev_insn_or_last_debug_insn.known_first ();
}

inline insn_info *
insn_info::next_nondebug_insn () const
{
  gcc_checking_assert (!is_debug_insn ());
  const insn_info *from = this;
  if (insn_info *first_debug = m_next_nondebug_or_debug_insn.second_or_null ())
    from = first_debug->last_debug_insn ();
  return from->m_next_nondebug_or_debug_insn.known_first ();
}

inline insn_info *
insn_info::prev_any_insn () const
{
  const insn_info *from = this;
  if (insn_info *last_debug = m_prev_insn_or_last_debug_insn.second_or_null ())
    // This instruction is the first in a subsequence of debug instructions.
    // Move to the following nondebug instruction.
    from = last_debug->m_next_nondebug_or_debug_insn.known_first ();
  return from->m_prev_insn_or_last_debug_insn.known_first ();
}

inline insn_info *
insn_info::next_any_insn () const
{
  // This should get optimized into an AND with -2.
  if (m_next_nondebug_or_debug_insn.is_first ())
    return m_next_nondebug_or_debug_insn.known_first ();
  return m_next_nondebug_or_debug_insn.known_second ();
}

inline bool
insn_info::is_phi () const
{
  return this == ebb ()->phi_insn ();
}

inline bool
insn_info::is_bb_head () const
{
  return this == m_bb->head_insn ();
}

inline bool
insn_info::is_bb_end () const
{
  return this == m_bb->end_insn ();
}

inline ebb_info *
insn_info::ebb () const
{
  return m_bb->ebb ();
}

inline int
insn_info::uid () const
{
  return m_cost_or_uid < 0 ? m_cost_or_uid : INSN_UID (m_rtl);
}

inline use_array
insn_info::uses () const
{
  return use_array (m_accesses + m_num_defs, m_num_uses);
}

inline bool
insn_info::has_call_clobbers () const
{
  return find_note<insn_call_clobbers_note> ();
}

inline def_array
insn_info::defs () const
{
  return def_array (m_accesses, m_num_defs);
}

inline unsigned int
insn_info::cost () const
{
  if (m_cost_or_uid < 0)
    return 0;
  if (m_cost_or_uid == UNKNOWN_COST)
    calculate_cost ();
  return m_cost_or_uid;
}

template<typename T>
inline const T *
insn_info::find_note () const
{
  // We could break if the note kind is > T::kind, but since the number
  // of notes should be very small, the check is unlikely to pay for itself.
  for (const insn_note *note = first_note (); note; note = note->next_note ())
    if (note->kind () == T::kind)
      return static_cast<const T *> (note);
  return nullptr;
}

// Only valid for debug instructions that come after a nondebug instruction,
// and so start a subsequence of debug instructions.  Return the last debug
// instruction in the subsequence.
inline insn_info *
insn_info::last_debug_insn () const
{
  return m_prev_insn_or_last_debug_insn.known_second ();
}

inline insn_range_info::insn_range_info (insn_info *first, insn_info *last)
  : first (first), last (last)
{
}

inline bool
insn_range_info::operator== (const insn_range_info &other) const
{
  return first == other.first && last == other.last;
}

inline bool
insn_range_info::operator!= (const insn_range_info &other) const
{
  return first != other.first || last != other.last;
}

inline insn_info *
insn_range_info::singleton () const
{
  return first == last ? last : nullptr;
}

inline bool
insn_range_info::includes (insn_info *insn) const
{
  return *insn >= *first && *insn <= *last;
}

inline insn_info *
insn_range_info::clamp_insn_to_range (insn_info *insn) const
{
  if (*first > *insn)
    return first;
  if (*last < *insn)
    return last;
  return insn;
}

inline bool
insn_range_info::is_subrange_of (const insn_range_info &other) const
{
  return *first >= *other.first && *last <= *other.last;
}

inline iterator_range<any_insn_iterator>
bb_info::all_insns () const
{
  return { m_head_insn, m_end_insn->next_any_insn () };
}

inline iterator_range<reverse_any_insn_iterator>
bb_info::reverse_all_insns () const
{
  return { m_end_insn, m_head_insn->prev_any_insn () };
}

inline iterator_range<nondebug_insn_iterator>
bb_info::nondebug_insns () const
{
  return { m_head_insn, m_end_insn->next_nondebug_insn () };
}

inline iterator_range<reverse_nondebug_insn_iterator>
bb_info::reverse_nondebug_insns () const
{
  return { m_end_insn, m_head_insn->prev_nondebug_insn () };
}

inline iterator_range<any_insn_iterator>
bb_info::real_insns () const
{
  return { m_head_insn->next_any_insn (), m_end_insn };
}

inline iterator_range<reverse_any_insn_iterator>
bb_info::reverse_real_insns () const
{
  return { m_end_insn->prev_any_insn (), m_head_insn };
}

inline iterator_range<nondebug_insn_iterator>
bb_info::real_nondebug_insns () const
{
  return { m_head_insn->next_nondebug_insn (), m_end_insn };
}

inline iterator_range<reverse_nondebug_insn_iterator>
bb_info::reverse_real_nondebug_insns () const
{
  return { m_end_insn->prev_nondebug_insn (), m_head_insn };
}

inline bool
ebb_call_clobbers_info::clobbers (resource_info resource) const
{
  // Only register clobbers are tracked this way.  Other clobbers are
  // recorded explicitly.
  return (resource.is_reg ()
	  && m_abi->clobbers_reg_p (resource.mode, resource.regno));
}

inline ebb_info *
ebb_info::prev_ebb () const
{
  if (bb_info *prev_bb = m_first_bb->prev_bb ())
    return prev_bb->ebb ();
  return nullptr;
}

inline ebb_info *
ebb_info::next_ebb () const
{
  if (bb_info *next_bb = m_last_bb->next_bb ())
    return next_bb->ebb ();
  return nullptr;
}

inline iterator_range<phi_iterator>
ebb_info::phis () const
{
  return { m_first_phi, nullptr };
}

inline iterator_range<bb_iterator>
ebb_info::bbs () const
{
  return { m_first_bb, m_last_bb->next_bb () };
}

inline iterator_range<reverse_bb_iterator>
ebb_info::reverse_bbs () const
{
  return { m_last_bb, m_first_bb->prev_bb () };
}

inline iterator_range<any_insn_iterator>
ebb_info::all_insns () const
{
  return { m_phi_insn, m_last_bb->end_insn ()->next_any_insn () };
}

inline iterator_range<reverse_any_insn_iterator>
ebb_info::reverse_all_insns () const
{
  return { m_last_bb->end_insn (), m_phi_insn->prev_any_insn () };
}

inline iterator_range<nondebug_insn_iterator>
ebb_info::nondebug_insns () const
{
  return { m_phi_insn, m_last_bb->end_insn ()->next_nondebug_insn () };
}

inline iterator_range<reverse_nondebug_insn_iterator>
ebb_info::reverse_nondebug_insns () const
{
  return { m_last_bb->end_insn (), m_phi_insn->prev_nondebug_insn () };
}

inline insn_range_info
ebb_info::insn_range () const
{
  return { m_phi_insn, m_last_bb->end_insn () };
}

inline void
ebb_info::set_first_call_clobbers (ebb_call_clobbers_info *call_clobbers)
{
  m_first_call_clobbers = call_clobbers;
}

inline ebb_call_clobbers_info *
ebb_info::first_call_clobbers () const
{
  return m_first_call_clobbers;
}

inline iterator_range<ebb_call_clobbers_iterator>
ebb_info::call_clobbers () const
{
  return { m_first_call_clobbers, nullptr };
}

inline insn_change::insn_change (insn_info *insn)
  : m_insn (insn),
    new_defs (insn->defs ()),
    new_uses (insn->uses ()),
    move_range (insn),
    new_cost (UNKNOWN_COST),
    m_is_deletion (false)
{
}

inline insn_change::insn_change (insn_info *insn, delete_action)
  : m_insn (insn),
    new_defs (),
    new_uses (),
    move_range (insn),
    new_cost (0),
    m_is_deletion (true)
{
}

inline insn_is_changing_closure::
insn_is_changing_closure (array_slice<insn_change *const> changes)
  : m_changes (changes)
{
}

inline bool
insn_is_changing_closure::operator() (const insn_info *insn) const
{
  for (const insn_change *change : m_changes)
    if (change->insn () == insn)
      return true;
  return false;
}

inline iterator_range<bb_iterator>
function_info::bbs () const
{
  return { m_first_bb, nullptr };
}

inline iterator_range<reverse_bb_iterator>
function_info::reverse_bbs () const
{
  return { m_last_bb, nullptr };
}

inline iterator_range<ebb_iterator>
function_info::ebbs () const
{
  return { m_first_bb->ebb (), nullptr };
}

inline iterator_range<reverse_ebb_iterator>
function_info::reverse_ebbs () const
{
  return { m_last_bb->ebb (), nullptr };
}

inline iterator_range<any_insn_iterator>
function_info::all_insns () const
{
  return { m_first_insn, nullptr };
}

inline iterator_range<reverse_any_insn_iterator>
function_info::reverse_all_insns () const
{
  return { m_last_insn, nullptr };
}

inline iterator_range<nondebug_insn_iterator>
function_info::nondebug_insns () const
{
  return { m_first_insn, nullptr };
}

inline iterator_range<reverse_nondebug_insn_iterator>
function_info::reverse_nondebug_insns () const
{
  return { m_last_insn, nullptr };
}

inline iterator_range<def_iterator>
function_info::mem_defs () const
{
  return { m_defs[0], nullptr };
}

inline iterator_range<def_iterator>
function_info::reg_defs (unsigned int regno) const
{
  return { m_defs[regno + 1], nullptr };
}

inline set_info *
function_info::single_dominating_def (unsigned int regno) const
{
  if (set_info *set = safe_dyn_cast<set_info *> (m_defs[regno + 1]))
    if (is_single_dominating_def (set))
      return set;
  return nullptr;
}

template<typename IgnorePredicate>
bool
function_info::add_regno_clobber (obstack_watermark &watermark,
				  insn_change &change, unsigned int regno,
				  IgnorePredicate ignore)
{
  // Check whether CHANGE already clobbers REGNO.
  if (find_access (change.new_defs, regno))
    return true;

  // Get the closest position to INSN at which the new instruction
  // could be placed.
  insn_info *insn = change.move_range.clamp_insn_to_range (change.insn ());
  def_array new_defs = insert_temp_clobber (watermark, insn, regno,
					    change.new_defs);
  if (!new_defs.is_valid ())
    return false;

  // Find a definition at or neighboring INSN.
  insn_range_info move_range = change.move_range;
  if (!restrict_movement_for_dead_range (move_range, regno, insn, ignore))
    return false;

  change.new_defs = new_defs;
  change.move_range = move_range;
  return true;
}

}
