Add pass constructor C99 feature removed.
[libfirm] / ir / opt / scalar_replace.c
1 /*
2  * Copyright (C) 1995-2008 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   Scalar replacement of compounds.
23  * @author  Beyhan Veliev, Michael Beck
24  * @version $Id$
25  */
26 #include "config.h"
27
28 #include <string.h>
29
30 #include "iroptimize.h"
31 #include "scalar_replace.h"
32 #include "opt_init.h"
33 #include "irflag_t.h"
34 #include "irouts.h"
35 #include "set.h"
36 #include "pset.h"
37 #include "array.h"
38 #include "tv.h"
39 #include "ircons_t.h"
40 #include "hashptr.h"
41 #include "irgwalk.h"
42 #include "irgmod.h"
43 #include "irnode_t.h"
44 #include "irpass.h"
45 #include "irtools.h"
46 #include "xmalloc.h"
47 #include "debug.h"
48 #include "error.h"
49
50 #define SET_VNUM(node, vnum) set_irn_link(node, INT_TO_PTR(vnum))
51 #define GET_VNUM(node)       (unsigned)PTR_TO_INT(get_irn_link(node))
52
53 /**
54  * A path element entry: it is either an entity
55  * or a tarval, because we evaluate only constant array
56  * accesses like a.b.c[8].d
57  */
58 typedef union {
59         ir_entity *ent;
60         tarval *tv;
61 } path_elem_t;
62
63 /**
64  * An access path, used to assign value numbers
65  * to variables that will be scalar replaced.
66  */
67 typedef struct _path_t {
68         unsigned    vnum;      /**< The value number. */
69         unsigned    path_len;  /**< The length of the access path. */
70         path_elem_t path[1];   /**< The path. */
71 } path_t;
72
73 /** The size of a path in bytes. */
74 #define PATH_SIZE(p)  (sizeof(*(p)) + sizeof((p)->path[0]) * ((p)->path_len - 1))
75
76 typedef struct _scalars_t {
77         ir_entity *ent;              /**< A entity for scalar replacement. */
78         ir_type *ent_owner;          /**< The owner of this entity. */
79 } scalars_t;
80
81 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
82
83 /**
84  * Compare two pathes.
85  *
86  * @return 0 if they are identically
87  */
88 static int path_cmp(const void *elt, const void *key, size_t size)
89 {
90         const path_t *p1 = elt;
91         const path_t *p2 = key;
92         (void) size;
93
94         /* we can use memcmp here, because identical tarvals should have identical addresses */
95         return memcmp(p1->path, p2->path, p1->path_len * sizeof(p1->path[0]));
96 }
97
98 /**
99  * Compare two elements of the scalars_t set.
100  *
101  * @return 0 if they are identically
102  */
103 static int ent_cmp(const void *elt, const void *key, size_t size)
104 {
105         const scalars_t *c1 = elt;
106         const scalars_t *c2 = key;
107         (void) size;
108
109         return c1->ent != c2->ent;
110 }
111
112 /**
113  * Calculate a hash value for a path.
114  */
115 static unsigned path_hash(const path_t *path)
116 {
117         unsigned hash = 0;
118         unsigned i;
119
120         for (i = 0; i < path->path_len; ++i)
121                 hash ^= (unsigned)PTR_TO_INT(path->path[i].ent);
122
123         return hash >> 4;
124 }
125
126 /**
127  * Returns non-zero, if all indeces of a Sel node are constants.
128  *
129  * @param sel  the Sel node that will be checked
130  */
131 static int is_const_sel(ir_node *sel)
132 {
133         int i, n = get_Sel_n_indexs(sel);
134
135         for (i = 0; i < n; ++i) {
136                 ir_node *idx = get_Sel_index(sel, i);
137
138                 if (!is_Const(idx))
139                         return 0;
140         }
141         return 1;
142 }
143
144 /**
145  * Check the mode of a Load/Store with the mode of the entity
146  * that is accessed.
147  * If the mode of the entity and the Load/Store mode do not match, we
148  * have the bad reinterpret case:
149  *
150  * int i;
151  * char b = *(char *)&i;
152  *
153  * We do NOT count this as one value and return address_taken
154  * in that case.
155  * However, we support an often used case. If the mode is two-complement
156  * we allow casts between signed/unsigned.
157  *
158  * @param mode     the mode of the Load/Store
159  * @param ent_mode the mode of the accessed entity
160  */
161 static int check_load_store_mode(ir_mode *mode, ir_mode *ent_mode)
162 {
163         if (ent_mode != mode) {
164                 if (ent_mode == NULL ||
165                     get_mode_size_bits(ent_mode) != get_mode_size_bits(mode) ||
166                     get_mode_sort(ent_mode) != get_mode_sort(mode) ||
167                     get_mode_arithmetic(ent_mode) != irma_twos_complement ||
168                     get_mode_arithmetic(mode) != irma_twos_complement)
169                         return 0;
170         }
171         return 1;
172 }
173
174 /*
175  * Returns non-zero, if the address of an entity
176  * represented by a Sel node (or it's successor Sels) is taken.
177  */
178 int is_address_taken(ir_node *sel)
179 {
180         int       i, input_nr, k;
181         ir_mode   *emode, *mode;
182         ir_node   *value;
183         ir_entity *ent;
184
185         if (! is_const_sel(sel))
186                 return 1;
187
188         for (i = get_irn_n_outs(sel) - 1; i >= 0; --i) {
189                 ir_node *succ = get_irn_out(sel, i);
190
191                 switch (get_irn_opcode(succ)) {
192                 case iro_Load:
193                         /* do not remove volatile variables */
194                         if (get_Load_volatility(succ) == volatility_is_volatile)
195                                 return 1;
196                         /* check if this load is not a hidden conversion */
197                         mode = get_Load_mode(succ);
198                         ent = get_Sel_entity(sel);
199                         emode = get_type_mode(get_entity_type(ent));
200                         if (! check_load_store_mode(mode, emode))
201                                 return 1;
202                         break;
203
204                 case iro_Store:
205                         /* check that Sel is not the Store's value */
206                         value = get_Store_value(succ);
207                         if (value == sel)
208                                 return 1;
209                         /* do not remove volatile variables */
210                         if (get_Store_volatility(succ) == volatility_is_volatile)
211                                 return 1;
212                         /* check if this Store is not a hidden conversion */
213                         mode = get_irn_mode(value);
214                         ent = get_Sel_entity(sel);
215                         emode = get_type_mode(get_entity_type(ent));
216                         if (! check_load_store_mode(mode, emode))
217                                 return 1;
218                         break;
219
220                 case iro_Sel: {
221                         int       res;
222                         ir_entity *entity = get_Sel_entity(succ);
223                         /* we can't handle unions correctly yet -> address taken */
224                         if (is_Union_type(get_entity_owner(entity)))
225                                 return 1;
226
227                         /* Check the Sel successor of Sel */
228                         res = is_address_taken(succ);
229                         if (res)
230                                 return 1;
231                         break;
232                 }
233
234                 case iro_Call:
235                         /* The address of an entity is given as a parameter.
236                          * As long as we do not have analyses that can tell what
237                          * is done with parameters, think is taken.
238                          * One special case: If the Call type tells that it's a
239                          * value parameter, the address is NOT taken.
240                          */
241                         return 1;
242
243                 case iro_Id: {
244                         int res = is_address_taken(succ);
245                         if (res)
246                                 return 1;
247                         break;
248                 }
249
250                 case iro_Tuple:
251                         /* Non-optimized Tuple, happens in inlining */
252                         for (input_nr = get_Tuple_n_preds(succ) - 1; input_nr >= 0; --input_nr) {
253                                 ir_node *pred = get_Tuple_pred(succ, input_nr);
254
255                                 if (pred == sel) {
256                                         /* we found one input */
257                                         for (k = get_irn_n_outs(succ) - 1; k >= 0; --k) {
258                                                 ir_node *proj = get_irn_out(succ, k);
259
260                                                 if (is_Proj(proj) && get_Proj_proj(proj) == input_nr) {
261                                                         int res = is_address_taken(proj);
262                                                         if (res)
263                                                                 return 1;
264                                                 }
265                                         }
266                                 }
267                         }
268                         break;
269
270                 default:
271                         /* another op, the address is taken */
272                         return 1;
273                 }
274         }
275         return 0;
276 }
277
278 /**
279  * Link all leave Sels with the entity.
280  *
281  * @param ent  the entity that will be scalar replaced
282  * @param sel  a Sel node that selects some fields of this entity
283  */
284 static int link_all_leave_sels(ir_entity *ent, ir_node *sel)
285 {
286         int i, is_leave = 1;
287
288         for (i = get_irn_n_outs(sel) - 1; i >= 0; --i) {
289                 ir_node *succ = get_irn_out(sel, i);
290
291                 if (is_Sel(succ)) {
292                         /* the current leave has further Sel's, no leave */
293                         is_leave = 0;
294                         link_all_leave_sels(ent, succ);
295                 } else if (is_Id(succ)) {
296                         is_leave &= link_all_leave_sels(ent, succ);
297                 }
298         }
299
300         if (is_leave) {
301                 /* beware of Id's */
302                 sel = skip_Id(sel);
303
304                 /* we know we are at a leave, because this function is only
305                  * called if the address is NOT taken, so sel's successor(s)
306                  * must be Loads or Stores
307                  */
308                 set_irn_link(sel, get_entity_link(ent));
309                 set_entity_link(ent, sel);
310         }
311         return is_leave;
312 }
313
314 /* we need a special address that serves as an address taken marker */
315 static char _x;
316 static void *ADDRESS_TAKEN = &_x;
317
318 /**
319  * Find possible scalar replacements.
320  *
321  * @param irg  an IR graph
322  *
323  * This function finds variables on the (members of the) frame type
324  * that can be scalar replaced, because their address is never taken.
325  * If such a variable is found, it's entity link will hold a list of all
326  * Sel nodes, that selects the atomic fields of this entity.
327  * Otherwise, the link will be ADDRESS_TAKEN or NULL.
328  *
329  * @return  non-zero if at least one entity could be replaced
330  *          potentially
331  */
332 static int find_possible_replacements(ir_graph *irg)
333 {
334         ir_node *irg_frame;
335         ir_type *frame_tp;
336         int     i, j, k, static_link_arg;
337         int     res = 0;
338
339         /*
340          * First, clear the link field of all interesting entities.
341          */
342         frame_tp = get_irg_frame_type(irg);
343         for (i = get_class_n_members(frame_tp) - 1; i >= 0; --i) {
344                 ir_entity *ent = get_class_member(frame_tp, i);
345                 set_entity_link(ent, NULL);
346         }
347
348         /* check for inner functions:
349          * FIXME: need a way to get the argument position for the static link */
350         static_link_arg = 0;
351         for (i = get_class_n_members(frame_tp) - 1; i >= 0; --i) {
352                 ir_entity *ent = get_class_member(frame_tp, i);
353                 if (is_method_entity(ent)) {
354                         ir_graph *inner_irg = get_entity_irg(ent);
355                         ir_node  *args;
356
357                         assure_irg_outs(inner_irg);
358                         args = get_irg_args(inner_irg);
359                         for (j = get_irn_n_outs(args) - 1; j >= 0; --j) {
360                                 ir_node *arg = get_irn_out(args, j);
361
362                                 if (get_Proj_proj(arg) == static_link_arg) {
363                                         for (k = get_irn_n_outs(arg) - 1; k >= 0; --k) {
364                                                 ir_node *succ = get_irn_out(arg, k);
365
366                                                 if (is_Sel(succ)) {
367                                                         ir_entity *ent = get_Sel_entity(succ);
368
369                                                         if (get_entity_owner(ent) == frame_tp) {
370                                                                 /* found an access to the outer frame */
371                                                                 set_entity_link(ent, ADDRESS_TAKEN);
372                                                         }
373                                                 }
374                                         }
375                                 }
376                         }
377                 }
378         }
379
380         /*
381          * Check the ir_graph for Sel nodes. If the entity of Sel
382          * isn't a scalar replacement set the link of this entity
383          * equal ADDRESS_TAKEN.
384          */
385         irg_frame = get_irg_frame(irg);
386         for (i = get_irn_n_outs(irg_frame) - 1; i >= 0; --i) {
387                 ir_node *succ = get_irn_out(irg_frame, i);
388
389                 if (is_Sel(succ)) {
390                         ir_entity *ent = get_Sel_entity(succ);
391                         ir_type *ent_type;
392
393                         /* we are only interested in entities on the frame, NOT
394                            on the value type */
395                         if (get_entity_owner(ent) != frame_tp)
396                                 continue;
397
398                         if (get_entity_link(ent) == ADDRESS_TAKEN)
399                                 continue;
400
401                         /*
402                          * Beware: in rare cases even entities on the frame might be
403                          * volatile. This might happen if the entity serves as a store
404                          * to a value that must survive a exception. Do not optimize
405                          * such entities away.
406                          */
407                         if (get_entity_volatility(ent) == volatility_is_volatile) {
408                                 set_entity_link(ent, ADDRESS_TAKEN);
409                                 continue;
410                         }
411
412                         ent_type = get_entity_type(ent);
413
414                         /* we can handle arrays, structs and atomic types yet */
415                         if (is_Array_type(ent_type) || is_Struct_type(ent_type) || is_atomic_type(ent_type)) {
416                                 if (is_address_taken(succ)) {
417                                          /* killing one */
418                                         if (get_entity_link(ent))
419                                                 --res;
420                                         set_entity_link(ent, ADDRESS_TAKEN);
421                                 } else {
422                                         /* possible found one */
423                                         if (get_entity_link(ent) == NULL)
424                                                 ++res;
425                                         link_all_leave_sels(ent, succ);
426                                 }
427                         }
428                 }
429         }
430
431         return res;
432 }
433
434 /**
435  * Return a path from the Sel node sel to it's root.
436  *
437  * @param sel  the Sel node
438  * @param len  the length of the path so far
439  */
440 static path_t *find_path(ir_node *sel, unsigned len)
441 {
442         int pos, i, n;
443         path_t *res;
444         ir_node *pred = get_Sel_ptr(sel);
445
446         /* the current Sel node will add some path elements */
447         n    = get_Sel_n_indexs(sel);
448         len += n + 1;
449
450         if (! is_Sel(pred)) {
451                 /* we found the root */
452                 res = XMALLOCF(path_t, path, len);
453                 res->path_len = len;
454         } else
455                 res = find_path(pred, len);
456
457         pos = res->path_len - len;
458
459         res->path[pos++].ent = get_Sel_entity(sel);
460         for (i = 0; i < n; ++i) {
461                 ir_node *index = get_Sel_index(sel, i);
462
463                 res->path[pos++].tv = get_Const_tarval(index);
464         }
465         return res;
466 }
467
468
469 /**
470  * Allocate value numbers for the leaves
471  * in our found entities.
472  *
473  * @param sels  a set that will contain all Sels that have a value number
474  * @param ent   the entity that will be scalar replaced
475  * @param vnum  the first value number we can assign
476  * @param modes a flexible array, containing all the modes of
477  *              the value numbers.
478  *
479  * @return the next free value number
480  */
481 static unsigned allocate_value_numbers(pset *sels, ir_entity *ent, unsigned vnum, ir_mode ***modes)
482 {
483         ir_node *sel, *next;
484         path_t *key, *path;
485         set *pathes = new_set(path_cmp, 8);
486
487         DB((dbg, SET_LEVEL_3, "  Visiting Sel nodes of entity %+F\n", ent));
488         /* visit all Sel nodes in the chain of the entity */
489         for (sel = get_entity_link(ent); sel; sel = next) {
490                 next = get_irn_link(sel);
491
492                 /* we must mark this sel for later */
493                 pset_insert_ptr(sels, sel);
494
495                 key  = find_path(sel, 0);
496                 path = set_find(pathes, key, PATH_SIZE(key), path_hash(key));
497
498                 if (path) {
499                         SET_VNUM(sel, path->vnum);
500                         DB((dbg, SET_LEVEL_3, "  %+F represents value %u\n", sel, path->vnum));
501                 } else {
502                         key->vnum = vnum++;
503
504                         set_insert(pathes, key, PATH_SIZE(key), path_hash(key));
505
506                         SET_VNUM(sel, key->vnum);
507                         DB((dbg, SET_LEVEL_3, "  %+F represents value %u\n", sel, key->vnum));
508
509                         ARR_EXTO(ir_mode *, *modes, (int)((key->vnum + 15) & ~15));
510
511                         (*modes)[key->vnum] = get_type_mode(get_entity_type(get_Sel_entity(sel)));
512
513                         assert((*modes)[key->vnum] && "Value is not atomic");
514
515 #ifdef DEBUG_libfirm
516                         /* Debug output */
517                         {
518                                 unsigned i;
519                                 DB((dbg, SET_LEVEL_2, "  %s", get_entity_name(key->path[0].ent)));
520                                 for (i = 1; i < key->path_len; ++i) {
521                                         if (is_entity(key->path[i].ent))
522                                                 DB((dbg, SET_LEVEL_2, ".%s", get_entity_name(key->path[i].ent)));
523                                         else
524                                                 DB((dbg, SET_LEVEL_2, "[%ld]", get_tarval_long(key->path[i].tv)));
525                                 }
526                                 DB((dbg, SET_LEVEL_2, " = %u (%s)\n", PTR_TO_INT(get_irn_link(sel)), get_mode_name((*modes)[key->vnum])));
527                         }
528 #endif /* DEBUG_libfirm */
529                 }
530                 free(key);
531         }
532
533         del_set(pathes);
534         set_entity_link(ent, NULL);
535         return vnum;
536 }
537
538 /**
539  * A list entry for the fixing lists
540  */
541 typedef struct _list_entry_t {
542         ir_node  *node;   /**< the node that must be fixed */
543         unsigned vnum;    /**< the value number of this node */
544 } list_entry_t;
545
546 /**
547  * environment for memory walker
548  */
549 typedef struct _env_t {
550         int          nvals;       /**< number of values */
551         ir_mode      **modes;     /**< the modes of the values */
552         pset         *sels;       /**< A set of all Sel nodes that have a value number */
553 } env_t;
554
555 /**
556  * topological post-walker.
557  */
558 static void topologic_walker(ir_node *node, void *ctx)
559 {
560         env_t        *env = ctx;
561         ir_node      *adr, *block, *mem, *val;
562         ir_mode      *mode;
563         unsigned     vnum;
564
565         if (is_Load(node)) {
566                 /* a load, check if we can resolve it */
567                 adr = get_Load_ptr(node);
568
569                 DB((dbg, SET_LEVEL_3, "  checking %+F for replacement ", node));
570                 if (! is_Sel(adr)) {
571                         DB((dbg, SET_LEVEL_3, "no Sel input (%+F)\n", adr));
572                         return;
573                 }
574
575                 if (! pset_find_ptr(env->sels, adr)) {
576                         DB((dbg, SET_LEVEL_3, "Sel %+F has no VNUM\n", adr));
577                         return;
578                 }
579
580                 /* ok, we have a Load that will be replaced */
581                 vnum = GET_VNUM(adr);
582                 assert(vnum < (unsigned)env->nvals);
583
584                 DB((dbg, SET_LEVEL_3, "replacing by value %u\n", vnum));
585
586                 block = get_nodes_block(node);
587                 set_cur_block(block);
588
589                 /* check, if we can replace this Load */
590                 val = get_value(vnum, env->modes[vnum]);
591
592                 /* Beware: A Load can contain a hidden conversion in Firm.
593                 This happens for instance in the following code:
594
595                  int i;
596                  unsigned j = *(unsigned *)&i;
597
598                 Handle this here. */
599                 mode = get_Load_mode(node);
600                 if (mode != get_irn_mode(val))
601                         val = new_d_Conv(get_irn_dbg_info(node), val, mode);
602
603                 mem = get_Load_mem(node);
604                 turn_into_tuple(node, pn_Load_max);
605                 set_Tuple_pred(node, pn_Load_M,         mem);
606                 set_Tuple_pred(node, pn_Load_res,       val);
607                 set_Tuple_pred(node, pn_Load_X_regular, new_Jmp());
608                 set_Tuple_pred(node, pn_Load_X_except,  new_Bad());
609         } else if (is_Store(node)) {
610                 DB((dbg, SET_LEVEL_3, "  checking %+F for replacement ", node));
611
612                 /* a Store always can be replaced */
613                 adr = get_Store_ptr(node);
614
615                 if (! is_Sel(adr)) {
616                         DB((dbg, SET_LEVEL_3, "no Sel input (%+F)\n", adr));
617                         return;
618                 }
619
620                 if (! pset_find_ptr(env->sels, adr)) {
621                         DB((dbg, SET_LEVEL_3, "Sel %+F has no VNUM\n", adr));
622                         return;
623                 }
624
625                 vnum = GET_VNUM(adr);
626                 assert(vnum < (unsigned)env->nvals);
627
628                 DB((dbg, SET_LEVEL_3, "replacing by value %u\n", vnum));
629
630                 block = get_nodes_block(node);
631                 set_cur_block(block);
632
633                 /* Beware: A Store can contain a hidden conversion in Firm. */
634                 val = get_Store_value(node);
635                 if (get_irn_mode(val) != env->modes[vnum])
636                         val = new_d_Conv(get_irn_dbg_info(node), val, env->modes[vnum]);
637
638                 set_value(vnum, val);
639
640                 mem = get_Store_mem(node);
641                 turn_into_tuple(node, pn_Store_max);
642                 set_Tuple_pred(node, pn_Store_M,         mem);
643                 set_Tuple_pred(node, pn_Store_X_regular, new_Jmp());
644                 set_Tuple_pred(node, pn_Store_X_except,  new_Bad());
645         }
646 }
647
648 /**
649  * Make scalar replacement.
650  *
651  * @param sels    A set containing all Sel nodes that have a value number
652  * @param nvals   The number of scalars.
653  * @param modes   A flexible array, containing all the modes of
654  *                the value numbers.
655  */
656 static void do_scalar_replacements(pset *sels, int nvals, ir_mode **modes)
657 {
658         env_t env;
659
660         ssa_cons_start(current_ir_graph, nvals);
661
662         env.nvals     = nvals;
663         env.modes     = modes;
664         env.sels      = sels;
665
666         /*
667          * second step: walk over the graph blockwise in topological order
668          * and fill the array as much as possible.
669          */
670         DB((dbg, SET_LEVEL_3, "Substituting Loads and Stores in %+F\n", current_ir_graph));
671         irg_walk_blkwise_graph(current_ir_graph, NULL, topologic_walker, &env);
672
673         ssa_cons_finish(current_ir_graph);
674 }
675
676 /*
677  * Find possible scalar replacements
678  *
679  * @param irg  The current ir graph.
680  */
681 int scalar_replacement_opt(ir_graph *irg)
682 {
683         unsigned  nvals;
684         int       i;
685         scalars_t key, *value;
686         ir_node   *irg_frame;
687         ir_mode   **modes;
688         set       *set_ent;
689         pset      *sels;
690         ir_type   *ent_type, *frame_tp;
691         ir_graph  *rem;
692         int       res = 0;
693
694         rem = current_ir_graph;
695         current_ir_graph = irg;
696
697         /* Call algorithm that computes the out edges */
698         assure_irg_outs(irg);
699
700         /* we use the link field to store the VNUM */
701         ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
702         irp_reserve_resources(irp, IR_RESOURCE_ENTITY_LINK);
703
704         /* Find possible scalar replacements */
705         if (find_possible_replacements(irg)) {
706                 DB((dbg, SET_LEVEL_1, "Scalar Replacement: %+F\n", irg));
707
708                 /* Insert in set the scalar replacements. */
709                 irg_frame = get_irg_frame(irg);
710                 nvals     = 0;
711                 modes     = NEW_ARR_F(ir_mode *, 16);
712                 set_ent   = new_set(ent_cmp, 8);
713                 sels      = pset_new_ptr(8);
714                 frame_tp  = get_irg_frame_type(irg);
715
716                 for (i = get_irn_n_outs(irg_frame) - 1; i >= 0; --i) {
717                         ir_node *succ = get_irn_out(irg_frame, i);
718
719                         if (is_Sel(succ)) {
720                                 ir_entity *ent = get_Sel_entity(succ);
721
722                                 /* we are only interested in entities on the frame, NOT
723                                    on the value type */
724                                 if (get_entity_owner(ent) != frame_tp)
725                                         continue;
726
727                                 if (get_entity_link(ent) == NULL || get_entity_link(ent) == ADDRESS_TAKEN)
728                                         continue;
729
730                                 ent_type = get_entity_type(ent);
731
732                                 key.ent       = ent;
733                                 key.ent_owner = get_entity_owner(ent);
734                                 set_insert(set_ent, &key, sizeof(key), HASH_PTR(key.ent));
735
736 #ifdef DEBUG_libfirm
737                                 if (is_Array_type(ent_type)) {
738                                         DB((dbg, SET_LEVEL_1, "  found array %s\n", get_entity_name(ent)));
739                                 } else if (is_Struct_type(ent_type)) {
740                                         DB((dbg, SET_LEVEL_1, "  found struct %s\n", get_entity_name(ent)));
741                                 } else if (is_atomic_type(ent_type))
742                                         DB((dbg, SET_LEVEL_1, "  found atomic value %s\n", get_entity_name(ent)));
743                                 else {
744                                         panic("Neither an array nor a struct or atomic value found in scalar replace");
745                                 }
746 #endif /* DEBUG_libfirm */
747
748                                 nvals = allocate_value_numbers(sels, ent, nvals, &modes);
749                         }
750                 }
751
752                 DB((dbg, SET_LEVEL_1, "  %u values will be needed\n", nvals));
753
754                 /* If scalars were found. */
755                 if (nvals > 0) {
756                         do_scalar_replacements(sels, nvals, modes);
757
758                         foreach_set(set_ent, value) {
759                                 remove_class_member(value->ent_owner, value->ent);
760                         }
761
762                         /*
763                          * We changed the graph, but did NOT introduce new blocks
764                          * neither changed control flow, cf-backedges should be still
765                          * consistent.
766                          */
767                         set_irg_outs_inconsistent(irg);
768                         set_irg_loopinfo_inconsistent(irg);
769
770                         res = 1;
771                 }
772                 del_pset(sels);
773                 del_set(set_ent);
774                 DEL_ARR_F(modes);
775         }
776
777         ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
778         irp_free_resources(irp, IR_RESOURCE_ENTITY_LINK);
779
780         current_ir_graph = rem;
781         return res;
782 }
783
784 ir_graph_pass_t *scalar_replacement_opt_pass(const char *name)
785 {
786         return def_graph_pass_ret(name ? name : "scalar_rep",
787                                   scalar_replacement_opt);
788 }
789
790 void firm_init_scalar_replace(void)
791 {
792         FIRM_DBG_REGISTER(dbg, "firm.opt.scalar_replace");
793 }