reference are integermode too for the backend
[libfirm] / ir / be / ia32 / ia32_transform.c
index a70c52e..41ae349 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
  *
  * This file is part of libFirm.
  *
@@ -55,6 +55,7 @@
 #include "../beutil.h"
 #include "../beirg_t.h"
 #include "../betranshlp.h"
+#include "../be_t.h"
 
 #include "bearch_ia32_t.h"
 #include "ia32_nodes_attr.h"
@@ -1339,33 +1340,28 @@ static ir_node *create_Div(ir_node *node)
        ir_node  *new_node;
        ir_mode  *mode;
        ir_node  *sign_extension;
-       int       has_exc;
        ia32_address_mode_t  am;
        ia32_address_t      *addr = &am.addr;
 
        /* the upper bits have random contents for smaller modes */
-       has_exc = 0;
        switch (get_irn_opcode(node)) {
        case iro_Div:
                op1     = get_Div_left(node);
                op2     = get_Div_right(node);
                mem     = get_Div_mem(node);
                mode    = get_Div_resmode(node);
-               has_exc = be_get_Proj_for_pn(node, pn_Div_X_except) != NULL;
                break;
        case iro_Mod:
                op1     = get_Mod_left(node);
                op2     = get_Mod_right(node);
                mem     = get_Mod_mem(node);
                mode    = get_Mod_resmode(node);
-               has_exc = be_get_Proj_for_pn(node, pn_Mod_X_except) != NULL;
                break;
        case iro_DivMod:
                op1     = get_DivMod_left(node);
                op2     = get_DivMod_right(node);
                mem     = get_DivMod_mem(node);
                mode    = get_DivMod_resmode(node);
-               has_exc = be_get_Proj_for_pn(node, pn_DivMod_X_except) != NULL;
                break;
        default:
                panic("invalid divmod node %+F", node);
@@ -1373,7 +1369,10 @@ static ir_node *create_Div(ir_node *node)
 
        match_arguments(&am, block, op1, op2, NULL, match_am);
 
-       if(!is_NoMem(mem)) {
+       /* Beware: We don't need a Sync, if the memory predecessor of the Div node
+          is the memory of the consumed address. We can have only the second op as address
+          in Div nodes, so check only op2. */
+       if(!is_NoMem(mem) && skip_Proj(mem) != skip_Proj(op2)) {
                new_mem = be_transform_node(mem);
                if(!is_NoMem(addr->mem)) {
                        ir_node *in[2];
@@ -1403,7 +1402,6 @@ static ir_node *create_Div(ir_node *node)
                                           sign_extension, am.new_op2);
        }
 
-       set_ia32_exc_label(new_node, has_exc);
        set_irn_pinned(new_node, get_irn_pinned(node));
 
        set_am_attributes(new_node, &am);
@@ -1849,8 +1847,6 @@ static ir_node *gen_Load(ir_node *node) {
                add_irn_dep(new_node, get_irg_frame(irg));
        }
 
-       set_ia32_exc_label(new_node,
-                          be_get_Proj_for_pn(node, pn_Load_X_except) != NULL);
        SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
 
        return new_node;
@@ -2025,7 +2021,7 @@ static ir_node *try_create_dest_am(ir_node *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);
+       unsigned  bits = get_mode_size_bits(mode);
        ir_node  *op1;
        ir_node  *op2;
        ir_node  *new_node;
@@ -2270,8 +2266,6 @@ static ir_node *gen_Store(ir_node *node)
        set_ia32_op_type(new_node, ia32_AddrModeD);
        set_ia32_ls_mode(new_node, mode);
 
-       set_ia32_exc_label(new_node,
-                          be_get_Proj_for_pn(node, pn_Store_X_except) != NULL);
        set_address(new_node, &addr);
        SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
 
@@ -2975,7 +2969,7 @@ static ir_node *gen_Conv(ir_node *node) {
        ir_node  *res       = NULL;
 
        if (src_mode == mode_b) {
-               assert(mode_is_int(tgt_mode));
+               assert(mode_is_int(tgt_mode) || mode_is_reference(tgt_mode));
                /* nothing to do, we already model bools as 0/1 ints */
                return be_transform_node(op);
        }
@@ -3250,7 +3244,7 @@ static void parse_asm_constraint(int pos, constraint_t *constraint, const char *
                /* a memory constraint: no need to do anything in backend about it
                 * (the dependencies are already respected by the memory edge of
                 * the node) */
-               constraint->req    = &no_register_req;
+               constraint->req = &no_register_req;
                return;
        }
 
@@ -3479,13 +3473,53 @@ static void parse_asm_constraint(int pos, constraint_t *constraint, const char *
 }
 
 static void parse_clobber(ir_node *node, int pos, constraint_t *constraint,
-                          const char *c)
+                          const char *clobber)
 {
-       (void) node;
+       ir_graph                    *irg  = get_irn_irg(node);
+       struct obstack              *obst = get_irg_obstack(irg);
+       const arch_register_t       *reg  = NULL;
+       int                          c;
+       size_t                       r;
+       arch_register_req_t         *req;
+       const arch_register_class_t *cls;
+       unsigned                    *limited;
+
        (void) pos;
-       (void) constraint;
-       (void) c;
-       panic("Clobbers not supported yet");
+
+       /* TODO: construct a hashmap instead of doing linear search for clobber
+        * register */
+       for(c = 0; c < N_CLASSES; ++c) {
+               cls = & ia32_reg_classes[c];
+               for(r = 0; r < cls->n_regs; ++r) {
+                       const arch_register_t *temp_reg = arch_register_for_index(cls, r);
+                       if(strcmp(temp_reg->name, clobber) == 0
+                                       || (c == CLASS_ia32_gp && strcmp(temp_reg->name+1, clobber) == 0)) {
+                               reg = temp_reg;
+                               break;
+                       }
+               }
+               if(reg != NULL)
+                       break;
+       }
+       if(reg == NULL) {
+               panic("Register '%s' mentioned in asm clobber is unknown\n", clobber);
+               return;
+       }
+
+       assert(reg->index < 32);
+
+       limited  = obstack_alloc(obst, sizeof(limited[0]));
+       *limited = 1 << reg->index;
+
+       req          = obstack_alloc(obst, sizeof(req[0]));
+       memset(req, 0, sizeof(req[0]));
+       req->type    = arch_register_req_type_limited;
+       req->cls     = cls;
+       req->limited = limited;
+
+       constraint->req                = req;
+       constraint->immediate_possible = 0;
+       constraint->immediate_type     = 0;
 }
 
 static int is_memory_op(const ir_asm_constraint *constraint)
@@ -3534,6 +3568,9 @@ static ir_node *gen_ASM(ir_node *node)
        n_out_constraints = get_ASM_n_output_constraints(node);
        n_clobbers        = get_ASM_n_clobbers(node);
        out_arity         = n_out_constraints + n_clobbers;
+       /* hack to keep space for mem proj */
+       if(n_clobbers > 0)
+               out_arity += 1;
 
        in_constraints  = get_ASM_input_constraints(node);
        out_constraints = get_ASM_output_constraints(node);
@@ -3556,14 +3593,19 @@ static ir_node *gen_ASM(ir_node *node)
 
                        if(constraint->pos > reg_map_size)
                                reg_map_size = constraint->pos;
-               } else {
+
+                       out_reg_reqs[i] = parsed_constraint.req;
+               } else if(i < out_arity - 1) {
                        ident *glob_id = clobbers [i - n_out_constraints];
+                       assert(glob_id != NULL);
                        c = get_id_str(glob_id);
                        parse_clobber(node, i, &parsed_constraint, c);
-               }
 
-               out_reg_reqs[i] = parsed_constraint.req;
+                       out_reg_reqs[i+1] = parsed_constraint.req;
+               }
        }
