prototypes should override non-prototypes
[cparser] / driver / firm_opt.c
index 5844b1d..c33995c 100644 (file)
@@ -9,10 +9,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <libfirm/firm.h>
-
-#ifdef FIRM_BACKEND
 #include <libfirm/be.h>
-#endif /* FIRM_BACKEND */
 
 
 #include "firm_opt.h"
 #include "firm_cmdline.h"
 #include "firm_timing.h"
 
+#ifdef _WIN32
+#define snprintf _snprintf
+#endif
+
 #if defined(_DEBUG) || defined(FIRM_DEBUG)
 #define DBG(x)  dbg_printf x
 #else
 #define CHECK_ALL(cond)                                 \
   do {                                                  \
     if (cond) {                                         \
-      int i                                           \
+      int ii;                                           \
       timer_push(TV_VERIFY);                            \
-      for (i = get_irp_n_irgs() - 1; i >= 0; --i)       \
-        irg_verify(get_irp_irg(i), VRFY_ENFORCE_SSA);   \
+      for (ii = get_irp_n_irgs() - 1; ii >= 0; --ii)    \
+        irg_verify(get_irp_irg(ii), VRFY_ENFORCE_SSA);  \
       timer_pop();                                      \
     }                                                   \
   } while (0)
@@ -107,7 +108,8 @@ static const ir_settings_arch_dep_t *ad_param = NULL;
 static create_intrinsic_fkt *arch_create_intrinsic = NULL;
 static void *create_intrinsic_ctx = NULL;
 static const ir_settings_if_conv_t *if_conv_info = NULL;
-static unsigned char be_support_inline_asm = FALSE;
+
+ir_mode *firm_imm_fp_mode = NULL;
 
 /* entities of runtime functions */
 ir_entity_ptr rts_entities[rts_max];
