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