*/
#include <string.h>
#include "firm_cmdline.h"
+#include "firm_opt.h"
#include <libfirm/firm.h>
#include <libfirm/be.h>
/* enabled = */ TRUE,
/* debug_mode = */ DBG_MODE_NONE,
/* const_folding = */ TRUE,
- /* reassoc = */ TRUE,
/* cse = */ TRUE,
/* control_flow = */ TRUE,
- /* combo = */ TRUE,
/* gcse = */ TRUE,
- /* gvn_pre = */ FALSE,
- /* jumpthreading = */ FALSE,
- /* if_conversion = */ FALSE,
- /* func_calls = */ TRUE,
- /* do_inline = */ FALSE,
- /* auto_inline = */ TRUE,
- /* tail_rec = */ TRUE,
- /* strength_red = */ TRUE,
- /* scalar_replace = */ TRUE,
/* confirm = */ TRUE,
/* muls = */ TRUE,
/* divs = */ TRUE,
/* mods = */ TRUE,
- /* fragile_ops = */ TRUE,
- /* load_store = */ TRUE,
- /* load_store_pre = */ FALSE,
- /* modes = */ FALSE,
- /* precise_exc = */ FALSE, /* never needed for C */
- /* use_DivMod = */ FALSE,
- /* remove_unused = */ TRUE,
- /* cloning = */ FALSE,
- /* auto_sync = */ FALSE,
/* alias_analysis = */ TRUE,
/* strict_alias = */ FALSE,
/* no_alias = */ FALSE,
- /* sync = */ TRUE,
- /* deconv = */ FALSE,
/* cc_opt = */ TRUE,
- /* bool_opt = */ FALSE,
- /* shape_blocks = */ FALSE,
/* freestanding; = */ FALSE,
/* fp_model = */ fp_model_precise,
/* lower_ll = */ FALSE,
/* spare_size = */ 128,
/* enable_statev = */ FALSE,
/* statev_filter = */ "",
- /* loop = */ FALSE
};
/* dumping options */
{ X("no-const-fold"), &firm_opt.const_folding, 0, "firm: disable constant folding" },
{ X("control_flow"), &firm_opt.control_flow, 1, "firm: enable control flow optimization" },
{ X("no-control-flow"), &firm_opt.control_flow, 0, "firm: disable control flow optimization" },
- { X("combo"), &firm_opt.combo, 1, "firm: enable combined CCE, UCE and GVN" },
- { X("no-combo"), &firm_opt.combo, 0, "firm: disable combined CCE, UCE and GVN" },
{ X("gcse"), &firm_opt.gcse, 1, "firm: enable global common subexpression elimination" },
{ X("no-gcse"), &firm_opt.gcse, 0, "firm: disable global common subexpression elimination" },
- { X("gvn-pre"), &firm_opt.gvn_pre, 1, "firm: enable GVN partial redundancy elimination" },
- { X("no-gvn-pre"), &firm_opt.gvn_pre, 0, "firm: disable GVN partial redundancy elimination" },
- { X("thread-jumps"), &firm_opt.jumpthreading, 1, "firm: enable path-sensitive jumpthreading optimization" },
- { X("no-thread-jumps"), &firm_opt.jumpthreading, 0, "firm: disable path-sensitive jumpthreading optimization" },
- { X("if-conv"), &firm_opt.if_conversion, 1, "firm: enable if-conversion optimization" },
- { X("no-if-conv"), &firm_opt.if_conversion, 0, "firm: disable if-conversion optimization" },
- { X("opt-func-call"), &firm_opt.func_calls, 1, "firm: enable function call optimization" },
- { X("no-opt-func-call"), &firm_opt.func_calls, 0, "firm: disable function call optimization" },
- { X("reassociation"), &firm_opt.reassoc, 1, "firm: enable reassociation" },
- { X("no-reassociation"), &firm_opt.reassoc, 0, "firm: disable reassociation" },
- { X("inline"), &firm_opt.do_inline, 1, "firm: enable FIRM inlining" },
- { X("no-inline"), &firm_opt.do_inline, 0, "firm: disable FIRM inlining" },
{ X("inline-max-size=<size>"), NULL, 0, "firm: set maximum size for function inlining" },
{ X("inline-threshold=<size>"),NULL, 0, "firm: set benefice threshold for function inlining" },
- { X("tail-rec"), &firm_opt.tail_rec, 1, "firm: enable tail-recursion optimization" },
- { X("no-tail-rec"), &firm_opt.tail_rec, 0, "firm: disable tail-recursion optimization" },
- { X("strength-red"), &firm_opt.strength_red, 1, "firm: enable strength reduction for loops" },
- { X("no-strength-red"), &firm_opt.strength_red, 0, "firm: disable strength reduction for loops" },
- { X("scalar-replace"), &firm_opt.scalar_replace, 1, "firm: enable scalar replacement" },
- { X("no-scalar-replace"), &firm_opt.scalar_replace, 0, "firm: disable scalar replacement" },
{ X("confirm"), &firm_opt.confirm, 1, "firm: enable Confirm optimization" },
{ X("no-confirm"), &firm_opt.confirm, 0, "firm: disable Confirm optimization" },
{ X("opt-mul"), &firm_opt.muls, 0, "firm: enable multiplication optimization" },
{ X("no-opt-div"), &firm_opt.divs, 0, "firm: disable division optimization" },
{ X("opt-mod"), &firm_opt.mods, 0, "firm: enable remainder optimization" },
{ X("no-opt-mod"), &firm_opt.mods, 0, "firm: disable remainder optimization" },
- { X("opt-fragile-ops"), &firm_opt.fragile_ops, 1, "firm: enable fragile ops optimization" },
- { X("no-opt-fragile-ops"), &firm_opt.fragile_ops, 0, "firm: disable fragile ops optimization" },
- { X("opt-load-store"), &firm_opt.load_store, 1, "firm: enable load store optimization" },
- { X("no-opt-load-store"), &firm_opt.load_store, 0, "firm: disable load store optimization" },
- { X("opt-load-store-pre"), &firm_opt.load_store_pre, 1, "firm: enable load store optimization and PRE" },
- { X("no-opt-load-store-pre"), &firm_opt.load_store_pre, 0, "firm: disable load store optimization and PRE" },
- { X("opt-modes"), &firm_opt.modes, 1, "firm: optimize integer modes" },
- { X("no-opt-modes"), &firm_opt.modes, 0, "firm: disable integer modes optimization" },
- { X("sync"), &firm_opt.auto_sync, 1, "firm: automatically create Sync nodes" },
- { X("no-sync"), &firm_opt.auto_sync, 0, "firm: do not create Sync nodes" },
{ X("opt-alias"), &firm_opt.alias_analysis, 1, "firm: enable alias analysis" },
{ X("no-opt-alias"), &firm_opt.alias_analysis, 0, "firm: disable alias analysis" },
{ X("alias"), &firm_opt.no_alias, 0, "firm: aliasing occurs" },
{ X("no-alias"), &firm_opt.no_alias, 1, "firm: no aliasing occurs" },
{ X("strict-aliasing"), &firm_opt.strict_alias, 1, "firm: strict alias rules" },
{ X("no-strict-aliasing"), &firm_opt.strict_alias, 0, "firm: strict alias rules" },
- { X("opt-proc-clone"), &firm_opt.cloning, 1, "firm: enable procedure cloning" },
- { X("no-opt-proc-clone"), &firm_opt.cloning, 0, "firm: disable procedure cloning" },
{ X("clone-threshold=<value>"),NULL, 0, "firm: set clone threshold to <value>" },
- { X("DivMod"), &firm_opt.use_DivMod, 1, "firm: use DivMod nodes" },
- { X("no-DivMod"), &firm_opt.use_DivMod, 0, "firm: don't use DivMod nodes" },
- { X("precise-except"), &firm_opt.precise_exc, 1, "firm: precise exception context" },
- { X("no-precise-except"), &firm_opt.precise_exc, 0, "firm: no precise exception context" },
- { X("remove-unused"), &firm_opt.remove_unused, 1, "firm: remove unused functions" },
- { X("no-remove-unused"), &firm_opt.remove_unused, 0, "firm: dont't remove unused functions" },
{ X("fp-precise"), &firm_opt.fp_model, fp_model_precise, "firm: precise fp model" },
{ X("fp-fast"), &firm_opt.fp_model, fp_model_fast, "firm: fast fp model" },
{ X("fp-strict"), &firm_opt.fp_model, fp_model_strict, "firm: strict fp model" },
- { X("sync"), &firm_opt.sync, 1, "firm: use Syncs to remove unnecesary memory dependencies" },
- { X("no-sync"), &firm_opt.sync, 0, "firm: do not use Syncs to remove unnecesary memory dependencies" },
- { X("deconv"), &firm_opt.deconv, 1, "firm: enable the conv node optimization" },
- { X("no-deconv"), &firm_opt.deconv, 0, "firm: disable the conv node optimization" },
{ X("opt-cc"), &firm_opt.cc_opt, 1, "firm: enable calling conventions optimization" },
{ X("no-opt-cc"), &firm_opt.cc_opt, 0, "firm: disable calling conventions optimization" },
- { X("bool"), &firm_opt.bool_opt, 1, "firm: enable bool simplification optimization" },
- { X("no-bool"), &firm_opt.bool_opt, 0, "firm: disable bool simplification optimization" },
- { X("shape-blocks"), &firm_opt.shape_blocks, 1, "firm: enable block shaping" },
- { X("no-shape-blocks"), &firm_opt.shape_blocks, 0, "firm: disable block shaping" },
{ X("freestanding"), &firm_opt.freestanding, 1, "firm: freestanding environment" },
{ X("hosted"), &firm_opt.freestanding, 0, "firm: hosted environment" },
- { X("loop"), &firm_opt.loop, 1, "firm: enable loop peeling and unrolling" },
- { X("no-loop"), &firm_opt.loop, 0, "firm: disable loop peeling and unrolling" },
/* other firm regarding options */
{ X("restrict"), &firm_opt.honor_restrict, 1, "firm: honor restrict keyword" },
/** Disable all optimizations. */
static void disable_opts(void) {
- /* firm_opt.const_folding */
- firm_opt.reassoc = FALSE;
firm_opt.cse = FALSE;
- /* firm_opt.control_flow */
firm_opt.gcse = FALSE;
- firm_opt.gvn_pre = FALSE;
- firm_opt.jumpthreading = FALSE;
- firm_opt.if_conversion = FALSE;
- firm_opt.func_calls = FALSE;
- firm_opt.do_inline = FALSE;
- firm_opt.auto_inline = FALSE;
- firm_opt.tail_rec = FALSE;
- firm_opt.strength_red = FALSE;
- firm_opt.scalar_replace = FALSE;
firm_opt.confirm = FALSE;
firm_opt.muls = FALSE;
firm_opt.divs = FALSE;
firm_opt.mods = FALSE;
- firm_opt.fragile_ops = FALSE;
- firm_opt.load_store = FALSE;
- firm_opt.remove_unused = FALSE;
- /* firm_opt.jmp_tbls */
- firm_opt.cloning = FALSE;
- /* firm_opt.auto_sync */
firm_opt.alias_analysis = FALSE;
firm_opt.strict_alias = FALSE;
firm_opt.no_alias = FALSE;
- firm_opt.sync = FALSE;
- firm_opt.deconv = FALSE;
firm_opt.cc_opt = FALSE;
- firm_opt.bool_opt = FALSE;
- firm_opt.shape_blocks = FALSE;
firm_opt.freestanding = TRUE;
- firm_opt.loop = FALSE;
} /* disable_opts */
+void print_option_help(const char *name, const char *description)
+{
+ printf("-f %-20s %s\n", name, description);
+}
+
/**
* Handles a firm option.
*/
}
else if (strncmp("clone-threshold=", opt, 16) == 0) {
sscanf(&opt[16], "%d", &firm_opt.clone_threshold);
- firm_opt.cloning = TRUE;
return 1;
}
else if (strncmp("inline-max-size=", opt, 16) == 0) {
if (len == firm_options[i].opt_len && strncmp(p, firm_options[i].option, len) == 0) {
if (!firm_options[i].flag) {
/* help option */
- for (i = 0; i < (int) (sizeof(firm_options)/sizeof(firm_options[0])); ++i) {
- printf("-f %-20s %s\n", firm_options[i].option,
- firm_options[i].description);
+ print_option_help(firm_options[0].option, firm_options[0].description);
+ firm_opt_option_help();
+ for (i = 1; i < (int) (sizeof(firm_options)/sizeof(firm_options[0])); ++i) {
+ print_option_help(firm_options[i].option, firm_options[i].description);
}
return -1;
}
}
}
- if (i < 0)
- return 0;
- return 1;
+ if (i >= 0)
+ return 1;
+
+ /* maybe this enables/disables an optimisations */
+ if (firm_opt_option(p))
+ return 1;
+
+ return 0;
} /* firm_option */
/**
#define DBG(x) ((void)0)
#endif /* _DEBUG || FIRM_DEBUG */
+static bool do_irg_opt(ir_graph *irg, const char *name);
/** dump all the graphs depending on cond */
#define DUMP_ALL(cond, suffix) \
DUMP_ONE(1, irg, name);
}
-#if 0
-static void dump_graph_cfg_count(ir_graph *const irg, const char *const suffix)
-{
- char name[64];
- snprintf(name, sizeof(name), "-%02d_%s", irg_dump_no[get_irg_idx(irg)]++, suffix);
- DUMP_ONE_CFG(1, irg, name);
-}
-#endif
-
static void dump_all_count(const char *const suffix)
{
const int n_irgs = get_irp_n_irgs();
} \
} while (0)
-#define DUMP_ONE_CFG_C(cond, irg, suffix) \
- do { \
- if (cond) { \
- dump_graph_cfg_count((irg), (suffix)); \
- } \
- } while (0)
-
#define DUMP_ALL_C(cond, suffix) \
do { \
if (cond) { \
opt_osr(irg, osr_flag_default | osr_flag_keep_reg_pressure | osr_flag_ignore_x86_shift);
}
+static void after_inline_opt(ir_graph *irg)
+{
+ do_irg_opt(irg, "scalar-replace");
+ do_irg_opt(irg, "local");
+ do_irg_opt(irg, "control-flow");
+ do_irg_opt(irg, "combo");
+}
+
static void do_inline(void)
{
- inline_functions(firm_opt.inline_maxsize, firm_opt.inline_threshold);
+ inline_functions(firm_opt.inline_maxsize, firm_opt.inline_threshold,
+ after_inline_opt);
}
static void do_cloning(void)
lower_switch(irg, firm_opt.spare_size);
}
-static void do_loop(ir_graph *irg)
-{
-#if 0 // FIXME undeclared
- loop_optimization(irg);
-#else
- (void)irg;
- abort();
-#endif
-}
-
typedef enum opt_target {
- OPT_TARGET_IRG,
- OPT_TARGET_IRP
-} opt_target;
+ OPT_TARGET_IRG, /**< optimization function works on a single graph */
+ OPT_TARGET_IRP /**< optimization function works on the complete program */
+} opt_target_t;
+
+typedef enum opt_flags {
+ OPT_FLAG_NONE = 0,
+ OPT_FLAG_ENABLED = 1 << 0, /**< enable the optimization */
+ OPT_FLAG_NO_DUMP = 1 << 1, /**< don't dump after transformation */
+ OPT_FLAG_NO_VERIFY = 1 << 2, /**< don't verify after transformation */
+ OPT_FLAG_HIDE_OPTIONS = 1 << 3, /**< do not automatically process
+ -foptions for this transformation */
+} opt_flags_t;
typedef void (*transform_irg_func)(ir_graph *irg);
typedef void (*transform_irp_func)(void);
typedef void (*func_ptr_t)(void);
typedef struct {
- opt_target target;
- const char *name;
- func_ptr_t func;
- bool enabled;
- bool dump;
- bool verify;
- int timer;
+ opt_target_t target;
+ const char *name;
+ func_ptr_t func;
+ int timer;
+ const char *description;
+ opt_flags_t flags;
} opt_config_t;
static opt_config_t opts[] = {
- { OPT_TARGET_IRP, "rts", (func_ptr_t) rts_map, true, true, true, TV_RTS },
- { OPT_TARGET_IRG, "combo", (func_ptr_t) combo, true, true, true, TV_COMBO },
- { OPT_TARGET_IRG, "controlflow", (func_ptr_t) optimize_cf, true, true, true, TV_CF_OPT },
- { OPT_TARGET_IRG, "local", (func_ptr_t) optimize_graph_df, true, true, true, TV_LOCAL_OPT },
- { OPT_TARGET_IRP, "gc_irgs", (func_ptr_t) remove_unused_functions, true, false, false, TV_CGANA },
- { OPT_TARGET_IRP, "tailrec", (func_ptr_t) opt_tail_recursion, true, true, true, TV_TAIL_REC },
- { OPT_TARGET_IRP, "funccalls", (func_ptr_t) do_optimize_funccalls, true, true, true, TV_REAL_FUNC_CALL },
- { OPT_TARGET_IRP, "lowerconst", (func_ptr_t) lower_const_code, true, false, false, TV_LOWER },
- { OPT_TARGET_IRG, "onereturn", (func_ptr_t) normalize_one_return, true, false, false, TV_ONERETURN },
- { OPT_TARGET_IRG, "scalar", (func_ptr_t) scalar_replacement_opt, true, true, true, TV_SCALAR_REPLACE },
- { OPT_TARGET_IRG, "reassoc", (func_ptr_t) optimize_reassociation, true, true, true, TV_REASSOCIATION },
- { OPT_TARGET_IRG, "gcse", (func_ptr_t) do_gcse, true, true, true, TV_CODE_PLACE },
- { OPT_TARGET_IRG, "place", (func_ptr_t) place_code, true, true, true, TV_CODE_PLACE },
- { OPT_TARGET_IRG, "confirm", (func_ptr_t) construct_confirms, true, true, true, TV_CONFIRM_CREATE },
- { OPT_TARGET_IRG, "ldst", (func_ptr_t) optimize_load_store, true, true, true, TV_LOAD_STORE },
- { OPT_TARGET_IRG, "sync", (func_ptr_t) opt_sync, true, true, true, TV_SYNC },
- { OPT_TARGET_IRG, "lower", (func_ptr_t) do_lower_highlevel, true, true, true, TV_LOWER },
- { OPT_TARGET_IRG, "deconv", (func_ptr_t) conv_opt, true, true, true, TV_DECONV },
- { OPT_TARGET_IRG, "jumpthreading", (func_ptr_t) opt_jumpthreading, true, true, true, TV_JUMPTHREADING },
- { OPT_TARGET_IRG, "remove_confirms", (func_ptr_t) remove_confirms, true, false, false, TV_CONFIRM_CREATE },
- { OPT_TARGET_IRG, "gvnpre", (func_ptr_t) do_gvn_pre, true, true, true, TV_GVNPRE },
- { OPT_TARGET_IRG, "ifconv", (func_ptr_t) do_if_conv, true, true, true, TV_IF_CONV },
- { OPT_TARGET_IRG, "bool", (func_ptr_t) opt_bool, true, true, true, TV_BOOLOPT },
- { OPT_TARGET_IRG, "shape-blocks",(func_ptr_t) shape_blocks, true, true, true, TV_END_MELT },
- { OPT_TARGET_IRG, "stred", (func_ptr_t) do_stred, true, true, true, TV_OSR },
- { OPT_TARGET_IRG, "dead", (func_ptr_t) dead_node_elimination, true, false, true, TV_DEAD_NODE },
- { OPT_TARGET_IRP, "inline", (func_ptr_t) do_inline, true, true, true, TV_INLINE },
- { OPT_TARGET_IRP, "clone", (func_ptr_t) do_cloning, true, true, true, TV_CLONE },
- { OPT_TARGET_IRG, "lower_switch", (func_ptr_t) do_lower_switch, true, true, true, TV_LOWER },
- { OPT_TARGET_IRG, "loop", (func_ptr_t) do_loop, true, true, true, TV_LOOP },
+ { OPT_TARGET_IRP, "rts", (func_ptr_t) rts_map, TV_RTS, "optimization of known library functions", OPT_FLAG_HIDE_OPTIONS },
+ { OPT_TARGET_IRG, "combo", (func_ptr_t) combo, TV_COMBO, "combined CCE, UCE and GVN", OPT_FLAG_NONE},
+ { OPT_TARGET_IRG, "control-flow", (func_ptr_t) optimize_cf, TV_CF_OPT, "optimization of control-flow", OPT_FLAG_HIDE_OPTIONS },
+ { OPT_TARGET_IRG, "local", (func_ptr_t) optimize_graph_df, TV_LOCAL_OPT, "local graph optimizations", OPT_FLAG_HIDE_OPTIONS },
+ { OPT_TARGET_IRP, "remove-unused", (func_ptr_t) remove_unused_functions, TV_CGANA, "removal of unused functions", OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY },
+ { OPT_TARGET_IRP, "opt-tail-rec", (func_ptr_t) opt_tail_recursion, TV_TAIL_REC, "tail-recursion eliminiation", OPT_FLAG_NONE },
+ { OPT_TARGET_IRP, "opt-func-call", (func_ptr_t) do_optimize_funccalls, TV_REAL_FUNC_CALL, "function call optimization", OPT_FLAG_NONE },
+ { OPT_TARGET_IRP, "lower-const", (func_ptr_t) lower_const_code, TV_LOWER, "lowering of constant code", OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY },
+ { OPT_TARGET_IRG, "one-return", (func_ptr_t) normalize_one_return, TV_ONERETURN, "normalisation to 1 return", OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY },
+ { OPT_TARGET_IRG, "scalar-replace", (func_ptr_t) scalar_replacement_opt, TV_SCALAR_REPLACE, "scalar replacement", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "reassociation", (func_ptr_t) optimize_reassociation, TV_REASSOCIATION, "reassociation", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "gcse", (func_ptr_t) do_gcse, TV_CODE_PLACE, "global common subexpression elimination", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "place", (func_ptr_t) place_code, TV_CODE_PLACE, "code placement", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "confirm", (func_ptr_t) construct_confirms, TV_CONFIRM_CREATE, "confirm optimisation", OPT_FLAG_HIDE_OPTIONS },
+ { OPT_TARGET_IRG, "opt-load-store", (func_ptr_t) optimize_load_store, TV_LOAD_STORE, "load store optimization", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "sync", (func_ptr_t) opt_sync, TV_SYNC, "automatic sync-node creation", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "lower", (func_ptr_t) do_lower_highlevel, TV_LOWER, "lowering", OPT_FLAG_HIDE_OPTIONS },
+ { OPT_TARGET_IRG, "deconv", (func_ptr_t) conv_opt, TV_DECONV, "conv node elimination", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "thread-jumps", (func_ptr_t) opt_jumpthreading, TV_JUMPTHREADING, "path-sensitive jumpthreading", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "remove-confirms", (func_ptr_t) remove_confirms, TV_CONFIRM_CREATE, "confirm removal", OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY },
+ { OPT_TARGET_IRG, "gvn-pre", (func_ptr_t) do_gvn_pre, TV_GVNPRE, "global value numbering partial redundancy elimination", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "if-conversion", (func_ptr_t) do_if_conv, TV_IF_CONV, "if-conversion", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "bool", (func_ptr_t) opt_bool, TV_BOOLOPT, "bool simplification", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "shape-blocks", (func_ptr_t) shape_blocks, TV_END_MELT, "block shaping", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "ivopts", (func_ptr_t) do_stred, TV_OSR, "induction variable strength reduction", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "remove-phi-cycles", (func_ptr_t) remove_phi_cycles, TV_OSR, "removal of phi cycles", OPT_FLAG_HIDE_OPTIONS },
+ { OPT_TARGET_IRG, "dead", (func_ptr_t) dead_node_elimination, TV_DEAD_NODE, "dead node elimination", OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY },
+ { OPT_TARGET_IRP, "inline", (func_ptr_t) do_inline, TV_INLINE, "inlining", OPT_FLAG_NONE },
+ { OPT_TARGET_IRP, "opt-proc-clone", (func_ptr_t) do_cloning, TV_CLONE, "procedure cloning", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "lower-switch", (func_ptr_t) do_lower_switch, TV_LOWER, "switch lowering", OPT_FLAG_HIDE_OPTIONS },
+ { OPT_TARGET_IRG, "invert-loops", (func_ptr_t) do_loop_inversion, TV_LOOP_INVERSION, "loop inversion", OPT_FLAG_NONE },
+ { OPT_TARGET_IRG, "peel-loops", (func_ptr_t) do_loop_peeling, TV_LOOP_PEELING, "loop peeling", OPT_FLAG_NONE },
};
static const int n_opts = sizeof(opts) / sizeof(opts[0]);
return config;
}
- assert(0);
return NULL;
}
static void set_opt_enabled(const char *name, bool enabled)
{
opt_config_t *config = get_opt(name);
- config->enabled = enabled;
+ config->flags = (config->flags & ~OPT_FLAG_ENABLED)
+ | (enabled ? OPT_FLAG_ENABLED : 0);
}
-static void do_irg_opt(ir_graph *irg, const char *name)
+static bool get_opt_enabled(const char *name)
+{
+ opt_config_t *config = get_opt(name);
+ return (config->flags & OPT_FLAG_ENABLED) != 0;
+}
+
+/**
+ * perform an optimisation on a single graph
+ *
+ * @return true if something changed, false otherwise
+ */
+static bool do_irg_opt(ir_graph *irg, const char *name)
{
transform_irg_func func;
ir_graph *old_irg;
opt_config_t *config = get_opt(name);
assert(config->target == OPT_TARGET_IRG);
- if (!config->enabled)
- return;
+ if (! (config->flags & OPT_FLAG_ENABLED))
+ return false;
if (config->timer != -1)
timer_push(config->timer);
CHECK_ONE(firm_opt.check_all, irg);
current_ir_graph = old_irg;
+ return true;
}
static void do_irp_opt(const char *name)
transform_irp_func func;
opt_config_t *config = get_opt(name);
assert(config->target == OPT_TARGET_IRP);
- if (!config->enabled)
+ if (! (config->flags & OPT_FLAG_ENABLED))
return;
if (config->timer != -1)
timer_pop();
}
+/**
+ * Enable transformations which should be always safe (and cheap) to perform
+ */
+static void enable_safe_defaults(void)
+{
+ set_opt_enabled("remove-unused", true);
+ set_opt_enabled("opt-tail-rec", true);
+ set_opt_enabled("opt-func-call", true);
+ set_opt_enabled("reassociation", true);
+ set_opt_enabled("control-flow", true);
+ set_opt_enabled("local", true);
+ set_opt_enabled("lower-const", true);
+ set_opt_enabled("scalar-replace", true);
+ set_opt_enabled("place", true);
+ set_opt_enabled("confirm", true);
+ set_opt_enabled("opt-load-store", true);
+ set_opt_enabled("lower", true);
+ set_opt_enabled("deconv", true);
+ set_opt_enabled("remove-confirms", true);
+ set_opt_enabled("ivopts", true);
+ set_opt_enabled("dead", true);
+ set_opt_enabled("lower-switch", true);
+ set_opt_enabled("remove-phi-cycles", true);
+}
+
/**
* run all the Firm optimizations
*
/* 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);
- set_opt_scalar_replacement(firm_opt.scalar_replace);
- set_opt_auto_create_sync(firm_opt.auto_sync);
set_opt_alias_analysis(firm_opt.alias_analysis);
- set_opt_combo(firm_opt.combo);
aa_opt = aa_opt_no_opt;
if (firm_opt.strict_alias)
/* parameter passing code should set them directly sometime... */
set_opt_enabled("rts", !firm_opt.freestanding);
- set_opt_enabled("gc_irgs", firm_opt.remove_unused);
- set_opt_enabled("tailrec", firm_opt.tail_rec);
- set_opt_enabled("funccalls", firm_opt.func_calls);
set_opt_enabled("gcse", firm_opt.gcse);
set_opt_enabled("place", !firm_opt.gcse);
set_opt_enabled("confirm", firm_opt.confirm);
- set_opt_enabled("remove_confirms", firm_opt.confirm);
- set_opt_enabled("sync", firm_opt.sync);
- set_opt_enabled("ldst", firm_opt.load_store);
- set_opt_enabled("deconv", firm_opt.deconv);
- set_opt_enabled("jumpthreading", firm_opt.jumpthreading);
- set_opt_enabled("gvnpre", firm_opt.gvn_pre);
- set_opt_enabled("ifconv", firm_opt.if_conversion);
- set_opt_enabled("bool", firm_opt.bool_opt);
- set_opt_enabled("shape-blocks", firm_opt.shape_blocks);
- set_opt_enabled("inline", firm_opt.do_inline);
- set_opt_enabled("clone", firm_opt.cloning);
- set_opt_enabled("combo", firm_opt.combo);
- set_opt_enabled("loop", firm_opt.loop);
+ set_opt_enabled("remove-confirms", firm_opt.confirm);
+
+ /* osr supersedes remove_phi_cycles */
+ if (get_opt_enabled("ivopts"))
+ set_opt_enabled("remove-phi-cycles", false);
timer_start(TV_ALL_OPT);
do_irp_opt("rts");
/* first step: kill dead code */
- if (firm_opt.combo) {
- for (i = 0; i < get_irp_n_irgs(); i++) {
- ir_graph *irg = get_irp_irg(i);
- do_irg_opt(irg, "combo");
- }
- } else {
- for (i = 0; i < get_irp_n_irgs(); i++) {
- ir_graph *irg = get_irp_irg(i);
- do_irg_opt(irg, "local");
- do_irg_opt(irg, "controlflow");
- }
+ for (i = 0; i < get_irp_n_irgs(); i++) {
+ ir_graph *irg = get_irp_irg(i);
+ do_irg_opt(irg, "combo");
+ do_irg_opt(irg, "local");
+ do_irg_opt(irg, "control-flow");
}
- do_irp_opt("gc_irgs");
- do_irp_opt("tailrec");
- do_irp_opt("funccalls");
- do_irp_opt("lowerconst");
+ do_irp_opt("remove-unused");
+ do_irp_opt("opt-tail-rec");
+ do_irp_opt("opt-func-call");
+ do_irp_opt("lower-const");
for (i = 0; i < get_irp_n_irgs(); i++) {
ir_graph *irg = get_irp_irg(i);
- do_irg_opt(irg, "scalar");
+ do_irg_opt(irg, "scalar-replace");
+ do_irg_opt(irg, "invert-loops");
do_irg_opt(irg, "local");
- do_irg_opt(irg, "reassoc");
+ do_irg_opt(irg, "reassociation");
do_irg_opt(irg, "local");
do_irg_opt(irg, "gcse");
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. */
- do_irg_opt(irg, "controlflow");
+ /* 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. */
+ do_irg_opt(irg, "control-flow");
do_irg_opt(irg, "confirm");
do_irg_opt(irg, "local");
}
- do_irg_opt(irg, "controlflow");
- do_irg_opt(irg, "ldst");
- do_irg_opt(irg, "loop");
+ do_irg_opt(irg, "control-flow");
+ do_irg_opt(irg, "opt-load-store");
do_irg_opt(irg, "lower");
do_irg_opt(irg, "deconv");
- do_irg_opt(irg, "jumpthreading");
- do_irg_opt(irg, "remove_confirms");
- do_irg_opt(irg, "gvnpre");
+ do_irg_opt(irg, "thread-jumps");
+ do_irg_opt(irg, "remove-confirms");
+ do_irg_opt(irg, "gvn-pre");
do_irg_opt(irg, "place");
- do_irg_opt(irg, "controlflow");
+ do_irg_opt(irg, "control-flow");
- if (firm_opt.if_conversion) {
- do_irg_opt(irg, "ifconv");
+ if (do_irg_opt(irg, "if-conversion")) {
do_irg_opt(irg, "local");
- do_irg_opt(irg, "controlflow");
+ do_irg_opt(irg, "control-flow");
}
do_irg_opt(irg, "bool");
do_irg_opt(irg, "shape-blocks");
- do_irg_opt(irg, "lower_switch");
- do_irg_opt(irg, "stred");
+ do_irg_opt(irg, "lower-switch");
+ do_irg_opt(irg, "ivopts");
do_irg_opt(irg, "local");
do_irg_opt(irg, "dead");
}
do_irp_opt("inline");
- do_irp_opt("clone");
+ do_irp_opt("opt-proc-clone");
for (i = 0; i < get_irp_n_irgs(); i++) {
ir_graph *irg = get_irp_irg(i);
do_irg_opt(irg, "local");
- do_irg_opt(irg, "controlflow");
- do_irg_opt(irg, "jumpthreading");
+ do_irg_opt(irg, "control-flow");
+ do_irg_opt(irg, "thread-jumps");
do_irg_opt(irg, "local");
- do_irg_opt(irg, "controlflow");
+ do_irg_opt(irg, "control-flow");
}
if (firm_dump.ir_graph) {
construct_cf_backedges(get_irp_irg(i));
}
- do_irp_opt("gc_irgs");
+ do_irp_opt("remove-unused");
DUMP_ALL(firm_dump.ir_graph, "-opt");
/* verify optimized graphs */
are enabled */
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
ir_graph *irg = get_irp_irg(i);
- do_irg_opt(irg, "reassoc");
+ do_irg_opt(irg, "reassociation");
}
/* enable architecture dependent optimizations */
current_ir_graph = irg;
- do_irg_opt(irg, "local");
- do_irg_opt(irg, "gcse");
- do_irg_opt(irg, "ldst");
- do_irg_opt(irg, "local");
- do_irg_opt(irg, "controlflow");
+ do_irg_opt(irg, "local");
+ do_irg_opt(irg, "gcse");
+ do_irg_opt(irg, "opt-load-store");
+ do_irg_opt(irg, "local");
+ do_irg_opt(irg, "control-flow");
- if (firm_opt.if_conversion) {
- do_irg_opt(irg, "ifconv");
- do_irg_opt(irg, "local");
- do_irg_opt(irg, "controlflow");
- }
+ if (do_irg_opt(irg, "if-conversion")) {
+ do_irg_opt(irg, "local");
+ do_irg_opt(irg, "control-flow");
+ }
- do_irg_opt(current_ir_graph, "sync");
+ do_irg_opt(current_ir_graph, "sync");
}
timer_stop(TV_ALL_OPT);
firm_parameter_t params;
unsigned pattern = 0;
- /* the automatic state is only set if inlining is enabled */
- firm_opt.auto_inline = firm_opt.do_inline;
-
if (firm_dump.stat_pattern)
pattern |= FIRMSTAT_PATTERN_ENABLED;
dbg_init(NULL, NULL, dbg_snprint);
edges_init_dbg(firm_opt.vrfy_edges);
- 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);
stat_dump_snapshot(input_filename, "final");
}
+int firm_opt_option(const char *opt)
+{
+ bool enable = true;
+ if (strncmp(opt, "no-", 3) == 0) {
+ enable = false;
+ opt = opt + 3;
+ }
+
+ opt_config_t *config = get_opt(opt);
+ if (config == NULL || (config->flags & OPT_FLAG_HIDE_OPTIONS))
+ return 0;
+
+ config->flags &= ~OPT_FLAG_ENABLED;
+ config->flags |= enable ? OPT_FLAG_ENABLED : 0;
+ return 1;
+}
+
+void firm_opt_option_help(void)
+{
+ int i;
+
+ for (i = 0; i < n_opts; ++i) {
+ char buf[1024];
+ char buf2[1024];
+
+ const opt_config_t *config = &opts[i];
+ if (config->flags & OPT_FLAG_HIDE_OPTIONS)
+ continue;
+
+ snprintf(buf2, sizeof(buf2), "firm: enable %s", config->description);
+ print_option_help(config->name, buf2);
+ snprintf(buf, sizeof(buf), "no-%s", config->name);
+ snprintf(buf2, sizeof(buf2), "firm: disable %s", config->description);
+ print_option_help(buf, buf2);
+ }
+}
+
/**
* Do very early initializations
*/
{
/* arg: need this here for command line options */
be_opt_register();
+
+ enable_safe_defaults();
}
*
* $Id: firm_timing.def 20710 2008-07-26 19:59:07Z beck $
*/
-DEFTIMEVAR(TV_ALL_OPT , "allopt", "Firm: all optimizations")
-DEFTIMEVAR(TV_VALUE_NUM , "valnum", "Firm: value numbers")
-DEFTIMEVAR(TV_CREATE , "create", "Firm: creation")
-DEFTIMEVAR(TV_COMBO , "combo", "Firm: combo")
-DEFTIMEVAR(TV_INLINE , "inline", "Firm: inlining")
-DEFTIMEVAR(TV_TAIL_REC , "tailrec", "Firm: tail-recursion")
-DEFTIMEVAR(TV_COMP_DOMS , "doms", "Firm: compute doms")
-DEFTIMEVAR(TV_LOCAL_OPT , "locopt", "Firm: local opt")
-DEFTIMEVAR(TV_REASSOCIATION , "reassoc", "Firm: reassociation")
-DEFTIMEVAR(TV_CF_OPT , "cfopt", "Firm: CF opt")
-DEFTIMEVAR(TV_LOAD_STORE , "ldst", "Firm: load/store opt")
-DEFTIMEVAR(TV_LOAD_STORE_2 , "ldst2", "Firm: enhanced load/store opt")
-DEFTIMEVAR(TV_STRENGTH_REDUCT , "strength", "Firm: strength red")
-DEFTIMEVAR(TV_DEAD_NODE , "deadnode", "Firm: dead node elim")
-DEFTIMEVAR(TV_DECONV , "deconv", "Firm: conv node opt")
-DEFTIMEVAR(TV_JUMPTHREADING , "jumpthreading", "Firm: jump threading")
-DEFTIMEVAR(TV_CODE_PLACE , "codeplace", "Firm: code placement")
-DEFTIMEVAR(TV_IF_CONV , "ifconv", "Firm: if conversion")
-DEFTIMEVAR(TV_OSR , "osr", "Firm: operator strenght reduce")
-DEFTIMEVAR(TV_LOOP , "loop", "Firm: loop peeling and unrolling")
-DEFTIMEVAR(TV_REAL_FUNC_CALL , "realfunc", "Firm: real func call")
-DEFTIMEVAR(TV_CGANA , "cgana", "Firm: CG analysis")
-DEFTIMEVAR(TV_CONFIRM_CREATE , "confirm", "Firm: Confirm creation")
-DEFTIMEVAR(TV_SCALAR_REPLACE , "scalar", "Firm: scalar replace")
-DEFTIMEVAR(TV_END_MELT , "end-melt", "Firm: melting end blocks")
-DEFTIMEVAR(TV_OPT , "other", "Firm: other opt")
-DEFTIMEVAR(TV_VERIFY , "verify", "Firm: verify pass")
-DEFTIMEVAR(TV_LOWER , "lower", "Firm: lowering")
-DEFTIMEVAR(TV_DW_LOWER , "dwlower", "Firm: double word lowering")
-DEFTIMEVAR(TV_FIRM_BE , "firmbe", "Firm: backend")
-DEFTIMEVAR(TV_FIRM2C_BE , "firm2c", "Firm: C-generating backend")
-DEFTIMEVAR(TV_FIRM_ASM , "firmasm", "Firm: Firm assembler")
-DEFTIMEVAR(TV_STAT_OUT , "statistics", "Firm: statistic output")
-DEFTIMEVAR(TV_VCG_DUMP , "vcg", "Firm: vcg dumping")
-DEFTIMEVAR(TV_SYNC , "sync", "Firm: Construct Sync")
-DEFTIMEVAR(TV_GVNPRE , "gvnpre", "Firm: GVNPRE")
-DEFTIMEVAR(TV_BOOLOPT , "bool", "Firm: Boolean optimisations")
-DEFTIMEVAR(TV_CLONE , "clone", "Firm: Procedure cloning")
-DEFTIMEVAR(TV_RTS , "runtime", "Firm: Known runtime function optimisation")
-DEFTIMEVAR(TV_ONERETURN , "oneret", "Firm: Normalize to one return")
+DEFTIMEVAR(TV_ALL_OPT , "allopt", "Firm: all optimizations")
+DEFTIMEVAR(TV_VALUE_NUM , "valnum", "Firm: value numbers")
+DEFTIMEVAR(TV_CREATE , "create", "Firm: creation")
+DEFTIMEVAR(TV_COMBO , "combo", "Firm: combo")
+DEFTIMEVAR(TV_INLINE , "inline", "Firm: inlining")
+DEFTIMEVAR(TV_TAIL_REC , "tailrec", "Firm: tail-recursion")
+DEFTIMEVAR(TV_COMP_DOMS , "doms", "Firm: compute doms")
+DEFTIMEVAR(TV_LOCAL_OPT , "locopt", "Firm: local opt")
+DEFTIMEVAR(TV_REASSOCIATION , "reassoc", "Firm: reassociation")
+DEFTIMEVAR(TV_CF_OPT , "cfopt", "Firm: CF opt")
+DEFTIMEVAR(TV_LOAD_STORE , "ldst", "Firm: load/store opt")
+DEFTIMEVAR(TV_LOAD_STORE_2 , "ldst2", "Firm: enhanced load/store opt")
+DEFTIMEVAR(TV_STRENGTH_REDUCT , "strength", "Firm: strength red")
+DEFTIMEVAR(TV_DEAD_NODE , "deadnode", "Firm: dead node elim")
+DEFTIMEVAR(TV_DECONV , "deconv", "Firm: conv node opt")
+DEFTIMEVAR(TV_JUMPTHREADING , "jumpthreading", "Firm: jump threading")
+DEFTIMEVAR(TV_CODE_PLACE , "codeplace", "Firm: code placement")
+DEFTIMEVAR(TV_IF_CONV , "ifconv", "Firm: if conversion")
+DEFTIMEVAR(TV_OSR , "osr", "Firm: operator strenght reduce")
+DEFTIMEVAR(TV_LOOP_UNROLL , "lunroll", "Firm: loop unrolling")
+DEFTIMEVAR(TV_REAL_FUNC_CALL , "realfunc", "Firm: real func call")
+DEFTIMEVAR(TV_CGANA , "cgana", "Firm: CG analysis")
+DEFTIMEVAR(TV_CONFIRM_CREATE , "confirm", "Firm: Confirm creation")
+DEFTIMEVAR(TV_SCALAR_REPLACE , "scalar", "Firm: scalar replace")
+DEFTIMEVAR(TV_END_MELT , "end-melt", "Firm: melting end blocks")
+DEFTIMEVAR(TV_OPT , "other", "Firm: other opt")
+DEFTIMEVAR(TV_VERIFY , "verify", "Firm: verify pass")
+DEFTIMEVAR(TV_LOWER , "lower", "Firm: lowering")
+DEFTIMEVAR(TV_DW_LOWER , "dwlower", "Firm: double word lowering")
+DEFTIMEVAR(TV_FIRM_BE , "firmbe", "Firm: backend")
+DEFTIMEVAR(TV_FIRM2C_BE , "firm2c", "Firm: C-generating backend")
+DEFTIMEVAR(TV_FIRM_ASM , "firmasm", "Firm: Firm assembler")
+DEFTIMEVAR(TV_STAT_OUT , "statistics", "Firm: statistic output")
+DEFTIMEVAR(TV_VCG_DUMP , "vcg", "Firm: vcg dumping")
+DEFTIMEVAR(TV_SYNC , "sync", "Firm: Construct Sync")
+DEFTIMEVAR(TV_GVNPRE , "gvnpre", "Firm: GVNPRE")
+DEFTIMEVAR(TV_BOOLOPT , "bool", "Firm: Boolean optimisations")
+DEFTIMEVAR(TV_CLONE , "clone", "Firm: Procedure cloning")
+DEFTIMEVAR(TV_RTS , "runtime", "Firm: Known runtime function optimisation")
+DEFTIMEVAR(TV_ONERETURN , "oneret", "Firm: Normalize to one return")
+DEFTIMEVAR(TV_LOOP_INVERSION , "loop-inversion", "Firm: Loop inversion")
+DEFTIMEVAR(TV_LOOP_PEELING , "loop-peeling", "Firm: Loop peeling")
-DEFTIMEVAR(TV_PARSING , "parsing", "Frontend: Parsing")
-DEFTIMEVAR(TV_CONSTRUCT , "construction", "Frontend: Graph construction")
-DEFTIMEVAR(TV_PREPROC , "preprocess", "Frontend: Preprocessor")
+DEFTIMEVAR(TV_PARSING , "parsing", "Frontend: Parsing")
+DEFTIMEVAR(TV_CONSTRUCT , "construction", "Frontend: Graph construction")
+DEFTIMEVAR(TV_PREPROC , "preprocess", "Frontend: Preprocessor")