+       if(n_clobbers > 1)
+               out_reg_reqs[n_out_constraints] = &no_register_req;
 
        /* construct input constraints */
        in_reg_reqs = obstack_alloc(obst, arity * sizeof(in_reg_reqs[0]));
@@ -4169,104 +4211,83 @@ static ir_node *gen_ia32_l_ShrD(ir_node *node)
        return gen_lowered_64bit_shifts(node, high, low, count);
 }
 
-/**
- * In case SSE Unit is used, the node is transformed into a vfst + xLoad.
- */
-static ir_node *gen_ia32_l_X87toSSE(ir_node *node) {
-       ir_node         *block   = be_transform_node(get_nodes_block(node));
-       ir_node         *val     = get_irn_n(node, 1);
-       ir_node         *new_val = be_transform_node(val);
-       ir_node         *res     = NULL;
-       ir_graph        *irg     = current_ir_graph;
-       dbg_info        *dbgi;
-       ir_node         *noreg, *new_ptr, *new_mem;
-       ir_node         *ptr, *mem;
+static ir_node *gen_ia32_l_LLtoFloat(ir_node *node) {
+       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  *frame        = get_irg_frame(irg);
+       ir_node  *noreg        = ia32_new_NoReg_gp(env_cg);
+       ir_node  *nomem        = new_NoMem();
+       ir_node  *val_low      = get_irn_n(node, n_ia32_l_LLtoFloat_val_low);
+       ir_node  *val_high     = get_irn_n(node, n_ia32_l_LLtoFloat_val_high);
+       ir_node  *new_val_low  = be_transform_node(val_low);
+       ir_node  *new_val_high = be_transform_node(val_high);
+       ir_node  *in[2];
+       ir_node  *sync;
+       ir_node  *fild;
+       ir_node  *store_low;
+       ir_node  *store_high;
 
-       if (ia32_cg_config.use_sse2) {
-               return new_val;
-       }
-
-       mem     = get_irn_n(node, 2);
-       new_mem = be_transform_node(mem);
-       ptr     = get_irn_n(node, 0);
-       new_ptr = be_transform_node(ptr);
-       noreg   = ia32_new_NoReg_gp(env_cg);
-       dbgi    = get_irn_dbg_info(node);
-
-       /* Store x87 -> MEM */
-       res = new_rd_ia32_vfst(dbgi, irg, block, new_ptr, noreg, new_mem, new_val,
-                              get_ia32_ls_mode(node));
-       set_ia32_frame_ent(res, get_ia32_frame_ent(node));
-       set_ia32_use_frame(res);
-       set_ia32_ls_mode(res, get_ia32_ls_mode(node));
-       set_ia32_op_type(res, ia32_AddrModeD);
-
-       /* Load MEM -> SSE */
-       res = new_rd_ia32_xLoad(dbgi, irg, block, new_ptr, noreg, res,
-                               get_ia32_ls_mode(node));
-       set_ia32_frame_ent(res, get_ia32_frame_ent(node));
-       set_ia32_use_frame(res);
-       set_ia32_op_type(res, ia32_AddrModeS);
-       res = new_rd_Proj(dbgi, irg, block, res, mode_xmm, pn_ia32_xLoad_res);
+       if(!mode_is_signed(get_irn_mode(val_high))) {
+               panic("unsigned long long -> float not supported yet (%+F)", node);
+       }
 
-       return res;
+       /* do a store */
+       store_low = new_rd_ia32_Store(dbgi, irg, block, frame, noreg, nomem,
+                                     new_val_low);
+       store_high = new_rd_ia32_Store(dbgi, irg, block, frame, noreg, nomem,
+                                      new_val_high);
+       SET_IA32_ORIG_NODE(store_low, ia32_get_old_node_name(env_cg, node));
+       SET_IA32_ORIG_NODE(store_high, ia32_get_old_node_name(env_cg, node));
+
+       set_ia32_use_frame(store_low);
+       set_ia32_use_frame(store_high);
+       set_ia32_op_type(store_low, ia32_AddrModeD);
+       set_ia32_op_type(store_high, ia32_AddrModeD);
+       set_ia32_ls_mode(store_low, mode_Iu);
+       set_ia32_ls_mode(store_high, mode_Is);
+       add_ia32_am_offs_int(store_high, 4);
+
+       in[0] = store_low;
+       in[1] = store_high;
+       sync  = new_rd_Sync(dbgi, irg, block, 2, in);
+
+       /* do a fild */
+       fild = new_rd_ia32_vfild(dbgi, irg, block, frame, noreg, sync);
+
+       set_ia32_use_frame(fild);
+       set_ia32_op_type(fild, ia32_AddrModeS);
+       set_ia32_ls_mode(fild, mode_Ls);
+
+       SET_IA32_ORIG_NODE(fild, ia32_get_old_node_name(env_cg, node));
+
+       return new_r_Proj(irg, block, fild, mode_vfp, pn_ia32_vfild_res);
 }
 
-/**
- * In case SSE Unit is used, the node is transformed into a xStore + vfld.
- */
-static ir_node *gen_ia32_l_SSEtoX87(ir_node *node) {
-       ir_node         *block   = be_transform_node(get_nodes_block(node));
-       ir_node         *val     = get_irn_n(node, 1);
-       ir_node         *new_val = be_transform_node(val);
-       ir_graph        *irg     = current_ir_graph;
-       ir_node         *res     = NULL;
-       ir_entity       *fent    = get_ia32_frame_ent(node);
-       ir_mode         *lsmode  = get_ia32_ls_mode(node);
-       int             offs     = 0;
-       ir_node         *noreg, *new_ptr, *new_mem;
-       ir_node         *ptr, *mem;
-       dbg_info        *dbgi;
-
-       if (! ia32_cg_config.use_sse2) {
-               /* SSE unit is not used -> skip this node. */
-               return new_val;
-       }
-
-       ptr     = get_irn_n(node, 0);
-       new_ptr = be_transform_node(ptr);
-       mem     = get_irn_n(node, 2);
-       new_mem = be_transform_node(mem);
-       noreg   = ia32_new_NoReg_gp(env_cg);
-       dbgi    = get_irn_dbg_info(node);
-
-       /* Store SSE -> MEM */
-       if (is_ia32_xLoad(skip_Proj(new_val))) {
-               ir_node *ld = skip_Proj(new_val);
-
-               /* we can vfld the value directly into the fpu */
-               fent = get_ia32_frame_ent(ld);
-               ptr  = get_irn_n(ld, 0);
-               offs = get_ia32_am_offs_int(ld);
-       } else {
-               res = new_rd_ia32_xStore(dbgi, irg, block, new_ptr, noreg, new_mem,
-                                        new_val);
-               set_ia32_frame_ent(res, fent);
-               set_ia32_use_frame(res);
-               set_ia32_ls_mode(res, lsmode);
-               set_ia32_op_type(res, ia32_AddrModeD);
-               mem = res;
-       }
-
-       /* Load MEM -> x87 */
-       res = new_rd_ia32_vfld(dbgi, irg, block, new_ptr, noreg, new_mem, lsmode);
-       set_ia32_frame_ent(res, fent);
-       set_ia32_use_frame(res);
-       add_ia32_am_offs_int(res, offs);
-       set_ia32_op_type(res, ia32_AddrModeS);
-       res = new_rd_Proj(dbgi, irg, block, res, mode_vfp, pn_ia32_vfld_res);
+static ir_node *gen_ia32_l_FloattoLL(ir_node *node) {
+       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  *frame      = get_irg_frame(irg);
+       ir_node  *noreg      = ia32_new_NoReg_gp(env_cg);
+       ir_node  *nomem      = new_NoMem();
+       ir_node  *val        = get_irn_n(node, n_ia32_l_FloattoLL_val);
+       ir_node  *new_val    = be_transform_node(val);
+       ir_node  *trunc_mode = ia32_new_Fpu_truncate(env_cg);
 
-       return res;
+       ir_node  *fist;
+
+       /* do a fist */
+       fist = new_rd_ia32_vfist(dbgi, irg, block, frame, noreg, nomem, new_val,
+                                trunc_mode);
+       SET_IA32_ORIG_NODE(fist, ia32_get_old_node_name(env_cg, node));
+       set_ia32_use_frame(fist);
+       set_ia32_op_type(fist, ia32_AddrModeD);
+       set_ia32_ls_mode(fist, mode_Ls);
+
+       return fist;
 }
 
 /**
@@ -4277,6 +4298,40 @@ static ir_node *bad_transform(ir_node *node) {
        return NULL;
 }
 
+static ir_node *gen_Proj_l_FloattoLL(ir_node *node) {
+       ir_graph *irg      = current_ir_graph;
+       ir_node  *block    = be_transform_node(get_nodes_block(node));
+       ir_node  *pred     = get_Proj_pred(node);
+       ir_node  *new_pred = be_transform_node(pred);
+       ir_node  *frame    = get_irg_frame(irg);
+       ir_node  *noreg    = ia32_new_NoReg_gp(env_cg);
+       dbg_info *dbgi     = get_irn_dbg_info(node);
+       long      pn       = get_Proj_proj(node);
+       ir_node  *load;
+       ir_node  *proj;
+       ia32_attr_t *attr;
+
+       load = new_rd_ia32_Load(dbgi, irg, block, frame, noreg, new_pred);
+       SET_IA32_ORIG_NODE(load, ia32_get_old_node_name(env_cg, node));
+       set_ia32_use_frame(load);
+       set_ia32_op_type(load, ia32_AddrModeS);
+       set_ia32_ls_mode(load, mode_Iu);
+       /* we need a 64bit stackslot (fist stores 64bit) even though we only load
+        * 32 bit from it with this particular load */
+       attr = get_ia32_attr(load);
+       attr->data.need_64bit_stackent = 1;
+
+       if (pn == pn_ia32_l_FloattoLL_res_high) {
+               add_ia32_am_offs_int(load, 4);
+       } else {
+               assert(pn == pn_ia32_l_FloattoLL_res_low);
+       }
+
+       proj = new_r_Proj(irg, block, load, mode_Iu, pn_ia32_Load_res);
+
+       return proj;
+}
+
 /**
  * Transform the Projs of an AddSP.
  */
@@ -4361,15 +4416,22 @@ static ir_node *gen_Proj_Load(ir_node *node) {
        /* renumber the proj */
        new_pred = be_transform_node(pred);
        if (is_ia32_Load(new_pred)) {
-               if (proj == pn_Load_res) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu,
-                                          pn_ia32_Load_res);
-               } else if (proj == pn_Load_M) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M,
-                                          pn_ia32_Load_M);
+               switch (proj) {
+               case pn_Load_res:
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_ia32_Load_res);
+               case pn_Load_M:
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_Load_M);
+               case pn_Load_X_regular:
+                       return new_rd_Jmp(dbgi, irg, block);
+               case pn_Load_X_except:
+                       /* This Load might raise an exception. Mark it. */
+                       set_ia32_exc_label(new_pred, 1);
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_X, pn_ia32_Load_X_exc);
+               default:
+                       break;
                }
