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