re-added stack pointer to spills and reloads
[libfirm] / ir / be / benode.c
index 2f32ea5..4e5a45a 100644 (file)
@@ -338,25 +338,38 @@ be_node_set_irn_reg(const void *_self, ir_node *irn, const arch_register_t *reg)
 }
 
 
-ir_node *be_new_Spill(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *to_spill)
+ir_node *be_new_Spill(const arch_register_class_t *cls, const arch_register_class_t *cls_frame,
+       ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *to_spill)
 {
        be_frame_attr_t *a;
+       ir_node         *in[2];
        ir_node         *res;
 
-       res       = new_ir_node(NULL, irg, bl, op_be_Spill, mode_M, 1, &to_spill);
+       in[0]     = frame;
+       in[1]     = to_spill;
+       res       = new_ir_node(NULL, irg, bl, op_be_Spill, mode_M, 2, in);
        a         = init_node_attr(res, 2);
        a->ent    = NULL;
        a->offset = 0;
 
+       be_node_set_reg_class(res, be_pos_Spill_frame, cls_frame);
        be_node_set_reg_class(res, be_pos_Spill_val, cls);
        return res;
 }
 
-ir_node *be_new_Reload(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, ir_node *mem, ir_mode *mode)
+ir_node *be_new_Reload(const arch_register_class_t *cls, const arch_register_class_t *cls_frame,
+       ir_graph *irg, ir_node *bl, ir_node *frame, ir_node *mem, ir_mode *mode)
 {
-       ir_node *res = new_ir_node(NULL, irg, bl, op_be_Reload, mode, 1, &mem);
+       ir_node *in[2];
+       ir_node *res;
+
+       in[0] = frame;
+       in[1] = mem;
+       res   = new_ir_node(NULL, irg, bl, op_be_Reload, mode, 2, in);
+
        init_node_attr(res, 2);
        be_node_set_reg_class(res, -1, cls);
+       be_node_set_reg_class(res, be_pos_Reload_frame, cls_frame);
        be_node_set_flags(res, -1, arch_irn_flags_rematerializable);
        return res;
 }
@@ -367,11 +380,22 @@ ir_node *be_get_Reload_mem(const ir_node *irn)
        return get_irn_n(irn, be_pos_Reload_mem);
 }
 
+ir_node *be_get_Reload_frame(const ir_node *irn)
+{
+       assert(be_is_Reload(irn));
+       return get_irn_n(irn, be_pos_Reload_frame);
+}
+
 ir_node *be_get_Spill_val(const ir_node *irn)
 {
        assert(be_is_Spill(irn));
        return get_irn_n(irn, be_pos_Spill_val);
 }
+ir_node *be_get_Spill_frame(const ir_node *irn)
+{
+       assert(be_is_Spill(irn));
+       return get_irn_n(irn, be_pos_Spill_frame);
+}
 
 ir_node *be_new_Perm(const arch_register_class_t *cls, ir_graph *irg, ir_node *bl, int n, ir_node *in[])
 {
@@ -945,27 +969,30 @@ int be_get_IncSP_offset(const ir_node *irn)
 
 ir_node *be_spill(const arch_env_t *arch_env, ir_node *irn)
 {
-       ir_node                     *bl  = get_nodes_block(irn);
-       ir_graph                    *irg = get_irn_irg(bl);
-       const arch_register_class_t *cls = arch_get_irn_reg_class(arch_env, irn, -1);
+       ir_node                     *bl        = get_nodes_block(irn);
+       ir_graph                    *irg       = get_irn_irg(bl);
+       ir_node                     *frame     = get_irg_frame(irg);
+       const arch_register_class_t *cls       = arch_get_irn_reg_class(arch_env, irn, -1);
+       const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
        ir_node                     *spill;
 
-
-       spill = be_new_Spill(cls, irg, bl, irn);
+       spill = be_new_Spill(cls, cls_frame, irg, bl, frame, irn);
        return spill;
 }
 
 ir_node *be_reload(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *insert, ir_mode *mode, ir_node *spill)
 {
        ir_node  *reload;
-       ir_node  *bl  = is_Block(insert) ? insert : get_nodes_block(insert);
-       ir_graph *irg = get_irn_irg(bl);
+       ir_node  *bl    = is_Block(insert) ? insert : get_nodes_block(insert);
+       ir_graph *irg   = get_irn_irg(bl);
+       ir_node  *frame = get_irg_frame(irg);
+       const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
 
        assert(be_is_Spill(spill) || (is_Phi(spill) && get_irn_mode(spill) == mode_M));
 
-       reload = be_new_Reload(cls, irg, bl, spill, mode);
+       reload = be_new_Reload(cls, cls_frame, irg, bl, frame, spill, mode);
 
-       if(is_Block(insert)) {
+       if (is_Block(insert)) {
                insert = sched_skip(insert, 0, sched_skip_cf_predicator, (void *) arch_env);
                sched_add_after(insert, reload);
        }
@@ -1026,17 +1053,29 @@ be_node_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_nod
 {
        int out_pos = pos;
 
-       if(pos < 0) {
-               if(get_irn_mode(irn) == mode_T)
+       if (pos < 0) {
+               if (get_irn_mode(irn) == mode_T)
                        return NULL;
 
-               out_pos = redir_proj((const ir_node **) &irn, pos);
+               out_pos = redir_proj((const ir_node **)&irn, pos);
                assert(is_be_node(irn));
                return put_out_reg_req(req, irn, out_pos);
        }
 
        else {
-               return is_be_node(irn) ? put_in_reg_req(req, irn, pos) : NULL;
+               if (is_be_node(irn)) {
+                       /*
+                               For spills and reloads, we return "none" as requirement for frame pointer,
+                               so every input is ok. Some backends need this (e.g. STA). We use an arbitrary
+                               large number as pos, so put_in_reg_req will return "none" as requirement.
+                       */
+                       if ((be_is_Spill(irn)  && pos == be_pos_Spill_frame) ||
+                               (be_is_Reload(irn) && pos == be_pos_Reload_frame))
+                               return put_in_reg_req(req, irn, INT_MAX);
+                       else
+                               return put_in_reg_req(req, irn, pos);
+               }
+               return NULL;
        }
 
        return req;