eec1b362c265d69cb7226b783947c9d41251b93e
[libfirm] / ir / opt / funccall.c
1 /*
2  * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   Optimization of function calls.
23  * @author  Michael Beck
24  * @version $Id$
25  */
26 #include "config.h"
27
28 #include "opt_init.h"
29
30 #include "irnode_t.h"
31 #include "irgraph_t.h"
32 #include "irgmod.h"
33 #include "irgwalk.h"
34 #include "dbginfo_t.h"
35 #include "irflag_t.h"
36 #include "irloop_t.h"
37 #include "ircons.h"
38 #include "iredges_t.h"
39 #include "irpass_t.h"
40 #include "iroptimize.h"
41 #include "analyze_irg_args.h"
42 #include "irhooks.h"
43 #include "raw_bitset.h"
44 #include "debug.h"
45
46 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
47
48 /**
49  * The walker environment for updating function calls.
50  */
51 typedef struct env_t {
52         size_t   n_calls_SymConst;
53         size_t   n_calls_Sel;
54         ir_node  *float_const_call_list;    /**< The list of all floating const function calls that will be changed. */
55         ir_node  *nonfloat_const_call_list; /**< The list of all non-floating const function calls that will be changed. */
56         ir_node  *pure_call_list;           /**< The list of all pure function calls that will be changed. */
57         ir_node  *nothrow_call_list;        /**< The list of all nothrow function calls that will be changed. */
58         ir_node  *proj_list;                /**< The list of all potential Proj nodes that must be fixed. */
59 } env_t;
60
61 /** Ready IRG's are marked in the ready set. */
62 static unsigned *ready_set;
63
64 /** IRG's that are in progress are marked here. */
65 static unsigned *busy_set;
66
67 /**
68  * We misuse the mtp_property_inherited flag as temporary here.
69  * The is ok, as we cannot set or get it anyway using the
70  * get_addtional_properties API.
71  */
72 #define mtp_temporary  mtp_property_inherited
73
74 /**
75  * Walker: Collect all calls to const and pure functions
76  * to lists. Collect all Proj(Call) nodes into a Proj list.
77  */
78 static void collect_const_and_pure_calls(ir_node *node, void *env)
79 {
80         env_t     *ctx = (env_t*)env;
81         ir_node   *call;
82         ir_node   *ptr;
83         ir_entity *ent;
84         unsigned  and_prop, or_prop, prop;
85
86         if (is_Call(node)) {
87                 call = node;
88
89                 /* set the link to NULL for all non-const/pure calls */
90                 set_irn_link(call, NULL);
91                 ptr = get_Call_ptr(call);
92                 if (is_Global(ptr)) {
93                         ent = get_Global_entity(ptr);
94
95                         prop = get_entity_additional_properties(ent);
96                         if ((prop & (mtp_property_const|mtp_property_pure)) == 0)
97                                 return;
98                         ++ctx->n_calls_SymConst;
99                 } else if (get_opt_closed_world() &&
100                            is_Sel(ptr) &&
101                            get_irg_callee_info_state(get_irn_irg(node)) == irg_callee_info_consistent) {
102                         /* If all possible callees are const functions, we can remove the memory edge. */
103                         size_t i, n_callees = get_Call_n_callees(call);
104                         if (n_callees == 0) {
105                                 /* This is kind of strange:  dying code or a Call that will raise an exception
106                                    when executed as there is no implementation to call.  So better not
107                                    optimize. */
108                                 return;
109                         }
110
111                         /* note that const function are a subset of pure ones */
112                         and_prop = mtp_property_const | mtp_property_pure;
113                         or_prop  = 0;
114                         for (i = 0; i < n_callees; ++i) {
115                                 ent = get_Call_callee(call, i);
116                                 if (ent == unknown_entity) {
117                                         /* we don't know which entity is called here */
118                                         return;
119                                 }
120                                 prop      = get_entity_additional_properties(ent);
121                                 and_prop &= prop;
122                                 or_prop  &= prop;
123                                 if (and_prop == mtp_no_property)
124                                         return;
125                         }
126                         prop = and_prop | (or_prop & mtp_property_has_loop);
127                         ++ctx->n_calls_Sel;
128                 } else
129                         return;
130
131                 /* ok, if we get here we found a call to a const or a pure function */
132                 if (prop & mtp_property_pure) {
133                         set_irn_link(call, ctx->pure_call_list);
134                         ctx->pure_call_list = call;
135                 } else {
136                         if (prop & mtp_property_has_loop) {
137                                 set_irn_link(call, ctx->nonfloat_const_call_list);
138                                 ctx->nonfloat_const_call_list = call;
139                         } else {
140                                 set_irn_link(call, ctx->float_const_call_list);
141                                 ctx->float_const_call_list = call;
142                         }
143                 }
144         } else if (is_Proj(node)) {
145                 /*
146                  * Collect all memory and exception Proj's from
147                  * calls.
148                  */
149                 call = get_Proj_pred(node);
150                 if (! is_Call(call))
151                         return;
152
153                 /* collect the Proj's in the Proj list */
154                 switch (get_Proj_proj(node)) {
155                 case pn_Call_M:
156                 case pn_Call_X_except:
157                 case pn_Call_X_regular:
158                         set_irn_link(node, ctx->proj_list);
159                         ctx->proj_list = node;
160                         break;
161                 default:
162                         break;
163                 }
164         }
165 }  /* collect_const_and_pure_calls */
166
167 /**
168  * Fix the list of collected Calls.
169  *
170  * @param irg  the graph that contained calls to pure functions
171  * @param ctx  context
172  */
173 static void fix_const_call_lists(ir_graph *irg, env_t *ctx)
174 {
175         ir_node *call, *next, *mem, *proj;
176         int exc_changed = 0;
177
178         /* First step: fix all calls by removing their memory input and let
179          * them floating.
180          * The original memory input is preserved in their link fields. */
181         for (call = ctx->float_const_call_list; call != NULL; call = next) {
182                 next = (ir_node*)get_irn_link(call);
183                 mem  = get_Call_mem(call);
184
185                 set_irn_link(call, mem);
186                 set_Call_mem(call, get_irg_no_mem(irg));
187
188                 /*
189                  * Unfortunately we cannot simply set the node to 'float'.
190                  * There is a reason for that:
191                  *
192                  * - The call might be inside a loop/if that is NOT entered
193                  *   and calls a endless function. Setting the call to float
194                  *   would allow to move it out from the loop/if causing this
195                  *   function be called even if the loop/if is not entered ...
196                  *
197                  * This could be fixed using post-dominators for calls and Pin nodes
198                  * but need some more analyzes to ensure that a call that potential
199                  * never returns is not executed before some code that generates
200                  * observable states...
201                  */
202
203                 /* finally, this call can float */
204                 set_irn_pinned(call, op_pin_state_floats);
205                 hook_func_call(irg, call);
206         }
207
208         /* Last step: fix all Proj's */
209         for (proj = ctx->proj_list; proj != NULL; proj = next) {
210                 next = (ir_node*)get_irn_link(proj);
211                 call = get_Proj_pred(proj);
212                 mem  = (ir_node*)get_irn_link(call);
213
214                 /* beware of calls in the pure call list */
215                 if (!mem || is_Call(mem))
216                         continue;
217                 assert(get_irn_mode(mem) == mode_M);
218
219                 switch (get_Proj_proj(proj)) {
220                 case pn_Call_M: {
221                         /* in dead code there might be cycles where proj == mem */
222                         if (proj != mem)
223                                 exchange(proj, mem);
224                          break;
225                 }
226                 case pn_Call_X_except:
227                         exc_changed = 1;
228                         exchange(proj, new_r_Bad(irg, mode_X));
229                         break;
230                 case pn_Call_X_regular: {
231                         ir_node *block = get_nodes_block(call);
232                         exc_changed = 1;
233                         exchange(proj, new_r_Jmp(block));
234                         break;
235                 }
236                 default:
237                         break;
238                 }
239         }
240
241         /* changes were done ... */
242         set_irg_outs_inconsistent(irg);
243         set_irg_loopinfo_state(irg, loopinfo_cf_inconsistent);
244
245         if (exc_changed) {
246                 /* ... including exception edges */
247                 set_irg_doms_inconsistent(irg);
248         }
249 }  /* fix_const_call_list */
250
251 /**
252  * Walker: Collect all calls to nothrow functions
253  * to lists. Collect all Proj(Call) nodes into a Proj list.
254  */
255 static void collect_nothrow_calls(ir_node *node, void *env)
256 {
257         env_t *ctx = (env_t*)env;
258         ir_node *call, *ptr;
259         ir_entity *ent;
260         unsigned prop;
261
262         if (is_Call(node)) {
263                 call = node;
264
265                 /* set the link to NULL for all non-const/pure calls */
266                 set_irn_link(call, NULL);
267                 ptr = get_Call_ptr(call);
268                 if (is_Global(ptr)) {
269                         ent = get_Global_entity(ptr);
270
271                         prop = get_entity_additional_properties(ent);
272                         if ((prop & mtp_property_nothrow) == 0)
273                                 return;
274                         ++ctx->n_calls_SymConst;
275                 } else if (get_opt_closed_world() &&
276                            is_Sel(ptr) &&
277                            get_irg_callee_info_state(get_irn_irg(node)) == irg_callee_info_consistent) {
278                         /* If all possible callees are nothrow functions, we can remove the exception edge. */
279                         size_t i, n_callees = get_Call_n_callees(call);
280                         if (n_callees == 0) {
281                                 /* This is kind of strange:  dying code or a Call that will raise an exception
282                                    when executed as there is no implementation to call.  So better not
283                                    optimize. */
284                                 return;
285                         }
286
287                         /* note that const function are a subset of pure ones */
288                         prop = mtp_property_nothrow;
289                         for (i = 0; i < n_callees; ++i) {
290                                 ent = get_Call_callee(call, i);
291                                 if (ent == unknown_entity) {
292                                         /* we don't know which entity is called here */
293                                         return;
294                                 }
295                                 prop &= get_entity_additional_properties(ent);
296                                 if (prop == mtp_no_property)
297                                         return;
298                         }
299                         ++ctx->n_calls_Sel;
300                 } else
301                         return;
302
303                 /* ok, if we get here we found a call to a nothrow function */
304                 set_irn_link(call, ctx->nothrow_call_list);
305                 ctx->nothrow_call_list = call;
306         } else if (is_Proj(node)) {
307                 /*
308                  * Collect all memory and exception Proj's from
309                  * calls.
310                  */
311                 call = get_Proj_pred(node);
312                 if (! is_Call(call))
313                         return;
314
315                 /* collect the Proj's in the Proj list */
316                 switch (get_Proj_proj(node)) {
317                 case pn_Call_M:
318                 case pn_Call_X_except:
319                 case pn_Call_X_regular:
320                         set_irn_link(node, ctx->proj_list);
321                         ctx->proj_list = node;
322                         break;
323                 default:
324                         break;
325                 }
326         }
327 }  /* collect_nothrow_calls */
328
329 /**
330  * Fix the list of collected nothrow Calls.
331  *
332  * @param irg        the graph that contained calls to pure functions
333  * @param call_list  the list of all call sites of const functions
334  * @param proj_list  the list of all memory/exception Proj's of this call sites
335  */
336 static void fix_nothrow_call_list(ir_graph *irg, ir_node *call_list, ir_node *proj_list)
337 {
338         ir_node *call, *next, *proj;
339         int exc_changed = 0;
340
341         /* First step: go through the list of calls and mark them. */
342         for (call = call_list; call; call = next) {
343                 next = (ir_node*)get_irn_link(call);
344
345                 /* current_ir_graph is in memory anyway, so it's a good marker */
346                 set_irn_link(call, &current_ir_graph);
347                 hook_func_call(irg, call);
348         }
349
350         /* Second step: Remove all exception Proj's */
351         for (proj = proj_list; proj; proj = next) {
352                 next = (ir_node*)get_irn_link(proj);
353                 call = get_Proj_pred(proj);
354
355                 /* handle only marked calls */
356                 if (get_irn_link(call) != &current_ir_graph)
357                         continue;
358
359                 /* kill any exception flow */
360                 switch (get_Proj_proj(proj)) {
361                 case pn_Call_X_except:
362                         exc_changed = 1;
363                         exchange(proj, new_r_Bad(irg, mode_X));
364                         break;
365                 case pn_Call_X_regular: {
366                         ir_node *block = get_nodes_block(call);
367                         exc_changed = 1;
368                         exchange(proj, new_r_Jmp(block));
369                         break;
370                 }
371                 default:
372                         break;
373                 }
374         }
375
376         /* changes were done ... */
377         set_irg_outs_inconsistent(irg);
378         set_irg_loopinfo_state(irg, loopinfo_cf_inconsistent);
379
380         if (exc_changed) {
381                 /* ... including exception edges */
382                 set_irg_doms_inconsistent(irg);
383         }
384 }  /* fix_nothrow_call_list */
385
386 /* marking */
387 #define SET_IRG_READY(irg)  rbitset_set(ready_set, get_irg_idx(irg))
388 #define IS_IRG_READY(irg)   rbitset_is_set(ready_set, get_irg_idx(irg))
389 #define SET_IRG_BUSY(irg)   rbitset_set(busy_set, get_irg_idx(irg))
390 #define CLEAR_IRG_BUSY(irg) rbitset_clear(busy_set, get_irg_idx(irg))
391 #define IS_IRG_BUSY(irg)    rbitset_is_set(busy_set, get_irg_idx(irg))
392
393 /* forward */
394 static mtp_additional_properties check_const_or_pure_function(ir_graph *irg, int top);
395
396 /**
397  * Calculate the bigger property of two. Handle the temporary flag right.
398  */
399 static mtp_additional_properties max_property(mtp_additional_properties a,
400                                               mtp_additional_properties b)
401 {
402         mtp_additional_properties r;
403         mtp_additional_properties t = (a | b) & mtp_temporary;
404         a &= ~mtp_temporary;
405         b &= ~mtp_temporary;
406
407         if (a == mtp_no_property || b == mtp_no_property)
408                 return mtp_no_property;
409         r = a > b ? a : b;
410         return r | t;
411 }  /* max_property */
412
413 /**
414  * Follow the memory chain starting at node and determine
415  * the mtp_property.
416  *
417  * @return mtp_property_const if only calls of const functions are detected
418  *         mtp_property_pure  if only Loads and const/pure calls detected
419  *         mtp_no_property    else
420  */
421 static mtp_additional_properties follow_mem_(ir_node *node)
422 {
423         mtp_additional_properties mode = mtp_property_const;
424         mtp_additional_properties m;
425         ir_node  *ptr;
426         int i;
427
428         for (;;) {
429                 if (mode == mtp_no_property)
430                         return mtp_no_property;
431
432                 if (irn_visited_else_mark(node))
433                         return mode;
434
435                 switch (get_irn_opcode(node)) {
436                 case iro_Proj:
437                         node = get_Proj_pred(node);
438                         break;
439
440                 case iro_NoMem:
441                         /* finish here */
442                         return mode;
443
444                 case iro_Phi:
445                 case iro_Sync:
446                         /* do a dfs search */
447                         for (i = get_irn_arity(node) - 1; i >= 0; --i) {
448                                 m    = follow_mem_(get_irn_n(node, i));
449                                 mode = max_property(mode, m);
450                                 if (mode == mtp_no_property)
451                                         return mtp_no_property;
452                         }
453                         return mode;
454
455                 case iro_Load:
456                         /* Beware volatile Loads are NOT allowed in pure functions. */
457                         if (get_Load_volatility(node) == volatility_is_volatile)
458                                 return mtp_no_property;
459                         mode = max_property(mode, mtp_property_pure);
460                         node = get_Load_mem(node);
461                         break;
462
463                 case iro_Call:
464                         /* A call is only tolerable if its either constant or pure. */
465                         ptr = get_Call_ptr(node);
466                         if (is_SymConst_addr_ent(ptr)) {
467                                 ir_entity *ent = get_SymConst_entity(ptr);
468                                 ir_graph  *irg = get_entity_irg(ent);
469
470                                 if (irg == NULL) {
471                                         m = get_entity_additional_properties(ent) & (mtp_property_const|mtp_property_pure);
472                                         mode = max_property(mode, m);
473                                 } else {
474                                         /* we have a graph, analyze it. */
475                                         m = check_const_or_pure_function(irg, /*top=*/0);
476                                         mode = max_property(mode, m);
477                                 }
478                         } else
479                                 return mtp_no_property;
480                         node = get_Call_mem(node);
481                         break;
482
483                 default:
484                         return mtp_no_property;
485                 }
486         }
487 }
488
489 /**
490  * Follow the memory chain starting at node and determine
491  * the mtp_property.
492  *
493  * @return mtp_property_const if only calls of const functions are detected
494  *         mtp_property_pure  if only Loads and const/pure calls detected
495  *         mtp_no_property else
496  */
497 static mtp_additional_properties follow_mem(ir_node *node, mtp_additional_properties mode)
498 {
499         mtp_additional_properties m = follow_mem_(node);
500         return max_property(mode, m);
501 }
502
503 /**
504  * Check if a graph represents a const or a pure function.
505  *
506  * @param irg  the graph to check
507  * @param top  if set, this is the top call
508  */
509 static mtp_additional_properties check_const_or_pure_function(ir_graph *irg, int top)
510 {
511         ir_node *end, *endbl;
512         int j;
513         mtp_additional_properties prop = get_irg_additional_properties(irg);
514
515         if (prop & mtp_property_const) {
516                 /* already marked as a const function */
517                 return mtp_property_const;
518         }
519         if (prop & mtp_property_pure) {
520                 /* already marked as a pure function */
521                 return mtp_property_pure;
522         }
523
524         if (IS_IRG_READY(irg)) {
525                 /* already checked */
526                 return mtp_no_property;
527         }
528         if (IS_IRG_BUSY(irg)) {
529                 /* We are still evaluate this method.
530                  * The function (indirectly) calls itself and thus may not terminate.
531                  */
532                 return mtp_no_property;
533         }
534         SET_IRG_BUSY(irg);
535
536         end   = get_irg_end(irg);
537         endbl = get_nodes_block(end);
538         prop  = mtp_property_const;
539
540         ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
541         inc_irg_visited(irg);
542         /* mark the initial mem: recursion of follow_mem() stops here */
543         mark_irn_visited(get_irg_initial_mem(irg));
544
545         /* visit every Return */
546         for (j = get_Block_n_cfgpreds(endbl) - 1; j >= 0; --j) {
547                 ir_node   *node = get_Block_cfgpred(endbl, j);
548                 unsigned   code = get_irn_opcode(node);
549                 ir_node   *mem;
550
551                 /* Bad nodes usually do NOT produce anything, so it's ok */
552                 if (code == iro_Bad)
553                         continue;
554
555                 if (code == iro_Return) {
556                         mem = get_Return_mem(node);
557
558                         /* Bad nodes usually do NOT produce anything, so it's ok */
559                         if (is_Bad(mem))
560                                 continue;
561
562                         if (mem != get_irg_initial_mem(irg))
563                                 prop = max_property(prop, follow_mem(mem, prop));
564                 } else {
565                         /* Exception found. Cannot be const or pure. */
566                         prop = mtp_no_property;
567                         break;
568                 }
569                 if (prop == mtp_no_property)
570                         break;
571         }
572
573         if (prop != mtp_no_property) {
574                 /* check, if a keep-alive exists */
575                 for (j = get_End_n_keepalives(end) - 1; j >= 0; --j) {
576                         ir_node *kept = get_End_keepalive(end, j);
577
578                         if (is_Block(kept)) {
579                                 prop = mtp_no_property;
580                                 break;
581                         }
582
583                         if (mode_M != get_irn_mode(kept))
584                                 continue;
585
586                         prop = max_property(prop, follow_mem(kept, prop));
587                         if (prop == mtp_no_property)
588                                 break;
589                 }
590         }
591
592         if (top) {
593                 /* Set the property only if we are at top-level. */
594                 if (prop != mtp_no_property) {
595                         add_irg_additional_properties(irg, prop);
596                 }
597                 SET_IRG_READY(irg);
598         }
599         CLEAR_IRG_BUSY(irg);
600         ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
601         return prop;
602 }  /* check_const_or_pure_function */
603
604 /**
605  * Handle calls to const functions.
606  *
607  * @param ctx  context
608  */
609 static void handle_const_Calls(env_t *ctx)
610 {
611         size_t i, n;
612
613         ctx->n_calls_SymConst = 0;
614         ctx->n_calls_Sel      = 0;
615
616         /* all calls of const functions can be transformed */
617         for (i = 0, n = get_irp_n_irgs(); i < n; ++i) {
618                 ir_graph *irg  = get_irp_irg(i);
619
620                 ctx->float_const_call_list    = NULL;
621                 ctx->nonfloat_const_call_list = NULL;
622                 ctx->pure_call_list           = NULL;
623                 ctx->proj_list                = NULL;
624
625                 ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
626                 irg_walk_graph(irg, NULL, collect_const_and_pure_calls, ctx);
627
628                 if (ctx->float_const_call_list != NULL)
629                         fix_const_call_lists(irg, ctx);
630                 ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
631         }
632 }  /* handle_const_Calls */
633
634 /**
635  * Handle calls to nothrow functions.
636  *
637  * @param ctx  context
638  */
639 static void handle_nothrow_Calls(env_t *ctx)
640 {
641         size_t i, n;
642
643         ctx->n_calls_SymConst = 0;
644         ctx->n_calls_Sel      = 0;
645
646         /* all calls of const functions can be transformed */
647         for (i = 0, n = get_irp_n_irgs(); i < n; ++i) {
648                 ir_graph *irg  = get_irp_irg(i);
649
650                 ctx->nothrow_call_list = NULL;
651                 ctx->proj_list         = NULL;
652
653                 ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
654                 irg_walk_graph(irg, NULL, collect_nothrow_calls, ctx);
655
656                 if (ctx->nothrow_call_list)
657                         fix_nothrow_call_list(irg, ctx->nothrow_call_list, ctx->proj_list);
658                 ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
659         }
660 }
661
662 /**
663  * Check, whether a given node represents a return value of
664  * a malloc like function (ie, new heap allocated memory).
665  *
666  * @param node  the node to check
667  */
668 static int is_malloc_call_result(const ir_node *node)
669 {
670         if (is_Alloc(node) && get_Alloc_where(node) == heap_alloc) {
671                 /* Firm style high-level allocation */
672                 return 1;
673         }
674         /* TODO: check mtp_malloc */
675         return 0;
676 }
677
678 /**
679  * Update a property depending on a call property.
680  */
681 static mtp_additional_properties update_property(mtp_additional_properties orig_prop, mtp_additional_properties call_prop)
682 {
683         mtp_additional_properties t = (orig_prop | call_prop) & mtp_temporary;
684         mtp_additional_properties r = orig_prop & call_prop;
685         return r | t;
686 }
687
688 /**
689  * Check if a node is stored.
690  */
691 static int is_stored(const ir_node *n)
692 {
693         const ir_edge_t *edge;
694         const ir_node   *ptr;
695
696         foreach_out_edge(n, edge) {
697                 const ir_node *succ = get_edge_src_irn(edge);
698
699                 switch (get_irn_opcode(succ)) {
700                 case iro_Return:
701                 case iro_Load:
702                 case iro_Cmp:
703                         /* ok */
704                         break;
705                 case iro_Store:
706                         if (get_Store_value(succ) == n)
707                                 return 1;
708                         /* ok if its only the address input */
709                         break;
710                 case iro_Sel:
711                 case iro_Cast:
712                 case iro_Confirm:
713                         if (is_stored(succ))
714                                 return 1;
715                         break;
716                 case iro_Call:
717                         ptr = get_Call_ptr(succ);
718                         if (is_Global(ptr)) {
719                                 ir_entity *ent = get_Global_entity(ptr);
720                                 size_t    i;
721
722                                 /* we know the called entity */
723                                 for (i = get_Call_n_params(succ); i > 0;) {
724                                         if (get_Call_param(succ, --i) == n) {
725                                                 /* n is the i'th param of the call */
726                                                 if (get_method_param_access(ent, i) & ptr_access_store) {
727                                                         /* n is store in ent */
728                                                         return 1;
729                                                 }
730                                         }
731                                 }
732                         } else {
733                                 /* unknown call address */
734                                 return 1;
735                         }
736                         break;
737                 default:
738                         /* bad, potential alias */
739                         return 1;
740                 }
741         }
742         return 0;
743 }  /* is_stored */
744
745 /**
746  * Check that the return value of an irg is not stored anywhere.
747  *
748  * return ~mtp_property_malloc if return values are stored, ~0 else
749  */
750 static mtp_additional_properties check_stored_result(ir_graph *irg)
751 {
752         ir_node  *end_blk = get_irg_end_block(irg);
753         int      i;
754         mtp_additional_properties res = ~mtp_no_property;
755         int      old_edges = edges_assure_kind(irg, EDGE_KIND_NORMAL);
756
757         for (i = get_Block_n_cfgpreds(end_blk) - 1; i >= 0; --i) {
758                 ir_node *pred = get_Block_cfgpred(end_blk, i);
759                 size_t  j;
760
761                 if (! is_Return(pred))
762                         continue;
763                 for (j = get_Return_n_ress(pred); j > 0;) {
764                         const ir_node *irn = get_Return_res(pred, --j);
765
766                         if (is_stored(irn)) {
767                                 /* bad, might create an alias */
768                                 res = ~mtp_property_malloc;
769                                 goto finish;
770                         }
771                 }
772         }
773 finish:
774         if (! old_edges)
775                 edges_deactivate_kind(irg, EDGE_KIND_NORMAL);
776         return res;
777 }
778
779 /**
780  * Check if a graph represents a nothrow or a malloc function.
781  *
782  * @param irg  the graph to check
783  * @param top  if set, this is the top call
784  */
785 static mtp_additional_properties check_nothrow_or_malloc(ir_graph *irg, int top)
786 {
787         mtp_additional_properties curr_prop = mtp_property_malloc | mtp_property_nothrow;
788         ir_node                  *end_blk   = get_irg_end_block(irg);
789         ir_entity *ent;
790         ir_type   *mtp;
791         int       i;
792
793         if (IS_IRG_READY(irg)) {
794                 /* already checked */
795                 return get_irg_additional_properties(irg);
796         }
797         if (IS_IRG_BUSY(irg)) {
798                 /* we are still evaluate this method. Be optimistic,
799                 return the best possible so far but mark the result as temporary. */
800                 return mtp_temporary | mtp_property_malloc | mtp_property_nothrow;
801         }
802         SET_IRG_BUSY(irg);
803
804         ent = get_irg_entity(irg);
805         mtp = get_entity_type(ent);
806
807         if (get_method_n_ress(mtp) <= 0)
808                 curr_prop &= ~mtp_property_malloc;
809
810         for (i = get_Block_n_cfgpreds(end_blk) - 1; i >= 0; --i) {
811                 ir_node *pred = get_Block_cfgpred(end_blk, i);
812
813                 if (is_Return(pred)) {
814                         if (curr_prop & mtp_property_malloc) {
815                                 size_t j;
816
817                                 /* check, if malloc is called here */
818                                 for (j = get_Return_n_ress(pred); j > 0;) {
819                                         ir_node *res = get_Return_res(pred, --j);
820
821                                         /* skip Confirms and Casts */
822                                         res = skip_HighLevel_ops(res);
823                                         /* skip Proj's */
824                                         while (is_Proj(res))
825                                                 res = get_Proj_pred(res);
826                                         if (is_malloc_call_result(res)) {
827                                                 /* ok, this is a malloc */
828                                         } else if (is_Call(res)) {
829                                                 ir_node *ptr = get_Call_ptr(res);
830
831                                                 if (is_Global(ptr)) {
832                                                         /* a direct call */
833                                                         ir_entity *ent    = get_Global_entity(ptr);
834                                                         ir_graph  *callee = get_entity_irg(ent);
835
836                                                         if (callee == irg) {
837                                                                 /* A self-recursive call. The property did not depend on this call. */
838                                                         } else if (callee != NULL) {
839                                                                 mtp_additional_properties prop = check_nothrow_or_malloc(callee, /*top=*/0);
840                                                                 curr_prop = update_property(curr_prop, prop);
841                                                         } else {
842                                                                 curr_prop = update_property(curr_prop, get_entity_additional_properties(ent));
843                                                         }
844                                                 } else if (get_opt_closed_world() &&
845                                                            is_Sel(ptr) &&
846                                                            get_irg_callee_info_state(irg) == irg_callee_info_consistent) {
847                                                         /* check if all possible callees are malloc functions. */
848                                                         size_t i, n_callees = get_Call_n_callees(res);
849                                                         if (n_callees == 0) {
850                                                                 /* This is kind of strange:  dying code or a Call that will raise an exception
851                                                                    when executed as there is no implementation to call.  So better not
852                                                                    optimize. */
853                                                                 curr_prop &= ~mtp_property_malloc;
854                                                                 continue;
855                                                         }
856
857                                                         for (i = 0; i < n_callees; ++i) {
858                                                                 ir_entity *ent = get_Call_callee(res, i);
859                                                                 if (ent == unknown_entity) {
860                                                                         /* we don't know which entity is called here */
861                                                                         curr_prop &= ~mtp_property_malloc;
862                                                                         break;
863                                                                 }
864                                                                 if ((get_entity_additional_properties(ent) & mtp_property_malloc) == 0) {
865                                                                         curr_prop &= ~mtp_property_malloc;
866                                                                         break;
867                                                                 }
868                                                         }
869                                                         /* if we pass the for cycle, malloc is still ok */
870                                                 } else {
871                                                         /* unknown call */
872                                                         curr_prop &= ~mtp_property_malloc;
873                                                 }
874                                         } else {
875                                                 /* unknown return value */
876                                                 curr_prop &= ~mtp_property_malloc;
877                                         }
878                                 }
879                         }
880                 } else if (curr_prop & mtp_property_nothrow) {
881                         /* exception flow detected */
882                         pred = skip_Proj(pred);
883
884                         if (is_Call(pred)) {
885                                 ir_node *ptr = get_Call_ptr(pred);
886
887                                 if (is_Global(ptr)) {
888                                         /* a direct call */
889                                         ir_entity *ent    = get_Global_entity(ptr);
890                                         ir_graph  *callee = get_entity_irg(ent);
891
892                                         if (callee == irg) {
893                                                 /* A self-recursive call. The property did not depend on this call. */
894                                         } else if (callee != NULL) {
895                                                 /* Note: we check here for nothrow only, so do NOT reset the malloc property */
896                                                 mtp_additional_properties prop = check_nothrow_or_malloc(callee, /*top=*/0) | mtp_property_malloc;
897                                                 curr_prop = update_property(curr_prop, prop);
898                                         } else {
899                                                 if ((get_entity_additional_properties(ent) & mtp_property_nothrow) == 0)
900                                                         curr_prop &= ~mtp_property_nothrow;
901                                         }
902                                 } else if (get_opt_closed_world() &&
903                                            is_Sel(ptr) &&
904                                            get_irg_callee_info_state(irg) == irg_callee_info_consistent) {
905                                         /* check if all possible callees are nothrow functions. */
906                                         size_t i, n_callees = get_Call_n_callees(pred);
907                                         if (n_callees == 0) {
908                                                 /* This is kind of strange:  dying code or a Call that will raise an exception
909                                                    when executed as there is no implementation to call.  So better not
910                                                    optimize. */
911                                                 curr_prop &= ~mtp_property_nothrow;
912                                                 continue;
913                                         }
914
915                                         for (i = 0; i < n_callees; ++i) {
916                                                 ir_entity *ent = get_Call_callee(pred, i);
917                                                 if (ent == unknown_entity) {
918                                                         /* we don't know which entity is called here */
919                                                         curr_prop &= ~mtp_property_nothrow;
920                                                         break;
921                                                 }
922                                                 if ((get_entity_additional_properties(ent) & mtp_property_nothrow) == 0) {
923                                                         curr_prop &= ~mtp_property_nothrow;
924                                                         break;
925                                                 }
926                                         }
927                                         /* if we pass the for cycle, nothrow is still ok */
928                                 } else {
929                                         /* unknown call */
930                                         curr_prop &= ~mtp_property_nothrow;
931                                 }
932                         } else {
933                                 /* real exception flow possible. */
934                                 curr_prop &= ~mtp_property_nothrow;
935                         }
936                 }
937                 if ((curr_prop & ~mtp_temporary) == mtp_no_property) {
938                         /* no need to search further */
939                         break;
940                 }
941         }
942
943         if (curr_prop & mtp_property_malloc) {
944                 /*
945                  * Note that the malloc property means not only return newly allocated
946                  * memory, but also that this memory is ALIAS FREE.
947                  * To ensure that, we do NOT allow that the returned memory is somewhere
948                  * stored.
949              */
950                 curr_prop &= check_stored_result(irg);
951         }
952
953         if (curr_prop != mtp_no_property) {
954                 if (top || (curr_prop & mtp_temporary) == 0) {
955                         /* We use the temporary flag here to mark an optimistic result.
956                            Set the property only if we are sure that it does NOT base on
957                            temporary results OR if we are at top-level. */
958                         add_irg_additional_properties(irg, curr_prop & ~mtp_temporary);
959                         SET_IRG_READY(irg);
960                 }
961         }
962         if (top)
963                 SET_IRG_READY(irg);
964         CLEAR_IRG_BUSY(irg);
965         return curr_prop;
966 }  /* check_nothrow_or_malloc */
967
968 /**
969  * When a function was detected as "const", it might be moved out of loops.
970  * This might be dangerous if the graph can contain endless loops.
971  */
972 static void check_for_possible_endless_loops(ir_graph *irg)
973 {
974         ir_loop *root_loop;
975         assure_cf_loop(irg);
976
977         root_loop = get_irg_loop(irg);
978         if (root_loop->flags & loop_outer_loop)
979                 add_irg_additional_properties(irg, mtp_property_has_loop);
980 }
981
982 /*
983  * optimize function calls by handling const functions
984  */
985 void optimize_funccalls(void)
986 {
987         size_t i, n;
988         size_t last_idx;
989         env_t  ctx;
990         size_t num_const   = 0;
991         size_t num_pure    = 0;
992         size_t num_nothrow = 0;
993         size_t num_malloc  = 0;
994
995         /* prepare: mark all graphs as not analyzed */
996         last_idx  = get_irp_last_idx();
997         ready_set = rbitset_malloc(last_idx);
998         busy_set  = rbitset_malloc(last_idx);
999
1000         /* first step: detect, which functions are nothrow or malloc */
1001         DB((dbg, LEVEL_2, "Detecting nothrow and malloc properties ...\n"));
1002         for (i = 0, n = get_irp_n_irgs(); i < n; ++i) {
1003                 ir_graph *irg = get_irp_irg(i);
1004                 unsigned prop = check_nothrow_or_malloc(irg, /*top=*/1);
1005
1006                 if (prop & mtp_property_nothrow) {
1007                         ++num_nothrow;
1008                         DB((dbg, LEVEL_2, "%+F has the nothrow property\n", irg));
1009                 } else if (prop & mtp_property_malloc) {
1010                         ++num_malloc;
1011                         DB((dbg, LEVEL_2, "%+F has the malloc property\n", irg));
1012                 }
1013         }
1014
1015         /* second step: remove exception edges: this must be done before the
1016            detection of const and pure functions take place. */
1017         handle_nothrow_Calls(&ctx);
1018         DB((dbg, LEVEL_1, "Detected %zu nothrow graphs, %zu malloc graphs.\n", num_nothrow, num_malloc));
1019         DB((dbg, LEVEL_1, "Optimizes %zu(SymConst) + %zu(Sel) calls to nothrow functions.\n",
1020                 ctx.n_calls_SymConst, ctx.n_calls_Sel));
1021
1022         rbitset_clear_all(ready_set, last_idx);
1023         rbitset_clear_all(busy_set, last_idx);
1024
1025         /* third step: detect, which functions are const or pure */
1026         DB((dbg, LEVEL_2, "Detecting const and pure properties ...\n"));
1027         for (i = 0, n = get_irp_n_irgs(); i < n; ++i) {
1028                 ir_graph *irg = get_irp_irg(i);
1029                 unsigned prop = check_const_or_pure_function(irg, /*top=*/1);
1030
1031                 if (prop & mtp_property_const) {
1032                         ++num_const;
1033                         DB((dbg, LEVEL_2, "%+F has the const property\n", irg));
1034                         check_for_possible_endless_loops(irg);
1035                 } else if (prop & mtp_property_pure) {
1036                         ++num_pure;
1037                         DB((dbg, LEVEL_2, "%+F has the pure property\n", irg));
1038                 }
1039         }
1040
1041         handle_const_Calls(&ctx);
1042         DB((dbg, LEVEL_1, "Detected %zu const graphs, %zu pure graphs.\n", num_const, num_pure));
1043         DB((dbg, LEVEL_1, "Optimizes %u(SymConst) + %u(Sel) calls to const functions.\n",
1044                    ctx.n_calls_SymConst, ctx.n_calls_Sel));
1045
1046         xfree(busy_set);
1047         xfree(ready_set);
1048 }
1049
1050 /* initialize the funccall optimization */
1051 void firm_init_funccalls(void)
1052 {
1053         FIRM_DBG_REGISTER(dbg, "firm.opt.funccalls");
1054 }
1055
1056 /* Creates an ir_prog pass for optimize_funccalls. */
1057 ir_prog_pass_t *optimize_funccalls_pass(const char *name)
1058 {
1059         return def_prog_pass(name ? name : "funccall", optimize_funccalls);
1060 }