#include <stdlib.h>
#include <string.h>
#include <libfirm/firm.h>
-
-#ifdef FIRM_BACKEND
#include <libfirm/be.h>
-#endif /* FIRM_BACKEND */
#include "firm_opt.h"
#include "firm_cmdline.h"
#include "firm_timing.h"
+#ifdef _WIN32
+#define snprintf _snprintf
+#endif
+
#if defined(_DEBUG) || defined(FIRM_DEBUG)
#define DBG(x) dbg_printf x
#else
static void *create_intrinsic_ctx = NULL;
static const ir_settings_if_conv_t *if_conv_info = NULL;
+ir_mode *firm_imm_fp_mode = NULL;
+
/* entities of runtime functions */
ir_entity_ptr rts_entities[rts_max];
} mapper[] = {
/* integer */
{ &rts_entities[rts_abs], i_mapper_abs },
+ { &rts_entities[rts_alloca], i_mapper_alloca },
{ &rts_entities[rts_labs], i_mapper_abs },
{ &rts_entities[rts_llabs], i_mapper_abs },
{ &rts_entities[rts_imaxabs], i_mapper_abs },
i_record rec[sizeof(mapper)/sizeof(mapper[0])];
unsigned i, n_map;
- for (i = n_map = 0; i < sizeof(mapper)/sizeof(mapper[0]); ++i)
+ for (i = n_map = 0; i < sizeof(mapper)/sizeof(mapper[0]); ++i) {
if (*mapper[i].ent != NULL) {
rec[n_map].i_call.kind = INTRINSIC_CALL;
rec[n_map].i_call.i_ent = *mapper[i].ent;
rec[n_map].i_call.ctx = NULL;
rec[n_map].i_call.link = NULL;
++n_map;
- } /* if */
+ } /* if */
+ }
if (n_map > 0)
lower_intrinsics(rec, n_map, /* part_block_used=*/0);
} /* rts_map */
ir_graph *irg;
unsigned aa_opt;
+ /* FIXME: cloning might ADD new graphs. */
irg_dump_no = calloc(get_irp_last_idx(), sizeof(*irg_dump_no));
set_opt_strength_red(firm_opt.strength_red);
CHECK_ALL(firm_opt.check_all);
}
- if (firm_opt.tail_rec) {
- timer_push(TV_TAIL_REC);
- opt_tail_recursion();
+ /* first step: kill dead code */
+ for (i = 0; i < get_irp_n_irgs(); i++) {
+ irg = current_ir_graph = get_irp_irg(i);
+ /* Confirm construction currently can only handle blocks with only one control
+ flow predecessor. Calling optimize_cf here removes Bad predecessors and help
+ the optimization of switch constructs. */
+ timer_push(TV_CF_OPT);
+ optimize_graph_df(irg);
+ optimize_cf(irg);
timer_pop();
-
- DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "tail_rec");
- CHECK_ALL(firm_opt.check_all);
}
if (firm_opt.func_calls) {
timer_push(TV_REAL_FUNC_CALL);
- optimize_funccalls(firm_const_exists);
+ optimize_funccalls(firm_const_exists, NULL);
timer_pop();
DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "func_call");
CHECK_ALL(firm_opt.check_all);
}
- if (firm_opt.do_inline) {
- timer_push(TV_INLINE);
- inline_leave_functions(500, 80, 30, FALSE);
- timer_pop();
- DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "inl");
- CHECK_ALL(firm_opt.check_all);
- }
+ /* do lowering on the const code irg */
+ lower_const_code();
for (i = 0; i < get_irp_n_irgs(); i++) {
irg = current_ir_graph = get_irp_irg(i);
-
#ifdef FIRM_EXT_GRS
/* If SIMD optimization is on, make sure we have only 1 return */
if (firm_ext_grs.create_pattern || firm_ext_grs.simd_opt)
DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "reassoc");
CHECK_ONE(firm_opt.check_all, irg);
+ compute_doms(irg);
+ CHECK_ONE(firm_opt.check_all, irg);
+
+ if (firm_opt.code_place) {
+ timer_push(TV_CODE_PLACE);
+ set_opt_global_cse(1);
+ optimize_graph_df(irg);
+ place_code(irg);
+ set_opt_global_cse(0);
+ timer_pop();
+ DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "place");
+ CHECK_ONE(firm_opt.check_all, irg);
+ }
+
if (firm_opt.confirm) {
/* Confirm construction currently can only handle blocks with only one control
flow predecessor. Calling optimize_cf here removes Bad predecessors and help
the optimization of switch constructs. */
timer_push(TV_CF_OPT);
- optimize_cf(irg);
+ optimize_cf(irg);
timer_pop();
DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "cfopt");
CHECK_ONE(firm_opt.check_all, irg);
timer_pop();
DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "confirms");
CHECK_ONE(firm_opt.check_all, irg);
- }
- timer_push(TV_LOCAL_OPT);
- optimize_graph_df(irg);
- timer_pop();
- DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "lopt");
- CHECK_ONE(firm_opt.check_all, irg);
-
- compute_doms(irg);
- CHECK_ONE(firm_opt.check_all, irg);
-
- if (firm_opt.code_place) {
- timer_push(TV_CODE_PLACE);
- set_opt_global_cse(1);
+ timer_push(TV_LOCAL_OPT);
optimize_graph_df(irg);
- place_code(irg);
- set_opt_global_cse(0);
timer_pop();
- DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "place");
+ DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "lopt");
CHECK_ONE(firm_opt.check_all, irg);
}
if (firm_opt.luffig) {
opt_ldst2(irg);
DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "ldst2");
+ CHECK_ONE(firm_opt.check_all, irg);
}
timer_push(TV_CF_OPT);
DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "cfopt");
CHECK_ONE(firm_opt.check_all, irg);
- /* should we really remove the Confirm here? */
- if (firm_opt.confirm) {
- timer_push(TV_CONFIRM_CREATE);
- remove_confirms(irg);
- timer_pop();
- }
-
irg_verify(irg, VRFY_ENFORCE_SSA);
if (firm_opt.gvn_pre) {
do_gvn_pre(irg);
irg_verify(irg, VRFY_ENFORCE_SSA);
}
- if (firm_opt.loop_unrolling) {
- timer_push(TV_LOOP_UNROLL);
- optimize_loop_unrolling(irg);
- timer_pop();
- DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "loop");
- CHECK_ONE(firm_opt.check_all, irg);
- }
-
if (firm_opt.load_store) {
timer_push(TV_LOAD_STORE);
optimize_load_store(irg);
timer_pop();
DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "ldst");
CHECK_ONE(firm_opt.check_all, irg);
- }
+ }
- lower_highlevel_graph(irg);
+ lower_highlevel_graph(irg, firm_opt.lower_bitfields);
if (firm_opt.deconv) {
timer_push(TV_DECONV);
CHECK_ONE(firm_opt.check_all, irg);
}
+ /* should we really remove the Confirm here? */
+ if (firm_opt.confirm) {
+ timer_push(TV_CONFIRM_CREATE);
+ remove_confirms(irg);
+ timer_pop();
+ }
+
compute_doms(irg);
compute_postdoms(irg);
DUMP_ONE_CFG_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "dom");
}
timer_push(TV_OSR);
- opt_osr(current_ir_graph, osr_flag_default /*| osr_flag_ignore_x86_shift*/);
+ opt_osr(current_ir_graph, osr_flag_default | osr_flag_keep_reg_pressure | osr_flag_ignore_x86_shift);
timer_pop();
DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "stred");
CHECK_ONE(firm_opt.check_all, irg);
CHECK_ONE(firm_opt.check_all, irg);
}
+ if (firm_opt.do_inline) {
+ inline_functions(500, 50);
+ DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "inl");
+ CHECK_ALL(firm_opt.check_all);
+ }
if (firm_opt.cloning) {
proc_cloning((float)firm_opt.clone_threshold);
DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "clone");
+ CHECK_ALL(firm_opt.check_all);
+ }
+ if (firm_opt.tail_rec) {
+ timer_push(TV_TAIL_REC);
+ opt_tail_recursion();
+ timer_pop();
+
+ DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "tail_rec");
+ CHECK_ALL(firm_opt.check_all);
+ }
+
+ if (firm_opt.cond_eval) {
+ for (i = 0; i < get_irp_n_irgs(); i++) {
+ irg = get_irp_irg(i);
+ timer_push(TV_COND_EVAL);
+ opt_cond_eval(irg);
+ timer_pop();
+ DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "cond_eval");
+ CHECK_ONE(firm_opt.check_all, irg);
+
+ timer_push(TV_CF_OPT);
+ optimize_cf(irg);
+ timer_pop();
+ DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "cfopt");
+ CHECK_ONE(firm_opt.check_all, irg);
+ }
}
if (firm_dump.ir_graph) {
DUMP_ALL(firm_dump.ir_graph, "-opt");
/* verify optimized graphs */
- for (i = get_irp_n_irgs() - 1; i >= 0; --i)
- irg_verify(get_irp_irg(i), VRFY_ENFORCE_SSA);
+ for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
+ ir_graph *irg = get_irp_irg(i);
+ irg_verify(irg, VRFY_ENFORCE_SSA);
+ }
if (firm_dump.statistic & STAT_AFTER_OPT)
stat_dump_snapshot(input_filename, "opt");
} /* compute_type_size */
/**
- * layout all types of the Firm graph
+ * layout all non-frame types of the Firm graph
*/
static void compute_type_sizes(void)
{
int i;
ir_type *tp;
- ir_graph *irg;
- /* all frame types */
- for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
- irg = get_irp_irg(i);
- /* do not optimize away variables in debug mode */
- if (firm_opt.debug_mode == DBG_MODE_NONE)
- opt_frame_irg(irg);
- compute_type_size(get_irg_frame_type(irg));
- }
-
- /* all other types */
+ /* all non-frame other types */
for (i = get_irp_n_types() - 1; i >= 0; --i) {
tp = get_irp_type(i);
compute_type_size(tp);
}
} /* compute_type_sizes */
+/**
+ * layout all frame-types of the Firm graph
+ */
+static void compute_frame_type_sizes(void)
+{
+ int i;
+ ir_graph *irg;
+
+ /* all frame types */
+ for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
+ irg = get_irp_irg(i);
+ /* do not optimize away variables in debug mode */
+ if (firm_opt.debug_mode == DBG_MODE_NONE)
+ opt_frame_irg(irg);
+ compute_type_size(get_irg_frame_type(irg));
+ }
+} /* compute_frame_type_sizes */
+
/**
* do Firm lowering
*
}
timer_push(TV_DW_LOWER);
lower_dw_ops(&init);
- DUMP_ALL(firm_dump.ir_graph, "-dw");
timer_pop();
}
CHECK_ONE(firm_opt.check_all, current_ir_graph);
}
+ /* enable architecture dependent optimizations */
+ arch_dep_set_opts((arch_dep_opts_t)
+ ((firm_opt.muls ? arch_dep_mul_to_shift : arch_dep_none) |
+ (firm_opt.divs ? arch_dep_div_by_const : arch_dep_none) |
+ (firm_opt.mods ? arch_dep_mod_by_const : arch_dep_none) ));
+
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
current_ir_graph = get_irp_irg(i);
CHECK_ONE(firm_opt.check_all, current_ir_graph);
}
-// set_opt_global_cse(0);
timer_push(TV_LOAD_STORE);
optimize_load_store(current_ir_graph);
timer_pop();
params.cc_mask = 0; /* no regparam, cdecl */
params.builtin_dbg = NULL;
-#ifdef FIRM_BACKEND
+ #ifdef FIRM_EXT_GRS
+ /* Activate Graph rewriting if SIMD optimization is turned on */
+ /* This has to be done before init_firm() is called! */
+ if (firm_ext_grs.simd_opt)
+ ext_grs_activate();
+#endif
+
+ init_firm(¶ms);
+
if (firm_be_opt.selection == BE_FIRM_BE) {
- const backend_params *be_params = be_init();
+ const backend_params *be_params = be_get_backend_param();
firm_opt.lower_ll = (a_byte) be_params->do_dw_lowering;
params.arch_op_settings = be_params->arch_op_settings;
ad_param = be_params->dep_param;
if_conv_info = be_params->if_conv_info;
- }
-#endif /* FIRM_BACKEND */
-#ifdef FIRM_EXT_GRS
- /* Activate Graph rewriting if SIMD optimization is turned on */
- /* This has to be done before init_firm() is called! */
- if (firm_ext_grs.simd_opt)
- ext_grs_activate();
-#endif
+ if (be_params->has_imm_fp_mode)
+ firm_imm_fp_mode = be_params->imm_fp_mode;
+ }
- init_firm(¶ms);
dbg_init(NULL, NULL, dbg_snprint);
edges_init_dbg(firm_opt.vrfy_edges);
//cbackend_set_debug_retrieve(dbg_retrieve);
set_opt_precise_exc_context(firm_opt.precise_exc);
set_opt_fragile_ops(firm_opt.fragile_ops);
+ /* Sel node cannot produce NULL pointers */
+ set_opt_sel_based_null_check_elim(1);
+
/* dynamic dispatch works currently only if whole world scenarios */
set_opt_dyn_meth_dispatch(0);
/* computes the sizes of all types that are still not computed */
compute_type_sizes();
+ /* lower copyb nodes */
+ for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
+ ir_graph *irg = get_irp_irg(i);
+ lower_CopyB(irg, 128, 4);
+ }
+
if (firm_dump.statistic & STAT_BEFORE_OPT) {
stat_dump_snapshot(input_filename, "noopt");
}
if (firm_opt.lower)
do_firm_lowering(input_filename);
+ /* computes the sizes of all frame types */
+ compute_frame_type_sizes();
+
/* set the phase to low */
for (i = get_irp_n_irgs() - 1; i >= 0; --i)
set_irg_phase_low(get_irp_irg(i));
ext_grs_simd_opt();
#endif
- /* enable architecture dependent optimizations */
- arch_dep_set_opts((arch_dep_opts_t)
- ((firm_opt.muls ? arch_dep_mul_to_shift : arch_dep_none) |
- (firm_opt.divs ? arch_dep_div_by_const : arch_dep_none) |
- (firm_opt.mods ? arch_dep_mod_by_const : arch_dep_none) ));
-
-
if (firm_dump.statistic & STAT_FINAL_IR)
stat_dump_snapshot(input_filename, "final-ir");
* Do very early initializations
*/
void firm_early_init(void) {
-#ifdef FIRM_BACKEND
/* arg: need this here for command line options */
be_opt_register();
-#endif
firm_init_options(NULL, 0, NULL);
} /* firm_early_init */