@@ -141,6 +143,7 @@ static void rts_map(void) {
   } mapper[] = {
     /* integer */
     { &rts_entities[rts_abs],     i_mapper_abs },
+       { &rts_entities[rts_alloca],  i_mapper_alloca },
     { &rts_entities[rts_labs],    i_mapper_abs },
     { &rts_entities[rts_llabs],   i_mapper_abs },
     { &rts_entities[rts_imaxabs], i_mapper_abs },
@@ -218,7 +221,7 @@ static void rts_map(void) {
   i_record rec[sizeof(mapper)/sizeof(mapper[0])];
   unsigned i, n_map;
 
-  for (i = n_map = 0; i < sizeof(mapper)/sizeof(mapper[0]); ++i)
+  for (i = n_map = 0; i < sizeof(mapper)/sizeof(mapper[0]); ++i) {
     if (*mapper[i].ent != NULL) {
       rec[n_map].i_call.kind     = INTRINSIC_CALL;
       rec[n_map].i_call.i_ent    = *mapper[i].ent;
@@ -226,7 +229,8 @@ static void rts_map(void) {
       rec[n_map].i_call.ctx      = NULL;
       rec[n_map].i_call.link     = NULL;
       ++n_map;
-  }  /* if */
+    }  /* if */
+  }
   if (n_map > 0)
     lower_intrinsics(rec, n_map, /* part_block_used=*/0);
 }  /* rts_map */
@@ -285,11 +289,11 @@ static void dump_all_count(const char *const suffix)
  */
 static void do_firm_optimizations(const char *input_filename, int firm_const_exists)
 {
-  ir_entity **keep_methods;
-  int i, arr_len;
+  int      i;
   ir_graph *irg;
   unsigned aa_opt;
 
+  /* FIXME: cloning might ADD new graphs. */
   irg_dump_no = calloc(get_irp_last_idx(), sizeof(*irg_dump_no));
 
   set_opt_strength_red(firm_opt.strength_red);
@@ -308,6 +312,9 @@ static void do_firm_optimizations(const char *input_filename, int firm_const_exi
   timer_start(TV_ALL_OPT);
 
   if (firm_opt.remove_unused) {
+       ir_entity **keep_methods;
+       int         arr_len;
+
     /* Analysis that finds the free methods,
        i.e. methods that are dereferenced.
        Optimizes polymorphic calls :-). */
@@ -325,35 +332,32 @@ static void do_firm_optimizations(const char *input_filename, int firm_const_exi
     CHECK_ALL(firm_opt.check_all);
   }
 
-  if (firm_opt.tail_rec) {
-    timer_push(TV_TAIL_REC);
-      opt_tail_recursion();
+  /* first step: kill dead code */
+  for (i = 0; i < get_irp_n_irgs(); i++) {
+    irg = current_ir_graph = get_irp_irg(i);
+    /* Confirm construction currently can only handle blocks with only one control
+       flow predecessor. Calling optimize_cf here removes Bad predecessors and help
+       the optimization of switch constructs. */
+    timer_push(TV_CF_OPT);
+      optimize_graph_df(irg);
+      optimize_cf(irg);
     timer_pop();
-
-    DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "tail_rec");
-    CHECK_ALL(firm_opt.check_all);
   }
 
   if (firm_opt.func_calls) {
     timer_push(TV_REAL_FUNC_CALL);
-      optimize_funccalls(firm_const_exists);
+      optimize_funccalls(firm_const_exists, NULL);
     timer_pop();
     DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "func_call");
     CHECK_ALL(firm_opt.check_all);
   }
 
-  if (firm_opt.do_inline) {
-    timer_push(TV_INLINE);
-      inline_leave_functions(500, 80, 30, FALSE);
-    timer_pop();
-    DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "inl");
-    CHECK_ALL(firm_opt.check_all);
-  }
+  /* do lowering on the const code irg */
+  lower_const_code();
 
   for (i = 0; i < get_irp_n_irgs(); i++) {
     irg = current_ir_graph = get_irp_irg(i);
 
-
 #ifdef FIRM_EXT_GRS
   /* If SIMD optimization is on, make sure we have only 1 return */
   if (firm_ext_grs.create_pattern || firm_ext_grs.simd_opt)
@@ -385,12 +389,26 @@ static void do_firm_optimizations(const char *input_filename, int firm_const_exi
     DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "reassoc");
     CHECK_ONE(firm_opt.check_all, irg);
 
+    compute_doms(irg);
+    CHECK_ONE(firm_opt.check_all, irg);
+
+    if (firm_opt.code_place) {
+      timer_push(TV_CODE_PLACE);
+        set_opt_global_cse(1);
+        optimize_graph_df(irg);
+        place_code(irg);
+        set_opt_global_cse(0);
+      timer_pop();
+      DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "place");
+      CHECK_ONE(firm_opt.check_all, irg);
+    }
+
     if (firm_opt.confirm) {
       /* Confirm construction currently can only handle blocks with only one control
          flow predecessor. Calling optimize_cf here removes Bad predecessors and help
          the optimization of switch constructs. */
       timer_push(TV_CF_OPT);
-        optimize_cf(irg);
+      optimize_cf(irg);
       timer_pop();
       DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "cfopt");
       CHECK_ONE(firm_opt.check_all, irg);
@@ -399,31 +417,18 @@ static void do_firm_optimizations(const char *input_filename, int firm_const_exi
       timer_pop();
       DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "confirms");
       CHECK_ONE(firm_opt.check_all, irg);
-    }
 
-    timer_push(TV_LOCAL_OPT);
-      optimize_graph_df(irg);
-    timer_pop();
-    DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "lopt");
-    CHECK_ONE(firm_opt.check_all, irg);
-
-    compute_doms(irg);
-    CHECK_ONE(firm_opt.check_all, irg);
-
-    if (firm_opt.code_place) {
-      timer_push(TV_CODE_PLACE);
-        set_opt_global_cse(1);
+      timer_push(TV_LOCAL_OPT);
         optimize_graph_df(irg);
-        place_code(irg);
-        set_opt_global_cse(0);
       timer_pop();
-      DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "place");
+      DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "lopt");
       CHECK_ONE(firm_opt.check_all, irg);
     }
 
     if (firm_opt.luffig) {
       opt_ldst2(irg);
       DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "ldst2");
+      CHECK_ONE(firm_opt.check_all, irg);
     }
 
     timer_push(TV_CF_OPT);
@@ -432,13 +437,6 @@ static void do_firm_optimizations(const char *input_filename, int firm_const_exi
     DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "cfopt");
     CHECK_ONE(firm_opt.check_all, irg);
 
