sparc: be more conservative when moving memops around
[libfirm] / ir / opt / funccall.c
index 256e32c..f5970ba 100644 (file)
  * @file
  * @brief   Optimization of function calls.
  * @author  Michael Beck
- * @version $Id$
  */
 #include "config.h"
 
 #include "opt_init.h"
+#include <stdbool.h>
 
 #include "irnode_t.h"
 #include "irgraph_t.h"
@@ -89,8 +89,8 @@ static void collect_const_and_pure_calls(ir_node *node, void *env)
                /* set the link to NULL for all non-const/pure calls */
                set_irn_link(call, NULL);
                ptr = get_Call_ptr(call);
-               if (is_Global(ptr)) {
-                       ent = get_Global_entity(ptr);
+               if (is_SymConst_addr_ent(ptr)) {
+                       ent = get_SymConst_entity(ptr);
 
                        prop = get_entity_additional_properties(ent);
                        if ((prop & (mtp_property_const|mtp_property_pure)) == 0)
@@ -113,7 +113,7 @@ static void collect_const_and_pure_calls(ir_node *node, void *env)
                        or_prop  = 0;
                        for (i = 0; i < n_callees; ++i) {
                                ent = get_Call_callee(call, i);
-                               if (ent == unknown_entity) {
+                               if (is_unknown_entity(ent)) {
                                        /* we don't know which entity is called here */
                                        return;
                                }
@@ -238,12 +238,10 @@ static void fix_const_call_lists(ir_graph *irg, env_t *ctx)
                }
        }
 
-       /* changes were done ... */
-       set_irg_loopinfo_state(irg, loopinfo_cf_inconsistent);
-
        if (exc_changed) {
                /* ... including exception edges */
-               set_irg_doms_inconsistent(irg);
+               clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE
+                                  | IR_GRAPH_PROPERTY_CONSISTENT_LOOPINFO);
        }
 }  /* fix_const_call_list */
 
@@ -264,8 +262,8 @@ static void collect_nothrow_calls(ir_node *node, void *env)
                /* set the link to NULL for all non-const/pure calls */
                set_irn_link(call, NULL);
                ptr = get_Call_ptr(call);
-               if (is_Global(ptr)) {
-                       ent = get_Global_entity(ptr);
+               if (is_SymConst_addr_ent(ptr)) {
+                       ent = get_SymConst_entity(ptr);
 
                        prop = get_entity_additional_properties(ent);
                        if ((prop & mtp_property_nothrow) == 0)
@@ -287,7 +285,7 @@ static void collect_nothrow_calls(ir_node *node, void *env)
                        prop = mtp_property_nothrow;
                        for (i = 0; i < n_callees; ++i) {
                                ent = get_Call_callee(call, i);
-                               if (ent == unknown_entity) {
+                               if (is_unknown_entity(ent)) {
                                        /* we don't know which entity is called here */
                                        return;
                                }
@@ -373,11 +371,10 @@ static void fix_nothrow_call_list(ir_graph *irg, ir_node *call_list, ir_node *pr
        }
 
        /* changes were done ... */
-       set_irg_loopinfo_state(irg, loopinfo_cf_inconsistent);
-
        if (exc_changed) {
                /* ... including exception edges */
-               set_irg_doms_inconsistent(irg);
+               clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE
+                                  | IR_GRAPH_PROPERTY_CONSISTENT_LOOPINFO);
        }
 }  /* fix_nothrow_call_list */
 
@@ -508,8 +505,23 @@ static mtp_additional_properties check_const_or_pure_function(ir_graph *irg, int
 {
        ir_node *end, *endbl;
        int j;
+       ir_entity *entity   = get_irg_entity(irg);
+       ir_type   *type     = get_entity_type(entity);
+       size_t     n_params = get_method_n_params(type);
+       size_t     i;
+       mtp_additional_properties may_be_const = mtp_property_const;
        mtp_additional_properties prop = get_irg_additional_properties(irg);
 
+       /* libfirm handles aggregate parameters by passing around pointers to
+        * stuff in memory, so if we have compound parameters we are never const */
+       for (i = 0; i < n_params; ++i) {
+               ir_type *param = get_method_param_type(type, i);
+               if (is_compound_type(param)) {
+                       prop        &= ~mtp_property_const;
+                       may_be_const = mtp_no_property;
+               }
+       }
+
        if (prop & mtp_property_const) {
                /* already marked as a const function */
                return mtp_property_const;
@@ -533,7 +545,7 @@ static mtp_additional_properties check_const_or_pure_function(ir_graph *irg, int
 
        end   = get_irg_end(irg);
        endbl = get_nodes_block(end);
-       prop  = mtp_property_const;
+       prop  = may_be_const;
 
        ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
        inc_irg_visited(irg);
@@ -626,8 +638,13 @@ static void handle_const_Calls(env_t *ctx)
                if (ctx->float_const_call_list != NULL)
                        fix_const_call_lists(irg, ctx);
                ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
+
+               confirm_irg_properties(irg,
+                       IR_GRAPH_PROPERTIES_CONTROL_FLOW
+                       | IR_GRAPH_PROPERTY_ONE_RETURN
+                       | IR_GRAPH_PROPERTY_MANY_RETURNS);
        }
-}  /* handle_const_Calls */
+}
 
 /**
  * Handle calls to nothrow functions.
@@ -686,10 +703,9 @@ static mtp_additional_properties update_property(mtp_additional_properties orig_
 /**
  * Check if a node is stored.
  */
-static int is_stored(const ir_node *n)
+static bool is_stored(const ir_node *n)
 {
-       const ir_edge_t *edge;
-       const ir_node   *ptr;
+       const ir_node *ptr;
 
        foreach_out_edge(n, edge) {
                const ir_node *succ = get_edge_src_irn(edge);
@@ -702,19 +718,19 @@ static int is_stored(const ir_node *n)
                        break;
                case iro_Store:
                        if (get_Store_value(succ) == n)
-                               return 1;
+                               return true;
                        /* ok if its only the address input */
                        break;
                case iro_Sel:
                case iro_Cast:
                case iro_Confirm:
                        if (is_stored(succ))
-                               return 1;
+                               return true;
                        break;
                case iro_Call:
                        ptr = get_Call_ptr(succ);
-                       if (is_Global(ptr)) {
-                               ir_entity *ent = get_Global_entity(ptr);
+                       if (is_SymConst_addr_ent(ptr)) {
+                               ir_entity *ent = get_SymConst_entity(ptr);
                                size_t    i;
 
                                /* we know the called entity */
@@ -723,22 +739,22 @@ static int is_stored(const ir_node *n)
                                                /* n is the i'th param of the call */
                                                if (get_method_param_access(ent, i) & ptr_access_store) {
                                                        /* n is store in ent */
-                                                       return 1;
+                                                       return true;
                                                }
                                        }
                                }
                        } else {
                                /* unknown call address */
-                               return 1;
+                               return true;
                        }
                        break;
                default:
                        /* bad, potential alias */
-                       return 1;
+                       return true;
                }
        }
-       return 0;
-}  /* is_stored */
+       return false;
+}
 
 /**
  * Check that the return value of an irg is not stored anywhere.
@@ -750,7 +766,8 @@ static mtp_additional_properties check_stored_result(ir_graph *irg)
        ir_node  *end_blk = get_irg_end_block(irg);
        int      i;
        mtp_additional_properties res = ~mtp_no_property;
-       int      old_edges = edges_assure_kind(irg, EDGE_KIND_NORMAL);
+
+       assure_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUT_EDGES);
 
        for (i = get_Block_n_cfgpreds(end_blk) - 1; i >= 0; --i) {
                ir_node *pred = get_Block_cfgpred(end_blk, i);
@@ -769,8 +786,7 @@ static mtp_additional_properties check_stored_result(ir_graph *irg)
                }
        }
 finish:
-       if (! old_edges)
-               edges_deactivate_kind(irg, EDGE_KIND_NORMAL);
+       confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_ALL);
        return res;
 }
 
@@ -826,9 +842,9 @@ static mtp_additional_properties check_nothrow_or_malloc(ir_graph *irg, int top)
                                        } else if (is_Call(res)) {
                                                ir_node *ptr = get_Call_ptr(res);
 
-                                               if (is_Global(ptr)) {
+                                               if (is_SymConst_addr_ent(ptr)) {
                                                        /* a direct call */
