[mono/mono] e4bf5439: [llvm] Decompose OP_STOREV_MEMBASE opcodes earlier since they might need write barriers.

"Zoltan Varga ([email protected])" <[email protected]> Tue, 19 Nov 2013 11:56:57 +0000
Newsgroups gmane.comp.gnome.mono.patches
Message-ID <00000142703873df-d4598afa-4155-417d-8846-3ff5c62d23e8-000000@email.amazonses.com>
   Branch: refs/heads/master
     Home: https://github.com/mono/mono
  Compare: https://github.com/mono/mono/compare/3a9ccd06832f...e4bf54392ad9

   Commit: e4bf54392ad9a7c85531d99422f133b124c3d1a3
   Author: Zoltan Varga <[email protected]> (vargaz)
     Date: 2013-11-19 11:55:45 GMT
      URL: https://github.com/mono/mono/commit/e4bf54392ad9a7c85531d99422f133b124c3d1a3

[llvm] Decompose OP_STOREV_MEMBASE opcodes earlier since they might need write barriers.

Changed paths:
  M mono/mini/decompose.c
  M mono/mini/mini-codegen.c
  M mono/mini/mini-llvm.c
  M mono/mini/mini.c
  M mono/mini/mini.h

Modified: mono/mini/decompose.c
===================================================================
@@ -1361,6 +1361,71 @@
 	}
 }
 
+void
+mono_decompose_vtype_opts_llvm (MonoCompile *cfg)
+{
+	MonoBasicBlock *bb, *first_bb;
+
+	/* Decompose only the OP_STOREV_MEMBASE opcodes, which need write barriers */
+
+	cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
+	first_bb = cfg->cbb;
+
+	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+		MonoInst *ins;
+		MonoInst *prev = NULL;
+		MonoInst *src_var, *src, *dest;
+		gboolean restart;
+		int dreg;
+
+		if (cfg->verbose_level > 2) mono_print_bb (bb, "BEFORE LOWER-VTYPE-OPTS(LLVM) ");
+
+		cfg->cbb->code = cfg->cbb->last_ins = NULL;
+		restart = TRUE;
+
+		while (restart) {
+			restart = FALSE;
+
+			for (ins = bb->code; ins; ins = ins->next) {
+				switch (ins->opcode) {
+				case OP_STOREV_MEMBASE: {
+					src_var = get_vreg_to_inst (cfg, ins->sreg1);
+
+					if (!src_var) {
+						g_assert (ins->klass);
+						src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
+					}
+
+					EMIT_NEW_VARLOADA_VREG ((cfg), (src), ins->sreg1, &ins->klass->byval_arg);
+
+					dreg = alloc_preg (cfg);
+					EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
+					mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
+					break;
+				}
+				default:
+					break;
+				}
+
+				g_assert (cfg->cbb == first_bb);
+
+				if (cfg->cbb->code || (cfg->cbb != first_bb)) {
+					/* Replace the original instruction with the new code sequence */
+
+					mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
+					first_bb->code = first_bb->last_ins = NULL;
+					first_bb->in_count = first_bb->out_count = 0;
+					cfg->cbb = first_bb;
+				}
+				else
+					prev = ins;
+			}
+		}
+
+		if (cfg->verbose_level > 2) mono_print_bb (bb, "AFTER LOWER-VTYPE-OPTS(LLVM) ");
+	}
+}
+
 inline static MonoInst *
 mono_get_domainvar (MonoCompile *cfg)
 {

Modified: mono/mini/mini-codegen.c
===================================================================
@@ -453,9 +453,22 @@ static inline int translate_bank (MonoRegState *rs, int bank, int hreg) {
 	else
 		printf (" %s", mono_inst_name (ins->opcode));
 	if (spec == MONO_ARCH_CPU_SPEC) {
+		gboolean dest_base = FALSE;
+		switch (ins->opcode) {
+		case OP_STOREV_MEMBASE:
+			dest_base = TRUE;
+			break;
+		default:
+			break;
+		}
+
 		/* This is a lowered opcode */
-		if (ins->dreg != -1)
-			printf (" R%d <-", ins->dreg);
+		if (ins->dreg != -1) {
+			if (dest_base)
+				printf (" [R%d + 0x%lx] <-", ins->dreg, (long)ins->inst_offset);
+			else
+				printf (" R%d <-", ins->dreg);
+		}
 		if (ins->sreg1 != -1)
 			printf (" R%d", ins->sreg1);
 		if (ins->sreg2 != -1)

Modified: mono/mini/mini-llvm.c
===================================================================
@@ -3454,9 +3454,10 @@
 
 			switch (ins->opcode) {
 			case OP_STOREV_MEMBASE:
-				if (cfg->gen_write_barriers && klass->has_references && ins->inst_destbasereg != cfg->frame_reg) {
-					/* FIXME: Emit write barriers like in mini_emit_stobj () */
-					LLVM_FAILURE (ctx, "storev_membase + write barriers");
+				if (cfg->gen_write_barriers && klass->has_references && ins->inst_destbasereg != cfg->frame_reg &&
+					LLVMGetInstructionOpcode (values [ins->inst_destbasereg]) != LLVMAlloca) {
+					/* Decomposed earlier */
+					g_assert_not_reached ();
 					break;
 				}
 				if (!addresses [ins->sreg1]) {
@@ -4210,7 +4211,7 @@
 #if 1
 	for (i = 0; i < header->num_clauses; ++i) {
 		clause = &header->clauses [i];
-		
+
 		if (i > 0 && clause->try_offset <= header->clauses [i - 1].handler_offset + header->clauses [i - 1].handler_len) {
 			/*
 			 * FIXME: Some tests still fail with nested clauses.

Modified: mono/mini/mini.c
===================================================================
@@ -5379,7 +5379,9 @@ void *mono_global_codeman_reserve (int size)
 	if (COMPILE_SOFT_FLOAT (cfg))
 		mono_decompose_soft_float (cfg);
 #endif
-	if (!COMPILE_LLVM (cfg))
+	if (COMPILE_LLVM (cfg))
+		mono_decompose_vtype_opts_llvm (cfg);
+	else
 		mono_decompose_vtype_opts (cfg);
 	if (cfg->flags & MONO_CFG_HAS_ARRAY_ACCESS)
 		mono_decompose_array_access_opts (cfg);

Modified: mono/mini/mini.h
===================================================================
@@ -2221,6 +2221,7 @@ int               mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoB
 MonoInst         *mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) MONO_INTERNAL;
 void              mono_decompose_long_opts (MonoCompile *cfg) MONO_INTERNAL;
 void              mono_decompose_vtype_opts (MonoCompile *cfg) MONO_INTERNAL;
+void              mono_decompose_vtype_opts_llvm (MonoCompile *cfg) MONO_INTERNAL;
 void              mono_decompose_array_access_opts (MonoCompile *cfg) MONO_INTERNAL;
 void              mono_decompose_soft_float (MonoCompile *cfg) MONO_INTERNAL;
 void              mono_handle_global_vregs (MonoCompile *cfg) MONO_INTERNAL;


_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches