2 * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
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.
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.
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
22 * @brief Implements several optimizations for IA32.
23 * @author Christian Wuerdig
34 #include "firm_types.h"
44 #include "../benode_t.h"
45 #include "../besched_t.h"
47 #include "ia32_new_nodes.h"
48 #include "bearch_ia32_t.h"
49 #include "gen_ia32_regalloc_if.h"
50 #include "ia32_transform.h"
51 #include "ia32_dbg_stat.h"
52 #include "ia32_util.h"
54 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
56 //#define AGGRESSIVE_AM
59 IA32_AM_CAND_NONE = 0, /**< no addressmode possible with irn inputs */
60 IA32_AM_CAND_LEFT = 1, /**< addressmode possible with left input */
61 IA32_AM_CAND_RIGHT = 2, /**< addressmode possible with right input */
62 IA32_AM_CAND_BOTH = 3 /**< addressmode possible with both inputs */
65 typedef int is_op_func_t(const ir_node *n);
66 typedef ir_node *load_func_t(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, ir_node *mem);
69 * checks if a node represents the NOREG value
71 static INLINE int be_is_NoReg(ia32_code_gen_t *cg, const ir_node *irn) {
72 return irn == cg->noreg_gp || irn == cg->noreg_xmm || irn == cg->noreg_vfp;
75 /********************************************************************************************************
76 * _____ _ _ ____ _ _ _ _ _
77 * | __ \ | | | | / __ \ | | (_) (_) | | (_)
78 * | |__) |__ ___ _ __ | |__ ___ | | ___ | | | |_ __ | |_ _ _ __ ___ _ ______ _| |_ _ ___ _ __
79 * | ___/ _ \/ _ \ '_ \| '_ \ / _ \| |/ _ \ | | | | '_ \| __| | '_ ` _ \| |_ / _` | __| |/ _ \| '_ \
80 * | | | __/ __/ |_) | | | | (_) | | __/ | |__| | |_) | |_| | | | | | | |/ / (_| | |_| | (_) | | | |
81 * |_| \___|\___| .__/|_| |_|\___/|_|\___| \____/| .__/ \__|_|_| |_| |_|_/___\__,_|\__|_|\___/|_| |_|
84 ********************************************************************************************************/
87 * NOTE: THESE PEEPHOLE OPTIMIZATIONS MUST BE CALLED AFTER SCHEDULING AND REGISTER ALLOCATION.
90 // only optimize up to 48 stores behind IncSPs
91 #define MAXPUSH_OPTIMIZE 48
94 * Tries to create pushs from IncSP,Store combinations
96 static void ia32_create_Pushs(ir_node *irn, ia32_code_gen_t *cg) {
100 ir_node *stores[MAXPUSH_OPTIMIZE];
101 ir_node *block = get_nodes_block(irn);
102 ir_graph *irg = cg->irg;
104 ir_mode *spmode = get_irn_mode(irn);
106 memset(stores, 0, sizeof(stores));
108 assert(be_is_IncSP(irn));
110 offset = be_get_IncSP_offset(irn);
115 * We first walk the schedule after the IncSP node as long as we find
116 * suitable stores that could be transformed to a push.
117 * We save them into the stores array which is sorted by the frame offset/4
118 * attached to the node
120 for(node = sched_next(irn); !sched_is_end(node); node = sched_next(node)) {
125 // it has to be a store
126 if(!is_ia32_Store(node))
129 // it has to use our sp value
130 if(get_irn_n(node, 0) != irn)
132 // store has to be attached to NoMem
133 mem = get_irn_n(node, 3);
138 if( (get_ia32_am_flavour(node) & ia32_am_IS) != 0)
141 offset = get_ia32_am_offs_int(node);
143 storeslot = offset / 4;
144 if(storeslot >= MAXPUSH_OPTIMIZE)
147 // storing into the same slot twice is bad (and shouldn't happen...)
148 if(stores[storeslot] != NULL)
151 // storing at half-slots is bad
155 stores[storeslot] = node;
158 curr_sp = get_irn_n(irn, 0);
160 // walk the stores in inverse order and create pushs for them
161 i = (offset / 4) - 1;
162 if(i >= MAXPUSH_OPTIMIZE) {
163 i = MAXPUSH_OPTIMIZE - 1;
166 for( ; i >= 0; --i) {
167 const arch_register_t *spreg;
169 ir_node *val, *mem, *mem_proj;
170 ir_node *store = stores[i];
171 ir_node *noreg = ia32_new_NoReg_gp(cg);
173 if(store == NULL || is_Bad(store))
176 val = get_irn_n(store, 2);
177 mem = get_irn_n(store, 3);
178 spreg = arch_get_irn_register(cg->arch_env, curr_sp);
180 push = new_rd_ia32_Push(get_irn_dbg_info(store), irg, block, noreg, noreg, val, curr_sp, mem);
182 set_ia32_am_support(push, ia32_am_Source, ia32_am_unary);
183 copy_ia32_Immop_attr(push, store);
185 sched_add_before(irn, push);
187 // create stackpointer proj
188 curr_sp = new_r_Proj(irg, block, push, spmode, pn_ia32_Push_stack);
189 arch_set_irn_register(cg->arch_env, curr_sp, spreg);
191 // create memory proj
192 mem_proj = new_r_Proj(irg, block, push, mode_M, pn_ia32_Push_M);
194 // use the memproj now
195 exchange(store, mem_proj);
197 // we can remove the store now
203 be_set_IncSP_offset(irn, offset);
205 // can we remove the IncSP now?
207 const ir_edge_t *edge, *next;
209 foreach_out_edge_safe(irn, edge, next) {
210 ir_node *arg = get_edge_src_irn(edge);
211 int pos = get_edge_src_pos(edge);
213 set_irn_n(arg, pos, curr_sp);
216 set_irn_n(irn, 0, new_Bad());
219 set_irn_n(irn, 0, curr_sp);
224 * Tries to optimize two following IncSP.
226 static void ia32_optimize_IncSP(ir_node *node)
231 ir_node *pred = be_get_IncSP_pred(node);
234 if(!be_is_IncSP(pred))
237 if(get_irn_n_edges(pred) > 1)
240 pred_offs = be_get_IncSP_offset(pred);
241 curr_offs = be_get_IncSP_offset(node);
243 if(pred_offs == BE_STACK_FRAME_SIZE_EXPAND) {
244 if(curr_offs != BE_STACK_FRAME_SIZE_SHRINK) {
248 } else if(pred_offs == BE_STACK_FRAME_SIZE_SHRINK) {
249 if(curr_offs != BE_STACK_FRAME_SIZE_EXPAND) {
253 } else if(curr_offs == BE_STACK_FRAME_SIZE_EXPAND
254 || curr_offs == BE_STACK_FRAME_SIZE_SHRINK) {
257 offs = curr_offs + pred_offs;
260 be_set_IncSP_offset(node, offs);
262 /* rewire dependency edges */
263 predpred = be_get_IncSP_pred(pred);
264 edges_reroute_kind(pred, predpred, EDGE_KIND_DEP, current_ir_graph);
267 be_set_IncSP_pred(node, predpred);
273 * Performs Peephole Optimizations.
275 static void ia32_peephole_optimize_node(ir_node *node, void *env) {
276 ia32_code_gen_t *cg = env;
278 if (be_is_IncSP(node)) {
279 ia32_optimize_IncSP(node);
281 if (cg->opt & IA32_OPT_PUSHARGS)
282 ia32_create_Pushs(node, cg);
286 void ia32_peephole_optimization(ir_graph *irg, ia32_code_gen_t *cg) {
287 irg_walk_graph(irg, ia32_peephole_optimize_node, NULL, cg);
290 /******************************************************************
292 * /\ | | | | | \/ | | |
293 * / \ __| | __| |_ __ ___ ___ ___| \ / | ___ __| | ___
294 * / /\ \ / _` |/ _` | '__/ _ \/ __/ __| |\/| |/ _ \ / _` |/ _ \
295 * / ____ \ (_| | (_| | | | __/\__ \__ \ | | | (_) | (_| | __/
296 * /_/ \_\__,_|\__,_|_| \___||___/___/_| |_|\___/ \__,_|\___|
298 ******************************************************************/
305 static int node_is_ia32_comm(const ir_node *irn) {
306 return is_ia32_irn(irn) ? is_ia32_commutative(irn) : 0;
309 static int ia32_get_irn_n_edges(const ir_node *irn) {
310 const ir_edge_t *edge;
313 foreach_out_edge(irn, edge) {
321 * Determines if pred is a Proj and if is_op_func returns true for it's predecessor.
323 * @param pred The node to be checked
324 * @param is_op_func The check-function
325 * @return 1 if conditions are fulfilled, 0 otherwise
327 static int pred_is_specific_node(const ir_node *pred, is_op_func_t *is_op_func) {
328 return is_op_func(pred);
332 * Determines if pred is a Proj and if is_op_func returns true for it's predecessor
333 * and if the predecessor is in block bl.
335 * @param bl The block
336 * @param pred The node to be checked
337 * @param is_op_func The check-function
338 * @return 1 if conditions are fulfilled, 0 otherwise
340 static int pred_is_specific_nodeblock(const ir_node *bl, const ir_node *pred,
341 int (*is_op_func)(const ir_node *n))
344 pred = get_Proj_pred(pred);
345 if ((bl == get_nodes_block(pred)) && is_op_func(pred)) {
354 * Checks if irn is a candidate for address calculation. We avoid transforming
355 * adds to leas if they have a load as pred, because then we can use AM mode
358 * - none of the operand must be a Load within the same block OR
359 * - all Loads must have more than one user OR
361 * @param block The block the Loads must/mustnot be in
362 * @param irn The irn to check
363 * return 1 if irn is a candidate, 0 otherwise
365 static int is_addr_candidate(const ir_node *irn)
367 #ifndef AGGRESSIVE_AM
368 const ir_node *block = get_nodes_block(irn);
369 ir_node *left, *right;
372 left = get_irn_n(irn, 2);
373 right = get_irn_n(irn, 3);
375 if (pred_is_specific_nodeblock(block, left, is_ia32_Ld)) {
376 n = ia32_get_irn_n_edges(left);
377 /* load with only one user: don't create LEA */
382 if (pred_is_specific_nodeblock(block, right, is_ia32_Ld)) {
383 n = ia32_get_irn_n_edges(right);
394 * Checks if irn is a candidate for address mode.
397 * - at least one operand has to be a Load within the same block AND
398 * - the load must not have other users than the irn AND
399 * - the irn must not have a frame entity set
401 * @param cg The ia32 code generator
402 * @param h The height information of the irg
403 * @param block The block the Loads must/mustnot be in
404 * @param irn The irn to check
405 * @return 0 if irn is no candidate, 1 if left load can be used, 2 if right one, 3 for both
407 static ia32_am_cand_t is_am_candidate(heights_t *h, const ir_node *block, ir_node *irn) {
408 ir_node *in, *load, *other, *left, *right;
409 int is_cand = 0, cand;
413 if (is_ia32_Ld(irn) || is_ia32_St(irn) ||
414 is_ia32_vfild(irn) || is_ia32_vfist(irn) ||
415 is_ia32_xStoreSimple(irn))
418 if(get_ia32_frame_ent(irn) != NULL)
419 return IA32_AM_CAND_NONE;
421 left = get_irn_n(irn, 2);
422 arity = get_irn_arity(irn);
423 is_binary = get_ia32_am_arity(irn) == ia32_am_binary;
426 right = get_irn_n(irn, 3);
428 assert(get_ia32_am_arity(irn) == ia32_am_unary);
435 if (pred_is_specific_nodeblock(block, in, is_ia32_Ld)) {
436 #ifndef AGGRESSIVE_AM
438 n = ia32_get_irn_n_edges(in);
439 is_cand = (n == 1) ? 1 : is_cand; /* load with more than one user: no AM */
444 load = get_Proj_pred(in);
447 /* 8bit Loads are not supported (for binary ops),
448 * they cannot be used with every register */
449 if (get_ia32_am_arity(irn) == ia32_am_binary &&
450 get_mode_size_bits(get_ia32_ls_mode(load)) < 16) {
454 /* If there is a data dependency of other irn from load: cannot use AM */
455 if (is_cand && is_binary && get_nodes_block(other) == block) {
456 other = skip_Proj(other);
457 is_cand = heights_reachable_in_block(h, other, load) ? 0 : is_cand;
458 /* this could happen in loops */
459 is_cand = heights_reachable_in_block(h, load, irn) ? 0 : is_cand;
463 cand = is_cand ? IA32_AM_CAND_LEFT : IA32_AM_CAND_NONE;
467 if (pred_is_specific_nodeblock(block, in, is_ia32_Ld)) {
468 #ifndef AGGRESSIVE_AM
470 n = ia32_get_irn_n_edges(in);
471 is_cand = (n == 1) ? 1 : is_cand; /* load with more than one user: no AM */
476 load = get_Proj_pred(in);
479 /* 8bit Loads are not supported, they cannot be used with every register */
480 /* 8bit Loads are not supported (for binary ops),
481 * they cannot be used with every register */
482 if (get_ia32_am_arity(irn) == ia32_am_binary &&
483 get_mode_size_bits(get_ia32_ls_mode(load)) < 16) {
487 /* If there is a data dependency of other irn from load: cannot use load */
488 if (is_cand && is_binary && get_nodes_block(other) == block) {
489 other = skip_Proj(other);
490 is_cand = heights_reachable_in_block(h, other, load) ? 0 : is_cand;
491 /* this could happen in loops */
492 is_cand = heights_reachable_in_block(h, load, irn) ? 0 : is_cand;
496 cand = is_cand ? (cand | IA32_AM_CAND_RIGHT) : cand;
498 /* if the irn has a frame entity: we do not use address mode */
503 * Compares the base and index addr and the load/store entities
504 * and returns 1 if they are equal.
506 static int load_store_addr_is_equal(const ir_node *load, const ir_node *store,
507 const ir_node *addr_b, const ir_node *addr_i)
509 if(get_irn_n(load, 0) != addr_b)
511 if(get_irn_n(load, 1) != addr_i)
514 if(get_ia32_frame_ent(load) != get_ia32_frame_ent(store))
517 if(get_ia32_am_sc(load) != get_ia32_am_sc(store))
519 if(is_ia32_am_sc_sign(load) != is_ia32_am_sc_sign(store))
521 if(get_ia32_am_offs_int(load) != get_ia32_am_offs_int(store))
523 if(get_ia32_ls_mode(load) != get_ia32_ls_mode(store))
529 typedef enum _ia32_take_lea_attr {
530 IA32_LEA_ATTR_NONE = 0,
531 IA32_LEA_ATTR_BASE = (1 << 0),
532 IA32_LEA_ATTR_INDEX = (1 << 1),
533 IA32_LEA_ATTR_OFFS = (1 << 2),
534 IA32_LEA_ATTR_SCALE = (1 << 3),
535 IA32_LEA_ATTR_AMSC = (1 << 4),
536 IA32_LEA_ATTR_FENT = (1 << 5)
537 } ia32_take_lea_attr;
540 * Decides if we have to keep the LEA operand or if we can assimilate it.
542 static int do_new_lea(ir_node *irn, ir_node *base, ir_node *index, ir_node *lea,
543 int have_am_sc, ia32_code_gen_t *cg)
545 ir_entity *irn_ent = get_ia32_frame_ent(irn);
546 ir_entity *lea_ent = get_ia32_frame_ent(lea);
548 int is_noreg_base = be_is_NoReg(cg, base);
549 int is_noreg_index = be_is_NoReg(cg, index);
550 ia32_am_flavour_t am_flav = get_ia32_am_flavour(lea);
552 /* If the Add and the LEA both have a different frame entity set: keep */
553 if (irn_ent && lea_ent && (irn_ent != lea_ent))
554 return IA32_LEA_ATTR_NONE;
555 else if (! irn_ent && lea_ent)
556 ret_val |= IA32_LEA_ATTR_FENT;
558 /* If the Add and the LEA both have already an address mode symconst: keep */
559 if (have_am_sc && get_ia32_am_sc(lea))
560 return IA32_LEA_ATTR_NONE;
561 else if (get_ia32_am_sc(lea))
562 ret_val |= IA32_LEA_ATTR_AMSC;
564 /* Check the different base-index combinations */
566 if (! is_noreg_base && ! is_noreg_index) {
567 /* Assimilate if base is the lea and the LEA is just a Base + Offset calculation */
568 if ((base == lea) && ! (am_flav & ia32_I ? 1 : 0)) {
569 if (am_flav & ia32_O)
570 ret_val |= IA32_LEA_ATTR_OFFS;
572 ret_val |= IA32_LEA_ATTR_BASE;
575 return IA32_LEA_ATTR_NONE;
577 else if (! is_noreg_base && is_noreg_index) {
578 /* Base is set but index not */
580 /* Base points to LEA: assimilate everything */
581 if (am_flav & ia32_O)
582 ret_val |= IA32_LEA_ATTR_OFFS;
583 if (am_flav & ia32_S)
584 ret_val |= IA32_LEA_ATTR_SCALE;
585 if (am_flav & ia32_I)
586 ret_val |= IA32_LEA_ATTR_INDEX;
588 ret_val |= IA32_LEA_ATTR_BASE;
590 else if (am_flav & ia32_B ? 0 : 1) {
591 /* Base is not the LEA but the LEA is an index only calculation: assimilate */
592 if (am_flav & ia32_O)
593 ret_val |= IA32_LEA_ATTR_OFFS;
594 if (am_flav & ia32_S)
595 ret_val |= IA32_LEA_ATTR_SCALE;
597 ret_val |= IA32_LEA_ATTR_INDEX;
600 return IA32_LEA_ATTR_NONE;
602 else if (is_noreg_base && ! is_noreg_index) {
603 /* Index is set but not base */
605 /* Index points to LEA: assimilate everything */
606 if (am_flav & ia32_O)
607 ret_val |= IA32_LEA_ATTR_OFFS;
608 if (am_flav & ia32_S)
609 ret_val |= IA32_LEA_ATTR_SCALE;
610 if (am_flav & ia32_B)
611 ret_val |= IA32_LEA_ATTR_BASE;
613 ret_val |= IA32_LEA_ATTR_INDEX;
615 else if (am_flav & ia32_I ? 0 : 1) {
616 /* Index is not the LEA but the LEA is a base only calculation: assimilate */
617 if (am_flav & ia32_O)
618 ret_val |= IA32_LEA_ATTR_OFFS;
619 if (am_flav & ia32_S)
620 ret_val |= IA32_LEA_ATTR_SCALE;
622 ret_val |= IA32_LEA_ATTR_BASE;
625 return IA32_LEA_ATTR_NONE;
628 assert(0 && "There must have been set base or index");
635 * Adds res before irn into schedule if irn was scheduled.
636 * @param irn The schedule point
637 * @param res The node to be scheduled
639 static INLINE void try_add_to_sched(ir_node *irn, ir_node *res) {
640 if (sched_is_scheduled(irn))
641 sched_add_before(irn, res);
645 * Removes node from schedule if it is not used anymore. If irn is a mode_T node
646 * all it's Projs are removed as well.
647 * @param irn The irn to be removed from schedule
649 static INLINE void try_kill(ir_node *node)
651 if(get_irn_mode(node) == mode_T) {
652 const ir_edge_t *edge, *next;
653 foreach_out_edge_safe(node, edge, next) {
654 ir_node *proj = get_edge_src_irn(edge);
659 if(get_irn_n_edges(node) != 0)
662 if (sched_is_scheduled(node)) {
670 * Folds Add or Sub to LEA if possible
672 static ir_node *fold_addr(ia32_code_gen_t *cg, ir_node *irn) {
673 ir_graph *irg = get_irn_irg(irn);
674 dbg_info *dbg_info = get_irn_dbg_info(irn);
675 ir_node *block = get_nodes_block(irn);
677 ir_node *shift = NULL;
678 ir_node *lea_o = NULL;
688 ir_entity *am_sc = NULL;
689 ir_entity *lea_ent = NULL;
690 ir_node *noreg = ia32_new_NoReg_gp(cg);
691 ir_node *left, *right, *temp;
692 ir_node *base, *index;
693 int consumed_left_shift;
694 ia32_am_flavour_t am_flav;
696 if (is_ia32_Add(irn))
699 left = get_irn_n(irn, 2);
700 right = get_irn_n(irn, 3);
702 /* "normalize" arguments in case of add with two operands */
703 if (isadd && ! be_is_NoReg(cg, right)) {
704 /* put LEA == ia32_am_O as right operand */
705 if (is_ia32_Lea(left) && get_ia32_am_flavour(left) == ia32_am_O) {
706 set_irn_n(irn, 2, right);
707 set_irn_n(irn, 3, left);
713 /* put LEA != ia32_am_O as left operand */
714 if (is_ia32_Lea(right) && get_ia32_am_flavour(right) != ia32_am_O) {
715 set_irn_n(irn, 2, right);
716 set_irn_n(irn, 3, left);
722 /* put SHL as left operand iff left is NOT a LEA */
723 if (! is_ia32_Lea(left) && pred_is_specific_node(right, is_ia32_Shl)) {
724 set_irn_n(irn, 2, right);
725 set_irn_n(irn, 3, left);
738 /* check for operation with immediate */
739 if (is_ia32_ImmConst(irn)) {
740 tarval *tv = get_ia32_Immop_tarval(irn);
742 DBG((dbg, LEVEL_1, "\tfound op with imm const"));
744 offs_cnst = get_tarval_long(tv);
747 else if (isadd && is_ia32_ImmSymConst(irn)) {
748 DBG((dbg, LEVEL_1, "\tfound op with imm symconst"));
752 am_sc = get_ia32_Immop_symconst(irn);
753 am_sc_sign = is_ia32_am_sc_sign(irn);
756 /* determine the operand which needs to be checked */
757 temp = be_is_NoReg(cg, right) ? left : right;
759 /* check if right operand is AMConst (LEA with ia32_am_O) */
760 /* but we can only eat it up if there is no other symconst */
761 /* because the linker won't accept two symconsts */
762 if (! have_am_sc && is_ia32_Lea(temp) && get_ia32_am_flavour(temp) == ia32_am_O) {
763 DBG((dbg, LEVEL_1, "\tgot op with LEA am_O"));
765 offs_lea = get_ia32_am_offs_int(temp);
766 am_sc = get_ia32_am_sc(temp);
767 am_sc_sign = is_ia32_am_sc_sign(temp);
774 else if (temp == right)
779 /* default for add -> make right operand to index */
782 consumed_left_shift = -1;
784 DBG((dbg, LEVEL_1, "\tgot LEA candidate with index %+F\n", index));
786 /* determine the operand which needs to be checked */
788 if (is_ia32_Lea(left)) {
790 consumed_left_shift = 0;
793 /* check for SHL 1,2,3 */
794 if (pred_is_specific_node(temp, is_ia32_Shl)) {
795 ir_node *right = get_irn_n(temp, n_ia32_Shl_right);
797 if (is_ia32_Immediate(right)) {
798 const ia32_immediate_attr_t *attr
799 = get_ia32_immediate_attr_const(right);
800 long shiftval = attr->offset;
803 index = get_irn_n(temp, 2);
804 consumed_left_shift = consumed_left_shift < 0 ? 1 : 0;
808 DBG((dbg, LEVEL_1, "\tgot scaled index %+F\n", index));
814 if (! be_is_NoReg(cg, index)) {
815 /* if we have index, but left == right -> no base */
819 else if (consumed_left_shift == 1) {
820 /* -> base is right operand */
821 base = (right == lea_o) ? noreg : right;
826 /* Try to assimilate a LEA as left operand */
827 if (is_ia32_Lea(left) && (get_ia32_am_flavour(left) != ia32_am_O)) {
828 /* check if we can assimilate the LEA */
829 int take_attr = do_new_lea(irn, base, index, left, have_am_sc, cg);
831 if (take_attr == IA32_LEA_ATTR_NONE) {
832 DBG((dbg, LEVEL_1, "\tleave old LEA, creating new one\n"));
835 DBG((dbg, LEVEL_1, "\tgot LEA as left operand ... assimilating\n"));
836 lea = left; /* for statistics */
838 if (take_attr & IA32_LEA_ATTR_OFFS)
839 offs = get_ia32_am_offs_int(left);
841 if (take_attr & IA32_LEA_ATTR_AMSC) {
842 am_sc = get_ia32_am_sc(left);
844 am_sc_sign = is_ia32_am_sc_sign(left);
847 if (take_attr & IA32_LEA_ATTR_SCALE)
848 scale = get_ia32_am_scale(left);
850 if (take_attr & IA32_LEA_ATTR_BASE)
851 base = get_irn_n(left, 0);
853 if (take_attr & IA32_LEA_ATTR_INDEX)
854 index = get_irn_n(left, 1);
856 if (take_attr & IA32_LEA_ATTR_FENT)
857 lea_ent = get_ia32_frame_ent(left);
861 /* ok, we can create a new LEA */
863 res = new_rd_ia32_Lea(dbg_info, irg, block, base, index);
864 /* we don't want stuff before the barrier... */
865 if(be_is_NoReg(cg, base) && be_is_NoReg(cg, index)) {
866 add_irn_dep(res, get_irg_frame(irg));
869 /* add the old offset of a previous LEA */
870 add_ia32_am_offs_int(res, offs);
872 /* add the new offset */
874 add_ia32_am_offs_int(res, offs_cnst);
875 add_ia32_am_offs_int(res, offs_lea);
877 /* either lea_O-cnst, -cnst or -lea_O */
878 if (offs_cnst != 0) {
879 add_ia32_am_offs_int(res, offs_lea);
880 add_ia32_am_offs_int(res, -offs_cnst);
882 add_ia32_am_offs_int(res, offs_lea);
886 /* set the address mode symconst */
888 set_ia32_am_sc(res, am_sc);
890 set_ia32_am_sc_sign(res);
893 /* copy the frame entity (could be set in case of Add */
894 /* which was a FrameAddr) */
895 if (lea_ent != NULL) {
896 set_ia32_frame_ent(res, lea_ent);
897 set_ia32_use_frame(res);
899 set_ia32_frame_ent(res, get_ia32_frame_ent(irn));
900 if(is_ia32_use_frame(irn))
901 set_ia32_use_frame(res);
905 set_ia32_am_scale(res, scale);
908 /* determine new am flavour */
909 if (offs || offs_cnst || offs_lea || have_am_sc) {
912 if (! be_is_NoReg(cg, base)) {
915 if (! be_is_NoReg(cg, index)) {
921 set_ia32_am_flavour(res, am_flav);
923 set_ia32_op_type(res, ia32_AddrModeS);
925 SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(cg, irn));
927 DBG((dbg, LEVEL_1, "\tLEA [%+F + %+F * %d + %d]\n", base, index, scale, get_ia32_am_offs_int(res)));
929 assert(irn && "Couldn't find result proj");
931 /* get the result Proj of the Add/Sub */
932 try_add_to_sched(irn, res);
934 /* exchange the old op with the new LEA */
938 /* we will exchange it, report here before the Proj is created */
939 if (shift && lea && lea_o) {
943 DBG_OPT_LEA4(irn, lea_o, lea, shift, res);
944 } else if (shift && lea) {
947 DBG_OPT_LEA3(irn, lea, shift, res);
948 } else if (shift && lea_o) {
951 DBG_OPT_LEA3(irn, lea_o, shift, res);
952 } else if (lea && lea_o) {
955 DBG_OPT_LEA3(irn, lea_o, lea, res);
958 DBG_OPT_LEA2(irn, shift, res);
961 DBG_OPT_LEA2(irn, lea, res);
964 DBG_OPT_LEA2(irn, lea_o, res);
966 DBG_OPT_LEA1(irn, res);
975 * Merges a Load/Store node with a LEA.
976 * @param irn The Load/Store node
979 static void merge_loadstore_lea(ir_node *irn, ir_node *lea) {
980 ir_entity *irn_ent = get_ia32_frame_ent(irn);
981 ir_entity *lea_ent = get_ia32_frame_ent(lea);
983 /* If the irn and the LEA both have a different frame entity set: do not merge */
984 if (irn_ent != NULL && lea_ent != NULL && (irn_ent != lea_ent))
986 else if (irn_ent == NULL && lea_ent != NULL) {
987 set_ia32_frame_ent(irn, lea_ent);
988 set_ia32_use_frame(irn);
991 /* get the AM attributes from the LEA */
992 add_ia32_am_offs_int(irn, get_ia32_am_offs_int(lea));
993 set_ia32_am_scale(irn, get_ia32_am_scale(lea));
994 set_ia32_am_flavour(irn, get_ia32_am_flavour(lea));
996 set_ia32_am_sc(irn, get_ia32_am_sc(lea));
997 if (is_ia32_am_sc_sign(lea))
998 set_ia32_am_sc_sign(irn);
1000 set_ia32_op_type(irn, is_ia32_Ld(irn) ? ia32_AddrModeS : ia32_AddrModeD);
1002 /* set base and index */
1003 set_irn_n(irn, 0, get_irn_n(lea, 0));
1004 set_irn_n(irn, 1, get_irn_n(lea, 1));
1008 /* clear remat flag */
1009 set_ia32_flags(irn, get_ia32_flags(irn) & ~arch_irn_flags_rematerializable);
1011 if (is_ia32_Ld(irn))
1012 DBG_OPT_LOAD_LEA(lea, irn);
1014 DBG_OPT_STORE_LEA(lea, irn);
1019 * Sets new_right index of irn to right and new_left index to left.
1020 * Also exchange left and right
1022 static void exchange_left_right(ir_node *irn, ir_node **left, ir_node **right,
1023 int new_left, int new_right)
1027 assert(is_ia32_commutative(irn));
1029 set_irn_n(irn, new_right, *right);
1030 set_irn_n(irn, new_left, *left);
1036 /* this is only needed for Compares, but currently ALL nodes
1037 * have this attribute :-) */
1038 set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn)));
1042 * Performs address calculation optimization (create LEAs if possible)
1044 static void optimize_lea(ia32_code_gen_t *cg, ir_node *irn) {
1045 if (! is_ia32_irn(irn))
1048 /* Following cases can occur: */
1049 /* - Sub (l, imm) -> LEA [base - offset] */
1050 /* - Sub (l, r == LEA with ia32_am_O) -> LEA [base - offset] */
1051 /* - Add (l, imm) -> LEA [base + offset] */
1052 /* - Add (l, r == LEA with ia32_am_O) -> LEA [base + offset] */
1053 /* - Add (l == LEA with ia32_am_O, r) -> LEA [base + offset] */
1054 /* - Add (l, r) -> LEA [base + index * scale] */
1055 /* with scale > 1 iff l/r == shl (1,2,3) */
1056 if (is_ia32_Sub(irn) || is_ia32_Add(irn)) {
1059 if(!is_addr_candidate(irn))
1062 DBG((dbg, LEVEL_1, "\tfound address calculation candidate %+F ... ", irn));
1063 res = fold_addr(cg, irn);
1066 DB((dbg, LEVEL_1, "transformed into %+F\n", res));
1068 DB((dbg, LEVEL_1, "not transformed\n"));
1069 } else if (is_ia32_Ld(irn) || is_ia32_St(irn)) {
1070 /* - Load -> LEA into Load } TODO: If the LEA is used by more than one Load/Store */
1071 /* - Store -> LEA into Store } it might be better to keep the LEA */
1072 ir_node *left = get_irn_n(irn, 0);
1074 if (is_ia32_Lea(left)) {
1075 const ir_edge_t *edge, *ne;
1078 /* merge all Loads/Stores connected to this LEA with the LEA */
1079 foreach_out_edge_safe(left, edge, ne) {
1080 src = get_edge_src_irn(edge);
1082 if (src && (get_edge_src_pos(edge) == 0) && (is_ia32_Ld(src) || is_ia32_St(src))) {
1083 DBG((dbg, LEVEL_1, "\nmerging %+F into %+F\n", left, irn));
1084 if (! is_ia32_got_lea(src))
1085 merge_loadstore_lea(src, left);
1086 set_ia32_got_lea(src);
1093 static void optimize_conv_store(ir_node *node)
1097 ir_mode *store_mode;
1099 if(!is_ia32_Store(node) && !is_ia32_Store8Bit(node))
1102 pred = get_irn_n(node, 2);
1103 if(!is_ia32_Conv_I2I(pred) && !is_ia32_Conv_I2I8Bit(pred))
1106 /* the store only stores the lower bits, so we only need the conv
1107 * it it shrinks the mode */
1108 conv_mode = get_ia32_ls_mode(pred);
1109 store_mode = get_ia32_ls_mode(node);
1110 if(get_mode_size_bits(conv_mode) < get_mode_size_bits(store_mode))
1113 set_irn_n(node, 2, get_irn_n(pred, 2));
1114 if(get_irn_n_edges(pred) == 0) {
1119 static void optimize_load_conv(ir_node *node)
1121 ir_node *pred, *predpred;
1125 if (!is_ia32_Conv_I2I(node) && !is_ia32_Conv_I2I8Bit(node))
1128 pred = get_irn_n(node, 2);
1132 predpred = get_Proj_pred(pred);
1133 if(!is_ia32_Load(predpred))
1136 /* the load is sign extending the upper bits, so we only need the conv
1137 * if it shrinks the mode */
1138 load_mode = get_ia32_ls_mode(predpred);
1139 conv_mode = get_ia32_ls_mode(node);
1140 if(get_mode_size_bits(conv_mode) < get_mode_size_bits(load_mode))
1143 if(get_mode_sign(conv_mode) != get_mode_sign(load_mode)) {
1144 /* change the load if it has only 1 user */
1145 if(get_irn_n_edges(pred) == 1) {
1147 if(get_mode_sign(conv_mode)) {
1148 newmode = find_signed_mode(load_mode);
1150 newmode = find_unsigned_mode(load_mode);
1152 assert(newmode != NULL);
1153 set_ia32_ls_mode(predpred, newmode);
1155 /* otherwise we have to keep the conv */
1161 exchange(node, pred);
1164 static void optimize_conv_conv(ir_node *node)
1170 if (!is_ia32_Conv_I2I(node) && !is_ia32_Conv_I2I8Bit(node))
1173 assert(n_ia32_Conv_I2I_val == n_ia32_Conv_I2I8Bit_val);
1174 pred = get_irn_n(node, n_ia32_Conv_I2I_val);
1175 if(!is_ia32_Conv_I2I(pred) && !is_ia32_Conv_I2I8Bit(pred))
1178 /* we know that after a conv, the upper bits are sign extended
1179 * so we only need the 2nd conv if it shrinks the mode */
1180 conv_mode = get_ia32_ls_mode(node);
1181 pred_mode = get_ia32_ls_mode(pred);
1182 if(get_mode_size_bits(conv_mode) < get_mode_size_bits(pred_mode))
1185 ir_fprintf(stderr, "Optimize: c1:%+F c2:%+F\n", pred_mode, conv_mode);
1187 /* adjust for signedness */
1188 ir_node *result_conv;
1189 if(get_mode_sign(conv_mode) != get_mode_sign(pred_mode)) {
1191 if(mode_is_signed(conv_mode)) {
1192 mode = find_signed_mode(pred_mode);
1194 mode = find_unsigned_mode(pred_mode);
1197 result_conv = exact_copy(pred);
1198 set_ia32_ls_mode(result_conv, mode);
1203 ir_fprintf(stderr, "Replaced with %+F\n", get_ia32_ls_mode(result_conv));
1206 exchange(node, result_conv);
1208 if(get_irn_n_edges(pred) == 0) {
1213 static void optimize_node(ir_node *node, void *env)
1215 ia32_code_gen_t *cg = env;
1217 optimize_load_conv(node);
1218 optimize_conv_store(node);
1219 optimize_conv_conv(node);
1220 optimize_lea(cg, node);
1224 * Checks for address mode patterns and performs the
1225 * necessary transformations.
1226 * This function is called by a walker.
1228 static void optimize_am(ir_node *irn, void *env) {
1229 ia32_am_opt_env_t *am_opt_env = env;
1230 ia32_code_gen_t *cg = am_opt_env->cg;
1231 ir_graph *irg = get_irn_irg(irn);
1232 heights_t *h = am_opt_env->h;
1233 ir_node *block, *left, *right;
1234 ir_node *store, *load, *mem_proj;
1235 ir_node *addr_b, *addr_i;
1236 int need_exchange_on_fail = 0;
1237 ia32_am_type_t am_support;
1238 ia32_am_arity_t am_arity;
1239 ia32_am_cand_t cand;
1240 ia32_am_cand_t orig_cand;
1242 int source_possible;
1244 static const arch_register_req_t dest_out_reg_req_0 = {
1245 arch_register_req_type_none,
1246 NULL, /* regclass */
1247 NULL, /* limit bitset */
1249 -1 /* different pos */
1251 static const arch_register_req_t *dest_am_out_reqs[] = {
1255 if (!is_ia32_irn(irn) || is_ia32_Ld(irn) || is_ia32_St(irn))
1257 if (is_ia32_Lea(irn))
1260 am_support = get_ia32_am_support(irn);
1261 am_arity = get_ia32_am_arity(irn);
1262 block = get_nodes_block(irn);
1264 /* fold following patterns:
1265 * - op -> Load into AMop with am_Source
1267 * - op is am_Source capable AND
1268 * - the Load is only used by this op AND
1269 * - the Load is in the same block
1270 * - Store -> op -> Load into AMop with am_Dest
1272 * - op is am_Dest capable AND
1273 * - the Store uses the same address as the Load AND
1274 * - the Load is only used by this op AND
1275 * - the Load and Store are in the same block AND
1276 * - nobody else uses the result of the op
1278 if (am_support == ia32_am_None)
1281 assert(am_arity == ia32_am_unary || am_arity == ia32_am_binary);
1283 cand = is_am_candidate(h, block, irn);
1284 if (cand == IA32_AM_CAND_NONE)
1288 DBG((dbg, LEVEL_1, "\tfound address mode candidate %+F (candleft %d candright %d)... \n", irn,
1289 cand & IA32_AM_CAND_LEFT, cand & IA32_AM_CAND_RIGHT));
1291 left = get_irn_n(irn, 2);
1292 if (am_arity == ia32_am_unary) {
1293 assert(get_irn_arity(irn) >= 4);
1295 assert(cand == IA32_AM_CAND_BOTH);
1297 assert(get_irn_arity(irn) >= 5);
1298 right = get_irn_n(irn, 3);
1301 dest_possible = am_support & ia32_am_Dest ? 1 : 0;
1302 source_possible = am_support & ia32_am_Source ? 1 : 0;
1304 DBG((dbg, LEVEL_2, "\tdest_possible %d source_possible %d ... \n", dest_possible, source_possible));
1306 if (dest_possible) {
1311 /* we should only have 1 user which is a store */
1312 if (ia32_get_irn_n_edges(irn) == 1) {
1313 ir_node *succ = get_edge_src_irn(get_irn_out_edge_first(irn));
1315 if (is_ia32_xStore(succ) || is_ia32_Store(succ)) {
1317 addr_b = get_irn_n(store, 0);
1318 addr_i = get_irn_n(store, 1);
1322 if (store == NULL) {
1323 DBG((dbg, LEVEL_2, "\tno store found, not using dest_mode\n"));
1328 if (dest_possible) {
1329 /* normalize nodes, we need the interesting load on the left side */
1330 if (cand & IA32_AM_CAND_RIGHT) {
1331 load = get_Proj_pred(right);
1332 if (load_store_addr_is_equal(load, store, addr_b, addr_i)
1333 && node_is_ia32_comm(irn)) {
1334 DBG((dbg, LEVEL_2, "\texchanging left/right\n"));
1335 exchange_left_right(irn, &left, &right, 3, 2);
1336 need_exchange_on_fail ^= 1;
1337 if (cand == IA32_AM_CAND_RIGHT)
1338 cand = IA32_AM_CAND_LEFT;
1343 if (dest_possible) {
1344 if(cand & IA32_AM_CAND_LEFT && is_Proj(left)) {
1345 load = get_Proj_pred(left);
1347 #ifndef AGGRESSIVE_AM
1348 /* we have to be the only user of the load */
1349 if (get_irn_n_edges(left) > 1) {
1350 DBG((dbg, LEVEL_2, "\tmatching load has too may users, not using dest_mode\n"));
1355 DBG((dbg, LEVEL_2, "\tno matching load found, not using dest_mode"));
1360 if (dest_possible) {
1361 /* the store has to use the loads memory or the same memory
1363 ir_node *loadmem = get_irn_n(load, 2);
1364 ir_node *storemem = get_irn_n(store, 3);
1365 assert(get_irn_mode(loadmem) == mode_M);
1366 assert(get_irn_mode(storemem) == mode_M);
1367 /* TODO there could be a sync between store and load... */
1368 if(storemem != loadmem && (!is_Proj(storemem) || get_Proj_pred(storemem) != load)) {
1369 DBG((dbg, LEVEL_2, "\tload/store using different memories, not using dest_mode"));
1374 if (dest_possible) {
1375 /* Compare Load and Store address */
1376 if (!load_store_addr_is_equal(load, store, addr_b, addr_i)) {
1377 DBG((dbg, LEVEL_2, "\taddresses not equal, not using dest_mode"));
1382 if (dest_possible) {
1383 ir_mode *lsmode = get_ia32_ls_mode(load);
1384 if(get_mode_size_bits(lsmode) != 32) {
1389 if (dest_possible) {
1390 /* all conditions fullfilled, do the transformation */
1391 assert(cand & IA32_AM_CAND_LEFT);
1393 /* set new base, index and attributes */
1394 set_irn_n(irn, 0, addr_b);
1395 set_irn_n(irn, 1, addr_i);
1396 add_ia32_am_offs_int(irn, get_ia32_am_offs_int(load));
1397 set_ia32_am_scale(irn, get_ia32_am_scale(load));
1398 set_ia32_am_flavour(irn, get_ia32_am_flavour(load));
1399 set_ia32_op_type(irn, ia32_AddrModeD);
1400 set_ia32_frame_ent(irn, get_ia32_frame_ent(load));
1401 set_ia32_ls_mode(irn, get_ia32_ls_mode(load));
1403 set_ia32_am_sc(irn, get_ia32_am_sc(load));
1404 if (is_ia32_am_sc_sign(load))
1405 set_ia32_am_sc_sign(irn);
1407 /* connect to Load memory and disconnect Load */
1408 if (am_arity == ia32_am_binary) {
1410 set_irn_n(irn, 4, get_irn_n(load, 2));
1411 set_irn_n(irn, 2, ia32_get_admissible_noreg(cg, irn, 2));
1414 set_irn_n(irn, 3, get_irn_n(load, 2));
1415 set_irn_n(irn, 2, ia32_get_admissible_noreg(cg, irn, 2));
1418 /* change node mode and out register requirements */
1419 set_irn_mode(irn, mode_M);
1420 set_ia32_out_req_all(irn, dest_am_out_reqs);
1422 /* connect the memory Proj of the Store to the op */
1423 edges_reroute(store, irn, irg);
1425 /* clear remat flag */
1426 set_ia32_flags(irn, get_ia32_flags(irn) & ~arch_irn_flags_rematerializable);
1430 DBG_OPT_AM_D(load, store, irn);
1432 DB((dbg, LEVEL_1, "merged with %+F and %+F into dest AM\n", load, store));
1433 need_exchange_on_fail = 0;
1434 source_possible = 0;
1437 if (source_possible) {
1438 /* normalize ops, we need the load on the right */
1439 if(cand == IA32_AM_CAND_LEFT) {
1440 if(node_is_ia32_comm(irn)) {
1441 exchange_left_right(irn, &left, &right, 3, 2);
1442 need_exchange_on_fail ^= 1;
1443 cand = IA32_AM_CAND_RIGHT;
1445 source_possible = 0;
1450 if (source_possible) {
1451 /* all conditions fullfilled, do transform */
1452 assert(cand & IA32_AM_CAND_RIGHT);
1453 load = get_Proj_pred(right);
1455 if(get_irn_n_edges(right) > 1) {
1456 source_possible = 0;
1458 /* TODO: this isn't really needed, but the code below is buggy
1459 as heights won't get recomputed when the graph is reconstructed
1460 so we can only transform loads with the result proj only */
1461 if(get_irn_n_edges(load) > 1) {
1462 source_possible = 0;
1466 if (source_possible) {
1467 ir_mode *ls_mode = get_ia32_ls_mode(load);
1468 if(get_mode_size_bits(ls_mode) != 32 || ls_mode == mode_D)
1469 source_possible = 0;
1473 if (source_possible) {
1474 addr_b = get_irn_n(load, 0);
1475 addr_i = get_irn_n(load, 1);
1477 /* set new base, index and attributes */
1478 set_irn_n(irn, 0, addr_b);
1479 set_irn_n(irn, 1, addr_i);
1480 add_ia32_am_offs_int(irn, get_ia32_am_offs_int(load));
1481 set_ia32_am_scale(irn, get_ia32_am_scale(load));
1482 set_ia32_am_flavour(irn, get_ia32_am_flavour(load));
1483 set_ia32_op_type(irn, ia32_AddrModeS);
1484 set_ia32_frame_ent(irn, get_ia32_frame_ent(load));
1486 /* set ls_mode if not already present (conv nodes already have ls_mode
1488 if(get_ia32_ls_mode(irn) == NULL) {
1489 set_ia32_ls_mode(irn, get_ia32_ls_mode(load));
1492 set_ia32_am_sc(irn, get_ia32_am_sc(load));
1493 if (is_ia32_am_sc_sign(load))
1494 set_ia32_am_sc_sign(irn);
1496 /* clear remat flag */
1497 set_ia32_flags(irn, get_ia32_flags(irn) & ~arch_irn_flags_rematerializable);
1499 if (is_ia32_use_frame(load)) {
1500 if(get_ia32_frame_ent(load) == NULL) {
1501 set_ia32_need_stackent(irn);
1503 set_ia32_use_frame(irn);
1506 /* connect to Load memory and disconnect Load */
1507 if (am_arity == ia32_am_binary) {
1509 right = ia32_get_admissible_noreg(cg, irn, 3);
1510 set_irn_n(irn, 3, right);
1511 set_irn_n(irn, 4, get_irn_n(load, n_ia32_Load_mem));
1514 right = ia32_get_admissible_noreg(cg, irn, 2);
1515 set_irn_n(irn, 2, right);
1516 set_irn_n(irn, 3, get_irn_n(load, n_ia32_Load_mem));
1519 DBG_OPT_AM_S(load, irn);
1521 /* If Load has a memory Proj, connect it to the op */
1522 mem_proj = ia32_get_proj_for_mode(load, mode_M);
1523 if (mem_proj != NULL) {
1525 ir_mode *mode = get_irn_mode(irn);
1527 if(mode != mode_T) {
1528 res_proj = new_rd_Proj(get_irn_dbg_info(irn), irg,
1529 get_nodes_block(irn),
1530 new_Unknown(mode_T), mode, 0);
1531 set_irn_mode(irn, mode_T);
1532 edges_reroute(irn, res_proj, irg);
1533 set_Proj_pred(res_proj, irn);
1535 set_Proj_pred(mem_proj, irn);
1536 set_Proj_proj(mem_proj, 1);
1538 /* hacky: we need some proj number which is not used yet... */
1539 set_Proj_proj(mem_proj, -1);
1540 set_Proj_pred(mem_proj, irn);
1545 need_exchange_on_fail = 0;
1547 /* immediate are only allowed on the right side */
1548 if(is_ia32_Immediate(left)) {
1549 exchange_left_right(irn, &left, &right, 3, 2);
1552 DB((dbg, LEVEL_1, "merged with %+F into source AM\n", load));
1555 /* was exchanged but optimize failed: exchange back */
1556 if (need_exchange_on_fail) {
1557 exchange_left_right(irn, &left, &right, 3, 2);
1562 * Performs conv and address mode optimization.
1564 void ia32_optimize_graph(ia32_code_gen_t *cg) {
1565 /* if we are supposed to do AM or LEA optimization: recalculate edges */
1566 if (! (cg->opt & (IA32_OPT_DOAM | IA32_OPT_LEA))) {
1567 /* no optimizations at all */
1571 /* beware: we cannot optimize LEA and AM in one run because */
1572 /* LEA optimization adds new nodes to the irg which */
1573 /* invalidates the phase data */
1575 if (cg->opt & IA32_OPT_LEA) {
1576 irg_walk_blkwise_graph(cg->irg, NULL, optimize_node, cg);
1580 be_dump(cg->irg, "-lea", dump_ir_block_graph_sched);
1582 /* hack for now, so these don't get created during optimize, because then
1583 * they will be unknown to the heights module
1585 ia32_new_NoReg_gp(cg);
1586 ia32_new_NoReg_fp(cg);
1587 ia32_new_NoReg_vfp(cg);
1589 if (cg->opt & IA32_OPT_DOAM) {
1590 /* we need height information for am optimization */
1591 heights_t *h = heights_new(cg->irg);
1592 ia32_am_opt_env_t env;
1597 irg_walk_blkwise_graph(cg->irg, NULL, optimize_am, &env);
1603 void ia32_init_optimize(void)
1605 FIRM_DBG_REGISTER(dbg, "firm.be.ia32.optimize");