From 08fe790a5784b31964a8783f6af1d14d62c366c4 Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Sun, 2 Apr 2006 21:32:57 +0000 Subject: [PATCH] interface changed: outfile is transmitted to the isa, not to the code generators decls are created now last moved entity cache to isa, so Fp constants are only created once --- ir/be/ia32/bearch_ia32.c | 72 +++++++++++++++++++++++++------------ ir/be/ia32/bearch_ia32.h | 1 + ir/be/ia32/bearch_ia32_t.h | 20 +++++++---- ir/be/ia32/ia32_gen_decls.c | 26 +++++++------- ir/be/ia32/ia32_optimize.c | 6 ++-- ir/be/ia32/ia32_transform.c | 55 ++++++++++++---------------- 6 files changed, 106 insertions(+), 74 deletions(-) diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index a11e652c1..1cc8ffc11 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -57,10 +57,12 @@ static set *cur_reg_set = NULL; #undef is_Start #define is_Start(irn) (get_irn_opcode(irn) == iro_Start) +/* Creates the unique per irg GP NoReg node. */ ir_node *ia32_new_NoReg_gp(ia32_code_gen_t *cg) { return be_abi_get_callee_save_irn(cg->birg->abi, &ia32_gp_regs[REG_GP_NOREG]); } +/* Creates the unique per irg FP NoReg node. */ ir_node *ia32_new_NoReg_fp(ia32_code_gen_t *cg) { return be_abi_get_callee_save_irn(cg->birg->abi, USE_SSE2(cg) ? &ia32_xmm_regs[REG_XMM_NOREG] : &ia32_vfp_regs[REG_VFP_NOREG]); @@ -730,7 +732,7 @@ static void ia32_after_ra(void *self) { irg_block_walk_graph(cg->irg, NULL, ia32_after_ra_walker, self); /* if we do x87 code generation, rewrite all the virtual instructions and registers */ - if (cg->used_x87) { + if (cg->used_fp == fp_x87) { x87_simulate_graph(cg->arch_env, cg->irg, cg->blk_sched); } } @@ -743,28 +745,23 @@ static void ia32_after_ra(void *self) { static void ia32_codegen(void *self) { ia32_code_gen_t *cg = self; ir_graph *irg = cg->irg; - FILE *out = cg->out; - - if (cg->emit_decls) { - ia32_gen_decls(cg->out); - cg->emit_decls = 0; - } ia32_finish_irg(irg, cg); be_dump(irg, "-finished", dump_ir_block_graph_sched); - ia32_gen_routine(out, irg, cg); + ia32_gen_routine(cg->isa->out, irg, cg); cur_reg_set = NULL; - pmap_destroy(cg->tv_ent); - pmap_destroy(cg->types); + /* remove it from the isa */ + cg->isa->cg = NULL; /* de-allocate code generator */ del_set(cg->reg_set); free(self); + } -static void *ia32_cg_init(FILE *F, const be_irg_t *birg); +static void *ia32_cg_init(const be_irg_t *birg); static const arch_code_generator_if_t ia32_code_gen_if = { ia32_cg_init, @@ -777,23 +774,21 @@ static const arch_code_generator_if_t ia32_code_gen_if = { }; /** - * Initializes the code generator. + * Initializes a IA32 code generator. */ -static void *ia32_cg_init(FILE *F, const be_irg_t *birg) { +static void *ia32_cg_init(const be_irg_t *birg) { ia32_isa_t *isa = (ia32_isa_t *)birg->main_env->arch_env->isa; ia32_code_gen_t *cg = xcalloc(1, sizeof(*cg)); cg->impl = &ia32_code_gen_if; cg->irg = birg->irg; cg->reg_set = new_set(ia32_cmp_irn_reg_assoc, 1024); - cg->out = F; cg->arch_env = birg->main_env->arch_env; - cg->types = pmap_create(); - cg->tv_ent = pmap_create(); + cg->isa = isa; cg->birg = birg; cg->blk_sched = NULL; cg->fp_kind = isa->fp_kind; - cg->used_x87 = 0; + cg->used_fp = fp_none; FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.cg"); @@ -804,6 +799,9 @@ static void *ia32_cg_init(FILE *F, const be_irg_t *birg) { cg->opt.immops = 1; cg->opt.extbb = 1; + /* enter it */ + isa->cg = cg; + #ifndef NDEBUG if (isa->name_obst_size) { //printf("freed %d bytes from name obst\n", isa->name_obst_size); @@ -839,6 +837,11 @@ static void *ia32_cg_init(FILE *F, const be_irg_t *birg) { * *****************************************************************/ +/** + * The template that generates a new ISA object. + * Note that this template can be changed by command line + * arguments. + */ static ia32_isa_t ia32_isa_template = { &ia32_isa_if, /* isa interface implementation */ &ia32_gp_regs[REG_ESP], /* stack pointer register */ @@ -847,9 +850,12 @@ static ia32_isa_t ia32_isa_template = { 0, /* number of code generator objects so far */ NULL, /* 16bit register names */ NULL, /* 8bit register names */ + NULL, /* types */ + NULL, /* tv_ents */ arch_pentium_4, /* instruction architecture */ arch_pentium_4, /* optimize for architecture */ fp_sse2, /* use sse2 unit */ + NULL, /* current code generator */ #ifndef NDEBUG NULL, /* name obstack */ 0 /* name obst size */ @@ -859,14 +865,14 @@ static ia32_isa_t ia32_isa_template = { /** * Initializes the backend ISA. */ -static void *ia32_init(void) { +static void *ia32_init(FILE *file_handle) { static int inited = 0; ia32_isa_t *isa; - if(inited) + if (inited) return NULL; - isa = xcalloc(1, sizeof(*isa)); + isa = xmalloc(sizeof(*isa)); memcpy(isa, &ia32_isa_template, sizeof(*isa)); ia32_register_init(isa); @@ -875,16 +881,33 @@ static void *ia32_init(void) { isa->regs_16bit = pmap_create(); isa->regs_8bit = pmap_create(); + isa->types = pmap_create(); + isa->tv_ent = pmap_create(); + isa->out = file_handle; ia32_build_16bit_reg_map(isa->regs_16bit); ia32_build_8bit_reg_map(isa->regs_8bit); + /* patch regigter names of x87 registers */ + if (USE_x87(isa)) { + ia32_st_regs[0].name = "st"; + ia32_st_regs[1].name = "st(1)"; + ia32_st_regs[2].name = "st(2)"; + ia32_st_regs[3].name = "st(3)"; + ia32_st_regs[4].name = "st(4)"; + ia32_st_regs[5].name = "st(5)"; + ia32_st_regs[6].name = "st(6)"; + ia32_st_regs[7].name = "st(7)"; + } + #ifndef NDEBUG - isa->name_obst = xcalloc(1, sizeof(*(isa->name_obst))); + isa->name_obst = xmalloc(sizeof(*isa->name_obst)); obstack_init(isa->name_obst); isa->name_obst_size = 0; #endif /* NDEBUG */ + fprintf(isa->out, "\t.intel_syntax\n"); + inited = 1; return isa; @@ -898,8 +921,13 @@ static void *ia32_init(void) { static void ia32_done(void *self) { ia32_isa_t *isa = self; + /* emit now all global declarations */ + ia32_gen_decls(isa->out); + pmap_destroy(isa->regs_16bit); pmap_destroy(isa->regs_8bit); + pmap_destroy(isa->tv_ent); + pmap_destroy(isa->types); #ifndef NDEBUG //printf("name obst size = %d bytes\n", isa->name_obst_size); @@ -915,7 +943,7 @@ static void ia32_done(void *self) { * We report always these: * - the general purpose registers * - the floating point register set (depending on the unit used for FP) - * - MMX/SE registers (currently not supported) + * - MMX/SSE registers (currently not supported) */ static int ia32_get_n_reg_class(const void *self) { return 2; diff --git a/ir/be/ia32/bearch_ia32.h b/ir/be/ia32/bearch_ia32.h index a478b16b3..bacfa03f2 100644 --- a/ir/be/ia32/bearch_ia32.h +++ b/ir/be/ia32/bearch_ia32.h @@ -4,6 +4,7 @@ #include "pset.h" #include "../bearch.h" +#define FP_USED(cg) ((cg)->used_fp = (cg)->fp_kind) #define USE_SSE2(cg) ((cg)->fp_kind == fp_sse2) #define USE_x87(cg) ((cg)->fp_kind == fp_x87) diff --git a/ir/be/ia32/bearch_ia32_t.h b/ir/be/ia32/bearch_ia32_t.h index e49dc243a..903118df2 100644 --- a/ir/be/ia32/bearch_ia32_t.h +++ b/ir/be/ia32/bearch_ia32_t.h @@ -48,33 +48,37 @@ typedef enum cpu_support { /** floating point support */ typedef enum fp_support { + fp_none, /**< no floating point instructions are used */ fp_x87, /**< use x87 instructions */ fp_sse2 /**< use SSE2 instructions */ } fp_support; +typedef struct _ia32_isa_t ia32_isa_t; + /** * IA32 code generator */ typedef struct _ia32_code_gen_t { const arch_code_generator_if_t *impl; /**< implementation */ ir_graph *irg; /**< current irg */ - FILE *out; /**< output file */ const arch_env_t *arch_env; /**< the arch env */ set *reg_set; /**< set to memorize registers for non-ia32 nodes (e.g. phi nodes) */ int emit_decls; /**< flag indicating if decls were already emitted */ - pmap *types; /**< A map of modes to primitive types */ - pmap *tv_ent; /**< A map of entities that store tarvals */ + ia32_isa_t *isa; /**< for fast access to the isa object */ const be_irg_t *birg; /**< The be-irg (contains additional information about the irg) */ ir_node **blk_sched; /**< an array containing the scheduled blocks */ ia32_optimize_t opt; /**< contains optimization information */ int arch; /**< instruction architecture */ int opt_arch; /**< optimize for architecture */ int fp_kind; /**< floating point kind */ - char used_x87; /**< x87 floating point unit used in this graph */ + char used_fp; /**< which floating point unit used in this graph */ DEBUG_ONLY(firm_dbg_module_t *mod;) /**< debugging module */ } ia32_code_gen_t; -typedef struct _ia32_isa_t { +/** + * IA32 ISA object + */ +struct _ia32_isa_t { const arch_isa_if_t *impl; const arch_register_t *sp; /**< The stack pointer register. */ const arch_register_t *bp; /**< The base pointer register. */ @@ -82,14 +86,18 @@ typedef struct _ia32_isa_t { int num_codegens; /**< The number of code generator objects created so far */ pmap *regs_16bit; /**< Contains the 16bits names of the gp registers */ pmap *regs_8bit; /**< Contains the 8bits names of the gp registers */ + pmap *types; /**< A map of modes to primitive types */ + pmap *tv_ent; /**< A map of entities that store const tarvals */ int arch; /**< instruction architecture */ int opt_arch; /**< optimize for architecture */ int fp_kind; /**< floating point kind */ + ia32_code_gen_t *cg; /**< the current code generator */ + FILE *out; /**< output file */ #ifndef NDEBUG struct obstack *name_obst; /**< holds the original node names (for debugging) */ unsigned long name_obst_size; #endif /* NDEBUG */ -} ia32_isa_t; +}; typedef struct _ia32_irn_ops_t { const arch_irn_ops_if_t *impl; diff --git a/ir/be/ia32/ia32_gen_decls.c b/ir/be/ia32/ia32_gen_decls.c index f6ef7d652..4704437bc 100644 --- a/ir/be/ia32/ia32_gen_decls.c +++ b/ir/be/ia32/ia32_gen_decls.c @@ -308,6 +308,11 @@ struct arr_info { int size; }; +static void dump_object_size(struct obstack *obst, char *name, int size) { + obstack_printf(obst, "\t.type\t%s,@object\n", name); + obstack_printf(obst, "\t.size\t%s,%d\n", name, size); +} + /* * Dumps the initialization of global variables that are not * "uninitialized". @@ -331,13 +336,12 @@ static void dump_global(struct obstack *rdata_obstack, struct obstack *data_obst obst = rdata_obstack; } - /* check, wether it is initialized, if yes create data */ + /* check, whether it is initialized, if yes create data */ if (variability != variability_uninitialized) { if (visibility == visibility_external_visible) { obstack_printf(obst, ".globl\t%s\n", ld_name); } - obstack_printf(obst, "\t.type\t%s,@object\n", ld_name); - obstack_printf(obst, "\t.size\t%s,%d\n", ld_name, (get_type_size_bits(ty) + 7) >> 3); + dump_object_size(obst, ld_name, (get_type_size_bits(ty) + 7) >> 3); align = get_type_alignment_bytes(ty); ia32_dump_align(obst, align); @@ -345,20 +349,20 @@ static void dump_global(struct obstack *rdata_obstack, struct obstack *data_obst obstack_printf(obst, "%s:\n", ld_name); if (is_atomic_type(ty)) { - if (get_entity_visibility(ent) != visibility_external_allocated) + if (get_entity_visibility(ent) != visibility_external_allocated) dump_atomic_init(obst, get_atomic_ent_value(ent)); } else { - int i, size = 0; + int i, size = 0; - if (ent_is_string_const(ent)) { - dump_string_cst(obst, ent); - } - else if (is_Array_type(ty)) { + if (ent_is_string_const(ent)) { + dump_string_cst(obst, ent); + } + else if (is_Array_type(ty)) { int filler; /* potential spare values should be already included! */ - for (i = 0; i < get_compound_ent_n_values(ent); ++i) { + for (i = 0; i < get_compound_ent_n_values(ent); ++i) { entity *step = get_compound_ent_value_member(ent, i); ir_type *stype = get_entity_type(step); @@ -523,8 +527,6 @@ void ia32_gen_decls(FILE *out) { obstack_init(&data); obstack_init(&comm); - fprintf(out, "\t.intel_syntax\n"); - ia32_dump_globals(&rodata, &data, &comm); size = obstack_object_size(&data); diff --git a/ir/be/ia32/ia32_optimize.c b/ir/be/ia32/ia32_optimize.c index e6bcc6d70..c6e2f76b3 100644 --- a/ir/be/ia32/ia32_optimize.c +++ b/ir/be/ia32/ia32_optimize.c @@ -120,7 +120,7 @@ static ir_type *get_prim_type(pmap *types, ir_mode *mode) static entity *get_entity_for_tv(ia32_code_gen_t *cg, ir_node *cnst) { tarval *tv = get_Const_tarval(cnst); - pmap_entry *e = pmap_find(cg->tv_ent, tv); + pmap_entry *e = pmap_find(cg->isa->tv_ent, tv); entity *res; ir_graph *rem; @@ -128,7 +128,7 @@ static entity *get_entity_for_tv(ia32_code_gen_t *cg, ir_node *cnst) ir_mode *mode = get_irn_mode(cnst); ir_type *tp = get_Const_type(cnst); if (tp == firm_unknown_type) - tp = get_prim_type(cg->types, mode); + tp = get_prim_type(cg->isa->types, mode); res = new_entity(get_glob_type(), unique_id("ia32FloatCnst_%u"), tp); @@ -143,6 +143,8 @@ static entity *get_entity_for_tv(ia32_code_gen_t *cg, ir_node *cnst) current_ir_graph = get_const_code_irg(); set_atomic_ent_value(res, new_Const_type(tv, tp)); current_ir_graph = rem; + + pmap_insert(cg->isa->tv_ent, tv, res); } else res = e->value; diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index ac98864bc..a07a02402 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -448,12 +448,11 @@ static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { assert((expr_op || imm_op) && "invalid operands"); if (mode_is_float(mode)) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) return gen_binop(env, op1, op2, new_rd_ia32_fAdd); - else { - env->cg->used_x87 = 1; + else return gen_binop(env, op1, op2, new_rd_ia32_vfadd); - } } else { /* integer ADD */ @@ -533,12 +532,11 @@ static ir_node *gen_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { ir_node *new_op; if (mode_is_float(env->mode)) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) new_op = gen_binop(env, op1, op2, new_rd_ia32_fMul); - else { - env->cg->used_x87 = 1; + else new_op = gen_binop(env, op1, op2, new_rd_ia32_vfmul); - } } else { new_op = gen_binop(env, op1, op2, new_rd_ia32_Mul); @@ -647,10 +645,10 @@ static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { ir_node *new_op; if (mode_is_float(env->mode)) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) new_op = gen_binop(env, op1, op2, new_rd_ia32_fMax); else { - env->cg->used_x87 = 1; assert(0); } } @@ -677,10 +675,10 @@ static ir_node *gen_Min(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { ir_node *new_op; if (mode_is_float(env->mode)) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) new_op = gen_binop(env, op1, op2, new_rd_ia32_fMin); else { - env->cg->used_x87 = 1; assert(0); } } @@ -767,12 +765,11 @@ static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { assert((expr_op || imm_op) && "invalid operands"); if (mode_is_float(mode)) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) return gen_binop(env, op1, op2, new_rd_ia32_fSub); - else { - env->cg->used_x87 = 1; + else return gen_binop(env, op1, op2, new_rd_ia32_vfsub); - } } else { /* integer SUB */ @@ -1119,6 +1116,7 @@ static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) { int size; if (mode_is_float(env->mode)) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) { new_op = new_rd_ia32_fEor(env->dbg, env->irg, env->block, noreg_gp, noreg_gp, op, noreg_fp, nomem, mode_T); @@ -1135,7 +1133,6 @@ static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) { new_op = new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, 0); } else { - env->cg->used_x87 = 1; new_op = new_rd_ia32_vfchs(env->dbg, env->irg, env->block, op, env->mode); SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn)); } @@ -1183,6 +1180,7 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) { ident *name; if (mode_is_float(mode)) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) { res = new_rd_ia32_fAnd(dbg,irg, block, noreg_gp, noreg_gp, op, noreg_fp, nomem, mode_T); @@ -1199,7 +1197,6 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) { res = new_rd_Proj(dbg, irg, block, res, mode, 0); } else { - env->cg->used_x87 = 1; res = new_rd_ia32_vfabs(dbg, irg, block, op, mode); SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn)); } @@ -1256,12 +1253,11 @@ static ir_node *gen_Load(ia32_transform_env_t *env) { } if (mode_is_float(mode)) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, lptr, noreg, get_Load_mem(node), env->mode); - else { - env->cg->used_x87 = 1; + else new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, lptr, noreg, get_Load_mem(node), env->mode); - } } else { new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, lptr, noreg, get_Load_mem(node), env->mode); @@ -1338,12 +1334,11 @@ static ir_node *gen_Store(ia32_transform_env_t *env) { } if (mode_is_float(mode)) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, sptr, noreg, sval, mem, mode_T); - else { - env->cg->used_x87 = 1; + else new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, sptr, noreg, sval, mem, mode_T); - } } else if (get_mode_size_bits(mode) == 8) { new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, sptr, noreg, sval, mem, mode_T); @@ -1445,10 +1440,10 @@ static ir_node *gen_Cond(ia32_transform_env_t *env) { } if (mode_is_float(get_irn_mode(expr))) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) res = new_rd_ia32_fCondJmp(dbg, irg, block, noreg, noreg, expr, noreg, nomem, mode_T); else { - env->cg->used_x87 = 1; assert(0); } } @@ -1460,10 +1455,10 @@ static ir_node *gen_Cond(ia32_transform_env_t *env) { } else { if (mode_is_float(get_irn_mode(cmp_a))) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) res = new_rd_ia32_fCondJmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem, mode_T); else { - env->cg->used_x87 = 1; assert(0); } } @@ -1758,12 +1753,11 @@ static ir_node *gen_StackParam(ia32_transform_env_t *env) { // } if (mode_is_float(mode)) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T); - else { - env->cg->used_x87 = 1; + else new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T); - } } else { new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T); @@ -1816,16 +1810,14 @@ static ir_node *gen_FrameLoad(ia32_transform_env_t *env) { ir_mode *mode = get_type_mode(get_entity_type(ent)); if (mode_is_float(mode)) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T); - else { - env->cg->used_x87 = 1; + else new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T); - } } - else { + else new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T); - } set_ia32_frame_ent(new_op, ent); set_ia32_use_frame(new_op); @@ -1855,12 +1847,11 @@ static ir_node *gen_FrameStore(ia32_transform_env_t *env) { ir_mode *mode = get_irn_mode(val); if (mode_is_float(mode)) { + FP_USED(env->cg); if (USE_SSE2(env->cg)) new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T); - else { - env->cg->used_x87 = 1; + else new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T); - } } else if (get_mode_size_bits(mode) == 8) { new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, mem, mode_T); -- 2.20.1