-       } else if(is_ia32_Conv_I2I(new_pred)
-                       || is_ia32_Conv_I2I8Bit(new_pred)) {
+       } else if (is_ia32_Conv_I2I(new_pred) ||
+                  is_ia32_Conv_I2I8Bit(new_pred)) {
                set_irn_mode(new_pred, mode_T);
                if (proj == pn_Load_res) {
                        return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_ia32_res);
@@ -4377,20 +4439,34 @@ static ir_node *gen_Proj_Load(ir_node *node) {
                        return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_mem);
                }
        } else if (is_ia32_xLoad(new_pred)) {
-               if (proj == pn_Load_res) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_xmm,
-                                          pn_ia32_xLoad_res);
-               } else if (proj == pn_Load_M) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M,
-                                          pn_ia32_xLoad_M);
+               switch (proj) {
+               case pn_Load_res:
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_xmm, pn_ia32_xLoad_res);
+               case pn_Load_M:
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_xLoad_M);
+               case pn_Load_X_regular:
+                       return new_rd_Jmp(dbgi, irg, block);
+               case pn_Load_X_except:
+                       /* This Load might raise an exception. Mark it. */
+                       set_ia32_exc_label(new_pred, 1);
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_X, pn_ia32_xLoad_X_exc);
+               default:
+                       break;
                }
        } else if (is_ia32_vfld(new_pred)) {
-               if (proj == pn_Load_res) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_vfp,
-                                          pn_ia32_vfld_res);
-               } else if (proj == pn_Load_M) {
-                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M,
-                                          pn_ia32_vfld_M);
+               switch (proj) {
+               case pn_Load_res:
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_vfp, pn_ia32_vfld_res);
+               case pn_Load_M:
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_vfld_M);
+               case pn_Load_X_regular:
+                       return new_rd_Jmp(dbgi, irg, block);
+               case pn_Load_X_except:
+                       /* This Load might raise an exception. Mark it. */
+                       set_ia32_exc_label(new_pred, 1);
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_X, pn_ia32_xLoad_X_exc);
+               default:
+                       break;
                }
        } else {
                /* can happen for ProJMs when source address mode happened for the
@@ -4399,7 +4475,7 @@ static ir_node *gen_Proj_Load(ir_node *node) {
                /* however it should not be the result proj, as that would mean the
                   load had multiple users and should not have been used for
                   SourceAM */
-               if(proj != pn_Load_M) {
+               if (proj != pn_Load_M) {
                        panic("internal error: transformed node not a Load");
                }
                return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, 1);
@@ -4430,6 +4506,11 @@ static ir_node *gen_Proj_DivMod(ir_node *node) {
                        return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_Div_M);
                case pn_Div_res:
                        return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_ia32_Div_div_res);
