Commit 81a5566a authored by Matthias Braun's avatar Matthias Braun
Browse files

lower_alloc: simplify code+interface, fix ia32 lower_alloc invocation

parent 04ead3ea
...@@ -1680,7 +1680,7 @@ static void ia32_lower_for_target(void) ...@@ -1680,7 +1680,7 @@ static void ia32_lower_for_target(void)
/* lower for mode_b stuff */ /* lower for mode_b stuff */
ir_lower_mode_b(irg, ia32_mode_gp); ir_lower_mode_b(irg, ia32_mode_gp);
be_after_transform(irg, "lower-modeb"); be_after_transform(irg, "lower-modeb");
lower_alloc(irg, IA32_REGISTER_SIZE, true, 0); lower_alloc(irg, ia32_cg_config.stack_alignment);
be_after_transform(irg, "lower-alloc"); be_after_transform(irg, "lower-alloc");
} }
......
...@@ -528,9 +528,7 @@ static void sparc_lower_for_target(void) ...@@ -528,9 +528,7 @@ static void sparc_lower_for_target(void)
foreach_irp_irg(i, irg) { foreach_irp_irg(i, irg) {
ir_lower_mode_b(irg, mode_Iu); ir_lower_mode_b(irg, mode_Iu);
be_after_transform(irg, "lower-modeb"); be_after_transform(irg, "lower-modeb");
/* TODO: Pass SPARC_MIN_STACKSIZE as addr_delta as soon as lower_alloc(irg, SPARC_PO2_STACK_ALIGNMENT);
* Alloc nodes are implemented more efficiently. */
lower_alloc(irg, SPARC_STACK_ALIGNMENT, true, 0);
be_after_transform(irg, "lower-alloc"); be_after_transform(irg, "lower-alloc");
} }
} }
......
...@@ -16,10 +16,7 @@ ...@@ -16,10 +16,7 @@
#include "irgmod.h" #include "irgmod.h"
#include "irnodeset.h" #include "irnodeset.h"
static bool lower_constant_sizes; static unsigned po2_stack_alignment;
static unsigned stack_alignment;
static long addr_delta;
static ir_nodeset_t transformed;
/** /**
* Adjust the size of a node representing a stack alloc to a certain * Adjust the size of a node representing a stack alloc to a certain
...@@ -31,66 +28,28 @@ static ir_nodeset_t transformed; ...@@ -31,66 +28,28 @@ static ir_nodeset_t transformed;
*/ */
static ir_node *adjust_alloc_size(dbg_info *dbgi, ir_node *size, ir_node *block) static ir_node *adjust_alloc_size(dbg_info *dbgi, ir_node *size, ir_node *block)
{ {
if (stack_alignment <= 1) /* Example: po2_alignment 4 (align to 16 bytes):
return size; * size = (size+15) & 0xfff...f8 */
if (is_Const(size) && !lower_constant_sizes) ir_mode *mode = get_irn_mode(size);
return size; ir_graph *irg = get_irn_irg(block);
ir_tarval *allone = get_mode_all_one(mode);
ir_mode *mode = get_irn_mode(size); ir_tarval *shr = tarval_shr_unsigned(allone, po2_stack_alignment);
ir_graph *irg = get_irn_irg(block); ir_tarval *mask = tarval_shl_unsigned(shr, po2_stack_alignment);
ir_node *mask = new_r_Const_long(irg, mode, stack_alignment - 1); ir_tarval *invmask = tarval_not(mask);
size = new_rd_Add(dbgi, block, size, mask, mode); ir_node *addv = new_r_Const(irg, invmask);
mask = new_r_Const_long(irg, mode, -(long)stack_alignment); ir_node *add = new_rd_Add(dbgi, block, size, addv, mode);
size = new_rd_And(dbgi, block, size, mask, mode); ir_node *maskc = new_r_Const(irg, mask);
return size; ir_node *and = new_rd_And(dbgi, block, add, maskc, mode);
} return and;
static bool transform_Proj_Alloc(ir_node *node)
{
/* we might need a result adjustment */
if (addr_delta == 0)
return false;
if (get_Proj_num(node) != pn_Alloc_res)
return false;
if (ir_nodeset_contains(&transformed, node))
return false;
ir_node *const alloc = get_Proj_pred(node);
dbg_info *const dbgi = get_irn_dbg_info(alloc);
ir_graph *const irg = get_irn_irg(node);
ir_node *const block = get_nodes_block(node);
ir_node *const delta = new_r_Const_long(irg, mode_P, addr_delta);
ir_node *const dummy = new_r_Dummy(irg, mode_P);
ir_node *const add = new_rd_Add(dbgi, block, dummy, delta, mode_P);
exchange(node, add);
ir_node *const new_proj = new_r_Proj(alloc, mode_P, pn_Alloc_res);
set_Add_left(add, new_proj);
ir_nodeset_insert(&transformed, new_proj);
return true;
} }
/** /**
* lower Alloca nodes to allocate "bytes" instead of a certain type * lower Alloca nodes to allocate "bytes" instead of a certain type
*/ */
static void lower_alloca_free(ir_node *node, void *data) static void lower_node(ir_node *node, void *data)
{ {
bool *changed = (bool*)data; bool *changed = (bool*)data;
(void) data; if (!is_Alloc(node))
if (is_Alloc(node)) {
} else if (is_Proj(node)) {
ir_node *proj_pred = get_Proj_pred(node);
if (is_Alloc(proj_pred)) {
*changed |= transform_Proj_Alloc(node);
}
return;
} else {
return;
}
if (!ir_nodeset_insert(&transformed, node))
return;
if (stack_alignment <= 1)
return; return;
ir_node *const size = get_Alloc_size(node); ir_node *const size = get_Alloc_size(node);
...@@ -100,25 +59,20 @@ static void lower_alloca_free(ir_node *node, void *data) ...@@ -100,25 +59,20 @@ static void lower_alloca_free(ir_node *node, void *data)
ir_node *const new_size = adjust_alloc_size(dbgi, size, block); ir_node *const new_size = adjust_alloc_size(dbgi, size, block);
ir_node *const new_node ir_node *const new_node
= new_rd_Alloc(dbgi, block, mem, new_size, 1); = new_rd_Alloc(dbgi, block, mem, new_size, 1);
ir_nodeset_insert(&transformed, new_node);
if (new_node != node) if (new_node != node)
exchange(node, new_node); exchange(node, new_node);
*changed = true; *changed = true;
} }
void lower_alloc(ir_graph *irg, unsigned new_stack_alignment, bool lower_consts, void lower_alloc(ir_graph *irg, unsigned new_po2_stack_alignment)
long new_addr_delta)
{ {
if (!is_po2(stack_alignment)) if (new_po2_stack_alignment == 0)
panic("stack alignment not a power of 2"); return;
addr_delta = new_addr_delta;
stack_alignment = new_stack_alignment; po2_stack_alignment = new_po2_stack_alignment;
lower_constant_sizes = lower_consts;
bool changed = false; bool changed = false;
ir_nodeset_init(&transformed); irg_walk_graph(irg, lower_node, NULL, &changed);
irg_walk_graph(irg, lower_alloca_free, NULL, &changed);
ir_nodeset_destroy(&transformed);
confirm_irg_properties(irg, changed ? IR_GRAPH_PROPERTIES_CONTROL_FLOW confirm_irg_properties(irg, changed ? IR_GRAPH_PROPERTIES_CONTROL_FLOW
: IR_GRAPH_PROPERTIES_ALL); : IR_GRAPH_PROPERTIES_ALL);
......
...@@ -15,12 +15,11 @@ ...@@ -15,12 +15,11 @@
#include "firm_types.h" #include "firm_types.h"
/** /**
* Lower Alloc/Free nodes: This changes them to allocate bytes instead of * Lower Alloc nodes: Ensure that alloc sizes are a multiple of a specified
* objects of a certain type. It can also make sure that the resulting * alignment.
* size is aligned. * @param irg graph to process
* @param po2_stack_alignment stack should be aligned to 2**po2_stack_alignment
*/ */
void lower_alloc(ir_graph *irg, unsigned stack_alignment, void lower_alloc(ir_graph *irg, unsigned po2_stack_alignment);
bool align_constant_sizes,
long addr_delta);
#endif #endif
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