- improve set transformation
authorMatthias Braun <matze@braunis.de>
Fri, 19 Oct 2007 11:10:56 +0000 (11:10 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 19 Oct 2007 11:10:56 +0000 (11:10 +0000)
- create SetMems
- support 3 operand IMul
- started writing a new incsp->store to push peephole phase

[r16273]

ir/be/ia32/bearch_ia32.c
ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_finish.c
ir/be/ia32/ia32_new_nodes.c
ir/be/ia32/ia32_optimize.c
ir/be/ia32/ia32_spec.pl
ir/be/ia32/ia32_transform.c

index b9b4e9b..2df1483 100644 (file)
@@ -906,7 +906,7 @@ static const arch_irn_ops_if_t ia32_irn_ops_if = {
        ia32_perform_memory_operand,
 };
 
-ia32_irn_ops_t ia32_irn_ops = {
+static ia32_irn_ops_t ia32_irn_ops = {
        &ia32_irn_ops_if,
        NULL
 };
@@ -925,9 +925,14 @@ ia32_irn_ops_t ia32_irn_ops = {
  **************************************************/
 
 static void ia32_before_abi(void *self) {
+       lower_mode_b_config_t lower_mode_b_config = {
+               mode_Iu,  /* lowered mode */
+               mode_Bu,  /* prefered mode for set */
+               0,        /* don't lower direct compares */
+       };
        ia32_code_gen_t *cg = self;
 
-       ir_lower_mode_b(cg->irg, mode_Iu, 0);
+       ir_lower_mode_b(cg->irg, &lower_mode_b_config);
        if(cg->dump)
                be_dump(cg->irg, "-lower_modeb", dump_ir_block_graph_sched);
 }
index 66562b0..603c77b 100644 (file)
@@ -563,6 +563,26 @@ void ia32_emit_am(const ir_node *node) {
        }
 }
 
+static void emit_ia32_IMul(const ir_node *node)
+{
+       ir_node               *left    = get_irn_n(node, n_ia32_IMul_left);
+       const arch_register_t *out_reg = get_out_reg(node, pn_ia32_IMul_res);
+
+       be_emit_cstring("\timul");
+       ia32_emit_mode_suffix(node);
+       be_emit_char(' ');
+
+       ia32_emit_binop(node);
+
+       /* do we need the 3-address form? */
+       if(is_ia32_NoReg_GP(left) ||
+                       get_in_reg(node, n_ia32_IMul_left) != out_reg) {
+               be_emit_cstring(", ");
+               emit_register(out_reg, get_ia32_ls_mode(node));
+       }
+       be_emit_finish_line_gas(node);
+}
+
 /*************************************************
  *                 _ _                         _
  *                (_) |                       | |
@@ -1838,6 +1858,7 @@ void ia32_register_emitters(void) {
        /* other ia32 emitter functions */
        IA32_EMIT(Asm);
        IA32_EMIT(CMov);
+       IA32_EMIT(IMul);
        IA32_EMIT(SwitchJmp);
        IA32_EMIT(CopyB);
        IA32_EMIT(CopyB_i);
index 5306d62..6cb6899 100644 (file)
@@ -142,6 +142,13 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) {
 }
 
 static INLINE int need_constraint_copy(ir_node *irn) {
+       /* the 3 operand form of IMul needs no constraint copy */
+       if(is_ia32_IMul(irn)) {
+               ir_node *right = get_irn_n(irn, n_ia32_IMul_right);
+               if(is_ia32_Immediate(right))
+                       return 0;
+       }
+
        return  ! is_ia32_Lea(irn)      &&
                ! is_ia32_Conv_I2I(irn)     &&
                ! is_ia32_Conv_I2I8Bit(irn) &&
index 9d03609..5b53ed9 100644 (file)
@@ -411,7 +411,6 @@ const ia32_immediate_attr_t *get_ia32_immediate_attr_const(const ir_node *node)
        const ia32_attr_t           *attr     = get_ia32_attr_const(node);
        const ia32_immediate_attr_t *imm_attr = CONST_CAST_IA32_ATTR(ia32_immediate_attr_t, attr);
 
-       assert(is_ia32_Immediate(node) || is_ia32_Const(node));
        return imm_attr;
 }
 
@@ -419,7 +418,6 @@ ia32_condcode_attr_t *get_ia32_condcode_attr(ir_node *node) {
        ia32_attr_t          *attr    = get_ia32_attr(node);
        ia32_condcode_attr_t *cc_attr = CAST_IA32_ATTR(ia32_condcode_attr_t, attr);
 
-       assert(is_ia32_SwitchJmp(node) || is_ia32_CMov(node) || is_ia32_Set(node) || is_ia32_Jcc(node));
        return cc_attr;
 }
 
@@ -427,7 +425,6 @@ const ia32_condcode_attr_t *get_ia32_condcode_attr_const(const ir_node *node) {
        const ia32_attr_t          *attr    = get_ia32_attr_const(node);
        const ia32_condcode_attr_t *cc_attr = CONST_CAST_IA32_ATTR(ia32_condcode_attr_t, attr);
 
-       assert(is_ia32_SwitchJmp(node) || is_ia32_CMov(node) || is_ia32_Set(node) || is_ia32_Jcc(node));
        return cc_attr;
 }
 
@@ -435,7 +432,6 @@ ia32_copyb_attr_t *get_ia32_copyb_attr(ir_node *node) {
        ia32_attr_t       *attr       = get_ia32_attr(node);
        ia32_copyb_attr_t *copyb_attr = CAST_IA32_ATTR(ia32_copyb_attr_t, attr);
 
-       assert(is_ia32_CopyB(node) || is_ia32_CopyB_i(node));
        return copyb_attr;
 }
 
@@ -443,7 +439,6 @@ const ia32_copyb_attr_t *get_ia32_copyb_attr_const(const ir_node *node) {
        const ia32_attr_t       *attr       = get_ia32_attr_const(node);
        const ia32_copyb_attr_t *copyb_attr = CONST_CAST_IA32_ATTR(ia32_copyb_attr_t, attr);
 
-       assert(is_ia32_CopyB(node) || is_ia32_CopyB_i(node));
        return copyb_attr;
 }
 
index 45295ce..f9ddc32 100644 (file)
@@ -39,6 +39,7 @@
 #include "height.h"
 #include "irbitset.h"
 #include "irprintf.h"
+#include "error.h"
 
 #include "../be_t.h"
 #include "../beabi.h"
@@ -59,30 +60,82 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 static const arch_env_t *arch_env;
 static ia32_code_gen_t  *cg;
 
-typedef int is_op_func_t(const ir_node *n);
-typedef ir_node *load_func_t(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, ir_node *mem);
+static void peephole_IncSP_IncSP(ir_node *node);
 
-/**
- * checks if a node represents the NOREG value
- */
-static INLINE int be_is_NoReg(ia32_code_gen_t *cg, const ir_node *irn) {
-       return irn == cg->noreg_gp || irn == cg->noreg_xmm || irn == cg->noreg_vfp;
-}
+#if 0
+static void peephole_ia32_Store_IncSP_to_push(ir_node *node)
+{
+       ir_node  *base  = get_irn_n(node, n_ia32_Store_base);
+       ir_node  *index = get_irn_n(node, n_ia32_Store_index);
+       ir_node  *mem   = get_irn_n(node, n_ia32_Store_mem);
+       ir_node  *incsp = base;
+       ir_node  *val;
+       ir_node  *noreg;
+       ir_graph *irg;
+       ir_node  *block;
+       dbg_info *dbgi;
+       ir_mode  *mode;
+       ir_node  *push;
+       ir_node  *proj;
+       int       offset;
+       int       node_offset;
+
+       /* nomem inidicates the store doesn't alias with anything else */
+       if(!is_NoMem(mem))
+               return;
 
-/********************************************************************************************************
- *  _____                _           _         ____        _   _           _          _   _
- * |  __ \              | |         | |       / __ \      | | (_)         (_)        | | (_)
- * | |__) |__  ___ _ __ | |__   ___ | | ___  | |  | |_ __ | |_ _ _ __ ___  _ ______ _| |_ _  ___  _ __
- * |  ___/ _ \/ _ \ '_ \| '_ \ / _ \| |/ _ \ | |  | | '_ \| __| | '_ ` _ \| |_  / _` | __| |/ _ \| '_ \
- * | |  |  __/  __/ |_) | | | | (_) | |  __/ | |__| | |_) | |_| | | | | | | |/ / (_| | |_| | (_) | | | |
- * |_|   \___|\___| .__/|_| |_|\___/|_|\___|  \____/| .__/ \__|_|_| |_| |_|_/___\__,_|\__|_|\___/|_| |_|
- *                | |                               | |
- *                |_|                               |_|
- ********************************************************************************************************/
+       /* find an IncSP in front of us, we might have to skip barriers for this */
+       while(is_Proj(incsp)) {
+               ir_node *proj_pred = get_Proj_pred(incsp);
+               if(!be_is_Barrier(proj_pred))
+                       return;
+               incsp = get_irn_n(proj_pred, get_Proj_proj(incsp));
+       }
+       if(!be_is_IncSP(incsp))
+               return;
 
-/**
- * NOTE: THESE PEEPHOLE OPTIMIZATIONS MUST BE CALLED AFTER SCHEDULING AND REGISTER ALLOCATION.
- */
+       peephole_IncSP_IncSP(incsp);
+
+       /* must be in the same block */
+       if(get_nodes_block(incsp) != get_nodes_block(node))
+               return;
+
+       if(!is_ia32_NoReg_GP(index) || get_ia32_am_sc(node) != NULL) {
+               panic("Invalid storeAM found (%+F)", node);
+       }
+
+       /* we should be the store to the end of the stackspace */
+       offset      = be_get_IncSP_offset(incsp);
+       mode        = get_ia32_ls_mode(node);
+       node_offset = get_ia32_am_offs_int(node);
+       if(node_offset != offset - get_mode_size_bytes(mode))
+               return;
+
+       /* we can use a push instead of the store */
+       irg   = current_ir_graph;
+       block = get_nodes_block(node);
+       dbgi  = get_irn_dbg_info(node);
+       noreg = ia32_new_NoReg_gp(cg);
+       base  = be_get_IncSP_pred(incsp);
+       val   = get_irn_n(node, n_ia32_Store_val);
+       push  = new_rd_ia32_Push(dbgi, irg, block, noreg, noreg, mem, base, val);
+
+       proj  = new_r_Proj(irg, block, push, mode_M, pn_ia32_Push_M);
+
+       be_set_IncSP_offset(incsp, offset - get_mode_size_bytes(mode));
+
+       sched_add_before(node, push);
+       sched_remove(node);
+
+       be_peephole_node_replaced(node, proj);
+       exchange(node, proj);
+}
+
+static void peephole_ia32_Store(ir_node *node)
+{
+       peephole_ia32_Store_IncSP_to_push(node);
+}
+#endif
 
 // only optimize up to 48 stores behind IncSPs
 #define MAXPUSH_OPTIMIZE       48
@@ -179,8 +232,6 @@ static void peephole_IncSP_Store_to_push(ir_node *irn)
 
                push = new_rd_ia32_Push(get_irn_dbg_info(store), irg, block, noreg, noreg, mem, curr_sp, val);
 
-               set_ia32_am_support(push, ia32_am_Source, ia32_am_unary);
-
                sched_add_before(irn, push);
 
                // create stackpointer proj
@@ -604,6 +655,7 @@ void ia32_peephole_optimization(ia32_code_gen_t *new_cg)
        /* register peephole optimisations */
        clear_irp_opcodes_generic_func();
        register_peephole_optimisation(op_ia32_Const, peephole_ia32_Const);
+       //register_peephole_optimisation(op_ia32_Store, peephole_ia32_Store);
        register_peephole_optimisation(op_be_IncSP, peephole_be_IncSP);
        register_peephole_optimisation(op_ia32_Lea, peephole_ia32_Lea);
 
@@ -638,15 +690,24 @@ static INLINE void try_kill(ir_node *node)
 static void optimize_conv_store(ir_node *node)
 {
        ir_node *pred;
+       ir_node *pred_proj;
        ir_mode *conv_mode;
        ir_mode *store_mode;
 
        if(!is_ia32_Store(node) && !is_ia32_Store8Bit(node))
                return;
 
-       pred = get_irn_n(node, 2);
+       assert(n_ia32_Store_val == n_ia32_Store8Bit_val);
+       pred_proj = get_irn_n(node, n_ia32_Store_val);
+       if(is_Proj(pred_proj)) {
+               pred = get_Proj_pred(pred_proj);
+       } else {
+               pred = pred_proj;
+       }
        if(!is_ia32_Conv_I2I(pred) && !is_ia32_Conv_I2I8Bit(pred))
                return;
+       if(get_ia32_op_type(pred) != ia32_Normal)
+               return;
 
        /* the store only stores the lower bits, so we only need the conv
         * it it shrinks the mode */
@@ -655,9 +716,11 @@ static void optimize_conv_store(ir_node *node)
        if(get_mode_size_bits(conv_mode) < get_mode_size_bits(store_mode))
                return;
 
-       set_irn_n(node, 2, get_irn_n(pred, 2));
-       if(get_irn_n_edges(pred) == 0) {
-               be_kill_node(pred);
+       set_irn_n(node, n_ia32_Store_val, get_irn_n(pred, n_ia32_Conv_I2I_val));
+       if(get_irn_n_edges(pred_proj) == 0) {
+               be_kill_node(pred_proj);
+               if(pred != pred_proj)
+                       be_kill_node(pred);
        }
 }
 
@@ -670,7 +733,8 @@ static void optimize_load_conv(ir_node *node)
        if (!is_ia32_Conv_I2I(node) && !is_ia32_Conv_I2I8Bit(node))
                return;
 
-       pred = get_irn_n(node, 2);
+       assert(n_ia32_Conv_I2I_val == n_ia32_Conv_I2I8Bit_val);
+       pred = get_irn_n(node, n_ia32_Conv_I2I_val);
        if(!is_Proj(pred))
                return;
 
@@ -780,8 +844,10 @@ static void optimize_conv_conv(ir_node *node)
        /* kill the conv */
        exchange(node, result_conv);
 
-       if(get_irn_n_edges(pred) == 0) {
-               be_kill_node(pred);
+       if(get_irn_n_edges(pred_proj) == 0) {
+               be_kill_node(pred_proj);
+               if(pred != pred_proj)
+                       be_kill_node(pred);
        }
        optimize_conv_conv(result_conv);
 }
index 805ec1a..a6390a2 100644 (file)
@@ -218,6 +218,7 @@ $arch = "ia32";
        binop => "${arch}_emit_binop(node);",
        x87_binop => "${arch}_emit_x87_binop(node);",
        CMP0  => "${arch}_emit_cmp_suffix_node(node, 0);",
+       CMP3  => "${arch}_emit_cmp_suffix_node(node, 3);",
 );
 
 #--------------------------------------------------#
@@ -452,9 +453,12 @@ l_Mul => {
 IMul => {
        irn_flags => "R",
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] },
+       # TODO: adjust out requirements for the 3 operand form
+       # (no need for should_be_same then)
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
+                          out => [ "in_r4 in_r5", "none", "flags" ] },
        ins       => [ "base", "index", "mem", "left", "right" ],