-                                                       ir_entity *ent    = get_Global_entity(ptr);
+                                                       ir_entity *ent    = get_SymConst_entity(ptr);
                                                        ir_graph  *callee = get_entity_irg(ent);
 
                                                        if (callee == irg) {
@@ -854,7 +870,7 @@ static mtp_additional_properties check_nothrow_or_malloc(ir_graph *irg, int top)
 
                                                        for (i = 0; i < n_callees; ++i) {
                                                                ir_entity *ent = get_Call_callee(res, i);
-                                                               if (ent == unknown_entity) {
+                                                               if (is_unknown_entity(ent)) {
                                                                        /* we don't know which entity is called here */
                                                                        curr_prop &= ~mtp_property_malloc;
                                                                        break;
@@ -882,9 +898,9 @@ static mtp_additional_properties check_nothrow_or_malloc(ir_graph *irg, int top)
                        if (is_Call(pred)) {
                                ir_node *ptr = get_Call_ptr(pred);
 
-                               if (is_Global(ptr)) {
+                               if (is_SymConst_addr_ent(ptr)) {
                                        /* a direct call */
-                                       ir_entity *ent    = get_Global_entity(ptr);
+                                       ir_entity *ent    = get_SymConst_entity(ptr);
                                        ir_graph  *callee = get_entity_irg(ent);
 
                                        if (callee == irg) {
@@ -912,7 +928,7 @@ static mtp_additional_properties check_nothrow_or_malloc(ir_graph *irg, int top)
 
                                        for (i = 0; i < n_callees; ++i) {
                                                ir_entity *ent = get_Call_callee(pred, i);
-                                               if (ent == unknown_entity) {
+                                               if (is_unknown_entity(ent)) {
                                                        /* we don't know which entity is called here */
                                                        curr_prop &= ~mtp_property_nothrow;
                                                        break;
@@ -970,11 +986,13 @@ static mtp_additional_properties check_nothrow_or_malloc(ir_graph *irg, int top)
 static void check_for_possible_endless_loops(ir_graph *irg)
 {
        ir_loop *root_loop;
-       assure_cf_loop(irg);
+       assure_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_LOOPINFO);
 
        root_loop = get_irg_loop(irg);
        if (root_loop->flags & loop_outer_loop)
                add_irg_additional_properties(irg, mtp_property_has_loop);
+
+       confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_ALL);
 }
 
 /*
@@ -1037,9 +1055,10 @@ void optimize_funccalls(void)
        }
 
        handle_const_Calls(&ctx);
-       DB((dbg, LEVEL_1, "Detected %zu const graphs, %zu pure graphs.\n", num_const, num_pure));
+       DB((dbg, LEVEL_1, "Detected %zu const graphs, %zu pure graphs.\n",
+           num_const, num_pure));
        DB((dbg, LEVEL_1, "Optimizes %u(SymConst) + %u(Sel) calls to const functions.\n",
-                  ctx.n_calls_SymConst, ctx.n_calls_Sel));
+           ctx.n_calls_SymConst, ctx.n_calls_Sel));
 
        xfree(busy_set);
        xfree(ready_set);