Commit 83811ec1 authored by Matthias Braun's avatar Matthias Braun
Browse files

a better version of a copyb lowerer

[r18000]
parent a786fc1b
......@@ -144,6 +144,12 @@ typedef struct {
*/
void lower_calls_with_compounds(const lower_params_t *params);
/**
* * Lower CopyB nodes of size smaller that max_size into Loads/Stores
*/
void lower_CopyB(ir_graph *irg, unsigned max_size, unsigned native_mode_bytes);
/**
* A callback type for creating an intrinsic entity for a given opcode.
*
......
......@@ -20,7 +20,7 @@
/**
* @file
* @brief Lower small CopyB nodes into a series of Load/store
* @author Michael Beck
* @author Matthias Braun, Michael Beck
* @version $Id$
*/
#ifdef HAVE_CONFIG_H
......@@ -30,59 +30,48 @@
#include "ircons.h"
#include "lowering.h"
#include "irprog_t.h"
#include "irgwalk.h"
#include "irnode_t.h"
#include "type_t.h"
#include "irtools.h"
typedef struct copyb_env {
ir_node *next; /**< link to the next one */
} copyb_env;
typedef struct walker_env {
struct obstack obst; /**< temporary space */
int max_size;
ir_node *list; /**< list of CopyB nodes. */
} walker_env;
/**
* Build a graph that copies an entity of type tp from src to tgt
*/
static ir_node *build_copy_graph(dbg_info *dbg, ir_node *blk, ir_node *mem, ir_node *src, ir_node *tgt, ir_type *tp) {
int i, n;
if (is_Array_type(tp)) {
assert(0);
} else {
for (i = 0, n = get_compound_n_members(tp); i < n; ++i) {
ir_entity *ent = get_compound_member(tp, i);
ir_node *s = new_d_simpleSel(dbg, mem, src, ent);
ir_node *d = new_d_simpleSel(dbg, mem, tgt, ent);
ir_type *ent_tp = get_entity_type(ent);
if (is_atomic_type(ent_tp)) {
ir_mode *mode = get_type_mode(ent_tp);
ir_node *irn = new_rd_Load(dbg, current_ir_graph, blk, mem, s, mode);
ir_node *res = new_r_Proj(current_ir_graph, blk, irn, mode, pn_Load_res);
mem = new_r_Proj(current_ir_graph, blk, irn, mode_M, pn_Load_M);
irn = new_rd_Store(dbg, current_ir_graph, blk, mem, d, res);
mem = new_r_Proj(current_ir_graph, blk, irn, mode_M, pn_Store_M);
} else {
mem = build_copy_graph(dbg, blk, mem, s, d, ent_tp);
}
}
#include "iredges_t.h"
#include "irgmod.h"
#include "error.h"
static unsigned max_size;
static unsigned native_mode_bytes;
static ir_mode *get_ir_mode(unsigned bytes)
{
switch(bytes) {
case 1: return mode_Bu;
case 2: return mode_Hu;
case 4: return mode_Iu;
case 8: return mode_Lu;
case 16: return mode_LLu;
default:
panic("unexpected mode size requested in copyb lowering");
}
return mem;
}
/**
* Walker: lower small CopyB nodes.
*/
static void lower_copyb_nodes(ir_node *irn, void *ctx) {
ir_type *tp;
int size;
walker_env *env = ctx;
ir_graph *irg = current_ir_graph;
ir_type *tp;
unsigned size;
unsigned mode_bytes;
unsigned offset;
ir_mode *mode;
ir_mode *addr_mode;
ir_node *mem;
ir_node *addr_src;
ir_node *addr_dst;
ir_node *block;
ir_node *proj_M = NULL;
const ir_edge_t *edge;
(void) ctx;
if (! is_CopyB(irn))
return;
......@@ -92,26 +81,74 @@ static void lower_copyb_nodes(ir_node *irn, void *ctx) {
return;
size = get_type_size_bytes(tp);
if (size > env->max_size)
if (size > max_size)
return;
/* for now, we can only handle Struct's */
if (is_Struct_type(tp)) {
irn = build_copy_graph(get_irn_dbg_info(irn), get_nodes_block(irn), get_CopyB_mem(irn), get_CopyB_src(irn), get_CopyB_dst(irn), tp);
foreach_out_edge(irn, edge) {
ir_node *node = get_edge_src_irn(edge);
long pn = get_Proj_proj(node);
/* we don't lower copybs with exception edges (yet) */
if(pn == pn_CopyB_X_except)
return;
if(pn == pn_CopyB_M_regular) {
assert(proj_M == NULL);
proj_M = node;
}
}
if(proj_M == NULL) {
panic("no projM on copyb");
}
}
/**
* Lower CopyB nodes of size smaller that max_size into Loads/Stores
*/
void lower_CopyB(int max_size) {
walker_env env;
int i;
obstack_init(&env.obst);
env.max_size = max_size;
env.list = NULL;
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
irg_walk_graph(get_irp_irg(i), firm_clear_link, lower_copyb_nodes, NULL);
addr_src = get_CopyB_src(irn);
addr_dst = get_CopyB_dst(irn);
mem = get_CopyB_mem(irn);
addr_mode = get_irn_mode(addr_src);
block = get_nodes_block(irn);
offset = 0;
mode_bytes = native_mode_bytes;
while(offset < size) {
mode = get_ir_mode(mode_bytes);
for( ; offset + mode_bytes <= size; offset += mode_bytes) {
/* construct offset */
ir_node *addr_const;
ir_node *add;
ir_node *load;
ir_node *load_res;
ir_node *load_mem;
ir_node *store;
ir_node *store_mem;
addr_const = new_r_Const_long(irg, block, mode_Iu, offset);
add = new_r_Add(irg, block, addr_src, addr_const, addr_mode);
load = new_r_Load(irg, block, mem, add, mode);
load_res = new_r_Proj(irg, block, load, mode, pn_Load_res);
load_mem = new_r_Proj(irg, block, load, mode_M, pn_Load_M);
addr_const = new_r_Const_long(irg, block, mode_Iu, offset);
add = new_r_Add(irg, block, addr_dst, addr_const, addr_mode);
store = new_r_Store(irg, block, mem, add, load_res);
store_mem = new_r_Proj(irg, block, store, mode_M, pn_Store_M);
mem = store_mem;
}
mode_bytes /= 2;
}
exchange(proj_M, mem);
}
void lower_CopyB(ir_graph *irg, unsigned new_max_size,
unsigned new_native_mode_bytes)
{
max_size = new_max_size;
native_mode_bytes = new_native_mode_bytes;
edges_assure(irg);
irg_walk_graph(irg, NULL, lower_copyb_nodes, NULL);
}
......@@ -223,8 +223,10 @@ static void lower_sel(ir_node *sel) {
newn = get_Sel_ptr(sel);
offset = get_entity_offset(ent);
if (offset != 0) {
tv = new_tarval_from_long(offset, mode_Int);
cnst = new_r_Const(irg, get_irg_start_block(irg), mode_Int, tv);
ir_mode *mode_UInt = get_reference_mode_unsigned_eq(mode);
tv = new_tarval_from_long(offset, mode_UInt);
cnst = new_r_Const(irg, get_irg_start_block(irg), mode_UInt, tv);
newn = new_rd_Add(dbg, irg, bl, newn, cnst, mode);
}
} else {
......
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