Commit 873a9d9a authored by Matthias Braun's avatar Matthias Braun
Browse files

ia32/amd64: Cleanup/unify call attribute

parent 1dfae908
......@@ -400,30 +400,15 @@ static ir_type *get_type_for_insn_size(x86_insn_size_t const size)
*/
static void amd64_collect_frame_entity_nodes(ir_node *node, void *data)
{
if (!is_amd64_irn(node))
return;
/* Disable coalescing for "returns twice" calls: In case of setjmp/longjmp
* our control flow graph isn't completely correct: There are no backedges
* from longjmp to the setjmp => coalescing would produce wrong results. */
be_fec_env_t *const env = (be_fec_env_t*)data;
if (is_amd64_call(node)) {
const amd64_call_addr_attr_t *attrs = get_amd64_call_addr_attr_const(node);
const ir_type *type = attrs->call_tp;
const mtp_additional_properties mtp
= get_method_additional_properties(type);
if (mtp & mtp_property_returns_twice)
be_forbid_coalescing(env);
}
/* we are only interested to report Load nodes */
if (!amd64_loads(node))
if (!is_amd64_irn(node) || !amd64_loads(node))
return;
const amd64_addr_attr_t *attr = get_amd64_addr_attr_const(node);
x86_imm32_t const *imm = &attr->addr.immediate;
if (imm->kind == X86_IMM_FRAMEENT && imm->entity == NULL) {
const ir_type *type = get_type_for_insn_size(attr->base.size);
ir_type const *const type = get_type_for_insn_size(attr->base.size);
be_fec_env_t *const env = (be_fec_env_t*)data;
be_load_needs_frame_entity(env, node, type);
}
}
......@@ -607,10 +592,16 @@ static void amd64_sp_sim(ir_node *const node, stack_pointer_state_t *state)
*/
static void amd64_finish_and_emit(ir_graph *irg)
{
bool omit_fp = amd64_get_irg_data(irg)->omit_fp;
amd64_irg_data_t const *const irg_data = amd64_get_irg_data(irg);
bool const omit_fp = irg_data->omit_fp;
/* create and coalesce frame entities */
be_fec_env_t *fec_env = be_new_frame_entity_coalescer(irg);
/* Disable coalescing for "returns twice" calls: In case of setjmp/longjmp
* our control flow graph isn't completely correct: There are no backedges
* from longjmp to the setjmp => coalescing would produce wrong results. */
if (irg_data->has_returns_twice_call)
be_forbid_coalescing(fec_env);
irg_walk_graph(irg, NULL, amd64_collect_frame_entity_nodes, fec_env);
be_assign_entities(fec_env, amd64_set_frame_entity, omit_fp);
be_free_frame_entity_coalescer(fec_env);
......
......@@ -16,6 +16,7 @@
typedef struct amd64_irg_data_t {
bool omit_fp;
bool has_returns_twice_call;
} amd64_irg_data_t;
extern pmap *amd64_constants; /**< A map of entities that store const tarvals */
......
......@@ -232,7 +232,8 @@ int amd64_call_addr_attrs_equal(const ir_node *const a, const ir_node *const b)
= get_amd64_call_addr_attr_const(a);
const amd64_call_addr_attr_t *const attr_b
= get_amd64_call_addr_attr_const(b);
return amd64_addr_attrs_equal(a, b) && attr_a->call_tp == attr_b->call_tp;
return amd64_addr_attrs_equal(a, b)
&& attr_a->n_reg_results == attr_b->n_reg_results;
}
int amd64_x87_attrs_equal(const ir_node *const a, const ir_node *const b)
......
......@@ -88,9 +88,9 @@ typedef struct amd64_switch_jmp_attr_t {
} amd64_switch_jmp_attr_t;
typedef struct amd64_call_addr_attr_t {
amd64_addr_attr_t base;
unsigned n_reg_results; /**< number of results in registers */
ir_type *call_tp;
amd64_addr_attr_t base;
unsigned n_reg_results; /**< number of results in registers */
bool returns_twice;
} amd64_call_addr_attr_t;
typedef struct amd64_x87_attr_t {
......
......@@ -1754,6 +1754,9 @@ static ir_node *gen_Call(ir_node *const node)
assert(n_params == cconv->n_parameters);
if (get_method_additional_properties(type) & mtp_property_returns_twice)
amd64_get_irg_data(irg)->has_returns_twice_call = true;
/* construct arguments */
/* stack pointer input */
......@@ -1917,7 +1920,6 @@ no_call_mem:;
},
.addr = addr,
},
.call_tp = type,
.n_reg_results = cconv->n_reg_results,
};
......
......@@ -902,19 +902,6 @@ static void ia32_after_ra_walker(ir_node *block, void *env)
*/
static void ia32_collect_frame_entity_nodes(ir_node *node, void *data)
{
be_fec_env_t *env = (be_fec_env_t*)data;
/* Disable coalescing for "returns twice" calls: In case of setjmp/longjmp
* our control flow graph isn't completely correct: There are no backedges
* from longjmp to the setjmp => coalescing would produce wrong results. */
if (is_ia32_Call(node)) {
const ia32_call_attr_t *attrs = get_ia32_call_attr_const(node);
const ir_type *type = attrs->call_tp;
mtp_additional_properties mtp
= get_method_additional_properties(type);
if (mtp & mtp_property_returns_twice)
be_forbid_coalescing(env);
}
if (!is_ia32_irn(node) || get_ia32_op_type(node) != ia32_AddrModeS)
return;
ia32_attr_t const *const attr = get_ia32_attr_const(node);
......@@ -956,7 +943,8 @@ static void ia32_collect_frame_entity_nodes(ir_node *node, void *data)
}
}
panic("invalid frame use type");
request_entity:
request_entity:;
be_fec_env_t *env = (be_fec_env_t*)data;
be_load_needs_frame_entity(env, node, type);
}
......@@ -1079,16 +1067,23 @@ static x87_attr_t *ia32_get_x87_attr(ir_node *const node)
return &attr->x87;
}
/**
* Last touchups for the graph before emit: x87 simulation to replace the
* virtual with real x87 instructions, creating a block schedule and
* peephole optimizations.
*/
static void ia32_before_emit(ir_graph *irg)
{
/* Last touchups for the graph before emit: x87 simulation to replace the
* virtual with real x87 instructions, creating a block schedule and
* peephole optimizations.
*/
bool omit_fp = ia32_get_irg_data(irg)->omit_fp;
ia32_irg_data_t const *const irg_data = ia32_get_irg_data(irg);
bool const omit_fp = irg_data->omit_fp;
/* create and coalesce frame entities */
be_fec_env_t *fec_env = be_new_frame_entity_coalescer(irg);
/* Disable coalescing for "returns twice" calls: In case of setjmp/longjmp
* our control flow graph isn't completely correct: There are no backedges
* from longjmp to the setjmp => coalescing would produce wrong results. */
if (irg_data->has_returns_twice_call)
be_forbid_coalescing(fec_env);
irg_walk_graph(irg, NULL, ia32_collect_frame_entity_nodes, fec_env);
be_assign_entities(fec_env, ia32_set_frame_entity, omit_fp);
be_free_frame_entity_coalescer(fec_env);
......
......@@ -25,14 +25,14 @@
#define IA32_REGISTER_SIZE 4
typedef struct ia32_irg_data_t {
bool do_x87_sim; /**< Should simulate x87 register stack. */
bool omit_fp; /**< No frame pointer is used. */
ir_node *noreg_gp; /**< unique NoReg_GP node */
ir_node *noreg_fp; /**< unique NoReg_FP node */
ir_node *noreg_xmm; /**< unique NoReg_XMM node */
ir_node *fpu_trunc_mode; /**< truncate fpu mode */
ir_node *get_eip; /**< get eip node */
bool do_x87_sim; /**< Should simulate x87 register stack. */
bool omit_fp; /**< No frame pointer is used. */
bool has_returns_twice_call;
ir_node *noreg_gp; /**< unique NoReg_GP node */
ir_node *noreg_fp; /**< unique NoReg_FP node */
ir_node *noreg_xmm; /**< unique NoReg_XMM node */
ir_node *fpu_trunc_mode; /**< truncate fpu mode */
ir_node *get_eip; /**< get eip node */
} ia32_irg_data_t;
extern pmap *ia32_tv_ent; /**< A map of entities that store const tarvals */
......
......@@ -594,15 +594,15 @@ void init_ia32_immediate_attributes(ir_node *res, x86_imm32_t const *const imm)
attr->imm = *imm;
}
void init_ia32_call_attributes(ir_node* res, unsigned pop, ir_type* call_tp)
void init_ia32_call_attributes(ir_node* res, uint8_t pop, uint8_t n_reg_results)
{
ia32_call_attr_t *attr = (ia32_call_attr_t*)get_irn_generic_attr(res);
#ifndef NDEBUG
attr->attr.attr_type |= IA32_ATTR_ia32_call_attr_t;
#endif
attr->pop = pop;
attr->call_tp = call_tp;
attr->pop = pop;
attr->n_reg_results = n_reg_results;
}
void init_ia32_copyb_attributes(ir_node *res, unsigned size)
......@@ -688,7 +688,8 @@ int ia32_call_attrs_equal(const ir_node *a, const ir_node *b)
const ia32_call_attr_t *attr_a = get_ia32_call_attr_const(a);
const ia32_call_attr_t *attr_b = get_ia32_call_attr_const(b);
return ia32_attrs_equal_(&attr_a->attr, &attr_b->attr)
&& attr_a->pop == attr_b->pop && attr_a->call_tp == attr_b->call_tp;
&& attr_a->pop == attr_b->pop
&& attr_a->n_reg_results == attr_b->n_reg_results;
}
int ia32_copyb_attrs_equal(const ir_node *a, const ir_node *b)
......
......@@ -19,7 +19,7 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags,
x86_insn_size_t size);
void init_ia32_x87_attributes(ir_node *res);
void init_ia32_immediate_attributes(ir_node *res, x86_imm32_t const *const imm);
void init_ia32_call_attributes(ir_node* res, unsigned pop, ir_type* call_tp);
void init_ia32_call_attributes(ir_node* res, uint8_t pop, uint8_t n_reg_res);
void init_ia32_copyb_attributes(ir_node *res, unsigned size);
void init_ia32_condcode_attributes(ir_node *res, x86_condition_code_t cc);
void init_ia32_climbframe_attributes(ir_node *res, unsigned count);
......
......@@ -126,8 +126,8 @@ struct ia32_attr_t {
typedef struct ia32_call_attr_t ia32_call_attr_t;
struct ia32_call_attr_t {
ia32_attr_t attr; /**< generic attribute */
unsigned pop; /**< number of bytes that get popped by the callee */
ir_type *call_tp; /**< The call type, copied from the original Call node. */
uint8_t pop; /**< number of bytes that get popped by the callee */
uint8_t n_reg_results;
};
/**
......
......@@ -94,7 +94,7 @@ $custom_init_attr_func = \&ia32_custom_init_attr;
"init_ia32_attributes(res, irn_flags, in_reqs, n_res, size);",
ia32_call_attr_t =>
"init_ia32_attributes(res, irn_flags, in_reqs, n_res, size);\n".
"\tinit_ia32_call_attributes(res, pop, call_tp);",
"\tinit_ia32_call_attributes(res, pop, n_reg_results);",
ia32_condcode_attr_t =>
"init_ia32_attributes(res, irn_flags, in_reqs, n_res, size);\n".
"\tinit_ia32_condcode_attributes(res, condition_code);",
......@@ -1251,7 +1251,7 @@ Call => {
fixed => "x86_insn_size_t const size = X86_SIZE_32;",
emit => "call %*AS3",
attr_type => "ia32_call_attr_t",
attr => "unsigned pop, ir_type *call_tp",
attr => "uint8_t pop, uint8_t n_reg_results",
am => "source,unary",
latency => 4, # random number
},
......
......@@ -5029,6 +5029,9 @@ static ir_node *gen_Call(ir_node *node)
ir_node **const in = ALLOCAN(ir_node*, n_ins);
arch_register_req_t const **const in_req = be_allocate_in_reqs(irg, n_ins);
if (get_method_additional_properties(type) & mtp_property_returns_twice)
ia32_get_irg_data(irg)->has_returns_twice_call = true;
in[n_ia32_Call_base] = am.addr.base;
in_req[n_ia32_Call_base] = req_gp;
in[n_ia32_Call_index] = am.addr.index;
......@@ -5116,7 +5119,9 @@ static ir_node *gen_Call(ir_node *node)
unsigned const n_out = o + n_reg_results + n_caller_saves;
/* Create node. */
ir_node *const call = new_bd_ia32_Call(dbgi, block, in_arity, in, in_req, n_out, cconv->sp_delta, type);
ir_node *const call = new_bd_ia32_Call(dbgi, block, in_arity, in, in_req,
n_out, cconv->sp_delta,
n_reg_results);
arch_set_additional_pressure(call, &ia32_reg_classes[CLASS_ia32_gp],
add_pressure);
......
......@@ -1177,8 +1177,8 @@ static void sim_ia32_Call(x87_state *const state, ir_node *const n)
/* at the begin of a call the x87 state should be empty */
assert(state->depth == 0 && "stack not empty before call");
ir_type *const call_tp = get_ia32_call_attr_const(n)->call_tp;
if (get_method_n_ress(call_tp) != 0) {
unsigned n_reg_results = get_ia32_call_attr_const(n)->n_reg_results;
if (n_reg_results != 0) {
/* If the called function returns a float, it is returned in st(0).
* This even happens if the return value is NOT used.
* Moreover, only one return result is supported. */
......
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