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