/*
- * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
+ * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* Implements "Strenght Reduction of Multiplications by Integer Constants" by Youfeng Wu.
* Implements Division and Modulo by Consts from "Hackers Delight",
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#include "ircons.h"
#include "irarch.h"
#include "irflag.h"
+#include "error.h"
#undef DEB
* Calculate the gain when using the generalized complementary technique
*/
static int calculate_gain(unsigned char *R, int r) {
- int max_gain = -1;
- int idx, i;
+ int max_gain = 0;
+ int idx = -1, i;
int gain;
/* the gain for r == 1 */
idx = i;
}
}
- if (max_gain > 0)
- return idx;
- return -1;
+ return idx;
}
/**
assert(r == 2);
ins = env->root;
+ if (R[1] <= env->max_S) {
+ ins = emit_LEA(env, ins, ins, R[1]);
+ if (R[0] != 0) {
+ ins = emit_SHIFT(env, ins, R[0]);
+ }
+ return ins;
+ }
if (R[0] != 0) {
ins = emit_SHIFT(env, ins, R[0]);
}
- if (R[1] <= env->max_S)
- return emit_LEA(env, ins, ins, R[1]);
ins2 = emit_SHIFT(env, env->root, R[0] + R[1]);
return emit_LEA(env, ins, ins2, 0);
case ZERO:
return inst->irn = new_r_Const(current_ir_graph, env->blk, env->mode, get_mode_null(env->mode));
default:
- assert(0);
+ panic("Unsupported instruction kind");
return NULL;
}
}
case ZERO:
inst->costs = costs = env->evaluate(inst->kind, NULL);
return costs;
- default:
- assert(0);
- return 0;
}
+ panic("Unsupported instruction kind");
}
/**
* Evaluate the replacement instructions and build a new graph
* if faster than the Mul.
- * returns the root of the new graph then or irn otherwise.
+ * Returns the root of the new graph then or irn otherwise.
*
* @param irn the Mul operation
* @param operand the multiplication operand
inst = decompose_mul(&env, R, r, tv);
/* the paper suggests 70% here */
- mul_costs = (env.evaluate(MUL, tv) * 7) / 10;
+ mul_costs = (env.evaluate(MUL, tv) * 7 + 5) / 10;
if (evaluate_insn(&env, inst) <= mul_costs && !env.fail) {
env.op = operand;
env.blk = get_nodes_block(irn);
}
}
}
- set_arch_dep_running(0);
+ //set_arch_dep_running(0);
return res;
}
#define SHL(a, b) tarval_shl(a, b)
#define SHR(a, b) tarval_shr(a, b)
#define ADD(a, b) tarval_add(a, b)
-#define SUB(a, b) tarval_sub(a, b)
+#define SUB(a, b) tarval_sub(a, b, NULL)
#define MUL(a, b) tarval_mul(a, b)
#define DIV(a, b) tarval_div(a, b)
#define MOD(a, b) tarval_mod(a, b)
/* generate the Mulh instruction */
c = new_r_Const(current_ir_graph, block, mode, mag.M);
- q = new_rd_Mulh(dbg, current_ir_graph, block, n, c, mode);
+ q = new_rd_Mulh(dbg, current_ir_graph, block, n, c, mode);
if (mag.need_add) {
if (mag.s > 0) {
if (params == NULL || (opts & arch_dep_div_by_const) == 0)
return irn;
- if (get_irn_opcode(irn) == iro_Div) {
+ if (is_Div(irn)) {
ir_node *c = get_Div_right(irn);
ir_node *block, *left;
ir_mode *mode;
int n, bits;
int k, n_flag;
- if (get_irn_op(c) != op_Const)
+ if (! is_Const(c))
return irn;
tv = get_Const_tarval(c);
ir_node *k_node;
ir_node *curr = left;
- if (k != 1) {
- k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k - 1);
- curr = new_rd_Shrs(dbg, current_ir_graph, block, left, k_node, mode);
- }
+ /* create the correction code for signed values only if there might be a remainder */
+ if (! is_Div_remainderless(irn)) {
+ if (k != 1) {
+ k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k - 1);
+ curr = new_rd_Shrs(dbg, current_ir_graph, block, left, k_node, mode);
+ }
- k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, bits - k);
- curr = new_rd_Shr(dbg, current_ir_graph, block, curr, k_node, mode);
+ k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, bits - k);
+ curr = new_rd_Shr(dbg, current_ir_graph, block, curr, k_node, mode);
- curr = new_rd_Add(dbg, current_ir_graph, block, left, curr, mode);
+ curr = new_rd_Add(dbg, current_ir_graph, block, left, curr, mode);
+ } else {
+ k_node = left;
+ }
k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k);
res = new_rd_Shrs(dbg, current_ir_graph, block, curr, k_node, mode);
if (params == NULL || (opts & arch_dep_mod_by_const) == 0)
return irn;
- if (get_irn_opcode(irn) == iro_Mod) {
+ if (is_Mod(irn)) {
ir_node *c = get_Mod_right(irn);
ir_node *block, *left;
ir_mode *mode;
int n, bits;
int k;
- if (get_irn_op(c) != op_Const)
+ if (! is_Const(c))
return irn;
tv = get_Const_tarval(c);
((opts & (arch_dep_div_by_const|arch_dep_mod_by_const)) != (arch_dep_div_by_const|arch_dep_mod_by_const)))
return;
- if (get_irn_opcode(irn) == iro_DivMod) {
+ if (is_DivMod(irn)) {
ir_node *c = get_DivMod_right(irn);
ir_node *block, *left;
ir_mode *mode;
int n, bits;
int k, n_flag;
- if (get_irn_op(c) != op_Const)
+ if (! is_Const(c))
return;
tv = get_Const_tarval(c);