From 29bf0481bdc0c1c5ec252a7323e1c029f873aa1a Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Wed, 26 Oct 2005 13:05:11 +0000 Subject: [PATCH] a general mechanism to lower calls to intrinsic functions [r6811] --- ir/lower/lower_intrinsics.c | 143 ++++++++++++++++++++++++++++++++++++ ir/lower/lower_intrinsics.h | 72 ++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 ir/lower/lower_intrinsics.c create mode 100644 ir/lower/lower_intrinsics.h diff --git a/ir/lower/lower_intrinsics.c b/ir/lower/lower_intrinsics.c new file mode 100644 index 000000000..fead00296 --- /dev/null +++ b/ir/lower/lower_intrinsics.c @@ -0,0 +1,143 @@ +/* + * Project: libFIRM + * File name: ir/lower/lower_intrinsics.c + * Purpose: lowering of Calls of intrinsic functions + * Author: Michael Beck + * Created: + * CVS-ID: $Id$ + * Copyright: (c) 1998-2005 Universität Karlsruhe + * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ALLOCA_H +#include +#endif +#ifdef HAVE_MALLOC_H +#include +#endif + +#include "irprog_t.h" +#include "irnode_t.h" +#include "irgwalk.h" +#include "ircons.h" +#include "irgmod.h" +#include "lower_intrinsics.h" +#include "pmap.h" + +typedef struct _walker_env { + pmap *map; /**< the intrinsic map. */ + unsigned nr_of_intrinsics; /**< statistics */ +} walker_env_t; + +/** + * walker: do the call mapping + */ +static void call_mapper(ir_node *call, void *env) { + walker_env_t *wenv = env; + ir_node *symconst; + pmap_entry *p; + const i_record *r; + entity *ent; + + if (get_irn_op(call) != op_Call) + return; + + symconst = get_Call_ptr(call); + if (get_irn_op(symconst) != op_SymConst || + get_SymConst_kind(symconst) != symconst_addr_ent) + return; + + ent = get_SymConst_entity(symconst); + p = pmap_find(wenv->map, ent); + + if (p) { + r = p->value; + wenv->nr_of_intrinsics += r->i_mapper(call, r->ctx) ? 1 : 0; + } +} + +/* Go through all graphs and map calls to intrinsic functions. */ +unsigned lower_intrinsic_calls(const i_record *list, int length) { + int i; + ir_graph *irg; + pmap *map = pmap_create_ex(length); + walker_env_t wenv; + unsigned nr_of_intrinsics = 0; + + /* fill a map for faster search */ + for (i = length - 1; i >= 0; --i) + pmap_insert(map, list[i].i_ent, (void *)&list[i]); + + wenv.map = map; + + for (i = get_irp_n_irgs() - 1; i >= 0; --i) { + irg = get_irp_irg(i); + + wenv.nr_of_intrinsics = 0; + irg_walk_graph(irg, NULL, call_mapper, map); + + if (wenv.nr_of_intrinsics) { + /* changes detected */ + set_irg_outs_inconsistent(irg); + set_irg_callee_info_state(irg, irg_callee_info_inconsistent); + + /* exception control flow might have changed */ + set_irg_dom_inconsistent(irg); + set_irg_loopinfo_inconsistent(irg); + + nr_of_intrinsics += wenv.nr_of_intrinsics; + } + } + pmap_destroy(map); + + return nr_of_intrinsics; +} + +/* A mapper for the integer abs. */ +int i_mapper_Abs(ir_node *call, void *ctx) { + ir_node *mem = get_Call_mem(call); + ir_node *block = get_nodes_block(call); + ir_node *op = get_Call_param(call, 0); + ir_node *irn; + dbg_info *dbg = get_irn_dbg_info(call); + + irn = new_rd_Abs(dbg, current_ir_graph, block, op, get_irn_mode(op)); + irn = new_Tuple(1, &irn); + + turn_into_tuple(call, pn_Call_max); + set_Tuple_pred(call, pn_Call_M_regular, mem); + set_Tuple_pred(call, pn_Call_X_except, new_Bad()); + set_Tuple_pred(call, pn_Call_T_result, irn); + set_Tuple_pred(call, pn_Call_M_except, mem); + set_Tuple_pred(call, pn_Call_P_value_res_base, new_Bad()); + + return 1; +} + +/* A mapper for the alloca() function. */ +int i_mapper_Alloca(ir_node *call, void *ctx) { + ir_node *mem = get_Call_mem(call); + ir_node *block = get_nodes_block(call); + ir_node *op = get_Call_param(call, 0); + ir_node *irn, *exc; + dbg_info *dbg = get_irn_dbg_info(call); + + irn = new_rd_Alloc(dbg, current_ir_graph, block, mem, op, firm_unknown_type, stack_alloc); + mem = new_Proj(irn, mode_M, pn_Alloc_M); + exc = new_Proj(irn, mode_X, pn_Alloc_X_except); + irn = new_Proj(irn, get_modeP_data(), pn_Alloc_res); + irn = new_Tuple(1, &irn); + + turn_into_tuple(call, pn_Call_max); + set_Tuple_pred(call, pn_Call_M_regular, mem); + set_Tuple_pred(call, pn_Call_X_except, exc); + set_Tuple_pred(call, pn_Call_T_result, irn); + set_Tuple_pred(call, pn_Call_M_except, mem); + set_Tuple_pred(call, pn_Call_P_value_res_base, new_Bad()); + + return 1; +} diff --git a/ir/lower/lower_intrinsics.h b/ir/lower/lower_intrinsics.h new file mode 100644 index 000000000..41f3247f6 --- /dev/null +++ b/ir/lower/lower_intrinsics.h @@ -0,0 +1,72 @@ +/* + * Project: libFIRM + * File name: ir/lower/lower_intrinsics.h + * Purpose: lowering of Calls of intrinsic functions + * Author: Michael Beck + * Created: + * CVS-ID: $Id$ + * Copyright: (c) 1998-2005 Universität Karlsruhe + * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. + */ + +/** + * @file lower_intrinsics.h + * + * Lowering of Calls of intrinsic functions. + * + * @author Michael Beck + */ +#ifndef _LOWER_INTRINSICS_H_ +#define _LOWER_INTRINSICS_H_ + +#include "firm_types.h" + +/** + * An intrinsic mapper function. + * + * @param call the Call node + * @param ctx a context + * + * @return non-zero if the call was mapped + */ +typedef int (*i_mapper_func)(ir_node *call, void *ctx); + +/** + * An intrinsic record. + */ +typedef struct _i_record { + entity *i_ent; /**< the entity representing an intrinsic */ + i_mapper_func i_mapper; /**< the mapper function to call */ + void *ctx; /**< mapper context */ +} i_record; + +/** + * Go through all graphs and map calls to intrinsic functions. + * + * Every call is reported to its mapper function, which is responsible for + * rebuilding the graph. + * + * current_ir_graph is always set. + * + * @param list an array of intrinsic map records + * @param length the length of the array + * + * @return number of found intrinsic calls + */ +unsigned lower_intrinsic_calls(const i_record *list, int length); + +/** + * A mapper for the integer absolute value: inttype abs(inttype v) + * + * @return always 1 + */ +int i_mapper_Abs(ir_node *call, void *ctx); + +/** + * A mapper for the alloca() function: pointer alloca(inttype size) + * + * @return always 1 + */ +int i_mapper_Alloca(ir_node *call, void *ctx); + +#endif /* _LOWER_INTRINSICS_H_ */ -- 2.20.1