/*
- * 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
-
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
+#include "config.h"
+#include <stdlib.h>
#include <assert.h>
#include "irnode_t.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 = 0, 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;
}
/**
case LEA:
l = build_graph(env, inst->in[0]);
r = build_graph(env, inst->in[1]);
- c = new_r_Const(current_ir_graph, env->blk, env->shf_mode, new_tarval_from_long(inst->shift_count, env->shf_mode));
+ c = new_Const_long(env->shf_mode, inst->shift_count);
r = new_rd_Shl(env->dbg, current_ir_graph, env->blk, r, c, env->mode);
return inst->irn = new_rd_Add(env->dbg, current_ir_graph, env->blk, l, r, env->mode);
case SHIFT:
l = build_graph(env, inst->in[0]);
- c = new_r_Const(current_ir_graph, env->blk, env->shf_mode, new_tarval_from_long(inst->shift_count, env->shf_mode));
+ c = new_Const_long(env->shf_mode, inst->shift_count);
return inst->irn = new_rd_Shl(env->dbg, current_ir_graph, env->blk, l, c, env->mode);
case SUB:
l = build_graph(env, inst->in[0]);
r = build_graph(env, inst->in[1]);
return inst->irn = new_rd_Add(env->dbg, current_ir_graph, env->blk, l, r, env->mode);
case ZERO:
- return inst->irn = new_r_Const(current_ir_graph, env->blk, env->mode, get_mode_null(env->mode));
+ return inst->irn = new_Const(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;
+ case MUL:
+ case ROOT:
+ break;
}
+ 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);
#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)
struct ms mag = magic(tv);
/* generate the Mulh instruction */
- c = new_r_Const(current_ir_graph, block, mode, mag.M);
+ c = new_Const(mag.M);
q = new_rd_Mulh(dbg, current_ir_graph, block, n, c, mode);
/* do we need an Add or Sub */
/* Do we need the shift */
if (mag.s > 0) {
- c = new_r_Const_long(current_ir_graph, block, mode_Iu, mag.s);
- q = new_rd_Shrs(dbg, current_ir_graph, block, q, c, mode);
+ c = new_Const_long(mode_Iu, mag.s);
+ q = new_rd_Shrs(dbg, current_ir_graph, block, q, c, mode);
}
/* final */
- c = new_r_Const_long(current_ir_graph, block, mode_Iu, bits-1);
+ c = new_Const_long(mode_Iu, bits - 1);
t = new_rd_Shr(dbg, current_ir_graph, block, q, c, mode);
q = new_rd_Add(dbg, current_ir_graph, block, q, t, mode);
ir_node *c;
/* 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);
+ c = new_Const(mag.M);
+ q = new_rd_Mulh(dbg, current_ir_graph, block, n, c, mode);
if (mag.need_add) {
if (mag.s > 0) {
/* use the GM scheme */
t = new_rd_Sub(dbg, current_ir_graph, block, n, q, mode);
- c = new_r_Const(current_ir_graph, block, mode_Iu, get_mode_one(mode_Iu));
+ c = new_Const(get_mode_one(mode_Iu));
t = new_rd_Shr(dbg, current_ir_graph, block, t, c, mode);
t = new_rd_Add(dbg, current_ir_graph, block, t, q, mode);
- c = new_r_Const_long(current_ir_graph, block, mode_Iu, mag.s-1);
+ c = new_Const_long(mode_Iu, mag.s - 1);
q = new_rd_Shr(dbg, current_ir_graph, block, t, c, mode);
} else {
/* use the default scheme */
q = new_rd_Add(dbg, current_ir_graph, block, q, n, mode);
}
} else if (mag.s > 0) { /* default scheme, shift needed */
- c = new_r_Const_long(current_ir_graph, block, mode_Iu, mag.s);
+ c = new_Const_long(mode_Iu, mag.s);
q = new_rd_Shr(dbg, current_ir_graph, block, q, c, mode);
}
}
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_Const_long(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_Const_long(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);
+ k_node = new_Const_long(mode_Iu, k);
res = new_rd_Shrs(dbg, current_ir_graph, block, curr, k_node, mode);
if (n_flag) { /* negate the result */
ir_node *k_node;
- k_node = new_r_Const(current_ir_graph, block, mode, get_mode_null(mode));
+ k_node = new_Const(get_mode_null(mode));
res = new_rd_Sub(dbg, current_ir_graph, block, k_node, res, mode);
}
} else { /* unsigned case */
ir_node *k_node;
- k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k);
+ k_node = new_Const_long(mode_Iu, k);
res = new_rd_Shr(dbg, current_ir_graph, block, left, k_node, mode);
}
} else {
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);
ir_node *curr = left;
if (k != 1) {
- k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k - 1);
+ k_node = new_Const_long(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);
+ k_node = new_Const_long(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);
- k_node = new_r_Const_long(current_ir_graph, block, mode, (-1) << k);
+ k_node = new_Const_long(mode, (-1) << k);
curr = new_rd_And(dbg, current_ir_graph, block, curr, k_node, mode);
res = new_rd_Sub(dbg, current_ir_graph, block, left, curr, mode);
} else { /* unsigned case */
ir_node *k_node;
- k_node = new_r_Const_long(current_ir_graph, block, mode, (1 << k) - 1);
+ k_node = new_Const_long(mode, (1 << k) - 1);
res = new_rd_And(dbg, current_ir_graph, block, left, k_node, mode);
}
} else {
((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);
ir_node *curr = left;
if (k != 1) {
- k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k - 1);
+ k_node = new_Const_long(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);
+ k_node = new_Const_long(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);
- c_k = new_r_Const_long(current_ir_graph, block, mode_Iu, k);
+ c_k = new_Const_long(mode_Iu, k);
*div = new_rd_Shrs(dbg, current_ir_graph, block, curr, c_k, mode);
if (n_flag) { /* negate the div result */
ir_node *k_node;
- k_node = new_r_Const(current_ir_graph, block, mode, get_mode_null(mode));
+ k_node = new_Const(get_mode_null(mode));
*div = new_rd_Sub(dbg, current_ir_graph, block, k_node, *div, mode);
}
- k_node = new_r_Const_long(current_ir_graph, block, mode, (-1) << k);
+ k_node = new_Const_long(mode, (-1) << k);
curr = new_rd_And(dbg, current_ir_graph, block, curr, k_node, mode);
*mod = new_rd_Sub(dbg, current_ir_graph, block, left, curr, mode);
} else { /* unsigned case */
ir_node *k_node;
- k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k);
+ k_node = new_Const_long(mode_Iu, k);
*div = new_rd_Shr(dbg, current_ir_graph, block, left, k_node, mode);
- k_node = new_r_Const_long(current_ir_graph, block, mode, (1 << k) - 1);
+ k_node = new_Const_long(mode, (1 << k) - 1);
*mod = new_rd_And(dbg, current_ir_graph, block, left, k_node, mode);
}
} else {