Commit 18011a85 authored by Matthias Braun's avatar Matthias Braun
Browse files

make if-conversion and archdep optimisations get their information directly...

make if-conversion and archdep optimisations get their information directly from the backend without frontends needing special code to transfer these infos

[r27937]
parent 0838670b
......@@ -29,6 +29,7 @@
#include <stdio.h>
#include "irarch.h"
#include "lowering.h"
#include "iroptimize.h"
#include "begin.h"
typedef enum {
......@@ -77,7 +78,7 @@ typedef struct backend_params {
void *create_intrinsic_ctx;
/** Backend settings for if-conversion. */
const ir_settings_if_conv_t *if_conv_info;
arch_allow_ifconv_func allow_ifconv;
/**
* some backends like x87 can only do arithmetic in a specific float
......
......@@ -79,11 +79,6 @@ struct ir_settings_arch_dep_t {
*/
typedef const ir_settings_arch_dep_t *(*arch_dep_params_factory_t)(void);
/**
* A default parameter factory for testing purposes.
*/
FIRM_API const ir_settings_arch_dep_t *arch_dep_default_factory(void);
/**
* Optimization flags.
*/
......@@ -94,15 +89,6 @@ typedef enum {
arch_dep_mod_by_const = 4 /**< optimize Mod into Shift/Add/Mulh */
} arch_dep_opts_t;
/**
* Initialize the machine dependent optimizations.
* @param factory A factory that delivers parameters for these
* optimizations. If NULL is passed, or this method
* is not called, the machine dependent optimizations
* are not enabled at all.
*/
FIRM_API void arch_dep_init(arch_dep_params_factory_t factory);
/**
* Set the optimizations that shall be applied.
* @param opts An optimization bit mask.
......
......@@ -254,38 +254,24 @@ FIRM_API ir_graph_pass_t *do_gvn_pre_pass(const char *name);
typedef int (*arch_allow_ifconv_func)(ir_node *sel, ir_node *mux_false,
ir_node *mux_true);
/**
* The parameters structure.
*/
struct ir_settings_if_conv_t {
int max_depth; /**< The maximum depth up to which expressions
are examined when it has to be decided if they
can be placed into another block. */
arch_allow_ifconv_func allow_ifconv; /**< Evaluator function, if not set all possible Psi
nodes will be created. */
};
/**
* Perform If conversion on a graph.
*
* @param irg The graph.
* @param params The parameters for the if conversion.
*
* Cannot handle blocks with Bad control predecessors, so call it after control
* flow optimization.
*/
FIRM_API void opt_if_conv(ir_graph *irg, const ir_settings_if_conv_t *params);
FIRM_API void opt_if_conv(ir_graph *irg);
/**
* Creates an ir_graph pass for opt_if_conv().
*
* @param name the name of this pass or NULL
* @param params The parameters for the if conversion.
*
* @return the newly created ir_graph pass
*/
FIRM_API ir_graph_pass_t *opt_if_conv_pass(
const char *name, const ir_settings_if_conv_t *params);
FIRM_API ir_graph_pass_t *opt_if_conv_pass(const char *name);
/**
* Tries to reduce dependencies for memory nodes where possible by parllelizing
......
......@@ -680,10 +680,6 @@ static int arm_is_valid_clobber(const char *clobber)
*/
static const backend_params *arm_get_libfirm_params(void)
{
static const ir_settings_if_conv_t ifconv = {
4, /* maxdepth, doesn't matter for Psi-conversion */
arm_is_mux_allowed /* allows or disallows Mux creation for given selector */
};
static ir_settings_arch_dep_t ad = {
1, /* allow subs */
1, /* Muls are fast enough on ARM but ... */
......@@ -696,10 +692,10 @@ static const backend_params *arm_get_libfirm_params(void)
static backend_params p = {
1, /* need dword lowering */
0, /* don't support inline assembler yet */
NULL, /* will be set later */
&ad, /* will be set later */
NULL, /* but yet no creator function */
NULL, /* context for create_intrinsic_fkt */
NULL, /* ifconv_info will be set below */
arm_is_mux_allowed, /* allow_ifconv function */
NULL, /* float arithmetic mode (TODO) */
0, /* no trampoline support: size 0 */
0, /* no trampoline support: align 0 */
......@@ -707,8 +703,6 @@ static const backend_params *arm_get_libfirm_params(void)
4 /* alignment of stack parameter */
};
p.dep_param = &ad;
p.if_conv_info = &ifconv;
return &p;
}
......
......@@ -2366,10 +2366,6 @@ static ir_node *ia32_create_trampoline_fkt(ir_node *block, ir_node *mem, ir_node
*/
static const backend_params *ia32_get_libfirm_params(void)
{
static const ir_settings_if_conv_t ifconv = {
4, /* maxdepth, doesn't matter for Mux-conversion */
ia32_is_mux_allowed /* allows or disallows Mux creation for given selector */
};
static const ir_settings_arch_dep_t ad = {
1, /* also use subs */
4, /* maximum shifts */
......@@ -2385,8 +2381,8 @@ static const backend_params *ia32_get_libfirm_params(void)
1, /* support inline assembly */
NULL, /* will be set later */
ia32_create_intrinsic_fkt,
&intrinsic_env, /* context for ia32_create_intrinsic_fkt */
NULL, /* ifconv info will be set below */
&intrinsic_env, /* context for ia32_create_intrinsic_fkt */
ia32_is_mux_allowed, /* ifconv info will be set below */
NULL, /* float arithmetic mode, will be set below */
12, /* size of trampoline code */
4, /* alignment of trampoline code */
......@@ -2401,7 +2397,6 @@ static const backend_params *ia32_get_libfirm_params(void)
init_asm_constraints();
p.dep_param = &ad;
p.if_conv_info = &ifconv;
if (! ia32_cg_config.use_sse2)
p.mode_float_arithmetic = mode_E;
return &p;
......
......@@ -137,7 +137,6 @@ void ir_init(const firm_parameter_t *param)
firm_init_loop_opt();
/* Init architecture dependent optimizations. */
arch_dep_init(arch_dep_default_factory);
arch_dep_set_opts(0);
init_irnode();
......
......@@ -24,7 +24,8 @@
* @author Sebastian Hack, Michael Beck
* @version $Id$
*
* Implements "Strength Reduction of Multiplications by Integer Constants" by Youfeng Wu.
* Implements "Strength Reduction of Multiplications by Integer Constants"
* by Youfeng Wu.
* Implements Division and Modulo by Consts from "Hackers Delight",
*/
#include "config.h"
......@@ -47,33 +48,19 @@
#include "ircons.h"
#include "irarch.h"
#include "irflag.h"
#include "be.h"
#include "error.h"
#undef DEB
#define MAX_BITSTR 64
/** The params got from the factory in arch_dep_init(...). */
static const ir_settings_arch_dep_t *params = NULL;
/** The bit mask, which optimizations to apply. */
static arch_dep_opts_t opts;
void arch_dep_init(arch_dep_params_factory_t factory)
{
opts = arch_dep_none;
if (factory != NULL)
params = factory();
}
void arch_dep_set_opts(arch_dep_opts_t the_opts)
{
opts = the_opts;
}
/** check, whether a mode allows a Mulh instruction. */
static int allow_Mulh(ir_mode *mode)
static int allow_Mulh(const ir_settings_arch_dep_t *params, ir_mode *mode)
{
if (get_mode_size_bits(mode) > params->max_bits_for_mulh)
return 0;
......@@ -97,6 +84,7 @@ struct instruction {
*/
typedef struct mul_env {
struct obstack obst; /**< an obstack for local space. */
const ir_settings_arch_dep_t *params;
ir_mode *mode; /**< the mode of the multiplication constant */
unsigned bits; /**< number of bits in the mode */
unsigned max_S; /**< the maximum LEA shift value. */
......@@ -353,7 +341,7 @@ static instruction *decompose_mul(mul_env *env, unsigned char *R, int r, tarval
if (r <= 2)
return decompose_simple_cases(env, R, r, N);
if (params->also_use_subs) {
if (env->params->also_use_subs) {
gain = calculate_gain(R, r);
if (gain > 0) {
instruction *instr1, *instr2;
......@@ -499,7 +487,7 @@ static int evaluate_insn(mul_env *env, instruction *inst)
inst->costs = costs;
return costs;
case SHIFT:
if (inst->shift_count > params->highest_shift_amount)
if (inst->shift_count > env->params->highest_shift_amount)
env->fail = 1;
if (env->n_shift <= 0)
env->fail = 1;
......@@ -540,13 +528,14 @@ static ir_node *do_decomposition(ir_node *irn, ir_node *operand, tarval *tv)
int mul_costs;
obstack_init(&env.obst);
env.params = be_get_backend_param()->dep_param;
env.mode = get_tarval_mode(tv);
env.bits = (unsigned)get_mode_size_bits(env.mode);
env.max_S = 3;
env.root = emit_ROOT(&env, operand);
env.fail = 0;
env.n_shift = params->maximum_shifts;
env.evaluate = params->evaluate != NULL ? params->evaluate : default_evaluate;
env.n_shift = env.params->maximum_shifts;
env.evaluate = env.params->evaluate != NULL ? env.params->evaluate : default_evaluate;
R = value_to_condensed(&env, tv, &r);
inst = decompose_mul(&env, R, r, tv);
......@@ -577,6 +566,7 @@ ir_node *arch_dep_replace_mul_with_shifts(ir_node *irn)
ir_node *right;
ir_node *operand;
tarval *tv;
const ir_settings_arch_dep_t *params = be_get_backend_param()->dep_param;
/* If the architecture dependent optimizations were not initialized
......@@ -900,6 +890,7 @@ static ir_node *replace_div_by_mulh(ir_node *div, tarval *tv)
/* Replace Divs with Shifts and Add/Subs and Mulh. */
ir_node *arch_dep_replace_div_by_const(ir_node *irn)
{
const ir_settings_arch_dep_t *params = be_get_backend_param()->dep_param;
ir_node *res = irn;
/* If the architecture dependent optimizations were not initialized
......@@ -984,7 +975,7 @@ ir_node *arch_dep_replace_div_by_const(ir_node *irn)
}
} else {
/* other constant */
if (allow_Mulh(mode))
if (allow_Mulh(params, mode))
res = replace_div_by_mulh(irn, tv);
}
}
......@@ -998,6 +989,7 @@ ir_node *arch_dep_replace_div_by_const(ir_node *irn)
/* Replace Mods with Shifts and Add/Subs and Mulh. */
ir_node *arch_dep_replace_mod_by_const(ir_node *irn)
{
const ir_settings_arch_dep_t *params = be_get_backend_param()->dep_param;
ir_node *res = irn;
/* If the architecture dependent optimizations were not initialized
......@@ -1071,7 +1063,7 @@ ir_node *arch_dep_replace_mod_by_const(ir_node *irn)
}
} else {
/* other constant */
if (allow_Mulh(mode)) {
if (allow_Mulh(params, mode)) {
res = replace_div_by_mulh(irn, tv);
res = new_rd_Mul(dbg, block, res, c, mode);
......@@ -1092,6 +1084,7 @@ ir_node *arch_dep_replace_mod_by_const(ir_node *irn)
/* Replace DivMods with Shifts and Add/Subs and Mulh. */
void arch_dep_replace_divmod_by_const(ir_node **div, ir_node **mod, ir_node *irn)
{
const ir_settings_arch_dep_t *params = be_get_backend_param()->dep_param;
*div = *mod = NULL;
/* If the architecture dependent optimizations were not initialized
......@@ -1181,7 +1174,7 @@ void arch_dep_replace_divmod_by_const(ir_node **div, ir_node **mod, ir_node *irn
}
} else {
/* other constant */
if (allow_Mulh(mode)) {
if (allow_Mulh(params, mode)) {
ir_node *t;
*div = replace_div_by_mulh(irn, tv);
......@@ -1198,21 +1191,3 @@ void arch_dep_replace_divmod_by_const(ir_node **div, ir_node **mod, ir_node *irn
if (*div)
hook_arch_dep_replace_division_by_const(irn);
}
static const ir_settings_arch_dep_t default_params = {
1, /* also use subs */
4, /* maximum shifts */
31, /* maximum shift amount */
default_evaluate, /* default evaluator */
0, /* allow Mulhs */
0, /* allow Mulus */
32 /* Mulh allowed up to 32 bit */
};
/* A default parameter factory for testing purposes. */
const ir_settings_arch_dep_t *arch_dep_default_factory(void)
{
return &default_params;
}
......@@ -23,7 +23,6 @@
* @author Christoph Mallon
* @version $Id$
*/
#include "config.h"
#include <assert.h>
......@@ -40,8 +39,8 @@
#include "irtools.h"
#include "array_t.h"
#include "irpass_t.h"
#include "be.h"
// debug
#include "irdump.h"
#include "debug.h"
......@@ -49,8 +48,8 @@
* Environment for if-conversion.
*/
typedef struct walker_env {
const ir_settings_if_conv_t *params; /**< Conversion parameter. */
int changed; /**< Set if the graph was changed. */
arch_allow_ifconv_func allow_ifconv;
bool changed; /**< Set if the graph was changed. */
} walker_env;
DEBUG_ONLY(static firm_dbg_module_t *dbg);
......@@ -67,14 +66,6 @@ static int default_allow_ifconv(ir_node *sel, ir_node *mux_false,
return 0;
}
/**
* Default options.
*/
static const ir_settings_if_conv_t default_info = {
0, /* doesn't matter for Mux */
default_allow_ifconv
};
/**
* Returns non-zero if a Block can be emptied.
*
......@@ -357,7 +348,7 @@ restart:
mux_true = get_Phi_pred(p, i);
mux_false = get_Phi_pred(p, j);
}
if (!env->params->allow_ifconv(sel, mux_false, mux_true)) {
if (!env->allow_ifconv(sel, mux_false, mux_true)) {
supported = false;
break;
}
......@@ -369,7 +360,7 @@ restart:
cond, projx0, projx1
));
env->changed = 1;
env->changed = true;
prepare_path(block, i, dependency);
prepare_path(block, j, dependency);
arity = get_irn_arity(block);
......@@ -485,13 +476,17 @@ static void collect_phis(ir_node *node, void *env)
}
}
void opt_if_conv(ir_graph *irg, const ir_settings_if_conv_t *params)
void opt_if_conv(ir_graph *irg)
{
walker_env env;
walker_env env;
const backend_params *be_params = be_get_backend_param();
/* get the parameters */
env.params = (params != NULL ? params : &default_info);
env.changed = 0;
if (be_params->allow_ifconv != NULL)
env.allow_ifconv = be_params->allow_ifconv;
else
env.allow_ifconv = default_allow_ifconv;
env.changed = false;
FIRM_DBG_REGISTER(dbg, "firm.opt.ifconv");
......@@ -523,27 +518,7 @@ void opt_if_conv(ir_graph *irg, const ir_settings_if_conv_t *params)
free_cdep(irg);
}
struct pass_t {
ir_graph_pass_t pass;
const ir_settings_if_conv_t *params;
};
/**
* Wrapper for running opt_if_conv() as an ir_graph pass.
*/
static int pass_wrapper(ir_graph *irg, void *context)
{
struct pass_t *pass = context;
opt_if_conv(irg, pass->params);
return 0;
}
ir_graph_pass_t *opt_if_conv_pass(const char *name,
const ir_settings_if_conv_t *params)
ir_graph_pass_t *opt_if_conv_pass(const char *name)
{
struct pass_t *pass = XMALLOCZ(struct pass_t);
pass->params = params;
return def_graph_pass_constructor(
&pass->pass, name ? name : "ifconv", pass_wrapper);
return def_graph_pass(name ? name : "ifconv", opt_if_conv);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment