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