fix cvt emitter
[libfirm] / ir / be / ia32 / ia32_optimize.c
1 /**
2  * Project:     libFIRM
3  * File name:   ir/be/ia32/ia32_optimize.c
4  * Purpose:     Implements several optimizations for IA32
5  * Author:      Christian Wuerdig
6  * CVS-ID:      $Id$
7  * Copyright:   (c) 2006 Universitaet Karlsruhe
8  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
9  */
10
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 #include "irnode.h"
16 #include "irprog_t.h"
17 #include "ircons.h"
18 #include "firm_types.h"
19 #include "iredges.h"
20 #include "tv.h"
21 #include "irgmod.h"
22 #include "irgwalk.h"
23 #include "height.h"
24 #include "irbitset.h"
25
26 #include "../be_t.h"
27 #include "../beabi.h"
28 #include "../benode_t.h"
29 #include "../besched_t.h"
30
31 #include "ia32_new_nodes.h"
32 #include "bearch_ia32_t.h"
33 #include "gen_ia32_regalloc_if.h"     /* the generated interface (register type and class defenitions) */
34 #include "ia32_transform.h"
35 #include "ia32_dbg_stat.h"
36 #include "ia32_util.h"
37
38 #define AGGRESSIVE_AM
39
40 typedef enum {
41         IA32_AM_CAND_NONE  = 0,  /**< no addressmode possible with irn inputs */
42         IA32_AM_CAND_LEFT  = 1,  /**< addressmode possible with left input */
43         IA32_AM_CAND_RIGHT = 2,  /**< addressmode possible with right input */
44         IA32_AM_CAND_BOTH  = 3   /**< addressmode possible with both inputs */
45 } ia32_am_cand_t;
46
47 typedef int is_op_func_t(const ir_node *n);
48 typedef ir_node *load_func_t(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, ir_node *mem);
49
50 /**
51  * checks if a node represents the NOREG value
52  */
53 static INLINE int be_is_NoReg(ia32_code_gen_t *cg, const ir_node *irn) {
54         return irn == cg->noreg_gp || irn == cg->noreg_xmm || irn == cg->noreg_vfp;
55 }
56
57 void ia32_pre_transform_phase(ia32_code_gen_t *cg) {
58         /*
59                 We need to transform the consts twice:
60                 - the psi condition tree transformer needs existing constants to be ia32 constants
61                 - the psi condition tree transformer inserts new firm constants which need to be transformed
62         */
63         //ia32_transform_all_firm_consts(cg);
64         irg_walk_graph(cg->irg, NULL, ia32_transform_psi_cond_tree, cg);
65         //ia32_transform_all_firm_consts(cg);
66 }
67
68 /********************************************************************************************************
69  *  _____                _           _         ____        _   _           _          _   _
70  * |  __ \              | |         | |       / __ \      | | (_)         (_)        | | (_)
71  * | |__) |__  ___ _ __ | |__   ___ | | ___  | |  | |_ __ | |_ _ _ __ ___  _ ______ _| |_ _  ___  _ __
72  * |  ___/ _ \/ _ \ '_ \| '_ \ / _ \| |/ _ \ | |  | | '_ \| __| | '_ ` _ \| |_  / _` | __| |/ _ \| '_ \
73  * | |  |  __/  __/ |_) | | | | (_) | |  __/ | |__| | |_) | |_| | | | | | | |/ / (_| | |_| | (_) | | | |
74  * |_|   \___|\___| .__/|_| |_|\___/|_|\___|  \____/| .__/ \__|_|_| |_| |_|_/___\__,_|\__|_|\___/|_| |_|
75  *                | |                               | |
76  *                |_|                               |_|
77  ********************************************************************************************************/
78
79 /**
80  * NOTE: THESE PEEPHOLE OPTIMIZATIONS MUST BE CALLED AFTER SCHEDULING AND REGISTER ALLOCATION.
81  */
82
83 static int ia32_const_equal(const ir_node *n1, const ir_node *n2) {
84         if(get_ia32_immop_type(n1) != get_ia32_immop_type(n2))
85                 return 0;
86
87         if(get_ia32_immop_type(n1) == ia32_ImmConst) {
88                 return get_ia32_Immop_tarval(n1) == get_ia32_Immop_tarval(n2);
89         } else if(get_ia32_immop_type(n1) == ia32_ImmSymConst) {
90                 return get_ia32_Immop_symconst(n1) == get_ia32_Immop_symconst(n2);
91         }
92
93         assert(get_ia32_immop_type(n1) == ia32_ImmNone);
94         return 1;
95 }
96
97 /**
98  * Checks for potential CJmp/CJmpAM optimization candidates.
99  */
100 static ir_node *ia32_determine_cjmp_cand(ir_node *irn, is_op_func_t *is_op_func) {
101         ir_node *cand = NULL;
102         ir_node *prev = sched_prev(irn);
103
104         if (is_Block(prev)) {
105                 if (get_Block_n_cfgpreds(prev) == 1)
106                         prev = get_Block_cfgpred(prev, 0);
107                 else
108                         prev = NULL;
109         }
110
111         /* The predecessor must be a ProjX. */
112         if (prev && is_Proj(prev) && get_irn_mode(prev) == mode_X) {
113                 prev = get_Proj_pred(prev);
114
115                 if (is_op_func(prev))
116                         cand = prev;
117         }
118
119         return cand;
120 }
121
122 static int is_TestJmp_cand(const ir_node *irn) {
123         return is_ia32_TestJmp(irn) || is_ia32_And(irn);
124 }
125
126 /**
127  * Checks if two consecutive arguments of cand matches
128  * the two arguments of irn (TestJmp).
129  */
130 static int is_TestJmp_replacement(ir_node *cand, ir_node *irn) {
131         ir_node *in1       = get_irn_n(irn, 0);
132         ir_node *in2       = get_irn_n(irn, 1);
133         int      i, n      = get_irn_arity(cand);
134         int      same_args = 0;
135
136         for (i = 0; i < n - 1; i++) {
137                 if (get_irn_n(cand, i)     == in1 &&
138                         get_irn_n(cand, i + 1) == in2)
139                 {
140                         same_args = 1;
141                         break;
142                 }
143         }
144
145         if (!same_args)
146                 return 0;
147
148         return ia32_const_equal(cand, irn);
149 }
150
151 /**
152  * Tries to replace a TestJmp by a CJmp or CJmpAM (in case of And)
153  */
154 static void ia32_optimize_TestJmp(ir_node *irn, ia32_code_gen_t *cg) {
155         ir_node *cand    = ia32_determine_cjmp_cand(irn, is_TestJmp_cand);
156         int      replace = 0;
157
158         /* we found a possible candidate */
159         replace = cand ? is_TestJmp_replacement(cand, irn) : 0;
160
161         if (replace) {
162                 DBG((cg->mod, LEVEL_1, "replacing %+F by ", irn));
163
164                 if (is_ia32_And(cand))
165                         set_irn_op(irn, op_ia32_CJmpAM);
166                 else
167                         set_irn_op(irn, op_ia32_CJmp);
168
169                 DB((cg->mod, LEVEL_1, "%+F\n", irn));
170         }
171 }
172
173 static int is_CondJmp_cand(const ir_node *irn) {
174         return is_ia32_CondJmp(irn) || is_ia32_Sub(irn);
175 }
176
177 /**
178  * Checks if the arguments of cand are the same of irn.
179  */
180 static int is_CondJmp_replacement(ir_node *cand, ir_node *irn) {
181         int i, arity;
182
183         arity = get_irn_arity(cand);
184         for (i = 0; i < arity; i++) {
185                 if (get_irn_n(cand, i) != get_irn_n(irn, i)) {
186                         return 0;
187                 }
188         }
189
190         return ia32_const_equal(cand, irn);
191 }
192
193 /**
194  * Tries to replace a CondJmp by a CJmpAM
195  */
196 static void ia32_optimize_CondJmp(ir_node *irn, ia32_code_gen_t *cg) {
197         ir_node *cand    = ia32_determine_cjmp_cand(irn, is_CondJmp_cand);
198         int      replace = 0;
199
200         /* we found a possible candidate */
201         replace = cand ? is_CondJmp_replacement(cand, irn) : 0;
202
203         if (replace) {
204                 DBG((cg->mod, LEVEL_1, "replacing %+F by ", irn));
205                 DBG_OPT_CJMP(irn);
206
207                 set_irn_op(irn, op_ia32_CJmpAM);
208
209                 DB((cg->mod, LEVEL_1, "%+F\n", irn));
210         }
211 }
212
213 // only optimize up to 48 stores behind IncSPs
214 #define MAXPUSH_OPTIMIZE        48
215
216 /**
217  * Tries to create pushs from IncSP,Store combinations
218  */
219 static void ia32_create_Pushs(ir_node *irn, ia32_code_gen_t *cg) {
220         int i;
221         int offset;
222         ir_node *node;
223         ir_node *stores[MAXPUSH_OPTIMIZE];
224         ir_node *block = get_nodes_block(irn);
225         ir_graph *irg = cg->irg;
226         ir_node *curr_sp;
227         ir_mode *spmode = get_irn_mode(irn);
228
229         memset(stores, 0, sizeof(stores));
230
231         assert(be_is_IncSP(irn));
232
233         offset = be_get_IncSP_offset(irn);
234         if(offset < 4)
235                 return;
236
237         /*
238          * We first walk the schedule after the IncSP node as long as we find
239          * suitable stores that could be transformed to a push.
240          * We save them into the stores array which is sorted by the frame offset/4
241          * attached to the node
242          */
243         for(node = sched_next(irn); !sched_is_end(node); node = sched_next(node)) {
244                 ir_node *mem;
245                 int offset;
246                 int storeslot;
247
248                 // it has to be a store
249                 if(!is_ia32_Store(node))
250                         break;
251
252                 // it has to use our sp value
253                 if(get_irn_n(node, 0) != irn)
254                         continue;
255                 // store has to be attached to NoMem
256                 mem = get_irn_n(node, 3);
257                 if(!is_NoMem(mem)) {
258                         continue;
259                 }
260
261                 if( (get_ia32_am_flavour(node) & ia32_am_IS) != 0)
262                         break;
263
264                 offset = get_ia32_am_offs_int(node);
265
266                 storeslot = offset / 4;
267                 if(storeslot >= MAXPUSH_OPTIMIZE)
268                         continue;
269
270                 // storing into the same slot twice is bad (and shouldn't happen...)
271                 if(stores[storeslot] != NULL)
272                         break;
273
274                 // storing at half-slots is bad
275                 if(offset % 4 != 0)
276                         break;
277
278                 stores[storeslot] = node;
279         }
280
281         curr_sp = get_irn_n(irn, 0);
282
283         // walk the stores in inverse order and create pushs for them
284         i = (offset / 4) - 1;
285         if(i >= MAXPUSH_OPTIMIZE) {
286                 i = MAXPUSH_OPTIMIZE - 1;
287         }
288
289         for( ; i >= 0; --i) {
290                 const arch_register_t *spreg;
291                 ir_node *push;
292                 ir_node *val, *mem, *mem_proj;
293                 ir_node *store = stores[i];
294                 ir_node *noreg = ia32_new_NoReg_gp(cg);
295
296                 if(store == NULL || is_Bad(store))
297                         break;
298
299                 val = get_irn_n(store, 2);
300                 mem = get_irn_n(store, 3);
301                 spreg = arch_get_irn_register(cg->arch_env, curr_sp);
302
303                 // create a push
304                 push = new_rd_ia32_Push(NULL, irg, block, noreg, noreg, val, curr_sp, mem);
305
306                 set_ia32_am_support(push, ia32_am_Source);
307                 copy_ia32_Immop_attr(push, store);
308
309                 sched_add_before(irn, push);
310
311                 // create stackpointer proj
312                 curr_sp = new_r_Proj(irg, block, push, spmode, pn_ia32_Push_stack);
313                 arch_set_irn_register(cg->arch_env, curr_sp, spreg);
314                 sched_add_before(irn, curr_sp);
315
316                 // create memory proj
317                 mem_proj = new_r_Proj(irg, block, push, mode_M, pn_ia32_Push_M);
318                 sched_add_before(irn, mem_proj);
319
320                 // use the memproj now
321                 exchange(store, mem_proj);
322
323                 // we can remove the store now
324                 sched_remove(store);
325
326                 offset -= 4;
327         }
328
329         be_set_IncSP_offset(irn, offset);
330
331         // can we remove the IncSP now?
332         if(offset == 0) {
333                 const ir_edge_t *edge, *next;
334
335                 foreach_out_edge_safe(irn, edge, next) {
336                         ir_node *arg = get_edge_src_irn(edge);
337                         int pos = get_edge_src_pos(edge);
338
339                         set_irn_n(arg, pos, curr_sp);
340                 }
341
342                 set_irn_n(irn, 0, new_Bad());
343                 sched_remove(irn);
344         } else {
345                 set_irn_n(irn, 0, curr_sp);
346         }
347 }
348
349 #if 0
350 /**
351  * Tries to optimize two following IncSP.
352  */
353 static void ia32_optimize_IncSP(ir_node *irn, ia32_code_gen_t *cg) {
354         ir_node *prev = be_get_IncSP_pred(irn);
355         int real_uses = get_irn_n_edges(prev);
356
357         if (be_is_IncSP(prev) && real_uses == 1) {
358                 /* first IncSP has only one IncSP user, kill the first one */
359                 int prev_offs = be_get_IncSP_offset(prev);
360                 int curr_offs = be_get_IncSP_offset(irn);
361
362                 be_set_IncSP_offset(prev, prev_offs + curr_offs);
363
364                 /* Omit the optimized IncSP */
365                 be_set_IncSP_pred(irn, be_get_IncSP_pred(prev));
366
367                 set_irn_n(prev, 0, new_Bad());
368                 sched_remove(prev);
369         }
370 }
371 #endif
372
373 /**
374  * Performs Peephole Optimizations.
375  */
376 static void ia32_peephole_optimize_node(ir_node *irn, void *env) {
377         ia32_code_gen_t *cg = env;
378
379         /* AMD CPUs want explicit compare before conditional jump  */
380         if (! ARCH_AMD(cg->opt_arch)) {
381                 if (is_ia32_TestJmp(irn))
382                         ia32_optimize_TestJmp(irn, cg);
383                 else if (is_ia32_CondJmp(irn))
384                         ia32_optimize_CondJmp(irn, cg);
385         }
386
387         if (be_is_IncSP(irn)) {
388                 // optimize_IncSP doesn't respect dependency edges yet...
389                 //ia32_optimize_IncSP(irn, cg);
390
391                 if (cg->opt & IA32_OPT_PUSHARGS)
392                         ia32_create_Pushs(irn, cg);
393         }
394 }
395
396 void ia32_peephole_optimization(ir_graph *irg, ia32_code_gen_t *cg) {
397         irg_walk_graph(irg, ia32_peephole_optimize_node, NULL, cg);
398 }
399
400 /******************************************************************
401  *              _     _                   __  __           _
402  *     /\      | |   | |                 |  \/  |         | |
403  *    /  \   __| | __| |_ __ ___  ___ ___| \  / | ___   __| | ___
404  *   / /\ \ / _` |/ _` | '__/ _ \/ __/ __| |\/| |/ _ \ / _` |/ _ \
405  *  / ____ \ (_| | (_| | | |  __/\__ \__ \ |  | | (_) | (_| |  __/
406  * /_/    \_\__,_|\__,_|_|  \___||___/___/_|  |_|\___/ \__,_|\___|
407  *
408  ******************************************************************/
409
410 typedef struct {
411         ia32_code_gen_t *cg;
412         heights_t       *h;
413 } ia32_am_opt_env_t;
414
415 static int node_is_ia32_comm(const ir_node *irn) {
416         return is_ia32_irn(irn) ? is_ia32_commutative(irn) : 0;
417 }
418
419 static int ia32_get_irn_n_edges(const ir_node *irn) {
420         const ir_edge_t *edge;
421         int cnt = 0;
422
423         foreach_out_edge(irn, edge) {
424                 cnt++;
425         }
426
427         return cnt;
428 }
429
430 /**
431  * Determines if pred is a Proj and if is_op_func returns true for it's predecessor.
432  *
433  * @param pred       The node to be checked
434  * @param is_op_func The check-function
435  * @return 1 if conditions are fulfilled, 0 otherwise
436  */
437 static int pred_is_specific_node(const ir_node *pred, is_op_func_t *is_op_func) {
438         return is_op_func(pred);
439 }
440
441 /**
442  * Determines if pred is a Proj and if is_op_func returns true for it's predecessor
443  * and if the predecessor is in block bl.
444  *
445  * @param bl         The block
446  * @param pred       The node to be checked
447  * @param is_op_func The check-function
448  * @return 1 if conditions are fulfilled, 0 otherwise
449  */
450 static int pred_is_specific_nodeblock(const ir_node *bl, const ir_node *pred,
451         int (*is_op_func)(const ir_node *n))
452 {
453         if (is_Proj(pred)) {
454                 pred = get_Proj_pred(pred);
455                 if ((bl == get_nodes_block(pred)) && is_op_func(pred)) {
456                         return 1;
457                 }
458         }
459
460         return 0;
461 }
462
463 /**
464  * Checks if irn is a candidate for address calculation. We avoid transforming
465  * adds to leas if they have a load as pred, because then we can use AM mode
466  * for the add later.
467  *
468  * - none of the operand must be a Load  within the same block OR
469  * - all Loads must have more than one user                    OR
470  *
471  * @param block   The block the Loads must/mustnot be in
472  * @param irn     The irn to check
473  * return 1 if irn is a candidate, 0 otherwise
474  */
475 static int is_addr_candidate(const ir_node *irn) {
476 #ifndef AGGRESSIVE_AM
477         const ir_node *block = get_nodes_block(irn);
478         ir_node *left, *right;
479         int      n;
480
481         left  = get_irn_n(irn, 2);
482         right = get_irn_n(irn, 3);
483
484         if (pred_is_specific_nodeblock(block, left, is_ia32_Ld)) {
485                 n         = ia32_get_irn_n_edges(left);
486                 /* load with only one user: don't create LEA */
487                 if(n == 1)
488                         return 0;
489         }
490
491         if (pred_is_specific_nodeblock(block, right, is_ia32_Ld)) {
492                 n         = ia32_get_irn_n_edges(right);
493                 if(n == 1)
494                         return 0;
495         }
496 #endif
497
498         return 1;
499 }
500
501 /**
502  * Checks if irn is a candidate for address mode.
503  *
504  * address mode (AM):
505  * - at least one operand has to be a Load within the same block AND
506  * - the load must not have other users than the irn             AND
507  * - the irn must not have a frame entity set
508  *
509  * @param cg          The ia32 code generator
510  * @param h           The height information of the irg
511  * @param block       The block the Loads must/mustnot be in
512  * @param irn         The irn to check
513  * return 0 if irn is no candidate, 1 if left load can be used, 2 if right one, 3 for both
514  */
515 static ia32_am_cand_t is_am_candidate(ia32_code_gen_t *cg, heights_t *h, const ir_node *block, ir_node *irn) {
516         ir_node *in, *load, *other, *left, *right;
517         int      is_cand = 0, cand;
518         int arity;
519
520         if (is_ia32_Ld(irn) || is_ia32_St(irn) || is_ia32_Store8Bit(irn) || is_ia32_vfild(irn) || is_ia32_vfist(irn) ||
521                 is_ia32_GetST0(irn) || is_ia32_SetST0(irn) || is_ia32_xStoreSimple(irn))
522                 return 0;
523
524         left  = get_irn_n(irn, 2);
525         arity = get_irn_arity(irn);
526         assert(arity == 5 || arity == 4);
527         if(arity == 5) {
528                 /* binary op */
529                 right = get_irn_n(irn, 3);
530         } else {
531                 /* unary op */
532                 right = left;
533         }
534
535         in = left;
536
537         if (pred_is_specific_nodeblock(block, in, is_ia32_Ld)) {
538 #ifndef AGGRESSIVE_AM
539                 int n;
540                 n         = ia32_get_irn_n_edges(in);
541                 is_cand   = (n == 1) ? 1 : is_cand;  /* load with more than one user: no AM */
542 #else
543                 is_cand   = 1;
544 #endif
545
546                 load  = get_Proj_pred(in);
547                 other = right;
548
549                 /* 8bit Loads are not supported (for binary ops),
550                  * they cannot be used with every register */
551                 if (get_irn_arity(irn) != 4 && get_mode_size_bits(get_ia32_ls_mode(load)) < 16) {
552                         assert(get_irn_arity(irn) == 5);
553                         is_cand = 0;
554                 }
555
556                 /* If there is a data dependency of other irn from load: cannot use AM */
557                 if (is_cand && get_nodes_block(other) == block) {
558                         other   = skip_Proj(other);
559                         is_cand = heights_reachable_in_block(h, other, load) ? 0 : is_cand;
560                         /* this could happen in loops */
561                         is_cand = heights_reachable_in_block(h, load, irn) ? 0 : is_cand;
562                 }
563         }
564
565         cand    = is_cand ? IA32_AM_CAND_LEFT : IA32_AM_CAND_NONE;
566         in      = right;
567         is_cand = 0;
568
569         if (pred_is_specific_nodeblock(block, in, is_ia32_Ld)) {
570 #ifndef AGGRESSIVE_AM
571                 int n;
572                 n         = ia32_get_irn_n_edges(in);
573                 is_cand   = (n == 1) ? 1 : is_cand;  /* load with more than one user: no AM */
574 #else
575                 is_cand = 1;
576 #endif
577
578                 load  = get_Proj_pred(in);
579                 other = left;
580
581                 /* 8bit Loads are not supported, they cannot be used with every register */
582                 if (get_mode_size_bits(get_ia32_ls_mode(load)) < 16)
583                         is_cand = 0;
584
585                 /* If there is a data dependency of other irn from load: cannot use load */
586                 if (is_cand && get_nodes_block(other) == block) {
587                         other   = skip_Proj(other);
588                         is_cand = heights_reachable_in_block(h, other, load) ? 0 : is_cand;
589                         /* this could happen in loops */
590                         is_cand = heights_reachable_in_block(h, load, irn) ? 0 : is_cand;
591                 }
592         }
593
594         cand = is_cand ? (cand | IA32_AM_CAND_RIGHT) : cand;
595
596         /* if the irn has a frame entity: we do not use address mode */
597         return get_ia32_frame_ent(irn) ? IA32_AM_CAND_NONE : cand;
598 }
599
600 /**
601  * Compares the base and index addr and the load/store entities
602  * and returns 1 if they are equal.
603  */
604 static int load_store_addr_is_equal(const ir_node *load, const ir_node *store,
605                                                                         const ir_node *addr_b, const ir_node *addr_i)
606 {
607         if(get_irn_n(load, 0) != addr_b)
608                 return 0;
609         if(get_irn_n(load, 1) != addr_i)
610                 return 0;
611
612         if(get_ia32_frame_ent(load) != get_ia32_frame_ent(store))
613                 return 0;
614
615         if(get_ia32_am_sc(load) != get_ia32_am_sc(store))
616                 return 0;
617         if(is_ia32_am_sc_sign(load) != is_ia32_am_sc_sign(store))
618                 return 0;
619         if(get_ia32_am_offs_int(load) != get_ia32_am_offs_int(store))
620                 return 0;
621         if(get_ia32_ls_mode(load) != get_ia32_ls_mode(store))
622                 return 0;
623
624         return 1;
625 }
626
627 typedef enum _ia32_take_lea_attr {
628         IA32_LEA_ATTR_NONE  = 0,
629         IA32_LEA_ATTR_BASE  = (1 << 0),
630         IA32_LEA_ATTR_INDEX = (1 << 1),
631         IA32_LEA_ATTR_OFFS  = (1 << 2),
632         IA32_LEA_ATTR_SCALE = (1 << 3),
633         IA32_LEA_ATTR_AMSC  = (1 << 4),
634         IA32_LEA_ATTR_FENT  = (1 << 5)
635 } ia32_take_lea_attr;
636
637 /**
638  * Decides if we have to keep the LEA operand or if we can assimilate it.
639  */
640 static int do_new_lea(ir_node *irn, ir_node *base, ir_node *index, ir_node *lea,
641                 int have_am_sc, ia32_code_gen_t *cg)
642 {
643         ir_entity *irn_ent  = get_ia32_frame_ent(irn);
644         ir_entity *lea_ent  = get_ia32_frame_ent(lea);
645         int        ret_val  = 0;
646         int        is_noreg_base  = be_is_NoReg(cg, base);
647         int        is_noreg_index = be_is_NoReg(cg, index);
648         ia32_am_flavour_t am_flav = get_ia32_am_flavour(lea);
649
650         /* If the Add and the LEA both have a different frame entity set: keep */
651         if (irn_ent && lea_ent && (irn_ent != lea_ent))
652                 return IA32_LEA_ATTR_NONE;
653         else if (! irn_ent && lea_ent)
654                 ret_val |= IA32_LEA_ATTR_FENT;
655
656         /* If the Add and the LEA both have already an address mode symconst: keep */
657         if (have_am_sc && get_ia32_am_sc(lea))
658                 return IA32_LEA_ATTR_NONE;
659         else if (get_ia32_am_sc(lea))
660                 ret_val |= IA32_LEA_ATTR_AMSC;
661
662         /* Check the different base-index combinations */
663
664         if (! is_noreg_base && ! is_noreg_index) {
665                 /* Assimilate if base is the lea and the LEA is just a Base + Offset calculation */
666                 if ((base == lea) && ! (am_flav & ia32_I ? 1 : 0)) {
667                         if (am_flav & ia32_O)
668                                 ret_val |= IA32_LEA_ATTR_OFFS;
669
670                         ret_val |= IA32_LEA_ATTR_BASE;
671                 }
672                 else
673                         return IA32_LEA_ATTR_NONE;
674         }
675         else if (! is_noreg_base && is_noreg_index) {
676                 /* Base is set but index not */
677                 if (base == lea) {
678                         /* Base points to LEA: assimilate everything */
679                         if (am_flav & ia32_O)
680                                 ret_val |= IA32_LEA_ATTR_OFFS;
681                         if (am_flav & ia32_S)
682                                 ret_val |= IA32_LEA_ATTR_SCALE;
683                         if (am_flav & ia32_I)
684                                 ret_val |= IA32_LEA_ATTR_INDEX;
685
686                         ret_val |= IA32_LEA_ATTR_BASE;
687                 }
688                 else if (am_flav & ia32_B ? 0 : 1) {
689                         /* Base is not the LEA but the LEA is an index only calculation: assimilate */
690                         if (am_flav & ia32_O)
691                                 ret_val |= IA32_LEA_ATTR_OFFS;
692                         if (am_flav & ia32_S)
693                                 ret_val |= IA32_LEA_ATTR_SCALE;
694
695                         ret_val |= IA32_LEA_ATTR_INDEX;
696                 }
697                 else
698                         return IA32_LEA_ATTR_NONE;
699         }
700         else if (is_noreg_base && ! is_noreg_index) {
701                 /* Index is set but not base */
702                 if (index == lea) {
703                         /* Index points to LEA: assimilate everything */
704                         if (am_flav & ia32_O)
705                                 ret_val |= IA32_LEA_ATTR_OFFS;
706                         if (am_flav & ia32_S)
707                                 ret_val |= IA32_LEA_ATTR_SCALE;
708                         if (am_flav & ia32_B)
709                                 ret_val |= IA32_LEA_ATTR_BASE;
710
711                         ret_val |= IA32_LEA_ATTR_INDEX;
712                 }
713                 else if (am_flav & ia32_I ? 0 : 1) {
714                         /* Index is not the LEA but the LEA is a base only calculation: assimilate */
715                         if (am_flav & ia32_O)
716                                 ret_val |= IA32_LEA_ATTR_OFFS;
717                         if (am_flav & ia32_S)
718                                 ret_val |= IA32_LEA_ATTR_SCALE;
719
720                         ret_val |= IA32_LEA_ATTR_BASE;
721                 }
722                 else
723                         return IA32_LEA_ATTR_NONE;
724         }
725         else {
726                 assert(0 && "There must have been set base or index");
727         }
728
729         return ret_val;
730 }
731
732 /**
733  * Adds res before irn into schedule if irn was scheduled.
734  * @param irn  The schedule point
735  * @param res  The node to be scheduled
736  */
737 static INLINE void try_add_to_sched(ir_node *irn, ir_node *res) {
738         if (sched_is_scheduled(irn))
739                 sched_add_before(irn, res);
740 }
741
742 /**
743  * Removes node from schedule if it is not used anymore. If irn is a mode_T node
744  * all it's Projs are removed as well.
745  * @param irn  The irn to be removed from schedule
746  */
747 static INLINE void try_remove_from_sched(ir_node *node) {
748         int i, arity;
749
750         if(get_irn_mode(node) == mode_T) {
751                 const ir_edge_t *edge;
752                 foreach_out_edge(node, edge) {
753                         ir_node *proj = get_edge_src_irn(edge);
754                         try_remove_from_sched(proj);
755                 }
756         }
757
758         if(get_irn_n_edges(node) != 0)
759                 return;
760
761         if (sched_is_scheduled(node)) {
762                 sched_remove(node);
763         }
764
765         arity = get_irn_arity(node);
766         for(i = 0; i < arity; ++i) {
767                 set_irn_n(node, i, new_Bad());
768         }
769 }
770
771 /**
772  * Folds Add or Sub to LEA if possible
773  */
774 static ir_node *fold_addr(ia32_code_gen_t *cg, ir_node *irn) {
775         ir_graph   *irg        = get_irn_irg(irn);
776         dbg_info   *dbg        = get_irn_dbg_info(irn);
777         ir_node    *block      = get_nodes_block(irn);
778         ir_node    *res        = irn;
779         ir_node    *shift      = NULL;
780         ir_node    *lea_o      = NULL;
781         ir_node    *lea        = NULL;
782         long        offs       = 0;
783         long        offs_cnst  = 0;
784         long        offs_lea   = 0;
785         int         scale      = 0;
786         int         isadd      = 0;
787         int         dolea      = 0;
788         int         have_am_sc = 0;
789         int         am_sc_sign = 0;
790         ident      *am_sc      = NULL;
791         ir_entity  *lea_ent    = NULL;
792         ir_node    *noreg      = ia32_new_NoReg_gp(cg);
793         ir_node    *left, *right, *temp;
794         ir_node    *base, *index;
795         int consumed_left_shift;
796         ia32_am_flavour_t am_flav;
797         DEBUG_ONLY(firm_dbg_module_t *mod = cg->mod;)
798
799         if (is_ia32_Add(irn))
800                 isadd = 1;
801
802         left  = get_irn_n(irn, 2);
803         right = get_irn_n(irn, 3);
804
805         /* "normalize" arguments in case of add with two operands */
806         if  (isadd && ! be_is_NoReg(cg, right)) {
807                 /* put LEA == ia32_am_O as right operand */
808                 if (is_ia32_Lea(left) && get_ia32_am_flavour(left) == ia32_am_O) {
809                         set_irn_n(irn, 2, right);
810                         set_irn_n(irn, 3, left);
811                         temp  = left;
812                         left  = right;
813                         right = temp;
814                 }
815
816                 /* put LEA != ia32_am_O as left operand */
817                 if (is_ia32_Lea(right) && get_ia32_am_flavour(right) != ia32_am_O) {
818                         set_irn_n(irn, 2, right);
819                         set_irn_n(irn, 3, left);
820                         temp  = left;
821                         left  = right;
822                         right = temp;
823                 }
824
825                 /* put SHL as left operand iff left is NOT a LEA */
826                 if (! is_ia32_Lea(left) && pred_is_specific_node(right, is_ia32_Shl)) {
827                         set_irn_n(irn, 2, right);
828                         set_irn_n(irn, 3, left);
829                         temp  = left;
830                         left  = right;
831                         right = temp;
832                 }
833         }
834
835         base    = left;
836         index   = noreg;
837         offs    = 0;
838         scale   = 0;
839         am_flav = 0;
840
841         /* check for operation with immediate */
842         if (is_ia32_ImmConst(irn)) {
843                 tarval *tv = get_ia32_Immop_tarval(irn);
844
845                 DBG((mod, LEVEL_1, "\tfound op with imm const"));
846
847                 offs_cnst = get_tarval_long(tv);
848                 dolea     = 1;
849         }
850         else if (isadd && is_ia32_ImmSymConst(irn)) {
851                 DBG((mod, LEVEL_1, "\tfound op with imm symconst"));
852
853                 have_am_sc = 1;
854                 dolea      = 1;
855                 am_sc      = get_ia32_Immop_symconst(irn);
856                 am_sc_sign = is_ia32_am_sc_sign(irn);
857         }
858
859         /* determine the operand which needs to be checked */
860         temp = be_is_NoReg(cg, right) ? left : right;
861
862         /* check if right operand is AMConst (LEA with ia32_am_O)  */
863         /* but we can only eat it up if there is no other symconst */
864         /* because the linker won't accept two symconsts           */
865         if (! have_am_sc && is_ia32_Lea(temp) && get_ia32_am_flavour(temp) == ia32_am_O) {
866                 DBG((mod, LEVEL_1, "\tgot op with LEA am_O"));
867
868                 offs_lea   = get_ia32_am_offs_int(temp);
869                 am_sc      = get_ia32_am_sc(temp);
870                 am_sc_sign = is_ia32_am_sc_sign(temp);
871                 have_am_sc = 1;
872                 dolea      = 1;
873                 lea_o      = temp;
874
875                 if (temp == base)
876                         base = noreg;
877                 else if (temp == right)
878                         right = noreg;
879         }
880
881         if (isadd) {
882                 /* default for add -> make right operand to index */
883                 index               = right;
884                 dolea               = 1;
885                 consumed_left_shift = -1;
886
887                 DBG((mod, LEVEL_1, "\tgot LEA candidate with index %+F\n", index));
888
889                 /* determine the operand which needs to be checked */
890                 temp = left;
891                 if (is_ia32_Lea(left)) {
892                         temp = right;
893                         consumed_left_shift = 0;
894                 }
895
896                 /* check for SHL 1,2,3 */
897                 if (pred_is_specific_node(temp, is_ia32_Shl)) {
898
899                         if (is_ia32_ImmConst(temp)) {
900                                 long shiftval = get_tarval_long(get_ia32_Immop_tarval(temp));
901
902                                 if (shiftval <= 3) {
903                                         index               = get_irn_n(temp, 2);
904                                         consumed_left_shift = consumed_left_shift < 0 ? 1 : 0;
905                                         shift = temp;
906                                         scale = shiftval;
907
908                                         DBG((mod, LEVEL_1, "\tgot scaled index %+F\n", index));
909                                 }
910                         }
911                 }
912
913                 /* fix base */
914                 if (! be_is_NoReg(cg, index)) {
915                         /* if we have index, but left == right -> no base */
916                         if (left == right) {
917                                 base = noreg;
918                         }
919                         else if (consumed_left_shift == 1) {
920                                 /* -> base is right operand  */
921                                 base = (right == lea_o) ? noreg : right;
922                         }
923                 }
924         }
925
926         /* Try to assimilate a LEA as left operand */
927         if (is_ia32_Lea(left) && (get_ia32_am_flavour(left) != ia32_am_O)) {
928                 /* check if we can assimilate the LEA */
929                 int take_attr = do_new_lea(irn, base, index, left, have_am_sc, cg);
930
931                 if (take_attr == IA32_LEA_ATTR_NONE) {
932                         DBG((mod, LEVEL_1, "\tleave old LEA, creating new one\n"));
933                 }
934                 else {
935                         DBG((mod, LEVEL_1, "\tgot LEA as left operand ... assimilating\n"));
936                         lea = left; /* for statistics */
937
938                         if (take_attr & IA32_LEA_ATTR_OFFS)
939                                 offs = get_ia32_am_offs_int(left);
940
941                         if (take_attr & IA32_LEA_ATTR_AMSC) {
942                                 am_sc      = get_ia32_am_sc(left);
943                                 have_am_sc = 1;
944                                 am_sc_sign = is_ia32_am_sc_sign(left);
945                         }
946
947                         if (take_attr & IA32_LEA_ATTR_SCALE)
948                                 scale = get_ia32_am_scale(left);
949
950                         if (take_attr & IA32_LEA_ATTR_BASE)
951                                 base = get_irn_n(left, 0);
952
953                         if (take_attr & IA32_LEA_ATTR_INDEX)
954                                 index = get_irn_n(left, 1);
955
956                         if (take_attr & IA32_LEA_ATTR_FENT)
957                                 lea_ent = get_ia32_frame_ent(left);
958                 }
959         }
960
961         /* ok, we can create a new LEA */
962         if (dolea) {
963                 res = new_rd_ia32_Lea(dbg, irg, block, base, index);
964
965                 /* add the old offset of a previous LEA */
966                 add_ia32_am_offs_int(res, offs);
967
968                 /* add the new offset */
969                 if (isadd) {
970                         add_ia32_am_offs_int(res, offs_cnst);
971                         add_ia32_am_offs_int(res, offs_lea);
972                 } else {
973                         /* either lea_O-cnst, -cnst or -lea_O  */
974                         if (offs_cnst != 0) {
975                                 add_ia32_am_offs_int(res, offs_lea);
976                                 add_ia32_am_offs_int(res, -offs_cnst);
977                         } else {
978                                 add_ia32_am_offs_int(res, offs_lea);
979                         }
980                 }
981
982                 /* set the address mode symconst */
983                 if (have_am_sc) {
984                         set_ia32_am_sc(res, am_sc);
985                         if (am_sc_sign)
986                                 set_ia32_am_sc_sign(res);
987                 }
988
989                 /* copy the frame entity (could be set in case of Add */
990                 /* which was a FrameAddr) */
991                 if (lea_ent != NULL) {
992                         set_ia32_frame_ent(res, lea_ent);
993                         set_ia32_use_frame(res);
994                 } else {
995                         set_ia32_frame_ent(res, get_ia32_frame_ent(irn));
996                         if(is_ia32_use_frame(irn))
997                                 set_ia32_use_frame(res);
998                 }
999
1000                 /* set scale */
1001                 set_ia32_am_scale(res, scale);
1002
1003                 am_flav = ia32_am_N;
1004                 /* determine new am flavour */
1005                 if (offs || offs_cnst || offs_lea || have_am_sc) {
1006                         am_flav |= ia32_O;
1007                 }
1008                 if (! be_is_NoReg(cg, base)) {
1009                         am_flav |= ia32_B;
1010                 }
1011                 if (! be_is_NoReg(cg, index)) {
1012                         am_flav |= ia32_I;
1013                 }
1014                 if (scale > 0) {
1015                         am_flav |= ia32_S;
1016                 }
1017                 set_ia32_am_flavour(res, am_flav);
1018
1019                 set_ia32_op_type(res, ia32_AddrModeS);
1020
1021                 SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(cg, irn));
1022
1023                 DBG((mod, LEVEL_1, "\tLEA [%+F + %+F * %d + %d]\n", base, index, scale, get_ia32_am_offs_int(res)));
1024
1025                 /* we will exchange it, report here before the Proj is created */
1026                 if (shift && lea && lea_o) {
1027                         try_remove_from_sched(shift);
1028                         try_remove_from_sched(lea);
1029                         try_remove_from_sched(lea_o);
1030                         DBG_OPT_LEA4(irn, lea_o, lea, shift, res);
1031                 }
1032                 else if (shift && lea) {
1033                         try_remove_from_sched(shift);
1034                         try_remove_from_sched(lea);
1035                         DBG_OPT_LEA3(irn, lea, shift, res);
1036                 }
1037                 else if (shift && lea_o) {
1038                         try_remove_from_sched(shift);
1039                         try_remove_from_sched(lea_o);
1040                         DBG_OPT_LEA3(irn, lea_o, shift, res);
1041                 }
1042                 else if (lea && lea_o) {
1043                         try_remove_from_sched(lea);
1044                         try_remove_from_sched(lea_o);
1045                         DBG_OPT_LEA3(irn, lea_o, lea, res);
1046                 }
1047                 else if (shift) {
1048                         try_remove_from_sched(shift);
1049                         DBG_OPT_LEA2(irn, shift, res);
1050                 }
1051                 else if (lea) {
1052                         try_remove_from_sched(lea);
1053                         DBG_OPT_LEA2(irn, lea, res);
1054                 }
1055                 else if (lea_o) {
1056                         try_remove_from_sched(lea_o);
1057                         DBG_OPT_LEA2(irn, lea_o, res);
1058                 }
1059                 else
1060                         DBG_OPT_LEA1(irn, res);
1061
1062                 /* get the result Proj of the Add/Sub */
1063                 try_add_to_sched(irn, res);
1064                 try_remove_from_sched(irn);
1065
1066                 assert(irn && "Couldn't find result proj");
1067
1068                 /* exchange the old op with the new LEA */
1069                 exchange(irn, res);
1070         }
1071
1072         return res;
1073 }
1074
1075
1076 /**
1077  * Merges a Load/Store node with a LEA.
1078  * @param irn The Load/Store node
1079  * @param lea The LEA
1080  */
1081 static void merge_loadstore_lea(ir_node *irn, ir_node *lea) {
1082         ir_entity *irn_ent = get_ia32_frame_ent(irn);
1083         ir_entity *lea_ent = get_ia32_frame_ent(lea);
1084
1085         /* If the irn and the LEA both have a different frame entity set: do not merge */
1086         if (irn_ent != NULL && lea_ent != NULL && (irn_ent != lea_ent))
1087                 return;
1088         else if (irn_ent == NULL && lea_ent != NULL) {
1089                 set_ia32_frame_ent(irn, lea_ent);
1090                 set_ia32_use_frame(irn);
1091         }
1092
1093         /* get the AM attributes from the LEA */
1094         add_ia32_am_offs_int(irn, get_ia32_am_offs_int(lea));
1095         set_ia32_am_scale(irn, get_ia32_am_scale(lea));
1096         set_ia32_am_flavour(irn, get_ia32_am_flavour(lea));
1097
1098         set_ia32_am_sc(irn, get_ia32_am_sc(lea));
1099         if (is_ia32_am_sc_sign(lea))
1100                 set_ia32_am_sc_sign(irn);
1101
1102         set_ia32_op_type(irn, is_ia32_Ld(irn) ? ia32_AddrModeS : ia32_AddrModeD);
1103
1104         /* set base and index */
1105         set_irn_n(irn, 0, get_irn_n(lea, 0));
1106         set_irn_n(irn, 1, get_irn_n(lea, 1));
1107
1108         try_remove_from_sched(lea);
1109
1110         /* clear remat flag */
1111         set_ia32_flags(irn, get_ia32_flags(irn) & ~arch_irn_flags_rematerializable);
1112
1113         if (is_ia32_Ld(irn))
1114                 DBG_OPT_LOAD_LEA(lea, irn);
1115         else
1116                 DBG_OPT_STORE_LEA(lea, irn);
1117
1118 }
1119
1120 /**
1121  * Sets new_right index of irn to right and new_left index to left.
1122  * Also exchange left and right
1123  */
1124 static void exchange_left_right(ir_node *irn, ir_node **left, ir_node **right, int new_left, int new_right) {
1125         ir_node *temp;
1126
1127         set_irn_n(irn, new_right, *right);
1128         set_irn_n(irn, new_left, *left);
1129
1130         temp   = *left;
1131         *left  = *right;
1132         *right = temp;
1133
1134         /* this is only needed for Compares, but currently ALL nodes
1135          * have this attribute :-) */
1136         set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn)));
1137 }
1138
1139 /**
1140  * Performs address calculation optimization (create LEAs if possible)
1141  */
1142 static void optimize_lea(ir_node *irn, void *env) {
1143         ia32_code_gen_t *cg  = env;
1144
1145         if (! is_ia32_irn(irn))
1146                 return;
1147
1148         /* Following cases can occur:                                  */
1149         /* - Sub (l, imm) -> LEA [base - offset]                       */
1150         /* - Sub (l, r == LEA with ia32_am_O)   -> LEA [base - offset] */
1151         /* - Add (l, imm) -> LEA [base + offset]                       */
1152         /* - Add (l, r == LEA with ia32_am_O)  -> LEA [base + offset]  */
1153         /* - Add (l == LEA with ia32_am_O, r)  -> LEA [base + offset]  */
1154         /* - Add (l, r) -> LEA [base + index * scale]                  */
1155         /*              with scale > 1 iff l/r == shl (1,2,3)          */
1156         if (is_ia32_Sub(irn) || is_ia32_Add(irn)) {
1157                 ir_node *res;
1158
1159                 if(!is_addr_candidate(irn))
1160                         return;
1161
1162                 DBG((cg->mod, LEVEL_1, "\tfound address calculation candidate %+F ... ", irn));
1163                 res = fold_addr(cg, irn);
1164
1165                 if (res != irn)
1166                         DB((cg->mod, LEVEL_1, "transformed into %+F\n", res));
1167                 else
1168                         DB((cg->mod, LEVEL_1, "not transformed\n"));
1169         } else if (is_ia32_Ld(irn) || is_ia32_St(irn) || is_ia32_Store8Bit(irn)) {
1170                 /* - Load  -> LEA into Load  } TODO: If the LEA is used by more than one Load/Store */
1171                 /* - Store -> LEA into Store }       it might be better to keep the LEA             */
1172                 ir_node *left = get_irn_n(irn, 0);
1173
1174                 if (is_ia32_Lea(left)) {
1175                         const ir_edge_t *edge, *ne;
1176                         ir_node *src;
1177
1178                         /* merge all Loads/Stores connected to this LEA with the LEA */
1179                         foreach_out_edge_safe(left, edge, ne) {
1180                                 src = get_edge_src_irn(edge);
1181
1182                                 if (src && (get_edge_src_pos(edge) == 0) && (is_ia32_Ld(src) || is_ia32_St(src) || is_ia32_Store8Bit(src))) {
1183                                         DBG((cg->mod, LEVEL_1, "\nmerging %+F into %+F\n", left, irn));
1184                                         if (! is_ia32_got_lea(src))
1185                                                 merge_loadstore_lea(src, left);
1186                                         set_ia32_got_lea(src);
1187                                 }
1188                         }
1189                 }
1190         }
1191 }
1192
1193 /**
1194  * Checks for address mode patterns and performs the
1195  * necessary transformations.
1196  * This function is called by a walker.
1197  */
1198 static void optimize_am(ir_node *irn, void *env) {
1199         ia32_am_opt_env_t *am_opt_env = env;
1200         ia32_code_gen_t   *cg         = am_opt_env->cg;
1201         ir_graph          *irg        = get_irn_irg(irn);
1202         heights_t         *h          = am_opt_env->h;
1203         ir_node           *block, *left, *right;
1204         ir_node           *store, *load, *mem_proj;
1205         ir_node           *addr_b, *addr_i;
1206         int               need_exchange_on_fail = 0;
1207         ia32_am_type_t    am_support;
1208         ia32_am_cand_t cand;
1209         ia32_am_cand_t orig_cand;
1210         int               dest_possible;
1211         int               source_possible;
1212         DEBUG_ONLY(firm_dbg_module_t *mod = cg->mod;)
1213
1214         if (!is_ia32_irn(irn) || is_ia32_Ld(irn) || is_ia32_St(irn) || is_ia32_Store8Bit(irn))
1215                 return;
1216         if (is_ia32_Lea(irn))
1217                 return;
1218
1219         am_support = get_ia32_am_support(irn);
1220         block = get_nodes_block(irn);
1221
1222         DBG((mod, LEVEL_1, "checking for AM\n"));
1223
1224         /* fold following patterns:                                                         */
1225         /* - op -> Load into AMop with am_Source                                            */
1226         /*   conditions:                                                                    */
1227         /*     - op is am_Source capable AND                                                */
1228         /*     - the Load is only used by this op AND                                       */
1229         /*     - the Load is in the same block                                              */
1230         /* - Store -> op -> Load  into AMop with am_Dest                                    */
1231         /*   conditions:                                                                    */
1232         /*     - op is am_Dest capable AND                                                  */
1233         /*     - the Store uses the same address as the Load AND                            */
1234         /*     - the Load is only used by this op AND                                       */
1235         /*     - the Load and Store are in the same block AND                               */
1236         /*     - nobody else uses the result of the op                                      */
1237         if (get_ia32_am_support(irn) == ia32_am_None)
1238                 return;
1239
1240         cand = is_am_candidate(cg, h, block, irn);
1241         if (cand == IA32_AM_CAND_NONE)
1242                 return;
1243
1244         orig_cand = cand;
1245         DBG((mod, LEVEL_1, "\tfound address mode candidate %+F ... ", irn));
1246
1247         left  = get_irn_n(irn, 2);
1248         if (get_irn_arity(irn) == 4) {
1249                 /* it's an "unary" operation */
1250                 right = left;
1251                 assert(cand == IA32_AM_CAND_BOTH);
1252         } else {
1253                 right = get_irn_n(irn, 3);
1254         }
1255
1256         dest_possible = am_support & ia32_am_Dest ? 1 : 0;
1257         source_possible = am_support & ia32_am_Source ? 1 : 0;
1258
1259         if (dest_possible) {
1260                 addr_b = NULL;
1261                 addr_i = NULL;
1262                 store  = NULL;
1263
1264                 /* we should only have 1 user which is a store */
1265                 if (ia32_get_irn_n_edges(irn) == 1) {
1266                         ir_node *succ = get_edge_src_irn(get_irn_out_edge_first(irn));
1267
1268                         if (is_ia32_xStore(succ) || is_ia32_Store(succ)) {
1269                                 store  = succ;
1270                                 addr_b = get_irn_n(store, 0);
1271                                 addr_i = get_irn_n(store, 1);
1272                         }
1273                 }
1274
1275                 if (store == NULL) {
1276                         dest_possible = 0;
1277                 }
1278         }
1279
1280         if (dest_possible) {
1281                 /* normalize nodes, we need the interesting load on the left side */
1282                 if (cand & IA32_AM_CAND_RIGHT) {
1283                         load = get_Proj_pred(right);
1284                         if (load_store_addr_is_equal(load, store, addr_b, addr_i)) {
1285                                 exchange_left_right(irn, &left, &right, 3, 2);
1286                                 need_exchange_on_fail ^= 1;
1287                                 if (cand == IA32_AM_CAND_RIGHT)
1288                                         cand = IA32_AM_CAND_LEFT;
1289                         }
1290                 }
1291         }
1292
1293         if (dest_possible) {
1294                 if(cand & IA32_AM_CAND_LEFT && is_Proj(left)) {
1295                         load = get_Proj_pred(left);
1296
1297 #ifndef AGGRESSIVE_AM
1298                         /* we have to be the only user of the load */
1299                         if (get_irn_n_edges(left) > 1) {
1300                                 dest_possible = 0;
1301                         }
1302 #endif
1303                 } else {
1304                         dest_possible = 0;
1305                 }
1306         }
1307
1308         if (dest_possible) {
1309                 /* the store has to use the loads memory or the same memory
1310                  * as the load */
1311                 ir_node *loadmem = get_irn_n(load, 2);
1312                 ir_node *storemem = get_irn_n(store, 3);
1313                 assert(get_irn_mode(loadmem) == mode_M);
1314                 assert(get_irn_mode(storemem) == mode_M);
1315                 if(storemem != loadmem || !is_Proj(storemem)
1316                                 || get_Proj_pred(storemem) != load) {
1317                         dest_possible = 0;
1318                 }
1319         }
1320
1321         if (dest_possible) {
1322                 /* Compare Load and Store address */
1323                 if (!load_store_addr_is_equal(load, store, addr_b, addr_i))
1324                         dest_possible = 0;
1325         }
1326
1327         if (dest_possible) {
1328                 /* all conditions fullfilled, do the transformation */
1329                 assert(cand & IA32_AM_CAND_LEFT);
1330
1331                 /* set new base, index and attributes */
1332                 set_irn_n(irn, 0, addr_b);
1333                 set_irn_n(irn, 1, addr_i);
1334                 add_ia32_am_offs_int(irn, get_ia32_am_offs_int(load));
1335                 set_ia32_am_scale(irn, get_ia32_am_scale(load));
1336                 set_ia32_am_flavour(irn, get_ia32_am_flavour(load));
1337                 set_ia32_op_type(irn, ia32_AddrModeD);
1338                 set_ia32_frame_ent(irn, get_ia32_frame_ent(load));
1339                 if(is_ia32_use_frame(load))
1340                         set_ia32_use_frame(irn);
1341                 set_ia32_ls_mode(irn, get_ia32_ls_mode(load));
1342
1343                 set_ia32_am_sc(irn, get_ia32_am_sc(load));
1344                 if (is_ia32_am_sc_sign(load))
1345                         set_ia32_am_sc_sign(irn);
1346
1347                 if (is_ia32_use_frame(load))
1348                         set_ia32_use_frame(irn);
1349
1350                 /* connect to Load memory and disconnect Load */
1351                 if (get_irn_arity(irn) == 5) {
1352                         /* binary AMop */
1353                         set_irn_n(irn, 4, get_irn_n(load, 2));
1354                         set_irn_n(irn, 2, ia32_get_admissible_noreg(cg, irn, 2));
1355                 } else {
1356                         /* unary AMop */
1357                         set_irn_n(irn, 3, get_irn_n(load, 2));
1358                         set_irn_n(irn, 2, ia32_get_admissible_noreg(cg, irn, 2));
1359                 }
1360
1361                 set_irn_mode(irn, mode_M);
1362
1363                 /* connect the memory Proj of the Store to the op */
1364                 mem_proj = ia32_get_proj_for_mode(store, mode_M);
1365                 edges_reroute(mem_proj, irn, irg);
1366
1367                 /* clear remat flag */
1368                 set_ia32_flags(irn, get_ia32_flags(irn) & ~arch_irn_flags_rematerializable);
1369
1370                 try_remove_from_sched(load);
1371                 try_remove_from_sched(store);
1372                 DBG_OPT_AM_D(load, store, irn);
1373
1374                 DB((mod, LEVEL_1, "merged with %+F and %+F into dest AM\n", load, store));
1375                 need_exchange_on_fail = 0;
1376                 source_possible = 0;
1377         }
1378
1379         if (source_possible) {
1380                 /* normalize ops, we need the load on the right */
1381                 if(cand == IA32_AM_CAND_LEFT) {
1382                         if(node_is_ia32_comm(irn)) {
1383                                 exchange_left_right(irn, &left, &right, 3, 2);
1384                                 need_exchange_on_fail ^= 1;
1385                                 cand = IA32_AM_CAND_RIGHT;
1386                         } else {
1387                                 source_possible = 0;
1388                         }
1389                 }
1390         }
1391
1392         if (source_possible) {
1393                 /* all conditions fullfilled, do transform */
1394                 assert(cand & IA32_AM_CAND_RIGHT);
1395                 load = get_Proj_pred(right);
1396
1397                 if(get_irn_n_edges(load) > 1) {
1398                         source_possible = 0;
1399                 }
1400         }
1401
1402         if (source_possible) {
1403                 addr_b = get_irn_n(load, 0);
1404                 addr_i = get_irn_n(load, 1);
1405
1406                 /* set new base, index and attributes */
1407                 set_irn_n(irn, 0, addr_b);
1408                 set_irn_n(irn, 1, addr_i);
1409                 add_ia32_am_offs_int(irn, get_ia32_am_offs_int(load));
1410                 set_ia32_am_scale(irn, get_ia32_am_scale(load));
1411                 set_ia32_am_flavour(irn, get_ia32_am_flavour(load));
1412                 set_ia32_op_type(irn, ia32_AddrModeS);
1413                 set_ia32_frame_ent(irn, get_ia32_frame_ent(load));
1414                 set_ia32_ls_mode(irn, get_ia32_ls_mode(load));
1415
1416                 set_ia32_am_sc(irn, get_ia32_am_sc(load));
1417                 if (is_ia32_am_sc_sign(load))
1418                         set_ia32_am_sc_sign(irn);
1419
1420                 /* clear remat flag */
1421                 set_ia32_flags(irn, get_ia32_flags(irn) & ~arch_irn_flags_rematerializable);
1422
1423                 if (is_ia32_use_frame(load))
1424                         set_ia32_use_frame(irn);
1425
1426                 /* connect to Load memory and disconnect Load */
1427                 if (get_irn_arity(irn) == 5) {
1428                         /* binary AMop */
1429                         set_irn_n(irn, 3, ia32_get_admissible_noreg(cg, irn, 3));
1430                         set_irn_n(irn, 4, get_irn_n(load, 2));
1431                 } else {
1432                         assert(get_irn_arity(irn) == 4);
1433                         /* unary AMop */
1434                         set_irn_n(irn, 2, ia32_get_admissible_noreg(cg, irn, 2));
1435                         set_irn_n(irn, 3, get_irn_n(load, 2));
1436                 }
1437
1438                 DBG_OPT_AM_S(load, irn);
1439
1440                 /* If Load has a memory Proj, connect it to the op */
1441                 mem_proj = ia32_get_proj_for_mode(load, mode_M);
1442                 if (mem_proj != NULL) {
1443                         ir_node *res_proj;
1444                         ir_mode *mode = get_irn_mode(irn);
1445
1446                         res_proj = new_rd_Proj(get_irn_dbg_info(irn), irg,
1447                                                get_nodes_block(irn), new_Unknown(mode_T),
1448                                                                    mode, 0);
1449                         set_irn_mode(irn, mode_T);
1450                         edges_reroute(irn, res_proj, irg);
1451                         set_Proj_pred(res_proj, irn);
1452
1453                         set_Proj_pred(mem_proj, irn);
1454                         set_Proj_proj(mem_proj, 1);
1455
1456                         if(sched_is_scheduled(irn)) {
1457                                 sched_add_after(irn, res_proj);
1458                                 sched_add_after(irn, mem_proj);
1459                         }
1460                 }
1461
1462                 if(get_irn_n_edges(load) == 0) {
1463                         try_remove_from_sched(load);
1464                 }
1465                 need_exchange_on_fail = 0;
1466
1467                 DB((mod, LEVEL_1, "merged with %+F into source AM\n", load));
1468         }
1469
1470         /* was exchanged but optimize failed: exchange back */
1471         if (need_exchange_on_fail) {
1472                 exchange_left_right(irn, &left, &right, 3, 2);
1473         }
1474 }
1475
1476 /**
1477  * Performs address mode optimization.
1478  */
1479 void ia32_optimize_addressmode(ia32_code_gen_t *cg) {
1480         /* if we are supposed to do AM or LEA optimization: recalculate edges */
1481         if (cg->opt & (IA32_OPT_DOAM | IA32_OPT_LEA)) {
1482                 edges_deactivate(cg->irg);
1483                 edges_activate(cg->irg);
1484         }
1485         else {
1486                 /* no optimizations at all */
1487                 return;
1488         }
1489
1490         /* beware: we cannot optimize LEA and AM in one run because */
1491         /*         LEA optimization adds new nodes to the irg which */
1492         /*         invalidates the phase data                       */
1493
1494         if (cg->opt & IA32_OPT_LEA) {
1495                 irg_walk_blkwise_graph(cg->irg, NULL, optimize_lea, cg);
1496         }
1497
1498         if (cg->dump)
1499                 be_dump(cg->irg, "-lea", dump_ir_block_graph_sched);
1500
1501         if (cg->opt & IA32_OPT_DOAM) {
1502                 /* we need height information for am optimization */
1503                 heights_t *h = heights_new(cg->irg);
1504                 ia32_am_opt_env_t env;
1505
1506                 env.cg = cg;
1507                 env.h  = h;
1508
1509                 irg_walk_blkwise_graph(cg->irg, NULL, optimize_am, &env);
1510
1511                 heights_free(h);
1512         }
1513 }