-    /* should we really remove the Confirm here? */
-    if (firm_opt.confirm) {
-      timer_push(TV_CONFIRM_CREATE);
-        remove_confirms(irg);
-      timer_pop();
-    }
-
     irg_verify(irg, VRFY_ENFORCE_SSA);
     if (firm_opt.gvn_pre) {
       do_gvn_pre(irg);
@@ -447,23 +445,15 @@ static void do_firm_optimizations(const char *input_filename, int firm_const_exi
       irg_verify(irg, VRFY_ENFORCE_SSA);
     }
 
-    if (firm_opt.loop_unrolling) {
-      timer_push(TV_LOOP_UNROLL);
-        optimize_loop_unrolling(irg);
-      timer_pop();
-      DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "loop");
-      CHECK_ONE(firm_opt.check_all, irg);
-       }
-
     if (firm_opt.load_store) {
       timer_push(TV_LOAD_STORE);
         optimize_load_store(irg);
       timer_pop();
       DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "ldst");
       CHECK_ONE(firm_opt.check_all, irg);
-       }
+    }
 
-    lower_highlevel_graph(irg);
+    lower_highlevel_graph(irg, firm_opt.lower_bitfields);
 
     if (firm_opt.deconv) {
       timer_push(TV_DECONV);
@@ -481,6 +471,13 @@ static void do_firm_optimizations(const char *input_filename, int firm_const_exi
       CHECK_ONE(firm_opt.check_all, irg);
     }
 
+    /* should we really remove the Confirm here? */
+    if (firm_opt.confirm) {
+      timer_push(TV_CONFIRM_CREATE);
+      remove_confirms(irg);
+      timer_pop();
+    }
+
     compute_doms(irg);
     compute_postdoms(irg);
     DUMP_ONE_CFG_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "dom");
@@ -518,7 +515,7 @@ static void do_firm_optimizations(const char *input_filename, int firm_const_exi
     }
 
     timer_push(TV_OSR);
-      opt_osr(current_ir_graph, osr_flag_default /*| osr_flag_ignore_x86_shift*/);
+      opt_osr(current_ir_graph, osr_flag_default | osr_flag_keep_reg_pressure | osr_flag_ignore_x86_shift);
     timer_pop();
     DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "stred");
     CHECK_ONE(firm_opt.check_all, irg);
@@ -537,9 +534,40 @@ static void do_firm_optimizations(const char *input_filename, int firm_const_exi
     CHECK_ONE(firm_opt.check_all, irg);
   }
 
+  if (firm_opt.do_inline) {
+    inline_functions(500, 50);
+    DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "inl");
+    CHECK_ALL(firm_opt.check_all);
+  }
   if (firm_opt.cloning) {
     proc_cloning((float)firm_opt.clone_threshold);
     DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "clone");
+    CHECK_ALL(firm_opt.check_all);
+  }
+  if (firm_opt.tail_rec) {
+    timer_push(TV_TAIL_REC);
+      opt_tail_recursion();
+    timer_pop();
+
+    DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "tail_rec");
+    CHECK_ALL(firm_opt.check_all);
+  }
+
+  if (firm_opt.cond_eval) {
+    for (i = 0; i < get_irp_n_irgs(); i++) {
+      irg = get_irp_irg(i);
+      timer_push(TV_COND_EVAL);
+        opt_cond_eval(irg);
+      timer_pop();
+      DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "cond_eval");
+      CHECK_ONE(firm_opt.check_all, irg);
+
+      timer_push(TV_CF_OPT);
+        optimize_cf(irg);
+      timer_pop();
+      DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "cfopt");
+      CHECK_ONE(firm_opt.check_all, irg);
+    }
   }
 
   if (firm_dump.ir_graph) {
@@ -567,8 +595,10 @@ static void do_firm_optimizations(const char *input_filename, int firm_const_exi
   DUMP_ALL(firm_dump.ir_graph, "-opt");
 
   /* verify optimized graphs */
-  for (i = get_irp_n_irgs() - 1; i >= 0; --i)
-    irg_verify(get_irp_irg(i), VRFY_ENFORCE_SSA);
+  for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
+    ir_graph *irg = get_irp_irg(i);
+    irg_verify(irg, VRFY_ENFORCE_SSA);
+  }
 
   if (firm_dump.statistic & STAT_AFTER_OPT)
     stat_dump_snapshot(input_filename, "opt");
@@ -664,6 +694,7 @@ static int compute_type_size(ir_type *ty)
       ir_node *upper   = get_array_upper_bound(ty, i);
       ir_graph *rem    = current_ir_graph;
       tarval  *tv_lower, *tv_upper;
+      long     val_lower, val_upper;
 
       current_ir_graph = get_const_code_irg();
       local_optimize_node(lower);
@@ -682,7 +713,9 @@ static int compute_type_size(ir_type *ty)
         return 0;
       }
 
