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