- BugFix: replaced wrong cast by right code (no crash because offset is 0)
[libfirm] / ir / opt / data_flow_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 arrays and compounds
23  * @author  Beyhan Veliev, Michael Beck
24  * @version $Id$
25  */
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "iroptimize.h"
31
32 #include <string.h>
33
34 #include "irflag_t.h"
35 #include "irouts.h"
36 #include "pset.h"
37 #include "ircons_t.h"
38 #include "hashptr.h"
39 #include "irgwalk.h"
40 #include "irnode_t.h"
41 #include "irtools.h"
42 #include "irdump.h"
43 #include "irloop.h"
44 #include "analyze_irg_args.h"
45 #include "irprintf.h"
46 #include "irgopt.h"
47 #include "xmalloc.h"
48
49 #define SET_ENT_VNUM(ent, vnum) set_entity_link(ent, INT_TO_PTR(vnum))
50 #define GET_ENT_VNUM(ent)       (unsigned)PTR_TO_INT(get_entity_link(ent))
51 #define SET_IRN_VNUM(irn, vnum) set_irn_link(irn, INT_TO_PTR(vnum))
52 #define GET_IRN_VNUM(irn)       (unsigned)PTR_TO_INT(get_irn_link(irn))
53 #define SYNCED    8
54
55
56 typedef struct _ent_leaves_t{
57   ir_entity *ent;             /**< An entity, that contains scalars for replace.*/
58   pset *leaves;               /**< All leaves of this entity.*/
59 } ent_leaves_t;
60
61 typedef struct _sels_t {
62   ir_node *sel;               /**< A sel node, thats entity have scalars.*/
63   ir_entity  *ent;            /**< The entity of this sel node.*/
64 }sels_t;
65
66 typedef struct _call_access_t {
67   ir_node *call;             /**< A call node, that have as parameter a scalar.*/
68   unsigned int access_type;  /**< The access type, with that this call access this scalar.*/
69 }call_access_t;
70
71 typedef struct _fixlist_entry_t {
72   ir_node *irn;             /**< An ir node, that must be fixed.*/
73   unsigned int vnum;        /**< The value number, that must became this ir node.*/
74 }fixlist_entry_t;
75
76 typedef struct _syncs_fixlist_entry_t {
77   ir_node *irn;             /**< A sync node that must be fixed.*/
78   int *accessed_vnum;       /**< A pointer to save an array with value numbers, that must became this sync.*/
79 }syncs_fixlist_entry_t;
80
81 /* A entry, that save the memory
82  * edge state and the access state for this leave
83  * int the array,that is created for every block.*/
84 typedef struct _leave_t {
85   ir_node *mem_edge_state;   /**< memory state for this scalar in this block.*/
86   unsigned int access_type;  /**< access state for this scalar in this block.*/
87   set *calls;                /**< call nodes,that change this scalar in this block.*/
88 }value_arr_entry_t;
89
90 /**
91  * A path element entry: it is either an entity
92  * or a tarval, because we evaluate only constant array
93  * accesses like a.b.c[8].d
94  */
95 typedef union {
96   ir_entity *ent;
97   tarval *tv;
98 } path_elem_t;
99
100 /**
101  * An access path, used to assign value numbers
102  * to variables that will be scalar replaced
103  */
104 typedef struct _path_t {
105   unsigned    vnum;      /**< the value number */
106   unsigned    path_len;  /**< the length of the access path */
107   path_elem_t path[1];   /**< the path */
108 } path_t;
109
110 /**
111  * environment for memory walker
112  */
113 typedef struct _env_t {
114   struct obstack obst;                   /**< a obstack for the memory edge */
115   set                   *set_sels;       /**< a set with all sels, that are reachable from an entity with a scalar.*/
116   set                   *set_ent;        /**< a set with all entities that have one or more scalars.*/
117   fixlist_entry_t       *fix_phis;       /**< list of all Phi nodes that must be fixed */
118   fixlist_entry_t       *fix_ls;         /**< list of all Load or Store nodes that must be fixed */
119   syncs_fixlist_entry_t *fix_syncs;      /**< list of all Sync nodes that must be fixed */
120   unsigned int          nvals;           /**< to save the number of scalars.*/
121   unsigned int          gl_mem_vnum;     /**< indicate the position of the globule memory edge state in var_arr.*/
122   unsigned int          vnum_state;      /**< indicate the position of the value number state in var_arr.*/
123   unsigned int          changes;         /**< to save if by anlyse_calls is changed anything.*/
124 } env_t;
125
126
127
128 /**
129  * Compare two elements of the ent_leaves_t set.
130  *
131  * @return 0 if they are identically
132  */
133 static int ent_leaves_t_cmp(const void *elt, const void *key, size_t size)
134 {
135   const ent_leaves_t *c1 = elt;
136   const ent_leaves_t *c2 = key;
137   (void) size;
138
139   return c1->ent != c2->ent;
140 }
141
142 /**
143  * Compare two elements of the ent_access_t set.
144  *
145  * @return 0 if they are identically
146  */
147 static int ent_cmp(const void *elt, const void *key)
148 {
149   const ir_entity *c1 = elt;
150   const ir_entity *c2 = key;
151
152   return c1 != c2;
153 }
154
155 /**
156  * Compare two elements of the sels_t set.
157  *
158  * @return 0 if they are identically
159  */
160 static int sels_cmp(const void *elt, const void *key, size_t size)
161 {
162   const sels_t *c1 = elt;
163   const sels_t *c2 = key;
164   (void) size;
165
166   return c1->sel != c2->sel;
167 }
168
169 /**
170  * Compare two elements of the leave_t set.
171  *
172  * @return 0 if they are identically
173  */
174 static int leave_cmp(const void *elt, const void *key)
175 {
176   ir_node *c1 = (ir_node *)elt;
177   ir_node *c2 = (ir_node *)key;
178
179   return get_Sel_entity(c1) != get_Sel_entity(c2);
180 }
181
182 /**
183  * Compare two elements of the call_access_t set.
184  *
185  * @return 0 if they are identically
186  */
187 static int call_cmp(const void *elt, const void *key, size_t size)
188 {
189   const call_access_t *c1 = elt;
190   const call_access_t *c2 = key;
191   (void) size;
192
193   return c1->call != c2->call;
194 }
195
196 /**
197  * Compare two paths.
198  *
199  * @return 0 if they are identically
200  */
201 static int path_cmp(const void *elt, const void *key, size_t size)
202 {
203   const path_t *p1 = elt;
204   const path_t *p2 = key;
205   (void) size;
206
207   /* we can use memcmp here, because identical tarvals should have identical addresses */
208   return memcmp(p1->path, p2->path, p1->path_len * sizeof(p1->path[0]));
209 }
210
211 /**
212  * Calculate a hash value for a path.
213  */
214 static unsigned path_hash(const path_t *path)
215 {
216   unsigned hash = 0;
217   unsigned i;
218
219   for (i = 0; i < path->path_len; ++i)
220     hash ^= (unsigned)PTR_TO_INT(path->path[i].ent);
221
222   return hash >> 4;
223 }
224
225 /**
226  * Returns non-zero, if all induces of a Sel node are constants.
227  *
228  * @param sel  the Sel node that will be checked
229  */
230 static int is_const_sel(ir_node *sel) {
231   int i, n = get_Sel_n_indexs(sel);
232
233   for (i = 0; i < n; ++i) {
234     ir_node *idx = get_Sel_index(sel, i);
235
236     if (get_irn_op(idx) != op_Const)
237       return 0;
238   }
239   return 1;
240 }
241
242 /**
243  * Returns non-zero, if the address of an entity
244  * represented by a Sel node (or it's successor Sels) is taken.
245  */
246 static int is_address_taken_2(ir_node *sel)
247 {
248   int i;
249
250   if (! is_const_sel(sel))
251     return 1;
252
253   for (i = get_irn_n_outs(sel) - 1; i >= 0; --i) {
254     ir_node *succ = get_irn_out(sel, i);
255
256     switch (get_irn_opcode(succ)) {
257     case iro_Load:
258       /* ok, we just load from that entity */
259       break;
260
261     case iro_Store:
262       /* check that Sel is not the Store's value */
263       if (get_Store_value(succ) == sel)
264         return 1;
265       break;
266
267     case iro_Sel: {
268       /* Check the Sel successor of Sel */
269       int res = is_address_taken_2(succ);
270
271       if (res)
272         return 1;
273       break;
274     }
275
276     case iro_Call:
277       /* The address of an entity is given as a parameter.
278        * We analyzes that later and optimizes this scalar
279        * if possible.
280        */
281       return 0;
282
283     default:
284       /* another op, the address is taken */
285       return 1;
286     }
287   }
288   return 0;
289 }
290
291 /**
292  * Link all Sels with the entity.
293  *
294  * @param ent  the entity that will be scalar replaced
295  * @param sel  a Sel node that selects some fields of this entity
296  */
297 static void link_all_leave_sels(ir_entity *ent, ir_node *sel)
298 {
299   int i, n;
300
301   n = get_irn_n_outs(sel);
302   for (i = 0; i < n; ++i) {
303     ir_node *succ = get_irn_out(sel, i);
304
305     if (get_irn_op(succ) == op_Sel)
306       link_all_leave_sels(ent, succ);
307
308   }
309
310    /* if Sel nodes with memory inputs are used, a entity can be
311     * visited more than once causing a ring here, so we use the
312     * node flag to mark linked nodes
313     */
314    if (irn_visited(sel))
315     return;
316
317   /*
318    * we link the sels to the entity.
319    */
320   set_irn_link(sel, get_entity_link(ent));
321   set_entity_link(ent, sel);
322
323   mark_irn_visited(sel);
324 }
325
326 /* we need a special address that serves as an address taken marker */
327 static char _x;
328 static void *ADDRESS_TAKEN = &_x;
329
330 /**
331  * Find possible scalar replacements.
332  *
333  * @param irg  an IR graph
334  *
335  * This function finds variables on the (members of the) frame type
336  * that can be scalar replaced, because their address is never taken.
337  * If such a variable is found, it's entity link will hold a list of all
338  * Sel nodes, that selects anythings of this entity.
339  * Otherwise, the link will be ADDRESS_TAKEN or NULL.
340  *
341  * @return  non-zero if at least one entity could be replaced
342  *          potentially
343  */
344 static int find_possible_replacements(ir_graph *irg)
345 {
346   ir_node *irg_frame = get_irg_frame(irg);
347   int i, n;
348   int res = 0;
349
350   inc_irg_visited(irg);
351
352   n = get_irn_n_outs(irg_frame);
353
354   /*
355    * First, clear the link field of all interestingentities.
356    * Note that we did not rely on the fact that there is only
357    * one Sel node per entity, so we might access one entity
358    * more than once here.
359    * That's why we have need two loops.
360    */
361   for (i = 0; i < n; ++i) {
362     ir_node *succ = get_irn_out(irg_frame, i);
363
364     if (get_irn_op(succ) == op_Sel) {
365       ir_entity *ent = get_Sel_entity(succ);
366       set_entity_link(ent, NULL);
367     }
368   }
369
370   /*
371    * Check the ir_graph for Sel nodes. If the entity of Sel
372    * isn't a scalar replacement set the link of this entity
373    * equal ADDRESS_TAKEN.
374    */
375   for (i = 0; i < n; ++i) {
376     ir_node *succ = get_irn_out(irg_frame, i);
377
378     if (get_irn_op(succ) == op_Sel) {
379       ir_entity *ent = get_Sel_entity(succ);
380       ir_type *ent_type;
381
382       if (get_entity_link(ent) == ADDRESS_TAKEN)
383         continue;
384
385       /*
386        * Beware: in rare cases even entities on the frame might be
387        * volatile. This might happen if the entity serves as a store
388        * to a value that must survive a exception. Do not optimize
389        * such entities away.
390        */
391       if (get_entity_volatility(ent) == volatility_is_volatile) {
392         set_entity_link(ent, ADDRESS_TAKEN);
393         continue;
394       }
395
396       ent_type = get_entity_type(ent);
397
398       /* we can handle arrays, structs and atomic types yet */
399       if (is_Array_type(ent_type) || is_Struct_type(ent_type) || is_atomic_type(ent_type)) {
400         if (is_address_taken_2(succ)) {
401           if (get_entity_link(ent)) /* killing one */
402             --res;
403           set_entity_link(ent, ADDRESS_TAKEN);
404         }
405         else {
406           /* possible found one */
407           if (get_entity_link(ent) == NULL)
408             ++res;
409           link_all_leave_sels(ent, succ);
410         }
411       }
412     }
413   }
414
415   return res;
416 }
417
418 static int is_leave_sel(ir_node *sel) {
419   int i;
420   ir_node *succ;
421
422   for(i = get_irn_n_outs(sel) - 1; i >= 0; i--) {
423     succ = get_irn_out(sel, i);
424     if(get_irn_op(succ) == op_Sel)
425       return 0;
426   }
427
428   return 1;
429 }
430
431 /**
432  * Return a path from the Sel node sel to it's root.
433  *
434  * @param sel  the Sel node
435  * @param len  the length of the path so far
436  */
437 static path_t *find_path(ir_node *sel, unsigned len)
438 {
439   int pos, i, n;
440   path_t *res;
441   ir_node *pred = get_Sel_ptr(sel);
442
443   /* the current Sel node will add some path elements */
444   n    = get_Sel_n_indexs(sel);
445   len += n + 1;
446
447   if (get_irn_op(pred) != op_Sel) {
448     /* we found the root */
449
450     res = xmalloc(sizeof(*res) + (len - 1) * sizeof(res->path));
451     res->path_len = len;
452   }
453   else
454     res = find_path(pred, len);
455
456   pos = res->path_len - len;
457
458   res->path[pos++].ent = get_Sel_entity(sel);
459   for (i = 0; i < n; ++i) {
460     ir_node *index = get_Sel_index(sel, i);
461
462     if(get_irn_op(index) == op_Const)
463       res->path[pos++].tv = get_Const_tarval(index);
464   }
465   return res;
466 }
467
468 /**
469  * Allocate value numbers for the leaves
470  * in our found entities.
471  *
472  * @param sels  a set that will contain all Sels that have a value number
473  * @param ent   the entity that will be scalar replaced
474  * @param vnum  the first value number we can assign
475  * @param modes a flexible array, containing all the modes of
476  *              the value numbers.
477  *
478  * @return the next free value number
479  */
480 static unsigned allocate_value_numbers(set *set_sels, pset *leaves, ir_entity *ent, unsigned vnum)
481 {
482   ir_node *sel, *next;
483   path_t *key, *path;
484   sels_t       key_sels;
485   set *pathes = new_set(path_cmp, 8);
486
487   /* visit all Sel nodes in the chain of the entity */
488   for (sel = get_entity_link(ent); sel; sel = next) {
489     next = get_irn_link(sel);
490
491     /* we save for every sel it root entity, why
492      * we need this information, when we split the memory edge,
493      * and we must mark this sel for later. */
494      key_sels.ent = ent;
495      key_sels.sel = sel;
496      set_insert(set_sels, &key_sels, sizeof(key_sels), HASH_PTR(sel));
497
498     if(! is_leave_sel(sel))
499       continue;
500     /* We have found a leave and we add it to the pset of this entity.*/
501     pset_insert(leaves, sel, HASH_PTR(get_Sel_entity(sel)));
502
503     key  = find_path(sel, 0);
504     path = set_find(pathes, key, sizeof(*key) + sizeof(key->path[0]) * key->path_len, path_hash(key));
505
506     if (path)
507       SET_IRN_VNUM(sel, path->vnum);
508     else {
509
510       key->vnum = vnum++;
511
512       set_insert(pathes, key, sizeof(*key) + sizeof(key->path[0]) * key->path_len, path_hash(key));
513
514       SET_IRN_VNUM(sel, key->vnum);
515     }
516     free(key);
517   }
518
519   del_set(pathes);
520   set_entity_link(ent, NULL);
521   return vnum;
522 }
523 /**
524  * Add a sync node to it fix list.
525  *
526  * @param sync     The sync node, that myst be addet to the fix list.
527  * @param unk_vnum An array whit the value number, that are synced with this sync node.
528  * @param env      The enviroment pinter.
529  */
530 static void add_sync_to_fixlist(ir_node *sync, int *unk_vnum, env_t *env) {
531
532    syncs_fixlist_entry_t *s;
533
534    s = obstack_alloc(&env->obst, sizeof(*s));
535    s->irn  = sync;
536    s->accessed_vnum = unk_vnum;
537    set_irn_link(sync, env->fix_syncs);
538    env->fix_syncs = s;
539 }
540 /**
541  * Add a ir node to it fix list.
542  *
543  * @param irn     The ir node, that myst be addet to the fix list.
544  * @param vnum    The value number, that must baceme this ir node as predecessor later.
545  * @param env     The enviroment pinter.
546  */
547 static void add_ls_to_fixlist(ir_node *irn, int vnum, env_t *env) {
548
549   fixlist_entry_t *l;
550
551   l = obstack_alloc(&env->obst, sizeof(*l));
552   l->irn  = irn;
553   l->vnum = vnum;
554
555   if(get_irn_op(irn) == op_Phi) {
556     set_irn_link(l->irn, env->fix_phis);
557     env->fix_phis = l;
558   }else {
559     set_irn_link(l->irn, env->fix_ls);
560     env->fix_ls = l;
561   }
562 }
563
564 static void add_mem_edge(value_arr_entry_t *val_arr, int vnum, ir_node ***in, int **accessed_vnum) {
565
566   if(val_arr[vnum].mem_edge_state != NULL)
567     ARR_APP1(ir_node *, *in, val_arr[vnum].mem_edge_state);
568   else {
569     ARR_APP1(int, *accessed_vnum, vnum);
570     ARR_APP1(ir_node *, *in, new_Unknown(mode_M));
571   }
572 }
573 /**
574  * The function handles the scalars, that wase stored
575  * in this block.
576  *
577  * @param blk    The block, that must be handled.
578  * @param env    The enviroment pinter.
579  */
580
581 /* Return the memory successor of the call node.*/
582 static ir_node *get_Call_mem_out(ir_node *call) {
583
584   int i;
585   ir_node *mem;
586
587   for(i = get_irn_n_outs(call) - 1; i >= 0; i--) {
588     mem = get_irn_out(call, i);
589     if(get_irn_mode(mem) == mode_M)
590       return mem;
591   }
592   /* is not reachable*/
593   return NULL;
594 }
595
596
597 static void sync_stored_scalars(ir_node *blk, env_t *env) {
598
599   int                   i;
600   int                   *unk_vnum;                   /**< An arraw, where are saved the value number, that
601                                                           are synced from this sync node.*/
602   ent_leaves_t          *value_ent;
603   value_arr_entry_t     *val_arr_blk, *val_arr;
604   ir_node               *pred, *leave, *sync, **in;
605   ir_node               *sync_blk;                     /**< The block, where the sync node must be created.*/
606
607
608   val_arr_blk = get_irn_link(blk);
609
610   for(value_ent = set_first(env->set_ent); value_ent; value_ent = set_next(env->set_ent)) {
611
612
613     if(val_arr_blk[GET_ENT_VNUM(value_ent->ent)].access_type <= 3)
614       /* This entity is not stored in this block.*/
615       continue;
616
617     for(i = get_Block_n_cfgpreds(blk) - 1; i >= 0; i--) {
618
619       pred = get_Block_cfgpred(blk, i);
620       pred = get_nodes_block(pred);
621       val_arr = get_irn_link(pred);
622
623       if(val_arr[GET_ENT_VNUM(value_ent->ent)].access_type == SYNCED)
624         /* This entity was synced.*/
625         continue;
626
627       if(val_arr[GET_ENT_VNUM(value_ent->ent)].access_type <= 3) {
628
629         /* To avoid repeated sync of this entity in this block.*/
630         val_arr[GET_ENT_VNUM(value_ent->ent)].access_type = SYNCED;
631         /* In this predecessor block is this entity not acessed.
632          * We must sync in the end ot this block.*/
633         if(get_Block_n_cfgpreds(blk) > 1)
634           sync_blk = get_nodes_block(get_Block_cfgpred(blk, i));
635         else
636           sync_blk = blk;
637
638         val_arr = get_irn_link(sync_blk);
639         /* An array to save the memory edges, that must be
640          * synced.*/
641         in = NEW_ARR_F(ir_node *, 1);
642
643         /* An array to save the value numbers,
644          * that must be repaired.*/
645         unk_vnum = NEW_ARR_F(int, 0);
646         /* The global memory edge.*/
647         if(val_arr[env->gl_mem_vnum].mem_edge_state == NULL)
648          in[0] = new_Unknown(mode_M);
649         else
650          in[0] = val_arr[env->gl_mem_vnum].mem_edge_state;
651
652         for(leave = pset_first(value_ent->leaves); leave; leave = pset_next(value_ent->leaves))
653           /* All this memory edges must be synced.*/
654           add_mem_edge(val_arr, GET_IRN_VNUM(leave), &in, &unk_vnum);
655
656         /* We create the sync and set it in the global memory state.*/
657         sync = new_r_Sync(current_ir_graph, sync_blk, ARR_LEN(in), in);
658         /* We must check this, why it is possible to get a Bad node
659          * form new_r_Sync(), when the node can be optimized.
660          * In this case we must do nothing.*/
661         if(get_irn_op(sync) == op_Sync)  {
662           val_arr[env->gl_mem_vnum].mem_edge_state = sync;
663           /* We add this sync node to the sync's fix list.*/
664           add_sync_to_fixlist(val_arr[env->gl_mem_vnum].mem_edge_state, unk_vnum, env);
665         }
666         DEL_ARR_F(in);
667       }
668     }
669   }
670 }
671 /**
672  * The function split the memory edge of load and store nodes, that have
673  * as predecessor a scalar
674  *
675  * @param irn   The node, that memory edge must be spleted.
676  * @param env   The enviroment pinter.
677  */
678 static void split_ls_mem_edge(ir_node *irn, env_t *env) {
679
680   ir_op              *op;
681   ir_node            *leave, *irn_blk, *mem_state, *new_mem_state;
682   unsigned           ent_vnum, sel_vnum, i;
683   value_arr_entry_t  *val_arr;
684   sels_t             key_sels, *value_sels;
685   ent_leaves_t       key_ent, *value_ent;
686
687   op = get_irn_op(irn);
688
689   if(op == op_Load)
690     key_sels.sel = get_Load_ptr(irn);
691   else
692     key_sels.sel = get_Store_ptr(irn);
693
694   value_sels = set_find(env->set_sels, &key_sels, sizeof(key_sels), HASH_PTR(key_sels.sel));
695
696   if(value_sels != NULL) {
697     /* we have found a load or store, that use a sel of our set
698      * and we must split or extend, if the memory edge have been
699      * split for this sel, the memory edge.*/
700
701     key_ent.ent = value_sels->ent;
702     value_ent = set_find(env->set_ent, &key_ent, sizeof(key_ent), HASH_PTR(key_ent.ent));
703     /*To check if the enities set is right filled. */
704     assert(value_ent && " This sel's entity isn't int the entity set.");
705
706     leave = pset_find(value_ent->leaves, key_sels.sel, HASH_PTR(get_Sel_entity(key_sels.sel)));
707     /*To check if the leaves set is right filled. */
708     assert(leave && "Anything in data_flow_scalar_replacment algorithm is wrong.");
709
710     ent_vnum = GET_ENT_VNUM(value_ent->ent);
711     sel_vnum = GET_IRN_VNUM(leave);
712     irn_blk = get_nodes_block(irn);
713     val_arr   = get_irn_link(irn_blk);
714
715     if(val_arr[ent_vnum].access_type == 0)
716       /* We have found a scalar, that address is not stored as jet.*/
717       i = sel_vnum;
718     else
719       /* This scalar have been stored.*/
720       i = env->gl_mem_vnum;
721
722     if(val_arr[i].mem_edge_state == NULL) {
723       /* We split now for this sel the memory edge in this block.*/
724       mem_state = new_Unknown(mode_M);
725       /* We must mark this node to fix later*/
726       add_ls_to_fixlist(irn, i, env);
727     }
728     else
729       /* We have split the memory edge and the current state is saved.*/
730       mem_state = val_arr[i].mem_edge_state;
731
732     /* We set this Load or Store to the memory edge of this
733      * sel.*/
734     if(op == op_Load)
735       set_Load_mem(irn, mem_state);
736     else
737       set_Store_mem(irn, mem_state);
738
739     /* When we have split or extended the memory edge we must
740      * update the memory_edge_state of this sel*/
741     new_mem_state = get_irn_out(irn, 0);
742     if(get_irn_mode(new_mem_state) == mode_M)
743       val_arr[i].mem_edge_state = new_mem_state;
744     else
745       val_arr[i].mem_edge_state = get_irn_out(irn, 1);
746   }
747 }
748
749 /**
750  * The function split the memory edge of phi nodes, that have
751  * as predecessor a scalar
752  *
753  * @param irn   The phi node, that memory edge must be spleted.
754  * @param env   The enviroment pinter.
755  */
756 static void split_phi_mem_edge(ir_node *irn, env_t *env) {
757
758   ir_node            *irn_blk, *unk, *leave, **in;
759   int                n, j;
760   ent_leaves_t       *value_ent;
761   value_arr_entry_t  *val_arr;
762
763   irn_blk = get_nodes_block(irn);
764   val_arr = get_irn_link(irn_blk);
765
766   n = get_Block_n_cfgpreds(irn_blk);
767
768   in = alloca(sizeof(*in) * n);
769
770   for(value_ent = set_first(env->set_ent); value_ent; value_ent = set_next(env->set_ent))
771      if(val_arr[GET_ENT_VNUM(value_ent->ent)].access_type < 3)
772        /* This scalar wasn't be saved and we need to produce a phi for it.*/
773        for(leave = pset_first(value_ent->leaves); leave; leave = pset_next(value_ent->leaves)){
774
775          unk = new_Unknown(mode_M);
776          for (j = n - 1; j >= 0; --j)
777            in[j] = unk;
778
779          val_arr[GET_IRN_VNUM(leave)].mem_edge_state = new_r_Phi(current_ir_graph, irn_blk, n, in, mode_M);
780
781          add_ls_to_fixlist(val_arr[GET_IRN_VNUM(leave)].mem_edge_state, GET_IRN_VNUM(leave), env);
782        }
783
784   /* We use for the global memory the phi node, that
785    * is already available.*/
786   val_arr[env->gl_mem_vnum].mem_edge_state = irn;
787 }
788
789 /**
790  * The function handles the call nodes, that have
791  * as parameter a scalar
792  *
793  * @param env                The enviroment pinter.
794  * @param call               The call node, that must be handled.
795  * @param accessed_entities  A set wit all entities, that are accessed from this call node.*/
796 static void split_call_mem_edge(env_t *env, ir_node *call, pset *accessed_entities) {
797
798   ent_leaves_t            key_ent, *value_ent;
799   value_arr_entry_t       *val_arr;
800   call_access_t           key_call, *value_call;
801   ir_node                 *call_blk, *new_mem_state, *leave;
802   ir_node                 *sync, **in;
803   ir_entity               *ent;
804   unsigned                ent_vnum;
805   int                     fix_irn = 0;                  /**< Set to 1 if we must add this call to it fix list.*/
806   int                     *accessed_leaves_vnum = NULL; /**< An arraw, where are saved the value number, that
807                                                              are synced from call's sync node, if we need it.*/
808
809   if(get_irn_node_nr(call) == 2763)
810     printf("\nHi\n");
811
812   call_blk = get_nodes_block(call);
813   val_arr  = get_irn_link(call_blk);
814   /* An array to save the memory edges, that must be
815    * synced.*/
816   in       = NEW_ARR_F(ir_node *, 1);
817   /* An array to save the value numbers of the memory
818    * edges that must be repaired.*/
819   accessed_leaves_vnum = NEW_ARR_F(int, 0);
820
821   /* We get the memory successor of the call node.
822    * It is the new memory state for all synced memory
823    * edges.*/
824   new_mem_state = get_Call_mem_out(call);
825
826   /* The global memory is the first predecessor of the create sync node.*/
827   if(val_arr[env->gl_mem_vnum].mem_edge_state == NULL) {
828     in[0] = new_Unknown(mode_M);
829     fix_irn = 1;
830   }
831   else
832     in[0] = val_arr[env->gl_mem_vnum].mem_edge_state;
833
834
835   for(ent = pset_first(accessed_entities); ent; ent = pset_next(accessed_entities)) {
836     /* Whit this loop we iterate all accessed entities from this call and collect
837      * all memory edges, that we must sync.*/
838     ent_vnum = GET_ENT_VNUM(ent);
839
840     key_call.call = call;
841     value_call    = set_find(val_arr[ent_vnum].calls, &key_call, sizeof(key_call), HASH_PTR(key_call.call));
842
843     key_ent.ent   = ent;
844     value_ent     = set_find(env->set_ent, &key_ent, sizeof(key_ent), HASH_PTR(key_ent.ent));
845
846     if(val_arr[ent_vnum].access_type <= 3) {
847       /* This scalar's address wasn't stored in this block.*/
848       switch(value_call->access_type) {
849
850       case ptr_access_none :
851         /* In this case we have nothing to do.*/
852       break;
853
854       case ptr_access_read:
855       case ptr_access_write:
856       case ptr_access_rw:
857         /* All this cases must be traded equal.*/
858
859         for(leave = pset_first(value_ent->leaves); leave; leave = pset_next(value_ent->leaves)){
860           /* All this memory edges must be synced.*/
861           add_mem_edge(val_arr, GET_IRN_VNUM(leave), &in, &accessed_leaves_vnum);
862
863           /* We update the memory state of this leave.*/
864           if(value_call->access_type != ptr_access_read)
865            val_arr[GET_IRN_VNUM(leave)].mem_edge_state = new_mem_state;
866         }
867
868       /* We are ready.*/
869       break;
870       }
871     }
872   }
873
874   /* We must update the global memory state.*/
875   val_arr[env->gl_mem_vnum].mem_edge_state = new_mem_state;
876
877   if(ARR_LEN(in) == 1) {
878     /* we must set the call memory to gobale momory*/
879     set_Call_mem(call,in[0]);
880
881     if(fix_irn)
882       /* We add this call node to the call fix list..*/
883       add_ls_to_fixlist(call, env->gl_mem_vnum, env);
884
885   } else {
886    /* We create the sync and set it as memory predecessor of the call node.*/
887       sync = new_r_Sync(current_ir_graph, call_blk, ARR_LEN(in), in);
888       /* We must check this, why it is possible to get a Bad node
889        * form new_r_Sync(), when the node can be optimized.
890        * In this case we must do nothing.*/
891       if(get_irn_op(sync) == op_Sync) {
892
893         set_Call_mem(call, sync);
894         if(ARR_LEN(accessed_leaves_vnum))
895           /* We add this sync node to the sync's fix list.*/
896           add_sync_to_fixlist(sync, accessed_leaves_vnum, env);
897       }
898   }
899   DEL_ARR_F(in);
900 }
901
902 /**
903  * The function split the memory edge from the passed
904  * ir node if this is needed
905  *
906  * @param irn   The node, that memory edge must be spleted.
907  * @param env   The enviroment pinter.
908  */
909 static void split_memory_edge(ir_node *irn, void *ctx) {
910
911    env_t              *env = ctx;
912    ir_node            *sel, *irn_blk;
913    ir_op              *op;
914    sels_t             key_sels, *value_sels;
915    value_arr_entry_t  *val_arr;
916    pset               *accessed_entities;  /**< A set to save all entities accessed from a call.*/
917    int                i;
918
919
920    op = get_irn_op(irn);
921
922    if(op == op_Block)
923      irn_blk = irn;
924    else
925      irn_blk = get_nodes_block(irn);
926
927    if (Block_not_block_visited(irn_blk)) {
928     /* We sync first the stored scalar address in this block.*/
929     mark_Block_block_visited(irn_blk);
930     sync_stored_scalars(irn_blk, env);
931    }
932
933    if(op == op_Load || op == op_Store)
934
935       split_ls_mem_edge(irn, env);
936
937    else {
938       if (op == op_Phi && get_irn_mode(irn) == mode_M) {
939         /*
940          * found a memory Phi: Here, we must create new Phi nodes
941          */
942         split_phi_mem_edge(irn, env);
943       }
944       else {
945         if(op == op_Call) {
946
947           /* Calls that have a NoMem input do neither read nor write memory.
948              We can completely ignore them here. */
949           if (get_irn_op(get_Call_mem(irn)) == op_NoMem)
950             return;
951
952           /* We save in this set all entities,
953            * that are accessed from this call node.*/
954           accessed_entities = new_pset(ent_cmp, 8);
955           val_arr = get_irn_link(get_nodes_block(irn));
956
957           for ( i = get_Call_n_params(irn) - 1; i >= 0; i--) {
958
959             sel = get_Call_param(irn, i);
960             value_sels = NULL;
961             if(get_irn_op(sel) == op_Sel) {
962               key_sels.sel = sel;
963               value_sels   = set_find(env->set_sels, &key_sels, sizeof(key_sels), HASH_PTR(key_sels.sel));
964
965             if(value_sels != NULL && val_arr[GET_ENT_VNUM(value_sels->ent)].access_type <= 3)
966               /* We save in this set all accessed entities from this call node whit
967                * access none, read, write or rw..*/
968               pset_insert(accessed_entities, value_sels->ent, HASH_PTR(value_sels->ent));
969             }
970           }
971
972           if(pset_count(accessed_entities))
973              split_call_mem_edge(env, irn, accessed_entities);
974
975           del_pset(accessed_entities);
976         }
977       }
978    }
979 }
980
981 /**
982  * searches through blocks beginning from block for value
983  * vnum and return it.
984  *
985  * @param block A block from the current ir graph.
986  * @param vnum  The value number, that must be found.
987  */
988 static ir_node *find_vnum_value(ir_node *block, unsigned vnum)
989 {
990   value_arr_entry_t *val_arr;
991   int               i;
992   ir_node           *res;
993
994   if (Block_not_block_visited(block)) {
995     mark_Block_block_visited(block);
996
997     val_arr = get_irn_link(block);
998
999     if (val_arr[vnum].mem_edge_state)
1000       return val_arr[vnum].mem_edge_state;
1001
1002     for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
1003       ir_node *pred = get_Block_cfgpred(block, i);
1004
1005       res = find_vnum_value(get_nodes_block(pred), vnum);
1006       if (res)
1007         return res;
1008     }
1009   }
1010   return NULL;
1011 }
1012
1013 /**
1014  * fix the Load/Store or Call list
1015  *
1016  * @param The enviroment pinter.
1017  */
1018 static void fix_ls(env_t *env)
1019 {
1020   fixlist_entry_t *l;
1021   ir_node      *irn, *block, *pred, *val = NULL;
1022   ir_op        *op;
1023   int          i;
1024
1025   for (l = env->fix_ls; l; l = get_irn_link(irn)) {
1026     irn = l->irn;
1027
1028     op     = get_irn_op(irn);
1029     block  = get_nodes_block(irn);
1030     for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
1031       pred = get_Block_cfgpred(block, i);
1032       pred = get_nodes_block(pred);
1033
1034       inc_irg_block_visited(current_ir_graph);
1035       val = find_vnum_value(pred, l->vnum);
1036
1037       if (val)
1038         break;
1039     }
1040
1041     if(val) {
1042       if(op == op_Store)
1043         set_Store_mem(irn, val);
1044       else
1045         if(op == op_Load)
1046           set_Load_mem(irn, val);
1047         else
1048           set_Call_mem(irn, val);
1049     }
1050   }
1051 }
1052
1053 /**
1054  * fix the Phi list
1055  *
1056  * @param The enviroment pinter.
1057  */
1058 static void fix_phis(env_t *env)
1059 {
1060   fixlist_entry_t *l;
1061   ir_node         *phi, *block, *pred, *val;
1062   int             i;
1063
1064   for (l = env->fix_phis; l; l = get_irn_link(phi)) {
1065     phi = l->irn;
1066
1067     block = get_nodes_block(phi);
1068     for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
1069
1070       pred = get_Block_cfgpred(block, i);
1071       pred = get_nodes_block(pred);
1072
1073       inc_irg_block_visited(current_ir_graph);
1074       val = find_vnum_value(pred, l->vnum);
1075
1076       if (val)
1077         set_irn_n(phi, i, val);
1078     }
1079   }
1080 }
1081
1082
1083 /**
1084  * fix the Sync list
1085  *
1086  * @param The enviroment pinter.
1087  */
1088 static void fix_syncs(env_t *env)
1089 {
1090   syncs_fixlist_entry_t *l;
1091   ir_node               *sync, *block, *pred, *val;
1092   int                   i, k;
1093
1094
1095   for (l = env->fix_syncs; l; l = get_irn_link(sync)) {
1096     sync = l->irn;
1097     k = 0;
1098
1099     /* The sync block must have one predecessor, when it
1100        have unknown nodes as predecessor.*/
1101     block = get_nodes_block(sync);
1102     pred  = get_Block_cfgpred(block, 0);
1103     pred  = get_nodes_block(pred);
1104
1105     /* We first repair the global memory edge at the first position of sync predecessors.*/
1106     if(get_irn_op(get_irn_n(sync, 0)) == op_Unknown) {
1107       inc_irg_block_visited(current_ir_graph);
1108       val = find_vnum_value(pred, env->gl_mem_vnum);
1109
1110       if(val)
1111         set_irn_n(sync, 0, val);
1112     }
1113
1114     for (i = get_irn_arity(sync) - 1; i >= 1; --i) {
1115       /* We repair the leaves*/
1116
1117       assert(k <= ARR_LEN(l->accessed_vnum) && "The algorythm for sync repair is wron");
1118       if(get_irn_op(get_irn_n(sync, i)) == op_Unknown) {
1119         inc_irg_block_visited(current_ir_graph);
1120         val = find_vnum_value(pred, l->accessed_vnum[k++]);
1121
1122         if(val)
1123           set_irn_n(sync, i, val);
1124       }
1125     }
1126     DEL_ARR_F(l->accessed_vnum);
1127   }
1128 }
1129 /**
1130  * For the end node we must sync all memory edges.
1131  *
1132  * @param The enviroment pinter.
1133  */
1134 static void sync_mem_edges(env_t *env) {
1135
1136   value_arr_entry_t *val_arr;
1137   ir_node           **in, *sync, *Return, *Return_blk;
1138   int               i, vnum, vnum_state;
1139
1140   Return     = get_Block_cfgpred(get_irg_end_block(current_ir_graph), 0);
1141   Return_blk = get_nodes_block(Return);
1142   val_arr    = get_irn_link(Return_blk);
1143
1144   vnum_state = 0;
1145
1146   for(i = 0; i <= (int)env->gl_mem_vnum; i++)
1147     /* we get the current state of non saved scalars.*/
1148     if(val_arr[i].access_type <= 3)
1149       vnum_state++;
1150
1151   /* We allocate the memory, that we need for the predecessors of the sync.*/
1152   in     = xmalloc(sizeof(ir_node*) *vnum_state);
1153
1154   /* The global memory edge is the first predecessor of this sync node.*/
1155   if(val_arr[env->gl_mem_vnum].mem_edge_state == NULL) {
1156     /* We must search through blocks for this memory state.*/
1157     inc_irg_block_visited(current_ir_graph);
1158     in[0] = find_vnum_value(Return_blk, env->gl_mem_vnum);
1159   }
1160   else
1161     in[0] = val_arr[env->gl_mem_vnum].mem_edge_state;
1162
1163
1164   for(i = 1, vnum = 0; vnum < (int)env->gl_mem_vnum; vnum++) {
1165
1166     if(val_arr[vnum].access_type <= 3) {
1167       /* we add the non saved scalars as predecessors of the sync.*/
1168
1169       if(val_arr[vnum].mem_edge_state == NULL) {
1170         /* We must search through blocks for this memory state.*/
1171         inc_irg_block_visited(current_ir_graph);
1172         in[i] = find_vnum_value(Return_blk, vnum);
1173       }
1174       else
1175         in[i] = val_arr[vnum].mem_edge_state;
1176       i++;
1177     }
1178   }
1179
1180   sync = new_r_Sync(current_ir_graph, Return_blk, vnum_state, in);
1181   set_Return_mem(Return, sync);
1182
1183   free(in);
1184 }
1185
1186 /**
1187  * Walker: allocate the value array for every block.
1188  *
1189  * @param block  A block from the current ir graph for that must be allocated a value array.
1190  * @param ctx    The enviroment pinter.
1191  */
1192 static void alloc_value_arr(ir_node *block, void *ctx)
1193 {
1194   env_t *env = ctx;
1195   int   i;
1196
1197   value_arr_entry_t *var_arr = obstack_alloc(&env->obst, sizeof(value_arr_entry_t) *(env->nvals + set_count(env->set_ent) + 1));
1198
1199   /* the value array is empty at start */
1200   memset(var_arr, 0, sizeof(value_arr_entry_t) * (env->nvals + set_count(env->set_ent) + 1));
1201   set_irn_link(block, var_arr);
1202
1203  /* We set the block value number state to optimal and later we update this.*/
1204   var_arr[env->vnum_state].access_type = env->nvals;
1205
1206   if(get_irg_start_block(current_ir_graph) == block)
1207     /* We initilize the startblocks array with the irg initilize memory, why
1208      * it must be the start point of all memory edges.*/
1209     for(i = (env->nvals + set_count(env->set_ent)) ; i >=0; i--)
1210       var_arr[i].mem_edge_state = get_irg_initial_mem(current_ir_graph);
1211
1212 }
1213
1214 /* Analyze call nodes to get information, if they store the address of a scalar.
1215  *
1216  * @param *irn   An ir node from the current_ir_graph.
1217  * @param *env   The enviroment pointer.
1218 */
1219 static void analyse_calls(ir_node *irn, void *ctx) {
1220
1221   int                 i, vnum;
1222   unsigned int        acces_type;
1223   ir_node             *param, *call_ptr, *blk;
1224   ir_op               *op;
1225   ir_entity           *meth_ent;
1226   sels_t              key_sels, *value_sels;
1227   call_access_t       key_call, *value_call;
1228   value_arr_entry_t   *val_arr;
1229   env_t               *env;
1230
1231   env = ctx;
1232   if(get_irn_op(irn) != op_Call)
1233     return;
1234
1235   /* Calls that have a NoMem input do neither read nor write memory.
1236      We can completely ignore them here. */
1237   if (get_irn_op(get_Call_mem(irn)) == op_NoMem)
1238     return;
1239
1240   /* We iterate over the parameters of this call nodes.*/
1241   for ( i = get_Call_n_params(irn) - 1; i >= 0; i--) {
1242     param = get_Call_param(irn, i);
1243     if(get_irn_op(param) == op_Sel) {
1244       /* We have found a parameter with operation sel.*/
1245       key_sels.sel = param;
1246       value_sels   = set_find(env->set_sels, &key_sels, sizeof(key_sels), HASH_PTR(key_sels.sel));
1247       if(value_sels != NULL ) {
1248
1249         /* We have found a call, that have as parameter a sel from our set_sels.*/
1250         call_ptr = get_Call_ptr(irn);
1251         op = get_irn_op(call_ptr);
1252
1253         if(op == op_SymConst && get_SymConst_kind(call_ptr) == symconst_addr_ent) {
1254           meth_ent = get_SymConst_entity(call_ptr);
1255           /* we get the access type for our sel.*/
1256           acces_type = get_method_param_access(meth_ent, i);
1257         } else
1258           /* We can't analyze this function and we asume, that it store the address.*/
1259           acces_type = ptr_access_store;
1260
1261         /* we save the access type and this call in the array allocated for this block.
1262          * The value number of this entity get us the position in the array to save this
1263          * information. Why we expect more calls as one we allocate a set.*/
1264         vnum    = GET_ENT_VNUM(value_sels->ent);
1265         blk     = get_nodes_block(irn);
1266         val_arr = get_irn_link(blk);
1267
1268         if(val_arr[vnum].access_type > 3)
1269           /* The address of this entity have been stored.*/
1270           continue;
1271
1272         if(val_arr[vnum].calls == NULL)
1273           /* for this entity i have found the firs call in this block and we must allocate the set.*/
1274           val_arr[vnum].calls = new_set(call_cmp, 8);
1275
1276           /* This call performs anything with the scalar and we must mark it.*/
1277           key_call.call = irn;
1278           key_call.access_type = acces_type;
1279           value_call = set_insert(val_arr[vnum].calls, &key_call, sizeof(key_call), HASH_PTR(key_call.call));
1280
1281         if(value_call->access_type < acces_type)
1282           /* this case tread, when a call access an entity more at once.
1283            * Than we must save the highest access type.*/
1284           value_call->access_type = acces_type;
1285
1286         if(acces_type > 3)
1287           /* This call save the address of our scalar and we can't
1288            * use the scalars of this entity for optimization as from now.
1289            * we mark this.*/
1290           val_arr[vnum].access_type = acces_type;
1291       }
1292     }
1293   }
1294 }
1295
1296 static int set_block_dominated_first_access(ir_node *blk, int vnum, unsigned int access) {
1297
1298   ir_node *idom, *succ;
1299   value_arr_entry_t *val_arr;
1300   int i, changes = 0;
1301
1302   idom = get_Block_idom(blk);
1303   for(i = get_Block_n_cfg_outs(idom) - 1; i >=1; i--) {
1304     succ = get_Block_cfg_out(idom, i);
1305     val_arr  = get_irn_link(succ);
1306     if(val_arr[vnum].access_type < 3) {
1307       val_arr[vnum].access_type = access;
1308       changes++;
1309     }
1310   }
1311   return changes;
1312 }
1313 /* Update the access information of a block if a predecessor of
1314  * this black have a higher access for an entity.
1315  *
1316  * @param *irn   An ir node from the current_ir_graph.
1317  * @param *env   The enviroment pointer.
1318  */
1319 static void set_block_access(ir_node *irn, void *ctx){
1320
1321   value_arr_entry_t *val_arr, *val_arr_pred;
1322   ent_leaves_t      *value_leaves;
1323   ir_node           *pred, *pred_blk, *leave;
1324   env_t             *env;
1325   int               i, vnum;
1326
1327   env     = ctx;
1328   val_arr = get_irn_link(irn);
1329
1330   for( i = get_Block_n_cfgpreds(irn) - 1; i >= 0; i--) {
1331     /* We analyze the predecessors of this block to see if this block must
1332      * be updated.*/
1333     pred = get_Block_cfgpred(irn, i);
1334     pred_blk = get_nodes_block(pred);
1335
1336     val_arr_pred = get_irn_link(pred_blk);
1337
1338     for(value_leaves = set_first(env->set_ent); value_leaves; value_leaves = set_next(env->set_ent)) {
1339       vnum = GET_ENT_VNUM(value_leaves->ent);
1340
1341       if((get_Block_n_cfgpreds(irn) > 1) && (val_arr[vnum].access_type > 3))
1342         env->changes =  set_block_dominated_first_access(irn, vnum, val_arr[vnum].access_type);
1343
1344       if((val_arr_pred[vnum].access_type > 3) && (val_arr[vnum].access_type < 3)) {
1345         /* We have found a block for update it access and value number information.*/
1346         val_arr[vnum].access_type = val_arr_pred[vnum].access_type;
1347         /* We update the access information of all leave, that belong to
1348          * this entity.*/
1349
1350         for(leave = pset_first(value_leaves->leaves); leave; leave = pset_next(value_leaves->leaves))
1351           val_arr[GET_IRN_VNUM(leave)].access_type = val_arr[vnum].access_type;
1352
1353         /* In this way can't be got the actuall number of value numbers.
1354         val_arr[env->vnum_state].access_type = val_arr_pred[env->vnum_state].access_type; */
1355         env->changes++;
1356       }
1357     }
1358   }
1359 }
1360 /* Free the allocated call sets.
1361  *
1362  * @param irn  A block form the ir graph.
1363  * @param env  The enviroment pinter.
1364  */
1365 static void free_call_info(ir_node *irn, void *ctx) {
1366
1367   int i;
1368   env_t             *env;
1369   value_arr_entry_t *val_arr;
1370
1371   env     = ctx;
1372   val_arr = get_irn_link(irn);
1373
1374   for(i = env->nvals + set_count(env->set_ent); i >= 0; i--) {
1375     if(val_arr[i].calls != NULL)
1376
1377       del_set(val_arr[i].calls);
1378   }
1379 }
1380
1381 static void print_block_state(ir_node *irn, void *ctx) {
1382
1383   value_arr_entry_t  *val_arr;
1384   ent_leaves_t       *value_leaves;
1385   call_access_t      *value_calls;
1386   env_t              *env;
1387   int                vnum;
1388
1389   env     = ctx;
1390   val_arr = get_irn_link(irn);
1391   ir_printf("\n\nThe actual value number state of this block is: %i \n",
1392             val_arr[env->vnum_state].access_type - 1);
1393
1394   for(value_leaves = set_first(env->set_ent); value_leaves; value_leaves = set_next(env->set_ent)) {
1395
1396     vnum = GET_ENT_VNUM(value_leaves->ent);
1397     ir_printf("The entity %F access type in the block with nr %u is %i \n",
1398               value_leaves->ent, get_irn_node_nr(irn), val_arr[vnum].access_type);
1399
1400     if(val_arr[vnum].calls != NULL)
1401       for(value_calls = set_first(val_arr[vnum].calls); value_calls; value_calls = set_next(val_arr[vnum].calls))
1402
1403         ir_printf("A call with nr %i acess a element of this entity with access %u \n",
1404                   get_irn_node_nr(value_calls->call), value_calls->access_type);
1405   }
1406
1407 }
1408
1409 /** Optimize the found scalar replacements.
1410 *
1411 * @param set_sels  A set with all entities, that
1412 *                  have scala(s).
1413 * @param set_ent   A set with all sels nodes,
1414 *                  that belong to our scalars.
1415 * @param vnum      The number of scalars.
1416 */
1417 static void do_data_flow_scalar_replacement(set *set_ent, set *set_sels, int vnum) {
1418
1419   env_t env;
1420
1421   obstack_init(&env.obst);
1422   env.set_ent     = set_ent;
1423   env.set_sels    = set_sels;
1424   env.fix_ls      = NULL;
1425   env.fix_phis    = NULL;
1426   env.fix_syncs   = NULL;
1427   env.gl_mem_vnum = vnum - 2;
1428   env.vnum_state  = vnum - 1;
1429   /* nvals are vnum - 1, why we indicate with nvals the number
1430    * of memory edges we will produce. For vnum_state we don't
1431    * need to produce a memory edge.*/
1432   env.nvals       = vnum - 1;
1433   env.changes     = 1;
1434
1435   /* first step: allocate the value arrays for every block */
1436   irg_block_walk_graph(current_ir_graph, NULL, alloc_value_arr, &env);
1437
1438   /* second step: we analyze all calls, that have as parameter scalar(s).
1439    * We mark the calls, that save the address of a scalar and we
1440    * mark the entity owner of this scalar as not optimizeble by now.*/
1441   irg_walk_graph(current_ir_graph, NULL, analyse_calls, &env);
1442
1443   while(env.changes) {
1444
1445
1446     env.changes  = 0;
1447     /*
1448     * third step: walk over the blocks of a graph and update
1449     * the information for the access of our scalars.
1450     */
1451     irg_block_walk_graph(current_ir_graph, NULL, set_block_access, &env);
1452
1453   }
1454
1455   // if(get_firm_verbosity())
1456     /* Debug info to see if analyse_calls work properly.*/
1457     irg_block_walk_graph(current_ir_graph, NULL, print_block_state, &env);
1458
1459   /*
1460    * fourth step: walk over the graph blockwise in topological order
1461    * and split the memrory edge.
1462    */
1463   inc_irg_block_visited(current_ir_graph);
1464   irg_walk_blkwise_graph(current_ir_graph, NULL, split_memory_edge, &env);
1465
1466
1467
1468   /* fifth step: fix all nodes, that have as predecessor Unknown.*/
1469   fix_ls(&env);
1470   fix_phis(&env);
1471   fix_syncs(&env);
1472
1473   /* sixth step: sync memory enges for the end block.*/
1474   sync_mem_edges(&env);
1475
1476   /*seventh step: free the allocated memory*/
1477   irg_block_walk_graph(current_ir_graph, NULL, free_call_info, &env);
1478   obstack_free(&env.obst, NULL);
1479 }
1480
1481 /*
1482  * Find possible scalar replacements
1483  *
1484  * @param irg  The current ir graph.
1485  */
1486 void data_flow_scalar_replacement_opt(ir_graph *irg) {
1487
1488   int          i, vnum = 0;
1489   ir_node      *irg_frame;
1490   set          *set_sels;
1491   set          *set_ent;
1492   ent_leaves_t key_leaves, *value_leaves;
1493
1494
1495   if (! get_opt_scalar_replacement())
1496     return;
1497
1498   set_sels = new_set(sels_cmp, 8);
1499   set_ent  = new_set(ent_leaves_t_cmp, 8);
1500
1501   /* Call algorithm that remove the critical edges of a ir graph. */
1502   remove_critical_cf_edges(irg);
1503
1504   /* Call algorithm that computes the out edges.*/
1505   assure_irg_outs(irg);
1506
1507   /* Call algorithm that computes the loop information.*/
1508   construct_cf_backedges(irg);
1509
1510   /* Call algorithm that computes the dominance information.*/
1511   assure_doms(irg);
1512
1513   /* Find possible scalar replacements */
1514   if (find_possible_replacements(irg)) {
1515
1516     /* Insert in set the scalar replacements. */
1517     irg_frame = get_irg_frame(irg);
1518
1519     for (i = 0 ; i < get_irn_n_outs(irg_frame); i++) {
1520       ir_node *succ = get_irn_out(irg_frame, i);
1521
1522       if (get_irn_op(succ) == op_Sel) {
1523         ir_entity *ent = get_Sel_entity(succ);
1524
1525         if (get_entity_link(ent) == NULL || get_entity_link(ent) == ADDRESS_TAKEN)
1526           continue;
1527         /* we have found a entity, that have scalars and we insert it to our set_ent*/
1528         key_leaves.ent = ent;
1529         key_leaves.leaves = new_pset(leave_cmp, 8);
1530         value_leaves = set_insert(set_ent, &key_leaves, sizeof(key_leaves), HASH_PTR(ent));
1531
1532         /* We allocate for every leave sel a vnum.*/
1533         vnum = allocate_value_numbers(set_sels, value_leaves->leaves, ent, vnum);
1534       }
1535     }
1536
1537     if(get_firm_verbosity())
1538       printf("vnumber in data flow= %i\n", vnum);
1539
1540     /* Allocate value number for the globule memory edge.
1541      * and a value number for the value numbers state.*/
1542     vnum = vnum + 2;
1543
1544     /* Allocate value numbers for the entities .*/
1545     for(i = vnum,value_leaves = set_first(set_ent); value_leaves; i++, value_leaves = set_next(set_ent))
1546       SET_ENT_VNUM(value_leaves->ent, i);
1547
1548     if (vnum)
1549       do_data_flow_scalar_replacement(set_ent, set_sels, vnum);
1550
1551     /*free the allocated memory.*/
1552     for(value_leaves = set_first(set_ent); value_leaves; value_leaves = set_next(set_ent))
1553       del_pset(value_leaves->leaves);
1554     del_set(set_ent);
1555     del_set(set_sels);
1556   }
1557 }