From 1fe88d089f25a5b40b25c65730fa3506f90d6359 Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Wed, 31 Oct 2007 17:48:56 +0000 Subject: [PATCH] add i_mapper_Sqrt() and i_mapper_Pow() for some constants [r16400] --- include/libfirm/lowering.h | 14 ++++++ ir/lower/lower_intrinsics.c | 97 +++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/include/libfirm/lowering.h b/include/libfirm/lowering.h index 32c161c08..32100c840 100644 --- a/include/libfirm/lowering.h +++ b/include/libfirm/lowering.h @@ -285,6 +285,20 @@ unsigned lower_intrinsics(i_record *list, int length, int part_block_used); */ int i_mapper_Abs(ir_node *call, void *ctx); +/** + * A mapper for the floating point sqrt(v): floattype sqrt(floattype v); + * + * @return 0 if the sqrt call was removed, 0 else. + */ +int i_mapper_Sqrt(ir_node *call, void *ctx); + +/** + * A mapper for the floating point pow(a, b): floattype pow(floattype a, floattype b); + * + * @return 0 if the pow call was removed, 0 else. + */ +int i_mapper_Pow(ir_node *call, void *ctx); + /** * A mapper for the alloca() function: pointer alloca(inttype size) * Replaces the call by a Alloca(stack_alloc) node. diff --git a/ir/lower/lower_intrinsics.c b/ir/lower/lower_intrinsics.c index 466950bfb..8f985e761 100644 --- a/ir/lower/lower_intrinsics.c +++ b/ir/lower/lower_intrinsics.c @@ -200,6 +200,103 @@ int i_mapper_Alloca(ir_node *call, void *ctx) { return 1; } +/* A mapper for the floating point sqrt. */ +int i_mapper_Sqrt(ir_node *call, void *ctx) { + dbg_info *dbg; + ir_node *irn, *mem, *block; + tarval *tv; + ir_node *op = get_Call_param(call, 0); + (void) ctx; + + if (!is_Const(op)) + return 0; + + tv = get_Const_tarval(op); + if (! tarval_is_null(tv) && !tarval_is_one(tv)) + return 0; + + mem = get_Call_mem(call); + block = get_nodes_block(call); + dbg = get_irn_dbg_info(call); + + /* sqrt(0) = 0, sqrt(1) = 1 */ + irn = 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_regular, new_r_Jmp(current_ir_graph, block)); + 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 floating point pow. */ +int i_mapper_Pow(ir_node *call, void *ctx) { + dbg_info *dbg; + ir_node *mem; + ir_node *left = get_Call_param(call, 0); + ir_node *right = get_Call_param(call, 1); + ir_node *block = get_nodes_block(call); + ir_node *irn, *reg_jmp, *exc_jmp; + (void) ctx; + + if (is_Const(left) && is_Const_one(left)) { + /* pow (1.0, x) = 1.0 */ + irn = left; + } else if (is_Const(right)) { + tarval *tv = get_Const_tarval(right); + if (tarval_is_null(tv)) { + /* pow(x, 0.0) = 1.0 */ + ir_mode *mode = get_tarval_mode(tv); + irn = new_r_Const(current_ir_graph, block, mode, get_mode_one(mode)); + } else if (tarval_is_one(tv)) { + /* pow(x, 1.0) = x */ + irn = left; + } else if (tarval_is_minus_one(tv)) { + /* pow(x, -1.0) = 1/x */ + irn = NULL; + } else + return 0; + } + + mem = get_Call_mem(call); + dbg = get_irn_dbg_info(call); + + if (irn == NULL) { + ir_mode *mode = get_irn_mode(left); + ir_node *quot; + + irn = new_r_Const(current_ir_graph, block, mode, get_mode_one(mode)); + quot = new_rd_Quot(dbg, current_ir_graph, block, mem, irn, left, mode, op_pin_state_pinned); + mem = new_r_Proj(current_ir_graph, block, quot, mode_M, pn_Quot_M); + irn = new_r_Proj(current_ir_graph, block, quot, mode, pn_Quot_res); + reg_jmp = new_r_Proj(current_ir_graph, block, quot, mode_X, pn_Quot_X_regular); + exc_jmp = new_r_Proj(current_ir_graph, block, quot, mode_X, pn_Quot_X_except); + } else { + /* Beware: do we need here a protection against CSE? Better we do it. */ + int old_cse = get_opt_cse(); + set_opt_cse(0); + reg_jmp = new_r_Jmp(current_ir_graph, block); + set_opt_cse(old_cse); + exc_jmp = new_Bad(); + } + 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_regular, reg_jmp); + set_Tuple_pred(call, pn_Call_X_except, exc_jmp); + 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; +} + /** * Returns the result mode of a node. */ -- 2.20.1