/* Resource constrained software pipeliner.  This file contains
   definitions used internally in the resource constrained software
   pipeliner.  Copyright (C) 2003 Free Software Foundation, Inc.

   Written 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 2, 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 COPYING.  If not, write to the Free
   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.  */

#ifndef GCC_RCSP_INT_H
#define GCC_RCSP_INT_H

/* The following macro value defines unrolling the loop.  There will
   be (RCSP_UNROLL_FACTOR * maximal iteration look ahead + 1) loop bodies.
   The value should be more 1.  */
#define RCSP_UNROLL_FACTOR 2

#if 0
/* The following macro value defines maximal size of successfuly
   pipelined loop in original loop size.  The value should be more
   1.  */
#define RCSP_EXPANSION_LOOP_FACTOR 8
#endif

/*??? The following enumeration decribes how one packet is connected to
   another packet in CFG.  */
enum achievable_mode
{
  IGNORE_ACHIEVABILITY = 0,
  UNACHIEVABLE,
  BASIC_BLOCK_PATH,	 /* Basic block connection.  */
  OTHER_PATH		 /* All other cases.  */
};

typedef enum achievable_mode achievable_mode_t;

typedef struct op *          op_ptr;
typedef struct dep *         dep_ptr;
typedef struct avail_list *  avail_list_ptr;
typedef struct insn *        insn_ptr;
typedef struct loc *         loc_ptr;
typedef void *               cpu_state_ptr;
typedef struct packet *      packet_ptr;

enum dep_mode
{
  DEF_USE = 0, /* True dependency.  */
  DEF_DEF,     /* Output dependency.  */
  USE_DEF      /* Anti dependency.  */
};

typedef enum dep_mode dep_mode_t;

/* ??? The following is a packet of operations.  All operations in a
   packet start simultaneously on the same processor cycle.

   There are three types of packets:

   a) formed packet.  They refer only for formed packets through
      member `pred' and only for formed/or frontier packets through
      `succ'.  Such packets are not changed any more.

   b) frontier packet whose forming started but has not finished yet.
      They refer only for formed packets through `pred' and only for
      interior packets through `succ'.  Directed CFGs starting with
      frontier packets are always acyclic.

   c) interior packets which simply contains original ops (insns).
      One interior packet corresponds to at most one op (insn).  They
      refer only for frontier or/and interior packets through `pred'
      and only for interior packets through `succ'.  Directed CFGs
      starting with interior packets are always acyclic.  Only
      interior packets can be in list `available'.  Finally, such
      packets will be removed.

   When software pipelining starts, we have only interior packets
   which form control flow directed acyclic graph (DA CFG).  When
   software pipelining finishes, we have only formed states.  */

struct packet
{
  /* All allocated packets are chained by this member.  */
  struct packet * all_packets_chain;
  /* Unique packet number.  */
  int number;
  /* The following is TRUE if the packet is the last packet on the
     exit from the loop.  It may be more one such packet when there
     are different exits from the loop.  Stop packets contain only
     dummy operations.  */
  char stop_packet_p;
  /* The following is TRUE if the packet is actually executed only
     once in the loop (it is on an exit branch from the loop).  Stop
     packet has also value TRUE.  */
  char exit_packet_p;
  /* The following member values are TRUE if the packet is
     correspondingly frontier packet and formed packet.  */
  char frontier_packet_p;
  char formed_packet_p;
  /* The following is defined only for stop packets.  It is TRUE for
     stop packet which corresponds the first insn after the loop.  */
  int main_exit_p;
  /* The following member is used as temporary variable during
     evaluation of packet achievability.  */
  achievable_mode_t achievable_result;
  /* Allocated length of the two next arrays.  */
  int succ_length;
  int pred_length;
  /* Successors (control flow from the packet) and predecessors
   (control flow to the packet).  The end of arrays is NULL
   element.  */
  packet_ptr * succ;
  packet_ptr * pred;
  /* The following members are used to traverse packets for different
     goals (see comments for `last_packet_visit_number...').  */
  int visit_number1;
  int visit_number2;
  int visit_number3;
  int visit_number4;
  int visit_number5;
  /* The following values refer for list of ops (the first and the
     last list elements) in the packet in the same order as they were
     added to packet during scheduling.  */
  op_ptr first_op;
  op_ptr last_op;
  /* The minimal iteration number of the ops (excluding ops in exit
     packets -- remember that ops from exit packets are never moved
     into the loop) which are in packet and in its available_list.
     The original value is -1.  */
  int min_it_n;
  /* The following temporary member is used for transformation of CFG
     and DDG.  Its value is a new copy of given packet.  */
  packet_ptr copy;
  /* The following is defined only for formed packets and for the
     current frontier packet.  This is available list for the packet.
     Available list contains all operations which are movable into the
     packet and depended on only issued operations.  Lists for formed
     packets also contain operations achievable from the packet (not
     only available).  The list contains only operations with the
     iteration lookahead.  The original article is completely wrong
     that only available ops are sufficient to reflect scheduler
     states which are used to searching for repetitive op patterns.
     ??? Storing achievable ops is too expensive.  Can we decrease
     this list.  */
  avail_list_ptr avail_list;
  /* The following is a reference for structure which represents
     functional units state.  The structure is defined only for
     formed and frontier packets.  */
  cpu_state_ptr cpu_state;
  /* The following is defined only for frontier packets.  */
  packet_ptr next_frontier_packet;
  /* The following member is used to link packets (e.g. for forming
     list of copied packets).  */
  packet_ptr next_packet;
  /* The following member is relative time when ops in packet is
     issued.  The value is negative for interior packets.  */
  int issue_time;
};