-      size *= get_tarval_long(tv_upper) - get_tarval_long(tv_lower);
+      val_upper = get_tarval_long(tv_upper);
+      val_lower = get_tarval_long(tv_lower);
+      size     *= val_upper - val_lower;
     }
     restore_optimization_state(&state);
 
@@ -708,24 +741,14 @@ static int compute_type_size(ir_type *ty)
 }  /* compute_type_size */
 
 /**
- * layout all types of the Firm graph
+ * layout all non-frame types of the Firm graph
  */
 static void compute_type_sizes(void)
 {
   int i;
   ir_type *tp;
-  ir_graph *irg;
 
-  /* all frame types */
-  for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
-    irg = get_irp_irg(i);
-    /* do not optimize away variables in debug mode */
-    if (firm_opt.debug_mode == DBG_MODE_NONE)
-      opt_frame_irg(irg);
-    compute_type_size(get_irg_frame_type(irg));
-  }
-
-  /* all other types */
+  /* all non-frame other types */
   for (i = get_irp_n_types() - 1; i >= 0; --i) {
     tp = get_irp_type(i);
     compute_type_size(tp);
@@ -741,6 +764,24 @@ static void compute_type_sizes(void)
   }
 }  /* compute_type_sizes */
 
+/**
+ * layout all frame-types of the Firm graph
+ */
+static void compute_frame_type_sizes(void)
+{
+  int i;
+  ir_graph *irg;
+
+  /* all frame types */
+  for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
+    irg = get_irp_irg(i);
+    /* do not optimize away variables in debug mode */
+    if (firm_opt.debug_mode == DBG_MODE_NONE)
+      opt_frame_irg(irg);
+    compute_type_size(get_irg_frame_type(irg));
+  }
+}  /* compute_frame_type_sizes */
+
 /**
  * do Firm lowering
  *
@@ -776,7 +817,6 @@ static void do_firm_lowering(const char *input_filename)
     }
     timer_push(TV_DW_LOWER);
       lower_dw_ops(&init);
-      DUMP_ALL(firm_dump.ir_graph, "-dw");
     timer_pop();
   }
 
@@ -806,6 +846,12 @@ static void do_firm_lowering(const char *input_filename)
       CHECK_ONE(firm_opt.check_all, current_ir_graph);
     }
 
+    /* enable architecture dependent optimizations */
+    arch_dep_set_opts((arch_dep_opts_t)
+                      ((firm_opt.muls ? arch_dep_mul_to_shift : arch_dep_none) |
+                      (firm_opt.divs ? arch_dep_div_by_const : arch_dep_none) |
+                      (firm_opt.mods ? arch_dep_mod_by_const : arch_dep_none) ));
+
     for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
       current_ir_graph = get_irp_irg(i);
 
@@ -828,7 +874,6 @@ static void do_firm_lowering(const char *input_filename)
         CHECK_ONE(firm_opt.check_all, current_ir_graph);
       }
 
-//      set_opt_global_cse(0);
       timer_push(TV_LOAD_STORE);
         optimize_load_store(current_ir_graph);
       timer_pop();
@@ -910,13 +955,19 @@ void gen_firm_init(void)
   params.cc_mask               = 0; /* no regparam, cdecl */
   params.builtin_dbg           = NULL;
 
