ia32_address_t addr;
ir_mode *ls_mode;
ir_node *mem_proj;
+ ir_node *am_node;
ia32_op_type_t op_type;
ir_node *new_op1;
ir_node *new_op2;
am->pinned = get_irn_pinned(load);
am->ls_mode = get_Load_mode(load);
am->mem_proj = be_get_Proj_for_pn(load, pn_Load_M);
+ am->am_node = node;
/* construct load address */
ia32_create_address_mode(addr, ptr, /*force=*/0);
ir_node *src_block = get_nodes_block(node);
ir_node *op1 = get_irn_n(node, n_ia32_l_binop_left);
ir_node *op2 = get_irn_n(node, n_ia32_l_binop_right);
+ ir_node *eflags = get_irn_n(node, n_ia32_l_binop_eflags);
dbg_info *dbgi;
- ir_node *block, *new_node, *eflags, *new_eflags;
+ ir_node *block, *new_node, *new_eflags;
ia32_address_mode_t am;
ia32_address_t *addr = &am.addr;
- match_arguments(&am, src_block, op1, op2, NULL, flags);
+ match_arguments(&am, src_block, op1, op2, eflags, flags);
dbgi = get_irn_dbg_info(node);
block = be_transform_node(src_block);
- eflags = get_irn_n(node, n_ia32_l_binop_eflags);
new_eflags = be_transform_node(eflags);
new_node = func(dbgi, current_ir_graph, block, addr->base, addr->index,
addr->mem, am.new_op1, am.new_op2, new_eflags);
{
ir_node *load;
- if(!is_Proj(node))
+ if (!is_Proj(node))
return 0;
/* we only use address mode if we're the only user of the load */
- if(get_irn_n_edges(node) > 1)
+ if (get_irn_n_edges(node) > 1)
return 0;
load = get_Proj_pred(node);
- if(!is_Load(load))
+ if (!is_Load(load))
return 0;
- if(get_nodes_block(load) != block)
+ if (get_nodes_block(load) != block)
return 0;
- /* Store should be attached to the load */
- if(!is_Proj(mem) || get_Proj_pred(mem) != load)
- return 0;
/* store should have the same pointer as the load */
- if(get_Load_ptr(load) != ptr)
+ if (get_Load_ptr(load) != ptr)
return 0;
/* don't do AM if other node inputs depend on the load (via mem-proj) */
- if(other != NULL && get_nodes_block(other) == block
- && heights_reachable_in_block(heights, other, load))
+ if (other != NULL &&
+ get_nodes_block(other) == block &&
+ heights_reachable_in_block(heights, other, load)) {
return 0;
+ }
+
+ if (is_Sync(mem)) {
+ int i;
+
+ for (i = get_Sync_n_preds(mem) - 1; i >= 0; --i) {
+ ir_node *const pred = get_Sync_pred(mem, i);
+
+ if (is_Proj(pred) && get_Proj_pred(pred) == load)
+ continue;
+
+ if (get_nodes_block(pred) == block &&
+ heights_reachable_in_block(heights, pred, load)) {
+ return 0;
+ }
+ }
+ } else {
+ /* Store should be attached to the load */
+ if (!is_Proj(mem) || get_Proj_pred(mem) != load)
+ return 0;
+ }
return 1;
}
ir_node *noreg_gp = ia32_new_NoReg_gp(env_cg);
ir_graph *irg = current_ir_graph;
dbg_info *dbgi;
+ ir_node *new_mem;
ir_node *new_node;
ir_node *new_op;
ir_node *mem_proj;
if(addr->mem == NULL)
addr->mem = new_NoMem();
- dbgi = get_irn_dbg_info(node);
- block = be_transform_node(src_block);
+ dbgi = get_irn_dbg_info(node);
+ block = be_transform_node(src_block);
+ new_mem = transform_AM_mem(irg, block, am.am_node, mem, addr->mem);
+
if(get_mode_size_bits(mode) == 8) {
new_node = func8bit(dbgi, irg, block, addr->base, addr->index,
- addr->mem, new_op);
+ new_mem, new_op);
} else {
- new_node = func(dbgi, irg, block, addr->base, addr->index, addr->mem,
+ new_node = func(dbgi, irg, block, addr->base, addr->index, new_mem,
new_op);
}
set_address(new_node, addr);
ir_node *ptr, ir_mode *mode,
construct_unop_dest_func *func)
{
- ir_graph *irg = current_ir_graph;
- ir_node *src_block = get_nodes_block(node);
- ir_node *block;
+ ir_graph *irg = current_ir_graph;
+ ir_node *src_block = get_nodes_block(node);
+ ir_node *block;
dbg_info *dbgi;
- ir_node *new_node;
- ir_node *mem_proj;
+ ir_node *new_mem;
+ ir_node *new_node;
+ ir_node *mem_proj;
ia32_address_mode_t am;
ia32_address_t *addr = &am.addr;
memset(&am, 0, sizeof(am));
dbgi = get_irn_dbg_info(node);
block = be_transform_node(src_block);
- new_node = func(dbgi, irg, block, addr->base, addr->index, addr->mem);
+ new_mem = transform_AM_mem(irg, block, am.am_node, mem, addr->mem);
+ new_node = func(dbgi, irg, block, addr->base, addr->index, new_mem);
set_address(new_node, addr);
set_ia32_op_type(new_node, ia32_AddrModeD);
set_ia32_ls_mode(new_node, mode);
if(is_Conv(val)) {
ir_node *conv_op = get_Conv_op(val);
ir_mode *pred_mode = get_irn_mode(conv_op);
+ if (!ia32_mode_needs_gp_reg(pred_mode))
+ break;
if(pred_mode == mode_b || bits <= get_mode_size_bits(pred_mode)) {
val = conv_op;
continue;
case iro_Sub:
op1 = get_Sub_left(val);
op2 = get_Sub_right(val);
- if(is_Const(op2)) {
- ir_fprintf(stderr, "Optimisation warning: not-normalize sub ,C"
- "found\n");
+ if (is_Const(op2)) {
+ ir_fprintf(stderr, "Optimisation warning: not-normalized sub ,C found\n");
}
new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
new_rd_ia32_SubMem, new_rd_ia32_SubMem8Bit,
*
* @return the created ia32 Store node
*/
-static ir_node *gen_float_const_Store(ir_node *node, ir_node *cns) {
- ir_mode *mode = get_irn_mode(cns);
- int size = get_mode_size_bits(mode);
- tarval *tv = get_Const_tarval(cns);
- ir_node *block = get_nodes_block(node);
- ir_node *new_block = be_transform_node(block);
- ir_node *ptr = get_Store_ptr(node);
- ir_node *mem = get_Store_mem(node);
- ir_graph *irg = current_ir_graph;
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *noreg = ia32_new_NoReg_gp(env_cg);
- int ofs = 4;
- ir_node *new_node;
- ia32_address_t addr;
-
- unsigned val = get_tarval_sub_bits(tv, 0) |
- (get_tarval_sub_bits(tv, 1) << 8) |
- (get_tarval_sub_bits(tv, 2) << 16) |
- (get_tarval_sub_bits(tv, 3) << 24);
- ir_node *imm = create_Immediate(NULL, 0, val);
-
- /* construct store address */
- memset(&addr, 0, sizeof(addr));
- ia32_create_address_mode(&addr, ptr, /*force=*/0);
-
- if (addr.base == NULL) {
- addr.base = noreg;
- } else {
- addr.base = be_transform_node(addr.base);
- }
-
- if (addr.index == NULL) {
- addr.index = noreg;
- } else {
- addr.index = be_transform_node(addr.index);
- }
- addr.mem = be_transform_node(mem);
-
- new_node = new_rd_ia32_Store(dbgi, irg, new_block, addr.base,
- addr.index, addr.mem, imm);
+static ir_node *gen_float_const_Store(ir_node *node, ir_node *cns)
+{
+ ir_mode *mode = get_irn_mode(cns);
+ unsigned size = get_mode_size_bytes(mode);
+ tarval *tv = get_Const_tarval(cns);
+ ir_node *block = get_nodes_block(node);
+ ir_node *new_block = be_transform_node(block);
+ ir_node *ptr = get_Store_ptr(node);
+ ir_node *mem = get_Store_mem(node);
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ int ofs = 0;
+ size_t i = 0;
+ ir_node *ins[4];
+ ia32_address_t addr;
- set_irn_pinned(new_node, get_irn_pinned(node));
- set_ia32_op_type(new_node, ia32_AddrModeD);
- set_ia32_ls_mode(new_node, mode_Iu);
+ assert(size % 4 == 0);
+ assert(size <= 16);
- set_address(new_node, &addr);
+ build_address_ptr(&addr, ptr, mem);
- /** add more stores if needed */
- while (size > 32) {
- unsigned val = get_tarval_sub_bits(tv, ofs) |
- (get_tarval_sub_bits(tv, ofs + 1) << 8) |
+ do {
+ unsigned val =
+ get_tarval_sub_bits(tv, ofs) |
+ (get_tarval_sub_bits(tv, ofs + 1) << 8) |
(get_tarval_sub_bits(tv, ofs + 2) << 16) |
(get_tarval_sub_bits(tv, ofs + 3) << 24);
ir_node *imm = create_Immediate(NULL, 0, val);
- addr.offset += 4;
- addr.mem = new_node;
-
- new_node = new_rd_ia32_Store(dbgi, irg, new_block, addr.base,
+ ir_node *new_node = new_rd_ia32_Store(dbgi, irg, new_block, addr.base,
addr.index, addr.mem, imm);
set_irn_pinned(new_node, get_irn_pinned(node));
set_ia32_op_type(new_node, ia32_AddrModeD);
set_ia32_ls_mode(new_node, mode_Iu);
-
set_address(new_node, &addr);
- size -= 32;
- ofs += 4;
- }
+ SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
- SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
- return new_node;
+ ins[i++] = new_node;
+
+ size -= 4;
+ ofs += 4;
+ addr.offset += 4;
+ } while (size != 0);
+
+ return i == 1 ? ins[0] : new_rd_Sync(dbgi, irg, new_block, i, ins);
}
/**
ir_mode *mode = get_irn_mode(val);
if (mode_is_float(mode) && is_Const(val)) {
- int transform = 1;
+ int transform;
/* we are storing a floating point constant */
if (ia32_cg_config.use_sse2) {
return new_node;
}
-/**
- * Transforms a CopyB node.
- *
- * @return The transformed node.
- */
-static ir_node *gen_CopyB(ir_node *node) {
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *src = get_CopyB_src(node);
- ir_node *new_src = be_transform_node(src);
- ir_node *dst = get_CopyB_dst(node);
- ir_node *new_dst = be_transform_node(dst);
- ir_node *mem = get_CopyB_mem(node);
- ir_node *new_mem = be_transform_node(mem);
- ir_node *res = NULL;
- ir_graph *irg = current_ir_graph;
- dbg_info *dbgi = get_irn_dbg_info(node);
- int size = get_type_size_bytes(get_CopyB_type(node));
- int rem;
-
- /* If we have to copy more than 32 bytes, we use REP MOVSx and */
- /* then we need the size explicitly in ECX. */
- if (size >= 32 * 4) {
- rem = size & 0x3; /* size % 4 */
- size >>= 2;
-
- res = new_rd_ia32_Const(dbgi, irg, block, NULL, 0, size);
- add_irn_dep(res, get_irg_frame(irg));
-
- res = new_rd_ia32_CopyB(dbgi, irg, block, new_dst, new_src, res, new_mem, rem);
- } else {
- if(size == 0) {
- ir_fprintf(stderr, "Optimisation warning copyb %+F with size <4\n",
- node);
- }
- res = new_rd_ia32_CopyB_i(dbgi, irg, block, new_dst, new_src, new_mem, size);
- }
-
- SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
-
- return res;
-}
-
static ir_node *gen_be_Copy(ir_node *node)
{
ir_node *new_node = be_duplicate_node(node);
}
/**
- * helper function: checks wether all Cmp projs are Lg or Eq which is needed
+ * 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)
switch (get_mode_size_bits(tgt_mode)) {
case 32: float_mantissa = 23 + 1; break; // + 1 for implicit 1
case 64: float_mantissa = 52 + 1; break;
- case 80: float_mantissa = 64 + 1; break;
+ case 80:
+ case 96: float_mantissa = 64; break;
default: float_mantissa = 0; break;
}
if (float_mantissa < int_mantissa) {
}
-typedef ir_node *construct_load_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
- ir_node *mem);
-
-typedef ir_node *construct_store_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
- ir_node *val, ir_node *mem);
-
-/**
- * Transforms a lowered Load into a "real" one.
- */
-static ir_node *gen_lowered_Load(ir_node *node, construct_load_func func)
-{
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *ptr = get_irn_n(node, 0);
- ir_node *new_ptr = be_transform_node(ptr);
- ir_node *mem = get_irn_n(node, 1);
- ir_node *new_mem = be_transform_node(mem);
- ir_graph *irg = current_ir_graph;
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_mode *mode = get_ia32_ls_mode(node);
- ir_node *noreg = ia32_new_NoReg_gp(env_cg);
- ir_node *new_op;
-
- new_op = func(dbgi, irg, block, new_ptr, noreg, new_mem);
-
- set_ia32_op_type(new_op, ia32_AddrModeS);
- set_ia32_am_offs_int(new_op, get_ia32_am_offs_int(node));
- set_ia32_am_scale(new_op, get_ia32_am_scale(node));
- set_ia32_am_sc(new_op, get_ia32_am_sc(node));
- if (is_ia32_am_sc_sign(node))
- set_ia32_am_sc_sign(new_op);
- set_ia32_ls_mode(new_op, mode);
- if (is_ia32_use_frame(node)) {
- set_ia32_frame_ent(new_op, get_ia32_frame_ent(node));
- set_ia32_use_frame(new_op);
- }
-
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
-
- return new_op;
-}
-
-/**
- * Transforms a lowered Store into a "real" one.
- */
-static ir_node *gen_lowered_Store(ir_node *node, construct_store_func func)
-{
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *ptr = get_irn_n(node, 0);
- ir_node *new_ptr = be_transform_node(ptr);
- ir_node *val = get_irn_n(node, 1);
- ir_node *new_val = be_transform_node(val);
- ir_node *mem = get_irn_n(node, 2);
- ir_node *new_mem = be_transform_node(mem);
- ir_graph *irg = current_ir_graph;
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *noreg = ia32_new_NoReg_gp(env_cg);
- ir_mode *mode = get_ia32_ls_mode(node);
- ir_node *new_op;
- long am_offs;
-
- new_op = func(dbgi, irg, block, new_ptr, noreg, new_val, new_mem);
-
- am_offs = get_ia32_am_offs_int(node);
- add_ia32_am_offs_int(new_op, am_offs);
-
- set_ia32_op_type(new_op, ia32_AddrModeD);
- set_ia32_ls_mode(new_op, mode);
- set_ia32_frame_ent(new_op, get_ia32_frame_ent(node));
- set_ia32_use_frame(new_op);
-
- SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
-
- return new_op;
-}
-
static ir_node *gen_ia32_l_ShlDep(ir_node *node)
{
ir_node *left = get_irn_n(node, n_ia32_l_ShlDep_val);
match_mode_neutral);
}
-/**
- * Transforms an ia32_l_vfild into a "real" ia32_vfild node
- *
- * @param node The node to transform
- * @return the created ia32 vfild node
- */
-static ir_node *gen_ia32_l_vfild(ir_node *node) {
- return gen_lowered_Load(node, new_rd_ia32_vfild);
-}
-
-/**
- * Transforms an ia32_l_Load into a "real" ia32_Load node
- *
- * @param node The node to transform
- * @return the created ia32 Load node
- */
-static ir_node *gen_ia32_l_Load(ir_node *node) {
- return gen_lowered_Load(node, new_rd_ia32_Load);
-}
-
-/**
- * Transforms an ia32_l_Store into a "real" ia32_Store node
- *
- * @param node The node to transform
- * @return the created ia32 Store node
- */
-static ir_node *gen_ia32_l_Store(ir_node *node) {
- return gen_lowered_Store(node, new_rd_ia32_Store);
-}
-
-/**
- * Transforms a l_vfist into a "real" vfist node.
- *
- * @param node The node to transform
- * @return the created ia32 vfist node
- */
-static ir_node *gen_ia32_l_vfist(ir_node *node) {
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *ptr = get_irn_n(node, 0);
- ir_node *new_ptr = be_transform_node(ptr);
- ir_node *val = get_irn_n(node, 1);
- ir_node *new_val = be_transform_node(val);
- ir_node *mem = get_irn_n(node, 2);
- ir_node *new_mem = be_transform_node(mem);
- ir_graph *irg = current_ir_graph;
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *noreg = ia32_new_NoReg_gp(env_cg);
- ir_mode *mode = get_ia32_ls_mode(node);
- ir_node *memres, *fist;
- long am_offs;
-
- memres = gen_vfist(dbgi, irg, block, new_ptr, noreg, new_mem, new_val, &fist);
- am_offs = get_ia32_am_offs_int(node);
- add_ia32_am_offs_int(fist, am_offs);
-
- set_ia32_op_type(fist, ia32_AddrModeD);
- set_ia32_ls_mode(fist, mode);
- set_ia32_frame_ent(fist, get_ia32_frame_ent(node));
- set_ia32_use_frame(fist);
-
- SET_IA32_ORIG_NODE(fist, ia32_get_old_node_name(env_cg, node));
-
- return memres;
-}
-
/**
* Transforms a l_MulS into a "real" MulS node.
*
/* the shift amount can be any mode that is bigger than 5 bits, since all
* other bits are ignored anyway */
- while (is_Conv(count) && get_irn_n_edges(count) == 1) {
+ while (is_Conv(count) &&
+ get_irn_n_edges(count) == 1 &&
+ mode_is_int(get_irn_mode(count))) {
assert(get_mode_size_bits(get_irn_mode(count)) >= 5);
count = get_Conv_op(count);
}
* the BAD transformer.
*/
static ir_node *bad_transform(ir_node *node) {
- panic("No transform function for %+F available.\n", node);
+ panic("No transform function for %+F available.", node);
return NULL;
}
return new_rd_Unknown(irg, mode);
}
-/**
- * Transform the Thread Local Storage Proj.
- */
-static ir_node *gen_Proj_tls(ir_node *node) {
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_graph *irg = current_ir_graph;
- dbg_info *dbgi = NULL;
- ir_node *res = new_rd_ia32_LdTls(dbgi, irg, block, mode_Iu);
-
- return res;
-}
-
static ir_node *gen_be_Call(ir_node *node) {
ir_node *res = be_duplicate_node(node);
+ ir_type *call_tp;
+
be_node_add_flags(res, -1, arch_irn_flags_modify_flags);
+ /* Run the x87 simulator if the call returns a float value */
+ call_tp = be_Call_get_type(node);
+ if (get_method_n_ress(call_tp) > 0) {
+ ir_type *const res_type = get_method_res_type(call_tp, 0);
+ ir_mode *const res_mode = get_type_mode(res_type);
+
+ if (res_mode != NULL && mode_is_float(res_mode)) {
+ env_cg->do_x87_sim = 1;
+ }
+ }
+
return res;
}
GEN(ia32_l_ShrD);
GEN(ia32_l_Sub);
GEN(ia32_l_Sbb);
- GEN(ia32_l_vfild);
- GEN(ia32_l_Load);
- GEN(ia32_l_vfist);
- GEN(ia32_l_Store);
GEN(ia32_l_LLtoFloat);
GEN(ia32_l_FloattoLL);
}
/**
- * Walker, checks if all ia32 nodes producing more than one result have
- * its Projs, otherwise creates new Projs and keep them using a be_Keep node.
+ * Walker, checks if all ia32 nodes producing more than one result have their
+ * Projs, otherwise creates new Projs and keeps them using a be_Keep node.
*/
static void add_missing_keep_walker(ir_node *node, void *data)
{