Commit 61c58871 authored by Matthias Braun's avatar Matthias Braun
Browse files

bespillslots: Change spillslot collection API to take size+align

Taking explicit size+po2align makes things easier compared to the
previously used ir_type: ir_type* is a middleend concept not everything
in the backend is represented as a type/mode anymore (x86_insn_size_t).
Furthermore we only respected size+alignment of that type anyway,
additional semantics would be unexpectedly ignored. It also simplifies
the code in some places.

This should also naturally fix a problem in 188.amp where we wrongly
passed the type for mode_Ls instead of the type for mode_D before.
parent 3bf2c113
......@@ -378,23 +378,14 @@ static void amd64_handle_intrinsics(ir_graph *irg)
}
static void amd64_set_frame_entity(ir_node *node, ir_entity *entity,
const ir_type *type)
unsigned size, unsigned po2align)
{
(void)type;
(void)size;
(void)po2align;
amd64_addr_attr_t *attr = get_amd64_addr_attr(node);
attr->addr.immediate.entity = entity;
}
static ir_type *get_type_for_insn_size(x86_insn_size_t const size)
{
/* TODO: do not hardcode node names here */
switch (size) {
case X86_SIZE_128: return get_type_for_mode(amd64_mode_xmm);
case X86_SIZE_80: return x86_type_E;
default: return get_type_for_mode(mode_Lu);
}
}
/**
* Collects nodes that need frame entities assigned.
*/
......@@ -404,12 +395,20 @@ static void amd64_collect_frame_entity_nodes(ir_node *node, void *data)
if (!is_amd64_irn(node) || !amd64_loads(node))
return;
const amd64_addr_attr_t *attr = get_amd64_addr_attr_const(node);
amd64_addr_attr_t const *attr = get_amd64_addr_attr_const(node);
x86_imm32_t const *imm = &attr->addr.immediate;
if (imm->kind == X86_IMM_FRAMEENT && imm->entity == NULL) {
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);
be_fec_env_t *const env = (be_fec_env_t*)data;
unsigned size;
unsigned po2align;
if (attr->base.size == X86_SIZE_80) {
size = 12;
po2align = 2;
} else {
size = x86_bytes_from_size(attr->base.size);
po2align = log2_floor(size);
}
be_load_needs_frame_entity(env, node, size, po2align);
}
}
......
......@@ -42,16 +42,17 @@ static void arm_collect_frame_entity_nodes(ir_node *node, void *data)
if (entity != NULL)
return;
const ir_mode *mode = attr->load_store_mode;
const ir_type *type = get_type_for_mode(mode);
be_fec_env_t *env = (be_fec_env_t*)data;
be_load_needs_frame_entity(env, node, type);
be_load_needs_frame_entity(env, node, get_mode_size_bytes(mode),
log2_floor(get_mode_size_bytes(mode)));
}
static void arm_set_frame_entity(ir_node *node, ir_entity *entity,
const ir_type *type)
unsigned size, unsigned po2align)
{
(void)type;
(void)size;
(void)po2align;
arm_load_store_attr_t *attr = get_arm_load_store_attr(node);
attr->entity = entity;
}
......
......@@ -47,8 +47,9 @@ typedef struct spill_t {
* produce. All spills that are joined through Phis form a spillweb.
*/
struct spillweb_t {
spillweb_t *merged_with;
const ir_type *type;
spillweb_t *merged_with;
unsigned slot_size;
unsigned slot_po2align;
};
typedef struct affinity_edge_t {
......@@ -116,28 +117,11 @@ static inline ir_node *get_memory_edge(const ir_node *node)
return NULL;
}
#ifndef NDEBUG
static bool modes_compatible(const ir_mode *mode0, const ir_mode *mode1)
{
ir_mode_arithmetic arith0 = get_mode_arithmetic(mode0);
ir_mode_arithmetic arith1 = get_mode_arithmetic(mode1);
return arith0 == arith1
|| (arith0 == irma_ieee754 && arith1 == irma_x86_extended_float)
|| (arith1 == irma_ieee754 && arith0 == irma_x86_extended_float);
}
#endif
static void merge_spilltypes(spillweb_t *web, const ir_type *type1)
static void merge_slotsizes(spillweb_t *web, unsigned size, unsigned po2align)
{
assert(web->merged_with == NULL);
assert(type1 != NULL);
const ir_type *type0 = web->type;
if (type0 == NULL) {
web->type = type1;
return;
}
assert(modes_compatible(get_type_mode(type0), get_type_mode(type1)));
web->type = get_type_size(type1) > get_type_size(type0) ? type1 : type0;
web->slot_size = MAX(size, web->slot_size);
web->slot_po2align = MAX(po2align, web->slot_po2align);
}
static spillweb_t *get_spill_web(spillweb_t *begin)
......@@ -159,9 +143,7 @@ static spillweb_t *merge_spillwebs(spillweb_t *web0, spillweb_t *web1)
assert(web0 != web1);
assert(web0->merged_with == NULL);
assert(web1->merged_with == NULL);
const ir_type *type1 = web1->type;
if (type1 != NULL)
merge_spilltypes(web0, type1);
merge_slotsizes(web0, web1->slot_size, web1->slot_po2align);
web1->merged_with = web0;
return web0;
}
......@@ -232,15 +214,16 @@ static spill_t *collect_spill(be_fec_env_t *env, ir_node *node, spillweb_t *web)
return spill;
}
void be_load_needs_frame_entity(be_fec_env_t *env, ir_node *node,
const ir_type *type)
void be_load_needs_frame_entity(be_fec_env_t *const env, ir_node *const node,
unsigned const slot_size,
unsigned const slot_po2align)
{
ir_node *mem = get_memory_edge(node);
spill_t *spill = collect_spill(env, mem, NULL);
DB((dbg, LEVEL_1, "Slot %d: Reload: %+F Type %+F\n",
spill->spillslot, node, type));
ir_node *const mem = get_memory_edge(node);
spill_t *const spill = collect_spill(env, mem, NULL);
DB((dbg, LEVEL_1, "Slot %d: Reload: %+F Size: %u Align: %u\n",
spill->spillslot, node, slot_size, 1u << slot_po2align));
ARR_APP1(ir_node*, env->reloads, node);
merge_spilltypes(spill->web, type);
merge_slotsizes(spill->web, slot_size, slot_po2align);
}
static int merge_interferences(be_fec_env_t *env, bitset_t** interferences,
......@@ -374,9 +357,9 @@ static void do_greedy_coalescing(be_fec_env_t *env)
}
typedef struct spill_slot_t {
int size;
int align;
ir_entity *entity;
unsigned size;
unsigned po2align;
} spill_slot_t;
typedef struct memperm_entry_t memperm_entry_t;
......@@ -390,7 +373,7 @@ struct memperm_entry_t {
typedef struct memperm_t {
ir_node *block;
int entrycount;
unsigned entrycount;
memperm_entry_t *entries;
} memperm_t;
......@@ -418,40 +401,22 @@ static memperm_t *get_memperm(be_fec_env_t *env, ir_node *block)
return res;
}
/**
* Enlarges a spillslot (if necessary) so that it can carry a value of size
* @p othersize and alignment @p otheralign.
*/
static void enlarge_spillslot(spill_slot_t *slot, int otheralign, int othersize)
{
if (othersize > slot->size)
slot->size = othersize;
if (otheralign > slot->align) {
if (otheralign % slot->align != 0)
slot->align *= otheralign;
else
slot->align = otheralign;
} else if (slot->align % otheralign != 0) {
slot->align *= otheralign;
}
}
static void assign_spill_entity(be_fec_env_t *env, ir_node *node,
ir_entity *entity, const ir_type *type)
ir_entity *entity, unsigned size,
unsigned po2align)
{
if (is_NoMem(node))
return;
if (is_Sync(node)) {
foreach_irn_in(node, i, in) {
assert(!is_Phi(in));
assign_spill_entity(env, in, entity, type);
assign_spill_entity(env, in, entity, size, po2align);
}
return;
}
node = skip_Proj(node);
env->set_frame_entity(node, entity, type);
env->set_frame_entity(node, entity, size, po2align);
}
/**
......@@ -466,20 +431,13 @@ static void assign_spillslots(be_fec_env_t *env)
/* construct spillslots */
for (size_t s = 0; s < spillcount; ++s) {
const spill_t *spill = spills[s];
int slotid = spill->spillslot;
const spillweb_t *web = get_spill_web(spill->web);
const ir_type *type = web->type;
int size = get_type_size(type);
int align = get_type_alignment(type);
spill_slot_t *slot = &spillslots[slotid];
if (slot->align == 0 && slot->size == 0) {
slot->align = align;
slot->size = size;
} else {
enlarge_spillslot(slot, align, size);
}
const spill_t *const spill = spills[s];
int const slotid = spill->spillslot;
spillweb_t const *const web = get_spill_web(spill->web);
spill_slot_t *const slot = &spillslots[slotid];
slot->size = MAX(slot->size, web->slot_size);
slot->po2align = MAX(slot->po2align, web->slot_po2align);
}
ir_type *const frame = get_irg_frame_type(env->irg);
......@@ -490,7 +448,7 @@ static void assign_spillslots(be_fec_env_t *env)
spill_slot_t *slot = &spillslots[slotid];
if (slot->entity == NULL)
slot->entity = new_spillslot(frame, slot->size, slot->align);
slot->entity = new_spillslot(frame, slot->size, slot->po2align);
if (is_Phi(node)) {
ir_node *block = get_nodes_block(node);
......@@ -504,16 +462,14 @@ static void assign_spillslots(be_fec_env_t *env)
int argslotid = argspill->spillslot;
if (slotid != argslotid) {
memperm_t *memperm;
memperm_entry_t *entry;
spill_slot_t *argslot = &spillslots[argslotid];
spill_slot_t *argslot = &spillslots[argslotid];
if (argslot->entity == NULL)
argslot->entity = new_spillslot(frame, argslot->size,
argslot->align);
argslot->po2align);
memperm = get_memperm(env, predblock);
entry = OALLOC(&env->obst, memperm_entry_t);
memperm_t *const memperm = get_memperm(env, predblock);
memperm_entry_t *const entry
= OALLOC(&env->obst, memperm_entry_t);
entry->node = node;
entry->pos = i;
entry->in = argslot->entity;
......@@ -525,7 +481,8 @@ static void assign_spillslots(be_fec_env_t *env)
}
} else {
const spillweb_t *web = get_spill_web(spill->web);
assign_spill_entity(env, node, slot->entity, web->type);
assign_spill_entity(env, node, slot->entity, web->slot_size,
web->slot_po2align);
}
}
......@@ -537,8 +494,8 @@ static void assign_spillslots(be_fec_env_t *env)
const spillweb_t *web = get_spill_web(spill->web);
assert(slot->entity != NULL);
env->set_frame_entity(reload, slot->entity, web->type);
env->set_frame_entity(reload, slot->entity, web->slot_size,
web->slot_po2align);
}
}
......
......@@ -32,10 +32,11 @@ void be_free_frame_entity_coalescer(be_fec_env_t *env);
void be_forbid_coalescing(be_fec_env_t *env);
void be_load_needs_frame_entity(be_fec_env_t *env, ir_node *node,
const ir_type *type);
unsigned slot_size, unsigned slot_po2align);
typedef void (*set_frame_entity_func)(ir_node *node, ir_entity *entity,
const ir_type *final_type);
unsigned final_size,
unsigned final_po2align);
/**
* Assigned frame entities to all the nodes added by be_node_needs_frame_entity.
......
......@@ -124,7 +124,7 @@ static ir_node *ia32_get_admissible_noreg(ir_node *irn, int pos)
}
static void ia32_set_frame_entity(ir_node *node, ir_entity *entity,
const ir_type *type)
unsigned size, unsigned po2align)
{
ia32_attr_t *const attr = get_ia32_attr(node);
attr->addr.immediate = (x86_imm32_t) {
......@@ -137,14 +137,14 @@ static void ia32_set_frame_entity(ir_node *node, ir_entity *entity,
/* set ls_mode based on entity unless we explicitly requested
* a certain mode */
if (get_ia32_frame_use(node) != IA32_FRAME_USE_AUTO
|| is_ia32_Cmp(node) || is_ia32_Conv_I2I(node))
|| is_ia32_Cmp(node) || is_ia32_Conv_I2I(node))
return;
ir_mode *mode = get_type_mode(type);
(void)po2align;
attr->size = size == 12 ? X86_SIZE_80 : x86_size_from_bytes(size);
/** 8bit stores have a special register requirement, so we can't simply
* change size to 8bit here. The "hack" in ia32_collect_frame_entity_nodes()
* should take care that it never happens. */
assert(!is_ia32_Store(node) || get_mode_size_bits(mode) > 8);
attr->size = x86_size_from_mode(mode);
assert(!is_ia32_Store(node) || attr->size > X86_SIZE_8);
}
static bool node_has_sp_base(ir_node const *const node)
......@@ -912,40 +912,43 @@ static void ia32_collect_frame_entity_nodes(ir_node *node, void *data)
if (attr->addr.immediate.entity != NULL)
return;
ir_type const *type;
unsigned size;
unsigned po2align;
switch (get_ia32_frame_use(node)) {
case IA32_FRAME_USE_NONE:
panic("X86_IMM_FRAMEENT but IA32_FRAME_USE_NONE");
case IA32_FRAME_USE_32BIT:
type = get_type_for_mode(ia32_mode_gp);
size = 4;
po2align = 2;
goto request_entity;
case IA32_FRAME_USE_64BIT:
type = get_type_for_mode(mode_Ls);
size = 8;
po2align = 3;
goto request_entity;
case IA32_FRAME_USE_AUTO: {
switch (get_ia32_attr_const(node)->size) {
case X86_SIZE_8:
x86_insn_size_t const insn_size = get_ia32_attr_const(node)->size;
size = x86_bytes_from_size(insn_size);
if (size == 10) {
size = 12;
po2align = 2;
} else if (size == 1) {
/* stupid hack: in some situations (like reloads folded into ConvI2I
* with 8bit mode, an 8bit entity and reload+spill would suffice,
* but an 8bit store has special register requirements on ia32 which
* we may not be able to fulfill anymore at this point, so extend
* the spillslot size to 16bit :-( */
type = get_type_for_mode(mode_Hu);
goto request_entity;
case X86_SIZE_16: type = get_type_for_mode(mode_Hu); goto request_entity;
case X86_SIZE_32: type = get_type_for_mode(mode_Iu); goto request_entity;
case X86_SIZE_64: type = get_type_for_mode(mode_Lu); goto request_entity;
case X86_SIZE_80: type = x86_type_E; goto request_entity;
case X86_SIZE_128:
break;
size = 2;
po2align = 1;
} else {
po2align = log2_floor(size);
}
panic("invalid size");
goto request_entity;
}
}
panic("invalid frame use type");
request_entity:;
be_fec_env_t *env = (be_fec_env_t*)data;
be_load_needs_frame_entity(env, node, type);
be_load_needs_frame_entity(env, node, size, po2align);
}
static int determine_ebp_input(ir_node *ret)
......
......@@ -161,17 +161,22 @@ static inline bool x86_imm32_equal(x86_imm32_t const *const imm0,
&& imm0->kind == imm1->kind;
}
static inline x86_insn_size_t x86_size_from_mode(ir_mode *const mode)
static inline x86_insn_size_t x86_size_from_bytes(unsigned bytes)
{
switch (get_mode_size_bits(mode)) {
case 8: return X86_SIZE_8;
case 16: return X86_SIZE_16;
case 32: return X86_SIZE_32;
case 64: return X86_SIZE_64;
case 80: return X86_SIZE_80;
case 128: return X86_SIZE_128;
switch (bytes) {
case 1: return X86_SIZE_8;
case 2: return X86_SIZE_16;
case 4: return X86_SIZE_32;
case 8: return X86_SIZE_64;
case 10: return X86_SIZE_80;
case 16: return X86_SIZE_128;
}
panic("Unexpected mode");
panic("Unexpected size");
}
static inline x86_insn_size_t x86_size_from_mode(ir_mode *const mode)
{
return x86_size_from_bytes(get_mode_size_bytes(mode));
}
static inline unsigned x86_bytes_from_size(x86_insn_size_t const size)
......
......@@ -561,16 +561,20 @@ static void sparc_collect_frame_entity_nodes(ir_node *node, void *data)
return;
if (!attr->is_frame_entity)
return;
if (arch_get_irn_flags(node) & sparc_arch_irn_flag_needs_64bit_spillslot)
mode = mode_Lu;
const ir_type *type = get_type_for_mode(mode);
be_load_needs_frame_entity(env, node, type);
unsigned size = get_mode_size_bytes(mode);
unsigned po2align = log2_floor(size);
if (arch_get_irn_flags(node) & sparc_arch_irn_flag_needs_64bit_spillslot) {
size = 8;
po2align = 3;
}
be_load_needs_frame_entity(env, node, size, po2align);
}
static void sparc_set_frame_entity(ir_node *node, ir_entity *entity,
const ir_type *type)
unsigned size, unsigned po2align)
{
(void)type;
(void)size;
(void)po2align;
/* we only say be_node_needs_frame_entity on nodes with load_store
* attributes, so this should be fine */
sparc_load_store_attr_t *attr = get_sparc_load_store_attr(node);
......
......@@ -119,13 +119,13 @@ ir_entity *new_label_entity(ir_label_t label)
}
ir_entity *new_spillslot(ir_type *const frame, unsigned const size,
unsigned const alignment)
unsigned const po2align)
{
assert(is_frame_type(frame));
ir_type *const type = get_unknown_type();
ir_entity *const res = intern_new_entity(frame, IR_ENTITY_SPILLSLOT, NULL,
type, ir_visibility_private);
set_entity_alignment(res, alignment);
set_entity_alignment(res, 1u << po2align);
res->attr.spillslot.base.offset = INVALID_OFFSET;
res->attr.spillslot.size = size;
return res;
......
......@@ -228,7 +228,7 @@ void ir_init_entity(ir_prog *irp);
*/
ir_entity *new_label_entity(ir_label_t label);
ir_entity *new_spillslot(ir_type *frame, unsigned size, unsigned alignment);
ir_entity *new_spillslot(ir_type *frame, unsigned size, unsigned po2align);
void set_entity_irg(ir_entity *ent, ir_graph *irg);
......
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