backend specific optimization module added
[libfirm] / ir / be / ia32 / ia32_optimize.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include "irnode.h"
6 #include "irprog_t.h"
7 #include "ircons.h"
8 #include "firm_types.h"
9
10 #include "ia32_new_nodes.h"
11 #include "bearch_ia32_t.h"
12
13 /**
14  * creates a unique ident by adding a number to a tag
15  *
16  * @param tag   the tag string, must contain a %d if a number
17  *              should be added
18  */
19 static ident *unique_id(const char *tag)
20 {
21   static unsigned id = 0;
22   char str[256];
23
24   snprintf(str, sizeof(str), tag, ++id);
25   return new_id_from_str(str);
26 }
27
28
29
30 /**
31  * Transforms a SymConst.
32  *
33  * @param mod     the debug module
34  * @param block   the block the new node should belong to
35  * @param node    the ir SymConst node
36  * @param mode    mode of the SymConst
37  * @return the created ia32 Const node
38  */
39 static ir_node *gen_SymConst(ia32_transform_env_t *env) {
40         ir_node           *cnst;
41         firm_dbg_module_t *mod   = env->mod;
42         dbg_info          *dbg   = env->dbg;
43         ir_mode           *mode  = env->mode;
44         ir_graph          *irg   = env->irg;
45         ir_node           *block = env->block;
46
47         if (mode_is_float(mode)) {
48                 cnst = new_rd_ia32_fConst(dbg, irg, block, mode);
49
50         }
51         else {
52                 cnst = new_rd_ia32_Const(dbg, irg, block, mode);
53         }
54
55         set_ia32_Const_attr(cnst, env->irn);
56         return cnst;
57 }
58
59 /**
60  * Transforms a Const.
61  *
62  * @param mod     the debug module
63  * @param block   the block the new node should belong to
64  * @param node    the ir Const node
65  * @param mode    mode of the Const
66  * @return the created ia32 Const node
67  */
68 static ir_node *gen_Const(ia32_transform_env_t *env) {
69         ir_node *cnst;
70         entity  *ent;
71         ir_type *tp;
72         symconst_symbol sym;
73         firm_dbg_module_t *mod   = env->mod;
74         dbg_info          *dbg   = env->dbg;
75         ir_mode           *mode  = env->mode;
76         ir_graph          *irg   = env->irg;
77         ir_node           *block = env->block;
78         ir_node           *node  = env->irn;
79
80         if (mode_is_float(mode)) {
81                 tp  = get_Const_type(node);
82                 if (tp == firm_unknown_type) {
83                         tp = new_type_primitive(unique_id("tp_ia32_float_%u"), mode);
84                 }
85
86                 ent = new_entity(get_glob_type(), unique_id("ia32FloatCnst_%u"), tp);
87
88                 set_entity_ld_ident(ent, get_entity_ident(ent));
89                 set_entity_visibility(ent, visibility_local);
90                 set_entity_variability(ent, variability_constant);
91                 set_entity_allocation(ent, allocation_static);
92
93                 set_atomic_ent_value(ent, node);
94
95                 sym.entity_p = ent;
96
97                 cnst = new_rd_SymConst(dbg, irg, block, sym, symconst_addr_ent);
98                 env->irn = cnst;
99                 cnst = gen_SymConst(env);
100         }
101         else {
102                 cnst = new_rd_ia32_Const(dbg, irg, block, mode);
103                 set_ia32_Const_attr(cnst, node);
104         }
105
106         return cnst;
107 }
108
109
110
111 /**
112  * Transforms (all) Const's into ia32_Const and places them in the
113  * block where they are used (or in the cfg-pred Block in case of Phi's)
114  */
115 void ia32_place_consts(ir_node *irn, void *env) {
116         ia32_code_gen_t      *cg = env;
117         ia32_transform_env_t  tenv;
118         ir_mode              *mode;
119         ir_node              *pred, *cnst;
120         int                   i;
121         opcode                opc;
122
123         if (is_Block(irn))
124                 return;
125
126         mode = get_irn_mode(irn);
127
128         tenv.arch_env = cg->arch_env;
129         tenv.block    = get_nodes_block(irn);
130         tenv.cg       = cg;
131         tenv.irg      = cg->irg;
132         tenv.mod      = firm_dbg_register("ir.be.ia32.optimize");
133
134         /* Loop over all predecessors and check for Sym/Const nodes */
135         for (i = 0; i < get_irn_arity(irn); i++) {
136                 pred      = get_irn_n(irn, i);
137                 cnst      = NULL;
138                 opc       = get_irn_opcode(pred);
139                 tenv.irn  = pred;
140                 tenv.mode = get_irn_mode(pred);
141                 tenv.dbg  = get_irn_dbg_info(pred);
142
143                 /* If it's a Phi, then we need to create the */
144                 /* new Const in it's predecessor block       */
145                 if (is_Phi(irn)) {
146                         tenv.block = get_Block_cfgpred_block(get_nodes_block(irn), i);
147                 }
148
149                 switch (opc) {
150                         case iro_Const:
151                                 cnst = gen_Const(&tenv);
152                                 break;
153                         case iro_SymConst:
154                                 cnst = gen_SymConst(&tenv);
155                                 break;
156                         default:
157                                 break;
158                 }
159
160                 /* if we found a const, then set it */
161                 if (cnst) {
162                         set_irn_n(irn, i, cnst);
163                 }
164         }
165 }