/*
- * 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.
*
#include "../beutil.h"
#include "../beirg_t.h"
#include "../betranshlp.h"
+#include "../be_t.h"
#include "bearch_ia32_t.h"
#include "ia32_nodes_attr.h"
#include "ia32_optimize.h"
#include "ia32_util.h"
#include "ia32_address_mode.h"
+#include "ia32_architecture.h"
#include "gen_ia32_regalloc_if.h"
static ia32_code_gen_t *env_cg = NULL;
static ir_node *initial_fpcw = NULL;
static heights_t *heights = NULL;
-static transform_config_t transform_config;
extern ir_op *get_op_Mulh(void);
typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg,
ir_node *block, ir_node *op);
-/****************************************************************************************************
- * _ _ __ _ _
- * | | | | / _| | | (_)
- * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
- * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
- * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
- * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
- *
- ****************************************************************************************************/
-
static ir_node *try_create_Immediate(ir_node *node,
char immediate_constraint_type);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_mode *mode = get_irn_mode(node);
+ assert(is_Const(node));
+
if (mode_is_float(mode)) {
ir_node *res = NULL;
ir_node *noreg = ia32_new_NoReg_gp(env_cg);
ir_node *load;
ir_entity *floatent;
- if (USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2) {
if (is_Const_null(node)) {
load = new_rd_ia32_xZero(dbgi, irg, block);
set_ia32_ls_mode(load, mode);
ir_node *noreg = ia32_new_NoReg_gp(env_cg);
ir_node *nomem = new_NoMem();
- if (USE_SSE2(env_cg))
+ if (ia32_cg_config.use_sse2)
cnst = new_rd_ia32_xLoad(dbgi, irg, block, noreg, noreg, nomem, mode_E);
else
cnst = new_rd_ia32_vfld(dbgi, irg, block, noreg, noreg, nomem, mode_E);
}
#endif /* NDEBUG */
-int ia32_use_source_address_mode(ir_node *block, ir_node *node, ir_node *other)
+/**
+ * return true if the node is a Proj(Load) and could be used in source address
+ * mode for another node. Will return only true if the @p other node is not
+ * dependent on the memory of the Load (for binary operations use the other
+ * input here, for unary operations use NULL).
+ */
+static int ia32_use_source_address_mode(ir_node *block, ir_node *node,
+ ir_node *other, ir_node *other2)
{
ir_mode *mode = get_irn_mode(node);
ir_node *load;
if(other != NULL && get_nodes_block(other) == block
&& heights_reachable_in_block(heights, other, load))
return 0;
+ if(other2 != NULL && get_nodes_block(other2) == block
+ && heights_reachable_in_block(heights, other2, load))
+ return 0;
return 1;
}
memset(addr, 0, sizeof(addr[0]));
ia32_create_address_mode(addr, ptr, /*force=*/0);
- if(addr->base == NULL) {
- addr->base = noreg_gp;
- } else {
- addr->base = be_transform_node(addr->base);
- }
-
- if(addr->index == NULL) {
- addr->index = noreg_gp;
- } else {
- addr->index = be_transform_node(addr->index);
- }
+ addr->base = addr->base ? be_transform_node(addr->base) : noreg_gp;
+ addr->index = addr->index ? be_transform_node(addr->index) : noreg_gp;
addr->mem = be_transform_node(mem);
}
ir_node *ptr;
ir_node *mem;
ir_node *new_mem;
- ir_node *base;
- ir_node *index;
if(is_Const(node)) {
ir_entity *entity = create_float_const_entity(node);
/* construct load address */
ia32_create_address_mode(addr, ptr, /*force=*/0);
- base = addr->base;
- index = addr->index;
-
- if(base == NULL) {
- base = noreg_gp;
- } else {
- base = be_transform_node(base);
- }
- if(index == NULL) {
- index = noreg_gp;
- } else {
- index = be_transform_node(index);
- }
-
- addr->base = base;
- addr->index = index;
+ addr->base = addr->base ? be_transform_node(addr->base) : noreg_gp;
+ addr->index = addr->index ? be_transform_node(addr->index) : noreg_gp;
addr->mem = new_mem;
}
}
#endif
+/**
+ * matches operands of a node into ia32 addressing/operand modes. This covers
+ * usage of source address mode, immediates, operations with non 32-bit modes,
+ * ...
+ * The resulting data is filled into the @p am struct. block is the block
+ * of the node whose arguments are matched. op1, op2 are the first and second
+ * input that are matched (op1 may be NULL). other_op is another unrelated
+ * input that is not matched! but which is needed sometimes to check if AM
+ * for op1/op2 is legal.
+ * @p flags describes the supported modes of the operation in detail.
+ */
static void match_arguments(ia32_address_mode_t *am, ir_node *block,
- ir_node *op1, ir_node *op2, match_flags_t flags)
+ ir_node *op1, ir_node *op2, ir_node *other_op,
+ match_flags_t flags)
{
ia32_address_t *addr = &am->addr;
ir_node *noreg_gp = ia32_new_NoReg_gp(env_cg);
if(mode_bits == 8) {
if (! (flags & match_8bit_am))
use_am = 0;
+ /* we don't automatically add upconvs yet */
assert((flags & match_mode_neutral) || (flags & match_8bit));
} else if(mode_bits == 16) {
if(! (flags & match_16bit_am))
use_am = 0;
+ /* we don't automatically add upconvs yet */
assert((flags & match_mode_neutral) || (flags & match_16bit));
}
}
}
- if(! (flags & match_try_am) && use_immediate)
+ /* match immediates. firm nodes are normalized: constants are always on the
+ * op2 input */
+ new_op2 = NULL;
+ if(! (flags & match_try_am) && use_immediate) {
new_op2 = try_create_Immediate(op2, 0);
- else
- new_op2 = NULL;
+ }
- if(new_op2 == NULL && use_am && ia32_use_source_address_mode(block, op2, op1)) {
+ if(new_op2 == NULL
+ && use_am && ia32_use_source_address_mode(block, op2, op1, other_op)) {
build_address(am, op2);
new_op1 = (op1 == NULL ? NULL : be_transform_node(op1));
if(mode_is_float(mode)) {
}
am->op_type = ia32_AddrModeS;
} else if(commutative && (new_op2 == NULL || use_am_and_immediates) &&
- use_am && ia32_use_source_address_mode(block, op1, op2)) {
+ use_am
+ && ia32_use_source_address_mode(block, op1, op2, other_op)) {
ir_node *noreg;
build_address(am, op1);
ia32_address_mode_t am;
ia32_address_t *addr = &am.addr;
- match_arguments(&am, block, op1, op2, flags);
+ match_arguments(&am, block, op1, op2, NULL, flags);
new_node = func(dbgi, irg, new_block, addr->base, addr->index, addr->mem,
am.new_op1, am.new_op2);
ia32_address_mode_t am;
ia32_address_t *addr = &am.addr;
- match_arguments(&am, src_block, op1, op2, flags);
+ match_arguments(&am, src_block, op1, op2, NULL, flags);
new_node = func(dbgi, irg, block, addr->base, addr->index,
addr->mem, am.new_op1, am.new_op2, new_eflags);
ia32_address_t *addr = &am.addr;
/* cannot use addresmode with long double on x87 */
- if (get_mode_size_bits(mode) > 64) flags &= ~match_am;
+ if (get_mode_size_bits(mode) > 64)
+ flags &= ~match_am;
- match_arguments(&am, block, op1, op2, flags);
+ match_arguments(&am, block, op1, op2, NULL, flags);
new_node = func(dbgi, irg, new_block, addr->base, addr->index, addr->mem,
am.new_op1, am.new_op2, get_fpcw());
ir_graph *irg = current_ir_graph;
ir_node *block = get_nodes_block(node);
ir_node *new_block = be_transform_node(block);
- ir_mode *mode = get_irn_mode(node);
ir_node *new_op1;
ir_node *new_op2;
ir_node *new_node;
- assert(! mode_is_float(mode));
+ assert(! mode_is_float(get_irn_mode(node)));
assert(flags & match_immediate);
assert((flags & ~(match_mode_neutral | match_immediate)) == 0);
ia32_address_mode_t am;
if (mode_is_float(mode)) {
- if (USE_SSE2(env_cg))
+ if (ia32_cg_config.use_sse2)
return gen_binop(node, op1, op2, new_rd_ia32_xAdd,
match_commutative | match_am);
else
}
/* test if we can use source address mode */
- match_arguments(&am, block, op1, op2, match_commutative
+ match_arguments(&am, block, op1, op2, NULL, match_commutative
| match_mode_neutral | match_am | match_immediate | match_try_am);
/* construct an Add with source address mode */
ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode)) {
- if (USE_SSE2(env_cg))
+ if (ia32_cg_config.use_sse2)
return gen_binop(node, op1, op2, new_rd_ia32_xMul,
match_commutative | match_am);
else
match_commutative | match_am);
}
- /*
- for the lower 32bit of the result it doesn't matter whether we use
- signed or unsigned multiplication so we use IMul as it has fewer
- constraints
- */
+ /* for the lower 32bit of the result it doesn't matter whether we use
+ * signed or unsigned multiplication so we use IMul as it has fewer
+ * constraints */
return gen_binop(node, op1, op2, new_rd_ia32_IMul,
match_commutative | match_am | match_mode_neutral |
match_immediate | match_am_and_immediates);
ir_mode *mode = get_irn_mode(node);
ir_node *op1 = get_Mulh_left(node);
ir_node *op2 = get_Mulh_right(node);
- ir_node *proj_EDX;
+ ir_node *proj_res_high;
ir_node *new_node;
- match_flags_t flags;
ia32_address_mode_t am;
ia32_address_t *addr = &am.addr;
- flags = match_commutative | match_am;
-
assert(!mode_is_float(mode) && "Mulh with float not supported");
assert(get_mode_size_bits(mode) == 32);
- match_arguments(&am, block, op1, op2, flags);
+ match_arguments(&am, block, op1, op2, NULL, match_commutative | match_am);
if (mode_is_signed(mode)) {
new_node = new_rd_ia32_IMul1OP(dbgi, irg, new_block, addr->base,
fix_mem_proj(new_node, &am);
- assert(pn_ia32_IMul1OP_EDX == pn_ia32_Mul_EDX);
- proj_EDX = new_rd_Proj(dbgi, irg, block, new_node,
- mode_Iu, pn_ia32_IMul1OP_EDX);
+ assert(pn_ia32_IMul1OP_res_high == pn_ia32_Mul_res_high);
+ proj_res_high = new_rd_Proj(dbgi, irg, block, new_node,
+ mode_Iu, pn_ia32_IMul1OP_res_high);
- return proj_EDX;
+ return proj_res_high;
}
ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode)) {
- if (USE_SSE2(env_cg))
+ if (ia32_cg_config.use_sse2)
return gen_binop(node, op1, op2, new_rd_ia32_xSub, match_am);
else
return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfsub,
panic("invalid divmod node %+F", node);
}
- match_arguments(&am, block, op1, op2, match_am);
+ match_arguments(&am, block, op1, op2, NULL, match_am);
if(!is_NoMem(mem)) {
new_mem = be_transform_node(mem);
ir_node *op1 = get_Quot_left(node);
ir_node *op2 = get_Quot_right(node);
- if (USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2) {
return gen_binop(node, op1, op2, new_rd_ia32_xDiv, match_am);
} else {
return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfdiv, match_am);
if (mode_is_float(mode)) {
ir_node *new_op = be_transform_node(op);
- if (USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2) {
/* TODO: non-optimal... if we have many xXors, then we should
* rather create a load for the const and use that instead of
* several AM nodes... */
dbg_info *dbgi = get_irn_dbg_info(node);
ir_mode *mode = get_irn_mode(node);
ir_node *noreg_gp = ia32_new_NoReg_gp(env_cg);
- ir_node *noreg_fp = ia32_new_NoReg_fp(env_cg);
ir_node *nomem = new_NoMem();
ir_node *new_op;
ir_node *new_node;
if (mode_is_float(mode)) {
new_op = be_transform_node(op);
- if (USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2) {
+ ir_node *noreg_fp = ia32_new_NoReg_xmm(env_cg);
new_node = new_rd_ia32_xAnd(dbgi,irg, new_block, noreg_gp, noreg_gp,
nomem, new_op, noreg_fp);
SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
}
} else {
+ ir_node *xor, *pval, *sign_extension;
+
if (get_mode_size_bits(mode) == 32) {
new_op = be_transform_node(op);
} else {
new_op = create_I2I_Conv(mode, mode_Is, dbgi, block, op, node);
}
- ir_node *xor;
- ir_node *pval = new_rd_ia32_ProduceVal(dbgi, irg, new_block);
- ir_node *sign_extension = new_rd_ia32_Cltd(dbgi, irg, new_block,
+ pval = new_rd_ia32_ProduceVal(dbgi, irg, new_block);
+ sign_extension = new_rd_ia32_Cltd(dbgi, irg, new_block,
new_op, pval);
add_irn_dep(pval, get_irg_frame(irg));
}
if (mode_is_float(mode)) {
- if (USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2) {
new_node = new_rd_ia32_xLoad(dbgi, irg, block, base, index, new_mem,
mode);
res_mode = mode_xmm;
set_address(new_node, &addr);
if(get_irn_pinned(node) == op_pin_state_floats) {
- set_ia32_flags(new_node, arch_irn_flags_rematerializable);
+ add_ia32_flags(new_node, arch_irn_flags_rematerializable);
}
/* make sure we are scheduled behind the initial IncSP/Barrier
ir_node *mem = get_Store_mem(node);
ir_node *ptr = get_Store_ptr(node);
ir_mode *mode = get_irn_mode(val);
- int bits = get_mode_size_bits(mode);
+ unsigned bits = get_mode_size_bits(mode);
ir_node *op1;
ir_node *op2;
ir_node *new_node;
val = get_Conv_op(val);
}
new_val = be_transform_node(val);
- if (USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2) {
new_node = new_rd_ia32_xStore(dbgi, irg, new_block, addr.base,
addr.index, addr.mem, new_val);
} else {
static ir_node *create_Switch(ir_node *node)
{
- ir_graph *irg = current_ir_graph;
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *sel = get_Cond_selector(node);
- ir_node *new_sel = be_transform_node(sel);
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *block = be_transform_node(get_nodes_block(node));
+ ir_node *sel = get_Cond_selector(node);
+ ir_node *new_sel = be_transform_node(sel);
int switch_min = INT_MAX;
+ int switch_max = INT_MIN;
+ long default_pn = get_Cond_defaultProj(node);
ir_node *new_node;
const ir_edge_t *edge;
/* determine the smallest switch case value */
foreach_out_edge(node, edge) {
ir_node *proj = get_edge_src_irn(edge);
- int pn = get_Proj_proj(proj);
+ long pn = get_Proj_proj(proj);
+ if(pn == default_pn)
+ continue;
+
if(pn < switch_min)
switch_min = pn;
+ if(pn > switch_max)
+ switch_max = pn;
+ }
+
+ if((unsigned) (switch_max - switch_min) > 256000) {
+ panic("Size of switch %+F bigger than 256000", node);
}
if (switch_min != 0) {
SET_IA32_ORIG_NODE(new_sel, ia32_get_old_node_name(env_cg, node));
}
- new_node = new_rd_ia32_SwitchJmp(dbgi, irg, block, new_sel,
- get_Cond_defaultProj(node));
+ new_node = new_rd_ia32_SwitchJmp(dbgi, irg, block, new_sel, default_pn);
SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
return new_node;
ir_node *new_right;
ir_node *new_node;
- if(transform_config.use_fucomi) {
+ if(ia32_cg_config.use_fucomi) {
new_right = be_transform_node(right);
new_node = new_rd_ia32_vFucomi(dbgi, irg, new_block, new_left,
new_right, 0);
set_ia32_commutative(new_node);
SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
} else {
- if(transform_config.use_ftst && is_Const_null(right)) {
+ if(ia32_cg_config.use_ftst && is_Const_0(right)) {
new_node = new_rd_ia32_vFtstFnstsw(dbgi, irg, new_block, new_left,
0);
} else {
ia32_address_mode_t am;
ia32_address_t *addr = &am.addr;
- match_arguments(&am, src_block, left, right, match_commutative | match_am);
+ match_arguments(&am, src_block, left, right, NULL,
+ match_commutative | match_am);
new_node = new_rd_ia32_Ucomi(dbgi, irg, new_block, addr->base, addr->index,
addr->mem, am.new_op1, am.new_op2,
int cmp_unsigned;
if(mode_is_float(cmp_mode)) {
- if (USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2) {
return create_Ucomi(node);
} else {
return create_Fucom(node);
ir_node *and_right = get_And_right(left);
ir_mode *mode = get_irn_mode(and_left);
- match_arguments(&am, block, and_left, and_right, match_commutative |
+ 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);
am.new_op2, am.ins_permuted, cmp_unsigned);
}
} else {
- match_arguments(&am, block, NULL, left, match_am | match_8bit_am |
- match_16bit_am | match_8bit | match_16bit);
+ match_arguments(&am, block, NULL, left, NULL,
+ match_am | match_8bit_am | match_16bit_am |
+ match_8bit | match_16bit);
if (am.op_type == ia32_AddrModeS) {
/* Cmp(AM, 0) */
ir_node *imm_zero = try_create_Immediate(right, 0);
}
} else {
/* Cmp(left, right) */
- match_arguments(&am, block, left, right, match_commutative | match_am |
- match_8bit_am | match_16bit_am | match_am_and_immediates |
+ match_arguments(&am, block, left, 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(cmp_mode) == 8) {
new_node = new_rd_ia32_Cmp8Bit(dbgi, irg, new_block, addr->base,
return new_node;
}
-static ir_node *create_CMov(ir_node *node, ir_node *new_flags, pn_Cmp pnc)
+static ir_node *create_CMov(ir_node *node, ir_node *flags, ir_node *new_flags,
+ pn_Cmp pnc)
{
ir_graph *irg = current_ir_graph;
dbg_info *dbgi = get_irn_dbg_info(node);
ia32_address_mode_t am;
ia32_address_t *addr;
- assert(transform_config.use_cmov);
+ assert(ia32_cg_config.use_cmov);
assert(mode_needs_gp_reg(get_irn_mode(val_true)));
addr = &am.addr;
match_flags = match_commutative | match_am | match_16bit_am |
match_mode_neutral;
- match_arguments(&am, block, val_false, val_true, match_flags);
+ match_arguments(&am, block, val_false, val_true, flags, match_flags);
new_node = new_rd_ia32_CMov(dbgi, irg, new_block, addr->base, addr->index,
addr->mem, am.new_op1, am.new_op2, new_flags,
} else if(is_Const_0(psi_true) && is_Const_1(psi_default)) {
new_node = create_set_32bit(dbgi, new_block, flags, pnc, node, 1);
} else {
- new_node = create_CMov(node, flags, pnc);
+ new_node = create_CMov(node, cond, flags, pnc);
}
return new_node;
}
if (src_mode == mode_Is) {
ia32_address_mode_t am;
- match_arguments(&am, src_block, NULL, op, match_am | match_try_am);
+ match_arguments(&am, src_block, NULL, op, NULL,
+ match_am | match_try_am);
if (am.op_type == ia32_AddrModeS) {
ia32_address_t *addr = &am.addr;
ia32_address_mode_t am;
ia32_address_t *addr = &am.addr;
+ (void) node;
if (src_bits < tgt_bits) {
smaller_mode = src_mode;
smaller_bits = src_bits;
}
#endif
- match_arguments(&am, block, NULL, op, match_8bit | match_16bit | match_am |
- match_8bit_am | match_16bit_am);
+ match_arguments(&am, block, NULL, op, NULL,
+ match_8bit | match_16bit |
+ match_am | match_8bit_am | match_16bit_am);
if (smaller_bits == 8) {
new_node = new_rd_ia32_Conv_I2I8Bit(dbgi, irg, new_block, addr->base,
addr->index, addr->mem, am.new_op2,
if (src_mode == tgt_mode) {
if (get_Conv_strict(node)) {
- if (USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2) {
/* when we are in SSE mode, we can kill all strict no-op conversion */
return be_transform_node(op);
}
}
/* ... to float */
- if (USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2) {
DB((dbg, LEVEL_1, "create Conv(float, float) ..."));
res = new_rd_ia32_Conv_FP2FP(dbgi, irg, new_block, noreg, noreg,
nomem, new_op);
} else {
/* ... to int */
DB((dbg, LEVEL_1, "create Conv(float, int) ..."));
- if (USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2) {
res = new_rd_ia32_Conv_FP2I(dbgi, irg, new_block, noreg, noreg,
nomem, new_op);
set_ia32_ls_mode(res, src_mode);
if (mode_is_float(tgt_mode)) {
/* ... to float */
DB((dbg, LEVEL_1, "create Conv(int, float) ..."));
- if (USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2) {
new_op = be_transform_node(op);
res = new_rd_ia32_Conv_I2FP(dbgi, irg, new_block, noreg, noreg,
nomem, new_op);
return new_node;
}
-/********************************************
- * _ _
- * | | | |
- * | |__ ___ _ __ ___ __| | ___ ___
- * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __|
- * | |_) | __/ | | | (_) | (_| | __/\__ \
- * |_.__/ \___|_| |_|\___/ \__,_|\___||___/
- *
- ********************************************/
-
/**
* Transforms a FrameAddr into an ia32 Add.
*/
int pn_ret_val, pn_ret_mem, arity, i;
assert(ret_val != NULL);
- if (be_Return_get_n_rets(node) < 1 || ! USE_SSE2(env_cg)) {
+ if (be_Return_get_n_rets(node) < 1 || ! ia32_cg_config.use_sse2) {
return be_duplicate_node(node);
}
ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode)) {
- if (USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2) {
return ia32_new_Unknown_xmm(env_cg);
} else {
/* Unknown nodes are buggy in x87 sim, use zero for now... */
/* all integer operations are on 32bit registers now */
mode = mode_Iu;
} else if(mode_is_float(mode)) {
- if (USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2) {
mode = mode_xmm;
} else {
mode = mode_vfp;
assert(get_irn_mode(op) == mode_P);
- match_arguments(&am, block, NULL, op,
+ match_arguments(&am, block, NULL, op, NULL,
match_am | match_8bit_am | match_16bit_am |
match_immediate | match_8bit | match_16bit);
return new_node;
}
-
-/**********************************************************************
- * _ _ _
- * | | | | | |
- * | | _____ _____ _ __ ___ __| | _ __ ___ __| | ___ ___
- * | |/ _ \ \ /\ / / _ \ '__/ _ \/ _` | | '_ \ / _ \ / _` |/ _ \/ __|
- * | | (_) \ V V / __/ | | __/ (_| | | | | | (_) | (_| | __/\__ \
- * |_|\___/ \_/\_/ \___|_| \___|\__,_| |_| |_|\___/ \__,_|\___||___/
- *
- **********************************************************************/
-
-/* These nodes are created in intrinsic lowering (64bit -> 32bit) */
-
typedef ir_node *construct_load_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
ir_node *mem);
static ir_node *gen_ia32_l_ShlDep(ir_node *node)
{
- ir_node *left = get_irn_n(node, n_ia32_l_ShlDep_left);
- ir_node *right = get_irn_n(node, n_ia32_l_ShlDep_right);
+ ir_node *left = get_irn_n(node, n_ia32_l_ShlDep_val);
+ ir_node *right = get_irn_n(node, n_ia32_l_ShlDep_count);
return gen_shift_binop(node, left, right, new_rd_ia32_Shl,
match_immediate | match_mode_neutral);
static ir_node *gen_ia32_l_ShrDep(ir_node *node)
{
- ir_node *left = get_irn_n(node, n_ia32_l_ShrDep_left);
- ir_node *right = get_irn_n(node, n_ia32_l_ShrDep_right);
+ ir_node *left = get_irn_n(node, n_ia32_l_ShrDep_val);
+ ir_node *right = get_irn_n(node, n_ia32_l_ShrDep_count);
return gen_shift_binop(node, left, right, new_rd_ia32_Shr,
match_immediate);
}
static ir_node *gen_ia32_l_SarDep(ir_node *node)
{
- ir_node *left = get_irn_n(node, n_ia32_l_SarDep_left);
- ir_node *right = get_irn_n(node, n_ia32_l_SarDep_right);
+ ir_node *left = get_irn_n(node, n_ia32_l_SarDep_val);
+ ir_node *right = get_irn_n(node, n_ia32_l_SarDep_count);
return gen_shift_binop(node, left, right, new_rd_ia32_Sar,
match_immediate);
}
static ir_node *gen_ia32_l_ShlD(ir_node *node)
{
- ir_node *high = get_irn_n(node, n_ia32_l_ShlD_high);
- ir_node *low = get_irn_n(node, n_ia32_l_ShlD_low);
+ ir_node *high = get_irn_n(node, n_ia32_l_ShlD_val_high);
+ ir_node *low = get_irn_n(node, n_ia32_l_ShlD_val_low);
ir_node *count = get_irn_n(node, n_ia32_l_ShlD_count);
return gen_lowered_64bit_shifts(node, high, low, count);
}
static ir_node *gen_ia32_l_ShrD(ir_node *node)
{
- ir_node *high = get_irn_n(node, n_ia32_l_ShrD_high);
- ir_node *low = get_irn_n(node, n_ia32_l_ShrD_low);
+ ir_node *high = get_irn_n(node, n_ia32_l_ShrD_val_high);
+ ir_node *low = get_irn_n(node, n_ia32_l_ShrD_val_low);
ir_node *count = get_irn_n(node, n_ia32_l_ShrD_count);
return gen_lowered_64bit_shifts(node, high, low, count);
}
-/**
- * In case SSE Unit is used, the node is transformed into a vfst + xLoad.
- */
-static ir_node *gen_ia32_l_X87toSSE(ir_node *node) {
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *val = get_irn_n(node, 1);
- ir_node *new_val = be_transform_node(val);
- ia32_code_gen_t *cg = env_cg;
- ir_node *res = NULL;
- ir_graph *irg = current_ir_graph;
- dbg_info *dbgi;
- ir_node *noreg, *new_ptr, *new_mem;
- ir_node *ptr, *mem;
-
- if (USE_SSE2(cg)) {
- return new_val;
- }
+static ir_node *gen_ia32_l_LLtoFloat(ir_node *node) {
+ ir_node *src_block = get_nodes_block(node);
+ ir_node *block = be_transform_node(src_block);
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *frame = get_irg_frame(irg);
+ ir_node *noreg = ia32_new_NoReg_gp(env_cg);
+ ir_node *nomem = new_NoMem();
+ ir_node *val_low = get_irn_n(node, n_ia32_l_LLtoFloat_val_low);
+ ir_node *val_high = get_irn_n(node, n_ia32_l_LLtoFloat_val_high);
+ ir_node *new_val_low = be_transform_node(val_low);
+ ir_node *new_val_high = be_transform_node(val_high);
+ ir_node *in[2];
+ ir_node *sync;
+ ir_node *fild;
+ ir_node *store_low;
+ ir_node *store_high;
- mem = get_irn_n(node, 2);
- new_mem = be_transform_node(mem);
- ptr = get_irn_n(node, 0);
- new_ptr = be_transform_node(ptr);
- noreg = ia32_new_NoReg_gp(cg);
- dbgi = get_irn_dbg_info(node);
-
- /* Store x87 -> MEM */
- res = new_rd_ia32_vfst(dbgi, irg, block, new_ptr, noreg, new_mem, new_val,
- get_ia32_ls_mode(node));
- set_ia32_frame_ent(res, get_ia32_frame_ent(node));
- set_ia32_use_frame(res);
- set_ia32_ls_mode(res, get_ia32_ls_mode(node));
- set_ia32_op_type(res, ia32_AddrModeD);
-
- /* Load MEM -> SSE */
- res = new_rd_ia32_xLoad(dbgi, irg, block, new_ptr, noreg, res,
- get_ia32_ls_mode(node));
- set_ia32_frame_ent(res, get_ia32_frame_ent(node));
- set_ia32_use_frame(res);
- set_ia32_op_type(res, ia32_AddrModeS);
- res = new_rd_Proj(dbgi, irg, block, res, mode_xmm, pn_ia32_xLoad_res);
+ if(!mode_is_signed(get_irn_mode(val_high))) {
+ panic("unsigned long long -> float not supported yet (%+F)", node);
+ }
- return res;
-}
+ /* do a store */
+ store_low = new_rd_ia32_Store(dbgi, irg, block, frame, noreg, nomem,
+ new_val_low);
+ store_high = new_rd_ia32_Store(dbgi, irg, block, frame, noreg, nomem,
+ new_val_high);
+ SET_IA32_ORIG_NODE(store_low, ia32_get_old_node_name(env_cg, node));
+ SET_IA32_ORIG_NODE(store_high, ia32_get_old_node_name(env_cg, node));
+
+ set_ia32_use_frame(store_low);
+ set_ia32_use_frame(store_high);
+ set_ia32_op_type(store_low, ia32_AddrModeD);
+ set_ia32_op_type(store_high, ia32_AddrModeD);
+ set_ia32_ls_mode(store_low, mode_Iu);
+ set_ia32_ls_mode(store_high, mode_Is);
+ add_ia32_am_offs_int(store_high, 4);
+
+ in[0] = store_low;
+ in[1] = store_high;
+ sync = new_rd_Sync(dbgi, irg, block, 2, in);
-/**
- * In case SSE Unit is used, the node is transformed into a xStore + vfld.
- */
-static ir_node *gen_ia32_l_SSEtoX87(ir_node *node) {
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *val = get_irn_n(node, 1);
- ir_node *new_val = be_transform_node(val);
- ia32_code_gen_t *cg = env_cg;
- ir_graph *irg = current_ir_graph;
- ir_node *res = NULL;
- ir_entity *fent = get_ia32_frame_ent(node);
- ir_mode *lsmode = get_ia32_ls_mode(node);
- int offs = 0;
- ir_node *noreg, *new_ptr, *new_mem;
- ir_node *ptr, *mem;
- dbg_info *dbgi;
-
- if (! USE_SSE2(cg)) {
- /* SSE unit is not used -> skip this node. */
- return new_val;
- }
+ /* do a fild */
+ fild = new_rd_ia32_vfild(dbgi, irg, block, frame, noreg, sync);
- ptr = get_irn_n(node, 0);
- new_ptr = be_transform_node(ptr);
- mem = get_irn_n(node, 2);
- new_mem = be_transform_node(mem);
- noreg = ia32_new_NoReg_gp(cg);
- dbgi = get_irn_dbg_info(node);
-
- /* Store SSE -> MEM */
- if (is_ia32_xLoad(skip_Proj(new_val))) {
- ir_node *ld = skip_Proj(new_val);
-
- /* we can vfld the value directly into the fpu */
- fent = get_ia32_frame_ent(ld);
- ptr = get_irn_n(ld, 0);
- offs = get_ia32_am_offs_int(ld);
- } else {
- res = new_rd_ia32_xStore(dbgi, irg, block, new_ptr, noreg, new_mem,
- new_val);
- set_ia32_frame_ent(res, fent);
- set_ia32_use_frame(res);
- set_ia32_ls_mode(res, lsmode);
- set_ia32_op_type(res, ia32_AddrModeD);
- mem = res;
- }
+ set_ia32_use_frame(fild);
+ set_ia32_op_type(fild, ia32_AddrModeS);
+ set_ia32_ls_mode(fild, mode_Ls);
- /* Load MEM -> x87 */
- res = new_rd_ia32_vfld(dbgi, irg, block, new_ptr, noreg, new_mem, lsmode);
- set_ia32_frame_ent(res, fent);
- set_ia32_use_frame(res);
- add_ia32_am_offs_int(res, offs);
- set_ia32_op_type(res, ia32_AddrModeS);
- res = new_rd_Proj(dbgi, irg, block, res, mode_vfp, pn_ia32_vfld_res);
+ SET_IA32_ORIG_NODE(fild, ia32_get_old_node_name(env_cg, node));
- return res;
+ return new_r_Proj(irg, block, fild, mode_vfp, pn_ia32_vfild_res);
}
-/*********************************************************
- * _ _ _
- * (_) | | (_)
- * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
- * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
- * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
- * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
- *
- *********************************************************/
+static ir_node *gen_ia32_l_FloattoLL(ir_node *node) {
+ (void) node;
+ panic("LLtoFloat NIY");
+}
/**
* the BAD transformer.
pn_ia32_xLoad_M);
}
}
- if (USE_SSE2(env_cg) && proj >= pn_be_Call_first_res
- && proj < (pn_be_Call_first_res + n_res) && mode_is_float(mode)
- && USE_SSE2(env_cg)) {
+ if (ia32_cg_config.use_sse2 && proj >= pn_be_Call_first_res
+ && proj < (pn_be_Call_first_res + n_res) && mode_is_float(mode)) {
ir_node *fstp;
ir_node *frame = get_irg_frame(irg);
ir_node *noreg = ia32_new_NoReg_gp(env_cg);
*/
static ir_node *gen_Proj_Cmp(ir_node *node)
{
- (void) node;
- panic("not all mode_b nodes are lowered");
-
-#if 0
- /* normally Cmps are processed when looking at Cond nodes, but this case
- * can happen in complicated Psi conditions */
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = get_nodes_block(node);
- ir_node *new_block = be_transform_node(block);
- ir_node *cmp = get_Proj_pred(node);
- ir_node *new_cmp = be_transform_node(cmp);
- long pnc = get_Proj_proj(node);
- ir_node *res;
-
- res = create_set_32bit(dbgi, new_block, new_cmp, pnc, node, 0);
-
- return res;
-#endif
+ /* this probably means not all mode_b nodes were lowered... */
+ panic("trying to directly transform Proj_Cmp %+F (mode_b not lowered?)",
+ node);
}
/**
GEN(ia32_l_Load);
GEN(ia32_l_vfist);
GEN(ia32_l_Store);
- GEN(ia32_l_X87toSSE);
- GEN(ia32_l_SSEtoX87);
+ GEN(ia32_l_LLtoFloat);
+ GEN(ia32_l_FloattoLL);
GEN(Const);
GEN(SymConst);
void ia32_transform_graph(ia32_code_gen_t *cg) {
int cse_last;
ir_graph *irg = cg->irg;
- int opt_arch = cg->isa->opt_arch;
- int arch = cg->isa->arch;
-
- /* TODO: look at cpu and fill transform config in with that... */
- transform_config.use_incdec = 1;
- transform_config.use_sse2 = 0;
- transform_config.use_ffreep = ARCH_ATHLON(opt_arch);
- transform_config.use_ftst = 0;
- transform_config.use_femms = ARCH_ATHLON(opt_arch) && ARCH_MMX(arch) && ARCH_AMD(arch);
- transform_config.use_fucomi = 1;
- transform_config.use_cmov = IS_P6_ARCH(arch);
register_transformers();
env_cg = cg;
initial_fpcw = NULL;
+BE_TIMER_PUSH(t_heights);
heights = heights_new(irg);
+BE_TIMER_POP(t_heights);
ia32_calculate_non_address_mode_nodes(cg->birg);
/* the transform phase is not safe for CSE (yet) because several nodes get