register slots are now automatically allocated together with the $ARCH_attribute
[libfirm] / ir / be / ia32 / ia32_optimize.c
index bcd7315..769bebb 100644 (file)
@@ -92,7 +92,9 @@ static ir_node *gen_SymConst(ia32_transform_env_t *env) {
        }
        else
                cnst = new_rd_ia32_Const(dbg, irg, block, get_irg_no_mem(irg), mode);
+
        set_ia32_Const_attr(cnst, env->irn);
+
        return cnst;
 }
 
@@ -440,6 +442,10 @@ static void ia32_create_Push(ir_node *irn, ia32_code_gen_t *cg) {
        proj_res = new_r_Proj(current_ir_graph, bl, push, get_irn_mode(sp), pn_ia32_Push_stack);
        proj_M   = new_r_Proj(current_ir_graph, bl, push, mode_M, pn_ia32_Push_M);
 
+       /* copy a possible constant from the store */
+       set_ia32_id_cnst(push, get_ia32_id_cnst(irn));
+       set_ia32_immop_type(push, get_ia32_immop_type(irn));
+
        /* the push must have SP out register */
        arch_set_irn_register(cg->arch_env, push, arch_get_irn_register(cg->arch_env, sp));
 
@@ -552,8 +558,11 @@ void ia32_peephole_optimization(ir_node *irn, void *env) {
                ia32_optimize_TestJmp(irn, cg);
        else if (is_ia32_CondJmp(irn))
                ia32_optimize_CondJmp(irn, cg);
-       else if (be_is_IncSP(irn))
-               ia32_optimize_IncSP(irn, cg);
+       /* seems to be buggy when using Pushes */
+//     else if (be_is_IncSP(irn))
+//             ia32_optimize_IncSP(irn, cg);
+       else if (is_ia32_Store(irn))
+               ia32_create_Push(irn, cg);
 }
 
 
@@ -1182,6 +1191,25 @@ static void merge_loadstore_lea(ir_node *irn, ir_node *lea) {
 
 }
 
+/**
+ * Sets new_right index of irn to right and new_left index to left.
+ * Also exchange left and right
+ */
+static void exchange_left_right(ir_node *irn, ir_node **left, ir_node **right, int new_left, int new_right) {
+       ir_node *temp;
+
+       set_irn_n(irn, new_right, *right);
+       set_irn_n(irn, new_left, *left);
+
+       temp   = *left;
+       *left  = *right;
+       *right = temp;
+
+       /* this is only needed for Compares, but currently ALL nodes
+        * have this attribute :-) */
+       set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn)));
+}
+
 /**
  * Optimizes a pattern around irn to address mode if possible.
  */
@@ -1194,7 +1222,8 @@ void ia32_optimize_am(ir_node *irn, void *env) {
        ir_node           *left, *right, *temp;
        ir_node           *store, *load, *mem_proj;
        ir_node           *succ, *addr_b, *addr_i;
-       int                check_am_src = 0;
+       int               check_am_src = 0;
+       int               need_exchange_on_fail = 0;
        DEBUG_ONLY(firm_dbg_module_t *mod = cg->mod;)
 
        if (! is_ia32_irn(irn))
@@ -1292,16 +1321,8 @@ void ia32_optimize_am(ir_node *irn, void *env) {
                                /* operand is a load, so we only need to check right operand.    */
                                if (pred_is_specific_nodeblock(block, left, is_ia32_Ld))
                                {
-                                       set_irn_n(irn, 2, right);
-                                       set_irn_n(irn, 3, left);
-
-                                       temp  = left;
-                                       left  = right;
-                                       right = temp;
-
-                                       /* this is only needed for Compares, but currently ALL nodes
-                                        * have this attribute :-) */
-                                       set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn)));
+                                       exchange_left_right(irn, &left, &right, 3, 2);
+                                       need_exchange_on_fail = 1;
                                }
                        }
 
@@ -1422,6 +1443,12 @@ void ia32_optimize_am(ir_node *irn, void *env) {
                                check_am_src = 1;
                        }
 
+                       /* was exchanged but optimize failed: exchange back */
+                       if (check_am_src && need_exchange_on_fail)
+                               exchange_left_right(irn, &left, &right, 3, 2);
+
+                       need_exchange_on_fail = 0;
+
                        /* normalize commutative ops */
                        if (check_am_src && node_is_ia32_comm(irn)) {
                                /* Assure that left operand is always a Load if there is one */
@@ -1429,16 +1456,8 @@ void ia32_optimize_am(ir_node *irn, void *env) {
                                /* left operand is a Load, so we only need to check the left */
                                /* operand afterwards.                                       */
                                if (pred_is_specific_nodeblock(block, right, is_ia32_Ld))       {
-                                       set_irn_n(irn, 2, right);
-                                       set_irn_n(irn, 3, left);
-
-                                       temp  = left;
-                                       left  = right;
-                                       right = temp;
-
-                                       /* this is only needed for Compares, but currently ALL nodes
-                                        * have this attribute :-) */
-                                       set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn)));
+                                       exchange_left_right(irn, &left, &right, 3, 2);
+                                       need_exchange_on_fail = 1;
                                }
                        }
 
@@ -1506,6 +1525,11 @@ void ia32_optimize_am(ir_node *irn, void *env) {
 
                                DB((mod, LEVEL_1, "merged with %+F into source AM\n", left));
                        }
+                       else {
+                               /* was exchanged but optimize failed: exchange back */
+                               if (need_exchange_on_fail)
+                                       exchange_left_right(irn, &left, &right, 3, 2);
+                       }
                }
        }
 }