-       emit      => '. imul%M %binop',
+       outs      => [ "res", "M", "flags" ],
        am        => "source,binary",
        latency   => 5,
        units     => [ "GP" ],
@@ -1054,6 +1058,21 @@ Set => {
        mode      => $mode_gp,
 },
 
+SetMem => {
+       #irn_flags => "R",
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "gp", "none", "eflags" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem","eflags" ],
+       attr_type => "ia32_condcode_attr_t",
+       attr      => "pn_Cmp pnc, int ins_permuted",
+       init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
+                     "\tset_ia32_ls_mode(res, mode_Bu);\n",
+       emit      => '. set%CMP3 %AM',
+       latency   => 1,
+       units     => [ "GP" ],
+       mode      => 'mode_M',
+},
+
 CMov => {
        #irn_flags => "R",
        # (note: leave the false,true order intact to make it compatible with other
index ed2c1b3..2c9f75a 100644 (file)
@@ -512,10 +512,32 @@ struct ia32_address_mode_t {
        ir_node        *new_op1;
        ir_node        *new_op2;
        op_pin_state    pinned;
-       unsigned        commutative:1;
-       unsigned        ins_permuted:1;
+       unsigned        commutative  : 1;
+       unsigned        ins_permuted : 1;
 };
 
+static void build_address_ptr(ia32_address_t *addr, ir_node *ptr, ir_node *mem)
+{
+       ir_node *noreg_gp = ia32_new_NoReg_gp(env_cg);
+
+       /* construct load address */
+       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->mem   = be_transform_node(mem);
+}
+
 static void build_address(ia32_address_mode_t *am, ir_node *node)
 {
        ir_node        *noreg_gp = ia32_new_NoReg_gp(env_cg);
@@ -1144,7 +1166,8 @@ static ir_node *gen_Mul(ir_node *node) {
                constraints
        */
        return gen_binop(node, op1, op2, new_rd_ia32_IMul,
-                        match_commutative | match_am | match_mode_neutral);
+                        match_commutative | match_am | match_mode_neutral |
+                        match_immediate | match_am_and_immediates);
 }
 
 /**
@@ -1712,6 +1735,38 @@ static ir_node *gen_Abs(ir_node *node)
        return new_node;
 }
 
+static ir_node *get_flags_node(ir_node *node, pn_Cmp *pnc_out)
+{
+       ir_graph *irg = current_ir_graph;
+       ir_node  *flags;
+       ir_node  *new_op;
+       ir_node  *noreg;
+       ir_node  *nomem;
+       ir_node  *new_block;
+       dbg_info *dbgi;
+
+       /* we have a Cmp as input */
+       if(is_Proj(node)) {
+               ir_node *pred = get_Proj_pred(node);
+               if(is_Cmp(pred)) {
+                       flags    = be_transform_node(pred);
+                       *pnc_out = get_Proj_proj(node);
+                       return flags;
+               }
+       }
+
+       /* a mode_b value, we have to compare it against 0 */
+       dbgi      = get_irn_dbg_info(node);
+       new_block = be_transform_node(get_nodes_block(node));
+       new_op    = be_transform_node(node);
+       noreg     = ia32_new_NoReg_gp(env_cg);
+       nomem     = new_NoMem();
+       flags     = new_rd_ia32_Test(dbgi, irg, new_block, noreg, noreg, nomem,
+                                    new_op, new_op, 0, 0);
+       *pnc_out  = pn_Cmp_Lg;
+       return flags;
+}
+
 /**
  * Transforms a Load.
  *
@@ -1886,10 +1941,9 @@ static ir_node *dest_am_unop(ir_node *node, ir_node *op, ir_node *mem,
                              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_node *noreg_gp  = ia32_new_NoReg_gp(env_cg);
-       ir_graph *irg      = current_ir_graph;
        dbg_info *dbgi;
        ir_node *new_node;
        ia32_address_mode_t  am;
@@ -1901,13 +1955,6 @@ static ir_node *dest_am_unop(ir_node *node, ir_node *op, ir_node *mem,
 
        build_address(&am, op);
 
-       if(addr->base == NULL)
-               addr->base = noreg_gp;
-       if(addr->index == NULL)
-               addr->index = noreg_gp;
-       if(addr->mem == NULL)
-               addr->mem = new_NoMem();
-
        dbgi     = get_irn_dbg_info(node);
        block    = be_transform_node(src_block);
        new_node = func(dbgi, irg, block, addr->base, addr->index, addr->mem);
@@ -1919,11 +1966,58 @@ static ir_node *dest_am_unop(ir_node *node, ir_node *op, ir_node *mem,
        return new_node;
 }
 
+static ir_node *try_create_SetMem(ir_node *node, ir_node *ptr, ir_node *mem) {
+       ir_mode  *mode        = get_irn_mode(node);
+       ir_node  *psi_true    = get_Psi_val(node, 0);
+       ir_node  *psi_default = get_Psi_default(node);
+       ir_graph *irg;
+       ir_node  *cond;
+       ir_node  *new_mem;
+       dbg_info *dbgi;
+       ir_node  *block;
+       ir_node  *new_block;
+       ir_node  *flags;
+       ir_node  *new_node;
+       int       negated;
+       pn_Cmp    pnc;
+       ia32_address_t addr;
+
+       if(get_mode_size_bits(mode) != 8)
+               return NULL;
+
+       if(is_Const_1(psi_true) && is_Const_0(psi_default)) {
+               negated = 0;
+       } else if(is_Const_0(psi_true) && is_Const_1(psi_default)) {
+               negated = 1;
+       } else {
+               return NULL;
+       }
+
+       build_address_ptr(&addr, ptr, mem);
+
+       irg       = current_ir_graph;
+       dbgi      = get_irn_dbg_info(node);
+       block     = get_nodes_block(node);
+       new_block = be_transform_node(block);
+       cond      = get_Psi_cond(node, 0);
+       flags     = get_flags_node(cond, &pnc);
+       new_mem   = be_transform_node(mem);
+       new_node  = new_rd_ia32_SetMem(dbgi, irg, new_block, addr.base,
+                                      addr.index, addr.mem, flags, pnc, negated);
+       set_address(new_node, &addr);
+       set_ia32_op_type(new_node, ia32_AddrModeD);
+       set_ia32_ls_mode(new_node, mode);
+       SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
+
+       return new_node;
+}
+
 static ir_node *try_create_dest_am(ir_node *node) {
        ir_node  *val  = get_Store_value(node);
        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);
        ir_node  *op1;
        ir_node  *op2;
        ir_node  *new_node;
@@ -1932,8 +2026,24 @@ static ir_node *try_create_dest_am(ir_node *node) {
        if(!mode_needs_gp_reg(mode))
                return NULL;
 
-       /* store must be the only user of the val node */
-       if(get_irn_n_edges(val) > 1)
+       while(1) {
+               /* store must be the only user of the val node */
+               if(get_irn_n_edges(val) > 1)
+                       return NULL;
+               /* skip pointless convs */
+               if(is_Conv(val)) {
+                       ir_node *conv_op   = get_Conv_op(val);
+                       ir_mode *pred_mode = get_irn_mode(conv_op);
+                       if(pred_mode == mode_b || bits <= get_mode_size_bits(pred_mode)) {
+                               val = conv_op;
+                               continue;
+                       }
+               }
+               break;
+       }
+
+       /* value must be in the same block */
+       if(get_nodes_block(node) != get_nodes_block(val))
                return NULL;
 
        switch(get_irn_opcode(val)) {
@@ -2019,6 +2129,9 @@ static ir_node *try_create_dest_am(ir_node *node) {
                                         match_dest_am | match_immediate);
                break;
        /* TODO: match ROR patterns... */
+       case iro_Psi:
+               new_node = try_create_SetMem(val, ptr, mem);
+               break;
        case iro_Minus:
                op1      = get_Minus_op(val);
                new_node = dest_am_unop(val, op1, mem, ptr, mode, new_rd_ia32_NegMem);
@@ -2033,6 +2146,13 @@ static ir_node *try_create_dest_am(ir_node *node) {
                return NULL;
        }
 
+       if(new_node != NULL) {
+               if(get_irn_pinned(new_node) != op_pin_state_pinned &&
+                               get_irn_pinned(node) == op_pin_state_pinned) {
+                       set_irn_pinned(new_node, op_pin_state_pinned);
+               }
+       }
+
        return new_node;
 }
 
