[llvm] Add some micro optimizations to the LLVM/AOT code.
authorZoltan Varga <vargaz@gmail.com>
Mon, 18 Nov 2013 06:52:32 +0000 (07:52 +0100)
committerZoltan Varga <vargaz@gmail.com>
Mon, 18 Nov 2013 06:52:32 +0000 (07:52 +0100)
mono/mini/aot-compiler.c
mono/mini/mini-llvm.c

index c115be245da7c6ba5bbcf5a7d481a8db66add63d..fa91e5cdb4db06779b0044ab8c462aaf8fd91768 100755 (executable)
@@ -165,7 +165,7 @@ typedef struct MonoAotCompile {
        GHashTable *method_depth;
        MonoCompile **cfgs;
        int cfgs_size;
-       GHashTable *patch_to_plt_entry;
+       GHashTable **patch_to_plt_entry;
        GHashTable *plt_offset_to_entry;
        GHashTable *patch_to_got_offset;
        GHashTable **patch_to_got_offset_by_type;
@@ -2906,7 +2906,9 @@ get_plt_entry (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
        if (!is_plt_patch (patch_info))
                return NULL;
 
-       res = g_hash_table_lookup (acfg->patch_to_plt_entry, patch_info);
+       if (!acfg->patch_to_plt_entry [patch_info->type])
+               acfg->patch_to_plt_entry [patch_info->type] = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
+       res = g_hash_table_lookup (acfg->patch_to_plt_entry [patch_info->type], patch_info);
 
        // FIXME: This breaks the calculation of final_got_size         
        if (!acfg->llvm && patch_info->type == MONO_PATCH_INFO_METHOD && (patch_info->data.method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
@@ -2936,7 +2938,7 @@ get_plt_entry (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
                else
                        res->llvm_symbol = g_strdup_printf ("%s_llvm", res->symbol);
 
-               g_hash_table_insert (acfg->patch_to_plt_entry, new_ji, res);
+               g_hash_table_insert (acfg->patch_to_plt_entry [new_ji->type], new_ji, res);
 
                g_hash_table_insert (acfg->plt_offset_to_entry, GUINT_TO_POINTER (res->plt_offset), res);
 
@@ -8530,7 +8532,7 @@ acfg_create (MonoAssembly *ass, guint32 opts)
        acfg->method_indexes = g_hash_table_new (NULL, NULL);
        acfg->method_depth = g_hash_table_new (NULL, NULL);
        acfg->plt_offset_to_entry = g_hash_table_new (NULL, NULL);
-       acfg->patch_to_plt_entry = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
+       acfg->patch_to_plt_entry = g_new0 (GHashTable*, MONO_PATCH_INFO_NUM);
        acfg->patch_to_got_offset = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
        acfg->patch_to_got_offset_by_type = g_new0 (GHashTable*, MONO_PATCH_INFO_NUM);
        for (i = 0; i < MONO_PATCH_INFO_NUM; ++i)
@@ -8582,7 +8584,11 @@ acfg_free (MonoAotCompile *acfg)
        g_hash_table_destroy (acfg->method_indexes);
        g_hash_table_destroy (acfg->method_depth);
        g_hash_table_destroy (acfg->plt_offset_to_entry);
-       g_hash_table_destroy (acfg->patch_to_plt_entry);
+       for (i = 0; i < MONO_PATCH_INFO_NUM; ++i) {
+               if (acfg->patch_to_plt_entry [i])
+                       g_hash_table_destroy (acfg->patch_to_plt_entry [i]);
+       }
+       g_free (acfg->patch_to_plt_entry);
        g_hash_table_destroy (acfg->patch_to_got_offset);
        g_hash_table_destroy (acfg->method_to_cfg);
        g_hash_table_destroy (acfg->token_info_hash);
index 277453e8ee04df2a130ada75d4a91878e0b65f6a..1bcc14ddf3c43e0c809b2180b4172b2d93d9d0eb 100644 (file)
@@ -35,6 +35,8 @@ typedef struct {
        LLVMValueRef got_var;
        const char *got_symbol;
        GHashTable *plt_entries;
+       char **bb_names;
+       GPtrArray *used;
 } MonoLLVMModule;
 
 /*
@@ -845,14 +847,28 @@ simd_op_to_llvm_type (int opcode)
 static LLVMBasicBlockRef
 get_bb (EmitContext *ctx, MonoBasicBlock *bb)
 {
-       char bb_name [128];
+       char bb_name_buf [128];
+       char *bb_name;
 
        if (ctx->bblocks [bb->block_num].bblock == NULL) {
                if (bb->flags & BB_EXCEPTION_HANDLER) {
                        int clause_index = (mono_get_block_region_notry (ctx->cfg, bb->region) >> 8) - 1;
-                       sprintf (bb_name, "EH_CLAUSE%d_BB%d", clause_index, bb->block_num);
+                       sprintf (bb_name_buf, "EH_CLAUSE%d_BB%d", clause_index, bb->block_num);
+                       bb_name = bb_name_buf;
+               } else if (bb->block_num < 256) {
+                       if (!ctx->lmodule->bb_names)
+                               ctx->lmodule->bb_names = g_new0 (char*, 256);
+                       if (!ctx->lmodule->bb_names [bb->block_num]) {
+                               char *n;
+
+                               n = g_strdup_printf ("BB%d", bb->block_num);
+                               mono_memory_barrier ();
+                               ctx->lmodule->bb_names [bb->block_num] = n;
+                       }
+                       bb_name = ctx->lmodule->bb_names [bb->block_num];
                } else {
-                       sprintf (bb_name, "BB%d", bb->block_num);
+                       sprintf (bb_name_buf, "BB%d", bb->block_num);
+                       bb_name = bb_name_buf;
                }
 
                ctx->bblocks [bb->block_num].bblock = LLVMAppendBasicBlock (ctx->lmethod, bb_name);
@@ -1669,15 +1685,30 @@ build_alloca (EmitContext *ctx, MonoType *t)
  * Put the global into the 'llvm.used' array to prevent it from being optimized away.
  */
 static void
-mark_as_used (LLVMModuleRef module, LLVMValueRef global)
+mark_as_used (MonoLLVMModule *lmodule, LLVMValueRef global)
 {
+       if (!lmodule->used)
+               lmodule->used = g_ptr_array_sized_new (16);
+       g_ptr_array_add (lmodule->used, global);
+}
+
+static void
+emit_llvm_used (MonoLLVMModule *lmodule)
+{
+       LLVMModuleRef module = lmodule->module;
        LLVMTypeRef used_type;
-       LLVMValueRef used, used_elem;
+       LLVMValueRef used, *used_elem;
+       int i;
                
-       used_type = LLVMArrayType (LLVMPointerType (LLVMInt8Type (), 0), 1);
+       if (!lmodule->used)
+               return;
+
+       used_type = LLVMArrayType (LLVMPointerType (LLVMInt8Type (), 0), lmodule->used->len);
        used = LLVMAddGlobal (module, used_type, "llvm.used");
-       used_elem = LLVMConstBitCast (global, LLVMPointerType (LLVMInt8Type (), 0));
-       LLVMSetInitializer (used, LLVMConstArray (LLVMPointerType (LLVMInt8Type (), 0), &used_elem, 1));
+       used_elem = g_new0 (LLVMValueRef, lmodule->used->len);
+       for (i = 0; i < lmodule->used->len; ++i)
+               used_elem [i] = LLVMConstBitCast (g_ptr_array_index (lmodule->used, i), LLVMPointerType (LLVMInt8Type (), 0));
+       LLVMSetInitializer (used, LLVMConstArray (LLVMPointerType (LLVMInt8Type (), 0), used_elem, lmodule->used->len));
        LLVMSetLinkage (used, LLVMAppendingLinkage);
        LLVMSetSection (used, "llvm.metadata");
 }
@@ -4217,7 +4248,7 @@ mono_llvm_emit_method (MonoCompile *cfg)
        ctx->addresses = g_new0 (LLVMValueRef, cfg->next_vreg);
        ctx->vreg_types = g_new0 (LLVMTypeRef, cfg->next_vreg);
        ctx->vreg_cli_types = g_new0 (MonoType*, cfg->next_vreg);
-       phi_values = g_ptr_array_new ();
+       phi_values = g_ptr_array_sized_new (256);
        /* 
         * This signals whenever the vreg was defined by a phi node with no input vars
         * (i.e. all its input bblocks end with NOT_REACHABLE).
@@ -4226,7 +4257,7 @@ mono_llvm_emit_method (MonoCompile *cfg)
        /* Whenever the bblock is unreachable */
        ctx->unreachable = g_new0 (gboolean, cfg->max_block_num);
 
-       bblock_list = g_ptr_array_new ();
+       bblock_list = g_ptr_array_sized_new (256);
 
        ctx->values = values;
        ctx->region_to_handler = g_hash_table_new (NULL, NULL);
@@ -4517,7 +4548,7 @@ mono_llvm_emit_method (MonoCompile *cfg)
        if (cfg->verbose_level > 1)
                mono_llvm_dump_value (method);
 
-       mark_as_used (module, method);
+       mark_as_used (ctx->lmodule, method);
 
        if (cfg->compile_aot) {
                LLVMValueRef md_args [16];
@@ -5185,11 +5216,13 @@ mono_llvm_emit_aot_module (const char *filename, int got_size)
 
        mono_llvm_replace_uses_of (aot_module.got_var, real_got);
 
-       mark_as_used (aot_module.module, real_got);
+       mark_as_used (&aot_module, real_got);
 
        /* Delete the dummy got so it doesn't become a global */
        LLVMDeleteGlobal (aot_module.got_var);
 
+       emit_llvm_used (&aot_module);
+
 #if 0
        {
                char *verifier_err;