3 * File name: ir/opt/ldstopt.c
4 * Purpose: optimization of function calls
5 * Author: Michael M. Beck
8 * Copyright: (c) 1998-2004 Universität Karlsruhe
9 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
12 #include "irgraph_t.h"
16 #include "dbginfo_t.h"
24 * The walker environment for rem_mem_from_real_fkt_calls
26 typedef struct _env_t {
27 eset *pure_fkt; /**< set containing all real functions */
28 int changed; /**< flag, is set if a graph was changed */
29 int n_calls_removed_SymConst;
30 int n_calls_removed_Sel;
34 * remove memory from real function calls by rerouting
35 * it's ProjM and connection the call with a NoMem node.
37 * Note: By "real function" we understand a function that did neither
38 * read nor write memory.
40 static void rem_mem_from_real_fkt_calls(ir_node *node, void *env)
43 ir_node *call, *ptr, *mem;
46 if (get_irn_op(node) == op_Call) {
49 set_irn_link(call, NULL);
51 ptr = get_Call_ptr(call);
52 if (get_irn_op(ptr) == op_SymConst && get_SymConst_kind(ptr) == symconst_addr_ent) {
54 ent = get_SymConst_entity(ptr);
56 if (! eset_contains(ctx->pure_fkt, ent))
58 ctx->n_calls_removed_SymConst++;
60 else if (get_irn_op(ptr) == op_Sel &&
61 get_irg_callee_info_state(current_ir_graph) == irg_callee_info_consistent) {
62 /* If all possible callees are real functions, we can remove the memory edge. */
63 int i, n_callees = get_Call_n_callees(call);
65 /* This is kind of strange: dying code or a Call that will raise an exception
66 when executed as there is no implementation to call. So better not
69 for (i = 0; i < n_callees; ++i) {
70 if (! eset_contains(ctx->pure_fkt, get_Call_callee(call, i)))
73 ctx->n_calls_removed_Sel++;
77 /* ok, if we get here we found a call to a pure function,
78 * route the NoMem node to the call */
79 mem = get_Call_mem(call);
81 set_irn_link(call, mem);
82 set_Call_mem(call, new_r_NoMem(current_ir_graph));
84 /* finally, this call can float */
85 set_irn_pinned(call, op_pin_state_floats);
87 hook_func_call(current_ir_graph, call);
90 } else if (get_irn_op(node) == op_Proj) {
91 call = get_Proj_pred(node);
92 if ((get_irn_op(call) != op_Call) ||
93 (get_irn_op(get_Call_mem(call)) != op_NoMem))
96 switch(get_Proj_proj(node)) {
97 case pn_Call_M_regular: {
98 ir_node *old_mem = get_irn_link(call);
99 if (old_mem) exchange(node, old_mem);
101 case pn_Call_X_except:
102 case pn_Call_M_except:
103 exchange(node, new_Bad());
111 * optimize function calls by handling real functions
113 void optimize_funccalls(void)
117 unsigned num_pure = 0;
118 eset *pure_fkt = eset_create();
120 if (! get_opt_real_func_call())
123 /* first step: detect, which functions are pure, i.e. do NOT change any memory */
124 for (i = 0, n = get_irp_n_irgs(); i < n; ++i) {
125 ir_graph *irg = get_irp_irg(i);
126 ir_node *end = get_irg_end(irg);
127 ir_node *endbl = get_nodes_block(end);
131 /* visit every Return */
132 for (j = 0, k = get_Block_n_cfgpreds(endbl); j < k; ++j) {
133 ir_node *node = get_Block_cfgpred(endbl, j);
134 ir_op *op = get_irn_op(node);
137 /* Bad nodes usually do NOT produce anything, so it's ok */
141 if (op == op_Return) {
142 mem = get_Return_mem(node);
144 /* Bad nodes usually do NOT produce anything, so it's ok */
148 change = mem != get_irg_initial_mem(irg);
153 /* exception found */
160 /* check, if a keep-alive exists */
161 for (j = 0, k = get_End_n_keepalives(end); j < k; ++j) {
162 ir_node *mem = get_End_keepalive(end, j);
164 if (mode_M != get_irn_mode(mem))
167 change = mem != get_irg_initial_mem(irg);
174 eset_insert(pure_fkt, get_irg_entity(irg));
183 ctx.pure_fkt = pure_fkt;
184 ctx.n_calls_removed_SymConst = 0;
185 ctx.n_calls_removed_Sel = 0;
187 /* all calls of pure functions can be transformed into FuncCalls */
188 for (i = 0, n = get_irp_n_irgs(); i < n; ++i) {
189 ir_graph *irg = get_irp_irg(i);
192 irg_walk_graph(irg, NULL, rem_mem_from_real_fkt_calls, &ctx);
195 /* changes were done */
196 set_irg_outs_inconsistent(irg);
197 set_irg_loopinfo_state(current_ir_graph, loopinfo_cf_inconsistent);
201 if (get_firm_verbosity()) {
202 printf("Detected %d functions without side effects.\n", num_pure);
203 printf("Optimizes %d(SymConst) + %d(Sel) calls to these functions.\n",
204 ctx.n_calls_removed_SymConst, ctx.n_calls_removed_Sel);
205 if (get_firm_verbosity() > 1) {
206 for (ent = eset_first(pure_fkt); ent; ent = eset_next(pure_fkt)) {
207 printf(" "); DDMEO(ent);
213 if (get_firm_verbosity()) {
214 printf("No functions without side effects detected\n");
218 eset_destroy(pure_fkt);