/*
- * Project: libFIRM
- * File name: ir/opt/funccall.c
- * Purpose: optimization of function calls
- * Author: Michael Beck
- * Created:
- * CVS-ID: $Id$
- * Copyright: (c) 1998-2006 Universität Karlsruhe
- * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
+ * Copyright (C) 1995-2007 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 Optimization of function calls.
+ * @author Michael Beck
+ * @version $Id$
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "iroptimize.h"
+
#include "irnode_t.h"
#include "irgraph_t.h"
#include "irgmod.h"
#include "dbginfo_t.h"
#include "irflag_t.h"
#include "ircons.h"
-#include "funccall.h"
#include "irhooks.h"
/**
/**
* Collect all calls to const and pure functions
- * to lists. Collect of Proj nodes into a Proj list.
+ * to lists. Collect all Proj(Call) nodes into a Proj list.
*/
static void collect_calls(ir_node *node, void *env)
{
env_t *ctx = env;
ir_node *call, *ptr;
- entity *ent;
+ ir_entity *ent;
unsigned mode;
- if (get_irn_op(node) == op_Call) {
+ if (is_Call(node)) {
call = node;
- /* the link will be NULL for all non-const/pure calls */
+ /* set the link to NULL for all non-const/pure calls */
set_irn_link(call, NULL);
ptr = get_Call_ptr(call);
- if (get_irn_op(ptr) == op_SymConst && get_SymConst_kind(ptr) == symconst_addr_ent) {
+ if (is_SymConst(ptr) && get_SymConst_kind(ptr) == symconst_addr_ent) {
ent = get_SymConst_entity(ptr);
mode = get_entity_additional_properties(ent);
if ((mode & (mtp_property_const|mtp_property_pure)) == 0)
return;
++ctx->n_calls_removed_SymConst;
- }
- else if (is_Sel(ptr) &&
- get_irg_callee_info_state(current_ir_graph) == irg_callee_info_consistent) {
+ } else if (get_opt_closed_world() &&
+ is_Sel(ptr) &&
+ get_irg_callee_info_state(current_ir_graph) == irg_callee_info_consistent) {
/* If all possible callees are const functions, we can remove the memory edge. */
int i, n_callees = get_Call_n_callees(call);
if (n_callees == 0)
/* This is kind of strange: dying code or a Call that will raise an exception
- when executed as there is no implementation to call. So better not
- optimize. */
+ when executed as there is no implementation to call. So better not
+ optimize. */
return;
/* note that const function are a subset of pure ones */
return;
}
++ctx->n_calls_removed_Sel;
- }
- else
+ } else
return;
/* ok, if we get here we found a call to a const or a pure function */
if (mode & mtp_property_pure) {
set_irn_link(call, ctx->pure_call_list);
ctx->pure_call_list = call;
- }
- else {
+ } else {
set_irn_link(call, ctx->const_call_list);
ctx->const_call_list = call;
}
- }
- else if (get_irn_op(node) == op_Proj) {
+ } else if (is_Proj(node)) {
/*
* Collect all memory and exception Proj's from
* calls.
*/
call = get_Proj_pred(node);
- if (get_irn_op(call) != op_Call)
+ if (! is_Call(call))
return;
+ /* collect the Proj's in the Proj list */
switch (get_Proj_proj(node)) {
case pn_Call_M_regular:
case pn_Call_X_except:
break;
}
}
-} /* rem_mem_from_const_fkt_calls */
+} /* collect_calls */
/**
* Fix the list of collected Calls.
*
* @param irg the graph that contained calls to pure functions
- * @param call_list the list of all call sites of pure functions
- * @param proj_list the list of all memory/exception Projs of this call sites
+ * @param call_list the list of all call sites of const functions
+ * @param proj_list the list of all memory/exception Proj's of this call sites
*/
static void fix_const_call_list(ir_graph *irg, ir_node *call_list, ir_node *proj_list) {
ir_node *call, *next, *mem, *proj;
int exc_changed = 0;
+ ir_graph *rem = current_ir_graph;
- /* fix all calls by removing it's memory input */
+ current_ir_graph = irg;
+
+ /* First step: fix all calls by removing it's memory input.
+ It's original memory input is preserved in their link fields. */
for (call = call_list; call; call = next) {
next = get_irn_link(call);
mem = get_Call_mem(call);
hook_func_call(irg, call);
}
- /* finally fix all Proj's */
+ /* Second step: fix all Proj's */
for (proj = proj_list; proj; proj = next) {
next = get_irn_link(proj);
call = get_Proj_pred(proj);
switch (get_Proj_proj(proj)) {
case pn_Call_M_regular: {
- exchange(proj, mem);
+ /* in dead code there might be cycles where proj == mem */
+ if (proj != mem)
+ exchange(proj, mem);
} break;
case pn_Call_X_except:
case pn_Call_M_except:
/* changes were done ... */
set_irg_outs_inconsistent(irg);
- set_irg_loopinfo_state(current_ir_graph, loopinfo_cf_inconsistent);
+ set_irg_loopinfo_state(irg, loopinfo_cf_inconsistent);
if (exc_changed) {
/* ... including exception edges */
set_irg_doms_inconsistent(irg);
}
+ current_ir_graph = rem;
} /* fix_call_list */
-
+#if 0
/**
* Check if a graph represents a const function.
*
}
return 0;
} /* is_const_function */
+#endif
/* a marker */
static char _mark;
ptr = get_Call_ptr(node);
if (get_irn_op(ptr) == op_SymConst &&
get_SymConst_kind(ptr) == symconst_addr_ent) {
- entity *ent = get_SymConst_entity(ptr);
- ir_graph *irg = get_entity_irg(ent);
+ ir_entity *ent = get_SymConst_entity(ptr);
+ ir_graph *irg = get_entity_irg(ent);
if (irg == current_ir_graph) {
/* A recursive call. The did not mode depend on this call */