quakeforge/tools/qfcc/include/dags.h
Bill Currie d8a78fc849 [qfcc] Handle aliased temps better
Because the aliases were treated as live, every alias of a temp resulted
in an assignment, which proved to be quite significant (4-5 assignments
in some simple GA expressions). By using an alias node in the dag, the
unaliased temp can be marked live while the alias is treated as an
operation rather than an operand. Now my GA expressions have no
superfluous assignments (generally no assignments at all).
2023-09-01 11:59:47 +09:00

119 lines
4 KiB
C

/*
dags.h
DAG representation of basic blocks
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2012/05/08
This program 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
of the License, or (at your option) any later version.
This program 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 this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef dags_h
#define dags_h
/** \defgroup qfcc_dags DAG building
\ingroup qfcc
*/
///@{
#include "QF/progs/pr_comp.h"
#include "statements.h"
struct dstring_s;
struct flownode_s;
typedef struct daglabel_s {
struct daglabel_s *next;
struct daglabel_s *daglabel_chain; ///< all labels created for a dag
int number; ///< index into array of labels in dag_t
unsigned live:1; ///< accessed via an alias FIXME redundant?
const char *opcode; ///< not if op
struct operand_s *op; ///< not if opcode;
struct dagnode_s *dagnode; ///< node with which this label is associated
struct expr_s *expr; ///< expression associated with this label
} daglabel_t;
typedef struct dagnode_s {
struct dagnode_s *next;
int number; ///< index into array of nodes in dag_t
int topo; ///< topological sort order
struct set_s *parents; ///< empty if root node
int cost; ///< cost of this node in temp vars
struct dagnode_s *killed; ///< node is unavailable for cse (by node)
st_type_t type; ///< type of node (st_none = leaf)
daglabel_t *label; ///< ident/const if leaf node, or operator
struct type_s *tl;
struct operand_s *value; ///< operand holding the value of this node
/// \name child nodes
/// if \a children[0] is null, the rest must be null as well. Similar for
/// \a children[1].
///
/// \a edges is the set of all nodes upon which this node depends. ie,
/// they must be evaluated before this node is evaluted. So while nodes
/// in \a edges may not be true children of this node, they are effective
/// children in the DAG. That is, \a edges is for producing a correct
/// topological sort of the DAG.
//@{
struct dagnode_s *children[3];
struct type_s *types[3]; ///< desired type of each operand (to alias)
struct set_s *edges; ///< includes nodes pointed to by \a children
int offset; ///< for alias nodes
//@}
struct set_s *identifiers; ///< set of identifiers attached to this node
struct set_s *reachable; ///< set of nodes reachable via edges (not
///< parents) for ensuring cycles are not
///< created
} dagnode_t;
typedef struct dag_s {
struct dag_s *next;
dagnode_t **nodes; ///< array of all dagnodes in this dag
int num_nodes;
int *topo; ///< nodes in topological sort order
int num_topo; ///< number of nodes in topo (may be <
///< num_nodes after dead node removal)
daglabel_t **labels; ///< array of all daglabels in this dag
int num_labels;
struct set_s *roots; ///< set of root nodes
struct flownode_s *flownode;///< flow node this dag represents
} dag_t;
const char *daglabel_string (daglabel_t *label);
void print_dag (struct dstring_s *dstr, dag_t *dag, const char *label);
void dot_dump_dag (void *_dag, const char *filename);
/** Make a dag for a single basic block.
\param flownode The flow graph node representing the basic block for which
the dag will be created. The node should have its live
variable information already computed.
\return The dag representing the basic block.
*/
dag_t *dag_create (struct flownode_s *flownode);
void dag_remove_dead_nodes (dag_t *dag);
void dag_generate (dag_t *dag, sblock_t *block);
///@}
#endif//dags_h