#endif
#include <limits.h>
+#include <stdbool.h>
#include "irargs_t.h"
#include "irnode_t.h"
#include "irdom.h"
#include "archop.h"
#include "error.h"
+#include "array_t.h"
#include "height.h"
#include "../benode_t.h"
ir_node *op, ir_node *orig_node);
/** Return non-zero is a node represents the 0 constant. */
-static int is_Const_0(ir_node *node) {
+static bool is_Const_0(ir_node *node) {
return is_Const(node) && is_Const_null(node);
}
/** Return non-zero is a node represents the 1 constant. */
-static int is_Const_1(ir_node *node) {
+static bool is_Const_1(ir_node *node) {
return is_Const(node) && is_Const_one(node);
}
/** Return non-zero is a node represents the -1 constant. */
-static int is_Const_Minus_1(ir_node *node) {
+static bool is_Const_Minus_1(ir_node *node) {
return is_Const(node) && is_Const_all_one(node);
}
/**
* returns true if constant can be created with a simple float command
*/
-static int is_simple_x87_Const(ir_node *node)
+static bool is_simple_x87_Const(ir_node *node)
{
tarval *tv = get_Const_tarval(node);
if (tarval_is_null(tv) || tarval_is_one(tv))
- return 1;
+ return true;
/* TODO: match all the other float constants */
- return 0;
+ return false;
}
/**
* returns true if constant can be created with a simple float command
*/
-static int is_simple_sse_Const(ir_node *node)
+static bool is_simple_sse_Const(ir_node *node)
{
tarval *tv = get_Const_tarval(node);
ir_mode *mode = get_tarval_mode(tv);
if (mode == mode_F)
- return 1;
+ return true;
if (tarval_is_null(tv) || tarval_is_one(tv))
- return 1;
+ return true;
if (mode == mode_D) {
unsigned val = get_tarval_sub_bits(tv, 0) |
(get_tarval_sub_bits(tv, 3) << 24);
if (val == 0)
/* lower 32bit are zero, really a 32bit constant */
- return 1;
+ return true;
}
/* TODO: match all the other float constants */
- return 0;
+ return false;
}
/**
am->commutative = commutative;
}
+static void set_transformed_and_mark(ir_node *const old_node, ir_node *const new_node)
+{
+ mark_irn_visited(old_node);
+ be_set_transformed_node(old_node, new_node);
+}
+
static ir_node *fix_mem_proj(ir_node *node, ia32_address_mode_t *am)
{
ir_mode *mode;
mode = get_irn_mode(node);
load = get_Proj_pred(am->mem_proj);
- mark_irn_visited(load);
- be_set_transformed_node(load, node);
+ set_transformed_and_mark(load, node);
if (mode != mode_T) {
set_irn_mode(node, mode_T);
return 1;
}
-static void set_transformed_and_mark(ir_node *const old_node, ir_node *const new_node)
-{
- mark_irn_visited(old_node);
- be_set_transformed_node(old_node, new_node);
-}
-
static ir_node *dest_am_binop(ir_node *node, ir_node *op1, ir_node *op2,
ir_node *mem, ir_node *ptr, ir_mode *mode,
construct_binop_dest_func *func,
* helper function: checks whether all Cmp projs are Lg or Eq which is needed
* to fold an and into a test node
*/
-static int can_fold_test_and(ir_node *node)
+static bool can_fold_test_and(ir_node *node)
{
const ir_edge_t *edge;
ir_node *proj = get_edge_src_irn(edge);
pn_Cmp pnc = get_Proj_proj(proj);
if(pnc != pn_Cmp_Eq && pnc != pn_Cmp_Lg)
- return 0;
+ return false;
}
- return 1;
+ return true;
+}
+
+/**
+ * returns true if it is assured, that the upper bits of a node are "clean"
+ * which means for a 16 or 8 bit value, that the upper bits in the register
+ * are 0 for unsigned and a copy of the last significant bit for unsigned
+ * numbers.
+ */
+static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
+{
+ assert(ia32_mode_needs_gp_reg(mode));
+ if (get_mode_size_bits(mode) >= 32)
+ return true;
+
+ if (is_ia32_Conv_I2I(transformed_node)
+ || is_ia32_Conv_I2I8Bit(transformed_node)) {
+ ir_mode *smaller_mode = get_ia32_ls_mode(transformed_node);
+ if (mode_is_signed(smaller_mode) != mode_is_signed(mode))
+ return false;
+ if (get_mode_size_bits(smaller_mode) > get_mode_size_bits(mode))
+ return false;
+
+ return true;
+ }
+
+ if (is_ia32_Shr(transformed_node) && !mode_is_signed(mode)) {
+ ir_node *right = get_irn_n(transformed_node, n_ia32_Shr_count);
+ if (is_ia32_Immediate(right) || is_ia32_Const(right)) {
+ const ia32_immediate_attr_t *attr
+ = get_ia32_immediate_attr_const(right);
+ if (attr->symconst == 0
+ && (unsigned) attr->offset >= (32 - get_mode_size_bits(mode))) {
+ return true;
+ }
+ }
+ }
+
+ if (is_ia32_And(transformed_node) && !mode_is_signed(mode)) {
+ ir_node *right = get_irn_n(transformed_node, n_ia32_And_right);
+ if (is_ia32_Immediate(right) || is_ia32_Const(right)) {
+ const ia32_immediate_attr_t *attr
+ = get_ia32_immediate_attr_const(right);
+ if (attr->symconst == 0
+ && (unsigned) attr->offset
+ <= (0xffffffff >> (32 - get_mode_size_bits(mode)))) {
+ return true;
+ }
+ }
+ }
+
+ if (is_ia32_Immediate(transformed_node)
+ || is_ia32_Const(transformed_node)) {
+ const ia32_immediate_attr_t *attr
+ = get_ia32_immediate_attr_const(transformed_node);
+ if (mode_is_signed(mode)) {
+ long shifted = attr->offset >> (get_mode_size_bits(mode) - 1);
+ if (shifted == 0 || shifted == -1)
+ return true;
+ } else {
+ unsigned long shifted = (unsigned long) attr->offset;
+ shifted >>= get_mode_size_bits(mode);
+ if (shifted == 0)
+ return true;
+ }
+ }
+
+ return false;
}
/**
/* Test(and_left, and_right) */
ir_node *and_left = get_And_left(left);
ir_node *and_right = get_And_right(left);
- ir_mode *mode = get_irn_mode(and_left);
+
+ /* matze: code here used mode instead of cmd_mode, I think it is always
+ * the same as cmp_mode, but I leave this here to see if this is really
+ * true...
+ */
+ assert(get_irn_mode(and_left) == cmp_mode);
match_arguments(&am, block, and_left, and_right, NULL,
match_commutative |
match_am | match_8bit_am | match_16bit_am |
match_am_and_immediates | match_immediate |
match_8bit | match_16bit);
- if (get_mode_size_bits(mode) == 8) {
+
+ /* use 32bit compare mode if possible since the opcode is smaller */
+ if (upper_bits_clean(am.new_op1, cmp_mode)
+ && upper_bits_clean(am.new_op2, cmp_mode)) {
+ cmp_mode = mode_is_signed(cmp_mode) ? mode_Is : mode_Iu;
+ }
+
+ if (get_mode_size_bits(cmp_mode) == 8) {
new_node = new_rd_ia32_Test8Bit(dbgi, irg, new_block, addr->base,
- addr->index, addr->mem, am.new_op1,
- am.new_op2, am.ins_permuted,
- cmp_unsigned);
+ addr->index, addr->mem, am.new_op1,
+ am.new_op2, am.ins_permuted,
+ cmp_unsigned);
} else {
new_node = new_rd_ia32_Test(dbgi, irg, new_block, addr->base,
- addr->index, addr->mem, am.new_op1,
- am.new_op2, am.ins_permuted, cmp_unsigned);
+ addr->index, addr->mem, am.new_op1,
+ am.new_op2, am.ins_permuted,
+ cmp_unsigned);
}
} else {
/* Cmp(left, right) */
match_commutative | match_am | match_8bit_am |
match_16bit_am | match_am_and_immediates |
match_immediate | match_8bit | match_16bit);
+ /* use 32bit compare mode if possible since the opcode is smaller */
+ if (upper_bits_clean(am.new_op1, cmp_mode)
+ && upper_bits_clean(am.new_op2, cmp_mode)) {
+ cmp_mode = mode_is_signed(cmp_mode) ? mode_Is : mode_Iu;
+ }
+
if (get_mode_size_bits(cmp_mode) == 8) {
new_node = new_rd_ia32_Cmp8Bit(dbgi, irg, new_block, addr->base,
addr->index, addr->mem, am.new_op1,
match_arguments(&am, block, NULL, op, NULL,
match_8bit | match_16bit |
match_am | match_8bit_am | match_16bit_am);
+
+ if (upper_bits_clean(am.new_op2, smaller_mode)) {
+ /* unnecessary conv. in theory it shouldn't have been AM */
+ assert(is_ia32_NoReg_GP(addr->base));
+ assert(is_ia32_NoReg_GP(addr->index));
+ assert(is_NoMem(addr->mem));
+ assert(am.addr.offset == 0);
+ assert(am.addr.symconst_ent == NULL);
+ return am.new_op2;
+ }
+
if (smaller_bits == 8) {
new_node = new_rd_ia32_Conv_I2I8Bit(dbgi, irg, new_block, addr->base,
addr->index, addr->mem, am.new_op2,
arity, in);
copy_node_attr(barrier, new_barrier);
be_duplicate_deps(barrier, new_barrier);
- be_set_transformed_node(barrier, new_barrier);
- mark_irn_visited(barrier);
+ set_transformed_and_mark(barrier, new_barrier);
/* transform normally */
return be_duplicate_node(node);
return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_SubSP_M);
}
- assert(0);
- return new_rd_Unknown(irg, get_irn_mode(node));
+ panic("No idea how to transform proj->AddSP");
}
/**
return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_AddSP_M);
}
- assert(0);
- return new_rd_Unknown(irg, get_irn_mode(node));
+ panic("No idea how to transform proj->SubSP");
}
/**
return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, 1);
}
- assert(0);
- return new_rd_Unknown(irg, get_irn_mode(node));
+ panic("No idea how to transform proj");
}
/**
ir_node *new_pred = be_transform_node(pred);
ir_graph *irg = current_ir_graph;
dbg_info *dbgi = get_irn_dbg_info(node);
- ir_mode *mode = get_irn_mode(node);
long proj = get_Proj_proj(node);
assert(is_ia32_Div(new_pred) || is_ia32_IDiv(new_pred));
break;
}
- assert(0);
- return new_rd_Unknown(irg, mode);
+ panic("No idea how to transform proj->DivMod");
}
/**
ir_node *new_pred = be_transform_node(pred);
ir_graph *irg = current_ir_graph;
dbg_info *dbgi = get_irn_dbg_info(node);
- ir_mode *mode = get_irn_mode(node);
long proj = get_Proj_proj(node);
switch(proj) {
break;
}
- assert(0);
- return new_rd_Unknown(irg, mode);
+ panic("No idea how to transform proj->CopyB");
}
/**
ir_node *new_pred = be_transform_node(pred);
ir_graph *irg = current_ir_graph;
dbg_info *dbgi = get_irn_dbg_info(node);
- ir_mode *mode = get_irn_mode(node);
long proj = get_Proj_proj(node);
switch(proj) {
break;
}
- assert(0);
- return new_rd_Unknown(irg, mode);
+ panic("No idea how to transform proj->Quot");
}
static ir_node *gen_be_Call(ir_node *node) {
if (proj == pn_Store_M) {
return be_transform_node(pred);
} else {
- assert(0);
- return new_r_Bad(current_ir_graph);
+ panic("No idea how to transform proj->Store");
}
case iro_Load:
return gen_Proj_Load(node);