/* The following describes an operation (insn).  */
struct op
{
  /* All allocated ops are chained by this member.  */
  struct op * all_ops_chain;
  /* Internal op representation.  */
  insn_ptr insn;
  /* Iteration number of the insn.  */
  int it_num;
  /* Packet to which op belongs.  */
  packet_ptr packet;
  /* The member values are packets which are targets of conditional
     branch op when the condition is correspondingly true or false.
     If op is not a branch the values are NULL.  If op is
     unconditional branch false_target is always NULL and true_target
     is always not NULL.  */
  packet_ptr true_target;
  packet_ptr false_target;
  /* Input and output data dependency arcs .*/
  dep_ptr out_deps;
  dep_ptr in_deps;
  /* The next operation in the packet.  */
  op_ptr next_op;
  /* The following member is used to form list of operations to which
     an input dependency has added.  If the value is not NULL then op
     is in the list.  */
  op_ptr next_added_in_deps_op;
  /* The following member value is not NULL only for added
     unconditional branch.  Its value is conditional branch op which
     resulted in adding this unconditional branch.  */
  op_ptr initiator_op;
  /* The following values are TRUE if op has been scheduled and if all
     its input ops have been started.  Scheduled op can not be
     ready.  */
  char scheduled_p;
  char ready_p;
  /* The following values are the previous and the next ready op with
     the same iteration.  These values are defined if scheduled_p is
     FALSE.  */
  op_ptr prev_ready_op;
  op_ptr next_ready_op;
  /* The following flag is TRUE for operations which define and use
     intersected locations.  Such operations are never considered as
     available operation requiring making CFG move consistent.
     Without such flag we will be not able to determine correctly that
     operation can be moved because we do not store dependencies
     inside operations, e.g. when operation modifies a location.  */
  char use_def_p;
 /* The following member may be FALSE only for conditional branch when
    insn makes jump onto false_target and true_target is achieved by
    fall through.  */
  char true_jump_p;
  /*** The following members are defined only for conditional branch: ***/
  /* The following member is TRUE if insn can be converted, i.e. jump
     and fall through (and as consequence condition of jump) can be
     exchanged.  */
  char can_be_converted_p;
  /* The member value is TRUE when we can not convert conditional
     branch any more because there are subsequent insns in the packet
     achieved by fall through or we fixed it when we added CFG
     consistent jumps.  The initial value is FALSE.  */
  char target_fixed_p;
  /* The following member value is TRUE if we already processed the
     conditional branch to add unconditional jumps.  Remember that in
     initial CFG we have no unconditional jumps at all.  Initial value
     is FALSE.  */
  char processed_4_consistent_jumps_p;
};

/* The following describes DDG arc.  */
struct dep
{
  /* All allocated deps are chained by this member.  */
  struct dep * all_deps_chain;
  /* Mode of data dependency.  */
  dep_mode_t dep_mode;
  /* Delay on the data dependency.  */
  int latency;
  /* Source and target of the data dependency.  */
  op_ptr from;
  op_ptr to;
  /* This is dependency on the following location in op `to'.  */
  loc_ptr to_loc;
  /* The previous and next output dependency of `from' with the same
     to_loc.  */
  dep_ptr prev_out_loc_dep;
  dep_ptr next_out_loc_dep;
  /* The prev/next in/out DDG arcs for operations `to' and `from'.  */
  dep_ptr prev_in;
  dep_ptr prev_out;
  dep_ptr next_in;
  dep_ptr next_out;
};

