-/**
- * @file irarch.c
- * @date 28.9.2004
- * @author Sebastian Hack
- * @brief Machine dependent firm optimizations.
+/*
+ * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
+ *
+ * This file is part of libFirm.
+ *
+ * This file may be distributed and/or modified under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * Licensees holding valid libFirm Professional Edition licenses may use
+ * this file in accordance with the libFirm Commercial License.
+ * Agreement provided with the Software.
*
- * $Id$
+ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ */
+
+/**
+ * @file
+ * @brief Machine dependent Firm optimizations.
+ * @date 28.9.2004
+ * @author Sebastian Hack, Michael Beck
+ * @version $Id$
*/
-#include <stdlib.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
#include <assert.h>
#include "irnode_t.h"
#include "irhooks.h"
#include "ircons.h"
#include "irarch.h"
+#include "irreflect.h"
#undef DEB
ir_node *in[2];
ir_node *res;
- if (! op_Mulh) {
- op_Mulh = new_ir_op(get_next_ir_opcode(), "Mulh", op_pin_state_floats, irop_flag_commutative, oparity_binary, 0, 0);
- }
-
in[0] = op1;
in[1] = op2;
res = new_ir_node(db, irg, block, op_Mulh, mode, 2, in);
if (factory != NULL)
params = factory();
- if (params && (opts & (arch_dep_div_by_const|arch_dep_mod_by_const))) {
- if (! op_Mulh) {
- /* create the Mulh operation */
- op_Mulh = new_ir_op(get_next_ir_opcode(), "Mulh", op_pin_state_floats, irop_flag_commutative, oparity_binary, 0, 0);
- }
+ if (! op_Mulh) {
+ rflct_sig_t *sig;
+ int mulh_opc = get_next_ir_opcode();
+
+ /* create the Mulh operation */
+ op_Mulh = new_ir_op(mulh_opc, "Mulh", op_pin_state_floats, irop_flag_commutative, oparity_binary, 0, 0, NULL);
+ sig = rflct_signature_allocate(1, 3);
+ rflct_signature_set_arg(sig, 0, 0, "Res", RFLCT_MC(Int), 0, 0);
+ rflct_signature_set_arg(sig, 1, 0, "Block", RFLCT_MC(BB), 0, 0);
+ rflct_signature_set_arg(sig, 1, 1, "Op 0", RFLCT_MC(Int), 0, 0);
+ rflct_signature_set_arg(sig, 1, 2, "Op 1", RFLCT_MC(Int), 0, 0);
+
+ rflct_new_opcode(mulh_opc, "Mulh", 0);
+ rflct_opcode_add_signature(mulh_opc, sig);
}
}
opts = the_opts;
}
-/* check, wheater a mode allows a Mulh instruction */
+/** check, whether a mode allows a Mulh instruction. */
static int allow_Mulh(ir_mode *mode)
{
if (get_mode_size_bits(mode) > params->max_bits_for_mulh)
return (mode_is_signed(mode) && params->allow_mulhs) || (!mode_is_signed(mode) && params->allow_mulhu);
}
+/* Replace Muls with Shifts and Add/Subs. */
ir_node *arch_dep_replace_mul_with_shifts(ir_node *irn)
{
ir_node *res = irn;
/* If the architecture dependent optimizations were not initialized
or this optimization was not enabled. */
- if(params == NULL || (opts & arch_dep_mul_to_shift) == 0)
+ if (params == NULL || (opts & arch_dep_mul_to_shift) == 0)
return irn;
- if(get_irn_opcode(irn) == iro_Mul && mode_is_int(mode)) {
- ir_node *block = get_nodes_block(irn);
+ if (get_irn_op(irn) == op_Mul && mode_is_int(mode)) {
+ ir_node *block = get_irn_n(irn, -1);
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(get_irn_opcode(left) == iro_Const) {
+ if (get_irn_opcode(left) == iro_Const) {
tv = get_Const_tarval(left);
operand = right;
} else if(get_irn_opcode(right) == iro_Const) {
operand = left;
}
- if(tv != NULL) {
+ if (tv != NULL) {
int maximum_shifts = params->maximum_shifts;
int also_use_subs = params->also_use_subs;
int highest_shift_amount = params->highest_shift_amount;
}
#endif
- // Go over all recorded one groups.
+ /* Go over all recorded one groups. */
curr_bit = compr[0];
for(i = 1; i < compr_len; i = end_of_group + 2) {
ones_in_group = compr[i];
zeros_in_group = 0;
- // Scan for singular 0s in a sequence
+ /* Scan for singular 0s in a sequence. */
for(j = i + 1; j < compr_len && compr[j] == 1; j += 2) {
zeros_in_group += 1;
ones_in_group += (j + 1 < compr_len ? compr[j + 1] : 0);
fprintf(stderr, " j:%d, ones:%d\n", j, curr_ones);
#endif
- // If this ones group is a singleton group (it has no
- // singleton zeros inside
+ /* If this ones group is a singleton group (it has no
+ singleton zeros inside. */
if(singleton)
shift_with_sub[shift_with_sub_pos++] = biased_curr_bit;
else if(j == i)
assert(amount >= 0 && "What is a negative shift??");
- if(amount != 0) {
+ if (amount != 0) {
ir_node *cnst = new_r_Const_long(current_ir_graph, block, mode_Iu, amount);
aux = new_r_Shl(current_ir_graph, block, operand, cnst, mode);
}
- if(curr) {
- if(sub)
+ if (curr) {
+ if (sub)
curr = new_r_Sub(current_ir_graph, block, curr, aux, mode);
else
curr = new_r_Add(current_ir_graph, block, curr, aux, mode);
#ifdef DEB
{
const char *prefix = "";
- for(i = 0; i < n; i++) {
+ for (i = 0; i < n; ++i) {
fprintf(stderr, "%s%d", prefix, shifts[i]);
prefix = ", ";
}
*/
static int tv_ld2(tarval *tv, int bits)
{
- int i, k, num;
+ int i, k = 0, num;
for (num = i = 0; i < bits; ++i) {
unsigned char v = get_tarval_sub_bits(tv, i);
#define ONE(m) get_mode_one(m)
#define ZERO(m) get_mode_null(m)
+/** The result of a the magic() function. */
struct ms {
tarval *M; /**< magic number */
int s; /**< shift amount */
return mag;
}
+/** The result of the magicu() function. */
struct mu {
tarval *M; /**< magic add constant */
int s; /**< shift amount */
}
/**
- * build the Mulh replacement code for n / tv
+ * Build the Mulh replacement code for n / tv.
*
- * Note thet 'div' might be a mod or DivMod operation as well
+ * Note that 'div' might be a mod or DivMod operation as well
*/
static ir_node *replace_div_by_mulh(ir_node *div, tarval *tv)
{
dbg_info *dbg = get_irn_dbg_info(div);
ir_node *n = get_binop_left(div);
- ir_node *block = get_nodes_block(div);
+ ir_node *block = get_irn_n(div, -1);
ir_mode *mode = get_irn_mode(n);
int bits = get_mode_size_bits(mode);
ir_node *q, *t, *c;
return q;
}
+/* Replace Divs with Shifts and Add/Subs and Mulh. */
ir_node *arch_dep_replace_div_by_const(ir_node *irn)
{
ir_node *res = irn;
if (get_irn_op(c) != op_Const)
return irn;
+ tv = get_Const_tarval(c);
+
+ /* check for division by zero */
+ if (classify_tarval(tv) == TV_CLASSIFY_NULL)
+ return irn;
+
left = get_Div_left(irn);
mode = get_irn_mode(left);
- block = get_nodes_block(irn);
+ block = get_irn_n(irn, -1);
dbg = get_irn_dbg_info(irn);
- tv = get_Const_tarval(c);
bits = get_mode_size_bits(mode);
n = (bits + 7) / 8;
}
if (res != irn)
- hook_arch_dep_replace_div_by_const(irn);
+ hook_arch_dep_replace_division_by_const(irn);
return res;
}
+/* Replace Mods with Shifts and Add/Subs and Mulh. */
ir_node *arch_dep_replace_mod_by_const(ir_node *irn)
{
ir_node *res = irn;
if (get_irn_op(c) != op_Const)
return irn;
+ tv = get_Const_tarval(c);
+
+ /* check for division by zero */
+ if (classify_tarval(tv) == TV_CLASSIFY_NULL)
+ return irn;
+
left = get_Mod_left(irn);
mode = get_irn_mode(left);
- block = get_nodes_block(irn);
+ block = get_irn_n(irn, -1);
dbg = get_irn_dbg_info(irn);
- tv = get_Const_tarval(c);
-
bits = get_mode_size_bits(mode);
n = (bits + 7) / 8;
}
if (res != irn)
- hook_arch_dep_replace_mod_by_const(irn);
+ hook_arch_dep_replace_division_by_const(irn);
return res;
}
+/* Replace DivMods with Shifts and Add/Subs and Mulh. */
void arch_dep_replace_divmod_by_const(ir_node **div, ir_node **mod, ir_node *irn)
{
*div = *mod = NULL;
if (get_irn_op(c) != op_Const)
return;
+ tv = get_Const_tarval(c);
+
+ /* check for division by zero */
+ if (classify_tarval(tv) == TV_CLASSIFY_NULL)
+ return;
+
left = get_DivMod_left(irn);
mode = get_irn_mode(left);
- block = get_nodes_block(irn);
+ block = get_irn_n(irn, -1);
dbg = get_irn_dbg_info(irn);
- tv = get_Const_tarval(c);
bits = get_mode_size_bits(mode);
n = (bits + 7) / 8;
}
if (*div)
- hook_arch_dep_replace_DivMod_by_const(irn);
+ hook_arch_dep_replace_division_by_const(irn);
}
32 /* Mulh allowed up to 32 bit */
};
+/* A default parameter factory for testing purposes. */
const arch_dep_params_t *arch_dep_default_factory(void) {
return &default_params;
}