/* Cost model declaration of RISC-V 'V' Extension for GNU compiler.
   Copyright (C) 2023-2025 Free Software Foundation, Inc.
   Contributed by Juzhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.

   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_RISCV_VECTOR_COST_H
#define GCC_RISCV_VECTOR_COST_H

namespace riscv_vector {

struct stmt_point
{
  /* Program point.  */
  unsigned int point;
  gimple *stmt;
  stmt_vec_info stmt_info;
};

enum cost_type_enum
{
  SCALAR_COST,
  VLA_VECTOR_COST,
  VLS_VECTOR_COST
};

/* Pair typedef used by live range: <start, end>.  */
typedef std::pair<unsigned int, unsigned int> pair;

/* rvv-specific vector costs.  */
class costs : public vector_costs
{
  using vector_costs::vector_costs;

public:
  costs (vec_info *, bool);

  bool better_main_loop_than_p (const vector_costs *other) const override;

private:
  unsigned int add_stmt_cost (int count, vect_cost_for_stmt kind,
			      stmt_vec_info stmt_info, slp_tree node,
			      tree vectype, int misalign,
			      vect_cost_model_location where) override;
  void finish_cost (const vector_costs *) override;

  /* True if we have performed one-time initialization based on the
     vec_info.  */
  bool m_analyzed_vinfo = false;

  /* - If M_COST_TYPE = SCALAR_COST then we're costing the original scalar code.
     - If M_COST_TYPE = VLA_VECTOR_COST is nonzero then we're costing VLA
       partial vectorization codes.
     - If M_COST_TYPE = VLS_VECTOR_COST is nonzero then we're costing VLS
       minimum length vector codes.  */
  enum cost_type_enum m_cost_type;

  /* On some CPUs, VLA and VLS provide the same theoretical vector
     throughput, such as 4x128 VLS vs. 2x256 VLA.  In those
     situations, we try to predict whether an VLS implementation
     of the loop could be completely unrolled and become straight-line code.
     If so, it is generally better to use the VLS version rather
     than length-agnostic VLA, since the VLA loop would execute an unknown
     number of times and so could not be completely unrolled in the same way.

     If we're applying this heuristic, M_UNROLLED_VLS_NITERS is the
     number of VLS loop iterations that would be unrolled and
     M_UNROLLED_VLS_STMTS estimates the total number of statements
     in the unrolled loop.  Both values are zero if we're not applying
     the heuristic.  */
  unsigned HOST_WIDE_INT m_unrolled_vls_niters = 0;
  unsigned HOST_WIDE_INT m_unrolled_vls_stmts = 0;

  tree cst0 = build_int_cst (integer_type_node, 0);

  /* Store the memory references already processed.  */
  typedef pair_hash <tree_operand_hash, tree_operand_hash> tree_pair_hash;
  hash_set <tree_pair_hash> memrefs;

  hash_map <stmt_vec_info, slp_tree> vinfo_slp_map;

  void analyze_loop_vinfo (loop_vec_info);
  void record_lmul_spills (loop_vec_info loop_vinfo);
  void record_potential_vls_unrolling (loop_vec_info);
  bool prefer_unrolled_loop () const;

  /* Analyze the vectorized program statements and compute the maximum live
     V_REGS live at some program point if we enable dynamic LMUL cost model.

     It's true when LMUL of loop vectorization factor > 1 and has unexpected
     V_REGS spills according to the analysis.  */
  bool m_has_unexpected_spills_p = false;
  void record_potential_unexpected_spills (loop_vec_info);

  void compute_local_program_points (vec_info *,
				     hash_map<basic_block, vec<stmt_point>> &);
  void update_local_live_ranges (vec_info *,
				 hash_map<basic_block, vec<stmt_point>> &,
				 hash_map<basic_block, hash_map<tree, pair>> &,
				 machine_mode *);
  machine_mode compute_local_live_ranges
    (loop_vec_info, const hash_map<basic_block, vec<stmt_point>> &,
     hash_map<basic_block, hash_map<tree, pair>> &);

  bool has_unexpected_spills_p (loop_vec_info);
  bool need_additional_vector_vars_p (stmt_vec_info, slp_tree);

  void adjust_vect_cost_per_loop (loop_vec_info);
  unsigned adjust_stmt_cost (enum vect_cost_for_stmt kind,
			     loop_vec_info,
			     stmt_vec_info stmt_info, slp_tree,
			     tree vectype, int stmt_cost);
};

} // namespace riscv_vector

#endif // GCC_RISCV_VECTOR_COST_H
