inline_leave_functions(): uses new collect_calls2() and needs loop-info
[libfirm] / ir / be / benode.c
index 00abf3c..7c55b6a 100644 (file)
@@ -73,8 +73,8 @@ typedef struct {
 
 typedef struct {
        const arch_register_t *reg;
-       be_req_t req;
-       be_req_t in_req;
+       be_req_t               req;
+       be_req_t               in_req;
 } be_reg_data_t;
 
 /** The generic be nodes attribute type. */
@@ -87,33 +87,36 @@ typedef struct {
        be_node_attr_t node_attr;     /**< base attributes of every be node. */
        int            num_ret_vals;  /**< number of return values */
        unsigned       pop;           /**< number of bytes that should be popped */
+       int            emit_pop;      /**< if set, emit pop bytes, even if pop = 0 */
 } be_return_attr_t;
 
 /** The be_IncSP attribute type. */
 typedef struct {
        be_node_attr_t node_attr;   /**< base attributes of every be node. */
-       int offset;                 /**< The offset by which the stack shall be expanded/shrinked. */
+       int            offset;      /**< The offset by which the stack shall be expanded/shrinked. */
+       int            align;       /**< whether stack should be aligned after the
+                                        IncSP */
 } be_incsp_attr_t;
 
 /** The be_Frame attribute type. */
 typedef struct {
-       be_node_attr_t node_attr;   /**< base attributes of every be node. */
-       ir_entity *ent;
-       int offset;
+       be_node_attr_t  node_attr;   /**< base attributes of every be node. */
+       ir_entity      *ent;
+       int             offset;
 } be_frame_attr_t;
 
 /** The be_Call attribute type. */
 typedef struct {
-       be_node_attr_t node_attr;  /**< base attributes of every be node. */
-       ir_entity *ent;            /**< The called entity if this is a static call. */
-       unsigned pop;
-       ir_type *call_tp;          /**< The call type, copied from the original Call node. */
+       be_node_attr_t  node_attr;  /**< base attributes of every be node. */
+       ir_entity      *ent;        /**< The called entity if this is a static call. */
+       unsigned        pop;
+       ir_type        *call_tp;    /**< The call type, copied from the original Call node. */
 } be_call_attr_t;
 
 typedef struct {
-       be_node_attr_t node_attr;  /**< base attributes of every be node. */
-       ir_entity **in_entities;
-       ir_entity **out_entities;
+       be_node_attr_t   node_attr;  /**< base attributes of every be node. */
+       ir_entity      **in_entities;
+       ir_entity      **out_entities;
 } be_memperm_attr_t;
 
 ir_op *op_be_Spill;
@@ -149,6 +152,15 @@ static const ir_op_ops be_node_op_ops;
 #define K   irop_flag_keep
 #define M   irop_flag_uses_memory
 
+static int be_reqs_equal(const be_req_t *req1, const be_req_t *req2)
+{
+       if(!reg_reqs_equal(&req1->req, &req2->req))
+               return 0;
+       if(req1->flags != req2->flags)
+               return 0;
+
+       return 1;
+}
 
 /**
  * Compare two be node attributes.
@@ -164,8 +176,8 @@ static int _node_cmp_attr(const be_node_attr_t *a, const be_node_attr_t *b) {
        len = ARR_LEN(a->reg_data);
        for (i = 0; i < len; ++i) {
                if (a->reg_data[i].reg != b->reg_data[i].reg ||
-                               memcmp(&a->reg_data[i].in_req, &b->reg_data[i].in_req, sizeof(b->reg_data[i].in_req)) ||
-                           memcmp(&a->reg_data[i].req,    &b->reg_data[i].req,    sizeof(a->reg_data[i].req)))
+                               !be_reqs_equal(&a->reg_data[i].in_req, &b->reg_data[i].in_req) ||
+                           !be_reqs_equal(&a->reg_data[i].req,    &b->reg_data[i].req))
                        return 1;
        }
 
@@ -177,7 +189,7 @@ static int _node_cmp_attr(const be_node_attr_t *a, const be_node_attr_t *b) {
  *
  * @return zero if both nodes have identically attributes
  */
-static int node_cmp_attr(const ir_node *a, const ir_node *b) {
+static int node_cmp_attr(ir_node *a, ir_node *b) {
        const be_node_attr_t *a_attr = get_irn_attr_const(a);
        const be_node_attr_t *b_attr = get_irn_attr_const(b);
 
@@ -189,7 +201,7 @@ static int node_cmp_attr(const ir_node *a, const ir_node *b) {
  *
  * @return zero if both nodes have identically attributes
  */
-static int FrameAddr_cmp_attr(const ir_node *a, const ir_node *b) {
+static int FrameAddr_cmp_attr(ir_node *a, ir_node *b) {
        const be_frame_attr_t *a_attr = get_irn_attr_const(a);
        const be_frame_attr_t *b_attr = get_irn_attr_const(b);
 
@@ -204,7 +216,7 @@ static int FrameAddr_cmp_attr(const ir_node *a, const ir_node *b) {
  *
  * @return zero if both nodes have identically attributes
  */
-static int Return_cmp_attr(const ir_node *a, const ir_node *b) {
+static int Return_cmp_attr(ir_node *a, ir_node *b) {
        const be_return_attr_t *a_attr = get_irn_attr_const(a);
        const be_return_attr_t *b_attr = get_irn_attr_const(b);
 
@@ -212,6 +224,8 @@ static int Return_cmp_attr(const ir_node *a, const ir_node *b) {
                return 1;
        if (a_attr->pop != b_attr->pop)
                return 1;
+       if (a_attr->emit_pop != b_attr->emit_pop)
+               return 1;
 
        return _node_cmp_attr(&a_attr->node_attr, &b_attr->node_attr);
 }
@@ -221,7 +235,7 @@ static int Return_cmp_attr(const ir_node *a, const ir_node *b) {
  *
  * @return zero if both nodes have identically attributes
  */
-static int IncSP_cmp_attr(const ir_node *a, const ir_node *b) {
+static int IncSP_cmp_attr(ir_node *a, ir_node *b) {
        const be_incsp_attr_t *a_attr = get_irn_attr_const(a);
        const be_incsp_attr_t *b_attr = get_irn_attr_const(b);
 
@@ -236,7 +250,7 @@ static int IncSP_cmp_attr(const ir_node *a, const ir_node *b) {
  *
  * @return zero if both nodes have identically attributes
  */
-static int Call_cmp_attr(const ir_node *a, const ir_node *b) {
+static int Call_cmp_attr(ir_node *a, ir_node *b) {
        const be_call_attr_t *a_attr = get_irn_attr_const(a);
        const be_call_attr_t *b_attr = get_irn_attr_const(b);
 
@@ -695,25 +709,36 @@ ir_node *be_new_Return(dbg_info *dbg, ir_graph *irg, ir_node *block, int n_res,
        a = get_irn_attr(res);
        a->num_ret_vals = n_res;
        a->pop          = pop;
+       a->emit_pop     = 0;
 
        return res;
 }
 
 /* Returns the number of real returns values */
-int be_Return_get_n_rets(const ir_node *ret)
-{
+int be_Return_get_n_rets(const ir_node *ret) {
        const be_return_attr_t *a = get_irn_generic_attr_const(ret);
        return a->num_ret_vals;
 }
 
-unsigned be_Return_get_pop(const ir_node *ret)
-{
+/* return the number of bytes that should be popped from stack when executing the Return. */
+unsigned be_Return_get_pop(const ir_node *ret) {
        const be_return_attr_t *a = get_irn_generic_attr_const(ret);
        return a->pop;
 }
 
-int be_Return_append_node(ir_node *ret, ir_node *node)
-{
+/* return non-zero, if number of popped bytes must be always emitted */
+int be_Return_get_emit_pop(const ir_node *ret) {
+       const be_return_attr_t *a = get_irn_generic_attr_const(ret);
+       return a->emit_pop;
+}
+
+/* return non-zero, if number of popped bytes must be always emitted */
+void be_Return_set_emit_pop(ir_node *ret, int emit_pop) {
+       be_return_attr_t *a = get_irn_generic_attr(ret);
+       a->emit_pop = emit_pop;
+}
+
+int be_Return_append_node(ir_node *ret, ir_node *node) {
        int pos;
 
        pos = add_irn_n(ret, node);
@@ -722,16 +747,19 @@ int be_Return_append_node(ir_node *ret, ir_node *node)
        return pos;
 }
 
-ir_node *be_new_IncSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl, ir_node *old_sp, int offset)
+ir_node *be_new_IncSP(const arch_register_t *sp, ir_graph *irg, ir_node *bl,
+                      ir_node *old_sp, int offset, int align)
 {
        be_incsp_attr_t *a;
        ir_node *irn;
        ir_node *in[1];
 
        in[0]     = old_sp;
-       irn       = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->reg_class->mode, sizeof(in) / sizeof(in[0]), in);
+       irn       = new_ir_node(NULL, irg, bl, op_be_IncSP, sp->reg_class->mode,
+                               sizeof(in) / sizeof(in[0]), in);
        a         = init_node_attr(irn, 1);
        a->offset = offset;
+       a->align  = align;
 
        be_node_set_flags(irn, -1, arch_irn_flags_ignore | arch_irn_flags_modify_sp);
 
@@ -1110,6 +1138,13 @@ int be_get_IncSP_offset(const ir_node *irn)
        return a->offset;
 }
 
+int be_get_IncSP_align(const ir_node *irn)
+{
+       const be_incsp_attr_t *a = get_irn_attr_const(irn);
+       assert(be_is_IncSP(irn));
+       return a->align;
+}
+
 ir_node *be_spill(const arch_env_t *arch_env, ir_node *block, ir_node *irn)
 {
        ir_graph                    *irg       = get_irn_irg(block);