Some more cleanup: Put the return type and other specifiers on the same line as the...
[libfirm] / ir / opt / opt_ldst.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   Dataflow driven Load/Store optimizations, uses some ideas from
23  *          VanDrunen's LEPRE
24  * @author  Michael Beck
25  * @version $Id$
26  */
27 #include "config.h"
28
29 #include "irnode_t.h"
30 #include "irflag_t.h"
31 #include "array_t.h"
32 #include "ircons.h"
33 #include "irdom.h"
34 #include "irgmod.h"
35 #include "irgwalk.h"
36 #include "irouts.h"
37 #include "irgraph.h"
38 #include "irgopt.h"
39 #include "iropt.h"
40 #include "iroptimize.h"
41 #include "irnodemap.h"
42 #include "raw_bitset.h"
43 #include "debug.h"
44 #include "error.h"
45 #include "irpass.h"
46
47 /* maximum number of output Proj's */
48 #define MAX_PROJ (pn_Load_max > pn_Store_max ? pn_Load_max : pn_Store_max)
49
50 /**
51  * Mapping an address to an dense ID.
52  */
53 typedef struct address_entry_t {
54         unsigned id;          /**< The ID */
55 } address_entry;
56
57 /**
58  * Memop-flags.
59  */
60 enum memop_flags {
61         FLAG_KILL_ALL    = 1, /**< KILL all addresses */
62         FLAG_KILLED_NODE = 2, /**< this node was killed */
63         FLAG_EXCEPTION   = 4, /**< this node has exception flow */
64         FLAG_IGNORE      = 8, /**< ignore this node (volatile or other) */
65 };
66
67 /**
68  * A value: This represents a value stored at a given address in
69  * memory. Do not confuse with values from value numbering.
70  */
71 typedef struct value_t value_t;
72 struct value_t {
73         ir_node  *address;    /**< the address of this value */
74         ir_node  *value;      /**< the value itself */
75         ir_mode  *mode;       /**< the mode of the value */
76         unsigned id;          /**< address id */
77 };
78
79 /**
80  * A memop describes an memory-related operation.
81  * These are Loads/Store and all other ops that might modify
82  * memory (Calls, CopyB) or causing exceptions.
83  */
84 typedef struct memop_t memop_t;
85 struct memop_t {
86         value_t  value;      /**< the value of this memop: only defined for Load/Store */
87         ir_node  *node;      /**< the memory op itself */
88         ir_node  *mem;       /**< the memory FROM this node */
89         ir_node  *replace;   /**< the replacement node if this memop is replaced */
90         memop_t  *next;      /**< links to the next memory op in the block in forward order. */
91         memop_t  *prev;      /**< links to the previous memory op in the block in forward order. */
92         unsigned flags;      /**< memop flags */
93         ir_node  *projs[MAX_PROJ]; /**< Projs of this memory op */
94 };
95
96 /**
97  * Additional data for every basic block.
98  */
99 typedef struct block_t block_t;
100 struct block_t {
101         memop_t  *memop_forward;     /**< topologically sorted list of memory ops in this block */
102         memop_t  *memop_backward;    /**< last memop in the list */
103         unsigned *avail_out;         /**< out-set of available addresses */
104         memop_t  **id_2_memop_avail; /**< maps avail address ids to memops */
105         unsigned *anticL_in;         /**< in-set of anticipated Load addresses */
106         memop_t  **id_2_memop_antic; /**< maps anticipated address ids to memops */
107         ir_node  *block;             /**< the associated block */
108         block_t  *forward_next;      /**< next block entry for forward iteration */
109         block_t  *backward_next;     /**< next block entry for backward iteration */
110         memop_t  *avail;             /**< used locally for the avail map */
111         memop_t  **trans_results;    /**< used to cached translated nodes due antic calculation. */
112 };
113
114 /**
115  * Metadata for this pass.
116  */
117 typedef struct ldst_env_t {
118         struct obstack  obst;              /**< obstack for temporary data */
119         ir_nodemap_t    adr_map;           /**< Map addresses to */
120         block_t         *forward;          /**< Inverse post-order list of all blocks Start->End */
121         block_t         *backward;         /**< Inverse post-order list of all blocks End->Start */
122         ir_node         *start_bl;         /**< start block of the current graph */
123         ir_node         *end_bl;           /**< end block of the current graph */
124         unsigned        *curr_set;         /**< current set of addresses */
125         memop_t         **curr_id_2_memop; /**< current map of address ids to memops */
126         unsigned        curr_adr_id;       /**< number for address mapping */
127         unsigned        n_mem_ops;         /**< number of memory operations (Loads/Stores) */
128         unsigned        rbs_size;          /**< size of all bitsets in bytes */
129         int             max_cfg_preds;     /**< maximum number of block cfg predecessors */
130         int             changed;           /**< Flags for changed graph state */
131 #ifdef DEBUG_libfirm
132         ir_node         **id_2_address;    /**< maps an id to the used address */
133 #endif
134 } ldst_env;
135
136 /* the one and only environment */
137 static ldst_env env;
138
139 #ifdef DEBUG_libfirm
140
141 static firm_dbg_module_t *dbg;
142
143 /**
144  * Dumps the block list.
145  *
146  * @param ldst environment
147  */
148 static void dump_block_list(ldst_env *env)
149 {
150         block_t *entry;
151         memop_t *op;
152         int     i;
153
154         for (entry = env->forward; entry != NULL; entry = entry->forward_next) {
155                 DB((dbg, LEVEL_2, "%+F {", entry->block));
156
157                 i = 0;
158                 for (op = entry->memop_forward; op != NULL; op = op->next) {
159                         if (i == 0) {
160                                 DB((dbg, LEVEL_2, "\n\t"));
161                         }                       DB((dbg, LEVEL_2, "%+F", op->node));
162                         if ((op->flags & FLAG_KILL_ALL) == FLAG_KILL_ALL)
163                                 DB((dbg, LEVEL_2, "X"));
164                         else if (op->flags & FLAG_KILL_ALL)
165                                 DB((dbg, LEVEL_2, "K"));
166                         DB((dbg, LEVEL_2, ", "));
167
168                         i = (i + 1) & 3;
169                 }
170                 DB((dbg, LEVEL_2, "\n}\n\n"));
171         }
172 }  /* dump_block_list */
173
174 /**
175  * Dumps the current set.
176  *
177  * @param bl   current block
178  * @param s    name of the set
179  */
180 static void dump_curr(block_t *bl, const char *s)
181 {
182         unsigned end = env.rbs_size - 1;
183         unsigned pos;
184         int      i;
185
186         DB((dbg, LEVEL_2, "%s[%+F] = {", s, bl->block));
187         i = 0;
188         for (pos = rbitset_next(env.curr_set, 0, 1); pos < end; pos = rbitset_next(env.curr_set, pos + 1, 1)) {
189                 memop_t *op = env.curr_id_2_memop[pos];
190
191                 if (i == 0) {
192                         DB((dbg, LEVEL_2, "\n\t"));
193                 }
194
195                 DB((dbg, LEVEL_2, "<%+F, %+F>, ", op->value.address, op->value.value));
196                 i = (i + 1) & 3;
197         }
198         DB((dbg, LEVEL_2, "\n}\n"));
199 }  /* dump_curr */
200
201 #else
202 static void dump_block_list(ldst_env *env)
203 {
204         (void) env;
205 }
206 static void dump_curr(block_t *bl, const char *s)
207 {
208         (void) bl;
209         (void) s;
210 }
211 #endif /* DEBUG_libfirm */
212
213 /** Get the block entry for a block node */
214 static block_t *get_block_entry(const ir_node *block)
215 {
216         assert(is_Block(block));
217
218         return get_irn_link(block);
219 }  /* get_block_entry */
220
221 /** Get the memop entry for a memory operation node */
222 static memop_t *get_irn_memop(const ir_node *irn)
223 {
224         assert(! is_Block(irn));
225         return get_irn_link(irn);
226 }  /* get_irn_memop */
227
228 /**
229  * Walk over the memory edges from definition to users.
230  * This ensures, that even operation without memory output are found.
231  *
232  * @param irn   start node
233  * @param pre   pre walker function
234  * @param post  post walker function
235  * @param ctx   context parameter for the walker functions
236  */
237 static void walk_memory(ir_node *irn, irg_walk_func *pre, irg_walk_func *post, void *ctx)
238 {
239         int     i;
240         ir_mode *mode;
241
242         mark_irn_visited(irn);
243
244         if (pre)
245                 pre(irn, ctx);
246
247         mode = get_irn_mode(irn);
248         if (mode == mode_M) {
249                 /* every successor uses memory */
250                 for (i = get_irn_n_outs(irn) - 1; i >= 0; --i) {
251                         ir_node *succ = get_irn_out(irn, i);
252
253                         if (! irn_visited(succ))
254                                 walk_memory(succ, pre, post, ctx);
255                 }
256         } else if (mode == mode_T) {
257                 /* only some Proj's uses memory */
258                 for (i = get_irn_n_outs(irn) - 1; i >= 0; --i) {
259                         ir_node *proj = get_irn_out(irn, i);
260
261                         if (get_irn_mode(proj) == mode_M && ! irn_visited(proj))
262                                 walk_memory(proj, pre, post, ctx);
263                 }
264         }
265         if (post)
266                 post(irn, ctx);
267 }  /* walk_memory */
268
269 /**
270  * Walks over all memory nodes of a graph.
271  *
272  * @param irg   a graph
273  * @param pre   pre walker function
274  * @param post  post walker function
275  * @param ctx   context parameter for the walker functions
276  */
277 static void walk_memory_irg(ir_graph *irg, irg_walk_func pre, irg_walk_func post, void *ctx)
278 {
279         inc_irg_visited(irg);
280
281         ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
282
283         /*
284          * there are two possible sources for memory: initial_mem and nomem
285          * we ignore nomem as this should NOT change the memory
286          */
287         walk_memory(get_irg_initial_mem(irg), pre, post, ctx);
288
289         ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
290 }  /* walk_memory_irg */
291
292 /**
293  * Register an address and allocate a (sparse, 0..n) ID for it.
294  *
295  * @param adr  the IR-node representing the address
296  *
297  * @return the allocated id
298  */
299 static unsigned register_address(ir_node *adr)
300 {
301         address_entry *entry;
302
303         /* skip Confirms and Casts */
304 restart:
305         if (is_Confirm(adr)) {
306                 adr = get_Confirm_value(adr);
307                 goto restart;
308         }
309         if (is_Cast(adr)) {
310                 adr = get_Cast_op(adr);
311                 goto restart;
312         }
313
314         entry = ir_nodemap_get(&env.adr_map, adr);
315
316         if (entry == NULL) {
317                 /* new address */
318                 entry = OALLOC(&env.obst, address_entry);
319
320                 entry->id = env.curr_adr_id++;
321                 ir_nodemap_insert(&env.adr_map, adr, entry);
322
323                 DB((dbg, LEVEL_3, "ADDRESS %+F has ID %u\n", adr, entry->id));
324 #ifdef DEBUG_libfirm
325                 ARR_APP1(ir_node *, env.id_2_address, adr);
326 #endif
327         }
328         return entry->id;
329 }  /* register_address */
330
331
332 /**
333  * translate an address through a Phi node into a given predecessor
334  * block.
335  *
336  * @param address  the address
337  * @param block    the block
338  * @param pos      the position of the predecessor in block
339  */
340 static ir_node *phi_translate(ir_node *address, const ir_node *block, int pos)
341 {
342         if (is_Phi(address) && get_nodes_block(address) == block)
343                 address = get_Phi_pred(address, pos);
344         return address;
345 }  /* phi_translate */
346
347 /**
348  * Walker: allocate an block entry for every block
349  * and register all potential addresses.
350  */
351 static void prepare_blocks(ir_node *irn, void *ctx)
352 {
353         (void)ctx;
354
355         if (is_Block(irn)) {
356                 block_t *entry = OALLOC(&env.obst, block_t);
357                 int     n;
358
359                 entry->memop_forward    = NULL;
360                 entry->memop_backward   = NULL;
361                 entry->avail_out        = NULL;
362                 entry->id_2_memop_avail = NULL;
363                 entry->anticL_in        = NULL;
364                 entry->id_2_memop_antic = NULL;
365                 entry->block            = irn;
366                 entry->forward_next     = NULL;
367                 entry->backward_next    = NULL;
368                 entry->avail            = NULL;
369                 entry->trans_results    = NULL;
370                 set_irn_link(irn, entry);
371
372                 set_Block_phis(irn, NULL);
373
374                 /* use block marks to track unreachable blocks */
375                 set_Block_mark(irn, 0);
376
377                 n = get_Block_n_cfgpreds(irn);
378                 if (n > env.max_cfg_preds)
379                         env.max_cfg_preds = n;
380         } else {
381                 ir_mode *mode = get_irn_mode(irn);
382
383                 if (mode_is_reference(mode)) {
384                         /*
385                          * Register ALL possible addresses: this is overkill yet but
386                          * simpler then doing it for all possible translated addresses
387                          * (which would be sufficient in the moment.
388                          */
389                         (void)register_address(irn);
390                 }
391         }
392 }  /* prepare_blocks */
393
394 /**
395  * Post-Walker, link in all Phi's
396  */
397 static void link_phis(ir_node *irn, void *ctx)
398 {
399         (void)ctx;
400
401         if (is_Phi(irn)) {
402                 ir_node *block = get_nodes_block(irn);
403                 add_Block_phi(block, irn);
404         }
405 }  /* link_phis */
406
407 /**
408  * Block walker: creates the inverse post-order list for the CFG.
409  */
410 static void inverse_post_order(ir_node *block, void *ctx)
411 {
412         block_t *entry = get_block_entry(block);
413
414         (void)ctx;
415
416         /* mark this block IS reachable from start */
417         set_Block_mark(block, 1);
418
419         /* create the list in inverse order */
420         entry->forward_next = env.forward;
421         env.forward         = entry;
422
423         /* remember the first visited (last in list) entry, needed for later */
424         if (env.backward == NULL)
425                 env.backward = entry;
426 }  /* inverse_post_order */
427
428 /**
429  * Block walker: create backward links for the memops of a block.
430  */
431 static void collect_backward(ir_node *block, void *ctx)
432 {
433         block_t *entry = get_block_entry(block);
434         memop_t *last, *op;
435
436         (void)ctx;
437
438         /*
439          * Do NOT link in the end block yet. We want it to be
440          * the first in the list. This is NOT guaranteed by the walker
441          * if we have endless loops.
442          */
443         if (block != env.end_bl) {
444                 entry->backward_next = env.backward;
445
446                 /* create the list in inverse order */
447                 env.backward = entry;
448         }
449
450         /* create backward links for all memory ops */
451         last = NULL;
452         for (op = entry->memop_forward; op != NULL; op = op->next) {
453                 op->prev = last;
454                 last     = op;
455         }
456         entry->memop_backward = last;
457 }  /* collect_backward */
458
459 /**
460  * Allocate a memop.
461  *
462  * @param irn  the IR-node representing the memop or NULL
463  *             if this is a translated (virtual) memop
464  *
465  * @return the allocated memop
466  */
467 static memop_t *alloc_memop(ir_node *irn)
468 {
469         memop_t *m = OALLOC(&env.obst, memop_t);
470
471         m->value.address = NULL;
472         m->value.value   = NULL;
473         m->value.mode    = NULL;
474
475         m->node          = irn;
476         m->mem           = NULL;
477         m->replace       = NULL;
478         m->next          = NULL;
479         m->flags         = 0;
480
481         memset(m->projs, 0, sizeof(m->projs));
482
483         if (irn != NULL)
484                 set_irn_link(irn, m);
485         return m;
486 }  /* alloc_memop */
487
488 /**
489  * Create a memop for a Phi-replacement.
490  *
491  * @param op   the memop to clone
492  * @param phi  the Phi-node representing the new value
493  */
494 static memop_t *clone_memop_phi(memop_t *op, ir_node *phi)
495 {
496         memop_t *m = OALLOC(&env.obst, memop_t);
497
498         m->value         = op->value;
499         m->value.value   = phi;
500
501         m->node          = phi;
502         m->replace       = NULL;
503         m->next          = NULL;
504         m->flags         = 0;
505
506         set_irn_link(phi, m);
507         return m;
508 }  /* clone_memop_phi */
509
510 /**
511  * Return the memory properties of a call node.
512  *
513  * @param call  the call node
514  *
515  * return a bitset of mtp_property_const and mtp_property_pure
516  */
517 static unsigned get_Call_memory_properties(ir_node *call)
518 {
519         ir_type *call_tp = get_Call_type(call);
520         unsigned prop = get_method_additional_properties(call_tp);
521
522         /* check first the call type */
523         if ((prop & (mtp_property_const|mtp_property_pure)) == 0) {
524                 /* try the called entity */
525                 ir_node *ptr = get_Call_ptr(call);
526
527                 if (is_Global(ptr)) {
528                         ir_entity *ent = get_Global_entity(ptr);
529
530                         prop = get_entity_additional_properties(ent);
531                 }
532         }
533         return prop & (mtp_property_const|mtp_property_pure);
534 }  /* get_Call_memory_properties */
535
536 /**
537  * Returns an entity if the address ptr points to a constant one.
538  *
539  * @param ptr  the address
540  *
541  * @return an entity or NULL
542  */
543 static ir_entity *find_constant_entity(ir_node *ptr)
544 {
545         for (;;) {
546                 if (is_SymConst(ptr) && get_SymConst_kind(ptr) == symconst_addr_ent) {
547                         return get_SymConst_entity(ptr);
548                 } else if (is_Sel(ptr)) {
549                         ir_entity *ent = get_Sel_entity(ptr);
550                         ir_type   *tp  = get_entity_owner(ent);
551
552                         /* Do not fiddle with polymorphism. */
553                         if (is_Class_type(get_entity_owner(ent)) &&
554                                 ((get_entity_n_overwrites(ent)    != 0) ||
555                                 (get_entity_n_overwrittenby(ent) != 0)   ) )
556                                 return NULL;
557
558                         if (is_Array_type(tp)) {
559                                 /* check bounds */
560                                 int i, n;
561
562                                 for (i = 0, n = get_Sel_n_indexs(ptr); i < n; ++i) {
563                                         ir_node *bound;
564                                         tarval *tlower, *tupper;
565                                         ir_node *index = get_Sel_index(ptr, i);
566                                         tarval *tv     = computed_value(index);
567
568                                         /* check if the index is constant */
569                                         if (tv == tarval_bad)
570                                                 return NULL;
571
572                                         bound  = get_array_lower_bound(tp, i);
573                                         tlower = computed_value(bound);
574                                         bound  = get_array_upper_bound(tp, i);
575                                         tupper = computed_value(bound);
576
577                                         if (tlower == tarval_bad || tupper == tarval_bad)
578                                                 return NULL;
579
580                                         if (tarval_cmp(tv, tlower) & pn_Cmp_Lt)
581                                                 return NULL;
582                                         if (tarval_cmp(tupper, tv) & pn_Cmp_Lt)
583                                                 return NULL;
584
585                                         /* ok, bounds check finished */
586                                 }
587                         }
588
589                         if (get_entity_linkage(ent) == IR_LINKAGE_CONSTANT)
590                                 return ent;
591
592                         /* try next */
593                         ptr = get_Sel_ptr(ptr);
594                 } else if (is_Add(ptr)) {
595                         ir_node *l = get_Add_left(ptr);
596                         ir_node *r = get_Add_right(ptr);
597
598                         if (get_irn_mode(l) == get_irn_mode(ptr) && is_Const(r))
599                                 ptr = l;
600                         else if (get_irn_mode(r) == get_irn_mode(ptr) && is_Const(l))
601                                 ptr = r;
602                         else
603                                 return NULL;
604
605                         /* for now, we support only one addition, reassoc should fold all others */
606                         if (! is_SymConst(ptr) && !is_Sel(ptr))
607                                 return NULL;
608                 } else if (is_Sub(ptr)) {
609                         ir_node *l = get_Sub_left(ptr);
610                         ir_node *r = get_Sub_right(ptr);
611
612                         if (get_irn_mode(l) == get_irn_mode(ptr) &&     is_Const(r))
613                                 ptr = l;
614                         else
615                                 return NULL;
616                         /* for now, we support only one subtraction, reassoc should fold all others */
617                         if (! is_SymConst(ptr) && !is_Sel(ptr))
618                                 return NULL;
619                 } else
620                         return NULL;
621         }
622 }  /* find_constant_entity */
623
624 /**
625  * Return the Selection index of a Sel node from dimension n
626  */
627 static long get_Sel_array_index_long(ir_node *n, int dim)
628 {
629         ir_node *index = get_Sel_index(n, dim);
630         assert(is_Const(index));
631         return get_tarval_long(get_Const_tarval(index));
632 }  /* get_Sel_array_index_long */
633
634 /**
635  * Returns the accessed component graph path for an
636  * node computing an address.
637  *
638  * @param ptr    the node computing the address
639  * @param depth  current depth in steps upward from the root
640  *               of the address
641  */
642 static compound_graph_path *rec_get_accessed_path(ir_node *ptr, int depth)
643 {
644         compound_graph_path *res = NULL;
645         ir_entity           *root, *field, *ent;
646         int                 path_len, pos, idx;
647         tarval              *tv;
648         ir_type             *tp;
649
650         if (is_SymConst(ptr)) {
651                 /* a SymConst. If the depth is 0, this is an access to a global
652                  * entity and we don't need a component path, else we know
653                  * at least its length.
654                  */
655                 assert(get_SymConst_kind(ptr) == symconst_addr_ent);
656                 root = get_SymConst_entity(ptr);
657                 res = (depth == 0) ? NULL : new_compound_graph_path(get_entity_type(root), depth);
658         } else if (is_Sel(ptr)) {
659                 /* it's a Sel, go up until we find the root */
660                 res = rec_get_accessed_path(get_Sel_ptr(ptr), depth+1);
661                 if (res == NULL)
662                         return NULL;
663
664                 /* fill up the step in the path at the current position */
665                 field    = get_Sel_entity(ptr);
666                 path_len = get_compound_graph_path_length(res);
667                 pos      = path_len - depth - 1;
668                 set_compound_graph_path_node(res, pos, field);
669
670                 if (is_Array_type(get_entity_owner(field))) {
671                         assert(get_Sel_n_indexs(ptr) == 1 && "multi dim arrays not implemented");
672                         set_compound_graph_path_array_index(res, pos, get_Sel_array_index_long(ptr, 0));
673                 }
674         } else if (is_Add(ptr)) {
675                 ir_node *l    = get_Add_left(ptr);
676                 ir_node *r    = get_Add_right(ptr);
677                 ir_mode *mode = get_irn_mode(ptr);
678                 tarval  *tmp;
679
680                 if (is_Const(r) && get_irn_mode(l) == mode) {
681                         ptr = l;
682                         tv  = get_Const_tarval(r);
683                 } else {
684                         ptr = r;
685                         tv  = get_Const_tarval(l);
686                 }
687 ptr_arith:
688                 mode = get_tarval_mode(tv);
689                 tmp  = tv;
690
691                 /* ptr must be a Sel or a SymConst, this was checked in find_constant_entity() */
692                 if (is_Sel(ptr)) {
693                         field = get_Sel_entity(ptr);
694                 } else {
695                         field = get_SymConst_entity(ptr);
696                 }
697                 idx = 0;
698                 for (ent = field;;) {
699                         unsigned size;
700                         tarval   *sz, *tv_index, *tlower, *tupper;
701                         ir_node  *bound;
702
703                         tp = get_entity_type(ent);
704                         if (! is_Array_type(tp))
705                                 break;
706                         ent = get_array_element_entity(tp);
707                         size = get_type_size_bytes(get_entity_type(ent));
708                         sz   = new_tarval_from_long(size, mode);
709
710                         tv_index = tarval_div(tmp, sz);
711                         tmp      = tarval_mod(tmp, sz);
712
713                         if (tv_index == tarval_bad || tmp == tarval_bad)
714                                 return NULL;
715
716                         assert(get_array_n_dimensions(tp) == 1 && "multiarrays not implemented");
717                         bound  = get_array_lower_bound(tp, 0);
718                         tlower = computed_value(bound);
719                         bound  = get_array_upper_bound(tp, 0);
720                         tupper = computed_value(bound);
721
722                         if (tlower == tarval_bad || tupper == tarval_bad)
723                                 return NULL;
724
725                         if (tarval_cmp(tv_index, tlower) & pn_Cmp_Lt)
726                                 return NULL;
727                         if (tarval_cmp(tupper, tv_index) & pn_Cmp_Lt)
728                                 return NULL;
729
730                         /* ok, bounds check finished */
731                         ++idx;
732                 }
733                 if (! tarval_is_null(tmp)) {
734                         /* access to some struct/union member */
735                         return NULL;
736                 }
737
738                 /* should be at least ONE array */
739                 if (idx == 0)
740                         return NULL;
741
742                 res = rec_get_accessed_path(ptr, depth + idx);
743                 if (res == NULL)
744                         return NULL;
745
746                 path_len = get_compound_graph_path_length(res);
747                 pos      = path_len - depth - idx;
748
749                 for (ent = field;;) {
750                         unsigned size;
751                         tarval   *sz, *tv_index;
752                         long     index;
753
754                         tp = get_entity_type(ent);
755                         if (! is_Array_type(tp))
756                                 break;
757                         ent = get_array_element_entity(tp);
758                         set_compound_graph_path_node(res, pos, ent);
759
760                         size = get_type_size_bytes(get_entity_type(ent));
761                         sz   = new_tarval_from_long(size, mode);
762
763                         tv_index = tarval_div(tv, sz);
764                         tv       = tarval_mod(tv, sz);
765
766                         /* worked above, should work again */
767                         assert(tv_index != tarval_bad && tv != tarval_bad);
768
769                         /* bounds already checked above */
770                         index = get_tarval_long(tv_index);
771                         set_compound_graph_path_array_index(res, pos, index);
772                         ++pos;
773                 }
774         } else if (is_Sub(ptr)) {
775                 ir_node *l = get_Sub_left(ptr);
776                 ir_node *r = get_Sub_right(ptr);
777
778                 ptr = l;
779                 tv  = get_Const_tarval(r);
780                 tv  = tarval_neg(tv);
781                 goto ptr_arith;
782         }
783         return res;
784 }  /* rec_get_accessed_path */
785
786 /**
787  * Returns an access path or NULL.  The access path is only
788  * valid, if the graph is in phase_high and _no_ address computation is used.
789  */
790 static compound_graph_path *get_accessed_path(ir_node *ptr)
791 {
792         compound_graph_path *gr = rec_get_accessed_path(ptr, 0);
793         return gr;
794 }  /* get_accessed_path */
795
796 typedef struct path_entry {
797         ir_entity         *ent;
798         struct path_entry *next;
799         long              index;
800 } path_entry;
801
802 static ir_node *rec_find_compound_ent_value(ir_node *ptr, path_entry *next)
803 {
804         path_entry       entry, *p;
805         ir_entity        *ent, *field;
806         ir_initializer_t *initializer;
807         tarval           *tv;
808         ir_type          *tp;
809         unsigned         n;
810
811         entry.next = next;
812         if (is_SymConst(ptr)) {
813                 /* found the root */
814                 ent         = get_SymConst_entity(ptr);
815                 initializer = get_entity_initializer(ent);
816                 for (p = next; p != NULL;) {
817                         if (initializer->kind != IR_INITIALIZER_COMPOUND)
818                                 return NULL;
819                         n  = get_initializer_compound_n_entries(initializer);
820                         tp = get_entity_type(ent);
821
822                         if (is_Array_type(tp)) {
823                                 ent = get_array_element_entity(tp);
824                                 if (ent != p->ent) {
825                                         /* a missing [0] */
826                                         if (0 >= n)
827                                                 return NULL;
828                                         initializer = get_initializer_compound_value(initializer, 0);
829                                         continue;
830                                 }
831                         }
832                         if (p->index >= (int) n)
833                                 return NULL;
834                         initializer = get_initializer_compound_value(initializer, p->index);
835
836                         ent = p->ent;
837                         p   = p->next;
838                 }
839                 tp = get_entity_type(ent);
840                 while (is_Array_type(tp)) {
841                         ent = get_array_element_entity(tp);
842                         tp = get_entity_type(ent);
843                         /* a missing [0] */
844                         n  = get_initializer_compound_n_entries(initializer);
845                         if (0 >= n)
846                                 return NULL;
847                         initializer = get_initializer_compound_value(initializer, 0);
848                 }
849
850                 switch (initializer->kind) {
851                 case IR_INITIALIZER_CONST:
852                         return get_initializer_const_value(initializer);
853                 case IR_INITIALIZER_TARVAL:
854                 case IR_INITIALIZER_NULL:
855                 default:
856                         return NULL;
857                 }
858         } else if (is_Sel(ptr)) {
859                 entry.ent = field = get_Sel_entity(ptr);
860                 tp = get_entity_owner(field);
861                 if (is_Array_type(tp)) {
862                         assert(get_Sel_n_indexs(ptr) == 1 && "multi dim arrays not implemented");
863                         entry.index = get_Sel_array_index_long(ptr, 0) - get_array_lower_bound_int(tp, 0);
864                 } else {
865                         int i, n_members = get_compound_n_members(tp);
866                         for (i = 0; i < n_members; ++i) {
867                                 if (get_compound_member(tp, i) == field)
868                                         break;
869                         }
870                         if (i >= n_members) {
871                                 /* not found: should NOT happen */
872                                 return NULL;
873                         }
874                         entry.index = i;
875                 }
876                 return rec_find_compound_ent_value(get_Sel_ptr(ptr), &entry);
877         }  else if (is_Add(ptr)) {
878                 ir_node  *l = get_Add_left(ptr);
879                 ir_node  *r = get_Add_right(ptr);
880                 ir_mode  *mode;
881                 unsigned pos;
882
883                 if (is_Const(r)) {
884                         ptr = l;
885                         tv  = get_Const_tarval(r);
886                 } else {
887                         ptr = r;
888                         tv  = get_Const_tarval(l);
889                 }
890 ptr_arith:
891                 mode = get_tarval_mode(tv);
892
893                 /* ptr must be a Sel or a SymConst, this was checked in find_constant_entity() */
894                 if (is_Sel(ptr)) {
895                         field = get_Sel_entity(ptr);
896                 } else {
897                         field = get_SymConst_entity(ptr);
898                 }
899
900                 /* count needed entries */
901                 pos = 0;
902                 for (ent = field;;) {
903                         tp = get_entity_type(ent);
904                         if (! is_Array_type(tp))
905                                 break;
906                         ent = get_array_element_entity(tp);
907                         ++pos;
908                 }
909                 /* should be at least ONE entry */
910                 if (pos == 0)
911                         return NULL;
912
913                 /* allocate the right number of entries */
914                 NEW_ARR_A(path_entry, p, pos);
915
916                 /* fill them up */
917                 pos = 0;
918                 for (ent = field;;) {
919                         unsigned size;
920                         tarval   *sz, *tv_index, *tlower, *tupper;
921                         long     index;
922                         ir_node  *bound;
923
924                         tp = get_entity_type(ent);
925                         if (! is_Array_type(tp))
926                                 break;
927                         ent = get_array_element_entity(tp);
928                         p[pos].ent  = ent;
929                         p[pos].next = &p[pos + 1];
930
931                         size = get_type_size_bytes(get_entity_type(ent));
932                         sz   = new_tarval_from_long(size, mode);
933
934                         tv_index = tarval_div(tv, sz);
935                         tv       = tarval_mod(tv, sz);
936
937                         if (tv_index == tarval_bad || tv == tarval_bad)
938                                 return NULL;
939
940                         assert(get_array_n_dimensions(tp) == 1 && "multiarrays not implemented");
941                         bound  = get_array_lower_bound(tp, 0);
942                         tlower = computed_value(bound);
943                         bound  = get_array_upper_bound(tp, 0);
944                         tupper = computed_value(bound);
945
946                         if (tlower == tarval_bad || tupper == tarval_bad)
947                                 return NULL;
948
949                         if (tarval_cmp(tv_index, tlower) & pn_Cmp_Lt)
950                                 return NULL;
951                         if (tarval_cmp(tupper, tv_index) & pn_Cmp_Lt)
952                                 return NULL;
953
954                         /* ok, bounds check finished */
955                         index = get_tarval_long(tv_index);
956                         p[pos].index = index;
957                         ++pos;
958                 }
959                 if (! tarval_is_null(tv)) {
960                         /* hmm, wrong access */
961                         return NULL;
962                 }
963                 p[pos - 1].next = next;
964                 return rec_find_compound_ent_value(ptr, p);
965         } else if (is_Sub(ptr)) {
966                 ir_node *l = get_Sub_left(ptr);
967                 ir_node *r = get_Sub_right(ptr);
968
969                 ptr = l;
970                 tv  = get_Const_tarval(r);
971                 tv  = tarval_neg(tv);
972                 goto ptr_arith;
973         }
974         return NULL;
975 }  /* rec_find_compound_ent_value */
976
977 static ir_node *find_compound_ent_value(ir_node *ptr)
978 {
979         return rec_find_compound_ent_value(ptr, NULL);
980 }  /* find_compound_ent_value */
981
982 /**
983  * Mark a Load memop to be replace by a definition
984  *
985  * @param op  the Load memop
986  */
987 static void mark_replace_load(memop_t *op, ir_node *def)
988 {
989         op->replace = def;
990         op->flags |= FLAG_KILLED_NODE;
991         env.changed = 1;
992 }  /* mark_replace_load */
993
994 /**
995  * Mark a Store memop to be removed.
996  *
997  * @param op  the Store memop
998  */
999 static void mark_remove_store(memop_t *op)
1000 {
1001         op->flags |= FLAG_KILLED_NODE;
1002         env.changed = 1;
1003 }  /* mark_remove_store */
1004
1005 /**
1006  * Update a memop for a Load.
1007  *
1008  * @param m  the memop
1009  */
1010 static void update_Load_memop(memop_t *m)
1011 {
1012         int       i;
1013         ir_node   *load = m->node;
1014         ir_node   *ptr;
1015         ir_entity *ent;
1016
1017         if (get_Load_volatility(load) == volatility_is_volatile)
1018                 m->flags |= FLAG_IGNORE;
1019
1020         ptr = get_Load_ptr(load);
1021
1022         m->value.address = ptr;
1023
1024         for (i = get_irn_n_outs(load) - 1; i >= 0; --i) {
1025                 ir_node *proj = get_irn_out(load, i);
1026                 long    pn;
1027
1028                 /* beware of keep edges */
1029                 if (is_End(proj))
1030                         continue;
1031
1032                 pn = get_Proj_proj(proj);
1033                 m->projs[pn] = proj;
1034                 switch (pn) {
1035                 case pn_Load_res:
1036                         m->value.value = proj;
1037                         m->value.mode  = get_irn_mode(proj);
1038                         break;
1039                 case pn_Load_X_except:
1040                         m->flags |= FLAG_EXCEPTION;
1041                         break;
1042                 case pn_Load_M:
1043                         m->mem = proj;
1044                         break;
1045                 case pn_Load_X_regular:
1046                         break;
1047                 default:
1048                         panic("Unsupported Proj from Load %+F", proj);
1049                 }
1050         }
1051
1052         /* check if we can determine the entity that will be loaded */
1053         ent = find_constant_entity(ptr);
1054
1055         if (ent != NULL && get_entity_visibility(ent) != ir_visibility_external) {
1056                 /* a static allocation that is not external: there should be NO exception
1057                  * when loading even if we cannot replace the load itself. */
1058                 ir_node *value = NULL;
1059
1060                 /* no exception, clear the m fields as it might be checked later again */
1061                 if (m->projs[pn_Load_X_except]) {
1062                         exchange(m->projs[pn_Load_X_except], new_Bad());
1063                         m->projs[pn_Load_X_except] = NULL;
1064                         m->flags &= ~FLAG_EXCEPTION;
1065                         env.changed = 1;
1066                 }
1067                 if (m->projs[pn_Load_X_regular]) {
1068                         exchange(m->projs[pn_Load_X_regular], new_r_Jmp(get_nodes_block(load)));
1069                         m->projs[pn_Load_X_regular] = NULL;
1070                         env.changed = 1;
1071                 }
1072
1073                 if (get_entity_linkage(ent) & IR_LINKAGE_CONSTANT) {
1074                         if (ent->initializer) {
1075                                 /* new style initializer */
1076                                 value = find_compound_ent_value(ptr);
1077                         } else if (entity_has_compound_ent_values(ent)) {
1078                                 /* old style initializer */
1079                                 compound_graph_path *path = get_accessed_path(ptr);
1080
1081                                 if (path != NULL) {
1082                                         assert(is_proper_compound_graph_path(path, get_compound_graph_path_length(path)-1));
1083
1084                                         value = get_compound_ent_value_by_path(ent, path);
1085                                         DB((dbg, LEVEL_1, "  Constant access at %F%F resulted in %+F\n", ent, path, value));
1086                                         free_compound_graph_path(path);
1087                                 }
1088                         }
1089                         if (value != NULL)
1090                                 value = can_replace_load_by_const(load, value);
1091                 }
1092
1093                 if (value != NULL) {
1094                         /* we completely replace the load by this value */
1095                         DB((dbg, LEVEL_1, "Replacing Load %+F by constant %+F\n", m->node, value));
1096                         mark_replace_load(m, value);
1097                         return;
1098                 }
1099         }
1100
1101         if (m->value.value != NULL && !(m->flags & FLAG_IGNORE)) {
1102                 /* only create an address if this node is NOT killed immediately or ignored */
1103                 m->value.id = register_address(ptr);
1104                 ++env.n_mem_ops;
1105         } else {
1106                 /* no user, KILL it */
1107                 mark_replace_load(m, NULL);
1108         }
1109 }  /* update_Load_memop */
1110
1111 /**
1112  * Update a memop for a Store.
1113  *
1114  * @param m  the memop
1115  */
1116 static void update_Store_memop(memop_t *m)
1117 {
1118         int     i;
1119         ir_node *store = m->node;
1120         ir_node *adr   = get_Store_ptr(store);
1121
1122         if (get_Store_volatility(store) == volatility_is_volatile) {
1123                 m->flags |= FLAG_IGNORE;
1124         } else {
1125                 /* only create an address if this node is NOT ignored */
1126                 m->value.id = register_address(adr);
1127                 ++env.n_mem_ops;
1128         }
1129
1130         m->value.address = adr;
1131
1132         for (i = get_irn_n_outs(store) - 1; i >= 0; --i) {
1133                 ir_node *proj = get_irn_out(store, i);
1134                 long    pn;
1135
1136                 /* beware of keep edges */
1137                 if (is_End(proj))
1138                         continue;
1139
1140                 pn = get_Proj_proj(proj);
1141                 m->projs[pn] = proj;
1142                 switch (pn) {
1143                 case pn_Store_X_except:
1144                         m->flags |= FLAG_EXCEPTION;
1145                         break;
1146                 case pn_Store_M:
1147                         m->mem = proj;
1148                         break;
1149                 case pn_Store_X_regular:
1150                         break;
1151                 default:
1152                         panic("Unsupported Proj from Store %+F", proj);
1153                 }
1154         }
1155         m->value.value = get_Store_value(store);
1156         m->value.mode  = get_irn_mode(m->value.value);
1157 }  /* update_Store_memop */
1158
1159 /**
1160  * Update a memop for a Call.
1161  *
1162  * @param m  the memop
1163  */
1164 static void update_Call_memop(memop_t *m)
1165 {
1166         ir_node  *call = m->node;
1167         unsigned prop  = get_Call_memory_properties(call);
1168         int      i;
1169
1170         if (prop & mtp_property_const) {
1171                 /* A constant call did NOT use memory at all, we
1172                    can kick it from the list. */
1173         } else if (prop & mtp_property_pure) {
1174                 /* pure calls READ memory */
1175                 m->flags = 0;
1176         } else
1177                 m->flags = FLAG_KILL_ALL;
1178
1179         for (i = get_irn_n_outs(call) - 1; i >= 0; --i) {
1180                 ir_node *proj = get_irn_out(call, i);
1181
1182                 /* beware of keep edges */
1183                 if (is_End(proj))
1184                         continue;
1185
1186                 switch (get_Proj_proj(proj)) {
1187                 case pn_Call_X_except:
1188                         m->flags |= FLAG_EXCEPTION;
1189                         break;
1190                 case pn_Call_M:
1191                         m->mem = proj;
1192                         break;
1193                 }
1194         }
1195 }  /* update_Call_memop */
1196
1197 /**
1198  * Update a memop for a Div/Mod/Quot/DivMod.
1199  *
1200  * @param m  the memop
1201  */
1202 static void update_DivOp_memop(memop_t *m)
1203 {
1204         ir_node *div = m->node;
1205         int     i;
1206
1207         for (i = get_irn_n_outs(div) - 1; i >= 0; --i) {
1208                 ir_node *proj = get_irn_out(div, i);
1209
1210                 /* beware of keep edges */
1211                 if (is_End(proj))
1212                         continue;
1213
1214                 switch (get_Proj_proj(proj)) {
1215                 case pn_Generic_X_except:
1216                         m->flags |= FLAG_EXCEPTION;
1217                         break;
1218                 case pn_Generic_M:
1219                         m->mem = proj;
1220                         break;
1221                 }
1222         }
1223 }  /* update_DivOp_memop */
1224
1225 /**
1226  * Update a memop for a Phi.
1227  *
1228  * @param m  the memop
1229  */
1230 static void update_Phi_memop(memop_t *m)
1231 {
1232         /* the Phi is it's own mem */
1233         m->mem = m->node;
1234 }  /* update_Phi_memop */
1235
1236 /**
1237  * Memory walker: collect all memory ops and build topological lists.
1238  */
1239 static void collect_memops(ir_node *irn, void *ctx)
1240 {
1241         memop_t  *op;
1242         ir_node  *block;
1243         block_t  *entry;
1244
1245         (void) ctx;
1246         if (is_Proj(irn)) {
1247                 /* we can safely ignore ProjM's except the initial memory */
1248                 if (irn != get_irg_initial_mem(current_ir_graph))
1249                         return;
1250         }
1251
1252         op    = alloc_memop(irn);
1253         block = get_nodes_block(irn);
1254         entry = get_block_entry(block);
1255
1256         if (is_Phi(irn)) {
1257                 update_Phi_memop(op);
1258                 /* Phis must be always placed first */
1259                 op->next = entry->memop_forward;
1260                 entry->memop_forward = op;
1261                 if (entry->memop_backward == NULL)
1262                         entry->memop_backward = op;
1263         } else {
1264                 switch (get_irn_opcode(irn)) {
1265                 case iro_Load:
1266                         update_Load_memop(op);
1267                         break;
1268                 case iro_Store:
1269                         update_Store_memop(op);
1270                         break;
1271                 case iro_Call:
1272                         update_Call_memop(op);
1273                         break;
1274                 case iro_Sync:
1275                 case iro_Pin:
1276                         op->mem = irn;
1277                         break;
1278                 case iro_Proj:
1279                         /* initial memory */
1280                         op->mem = irn;
1281                         break;
1282                 case iro_Return:
1283                 case iro_End:
1284                         /* we can those to find the memory edge */
1285                         break;
1286                 case iro_Div:
1287                 case iro_DivMod:
1288                 case iro_Quot:
1289                 case iro_Mod:
1290                         update_DivOp_memop(op);
1291                         break;
1292
1293                 case iro_Builtin:
1294                         /* TODO: handle some builtins */
1295                 default:
1296                         /* unsupported operation */
1297                         op->flags = FLAG_KILL_ALL;
1298                 }
1299
1300
1301                 /* all other should be placed last */
1302                 if (entry->memop_backward == NULL) {
1303                         entry->memop_forward = entry->memop_backward = op;
1304                 } else {
1305                         entry->memop_backward->next = op;
1306                         entry->memop_backward       = op;
1307                 }
1308         }
1309 }  /* collect_memops */
1310
1311 /**
1312  * Find an address in the current set.
1313  *
1314  * @param value  the value to be searched for
1315  *
1316  * @return a memop for the value or NULL if the value does
1317  *         not exists in the set or cannot be converted into
1318  *         the requested mode
1319  */
1320 static memop_t *find_address(const value_t *value)
1321 {
1322         if (rbitset_is_set(env.curr_set, value->id)) {
1323                 memop_t *res = env.curr_id_2_memop[value->id];
1324
1325                 if (res->value.mode == value->mode)
1326                         return res;
1327                 /* allow hidden casts */
1328                 if (get_mode_arithmetic(res->value.mode) == irma_twos_complement &&
1329                     get_mode_arithmetic(value->mode) == irma_twos_complement &&
1330                     get_mode_size_bits(res->value.mode) == get_mode_size_bits(value->mode))
1331                         return res;
1332         }
1333         return NULL;
1334 }  /* find_address */
1335
1336 /**
1337  * Find an address in the avail_out set.
1338  *
1339  * @param bl     the block
1340  */
1341 static memop_t *find_address_avail(const block_t *bl, unsigned id, const ir_mode *mode)
1342 {
1343         if (rbitset_is_set(bl->avail_out, id)) {
1344                 memop_t *res = bl->id_2_memop_avail[id];
1345
1346                 if (res->value.mode == mode)
1347                         return res;
1348                 /* allow hidden casts */
1349                 if (get_mode_arithmetic(res->value.mode) == irma_twos_complement &&
1350                     get_mode_arithmetic(mode) == irma_twos_complement &&
1351                     get_mode_size_bits(res->value.mode) == get_mode_size_bits(mode))
1352                         return res;
1353         }
1354         return NULL;
1355 }  /* find_address_avail */
1356
1357 /**
1358  * Kill all addresses from the current set.
1359  */
1360 static void kill_all(void)
1361 {
1362         rbitset_clear_all(env.curr_set, env.rbs_size);
1363
1364         /* set sentinel */
1365         rbitset_set(env.curr_set, env.rbs_size - 1);
1366 }  /* kill_all */
1367
1368 /**
1369  * Kill memops that are not alias free due to a Store value from the current set.
1370  *
1371  * @param value  the Store value
1372  */
1373 static void kill_memops(const value_t *value)
1374 {
1375         unsigned end = env.rbs_size - 1;
1376         unsigned pos;
1377
1378         for (pos = rbitset_next(env.curr_set, 0, 1); pos < end; pos = rbitset_next(env.curr_set, pos + 1, 1)) {
1379                 memop_t *op = env.curr_id_2_memop[pos];
1380
1381                 if (ir_no_alias != get_alias_relation(current_ir_graph, value->address, value->mode,
1382                                                           op->value.address, op->value.mode)) {
1383                         rbitset_clear(env.curr_set, pos);
1384                         env.curr_id_2_memop[pos] = NULL;
1385                         DB((dbg, LEVEL_2, "KILLING %+F because of possible alias address %+F\n", op->node, value->address));
1386                 }
1387         }
1388 }  /* kill_memops */
1389
1390 /**
1391  * Add the value of a memop to the current set.
1392  *
1393  * @param op  the memory op
1394  */
1395 static void add_memop(memop_t *op)
1396 {
1397         rbitset_set(env.curr_set, op->value.id);
1398         env.curr_id_2_memop[op->value.id] = op;
1399 }  /* add_memop */
1400
1401 /**
1402  * Add the value of a memop to the avail_out set.
1403  *
1404  * @param bl  the block
1405  * @param op  the memory op
1406  */
1407 static void add_memop_avail(block_t *bl, memop_t *op)
1408 {
1409         rbitset_set(bl->avail_out, op->value.id);
1410         bl->id_2_memop_avail[op->value.id] = op;
1411 }  /* add_memop_avail */
1412
1413 /**
1414  * Check, if we can convert a value of one mode to another mode
1415  * without changing the representation of bits.
1416  *
1417  * @param from  the original mode
1418  * @param to    the destination mode
1419  */
1420 static int can_convert_to(const ir_mode *from, const ir_mode *to)
1421 {
1422         if (get_mode_arithmetic(from) == irma_twos_complement &&
1423             get_mode_arithmetic(to) == irma_twos_complement &&
1424             get_mode_size_bits(from) == get_mode_size_bits(to))
1425                 return 1;
1426         return 0;
1427 }  /* can_convert_to */
1428
1429 /**
1430  * Add a Conv to the requested mode if needed.
1431  *
1432  * @param irn   the IR-node to convert
1433  * @param mode  the destination mode
1434  *
1435  * @return the possible converted node or NULL
1436  *         if the conversion is not possible
1437  */
1438 static ir_node *conv_to(ir_node *irn, ir_mode *mode)
1439 {
1440         ir_mode *other = get_irn_mode(irn);
1441         if (other != mode) {
1442                 /* different modes: check if conversion is possible without changing the bits */
1443                 if (can_convert_to(other, mode)) {
1444                         ir_node *block = get_nodes_block(irn);
1445                         return new_r_Conv(block, irn, mode);
1446                 }
1447                 /* otherwise not possible ... yet */
1448                 return NULL;
1449         }
1450         return irn;
1451 }  /* conv_to */
1452
1453 /**
1454  * Update the address of an value if this address was a load result
1455  * and the load is killed now.
1456  *
1457  * @param value  the value whose address is updated
1458  */
1459 static void update_address(value_t *value)
1460 {
1461         if (is_Proj(value->address)) {
1462                 ir_node *load = get_Proj_pred(value->address);
1463
1464                 if (is_Load(load)) {
1465                         const memop_t *op = get_irn_memop(load);
1466
1467                         if (op->flags & FLAG_KILLED_NODE)
1468                                 value->address = op->replace;
1469                 }
1470         }
1471 }  /* update_address */
1472
1473 /**
1474  * Do forward dataflow analysis on the given block and calculate the
1475  * GEN and KILL in the current (avail) set.
1476  *
1477  * @param bl  the block
1478  */
1479 static void calc_gen_kill_avail(block_t *bl)
1480 {
1481         memop_t *op;
1482         ir_node *def;
1483
1484         for (op = bl->memop_forward; op != NULL; op = op->next) {
1485                 switch (get_irn_opcode(op->node)) {
1486                 case iro_Phi:
1487                         /* meet */
1488                         break;
1489                 case iro_Sync:
1490                         /* join */
1491                         break;
1492                 case iro_Load:
1493                         if (! (op->flags & (FLAG_KILLED_NODE|FLAG_IGNORE))) {
1494                                 /* do we have this already? */
1495                                 memop_t *other;
1496
1497                                 update_address(&op->value);
1498                                 other = find_address(&op->value);
1499                                 if (other != NULL && other != op) {
1500                                         def = conv_to(other->value.value, op->value.mode);
1501                                         if (def != NULL) {
1502 #ifdef DEBUG_libfirm
1503                                                 if (is_Store(other->node)) {
1504                                                         /* RAW */
1505                                                         DB((dbg, LEVEL_1, "RAW %+F <- %+F(%+F)\n", op->node, def, other->node));
1506                                                 } else {
1507                                                         /* RAR */
1508                                                         DB((dbg, LEVEL_1, "RAR %+F <- %+F(%+F)\n", op->node, def, other->node));
1509                                                 }
1510 #endif
1511                                                 mark_replace_load(op, def);
1512                                                 /* do NOT change the memop table */
1513                                                 continue;
1514                                         }
1515                                 }
1516                                 /* add this value */
1517                                 add_memop(op);
1518                         }
1519                         break;
1520                 case iro_Store:
1521                         if (! (op->flags & FLAG_KILLED_NODE)) {
1522                                 /* do we have this store already */
1523                                 memop_t *other;
1524
1525                                 update_address(&op->value);
1526                                 other = find_address(&op->value);
1527                                 if (other != NULL) {
1528                                         if (is_Store(other->node)) {
1529                                                 if (op != other && !(other->flags & FLAG_IGNORE) &&
1530                                                     get_nodes_block(other->node) == get_nodes_block(op->node)) {
1531                                                         /*
1532                                                          * A WAW in the same block we can kick the first store.
1533                                                          * This is a shortcut: we know that the second Store will be anticipated
1534                                                          * then in an case.
1535                                                          */
1536                                                         DB((dbg, LEVEL_1, "WAW %+F <- %+F\n", other->node, op->node));
1537                                                         mark_remove_store(other);
1538                                                         /* FIXME: a Load might be get freed due to this killed store */
1539                                                 }
1540                                         } else if (other->value.value == op->value.value && !(op->flags & FLAG_IGNORE)) {
1541                                                 /* WAR */
1542                                                 DB((dbg, LEVEL_1, "WAR %+F <- %+F\n", op->node, other->node));
1543                                                 mark_remove_store(op);
1544                                                 /* do NOT change the memop table */
1545                                                 continue;
1546                                         }
1547                                 }
1548                                 /* KILL all possible aliases */
1549                                 kill_memops(&op->value);
1550                                 /* add this value */
1551                                 add_memop(op);
1552                         }
1553                         break;
1554                 default:
1555                         if (op->flags & FLAG_KILL_ALL)
1556                                 kill_all();
1557                 }
1558         }
1559 }  /* calc_gen_kill_avail */
1560
1561 #define BYTE_SIZE(x)  (((x) + 7) >> 3)
1562
1563 /**
1564  * Do forward dataflow analysis on a given block to calculate the avail_out set
1565  * for this block only.
1566  *
1567  * @param block  the block
1568  */
1569 static void forward_avail(block_t *bl)
1570 {
1571         /* fill the data from the current block */
1572         env.curr_id_2_memop = bl->id_2_memop_avail;
1573         env.curr_set        = bl->avail_out;
1574
1575         calc_gen_kill_avail(bl);
1576         dump_curr(bl, "Avail_out");
1577 }  /* forward_avail */
1578
1579 /**
1580  * Do backward dataflow analysis on a given block to calculate the antic set
1581  * of Loaded addresses.
1582  *
1583  * @param bl  the block
1584  *
1585  * @return non-zero if the set has changed since last iteration
1586  */
1587 static int backward_antic(block_t *bl)
1588 {
1589         memop_t *op;
1590         ir_node *block = bl->block;
1591         int     n = get_Block_n_cfg_outs(block);
1592
1593         if (n == 1) {
1594                 ir_node  *succ    = get_Block_cfg_out(block, 0);
1595                 block_t  *succ_bl = get_block_entry(succ);
1596                 int      pred_pos = get_Block_cfgpred_pos(succ, block);
1597                 unsigned end      = env.rbs_size - 1;
1598                 unsigned pos;
1599
1600                 kill_all();
1601
1602                 if (bl->trans_results == NULL) {
1603                         /* allocate the translate cache */
1604                         bl->trans_results = OALLOCNZ(&env.obst, memop_t*, env.curr_adr_id);
1605                 }
1606
1607                 /* check for partly redundant values */
1608                 for (pos = rbitset_next(succ_bl->anticL_in, 0, 1);
1609                      pos < end;
1610                      pos = rbitset_next(succ_bl->anticL_in, pos + 1, 1)) {
1611                         /*
1612                          * do Phi-translation here: Note that at this point the nodes are
1613                          * not changed, so we can safely cache the results.
1614                          * However: Loads of Load results ARE bad, because we have no way
1615                           to translate them yet ...
1616                          */
1617                         memop_t *op = bl->trans_results[pos];
1618                         if (op == NULL) {
1619                                 /* not yet translated */
1620                                 ir_node *adr, *trans_adr;
1621
1622                                 op  = succ_bl->id_2_memop_antic[pos];
1623                                 adr = op->value.address;
1624
1625                                 trans_adr = phi_translate(adr, succ, pred_pos);
1626                                 if (trans_adr != adr) {
1627                                         /* create a new entry for the translated one */
1628                                         memop_t *new_op;
1629
1630                                         new_op = alloc_memop(NULL);
1631                                         new_op->value.address = trans_adr;
1632                                         new_op->value.id      = register_address(trans_adr);
1633                                         new_op->value.mode    = op->value.mode;
1634                                         new_op->node          = op->node; /* we need the node to decide if Load/Store */
1635                                         new_op->flags         = op->flags;
1636
1637                                         bl->trans_results[pos] = new_op;
1638                                         op = new_op;
1639                                 }
1640                         }
1641                         env.curr_id_2_memop[op->value.id] = op;
1642                         rbitset_set(env.curr_set, op->value.id);
1643                 }
1644         } else if (n > 1) {
1645                 ir_node *succ    = get_Block_cfg_out(block, 0);
1646                 block_t *succ_bl = get_block_entry(succ);
1647                 int i;
1648
1649                 rbitset_copy(env.curr_set, succ_bl->anticL_in, env.rbs_size);
1650                 memcpy(env.curr_id_2_memop, succ_bl->id_2_memop_antic, env.rbs_size * sizeof(env.curr_id_2_memop[0]));
1651
1652                 /* Hmm: probably we want kill merges of Loads ans Stores here */
1653                 for (i = n - 1; i > 0; --i) {
1654                         ir_node *succ    = get_Block_cfg_out(bl->block, i);
1655                         block_t *succ_bl = get_block_entry(succ);
1656
1657                         rbitset_and(env.curr_set, succ_bl->anticL_in, env.rbs_size);
1658                 }
1659         } else {
1660                 /* block ends with a noreturn call */
1661                 kill_all();
1662         }
1663
1664         dump_curr(bl, "AnticL_out");
1665
1666         for (op = bl->memop_backward; op != NULL; op = op->prev) {
1667                 switch (get_irn_opcode(op->node)) {
1668                 case iro_Phi:
1669                         /* meet */
1670                         break;
1671                 case iro_Sync:
1672                         /* join */
1673                         break;
1674                 case iro_Load:
1675                         if (! (op->flags & (FLAG_KILLED_NODE|FLAG_IGNORE))) {
1676                                 /* always add it */
1677                                 add_memop(op);
1678                         }
1679                         break;
1680                 case iro_Store:
1681                         if (! (op->flags & FLAG_KILLED_NODE)) {
1682                                 /* a Store: check which memops must be killed */
1683                                 kill_memops(&op->value);
1684                         }
1685                         break;
1686                 default:
1687                         if (op->flags & FLAG_KILL_ALL)
1688                                 kill_all();
1689                 }
1690         }
1691
1692         memcpy(bl->id_2_memop_antic, env.curr_id_2_memop, env.rbs_size * sizeof(env.curr_id_2_memop[0]));
1693         if (! rbitset_equal(bl->anticL_in, env.curr_set, env.rbs_size)) {
1694                 /* changed */
1695                 rbitset_copy(bl->anticL_in, env.curr_set, env.rbs_size);
1696                 dump_curr(bl, "AnticL_in*");
1697                 return 1;
1698         }
1699         dump_curr(bl, "AnticL_in");
1700         return 0;
1701 }  /* backward_antic */
1702
1703 /**
1704  * Replace a Load memop by a already known value.
1705  *
1706  * @param op  the Load memop
1707  */
1708 static void replace_load(memop_t *op)
1709 {
1710         ir_node *load = op->node;
1711         ir_node *def  = skip_Id(op->replace);
1712         ir_node *proj;
1713         ir_mode *mode;
1714
1715         if (def != NULL)
1716                 DB((dbg, LEVEL_1, "Replacing %+F by definition %+F\n", load, is_Proj(def) ? get_Proj_pred(def) : def));
1717         else {
1718                 if (op->flags & FLAG_EXCEPTION) {
1719                         /* bad: this node is unused and executed for exception only */
1720                         DB((dbg, LEVEL_1, "Unused %+F executed for exception only ...\n", load));
1721                         return;
1722                 }
1723                 DB((dbg, LEVEL_1, "Killing unused %+F\n", load));
1724         }
1725
1726         if (op->mem != NULL) {
1727                 /* in rare cases a Load might have NO memory */
1728                 exchange(op->mem, get_Load_mem(load));
1729         }
1730         proj = op->projs[pn_Load_res];
1731         if (proj != NULL) {
1732                 mode = get_irn_mode(proj);
1733                 if (get_irn_mode(def) != mode) {
1734                         /* a hidden cast */
1735                         dbg_info *db    = get_irn_dbg_info(load);
1736                         ir_node  *block = get_nodes_block(proj);
1737                         def = new_rd_Conv(db, block, def, mode);
1738                 }
1739                 exchange(proj, def);
1740         }
1741         proj = op->projs[pn_Load_X_except];
1742         if (proj != NULL) {
1743                 exchange(proj, new_Bad());
1744         }
1745         proj = op->projs[pn_Load_X_regular];
1746         if (proj != NULL) {
1747                 exchange(proj, new_r_Jmp(get_nodes_block(load)));
1748         }
1749 }  /* replace_load */
1750
1751 /**
1752  * Remove a Store memop.
1753  *
1754  * @param op  the Store memop
1755  */
1756 static void remove_store(memop_t *op)
1757 {
1758         ir_node *store = op->node;
1759         ir_node *proj;
1760
1761         DB((dbg, LEVEL_1, "Removing %+F\n", store));
1762
1763         if (op->mem != NULL) {
1764                 /* in rare cases a Store might have no memory */
1765                 exchange(op->mem, get_Store_mem(store));
1766         }
1767         proj = op->projs[pn_Store_X_except];
1768         if (proj != NULL) {
1769                 exchange(proj, new_Bad());
1770         }
1771         proj = op->projs[pn_Store_X_regular];
1772         if (proj != NULL) {
1773                 exchange(proj, new_r_Jmp(get_nodes_block(store)));
1774         }
1775 }  /* remove_store */
1776
1777
1778 /**
1779  * Do all necessary replacements for a given block.
1780  *
1781  * @param bl  the block
1782  */
1783 static void do_replacements(block_t *bl)
1784 {
1785         memop_t *op;
1786
1787         for (op = bl->memop_forward; op != NULL; op = op->next) {
1788                 if (op->flags & FLAG_KILLED_NODE) {
1789                         switch (get_irn_opcode(op->node)) {
1790                         case iro_Load:
1791                                 replace_load(op);
1792                                 break;
1793                         case iro_Store:
1794                                 remove_store(op);
1795                                 break;
1796                         }
1797                 }
1798         }
1799 }  /* do_replacements */
1800
1801 /**
1802  * Calculate the Avail_out sets for all basic blocks.
1803  */
1804 static void calcAvail(void)
1805 {
1806         memop_t  **tmp_memop = env.curr_id_2_memop;
1807         unsigned *tmp_set    = env.curr_set;
1808         block_t  *bl;
1809
1810         /* calculate avail_out */
1811         DB((dbg, LEVEL_2, "Calculate Avail_out\n"));
1812
1813         /* iterate over all blocks in in any order, skip the start block */
1814         for (bl = env.forward->forward_next; bl != NULL; bl = bl->forward_next) {
1815                 forward_avail(bl);
1816         }
1817
1818         /* restore the current sets */
1819         env.curr_id_2_memop = tmp_memop;
1820         env.curr_set        = tmp_set;
1821 }  /* calcAvail */
1822
1823 /**
1824  * Calculate the Antic_in sets for all basic blocks.
1825  */
1826 static void calcAntic(void)
1827 {
1828         int i, need_iter;
1829
1830         /* calculate antic_out */
1831         DB((dbg, LEVEL_2, "Calculate Antic_in\n"));
1832         i = 0;
1833         do {
1834                 block_t *bl;
1835
1836                 DB((dbg, LEVEL_2, "Iteration %d:\n=========\n", i));
1837
1838                 need_iter = 0;
1839
1840                 /* over all blocks in reverse post order */
1841                 for (bl = env.backward->backward_next; bl != NULL; bl = bl->backward_next) {
1842                         need_iter |= backward_antic(bl);
1843                 }
1844                 ++i;
1845         } while (need_iter);
1846         DB((dbg, LEVEL_2, "Get anticipated Load set after %d iterations\n", i));
1847 }  /* calcAntic */
1848
1849 /**
1850  * Return the node representing the last memory in a block.
1851  *
1852  * @param bl  the block
1853  */
1854 static ir_node *find_last_memory(block_t *bl)
1855 {
1856         for (;;) {
1857                 if (bl->memop_backward != NULL) {
1858                         return bl->memop_backward->mem;
1859                 }
1860                 /* if there is NO memory in this block, go to the dominator */
1861                 bl = get_block_entry(get_Block_idom(bl->block));
1862         }
1863 }  /* find_last_memory */
1864
1865 /**
1866  * Reroute all memory users of old memory
1867  * to a new memory IR-node.
1868  *
1869  * @param omem  the old memory IR-node
1870  * @param nmem  the new memory IR-node
1871  */
1872 static void reroute_all_mem_users(ir_node *omem, ir_node *nmem)
1873 {
1874         int i;
1875
1876         for (i = get_irn_n_outs(omem) - 1; i >= 0; --i) {
1877                 int     n_pos;
1878                 ir_node *user = get_irn_out_ex(omem, i, &n_pos);
1879
1880                 set_irn_n(user, n_pos, nmem);
1881         }
1882
1883         /* all edges previously point to omem now point to nmem */
1884         nmem->out = omem->out;
1885 }  /* reroute_all_mem_users */
1886
1887 /**
1888  * Reroute memory users of old memory that are dominated by a given block
1889  * to a new memory IR-node.
1890  *
1891  * @param omem     the old memory IR-node
1892  * @param nmem     the new memory IR-node
1893  * @param pass_bl  the block the memory must pass
1894  */
1895 static void reroute_mem_through(ir_node *omem, ir_node *nmem, ir_node *pass_bl)
1896 {
1897         int             i, j, n = get_irn_n_outs(omem);
1898         ir_def_use_edge *edges = NEW_ARR_D(ir_def_use_edge, &env.obst, n + 1);
1899
1900         for (i = j = 0; i < n; ++i) {
1901                 int     n_pos;
1902                 ir_node *user   = get_irn_out_ex(omem, i, &n_pos);
1903                 ir_node *use_bl = get_nodes_block(user);
1904
1905
1906                 if (is_Phi(user)) {
1907                         use_bl = get_Block_cfgpred_block(use_bl, n_pos);
1908                 }
1909                 if (block_dominates(pass_bl, use_bl)) {
1910                         /* found an user that is dominated */
1911                         ++j;
1912                         edges[j].pos = n_pos;
1913                         edges[j].use = user;
1914
1915                         set_irn_n(user, n_pos, nmem);
1916                 }
1917         }
1918
1919         /* Modify the out structure: we create a new out edge array on our
1920            temporary obstack here. This should be no problem, as we invalidate the edges
1921            at the end either. */
1922         /* first entry is used for the length */
1923         edges[0].pos = j;
1924         nmem->out = edges;
1925 }  /* reroute_mem_through */
1926
1927 /**
1928  * insert Loads, making partly redundant Loads fully redundant
1929  */
1930 static int insert_Load(block_t *bl)
1931 {
1932         ir_node  *block = bl->block;
1933         int      i, n = get_Block_n_cfgpreds(block);
1934         unsigned end = env.rbs_size - 1;
1935         unsigned pos;
1936
1937         DB((dbg, LEVEL_3, "processing %+F\n", block));
1938
1939         if (n == 0) {
1940                 /* might still happen for an unreachable block (end for instance) */
1941                 return 0;
1942         }
1943
1944         if (n > 1) {
1945                 ir_node **ins;
1946                 int     pos;
1947
1948                 NEW_ARR_A(ir_node *, ins, n);
1949
1950                 rbitset_set_all(env.curr_set, env.rbs_size);
1951
1952                 /* More than one predecessors, calculate the join for all avail_outs ignoring unevaluated
1953                    Blocks. These put in Top anyway. */
1954                 for (i = n - 1; i >= 0; --i) {
1955                         ir_node *pred = skip_Proj(get_Block_cfgpred(block, i));
1956                         ir_node *blk  = get_nodes_block(pred);
1957                         block_t *pred_bl;
1958
1959                         pred_bl = get_block_entry(blk);
1960                         rbitset_and(env.curr_set, pred_bl->avail_out, env.rbs_size);
1961
1962                         if (is_Load(pred) || is_Store(pred)) {
1963                                 /* We reached this block by an exception from a Load or Store:
1964                                  * the memop creating the exception was NOT completed than, kill it
1965                                  */
1966                                 memop_t *exc_op = get_irn_memop(pred);
1967                                 rbitset_clear(env.curr_set, exc_op->value.id);
1968                         }
1969
1970                 }
1971                 /*
1972                  * Ensure that all values are in the map: build Phi's if necessary:
1973                  * Note: the last bit is the sentinel and ALWAYS set, so start with -2.
1974                  */
1975                 for (pos = env.rbs_size - 2; pos >= 0; --pos) {
1976                         if (! rbitset_is_set(env.curr_set, pos))
1977                                 env.curr_id_2_memop[pos] = NULL;
1978                         else {
1979                                 ir_node *pred    = get_Block_cfgpred_block(bl->block, 0);
1980                                 block_t *pred_bl = get_block_entry(pred);
1981                                 int     need_phi = 0;
1982                                 memop_t *first   = NULL;
1983                                 ir_mode *mode    = NULL;
1984
1985                                 for (i = 0; i < n; ++i) {
1986                                         memop_t *mop;
1987
1988                                         pred    = get_Block_cfgpred_block(bl->block, i);
1989                                         pred_bl = get_block_entry(pred);
1990
1991                                         mop = pred_bl->id_2_memop_avail[pos];
1992                                         if (first == NULL) {
1993                                                 first = mop;
1994                                                 ins[0] = first->value.value;
1995                                                 mode = get_irn_mode(ins[0]);
1996
1997                                                 /* no Phi needed so far */
1998                                                 env.curr_id_2_memop[pos] = first;
1999                                         } else {
2000                                                 ins[i] = conv_to(mop->value.value, mode);
2001                                                 if (ins[i] != ins[0]) {
2002                                                         if (ins[i] == NULL) {
2003                                                                 /* conversion failed */
2004                                                                 env.curr_id_2_memop[pos] = NULL;
2005                                                                 rbitset_clear(env.curr_set, pos);
2006                                                                 break;
2007                                                         }
2008                                                         need_phi = 1;
2009                                                 }
2010                                         }
2011                                 }
2012                                 if (need_phi) {
2013                                         /* build a Phi  */
2014                                         ir_node *phi = new_r_Phi(bl->block, n, ins, mode);
2015                                         memop_t *phiop = alloc_memop(phi);
2016
2017                                         phiop->value = first->value;
2018                                         phiop->value.value = phi;
2019
2020                                         /* no need to link it in, as it is a DATA phi */
2021
2022                                         env.curr_id_2_memop[pos] = phiop;
2023
2024                                         DB((dbg, LEVEL_3, "Created new %+F on merging value for address %+F\n", phi, first->value.address));
2025                                 }
2026                         }
2027                 }
2028         } else {
2029                 /* only one predecessor, simply copy the map */
2030                 ir_node *pred    = get_Block_cfgpred_block(bl->block, 0);
2031                 block_t *pred_bl = get_block_entry(pred);
2032
2033                 rbitset_copy(env.curr_set, pred_bl->avail_out, env.rbs_size);
2034
2035                 memcpy(env.curr_id_2_memop, pred_bl->id_2_memop_avail, env.rbs_size * sizeof(bl->id_2_memop_avail[0]));
2036         }
2037
2038         if (n > 1) {
2039                 /* check for partly redundant values */
2040                 for (pos = rbitset_next(bl->anticL_in, 0, 1);
2041                      pos < end;
2042                      pos = rbitset_next(bl->anticL_in, pos + 1, 1)) {
2043                         memop_t *op = bl->id_2_memop_antic[pos];
2044                         int     have_some, all_same;
2045                         ir_node *first;
2046
2047                         if (rbitset_is_set(env.curr_set, pos)) {
2048                                 /* already avail */
2049                                 continue;
2050                         }
2051
2052                         assert(is_Load(op->node));
2053
2054                         DB((dbg, LEVEL_3, "anticipated %+F\n", op->node));
2055
2056                         have_some  = 0;
2057                         all_same   = 1;
2058                         first      = 0;
2059                         for (i = n - 1; i >= 0; --i) {
2060                                 ir_node *pred    = get_Block_cfgpred_block(block, i);
2061                                 block_t *pred_bl = get_block_entry(pred);
2062                                 ir_mode *mode    = op->value.mode;
2063                                 memop_t *e;
2064                                 ir_node *adr;
2065
2066                                 adr = phi_translate(op->value.address, block, i);
2067                                 DB((dbg, LEVEL_3, ".. using address %+F in pred %d\n", adr, i));
2068                                 e   = find_address_avail(pred_bl, register_address(adr), mode);
2069                                 if (e == NULL) {
2070                                         ir_node *ef_block = get_nodes_block(adr);
2071                                         if (! block_dominates(ef_block, pred)) {
2072                                                 /* cannot place a copy here */
2073                                                 have_some = 0;
2074                                                 DB((dbg, LEVEL_3, "%+F cannot be moved into predecessor %+F\n", op->node, pred));
2075                                                 break;
2076                                         }
2077                                         DB((dbg, LEVEL_3, "%+F is not available in predecessor %+F\n", op->node, pred));
2078                                         pred_bl->avail = NULL;
2079                                         all_same       = 0;
2080                                 } else {
2081                                         if (e->value.mode != mode && !can_convert_to(e->value.mode, mode)) {
2082                                                 /* cannot create a Phi due to different modes */
2083                                                 have_some = 0;
2084                                                 break;
2085                                         }
2086                                         pred_bl->avail = e;
2087                                         have_some      = 1;
2088                                         DB((dbg, LEVEL_3, "%+F is available for %+F in predecessor %+F\n", e->node, op->node, pred));
2089                                         if (first == NULL)
2090                                                 first = e->node;
2091                                         else if (first != e->node)
2092                                                 all_same = 0;
2093                                 }
2094                         }
2095                         if (have_some && !all_same) {
2096                                 ir_mode *mode = op->value.mode;
2097                                 ir_node **in, *phi;
2098                                 memop_t *phi_op;
2099
2100                                 NEW_ARR_A(ir_node *, in, n);
2101
2102                                 for (i = n - 1; i >= 0; --i) {
2103                                         ir_node *pred    = get_Block_cfgpred_block(block, i);
2104                                         block_t *pred_bl = get_block_entry(pred);
2105
2106                                         if (pred_bl->avail == NULL) {
2107                                                 /* create a new Load here and make to make it fully redundant */
2108                                                 dbg_info *db       = get_irn_dbg_info(op->node);
2109                                                 ir_node  *last_mem = find_last_memory(pred_bl);
2110                                                 ir_node  *load, *def, *adr;
2111                                                 memop_t  *new_op;
2112
2113                                                 assert(last_mem != NULL);
2114                                                 adr  = phi_translate(op->value.address, block, i);
2115                                                 load = new_rd_Load(db, pred, last_mem, adr, mode, cons_none);
2116                                                 def  = new_r_Proj(pred, load, mode, pn_Load_res);
2117                                                 DB((dbg, LEVEL_1, "Created new %+F in %+F for party redundant %+F\n", load, pred, op->node));
2118
2119                                                 new_op                = alloc_memop(load);
2120                                                 new_op->mem           = new_r_Proj(pred, load, mode_M, pn_Load_M);
2121                                                 new_op->value.address = adr;
2122                                                 new_op->value.id      = op->value.id;
2123                                                 new_op->value.mode    = mode;
2124                                                 new_op->value.value   = def;
2125
2126                                                 new_op->projs[pn_Load_M]   = new_op->mem;
2127                                                 new_op->projs[pn_Load_res] = def;
2128
2129                                                 new_op->prev = pred_bl->memop_backward;
2130                                                 if (pred_bl->memop_backward != NULL)
2131                                                         pred_bl->memop_backward->next = new_op;
2132
2133                                                 pred_bl->memop_backward = new_op;
2134
2135                                                 if (pred_bl->memop_forward == NULL)
2136                                                         pred_bl->memop_forward = new_op;
2137
2138                                                 if (get_nodes_block(last_mem) == pred) {
2139                                                         /* We have add a new last memory op in pred block.
2140                                                            If pred had already a last mem, reroute all memory
2141                                                            users. */
2142                                                         reroute_all_mem_users(last_mem, new_op->mem);
2143                                                 } else {
2144                                                         /* reroute only those memory going through the pre block */
2145                                                         reroute_mem_through(last_mem, new_op->mem, pred);
2146                                                 }
2147
2148                                                 /* we added this load at the end, so it will be avail anyway */
2149                                                 add_memop_avail(pred_bl, new_op);
2150                                                 pred_bl->avail = new_op;
2151                                         }
2152                                         in[i] = conv_to(pred_bl->avail->value.value, mode);
2153                                 }
2154                                 phi = new_r_Phi(block, n, in, mode);
2155                                 DB((dbg, LEVEL_1, "Created new %+F in %+F for now redundant %+F\n", phi, block, op->node));
2156
2157                                 phi_op = clone_memop_phi(op, phi);
2158                                 add_memop(phi_op);
2159                         }
2160                 }
2161         }
2162
2163         /* recalculate avail by gen and kill */
2164         calc_gen_kill_avail(bl);
2165
2166         /* always update the map after gen/kill, as values might have been changed due to RAR/WAR/WAW */
2167         memcpy(bl->id_2_memop_avail, env.curr_id_2_memop, env.rbs_size * sizeof(env.curr_id_2_memop[0]));
2168
2169         if (!rbitset_equal(bl->avail_out, env.curr_set, env.rbs_size)) {
2170                 /* the avail set has changed */
2171                 rbitset_copy(bl->avail_out, env.curr_set, env.rbs_size);
2172                 dump_curr(bl, "Avail_out*");
2173                 return 1;
2174         }
2175         dump_curr(bl, "Avail_out");
2176         return 0;
2177 }  /* insert_Load */
2178
2179 /**
2180  * Insert Loads upwards.
2181  */
2182 static void insert_Loads_upwards(void)
2183 {
2184         int i, need_iter;
2185         block_t *bl;
2186
2187         /* recalculate antic_out and insert Loads */
2188         DB((dbg, LEVEL_2, "Inserting Loads\n"));
2189
2190         i = 0;
2191         do {
2192                 DB((dbg, LEVEL_2, "Iteration %d:\n=========\n", i));
2193
2194                 need_iter = 0;
2195
2196                 /* over all blocks in reverse post order, skip the start block */
2197                 for (bl = env.forward->forward_next; bl != NULL; bl = bl->forward_next) {
2198                         need_iter |= insert_Load(bl);
2199                 }
2200                 ++i;
2201         } while (need_iter);
2202
2203         DB((dbg, LEVEL_2, "Finished Load inserting after %d iterations\n", i));
2204 }  /* insert_Loads_upwards */
2205
2206 /**
2207  * Kill unreachable control flow.
2208  *
2209  * @param irg  the graph to operate on
2210  */
2211 static void kill_unreachable_blocks(ir_graph *irg)
2212 {
2213         block_t *bl;
2214         ir_node **ins;
2215         int     changed = 0;
2216
2217         NEW_ARR_A(ir_node *, ins, env.max_cfg_preds);
2218
2219         for (bl = env.forward; bl != NULL; bl = bl->forward_next) {
2220                 ir_node *block = bl->block;
2221                 int     i, j, k, n;
2222
2223                 assert(get_Block_mark(block));
2224
2225                 n = get_Block_n_cfgpreds(block);
2226
2227                 for (i = j = 0; i < n; ++i) {
2228                         ir_node *pred = get_Block_cfgpred(block, i);
2229                         ir_node *pred_bl;
2230
2231                         if (is_Bad(pred))
2232                                 continue;
2233
2234                         pred_bl = get_nodes_block(skip_Proj(pred));
2235                         if (! get_Block_mark(pred_bl))
2236                                 continue;
2237
2238                         ins[j++] = pred;
2239                 }
2240                 if (j != n) {
2241                         ir_node *phi, *next;
2242
2243                         /* some unreachable blocks detected */
2244                         changed = 1;
2245
2246                         DB((dbg, LEVEL_1, "Killing dead block predecessors on %+F\n", block));
2247
2248                         set_irn_in(block, j, ins);
2249
2250                         /* shorten all Phi nodes */
2251                         for (phi = get_Block_phis(block); phi != NULL; phi = next) {
2252                                 next = get_Phi_next(phi);
2253
2254                                 for (i = k = 0; i < n; ++i) {
2255                                         ir_node *pred = get_Block_cfgpred_block(block, i);
2256
2257                                         if (is_Bad(pred))
2258                                                 continue;
2259
2260                                         if (! get_Block_mark(pred))
2261                                                 continue;
2262
2263                                         ins[k++] = get_Phi_pred(phi, i);
2264                                 }
2265                                 if (k == 1)
2266                                         exchange(phi, ins[0]);
2267                                 else
2268                                         set_irn_in(phi, k, ins);
2269                         }
2270                 }
2271
2272         }
2273
2274         if (changed) {
2275                 /* kick keep alives */
2276                 ir_node *end = get_irg_end(irg);
2277                 int     i, j, n = get_End_n_keepalives(end);
2278
2279                 NEW_ARR_A(ir_node *, ins, n);
2280
2281                 for (i = j = 0; i < n; ++i) {
2282                         ir_node *ka = get_End_keepalive(end, i);
2283                         ir_node *ka_bl;
2284
2285                         if (is_Bad(ka))
2286                                 continue;
2287                         if (is_Block(ka))
2288                                 ka_bl = ka;
2289                         else
2290                                 ka_bl = get_nodes_block(skip_Proj(ka));
2291                         if (get_Block_mark(ka_bl))
2292                                 ins[j++] = ka;
2293                 }
2294                 if (j != n)
2295                         set_End_keepalives(end, j, ins);
2296
2297                 free_irg_outs(irg);
2298
2299                 /* this transformation do NOT invalidate the dominance */
2300         }
2301 }  /* kill_unreachable_blocks */
2302
2303 int opt_ldst(ir_graph *irg)
2304 {
2305         block_t  *bl;
2306         ir_graph *rem = current_ir_graph;
2307
2308         current_ir_graph = irg;
2309
2310         FIRM_DBG_REGISTER(dbg, "firm.opt.ldst");
2311 //      firm_dbg_set_mask(dbg, -1);
2312
2313         DB((dbg, LEVEL_1, "\nDoing Load/Store optimization on %+F\n", irg));
2314
2315         /* we need landing pads */
2316         remove_critical_cf_edges(irg);
2317
2318 //      dump_ir_block_graph(irg, "-XXX");
2319
2320         if (get_opt_alias_analysis()) {
2321                 assure_irg_entity_usage_computed(irg);
2322                 assure_irp_globals_entity_usage_computed();
2323         }
2324
2325         obstack_init(&env.obst);
2326         ir_nodemap_init(&env.adr_map);
2327
2328         env.forward       = NULL;
2329         env.backward      = NULL;
2330         env.curr_adr_id   = 0;
2331         env.n_mem_ops     = 0;
2332         env.max_cfg_preds = 0;
2333         env.changed       = 0;
2334         env.start_bl      = get_irg_start_block(irg);
2335         env.end_bl        = get_irg_end_block(irg);
2336 #ifdef DEBUG_libfirm
2337         env.id_2_address  = NEW_ARR_F(ir_node *, 0);
2338 #endif
2339
2340         assure_irg_outs(irg);
2341
2342         ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_BLOCK_MARK);
2343
2344         /* first step: allocate block entries. Note that some blocks might be
2345            unreachable here. Using the normal walk ensures that ALL blocks are initialized. */
2346         irg_walk_graph(irg, prepare_blocks, link_phis, NULL);
2347
2348         /* produce an inverse post-order list for the CFG: this links only reachable
2349            blocks */
2350         irg_out_block_walk(get_irg_start_block(irg), NULL, inverse_post_order, NULL);
2351
2352         if (! get_Block_mark(env.end_bl)) {
2353                 /*
2354                  * The end block is NOT reachable due to endless loops
2355                  * or no_return calls.
2356                  * Place the end block last.
2357                  * env.backward points to the last block in the list for this purpose.
2358                  */
2359                 env.backward->forward_next = get_block_entry(env.end_bl);
2360
2361                 set_Block_mark(env.end_bl, 1);
2362         }
2363
2364         /* KILL unreachable blocks: these disturb the data flow analysis */
2365         kill_unreachable_blocks(irg);
2366
2367         assure_doms(irg);
2368
2369         /* second step: find and sort all memory ops */
2370         walk_memory_irg(irg, collect_memops, NULL, NULL);
2371
2372 #ifdef DEBUG_libfirm
2373         /* check that the backward map is correct */
2374         assert((unsigned)ARR_LEN(env.id_2_address) == env.curr_adr_id);
2375 #endif
2376
2377         if (env.n_mem_ops == 0) {
2378                 /* no memory ops */
2379                 goto end;
2380         }
2381
2382         /* create the backward links. */
2383         env.backward = NULL;
2384         irg_block_walk_graph(irg, NULL, collect_backward, NULL);
2385
2386         /* link the end block in */
2387         bl = get_block_entry(env.end_bl);
2388         bl->backward_next = env.backward;
2389         env.backward      = bl;
2390
2391         /* check that we really start with the start / end block */
2392         assert(env.forward->block  == env.start_bl);
2393         assert(env.backward->block == env.end_bl);
2394
2395         /* create address sets: for now, only the existing addresses are allowed plus one
2396            needed for the sentinel */
2397         env.rbs_size = env.curr_adr_id + 1;
2398
2399         /* create the current set */
2400         env.curr_set = rbitset_obstack_alloc(&env.obst, env.rbs_size);
2401         rbitset_set(env.curr_set, env.rbs_size - 1);
2402         env.curr_id_2_memop = NEW_ARR_D(memop_t *, &env.obst, env.rbs_size);
2403         memset(env.curr_id_2_memop, 0, env.rbs_size * sizeof(env.curr_id_2_memop[0]));
2404
2405         for (bl = env.forward; bl != NULL; bl = bl->forward_next) {
2406                 /* set sentinel bits */
2407                 bl->avail_out  = rbitset_obstack_alloc(&env.obst, env.rbs_size);
2408                 rbitset_set(bl->avail_out, env.rbs_size - 1);
2409
2410                 bl->id_2_memop_avail = NEW_ARR_D(memop_t *, &env.obst, env.rbs_size);
2411                 memset(bl->id_2_memop_avail, 0, env.rbs_size * sizeof(bl->id_2_memop_avail[0]));
2412
2413                 bl->anticL_in  = rbitset_obstack_alloc(&env.obst, env.rbs_size);
2414                 rbitset_set(bl->anticL_in, env.rbs_size - 1);
2415
2416                 bl->id_2_memop_antic = NEW_ARR_D(memop_t *, &env.obst, env.rbs_size);
2417                 memset(bl->id_2_memop_antic, 0, env.rbs_size * sizeof(bl->id_2_memop_antic[0]));
2418         }
2419
2420 //      dump_block_list(&env);
2421         (void) dump_block_list;
2422
2423         calcAvail();
2424         calcAntic();
2425
2426         insert_Loads_upwards();
2427
2428         if (env.changed) {
2429                 /* over all blocks in reverse post order */
2430                 for (bl = env.forward; bl != NULL; bl = bl->forward_next) {
2431                         do_replacements(bl);
2432                 }
2433
2434                 /* not only invalidate but free them. We might allocate new out arrays
2435                    on our obstack which will be deleted yet. */
2436                 free_irg_outs(irg);
2437                 set_irg_entity_usage_state(irg, ir_entity_usage_not_computed);
2438         }
2439 end:
2440
2441         ir_free_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_BLOCK_MARK);
2442         ir_nodemap_destroy(&env.adr_map);
2443         obstack_free(&env.obst, NULL);
2444
2445 //      dump_ir_block_graph(irg, "-YYY");
2446
2447 #ifdef DEBUG_libfirm
2448         DEL_ARR_F(env.id_2_address);
2449 #endif
2450
2451         current_ir_graph = rem;
2452         return env.changed != 0;
2453 }  /* opt_ldst */
2454
2455 ir_graph_pass_t *opt_ldst_pass(const char *name)
2456 {
2457         return def_graph_pass_ret(name ? name : "ldst_df", opt_ldst);
2458 }  /* opt_ldst_pass */