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