small improvements: cache different environment members in local variables
[libfirm] / ir / be / ia32 / bearch_ia32.c
index 30025b4..a810915 100644 (file)
@@ -177,7 +177,7 @@ ir_node *ia32_new_Fpu_truncate(ia32_code_gen_t *cg) {
 
 
 /**
- * Returns gp_noreg or fp_noreg, depending in input requirements.
+ * Returns the admissible noreg register node for input register pos of node irn.
  */
 ir_node *ia32_get_admissible_noreg(ia32_code_gen_t *cg, ir_node *irn, int pos) {
        const arch_register_req_t *req;
@@ -210,15 +210,13 @@ ir_node *ia32_get_admissible_noreg(ia32_code_gen_t *cg, ir_node *irn, int pos) {
  * If the node returns a tuple (mode_T) then the proj's
  * will be asked for this information.
  */
-static const arch_register_req_t *ia32_get_irn_reg_req(const void *self,
-                                                       const ir_node *node,
+static const arch_register_req_t *ia32_get_irn_reg_req(const ir_node *node,
                                                                                                           int pos)
 {
-       long node_pos = pos == -1 ? 0 : pos;
-       ir_mode *mode     = is_Block(node) ? NULL : get_irn_mode(node);
-       (void) self;
+       ir_mode *mode = get_irn_mode(node);
+       long    node_pos;
 
-       if (is_Block(node) || mode == mode_X) {
+       if (mode == mode_X || is_Block(node)) {
                return arch_no_register_req;
        }
 
@@ -226,11 +224,9 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self,
                return arch_no_register_req;
        }
 
+       node_pos = pos == -1 ? 0 : pos;
        if (is_Proj(node)) {
-               if(mode == mode_M)
-                       return arch_no_register_req;
-
-               if(pos >= 0) {
+               if (mode == mode_M || pos >= 0) {
                        return arch_no_register_req;
                }
 
@@ -240,7 +236,7 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self,
 
        if (is_ia32_irn(node)) {
                const arch_register_req_t *req;
-               if(pos >= 0)
+               if (pos >= 0)
                        req = get_ia32_in_req(node, pos);
                else
                        req = get_ia32_out_req(node, node_pos);
@@ -252,15 +248,12 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self,
 
        /* unknowns should be transformed already */
        assert(!is_Unknown(node));
-
        return arch_no_register_req;
 }
 
-static void ia32_set_irn_reg(const void *self, ir_node *irn,
-                             const arch_register_t *reg)
+static void ia32_set_irn_reg(ir_node *irn, const arch_register_t *reg)
 {
-       int                   pos = 0;
-       (void) self;
+       int    pos = 0;
 
        if (get_irn_mode(irn) == mode_X) {
                return;
@@ -281,12 +274,10 @@ static void ia32_set_irn_reg(const void *self, ir_node *irn,
        }
 }
 
-static const arch_register_t *ia32_get_irn_reg(const void *self,
-                                               const ir_node *irn)
+static const arch_register_t *ia32_get_irn_reg(const ir_node *irn)
 {
        int pos = 0;
        const arch_register_t *reg = NULL;
-       (void) self;
 
        if (is_Proj(irn)) {
 
@@ -310,9 +301,8 @@ static const arch_register_t *ia32_get_irn_reg(const void *self,
        return reg;
 }
 
-static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) {
+static arch_irn_class_t ia32_classify(const ir_node *irn) {
        arch_irn_class_t classification = arch_irn_class_normal;
-       (void) self;
 
        irn = skip_Proj_const(irn);
 
@@ -334,9 +324,8 @@ static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) {
        return classification;
 }
 
-static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
+static arch_irn_flags_t ia32_get_flags(const ir_node *irn) {
        arch_irn_flags_t flags = arch_irn_flags_none;
-       (void) self;
 
        if (is_Unknown(irn))
                return arch_irn_flags_ignore;
@@ -363,30 +352,26 @@ static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
  */
 typedef struct {
        be_abi_call_flags_bits_t flags;  /**< The call flags. */
-       const arch_isa_t *isa;           /**< The ISA handle. */
        const arch_env_t *aenv;          /**< The architecture environment. */
        ir_graph *irg;                   /**< The associated graph. */
 } ia32_abi_env_t;
 
-static ir_entity *ia32_get_frame_entity(const void *self, const ir_node *irn) {
-       (void) self;
+static ir_entity *ia32_get_frame_entity(const ir_node *irn) {
        return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
 }
 
-static void ia32_set_frame_entity(const void *self, ir_node *irn, ir_entity *ent) {
-       (void) self;
+static void ia32_set_frame_entity(ir_node *irn, ir_entity *ent) {
        set_ia32_frame_ent(irn, ent);
 }
 
-static void ia32_set_frame_offset(const void *self, ir_node *irn, int bias)
+static void ia32_set_frame_offset(ir_node *irn, int bias)
 {
-       const ia32_irn_ops_t *ops = self;
-
        if (get_ia32_frame_ent(irn) == NULL)
                return;
 
-       if (is_ia32_Pop(irn)) {
-               int omit_fp = be_abi_omit_fp(ops->cg->birg->abi);
+       if (is_ia32_Pop(irn) || is_ia32_PopMem(irn)) {
+               ia32_code_gen_t *cg = ia32_current_cg;
+               int omit_fp = be_abi_omit_fp(cg->birg->abi);
                if (omit_fp) {
                        /* Pop nodes modify the stack pointer before calculating the
                         * destination address, so fix this here
@@ -397,14 +382,12 @@ static void ia32_set_frame_offset(const void *self, ir_node *irn, int bias)
        add_ia32_am_offs_int(irn, bias);
 }
 
-static int ia32_get_sp_bias(const void *self, const ir_node *node)
+static int ia32_get_sp_bias(const ir_node *node)
 {
-       (void) self;
-
        if (is_ia32_Push(node))
                return 4;
 
-       if (is_ia32_Pop(node))
+       if (is_ia32_Pop(node) || is_ia32_PopMem(node))
                return -4;
 
        return 0;
@@ -420,7 +403,7 @@ static void ia32_abi_dont_save_regs(void *self, pset *s)
 {
        ia32_abi_env_t *env = self;
        if(env->flags.try_omit_fp)
-               pset_insert_ptr(s, env->isa->bp);
+               pset_insert_ptr(s, env->aenv->bp);
 }
 
 /**
@@ -436,48 +419,49 @@ static void ia32_abi_dont_save_regs(void *self, pset *s)
  */
 static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap *reg_map)
 {
-       ia32_abi_env_t *env = self;
-       const ia32_isa_t *isa     = (ia32_isa_t *)env->isa;
-       ia32_code_gen_t *cg = isa->cg;
+       ia32_abi_env_t   *env      = self;
+       ia32_code_gen_t  *cg       = ia32_current_cg;
+       const arch_env_t *arch_env = env->aenv;
 
        if (! env->flags.try_omit_fp) {
-               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);
-               ir_node *noreg = ia32_new_NoReg_gp(cg);
-               ir_node *push;
+               ir_graph *irg     =env->irg;
+               ir_node  *bl      = get_irg_start_block(irg);
+               ir_node  *curr_sp = be_abi_reg_map_get(reg_map, arch_env->sp);
+               ir_node  *curr_bp = be_abi_reg_map_get(reg_map, arch_env->bp);
+               ir_node  *noreg = ia32_new_NoReg_gp(cg);
+               ir_node  *push;
 
                /* ALL nodes representing bp must be set to ignore. */
                be_node_set_flags(get_Proj_pred(curr_bp), BE_OUT_POS(get_Proj_proj(curr_bp)), arch_irn_flags_ignore);
 
                /* push ebp */
-               push    = new_rd_ia32_Push(NULL, env->irg, bl, noreg, noreg, *mem, curr_sp, curr_bp);
-               curr_sp = new_r_Proj(env->irg, bl, push, get_irn_mode(curr_sp), pn_ia32_Push_stack);
-               *mem    = new_r_Proj(env->irg, bl, push, mode_M, pn_ia32_Push_M);
+               push    = new_rd_ia32_Push(NULL, irg, bl, noreg, noreg, *mem, curr_bp, curr_sp);
+               curr_sp = new_r_Proj(irg, bl, push, get_irn_mode(curr_sp), pn_ia32_Push_stack);
+               *mem    = new_r_Proj(irg, bl, push, mode_M, pn_ia32_Push_M);
 
                /* the push must have SP out register */
-               arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
+               arch_set_irn_register(arch_env, curr_sp, arch_env->sp);
                set_ia32_flags(push, arch_irn_flags_ignore);
 
                /* move esp to ebp */
-               curr_bp  = be_new_Copy(env->isa->bp->reg_class, env->irg, bl, curr_sp);
-               be_set_constr_single_reg(curr_bp, BE_OUT_POS(0), env->isa->bp);
-               arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);
+               curr_bp  = be_new_Copy(arch_env->bp->reg_class, irg, bl, curr_sp);
+               be_set_constr_single_reg(curr_bp, BE_OUT_POS(0), arch_env->bp);
+               arch_set_irn_register(arch_env, curr_bp, arch_env->bp);
                be_node_set_flags(curr_bp, BE_OUT_POS(0), arch_irn_flags_ignore);
 
                /* beware: the copy must be done before any other sp use */
-               curr_sp = be_new_CopyKeep_single(env->isa->sp->reg_class, env->irg, bl, curr_sp, curr_bp, get_irn_mode(curr_sp));
-               be_set_constr_single_reg(curr_sp, BE_OUT_POS(0), env->isa->sp);
-               arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
+               curr_sp = be_new_CopyKeep_single(arch_env->sp->reg_class, irg, bl, curr_sp, curr_bp, get_irn_mode(curr_sp));
+               be_set_constr_single_reg(curr_sp, BE_OUT_POS(0), arch_env->sp);
+               arch_set_irn_register(arch_env, curr_sp, arch_env->sp);
                be_node_set_flags(curr_sp, BE_OUT_POS(0), arch_irn_flags_ignore);
 
-               be_abi_reg_map_set(reg_map, env->isa->sp, curr_sp);
-               be_abi_reg_map_set(reg_map, env->isa->bp, curr_bp);
+               be_abi_reg_map_set(reg_map, arch_env->sp, curr_sp);
+               be_abi_reg_map_set(reg_map, arch_env->bp, curr_bp);
 
-               return env->isa->bp;
+               return arch_env->bp;
        }
 
-       return env->isa->sp;
+       return arch_env->sp;
 }
 
 /**
@@ -492,17 +476,18 @@ static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap
  */
 static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map)
 {
-       ia32_abi_env_t *env     = self;
-       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);
+       ia32_abi_env_t   *env      = self;
+       const arch_env_t *arch_env = env->aenv;
+       ir_node          *curr_sp  = be_abi_reg_map_get(reg_map, arch_env->sp);
+       ir_node          *curr_bp  = be_abi_reg_map_get(reg_map, arch_env->bp);
+       ir_graph         *irg      = env->irg;
 
        if (env->flags.try_omit_fp) {
                /* simply remove the stack frame here */
-               curr_sp = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK, 0);
+               curr_sp = be_new_IncSP(arch_env->sp, irg, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK, 0);
                add_irn_dep(curr_sp, *mem);
        } else {
-               ir_mode         *mode_bp = env->isa->bp->reg_class->mode;
-               ir_graph        *irg     = current_ir_graph;
+               ir_mode *mode_bp = arch_env->bp->reg_class->mode;
 
                if (ia32_cg_config.use_leave) {
                        ir_node *leave;
@@ -521,7 +506,7 @@ static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_
 
                        /* copy ebp to esp */
                        curr_sp = be_new_Copy(&ia32_reg_classes[CLASS_ia32_gp], irg, bl, curr_bp);
-                       arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
+                       arch_set_irn_register(arch_env, curr_sp, arch_env->sp);
                        be_node_set_flags(curr_sp, BE_OUT_POS(0), arch_irn_flags_ignore);
 
                        /* pop ebp */
@@ -532,12 +517,12 @@ static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_
 
                        *mem = new_r_Proj(irg, bl, pop, mode_M, pn_ia32_Pop_M);
                }
-               arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
-               arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);
+               arch_set_irn_register(arch_env, curr_sp, arch_env->sp);
+               arch_set_irn_register(arch_env, curr_bp, arch_env->bp);
        }
 
-       be_abi_reg_map_set(reg_map, env->isa->sp, curr_sp);
-       be_abi_reg_map_set(reg_map, env->isa->bp, curr_bp);
+       be_abi_reg_map_set(reg_map, arch_env->sp, curr_sp);
+       be_abi_reg_map_set(reg_map, arch_env->bp, curr_bp);
 }
 
 /**
@@ -554,7 +539,6 @@ static void *ia32_abi_init(const be_abi_call_t *call, const arch_env_t *aenv, ir
        env->flags = fl.bits;
        env->irg   = irg;
        env->aenv  = aenv;
-       env->isa   = aenv->isa;
        return env;
 }
 
@@ -616,11 +600,10 @@ static ir_type *ia32_abi_get_between_type(void *self)
  *
  * @return     The estimated cycle count for this operation
  */
-static int ia32_get_op_estimated_cost(const void *self, const ir_node *irn)
+static int ia32_get_op_estimated_cost(const ir_node *irn)
 {
        int            cost;
        ia32_op_type_t op_tp;
-       (void) self;
 
        if (is_Proj(irn))
                return 0;
@@ -667,13 +650,12 @@ static int ia32_get_op_estimated_cost(const void *self, const ir_node *irn)
  * @param obstack   The obstack to use for allocation of the returned nodes array
  * @return          The inverse operation or NULL if operation invertible
  */
-static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obst) {
+static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obst) {
        ir_graph *irg;
        ir_mode  *mode;
        ir_mode  *irn_mode;
        ir_node  *block, *noreg, *nomem;
        dbg_info *dbg;
-       (void) self;
 
        /* we cannot invert non-ia32 irns */
        if (! is_ia32_irn(irn))
@@ -816,24 +798,24 @@ static int ia32_is_spillmode_compatible(const ir_mode *mode, const ir_mode *spil
 }
 
 /**
- * Check if irn can load it's operand at position i from memory (source addressmode).
+ * Check if irn can load its 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) {
+static int ia32_possible_memory_operand(const ir_node *irn, unsigned int i) {
        ir_node *op = get_irn_n(irn, i);
        const ir_mode *mode = get_irn_mode(op);
        const ir_mode *spillmode = get_spill_mode(op);
-       (void) self;
 
-       if (! is_ia32_irn(irn)                                  ||  /* must be an ia32 irn */
+       if (
+               (i != n_ia32_binary_left && i != n_ia32_binary_right) || /* a "real" operand position must be requested */
+               ! is_ia32_irn(irn)                                    ||  /* must be an ia32 irn */
                get_ia32_am_arity(irn) != ia32_am_binary              ||  /* must be a binary operation TODO is this necessary? */
                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 */
                ! ia32_is_spillmode_compatible(mode, spillmode)       ||
-               (i != n_ia32_binary_left && i != n_ia32_binary_right) || /* a "real" operand position must be requested */
                is_ia32_use_frame(irn))                                  /* must not already use frame */
                return 0;
 
@@ -845,7 +827,7 @@ static int ia32_possible_memory_operand(const void *self, const ir_node *irn, un
                 * (As this (currently) breaks constraint handling copies)
                 */
                req = get_ia32_in_req(irn, n_ia32_binary_left);
-               if(req->type & arch_register_req_type_limited) {
+               if (req->type & arch_register_req_type_limited) {
                        return 0;
                }
        }
@@ -853,13 +835,12 @@ static int ia32_possible_memory_operand(const void *self, const ir_node *irn, un
        return 1;
 }
 
-static void ia32_perform_memory_operand(const void *self, ir_node *irn,
-                                        ir_node *spill, unsigned int i)
+static void ia32_perform_memory_operand(ir_node *irn, ir_node *spill,
+                                        unsigned int i)
 {
-       const ia32_irn_ops_t *ops = self;
-       ia32_code_gen_t      *cg  = ops->cg;
+       ia32_code_gen_t *cg = ia32_current_cg;
 
-       assert(ia32_possible_memory_operand(self, irn, i) && "Cannot perform memory operand change");
+       assert(ia32_possible_memory_operand(irn, i) && "Cannot perform memory operand change");
 
        if (i == n_ia32_binary_left) {
                ia32_swap_left_right(irn);
@@ -891,7 +872,7 @@ static const be_abi_callbacks_t ia32_abi_callbacks = {
 
 /* fill register allocator interface */
 
-static const arch_irn_ops_if_t ia32_irn_ops_if = {
+static const arch_irn_ops_t ia32_irn_ops = {
        ia32_get_irn_reg_req,
        ia32_set_irn_reg,
        ia32_get_irn_reg,
@@ -907,13 +888,6 @@ static const arch_irn_ops_if_t ia32_irn_ops_if = {
        ia32_perform_memory_operand,
 };
 
-static ia32_irn_ops_t ia32_irn_ops = {
-       &ia32_irn_ops_if,
-       NULL
-};
-
-
-
 /**************************************************
  *                _                         _  __
  *               | |                       (_)/ _|
@@ -1083,7 +1057,7 @@ static void turn_back_am(ir_node *node)
 static ir_node *flags_remat(ir_node *node, ir_node *after)
 {
        /* we should turn back source address mode when rematerializing nodes */
-       ia32_op_type_t  type = get_ia32_op_type(node);
+       ia32_op_type_t type;
        ir_node        *block;
        ir_node        *copy;
 
@@ -1093,6 +1067,7 @@ static ir_node *flags_remat(ir_node *node, ir_node *after)
                block = get_nodes_block(after);
        }
 
+       type = get_ia32_op_type(node);
        switch (type) {
                case ia32_AddrModeS: turn_back_am(node); break;
 
@@ -1158,7 +1133,7 @@ static void transform_to_Load(ia32_code_gen_t *cg, ir_node *node) {
                        new_op = new_rd_ia32_vfld(dbg, irg, block, ptr, noreg, mem, spillmode);
        }
        else if (get_mode_size_bits(spillmode) == 128) {
-               // Reload 128 bit sse registers
+               /* Reload 128 bit SSE registers */
                new_op = new_rd_ia32_xxLoad(dbg, irg, block, ptr, noreg, mem);
        }
        else
@@ -1226,7 +1201,7 @@ static void transform_to_Store(ia32_code_gen_t *cg, ir_node *node) {
                else
                        store = new_rd_ia32_vfst(dbg, irg, block, ptr, noreg, nomem, val, mode);
        } else if (get_mode_size_bits(mode) == 128) {
-               // Spill 128 bit SSE registers
+               /* Spill 128 bit SSE registers */
                store = new_rd_ia32_xxStore(dbg, irg, block, ptr, noreg, nomem, val);
        } else if (get_mode_size_bits(mode) == 8) {
                store = new_rd_ia32_Store8Bit(dbg, irg, block, ptr, noreg, nomem, val);
@@ -1256,7 +1231,7 @@ static ir_node *create_push(ia32_code_gen_t *cg, ir_node *node, ir_node *schedpo
        ir_node *noreg = ia32_new_NoReg_gp(cg);
        ir_node *frame = get_irg_frame(irg);
 
-       ir_node *push = new_rd_ia32_Push(dbg, irg, block, frame, noreg, mem, sp, noreg);
+       ir_node *push = new_rd_ia32_Push(dbg, irg, block, frame, noreg, mem, noreg, sp);
 
        set_ia32_frame_ent(push, ent);
        set_ia32_use_frame(push);
@@ -1301,7 +1276,7 @@ static ir_node* create_spproj(ia32_code_gen_t *cg, ir_node *node, ir_node *pred,
 }
 
 /**
- * Transform memperm, currently we do this the ugly way and produce
+ * Transform MemPerm, currently we do this the ugly way and produce
  * push/pop into/from memory cascades. This is possible without using
  * any registers.
  */
@@ -1411,7 +1386,7 @@ static void ia32_after_ra_walker(ir_node *block, void *env) {
                        transform_to_Load(cg, node);
                } else if (be_is_Spill(node)) {
                        transform_to_Store(cg, node);
-               } else if(be_is_MemPerm(node)) {
+               } else if (be_is_MemPerm(node)) {
                        transform_MemPerm(cg, node);
                }
        }
@@ -1458,6 +1433,7 @@ static void ia32_collect_frame_entity_nodes(ir_node *node, void *data)
                                   is_ia32_xStoreSimple(node) ||
                                   is_ia32_vfst(node) ||
                                   is_ia32_vfist(node) ||
+                                  is_ia32_vfisttp(node) ||
                               is_ia32_FnstCW(node));
 #endif
                }
@@ -1566,14 +1542,14 @@ static const arch_code_generator_if_t ia32_code_gen_if = {
  * Initializes a IA32 code generator.
  */
 static void *ia32_cg_init(be_irg_t *birg) {
-       ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env.isa;
+       ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env;
        ia32_code_gen_t *cg  = xcalloc(1, sizeof(*cg));
 
        cg->impl      = &ia32_code_gen_if;
        cg->irg       = birg->irg;
        cg->reg_set   = new_set(ia32_cmp_irn_reg_assoc, 1024);
-       cg->arch_env  = &birg->main_env->arch_env;
        cg->isa       = isa;
+       cg->arch_env  = birg->main_env->arch_env;
        cg->birg      = birg;
        cg->blk_sched = NULL;
        cg->dump      = (birg->main_env->options->dump_flags & DUMP_BE) ? 1 : 0;
@@ -1596,8 +1572,6 @@ static void *ia32_cg_init(be_irg_t *birg) {
 
        cur_reg_set = cg->reg_set;
 
-       ia32_irn_ops.cg = cg;
-
        assert(ia32_current_cg == NULL);
        ia32_current_cg = cg;
 
@@ -1673,7 +1647,7 @@ static ia32_isa_t ia32_isa_template = {
 /**
  * Initializes the backend ISA.
  */
-static void *ia32_init(FILE *file_handle) {
+static arch_env_t *ia32_init(FILE *file_handle) {
        static int inited = 0;
        ia32_isa_t *isa;
 
@@ -1691,7 +1665,7 @@ static void *ia32_init(FILE *file_handle) {
        }
 
        ia32_register_init();
-       ia32_create_opcodes();
+       ia32_create_opcodes(&ia32_irn_ops);
 
        be_emit_init(file_handle);
        isa->regs_16bit     = pmap_create();
@@ -1725,7 +1699,7 @@ static void *ia32_init(FILE *file_handle) {
         */
        inc_master_type_visited();
 
-       return isa;
+       return &isa->arch_env;
 }
 
 
@@ -1737,7 +1711,7 @@ static void ia32_done(void *self) {
        ia32_isa_t *isa = self;
 
        /* emit now all global declarations */
-       be_gas_emit_decls(isa->arch_isa.main_env, 1);
+       be_gas_emit_decls(isa->arch_env.main_env, 1);
 
        pmap_destroy(isa->regs_16bit);
        pmap_destroy(isa->regs_8bit);
@@ -1896,25 +1870,6 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
        }
 }
 
-
-static const void *ia32_get_irn_ops(const arch_irn_handler_t *self,
-                                    const ir_node *irn)
-{
-       (void) self;
-       (void) irn;
-       return &ia32_irn_ops;
-}
-
-const arch_irn_handler_t ia32_irn_handler = {
-       ia32_get_irn_ops
-};
-
-const arch_irn_handler_t *ia32_get_irn_handler(const void *self)
-{
-       (void) self;
-       return &ia32_irn_handler;
-}
-
 int ia32_to_appear_in_schedule(void *block_env, const ir_node *irn)
 {
        (void) block_env;
@@ -1945,8 +1900,8 @@ static const arch_code_generator_if_t *ia32_get_code_generator_if(void *self)
  * Returns the estimated execution time of an ia32 irn.
  */
 static sched_timestep_t ia32_sched_exectime(void *env, const ir_node *irn) {
-       const arch_env_t *arch_env = env;
-       return is_ia32_irn(irn) ? ia32_get_op_estimated_cost(arch_get_irn_ops(arch_env, irn), irn) : 1;
+       (void) env;
+       return is_ia32_irn(irn) ? ia32_get_op_estimated_cost(irn) : 1;
 }
 
 list_sched_selector_t ia32_sched_selector;
@@ -2067,37 +2022,139 @@ static ir_graph **ia32_get_irg_list(const void *self, ir_graph ***irg_list)
  */
 static int ia32_is_psi_allowed(ir_node *sel, ir_node *phi_list, int i, int j)
 {
-       ir_node *phi;
-
-       (void)sel;
-       (void)i;
-       (void)j;
+       ir_node *phi, *left;
+       ir_node *cmp = NULL;
+       ir_mode *cmp_mode;
+
+       if (ia32_cg_config.use_cmov) {
+               /* we can't handle psis with 64bit compares yet */
+               if (is_Proj(sel)) {
+                       cmp = get_Proj_pred(sel);
+                       if (is_Cmp(cmp)) {
+                               left     = get_Cmp_left(cmp);
+                               cmp_mode = get_irn_mode(left);
+                               if (!mode_is_float(cmp_mode) && get_mode_size_bits(cmp_mode) > 32)
+                                       return 0;
+                       } else {
+                               cmp = NULL;
+                       }
+               }
 
-       if(!ia32_cg_config.use_cmov) {
-               /* TODO: we could still handle abs(x)... */
-               return 0;
-       }
+               if (ia32_cg_config.use_sse2 && cmp != NULL) {
+                       pn_Cmp pn   = get_Proj_proj(sel);
+                       ir_node *cl = get_Cmp_left(cmp);
+                       ir_node *cr = get_Cmp_right(cmp);
+
+                       /* check the Phi nodes: no 64bit and no floating point cmov */
+                       for (phi = phi_list; phi; phi = get_irn_link(phi)) {
+                               ir_mode *mode = get_irn_mode(phi);
+
+                               if (mode_is_float(mode)) {
+                                       /* check for Min, Max */
+                                       ir_node *t = get_Phi_pred(phi, i);
+                                       ir_node *f = get_Phi_pred(phi, j);
+                                       int res    = 0;
+
+                                       /* SSE2 supports Min & Max */
+                                       if (pn == pn_Cmp_Lt || pn == pn_Cmp_Le || pn == pn_Cmp_Ge || pn == pn_Cmp_Gt) {
+                                               if (cl == t && cr == f) {
+                                                       /* Psi(a <=/>= b, a, b) => MIN, MAX */
+                                                       res = 1;
+                                               } else if (cl == f && cr == t) {
+                                                       /* Psi(a <=/>= b, b, a) => MAX, MIN */
+                                                       res = 1;
+                                               }
+                                       }
+                                       if (! res)
+                                               return 0;
+
+                               } else if (get_mode_size_bits(mode) > 32)
+                                       return 0;
+                       }
+               } else {
+                       /* check the Phi nodes: no 64bit and no floating point cmov */
+                       for (phi = phi_list; phi; phi = get_irn_link(phi)) {
+                               ir_mode *mode = get_irn_mode(phi);
 
-       /* we can't handle psis with 64bit compares yet */
-       if(is_Proj(sel)) {
-               ir_node *pred = get_Proj_pred(sel);
-               if(is_Cmp(pred)) {
-                       ir_node *left     = get_Cmp_left(pred);
-                       ir_mode *cmp_mode = get_irn_mode(left);
-                       if(!mode_is_float(cmp_mode) && get_mode_size_bits(cmp_mode) > 32)
-                               return 0;
+                               if (mode_is_float(mode) || get_mode_size_bits(mode) > 32)
+                                       return 0;
+                       }
                }
-       }
 
-       /* check the Phi nodes */
-       for (phi = phi_list; phi; phi = get_irn_link(phi)) {
-               ir_mode *mode = get_irn_mode(phi);
+               return 1;
+       } else {
+               ir_node *cl, *cr;
+               pn_Cmp  pn;
 
-               if (mode_is_float(mode) || get_mode_size_bits(mode) > 32)
+               /* No cmov, only some special cases */
+               if (! is_Proj(sel))
+                       return 0;
+               cmp = get_Proj_pred(sel);
+               if (! is_Cmp(cmp))
                        return 0;
-       }
 
-       return 1;
+               left     = get_Cmp_left(cmp);
+               cmp_mode = get_irn_mode(left);
+
+               /* Now some supported cases here */
+               pn = get_Proj_proj(sel);
+               cl = get_Cmp_left(cmp);
+               cr = get_Cmp_right(cmp);
+
+               for (phi = phi_list; phi; phi = get_irn_link(phi)) {
+                       ir_mode *mode = get_irn_mode(phi);
+                       int res = 0;
+                       ir_node *t, *f;
+
+                       t = get_Phi_pred(phi, i);
+                       f = get_Phi_pred(phi, j);
+
+                       /* no floating point and no 64bit yet */
+                       if (mode_is_float(mode) || get_mode_size_bits(mode) > 32)
+                               return 0;
+
+                       if (is_Const(t) && is_Const(f)) {
+                               if ((is_Const_null(t) && is_Const_one(f)) || (is_Const_one(t) && is_Const_null(f))) {
+                                       /* always support Psi(x, C1, C2) */
+                                       res = 1;
+                               }
+                       } else if (pn == pn_Cmp_Lt || pn == pn_Cmp_Le || pn == pn_Cmp_Ge || pn == pn_Cmp_Gt) {
+                               if (0) {
+#if 0
+                               } else if (cl == t && cr == f) {
+                                       /* Psi(a <=/>= b, a, b) => Min, Max */
+                                       res = 1;
+                               } else if (cl == f && cr == t) {
+                                       /* Psi(a <=/>= b, b, a) => Max, Min */
+                                       res = 1;
+#endif
+                               } else if ((pn & pn_Cmp_Gt) && !mode_is_signed(mode) &&
+                                          is_Const(f) && is_Const_null(f) && is_Sub(t) &&
+                                          get_Sub_left(t) == cl && get_Sub_right(t) == cr) {
+                                       /* Psi(a >=u b, a - b, 0) unsigned Doz */
+                                       res = 1;
+                               } else if ((pn & pn_Cmp_Lt) && !mode_is_signed(mode) &&
+                                          is_Const(t) && is_Const_null(t) && is_Sub(f) &&
+                                          get_Sub_left(f) == cl && get_Sub_right(f) == cr) {
+                                       /* Psi(a <=u b, 0, a - b) unsigned Doz */
+                                       res = 1;
+                               } else if (is_Const(cr) && is_Const_null(cr)) {
+                                       if (cl == t && is_Minus(f) && get_Minus_op(f) == cl) {
+                                               /* Psi(a <=/>= 0 ? a : -a) Nabs/Abs */
+                                               res = 1;
+                                       } else if (cl == f && is_Minus(t) && get_Minus_op(t) == cl) {
+                                               /* Psi(a <=/>= 0 ? -a : a) Abs/Nabs */
+                                               res = 1;
+                                       }
+                               }
+                       }
+                       if (! res)
+                               return 0;
+               }
+               /* all checks passed */
+               return 1;
+       }
+       return 0;
 }
 
 /**
@@ -2150,7 +2207,7 @@ static lc_opt_enum_int_var_t gas_var = {
 static const lc_opt_table_entry_t ia32_options[] = {
        LC_OPT_ENT_ENUM_INT("gasmode", "set the GAS compatibility mode", &gas_var),
        LC_OPT_ENT_INT("stackalign", "set stack alignment for calls",
-                      &ia32_isa_template.arch_isa.stack_alignment),
+                      &ia32_isa_template.arch_env.stack_alignment),
        LC_OPT_LAST
 };
 
@@ -2161,7 +2218,6 @@ const arch_isa_if_t ia32_isa_if = {
        ia32_get_reg_class,
        ia32_get_reg_class_for_mode,
        ia32_get_call_abi,
-       ia32_get_irn_handler,
        ia32_get_code_generator_if,
        ia32_get_list_sched_selector,
        ia32_get_ilp_sched_selector,