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