Fixed the Phi optimize case: after fixing CSE for Phi nodes, it was broken
[libfirm] / ir / opt / opt_calling_conv.c
1 /*
2  * Copyright (C) 1995-2007 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   Change the calling conventions of "local" methods
23  * @author  Michael Beck
24  * @version $Id$
25  */
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "iroptimize.h"
31 #include "debug.h"
32 #include "irnode_t.h"
33 #include "irgwalk.h"
34 #include "irmemory.h"
35
36 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
37
38 /**
39  * Copy the calling conventions from the entities to the call type.
40  */
41 static void update_calls(ir_node *call, void *env) {
42         if (is_Call(call)) {
43                 ir_node *ptr = get_Call_ptr(call);
44
45                 if (is_SymConst(ptr)) {
46                         ir_entity *ent = get_SymConst_entity(ptr);
47                         ir_type *mtp = get_entity_type(ent);
48                         ir_type *ctp = get_Call_type(call);
49                         unsigned cc  = get_method_calling_convention(mtp);
50
51                         if (cc != get_method_calling_convention(ctp)) {
52                                 set_method_calling_convention(ctp, cc);
53                                 DB((dbg, LEVEL_1, "changed calling convention of calll to %+F\n", ent));
54                         }
55                 }
56         }
57 }
58
59 /**
60  * Change the calling conventions for all local methods.
61  *
62  * @param cc  new calling convention
63  */
64 void opt_change_calling_conventions(unsigned cc) {
65         int i;
66         int changed = 0;
67
68         FIRM_DBG_REGISTER(dbg, "firm.opt.cc");
69
70         assure_irp_globals_address_taken_computed();
71
72         /* first step: change the calling conventions of the local non-escaped entities */
73         for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
74                 ir_graph               *irg = get_irp_irg(i);
75                 ir_entity              *ent = get_irg_entity(irg);
76                 ir_address_taken_state state = get_entity_address_taken(ent);
77
78                 if (get_entity_visibility(ent) == visibility_local &&
79                     state == ir_address_not_taken) {
80                         ir_type *mtp = get_entity_type(ent);
81
82                         unsigned new_cc, old_cc = get_method_calling_convention(mtp) & ~cc_bits;
83
84                         new_cc = old_cc | (cc & cc_bits);
85
86                         if (new_cc != old_cc) {
87                                 set_method_calling_convention(mtp, new_cc);
88                                 changed = 1;
89                                 DB((dbg, LEVEL_1, "changed calling convention of %+F\n", ent));
90                         }
91                 }
92         }
93
94         if (changed)
95                 all_irg_walk(NULL, update_calls, NULL);
96 }