Commit 35a87ce1 authored by Matthias Braun's avatar Matthias Braun
Browse files

remove old+unused rta code

parent 1553e921
......@@ -105,7 +105,6 @@
#include "irtypeinfo.h"
#include "irverify.h"
#include "lowering.h"
#include "rta.h"
#include "structure.h"
#include "timing.h"
#include "trouts.h"
......
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief Interprocedural analysis to improve the call graph estimate.
* @author Florian
* @date 09.06.2002
* @version $Id$
* @brief
* (TODO translate to english)
* Intraprozedurale Analyse zur Absch�tzung der Aufrufrelation. Es wird
* die Menge der instantiierten Klassen bestimmt, und daraus eine Absch�tzung
* der aufgerufenen Methoden.
*
* Voraussetzung ist, dass das Programm keine Methodenzeiger handhaben kann.
* In diesem Fall koennten Methoden verloren gehen. Oder wir muessen nach
* allen "freien" Methoden suchen (siehe cgana).
*
* @@@ Die Analyse sollte wissen, von welchen Klassen Instanzen ausserhalb
* der Uebersetzungseinheit alloziert werden koennen. Diese muessen in
* die initiale Menge allozierter Klassen aufgenommern werden.
*
* Nach: David F. Bacon and Peter F. Sweeney,
* Fast static analysis of C++ virtual function calls
* OOPSLA 1996
*/
#ifndef FIRM_ANA_RTA_H
#define FIRM_ANA_RTA_H
#include "firm_types.h"
#include "begin.h"
/**
* Initialise the RTA data structures and perform RTA.
* Expects that all allocations are done by Alloc nodes.
*/
FIRM_API void rta_init(void);
/**
* Delete all graphs that have been found to be dead.
*/
FIRM_API void rta_delete_dead_graphs (void);
/** Clean up our data structures.
* Finishes the RTA.
*/
FIRM_API void rta_cleanup(void);
/** Returns non-zero if the given class is alive. */
FIRM_API int rta_is_alive_class(ir_type *clazz);
/** Returns non-zero if the given graph is alive. */
FIRM_API int rta_is_alive_graph(ir_graph *graph);
/** report for all graphs and types whether they are alive */
FIRM_API void rta_report(void);
#include "end.h"
#endif
......@@ -36,7 +36,6 @@
#include <string.h>
#include "cgana.h"
#include "rta.h"
#include "xmalloc.h"
#include "irnode_t.h"
......
/*
* Copyright (C) 1995-2011 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief Interprocedural analysis to improve the call graph estimate.
* @author Florian Liekweg
* @version 09.06.2002
* @version $Id$
*/
#include "config.h"
#include "rta.h"
#include <stdlib.h>
#include <stdbool.h>
#include "irnode_t.h"
#include "irprog_t.h"
#include "irgraph_t.h"
#include "pset_new.h"
#include "irgwalk.h"
#include "irgmod.h"
#include "irverify.h"
#include "irprintf.h"
#include "debug.h"
#include "error.h"
/** The debug handle. */
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
/* base data */
static pset_new_t *_live_classes = NULL;
/* cache computed results */
static pset_new_t *_live_graphs = NULL;
/**
* Add a graph to the set of live graphs.
*
* @param graph the graph to add
* @return non-zero if the graph was added, zero
* if it was already in the live set
*/
static bool add_graph(ir_graph *graph)
{
if (!pset_new_contains(_live_graphs, graph)) {
DB((dbg, LEVEL_2, "RTA: new graph of %+F\n", graph));
pset_new_insert(_live_graphs, graph);
return true;
}
return false;
}
/**
* Add a class to the set of live classes.
*
* @param clazz the class to add
* @return non-zero if the graph was added, zero
* if it was already in the live set
*/
static bool add_class(ir_type *clazz)
{
if (!pset_new_contains(_live_classes, clazz)) {
DB((dbg, LEVEL_2, "RTA: new class: %+F\n", clazz));
pset_new_insert(_live_classes, clazz);
return true;
}
return false;
}
/** Given an entity, add all implementing graphs that belong to live classes
* to _live_graphs.
*
* Iff additions occurred, return true, else false.
*/
static bool add_implementing_graphs(ir_entity *method)
{
size_t i;
size_t n_over = get_entity_n_overwrittenby(method);
ir_graph *graph = get_entity_irg(method);
bool change = false;
if (NULL == graph)
graph = get_entity_irg(method);
DB((dbg, LEVEL_2, "RTA: new call to %+F\n", method));
if (rta_is_alive_class(get_entity_owner(method))) {
if (NULL != graph)
change = add_graph(graph);
}
for (i = 0; i < n_over; ++i) {
ir_entity *over = get_entity_overwrittenby(method, i);
change |= add_implementing_graphs(over);
}
return change;
}
/**
* Walker: Enter all method accesses and all class allocations into
* our tables.
*
* Set *(int*)env to true iff (possibly) new graphs have been found.
*/
static void rta_act(ir_node *node, void *env)
{
bool *change = (bool*)env;
unsigned op = get_irn_opcode(node);
if (iro_Call == op) { /* CALL */
ir_entity *ent = NULL;
ir_node *ptr = get_Call_ptr(node);
/* CALL SEL */
if (iro_Sel == get_irn_opcode(ptr)) {
ent = get_Sel_entity(ptr);
*change |= add_implementing_graphs(ent);
/* CALL SYMCONST */
} else if (iro_SymConst == get_irn_opcode(ptr)) {
if (get_SymConst_kind(ptr) == symconst_addr_ent) {
ir_graph *graph;
ent = get_SymConst_entity(ptr);
graph = get_entity_irg(ent);
if (graph) {
*change |= add_graph(graph);
} else {
/* it's an external allocated thing. */
}
} else {
/* other symconst. */
panic("This SymConst can not be an address for a method call.");
}
/* STRANGE */
} else {
panic("Unexpected address expression: can not analyse, therefore can not do correct rta!");
}
} else if (iro_Alloc == op) { /* ALLOC */
ir_type *type = get_Alloc_type(node);
*change |= add_class(type);
}
}
/**
Traverse the given graph to collect method accesses and
object allocations.
*/
static bool rta_fill_graph(ir_graph* graph)
{
bool change = false;
irg_walk_graph(graph, rta_act, NULL, &change);
return change;
}
/**
* Traverse all graphs to collect method accesses and object allocations.
*/
static int rta_fill_incremental(void)
{
size_t i, n;
int n_runs = 0;
bool rerun = true;
/* init_tables has added main_irg to _live_graphs */
/* Need to take care of graphs that are externally
visible or sticky. Pretend that they are called: */
for (i = 0, n = get_irp_n_irgs(); i < n; ++i) {
ir_graph *graph = get_irp_irg(i);
ir_entity *ent = get_irg_entity(graph);
ir_linkage linkage = get_entity_linkage(ent);
if ((linkage & IR_LINKAGE_HIDDEN_USER) || entity_is_externally_visible(ent))
pset_new_insert(_live_graphs, graph);
}
while (rerun) {
ir_graph *graph;
pset_new_iterator_t iter;
/* start off new */
pset_new_t *live_graphs = _live_graphs;
_live_graphs = XMALLOC(pset_new_t);
pset_new_init(_live_graphs);
DB((dbg, LEVEL_2, "RTA: RUN %i\n", n_runs));
/* collect what we have found previously */
foreach_pset_new(live_graphs, ir_graph*, graph, iter) {
pset_new_insert(_live_graphs, graph);
}
rerun = false;
foreach_pset_new(live_graphs, ir_graph*, graph, iter) {
DB((dbg, LEVEL_2, "RTA: RUN %i: considering graph of %+F\n", n_runs, graph));
rerun |= rta_fill_graph(graph);
}
pset_new_destroy(live_graphs);
free(live_graphs);
++n_runs;
}
return n_runs;
}
#ifdef DEBUG_libfirm
/**
* Count the number of graphs that we have found to be live.
*/
static size_t stats(void)
{
size_t i, n;
size_t n_live_graphs = 0;
for (i = 0, n = get_irp_n_irgs(); i < n; ++i) {
ir_graph *graph = get_irp_irg(i);
if (rta_is_alive_graph(graph))
++n_live_graphs;
}
return n_live_graphs;
}
#endif
/* remove a graph, part I */
/*
We removed the first graph to implement the entity, so we're
abstract now. Pretend that it wasn't there at all, and every
entity that used to inherit this entity's graph is now abstract.
*/
/**
Initialize the static data structures.
*/
static void init_tables(void)
{
ir_graph *irg;
ir_segment_t segment;
_live_classes = XMALLOC(pset_new_t);
pset_new_init(_live_classes);
_live_graphs = XMALLOC(pset_new_t);
pset_new_init(_live_graphs);
irg = get_irp_main_irg();
if (irg != NULL) {
/* add the main irg to the live set if one is specified */
pset_new_insert(_live_graphs, irg);
}
/* Find static allocated classes in all segments */
for (segment = IR_SEGMENT_FIRST; segment <= IR_SEGMENT_LAST; ++segment) {
ir_type *tp = get_segment_type(segment);
size_t n = get_compound_n_members(tp);
size_t i;
for (i = 0; i < n; ++i) {
ir_type *member_type = get_entity_type(get_compound_member(tp, i));
if (is_Class_type(member_type))
pset_new_insert(_live_classes, member_type);
}
}
}
/*
* Initialize the RTA data structures, and perform RTA.
*/
void rta_init(void)
{
int n_runs = 0;
FIRM_DBG_REGISTER(dbg, "firm.ana.rta");
# ifdef DEBUG_libfirm
{
size_t i;
for (i = get_irp_n_irgs(); i > 0;) {
irg_verify(get_irp_irg(--i), 0);
}
tr_verify();
}
# endif /* defined DEBUG_libfirm */
init_tables();
n_runs = rta_fill_incremental();
DB((dbg, LEVEL_1, "RTA: n_graphs = %zu\n", get_irp_n_irgs()));
DB((dbg, LEVEL_1, "RTA: n_live_graphs = %zu\n", stats()));
DB((dbg, LEVEL_1, "RTA: n_runs = %i\n", n_runs));
# ifdef DEBUG_libfirm
{
size_t i;
for (i = get_irp_n_irgs(); i > 0;) {
irg_verify(get_irp_irg(--i), 0);
}
tr_verify();
}
# endif /* defined DEBUG_libfirm */
}
/**
* walker for all types and entities
*
* Changes the peculiarity of entities that represents
* dead graphs to peculiarity_description.
*/
static void make_entity_to_description(type_or_ent tore, void *env)
{
(void) env;
if (is_entity(tore.ent)) {
ir_entity *ent = tore.ent;
if ((is_Method_type(get_entity_type(ent))) &&
!entity_is_externally_visible(ent)) {
ir_graph *irg = get_entity_irg(ent);
if (irg != NULL && ! pset_new_contains(_live_graphs, irg)) {
set_entity_peculiarity(ent, peculiarity_description);
set_entity_irg(ent, NULL);
}
}
}
}
/* Delete all graphs that we have found to be dead from the program
If verbose == 1, print statistics, if > 1, chatter about every detail
*/
void rta_delete_dead_graphs(void)
{
size_t i, n_dead_irgs, n_graphs = get_irp_n_irgs();
ir_graph *irg, *next_irg, *dead_irgs;
irp_reserve_resources(irp, IRP_RESOURCE_IRG_LINK);
n_dead_irgs = 0;
dead_irgs = NULL;
for (i = n_graphs; i > 0;) {
irg = get_irp_irg(--i);
if (! rta_is_alive_graph(irg)) {
set_irg_link(irg, dead_irgs);
dead_irgs = irg;
++n_dead_irgs;
}
}
/* Hmm, probably we need to run this only if dead_irgs is non-NULL */
type_walk(make_entity_to_description, NULL, NULL);
for (irg = dead_irgs; irg != NULL; irg = next_irg) {
next_irg = (ir_graph*) get_irg_link(irg);
remove_irp_irg(irg);
}
DB((dbg, LEVEL_1, "RTA: dead methods = %zu\n", n_dead_irgs));
irp_free_resources(irp, IRP_RESOURCE_IRG_LINK);
}
/* Clean up the RTA data structures. Call this after calling rta_init */
void rta_cleanup(void)
{
# ifdef DEBUG_libfirm
size_t i;
for (i = get_irp_n_irgs(); i > 0;) {
irg_verify(get_irp_irg(--i), 0);
}
tr_verify();
# endif /* defined DEBUG_libfirm */
if (_live_classes != NULL) {
pset_new_destroy(_live_classes);
free(_live_classes);
_live_classes = NULL;
}
if (_live_graphs != NULL) {
pset_new_destroy(_live_graphs);
free(_live_graphs);
_live_graphs = NULL;
}
}
/* Say whether this class might be instantiated at any point in the program: */
int rta_is_alive_class(ir_type *clazz)
{
return pset_new_contains(_live_classes, clazz);
}
/* Say whether this graph might be run at any time in the program: */
int rta_is_alive_graph(ir_graph *graph)
{
return pset_new_contains(_live_graphs, graph);
}
/* dump our opinion */
void rta_report(void)
{
size_t i, n;
n = get_irp_n_types();
for (i = 0; i < n; ++i) {
ir_type *tp = get_irp_type(i);
if (is_Class_type(tp) && rta_is_alive_class(tp)) {
ir_printf("RTA: considered allocated: %+F\n", tp);
}
}
n = get_irp_n_irgs();
for (i = 0; i < n; i++) {
ir_graph *irg = get_irp_irg(i);
if (rta_is_alive_graph(irg)) {
ir_printf("RTA: considered called: graph of %+F\n", irg);
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment