Commit 269be573 authored by Matthias Braun's avatar Matthias Braun
Browse files

backend is responsible for defining what lowering operations need to be...

backend is responsible for defining what lowering operations need to be performed => so the logical thing is to use a backend callback for performing lowerings

[r27938]
parent 18011a85
......@@ -58,25 +58,28 @@ typedef enum {
*/
typedef ir_node *(create_trampoline_fkt)(ir_node *block, ir_node *mem, ir_node *trampoline, ir_node *env, ir_node *callee);
/** callback where the backend performs required lowering for the target
* architecture. Typical examples are transforming doubleword operations into
* sequences of word operations. The callback should be invoked before the
* frontend, because it is usually a good idea to perform other optimisations
* after the lowering
*/
typedef void (*lower_for_target_func)(void);
/**
* This structure contains parameters that should be
* propagated to the libFirm parameter set.
*/
typedef struct backend_params {
/** If set, the backend cannot handle DWORD access. */
unsigned do_dw_lowering:1;
/** If set, the backend supports inline assembly. */
unsigned support_inline_asm:1;
/** callback that performs lowerings required for target architecture */
lower_for_target_func lower_for_target;
/** Settings for architecture dependent optimizations. */
const ir_settings_arch_dep_t *dep_param;
/** The architecture specific intrinsic function creator. */
create_intrinsic_fkt *arch_create_intrinsic_fkt;
/** The context parameter for the create intrinsic function. */
void *create_intrinsic_ctx;
/** Backend settings for if-conversion. */
arch_allow_ifconv_func allow_ifconv;
......@@ -117,6 +120,12 @@ FIRM_API int be_parse_arg(const char *arg);
*/
FIRM_API const backend_params *be_get_backend_param(void);
/**
* Creates an ir_prog pass which performs lowerings necessary for the target
* architecture. (Calling backend_params->lower_for_target)
*/
FIRM_API ir_prog_pass_t *lower_for_target_pass(const char *name);
/**
* Main interface to the frontend.
*/
......
......@@ -185,23 +185,17 @@ FIRM_API ir_graph_pass_t *lower_switch_pass(const char *name,
* @param context the context parameter
*/
typedef ir_entity *(create_intrinsic_fkt)(ir_type *method, const ir_op *op,
const ir_mode *imode, const ir_mode *omode,
void *context);
const ir_mode *imode,
const ir_mode *omode, void *context);
/**
* The lowering parameter description.
*/
typedef struct lwrdw_param_t {
int enable; /**< if true lowering is enabled */
int little_endian; /**< if true should be lowered for little endian, else big endian */
ir_mode *high_signed; /**< the double word signed mode to be lowered, typically Ls */
ir_mode *high_unsigned; /**< the double word unsigned mode to be lowered, typically Lu */
ir_mode *low_signed; /**< the word signed mode to be used, typically Is */
ir_mode *low_unsigned; /**< the word unsigned mode to be used, typically Iu */
/** callback that creates the intrinsic entity */
create_intrinsic_fkt *create_intrinsic;
void *ctx; /**< context parameter for the creator function */
unsigned little_endian : 1; /**< if true should be lowered for little endian, else big endian */
unsigned doubleword_size; /**< bitsize of the doubleword mode */
create_intrinsic_fkt *create_intrinsic; /**< callback that creates the intrinsic entity */
void *ctx; /**< context parameter for the creator function */
} lwrdw_param_t;
/**
......@@ -211,17 +205,6 @@ typedef struct lwrdw_param_t {
*/
FIRM_API void lower_dw_ops(const lwrdw_param_t *param);
/**
* Creates an ir_prog pass for lower_dw_ops().
*
* @param name the name of this pass or NULL
* @param param parameter for lowering
*
* @return the newly created ir_prog pass
*/
FIRM_API ir_prog_pass_t *lower_dw_ops_pass(const char *name,
const lwrdw_param_t *param);
/**
* Default implementation. Context is unused.
*/
......
......@@ -443,17 +443,19 @@ static int TEMPLATE_get_reg_class_alignment(const arch_register_class_t *cls)
return get_mode_size_bytes(mode);
}
static void TEMPLATE_lower_for_target(void)
{
}
/**
* Returns the libFirm configuration parameter for this backend.
*/
static const backend_params *TEMPLATE_get_backend_params(void)
{
static backend_params p = {
0, /* no dword lowering */
0, /* no inline assembly */
NULL, /* will be set later */
NULL, /* no creator function */
NULL, /* context for create_intrinsic_fkt */
TEMPLATE_lower_for_target, /* lowering for target */
NULL, /* architecture dependent settings, will be set later */
NULL, /* parameter for if conversion */
NULL, /* float arithmetic mode */
0, /* no trampoline support: size 0 */
......
......@@ -601,16 +601,18 @@ static int amd64_get_reg_class_alignment(const arch_register_class_t *cls)
return get_mode_size_bytes(mode);
}
static void amd64_lower_for_target(void)
{
}
/**
* Returns the libFirm configuration parameter for this backend.
*/
static const backend_params *amd64_get_backend_params(void) {
static backend_params p = {
0, /* no dword lowering */
0, /* no inline assembly */
amd64_lower_for_target, /* lowering callback */
NULL, /* will be set later */
NULL, /* no creator function */
NULL, /* context for create_intrinsic_fkt */
NULL, /* parameter for if conversion */
NULL, /* float arithmetic mode */
0, /* no trampoline support: size 0 */
......
......@@ -690,11 +690,9 @@ static const backend_params *arm_get_libfirm_params(void)
32, /* SMUL & UMUL available for 32 bit */
};
static backend_params p = {
1, /* need dword lowering */
0, /* don't support inline assembler yet */
NULL, /* lowering function */
&ad, /* will be set later */
NULL, /* but yet no creator function */
NULL, /* context for create_intrinsic_fkt */
arm_is_mux_allowed, /* allow_ifconv function */
NULL, /* float arithmetic mode (TODO) */
0, /* no trampoline support: size 0 */
......
......@@ -49,6 +49,7 @@
#include "firmstat.h"
#include "execfreq.h"
#include "irprofile.h"
#include "irpass_t.h"
#include "bearch.h"
#include "be_t.h"
......@@ -341,11 +342,9 @@ int be_parse_arg(const char *arg)
/** The be parameters returned by default, all off. */
static const backend_params be_params = {
0, /* need dword lowering */
0, /* don't support inline assembler yet */
NULL, /* no lowering required */
NULL, /* will be set later */
NULL, /* but yet no creator function */
NULL, /* context for create_intrinsic_fkt */
NULL, /* no if conversion settings */
NULL, /* no float arithmetic mode */
0, /* no trampoline support: size 0 */
......@@ -642,8 +641,6 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
if (!arch_env->custom_abi) {
dump(DUMP_ABI, irg, "abi");
/* do local optimizations */
optimize_graph_df(irg);
}
/* we have to do cfopt+remove_critical_edges as we can't have Bad-blocks
......@@ -916,6 +913,23 @@ void be_main(FILE *file_handle, const char *cup_name)
#endif
}
static int do_lower_for_target(ir_prog *irp, void *context)
{
const backend_params *be_params = be_get_backend_param();
be_params->lower_for_target();
(void) context;
(void) irp;
return 0;
}
ir_prog_pass_t *lower_for_target_pass(const char *name)
{
ir_prog_pass_t *pass = XMALLOCZ(ir_prog_pass_t);
return def_prog_pass_constructor(pass,
name ? name : "lower_for_target",
do_lower_for_target);
}
unsigned be_put_ignore_regs(const ir_graph *irg,
const arch_register_class_t *cls, bitset_t *bs)
{
......
......@@ -824,17 +824,7 @@ static ir_entity *mcount = NULL;
static void ia32_before_abi(void *self)
{
lower_mode_b_config_t lower_mode_b_config = {
mode_Iu, /* lowered mode */
mode_Bu, /* preferred mode for set */
0, /* don't lower direct compares */
};
ia32_code_gen_t *cg = self;
ir_lower_mode_b(cg->irg, &lower_mode_b_config);
if (cg->dump)
dump_ir_graph(cg->irg, "lower_modeb");
if (cg->gprof) {
if (mcount == NULL) {
ir_type *tp = new_type_method(0, 0);
......@@ -2335,6 +2325,32 @@ static int ia32_is_valid_clobber(const char *clobber)
return ia32_get_clobber_register(clobber) != NULL;
}
static void ia32_lower_for_target(void)
{
int n_irgs = get_irp_n_irgs();
int i;
lower_mode_b_config_t lower_mode_b_config = {
mode_Iu, /* lowered mode */
mode_Bu, /* preferred mode for set */
0, /* don't lower direct compares */
};
/* perform doubleword lowering */
lwrdw_param_t lower_dw_params = {
1, /* little endian */
64, /* doubleword size */
ia32_create_intrinsic_fkt,
&intrinsic_env,
};
lower_dw_ops(&lower_dw_params);
/* lower for mode_b stuff */
for (i = 0; i < n_irgs; ++i) {
ir_graph *irg = get_irp_irg(i);
ir_lower_mode_b(irg, &lower_mode_b_config);
}
}
/**
* Create the trampoline code.
*/
......@@ -2377,12 +2393,10 @@ static const backend_params *ia32_get_libfirm_params(void)
32, /* Mulh allowed up to 32 bit */
};
static backend_params p = {
1, /* need dword lowering */
1, /* support inline assembly */
ia32_lower_for_target,
NULL, /* will be set later */
ia32_create_intrinsic_fkt,
&intrinsic_env, /* context for ia32_create_intrinsic_fkt */
ia32_is_mux_allowed, /* ifconv info will be set below */
ia32_is_mux_allowed,
NULL, /* float arithmetic mode, will be set below */
12, /* size of trampoline code */
4, /* alignment of trampoline code */
......
......@@ -561,17 +561,20 @@ static int sparc_get_reg_class_alignment(const arch_register_class_t *cls)
return get_mode_size_bytes(mode);
}
static void sparc_lower_for_target(void)
{
/* TODO, doubleword lowering and others */
}
/**
* Returns the libFirm configuration parameter for this backend.
*/
static const backend_params *sparc_get_backend_params(void)
{
static backend_params p = {
0, /* no dword lowering */
0, /* no inline assembly */
sparc_lower_for_target, /* lowering callback */
NULL, /* will be set later */
NULL, /* no creator function */
NULL, /* context for create_intrinsic_fkt */
NULL, /* parameter for if conversion */
NULL, /* float arithmetic mode */
0, /* no trampoline support: size 0 */
......
......@@ -5656,9 +5656,6 @@ static ir_node *transform_node_Mux(ir_node *n)
ir_node *f = get_Mux_false(n);
ir_graph *irg = current_ir_graph;
if (is_irg_state(irg, IR_GRAPH_STATE_KEEP_MUX))
return n;
if (is_Mux(t)) {
ir_node* block = get_nodes_block(n);
ir_node* c0 = sel;
......@@ -5772,7 +5769,8 @@ static ir_node *transform_node_Mux(ir_node *n)
}
/* more normalization: try to normalize Mux(x, C1, C2) into Mux(x, +1/-1, 0) op C2 */
if (is_Const(t) && is_Const(f) && mode_is_int(mode)) {
if (is_Const(t) && is_Const(f) && mode_is_int(mode)
&& !is_irg_state(irg, IR_GRAPH_STATE_KEEP_MUX)) {
tarval *a = get_Const_tarval(t);
tarval *b = get_Const_tarval(f);
tarval *diff, *min;
......@@ -5791,6 +5789,7 @@ static ir_node *transform_node_Mux(ir_node *n)
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_CONV);
return n;
}
/* TODO: it's not really clear if that helps in general or should be moved
* to backend, especially with the MUX->Conv transformation above */
if (tarval_cmp(a, b) & pn_Cmp_Gt) {
......
This diff is collapsed.
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