BugFix: = was erronously used instead of ==
[libfirm] / ir / opt / data_flow_scalar_replace.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/opt/scalar_replace.c
4  * Purpose:     scalar replacement of arrays and compounds
5  * Author:      Beyhan Veliev
6  * Modified by: Michael Beck
7  * Created:
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 1998-2005 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #ifdef HAVE_ALLOCA_H
17 #include <alloca.h>
18 #endif
19
20 #ifdef HAVE_MALLOC_H
21 #include <malloc.h>
22 #endif
23
24 #ifdef HAVE_STRING_H
25 #include <string.h>
26 #endif
27
28 #include "data_flow_scalar_replace.h"
29 #include "irflag_t.h"
30 #include "irouts.h"
31 #include "pset.h"
32 #include "ircons_t.h"
33 #include "hashptr.h"
34 #include "irgwalk.h"
35 #include "irgmod.h"
36 #include "irnode_t.h"
37 #include "irtools.h"
38 #include "irdump.h"
39 #include "irloop.h"
40 #include "analyze_irg_args.h"
41 #include "irprintf.h"
42
43 #define SET_ENT_VNUM(ent, vnum) set_entity_link(ent, INT_TO_PTR(vnum))
44 #define GET_ENT_VNUM(ent)       (unsigned)PTR_TO_INT(get_entity_link(ent))
45 #define SET_IRN_VNUM(irn, vnum) set_irn_link(irn, INT_TO_PTR(vnum))
46 #define GET_IRN_VNUM(irn)       (unsigned)PTR_TO_INT(get_irn_link(irn))
47
48
49 /* To save for an entity all leaves for that the memory
50  * edge was split.*/
51 typedef struct _ent_leaves_t{
52   entity  *ent;
53   pset *leaves;
54 } ent_leaves_t;
55
56 typedef struct _sels_t {
57   ir_node *sel;
58   entity  *ent;
59 }sels_t;
60
61 typedef struct _call_access_t {
62   ir_node *call;
63   unsigned int access_type;
64 }call_access_t;
65
66 typedef struct _fixlist_entry_t {
67   ir_node *irn;
68   unsigned int vnum;
69 }fixlist_entry_t;
70
71 typedef struct _syncs_fixlist_entry_t {
72   ir_node *irn;
73   int *accessed_vnum;
74 }syncs_fixlist_entry_t;
75
76 /* A entry, that save the memory
77  * edge state and the access state for this leave
78  * int the array,that is created for every block.*/
79 typedef struct _leave_t {
80   ir_node *mem_edge_state;  /**< memory state for this scalar.*/
81   unsigned int access_type; /**< access state for this scalar.*/
82   set *calls;              /**< call nodes,that change this scalar.*/
83 }value_arr_entry_t;
84
85 /**
86  * environment for memory walker
87  */
88 typedef struct _env_t {
89   struct obstack obst;                   /**< a obstack for the memory edge */
90   set                   *set_sels;       /**< a set with all sels, that are reachable from an entity with a scalar.*/
91   set                   *set_ent;        /**< a set with all entities that have one or more scalars.*/
92   fixlist_entry_t       *fix_phis;       /**< list of all Phi nodes that must be fixed */
93   fixlist_entry_t       *fix_ls;         /**< list of all Load or Store nodes that must be fixed */
94   syncs_fixlist_entry_t *fix_syncs;      /**< list of all Sync nodes that must be fixed */
95   unsigned int          nvals;           /**< to save the number of scalars.*/
96   unsigned int          gl_mem_vnum;     /**< indicate the position of the globule memory edge state in var_arr.*/
97   unsigned int          vnum_state;      /**< indicate the position of the value number state in var_arr.*/
98   unsigned int          changes;         /**< to save if by anlyse_calls is changed anything.*/
99 } env_t;
100
101 /**
102  * A path element entry: it is either an entity
103  * or a tarval, because we evaluate only constant array
104  * accesses like a.b.c[8].d
105  */
106 typedef union {
107   entity *ent;
108   tarval *tv;
109 } path_elem_t;
110
111 /**
112  * An access path, used to assign value numbers
113  * to variables that will be scalar replaced
114  */
115 typedef struct _path_t {
116   unsigned    vnum;      /**< the value number */
117   unsigned    path_len;  /**< the length of the access path */
118   path_elem_t path[1];   /**< the path */
119 } path_t;
120
121 /* we need a special address that serves as an address stored. */
122 static char _s;
123 static void *ADDRESS_STORED = &_s;
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
136   return c1->ent != c2->ent;
137 }
138
139 /**
140  * Compare two elements of the ent_access_t set.
141  *
142  * @return 0 if they are identically
143  */
144 static int ent_cmp(const void *elt, const void *key, size_t size)
145 {
146   const entity *c1 = elt;
147   const entity *c2 = key;
148
149   return c1 != c2;
150 }
151
152 /**
153  * Compare two elements of the sels_t set.
154  *
155  * @return 0 if they are identically
156  */
157 static int sels_cmp(const void *elt, const void *key, size_t size)
158 {
159   const sels_t *c1 = elt;
160   const sels_t *c2 = key;
161
162   return c1->sel != c2->sel;
163 }
164
165 /**
166  * Compare two elements of the leave_t set.
167  *
168  * @return 0 if they are identically
169  */
170 static int leave_cmp(const void *elt, const void *key, size_t size)
171 {
172   const ir_node *c1 = elt;
173   const ir_node *c2 = key;
174
175   return c1 != c2;
176 }
177
178 /**
179  * Compare two elements of the call_access_t set.
180  *
181  * @return 0 if they are identically
182  */
183 static int call_cmp(const void *elt, const void *key, size_t size)
184 {
185   const call_access_t *c1 = elt;
186   const call_access_t *c2 = key;
187
188   return c1->call != c2->call;
189 }
190
191 /**
192  * Compare two paths.
193  *
194  * @return 0 if they are identically
195  */
196 static int path_cmp(const void *elt, const void *key, size_t size)
197 {
198   const path_t *p1 = elt;
199   const path_t *p2 = key;
200
201   /* we can use memcmp here, because identical tarvals should have identical addresses */
202   return memcmp(p1->path, p2->path, p1->path_len * sizeof(p1->path[0]));
203 }
204
205 /**
206  * Calculate a hash value for a path.
207  */
208 static unsigned path_hash(const path_t *path)
209 {
210   unsigned hash = 0;
211   unsigned i;
212
213   for (i = 0; i < path->path_len; ++i)
214     hash ^= (unsigned)PTR_TO_INT(path->path[i].ent);
215
216   return hash >> 4;
217 }
218
219 /**
220  * Returns non-zero, if all induces of a Sel node are constants.
221  *
222  * @param sel  the Sel node that will be checked
223  */
224 static int is_const_sel(ir_node *sel) {
225   int i, n = get_Sel_n_indexs(sel);
226
227   for (i = 0; i < n; ++i) {
228     ir_node *idx = get_Sel_index(sel, i);
229
230     if (get_irn_op(idx) != op_Const)
231       return 0;
232   }
233   return 1;
234 }
235
236 /*
237  * Returns non-zero, if the address of an entity
238  * represented by a Sel node (or it's successor Sels) is taken.
239  */
240 static int is_address_taken(ir_node *sel)
241 {
242   int i;
243
244   if (! is_const_sel(sel))
245     return 1;
246
247   for (i = get_irn_n_outs(sel) - 1; i >= 0; --i) {
248     ir_node *succ = get_irn_out(sel, i);
249
250     switch (get_irn_opcode(succ)) {
251     case iro_Load:
252       /* ok, we just load from that entity */
253       break;
254
255     case iro_Store:
256       /* check that Sel is not the Store's value */
257       if (get_Store_value(succ) == sel)
258         return 1;
259       break;
260
261     case iro_Sel: {
262       /* Check the Sel successor of Sel */
263       int res = is_address_taken(succ);
264
265       if (res)
266         return 1;
267       break;
268     }
269
270     case iro_Call:
271       /* The address of an entity is given as a parameter.
272        * We analyzes that later and optimizes this scalar
273        * if possible.
274        */
275       return 0;
276
277     default:
278       /* another op, the address is taken */
279       return 1;
280     }
281   }
282   return 0;
283 }
284
285 /**
286  * Link all Sels with the entity.
287  *
288  * @param ent  the entity that will be scalar replaced
289  * @param sel  a Sel node that selects some fields of this entity
290  */
291 static void link_all_leave_sels(entity *ent, ir_node *sel)
292 {
293   int i, n;
294
295   n = get_irn_n_outs(sel);
296   for (i = 0; i < n; ++i) {
297     ir_node *succ = get_irn_out(sel, i);
298
299     if (get_irn_op(succ) == op_Sel)
300       link_all_leave_sels(ent, succ);
301
302   }
303
304    /* if Sel nodes with memory inputs are used, a entity can be
305     * visited more than once causing a ring here, so we use the
306     * node flag to mark linked nodes
307     */
308    if (irn_visited(sel))
309     return;
310
311   /*
312    * we link the sels to the entity.
313    */
314   set_irn_link(sel, get_entity_link(ent));
315   set_entity_link(ent, sel);
316
317   mark_irn_visited(sel);
318 }
319
320 /* we need a special address that serves as an address taken marker */
321 static char _x;
322 static void *ADDRESS_TAKEN = &_x;
323
324 /**
325  * Find possible scalar replacements.
326  *
327  * @param irg  an IR graph
328  *
329  * This function finds variables on the (members of the) frame type
330  * that can be scalar replaced, because their address is never taken.
331  * If such a variable is found, it's entity link will hold a list of all
332  * Sel nodes, that selects anythings of this entity.
333  * Otherwise, the link will be ADDRESS_TAKEN or NULL.
334  *
335  * @return  non-zero if at least one entity could be replaced
336  *          potentially
337  */
338 static int find_possible_replacements(ir_graph *irg)
339 {
340   ir_node *irg_frame = get_irg_frame(irg);
341   int i, n;
342   int res = 0;
343
344   inc_irg_visited(irg);
345
346   n = get_irn_n_outs(irg_frame);
347
348   /*
349    * First, clear the link field of all interestingentities.
350    * Note that we did not rely on the fact that there is only
351    * one Sel node per entity, so we might access one entity
352    * more than once here.
353    * That's why we have need two loops.
354    */
355   for (i = 0; i < n; ++i) {
356     ir_node *succ = get_irn_out(irg_frame, i);
357
358     if (get_irn_op(succ) == op_Sel) {
359       entity *ent = get_Sel_entity(succ);
360       set_entity_link(ent, NULL);
361     }
362   }
363
364   /*
365    * Check the ir_graph for Sel nodes. If the entity of Sel
366    * isn't a scalar replacement set the link of this entity
367    * equal ADDRESS_TAKEN.
368    */
369   for (i = 0; i < n; ++i) {
370     ir_node *succ = get_irn_out(irg_frame, i);
371
372     if (get_irn_op(succ) == op_Sel) {
373       entity *ent = get_Sel_entity(succ);
374       ir_type *ent_type;
375
376       if (get_entity_link(ent) == ADDRESS_TAKEN)
377         continue;
378
379       ent_type = get_entity_type(ent);
380
381       /* we can handle arrays, structs and atomic types yet */
382       if (is_Array_type(ent_type) || is_Struct_type(ent_type) || is_atomic_type(ent_type)) {
383         if (is_address_taken(succ)) {
384           if (get_entity_link(ent)) /* killing one */
385             --res;
386           set_entity_link(ent, ADDRESS_TAKEN);
387         }
388         else {
389           /* possible found one */
390           if (get_entity_link(ent) == NULL)
391             ++res;
392           link_all_leave_sels(ent, succ);
393         }
394       }
395     }
396   }
397
398   return res;
399 }
400
401 static int is_leave_sel(ir_node *sel) {
402   int i;
403   ir_node *succ;
404
405   for(i = get_irn_n_outs(sel) - 1; i >= 0; i--) {
406     succ = get_irn_out(sel, i);
407     if(get_irn_op(succ) == op_Sel)
408       return 0;
409   }
410
411   return 1;
412 }
413
414 /**
415  * Return a path from the Sel node sel to it's root.
416  *
417  * @param sel  the Sel node
418  * @param len  the length of the path so far
419  */
420 static path_t *find_path(ir_node *sel, unsigned len)
421 {
422   int pos, i, n;
423   path_t *res;
424   ir_node *pred = get_Sel_ptr(sel);
425
426   /* the current Sel node will add some path elements */
427   n    = get_Sel_n_indexs(sel);
428   len += n + 1;
429
430   if (get_irn_op(pred) != op_Sel) {
431     /* we found the root */
432
433     res = xmalloc(sizeof(*res) + (len - 1) * sizeof(res->path));
434     res->path_len = len;
435   }
436   else
437     res = find_path(pred, len);
438
439   pos = res->path_len - len;
440
441   res->path[pos++].ent = get_Sel_entity(sel);
442   for (i = 0; i < n; ++i) {
443     ir_node *index = get_Sel_index(sel, i);
444
445     res->path[pos++].tv = get_Const_tarval(index);
446   }
447   return res;
448 }
449
450 /**
451  * Allocate value numbers for the leaves
452  * in our found entities.
453  *
454  * @param sels  a set that will contain all Sels that have a value number
455  * @param ent   the entity that will be scalar replaced
456  * @param vnum  the first value number we can assign
457  * @param modes a flexible array, containing all the modes of
458  *              the value numbers.
459  *
460  * @return the next free value number
461  */
462 static unsigned allocate_value_numbers(set *set_sels, pset *leaves, entity *ent, unsigned vnum)
463 {
464   ir_node *sel, *next;
465   path_t *key, *path;
466   sels_t       key_sels;
467   set *pathes = new_set(path_cmp, 8);
468
469   /* visit all Sel nodes in the chain of the entity */
470   for (sel = get_entity_link(ent); sel; sel = next) {
471     next = get_irn_link(sel);
472
473     /* we save for every sel it root entity, why
474      * we need this information, when we split the memory edge,
475      * and we must mark this sel for later. */
476      key_sels.ent = ent;
477      key_sels.sel = sel;
478      set_insert(set_sels, &key_sels, sizeof(key_sels), HASH_PTR(sel));
479
480     if(! is_leave_sel(sel))
481       continue;
482
483     /* We have found a leave and we add it to the pset of this entity.*/
484     pset_insert_ptr(leaves, sel);
485
486     key  = find_path(sel, 0);
487     path = set_find(pathes, key, sizeof(*key) + sizeof(key->path[0]) * key->path_len, path_hash(key));
488
489     if (path)
490       SET_IRN_VNUM(sel, path->vnum);
491     else {
492
493       key->vnum = vnum++;
494
495       set_insert(pathes, key, sizeof(*key) + sizeof(key->path[0]) * key->path_len, path_hash(key));
496
497       SET_IRN_VNUM(sel, key->vnum);
498     }
499     free(key);
500   }
501
502   del_set(pathes);
503   set_entity_link(ent, NULL);
504   return vnum;
505 }
506 /* Analyze if this scalar was stored in this block
507    or earlier.*/
508 static int is_scalar_stored(ir_node *call_blk, int ent_vnum) {
509
510   value_arr_entry_t *val_arr, *val_arr_pred;
511   ir_node *pred;
512   int n;
513
514   val_arr = get_irn_link(call_blk);
515
516   if(val_arr[ent_vnum].access_type == 0)
517     return 0;
518
519   n = get_Block_n_cfgpreds(call_blk) - 1;
520
521   for( ; n >= 0; n--) {
522     pred = get_Block_cfgpred(call_blk, n);
523     pred = get_nodes_block(pred);
524     val_arr_pred = get_irn_link(pred);
525
526     if(val_arr_pred[ent_vnum].access_type != 0)
527       /* This scalar wasn't stored in this block.*/
528       return 1;
529   }
530   return 0;
531 }
532
533
534 /* The function handles the call nodes, that have
535  * as parameter a scalar*/
536 static void handle_call(env_t *env, ir_node *call, pset *accessed_entities) {
537
538   ent_leaves_t  key_ent, *value_ent;
539   value_arr_entry_t *val_arr;
540   call_access_t key_call, *value_call;
541   ir_node *call_blk, *new_mem_state, *leave;
542   ir_node *sync, **in;
543   entity *ent;
544   fixlist_entry_t *l;
545   syncs_fixlist_entry_t *s;
546   int fix_irn = 0, *accessed_leaves_vnum = NULL;
547   unsigned ent_vnum;
548
549   call_blk = get_nodes_block(call);
550   val_arr  = get_irn_link(call_blk);
551   /* To save the memory edges, that must be
552    * synced.*/
553   in       = NEW_ARR_F(ir_node *, 1);
554   /* To save the value numbers of the memory
555    * edges that must be repaired.*/
556   accessed_leaves_vnum = NEW_ARR_F(int, 0);
557
558   /* We get the memory successor of the call node.
559    * It is the new memory state for all synced memory
560    * edges.*/
561   new_mem_state = get_irn_out(call, 0);
562   if(get_irn_mode(new_mem_state) != mode_M)
563     new_mem_state = get_irn_out(call,1);
564
565   if(val_arr[env->gl_mem_vnum].mem_edge_state == NULL) {
566     in[0] = new_Unknown(mode_M);
567     fix_irn = 1;
568   } else
569     in[0] = val_arr[env->gl_mem_vnum].mem_edge_state;
570
571   for(ent = pset_first(accessed_entities); ent; ent = pset_next(accessed_entities)) {
572     /* Whit this loop we iterate all accessed entities an collect
573      * all memory edges, that we must sync.*/
574     ent_vnum = GET_ENT_VNUM(ent);
575
576     key_call.call = call;
577     value_call = set_find(val_arr[ent_vnum].calls, &key_call, sizeof(key_call), HASH_PTR(key_call.call));
578
579     key_ent.ent = ent;
580     value_ent = set_find(env->set_ent, &key_ent, sizeof(key_ent), HASH_PTR(key_ent.ent));
581
582     if(!is_scalar_stored(call_blk, ent_vnum)) {
583       /* This scalar's address wasn't stored in this block.*/
584       switch(value_call->access_type) {
585
586       case ptr_access_none :
587         /* In this case we have nothing to do.*/
588       break;
589
590       case ptr_access_read:
591       case ptr_access_write:
592       case ptr_access_rw:
593       case 5:
594       case ptr_access_all:
595         /* All this cases must be traded equal.*/
596
597         for(leave = pset_first(value_ent->leaves); leave; leave = pset_next(value_ent->leaves)){
598           /* All this memory edges must be synced.*/
599           if(val_arr[GET_IRN_VNUM(leave)].mem_edge_state != NULL)
600             ARR_APP1(ir_node *, in, val_arr[GET_IRN_VNUM(leave)].mem_edge_state);
601           else {
602             ARR_APP1(int, accessed_leaves_vnum, GET_IRN_VNUM(leave));
603             ARR_APP1(ir_node *, in, new_Unknown(mode_M));
604             fix_irn = 1;
605           }
606           /* We update the memory state of this leave.*/
607           if(value_call->access_type != ptr_access_read)
608             val_arr[GET_IRN_VNUM(leave)].mem_edge_state = new_mem_state;
609         }
610
611       /* We are ready.*/
612       break;
613       }
614     }
615   }
616
617   /* We must update the global memory state.*/
618   val_arr[env->gl_mem_vnum].mem_edge_state = new_mem_state;
619
620   if(ARR_LEN(in) == 1) {
621     /* we must set the call memory to gobale momory*/
622     set_Call_mem(call,in[0]);
623
624     if(fix_irn) {
625       /* We add this call node to the call fix list..*/
626       l = obstack_alloc(&env->obst, sizeof(*l));
627       l->irn = call;
628       l->vnum = env->gl_mem_vnum;
629       set_irn_link(l->irn, env->fix_ls);
630       env->fix_ls = l;
631     }
632   } else {
633    /* We create the sync and set it as memory predecessor of the call node.*/
634       sync = new_r_Sync(current_ir_graph, call_blk, ARR_LEN(in), in);
635       set_Call_mem(call, sync);
636
637       if(fix_irn) {
638         /* We add this sync node to the sync's fix list.*/
639         s = obstack_alloc(&env->obst, sizeof(*s));
640         s->irn  = sync;
641         s->accessed_vnum = accessed_leaves_vnum;
642         set_irn_link(sync, env->fix_syncs);
643         env->fix_syncs = s;
644       }
645   }
646   DEL_ARR_F(in);
647 }
648
649 /* The function split the memory edge.*/
650 static void split_memory_edge(ir_node *irn, void *ctx) {
651
652    env_t   *env = ctx;
653    ir_node *new_mem_state, *mem_state, *unk;
654    ir_node *leave, *sel, *irn_blk, **in;
655    ir_op   *op;
656    sels_t  key_sels, *value_sels;
657    ent_leaves_t key_ent, *value_ent;
658    value_arr_entry_t *val_arr;
659    fixlist_entry_t *l;
660    pset *accessed_entities;
661    unsigned ent_vnum, sel_vnum;
662    int i, j, n;
663
664
665    op = get_irn_op(irn);
666
667    if(op == op_Load || op == op_Store) {
668
669      if(op == op_Load)
670        key_sels.sel = get_Load_ptr(irn);
671      else
672        key_sels.sel = get_Store_ptr(irn);
673
674      value_sels = set_find(env->set_sels, &key_sels, sizeof(key_sels), HASH_PTR(key_sels.sel));
675
676      if(value_sels != NULL) {
677      /* we have found a load or store, that use a sel of our set
678       * and we must split or extend, if the memory edge have been
679       * split for this sel, the memory edge.*/
680
681        key_ent.ent = value_sels->ent;
682        value_ent = set_find(env->set_ent, &key_ent, sizeof(key_ent), HASH_PTR(key_ent.ent));
683        assert(value_ent && " This sel's entity isn't int the entity set.");
684
685        leave = pset_find_ptr(value_ent->leaves, key_sels.sel);
686
687        assert(leave && "Anything in data_flow_scalar_replacment algorithm is wrong.");
688
689        ent_vnum = GET_ENT_VNUM(value_ent->ent);
690        sel_vnum = GET_IRN_VNUM(leave);
691
692        irn_blk = get_nodes_block(irn);
693        val_arr   = get_irn_link(irn_blk);
694
695        if(val_arr[ent_vnum].access_type == 0)
696          /* We have found a scalar, that address i not stored as jet.*/
697          i = sel_vnum;
698        else
699          /* This scalar have been stored.*/
700          i = env->gl_mem_vnum;
701
702        if(val_arr[i].mem_edge_state == NULL) {
703           /* We split now for this sel the memory edge in this block.*/
704           mem_state = new_Unknown(mode_M);
705           /* We must mark this node to fix later*/
706           l = obstack_alloc(&env->obst, sizeof(*l));
707           l->irn  = irn;
708           l->vnum = i;
709
710           set_irn_link(irn, env->fix_ls);
711           env->fix_ls = l;
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     else
733       if (op == op_Phi && get_irn_mode(irn) == mode_M) {
734         /*
735          * found a memory Phi: Here, we must create new Phi nodes
736          */
737         irn_blk = get_nodes_block(irn);
738         val_arr = get_irn_link(irn_blk);
739
740         n = get_Block_n_cfgpreds(irn_blk);
741
742         in = alloca(sizeof(*in) * n);
743
744         for (i = val_arr[env->gl_mem_vnum].access_type - 1; i >= 0; --i) {
745         unk = new_Unknown(mode_M);
746         for (j = n - 1; j >= 0; --j)
747           in[j] = unk;
748
749         val_arr[i].mem_edge_state = new_r_Phi(current_ir_graph, irn_blk, n, in, mode_M);
750
751         l = obstack_alloc(&env->obst, sizeof(*l));
752         l->irn = val_arr[i].mem_edge_state;
753         l->vnum = i;
754
755         set_irn_link(val_arr[i].mem_edge_state, env->fix_phis);
756         env->fix_phis = l;
757     }
758    }
759    if(op == op_Call) {
760       /* We save in this set all entities,
761        * that are accessed from this call node.*/
762       accessed_entities = new_pset(ent_cmp, 8);
763
764        for ( i = get_Call_n_params(irn) - 1; i >= 0; i--) {
765          sel = get_Call_param(irn, i);
766          if(get_irn_op(sel) == op_Sel) {
767            key_sels.sel = sel;
768            value_sels   = set_find(env->set_sels, &key_sels, sizeof(key_sels), HASH_PTR(key_sels.sel));
769          }
770
771          if(value_sels != NULL)
772            /* We save in this set all accessed entities from this call node.*/
773           pset_insert(accessed_entities, value_sels->ent, HASH_PTR(value_sels->ent));
774       }
775       if(pset_count(accessed_entities))
776        handle_call(env, irn, accessed_entities);
777   }
778 }
779
780 /**
781  * searches through blocks beginning from block for value
782  * vnum and return it.
783  */
784 static ir_node *find_value(ir_node *block, unsigned vnum)
785 {
786   value_arr_entry_t *val_arr;
787   int i;
788   ir_node *res;
789
790   if (Block_not_block_visited(block)) {
791     mark_Block_block_visited(block);
792
793     val_arr = get_irn_link(block);
794
795     if (val_arr[vnum].mem_edge_state)
796       return val_arr[vnum].mem_edge_state;
797
798     for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
799       ir_node *pred = get_Block_cfgpred(block, i);
800
801       res = find_value(get_nodes_block(pred), vnum);
802       if (res)
803         return res;
804     }
805   }
806   return NULL;
807 }
808
809 /**
810  * fix the Load/Store or Call list
811  */
812 static void fix_ls(env_t *env)
813 {
814   fixlist_entry_t *l;
815   ir_node      *irn, *block, *pred, *val;
816   ir_op        *op;
817   int          i;
818
819   for (l = env->fix_ls; l; l = get_irn_link(irn)) {
820     irn = l->irn;
821
822     op     = get_irn_op(irn);
823     block  = get_nodes_block(irn);
824     for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
825       pred = get_Block_cfgpred(block, i);
826       pred = get_nodes_block(pred);
827
828       inc_irg_block_visited(current_ir_graph);
829       val = find_value(pred, l->vnum);
830
831       if (val)
832         break;
833     }
834
835     if(op == op_Store)
836       set_Store_mem(irn, val);
837     else
838       if(op == op_Load)
839         set_Load_mem(irn, val);
840       else
841         set_Call_mem(irn, val);
842   }
843 }
844
845 /**
846  * fix the Phi list
847  */
848 static void fix_phis(env_t *env)
849 {
850   fixlist_entry_t *l;
851   ir_node      *phi, *block, *pred, *val;
852   int          i;
853
854   for (l = env->fix_phis; l; l = get_irn_link(phi)) {
855     phi = l->irn;
856
857     block = get_nodes_block(phi);
858     for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
859
860       pred = get_Block_cfgpred(block, i);
861       pred = get_nodes_block(pred);
862
863       inc_irg_block_visited(current_ir_graph);
864       val = find_value(pred, l->vnum);
865
866       if (val)
867         set_irn_n(phi, i, val);
868     }
869   }
870 }
871
872
873 /**
874  * fix the Sync list
875  */
876 static void fix_syncs(env_t *env)
877 {
878   syncs_fixlist_entry_t *l;
879   ir_node      *sync, *block, *pred, *val;
880   int i, k = 0;
881
882
883   for (l = env->fix_syncs; l; l = get_irn_link(sync)) {
884     sync = l->irn;
885
886     /* The sync block must have one predecessor, when it
887        have unknown nodes as predecessor.*/
888     block = get_nodes_block(sync);
889     pred  = get_Block_cfgpred(block, 0);
890     pred  = get_nodes_block(pred);
891
892     /* We first repair the global memory edge at the first position of sync predecessors.*/
893     if(get_irn_op(get_irn_n(sync, 0)) == op_Unknown) {
894       inc_irg_block_visited(current_ir_graph);
895       val = find_value(pred, env->gl_mem_vnum);
896       set_irn_n(sync, 0, val);
897     }
898
899     for (i = get_irn_arity(sync) - 1; i >= 0; --i) {
900       /* We repair the leaves*/
901       if(get_irn_op(get_irn_n(sync, i)) == op_Unknown) {
902         inc_irg_block_visited(current_ir_graph);
903         val = find_value(pred, l->accessed_vnum[k++]);
904         set_irn_n(sync, i, val);
905       }
906     }
907   }
908 }
909 /* For the end node we must sync all memory edges.*/
910 static void sync_mem_edges(env_t *env) {
911
912   ent_leaves_t *entry_ent;
913   ir_node      *leave;
914   value_arr_entry_t *val_arr;
915   ir_node **in, *sync, *Return, *Return_blk;
916   int i = 1;
917
918   Return     = get_Block_cfgpred(get_irg_end_block(current_ir_graph), 0);
919   Return_blk = get_nodes_block(Return);
920   val_arr    = get_irn_link(Return_blk);
921   /* We allocate the memory, that we need for the successors of the sync.*/
922   in     = malloc(sizeof(ir_node*) *val_arr[env->vnum_state].access_type);
923   /* The global memory edge is the first predecessor of this sync node.*/
924   if(val_arr[env->gl_mem_vnum].mem_edge_state == NULL) {
925     /* We must search through blocks for this memory state.*/
926     inc_irg_block_visited(current_ir_graph);
927     in[0] = find_value(Return_blk, env->gl_mem_vnum);
928   }
929   else
930     in[0] = val_arr[env->gl_mem_vnum].mem_edge_state;
931
932
933   for(entry_ent = set_first(env->set_ent); entry_ent; entry_ent = set_next(env->set_ent)) {
934     if(val_arr[GET_ENT_VNUM(entry_ent->ent)].access_type ==0)
935       /* The address of this entity was not stored. We must sync the memory edges of it's scalars.*/
936       for(leave = pset_first(entry_ent->leaves); leave; leave = pset_next(entry_ent->leaves)) {
937         if(val_arr[GET_IRN_VNUM(leave)].mem_edge_state == NULL) {
938           /* We must search through blocks for this memory state.*/
939           inc_irg_block_visited(current_ir_graph);
940           in[i] = find_value(Return_blk, GET_IRN_VNUM(leave));
941         }
942         else
943           in[i] = val_arr[GET_IRN_VNUM(leave)].mem_edge_state;
944         i++;
945     }
946   }
947
948   //assert(i < env->nvals && "Our nvals algorithm is baggy." );
949
950   sync = new_r_Sync(current_ir_graph, Return_blk, val_arr[env->vnum_state].access_type, in);
951   set_Return_mem(Return, sync);
952
953   free(in);
954 }
955
956 /**
957  * Walker: allocate the value array for every block.
958  */
959 static void alloc_value_arr(ir_node *block, void *ctx)
960 {
961   env_t *env = ctx;
962   int i;
963   value_arr_entry_t *var_arr = obstack_alloc(&env->obst, sizeof(value_arr_entry_t) *(env->nvals + set_count(env->set_ent) + 1));
964
965   /* the value array is empty at start */
966   memset(var_arr, 0, sizeof(value_arr_entry_t) * (env->nvals + set_count(env->set_ent) + 1));
967   set_irn_link(block, var_arr);
968  /* We set the block value number state to optimal and later we update this.*/
969   var_arr[env->vnum_state].access_type = env->nvals;
970
971   if(get_irg_start_block(current_ir_graph) == block)
972     for(i = (env->nvals + set_count(env->set_ent)) ; i >=0; i--)
973       var_arr[i].mem_edge_state = get_irg_initial_mem(current_ir_graph);
974
975 }
976
977 /* Analyze call nodes to get information, if they store the address of a scalar. */
978 static void analyse_calls(ir_node *irn, void *ctx) {
979
980   int           i, vnum;
981   unsigned int  acces_type;
982   env_t         *env = ctx;
983   ir_node       *param, *call_ptr, *blk;
984   ir_op         *op;
985   entity        *meth_ent;
986   sels_t        key_sels, *value_sels;
987   call_access_t key_call, *value_call;
988   value_arr_entry_t *val_arr;
989   ent_leaves_t key_ent, *value_ent;
990
991   if(get_irn_op(irn) != op_Call)
992     return;
993
994     for ( i = get_Call_n_params(irn) - 1; i >= 0; i--) {
995       param = get_Call_param(irn, i);
996       if(get_irn_op(param) == op_Sel) {
997
998          key_sels.sel = param;
999          value_sels   = set_find(env->set_sels, &key_sels, sizeof(key_sels), HASH_PTR(key_sels.sel));
1000           if(value_sels != NULL ) {
1001             /* We have found a call, that have as parameter a sel from our set_sels.*/
1002             call_ptr = get_Call_ptr(irn);
1003             op = get_irn_op(call_ptr);
1004
1005             if(op == op_SymConst && get_SymConst_kind(call_ptr) == symconst_addr_ent)
1006               meth_ent = get_SymConst_entity(call_ptr);
1007             else
1008               continue;
1009             /* we get the access type for our sel.*/
1010             acces_type = get_method_param_access(meth_ent, i);
1011             /* we save the access type and this call in the array allocated for this block.
1012              * The value number of this entity get us the position in the array to save this
1013              * information. Why we expect more calls as one we allocate a set.*/
1014             vnum    = GET_ENT_VNUM(value_sels->ent);
1015             blk     = get_nodes_block(irn);
1016             val_arr = get_irn_link(blk);
1017
1018             if(val_arr[vnum].access_type > 3)
1019               /* The address of this entity have been stored.*/
1020               continue;
1021
1022             if(val_arr[vnum].calls == NULL)
1023               /* for this entity i have found the firs call in this block and we must allocate the set.*/
1024               val_arr[vnum].calls = new_set(call_cmp, 8);
1025
1026             /* This call performs anything with the scalar and we must mark it.*/
1027             key_call.call = irn;
1028             key_call.access_type = acces_type;
1029             value_call = set_insert(val_arr[vnum].calls, &key_call, sizeof(key_call), HASH_PTR(key_call.call));
1030
1031             if(value_call->access_type < acces_type)
1032               /* this case tread, when a call access an entity more at once.
1033                * Than we must save the highest access type.*/
1034                value_call->access_type = acces_type;
1035
1036             if(acces_type > 3) {
1037               /* This call save the address of our scalar and we can't
1038                * use the scalars of this entity for optimization as from now.
1039                * we mark this.*/
1040               val_arr[vnum].access_type = acces_type;
1041               /* We must update our scalars number.*/
1042               key_ent.ent = value_sels->ent;
1043               value_ent = set_find(env->set_ent, &key_ent, sizeof(key_ent), HASH_PTR(key_ent.ent));
1044               val_arr[env->vnum_state].access_type -= pset_count(value_ent->leaves);
1045             }
1046        }
1047      }
1048     }
1049 }
1050 /* Update the access information of a block if a predecessor of
1051  * this black have a store access for an entity.*/
1052 static void set_block_access(ir_node *irn, void *ctx){
1053
1054   value_arr_entry_t *val_arr, *val_arr_pred;
1055   ent_leaves_t      *value_leaves;
1056   env_t             *env = ctx;
1057   ir_node           *pred, *pred_blk;
1058   int               i, vnum;
1059
1060   val_arr = get_irn_link(irn);
1061
1062   for( i = get_Block_n_cfgpreds(irn) - 1; i >= 0; i--) {
1063     /* We analyze the predecessors of this block to see if this block must
1064      * be updated.*/
1065     pred = get_Block_cfgpred(irn, i);
1066     pred_blk = get_nodes_block(pred);
1067     val_arr_pred = get_irn_link(pred_blk);
1068
1069     for(value_leaves = set_first(env->set_ent); value_leaves; value_leaves = set_next(env->set_ent)) {
1070       vnum = GET_ENT_VNUM(value_leaves->ent);
1071
1072       if((val_arr_pred[vnum].access_type > 3) && (val_arr[vnum].access_type < 3)) {
1073         /* We have found a block for update it access and value number information.*/
1074             val_arr[vnum].access_type = val_arr_pred[vnum].access_type;
1075             val_arr[env->vnum_state].access_type = val_arr_pred[env->vnum_state].access_type;
1076             env->changes++;
1077           }
1078       }
1079   }
1080 }
1081
1082 static void print_block_state(ir_node *irn, void *ctx) {
1083
1084   env_t *env = ctx;
1085   value_arr_entry_t *val_arr;
1086   ent_leaves_t *value_leaves;
1087   call_access_t *value_calls;
1088   int vnum;
1089
1090   val_arr = get_irn_link(irn);
1091
1092   ir_printf("\n\nThe actual value number state of this block is: %i \n", val_arr[env->vnum_state].access_type - 1);
1093
1094   for(value_leaves = set_first(env->set_ent); value_leaves; value_leaves = set_next(env->set_ent)) {
1095     vnum = GET_ENT_VNUM(value_leaves->ent);
1096     ir_printf("The entity %F access type in the block with nr %u is %i \n", value_leaves->ent, get_irn_node_nr(irn),
1097                val_arr[vnum].access_type);
1098     if(val_arr[vnum].calls != NULL)
1099       for(value_calls = set_first(val_arr[vnum].calls); value_calls; value_calls = set_next(val_arr[vnum].calls))
1100         ir_printf("A call with nr %i acess a element of this entity with access %u \n",
1101                   get_irn_node_nr(value_calls->call), value_calls->access_type);
1102   }
1103
1104 }
1105
1106 /** Optimize the found scalar replacements.
1107 *
1108 * @param sels  A pset with all sels nodes,
1109 *              that belong to our scalars.
1110 */
1111 static void do_data_flow_scalar_replacement(set *set_ent, set *set_sels, int vnum) {
1112
1113   env_t env;
1114
1115   obstack_init(&env.obst);
1116   env.set_ent     = set_ent;
1117   env.set_sels    = set_sels;
1118   env.fix_ls      = NULL;
1119   env.fix_phis    = NULL;
1120   env.fix_syncs   = NULL;
1121   env.gl_mem_vnum = vnum - 2;
1122   env.vnum_state  = vnum - 1;
1123   /* nvals are vnum - 1, why we indicate with nvals the number
1124    * of memory edges we will produce. For vnum_state we don't
1125    * need to produce a memory edge.*/
1126   env.nvals       = vnum - 1;
1127   env.changes     = 1;
1128
1129   /* first step: allocate the value arrays for every block */
1130   irg_block_walk_graph(current_ir_graph, NULL, alloc_value_arr, &env);
1131
1132   /* second step: we analyze all calls, that have as parameter scalar(s)
1133    * and we mark this calls. If the call save the address of a scalar we
1134    * mark the entity owner of this scalar as not optimizeble by now.*/
1135   irg_walk_graph(current_ir_graph, NULL, analyse_calls, &env);
1136
1137   while(env.changes) {
1138
1139
1140     env.changes  = 0;
1141     /*
1142     * third step: walk over the blocks of a graph and update
1143     * the information for the access of our scalars.
1144     */
1145     irg_block_walk_graph(current_ir_graph, NULL, set_block_access, &env);
1146
1147   }
1148   /* Debug info to see if analyse_calls work properly.*/
1149   irg_block_walk_graph(current_ir_graph, NULL, print_block_state, &env);
1150   /*
1151    * fourth step: walk over the graph blockwise in topological order
1152    * and split the memrory edge.
1153    */
1154   irg_walk_blkwise_graph(current_ir_graph, NULL, split_memory_edge, &env);
1155
1156   /* fifth step: fix all nodes, that have as predecessor Unknown.*/
1157   fix_ls(&env);
1158   fix_phis(&env);
1159   fix_syncs(&env);
1160
1161   sync_mem_edges(&env);
1162 }
1163
1164 /*
1165  * Find possible scalar replacements
1166  *
1167  * @param irg  The current ir graph.
1168  */
1169 void data_flow_scalar_replacement_opt(ir_graph *irg)
1170 {
1171   int          i, vnum = 0;
1172   ir_node      *irg_frame;
1173   set          *set_sels;
1174   set          *set_ent;
1175   ir_graph     *rem;
1176   ent_leaves_t key_leaves, *value_leaves;
1177
1178
1179   if (! get_opt_scalar_replacement())
1180     return;
1181
1182   rem = current_ir_graph;
1183   set_sels = new_set(sels_cmp, 8);
1184   set_ent  = new_set(ent_leaves_t_cmp, 8);
1185
1186   /* Call algorithm that computes the out edges */
1187   if (get_irg_outs_state(irg) != outs_consistent)
1188     compute_irg_outs(irg);
1189
1190   /* Find possible scalar replacements */
1191   if (find_possible_replacements(irg)) {
1192
1193     if (get_opt_scalar_replacement_verbose()) {
1194       printf("Scalar Replacement: %s\n", get_entity_name(get_irg_entity(irg)));
1195     }
1196
1197     /* Insert in set the scalar replacements. */
1198     irg_frame = get_irg_frame(irg);
1199
1200     for (i = 0 ; i < get_irn_n_outs(irg_frame); i++) {
1201       ir_node *succ = get_irn_out(irg_frame, i);
1202
1203       if (get_irn_op(succ) == op_Sel) {
1204         entity *ent = get_Sel_entity(succ);
1205
1206         if (get_entity_link(ent) == NULL || get_entity_link(ent) == ADDRESS_TAKEN)
1207           continue;
1208         /* we have found a entity, that have scalars and we insert it to our set_ent*/
1209         key_leaves.ent = ent;
1210         key_leaves.leaves = new_pset(leave_cmp, 8);
1211         value_leaves = set_insert(set_ent, &key_leaves, sizeof(key_leaves), HASH_PTR(ent));
1212
1213         /* We allocate for every leave sel a vnum.*/
1214         vnum = allocate_value_numbers(set_sels, value_leaves->leaves, ent, vnum);
1215       }
1216     }
1217     printf("vnumber in data flow= %i\n", vnum);
1218
1219     /* Allocate value number for the globule memory edge.
1220      * and a value number for the value numbers state.*/
1221     vnum = vnum + 2;
1222
1223     /* Allocate value numbers for the entities .*/
1224     for(i = vnum,value_leaves = set_first(set_ent); value_leaves; i++, value_leaves = set_next(set_ent))
1225       SET_ENT_VNUM(value_leaves->ent, i);
1226
1227     if (vnum) {
1228       do_data_flow_scalar_replacement(set_ent, set_sels, vnum);
1229     }
1230   }
1231 }