introduce more generic resource reservation debug helpers instead of old set_using_xx...
[libfirm] / ir / be / ia32 / bearch_ia32.c
index 215872f..e52ee6d 100644 (file)
@@ -927,6 +927,15 @@ static void ia32_before_abi(void *self) {
        }
 }
 
+typedef enum transformer_t {
+       TRANSFORMER_DEFAULT,
+#ifdef FIRM_GRGEN_BE
+       TRANSFORMER_PBQP
+#endif
+} transformer_t;
+
+static transformer_t be_transformer = TRANSFORMER_DEFAULT;
+
 /**
  * Transforms the standard firm graph into
  * an ia32 firm graph
@@ -948,22 +957,29 @@ static void ia32_prepare_graph(void *self) {
        if (cg->dump)
                be_dump(cg->irg, "-pre_transform", dump_ir_block_graph_sched);
 
-#ifdef FIRM_GRGEN_BE
-       // disable CSE, because of two-step node-construction
-       set_opt_cse(0);
+       switch (be_transformer) {
+               case TRANSFORMER_DEFAULT:
+                       /* transform remaining nodes into assembler instructions */
+                       ia32_transform_graph(cg);
+                       break;
 
-       /* transform nodes into assembler instructions by PBQP magic */
-       ia32_transform_graph_by_pbqp(cg);
+#ifdef FIRM_GRGEN_BE
+               case TRANSFORMER_PBQP:
+                       // disable CSE, because of two-step node-construction
+                       set_opt_cse(0);
 
-       if (cg->dump)
-               be_dump(cg->irg, "-after_pbqp_transform", dump_ir_block_graph_sched);
-       set_opt_cse(1);
-#else
+                       /* transform nodes into assembler instructions by PBQP magic */
+                       ia32_transform_graph_by_pbqp(cg);
 
-       /* transform remaining nodes into assembler instructions */
-       ia32_transform_graph(cg);
+                       if (cg->dump)
+                               be_dump(cg->irg, "-after_pbqp_transform", dump_ir_block_graph_sched);
+                       set_opt_cse(1);
+                       break;
 #endif
 
+               default: panic("Invalid transformer");
+       }
+
        /* do local optimizations (mainly CSE) */
        optimize_graph_df(cg->irg);
 
@@ -1848,7 +1864,9 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
        ir_mode  *mode;
        unsigned  cc;
        int       n, i, regnum;
+       int                 pop_amount = 0;
        be_abi_call_flags_t call_flags = be_abi_call_get_flags(abi);
+
        (void) self;
 
        /* set abi flags for calls */
@@ -1866,8 +1884,9 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
                cc = cc_cdecl_set;
        } else {
                cc = get_method_calling_convention(method_type);
-               if (get_method_additional_properties(method_type) & mtp_property_private
-                               && (ia32_cg_config.optimize_cc)) {
+               if (!(cc & cc_fixed)                                                     &&
+                   get_method_additional_properties(method_type) & mtp_property_private &&
+                   ia32_cg_config.optimize_cc) {
                        /* set the calling conventions to register parameter */
                        cc = (cc & ~cc_bits) | cc_reg_param;
                }
@@ -1876,7 +1895,7 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
        /* we have to pop the shadow parameter ourself for compound calls */
        if( (get_method_calling_convention(method_type) & cc_compound_ret)
                        && !(cc & cc_reg_param)) {
-               be_abi_call_set_pop(abi, get_mode_size_bytes(mode_P_data));
+               pop_amount += get_mode_size_bytes(mode_P_data);
        }
 
        n = get_method_n_params(method_type);
@@ -1895,12 +1914,21 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
                } else {
                        /* Micro optimisation: if the mode is shorter than 4 bytes, load 4 bytes.
                         * movl has a shorter opcode than mov[sz][bw]l */
-                       ir_mode *load_mode = mode;
-                       if (mode != NULL && get_mode_size_bytes(mode) < 4) load_mode = mode_Iu;
+                       ir_mode  *load_mode = mode;
+                       unsigned  size      = get_mode_size_bytes(mode);
+
+                       if (cc & cc_callee_clear_stk) {
+                               pop_amount += (size + 3U) & ~3U;
+                       }
+
+                       if (mode != NULL && size < 4) load_mode = mode_Iu;
+
                        be_abi_call_param_stack(abi, i, load_mode, 4, 0, 0);
                }
        }
 
+       be_abi_call_set_pop(abi, pop_amount);
+
        /* set return registers */
        n = get_method_n_ress(method_type);
 
@@ -2284,8 +2312,21 @@ static lc_opt_enum_int_var_t gas_var = {
        (int*) &be_gas_flavour, gas_items
 };
 
+static const lc_opt_enum_int_items_t transformer_items[] = {
+       { "default", TRANSFORMER_DEFAULT },
+#ifdef FIRM_GRGEN_BE
+       { "pbqp",    TRANSFORMER_PBQP    },
+#endif
+       { NULL,      0                   }
+};
+
+static lc_opt_enum_int_var_t transformer_var = {
+       (int*)&be_transformer, transformer_items
+};
+
 static const lc_opt_table_entry_t ia32_options[] = {
        LC_OPT_ENT_ENUM_INT("gasmode", "set the GAS compatibility mode", &gas_var),
+       LC_OPT_ENT_ENUM_INT("transformer", "the transformer used for code selection", &transformer_var),
        LC_OPT_ENT_INT("stackalign", "set power of two stack alignment for calls",
                       &ia32_isa_template.arch_env.stack_alignment),
        LC_OPT_LAST