@@ -2189,38 +2309,6 @@ static ir_node *create_Switch(ir_node *node)
        return new_node;
 }
 
-static ir_node *get_flags_node(ir_node *node, pn_Cmp *pnc_out)
-{
-       ir_graph *irg = current_ir_graph;
-       ir_node  *flags;
-       ir_node  *new_op;
-       ir_node  *noreg;
-       ir_node  *nomem;
-       ir_node  *new_block;
-       dbg_info *dbgi;
-
-       /* we have a Cmp as input */
-       if(is_Proj(node)) {
-               ir_node *pred = get_Proj_pred(node);
-               if(is_Cmp(pred)) {
-                       flags    = be_transform_node(pred);
-                       *pnc_out = get_Proj_proj(node);
-                       return flags;
-               }
-       }
-
-       /* a mode_b value, we have to compare it against 0 */
-       dbgi      = get_irn_dbg_info(node);
-       new_block = be_transform_node(get_nodes_block(node));
-       new_op    = be_transform_node(node);
-       noreg     = ia32_new_NoReg_gp(env_cg);
-       nomem     = new_NoMem();
-       flags     = new_rd_ia32_Test(dbgi, irg, new_block, noreg, noreg, nomem,
-                                    new_op, new_op, 0, 0);
-       *pnc_out  = pn_Cmp_Lg;
-       return flags;
-}
-
 static ir_node *gen_Cond(ir_node *node) {
        ir_node  *block     = get_nodes_block(node);
        ir_node  *new_block = be_transform_node(block);
@@ -2537,14 +2625,18 @@ static ir_node *create_set_32bit(dbg_info *dbgi, ir_node *new_block,
        ir_graph *irg   = current_ir_graph;
        ir_node  *noreg = ia32_new_NoReg_gp(env_cg);
        ir_node  *nomem = new_NoMem();
+       ir_mode  *mode  = get_irn_mode(orig_node);
        ir_node  *new_node;
 
        new_node = new_rd_ia32_Set(dbgi, irg, new_block, flags, pnc, ins_permuted);
        SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, orig_node));
-       new_node = new_rd_ia32_Conv_I2I8Bit(dbgi, irg, new_block, noreg, noreg,
-                                           nomem, new_node, mode_Bu);
-       SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, orig_node));
-       (void) orig_node;
+
+       /* we might need to conv the result up */
+       if(get_mode_size_bits(mode) > 8) {
+               new_node = new_rd_ia32_Conv_I2I8Bit(dbgi, irg, new_block, noreg, noreg,
+                                                   nomem, new_node, mode_Bu);
+               SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, orig_node));
+       }
 
        return new_node;
 }
@@ -4562,6 +4654,10 @@ static ir_node *gen_Proj_be_Call(ir_node *node) {
  */
 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);
@@ -4575,6 +4671,7 @@ static ir_node *gen_Proj_Cmp(ir_node *node)
        res = create_set_32bit(dbgi, new_block, new_cmp, pnc, node, 0);
 
        return res;
+#endif
 }
 
 /**