/* The following describes list of packets.  */
struct avail_list
{
  /* All allocated els are chained by this member.  */
  struct avail_list * all_avail_list_els_chain;
  /* The following is operation which could be moved into frontier
     packet to which the available list belongs.  */
  op_ptr op;
  /* The prev, next list element.  */
  avail_list_ptr prev_avail;
  avail_list_ptr next_avail;
  /* The following is frontier or formed packet to which given
     available list belongs.  */
  packet_ptr packet;
  /* The following member is used for sets "available".  Ops in the
     set are of only interior packets.  The member value is time until
     all data used in the operation (insn) are accessible.  */
  int delay;
  /* The following is cost of moving the op to the packet to which the
     available list belongs.  */
  int cost;
  /* The following is TRUE if we should make changes in CFG before
     moving OP into the packet.  */
  int inconsistence_p;
  /* The following member value is FALSE for achievable but available
     ops.  */
  int avail_p;
};

/* The following describes type of writting.  */
enum write_kind
{
  /* The following is obligatory writing.  */
  USUAL_WRITE = 0,
  /* The following is nonobligatory writing.  */
  POSSIBLE_WRITE,
  /* The following is write barrier, i.e. any
     writes cannot be moved through the barrier.  */
  WRITE_BARRIER
};

typedef enum write_kind write_kind_t;

/* Define this to debug RCSP.  */
#define RCSP_DEBUG

extern int iteration_look_ahead;

#ifdef RCSP_DEBUG
extern int rcsp_debug_level;
#endif

extern int last_packet_visit_number1;

extern void * rcsp_malloc  (size_t);
extern void * rcsp_realloc (void *, size_t, size_t);
extern void   rcsp_free    (void *);

struct packet;

/* Functions defined in rcsp.c and used by rscp-core.c.  */
extern int           nonbranch_p                    (insn_ptr);
extern int           uncond_branch_p                (insn_ptr);
extern int           cond_branch_p                  (insn_ptr);
extern void          convert_cond_branch            (insn_ptr);
extern insn_ptr      create_uncond_branch           (insn_ptr);
extern int           dest_packet_requires_jump_p    (struct packet *);
extern int           insn_eq_p                      (insn_ptr, insn_ptr);
extern unsigned      insn_hash                      (insn_ptr);
extern const char *  insn_name                      (insn_ptr, int);
extern int           insn_dummy_p                   (insn_ptr);
extern insn_ptr      insn_copy                      (insn_ptr);
extern int           insn_dep_time                  (insn_ptr, insn_ptr, int);
extern int           insn_risky_speculative_move_p  (insn_ptr, struct packet *);
extern void          cpu_state_reset                (cpu_state_ptr);
extern int           cpu_state_issue                (insn_ptr, cpu_state_ptr);
extern void          cpu_state_advance_cycle        (cpu_state_ptr);
extern int           cpu_state_size                 (void);
extern void          cpu_state_union                (cpu_state_ptr, cpu_state_ptr);
extern int           loc_eq_p                       (loc_ptr, loc_ptr);
extern unsigned      loc_hash                       (loc_ptr);
extern loc_ptr       loc_sub                        (loc_ptr, int);
extern loc_ptr       loc_super                      (loc_ptr, int);
extern loc_ptr       getloc                         (insn_ptr, int, int *, write_kind_t *);


/* Functions defined in rcsp-core.c and used by rscp.c.  */
extern op_ptr      op_create             (insn_ptr, int);
extern packet_ptr  packet_create         (int);
extern void        packet_append_op      (packet_ptr, op_ptr, int);
extern void        packet_connect        (packet_ptr, packet_ptr, int, int);
extern op_ptr      packet_find_branch    (packet_ptr, packet_ptr, int);
extern packet_ptr  packet_copy           (packet_ptr);
extern void        packet_change_dest    (packet_ptr, packet_ptr, packet_ptr);
extern void        packet_change_src     (packet_ptr, packet_ptr, packet_ptr);
extern packet_ptr  create_dummy_packet   (void);
extern void        start_pipeline_data   (void);
extern void        finish_pipeline_data  (void);
extern packet_ptr  pipeline              (packet_ptr, FILE *, const char *);

#endif
