mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-18 06:10:24 +08:00
ipa-cp.c: New file.
* ipa-cp.c: New file. Contains IPCP specific functionality. * ipa-prop.h: New file. Contains structures/definitions that can be used by several interprocedural data flow optimizations (and also IPCP). * ipa-prop.c: New file. From-SVN: r102624
This commit is contained in:
parent
ee2242a25a
commit
518dc85936
1143
gcc/ipa-cp.c
Normal file
1143
gcc/ipa-cp.c
Normal file
File diff suppressed because it is too large
Load Diff
676
gcc/ipa-prop.c
Normal file
676
gcc/ipa-prop.c
Normal file
@ -0,0 +1,676 @@
|
||||
/* Interprocedural analyses.
|
||||
Copyright (C) 2005 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 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. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tree.h"
|
||||
#include "langhooks.h"
|
||||
#include "ggc.h"
|
||||
#include "target.h"
|
||||
#include "cgraph.h"
|
||||
#include "ipa-prop.h"
|
||||
#include "tree-flow.h"
|
||||
#include "tree-pass.h"
|
||||
#include "flags.h"
|
||||
#include "timevar.h"
|
||||
|
||||
/* This file contains interfaces that can be used for various IPA
|
||||
optimizations:
|
||||
|
||||
- ipa_methodlist interface - It is used to create and handle a temporary
|
||||
worklist used in the propagation stage of IPCP. (can be used for more
|
||||
IPA optimizations).
|
||||
|
||||
- ipa_callsite interface - for each callsite this interface creates and
|
||||
handles ipa_edge structure associated with it.
|
||||
|
||||
- ipa_method interface - for each method this interface creates and
|
||||
handles ipa_node structure associated with it. */
|
||||
|
||||
/* ipa_methodlist interface. */
|
||||
|
||||
/* Create a new worklist node. */
|
||||
static inline ipa_methodlist_p
|
||||
ipa_create_methodlist_node (void)
|
||||
{
|
||||
return (ipa_methodlist_p) xcalloc (1, sizeof (struct ipa_methodlist));
|
||||
}
|
||||
|
||||
/* Return true if worklist WL is empty. */
|
||||
bool
|
||||
ipa_methodlist_not_empty (ipa_methodlist_p wl)
|
||||
{
|
||||
return (wl != NULL);
|
||||
}
|
||||
|
||||
/* Return the method in worklist element WL. */
|
||||
static inline struct cgraph_node *
|
||||
ipa_methodlist_method (ipa_methodlist_p wl)
|
||||
{
|
||||
return wl->method_p;
|
||||
}
|
||||
|
||||
/* Make worklist element WL point to method MT in the callgraph. */
|
||||
static inline void
|
||||
ipa_methodlist_method_set (ipa_methodlist_p wl, struct cgraph_node *mt)
|
||||
{
|
||||
wl->method_p = mt;
|
||||
}
|
||||
|
||||
/* Return the next element in the worklist following worklist
|
||||
element WL. */
|
||||
static inline ipa_methodlist_p
|
||||
ipa_methodlist_next_method (ipa_methodlist_p wl)
|
||||
{
|
||||
return wl->next_method;
|
||||
}
|
||||
|
||||
/* Set worklist element WL1 to point to worklist element WL2. */
|
||||
static inline void
|
||||
ipa_methodlist_next_method_set (ipa_methodlist_p wl1, ipa_methodlist_p wl2)
|
||||
{
|
||||
wl1->next_method = wl2;
|
||||
}
|
||||
|
||||
/* Initialize worklist to contain all methods. */
|
||||
ipa_methodlist_p
|
||||
ipa_methodlist_init (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
ipa_methodlist_p wl;
|
||||
|
||||
wl = NULL;
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
ipa_add_method (&wl, node);
|
||||
|
||||
return wl;
|
||||
}
|
||||
|
||||
/* Add method MT to the worklist. Set worklist element WL
|
||||
to point to MT. */
|
||||
void
|
||||
ipa_add_method (ipa_methodlist_p * wl, struct cgraph_node *mt)
|
||||
{
|
||||
ipa_methodlist_p temp;
|
||||
|
||||
temp = ipa_create_methodlist_node ();
|
||||
ipa_methodlist_method_set (temp, mt);
|
||||
ipa_methodlist_next_method_set (temp, *wl);
|
||||
*wl = temp;
|
||||
}
|
||||
|
||||
/* Remove a method from the worklist. WL points to the first
|
||||
element in the list, which is removed. */
|
||||
struct cgraph_node *
|
||||
ipa_remove_method (ipa_methodlist_p * wl)
|
||||
{
|
||||
ipa_methodlist_p first;
|
||||
struct cgraph_node *return_method;
|
||||
|
||||
first = *wl;
|
||||
*wl = ipa_methodlist_next_method (*wl);
|
||||
return_method = ipa_methodlist_method (first);
|
||||
free (first);
|
||||
return return_method;
|
||||
}
|
||||
|
||||
/* ipa_method interface. */
|
||||
|
||||
/* Return number of formals of method MT. */
|
||||
int
|
||||
ipa_method_formal_count (struct cgraph_node *mt)
|
||||
{
|
||||
return IPA_NODE_REF (mt)->ipa_arg_num;
|
||||
}
|
||||
|
||||
/* Set number of formals of method MT to I. */
|
||||
void
|
||||
ipa_method_formal_count_set (struct cgraph_node *mt, int i)
|
||||
{
|
||||
IPA_NODE_REF (mt)->ipa_arg_num = i;
|
||||
}
|
||||
|
||||
/* Return whether I-th formal of MT is modified in MT. */
|
||||
static inline bool
|
||||
ipa_method_is_modified (struct cgraph_node *mt, int i)
|
||||
{
|
||||
return IPA_NODE_REF (mt)->ipa_mod[i];
|
||||
}
|
||||
|
||||
/* Return the tree of I-th formal of MT. */
|
||||
tree
|
||||
ipa_method_get_tree (struct cgraph_node *mt, int i)
|
||||
{
|
||||
return IPA_NODE_REF (mt)->ipa_param_tree[i];
|
||||
}
|
||||
|
||||
/* Create tree map structure for MT. */
|
||||
static inline void
|
||||
ipa_method_tree_map_create (struct cgraph_node *mt)
|
||||
{
|
||||
IPA_NODE_REF (mt)->ipa_param_tree =
|
||||
xcalloc (ipa_method_formal_count (mt), sizeof (tree));
|
||||
}
|
||||
|
||||
/* Create modify structure for MT. */
|
||||
static inline void
|
||||
ipa_method_modify_create (struct cgraph_node *mt)
|
||||
{
|
||||
((struct ipa_node *) mt->aux)->ipa_mod =
|
||||
xcalloc (ipa_method_formal_count (mt), sizeof (bool));
|
||||
}
|
||||
|
||||
/* Set modify of I-th formal of MT to VAL. */
|
||||
static inline void
|
||||
ipa_method_modify_set (struct cgraph_node *mt, int i, bool val)
|
||||
{
|
||||
IPA_NODE_REF (mt)->ipa_mod[i] = val;
|
||||
}
|
||||
|
||||
/* Return index of the formal whose tree is PTREE in method MT. */
|
||||
static int
|
||||
ipa_method_tree_map (struct cgraph_node *mt, tree ptree)
|
||||
{
|
||||
int i, count;
|
||||
|
||||
count = ipa_method_formal_count (mt);
|
||||
for (i = 0; i < count; i++)
|
||||
if (IPA_NODE_REF (mt)->ipa_param_tree[i] == ptree)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Insert the formal trees to the ipa_param_tree array in method MT. */
|
||||
void
|
||||
ipa_method_compute_tree_map (struct cgraph_node *mt)
|
||||
{
|
||||
tree fndecl;
|
||||
tree fnargs;
|
||||
tree parm;
|
||||
int param_num;
|
||||
|
||||
ipa_method_tree_map_create (mt);
|
||||
fndecl = mt->decl;
|
||||
fnargs = DECL_ARGUMENTS (fndecl);
|
||||
param_num = 0;
|
||||
for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
|
||||
{
|
||||
IPA_NODE_REF (mt)->ipa_param_tree[param_num] = parm;
|
||||
param_num++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Count number of formals in MT. Insert the result to the
|
||||
ipa_node. */
|
||||
void
|
||||
ipa_method_formal_compute_count (struct cgraph_node *mt)
|
||||
{
|
||||
tree fndecl;
|
||||
tree fnargs;
|
||||
tree parm;
|
||||
int param_num;
|
||||
|
||||
fndecl = mt->decl;
|
||||
fnargs = DECL_ARGUMENTS (fndecl);
|
||||
param_num = 0;
|
||||
for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
|
||||
param_num++;
|
||||
ipa_method_formal_count_set (mt, param_num);
|
||||
}
|
||||
|
||||
/* Check STMT to detect whether a formal is modified within MT,
|
||||
the appropriate entry is updated in the ipa_mod array of ipa_node
|
||||
(associated with MT). */
|
||||
static void
|
||||
ipa_method_modify_stmt (struct cgraph_node *mt, tree stmt)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
switch (TREE_CODE (stmt))
|
||||
{
|
||||
case MODIFY_EXPR:
|
||||
if (TREE_CODE (TREE_OPERAND (stmt, 0)) == PARM_DECL)
|
||||
{
|
||||
i = ipa_method_tree_map (mt, TREE_OPERAND (stmt, 0));
|
||||
if (i >= 0)
|
||||
ipa_method_modify_set (mt, i, true);
|
||||
}
|
||||
break;
|
||||
case ASM_EXPR:
|
||||
/* Asm code could modify any of the parameters. */
|
||||
for (j = 0; j < ipa_method_formal_count (mt); j++)
|
||||
ipa_method_modify_set (mt, j, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize ipa_mod array of MT. */
|
||||
static void
|
||||
ipa_method_modify_init (struct cgraph_node *mt)
|
||||
{
|
||||
int i, count;
|
||||
|
||||
ipa_method_modify_create (mt);
|
||||
count = ipa_method_formal_count (mt);
|
||||
for (i = 0; i < count; i++)
|
||||
ipa_method_modify_set (mt, i, false);
|
||||
}
|
||||
|
||||
/* The modify computation driver for MT. Compute which formal arguments
|
||||
of method MT are locally modified. Formals may be modified in MT
|
||||
if their address is taken, or if
|
||||
they appear on the left hand side of an assignment. */
|
||||
void
|
||||
ipa_method_compute_modify (struct cgraph_node *mt)
|
||||
{
|
||||
tree decl;
|
||||
tree body;
|
||||
int j, count;
|
||||
basic_block bb;
|
||||
struct function *func;
|
||||
block_stmt_iterator bsi;
|
||||
tree stmt, parm_tree;
|
||||
|
||||
ipa_method_modify_init (mt);
|
||||
decl = mt->decl;
|
||||
count = ipa_method_formal_count (mt);
|
||||
/* ??? Handle pending sizes case. Set all parameters
|
||||
of the method to be modified. */
|
||||
if (DECL_UNINLINABLE (decl))
|
||||
{
|
||||
for (j = 0; j < count; j++)
|
||||
ipa_method_modify_set (mt, j, true);
|
||||
return;
|
||||
}
|
||||
/* Formals whose address is taken are considered modified. */
|
||||
for (j = 0; j < count; j++)
|
||||
{
|
||||
parm_tree = ipa_method_get_tree (mt, j);
|
||||
if (TREE_ADDRESSABLE (parm_tree))
|
||||
ipa_method_modify_set (mt, j, true);
|
||||
}
|
||||
body = DECL_SAVED_TREE (decl);
|
||||
if (body != NULL)
|
||||
{
|
||||
func = DECL_STRUCT_FUNCTION (decl);
|
||||
FOR_EACH_BB_FN (bb, func)
|
||||
{
|
||||
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
|
||||
{
|
||||
stmt = bsi_stmt (bsi);
|
||||
ipa_method_modify_stmt (mt, stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ipa_callsite interface. */
|
||||
|
||||
/* Return number of arguments in callsite CS. */
|
||||
int
|
||||
ipa_callsite_param_count (struct cgraph_edge *cs)
|
||||
{
|
||||
return IPA_EDGE_REF (cs)->ipa_param_num;
|
||||
}
|
||||
|
||||
/* Set number of arguments in callsite CS to I. */
|
||||
void
|
||||
ipa_callsite_param_count_set (struct cgraph_edge *cs, int i)
|
||||
{
|
||||
IPA_EDGE_REF (cs)->ipa_param_num = i;
|
||||
}
|
||||
|
||||
/* Return the jump function (ipa_jump_func struct) for argument I of
|
||||
callsite CS. */
|
||||
struct ipa_jump_func *
|
||||
ipa_callsite_param (struct cgraph_edge *cs, int i)
|
||||
{
|
||||
return &(IPA_EDGE_REF (cs)->ipa_param_map[i]);
|
||||
}
|
||||
|
||||
/* return the callee (cgraph_node) of callsite CS. */
|
||||
struct cgraph_node *
|
||||
ipa_callsite_callee (struct cgraph_edge *cs)
|
||||
{
|
||||
return cs->callee;
|
||||
}
|
||||
|
||||
/* Set field 'type' of jump function (ipa_jump_func struct) of argument I
|
||||
in callsite CS. */
|
||||
static inline void
|
||||
ipa_callsite_param_set_type (struct cgraph_edge *cs, int i,
|
||||
enum jump_func_type type1)
|
||||
{
|
||||
IPA_EDGE_REF (cs)->ipa_param_map[i].type = type1;
|
||||
}
|
||||
|
||||
/* Set FORMAL as 'info_type' field of jump function (ipa_jump_func struct)
|
||||
of argument I of callsite CS. */
|
||||
static inline void
|
||||
ipa_callsite_param_set_info_type_formal (struct cgraph_edge *cs, int i,
|
||||
unsigned int formal)
|
||||
{
|
||||
ipa_callsite_param (cs, i)->info_type.formal_id = formal;
|
||||
}
|
||||
|
||||
/* Set int-valued INFO_TYPE1 as 'info_type' field of
|
||||
jump function (ipa_jump_func struct) of argument I of callsite CS. */
|
||||
static inline void
|
||||
ipa_callsite_param_set_info_type (struct cgraph_edge *cs, int i, tree info_type1)
|
||||
{
|
||||
ipa_callsite_param (cs, i)->info_type.value = info_type1;
|
||||
}
|
||||
|
||||
/* Allocate space for callsite CS. */
|
||||
static inline void
|
||||
ipa_callsite_param_map_create (struct cgraph_edge *cs)
|
||||
{
|
||||
IPA_EDGE_REF (cs)->ipa_param_map =
|
||||
xcalloc (ipa_callsite_param_count (cs), sizeof (struct ipa_jump_func));
|
||||
}
|
||||
|
||||
/* Return the call expr tree related to callsite CS. */
|
||||
static inline tree
|
||||
ipa_callsite_tree (struct cgraph_edge *cs)
|
||||
{
|
||||
return cs->call_stmt;
|
||||
}
|
||||
|
||||
/* Return the caller (cgraph_node) of CS. */
|
||||
static inline struct cgraph_node *
|
||||
ipa_callsite_caller (struct cgraph_edge *cs)
|
||||
{
|
||||
return cs->caller;
|
||||
}
|
||||
|
||||
/* Count number of arguments callsite CS has and store it in
|
||||
ipa_edge structure corresponding to this callsite. */
|
||||
void
|
||||
ipa_callsite_compute_count (struct cgraph_edge *cs)
|
||||
{
|
||||
tree call_tree;
|
||||
tree arg;
|
||||
int arg_num;
|
||||
|
||||
call_tree = get_call_expr_in (ipa_callsite_tree (cs));
|
||||
gcc_assert (TREE_CODE (call_tree) == CALL_EXPR);
|
||||
arg = TREE_OPERAND (call_tree, 1);
|
||||
arg_num = 0;
|
||||
for (; arg != NULL_TREE; arg = TREE_CHAIN (arg))
|
||||
arg_num++;
|
||||
ipa_callsite_param_count_set (cs, arg_num);
|
||||
}
|
||||
|
||||
/* Compute jump function for all arguments of callsite CS
|
||||
and insert the information in the ipa_param_map array
|
||||
in the ipa_edge corresponding to this callsite. (Explanation
|
||||
on jump functions is in ipa-prop.h). */
|
||||
void
|
||||
ipa_callsite_compute_param (struct cgraph_edge *cs)
|
||||
{
|
||||
tree call_tree;
|
||||
tree arg, cst_decl, arg_type, formal_type;
|
||||
int arg_num;
|
||||
int i;
|
||||
struct cgraph_node *mt;
|
||||
|
||||
if (ipa_callsite_param_count (cs) == 0)
|
||||
return;
|
||||
ipa_callsite_param_map_create (cs);
|
||||
call_tree = get_call_expr_in (ipa_callsite_tree (cs));
|
||||
gcc_assert (TREE_CODE (call_tree) == CALL_EXPR);
|
||||
arg = TREE_OPERAND (call_tree, 1);
|
||||
arg_num = 0;
|
||||
|
||||
for (; arg != NULL_TREE; arg = TREE_CHAIN (arg))
|
||||
{
|
||||
/* If the formal parameter was passed as argument, we store
|
||||
FORMAL_IPATYPE and its index in the caller as the jump function
|
||||
of this argument. */
|
||||
if (TREE_CODE (TREE_VALUE (arg)) == PARM_DECL)
|
||||
{
|
||||
mt = ipa_callsite_caller (cs);
|
||||
i = ipa_method_tree_map (mt, TREE_VALUE (arg));
|
||||
if (i < 0 || ipa_method_is_modified (mt, i))
|
||||
ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE);
|
||||
else
|
||||
{
|
||||
arg_type = TREE_TYPE (TREE_VALUE (arg));
|
||||
formal_type = TREE_TYPE (ipa_method_get_tree (cs->callee, arg_num));
|
||||
if (TYPE_NAME (arg_type) == TYPE_NAME (formal_type)
|
||||
&& TYPE_CONTEXT (arg_type) == TYPE_CONTEXT (formal_type)
|
||||
&& attribute_list_equal (TYPE_ATTRIBUTES (arg_type),
|
||||
TYPE_ATTRIBUTES (formal_type)))
|
||||
{
|
||||
ipa_callsite_param_set_type (cs, arg_num, FORMAL_IPATYPE);
|
||||
ipa_callsite_param_set_info_type_formal (cs, arg_num, i);
|
||||
}
|
||||
else
|
||||
ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE);
|
||||
}
|
||||
}
|
||||
/* If a constant value was passed as argument,
|
||||
we store CONST_IPATYPE and its value as the jump function
|
||||
of this argument. */
|
||||
else if (TREE_CODE (TREE_VALUE (arg)) == INTEGER_CST
|
||||
|| TREE_CODE (TREE_VALUE (arg)) == REAL_CST)
|
||||
{
|
||||
arg_type = TREE_TYPE (TREE_VALUE (arg));
|
||||
formal_type = TREE_TYPE (ipa_method_get_tree (cs->callee, arg_num));
|
||||
if (TYPE_NAME (arg_type) == TYPE_NAME (formal_type)
|
||||
&& TYPE_CONTEXT (arg_type) == TYPE_CONTEXT (formal_type)
|
||||
&& attribute_list_equal (TYPE_ATTRIBUTES (arg_type),
|
||||
TYPE_ATTRIBUTES (formal_type)))
|
||||
{
|
||||
ipa_callsite_param_set_type (cs, arg_num, CONST_IPATYPE);
|
||||
ipa_callsite_param_set_info_type (cs, arg_num, TREE_VALUE (arg));
|
||||
}
|
||||
else
|
||||
ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE);
|
||||
}
|
||||
/* This is for the case of Fortran. If the address of a const_decl
|
||||
was passed as argument then we store
|
||||
CONST_IPATYPE_REF/CONST_IPATYPE_REF and the costant
|
||||
value as the jump function corresponding to this argument. */
|
||||
else if (TREE_CODE (TREE_VALUE (arg)) == ADDR_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (TREE_VALUE (arg), 0)) ==
|
||||
CONST_DECL)
|
||||
{
|
||||
cst_decl = TREE_OPERAND (TREE_VALUE (arg), 0);
|
||||
arg_type = TREE_TYPE (DECL_INITIAL (cst_decl));
|
||||
formal_type =
|
||||
TREE_TYPE (TREE_TYPE (ipa_method_get_tree (cs->callee, arg_num)));
|
||||
if (TREE_CODE (DECL_INITIAL (cst_decl)) == INTEGER_CST
|
||||
|| TREE_CODE (DECL_INITIAL (cst_decl)) == REAL_CST)
|
||||
{
|
||||
if (TYPE_NAME (arg_type) == TYPE_NAME (formal_type)
|
||||
&& TYPE_CONTEXT (arg_type) == TYPE_CONTEXT (formal_type)
|
||||
&& attribute_list_equal (TYPE_ATTRIBUTES (arg_type),
|
||||
TYPE_ATTRIBUTES (formal_type)))
|
||||
|
||||
{
|
||||
ipa_callsite_param_set_type (cs, arg_num,
|
||||
CONST_IPATYPE_REF);
|
||||
ipa_callsite_param_set_info_type (cs, arg_num, DECL_INITIAL (cst_decl));
|
||||
|
||||
}
|
||||
else
|
||||
ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE);
|
||||
}
|
||||
}
|
||||
else
|
||||
ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE);
|
||||
arg_num++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return type of jump function JF. */
|
||||
enum jump_func_type
|
||||
get_type (struct ipa_jump_func *jf)
|
||||
{
|
||||
return jf->type;
|
||||
}
|
||||
|
||||
/* Return info type of jump function JF. */
|
||||
union parameter_info *
|
||||
ipa_jf_get_info_type (struct ipa_jump_func *jf)
|
||||
{
|
||||
return &(jf->info_type);
|
||||
}
|
||||
|
||||
/* Allocate and initialize ipa_node structure.
|
||||
cgraph_node NODE points to the new allocated ipa_node. */
|
||||
void
|
||||
ipa_node_create (struct cgraph_node *node)
|
||||
{
|
||||
node->aux = xcalloc (1, sizeof (struct ipa_node));
|
||||
}
|
||||
|
||||
/* Allocate and initialize ipa_node structure for all
|
||||
nodes in callgraph. */
|
||||
void
|
||||
ipa_nodes_create (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
ipa_node_create (node);
|
||||
}
|
||||
|
||||
/* Allocate and initialize ipa_edge structure. */
|
||||
void
|
||||
ipa_edges_create (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
struct cgraph_edge *cs;
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
for (cs = node->callees; cs; cs = cs->next_callee)
|
||||
cs->aux = xcalloc (1, sizeof (struct ipa_edge));
|
||||
}
|
||||
|
||||
/* Free ipa_node structure. */
|
||||
void
|
||||
ipa_nodes_free (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
free (node->aux);
|
||||
node->aux = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free ipa_edge structure. */
|
||||
void
|
||||
ipa_edges_free (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
struct cgraph_edge *cs;
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
for (cs = node->callees; cs; cs = cs->next_callee)
|
||||
{
|
||||
free (cs->aux);
|
||||
cs->aux = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free ipa data structures of ipa_node and ipa_edge. */
|
||||
void
|
||||
ipa_free (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
struct cgraph_edge *cs;
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
if (node->aux == NULL)
|
||||
continue;
|
||||
if (IPA_NODE_REF (node)->ipcp_cval)
|
||||
free (IPA_NODE_REF (node)->ipcp_cval);
|
||||
if (IPA_NODE_REF (node)->ipa_param_tree)
|
||||
free (IPA_NODE_REF (node)->ipa_param_tree);
|
||||
if (IPA_NODE_REF (node)->ipa_mod)
|
||||
free (IPA_NODE_REF (node)->ipa_mod);
|
||||
for (cs = node->callees; cs; cs = cs->next_callee)
|
||||
{
|
||||
if (cs->aux)
|
||||
if (IPA_EDGE_REF (cs)->ipa_param_map)
|
||||
free (IPA_EDGE_REF (cs)->ipa_param_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Print ipa_tree_map data structures of all methods in the
|
||||
callgraph to F. */
|
||||
void
|
||||
ipa_method_tree_print (FILE * f)
|
||||
{
|
||||
int i, count;
|
||||
tree temp;
|
||||
struct cgraph_node *node;
|
||||
|
||||
fprintf (f, "\nPARAM TREE MAP PRINT\n");
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
fprintf (f, "method %s Trees :: \n", cgraph_node_name (node));
|
||||
count = ipa_method_formal_count (node);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
temp = ipa_method_get_tree (node, i);
|
||||
if (TREE_CODE (temp) == PARM_DECL)
|
||||
fprintf (f, " param [%d] : %s\n", i,
|
||||
(*lang_hooks.decl_printable_name) (temp, 2));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Print ipa_modify data structures of all methods in the
|
||||
callgraph to F. */
|
||||
void
|
||||
ipa_method_modify_print (FILE * f)
|
||||
{
|
||||
int i, count;
|
||||
bool temp;
|
||||
struct cgraph_node *node;
|
||||
|
||||
fprintf (f, "\nMODIFY PRINT\n");
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
fprintf (f, "method %s :: \n", cgraph_node_name (node));
|
||||
count = ipa_method_formal_count (node);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
temp = ipa_method_is_modified (node, i);
|
||||
if (temp)
|
||||
fprintf (f, " param [%d] true \n", i);
|
||||
else
|
||||
fprintf (f, " param [%d] false \n", i);
|
||||
}
|
||||
}
|
||||
}
|
204
gcc/ipa-prop.h
Normal file
204
gcc/ipa-prop.h
Normal file
@ -0,0 +1,204 @@
|
||||
/* Interprocedural analyses.
|
||||
Copyright (C) 2005 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 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 IPA_PROP_H
|
||||
#define IPA_PROP_H
|
||||
|
||||
#include "tree.h"
|
||||
|
||||
/* The following definitions and interfaces are used by
|
||||
interprocedural analyses. */
|
||||
|
||||
/* A jump function for a callsite represents the values passed as actual
|
||||
arguments of the callsite. There are three main types of values :
|
||||
Formal - the caller's formal parameter is passed as an actual argument.
|
||||
Constant - a constant is passed as a an actual argument.
|
||||
Unknown - neither of the above.
|
||||
Integer and real constants are represented as CONST_IPATYPE and Fortran
|
||||
constants are represented as CONST_IPATYPE_REF. */
|
||||
enum jump_func_type
|
||||
{
|
||||
UNKNOWN_IPATYPE,
|
||||
CONST_IPATYPE,
|
||||
CONST_IPATYPE_REF,
|
||||
FORMAL_IPATYPE
|
||||
};
|
||||
|
||||
/* All formal parameters in the program have a cval computed by
|
||||
the interprocedural stage of IPCP.
|
||||
There are three main values of cval :
|
||||
TOP - unknown.
|
||||
BOTTOM - non constant.
|
||||
CONSTANT_TYPE - constant value.
|
||||
Cval of formal f will have a constant value if all callsites to this
|
||||
function have the same constant value passed to f.
|
||||
Integer and real constants are represented as CONST_IPATYPE and Fortran
|
||||
constants are represented as CONST_IPATYPE_REF. */
|
||||
enum cvalue_type
|
||||
{
|
||||
BOTTOM,
|
||||
CONST_VALUE,
|
||||
CONST_VALUE_REF,
|
||||
TOP
|
||||
};
|
||||
|
||||
/* Represents the value of either jump function or cval.
|
||||
value represnts a constant.
|
||||
formal_id is used only in jump function context and represents
|
||||
pass-through parameter (the formal of caller is passed
|
||||
as argument). */
|
||||
union parameter_info
|
||||
{
|
||||
unsigned int formal_id;
|
||||
tree value;
|
||||
};
|
||||
|
||||
/* A jump function for a callsite represents the values passed as actual
|
||||
arguments of the callsite. See enum jump_func_type for the various
|
||||
types of jump functions supported. */
|
||||
struct ipa_jump_func
|
||||
{
|
||||
enum jump_func_type type;
|
||||
union parameter_info info_type;
|
||||
};
|
||||
|
||||
/* All formal parameters in the program have a cval computed by
|
||||
the interprocedural stage of IPCP. See enum cvalue_type for
|
||||
the various types of cvals supported */
|
||||
struct ipcp_formal
|
||||
{
|
||||
enum cvalue_type cval_type;
|
||||
union parameter_info cvalue;
|
||||
};
|
||||
|
||||
/* Represent which DECL tree (or reference to such tree)
|
||||
will be replaced by another tree while versioning. */
|
||||
struct ipa_replace_map
|
||||
{
|
||||
/* The tree that will be replaced. */
|
||||
tree old_tree;
|
||||
/* The new (replacing) tree. */
|
||||
tree new_tree;
|
||||
/* True when a substitution should be done, false otherwise. */
|
||||
bool replace_p;
|
||||
/* True when we replace a reference to old_tree. */
|
||||
bool ref_p;
|
||||
};
|
||||
|
||||
/* Return the field in cgraph_node/cgraph_edge struct that points
|
||||
to ipa_node/ipa_edge struct. */
|
||||
#define IPA_NODE_REF(MT) ((struct ipa_node *)(MT)->aux)
|
||||
#define IPA_EDGE_REF(EDGE) ((struct ipa_edge *)(EDGE)->aux)
|
||||
|
||||
/* ipa_node stores information related to a method and
|
||||
its formal parameters. It is pointed to by a field in the
|
||||
method's corresponding cgraph_node.
|
||||
|
||||
ipa_edge stores information related to a callsite and
|
||||
its arguments. It is pointed to by a field in the
|
||||
callsite's corresponding cgraph_edge. */
|
||||
struct ipa_node
|
||||
{
|
||||
/* Number of formal parameters of this method. When set to 0,
|
||||
this method's parameters would not be analyzed by the different
|
||||
stages of IPA CP. */
|
||||
int ipa_arg_num;
|
||||
/* Array of cvals. */
|
||||
struct ipcp_formal *ipcp_cval;
|
||||
/* Mapping each parameter to its PARM_DECL tree. */
|
||||
tree *ipa_param_tree;
|
||||
/* Indicating which parameter is modified in its method. */
|
||||
bool *ipa_mod;
|
||||
/* Only for versioned nodes this field would not be NULL,
|
||||
it points to the node that IPA cp cloned from. */
|
||||
struct cgraph_node *ipcp_orig_node;
|
||||
/* Meaningful only for original methods. Expresses the
|
||||
ratio between the direct calls and sum of all invocations of
|
||||
this function (given by profiling info). It is used to calculate
|
||||
the profiling information of the original function and the versioned
|
||||
one. */
|
||||
gcov_type count_scale;
|
||||
};
|
||||
|
||||
struct ipa_edge
|
||||
{
|
||||
/* Number of actual arguments in this callsite. When set to 0,
|
||||
this callsite's parameters would not be analyzed by the different
|
||||
stages of IPA CP. */
|
||||
int ipa_param_num;
|
||||
/* Array of the callsite's jump function of each parameter. */
|
||||
struct ipa_jump_func *ipa_param_map;
|
||||
};
|
||||
|
||||
/* A methodlist element (referred to also as methodlist node). It is used
|
||||
to create a temporary worklist used in
|
||||
the propagation stage of IPCP. (can be used for more IPA
|
||||
optimizations) */
|
||||
struct ipa_methodlist
|
||||
{
|
||||
struct cgraph_node *method_p;
|
||||
struct ipa_methodlist *next_method;
|
||||
};
|
||||
|
||||
/* A pointer to a methodlist elemement. */
|
||||
typedef struct ipa_methodlist *ipa_methodlist_p;
|
||||
|
||||
/* ipa_methodlist interface. */
|
||||
ipa_methodlist_p ipa_methodlist_init (void);
|
||||
bool ipa_methodlist_not_empty (ipa_methodlist_p);
|
||||
void ipa_add_method (ipa_methodlist_p *, struct cgraph_node *);
|
||||
struct cgraph_node *ipa_remove_method (ipa_methodlist_p *);
|
||||
|
||||
/* ipa_callsite interface. */
|
||||
int ipa_callsite_param_count (struct cgraph_edge *);
|
||||
void ipa_callsite_param_count_set (struct cgraph_edge *, int);
|
||||
struct ipa_jump_func *ipa_callsite_param (struct cgraph_edge *, int);
|
||||
struct cgraph_node *ipa_callsite_callee (struct cgraph_edge *);
|
||||
void ipa_callsite_compute_param (struct cgraph_edge *);
|
||||
void ipa_callsite_compute_count (struct cgraph_edge *);
|
||||
|
||||
/* ipa_method interface. */
|
||||
int ipa_method_formal_count (struct cgraph_node *);
|
||||
void ipa_method_formal_count_set (struct cgraph_node *, int);
|
||||
tree ipa_method_get_tree (struct cgraph_node *, int);
|
||||
void ipa_method_compute_tree_map (struct cgraph_node *);
|
||||
void ipa_method_formal_compute_count (struct cgraph_node *);
|
||||
void ipa_method_compute_modify (struct cgraph_node *);
|
||||
|
||||
/* jump function interface. */
|
||||
enum jump_func_type get_type (struct ipa_jump_func *);
|
||||
union parameter_info *ipa_jf_get_info_type (struct ipa_jump_func *);
|
||||
|
||||
/* ipa_node and ipa_edge interfaces. */
|
||||
void ipa_node_create (struct cgraph_node *);
|
||||
void ipa_free (void);
|
||||
void ipa_nodes_create (void);
|
||||
void ipa_edges_create (void);
|
||||
void ipa_edges_free (void);
|
||||
void ipa_nodes_free (void);
|
||||
|
||||
|
||||
/* Debugging interface. */
|
||||
void ipa_method_tree_print (FILE *);
|
||||
void ipa_method_modify_print (FILE *);
|
||||
|
||||
void ipcp_driver (void);
|
||||
|
||||
#endif /* IPA_PROP_H */
|
Loading…
x
Reference in New Issue
Block a user