* 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
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");
}
/**
/* Replace Muls with Shifts and Add/Subs. */
ir_node *arch_dep_replace_mul_with_shifts(ir_node *irn) {
- ir_node *res = irn;
+ ir_graph *irg;
+ ir_node *res = irn;
ir_mode *mode = get_irn_mode(irn);
+ ir_node *left;
+ ir_node *right;
+ ir_node *operand;
+ tarval *tv;
+
/* If the architecture dependent optimizations were not initialized
or this optimization was not enabled. */
if (params == NULL || (opts & arch_dep_mul_to_shift) == 0)
return irn;
- set_arch_dep_running(1);
- {
- if (is_Mul(irn) && mode_is_int(mode)) {
- ir_node *left = get_binop_left(irn);
- ir_node *right = get_binop_right(irn);
- tarval *tv = NULL;
- ir_node *operand = NULL;
-
- /* Look, if one operand is a constant. */
- if (is_Const(left)) {
- tv = get_Const_tarval(left);
- operand = right;
- } else if (is_Const(right)) {
- tv = get_Const_tarval(right);
- operand = left;
- }
+ if (!is_Mul(irn) || !mode_is_int(mode))
+ return res;
+
+ /* we should never do the reverse transformations again
+ (like x+x -> 2*x) */
+ irg = get_irn_irg(irn);
+ set_irg_state(irg, IR_GRAPH_STATE_ARCH_DEP);
+
+ left = get_binop_left(irn);
+ right = get_binop_right(irn);
+ tv = NULL;
+ operand = NULL;
+
+ /* Look, if one operand is a constant. */
+ if (is_Const(left)) {
+ tv = get_Const_tarval(left);
+ operand = right;
+ } else if (is_Const(right)) {
+ tv = get_Const_tarval(right);
+ operand = left;
+ }
- if (tv != NULL) {
- res = do_decomposition(irn, operand, tv);
+ if (tv != NULL) {
+ res = do_decomposition(irn, operand, tv);
- if (res != irn) {
- hook_arch_dep_replace_mul_with_shifts(irn);
- exchange(irn, res);
- }
- }
+ if (res != irn) {
+ hook_arch_dep_replace_mul_with_shifts(irn);
+ exchange(irn, res);
}
}
- //set_arch_dep_running(0);
return res;
}
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);
+ c = new_Const(mag.M);
q = new_rd_Mulh(dbg, current_ir_graph, block, n, c, mode);
if (mag.need_add) {
/* 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);
}
}
ir_node *curr = left;
/* create the correction code for signed values only if there might be a remainder */
- if (! is_Div_remainderless(irn)) {
+ if (! get_Div_no_remainder(irn)) {
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 = 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 {
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 {
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 {