+               case pn_Div_X_regular:
+                       return new_rd_Jmp(dbgi, irg, block);
+               case pn_Div_X_except:
+                       set_ia32_exc_label(new_pred, 1);
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_X, pn_ia32_Div_X_exc);
                default:
                        break;
                }
@@ -4440,6 +4521,9 @@ static ir_node *gen_Proj_DivMod(ir_node *node) {
                        return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_Div_M);
                case pn_Mod_res:
                        return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_ia32_Div_mod_res);
+               case pn_Mod_X_except:
+                       set_ia32_exc_label(new_pred, 1);
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_X, pn_ia32_Div_X_exc);
                default:
                        break;
                }
@@ -4452,6 +4536,11 @@ static ir_node *gen_Proj_DivMod(ir_node *node) {
                        return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_ia32_Div_div_res);
                case pn_DivMod_res_mod:
                        return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_ia32_Div_mod_res);
+               case pn_DivMod_X_regular:
+                       return new_rd_Jmp(dbgi, irg, block);
+               case pn_DivMod_X_except:
+                       set_ia32_exc_label(new_pred, 1);
+                       return new_rd_Proj(dbgi, irg, block, new_pred, mode_X, pn_ia32_Div_X_exc);
                default:
                        break;
                }
@@ -4693,6 +4782,8 @@ static ir_node *gen_Proj(ir_node *node) {
                if (node == be_get_old_anchor(anchor_tls)) {
                        return gen_Proj_tls(node);
                }
+       } else if (is_ia32_l_FloattoLL(pred)) {
+               return gen_Proj_l_FloattoLL(node);
 #ifdef FIRM_EXT_GRS
        } else if(!is_ia32_irn(pred)) { // Quick hack for SIMD optimization
 #else
@@ -4779,8 +4870,8 @@ static void register_transformers(void)
        GEN(ia32_l_Load);
        GEN(ia32_l_vfist);
        GEN(ia32_l_Store);
-       GEN(ia32_l_X87toSSE);
-       GEN(ia32_l_SSEtoX87);
+       GEN(ia32_l_LLtoFloat);
+       GEN(ia32_l_FloattoLL);
 
        GEN(Const);
        GEN(SymConst);
@@ -4920,7 +5011,9 @@ void ia32_transform_graph(ia32_code_gen_t *cg) {
        env_cg       = cg;
        initial_fpcw = NULL;
 
+BE_TIMER_PUSH(t_heights);
        heights      = heights_new(irg);
+BE_TIMER_POP(t_heights);
        ia32_calculate_non_address_mode_nodes(cg->birg);
 
        /* the transform phase is not safe for CSE (yet) because several nodes get