Remove unused operand specifications.
[libfirm] / ir / be / ia32 / ia32_transform.c
index 8144253..48f4012 100644 (file)
@@ -447,8 +447,7 @@ const char *ia32_get_old_node_name(ia32_code_gen_t *cg, ir_node *irn) {
 }
 #endif /* NDEBUG */
 
-static int use_source_address_mode(ir_node *block, ir_node *node,
-                                   ir_node *other)
+int use_source_address_mode(ir_node *block, ir_node *node, ir_node *other)
 {
        ir_mode *mode;
        ir_node *load;
@@ -553,7 +552,8 @@ typedef enum {
        match_commutative       = 1 << 0,
        match_am_and_immediates = 1 << 1,
        match_no_am             = 1 << 2,
-       match_8_16_bit_am       = 1 << 3
+       match_8_16_bit_am       = 1 << 3,
+       match_no_immediate      = 1 << 4
 } match_flags_t;
 
 static void match_arguments(ia32_address_mode_t *am, ir_node *block,
@@ -566,20 +566,27 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block,
        int             use_am;
        int             commutative;
        int             use_am_and_immediates;
+       int             use_immediate;
 
        memset(am, 0, sizeof(am[0]));
 
        commutative           = (flags & match_commutative) != 0;
        use_am_and_immediates = (flags & match_am_and_immediates) != 0;
        use_am                = ! (flags & match_no_am);
+       use_immediate         = !(flags & match_no_immediate);
+
+       assert(op2 != NULL);
+       assert(!commutative || op1 != NULL);
+
        if(!(flags & match_8_16_bit_am)
+                       && op1 != NULL
                        && get_mode_size_bits(get_irn_mode(op1)) < 32)
                use_am = 0;
 
-       new_op2 = try_create_Immediate(op2, 0);
+       new_op2 = (use_immediate ? try_create_Immediate(op2, 0) : NULL);
        if(new_op2 == NULL && use_am && use_source_address_mode(block, op2, op1)) {
                build_address(am, op2);
-               new_op1     = be_transform_node(op1);
+               new_op1     = (op1 == NULL ? NULL : be_transform_node(op1));
                new_op2     = noreg_gp;
                am->op_type = ia32_AddrModeS;
        } else if(commutative && (new_op2 == NULL || use_am_and_immediates) &&
@@ -594,7 +601,7 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block,
                }
                am->op_type = ia32_AddrModeS;
        } else {
-               new_op1 = be_transform_node(op1);
+               new_op1 = (op1 == NULL ? NULL : be_transform_node(op1));
                if(new_op2 == NULL)
                        new_op2 = be_transform_node(op2);
                am->op_type = ia32_Normal;
@@ -1620,8 +1627,8 @@ static ir_node *gen_Load(ir_node *node) {
 
                /* create a conv node with address mode for smaller modes */
                if(get_mode_size_bits(mode) < 32) {
-                       new_op = new_rd_ia32_Conv_I2I(dbgi, irg, block, base, index, new_mem,
-                                                     noreg, mode);
+                       new_op = new_rd_ia32_Conv_I2I(dbgi, irg, block, base, index,
+                                                     new_mem, noreg, mode);
                } else {
                        new_op = new_rd_ia32_Load(dbgi, irg, block, base, index, new_mem);
                }
@@ -2145,7 +2152,8 @@ static ir_node *try_create_Test(ir_node *node)
        if(!is_Const_0(cmp_right))
                return NULL;
 
-       if(is_And(cmp_left) && can_fold_test_and(node)) {
+       if(is_And(cmp_left) && get_irn_n_edges(cmp_left) == 1 &&
+                       can_fold_test_and(node)) {
                ir_node *and_left  = get_And_left(cmp_left);
                ir_node *and_right = get_And_right(cmp_left);
 
@@ -2455,18 +2463,47 @@ static ir_node *gen_x87_strict_conv(ir_mode *tgt_mode, ir_node *node)
  * Create a conversion from general purpose to x87 register
  */
 static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode) {
-       ir_node   *block  = be_transform_node(get_nodes_block(node));
-       ir_node   *op     = get_Conv_op(node);
-       ir_node   *new_op = be_transform_node(op);
-       ir_graph  *irg    = current_ir_graph;
-       dbg_info  *dbgi   = get_irn_dbg_info(node);
-       ir_node   *noreg  = ia32_new_NoReg_gp(env_cg);
-       ir_node   *nomem  = new_NoMem();
-       ir_mode   *mode   = get_irn_mode(op);
-       ir_mode   *store_mode;
-       ir_node   *fild, *store;
-       ir_node   *res;
-       int        src_bits;
+       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  *op         = get_Conv_op(node);
+       ir_node  *new_op;
+       ir_node  *noreg;
+       ir_node  *nomem;
+       ir_mode  *mode;
+       ir_mode  *store_mode;
+       ir_node  *fild;
+       ir_node  *store;
+       ir_node  *res;
+       int       src_bits;
+
+       /* fild can use source AM if the operand is a signed 32bit integer */
+       if (src_mode == mode_Is) {
+               ia32_address_mode_t am;
+
+               match_arguments(&am, src_block, NULL, op, match_no_immediate);
+               if (am.op_type == ia32_AddrModeS) {
+                       ia32_address_t *addr = &am.addr;
+
+                       fild = new_rd_ia32_vfild(dbgi, irg, block, addr->base, addr->index, addr->mem);
+                       res  = new_r_Proj(irg, block, fild, mode_vfp, pn_ia32_vfild_res);
+
+                       set_am_attributes(fild, &am);
+                       SET_IA32_ORIG_NODE(fild, ia32_get_old_node_name(env_cg, node));
+
+                       fix_mem_proj(fild, &am);
+
+                       return res;
+               }
+               new_op = am.new_op2;
+       } else {
+               new_op = be_transform_node(op);
+       }
+
+       noreg  = ia32_new_NoReg_gp(env_cg);
+       nomem  = new_NoMem();
+       mode   = get_irn_mode(op);
 
        /* first convert to 32 bit signed if necessary */
        src_bits = get_mode_size_bits(src_mode);
@@ -2561,7 +2598,7 @@ static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode,
                new_op     = noreg;
                am.op_type = ia32_AddrModeS;
        } else {
-               new_op = be_transform_node(op);
+               new_op     = be_transform_node(op);
                am.op_type = ia32_Normal;
        }
        if(addr->base == NULL)
@@ -3027,10 +3064,12 @@ void parse_asm_constraint(int pos, constraint_t *constraint, const char *c)
                case 'y': /* we don't support mmx registers yet */
                case 'Z': /* not available in 32 bit mode */
                case 'e': /* not available in 32 bit mode */
-                       assert(0 && "asm constraint not supported");
+                       panic("unsupported asm constraint '%c' found in (%+F)",
+                             *c, current_ir_graph);
                        break;
                default:
-                       assert(0 && "unknown asm constraint found");
+                       panic("unknown asm constraint '%c' found in (%+F)", *c,
+                             current_ir_graph);
                        break;
                }
                ++c;
@@ -3051,7 +3090,8 @@ void parse_asm_constraint(int pos, constraint_t *constraint, const char *c)
                req->cls             = other_constr->cls;
                req->type            = arch_register_req_type_should_be_same;
                req->limited         = NULL;
-               req->other_same      = pos;
+               req->other_same[0]   = pos;
+               req->other_same[1]   = -1;
                req->other_different = -1;
 
                /* switch constraints. This is because in firm we have same_as
@@ -3788,32 +3828,47 @@ static ir_node *gen_ia32_l_IMul(ir_node *node) {
        return muls;
 }
 
-static ir_node *gen_ia32_Add64Bit(ir_node *node)
-{
-       ir_node  *a_l    = be_transform_node(get_irn_n(node, 0));
-       ir_node  *a_h    = be_transform_node(get_irn_n(node, 1));
-       ir_node  *b_l    = create_immediate_or_transform(get_irn_n(node, 2), 0);
-       ir_node  *b_h    = create_immediate_or_transform(get_irn_n(node, 3), 0);
-       ir_node  *block  = be_transform_node(get_nodes_block(node));
-       dbg_info *dbgi   = get_irn_dbg_info(node);
-       ir_graph *irg    = current_ir_graph;
-       ir_node  *new_op = new_rd_ia32_Add64Bit(dbgi, irg, block, a_l, a_h, b_l, b_h);
-       SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
-       return new_op;
+static ir_node *gen_ia32_l_Sub(ir_node *node) {
+       ir_node *left    = get_irn_n(node, n_ia32_l_Sub_left);
+       ir_node *right   = get_irn_n(node, n_ia32_l_Sub_right);
+       ir_node *lowered = gen_binop(node, left, right, new_rd_ia32_Sub, 0);
+
+       if(is_Proj(lowered)) {
+               lowered = get_Proj_pred(lowered);
+       } else {
+               assert(is_ia32_Sub(lowered));
+               set_irn_mode(lowered, mode_T);
+       }
+
+       return lowered;
 }
 
-static ir_node *gen_ia32_Sub64Bit(ir_node *node)
-{
-       ir_node  *a_l    = be_transform_node(get_irn_n(node, 0));
-       ir_node  *a_h    = be_transform_node(get_irn_n(node, 1));
-       ir_node  *b_l    = create_immediate_or_transform(get_irn_n(node, 2), 0);
-       ir_node  *b_h    = create_immediate_or_transform(get_irn_n(node, 3), 0);
-       ir_node  *block  = be_transform_node(get_nodes_block(node));
-       dbg_info *dbgi   = get_irn_dbg_info(node);
-       ir_graph *irg    = current_ir_graph;
-       ir_node  *new_op = new_rd_ia32_Sub64Bit(dbgi, irg, block, a_l, a_h, b_l, b_h);
-       SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
-       return new_op;
+static ir_node *gen_ia32_l_Sbb(ir_node *node) {
+       ir_node  *src_block = get_nodes_block(node);
+       ir_node  *block     = be_transform_node(src_block);
+       ir_node  *op1       = get_irn_n(node, n_ia32_l_Sbb_left);
+       ir_node  *op2       = get_irn_n(node, n_ia32_l_Sbb_right);
+       ir_node  *flags     = get_irn_n(node, n_ia32_l_Sbb_eflags);
+       ir_node  *new_flags = be_transform_node(flags);
+       ir_graph *irg       = current_ir_graph;
+       dbg_info *dbgi      = get_irn_dbg_info(node);
+       ir_node  *new_node;
+       ia32_address_mode_t  am;
+       ia32_address_t      *addr = &am.addr;
+
+       match_arguments(&am, src_block, op1, op2, match_commutative);
+
+       new_node = new_rd_ia32_Sbb(dbgi, irg, block, addr->base, addr->index,
+                                  addr->mem, am.new_op1, am.new_op2, new_flags);
+       set_am_attributes(new_node, &am);
+       /* we can't use source address mode anymore when using immediates */
+       if(is_ia32_Immediate(am.new_op1) || is_ia32_Immediate(am.new_op2))
+               set_ia32_am_support(new_node, ia32_am_None, ia32_am_arity_none);
+       SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
+
+       new_node = fix_mem_proj(new_node, &am);
+
+       return new_node;
 }
 
 /**
@@ -4499,8 +4554,6 @@ static void register_transformers(void)
        GEN(IJmp);
 
        /* transform ops from intrinsic lowering */
-       GEN(ia32_Add64Bit);
-       GEN(ia32_Sub64Bit);
        GEN(ia32_l_Add);
        GEN(ia32_l_Adc);
        GEN(ia32_l_Neg);
@@ -4512,6 +4565,8 @@ static void register_transformers(void)
        GEN(ia32_l_SarDep);
        GEN(ia32_l_ShlD);
        GEN(ia32_l_ShrD);
+       GEN(ia32_l_Sub);
+       GEN(ia32_l_Sbb);
        GEN(ia32_l_vfdiv);
        GEN(ia32_l_vfprem);
        GEN(ia32_l_vfmul);
@@ -4654,14 +4709,18 @@ void ia32_add_missing_keeps(ia32_code_gen_t *cg)
 
 /* do the transformation */
 void ia32_transform_graph(ia32_code_gen_t *cg) {
+       ir_graph *irg = cg->irg;
+
        register_transformers();
        env_cg       = cg;
        initial_fpcw = NULL;
 
-       heights      = heights_new(cg->irg);
+       heights      = heights_new(irg);
+       calculate_non_address_mode_nodes(irg);
 
        be_transform_graph(cg->birg, ia32_pretransform_node, cg);
 
+       free_non_address_mode_nodes();
        heights_free(heights);
        heights = NULL;
 }