-#ifdef FIRM_BACKEND
-  if (firm_be_opt.selection == BE_FIRM_BE) {
-    const backend_params *be_params = be_init();
+  #ifdef FIRM_EXT_GRS
+  /* Activate Graph rewriting if SIMD optimization is turned on */
+  /* This has to be done before init_firm() is called! */
+  if (firm_ext_grs.simd_opt)
+    ext_grs_activate();
+#endif
 
-    be_support_inline_asm   = be_params->support_inline_asm;
+  init_firm(&params);
 
-    firm_opt.lower_ll       = be_params->do_dw_lowering;
+  if (firm_be_opt.selection == BE_FIRM_BE) {
+    const backend_params *be_params = be_get_backend_param();
+
+    firm_opt.lower_ll       = (a_byte) be_params->do_dw_lowering;
     params.arch_op_settings = be_params->arch_op_settings;
 
     arch_create_intrinsic   = be_params->arch_create_intrinsic_fkt;
@@ -924,17 +975,11 @@ void gen_firm_init(void)
 
     ad_param                = be_params->dep_param;
     if_conv_info            = be_params->if_conv_info;
-  }
-#endif /* FIRM_BACKEND */
 
-#ifdef FIRM_EXT_GRS
-  /* Activate Graph rewriting if SIMD optimization is turned on */
-  /* This has to be done before init_firm() is called! */
-  if (firm_ext_grs.simd_opt)
-         ext_grs_activate();
-#endif
+    if (be_params->has_imm_fp_mode)
+      firm_imm_fp_mode = be_params->imm_fp_mode;
+  }
 
-  init_firm(&params);
   dbg_init(NULL, NULL, dbg_snprint);
   edges_init_dbg(firm_opt.vrfy_edges);
   //cbackend_set_debug_retrieve(dbg_retrieve);
@@ -942,6 +987,9 @@ void gen_firm_init(void)
   set_opt_precise_exc_context(firm_opt.precise_exc);
   set_opt_fragile_ops(firm_opt.fragile_ops);
 
+  /* Sel node cannot produce NULL pointers */
+  set_opt_sel_based_null_check_elim(1);
+
   /* dynamic dispatch works currently only if whole world scenarios */
   set_opt_dyn_meth_dispatch(0);
 
@@ -950,7 +998,7 @@ void gen_firm_init(void)
   /* do not run architecture dependent optimizations in building phase */
   arch_dep_set_opts(arch_dep_none);
 
-  do_node_verification(firm_opt.vrfy);
+  do_node_verification((firm_verification_t) firm_opt.vrfy);
   if (firm_dump.filter)
     only_dump_method_with_name(new_id_from_str(firm_dump.filter));
 
@@ -995,7 +1043,8 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int firm
   int i;
 
   /* the general for dumping option must be set, or the others will not work */
-  firm_dump.ir_graph |= firm_dump.all_phases | firm_dump.extbb;
+  firm_dump.ir_graph
+      = (a_byte) (firm_dump.ir_graph | firm_dump.all_phases | firm_dump.extbb);
 
   dump_keepalive_edges(1);
   dump_consts_local(1);
@@ -1039,6 +1088,12 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int firm
   /* computes the sizes of all types that are still not computed */
   compute_type_sizes();
 
+  /* lower copyb nodes */
+  for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
+    ir_graph *irg = get_irp_irg(i);
+    lower_CopyB(irg, 128, 4);
+  }
+
   if (firm_dump.statistic & STAT_BEFORE_OPT) {
     stat_dump_snapshot(input_filename, "noopt");
   }
@@ -1056,6 +1111,9 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int firm
   if (firm_opt.lower)
     do_firm_lowering(input_filename);
 
+  /* computes the sizes of all frame types */
+  compute_frame_type_sizes();
+
   /* set the phase to low */
   for (i = get_irp_n_irgs() - 1; i >= 0; --i)
     set_irg_phase_low(get_irp_irg(i));
@@ -1077,12 +1135,6 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int firm
     ext_grs_simd_opt();
 #endif
 
-  /* enable architecture dependent optimizations */
-  arch_dep_set_opts((firm_opt.muls ? arch_dep_mul_to_shift : arch_dep_none) |
-                    (firm_opt.divs ? arch_dep_div_by_const : arch_dep_none) |
-                    (firm_opt.mods ? arch_dep_mod_by_const : arch_dep_none) );
-
-
   if (firm_dump.statistic & STAT_FINAL_IR)
     stat_dump_snapshot(input_filename, "final-ir");
 
@@ -1103,9 +1155,7 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int firm
  * Do very early initializations
  */
 void firm_early_init(void) {
-#ifdef FIRM_BACKEND
   /* arg: need this here for command line options */
   be_opt_register();
-#endif
   firm_init_options(NULL, 0, NULL);
 }  /* firm_early_init */