Commit 8e750128 authored by Matthias Braun's avatar Matthias Braun
Browse files

- cleaned up spill/reload transform code a bit

- don't do address mode if spill size is bad (no addressmode for mode_E)
- don't do super exact spilling for now
- fixed bug where node compare didn't respect some node attributes
parent 20867cbc
...@@ -723,6 +723,43 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in ...@@ -723,6 +723,43 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in
return inverse; return inverse;
} }
/**
* Get the mode that should be used for spilling value node
*/
static ir_mode *get_spill_mode(ia32_code_gen_t *cg, const ir_node *node)
{
ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode)) {
#if 0
// super exact spilling...
if (USE_SSE2(cg))
return mode_D;
else
return mode_E;
#else
return mode;
#endif
}
else
return mode_Is;
assert(0);
return mode;
}
/**
* Checks wether an addressmode reload for a node with mode mode is compatible
* with a spillslot of mode spill_mode
*/
static int ia32_is_spillmode_compatible(const ir_mode *mode, const ir_mode *spillmode)
{
if(mode_is_float(mode)) {
return mode == spillmode;
} else {
return 1;
}
}
/** /**
* Check if irn can load it's operand at position i from memory (source addressmode). * Check if irn can load it's operand at position i from memory (source addressmode).
* @param self Pointer to irn ops itself * @param self Pointer to irn ops itself
...@@ -731,10 +768,17 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in ...@@ -731,10 +768,17 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in
* @return Non-Zero if operand can be loaded * @return Non-Zero if operand can be loaded
*/ */
static int ia32_possible_memory_operand(const void *self, const ir_node *irn, unsigned int i) { static int ia32_possible_memory_operand(const void *self, const ir_node *irn, unsigned int i) {
const ia32_irn_ops_t *ops = self;
ia32_code_gen_t *cg = ops->cg;
ir_node *op = get_irn_n(irn, i);
const ir_mode *mode = get_irn_mode(op);
const ir_mode *spillmode = get_spill_mode(cg, op);
if (! is_ia32_irn(irn) || /* must be an ia32 irn */ if (! is_ia32_irn(irn) || /* must be an ia32 irn */
get_irn_arity(irn) != 5 || /* must be a binary operation */ get_irn_arity(irn) != 5 || /* must be a binary operation */
get_ia32_op_type(irn) != ia32_Normal || /* must not already be a addressmode irn */ get_ia32_op_type(irn) != ia32_Normal || /* must not already be a addressmode irn */
! (get_ia32_am_support(irn) & ia32_am_Source) || /* must be capable of source addressmode */ ! (get_ia32_am_support(irn) & ia32_am_Source) || /* must be capable of source addressmode */
! ia32_is_spillmode_compatible(mode, spillmode) ||
(i != 2 && i != 3) || /* a "real" operand position must be requested */ (i != 2 && i != 3) || /* a "real" operand position must be requested */
(i == 2 && ! is_ia32_commutative(irn)) || /* if first operand requested irn must be commutative */ (i == 2 && ! is_ia32_commutative(irn)) || /* if first operand requested irn must be commutative */
is_ia32_use_frame(irn)) /* must not already use frame */ is_ia32_use_frame(irn)) /* must not already use frame */
...@@ -980,12 +1024,12 @@ static void ia32_before_ra(void *self) { ...@@ -980,12 +1024,12 @@ static void ia32_before_ra(void *self) {
/** /**
* Transforms a be node into a Load. * Transforms a be_Reload into a ia32 Load.
*/ */
static void transform_to_Load(ia32_transform_env_t *env) { static void transform_to_Load(ia32_transform_env_t *env) {
ir_node *irn = env->irn; ir_node *irn = env->irn;
ir_entity *ent = be_get_frame_entity(irn); ir_entity *ent = be_get_frame_entity(irn);
ir_mode *mode = env->mode; ir_mode *mode = get_spill_mode(env->cg, irn);
ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *noreg = ia32_new_NoReg_gp(env->cg);
ir_node *sched_point = NULL; ir_node *sched_point = NULL;
ir_node *ptr = get_irg_frame(env->irg); ir_node *ptr = get_irg_frame(env->irg);
...@@ -1034,12 +1078,13 @@ static void transform_to_Load(ia32_transform_env_t *env) { ...@@ -1034,12 +1078,13 @@ static void transform_to_Load(ia32_transform_env_t *env) {
} }
/** /**
* Transforms a be node into a Store. * Transforms a be_Spill node into a ia32 Store.
*/ */
static void transform_to_Store(ia32_transform_env_t *env) { static void transform_to_Store(ia32_transform_env_t *env) {
ir_node *irn = env->irn; ir_node *irn = env->irn;
ir_entity *ent = be_get_frame_entity(irn); ir_entity *ent = be_get_frame_entity(irn);
ir_mode *mode = env->mode; const ir_node *spillval = get_irn_n(irn, be_pos_Spill_val);
ir_mode *mode = get_spill_mode(env->cg, spillval);
ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *noreg = ia32_new_NoReg_gp(env->cg);
ir_node *nomem = new_rd_NoMem(env->irg); ir_node *nomem = new_rd_NoMem(env->irg);
ir_node *ptr = get_irg_frame(env->irg); ir_node *ptr = get_irg_frame(env->irg);
...@@ -1209,22 +1254,6 @@ static void transform_MemPerm(ia32_transform_env_t *env) { ...@@ -1209,22 +1254,6 @@ static void transform_MemPerm(ia32_transform_env_t *env) {
sched_remove(node); sched_remove(node);
} }
/**
* Fix the mode of Spill/Reload
*/
static ir_mode *fix_spill_mode(ia32_code_gen_t *cg, ir_mode *mode)
{
if (mode_is_float(mode)) {
if (USE_SSE2(cg))
mode = mode_D;
else
mode = mode_E;
}
else
mode = mode_Is;
return mode;
}
/** /**
* Block-Walker: Calls the transform functions Spill and Reload. * Block-Walker: Calls the transform functions Spill and Reload.
*/ */
...@@ -1241,24 +1270,15 @@ static void ia32_after_ra_walker(ir_node *block, void *env) { ...@@ -1241,24 +1270,15 @@ static void ia32_after_ra_walker(ir_node *block, void *env) {
/* beware: the schedule is changed here */ /* beware: the schedule is changed here */
for (node = sched_last(block); !sched_is_begin(node); node = prev) { for (node = sched_last(block); !sched_is_begin(node); node = prev) {
prev = sched_prev(node); prev = sched_prev(node);
tenv.dbg = get_irn_dbg_info(node);
tenv.irn = node;
tenv.mode = get_irn_mode(node);
if (be_is_Reload(node)) { if (be_is_Reload(node)) {
/* we always reload the whole register */
tenv.dbg = get_irn_dbg_info(node);
tenv.irn = node;
tenv.mode = fix_spill_mode(cg, get_irn_mode(node));
transform_to_Load(&tenv); transform_to_Load(&tenv);
} } else if (be_is_Spill(node)) {
else if (be_is_Spill(node)) {
ir_node *spillval = get_irn_n(node, be_pos_Spill_val);
/* we always spill the whole register */
tenv.dbg = get_irn_dbg_info(node);
tenv.irn = node;
tenv.mode = fix_spill_mode(cg, get_irn_mode(spillval));
transform_to_Store(&tenv); transform_to_Store(&tenv);
} } else if(be_is_MemPerm(node)) {
else if(be_is_MemPerm(node)) {
tenv.dbg = get_irn_dbg_info(node);
tenv.irn = node;
transform_MemPerm(&tenv); transform_MemPerm(&tenv);
} }
} }
...@@ -1267,9 +1287,6 @@ static void ia32_after_ra_walker(ir_node *block, void *env) { ...@@ -1267,9 +1287,6 @@ static void ia32_after_ra_walker(ir_node *block, void *env) {
/** /**
* We transform Spill and Reload here. This needs to be done before * We transform Spill and Reload here. This needs to be done before
* stack biasing otherwise we would miss the corrected offset for these nodes. * stack biasing otherwise we would miss the corrected offset for these nodes.
*
* If x87 instruction should be emitted, run the x87 simulator and patch
* the virtual instructions. This must obviously be done after register allocation.
*/ */
static void ia32_after_ra(void *self) { static void ia32_after_ra(void *self) {
ia32_code_gen_t *cg = self; ia32_code_gen_t *cg = self;
...@@ -1281,7 +1298,9 @@ static void ia32_after_ra(void *self) { ...@@ -1281,7 +1298,9 @@ static void ia32_after_ra(void *self) {
} }
/** /**
* Last touchups for the graph before emit * Last touchups for the graph before emit: x87 simulation to replace the
* virtual with real x87 instructions, creating a block schedule and peephole
* optimisations.
*/ */
static void ia32_finish(void *self) { static void ia32_finish(void *self) {
ia32_code_gen_t *cg = self; ia32_code_gen_t *cg = self;
......
...@@ -349,7 +349,7 @@ static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) { ...@@ -349,7 +349,7 @@ static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
fprintf(F, "AM scale = %d\n", get_ia32_am_scale(n)); fprintf(F, "AM scale = %d\n", get_ia32_am_scale(n));
/* dump pn code */ /* dump pn code */
fprintf(F, "pn_code = %ld\n", get_ia32_pncode(n)); fprintf(F, "pn_code = %ld (%s)\n", get_ia32_pncode(n), get_pnc_string(get_ia32_pncode(n)));
/* dump n_res */ /* dump n_res */
fprintf(F, "n_res = %d\n", get_ia32_n_res(n)); fprintf(F, "n_res = %d\n", get_ia32_n_res(n));
...@@ -1386,13 +1386,28 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags, const ia32_regi ...@@ -1386,13 +1386,28 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags, const ia32_regi
int ia32_compare_immop_attr(ia32_attr_t *a, ia32_attr_t *b) { int ia32_compare_immop_attr(ia32_attr_t *a, ia32_attr_t *b) {
int equ = 0; int equ = 0;
if (a->data.tp == b->data.tp) { if (a->data.tp != b->data.tp)
equ = (a->cnst == b->cnst); return 1;
equ = equ ? (a->data.use_frame == b->data.use_frame) : 0;
if (equ && a->data.use_frame && b->data.use_frame) if (a->cnst != b->cnst)
equ = (a->frame_ent == b->frame_ent); return 1;
}
if (a->data.use_frame != b->data.use_frame)
return 1;
if (a->data.use_frame && a->frame_ent != b->frame_ent)
return 1;
if (a->data.am_flavour != b->data.am_flavour
|| a->data.am_scale != b->data.am_scale
|| a->data.offs_sign != b->data.offs_sign
|| a->data.am_sc_sign != b->data.am_sc_sign
|| a->am_offs != b->am_offs
|| a->am_sc != b->am_sc)
return 1;
if(a->pn_code != b->pn_code)
return 1;
return !equ; return !equ;
} }
......
...@@ -1230,6 +1230,7 @@ else { ...@@ -1230,6 +1230,7 @@ else {
"comment" => "construct Set: Set(sel) == sel ? 1 : 0", "comment" => "construct Set: Set(sel) == sel ? 1 : 0",
"reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "eax ebx ecx edx", "none" ] }, "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "eax ebx ecx edx", "none" ] },
"outs" => [ "res", "M" ], "outs" => [ "res", "M" ],
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"latency" => 2, "latency" => 2,
"units" => [ "ALU" ], "units" => [ "ALU" ],
}, },
......
Supports Markdown
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