#include "ia32_x87.h"
#include "ia32_dbg_stat.h"
#include "ia32_finish.h"
+#include "ia32_util.h"
#define DEBUG_MODULE "firm.be.ia32.isa"
USE_SSE2(cg) ? &ia32_xmm_regs[REG_XMM_NOREG] : &ia32_vfp_regs[REG_VFP_NOREG]);
}
-/* returns the first Proj with given mode from mode_T node */
-static ir_node *get_proj_for_mode(ir_node *node, ir_mode *mode) {
- const ir_edge_t *edge;
-
- assert(get_irn_mode(node) == mode_T && "Need mode_T node.");
-
- foreach_out_edge(node, edge) {
- ir_node *proj = get_edge_src_irn(edge);
- if (get_irn_mode(proj) == mode)
- return proj;
- }
-
- return NULL;
-}
-
/**************************************************
* _ _ _ __
* | | | (_)/ _|
ia32_abi_env_t *env = self;
if (!env->flags.try_omit_fp) {
- int reg_size = get_mode_size_bytes(env->isa->bp->reg_class->mode);
ir_node *bl = get_irg_start_block(env->irg);
ir_node *curr_sp = be_abi_reg_map_get(reg_map, env->isa->sp);
ir_node *curr_bp = be_abi_reg_map_get(reg_map, env->isa->bp);
else {
const ia32_isa_t *isa = (ia32_isa_t *)env->isa;
ir_mode *mode_bp = env->isa->bp->reg_class->mode;
- int reg_size = get_mode_size_bytes(env->isa->bp->reg_class->mode);
/* gcc always emits a leave at the end of a routine */
if (1 || ARCH_AMD(isa->opt_arch)) {
static int ia32_get_op_estimated_cost(const void *self, const ir_node *irn)
{
int cost;
+
+ if(is_Proj(irn))
+ return 0;
+
switch (get_ia32_irn_opcode(irn)) {
case iro_ia32_xDiv:
case iro_ia32_DivMod:
}
else {
/* normal add: inverse == sub */
- ir_node *proj = get_irn_out_edge_first(irn)->src;
- assert(proj && is_Proj(proj));
+ ir_node *proj = ia32_get_res_proj(irn);
+ assert(proj);
inverse->nodes[0] = new_rd_ia32_Sub(NULL, irg, block, noreg, noreg, proj, get_irn_n(irn, i ^ 1), nomem);
pnc = pn_ia32_Sub_res;
}
else {
/* normal sub */
- ir_node *proj = get_irn_out_edge_first(irn)->src;
- assert(proj && is_Proj(proj));
+ ir_node *proj = ia32_get_res_proj(irn);
+ assert(proj);
if (i == 2) {
inverse->nodes[0] = new_rd_ia32_Add(NULL, irg, block, noreg, noreg, proj, get_irn_n(irn, 3), nomem);
inverse->costs += 1;
}
break;
- case iro_ia32_Not:
- inverse->nodes[0] = new_rd_ia32_Not(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), nomem);
+ case iro_ia32_Not: {
+ ir_node *proj = ia32_get_res_proj(irn);
+ assert(proj);
+
+ inverse->nodes[0] = new_rd_ia32_Not(NULL, irg, block, noreg, noreg, proj, nomem);
pnc = pn_ia32_Not_res;
inverse->costs += 1;
break;
- case iro_ia32_Minus:
- inverse->nodes[0] = new_rd_ia32_Minus(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), nomem);
- pnc = pn_ia32_Minus_res;
+ }
+ case iro_ia32_Minus: {
+ ir_node *proj = ia32_get_res_proj(irn);
+ assert(proj);
+
+ inverse->nodes[0] = new_rd_ia32_Minus(NULL, irg, block, noreg, noreg, proj, nomem);
+ pnc = pn_ia32_Minus_res;
inverse->costs += 1;
break;
+ }
default:
/* inverse operation not supported */
return NULL;
return inverse;
}
+/**
+ * Check if irn can load it's operand at position i from memory (source addressmode).
+ * @param self Pointer to irn ops itself
+ * @param irn The irn to be checked
+ * @param i The operands position
+ * @return Non-Zero if operand can be loaded
+ */
+static int ia32_possible_memory_operand(const void *self, const ir_node *irn, unsigned int i) {
+ if (! is_ia32_irn(irn) || /* must be an ia32 irn */
+ get_irn_arity(irn) != 5 || /* must be a binary operation */
+ get_ia32_op_type(irn) != ia32_Normal || /* must not already be a addressmode irn */
+ ! (get_ia32_am_support(irn) & ia32_am_Source) || /* must be capable of source addressmode */
+ (i != 2 && i != 3) || /* a "real" operand position must be requested */
+ (i == 2 && ! is_ia32_commutative(irn)) || /* if first operand requested irn must be commutative */
+ is_ia32_use_frame(irn)) /* must not already use frame */
+ return 0;
+
+ return 1;
+}
+
+static void ia32_perform_memory_operand(const void *self, ir_node *irn, ir_node *reload, unsigned int i) {
+ assert(ia32_possible_memory_operand(self, irn, i) && "Cannot perform memory operand change");
+ assert(get_nodes_block(reload) == get_nodes_block(irn) && "Reload must be in same block as irn.");
+
+ if (get_irn_n_edges(reload) > 1)
+ return;
+
+ if (i == 2) {
+ ir_node *tmp = get_irn_n(irn, 3);
+ set_irn_n(irn, 3, get_irn_n(irn, 2));
+ set_irn_n(irn, 2, tmp);
+ }
+
+ set_ia32_am_support(irn, ia32_am_Source);
+ set_ia32_op_type(irn, ia32_AddrModeS);
+ set_ia32_am_flavour(irn, ia32_B);
+ set_ia32_ls_mode(irn, get_irn_mode(reload));
+ set_ia32_frame_ent(irn, be_get_frame_entity(reload));
+ set_ia32_use_frame(irn);
+
+ set_irn_n(irn, 0, be_get_Reload_frame(reload));
+ set_irn_n(irn, 4, be_get_Reload_mem(reload));
+
+ /*
+ Input at position one is index register, which is NoReg.
+ We would need cg object to get a real noreg, but we cannot
+ access it from here.
+ */
+ set_irn_n(irn, 3, get_irn_n(irn, 1));
+
+ DBG_OPT_AM_S(reload, irn);
+}
+
static const be_abi_callbacks_t ia32_abi_callbacks = {
ia32_abi_init,
free,
ia32_get_frame_entity,
ia32_set_stack_bias,
ia32_get_inverse,
- ia32_get_op_estimated_cost
+ ia32_get_op_estimated_cost,
+ ia32_possible_memory_operand,
+ ia32_perform_memory_operand,
};
ia32_irn_ops_t ia32_irn_ops = {
/* tuple node has one user which is not the mem proj-> ok */
if (mode == mode_T && get_irn_n_edges(irn) == 1) {
- mem_proj = get_proj_for_mode(irn, mode_M);
+ mem_proj = ia32_get_proj_for_mode(irn, mode_M);
if (! mem_proj)
return;
}
transform_to_Load(&tenv);
}
else if (be_is_Spill(node)) {
+ ir_node *spillval = get_irn_n(node, be_pos_Spill_val);
/* we always spill the whole register */
tenv.dbg = get_irn_dbg_info(node);
tenv.irn = node;
- tenv.mode = fix_spill_mode(cg, get_irn_mode(be_get_Spill_context(node)));
+ tenv.mode = fix_spill_mode(cg, get_irn_mode(spillval));
transform_to_Store(&tenv);
}
}
*/
static void ia32_after_ra(void *self) {
ia32_code_gen_t *cg = self;
+
irg_block_walk_graph(cg->irg, NULL, ia32_after_ra_walker, self);
/* if we do x87 code generation, rewrite all the virtual instructions and registers */
* Return the register class for index i.
*/
static const arch_register_class_t *ia32_get_reg_class(const void *self, int i) {
- const ia32_isa_t *isa = self;
assert(i >= 0 && i < 3 && "Invalid ia32 register class requested.");
if (i == 0)
return &ia32_reg_classes[CLASS_ia32_gp];