Commit b88cb873 authored by Christian Würdig's avatar Christian Würdig
Browse files

added extra finish module

moved irg finish functions into this module
fixed indenting
parent ab5e80c1
......@@ -23,7 +23,7 @@ SOURCES = Makefile.in $(arch)_new_nodes.c $(arch)_new_nodes.h gen_$(arch)_new_no
bearch_$(arch).c gen_$(arch)_regalloc_if_t.h gen_$(arch)_regalloc_if.h gen_$(arch)_regalloc_if.c \
$(arch)_transform.c $(arch)_transform.h $(arch)_gen_decls.c $(arch)_gen_decls.h \
$(arch)_map_regs.c $(arch)_map_regs.h $(arch)_optimize.c $(arch)_optimize.h \
$(arch)_x87.c $(arch)_x87.h $(arch)_intrinsics.c
$(arch)_x87.c $(arch)_x87.h $(arch)_intrinsics.c $(arch)_finish.c $(arch)_finish.h
include $(topdir)/MakeRules
......
......@@ -49,6 +49,7 @@
#include "ia32_optimize.h"
#include "ia32_x87.h"
#include "ia32_dbg_stat.h"
#include "ia32_finish.h"
#define DEBUG_MODULE "firm.be.ia32.isa"
......@@ -446,7 +447,7 @@ static ir_type *ia32_abi_get_between_type(void *self)
ia32_abi_env_t *env = self;
if(!between_type) {
if ( !between_type) {
entity *old_bp_ent;
entity *ret_addr_ent;
entity *omit_fp_ret_addr_ent;
......@@ -463,8 +464,8 @@ static ir_type *ia32_abi_get_between_type(void *self)
set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));
set_type_state(between_type, layout_fixed);
omit_fp_between_type = new_type_struct(IDENT("ia32_between_type_omit_fp"));
omit_fp_ret_addr_ent = new_entity(omit_fp_between_type, IDENT("ret_addr"), ret_addr_type);
omit_fp_between_type = new_type_struct(IDENT("ia32_between_type_omit_fp"));
omit_fp_ret_addr_ent = new_entity(omit_fp_between_type, IDENT("ret_addr"), ret_addr_type);
set_entity_offset_bytes(omit_fp_ret_addr_ent, 0);
set_type_size_bytes(omit_fp_between_type, get_type_size_bytes(ret_addr_type));
......@@ -485,42 +486,42 @@ static ir_type *ia32_abi_get_between_type(void *self)
*/
static int ia32_get_op_estimated_cost(const void *self, const ir_node *irn)
{
int cost;
switch (get_ia32_irn_opcode(irn)) {
case iro_ia32_xDiv:
case iro_ia32_DivMod:
cost = 8;
break;
case iro_ia32_xLoad:
case iro_ia32_l_Load:
case iro_ia32_Load:
case iro_ia32_Push:
case iro_ia32_Pop:
cost = 10;
break;
case iro_ia32_xStore:
case iro_ia32_l_Store:
case iro_ia32_Store:
case iro_ia32_Store8Bit:
cost = 50;
break;
case iro_ia32_MulS:
case iro_ia32_Mul:
case iro_ia32_Mulh:
case iro_ia32_xMul:
case iro_ia32_l_MulS:
case iro_ia32_l_Mul:
cost = 2;
break;
default:
cost = 1;
}
return cost;
int cost;
switch (get_ia32_irn_opcode(irn)) {
case iro_ia32_xDiv:
case iro_ia32_DivMod:
cost = 8;
break;
case iro_ia32_xLoad:
case iro_ia32_l_Load:
case iro_ia32_Load:
case iro_ia32_Push:
case iro_ia32_Pop:
cost = 10;
break;
case iro_ia32_xStore:
case iro_ia32_l_Store:
case iro_ia32_Store:
case iro_ia32_Store8Bit:
cost = 50;
break;
case iro_ia32_MulS:
case iro_ia32_Mul:
case iro_ia32_Mulh:
case iro_ia32_xMul:
case iro_ia32_l_MulS:
case iro_ia32_l_Mul:
cost = 2;
break;
default:
cost = 1;
}
return cost;
}
/**
......@@ -725,147 +726,6 @@ static void ia32_prepare_graph(void *self) {
DEBUG_ONLY(cg->mod = old_mod;)
}
static INLINE int need_constraint_copy(ir_node *irn) {
return \
! is_ia32_Lea(irn) && \
! is_ia32_Conv_I2I(irn) && \
! is_ia32_Conv_I2I8Bit(irn) && \
! is_ia32_CmpCMov(irn) && \
! is_ia32_CmpSet(irn);
}
/**
* Insert copies for all ia32 nodes where the should_be_same requirement
* is not fulfilled.
* Transform Sub into Neg -- Add if IN2 == OUT
*/
static void ia32_finish_node(ir_node *irn, void *env) {
ia32_code_gen_t *cg = env;
const ia32_register_req_t **reqs;
const arch_register_t *out_reg, *in_reg, *in2_reg;
int n_res, i;
ir_node *copy, *in_node, *block, *in2_node;
ia32_op_type_t op_tp;
if (is_ia32_irn(irn)) {
/* AM Dest nodes don't produce any values */
op_tp = get_ia32_op_type(irn);
if (op_tp == ia32_AddrModeD)
goto end;
reqs = get_ia32_out_req_all(irn);
n_res = get_ia32_n_res(irn);
block = get_nodes_block(irn);
/* check all OUT requirements, if there is a should_be_same */
if ((op_tp == ia32_Normal || op_tp == ia32_AddrModeS) && need_constraint_copy(irn))
{
for (i = 0; i < n_res; i++) {
if (arch_register_req_is(&(reqs[i]->req), should_be_same)) {
/* get in and out register */
out_reg = get_ia32_out_reg(irn, i);
in_node = get_irn_n(irn, reqs[i]->same_pos);
in_reg = arch_get_irn_register(cg->arch_env, in_node);
/* don't copy ignore nodes */
if (arch_irn_is(cg->arch_env, in_node, ignore) && is_Proj(in_node))
continue;
/* check if in and out register are equal */
if (! REGS_ARE_EQUAL(out_reg, in_reg)) {
/* in case of a commutative op: just exchange the in's */
/* beware: the current op could be everything, so test for ia32 */
/* commutativity first before getting the second in */
if (is_ia32_commutative(irn)) {
in2_node = get_irn_n(irn, reqs[i]->same_pos ^ 1);
in2_reg = arch_get_irn_register(cg->arch_env, in2_node);
if (REGS_ARE_EQUAL(out_reg, in2_reg)) {
set_irn_n(irn, reqs[i]->same_pos, in2_node);
set_irn_n(irn, reqs[i]->same_pos ^ 1, in_node);
}
else
goto insert_copy;
}
else {
insert_copy:
DBG((cg->mod, LEVEL_1, "inserting copy for %+F in_pos %d\n", irn, reqs[i]->same_pos));
/* create copy from in register */
copy = be_new_Copy(arch_register_get_class(in_reg), cg->irg, block, in_node);
DBG_OPT_2ADDRCPY(copy);
/* destination is the out register */
arch_set_irn_register(cg->arch_env, copy, out_reg);
/* insert copy before the node into the schedule */
sched_add_before(irn, copy);
/* set copy as in */
set_irn_n(irn, reqs[i]->same_pos, copy);
}
}
}
}
}
/* If we have a CondJmp/CmpSet/xCmpSet with immediate, we need to */
/* check if it's the right operand, otherwise we have */
/* to change it, as CMP doesn't support immediate as */
/* left operands. */
if ((is_ia32_CondJmp(irn) || is_ia32_CmpSet(irn) || is_ia32_xCmpSet(irn)) &&
(is_ia32_ImmConst(irn) || is_ia32_ImmSymConst(irn)) &&
op_tp == ia32_AddrModeS)
{
set_ia32_op_type(irn, ia32_AddrModeD);
set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn)));
}
/* check if there is a sub which need to be transformed */
ia32_transform_sub_to_neg_add(irn, cg);
/* transform a LEA into an Add if possible */
ia32_transform_lea_to_add(irn, cg);
}
end:
/* check for peephole optimization */
ia32_peephole_optimization(irn, cg);
}
static void ia32_finish_irg_walker(ir_node *block, void *env) {
ir_node *irn, *next;
for (irn = sched_first(block); ! sched_is_end(irn); irn = next) {
next = sched_next(irn);
ia32_finish_node(irn, env);
}
}
static void ia32_push_on_queue_walker(ir_node *block, void *env) {
waitq *wq = env;
waitq_put(wq, block);
}
/**
* Add Copy nodes for not fulfilled should_be_equal constraints
*/
static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
waitq *wq = new_waitq();
/* Push the blocks on the waitq because ia32_finish_irg_walker starts more walks ... */
irg_block_walk_graph(irg, NULL, ia32_push_on_queue_walker, wq);
while (! waitq_empty(wq)) {
ir_node *block = waitq_get(wq);
ia32_finish_irg_walker(block, cg);
}
del_waitq(wq);
}
/**
* Dummy functions for hooks we don't need but which must be filled.
*/
......
......@@ -419,9 +419,9 @@ const char *ia32_emit_binop(const ir_node *n, ia32_emit_env_t *env) {
get_ia32_cnst(n)); /* tell the assembler to store it's address. */
}
else {
const arch_register_t *in1 = get_in_reg(n, 2);
ir_mode *mode = get_ia32_res_mode(n);
const char *in_name;
const arch_register_t *in1 = get_in_reg(n, get_irn_arity(n) == 5 ? 3 : 2);
ir_mode *mode = get_ia32_res_mode(n);
const char *in_name;
mode = mode ? mode : get_ia32_ls_mode(n);
in_name = ia32_get_reg_name_for_mode(env, mode, in1);
......
......@@ -1099,6 +1099,8 @@ static ir_node *fold_addr(ia32_code_gen_t *cg, ir_node *irn, ir_node *noreg) {
if (temp == base)
base = noreg;
else if (temp == right)
right = noreg;
}
if (isadd) {
......@@ -1402,7 +1404,7 @@ static void optimize_lea(ir_node *irn, void *env) {
foreach_out_edge_safe(left, edge, ne) {
src = get_edge_src_irn(edge);
if (src && (is_ia32_Ld(src) || is_ia32_St(src) || is_ia32_Store8Bit(src))) {
if (src && (get_edge_src_pos(edge) == 0) && (is_ia32_Ld(src) || is_ia32_St(src) || is_ia32_Store8Bit(src))) {
DBG((cg->mod, LEVEL_1, "\nmerging %+F into %+F\n", left, irn));
if (! is_ia32_got_lea(src))
merge_loadstore_lea(src, left);
......@@ -1431,7 +1433,7 @@ static void optimize_am(ir_node *irn, void *env) {
int need_exchange_on_fail = 0;
DEBUG_ONLY(firm_dbg_module_t *mod = cg->mod;)
if (! is_ia32_irn(irn))
if (! is_ia32_irn(irn) || is_ia32_Ld(irn) || is_ia32_St(irn) || is_ia32_Store8Bit(irn))
return;
block = get_nodes_block(irn);
......@@ -1702,6 +1704,9 @@ void ia32_optimize_addressmode(ia32_code_gen_t *cg) {
irg_walk_blkwise_graph(cg->irg, NULL, optimize_lea, cg);
}
if (cg->dump)
be_dump(cg->irg, "-lea", dump_ir_block_graph_sched);
if (cg->opt & IA32_OPT_DOAM) {
/* we need height information for am optimization */
heights_t *h = heights_new(cg->irg);
......
......@@ -1169,7 +1169,7 @@ static ir_node *gen_Rot(ia32_transform_env_t *env) {
* @param op The Minus operand
* @return The created ia32 Minus node
*/
static ir_node *gen_Minus_ex(ia32_transform_env_t *env, ir_node *op) {
ir_node *gen_Minus_ex(ia32_transform_env_t *env, ir_node *op) {
ident *name;
ir_node *new_op;
int size;
......@@ -2619,197 +2619,6 @@ static ir_node *gen_ia32_l_SSEtoX87(ia32_transform_env_t *env) {
*
*********************************************************/
/**
* Transforms a Sub or xSub into Neg--Add iff OUT_REG == SRC2_REG.
* THIS FUNCTIONS MUST BE CALLED AFTER REGISTER ALLOCATION.
*/
void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) {
ia32_transform_env_t tenv;
ir_node *in1, *in2, *noreg, *nomem, *res;
const arch_register_t *in1_reg, *in2_reg, *out_reg, **slots;
/* Return if AM node or not a Sub or xSub */
if (get_ia32_op_type(irn) != ia32_Normal || !(is_ia32_Sub(irn) || is_ia32_xSub(irn)))
return;
noreg = ia32_new_NoReg_gp(cg);
nomem = new_rd_NoMem(cg->irg);
in1 = get_irn_n(irn, 2);
in2 = get_irn_n(irn, 3);
in1_reg = arch_get_irn_register(cg->arch_env, in1);
in2_reg = arch_get_irn_register(cg->arch_env, in2);
out_reg = get_ia32_out_reg(irn, 0);
tenv.block = get_nodes_block(irn);
tenv.dbg = get_irn_dbg_info(irn);
tenv.irg = cg->irg;
tenv.irn = irn;
tenv.mode = get_ia32_res_mode(irn);
tenv.cg = cg;
DEBUG_ONLY(tenv.mod = cg->mod;)
/* in case of sub and OUT == SRC2 we can transform the sequence into neg src2 -- add */
if (REGS_ARE_EQUAL(out_reg, in2_reg)) {
/* generate the neg src2 */
res = gen_Minus_ex(&tenv, in2);
arch_set_irn_register(cg->arch_env, res, in2_reg);
/* add to schedule */
sched_add_before(irn, res);
/* generate the add */
if (mode_is_float(tenv.mode)) {
res = new_rd_ia32_xAdd(tenv.dbg, tenv.irg, tenv.block, noreg, noreg, res, in1, nomem);
set_ia32_am_support(res, ia32_am_Source);
}
else {
res = new_rd_ia32_Add(tenv.dbg, tenv.irg, tenv.block, noreg, noreg, res, in1, nomem);
set_ia32_am_support(res, ia32_am_Full);
set_ia32_commutative(res);
}
set_ia32_res_mode(res, tenv.mode);
SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(tenv.cg, irn));
/* copy register */
slots = get_ia32_slots(res);
slots[0] = in2_reg;
/* add to schedule */
sched_add_before(irn, res);
/* remove the old sub */
sched_remove(irn);
DBG_OPT_SUB2NEGADD(irn, res);
/* exchange the add and the sub */
exchange(irn, res);
}
}
/**
* Transforms a LEA into an Add if possible
* THIS FUNCTIONS MUST BE CALLED AFTER REGISTER ALLOCATION.
*/
void ia32_transform_lea_to_add(ir_node *irn, ia32_code_gen_t *cg) {
ia32_am_flavour_t am_flav;
int imm = 0;
ir_node *res = NULL;
ir_node *nomem, *noreg, *base, *index, *op1, *op2;
char *offs;
ia32_transform_env_t tenv;
const arch_register_t *out_reg, *base_reg, *index_reg;
/* must be a LEA */
if (! is_ia32_Lea(irn))
return;
am_flav = get_ia32_am_flavour(irn);
if (get_ia32_am_sc(irn))
return;
/* only some LEAs can be transformed to an Add */
if (am_flav != ia32_am_B && am_flav != ia32_am_OB && am_flav != ia32_am_OI && am_flav != ia32_am_BI)
return;
noreg = ia32_new_NoReg_gp(cg);
nomem = new_rd_NoMem(cg->irg);
op1 = noreg;
op2 = noreg;
base = get_irn_n(irn, 0);
index = get_irn_n(irn,1);
offs = get_ia32_am_offs(irn);
/* offset has a explicit sign -> we need to skip + */
if (offs && offs[0] == '+')
offs++;
out_reg = arch_get_irn_register(cg->arch_env, irn);
base_reg = arch_get_irn_register(cg->arch_env, base);
index_reg = arch_get_irn_register(cg->arch_env, index);
tenv.block = get_nodes_block(irn);
tenv.dbg = get_irn_dbg_info(irn);
tenv.irg = cg->irg;
tenv.irn = irn;
DEBUG_ONLY(tenv.mod = cg->mod;)
tenv.mode = get_irn_mode(irn);
tenv.cg = cg;
switch(get_ia32_am_flavour(irn)) {
case ia32_am_B:
/* out register must be same as base register */
if (! REGS_ARE_EQUAL(out_reg, base_reg))
return;
op1 = base;
break;
case ia32_am_OB:
/* out register must be same as base register */
if (! REGS_ARE_EQUAL(out_reg, base_reg))
return;
op1 = base;
imm = 1;
break;
case ia32_am_OI:
/* out register must be same as index register */
if (! REGS_ARE_EQUAL(out_reg, index_reg))
return;
op1 = index;
imm = 1;
break;
case ia32_am_BI:
/* out register must be same as one in register */
if (REGS_ARE_EQUAL(out_reg, base_reg)) {
op1 = base;
op2 = index;
}
else if (REGS_ARE_EQUAL(out_reg, index_reg)) {
op1 = index;
op2 = base;
}
else {
/* in registers a different from out -> no Add possible */
return;
}
default:
break;
}
res = new_rd_ia32_Add(tenv.dbg, tenv.irg, tenv.block, noreg, noreg, op1, op2, nomem);
arch_set_irn_register(cg->arch_env, res, out_reg);
set_ia32_op_type(res, ia32_Normal);
set_ia32_commutative(res);
set_ia32_res_mode(res, tenv.mode);
if (imm) {
set_ia32_cnst(res, offs);
set_ia32_immop_type(res, ia32_ImmConst);
}
SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(cg, irn));
/* add Add to schedule */
sched_add_before(irn, res);
DBG_OPT_LEA2ADD(irn, res);
res = new_rd_Proj(tenv.dbg, tenv.irg, tenv.block, res, tenv.mode, pn_ia32_Add_res);
/* add result Proj to schedule */
sched_add_before(irn, res);
/* remove the old LEA */
sched_remove(irn);
/* exchange the Add and the LEA */
exchange(irn, res);
}
/**
* the BAD transformer.
*/
......
......@@ -20,18 +20,6 @@ void ia32_register_transformers(void);
*/
void ia32_transform_node(ir_node *node, void *env);
/**
* Transforms a Sub or fSub into Neg--Add iff OUT_REG == SRC2_REG.
* THIS FUNCTIONS MUST BE CALLED AFTER REGISTER ALLOCATION.
*/
void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg);
/**
* Transforms a LEA into an Add if possible
* THIS FUNCTIONS MUST BE CALLED AFTER REGISTER ALLOCATION.
*/
void ia32_transform_lea_to_add(ir_node *irn, ia32_code_gen_t *cg);
/**
* The Psi selector can be a tree of compares combined with "And"s and "Or"s.
* We create a Set node, respectively a xCmp in case the Psi is a float, for each
......@@ -40,6 +28,15 @@ void ia32_transform_lea_to_add(ir_node *irn, ia32_code_gen_t *cg);
*/
void ia32_transform_psi_cond_tree(ir_node *node, void *env);
/**
* Transforms a Minus node.
*
* @param env The transformation environment
* @param op The Minus operand
* @return The created ia32 Minus node
*/
ir_node *gen_Minus_ex(ia32_transform_env_t *env, ir_node *op);
#ifndef NDEBUG
/**
* Prints the old node name on cg obst and returns a pointer to it.
......
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