[Mono-dev] [PATCH]: Rewrite instruction list handling.

David Miller davem at davemloft.net
Mon Nov 12 19:28:09 EST 2007


The story behind this is that I wrote a branch delay slot filling pass
for RISC chips like sparc.  Like the local register allocator it wants
to do a backwards scan of the basic block instructions and I felt it
was pointless to add "reverse the instruction list" code all over
again in this new pass when we can just maintain the instructions
correctly on a real doubly linked list and scan in whatever direction
we want, whenever we want.  No more tricks are needed to insert
instructions before an arbitrary instruction, and deletion of
arbitrary instructions became much simpler as well.

In fact, significant chunks special list handling code got removed.
And I am certain many other significant cleanups and simplifications
become possible after this patch goes in.

I've built and regression tested this patch on x86, ppc, and sparc.
I would really appreciate help in regression testing the other
JIT targets which I do not have access to.

If you test and hit into any problems they are usually not that
hard to debug.  Most bugs can be figured out by dumping the IR
stream using an unmodified mono and comparing it to with the
patch applied.  Look for instructions ordered improperly.

Most of this change was very straight-forward.  One notable exception
was the local register allocator, which emits it's spill code
strangely.  Code that said things like "emit after this instruction"
really meant "insert before next non-spill instruction".

2007-11-12  David S. Miller  <davem at davemloft.net>

	* mini.h (MonoInstList): New type.
	(MONO_INST_LIST_INIT, MONO_INST_LIST_EMPTY,
	__MONO_INST_LIST_ADD, MONO_INST_LIST_ADD,
	MONO_INST_LIST_ADD_TAIL, __MONO_INST_LIST_DEL,
	__MONO_INST_LIST_SPLICE, MONO_INST_LIST_SPLICE,
	MONO_INST_LIST_SPLICE_TAIL, MONO_INST_LIST_SPLICE_INIST,
	MONO_INST_LIST_SPLICE_TAIL_INIT, mono_container_of,
	MONO_INST_LIST_ENTRY, MONO_INST_LIST_FIRST_ENTRY,
	MONO_INST_LIST_LAST_ENTRY, MONO_INST_LIST_FOR_EACH,
	MONO_INST_LIST_FOR_EACH_PREV, MONO_INST_LIST_FOR_EACH_SAFE,
	MONO_INST_LIST_FOR_EACH_PREV_SAFE,
	MONO_INST_LIST_FOR_EACH_ENTRY,
	MONO_INST_LIST_FOR_EACH_ENTRY_REVERSE,
	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE,
	mono_inst_list_first, mono_inst_list_last,
	mono_inst_list_next, mono_inst_list_prev): New instruction
	list handling interfaces.
	(MonoBasicBlock): Remove 'last_ins' and 'code', replace with
	list head 'ins_list'.
	(MonoInst): Replace next pointer with list head 'node'.
	(MonoCallInst): Make 'out_args' a MonoInstList.
	(MONO_INST_NEW_CALL): Explicitly init ->out_args.
	(MonoCompile): Delete reverse_inst_list and
	reverse_inst_list_len.
	* mini-hppa.c (mono_arch_call_opcode, NEW_INS,
	mono_arch_lowering_pass, mono_arch_local_regalloc,
	mono_arch_output_basic_block, mono_arch_emit_prolog):
	Convert to new instruction lists.
	(insert_after_ins): Delete.
	* inssel.brg (MONO_EMIT_NEW_BRANCH_BLOCK): Convert to new
	instruction lists.
	* mini-hppa.h (MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK): Likewise.
	* mini.c (NEW_BBLOCK, ADD_BBLOCK, CHECK_BBLOCK,
	split_bblock, mono_add_ins_to_end, mono_emit_call_args,
	mono_emulate_opcode, mono_emit_load_got_addr,
	inline_method, mono_method_to_ir, mono_print_bb_code,
	print_dfn, decompose_pass, nullify_basic_block,
	replace_out_block_in_code, remove_block_if_useless,
	merge_basic_blocks, move_basic_block_to_end,
	try_unsigned_compare, optimize_branches, mono_print_code,
	mini_select_instructions, remove_critical_edges): Likewise.
	* mini-amd64.c (emit_sig_cookie, mono_arch_call_opcode,
	peephole_pass_1, peephole_pass, mono_arch_lowering_pass,
	mono_arch_output_basic_block, mono_arch_emit_prolog):
	Likewise.
	* mini-mips.c (mono_arch_call_opcode, peephole_pass,
	NEW_INS, mono_arch_lowering_pass, mono_arch_local_regalloc,
	mono_arch_output_basic_block): Likewise.
	(inst_list_prepend, insert_after_ins): Delete.
	* mini-mips.h (MONO_EMIT_NEW_BRANCH_NONZERO_LABEL,
	MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK): Convert to new
	instruction lists.
	* mini-x86.c (emit_sig_cookie, mono_arch_call_opcode,
	peephole_pass_1, peephole_pass, mono_arch_output_basic_block,
	mono_arch_emit_prolog): Likewise.
	* cfold.c (mono_constant_fold): Likewise.
	* liveness.c (visit_bb, mono_analyze_liveness,
	optimize_initlocals): Likewise.
	* ssapre.c (dump_code, process_bb, code_motion): Likewise.
	* graph.c (mono_draw_code_cfg): Likewise.
	* ssa.c (mono_ssa_rename_vars, mono_ssa_compute,
	mono_ssa_remove, mono_ssa_avoid_copies, mono_ssa_create_def_use,
	mono_ssa_cprop): Likewise.
	* abcremoval (get_relations_from_previous_bb, process_block):
	Likewise.
	* local-propagation (mono_cprop_invalidate_values,
	mono_local_cprop_bb): Likewise.
	* mini-s390x.c (mono_arch_call_opcode, emit_sig_cookie,
	peephole_pass, mono_arch_output_basic_block,
	mono_arch_emit_prolog):	Likewise.
	* mini-arm.c (mono_arch_call_opcode, peephole_pass,
	NEW_INS, mono_arch_lowering_pass, mono_arch_local_regalloc,
	mono_arch_emit_prolog): Likewise.
	(insert_after_ins): Delete.
	* aliasing.c (print_code_with_aliasing_information,
	mono_build_aliasing_information, mono_aliasing_deadce):
	Convert to new instruction lists.
	* mini-ia64.c (emit_sig_cookie, mono_arch_call_opcode,
	peephole_pass, NEW_INS, mono_arch_lowering_pass,
	mono_arch_local_regalloc, mono_arch_output_basic_block):
	Likewise.
	(insert_after_ins): Delete.
	* mini-sparc.c (emit_sig_cookie, mono_arch_call_opcode,
	peephole_pass, mono_arch_output_basic_block): Convert to
	new instruction lists.
	* mini-codegen (InstList, inst_list_prepend,
	insert_after_ins): Delete.
	(insert_before_ins, get_register_force_spilling,
	get_register_spilling, free_up_ireg, free_up_reg,
	create_copy_ins, create_spilled_store, alloc_int_reg,
	alloc_float_reg, alloc_reg, mono_local_regalloc): Convert
	to new instruction lists.
	* mini-ppc.c (mono_arch_call_opcode, peephole_pass,
	NEW_INS, mono_arch_lowering_pass, mono_arch_local_regalloc,
	mono_arch_output_basic_block, mono_arch_emit_prolog): Likewise.
	(insert_after_ins): Delete.
	* mini-alpha.c (NEW_INS, peephole_pass, mono_arch_lowering_pass,
	mono_arch_local_regalloc, mono_arch_output_basic_block,
	mono_arch_call_opcode): Convert to new instruction lists.
	(insert_after_ins): Delete.
	* mini-s390.c (mono_arch_call_opcode, emit_sig_cookie,
	peephole_pass, mono_arch_output_basic_block,
	mono_arch_emit_prolog): Convert to new instruction lists.

Index: mono/mini/mini-hppa.c
===================================================================
--- mono/mini/mini-hppa.c	(revision 89301)
+++ mono/mini/mini-hppa.c	(working copy)
@@ -702,10 +702,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			arg->inst_left = in;
 			arg->inst_call = call;
 			arg->type = in->type;
-
-			/* prepend, we'll need to reverse them later */
-			arg->next = call->out_args;
-			call->out_args = arg;
+			MONO_INST_LIST_ADD_TAIL(&arg->node, &call->out_args);
 
 			switch (ainfo->storage) {
 			case ArgInIReg:
@@ -754,19 +751,6 @@ mono_arch_call_opcode (MonoCompile *cfg,
 		}
 	}
 
-	/*
-	 * Reverse the call->out_args list.
-	 */
-	{
-		MonoInst *prev = NULL, *list = call->out_args, *next;
-		while (list) {
-			next = list->next;
-			list->next = prev;
-			prev = list;
-			list = next;
-		}
-		call->out_args = prev;
-	}
 	call->stack_usage = cinfo->stack_usage;
 	cfg->param_area = MAX (cfg->param_area, call->stack_usage);
 	cfg->param_area = ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT);
@@ -786,23 +770,10 @@ peephole_pass (MonoCompile *cfg, MonoBas
 	DEBUG_FUNC_EXIT();
 }
 
-static void
-insert_after_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *to_insert)
-{
-	if (ins == NULL) {
-		ins = bb->code;
-		bb->code = to_insert;
-		to_insert->next = ins;
-	} else {
-		to_insert->next = ins->next;
-		ins->next = to_insert;
-	}
-}
-
-#define NEW_INS(cfg,dest,op) do {       \
+#define NEW_INS(cfg,ins,dest,op) do {					\
 		(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
 		(dest)->opcode = (op);  \
-		insert_after_ins (bb, last_ins, (dest)); \
+		MONO_INST_LIST_ADD_TAIL(&(dest)->node, &(ins)->node); \
 	} while (0)
 
 static int
@@ -881,21 +852,20 @@ map_to_reg_reg_op (int op)
 static void
 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *next, *temp, *last_ins = NULL;
+	MonoInst *ins, *next, *temp, *temp2;
 	int imm;
 
 	/* setup the virtual reg allocator */
 	if (bb->max_vreg > cfg->rs->next_vreg)
 		cfg->rs->next_vreg = bb->max_vreg;
 
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 loop_start:
 		switch (ins->opcode) {
 		case OP_ADD_IMM:
 		case OP_ADDCC_IMM:
 			if (!hppa_check_bits (ins->inst_imm, 11)) {
-				NEW_INS (cfg, temp, OP_ICONST);
+				NEW_INS (cfg, ins, temp, OP_ICONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->sreg2 = temp->dreg;
@@ -905,7 +875,7 @@ loop_start:
 		case OP_SUB_IMM:
 		case OP_SUBCC_IMM:
 			if (!hppa_check_bits (ins->inst_imm, 11)) {
-				NEW_INS (cfg, temp, OP_ICONST);
+				NEW_INS (cfg, ins, temp, OP_ICONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->sreg2 = temp->dreg;
@@ -931,7 +901,7 @@ loop_start:
 			}
 			else {
 				int tmp = mono_regstate_next_int (cfg->rs);
-				NEW_INS (cfg, temp, OP_ICONST);
+				NEW_INS (cfg, ins, temp, OP_ICONST);
 				temp->inst_c0 = ins->inst_c0;
 				temp->dreg = tmp;
 
@@ -946,35 +916,35 @@ loop_start:
 			int freg1 = mono_regstate_next_float (cfg->rs);
 			int freg2 = mono_regstate_next_float (cfg->rs);
 
-			NEW_INS(cfg, temp, OP_STORE_MEMBASE_REG);
+			NEW_INS(cfg, ins, temp, OP_STORE_MEMBASE_REG);
 			temp->sreg1 = ins->sreg1;
 			temp->inst_destbasereg = hppa_sp;
 			temp->inst_offset = -16;
 
-			NEW_INS(cfg, temp, OP_LOADR4_MEMBASE);
-			temp->dreg = freg1;
-			temp->inst_basereg = hppa_sp;
-			temp->inst_offset = -16;
+			NEW_INS(cfg, temp, temp2, OP_LOADR4_MEMBASE);
+			temp2->dreg = freg1;
+			temp2->inst_basereg = hppa_sp;
+			temp2->inst_offset = -16;
 
-			NEW_INS(cfg, temp, OP_STORE_MEMBASE_REG);
+			NEW_INS(cfg, temp2, temp, OP_STORE_MEMBASE_REG);
 			temp->sreg1 = ins->sreg2;
 			temp->inst_destbasereg = hppa_sp;
 			temp->inst_offset = -16;
 
-			NEW_INS(cfg, temp, OP_LOADR4_MEMBASE);
-			temp->dreg = freg2;
-			temp->inst_basereg = hppa_sp;
-			temp->inst_offset = -16;
+			NEW_INS(cfg, temp, temp2, OP_LOADR4_MEMBASE);
+			temp2->dreg = freg2;
+			temp2->inst_basereg = hppa_sp;
+			temp2->inst_offset = -16;
 
-			NEW_INS (cfg, temp, OP_HPPA_XMPYU);
+			NEW_INS (cfg, temp2, temp, OP_HPPA_XMPYU);
 			temp->dreg = freg2;
 			temp->sreg1 = freg1;
 			temp->sreg2 = freg2;
 
-			NEW_INS(cfg, temp, OP_HPPA_STORER4_RIGHT);
-			temp->sreg1 = freg2;
-			temp->inst_destbasereg = hppa_sp;
-			temp->inst_offset = -16;
+			NEW_INS(cfg, temp, temp2, OP_HPPA_STORER4_RIGHT);
+			temp2->sreg1 = freg2;
+			temp2->inst_destbasereg = hppa_sp;
+			temp2->inst_offset = -16;
 
 			ins->opcode = OP_LOAD_MEMBASE;
 			ins->inst_basereg = hppa_sp;
@@ -985,10 +955,7 @@ loop_start:
 		default:
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 	bb->max_vreg = cfg->rs->next_vreg;
 	
 }
@@ -997,7 +964,7 @@ void
 mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
 {
 	DEBUG_FUNC_ENTER();
-	if (!bb->code)
+	if (MONO_INST_LIST_EMPTY(&bb->ins_list))
 		return;
 	mono_arch_lowering_pass (cfg, bb);
 	mono_local_regalloc (cfg, bb);
@@ -1261,7 +1228,6 @@ mono_arch_output_basic_block (MonoCompil
 	MonoCallInst *call;
 	guint offset;
 	guint32 *code = (guint32*)(cfg->native_code + cfg->code_len);
-	MonoInst *last_ins = NULL;
 	int max_len, cpos;
 	const char *spec;
 
@@ -1278,8 +1244,7 @@ mono_arch_output_basic_block (MonoCompil
 		NOT_IMPLEMENTED;
 	}
 
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 		guint8* code_start;
 
 		offset = (guint8*)code - cfg->native_code;
@@ -1746,7 +1711,6 @@ mono_arch_output_basic_block (MonoCompil
 			break;
 		case OP_BR: {
 			guint32 target;
-			DEBUG (printf ("target: %p, next: %p, curr: %p, last: %p\n", ins->inst_target_bb, bb->next_bb, ins, bb->last_ins));
 			if (ins->flags & MONO_INST_BRLABEL) {
 				mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_LABEL, ins->inst_i0);
 			} else {
@@ -2062,10 +2026,6 @@ mono_arch_output_basic_block (MonoCompil
 		}
 	       
 		cpos += max_len;
-
-		last_ins = ins;
-		
-		ins = ins->next;
 	}
 
 	cfg->code_len = (guint8*)code - cfg->native_code;
@@ -2337,16 +2297,14 @@ mono_arch_emit_prolog (MonoCompile *cfg)
 	 */
 	max_offset = 0;
 	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-		MonoInst *ins = bb->code;
+		MonoInst *ins;
 		bb->max_offset = max_offset;
 
 		if (cfg->prof_options & MONO_PROFILE_COVERAGE)
 			max_offset += 6; 
 
-		while (ins) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node)
 			max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
-			ins = ins->next;
-		}
 	}
 
 	DEBUG (printf ("Incoming arguments: \n"));
Index: mono/mini/inssel.brg
===================================================================
--- mono/mini/inssel.brg	(revision 89301)
+++ mono/mini/inssel.brg	(working copy)
@@ -250,9 +250,9 @@
         	MonoInst *target_label; \
 		target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));	\
 		target_label->opcode = OP_LABEL;	\
-	        target_label->next = (targetbb)->code; \
+		MONO_INST_LIST_ADD(&target_label->node, \
+				   &(targetbb)->ins_list); \
 		target_label->inst_c0 = (targetbb)->native_offset; \
-	        (targetbb)->code = target_label; \
 		inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));	\
 		inst->opcode = op;	\
 		inst->inst_i0 = target_label;	\
Index: mono/mini/mini-hppa.h
===================================================================
--- mono/mini/mini-hppa.h	(revision 89301)
+++ mono/mini/mini-hppa.h	(working copy)
@@ -136,9 +136,9 @@ typedef struct MonoCompileArch {
 		MonoInst *target_label; \
 		target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));	\
 		target_label->opcode = OP_LABEL;	\
-	        target_label->next = (targetbb)->code; \
+		MONO_INST_LIST_ADD(&target_label->node, \
+				   &(targetbb)->ins_list); \
 		target_label->inst_c0 = (targetbb)->native_offset; \
-	        (targetbb)->code = target_label; \
 		inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));	\
 		g_assert (op >= CEE_BEQ && op <= CEE_BLT_UN); \
 		inst->opcode = OP_HPPA_BEQ + (op - CEE_BEQ); \
Index: mono/mini/mini.c
===================================================================
--- mono/mini/mini.c	(revision 89301)
+++ mono/mini/mini.c	(working copy)
@@ -405,7 +405,13 @@ mono_jump_info_token_new (MonoMemPool *m
  * dfn: Depth First Number
  * block_num: unique ID assigned at bblock creation
  */
-#define NEW_BBLOCK(cfg) (mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock)))
+#define NEW_BBLOCK(cfg,new_bb) \
+do { \
+	new_bb = mono_mempool_alloc0 ((cfg)->mempool, \
+				      sizeof (MonoBasicBlock)); \
+	MONO_INST_LIST_INIT(&new_bb->ins_list); \
+} while (0)
+
 #define ADD_BBLOCK(cfg,b) do {	\
 		cfg->cil_offset_to_bb [(b)->cil_code - cfg->cil_start] = (b);	\
 		(b)->block_num = cfg->num_bblocks++;	\
@@ -416,18 +422,20 @@ mono_jump_info_token_new (MonoMemPool *m
 		(tblock) = cfg->cil_offset_to_bb [(ip) - cfg->cil_start]; \
 		if (!(tblock)) {	\
 			if ((ip) >= end || (ip) < header->code) UNVERIFIED; \
-			(tblock) = NEW_BBLOCK (cfg);	\
+			NEW_BBLOCK (cfg, (tblock));	\
 			(tblock)->cil_code = (ip);	\
 			ADD_BBLOCK (cfg, (tblock));	\
 		} \
 	} while (0)
 
-#define CHECK_BBLOCK(target,ip,tblock) do {	\
-		if ((target) < (ip) && !(tblock)->code)	{	\
-			bb_recheck = g_list_prepend (bb_recheck, (tblock));	\
-			if (cfg->verbose_level > 2) g_print ("queued block %d for check at IL%04x from IL%04x\n", (tblock)->block_num, (int)((target) - header->code), (int)((ip) - header->code));	\
-		}	\
-	} while (0)
+#define CHECK_BBLOCK(target,ip,tblock) \
+do {	if ((target) < (ip) && \
+	    MONO_INST_LIST_EMPTY(&(tblock)->ins_list)) { \
+		bb_recheck = g_list_prepend (bb_recheck, (tblock)); \
+		if (cfg->verbose_level > 2) \
+			g_print ("queued block %d for check at IL%04x from IL%04x\n", (tblock)->block_num, (int)((target) - header->code), (int)((ip) - header->code));	\
+	} \
+} while (0)
 
 #define NEW_ICONST(cfg,dest,val) do {	\
 		(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));	\
@@ -1077,7 +1085,7 @@ split_bblock (MonoCompile *cfg, MonoBasi
 	MonoInst *inst;
 	MonoBasicBlock *bb;
 
-	if (second->code)
+	if (! MONO_INST_LIST_EMPTY(&second->ins_list))
 		return;
 	
 	/* 
@@ -1099,23 +1107,34 @@ split_bblock (MonoCompile *cfg, MonoBasi
 	first->out_bb = NULL;
 	link_bblock (cfg, first, second);
 
-	second->last_ins = first->last_ins;
-
 	/*g_print ("start search at %p for %p\n", first->cil_code, second->cil_code);*/
-	for (inst = first->code; inst && inst->next; inst = inst->next) {
+	MONO_INST_LIST_FOR_EACH_ENTRY (inst, &first->ins_list, node) {
+		MonoInst *inst_next;
+
 		/*char *code = mono_disasm_code_one (NULL, cfg->method, inst->next->cil_code, NULL);
 		g_print ("found %p: %s", inst->next->cil_code, code);
 		g_free (code);*/
-		if (inst->cil_code < second->cil_code && inst->next->cil_code >= second->cil_code) {
-			second->code = inst->next;
-			inst->next = NULL;
-			first->last_ins = inst;
-			second->next_bb = first->next_bb;
-			first->next_bb = second;
-			return;
-		}
+		if (inst->cil_code >= second->cil_code)
+			continue;
+
+		inst_next = mono_inst_list_next(&inst->node,
+						&first->ins_list);
+		if (!inst_next)
+			break;
+
+		if (inst_next->cil_code < second->cil_code)
+			continue;
+			
+		second->ins_list.next = inst->node.next;
+		second->ins_list.prev = first->ins_list.prev;
+		inst->node.next = &first->ins_list;
+		first->ins_list.prev = &inst->node;
+
+		second->next_bb = first->next_bb;
+		first->next_bb = second;
+		return;
 	}
-	if (!second->code) {
+	if (MONO_INST_LIST_EMPTY(&second->ins_list)) {
 		g_warning ("bblock split failed in %s::%s\n", cfg->method->klass->name, cfg->method->name);
 		//G_BREAKPOINT ();
 	}
@@ -1838,45 +1857,16 @@ array_access_to_klass (int opcode, MonoI
 void
 mono_add_ins_to_end (MonoBasicBlock *bb, MonoInst *inst)
 {
-	MonoInst *prev;
-	if (!bb->code) {
-		MONO_ADD_INS (bb, inst);
-		return;
-	}
-	switch (bb->last_ins->opcode) {
-	case CEE_BEQ:
-	case CEE_BGE:
-	case CEE_BGT:
-	case CEE_BLE:
-	case CEE_BLT:
-	case CEE_BNE_UN:
-	case CEE_BGE_UN:
-	case CEE_BGT_UN:
-	case CEE_BLE_UN:
-	case CEE_BLT_UN:
-	case OP_BR:
-	case CEE_SWITCH:
-		prev = bb->code;
-		while (prev->next && prev->next != bb->last_ins)
-			prev = prev->next;
-		if (prev == bb->code) {
-			if (bb->last_ins == bb->code) {
-				inst->next = bb->code;
-				bb->code = inst;
-			} else {
-				inst->next = prev->next;
-				prev->next = inst;
-			}
-		} else {
-			inst->next = bb->last_ins;
-			prev->next = inst;
-		}
-		break;
-	//	g_warning ("handle conditional jump in add_ins_to_end ()\n");
-	default:
+	MonoInst *last = mono_inst_list_last(&bb->ins_list);
+
+	if (last &&
+	    ((last->opcode >= CEE_BEQ &&
+	      last->opcode <= CEE_BLT_UN) ||
+	     last->opcode == OP_BR ||
+	     last->opcode == CEE_SWITCH))
+		MONO_INST_LIST_ADD_TAIL(&inst->node, &last->node);
+	else
 		MONO_ADD_INS (bb, inst);
-		break;
-	}
 }
 
 void
@@ -2551,7 +2541,7 @@ mono_emit_call_args (MonoCompile *cfg, M
 		     MonoInst **args, int calli, int virtual, const guint8 *ip, gboolean to_end)
 {
 	MonoCallInst *call;
-	MonoInst *arg;
+	MonoInst *arg, *n;
 
 	MONO_INST_NEW_CALL (cfg, call, ret_type_to_call_opcode (sig->ret, calli, virtual));
 
@@ -2579,16 +2569,13 @@ mono_emit_call_args (MonoCompile *cfg, M
 	call = mono_arch_call_opcode (cfg, bblock, call, virtual);
 	type_to_eval_stack_type (cfg, sig->ret, &call->inst);
 
-	for (arg = call->out_args; arg;) {
-		MonoInst *narg = arg->next;
-		arg->next = NULL;
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(arg, n, &call->out_args, node) {
 		if (!arg->cil_code)
 			arg->cil_code = ip;
 		if (to_end)
 			mono_add_ins_to_end (bblock, arg);
 		else
 			MONO_ADD_INS (bblock, arg);
-		arg = narg;
 	}
 	return call;
 }
@@ -2686,8 +2673,8 @@ mono_emit_jit_icall (MonoCompile *cfg, M
 static void
 mono_emulate_opcode (MonoCompile *cfg, MonoInst *tree, MonoInst **iargs, MonoJitICallInfo *info)
 {
-	MonoInst *ins, *temp = NULL, *store, *load, *begin;
-	MonoInst *last_arg = NULL;
+	MonoInst *ins, *temp = NULL, *store, *load;
+	MonoInstList *head, *list;
 	int nargs;
 	MonoCallInst *call;
 
@@ -2695,6 +2682,7 @@ mono_emulate_opcode (MonoCompile *cfg, M
 	//mono_print_tree_nl (tree);
 	MONO_INST_NEW_CALL (cfg, call, ret_type_to_call_opcode (info->sig->ret, FALSE, FALSE));
 	ins = (MonoInst*)call;
+	MONO_INST_LIST_INIT(&ins->node);
 	
 	call->inst.cil_code = tree->cil_code;
 	call->args = iargs;
@@ -2706,6 +2694,7 @@ mono_emulate_opcode (MonoCompile *cfg, M
 		temp = mono_compile_create_var (cfg, info->sig->ret, OP_LOCAL);
 		temp->flags |= MONO_INST_IS_TEMP;
 		NEW_TEMPSTORE (cfg, store, temp->inst_c0, ins);
+		MONO_INST_LIST_INIT(&store->node);
 		/* FIXME: handle CEE_STIND_R4 */
 		store->cil_code = tree->cil_code;
 	} else {
@@ -2714,15 +2703,13 @@ mono_emulate_opcode (MonoCompile *cfg, M
 
 	nargs = info->sig->param_count + info->sig->hasthis;
 
-	for (last_arg = call->out_args; last_arg && last_arg->next; last_arg = last_arg->next) ;
-
-	if (nargs)
-		last_arg->next = store;
-
-	if (nargs)
-		begin = call->out_args;
-	else
-		begin = store;
+	if (nargs) {
+		MONO_INST_LIST_ADD_TAIL(&store->node,
+					&call->out_args);
+		list = &call->out_args;
+	} else {
+		list = &store->node;
+	}
 
 	if (cfg->prev_ins) {
 		/* 
@@ -2730,13 +2717,13 @@ mono_emulate_opcode (MonoCompile *cfg, M
 		 * node before it is called for its children. dec_foreach needs to
 		 * take this into account.
 		 */
-		store->next = cfg->prev_ins->next;
-		cfg->prev_ins->next = begin;
+		head = &cfg->prev_ins->node;
 	} else {
-		store->next = cfg->cbb->code;
-		cfg->cbb->code = begin;
+		head = &cfg->cbb->ins_list;
 	}
 
+	MONO_INST_LIST_SPLICE_INIT(list, head);
+
 	call->fptr = mono_icall_get_wrapper (info);
 
 	if (!MONO_TYPE_IS_VOID (info->sig->ret)) {
@@ -3119,12 +3106,7 @@ mono_emit_load_got_addr (MonoCompile *cf
 	NEW_TEMPSTORE (cfg, store, cfg->got_var->inst_c0, get_got);
 
 	/* Add it to the start of the first bblock */
-	if (cfg->bb_entry->code) {
-		store->next = cfg->bb_entry->code;
-		cfg->bb_entry->code = store;
-	}
-	else
-		MONO_ADD_INS (cfg->bb_entry, store);
+	MONO_INST_LIST_ADD(&store->node, &cfg->bb_entry->ins_list);
 
 	cfg->got_var_allocated = TRUE;
 
@@ -3601,11 +3583,11 @@ inline_method (MonoCompile *cfg, MonoMet
 		mono_compile_create_var (cfg, cheader->locals [i], OP_LOCAL);
 
 	/* allocate starte and end blocks */
-	sbblock = NEW_BBLOCK (cfg);
+	NEW_BBLOCK (cfg, sbblock);
 	sbblock->block_num = cfg->num_bblocks++;
 	sbblock->real_offset = real_offset;
 
-	ebblock = NEW_BBLOCK (cfg);
+	NEW_BBLOCK (cfg, ebblock);
 	ebblock->block_num = cfg->num_bblocks++;
 	ebblock->real_offset = real_offset;
 
@@ -4131,13 +4113,15 @@ mono_method_to_ir (MonoCompile *cfg, Mon
 			cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
 
 		/* ENTRY BLOCK */
-		cfg->bb_entry = start_bblock = NEW_BBLOCK (cfg);
+		NEW_BBLOCK (cfg, start_bblock);
+		cfg->bb_entry = start_bblock;
 		start_bblock->cil_code = NULL;
 		start_bblock->cil_length = 0;
 		start_bblock->block_num = cfg->num_bblocks++;
 
 		/* EXIT BLOCK */
-		cfg->bb_exit = end_bblock = NEW_BBLOCK (cfg);
+		NEW_BBLOCK (cfg, end_bblock);
+		cfg->bb_exit = end_bblock;
 		end_bblock->cil_code = NULL;
 		end_bblock->cil_length = 0;
 		end_bblock->block_num = cfg->num_bblocks++;
@@ -4228,7 +4212,7 @@ mono_method_to_ir (MonoCompile *cfg, Mon
 	}
 
 	/* FIRST CODE BLOCK */
-	bblock = NEW_BBLOCK (cfg);
+	NEW_BBLOCK (cfg, bblock);
 	bblock->cil_code = ip;
 
 	ADD_BBLOCK (cfg, bblock);
@@ -4283,7 +4267,8 @@ mono_method_to_ir (MonoCompile *cfg, Mon
 	
 	if ((header->init_locals || (cfg->method == method && (cfg->opt & MONO_OPT_SHARED))) || cfg->compile_aot || security || pinvoke) {
 		/* we use a separate basic block for the initialization code */
-		cfg->bb_init = init_localsbb = NEW_BBLOCK (cfg);
+		NEW_BBLOCK (cfg, init_localsbb);
+		cfg->bb_init = init_localsbb;
 		init_localsbb->real_offset = real_offset;
 		start_bblock->next_bb = init_localsbb;
 		init_localsbb->next_bb = bblock;
@@ -8861,14 +8846,13 @@ mono_inst_foreach (MonoInst *tree, MonoI
 
 G_GNUC_UNUSED
 static void
-mono_print_bb_code (MonoBasicBlock *bb) {
-	if (bb->code) {
-		MonoInst *c = bb->code;
-		while (c) {
-			mono_print_tree (c);
-			g_print ("\n");
-			c = c->next;
-		}
+mono_print_bb_code (MonoBasicBlock *bb)
+{
+	MonoInst *c;
+
+	MONO_INST_LIST_FOR_EACH_ENTRY(c, &bb->ins_list, node) {
+		mono_print_tree (c);
+		g_print ("\n");
 	}
 }
 
@@ -8881,6 +8865,8 @@ print_dfn (MonoCompile *cfg) {
 	g_print ("IR code for method %s\n", mono_method_full_name (cfg->method, TRUE));
 
 	for (i = 0; i < cfg->num_bblocks; ++i) {
+		MonoInst *c;
+
 		bb = cfg->bblocks [i];
 		/*if (bb->cil_code) {
 			char* code1, *code2;
@@ -8897,15 +8883,9 @@ print_dfn (MonoCompile *cfg) {
 		} else*/
 			code = g_strdup ("\n");
 		g_print ("\nBB%d DFN%d (len: %d): %s", bb->block_num, i, bb->cil_length, code);
-		if (bb->code) {
-			MonoInst *c = bb->code;
-			while (c) {
-				mono_print_tree (c);
-				g_print ("\n");
-				c = c->next;
-			}
-		} else {
-
+		MONO_INST_LIST_FOR_EACH_ENTRY(c, &bb->ins_list, node) {
+			mono_print_tree (c);
+			g_print ("\n");
 		}
 
 		g_print ("\tprev:");
@@ -8934,14 +8914,7 @@ print_dfn (MonoCompile *cfg) {
 void
 mono_bblock_add_inst (MonoBasicBlock *bb, MonoInst *inst)
 {
-	inst->next = NULL;
-	if (bb->last_ins) {
-		g_assert (bb->code);
-		bb->last_ins->next = inst;
-		bb->last_ins = inst;
-	} else {
-		bb->last_ins = bb->code = inst;
-	}
+	MONO_INST_LIST_ADD_TAIL(&inst->node, &bb->ins_list);
 }
 
 void
@@ -9508,7 +9481,7 @@ decompose_pass (MonoCompile *cfg) {
 		MonoInst *tree;
 		cfg->cbb = bb;
 		cfg->prev_ins = NULL;
-		for (tree = cfg->cbb->code; tree; tree = tree->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(tree, &cfg->cbb->ins_list, node){
 			dec_foreach (tree, cfg);
 			cfg->prev_ins = tree;
 		}
@@ -9523,7 +9496,7 @@ nullify_basic_block (MonoBasicBlock *bb)
 	bb->in_bb = NULL;
 	bb->out_bb = NULL;
 	bb->next_bb = NULL;
-	bb->code = bb->last_ins = NULL;
+	MONO_INST_LIST_INIT(&bb->ins_list);
 	bb->cil_code = NULL;
 }
 
@@ -9571,50 +9544,48 @@ static void
 replace_out_block_in_code (MonoBasicBlock *bb, MonoBasicBlock *orig, MonoBasicBlock *repl) {
 	MonoInst *inst;
 	
-	for (inst = bb->code; inst != NULL; inst = inst->next) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node) {
 		if (inst->opcode == OP_CALL_HANDLER) {
-			if (inst->inst_target_bb == orig) {
+			if (inst->inst_target_bb == orig)
 				inst->inst_target_bb = repl;
-			}
 		}
 	}
-	if (bb->last_ins != NULL) {
-		switch (bb->last_ins->opcode) {
-		case OP_BR:
-			if (bb->last_ins->inst_target_bb == orig) {
-				bb->last_ins->inst_target_bb = repl;
-			}
-			break;
-		case CEE_SWITCH: {
-			int i;
-			int n = GPOINTER_TO_INT (bb->last_ins->klass);
-			for (i = 0; i < n; i++ ) {
-				if (bb->last_ins->inst_many_bb [i] == orig) {
-					bb->last_ins->inst_many_bb [i] = repl;
-				}
-			}
-			break;
-		}
-		case CEE_BNE_UN:
-		case CEE_BEQ:
-		case CEE_BLT:
-		case CEE_BLT_UN:
-		case CEE_BGT:
-		case CEE_BGT_UN:
-		case CEE_BGE:
-		case CEE_BGE_UN:
-		case CEE_BLE:
-		case CEE_BLE_UN:
-			if (bb->last_ins->inst_true_bb == orig) {
-				bb->last_ins->inst_true_bb = repl;
-			}
-			if (bb->last_ins->inst_false_bb == orig) {
-				bb->last_ins->inst_false_bb = repl;
-			}
-			break;
-		default:
-			break;
+
+	inst = mono_inst_list_last(&bb->ins_list);
+	if (!inst)
+		return;
+
+	switch (inst->opcode) {
+	case OP_BR:
+		if (inst->inst_target_bb == orig)
+			inst->inst_target_bb = repl;
+		break;
+	case CEE_SWITCH: {
+		int i;
+		int n = GPOINTER_TO_INT (inst->klass);
+		for (i = 0; i < n; i++ ) {
+			if (inst->inst_many_bb [i] == orig)
+				inst->inst_many_bb [i] = repl;
 		}
+		break;
+	}
+	case CEE_BNE_UN:
+	case CEE_BEQ:
+	case CEE_BLT:
+	case CEE_BLT_UN:
+	case CEE_BGT:
+	case CEE_BGT_UN:
+	case CEE_BGE:
+	case CEE_BGE_UN:
+	case CEE_BLE:
+	case CEE_BLE_UN:
+		if (inst->inst_true_bb == orig)
+			inst->inst_true_bb = repl;
+		if (inst->inst_false_bb == orig)
+			inst->inst_false_bb = repl;
+		break;
+	default:
+		break;
 	}
 }
 
@@ -9651,7 +9622,7 @@ remove_block_if_useless (MonoCompile *cf
 		return FALSE;
 	}
 	
-	for (inst = bb->code; inst != NULL; inst = inst->next) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node) {
 		switch (inst->opcode) {
 		case OP_NOP:
 			break;
@@ -9674,9 +9645,9 @@ remove_block_if_useless (MonoCompile *cf
 	}
 	
 	/* Do not touch BBs following a switch (they are the "default" branch) */
-	if ((previous_bb->last_ins != NULL) && (previous_bb->last_ins->opcode == CEE_SWITCH)) {
+	inst = mono_inst_list_last(&previous_bb->ins_list);
+	if (inst && inst->opcode == CEE_SWITCH)
 		return FALSE;
-	}
 	
 	/* Do not touch BBs following the entry BB and jumping to something that is not */
 	/* thiry "next" bb (the entry BB cannot contain the branch) */
@@ -9693,6 +9664,7 @@ remove_block_if_useless (MonoCompile *cf
 	
 	/* Check that there is a target BB, and that bb is not an empty loop (Bug 75061) */
 	if ((target_bb != NULL) && (target_bb != bb)) {
+		MonoInst *last_ins;
 		int i;
 
 		if (cfg->verbose_level > 1) {
@@ -9709,12 +9681,14 @@ remove_block_if_useless (MonoCompile *cf
 		
 		mono_unlink_bblock (cfg, bb, target_bb);
 		
+		last_ins = mono_inst_list_last(&previous_bb->ins_list);
+
 		if ((previous_bb != cfg->bb_entry) &&
-				(previous_bb->region == bb->region) &&
-				((previous_bb->last_ins == NULL) ||
-				((previous_bb->last_ins->opcode != OP_BR) &&
-				(! (MONO_IS_COND_BRANCH_OP (previous_bb->last_ins))) &&
-				(previous_bb->last_ins->opcode != CEE_SWITCH)))) {
+		    (previous_bb->region == bb->region) &&
+		    ((last_ins == NULL) ||
+		     ((last_ins->opcode != OP_BR) &&
+		      (! (MONO_IS_COND_BRANCH_OP (last_ins))) &&
+		      (last_ins->opcode != CEE_SWITCH)))) {
 			for (i = 0; i < previous_bb->out_count; i++) {
 				if (previous_bb->out_bb [i] == target_bb) {
 					MonoInst *jump;
@@ -9739,25 +9713,21 @@ remove_block_if_useless (MonoCompile *cf
 static void
 merge_basic_blocks (MonoBasicBlock *bb, MonoBasicBlock *bbn) 
 {
+	MonoInst *last_ins;
+
 	bb->out_count = bbn->out_count;
 	bb->out_bb = bbn->out_bb;
 
 	replace_basic_block (bb, bbn, bb);
 
+	last_ins = mono_inst_list_last(&bb->ins_list);
+
 	/* Nullify branch at the end of bb */
-	if (bb->last_ins && MONO_IS_BRANCH_OP (bb->last_ins)) {
-		bb->last_ins->opcode = OP_NOP;
-	}		
+	if (last_ins && MONO_IS_BRANCH_OP (last_ins))
+		last_ins->opcode = OP_NOP;
+
+	MONO_INST_LIST_SPLICE_TAIL_INIT(&bbn->ins_list, &bb->ins_list);
 
-	if (bb->last_ins) {
-		if (bbn->code) {
-			bb->last_ins->next = bbn->code;
-			bb->last_ins = bbn->last_ins;
-		}
-	} else {
-		bb->code = bbn->code;
-		bb->last_ins = bbn->last_ins;
-	}
 	bb->next_bb = bbn->next_bb;
 	nullify_basic_block (bbn);
 }
@@ -9766,6 +9736,7 @@ static void
 move_basic_block_to_end (MonoCompile *cfg, MonoBasicBlock *bb)
 {
 	MonoBasicBlock *bbn, *next;
+	MonoInst *last_ins;
 
 	next = bb->next_bb;
 
@@ -9782,8 +9753,10 @@ move_basic_block_to_end (MonoCompile *cf
 	bbn->next_bb = bb;
 	bb->next_bb = NULL;
 
+	last_ins = mono_inst_list_last(&bb->ins_list);
+
 	/* Add a branch */
-	if (next && (!bb->last_ins || (bb->last_ins->opcode != OP_NOT_REACHED))) {
+	if (next && (!last_ins || (last_ins->opcode != OP_NOT_REACHED))) {
 		MonoInst *ins;
 
 		MONO_INST_NEW (cfg, ins, OP_BR);
@@ -9865,20 +9838,20 @@ tree_is_unsigned (MonoInst* ins) {
  * Note that this can't be applied if the second arg is not positive...
  */
 static int
-try_unsigned_compare (MonoCompile *cfg, MonoBasicBlock *bb)
+try_unsigned_compare (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *bb_last)
 {
 	MonoBasicBlock *truet, *falset;
-	MonoInst *cmp_inst = bb->last_ins->inst_left;
+	MonoInst *cmp_inst = bb_last->inst_left;
 	MonoInst *condb;
 	if (!cmp_inst->inst_right->inst_c0 == 0)
 		return FALSE;
-	truet = bb->last_ins->inst_true_bb;
-	falset = bb->last_ins->inst_false_bb;
+	truet = bb_last->inst_true_bb;
+	falset = bb_last->inst_false_bb;
 	if (falset->in_count != 1)
 		return FALSE;
-	condb = falset->last_ins;
+	condb = mono_inst_list_last(&falset->ins_list);
 	/* target bb must have one instruction */
-	if (!condb || (condb != falset->code))
+	if (!condb || (condb->node.next != &falset->ins_list))
 		return FALSE;
 	if ((((condb->opcode == CEE_BLE || condb->opcode == CEE_BLT) && (condb->inst_false_bb == truet))
 			|| ((condb->opcode == CEE_BGE || condb->opcode == CEE_BGT) && (condb->inst_true_bb == truet)))
@@ -9887,8 +9860,8 @@ try_unsigned_compare (MonoCompile *cfg, 
 			return FALSE;
 		condb->opcode = get_unsigned_condbranch (condb->opcode);
 		/* change the original condbranch to just point to the new unsigned check */
-		bb->last_ins->opcode = OP_BR;
-		bb->last_ins->inst_target_bb = falset;
+		bb_last->opcode = OP_BR;
+		bb_last->inst_target_bb = falset;
 		replace_out_block (bb, truet, NULL);
 		replace_in_block (truet, bb, NULL);
 		return TRUE;
@@ -9924,6 +9897,7 @@ optimize_branches (MonoCompile *cfg)
 
 		/* we skip the entry block (exit is handled specially instead ) */
 		for (previous_bb = cfg->bb_entry, bb = cfg->bb_entry->next_bb; bb; previous_bb = bb, bb = bb->next_bb) {
+			MonoInst *last_ins;
 
 			/* dont touch code inside exception clauses */
 			if (bb->region != -1)
@@ -9947,20 +9921,22 @@ optimize_branches (MonoCompile *cfg)
 				changed = TRUE;
 			}
 
+			last_ins = mono_inst_list_last(&bb->ins_list);
 			if (bb->out_count == 1) {
 				bbn = bb->out_bb [0];
 
 				/* conditional branches where true and false targets are the same can be also replaced with OP_BR */
-				if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins)) {
+				if (last_ins &&
+				    MONO_IS_COND_BRANCH_OP (last_ins)) {
 					MonoInst *pop;
 					MONO_INST_NEW (cfg, pop, CEE_POP);
-					pop->inst_left = bb->last_ins->inst_left->inst_left;
+					pop->inst_left = last_ins->inst_left->inst_left;
 					mono_add_ins_to_end (bb, pop);
 					MONO_INST_NEW (cfg, pop, CEE_POP);
-					pop->inst_left = bb->last_ins->inst_left->inst_right;
+					pop->inst_left = last_ins->inst_left->inst_right;
 					mono_add_ins_to_end (bb, pop);
-					bb->last_ins->opcode = OP_BR;
-					bb->last_ins->inst_target_bb = bb->last_ins->inst_true_bb;
+					last_ins->opcode = OP_BR;
+					last_ins->inst_target_bb = last_ins->inst_true_bb;
 					changed = TRUE;
 					if (cfg->verbose_level > 2)
 						g_print ("cond branch removal triggered in %d %d\n", bb->block_num, bb->out_count);
@@ -9970,8 +9946,8 @@ optimize_branches (MonoCompile *cfg)
 					/* the block are in sequence anyway ... */
 
 					/* branches to the following block can be removed */
-					if (bb->last_ins && bb->last_ins->opcode == OP_BR) {
-						bb->last_ins->opcode = OP_NOP;
+					if (last_ins && last_ins->opcode == OP_BR) {
+						last_ins->opcode = OP_NOP;
 						changed = TRUE;
 						if (cfg->verbose_level > 2)
 							g_print ("br removal triggered %d -> %d\n", bb->block_num, bbn->block_num);
@@ -10008,84 +9984,92 @@ optimize_branches (MonoCompile *cfg)
 			if (bb->out_count == 1) {
 				bbn = bb->out_bb [0];
 
-				if (bb->last_ins && bb->last_ins->opcode == OP_BR) {
-					bbn = bb->last_ins->inst_target_bb;
-					if (bb->region == bbn->region && bbn->code && bbn->code->opcode == OP_BR &&
-					    bbn->code->inst_target_bb->region == bb->region) {
-						
+				if (last_ins && last_ins->opcode == OP_BR) {
+					MonoInst *bbn_code;
+
+					bbn = last_ins->inst_target_bb;
+					bbn_code = mono_inst_list_first(&bbn->ins_list);
+					if (bb->region == bbn->region &&
+					    bbn_code &&
+					    bbn_code->opcode == OP_BR &&
+					    bbn_code->inst_target_bb->region == bb->region) {
 						if (cfg->verbose_level > 2)
 							g_print ("in %s branch to branch triggered %d -> %d -> %d\n", cfg->method->name, 
-								 bb->block_num, bbn->block_num, bbn->code->inst_target_bb->block_num);
+								 bb->block_num, bbn->block_num, bbn_code->inst_target_bb->block_num);
 
 						replace_in_block (bbn, bb, NULL);
-						replace_out_block (bb, bbn, bbn->code->inst_target_bb);
-						link_bblock (cfg, bb, bbn->code->inst_target_bb);
-						bb->last_ins->inst_target_bb = bbn->code->inst_target_bb;
+						replace_out_block (bb, bbn, bbn_code->inst_target_bb);
+						link_bblock (cfg, bb, bbn_code->inst_target_bb);
+						last_ins->inst_target_bb = bbn_code->inst_target_bb;
 						changed = TRUE;
 						continue;
 					}
 				}
 			} else if (bb->out_count == 2) {
-				if (bb->last_ins && MONO_IS_COND_BRANCH_NOFP (bb->last_ins)) {
-					int branch_result = mono_eval_cond_branch (bb->last_ins);
+				if (last_ins && MONO_IS_COND_BRANCH_NOFP (last_ins)) {
+					int branch_result = mono_eval_cond_branch (last_ins);
 					MonoBasicBlock *taken_branch_target = NULL, *untaken_branch_target = NULL;
+					MonoInst *bbn_code;
+
 					if (branch_result == BRANCH_TAKEN) {
-						taken_branch_target = bb->last_ins->inst_true_bb;
-						untaken_branch_target = bb->last_ins->inst_false_bb;
+						taken_branch_target = last_ins->inst_true_bb;
+						untaken_branch_target = last_ins->inst_false_bb;
 					} else if (branch_result == BRANCH_NOT_TAKEN) {
-						taken_branch_target = bb->last_ins->inst_false_bb;
-						untaken_branch_target = bb->last_ins->inst_true_bb;
+						taken_branch_target = last_ins->inst_false_bb;
+						untaken_branch_target = last_ins->inst_true_bb;
 					}
 					if (taken_branch_target) {
 						/* if mono_eval_cond_branch () is ever taken to handle 
 						 * non-constant values to compare, issue a pop here.
 						 */
-						bb->last_ins->opcode = OP_BR;
-						bb->last_ins->inst_target_bb = taken_branch_target;
+						last_ins->opcode = OP_BR;
+						last_ins->inst_target_bb = taken_branch_target;
 						mono_unlink_bblock (cfg, bb, untaken_branch_target);
 						changed = TRUE;
 						continue;
 					}
-					bbn = bb->last_ins->inst_true_bb;
-					if (bb->region == bbn->region && bbn->code && bbn->code->opcode == OP_BR &&
-					    bbn->code->inst_target_bb->region == bb->region) {
+					bbn = last_ins->inst_true_bb;
+					bbn_code = mono_inst_list_first(&bbn->ins_list);
+					if (bb->region == bbn->region && bbn_code && bbn_code->opcode == OP_BR &&
+					    bbn_code->inst_target_bb->region == bb->region) {
 						if (cfg->verbose_level > 2)		
 							g_print ("cbranch1 to branch triggered %d -> (%d) %d (0x%02x)\n", 
-								 bb->block_num, bbn->block_num, bbn->code->inst_target_bb->block_num, 
-								 bbn->code->opcode);
+								 bb->block_num, bbn->block_num, bbn_code->inst_target_bb->block_num, 
+								 bbn_code->opcode);
 
 						/* 
 						 * Unlink, then relink bblocks to avoid various
 						 * tricky situations when the two targets of the branch
 						 * are equal, or will become equal after the change.
 						 */
-						mono_unlink_bblock (cfg, bb, bb->last_ins->inst_true_bb);
-						mono_unlink_bblock (cfg, bb, bb->last_ins->inst_false_bb);
+						mono_unlink_bblock (cfg, bb, last_ins->inst_true_bb);
+						mono_unlink_bblock (cfg, bb, last_ins->inst_false_bb);
 
-						bb->last_ins->inst_true_bb = bbn->code->inst_target_bb;
+						last_ins->inst_true_bb = bbn_code->inst_target_bb;
 
-						link_bblock (cfg, bb, bb->last_ins->inst_true_bb);
-						link_bblock (cfg, bb, bb->last_ins->inst_false_bb);
+						link_bblock (cfg, bb, last_ins->inst_true_bb);
+						link_bblock (cfg, bb, last_ins->inst_false_bb);
 
 						changed = TRUE;
 						continue;
 					}
 
-					bbn = bb->last_ins->inst_false_bb;
-					if (bb->region == bbn->region && bbn->code && bbn->code->opcode == OP_BR &&
-					    bbn->code->inst_target_bb->region == bb->region) {
+					bbn = last_ins->inst_false_bb;
+					bbn_code = mono_inst_list_first(&bbn->ins_list);
+					if (bb->region == bbn->region && bbn_code && bbn_code->opcode == OP_BR &&
+					    bbn_code->inst_target_bb->region == bb->region) {
 						if (cfg->verbose_level > 2)
 							g_print ("cbranch2 to branch triggered %d -> (%d) %d (0x%02x)\n", 
-								 bb->block_num, bbn->block_num, bbn->code->inst_target_bb->block_num, 
-								 bbn->code->opcode);
+								 bb->block_num, bbn->block_num, bbn_code->inst_target_bb->block_num, 
+								 bbn_code->opcode);
 
-						mono_unlink_bblock (cfg, bb, bb->last_ins->inst_true_bb);
-						mono_unlink_bblock (cfg, bb, bb->last_ins->inst_false_bb);
+						mono_unlink_bblock (cfg, bb, last_ins->inst_true_bb);
+						mono_unlink_bblock (cfg, bb, last_ins->inst_false_bb);
 
-						bb->last_ins->inst_false_bb = bbn->code->inst_target_bb;
+						last_ins->inst_false_bb = bbn_code->inst_target_bb;
 
-						link_bblock (cfg, bb, bb->last_ins->inst_true_bb);
-						link_bblock (cfg, bb, bb->last_ins->inst_false_bb);
+						link_bblock (cfg, bb, last_ins->inst_true_bb);
+						link_bblock (cfg, bb, last_ins->inst_false_bb);
 
 						changed = TRUE;
 						continue;
@@ -10093,23 +10077,23 @@ optimize_branches (MonoCompile *cfg)
 				}
 
 				/* detect and optimize to unsigned compares checks like: if (v < 0 || v > limit */
-				if (bb->last_ins && bb->last_ins->opcode == CEE_BLT && bb->last_ins->inst_left->inst_right->opcode == OP_ICONST) {
-					if (try_unsigned_compare (cfg, bb)) {
-						/*g_print ("applied in bb %d (->%d) %s\n", bb->block_num, bb->last_ins->inst_target_bb->block_num, mono_method_full_name (cfg->method, TRUE));*/
+				if (last_ins && last_ins->opcode == CEE_BLT && last_ins->inst_left->inst_right->opcode == OP_ICONST) {
+					if (try_unsigned_compare (cfg, bb, last_ins)) {
+						/*g_print ("applied in bb %d (->%d) %s\n", bb->block_num, last_ins->inst_target_bb->block_num, mono_method_full_name (cfg->method, TRUE));*/
 						changed = TRUE;
 						continue;
 					}
 				}
 
-				if (bb->last_ins && MONO_IS_COND_BRANCH_NOFP (bb->last_ins)) {
-					if (bb->last_ins->inst_false_bb->out_of_line && (bb->region == bb->last_ins->inst_false_bb->region)) {
+				if (last_ins && MONO_IS_COND_BRANCH_NOFP (last_ins)) {
+					if (last_ins->inst_false_bb->out_of_line && (bb->region == last_ins->inst_false_bb->region)) {
 						/* Reverse the branch */
-						bb->last_ins->opcode = reverse_branch_op (bb->last_ins->opcode);
-						bbn = bb->last_ins->inst_false_bb;
-						bb->last_ins->inst_false_bb = bb->last_ins->inst_true_bb;
-						bb->last_ins->inst_true_bb = bbn;
+						last_ins->opcode = reverse_branch_op (last_ins->opcode);
+						bbn = last_ins->inst_false_bb;
+						last_ins->inst_false_bb = last_ins->inst_true_bb;
+						last_ins->inst_true_bb = bbn;
 
-						move_basic_block_to_end (cfg, bb->last_ins->inst_true_bb);
+						move_basic_block_to_end (cfg, last_ins->inst_true_bb);
 						if (cfg->verbose_level > 2)
 							g_print ("cbranch to throw block triggered %d.\n", 
 									 bb->block_num);
@@ -10174,20 +10158,16 @@ mono_print_code (MonoCompile *cfg)
 	MonoBasicBlock *bb;
 	
 	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-		MonoInst *tree = bb->code;	
+		MonoInst *tree;
 
-		if (!tree)
-			continue;
-		
-		g_print ("CODE BLOCK %d (nesting %d):\n", bb->block_num, bb->nesting);
+		if (!MONO_INST_LIST_EMPTY(&bb->ins_list))
+			g_print ("CODE BLOCK %d (nesting %d):\n",
+				 bb->block_num, bb->nesting);
 
-		for (; tree; tree = tree->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(tree, &bb->ins_list, node) {
 			mono_print_tree (tree);
 			g_print ("\n");
 		}
-
-		if (bb->last_ins)
-			bb->last_ins->next = NULL;
 	}
 }
 
@@ -10269,22 +10249,24 @@ mini_select_instructions (MonoCompile *c
 	cfg->rs = mono_regstate_new ();
 
 	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-		if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins) &&
-		    bb->next_bb != bb->last_ins->inst_false_bb) {
+		MonoInst *last_ins = mono_inst_list_last(&bb->ins_list);
+
+		if (last_ins && MONO_IS_COND_BRANCH_OP (last_ins) &&
+		    bb->next_bb != last_ins->inst_false_bb) {
 
 			/* we are careful when inverting, since bugs like #59580
 			 * could show up when dealing with NaNs.
 			 */
-			if (MONO_IS_COND_BRANCH_NOFP(bb->last_ins) && bb->next_bb == bb->last_ins->inst_true_bb) {
-				MonoBasicBlock *tmp =  bb->last_ins->inst_true_bb;
-				bb->last_ins->inst_true_bb = bb->last_ins->inst_false_bb;
-				bb->last_ins->inst_false_bb = tmp;
+			if (MONO_IS_COND_BRANCH_NOFP(last_ins) && bb->next_bb == last_ins->inst_true_bb) {
+				MonoBasicBlock *tmp =  last_ins->inst_true_bb;
+				last_ins->inst_true_bb = last_ins->inst_false_bb;
+				last_ins->inst_false_bb = tmp;
 
-				bb->last_ins->opcode = reverse_branch_op (bb->last_ins->opcode);
+				last_ins->opcode = reverse_branch_op (last_ins->opcode);
 			} else {			
 				MonoInst *inst = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst));
 				inst->opcode = OP_BR;
-				inst->inst_target_bb = bb->last_ins->inst_false_bb;
+				inst->inst_target_bb = last_ins->inst_false_bb;
 				mono_bblock_add_inst (bb, inst);
 			}
 		}
@@ -10293,11 +10275,10 @@ mini_select_instructions (MonoCompile *c
 #ifdef DEBUG_SELECTION
 	if (cfg->verbose_level >= 4) {
 	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-		MonoInst *tree = bb->code;	
+		MonoInst *tree;	
 		g_print ("DUMP BLOCK %d:\n", bb->block_num);
-		if (!tree)
-			continue;
-		for (; tree; tree = tree->next) {
+
+		MONO_INST_LIST_FOR_EACH_ENTRY(tree, &bb->ins_list, node) {
 			mono_print_tree (tree);
 			g_print ("\n");
 		}
@@ -10306,13 +10287,14 @@ mini_select_instructions (MonoCompile *c
 #endif
 
 	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-		MonoInst *tree = bb->code, *next;	
+		MonoInst *tree, *n;	
+		MonoInstList head;
 		MBState *mbstate;
 
-		if (!tree)
+		MONO_INST_LIST_INIT(&head);
+		if (MONO_INST_LIST_EMPTY(&bb->ins_list))
 			continue;
-		bb->code = NULL;
-		bb->last_ins = NULL;
+		MONO_INST_LIST_SPLICE_INIT(&bb->ins_list, &head);
 		
 		cfg->cbb = bb;
 		mono_regstate_reset (cfg->rs);
@@ -10321,8 +10303,7 @@ mini_select_instructions (MonoCompile *c
 		if (cfg->verbose_level >= 3)
 			g_print ("LABEL BLOCK %d:\n", bb->block_num);
 #endif
-		for (; tree; tree = next) {
-			next = tree->next;
+		MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(tree, n, &head, node) {
 #ifdef DEBUG_SELECTION
 			if (cfg->verbose_level >= 3) {
 				mono_print_tree (tree);
@@ -10340,9 +10321,6 @@ mini_select_instructions (MonoCompile *c
 		}
 		bb->max_vreg = cfg->rs->next_vreg;
 
-		if (bb->last_ins)
-			bb->last_ins->next = NULL;
-
 		mono_mempool_empty (cfg->state_pool); 
 	}
 	mono_mempool_destroy (cfg->state_pool); 
@@ -10529,6 +10507,7 @@ remove_critical_edges (MonoCompile *cfg)
 	
 	if (cfg->verbose_level > 3) {
 		for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+			MonoInst *last_ins;
 			int i;
 			printf ("remove_critical_edges %s, BEFORE BB%d (in:", mono_method_full_name (cfg->method, TRUE), bb->block_num);
 			for (i = 0; i < bb->in_count; i++) {
@@ -10539,9 +10518,10 @@ remove_critical_edges (MonoCompile *cfg)
 				printf (" %d", bb->out_bb [i]->block_num);
 			}
 			printf (")");
-			if (bb->last_ins != NULL) {
+			last_ins = mono_inst_list_last(&bb->ins_list);
+			if (last_ins) {
 				printf (" ");
-				mono_print_tree (bb->last_ins);
+				mono_print_tree (last_ins);
 			}
 			printf ("\n");
 		}
@@ -10554,6 +10534,7 @@ remove_critical_edges (MonoCompile *cfg)
 				MonoBasicBlock *in_bb = bb->in_bb [in_bb_index];
 				if (in_bb->out_count > 1) {
 					MonoBasicBlock *new_bb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
+					MONO_INST_LIST_INIT(&new_bb->ins_list);
 					new_bb->block_num = cfg->num_bblocks++;
 //					new_bb->real_offset = bb->real_offset;
 					new_bb->region = bb->region;
@@ -10561,12 +10542,14 @@ remove_critical_edges (MonoCompile *cfg)
 					/* Do not alter the CFG while altering the BB list */
 					if (previous_bb->region == bb->region) {
 						if (previous_bb != cfg->bb_entry) {
+							MonoInst *last_ins;
 							/* If previous_bb "followed through" to bb, */
 							/* keep it linked with a OP_BR */
-							if ((previous_bb->last_ins == NULL) ||
-									((previous_bb->last_ins->opcode != OP_BR) &&
-									(! (MONO_IS_COND_BRANCH_OP (previous_bb->last_ins))) &&
-									(previous_bb->last_ins->opcode != CEE_SWITCH))) {
+							last_ins = mono_inst_list_last(&previous_bb->ins_list);
+							if ((last_ins == NULL) ||
+									((last_ins->opcode != OP_BR) &&
+									(! (MONO_IS_COND_BRANCH_OP (last_ins))) &&
+									(last_ins->opcode != CEE_SWITCH))) {
 								int i;
 								/* Make sure previous_bb really falls through bb */
 								for (i = 0; i < previous_bb->out_count; i++) {
@@ -10585,6 +10568,7 @@ remove_critical_edges (MonoCompile *cfg)
 							/* put a new BB in the middle to hold the OP_BR */
 							MonoInst *jump;
 							MonoBasicBlock *new_bb_after_entry = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
+							MONO_INST_LIST_INIT(&new_bb_after_entry->ins_list);
 							new_bb_after_entry->block_num = cfg->num_bblocks++;
 //							new_bb_after_entry->real_offset = bb->real_offset;
 							new_bb_after_entry->region = bb->region;
@@ -10631,6 +10615,7 @@ remove_critical_edges (MonoCompile *cfg)
 	
 	if (cfg->verbose_level > 3) {
 		for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+			MonoInst *last_ins;
 			int i;
 			printf ("remove_critical_edges %s, AFTER BB%d (in:", mono_method_full_name (cfg->method, TRUE), bb->block_num);
 			for (i = 0; i < bb->in_count; i++) {
@@ -10641,9 +10626,10 @@ remove_critical_edges (MonoCompile *cfg)
 				printf (" %d", bb->out_bb [i]->block_num);
 			}
 			printf (")");
-			if (bb->last_ins != NULL) {
+			last_ins = mono_inst_list_last(&bb->ins_list);
+			if (last_ins) {
 				printf (" ");
-				mono_print_tree (bb->last_ins);
+				mono_print_tree (last_ins);
 			}
 			printf ("\n");
 		}
Index: mono/mini/mini.h
===================================================================
--- mono/mini/mini.h	(revision 89301)
+++ mono/mini/mini.h	(working copy)
@@ -95,6 +95,7 @@ enum {
 #define MONO_INST_NEW_CALL(cfg,dest,op) do {	\
 		(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoCallInst));	\
 		(dest)->inst.opcode = (op);	\
+		MONO_INST_LIST_INIT(&(dest)->out_args); \
 	} while (0)
 
 #define MONO_INST_NEW_CALL_ARG(cfg,dest,op) do {	\
@@ -102,21 +103,13 @@ enum {
 		(dest)->ins.opcode = (op);	\
 	} while (0)
 
-#define MONO_ADD_INS(b,inst) do {	\
-		if ((b)->last_ins) {	\
-			(b)->last_ins->next = (inst);	\
-			(b)->last_ins = (inst);	\
-		} else {	\
-			(b)->code = (b)->last_ins = (inst);	\
-		}	\
-	} while (0)
-
 #define NULLIFY_INS(ins) do { \
         (ins)->opcode = OP_NOP; \
         (ins)->dreg = (ins)->sreg1 = (ins)->sreg2 = -1; \
 		(ins)->ssa_op = MONO_SSA_NOP; \
     } while (0)
 
+typedef struct MonoInstList MonoInstList;
 typedef struct MonoInst MonoInst;
 typedef struct MonoCallInst MonoCallInst;
 typedef struct MonoCallArgParm MonoCallArgParm;
@@ -139,6 +132,139 @@ extern gboolean mono_compile_aot;
 extern MonoMethodDesc *mono_inject_async_exc_method;
 extern int mono_inject_async_exc_pos;
 
+struct MonoInstList {
+	struct MonoInstList *next, *prev;
+};
+
+#define MONO_INST_LIST_INIT(list)	\
+do {	(list)->next = (list);		\
+	(list)->prev = (list);		\
+} while (0)
+
+static inline int MONO_INST_LIST_EMPTY(MonoInstList *list)
+{
+	return list->next == list;
+}
+
+static inline void __MONO_INST_LIST_ADD(MonoInstList *new,
+					MonoInstList *prev,
+					MonoInstList *next)
+{
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
+}
+
+
+static inline void MONO_INST_LIST_ADD(MonoInstList *new,
+				      MonoInstList *head)
+{
+	__MONO_INST_LIST_ADD(new, head, head->next);
+}
+
+static inline void MONO_INST_LIST_ADD_TAIL(MonoInstList *new,
+					   MonoInstList *head)
+{
+	__MONO_INST_LIST_ADD(new, head->prev, head);
+}
+
+static inline void __MONO_INST_LIST_DEL(MonoInstList *prev,
+					MonoInstList *next)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+static inline void __MONO_INST_LIST_SPLICE(MonoInstList *list,
+					   MonoInstList *head)
+{
+	MonoInstList *first = list->next;
+	MonoInstList *last = list->prev;
+	MonoInstList *at = head->next;
+
+	first->prev = head;
+	head->next = first;
+
+	last->next = at;
+	at->prev = last;
+}
+
+static inline void MONO_INST_LIST_SPLICE(MonoInstList *list,
+					 MonoInstList *head) 
+{
+	if (! MONO_INST_LIST_EMPTY(list))
+		__MONO_INST_LIST_SPLICE(list, head);
+}
+
+static inline void MONO_INST_LIST_SPLICE_TAIL(MonoInstList *list,
+					      MonoInstList *head) 
+{
+	if (! MONO_INST_LIST_EMPTY(list))
+		__MONO_INST_LIST_SPLICE(list, head->prev);
+}
+
+static inline void MONO_INST_LIST_SPLICE_INIT(MonoInstList *list,
+					      MonoInstList *head)
+{
+	if (! MONO_INST_LIST_EMPTY(list)) {
+		__MONO_INST_LIST_SPLICE(list, head);
+		MONO_INST_LIST_INIT(list);
+	}
+}
+
+static inline void MONO_INST_LIST_SPLICE_TAIL_INIT(MonoInstList *list,
+						   MonoInstList *head)
+{
+	if (! MONO_INST_LIST_EMPTY(list)) {
+		__MONO_INST_LIST_SPLICE(list, head->prev);
+		MONO_INST_LIST_INIT(list);
+	}
+}
+
+#define mono_container_of(ptr, type, member) ({			\
+	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
+	(type *)( (char *)__mptr - offsetof(type,member) );})
+
+#define MONO_INST_LIST_ENTRY(ptr, type, member) \
+	mono_container_of(ptr, type, member)
+
+#define MONO_INST_LIST_FIRST_ENTRY(ptr, type, member) \
+	MONO_INST_LIST_ENTRY((ptr)->next, type, member)
+
+#define MONO_INST_LIST_LAST_ENTRY(ptr, type, member) \
+	MONO_INST_LIST_ENTRY((ptr)->prev, type, member)
+
+#define MONO_INST_LIST_FOR_EACH(pos, head) \
+	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define MONO_INST_LIST_FOR_EACH_PREV(pos, head) \
+	for (pos = (head)->prev; pos != (head); pos = pos->prev)
+
+#define MONO_INST_LIST_FOR_EACH_SAFE(pos, n, head) \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+		pos = n, n = pos->next)
+
+#define MONO_INST_LIST_FOR_EACH_PREV_SAFE(pos, n, head) \
+	for (pos = (head)->prev, n = pos->prev; pos != (head); \
+		pos = n, n = pos->prev)
+
+#define MONO_INST_LIST_FOR_EACH_ENTRY(pos, head, member) \
+	for (pos = MONO_INST_LIST_ENTRY((head)->next, typeof(*pos), member);\
+	     &pos->member != (head);\
+	     pos = MONO_INST_LIST_ENTRY(pos->member.next,typeof(*pos),member))
+
+#define MONO_INST_LIST_FOR_EACH_ENTRY_REVERSE(pos, head, member) \
+	for (pos = MONO_INST_LIST_ENTRY((head)->prev, typeof(*pos), member);\
+	     &pos->member != (head);\
+	     pos = MONO_INST_LIST_ENTRY(pos->member.prev,typeof(*pos),member))
+
+#define MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(pos, n, head, member) \
+	for (pos = MONO_INST_LIST_ENTRY((head)->next, typeof(*pos), member),\
+		n = MONO_INST_LIST_ENTRY(pos->member.next,typeof(*pos),member);\
+	     &pos->member != (head); 					\
+	     pos = n, n=MONO_INST_LIST_ENTRY(n->member.next,typeof(*n),member))
+
 struct MonoEdge {
 	MonoEdge *next;
 	MonoBasicBlock *bb;
@@ -171,19 +297,11 @@ typedef struct {
  * at the beginning of the block, never in the middle.
  */
 struct MonoBasicBlock {
-	MonoInst *last_ins;
+	MonoInstList ins_list;
 
 	/* the next basic block in the order it appears in IL */
 	MonoBasicBlock *next_bb;
 
-	/*
-	 * Before instruction selection it is the first tree in the
-	 * forest and the first item in the list of trees. After
-	 * instruction selection it is the first instruction and the
-	 * first item in the list of instructions.
-	 */
-	MonoInst *code;
-
 	/* unique block number identification */
 	gint32 block_num;
 	
@@ -281,6 +399,8 @@ typedef struct MonoMemcpyArgs {
 } MonoMemcpyArgs;
 
 struct MonoInst {
+	MonoInstList node;
+
 	union {
 		union {
 			MonoInst *src;
@@ -318,17 +438,56 @@ struct MonoInst {
 		gpointer data;
 	} backend;
 	
-	MonoInst *next;
 	MonoClass *klass;
 	const unsigned char* cil_code; /* for debugging and bblock splitting */
 };
 	
+static inline void MONO_ADD_INS(MonoBasicBlock *bb, MonoInst *inst)
+{
+	MONO_INST_LIST_ADD_TAIL(&inst->node, &bb->ins_list);
+}
+
+static inline void MONO_DEL_INS(MonoInst *inst)
+{
+	__MONO_INST_LIST_DEL(inst->node.prev, inst->node.next);
+}
+
+static inline MonoInst *mono_inst_list_first(MonoInstList *head)
+{
+	if (MONO_INST_LIST_EMPTY(head))
+		return NULL;
+	return MONO_INST_LIST_FIRST_ENTRY(head, MonoInst, node);
+}
+
+static inline MonoInst *mono_inst_list_last(MonoInstList *head)
+{
+	if (MONO_INST_LIST_EMPTY(head))
+		return NULL;
+	return MONO_INST_LIST_LAST_ENTRY(head, MonoInst, node);
+}
+
+static inline MonoInst *mono_inst_list_next(MonoInstList *ins,
+					    MonoInstList *head)
+{
+	if (ins->next == head)
+		return NULL;
+	return MONO_INST_LIST_ENTRY(ins->next, MonoInst, node);
+}
+
+static inline MonoInst *mono_inst_list_prev(MonoInstList *ins,
+					    MonoInstList *head)
+{
+	if (ins->prev == head)
+		return NULL;
+	return MONO_INST_LIST_ENTRY(ins->prev, MonoInst, node);
+}
+
 struct MonoCallInst {
 	MonoInst inst;
 	MonoMethodSignature *signature;
 	MonoMethod *method;
 	MonoInst **args;
-	MonoInst *out_args;
+	MonoInstList out_args;
 	gconstpointer fptr;
 	guint stack_usage;
 	gboolean virtual;
@@ -637,9 +796,7 @@ typedef struct {
 	/* Fields used by the local reg allocator */
 	void*            reginfo;
 	void*            reginfof;
-	void*            reverse_inst_list;
 	int              reginfo_len, reginfof_len;
-	int              reverse_inst_list_len;
 } MonoCompile;
 
 typedef enum {
Index: mono/mini/mini-amd64.c
===================================================================
--- mono/mini/mini-amd64.c	(revision 89301)
+++ mono/mini/mini-amd64.c	(working copy)
@@ -1251,10 +1251,7 @@ emit_sig_cookie (MonoCompile *cfg, MonoC
 	MONO_INST_NEW (cfg, arg, OP_OUTARG);
 	arg->inst_left = sig_arg;
 	arg->type = STACK_PTR;
-
-	/* prepend, so they get reversed */
-	arg->next = call->out_args;
-	call->out_args = arg;
+	MONO_INST_LIST_ADD(&arg->node, &call->out_args);
 }
 
 /* 
@@ -1296,9 +1293,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			arg->cil_code = in->cil_code;
 			arg->inst_left = in;
 			arg->type = in->type;
-			/* prepend, so they get reversed */
-			arg->next = call->out_args;
-			call->out_args = arg;
+			MONO_INST_LIST_ADD(&arg->node, &call->out_args);
 
 			if ((i >= sig->hasthis) && (MONO_TYPE_ISSTRUCT(sig->params [i - sig->hasthis]))) {
 				guint32 align;
@@ -1367,9 +1362,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 						MONO_INST_NEW (cfg, arg, OP_OUTARG);
 						arg->cil_code = in->cil_code;
 						arg->type = in->type;
-						/* prepend, so they get reversed */
-						arg->next = call->out_args;
-						call->out_args = arg;
+						MONO_INST_LIST_ADD(&arg->node, &call->out_args);
 
 						add_outarg_reg (cfg, call, arg, ainfo->pair_storage [1], ainfo->pair_regs [1], load);
 
@@ -1381,9 +1374,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 						arg->inst_right = in;
 						arg->type = in->type;
 
-						/* prepend, so they get reversed */
-						arg->next = call->out_args;
-						call->out_args = arg;
+						MONO_INST_LIST_ADD(&arg->node, &call->out_args);
 					}
 				}
 				else {
@@ -1426,9 +1417,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 
 	if (cinfo->need_stack_align) {
 		MONO_INST_NEW (cfg, arg, OP_AMD64_OUTARG_ALIGN_STACK);
-		/* prepend, so they get reversed */
-		arg->next = call->out_args;
-		call->out_args = arg;
+		MONO_INST_LIST_ADD(&arg->node, &call->out_args);
 	}
 
 	call->stack_usage = cinfo->stack_usage;
@@ -1613,10 +1602,11 @@ store_membase_imm_to_store_membase_reg (
 static void
 peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *last_ins = NULL;
-	ins = bb->code;
+	MonoInst *ins, *n;
 
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
+		MonoInst *last_ins = mono_inst_list_prev(&ins->node,
+							 &bb->ins_list);
 
 		switch (ins->opcode) {
 		case OP_ADD_IMM:
@@ -1644,7 +1634,12 @@ peephole_pass_1 (MonoCompile *cfg, MonoB
 				 * propagation). These instruction sequences are very common
 				 * in the initlocals bblock.
 				 */
-				for (ins2 = ins->next; ins2; ins2 = ins2->next) {
+				for (ins2 = mono_inst_list_next(&ins->node,
+								&bb->ins_list);
+				     ins2;
+				     ins2 = mono_inst_list_next(&ins2->node,
+								&bb->ins_list))
+				{
 					if (((ins2->opcode == OP_STORE_MEMBASE_IMM) || (ins2->opcode == OP_STOREI4_MEMBASE_IMM) || (ins2->opcode == OP_STOREI8_MEMBASE_IMM) || (ins2->opcode == OP_STORE_MEMBASE_IMM)) && (ins2->inst_imm == 0)) {
 						ins2->opcode = store_membase_imm_to_store_membase_reg (ins2->opcode);
 						ins2->sreg1 = ins->dreg;
@@ -1709,8 +1704,7 @@ peephole_pass_1 (MonoCompile *cfg, MonoB
 			    ins->inst_basereg == last_ins->inst_destbasereg &&
 			    ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -1735,8 +1729,7 @@ peephole_pass_1 (MonoCompile *cfg, MonoB
 			      ins->inst_offset == last_ins->inst_offset) {
 
 				if (ins->dreg == last_ins->dreg) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					ins->opcode = OP_MOVE;
@@ -1778,8 +1771,7 @@ peephole_pass_1 (MonoCompile *cfg, MonoB
 					ins->inst_basereg == last_ins->inst_destbasereg &&
 					ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -1802,8 +1794,7 @@ peephole_pass_1 (MonoCompile *cfg, MonoB
 					ins->inst_basereg == last_ins->inst_destbasereg &&
 					ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -1822,11 +1813,7 @@ peephole_pass_1 (MonoCompile *cfg, MonoB
 			 * OP_MOVE reg, reg 
 			 */
 			if (ins->dreg == ins->sreg1) {
-				if (last_ins)
-					last_ins->next = ins->next;				
-				else
-					bb->code = ins->next;
-				ins = ins->next;
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			/* 
@@ -1838,32 +1825,35 @@ peephole_pass_1 (MonoCompile *cfg, MonoB
 			if (last_ins && last_ins->opcode == OP_MOVE &&
 			    ins->sreg1 == last_ins->dreg &&
 			    ins->dreg == last_ins->sreg1) {
-				last_ins->next = ins->next;				
-				ins = ins->next;				
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 }
 
 static void
 peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *last_ins = NULL;
-	ins = bb->code;
+	MonoInst *ins, *n, *ins2;
 
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
+		MonoInst *last_ins = mono_inst_list_prev(&ins->node,
+							 &bb->ins_list);
 
 		switch (ins->opcode) {
 		case OP_ICONST:
-		case OP_I8CONST:
+		case OP_I8CONST: {
+			MonoInst *next;
+
 			/* reg = 0 -> XOR (reg, reg) */
 			/* XOR sets cflags on x86, so we cant do it always */
-			if (ins->inst_c0 == 0 && (!ins->next || (ins->next && INST_IGNORES_CFLAGS (ins->next->opcode)))) {
+			next = mono_inst_list_next(&ins->node,
+						   &bb->ins_list);
+			if (ins->inst_c0 == 0 &&
+			    (!next ||
+			     (next && INST_IGNORES_CFLAGS (next->opcode)))) {
 				ins->opcode = OP_LXOR;
 				ins->sreg1 = ins->dreg;
 				ins->sreg2 = ins->dreg;
@@ -1871,6 +1861,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			}
 			else
 				break;
+		}
 		case CEE_XOR:
 		case OP_LXOR:
 			if ((ins->sreg1 == ins->sreg2) && (ins->sreg1 == ins->dreg)) {
@@ -1882,7 +1873,12 @@ peephole_pass (MonoCompile *cfg, MonoBas
 				 * propagation). These instruction sequences are very common
 				 * in the initlocals bblock.
 				 */
-				for (ins2 = ins->next; ins2; ins2 = ins2->next) {
+				for (ins2 = mono_inst_list_next(&ins->node,
+								&bb->ins_list);
+				     ins2;
+				     ins2 = mono_inst_list_next(&ins2->node,
+								&bb->ins_list))
+				{
 					if (((ins2->opcode == OP_STORE_MEMBASE_IMM) || (ins2->opcode == OP_STOREI4_MEMBASE_IMM) || (ins2->opcode == OP_STOREI8_MEMBASE_IMM) || (ins2->opcode == OP_STORE_MEMBASE_IMM)) && (ins2->inst_imm == 0)) {
 						ins2->opcode = store_membase_imm_to_store_membase_reg (ins2->opcode);
 						ins2->sreg1 = ins->dreg;
@@ -1911,8 +1907,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 				if (ins->dreg != ins->sreg1) {
 					ins->opcode = OP_MOVE;
 				} else {
-					last_ins->next = ins->next;
-					ins = ins->next;
+					MONO_DEL_INS(ins);
 					continue;
 				}
 			}
@@ -1967,8 +1962,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			    ins->inst_basereg == last_ins->inst_destbasereg &&
 			    ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -1993,8 +1987,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			      ins->inst_offset == last_ins->inst_offset) {
 
 				if (ins->dreg == last_ins->dreg) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					ins->opcode = OP_MOVE;
@@ -2036,8 +2029,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 					ins->inst_basereg == last_ins->inst_destbasereg &&
 					ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -2060,8 +2052,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 					ins->inst_basereg == last_ins->inst_destbasereg &&
 					ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -2080,11 +2071,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			 * OP_MOVE reg, reg 
 			 */
 			if (ins->dreg == ins->sreg1) {
-				if (last_ins)
-					last_ins->next = ins->next;
-				else
-					bb->code = ins->next;
-				ins = ins->next;
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			/* 
@@ -2096,36 +2083,18 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			if (last_ins && last_ins->opcode == OP_MOVE &&
 			    ins->sreg1 == last_ins->dreg &&
 			    ins->dreg == last_ins->sreg1) {
-				last_ins->next = ins->next;				
-				ins = ins->next;				
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
-	}
-	bb->last_ins = last_ins;
-}
-
-static void
-insert_after_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *to_insert)
-{
-	if (ins == NULL) {
-		ins = bb->code;
-		bb->code = to_insert;
-		to_insert->next = ins;
-	}
-	else {
-		to_insert->next = ins->next;
-		ins->next = to_insert;
 	}
 }
 
-#define NEW_INS(cfg,dest,op) do {	\
+#define NEW_INS(cfg,ins,dest,op) do {					\
 		(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));	\
 		(dest)->opcode = (op);	\
-        insert_after_ins (bb, last_ins, (dest)); \
+	MONO_INST_LIST_ADD_TAIL(&(dest)->node, &(ins)->node); \
 	} while (0)
 
 /*
@@ -2137,8 +2106,7 @@ insert_after_ins (MonoBasicBlock *bb, Mo
 static void
 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *temp, *last_ins = NULL;
-	ins = bb->code;
+	MonoInst *ins, *n, *temp;
 
 	if (bb->max_vreg > cfg->rs->next_vreg)
 		cfg->rs->next_vreg = bb->max_vreg;
@@ -2148,13 +2116,13 @@ mono_arch_lowering_pass (MonoCompile *cf
 	 * description can't model some parts of the composite instructions like
 	 * cdq.
 	 */
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
 		switch (ins->opcode) {
 		case OP_DIV_IMM:
 		case OP_REM_IMM:
 		case OP_IDIV_IMM:
 		case OP_IREM_IMM:
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_imm;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			switch (ins->opcode) {
@@ -2175,7 +2143,7 @@ mono_arch_lowering_pass (MonoCompile *cf
 			break;
 		case OP_COMPARE_IMM:
 			if (!amd64_is_imm32 (ins->inst_imm)) {
-				NEW_INS (cfg, temp, OP_I8CONST);
+				NEW_INS (cfg, ins, temp, OP_I8CONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->opcode = OP_COMPARE;
@@ -2185,7 +2153,7 @@ mono_arch_lowering_pass (MonoCompile *cf
 		case OP_LOAD_MEMBASE:
 		case OP_LOADI8_MEMBASE:
 			if (!amd64_is_imm32 (ins->inst_offset)) {
-				NEW_INS (cfg, temp, OP_I8CONST);
+				NEW_INS (cfg, ins, temp, OP_I8CONST);
 				temp->inst_c0 = ins->inst_offset;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->opcode = OP_AMD64_LOADI8_MEMINDEX;
@@ -2195,7 +2163,7 @@ mono_arch_lowering_pass (MonoCompile *cf
 		case OP_STORE_MEMBASE_IMM:
 		case OP_STOREI8_MEMBASE_IMM:
 			if (!amd64_is_imm32 (ins->inst_imm)) {
-				NEW_INS (cfg, temp, OP_I8CONST);
+				NEW_INS (cfg, ins, temp, OP_I8CONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->opcode = OP_STOREI8_MEMBASE_REG;
@@ -2205,10 +2173,7 @@ mono_arch_lowering_pass (MonoCompile *cf
 		default:
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 
 	bb->max_vreg = cfg->rs->next_vreg;
 }
@@ -2245,7 +2210,7 @@ cc_signed_table [] = {
 void
 mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	if (!bb->code)
+	if (MONO_INST_LIST_EMPTY(&bb->ins_list))
 		return;
 
 	mono_arch_lowering_pass (cfg, bb);
@@ -2563,7 +2528,6 @@ mono_arch_output_basic_block (MonoCompil
 	MonoCallInst *call;
 	guint offset;
 	guint8 *code = cfg->native_code + cfg->code_len;
-	MonoInst *last_ins = NULL;
 	guint last_offset = 0;
 	int max_len, cpos;
 
@@ -2602,8 +2566,7 @@ mono_arch_output_basic_block (MonoCompil
 
 	mono_debug_open_block (cfg, bb, offset);
 
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 		offset = code - cfg->native_code;
 
 		max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
@@ -3397,9 +3360,6 @@ mono_arch_output_basic_block (MonoCompil
 		case OP_NOP:
 			break;
 		case OP_BR:
-			//g_print ("target: %p, next: %p, curr: %p, last: %p\n", ins->inst_target_bb, bb->next_bb, ins, bb->last_ins);
-			//if ((ins->inst_target_bb == bb->next_bb) && ins == bb->last_ins)
-			//break;
 			if (ins->flags & MONO_INST_BRLABEL) {
 				if (ins->inst_i0->inst_c0) {
 					amd64_jump_code (code, cfg->native_code + ins->inst_i0->inst_c0);
@@ -4263,10 +4223,7 @@ mono_arch_output_basic_block (MonoCompil
 	       
 		cpos += max_len;
 
-		last_ins = ins;
 		last_offset = offset;
-		
-		ins = ins->next;
 	}
 
 	cfg->code_len = code - cfg->native_code;
@@ -4491,7 +4448,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
 	max_offset = 0;
 	if (cfg->opt & MONO_OPT_BRANCH) {
 		for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-			MonoInst *ins = bb->code;
+			MonoInst *ins;
 			bb->max_offset = max_offset;
 
 			if (cfg->prof_options & MONO_PROFILE_COVERAGE)
@@ -4500,12 +4457,11 @@ mono_arch_emit_prolog (MonoCompile *cfg)
 			if ((cfg->opt & MONO_OPT_LOOP) && bb_is_loop_start (bb))
 				max_offset += LOOP_ALIGNMENT;
 
-			while (ins) {
+			MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 				if (ins->opcode == OP_LABEL)
 					ins->inst_c1 = max_offset;
 				
 				max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
-				ins = ins->next;
 			}
 		}
 	}
Index: mono/mini/mini-mips.c
===================================================================
--- mono/mini/mini-mips.c	(revision 89301)
+++ mono/mini/mini-mips.c	(working copy)
@@ -1188,10 +1188,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			MONO_INST_NEW (cfg, arg, OP_OUTARG);
 			arg->inst_imm = cinfo->sig_cookie.offset;
 			arg->inst_left = sig_arg;
-			
-			/* prepend, so they get reversed */
-			arg->next = call->out_args;
-			call->out_args = arg;
+			MONO_INST_LIST_ADD_TAIL(&arg->node, &call->out_args);
 		}
 		if (is_virtual && i == 0) {
 			/* the argument will be attached to the call instrucion */
@@ -1204,9 +1201,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			arg->inst_left = in;
 			arg->inst_call = call;
 			arg->type = in->type;
-			/* prepend, we'll need to reverse them later */
-			arg->next = call->out_args;
-			call->out_args = arg;
+			MONO_INST_LIST_ADD_TAIL(&arg->node, &call->out_args);
 			if (ainfo->regtype == RegTypeGeneral) {
 				arg->backend.reg3 = ainfo->reg;
 				call->used_iregs |= 1 << ainfo->reg;
@@ -1257,19 +1252,6 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			}
 		}
 	}
-	/*
-	 * Reverse the call->out_args list.
-	 */
-	{
-		MonoInst *prev = NULL, *list = call->out_args, *next;
-		while (list) {
-			next = list->next;
-			list->next = prev;
-			prev = list;
-			list = next;
-		}
-		call->out_args = prev;
-	}
 	call->stack_usage = cinfo->stack_usage;
 	cfg->param_area = MAX (cfg->param_area, cinfo->stack_usage);
 	cfg->param_area = MAX (cfg->param_area, 16); /* a0-a3 always present */
@@ -1287,10 +1269,11 @@ mono_arch_call_opcode (MonoCompile *cfg,
 static void
 peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *last_ins = NULL;
-	ins = bb->code;
+	MonoInst *ins, *n;
 
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
+		MonoInst *last_ins = mono_inst_list_prev(&ins->node,
+							 &bb->ins_list);
 
 		switch (ins->opcode) {
 		case OP_MUL_IMM: 
@@ -1299,8 +1282,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 				if (ins->dreg != ins->sreg1) {
 					ins->opcode = OP_MOVE;
 				} else {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				}
 			} else {
@@ -1322,8 +1304,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			    ins->inst_basereg == last_ins->inst_destbasereg &&
 			    ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -1347,8 +1328,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			      ins->inst_offset == last_ins->inst_offset) {
 
 				if (ins->dreg == last_ins->dreg) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					ins->opcode = OP_MOVE;
@@ -1405,9 +1385,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			 * OP_MOVE reg, reg 
 			 */
 			if (ins->dreg == ins->sreg1) {
-				if (last_ins)
-					last_ins->next = ins->next;				
-				ins = ins->next;
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			/* 
@@ -1417,47 +1395,18 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			if (last_ins && last_ins->opcode == OP_MOVE &&
 			    ins->sreg1 == last_ins->dreg &&
 			    ins->dreg == last_ins->sreg1) {
-				last_ins->next = ins->next;				
-				ins = ins->next;				
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
-	}
-	bb->last_ins = last_ins;
-}
-
-static inline InstList*
-inst_list_prepend (MonoMemPool *pool, InstList *list, MonoInst *data)
-{
-	InstList *item = mono_mempool_alloc (pool, sizeof (InstList));
-	item->data = data;
-	item->prev = NULL;
-	item->next = list;
-	if (list)
-		list->prev = item;
-	return item;
-}
-
-static void
-insert_after_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *to_insert)
-{
-	if (ins == NULL) {
-		ins = bb->code;
-		bb->code = to_insert;
-		to_insert->next = ins;
-	} else {
-		to_insert->next = ins->next;
-		ins->next = to_insert;
 	}
 }
 
-#define NEW_INS(cfg,dest,op) do {       \
+#define NEW_INS(cfg,ins,dest,op) do {					\
 		(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
 		(dest)->opcode = (op);  \
-		insert_after_ins (bb, last_ins, (dest)); \
+		MONO_INST_LIST_ADD_TAIL(&(dest)->node, &(ins)->node); \
 	} while (0)
 
 static int
@@ -1536,21 +1485,20 @@ map_to_reg_reg_op (int op)
 static void
 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *next, *temp, *last_ins = NULL;
+	MonoInst *ins, *next, *temp;
 	int imm;
 
 	/* setup the virtual reg allocator */
 	if (bb->max_vreg > cfg->rs->next_vreg)
 		cfg->rs->next_vreg = bb->max_vreg;
 
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->list, node) {
 loop_start:
 		switch (ins->opcode) {
 		case OP_ADD_IMM:
 		case OP_ADDCC_IMM:
 			if (!mips_is_imm16 (ins->inst_imm)) {
-				NEW_INS (cfg, temp, OP_ICONST);
+				NEW_INS (cfg, ins, temp, OP_ICONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->sreg2 = temp->dreg;
@@ -1560,7 +1508,7 @@ loop_start:
 #if 0
 		case OP_SUB_IMM:
 			if (!mips_is_imm16 (-ins->inst_imm)) {
-				NEW_INS (cfg, temp, OP_ICONST);
+				NEW_INS (cfg, ins, temp, OP_ICONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->sreg2 = temp->dreg;
@@ -1573,7 +1521,7 @@ loop_start:
 		case OP_OR_IMM:
 		case OP_XOR_IMM:
 			if ((ins->inst_imm & 0xffff0000) && (ins->inst_imm & 0xffff)) {
-				NEW_INS (cfg, temp, OP_ICONST);
+				NEW_INS (cfg, ins, temp, OP_ICONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->sreg2 = temp->dreg;
@@ -1585,7 +1533,7 @@ loop_start:
 		case OP_SBB_IMM:
 		case OP_SUBCC_IMM:
 		case OP_ADC_IMM:
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_imm;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			ins->sreg2 = temp->dreg;
@@ -1594,9 +1542,11 @@ loop_start:
 #endif
 #if 0
 		case OP_COMPARE_IMM:
-			if (compare_opcode_is_unsigned (ins->next->opcode)) {
+			next = mono_inst_list_next(&ins->node, &bb->ins_list);
+			g_assert(next);
+			if (compare_opcode_is_unsigned (next->opcode)) {
 				if (!ppc_is_uimm16 (ins->inst_imm)) {
-					NEW_INS (cfg, temp, OP_ICONST);
+					NEW_INS (cfg, ins, temp, OP_ICONST);
 					temp->inst_c0 = ins->inst_imm;
 					temp->dreg = mono_regstate_next_int (cfg->rs);
 					ins->sreg2 = temp->dreg;
@@ -1604,7 +1554,7 @@ loop_start:
 				}
 			} else {
 				if (!ppc_is_imm16 (ins->inst_imm)) {
-					NEW_INS (cfg, temp, OP_ICONST);
+					NEW_INS (cfg, ins, temp, OP_ICONST);
 					temp->inst_c0 = ins->inst_imm;
 					temp->dreg = mono_regstate_next_int (cfg->rs);
 					ins->sreg2 = temp->dreg;
@@ -1631,7 +1581,7 @@ loop_start:
 				break;
 			}
 			if (!ppc_is_imm16 (ins->inst_imm)) {
-				NEW_INS (cfg, temp, OP_ICONST);
+				NEW_INS (cfg, ins, temp, OP_ICONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->sreg2 = temp->dreg;
@@ -1662,7 +1612,7 @@ loop_start:
 			 */
 			if (ppc_is_imm16 (ins->inst_offset))
 				break;
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_offset;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			ins->sreg2 = temp->dreg;
@@ -1678,27 +1628,23 @@ loop_start:
 				ins->opcode = map_to_reg_reg_op (ins->opcode);
 			}
 #if 0
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_imm;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			ins->sreg1 = temp->dreg;
 			ins->opcode = map_to_reg_reg_op (ins->opcode);
-			last_ins = temp;
 			goto loop_start; /* make it handle the possibly big ins->inst_offset */
 #endif
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 	bb->max_vreg = cfg->rs->next_vreg;
 }
 
 void
 mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	if (!bb->code)
+	if (MONO_INST_LIST_EMPTY(&bb->ins_list))
 		return;
 	mono_arch_lowering_pass (cfg, bb);
 	mono_local_regalloc (cfg, bb);
@@ -1741,7 +1687,6 @@ mono_arch_output_basic_block (MonoCompil
 	MonoCallInst *call;
 	guint offset;
 	guint8 *code = cfg->native_code + cfg->code_len;
-	MonoInst *last_ins = NULL;
 	guint last_offset = 0;
 	int max_len, cpos;
 	int ins_cnt = 0;
@@ -1771,8 +1716,7 @@ mono_arch_output_basic_block (MonoCompil
 		mips_sw (code, mips_temp, mips_at, 0);
 	}
 #endif
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 		offset = code - cfg->native_code;
 
 		max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
@@ -2979,10 +2923,7 @@ mono_arch_output_basic_block (MonoCompil
 	       
 		cpos += max_len;
 
-		last_ins = ins;
 		last_offset = offset;
-		
-		ins = ins->next;
 	}
 
 	cfg->code_len = code - cfg->native_code;
Index: mono/mini/mini-mips.h
===================================================================
--- mono/mini/mini-mips.h	(revision 89301)
+++ mono/mini/mini-mips.h	(working copy)
@@ -269,9 +269,9 @@ typedef struct {
         	MonoInst *target_label; \
 		target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));	\
 		target_label->opcode = OP_LABEL;	\
-	        target_label->next = (targetbb)->code; \
+		MONO_INST_LIST_ADD(&target_label->node, \
+				   &(targetbb)->ins_list); \
 		target_label->inst_c0 = (targetbb)->native_offset; \
-	        (targetbb)->code = target_label; \
 		inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));	\
 		inst->opcode = op;	\
                 (inst)->sreg1 = sr1; \
@@ -286,9 +286,9 @@ typedef struct {
         	MonoInst *target_label; \
 		target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));	\
 		target_label->opcode = OP_LABEL;	\
-	        target_label->next = (targetbb)->code; \
+		MONO_INST_LIST_ADD(&target_label->node, \
+				   &(targetbb)->ins_list); \
 		target_label->inst_c0 = (targetbb)->native_offset; \
-	        (targetbb)->code = target_label; \
 		inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));	\
 		inst->opcode = op;	\
                 (inst)->sreg1 = sr1; \
Index: mono/mini/mini-x86.c
===================================================================
--- mono/mini/mini-x86.c	(revision 89301)
+++ mono/mini/mini-x86.c	(working copy)
@@ -926,9 +926,7 @@ emit_sig_cookie (MonoCompile *cfg, MonoC
 
 	arg->inst_left = sig_arg;
 	arg->type = STACK_PTR;
-	/* prepend, so they get reversed */
-	arg->next = call->out_args;
-	call->out_args = arg;
+	MONO_INST_LIST_ADD(&arg->node, &call->out_args);
 }
 
 /*
@@ -1006,9 +1004,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			arg->cil_code = in->cil_code;
 			arg->inst_left = in;
 			arg->type = in->type;
-			/* prepend, so they get reversed */
-			arg->next = call->out_args;
-			call->out_args = arg;
+			MONO_INST_LIST_ADD(&arg->node, &call->out_args);
 
 			if ((i >= sig->hasthis) && (MONO_TYPE_ISSTRUCT(t))) {
 				guint32 size, align;
@@ -1088,9 +1084,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			zero_inst->inst_p0 = 0;
 			arg->inst_left = zero_inst;
 			arg->type = STACK_PTR;
-			/* prepend, so they get reversed */
-			arg->next = call->out_args;
-			call->out_args = arg;
+			MONO_INST_LIST_ADD(&arg->node, &call->out_args);
 		}
 		else
 			/* if the function returns a struct, the called method already does a ret $0x4 */
@@ -1104,8 +1098,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 	if (cinfo->need_stack_align) {
 		MONO_INST_NEW (cfg, arg, OP_X86_OUTARG_ALIGN_STACK);
 		arg->inst_c0 = cinfo->stack_align_amount;
-		arg->next = call->out_args;
-		call->out_args = arg;
+		MONO_INST_LIST_ADD(&arg->node, &call->out_args);
         }
 #endif 
 
@@ -1326,10 +1319,11 @@ emit_call (MonoCompile *cfg, guint8 *cod
 static void
 peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *last_ins = NULL;
-	ins = bb->code;
+	MonoInst *ins, *n;
 
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
+		MonoInst *last_ins = mono_inst_list_prev(&ins->node,
+							 &bb->ins_list);
 		switch (ins->opcode) {
 		case OP_IADD_IMM:
 		case OP_ADD_IMM:
@@ -1399,8 +1393,7 @@ peephole_pass_1 (MonoCompile *cfg, MonoB
 			    ins->inst_basereg == last_ins->inst_destbasereg &&
 			    ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -1425,8 +1418,7 @@ peephole_pass_1 (MonoCompile *cfg, MonoB
 			      ins->inst_offset == last_ins->inst_offset) {
 
 				if (ins->dreg == last_ins->dreg) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					ins->opcode = OP_MOVE;
@@ -1497,9 +1489,7 @@ peephole_pass_1 (MonoCompile *cfg, MonoB
 			 * OP_MOVE reg, reg 
 			 */
 			if (ins->dreg == ins->sreg1) {
-				if (last_ins)
-					last_ins->next = ins->next;				
-				ins = ins->next;
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			/* 
@@ -1511,8 +1501,7 @@ peephole_pass_1 (MonoCompile *cfg, MonoB
 			if (last_ins && last_ins->opcode == OP_MOVE &&
 			    ins->sreg1 == last_ins->dreg &&
 			    ins->dreg == last_ins->sreg1) {
-				last_ins->next = ins->next;				
-				ins = ins->next;				
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			break;
@@ -1527,25 +1516,29 @@ peephole_pass_1 (MonoCompile *cfg, MonoB
 			}
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 }
 
 static void
 peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *last_ins = NULL;
-	ins = bb->code;
+	MonoInst *ins, *n;
 
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
+		MonoInst *last_ins = mono_inst_list_prev(&ins->node,
+							 &bb->ins_list);
 
 		switch (ins->opcode) {
-		case OP_ICONST:
+		case OP_ICONST: {
+			MonoInst *next;
+
 			/* reg = 0 -> XOR (reg, reg) */
 			/* XOR sets cflags on x86, so we cant do it always */
-			if (ins->inst_c0 == 0 && (!ins->next || (ins->next && INST_IGNORES_CFLAGS (ins->next->opcode)))) {
+			next = mono_inst_list_next(&ins->node,
+						   &bb->ins_list);
+			if (ins->inst_c0 == 0 &&
+			    (!next ||
+			     (next && INST_IGNORES_CFLAGS (next->opcode)))) {
 				MonoInst *ins2;
 
 				ins->opcode = OP_IXOR;
@@ -1556,7 +1549,12 @@ peephole_pass (MonoCompile *cfg, MonoBas
 				 * Convert succeeding STORE_MEMBASE_IMM 0 ins to STORE_MEMBASE_REG 
 				 * since it takes 3 bytes instead of 7.
 				 */
-				for (ins2 = ins->next; ins2; ins2 = ins2->next) {
+				for (ins2 = mono_inst_list_next(&ins->node,
+								&bb->ins_list);
+				     ins2;
+				     ins2 = mono_inst_list_next(&ins2->node,
+								&bb->ins_list))
+				{
 					if ((ins2->opcode == OP_STORE_MEMBASE_IMM) && (ins2->inst_imm == 0)) {
 						ins2->opcode = OP_STORE_MEMBASE_REG;
 						ins2->sreg1 = ins->dreg;
@@ -1573,6 +1571,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 				}
 			}
 			break;
+		}
 		case OP_IADD_IMM:
 		case OP_ADD_IMM:
 			if ((ins->inst_imm == 1) && (ins->dreg == ins->sreg1))
@@ -1621,8 +1620,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			    ins->inst_basereg == last_ins->inst_destbasereg &&
 			    ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -1647,8 +1645,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			      ins->inst_offset == last_ins->inst_offset) {
 
 				if (ins->dreg == last_ins->dreg) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					ins->opcode = OP_MOVE;
@@ -1719,9 +1716,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			 * OP_MOVE reg, reg 
 			 */
 			if (ins->dreg == ins->sreg1) {
-				if (last_ins)
-					last_ins->next = ins->next;				
-				ins = ins->next;
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			/* 
@@ -1733,8 +1728,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			if (last_ins && last_ins->opcode == OP_MOVE &&
 			    ins->sreg1 == last_ins->dreg &&
 			    ins->dreg == last_ins->sreg1) {
-				last_ins->next = ins->next;				
-				ins = ins->next;				
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			break;
@@ -1748,10 +1742,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			}
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 }
 
 static const int 
@@ -2090,7 +2081,6 @@ mono_arch_output_basic_block (MonoCompil
 	MonoCallInst *call;
 	guint offset;
 	guint8 *code = cfg->native_code + cfg->code_len;
-	MonoInst *last_ins = NULL;
 	guint last_offset = 0;
 	int max_len, cpos;
 
@@ -2128,8 +2118,7 @@ mono_arch_output_basic_block (MonoCompil
 
 	mono_debug_open_block (cfg, bb, offset);
 
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 		offset = code - cfg->native_code;
 
 		max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
@@ -2791,9 +2780,6 @@ mono_arch_output_basic_block (MonoCompil
 			ins->inst_c0 = code - cfg->native_code;
 			break;
 		case OP_BR:
-			//g_print ("target: %p, next: %p, curr: %p, last: %p\n", ins->inst_target_bb, bb->next_bb, ins, bb->last_ins);
-			//if ((ins->inst_target_bb == bb->next_bb) && ins == bb->last_ins)
-			//break;
 			if (ins->flags & MONO_INST_BRLABEL) {
 				if (ins->inst_i0->inst_c0) {
 					x86_jump_code (code, cfg->native_code + ins->inst_i0->inst_c0);
@@ -3533,10 +3519,7 @@ mono_arch_output_basic_block (MonoCompil
 	       
 		cpos += max_len;
 
-		last_ins = ins;
 		last_offset = offset;
-		
-		ins = ins->next;
 	}
 
 	cfg->code_len = code - cfg->native_code;
@@ -3774,7 +3757,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
 	max_offset = 0;
 	if (cfg->opt & MONO_OPT_BRANCH) {
 		for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-			MonoInst *ins = bb->code;
+			MonoInst *ins;
 			bb->max_offset = max_offset;
 
 			if (cfg->prof_options & MONO_PROFILE_COVERAGE)
@@ -3783,12 +3766,11 @@ mono_arch_emit_prolog (MonoCompile *cfg)
 			if ((cfg->opt & MONO_OPT_LOOP) && bb_is_loop_start (bb))
 				max_offset += LOOP_ALIGNMENT;
 
-			while (ins) {
+			MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 				if (ins->opcode == OP_LABEL)
 					ins->inst_c1 = max_offset;
 				
 				max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
-				ins = ins->next;
 			}
 		}
 	}
Index: mono/mini/cfold.c
===================================================================
--- mono/mini/cfold.c	(revision 89301)
+++ mono/mini/cfold.c	(working copy)
@@ -249,7 +249,7 @@ mono_constant_fold (MonoCompile *cfg)
 	
 	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
 		MonoInst *ins;
-		for (ins = bb->code; ins; ins = ins->next)	
+		MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node)
 			mono_inst_foreach (ins, mono_constant_fold_inst, NULL);
 	}
 }
Index: mono/mini/liveness.c
===================================================================
--- mono/mini/liveness.c	(revision 89301)
+++ mono/mini/liveness.c	(working copy)
@@ -197,8 +197,10 @@ visit_bb (MonoCompile *cfg, MonoBasicBlo
 	if (cfg->aliasing_info != NULL)
 		mono_aliasing_initialize_code_traversal (cfg->aliasing_info, bb);
 	
-	for (tree_num = 0, inst = bb->code; inst; inst = inst->next, tree_num++) {
+	tree_num = 0;
+	MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node) {
 		update_volatile (cfg, bb, inst, tree_num);
+		tree_num++;
 	}
 
 	*visited = g_slist_append (*visited, bb);
@@ -291,11 +293,13 @@ mono_analyze_liveness (MonoCompile *cfg)
 		if (cfg->aliasing_info != NULL)
 			mono_aliasing_initialize_code_traversal (cfg->aliasing_info, bb);
 		
-		for (tree_num = 0, inst = bb->code; inst; inst = inst->next, tree_num++) {
+		tree_num = 0;
+		MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node) {
 #ifdef DEBUG_LIVENESS
 			mono_print_tree (inst); printf ("\n");
 #endif
 			update_gen_kill_set (cfg, bb, inst, tree_num);
+			tree_num++;
 		}
 
 #ifdef DEBUG_LIVENESS
@@ -527,11 +531,10 @@ optimize_initlocals (MonoCompile *cfg)
 
 	mono_bitset_clear_all (used);
 	initlocals_bb = cfg->bb_entry->next_bb;
-	for (ins = initlocals_bb->code; ins; ins = ins->next) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &initlocals_bb->ins_list, node)
 		update_used (cfg, ins, used);
-	}
 
-	for (ins = initlocals_bb->code; ins; ins = ins->next) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &initlocals_bb->ins_list, node) {
 		if (ins->ssa_op == MONO_SSA_STORE) {
 			int idx = ins->inst_i0->inst_c0;
 			MonoInst *var = cfg->varinfo [idx];
Index: mono/mini/ssapre.c
===================================================================
--- mono/mini/ssapre.c	(revision 89301)
+++ mono/mini/ssapre.c	(working copy)
@@ -270,9 +270,10 @@ static void dump_code (MonoSsapreWorkAre
 		MonoInst *current_inst;
 		
 		print_bb_info (current_bb, TRUE);
-		for (current_inst = current_bb->bb->code; current_inst != NULL; current_inst = current_inst->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(current_inst,
+					      &current_bb->bb->ins_list,
+					      node)
 			mono_print_tree_nl (current_inst);
-		}
 	}
 }
 
@@ -824,9 +825,8 @@ process_bb (MonoSsapreWorkArea *area, Mo
 	
 	bb_info->phi_insertion_point = NULL;
 	
-	current_inst = bb->code;
 	previous_inst = NULL;
-	while (current_inst != NULL) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(current_inst, &bb->ins_list, node) {
 		/* Ugly hack to fix missing variable definitions */
 		/* (the SSA construction code should have done it already!) */
 		switch (current_inst->opcode) {
@@ -865,7 +865,6 @@ process_bb (MonoSsapreWorkArea *area, Mo
 		}
 		
 		previous_inst = current_inst;
-		current_inst = current_inst->next;
 	}
 	
 	if (current_depth > area->dt_depth) {
@@ -1905,11 +1904,11 @@ static void code_motion (MonoSsapreWorkA
 			}
 			store = mono_compile_create_var_store (area->cfg, current_bb->phi_variable_index, phi);
 			if (current_bb->phi_insertion_point != NULL) {
-				store->next = current_bb->phi_insertion_point->next;
-				current_bb->phi_insertion_point->next = store;
+				MONO_INST_LIST_ADD(&store->node,
+						   &current_bb->phi_insertion_point->node);
 			} else {
-				store->next = current_bb->bb->code;
-				current_bb->bb->code = store;
+				MONO_INST_LIST_ADD(&store->node,
+						   &current_bb->bb->ins_list);
 			}
 			area->cfg->vars [current_bb->phi_variable_index]->def = store;
 			current_bb->phi_insertion_point = store;
@@ -1925,11 +1924,11 @@ static void code_motion (MonoSsapreWorkA
 	 			*moved_expression = *(current_expression->occurrence);
 	 			store = mono_compile_create_var_store (area->cfg, current_expression->variable_index, moved_expression);
 	 			if (current_expression->previous_tree != NULL) {
-		 			store->next = current_expression->previous_tree->next;
-		 			current_expression->previous_tree->next = store;
+		 			MONO_INST_LIST_ADD(&store->node,
+							   &current_expression->previous_tree->node);
 	 			} else {
-		 			store->next = current_bb->bb->code;
-		 			current_bb->bb->code = store;
+					MONO_INST_LIST_ADD(&store->node,
+							   &current_bb->bb->ins_list);
 	 			}
 				area->cfg->vars [current_expression->variable_index]->def = store;
 	 			mono_compile_make_var_load (area->cfg, current_expression->occurrence, current_expression->variable_index);
@@ -1981,7 +1980,7 @@ static void code_motion (MonoSsapreWorkA
 	 		inserted_expression = create_expression (area, &expression_description, &prototype_occurrence);
 	 		store = mono_compile_create_var_store (area->cfg, current_bb->phi_argument_variable_index, inserted_expression);
 			area->cfg->vars [current_bb->phi_argument_variable_index]->def = store;
-	 		store->next = NULL;
+			MONO_INST_LIST_INIT(&store->node);
 	 		mono_add_ins_to_end (current_bb->bb, store);
 	 		
 	 		area->inserted_occurrences ++;
Index: mono/mini/graph.c
===================================================================
--- mono/mini/graph.c	(revision 89301)
+++ mono/mini/graph.c	(working copy)
@@ -289,7 +289,7 @@ mono_draw_code_cfg (MonoCompile *cfg, FI
 
 		fprintf (fp, "BB%d [%sshape=record,labeljust=l,label=\"{BB%d|", bb->block_num, color, bb->block_num);
 			
-		for (inst = bb->code; inst; inst = inst->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node) {
 			mono_print_label (fp, inst);
 			fprintf (fp, "\\n");			
 		}
Index: mono/mini/ssa.c
===================================================================
--- mono/mini/ssa.c	(revision 89301)
+++ mono/mini/ssa.c	(working copy)
@@ -202,7 +202,7 @@ mono_ssa_rename_vars (MonoCompile *cfg, 
 	printf ("RENAME VARS BB%d %s\n", bb->block_num, mono_method_full_name (cfg->method, TRUE));
 #endif
 
-	for (inst = bb->code; inst; inst = inst->next) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node) {
 		if (inst->opcode != OP_PHI)
 			replace_usage (cfg, bb, inst, stack);
 
@@ -237,7 +237,7 @@ mono_ssa_rename_vars (MonoCompile *cfg, 
 			if (n->in_bb [j] == bb)
 				break;
 		
-		for (inst = n->code; inst; inst = inst->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(inst, &n->ins_list, node) {
 			if (inst->ssa_op == MONO_SSA_STORE && inst->inst_i1->opcode == OP_PHI) {
 				idx = inst->inst_i1->inst_c0;
 				if (stack [idx])
@@ -294,7 +294,9 @@ mono_ssa_compute (MonoCompile *cfg)
 		mono_bitset_set (vinfo [i].def_in, 0);
 	}
 	for (i = 0; i < cfg->num_bblocks; ++i) {
-		for (inst = cfg->bblocks [i]->code; inst; inst = inst->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(inst,
+					      &cfg->bblocks[i]->ins_list,
+					      node) {
 			if (inst->ssa_op == MONO_SSA_STORE) {
 				idx = inst->inst_i0->inst_c0;
 				g_assert (idx < cfg->num_varinfo);
@@ -334,10 +336,7 @@ mono_ssa_compute (MonoCompile *cfg)
 			store->inst_i1 = inst;
 			store->klass = store->inst_i0->klass;
 	     
-			store->next = bb->code;
-			bb->code = store;
-			if (!bb->last_ins)
-				bb->last_ins = bb->code;
+			MONO_INST_LIST_ADD(&store->node, &bb->ins_list);
 
 #ifdef DEBUG_SSA
 			printf ("ADD PHI BB%d %s\n", cfg->bblocks [idx]->block_num, mono_method_full_name (cfg->method, TRUE));
@@ -467,7 +466,7 @@ mono_ssa_remove (MonoCompile *cfg)
 
 	for (i = 0; i < cfg->num_bblocks; ++i) {
 		MonoBasicBlock *bb = cfg->bblocks [i];
-		for (inst = bb->code; inst; inst = inst->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node) {
 			if (inst->ssa_op == MONO_SSA_STORE && inst->inst_i1->opcode == OP_PHI) {
 				
 				phi = inst->inst_i1;
@@ -554,7 +553,7 @@ mono_ssa_remove (MonoCompile *cfg)
 	for (i = 0; i < cfg->num_bblocks; ++i) {
 		MonoBasicBlock *bb = cfg->bblocks [i];
 
-		for (inst = bb->code; inst; inst = inst->next)
+		MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node)
 			mono_ssa_replace_copies (cfg, bb, inst, is_live);
 	}
 
@@ -677,7 +676,7 @@ mono_ssa_avoid_copies (MonoCompile *cfg)
 	g_assert ((cfg->comp_done & MONO_COMP_SSA_DEF_USE));
 
 	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-		for (inst = bb->code; inst; inst = inst->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node) {
 			if (inst->ssa_op == MONO_SSA_STORE && inst->inst_i0->opcode == OP_LOCAL &&
 			    !IS_CALL (inst->inst_i1->opcode) && inst->inst_i1->opcode != OP_PHI && !inst->flags) {
 				i1 = cfg->vars [inst->inst_i0->inst_c0];
@@ -701,10 +700,17 @@ mono_ssa_avoid_copies (MonoCompile *cfg)
 					}
 				}
 #endif			
-				if ((next = inst->next) && next->ssa_op == MONO_SSA_STORE && next->inst_i0->opcode == OP_LOCAL &&
-				    next->inst_i1->ssa_op == MONO_SSA_LOAD &&  next->inst_i1->inst_i0->opcode == OP_LOCAL &&
-				    next->inst_i1->inst_i0->inst_c0 == inst->inst_i0->inst_c0 && g_list_length (i1->uses) == 1 &&
-				    inst->opcode == next->opcode && inst->inst_i0->type == next->inst_i0->type) {
+				next = mono_inst_list_next(&inst->node,
+							   &bb->ins_list);
+				if (next &&
+				    next->ssa_op == MONO_SSA_STORE &&
+				    next->inst_i0->opcode == OP_LOCAL &&
+				    next->inst_i1->ssa_op == MONO_SSA_LOAD &&
+				    next->inst_i1->inst_i0->opcode == OP_LOCAL &&
+				    next->inst_i1->inst_i0->inst_c0 == inst->inst_i0->inst_c0 &&
+				    g_list_length (i1->uses) == 1 &&
+				    inst->opcode == next->opcode &&
+				    inst->inst_i0->type == next->inst_i0->type) {
 					i2 = cfg->vars [next->inst_i0->inst_c0];
 					//printf ("ELIM. COPY in BB%d %s\n", bb->block_num, mono_method_full_name (cfg->method, TRUE));
 					inst->inst_i0 = next->inst_i0;
@@ -728,7 +734,7 @@ mono_ssa_create_def_use (MonoCompile *cf
 
 	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
 		MonoInst *inst;
-		for (inst = bb->code; inst; inst = inst->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node) {
 			gboolean has_side_effects = analyze_dev_use (cfg, bb, inst, inst);
 			if (has_side_effects && (inst->ssa_op == MONO_SSA_STORE) && 
 					(inst->inst_i0->opcode == OP_LOCAL || inst->inst_i0->opcode == OP_ARG)) {
@@ -1134,9 +1140,8 @@ mono_ssa_cprop (MonoCompile *cfg) 
 			}
 		}
 
-		for (inst = bb->code; inst; inst = inst->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node)
 			visit_inst (cfg, bb, inst, &cvars, &bblock_list, carray);
-		}
 
 		while (cvars) {
 			MonoMethodVar *info = (MonoMethodVar *)cvars->data;			
@@ -1153,9 +1158,8 @@ mono_ssa_cprop (MonoCompile *cfg) 
 
 	for (bb = cfg->bb_entry->next_bb; bb; bb = bb->next_bb) {
 		MonoInst *inst;
-		for (inst = bb->code; inst; inst = inst->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node)
 			fold_tree (cfg, bb, inst, carray);
-		}
 	}
 
 	g_free (carray);
Index: mono/mini/abcremoval.c
===================================================================
--- mono/mini/abcremoval.c	(revision 89301)
+++ mono/mini/abcremoval.c	(working copy)
@@ -564,8 +564,9 @@ get_relations_from_previous_bb (MonoVari
 	
 	if (bb->in_count == 1) { /* Should write the code to "sum" conditions... */
 		in_bb = bb->in_bb [0];
-		branch = in_bb->last_ins;
-		if (branch == NULL) return;
+		branch = mono_inst_list_last(&in_bb->ins_list);
+		if (branch == NULL)
+			return;
 		branch_relation = get_relation_from_branch_instruction (branch->opcode);
 		if ((branch_relation != MONO_ANY_RELATION) && (branch->inst_left->opcode == OP_COMPARE)) {
 			MonoSummarizedValue left_value;
@@ -1263,19 +1264,15 @@ process_block (MonoBasicBlock *bb, MonoV
 	apply_change_to_evaluation_area (area, &(additional_relations.relation2));
 	
 	inst_index = 0;
-	current_inst = bb->code;
-	while (current_inst != NULL) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(current_inst, &bb->ins_list, node) {
 		if (TRACE_ABC_REMOVAL) {
 			printf ("Processing instruction %d\n", inst_index);
 			inst_index++;
 		}
 		
 		process_inst (current_inst, area);
-		
-		current_inst = current_inst->next;
 	}
 	
-	
 	if (TRACE_ABC_REMOVAL) {
 		printf ("Processing block %d [dfn %d] done.\n", bb->block_num, bb->dfn);
 	}
Index: mono/mini/local-propagation.c
===================================================================
--- mono/mini/local-propagation.c	(revision 89301)
+++ mono/mini/local-propagation.c	(working copy)
@@ -801,10 +801,10 @@ mono_cprop_invalidate_values (MonoInst *
 static void
 mono_local_cprop_bb (MonoCompile *cfg, TreeMover *tree_mover, MonoBasicBlock *bb, MonoInst **acp, int acp_size)
 {
-	MonoInst *tree = bb->code;
+	MonoInst *tree;
 	int i;
 
-	if (!tree)
+	if (MONO_INST_LIST_EMPTY(&bb->ins_list))
 		return;
 
 	if (tree_mover != NULL) {
@@ -813,7 +813,7 @@ mono_local_cprop_bb (MonoCompile *cfg, T
 			printf ("Running tree mover on BB%d\n", bb->block_num);
 		}
 	}
-	for (; tree; tree = tree->next) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(tree, &bb->ins_list, node) {
 		if (tree_mover != NULL) {
 			if (MONO_DEBUG_TREE_MOVER) {
 				printf ("Running tree mover on tree ");
Index: mono/mini/mini-s390x.c
===================================================================
--- mono/mini/mini-s390x.c	(revision 89301)
+++ mono/mini/mini-s390x.c	(working copy)
@@ -1902,10 +1902,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			arg->ins.cil_code   = in->cil_code;
 			arg->ins.inst_left  = in;
 			arg->ins.type       = in->type;
-
-			/* prepend, we'll need to reverse them later */
-			arg->ins.next       = call->out_args;
-			call->out_args      = (MonoInst *) arg;
+			MONO_INST_LIST_ADD_TAIL(&arg->ins.node, &call->out_args);
 			arg->ins.inst_right = (MonoInst *) call;
 			if (ainfo->regtype == RegTypeGeneral) {
 				arg->ins.backend.reg3 = ainfo->reg;
@@ -1953,20 +1950,6 @@ mono_arch_call_opcode (MonoCompile *cfg,
 		emit_sig_cookie (cfg, call, cinfo, sizeof(MonoType *));
 	}
 
-	/*
-	 * Reverse the call->out_args list.
-	 */
-	{
-		MonoInst *prev = NULL, *list = call->out_args, *next;
-		while (list) {
-			next = list->next;
-			list->next = prev;
-			prev = list;
-			list = next;
-		}
-		call->out_args = prev;
-	}
-
 	g_free (cinfo);
 	return call;
 }
@@ -2014,10 +1997,7 @@ emit_sig_cookie (MonoCompile *cfg, MonoC
 	arg->ins.inst_right  = (MonoInst *) call;
 	arg->size            = argSize;
 	arg->offset          = cinfo->sigCookie.offset;
-
-	/* prepend, we'll need to reverse them later */
-	arg->ins.next       = call->out_args;
-	call->out_args      = (MonoInst *) arg;
+	MONO_INST_LIST_ADD_TAIL(&arg->ins.node, &call->out_args);
 }
 
 /*========================= End of Function ========================*/
@@ -2240,10 +2220,11 @@ handle_enum:
 static void
 peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *last_ins = NULL;
-	ins = bb->code;
+	MonoInst *ins, *n;
 
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
+		MonoInst *last_ins = mono_inst_list_prev(&ins->node,
+							 &bb->ins_list);
 
 		switch (ins->opcode) {
 		case OP_MUL_IMM: 
@@ -2252,8 +2233,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 				if (ins->dreg != ins->sreg1) {
 					ins->opcode = OP_MOVE;
 				} else {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				}
 			}
@@ -2269,8 +2249,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			    ins->inst_basereg == last_ins->inst_destbasereg &&
 			    ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					ins->opcode = OP_MOVE;
@@ -2292,8 +2271,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			      ins->inst_offset == last_ins->inst_offset) {
 
 				if (ins->dreg == last_ins->dreg) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					ins->opcode = OP_MOVE;
@@ -2327,9 +2305,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			 * OP_MOVE reg, reg 
 			 */
 			if (ins->dreg == ins->sreg1) {
-				if (last_ins)
-					last_ins->next = ins->next;				
-				ins = ins->next;
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			/* 
@@ -2339,16 +2315,12 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			if (last_ins && last_ins->opcode == OP_MOVE &&
 			    ins->sreg1 == last_ins->dreg &&
 			    ins->dreg == last_ins->sreg1) {
-				last_ins->next = ins->next;				
-				ins = ins->next;				
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 }
 
 /*========================= End of Function ========================*/
@@ -2444,11 +2416,10 @@ emit_float_to_int (MonoCompile *cfg, guc
 void
 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins;
+	MonoInst *ins, *next;
 	MonoCallInst *call;
 	guint offset;
 	guint8 *code = cfg->native_code + cfg->code_len;
-	MonoInst *last_ins = NULL;
 	guint last_offset = 0;
 	int max_len, cpos, src2;
 
@@ -2473,8 +2444,7 @@ mono_arch_output_basic_block (MonoCompil
 		//x86_inc_mem (code, &cov->data [bb->dfn].count); 
 	}
 
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 		offset = code - cfg->native_code;
 
 		max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
@@ -2649,18 +2619,22 @@ mono_arch_output_basic_block (MonoCompil
 			break;
 		case OP_COMPARE: 
 		case OP_LCOMPARE: {
-			if ((ins->next) && 
-			    (opcode_to_cond(ins->next->opcode) >= CMP_LE_UN))
+			next = mono_inst_list_next(&ins->node,
+						   &bb->inst_list);
+			if ((next) && 
+			    (opcode_to_cond(next->opcode) >= CMP_LE_UN))
 				s390_clgr (code, ins->sreg1, ins->sreg2);
 			else
 				s390_cgr  (code, ins->sreg1, ins->sreg2);
 		}
 			break;
 		case OP_COMPARE_IMM: {
+			next = mono_inst_list_next(&ins->node,
+						   &bb->inst_list);
 			if (s390_is_imm16 (ins->inst_imm)) {
 				s390_lghi (code, s390_r0, ins->inst_imm);
-				if ((ins->next) && 
-				    (opcode_to_cond(ins->next->opcode) >= CMP_LE_UN))
+				if ((next) && 
+				    (opcode_to_cond(next->opcode) >= CMP_LE_UN))
 					s390_clgr (code, ins->sreg1, s390_r0);
 				else
 					s390_cgr  (code, ins->sreg1, s390_r0);
@@ -2669,8 +2643,8 @@ mono_arch_output_basic_block (MonoCompil
 				s390_basr (code, s390_r13, 0);
 				s390_j    (code, 6);
 				s390_llong(code, ins->inst_imm);
-				if ((ins->next) && 
-				    (opcode_to_cond(ins->next->opcode) >= CMP_LE_UN))
+				if ((next) && 
+				    (opcode_to_cond(next->opcode) >= CMP_LE_UN))
 					s390_clg  (code, ins->sreg1, 0, s390_r13, 4);
 				else
 					s390_cg	  (code, ins->sreg1, 0, s390_r13, 4);
@@ -2678,18 +2652,22 @@ mono_arch_output_basic_block (MonoCompil
 		}
 			break;
 		case OP_ICOMPARE: {
-			if ((ins->next) && 
-			    (opcode_to_cond(ins->next->opcode) >= CMP_LE_UN))
+			next = mono_inst_list_next(&ins->node,
+						   &bb->inst_list);
+			if ((next) && 
+			    (opcode_to_cond(next->opcode) >= CMP_LE_UN))
 				s390_clr  (code, ins->sreg1, ins->sreg2);
 			else
 				s390_cr   (code, ins->sreg1, ins->sreg2);
 		}
 			break;
 		case OP_ICOMPARE_IMM: {
+			next = mono_inst_list_next(&ins->node,
+						   &bb->inst_list);
 			if (s390_is_imm16 (ins->inst_imm)) {
 				s390_lghi (code, s390_r0, ins->inst_imm);
-				if ((ins->next) && 
-				    (opcode_to_cond(ins->next->opcode) >= CMP_LE_UN))
+				if ((next) && 
+				    (opcode_to_cond(next->opcode) >= CMP_LE_UN))
 					s390_clr  (code, ins->sreg1, s390_r0);
 				else
 					s390_cr   (code, ins->sreg1, s390_r0);
@@ -2698,8 +2676,8 @@ mono_arch_output_basic_block (MonoCompil
 				s390_basr (code, s390_r13, 0);
 				s390_j    (code, 4);
 				s390_word (code, ins->inst_imm);
-				if ((ins->next) && 
-				    (opcode_to_cond(ins->next->opcode) >= CMP_LE_UN))
+				if ((next) && 
+				    (opcode_to_cond(next->opcode) >= CMP_LE_UN))
 					s390_cl  (code, ins->sreg1, 0, s390_r13, 4);
 				else
 					s390_c   (code, ins->sreg1, 0, s390_r13, 4);
@@ -3520,9 +3498,11 @@ mono_arch_output_basic_block (MonoCompil
 			break;
 		case OP_FCONV_TO_R4: {
 			g_error ("Shouldn't be reached");
-			if ((ins->next) &&
-			    (ins->next->opcode != OP_FMOVE) &&
-			    (ins->next->opcode != OP_STORER4_MEMBASE_REG))
+			next = mono_inst_list_next(&ins->node,
+						   &bb->inst_list);
+			if ((next) &&
+			    (next->opcode != OP_FMOVE) &&
+			    (next->opcode != OP_STORER4_MEMBASE_REG))
 				s390_ledbr (code, ins->dreg, ins->sreg1);
 		}
 			break;
@@ -4220,10 +4200,7 @@ mono_arch_output_basic_block (MonoCompil
 	       
 		cpos += max_len;
 
-		last_ins = ins;
 		last_offset = offset;
-		
-		ins = ins->next;
 	}
 
 	cfg->code_len = code - cfg->native_code;
@@ -4506,16 +4483,14 @@ mono_arch_emit_prolog (MonoCompile *cfg)
 	 */
 	max_offset = 0;
 	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-		MonoInst *ins = bb->code;
+		MonoInst *ins;
 		bb->max_offset = max_offset;
 
 		if (cfg->prof_options & MONO_PROFILE_COVERAGE)
 			max_offset += 6; 
 
-		while (ins) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node)
 			max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
-			ins = ins->next;
-		}
 	}
 
 	/* load arguments allocated to register from the stack */
Index: mono/mini/mini-arm.c
===================================================================
--- mono/mini/mini-arm.c	(revision 89301)
+++ mono/mini/mini-arm.c	(working copy)
@@ -1029,10 +1029,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			MONO_INST_NEW (cfg, arg, OP_OUTARG);
 			arg->inst_imm = cinfo->sig_cookie.offset;
 			arg->inst_left = sig_arg;
-			
-			/* prepend, so they get reversed */
-			arg->next = call->out_args;
-			call->out_args = arg;
+			MONO_INST_LIST_ADD_TAIL(&arg->node, &call->out_args);
 		}
 		if (is_virtual && i == 0) {
 			/* the argument will be attached to the call instrucion */
@@ -1045,9 +1042,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			arg->inst_left = in;
 			arg->inst_right = (MonoInst*)call;
 			arg->type = in->type;
-			/* prepend, we'll need to reverse them later */
-			arg->next = call->out_args;
-			call->out_args = arg;
+			MONO_INST_LIST_ADD_TAIL(&arg->node, &call->out_args);
 			if (ainfo->regtype == RegTypeGeneral) {
 				arg->backend.reg3 = ainfo->reg;
 				call->used_iregs |= 1 << ainfo->reg;
@@ -1103,19 +1098,6 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			}
 		}
 	}
-	/*
-	 * Reverse the call->out_args list.
-	 */
-	{
-		MonoInst *prev = NULL, *list = call->out_args, *next;
-		while (list) {
-			next = list->next;
-			list->next = prev;
-			prev = list;
-			list = next;
-		}
-		call->out_args = prev;
-	}
 	call->stack_usage = cinfo->stack_usage;
 	cfg->param_area = MAX (cfg->param_area, cinfo->stack_usage);
 	cfg->flags |= MONO_CFG_HAS_CALLS;
@@ -1289,10 +1271,11 @@ if (ins->flags & MONO_INST_BRLABEL) { \
 static void
 peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *last_ins = NULL;
-	ins = bb->code;
+	MonoInst *ins, *n;
 
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
+		MonoInst *last_ins = mono_inst_list_prev(&ins->node,
+							 &bb->ins_list);
 
 		switch (ins->opcode) {
 		case OP_MUL_IMM: 
@@ -1301,8 +1284,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 				if (ins->dreg != ins->sreg1) {
 					ins->opcode = OP_MOVE;
 				} else {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				}
 			} else {
@@ -1324,8 +1306,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			    ins->inst_basereg == last_ins->inst_destbasereg &&
 			    ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -1348,8 +1329,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			      ins->inst_offset == last_ins->inst_offset) {
 
 				if (ins->dreg == last_ins->dreg) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					ins->opcode = OP_MOVE;
@@ -1404,9 +1384,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			 * OP_MOVE reg, reg 
 			 */
 			if (ins->dreg == ins->sreg1) {
-				if (last_ins)
-					last_ins->next = ins->next;				
-				ins = ins->next;
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			/* 
@@ -1416,16 +1394,12 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			if (last_ins && last_ins->opcode == OP_MOVE &&
 			    ins->sreg1 == last_ins->dreg &&
 			    ins->dreg == last_ins->sreg1) {
-				last_ins->next = ins->next;				
-				ins = ins->next;				
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 }
 
 /* 
@@ -1458,23 +1432,10 @@ branch_cc_table [] = {
 };
 
 
-static void
-insert_after_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *to_insert)
-{
-	if (ins == NULL) {
-		ins = bb->code;
-		bb->code = to_insert;
-		to_insert->next = ins;
-	} else {
-		to_insert->next = ins->next;
-		ins->next = to_insert;
-	}
-}
-
-#define NEW_INS(cfg,dest,op) do {       \
+#define NEW_INS(cfg,ins,dest,op) do {					\
 		(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
 		(dest)->opcode = (op);  \
-		insert_after_ins (bb, last_ins, (dest)); \
+	MONO_INST_LIST_ADD_TAIL(&(dest)->node, &(ins)->node); \
 	} while (0)
 
 static int
@@ -1547,16 +1508,18 @@ map_to_reg_reg_op (int op)
 static void
 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *temp, *last_ins = NULL;
 	int rot_amount, imm8, low_imm;
+	MonoInst *ins, *temp;
 
 	/* setup the virtual reg allocator */
 	if (bb->max_vreg > cfg->rs->next_vreg)
 		cfg->rs->next_vreg = bb->max_vreg;
 
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
+		MonoInst *last_ins;
+
 loop_start:
+		last_ins = mono_inst_list_prev(&ins->node, &bb->ins_list);
 		switch (ins->opcode) {
 		case OP_ADD_IMM:
 		case OP_SUB_IMM:
@@ -1569,7 +1532,7 @@ loop_start:
 		case OP_OR_IMM:
 		case OP_XOR_IMM:
 			if ((imm8 = mono_arm_is_rotated_imm8 (ins->inst_imm, &rot_amount)) < 0) {
-				NEW_INS (cfg, temp, OP_ICONST);
+				NEW_INS (cfg, ins, temp, OP_ICONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->sreg2 = temp->dreg;
@@ -1592,7 +1555,7 @@ loop_start:
 				ins->inst_imm = imm8;
 				break;
 			}
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_imm;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			ins->sreg2 = temp->dreg;
@@ -1609,7 +1572,7 @@ loop_start:
 			 */
 			if (arm_is_imm12 (ins->inst_offset))
 				break;
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_offset;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			ins->sreg2 = temp->dreg;
@@ -1620,7 +1583,7 @@ loop_start:
 		case OP_LOADI1_MEMBASE:
 			if (arm_is_imm8 (ins->inst_offset))
 				break;
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_offset;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			ins->sreg2 = temp->dreg;
@@ -1632,7 +1595,7 @@ loop_start:
 				break;
 			low_imm = ins->inst_offset & 0x1ff;
 			if ((imm8 = mono_arm_is_rotated_imm8 (ins->inst_offset & ~0x1ff, &rot_amount)) >= 0) {
-				NEW_INS (cfg, temp, OP_ADD_IMM);
+				NEW_INS (cfg, ins, temp, OP_ADD_IMM);
 				temp->inst_imm = ins->inst_offset & ~0x1ff;
 				temp->sreg1 = ins->inst_basereg;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
@@ -1648,7 +1611,7 @@ loop_start:
 		case OP_STOREI1_MEMBASE_REG:
 			if (arm_is_imm12 (ins->inst_offset))
 				break;
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_offset;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			ins->sreg2 = temp->dreg;
@@ -1657,7 +1620,7 @@ loop_start:
 		case OP_STOREI2_MEMBASE_REG:
 			if (arm_is_imm8 (ins->inst_offset))
 				break;
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_offset;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			ins->sreg2 = temp->dreg;
@@ -1669,7 +1632,7 @@ loop_start:
 				break;
 			low_imm = ins->inst_offset & 0x1ff;
 			if ((imm8 = mono_arm_is_rotated_imm8 (ins->inst_offset & ~ 0x1ff, &rot_amount)) >= 0 && arm_is_fpimm8 (low_imm)) {
-				NEW_INS (cfg, temp, OP_ADD_IMM);
+				NEW_INS (cfg, ins, temp, OP_ADD_IMM);
 				temp->inst_imm = ins->inst_offset & ~0x1ff;
 				temp->sreg1 = ins->inst_destbasereg;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
@@ -1685,26 +1648,21 @@ loop_start:
 		case OP_STOREI1_MEMBASE_IMM:
 		case OP_STOREI2_MEMBASE_IMM:
 		case OP_STOREI4_MEMBASE_IMM:
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_imm;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			ins->sreg1 = temp->dreg;
 			ins->opcode = map_to_reg_reg_op (ins->opcode);
-			last_ins = temp;
 			goto loop_start; /* make it handle the possibly big ins->inst_offset */
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 	bb->max_vreg = cfg->rs->next_vreg;
-
 }
 
 void
 mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	if (!bb->code)
+	if (MONO_INST_LIST_EMPTY(&bb->ins_list))
 		return;
 	mono_arch_lowering_pass (cfg, bb);
 	mono_local_regalloc (cfg, bb);
@@ -2012,7 +1970,6 @@ mono_arch_output_basic_block (MonoCompil
 	MonoCallInst *call;
 	guint offset;
 	guint8 *code = cfg->native_code + cfg->code_len;
-	MonoInst *last_ins = NULL;
 	guint last_offset = 0;
 	int max_len, cpos;
 	int imm8, rot_amount;
@@ -2038,8 +1995,7 @@ mono_arch_output_basic_block (MonoCompil
 		//x86_inc_mem (code, &cov->data [bb->dfn].count); 
 	}
 
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 		offset = code - cfg->native_code;
 
 		max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
@@ -3015,10 +2971,7 @@ mono_arch_output_basic_block (MonoCompil
 	       
 		cpos += max_len;
 
-		last_ins = ins;
 		last_offset = offset;
-		
-		ins = ins->next;
 	}
 
 	cfg->code_len = code - cfg->native_code;
@@ -3186,16 +3139,14 @@ mono_arch_emit_prolog (MonoCompile *cfg)
 	 */
 	max_offset = 0;
 	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-		MonoInst *ins = bb->code;
+		MonoInst *ins;
 		bb->max_offset = max_offset;
 
 		if (cfg->prof_options & MONO_PROFILE_COVERAGE)
 			max_offset += 6; 
 
-		while (ins) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node)
 			max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
-			ins = ins->next;
-		}
 	}
 
 	/* load arguments allocated to register from the stack */
Index: mono/mini/aliasing.c
===================================================================
--- mono/mini/aliasing.c	(revision 89301)
+++ mono/mini/aliasing.c	(working copy)
@@ -314,7 +314,9 @@ print_code_with_aliasing_information (Mo
 		
 		printf ("CODE FOR BB %d\n", bb_info->bb->block_num);
 		mono_aliasing_initialize_code_traversal (info, bb_info->bb);
-		for (inst = bb_info->bb->code; inst != NULL; inst = inst->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(inst,
+					      &bb_info->bb->ins_list,
+					      node) {
 			print_tree_with_aliasing_information (info, inst);
 			printf ("\n");
 		}
@@ -733,7 +735,7 @@ mono_build_aliasing_information (MonoCom
 		bb_info->potential_alias_uses = NULL;
 		info->next_interesting_inst = NULL;
 		
-		for (inst = bb->code; inst != NULL; inst = inst->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node) {
 			if (FOLLOW_ALIAS_ANALYSIS) {
 				printf ("TRAVERSING INST: ");
 				mono_print_tree_nl (inst);
@@ -1005,7 +1007,7 @@ mono_aliasing_deadce (MonoAliasingInform
 			printf ("Working on BB %d\n", bb->block_num);
 		}
 		
-		for (inst = bb->code; inst != NULL; inst = inst->next) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(inst, &bb->ins_list, node) {
 			mono_aliasing_deadce_on_inst (info, possibly_dead_assignments, inst);
 			if (inst->opcode == OP_JMP) {
 				/* Keep arguments live! */
Index: mono/mini/mini-ia64.c
===================================================================
--- mono/mini/mini-ia64.c	(revision 89301)
+++ mono/mini/mini-ia64.c	(working copy)
@@ -1009,9 +1009,7 @@ emit_sig_cookie (MonoCompile *cfg, MonoC
 	arg->inst_imm = 16 + cinfo->sig_cookie.offset;
 	arg->type = STACK_PTR;
 
-	/* prepend, so they get reversed */
-	arg->next = call->out_args;
-	call->out_args = arg;
+	MONO_INST_LIST_ADD(&arg->node, &call->out_args);
 }
 
 /* 
@@ -1063,9 +1061,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			arg->cil_code = in->cil_code;
 			arg->inst_left = in;
 			arg->type = in->type;
-			/* prepend, so they get reversed */
-			arg->next = call->out_args;
-			call->out_args = arg;
+			MONO_INST_LIST_ADD(&arg->node, &call->out_args);
 
 			if (sig->hasthis && (i == 0))
 				arg_type = &mono_defaults.object_class->byval_arg;
@@ -1142,10 +1138,9 @@ mono_arch_call_opcode (MonoCompile *cfg,
 						else
 							MONO_INST_NEW (cfg, set_reg, OP_OUTARG_REG);
 						add_outarg_reg (cfg, call, set_reg, arg_storage, dest_reg, load);
-						if (set_reg != call->out_args) {
-							set_reg->next = call->out_args;
-							call->out_args = set_reg;
-						}
+						if (&set_reg->node !=
+						    &call->out_args)
+							MONO_INST_LIST_ADD(&set_reg->node, &call->out_args);
 					}
 
 					/* 
@@ -1175,10 +1170,9 @@ mono_arch_call_opcode (MonoCompile *cfg,
 						outarg->inst_left = load;
 						outarg->inst_imm = 16 + ainfo->offset + (slot - 8) * 8;
 
-						if (outarg != call->out_args) {
-							outarg->next = call->out_args;
-							call->out_args = outarg;
-						}
+						if (&outarg->node !=
+						    &call->out_args)
+							MONO_INST_LIST_ADD(&outarg->node, &call->out_args);
 					}
 
 					/* Trees can't be shared so make a copy */
@@ -1188,10 +1182,8 @@ mono_arch_call_opcode (MonoCompile *cfg,
 					arg->inst_left = vtaddr;
 					arg->inst_right = in;
 					arg->type = in->type;
-					
-					/* prepend, so they get reversed */
-					arg->next = call->out_args;
-					call->out_args = arg;
+					MONO_INST_LIST_ADD(&arg->node,
+							   &call->out_args);
 				}
 				else {
 					MONO_INST_NEW (cfg, stack_addr, OP_REGOFFSET);
@@ -1244,10 +1236,12 @@ mono_arch_call_opcode (MonoCompile *cfg,
 static void
 peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *last_ins = NULL;
-	ins = bb->code;
+	MonoInst *ins, *n;
+
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
+		MonoInst *last_ins = mono_inst_list_prev(&ins->node,
+							 &bb->ins_list);
 
-	while (ins) {
 		switch (ins->opcode) {
 		case OP_MOVE:
 		case OP_FMOVE:
@@ -1257,9 +1251,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			 * OP_MOVE reg, reg 
 			 */
 			if (ins->dreg == ins->sreg1) {
-				if (last_ins)
-					last_ins->next = ins->next;				
-				ins = ins->next;
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			/* 
@@ -1271,8 +1263,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			if (last_ins && last_ins->opcode == OP_MOVE &&
 			    ins->sreg1 == last_ins->dreg &&
 			    ins->dreg == last_ins->sreg1) {
-				last_ins->next = ins->next;				
-				ins = ins->next;				
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			break;
@@ -1285,16 +1276,13 @@ peephole_pass (MonoCompile *cfg, MonoBas
 				} else {
 					last_ins->next = ins->next;
 					ins = ins->next;
+					MONO_DEL_INS(ins);
 					continue;
 				}
 			}
 			break;
 		}
-
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 }
 
 int cond_to_ia64_cmp [][3] = {
@@ -1336,25 +1324,10 @@ opcode_to_ia64_cmp_imm (int opcode, int 
 	return cond_to_ia64_cmp_imm [mono_opcode_to_cond (opcode)][mono_opcode_to_type (opcode, cmp_opcode)];
 }
 
-static void
-insert_after_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *to_insert)
-{
-	if (ins == NULL) {
-		ins = bb->code;
-		bb->code = to_insert;
-		to_insert->next = ins;
-	}
-	else {
-		to_insert->next = ins->next;
-		ins->next = to_insert;
-	}
-}
-
-#define NEW_INS(cfg,dest,op) do {	\
+#define NEW_INS(cfg,ins,dest,op) do {					\
 		(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));	\
 		(dest)->opcode = (op);	\
-        insert_after_ins (bb, last_ins, (dest)); \
-        last_ins = (dest); \
+		MONO_INST_LIST_ADD_TAIL(&(dest)->node, &(ins)->node); \
 	} while (0)
 
 /*
@@ -1366,13 +1339,12 @@ insert_after_ins (MonoBasicBlock *bb, Mo
 static void
 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *next, *temp, *temp2, *temp3, *last_ins = NULL;
-	ins = bb->code;
+	MonoInst *ins, *n, *next, *temp, *temp2, *temp3;
 
 	if (bb->max_vreg > cfg->rs->next_vreg)
 		cfg->rs->next_vreg = bb->max_vreg;
 
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
 		switch (ins->opcode) {
 		case OP_STOREI1_MEMBASE_IMM:
 		case OP_STOREI2_MEMBASE_IMM:
@@ -1383,16 +1355,16 @@ mono_arch_lowering_pass (MonoCompile *cf
 			if (ins->inst_offset == 0) {
 				temp2 = NULL;
 			} else if (ia64_is_imm14 (ins->inst_offset)) {
-				NEW_INS (cfg, temp2, OP_ADD_IMM);
+				NEW_INS (cfg, ins, temp2, OP_ADD_IMM);
 				temp2->sreg1 = ins->inst_destbasereg;
 				temp2->inst_imm = ins->inst_offset;
 				temp2->dreg = mono_regstate_next_int (cfg->rs);
 			}
 			else {
-				NEW_INS (cfg, temp, OP_I8CONST);
+				NEW_INS (cfg, ins, temp, OP_I8CONST);
 				temp->inst_c0 = ins->inst_offset;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
-				NEW_INS (cfg, temp2, CEE_ADD);
+				NEW_INS (cfg, ins, temp2, CEE_ADD);
 				temp2->sreg1 = ins->inst_destbasereg;
 				temp2->sreg2 = temp->dreg;
 				temp2->dreg = mono_regstate_next_int (cfg->rs);
@@ -1419,7 +1391,7 @@ mono_arch_lowering_pass (MonoCompile *cf
 			if (ins->inst_imm == 0)
 				ins->sreg1 = IA64_R0;
 			else {
-				NEW_INS (cfg, temp3, OP_I8CONST);
+				NEW_INS (cfg, ins, temp3, OP_I8CONST);
 				temp3->inst_c0 = ins->inst_imm;
 				temp3->dreg = mono_regstate_next_int (cfg->rs);
 				ins->sreg1 = temp3->dreg;
@@ -1441,16 +1413,16 @@ mono_arch_lowering_pass (MonoCompile *cf
 				break;
 			}
 			else if (ia64_is_imm14 (ins->inst_offset)) {
-				NEW_INS (cfg, temp2, OP_ADD_IMM);
+				NEW_INS (cfg, ins, temp2, OP_ADD_IMM);
 				temp2->sreg1 = ins->inst_destbasereg;
 				temp2->inst_imm = ins->inst_offset;
 				temp2->dreg = mono_regstate_next_int (cfg->rs);
 			}
 			else {
-				NEW_INS (cfg, temp, OP_I8CONST);
+				NEW_INS (cfg, ins, temp, OP_I8CONST);
 				temp->inst_c0 = ins->inst_offset;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
-				NEW_INS (cfg, temp2, CEE_ADD);
+				NEW_INS (cfg, ins, temp2, CEE_ADD);
 				temp2->sreg1 = ins->inst_destbasereg;
 				temp2->sreg2 = temp->dreg;
 				temp2->dreg = mono_regstate_next_int (cfg->rs);
@@ -1480,16 +1452,16 @@ mono_arch_lowering_pass (MonoCompile *cf
 				break;
 			}
 			else if (ia64_is_imm14 (ins->inst_offset)) {
-				NEW_INS (cfg, temp2, OP_ADD_IMM);
+				NEW_INS (cfg, ins, temp2, OP_ADD_IMM);
 				temp2->sreg1 = ins->inst_basereg;
 				temp2->inst_imm = ins->inst_offset;
 				temp2->dreg = mono_regstate_next_int (cfg->rs);
 			}
 			else {
-				NEW_INS (cfg, temp, OP_I8CONST);
+				NEW_INS (cfg, ins, temp, OP_I8CONST);
 				temp->inst_c0 = ins->inst_offset;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
-				NEW_INS (cfg, temp2, CEE_ADD);
+				NEW_INS (cfg, ins, temp2, CEE_ADD);
 				temp2->sreg1 = ins->inst_basereg;
 				temp2->sreg2 = temp->dreg;
 				temp2->dreg = mono_regstate_next_int (cfg->rs);
@@ -1616,7 +1588,7 @@ mono_arch_lowering_pass (MonoCompile *cf
 			if (ins->inst_imm == 0)
 				ins->sreg2 = IA64_R0;
 			else {
-				NEW_INS (cfg, temp, OP_I8CONST);
+				NEW_INS (cfg, ins, temp, OP_I8CONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->sreg2 = temp->dreg;
@@ -1633,7 +1605,8 @@ mono_arch_lowering_pass (MonoCompile *cf
 			 * The compare_imm instructions have switched up arguments, and 
 			 * some of them take an imm between -127 and 128.
 			 */
-			next = ins->next;
+			next = mono_inst_list_next(&ins->node, &bb->ins_list);
+			g_assert(next);
 			cond = mono_opcode_to_cond (next->opcode);
 			if ((cond == CMP_LT) || (cond == CMP_GE))
 				imm = ia64_is_imm8 (ins->inst_imm - 1);
@@ -1652,7 +1625,7 @@ mono_arch_lowering_pass (MonoCompile *cf
 				if (ins->inst_imm == 0)
 					ins->sreg2 = IA64_R0;
 				else {
-					NEW_INS (cfg, temp, OP_I8CONST);
+					NEW_INS (cfg, ins, temp, OP_I8CONST);
 					temp->inst_c0 = ins->inst_imm;
 					temp->dreg = mono_regstate_next_int (cfg->rs);
 					ins->sreg2 = temp->dreg;
@@ -1718,7 +1691,8 @@ mono_arch_lowering_pass (MonoCompile *cf
 		case OP_FCOMPARE: {
 			/* Instead of compare+b<cond>, ia64 has compare<cond>+br */
 
-			next = ins->next;
+			next = mono_inst_list_next(&ins->node, &bb->ins_list);
+			g_assert(next);
 
 			ins->opcode = opcode_to_ia64_cmp (next->opcode, ins->opcode);
 			switch (next->opcode) {
@@ -1810,7 +1784,7 @@ mono_arch_lowering_pass (MonoCompile *cf
 				sum_reg = 0;
 				for (i = 0; i < 64; ++i) {
 					if (ins->inst_imm & (((gint64)1) << i)) {
-						NEW_INS (cfg, temp, shl_op);
+						NEW_INS (cfg, ins, temp, shl_op);
 						temp->dreg = mono_regstate_next_int (cfg->rs);
 						temp->sreg1 = ins->sreg1;
 						temp->inst_imm = i;
@@ -1818,7 +1792,7 @@ mono_arch_lowering_pass (MonoCompile *cf
 						if (sum_reg == 0)
 							sum_reg = temp->dreg;
 						else {
-							NEW_INS (cfg, temp2, CEE_ADD);
+							NEW_INS (cfg, ins, temp2, CEE_ADD);
 							temp2->dreg = mono_regstate_next_int (cfg->rs);
 							temp2->sreg1 = sum_reg;
 							temp2->sreg2 = temp->dreg;
@@ -1832,25 +1806,25 @@ mono_arch_lowering_pass (MonoCompile *cf
 			break;
 		}
 		case CEE_CONV_OVF_U4:
-			NEW_INS (cfg, temp, OP_IA64_CMP4_LT);
+			NEW_INS (cfg, ins, temp, OP_IA64_CMP4_LT);
 			temp->sreg1 = ins->sreg1;
 			temp->sreg2 = IA64_R0;
 
-			NEW_INS (cfg, temp, OP_IA64_COND_EXC);
+			NEW_INS (cfg, ins, temp, OP_IA64_COND_EXC);
 			temp->inst_p1 = (char*)"OverflowException";
 
 			ins->opcode = OP_MOVE;
 			break;
 		case CEE_CONV_OVF_I4_UN:
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = 0x7fffffff;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 
-			NEW_INS (cfg, temp2, OP_IA64_CMP4_GT_UN);
+			NEW_INS (cfg, ins, temp2, OP_IA64_CMP4_GT_UN);
 			temp2->sreg1 = ins->sreg1;
 			temp2->sreg2 = temp->dreg;
 
-			NEW_INS (cfg, temp, OP_IA64_COND_EXC);
+			NEW_INS (cfg, ins, temp, OP_IA64_COND_EXC);
 			temp->inst_p1 = (char*)"OverflowException";
 
 			ins->opcode = OP_MOVE;
@@ -1860,7 +1834,7 @@ mono_arch_lowering_pass (MonoCompile *cf
 		case OP_FCONV_TO_U2:
 		case OP_FCONV_TO_I1:
 		case OP_FCONV_TO_U1:
-			NEW_INS (cfg, temp, OP_FCONV_TO_I8);
+			NEW_INS (cfg, ins, temp, OP_FCONV_TO_I8);
 			temp->sreg1 = ins->sreg1;
 			temp->dreg = ins->dreg;
 
@@ -1888,10 +1862,7 @@ mono_arch_lowering_pass (MonoCompile *cf
 		default:
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 
 	bb->max_vreg = cfg->rs->next_vreg;
 }
@@ -1899,7 +1870,7 @@ mono_arch_lowering_pass (MonoCompile *cf
 void
 mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	if (!bb->code)
+	if (MONO_INST_LIST_EMPTY(&bb->ins_list))
 		return;
 
 	mono_arch_lowering_pass (cfg, bb);
@@ -2113,7 +2084,6 @@ mono_arch_output_basic_block (MonoCompil
 	guint offset;
 	Ia64CodegenState code;
 	guint8 *code_start = cfg->native_code + cfg->code_len;
-	MonoInst *last_ins = NULL;
 	guint last_offset = 0;
 	int max_len, cpos;
 
@@ -2142,8 +2112,7 @@ mono_arch_output_basic_block (MonoCompil
 		break_count ();
 #endif
 
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 		offset = code.buf - cfg->native_code;
 
 		max_len = ((int)(((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN])) + 128;
@@ -3123,10 +3092,7 @@ mono_arch_output_basic_block (MonoCompil
 	       
 		cpos += max_len;
 
-		last_ins = ins;
 		last_offset = offset;
-		
-		ins = ins->next;
 	}
 
 	ia64_codegen_close (code);
Index: mono/mini/mini-sparc.c
===================================================================
--- mono/mini/mini-sparc.c	(revision 89301)
+++ mono/mini/mini-sparc.c	(working copy)
@@ -1039,9 +1039,7 @@ emit_sig_cookie (MonoCompile *cfg, MonoC
 	sig_arg->inst_p0 = tmp_sig;
 	arg->inst_left = sig_arg;
 	arg->type = STACK_PTR;
-	/* prepend, so they get reversed */
-	arg->next = call->out_args;
-	call->out_args = arg;
+	MONO_INST_LIST_ADD_TAIL(&arg->node, &call->out_args);
 }
 
 /* 
@@ -1081,9 +1079,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			arg->cil_code = in->cil_code;
 			arg->inst_left = in;
 			arg->type = in->type;
-			/* prepend, we'll need to reverse them later */
-			arg->next = call->out_args;
-			call->out_args = arg;
+			MONO_INST_LIST_ADD_TAIL(&arg->node, &call->out_args);
 
 			if ((i >= sig->hasthis) && (MONO_TYPE_ISSTRUCT(sig->params [i - sig->hasthis]))) {
 				MonoInst *inst;
@@ -1193,19 +1189,6 @@ mono_arch_call_opcode (MonoCompile *cfg,
 		emit_sig_cookie (cfg, call, cinfo);
 	}
 
-	/*
-	 * Reverse the call->out_args list.
-	 */
-	{
-		MonoInst *prev = NULL, *list = call->out_args, *next;
-		while (list) {
-			next = list->next;
-			list->next = prev;
-			prev = list;
-			list = next;
-		}
-		call->out_args = prev;
-	}
 	call->stack_usage = cinfo->stack_usage + extra_space;
 	call->out_ireg_args = NULL;
 	call->out_freg_args = NULL;
@@ -1493,10 +1476,11 @@ emit_call (MonoCompile *cfg, guint32 *co
 static void
 peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *last_ins = NULL;
-	ins = bb->code;
+	MonoInst *ins, *n;
 
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
+		MonoInst *last_ins = mono_inst_list_prev(&ins->node,
+							 &bb->ins_list);
 
 		switch (ins->opcode) {
 		case OP_MUL_IMM: 
@@ -1505,8 +1489,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 				if (ins->dreg != ins->sreg1) {
 					ins->opcode = OP_MOVE;
 				} else {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				}
 			}
@@ -1523,8 +1506,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			    ins->inst_basereg == last_ins->inst_destbasereg &&
 			    ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -1547,8 +1529,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			      ins->inst_offset == last_ins->inst_offset) {
 
 				if (ins->dreg == last_ins->dreg) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					ins->opcode = OP_MOVE;
@@ -1582,8 +1563,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 					ins->inst_basereg == last_ins->inst_destbasereg &&
 					ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -1597,8 +1577,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 					ins->inst_basereg == last_ins->inst_destbasereg &&
 					ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -1622,8 +1601,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 				if (sparcv9) {
 					last_ins->opcode = OP_STOREI8_MEMBASE_IMM;
 					last_ins->inst_offset = ins->inst_offset;
-					last_ins->next = ins->next;				
-					ins = ins->next;
+					MONO_DEL_INS(ins);
 					continue;
 				}
 			}
@@ -1652,7 +1630,6 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			if (v64 && (mono_method_get_header (cfg->method)->code_size < 10000) && last_ins && 
 				(last_ins->opcode == OP_COMPARE_IMM) &&
 				(last_ins->inst_imm == 0)) {
-				MonoInst *next = ins->next;
 				switch (ins->opcode) {
 				case CEE_BEQ:
 					ins->opcode = OP_SPARC_BRZ;
@@ -1693,10 +1670,17 @@ peephole_pass (MonoCompile *cfg, MonoBas
 				default:
 					g_assert_not_reached ();
 				}
-				ins->sreg1 = last_ins->sreg1;
-				*last_ins = *ins;
-				last_ins->next = next;
-				ins = next;
+				last_ins->data = ins->data;
+				last_ins->opcode = ins->opcode;
+				last_ins->type = ins->type;
+				last_ins->ssa_op = ins->ssa_op;
+				last_ins->flags = ins->flags;
+				last_ins->dreg = ins->dreg;
+				last_ins->sreg2 = ins->sreg2;
+				last_ins->backend = ins->backend;
+				last_ins->klass = ins->klass;
+				last_ins->cil_code = ins->cil_code;
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			break;
@@ -1707,9 +1691,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			 * OP_MOVE reg, reg 
 			 */
 			if (ins->dreg == ins->sreg1) {
-				if (last_ins)
-					last_ins->next = ins->next;				
-				ins = ins->next;
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			/* 
@@ -1719,16 +1701,12 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			if (last_ins && last_ins->opcode == OP_MOVE &&
 			    ins->sreg1 == last_ins->dreg &&
 			    ins->dreg == last_ins->sreg1) {
-				last_ins->next = ins->next;				
-				ins = ins->next;				
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 }
 
 static int
@@ -2372,7 +2350,6 @@ mono_arch_output_basic_block (MonoCompil
 	MonoCallInst *call;
 	guint offset;
 	guint32 *code = (guint32*)(cfg->native_code + cfg->code_len);
-	MonoInst *last_ins = NULL;
 	int max_len, cpos;
 	const char *spec;
 
@@ -2388,8 +2365,7 @@ mono_arch_output_basic_block (MonoCompil
 		NOT_IMPLEMENTED;
 	}
 
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 		guint8* code_start;
 
 		offset = (guint8*)code - cfg->native_code;
@@ -3145,8 +3121,8 @@ mono_arch_output_basic_block (MonoCompil
 			ins->inst_c0 = (guint8*)code - cfg->native_code;
 			break;
 		case OP_BR:
-			//g_print ("target: %p, next: %p, curr: %p, last: %p\n", ins->inst_target_bb, bb->next_bb, ins, bb->last_ins);
-			if ((ins->inst_target_bb == bb->next_bb) && ins == bb->last_ins)
+			if ((ins->inst_target_bb == bb->next_bb) &&
+			    ins->node.next == &bb->ins_list)
 				break;
 			if (ins->flags & MONO_INST_BRLABEL) {
 				if (ins->inst_i0->inst_c0) {
@@ -3650,10 +3626,6 @@ mono_arch_output_basic_block (MonoCompil
 		}
 	       
 		cpos += max_len;
-
-		last_ins = ins;
-		
-		ins = ins->next;
 	}
 
 	cfg->code_len = (guint8*)code - cfg->native_code;
Index: mono/mini/mini-codegen.c
===================================================================
--- mono/mini/mini-codegen.c	(revision 89301)
+++ mono/mini/mini-codegen.c	(working copy)
@@ -443,71 +443,17 @@ print_regtrack (RegTrack *t, int num)
 }
 #endif /* DISABLE_LOGGING */
 
-typedef struct InstList InstList;
-
-struct InstList {
-	InstList *prev;
-	InstList *next;
-	MonoInst *data;
-};
-
-static inline InstList*
-inst_list_prepend (guint8 *mem, InstList *list, MonoInst *data)
-{
-	InstList *item = (InstList*)(gpointer)mem;
-	item->data = data;
-	item->prev = NULL;
-	item->next = list;
-	if (list)
-		list->prev = item;
-	return item;
-}
-
 static inline void
-insert_before_ins (MonoInst *ins, InstList *item, MonoInst* to_insert)
+insert_before_ins (MonoInst *ins, MonoInst* to_insert)
 {
-	MonoInst *prev;
-
-	/*
-	 * If this function is called multiple times, the new instructions are inserted
-	 * in the proper order.
-	 */
-
-	if (item->next) {
-		prev = item->next->data;
-
-		while (prev->next != ins)
-			prev = prev->next;
-		to_insert->next = ins;
-		prev->next = to_insert;
-	} else {
-		to_insert->next = ins;
-	}
-
-	/*
-	 * insert_after_ins insert the new instruction before item->data, so
-	 * we have to modify it to point to the first of the prepended instructions.
-	 */
-	if (item->data == ins)
-		item->data = to_insert; 
-}
-
-static inline void
-insert_after_ins (MonoInst *ins, InstList *item, MonoInst* to_insert)
-{
-	if (item->prev) {
-		while (ins->next != item->prev->data)
-			ins = ins->next;
-	}
-	to_insert->next = ins->next;
-	ins->next = to_insert;
+	MONO_INST_LIST_ADD_TAIL(&to_insert->node, &ins->node);
 }
 
 /*
  * Force the spilling of the variable in the symbolic register 'reg'.
  */
 static int
-get_register_force_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, int reg, gboolean fp)
+get_register_force_spilling (MonoCompile *cfg, MonoInst *ins, MonoInstList *next, int reg, gboolean fp)
 {
 	MonoInst *load;
 	int i, sel, spill;
@@ -537,7 +483,7 @@ get_register_force_spilling (MonoCompile
 	load->dreg = sel;
 	load->inst_basereg = cfg->frame_reg;
 	load->inst_offset = mono_spillvar_offset (cfg, spill, fp);
-	insert_after_ins (ins, item, load);
+	MONO_INST_LIST_ADD_TAIL(&load->node, next);
 	DEBUG (printf ("SPILLED LOAD (%d at 0x%08lx(%%ebp)) R%d (freed %s)\n", spill, (long)load->inst_offset, i, mono_regname_full (sel, fp)));
 	if (fp)
 		i = mono_regstate_alloc_float (cfg->rs, regmask (sel));
@@ -554,7 +500,7 @@ get_register_force_spilling (MonoCompile
 #endif
 
 static int
-get_register_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, regmask_t regmask, int reg, gboolean fp)
+get_register_spilling (MonoCompile *cfg, MonoInst *ins, MonoInstList *next, regmask_t regmask, int reg, gboolean fp)
 {
 	MonoInst *load;
 	int i, sel, spill;
@@ -625,7 +571,7 @@ get_register_spilling (MonoCompile *cfg,
 	load->dreg = sel;
 	load->inst_basereg = cfg->frame_reg;
 	load->inst_offset = mono_spillvar_offset (cfg, spill, fp);
-	insert_after_ins (ins, item, load);
+	MONO_INST_LIST_ADD_TAIL(&load->node, next);
 	DEBUG (printf ("\tSPILLED LOAD (%d at 0x%08lx(%%ebp)) R%d (freed %s)\n", spill, (long)load->inst_offset, i, mono_regname_full (sel, fp)));
 	if (fp)
 		i = mono_regstate_alloc_float (cfg->rs, regmask (sel));
@@ -637,29 +583,34 @@ get_register_spilling (MonoCompile *cfg,
 }
 
 static void
-free_up_ireg (MonoCompile *cfg, InstList *item, MonoInst *ins, int hreg)
+free_up_ireg (MonoCompile *cfg, MonoInst *ins, MonoInstList *next, int hreg)
 {
 	if (!(cfg->rs->ifree_mask & (regmask (hreg)))) {
 		DEBUG (printf ("\tforced spill of R%d\n", cfg->rs->isymbolic [hreg]));
-		get_register_force_spilling (cfg, item, ins, cfg->rs->isymbolic [hreg], FALSE);
+		get_register_force_spilling (cfg, ins, next,
+					     cfg->rs->isymbolic [hreg], FALSE);
 		mono_regstate_free_int (cfg->rs, hreg);
 	}
 }
 
 static void
-free_up_reg (MonoCompile *cfg, InstList *item, MonoInst *ins, int hreg, gboolean fp)
+free_up_reg (MonoCompile *cfg, MonoInst *ins, MonoInstList *next, int hreg, gboolean fp)
 {
 	if (fp) {
 		if (!(cfg->rs->ffree_mask & (regmask (hreg)))) {
 			DEBUG (printf ("\tforced spill of R%d\n", cfg->rs->isymbolic [hreg]));
-			get_register_force_spilling (cfg, item, ins, cfg->rs->isymbolic [hreg], fp);
+			get_register_force_spilling (cfg, ins, next,
+						     cfg->rs->isymbolic [hreg],
+						     fp);
 			mono_regstate_free_float (cfg->rs, hreg);
 		}
 	}
 	else {
 		if (!(cfg->rs->ifree_mask & (regmask (hreg)))) {
 			DEBUG (printf ("\tforced spill of R%d\n", cfg->rs->isymbolic [hreg]));
-			get_register_force_spilling (cfg, item, ins, cfg->rs->isymbolic [hreg], fp);
+			get_register_force_spilling (cfg, ins, next,
+						     cfg->rs->isymbolic [hreg],
+						     fp);
 			mono_regstate_free_int (cfg->rs, hreg);
 		}
 	}
@@ -679,9 +630,8 @@ create_copy_ins (MonoCompile *cfg, int d
 	copy->sreg1 = src;
 	copy->cil_code = ip;
 	if (ins) {
-		copy->next = ins->next;
+		MONO_INST_LIST_ADD(&copy->node, &ins->node);
 		copy->cil_code = ins->cil_code;
-		ins->next = copy;
 	}
 	DEBUG (printf ("\tforced copy from %s to %s\n", mono_regname_full (src, fp), mono_regname_full (dest, fp)));
 	return copy;
@@ -695,10 +645,9 @@ create_spilled_store (MonoCompile *cfg, 
 	store->sreg1 = reg;
 	store->inst_destbasereg = cfg->frame_reg;
 	store->inst_offset = mono_spillvar_offset (cfg, spill, fp);
-	if (ins) {
-		store->next = ins->next;
-		ins->next = store;
-	}
+	if (ins)
+		MONO_INST_LIST_ADD(&store->node, &ins->node);
+
 	DEBUG (printf ("\tSPILLED STORE (%d at 0x%08lx(%%ebp)) R%d (from %s)\n", spill, (long)store->inst_offset, prev_reg, mono_regname_full (reg, fp)));
 	return store;
 }
@@ -711,7 +660,7 @@ enum {
 };
 
 static inline int
-alloc_int_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, regmask_t dest_mask, int sym_reg, RegTrack *info)
+alloc_int_reg (MonoCompile *cfg, MonoInst *ins, MonoInstList *next, regmask_t dest_mask, int sym_reg, RegTrack *info)
 {
 	int val;
 
@@ -725,32 +674,32 @@ alloc_int_reg (MonoCompile *cfg, InstLis
 
 	val = mono_regstate_alloc_int (cfg->rs, dest_mask);
 	if (val < 0)
-		val = get_register_spilling (cfg, tmp, ins, dest_mask, sym_reg, FALSE);
+		val = get_register_spilling (cfg, ins, next, dest_mask, sym_reg, FALSE);
 
 	return val;
 }
 
 static inline int
-alloc_float_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, regmask_t dest_mask, int sym_reg)
+alloc_float_reg (MonoCompile *cfg, MonoInst *ins, MonoInstList *next, regmask_t dest_mask, int sym_reg)
 {
 	int val;
 
 	val = mono_regstate_alloc_float (cfg->rs, dest_mask);
 
 	if (val < 0) {
-		val = get_register_spilling (cfg, tmp, ins, dest_mask, sym_reg, TRUE);
+		val = get_register_spilling (cfg, ins, next, dest_mask, sym_reg, TRUE);
 	}
 
 	return val;
 }
 
 static inline int
-alloc_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, regmask_t dest_mask, int sym_reg, RegTrack *info, gboolean fp)
+alloc_reg (MonoCompile *cfg, MonoInst *ins, MonoInstList *next, regmask_t dest_mask, int sym_reg, RegTrack *info, gboolean fp)
 {
 	if (fp)
-		return alloc_float_reg (cfg, tmp, ins, dest_mask, sym_reg);
+		return alloc_float_reg (cfg, ins, next, dest_mask, sym_reg);
 	else
-		return alloc_int_reg (cfg, tmp, ins, dest_mask, sym_reg, info);
+		return alloc_int_reg (cfg, ins, next, dest_mask, sym_reg, info);
 }
 
 static inline void
@@ -789,27 +738,23 @@ assign_ireg (MonoCompile *cfg, MonoRegSt
  * Local register allocation.
  * We first scan the list of instructions and we save the liveness info of
  * each register (when the register is first used, when it's value is set etc.).
- * We also reverse the list of instructions (in the InstList list) because assigning
- * registers backwards allows for more tricks to be used.
  */
 void
 mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
 {
 	MonoInst *ins;
 	MonoRegState *rs = cfg->rs;
-	int i, val, fpcount, ins_count;
+	int i, val, fpcount;
 	RegTrack *reginfo;
-	InstList *tmp, *reversed = NULL;
 	const char *spec;
 	GList *fspill_list = NULL;
 	gboolean fp;
 	int fspill = 0;
-	guint8 *inst_list, *mem;
 #if MONO_ARCH_USE_FPSTACK
 	gboolean need_fpstack = use_fpstack;
 #endif
 
-	if (!bb->code)
+	if (MONO_INST_LIST_EMPTY(&bb->ins_list))
 		return;
 
 	rs->next_vreg = bb->max_vreg;
@@ -821,11 +766,6 @@ mono_local_regalloc (MonoCompile *cfg, M
 	if (use_fpstack)
 		rs->ffree_mask = 0xff & ~(regmask (MONO_ARCH_FPSTACK_SIZE));
 
-	ins = bb->code;
-
-	/*if (cfg->opt & MONO_OPT_COPYPROP)
-		local_copy_prop (cfg, ins);*/
-
 	if (cfg->reginfo && cfg->reginfo_len < rs->next_vreg) {
 		cfg->reginfo = NULL;
 	}
@@ -839,27 +779,11 @@ mono_local_regalloc (MonoCompile *cfg, M
 
 	memset (reginfo, 0, rs->next_vreg * sizeof (RegTrack));
 
-	ins_count = 0;
-	for (ins = bb->code; ins; ins = ins->next) {
-		ins_count ++;
-	}
-
-	if (cfg->reverse_inst_list && (cfg->reverse_inst_list_len < ins_count)) {
-		cfg->reverse_inst_list = NULL;
-	}
-
-	inst_list = cfg->reverse_inst_list;
-	if (!inst_list) {
-		cfg->reverse_inst_list_len = MAX (ins_count, 1024);
-		inst_list = cfg->reverse_inst_list = mono_mempool_alloc (cfg->mempool, cfg->reverse_inst_list_len * sizeof (InstList));
-	}
-	mem = inst_list;
-
 	i = 1;
 	fpcount = 0;
 	DEBUG (printf ("\nLOCAL REGALLOC: BASIC BLOCK: %d\n", bb->block_num));
 	/* forward pass on the instructions to collect register liveness info */
-	for (ins = bb->code; ins; ins = ins->next) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 		spec = ins_get_spec (ins->opcode);
 
 		if (G_UNLIKELY (spec == MONO_ARCH_CPU_SPEC)) {
@@ -1006,8 +930,6 @@ mono_local_regalloc (MonoCompile *cfg, M
 			}
 		}
 
-		reversed = inst_list_prepend (mem, reversed, ins);
-		mem += sizeof (InstList);
 		++i;
 	}
 
@@ -1015,16 +937,21 @@ mono_local_regalloc (MonoCompile *cfg, M
 	fspill = 0;
 
 	DEBUG (print_regtrack (reginfo, rs->next_vreg));
-	tmp = reversed;
-	while (tmp) {
+	ins = mono_inst_list_last(&bb->ins_list);
+	while (ins) {
 		int prev_dreg, prev_sreg1, prev_sreg2, clob_dreg;
 		int dest_dreg, dest_sreg1, dest_sreg2, clob_reg;
 		int dreg_high, sreg1_high;
 		regmask_t dreg_mask, sreg1_mask, sreg2_mask, mask;
 		regmask_t dreg_fixed_mask, sreg1_fixed_mask, sreg2_fixed_mask;
 		const unsigned char *ip;
+		MonoInst *prev_ins;
+		MonoInstList *next;
+
+		prev_ins = mono_inst_list_prev(&ins->node, &bb->ins_list);
+		next = ins->node.next;
 		--i;
-		ins = tmp->data;
+		g_assert (i >= 0);
 		spec = ins_get_spec (ins->opcode);
 		prev_dreg = -1;
 		prev_sreg2 = -1;
@@ -1075,7 +1002,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 					g_assert (spill_node);
 
 					store = create_spilled_store_float (cfg, GPOINTER_TO_INT (spill_node->data), ins->dreg, ins);
-					insert_before_ins (ins, tmp, store);
+					insert_before_ins (ins, store);
 					fspill_list = g_list_remove (fspill_list, spill_node->data);
 					fspill--;
 				}
@@ -1098,9 +1025,9 @@ mono_local_regalloc (MonoCompile *cfg, M
 					fspill++;
 					fspill_list = g_list_prepend (fspill_list, GINT_TO_POINTER(fspill));
 					load = create_spilled_load_float (cfg, fspill, ins->sreg1, ins);
-					insert_before_ins (ins, tmp, load);
+					insert_before_ins (ins, load);
 					if (store) 
-						insert_before_ins (load, tmp, store);
+						insert_before_ins (load, store);
 				}
 			}
 
@@ -1124,9 +1051,9 @@ mono_local_regalloc (MonoCompile *cfg, M
 					fspill++;
 					fspill_list = g_list_prepend (fspill_list, GINT_TO_POINTER(fspill));
 					load = create_spilled_load_float (cfg, fspill, ins->sreg2, ins);
-					insert_before_ins (ins, tmp, load);
+					insert_before_ins (ins, load);
 					if (store) 
-						insert_before_ins (load, tmp, store);
+						insert_before_ins (load, store);
 				}
 			}
 		}
@@ -1140,7 +1067,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 				if (is_global_ireg (ins->sreg2)) {
 					/* Argument already in hard reg, need to copy */
 					MonoInst *copy = create_copy_ins (cfg, dest_sreg2, ins->sreg2, NULL, ip, FALSE);
-					insert_before_ins (ins, tmp, copy);
+					insert_before_ins (ins, copy);
 				}
 				else {
 					val = rs->vassign [ins->sreg2];
@@ -1153,7 +1080,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 					} else {
 						/* Argument already in hard reg, need to copy */
 						MonoInst *copy = create_copy_ins (cfg, dest_sreg2, val, NULL, ip, FALSE);
-						insert_before_ins (ins, tmp, copy);
+						insert_before_ins (ins, copy);
 					}
 				}
 			} else {
@@ -1174,7 +1101,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 					 * and then copy from this to dest_sreg2.
 					 */
 					int new_dest;
-					new_dest = alloc_int_reg (cfg, tmp, ins, dreg_mask, ins->dreg, &reginfo [ins->dreg]);
+					new_dest = alloc_int_reg (cfg, ins, next, dreg_mask, ins->dreg, &reginfo [ins->dreg]);
 					g_assert (new_dest >= 0);
 					DEBUG (printf ("\tchanging dreg R%d to %s from %s\n", ins->dreg, mono_arch_regname (new_dest), mono_arch_regname (dest_sreg2)));
 
@@ -1188,7 +1115,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 
 				if (is_global_ireg (ins->sreg2)) {
 					MonoInst *copy = create_copy_ins (cfg, dest_sreg2, ins->sreg2, NULL, ip, FALSE);
-					insert_before_ins (ins, tmp, copy);
+					insert_before_ins (ins, copy);
 				}
 				else {
 					val = rs->vassign [ins->sreg2];
@@ -1204,7 +1131,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 
 				if (need_spill) {
 					DEBUG (printf ("\tforced spill of R%d\n", rs->isymbolic [dest_sreg2]));
-					get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [dest_sreg2], FALSE);
+					get_register_force_spilling (cfg, ins, next, rs->isymbolic [dest_sreg2], FALSE);
 					mono_regstate_free_int (rs, dest_sreg2);
 				}
 
@@ -1235,7 +1162,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 			val = rassign (cfg, ins->dreg, fp);
 			if (is_soft_reg (ins->dreg, fp) && (val >= 0) && (!(regmask (val) & dreg_mask))) {
 				/* DREG is already allocated to a register needed for sreg1 */
-				get_register_force_spilling (cfg, tmp, ins, ins->dreg, FALSE);
+				get_register_force_spilling (cfg, ins, next, ins->dreg, FALSE);
 				mono_regstate_free_int (rs, val);
 			}
 		}
@@ -1251,13 +1178,13 @@ mono_local_regalloc (MonoCompile *cfg, M
 
 			if (dest_dreg != -1) {
 				if (rs->vassign [ins->dreg] != dest_dreg)
-					free_up_ireg (cfg, tmp, ins, dest_dreg);
+					free_up_ireg (cfg, ins, next, dest_dreg);
 
 				dreg2 = ins->dreg + 1;
 				dest_dreg2 = MONO_ARCH_INST_REGPAIR_REG2 (spec [MONO_INST_DEST], dest_dreg);
 				if (dest_dreg2 != -1) {
 					if (rs->vassign [dreg2] != dest_dreg2)
-						free_up_ireg (cfg, tmp, ins, dest_dreg2);
+						free_up_ireg (cfg, ins, next, dest_dreg2);
 				}
 			}
 		}
@@ -1271,7 +1198,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 				 */
 				val = mono_regstate_alloc_int (rs, dreg_fixed_mask);
 				if (val < 0)
-					val = get_register_spilling (cfg, tmp, ins, dreg_fixed_mask, -1, fp);
+					val = get_register_spilling (cfg, ins, next, dreg_fixed_mask, -1, fp);
 				mono_regstate_free_int (rs, val);
 				dest_dreg = val;
 
@@ -1293,7 +1220,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 					/* the register gets spilled after this inst */
 					spill = -val -1;
 				}
-				val = alloc_reg (cfg, tmp, ins, dreg_mask, ins->dreg, &reginfo [ins->dreg], fp);
+				val = alloc_reg (cfg, ins, next, dreg_mask, ins->dreg, &reginfo [ins->dreg], fp);
 				assign_reg (cfg, rs, ins->dreg, val, fp);
 				if (spill)
 					create_spilled_store (cfg, spill, val, prev_dreg, ins, fp);
@@ -1324,7 +1251,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 				}
 				val = mono_regstate_alloc_int (rs, mask);
 				if (val < 0)
-					val = get_register_spilling (cfg, tmp, ins, mask, reg2, fp);
+					val = get_register_spilling (cfg, ins, next, mask, reg2, fp);
 				if (spill)
 					create_spilled_store (cfg, spill, val, reg2, ins, fp);
 			}
@@ -1332,7 +1259,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 				if (! (mask & (regmask (val)))) {
 					val = mono_regstate_alloc_int (rs, mask);
 					if (val < 0)
-						val = get_register_spilling (cfg, tmp, ins, mask, reg2, fp);
+						val = get_register_spilling (cfg, ins, next, mask, reg2, fp);
 
 					/* Reallocate hreg to the correct register */
 					create_copy_ins (cfg, rs->vassign [reg2], val, ins, ip, fp);
@@ -1375,11 +1302,11 @@ mono_local_regalloc (MonoCompile *cfg, M
 
 			if (fp) {
 				if (rs->fsymbolic [dest_dreg] >= MONO_MAX_FREGS)
-					free_up_reg (cfg, tmp, ins, dest_dreg, fp);
+					free_up_reg (cfg, ins, next, dest_dreg, fp);
 			}
 			else {
 				if (rs->isymbolic [dest_dreg] >= MONO_MAX_IREGS)
-					free_up_reg (cfg, tmp, ins, dest_dreg, fp);
+					free_up_reg (cfg, ins, next, dest_dreg, fp);
 			}
 		}
 
@@ -1397,7 +1324,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 		 */
 		if ((clob_reg != -1) && (!(rs->ifree_mask & (regmask (clob_reg))))) {
 			DEBUG (printf ("\tforced spill of clobbered reg R%d\n", rs->isymbolic [clob_reg]));
-			get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [clob_reg], FALSE);
+			get_register_force_spilling (cfg, ins, next, rs->isymbolic [clob_reg], FALSE);
 			mono_regstate_free_int (rs, clob_reg);
 		}
 
@@ -1424,7 +1351,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 			for (j = 0; j < MONO_MAX_IREGS; ++j) {
 				s = regmask (j);
 				if ((clob_mask & s) && !(rs->ifree_mask & s) && (j != ins->sreg1) && (j != dreg) && (j != dreg2)) {
-					get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [j], FALSE);
+					get_register_force_spilling (cfg, ins, next, rs->isymbolic [j], FALSE);
 					mono_regstate_free_int (rs, j);
 				}
 			}
@@ -1439,7 +1366,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 				for (j = 0; j < MONO_MAX_FREGS; ++j) {
 					s = regmask (j);
 					if ((clob_mask & s) && !(rs->ffree_mask & s) && (j != ins->sreg1) && (j != dreg)) {
-						get_register_force_spilling (cfg, tmp, ins, rs->fsymbolic [j], TRUE);
+						get_register_force_spilling (cfg, ins, next, rs->fsymbolic [j], TRUE);
 						mono_regstate_free_float (rs, j);
 					}
 				}
@@ -1539,7 +1466,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 					 */
 					val = mono_regstate_alloc_int (rs, sreg1_fixed_mask);
 					if (val < 0)
-						val = get_register_spilling (cfg, tmp, ins, sreg1_fixed_mask, -1, fp);
+						val = get_register_spilling (cfg, ins, next, sreg1_fixed_mask, -1, fp);
 					mono_regstate_free_int (rs, val);
 					dest_sreg1 = val;
 
@@ -1554,13 +1481,13 @@ mono_local_regalloc (MonoCompile *cfg, M
 
 				if (!(rs->ifree_mask & (regmask (dest_sreg1)))) {
 					DEBUG (printf ("\tforced spill of R%d\n", rs->isymbolic [dest_sreg1]));
-					get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [dest_sreg1], FALSE);
+					get_register_force_spilling (cfg, ins, next, rs->isymbolic [dest_sreg1], FALSE);
 					mono_regstate_free_int (rs, dest_sreg1);
 				}
 				if (is_global_ireg (ins->sreg1)) {
 					/* The argument is already in a hard reg, need to copy */
 					MonoInst *copy = create_copy_ins (cfg, dest_sreg1, ins->sreg1, NULL, ip, FALSE);
-					insert_before_ins (ins, tmp, copy);
+					insert_before_ins (ins, copy);
 					ins->sreg1 = dest_sreg1;
 				}
 			}
@@ -1583,7 +1510,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 						sreg1_mask = regmask (ins->dreg);
 					}
 
-					val = alloc_reg (cfg, tmp, ins, sreg1_mask, ins->sreg1, &reginfo [ins->sreg1], fp);
+					val = alloc_reg (cfg, ins, next, sreg1_mask, ins->sreg1, &reginfo [ins->sreg1], fp);
 					assign_reg (cfg, rs, ins->sreg1, val, fp);
 					DEBUG (printf ("\tassigned sreg1 %s to R%d\n", mono_regname_full (val, fp), ins->sreg1));
 
@@ -1593,7 +1520,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 						 * Need to insert before the instruction since it can
 						 * overwrite sreg1.
 						 */
-						insert_before_ins (ins, tmp, store);
+						insert_before_ins (ins, store);
 					}
 				}
 				else if ((dest_sreg1 != -1) && (dest_sreg1 != val)) {
@@ -1625,7 +1552,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 				}
 				val = mono_regstate_alloc_int (rs, mask);
 				if (val < 0)
-					val = get_register_spilling (cfg, tmp, ins, mask, reg2, fp);
+					val = get_register_spilling (cfg, ins, next, mask, reg2, fp);
 				if (spill)
 					g_assert_not_reached ();
 			}
@@ -1637,7 +1564,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 #if 0
 					val = mono_regstate_alloc_int (rs, mask);
 					if (val < 0)
-						val = get_register_spilling (cfg, tmp, ins, mask, reg2, fp);
+						val = get_register_spilling (cfg, ins, next, mask, reg2, fp);
 
 					/* Reallocate hreg to the correct register */
 					create_copy_ins (cfg, rs->vassign [reg2], val, ins, ip, fp);
@@ -1663,7 +1590,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 				 * copying sreg1 to dreg could clobber sreg2, so allocate a new
 				 * register for it.
 				 */
-				int reg2 = alloc_reg (cfg, tmp, ins, dreg_mask, ins->sreg2, NULL, fp);
+				int reg2 = alloc_reg (cfg, ins, next, dreg_mask, ins->sreg2, NULL, fp);
 
 				DEBUG (printf ("\tneed to copy sreg2 %s to reg %s\n", mono_regname_full (ins->sreg2, fp), mono_regname_full (reg2, fp)));
 				sreg2_copy = create_copy_ins (cfg, reg2, ins->sreg2, NULL, ip, fp);
@@ -1691,10 +1618,10 @@ mono_local_regalloc (MonoCompile *cfg, M
 
 			DEBUG (printf ("\tneed to copy sreg1 %s to dreg %s\n", mono_regname_full (ins->sreg1, fp), mono_regname_full (ins->dreg, fp)));
 			copy = create_copy_ins (cfg, ins->dreg, ins->sreg1, NULL, ip, fp);
-			insert_before_ins (ins, tmp, copy);
+			insert_before_ins (ins, copy);
 
 			if (sreg2_copy)
-				insert_before_ins (copy, tmp, sreg2_copy);
+				insert_before_ins (copy, sreg2_copy);
 
 			/*
 			 * Need to prevent sreg2 to be allocated to sreg1, since that
@@ -1721,7 +1648,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 					/* the register gets spilled after this inst */
 					spill = -val -1;
 				}
-				val = alloc_reg (cfg, tmp, ins, sreg2_mask, ins->sreg2, &reginfo [ins->sreg2], fp);
+				val = alloc_reg (cfg, ins, next, sreg2_mask, ins->sreg2, &reginfo [ins->sreg2], fp);
 				assign_reg (cfg, rs, ins->sreg2, val, fp);
 				DEBUG (printf ("\tassigned sreg2 %s to R%d\n", mono_regname_full (val, fp), ins->sreg2));
 				if (spill) {
@@ -1730,7 +1657,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 					 * Need to insert before the instruction since it can
 					 * overwrite sreg2.
 					 */
-					insert_before_ins (ins, tmp, store);
+					insert_before_ins (ins, store);
 				}
 			}
 			ins->sreg2 = val;
@@ -1749,10 +1676,7 @@ mono_local_regalloc (MonoCompile *cfg, M
 		}*/
 	
 		DEBUG (mono_print_ins (i, ins));
-		/* this may result from a insert_before call */
-		if (!tmp->next)
-			bb->code = tmp->data;
-		tmp = tmp->next;
+		ins = prev_ins;
 	}
 
 	g_list_free (fspill_list);
Index: mono/mini/mini-ppc.c
===================================================================
--- mono/mini/mini-ppc.c	(revision 89301)
+++ mono/mini/mini-ppc.c	(working copy)
@@ -1143,10 +1143,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			MONO_INST_NEW (cfg, arg, OP_OUTARG);
 			arg->inst_imm = cinfo->sig_cookie.offset;
 			arg->inst_left = sig_arg;
-			
-			/* prepend, so they get reversed */
-			arg->next = call->out_args;
-			call->out_args = arg;
+			MONO_INST_LIST_ADD_TAIL(&arg->node, &call->out_args);
 		}
 		if (is_virtual && i == 0) {
 			/* the argument will be attached to the call instrucion */
@@ -1159,9 +1156,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			arg->inst_left = in;
 			arg->inst_call = call;
 			arg->type = in->type;
-			/* prepend, we'll need to reverse them later */
-			arg->next = call->out_args;
-			call->out_args = arg;
+			MONO_INST_LIST_ADD_TAIL(&arg->node, &call->out_args);
 			if (ainfo->regtype == RegTypeGeneral) {
 				arg->backend.reg3 = ainfo->reg;
 				call->used_iregs |= 1 << ainfo->reg;
@@ -1216,19 +1211,6 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			}
 		}
 	}
-	/*
-	 * Reverse the call->out_args list.
-	 */
-	{
-		MonoInst *prev = NULL, *list = call->out_args, *next;
-		while (list) {
-			next = list->next;
-			list->next = prev;
-			prev = list;
-			list = next;
-		}
-		call->out_args = prev;
-	}
 	call->stack_usage = cinfo->stack_usage;
 	cfg->param_area = MAX (cfg->param_area, cinfo->stack_usage);
 	cfg->flags |= MONO_CFG_HAS_CALLS;
@@ -1445,11 +1427,11 @@ if (ins->flags & MONO_INST_BRLABEL) { \
 static void
 peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *last_ins = NULL;
-	ins = bb->code;
-
-	while (ins) {
+	MonoInst *ins, *n;
 
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
+		MonoInst *last_ins = mono_inst_list_prev(&ins->node,
+							 &bb->ins_list);
 		switch (ins->opcode) {
 		case OP_MUL_IMM: 
 			/* remove unnecessary multiplication with 1 */
@@ -1457,8 +1439,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 				if (ins->dreg != ins->sreg1) {
 					ins->opcode = OP_MOVE;
 				} else {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				}
 			} else {
@@ -1480,8 +1461,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			    ins->inst_basereg == last_ins->inst_destbasereg &&
 			    ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					//static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
@@ -1504,8 +1484,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			      ins->inst_offset == last_ins->inst_offset) {
 
 				if (ins->dreg == last_ins->dreg) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					ins->opcode = OP_MOVE;
@@ -1560,9 +1539,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			 * OP_MOVE reg, reg 
 			 */
 			if (ins->dreg == ins->sreg1) {
-				if (last_ins)
-					last_ins->next = ins->next;				
-				ins = ins->next;
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			/* 
@@ -1572,16 +1549,12 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			if (last_ins && last_ins->opcode == OP_MOVE &&
 			    ins->sreg1 == last_ins->dreg &&
 			    ins->dreg == last_ins->sreg1) {
-				last_ins->next = ins->next;				
-				ins = ins->next;				
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 }
 
 /* 
@@ -1628,23 +1601,10 @@ branch_b1_table [] = {
 	PPC_BR_LT 
 };
 
-static void
-insert_after_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *to_insert)
-{
-	if (ins == NULL) {
-		ins = bb->code;
-		bb->code = to_insert;
-		to_insert->next = ins;
-	} else {
-		to_insert->next = ins->next;
-		ins->next = to_insert;
-	}
-}
-
-#define NEW_INS(cfg,dest,op) do {       \
+#define NEW_INS(cfg,ins,dest,op) do {					\
 		(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
 		(dest)->opcode = (op);  \
-		insert_after_ins (bb, last_ins, (dest)); \
+		MONO_INST_LIST_ADD_TAIL(&(dest)->node, &(ins)->node);	\
 	} while (0)
 
 static int
@@ -1727,21 +1687,20 @@ map_to_reg_reg_op (int op)
 static void
 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *next, *temp, *last_ins = NULL;
+	MonoInst *ins, *next, *temp;
 	int imm;
 
 	/* setup the virtual reg allocator */
 	if (bb->max_vreg > cfg->rs->next_vreg)
 		cfg->rs->next_vreg = bb->max_vreg;
 
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 loop_start:
 		switch (ins->opcode) {
 		case OP_ADD_IMM:
 		case OP_ADDCC_IMM:
 			if (!ppc_is_imm16 (ins->inst_imm)) {
-				NEW_INS (cfg, temp, OP_ICONST);
+				NEW_INS (cfg, ins, temp, OP_ICONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->sreg2 = temp->dreg;
@@ -1750,7 +1709,7 @@ loop_start:
 			break;
 		case OP_SUB_IMM:
 			if (!ppc_is_imm16 (-ins->inst_imm)) {
-				NEW_INS (cfg, temp, OP_ICONST);
+				NEW_INS (cfg, ins, temp, OP_ICONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->sreg2 = temp->dreg;
@@ -1761,7 +1720,7 @@ loop_start:
 		case OP_OR_IMM:
 		case OP_XOR_IMM:
 			if ((ins->inst_imm & 0xffff0000) && (ins->inst_imm & 0xffff)) {
-				NEW_INS (cfg, temp, OP_ICONST);
+				NEW_INS (cfg, ins, temp, OP_ICONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->sreg2 = temp->dreg;
@@ -1771,16 +1730,18 @@ loop_start:
 		case OP_SBB_IMM:
 		case OP_SUBCC_IMM:
 		case OP_ADC_IMM:
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_imm;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			ins->sreg2 = temp->dreg;
 			ins->opcode = map_to_reg_reg_op (ins->opcode);
 			break;
 		case OP_COMPARE_IMM:
-			if (compare_opcode_is_unsigned (ins->next->opcode)) {
+			next = mono_inst_list_next(&ins->node, &bb->ins_list);
+			g_assert(next);
+			if (compare_opcode_is_unsigned (next->opcode)) {
 				if (!ppc_is_uimm16 (ins->inst_imm)) {
-					NEW_INS (cfg, temp, OP_ICONST);
+					NEW_INS (cfg, ins, temp, OP_ICONST);
 					temp->inst_c0 = ins->inst_imm;
 					temp->dreg = mono_regstate_next_int (cfg->rs);
 					ins->sreg2 = temp->dreg;
@@ -1788,7 +1749,7 @@ loop_start:
 				}
 			} else {
 				if (!ppc_is_imm16 (ins->inst_imm)) {
-					NEW_INS (cfg, temp, OP_ICONST);
+					NEW_INS (cfg, ins, temp, OP_ICONST);
 					temp->inst_c0 = ins->inst_imm;
 					temp->dreg = mono_regstate_next_int (cfg->rs);
 					ins->sreg2 = temp->dreg;
@@ -1813,7 +1774,7 @@ loop_start:
 				break;
 			}
 			if (!ppc_is_imm16 (ins->inst_imm)) {
-				NEW_INS (cfg, temp, OP_ICONST);
+				NEW_INS (cfg, ins, temp, OP_ICONST);
 				temp->inst_c0 = ins->inst_imm;
 				temp->dreg = mono_regstate_next_int (cfg->rs);
 				ins->sreg2 = temp->dreg;
@@ -1842,7 +1803,7 @@ loop_start:
 			 */
 			if (ppc_is_imm16 (ins->inst_offset))
 				break;
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_offset;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			ins->sreg2 = temp->dreg;
@@ -1852,31 +1813,26 @@ loop_start:
 		case OP_STOREI1_MEMBASE_IMM:
 		case OP_STOREI2_MEMBASE_IMM:
 		case OP_STOREI4_MEMBASE_IMM:
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_imm;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			ins->sreg1 = temp->dreg;
 			ins->opcode = map_to_reg_reg_op (ins->opcode);
-			last_ins = temp;
 			goto loop_start; /* make it handle the possibly big ins->inst_offset */
 		case OP_R8CONST:
 		case OP_R4CONST:
-			NEW_INS (cfg, temp, OP_ICONST);
+			NEW_INS (cfg, ins, temp, OP_ICONST);
 			temp->inst_c0 = ins->inst_p0;
 			temp->dreg = mono_regstate_next_int (cfg->rs);
 			ins->inst_basereg = temp->dreg;
 			ins->inst_offset = 0;
 			ins->opcode = ins->opcode == OP_R4CONST? OP_LOADR4_MEMBASE: OP_LOADR8_MEMBASE;
-			last_ins = temp;
 			/* make it handle the possibly big ins->inst_offset
 			 * later optimize to use lis + load_membase
 			 */
 			goto loop_start;
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 	bb->max_vreg = cfg->rs->next_vreg;
 	
 }
@@ -1884,7 +1840,7 @@ loop_start:
 void
 mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	if (!bb->code)
+	if (MONO_INST_LIST_EMPTY(&bb->ins_list))
 		return;
 	mono_arch_lowering_pass (cfg, bb);
 	mono_local_regalloc (cfg, bb);
@@ -2148,11 +2104,10 @@ ppc_patch (guchar *code, guchar *target)
 void
 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins;
+	MonoInst *ins, *next;
 	MonoCallInst *call;
 	guint offset;
 	guint8 *code = cfg->native_code + cfg->code_len;
-	MonoInst *last_ins = NULL;
 	guint last_offset = 0;
 	int max_len, cpos;
 
@@ -2177,8 +2132,7 @@ mono_arch_output_basic_block (MonoCompil
 		//x86_inc_mem (code, &cov->data [bb->dfn].count); 
 	}
 
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 		offset = code - cfg->native_code;
 
 		max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
@@ -2314,13 +2268,15 @@ mono_arch_output_basic_block (MonoCompil
 			ppc_rlwinm (code, ins->dreg, ins->sreg1, 0, 16, 31);
 			break;
 		case OP_COMPARE:
-			if (ins->next && compare_opcode_is_unsigned (ins->next->opcode))
+			next = mono_inst_list_next(&ins->node, &bb->ins_list);
+			if (next && compare_opcode_is_unsigned (next->opcode))
 				ppc_cmpl (code, 0, 0, ins->sreg1, ins->sreg2);
 			else
 				ppc_cmp (code, 0, 0, ins->sreg1, ins->sreg2);
 			break;
 		case OP_COMPARE_IMM:
-			if (ins->next && compare_opcode_is_unsigned (ins->next->opcode)) {
+			next = mono_inst_list_next(&ins->node, &bb->ins_list);
+			if (next && compare_opcode_is_unsigned (next->opcode)) {
 				if (ppc_is_uimm16 (ins->inst_imm)) {
 					ppc_cmpli (code, 0, 0, ins->sreg1, (ins->inst_imm & 0xffff));
 				} else {
@@ -2810,9 +2766,6 @@ mono_arch_output_basic_block (MonoCompil
 			ins->inst_c0 = code - cfg->native_code;
 			break;
 		case OP_BR:
-			//g_print ("target: %p, next: %p, curr: %p, last: %p\n", ins->inst_target_bb, bb->next_bb, ins, bb->last_ins);
-			//if ((ins->inst_target_bb == bb->next_bb) && ins == bb->last_ins)
-			//break;
 			if (ins->flags & MONO_INST_BRLABEL) {
 				/*if (ins->inst_i0->inst_c0) {
 					ppc_b (code, 0);
@@ -3111,10 +3064,7 @@ mono_arch_output_basic_block (MonoCompil
 	       
 		cpos += max_len;
 
-		last_ins = ins;
 		last_offset = offset;
-		
-		ins = ins->next;
 	}
 
 	cfg->code_len = code - cfg->native_code;
@@ -3291,16 +3241,14 @@ mono_arch_emit_prolog (MonoCompile *cfg)
 	 */
 	max_offset = 0;
 	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-		MonoInst *ins = bb->code;
+		MonoInst *ins;
 		bb->max_offset = max_offset;
 
 		if (cfg->prof_options & MONO_PROFILE_COVERAGE)
 			max_offset += 6; 
 
-		while (ins) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node)
 			max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
-			ins = ins->next;
-		}
 	}
 
 	/* load arguments allocated to register from the stack */
Index: mono/mini/mini-alpha.c
===================================================================
--- mono/mini/mini-alpha.c	(revision 89301)
+++ mono/mini/mini-alpha.c	(working copy)
@@ -28,10 +28,10 @@
 
 #define ALPHA_PRINT if (mini_alpha_verbose_level)
 
-#define NEW_INS(cfg,dest,op) do {       \
+#define NEW_INS(cfg,ins,dest,op) do {					\
    (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
    (dest)->opcode = (op);  \
-   insert_after_ins (bb, last_ins, (dest)); \
+   MONO_INST_LIST_ADD_TAIL(&(dest)->node, &(ins)->node);
 } while (0)
 
 #define NEW_ICONST(cfg,dest,val) do {					\
@@ -295,22 +295,6 @@ add_outarg_reg (MonoCompile *cfg, MonoCa
     }
 }
 
-static void
-insert_after_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *to_insert)
-{
-   if (ins == NULL)
-     {
-       ins = bb->code;
-       bb->code = to_insert;
-       to_insert->next = ins;
-     }
-   else
-     {
-       to_insert->next = ins->next;
-       ins->next = to_insert;
-     }
-}
-
 static void add_got_entry(MonoCompile *cfg, AlphaGotType ge_type,
 			  AlphaGotData ge_data,
 			  int ip, MonoJumpInfoType type, gconstpointer target)
@@ -442,13 +426,13 @@ mono_arch_free_jit_tls_data (MonoJitTlsD
 static void
   peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-  MonoInst *ins, *last_ins = NULL;
-  ins = bb->code;
+  MonoInst *ins, *n;
    
   CFG_DEBUG(3) g_print ("ALPHA: PEEPHOLE pass\n");
 
-  while (ins) 
-    {	
+  MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
+      MonoInst *last_ins = mono_inst_list_prev(&ins->node,
+					       &bb->ins_list);
       switch (ins->opcode) 
 	{	 
 	case OP_MOVE:
@@ -462,10 +446,7 @@ static void
 	  if (ins->dreg == ins->sreg1 &&
 	      ins->dreg != alpha_at) 
 	    {
-	      if (last_ins)
-		last_ins->next = ins->next;
-	      
-	      ins = ins->next;
+	      MONO_DEL_INS(ins);
 	      continue;
 	    }
 	  
@@ -480,9 +461,7 @@ static void
 	      last_ins->dreg != alpha_at &&
 	      ins->dreg == last_ins->sreg1) 
 	    {
-	      last_ins->next = ins->next;
-	      
-	      ins = ins->next;
+	      MONO_DEL_INS(ins);
 	      continue;
 	    }
 	  
@@ -498,8 +477,7 @@ static void
 		}
 	      else 
 		{
-		  last_ins->next = ins->next;
-		  ins = ins->next;
+		  MONO_DEL_INS(ins);
 		  continue;
 		}
 	    }
@@ -525,9 +503,7 @@ static void
             {
               if (ins->dreg == last_ins->sreg1)
                 {
-                  last_ins->next = ins->next;
-
-                  ins = ins->next;
+		  MONO_DEL_INS(ins);
                   continue;
                 }
               else
@@ -558,9 +534,7 @@ static void
 	    {
 	      if (ins->dreg == last_ins->sreg1)
 		{
-		  last_ins->next = ins->next;
-
-		  ins = ins->next;
+		  MONO_DEL_INS(ins);
 		  continue;
 		}
 	      else
@@ -589,9 +563,7 @@ static void
 	    {
 	      if (ins->dreg == last_ins->dreg)
 		{
-		  last_ins->next = ins->next;
-		  
-		  ins = ins->next;
+		  MONO_DEL_INS(ins);
 		  continue;
 		}
 	      else
@@ -605,12 +577,7 @@ static void
 	  break;      
 #endif
 	}
-      
-      last_ins = ins;
-      ins = ins->next;
     }
-   
-  bb->last_ins = last_ins;
 }
 
 
@@ -949,10 +916,7 @@ static void cvt_cmp_branch(MonoInst *cur
 static void
   mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {   
-   MonoInst *ins, *temp, *last_ins = NULL;
-   MonoInst *next;
-   
-   ins = bb->code;
+   MonoInst *ins, *n, *next, *temp;
    
    if (bb->max_vreg > cfg->rs->next_vreg)
 	 cfg->rs->next_vreg = bb->max_vreg;
@@ -963,8 +927,7 @@ static void
     * cdq.
     */
    
-   while (ins) 
-     {
+   MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
        switch (ins->opcode) 
 	 {	 
 	 case OP_DIV_IMM:
@@ -972,7 +935,7 @@ static void
 	 case OP_IDIV_IMM:
 	 case OP_IREM_IMM:
 	 case OP_MUL_IMM:
-	   NEW_INS (cfg, temp, OP_I8CONST);
+	   NEW_INS (cfg, ins, temp, OP_I8CONST);
 	   temp->inst_c0 = ins->inst_imm;
 	   temp->dreg = mono_regstate_next_int (cfg->rs);
 	   
@@ -1006,7 +969,8 @@ static void
 	     // Instead of compare+b<cond>/fcompare+b<cond>,
 	     // Alpha has compare<cond>+br<cond>/fcompare<cond>+br<cond>
 	     // we need to convert
-	     next = ins->next;
+	     next = mono_inst_list_next(&ins->node, &bb->ins_list);
+	     g_assert(next);
 
 	     cvt_cmp_branch(ins, next);
 	   }
@@ -1015,7 +979,7 @@ static void
 	 case OP_COMPARE_IMM:
 	   if (!alpha_is_imm (ins->inst_imm)) 
 	     {	  
-	       NEW_INS (cfg, temp, OP_I8CONST);
+	       NEW_INS (cfg, ins, temp, OP_I8CONST);
 	       temp->inst_c0 = ins->inst_imm;
 	       temp->dreg = mono_regstate_next_int (cfg->rs);
 	       ins->opcode = OP_COMPARE;
@@ -1025,7 +989,8 @@ static void
 	       continue;
 	     }
 	   
-	   next = ins->next;
+	   next = mono_inst_list_next(&ins->node, &bb->ins_list);
+	   g_assert(next);
 	   
 	   cvt_cmp_branch(ins, next);
 			 
@@ -1034,7 +999,7 @@ static void
 	 case OP_ICOMPARE_IMM:
            if (!alpha_is_imm (ins->inst_imm))
              {
-               NEW_INS (cfg, temp, OP_ICONST);
+	       NEW_INS (cfg, ins, temp, OP_ICONST);
                temp->inst_c0 = ins->inst_imm;
                temp->dreg = mono_regstate_next_int (cfg->rs);
                ins->opcode = OP_ICOMPARE;
@@ -1044,7 +1009,8 @@ static void
                continue;
              }
 
-           next = ins->next;
+	   next = mono_inst_list_next(&ins->node, &bb->ins_list);
+	   g_assert(next);
 
            cvt_cmp_branch(ins, next);
 
@@ -1054,7 +1020,7 @@ static void
 	 case OP_STOREI8_MEMBASE_IMM:
 	   if (ins->inst_imm != 0) 
 	     {	  
-	       NEW_INS (cfg, temp, OP_I8CONST);
+	       NEW_INS (cfg, ins, temp, OP_I8CONST);
 	       temp->inst_c0 = ins->inst_imm;
 	       temp->dreg = mono_regstate_next_int (cfg->rs);
 	       ins->opcode = OP_STOREI8_MEMBASE_REG;
@@ -1066,7 +1032,7 @@ static void
 	   if (ins->inst_imm != 0)
 	     {
 	       MonoInst *temp;
-	       NEW_INS (cfg, temp, OP_ICONST);
+	       NEW_INS (cfg, ins, temp, OP_ICONST);
 	       temp->inst_c0 = ins->inst_imm;
 	       temp->dreg = mono_regstate_next_int (cfg->rs);
 	       ins->opcode = OP_STOREI4_MEMBASE_REG;
@@ -1078,7 +1044,7 @@ static void
 	   if (ins->inst_imm != 0 || !bwx_supported)
              {
                MonoInst *temp;
-               NEW_INS (cfg, temp, OP_ICONST);
+               NEW_INS (cfg, ins, temp, OP_ICONST);
                temp->inst_c0 = ins->inst_imm;
                temp->dreg = mono_regstate_next_int (cfg->rs);
                ins->opcode = OP_STOREI1_MEMBASE_REG;
@@ -1090,7 +1056,7 @@ static void
            if (ins->inst_imm != 0 || !bwx_supported)
 	   {
 	     MonoInst *temp;
-	     NEW_INS (cfg, temp, OP_ICONST);
+	     NEW_INS (cfg, ins, temp, OP_ICONST);
 	     temp->inst_c0 = ins->inst_imm;
 	     temp->dreg = mono_regstate_next_int (cfg->rs);
 	     ins->opcode = OP_STOREI2_MEMBASE_REG;
@@ -1109,7 +1075,7 @@ static void
 	   if (!alpha_is_imm(ins->inst_imm))
 	     {
 	       MonoInst *temp;
-	       NEW_INS (cfg, temp, OP_ICONST);
+	       NEW_INS (cfg, ins, temp, OP_ICONST);
 	       temp->inst_c0 = ins->inst_imm;
 	       temp->dreg = mono_regstate_next_int (cfg->rs);
 				  
@@ -1152,7 +1118,7 @@ static void
 	   if (!alpha_is_imm(ins->inst_imm))
 	     {
 	       MonoInst *temp;
-	       NEW_INS (cfg, temp, OP_ICONST);
+	       NEW_INS (cfg, ins, temp, OP_ICONST);
 	       temp->inst_c0 = ins->inst_imm;
 	       temp->dreg = mono_regstate_next_int (cfg->rs);
 	       
@@ -1181,7 +1147,7 @@ static void
 	   if (!alpha_is_imm(ins->inst_imm))
 	     {
 	       MonoInst *temp;
-	       NEW_INS(cfg, temp, OP_ICONST);
+	       NEW_INS(cfg, ins, temp, OP_ICONST);
 	       temp->inst_c0 = ins->inst_imm;
 	       temp->dreg = mono_regstate_next_int(cfg->rs);
 	       ins->sreg2 = temp->dreg;
@@ -1192,7 +1158,7 @@ static void
            if (!alpha_is_imm(ins->inst_imm))
              {
                MonoInst *temp;
-               NEW_INS(cfg, temp, OP_ICONST);
+               NEW_INS(cfg, ins, temp, OP_ICONST);
                temp->inst_c0 = ins->inst_imm;
                temp->dreg = mono_regstate_next_int(cfg->rs);
                ins->sreg2 = temp->dreg;
@@ -1203,13 +1169,8 @@ static void
 	 default:
 	   break;
 	 }
-		
-       last_ins = ins;
-       ins = ins->next;
      }
    
-   bb->last_ins = last_ins;
-   
    bb->max_vreg = cfg->rs->next_vreg;
 }
 
@@ -1232,7 +1193,7 @@ mono_arch_local_regalloc (MonoCompile *c
 {
   CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_local_regalloc");
    
-  if (!bb->code)
+  if (MONO_INST_LIST_EMPTY(&bb->ins_list))
     return;
    
   mono_arch_lowering_pass (cfg, bb);
@@ -2233,7 +2194,6 @@ mono_arch_output_basic_block (MonoCompil
    MonoCallInst *call;
    guint offset;
    unsigned int *code = (unsigned int *)(cfg->native_code + cfg->code_len);
-   MonoInst *last_ins = NULL;
    guint last_offset = 0;
    int max_len, cpos;
    
@@ -2251,9 +2211,7 @@ mono_arch_output_basic_block (MonoCompil
 
    mono_debug_open_block (cfg, bb, offset);
    
-   ins = bb->code;
-   while (ins)
-     {
+   MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
        offset = ((char *)code) - ((char *)cfg->native_code);
 	  
        max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
@@ -3664,9 +3622,6 @@ mono_arch_output_basic_block (MonoCompil
 	   break;
 	   
 	 case OP_BR:
-	   CFG_DEBUG(4) g_print("ALPHA_CHECK: [br] target: %p, next: %p, curr: %p, last: %p [",
-		  ins->inst_target_bb, bb->next_bb, ins, bb->last_ins);
-	   
 	   if (ins->flags & MONO_INST_BRLABEL)
 	     {
 	       if (ins->inst_i0->inst_c0)
@@ -4007,10 +3962,7 @@ mono_arch_output_basic_block (MonoCompil
        
        cpos += max_len;
        
-       last_ins = ins;
        last_offset = offset;
-       
-       ins = ins->next;	  
      }
    
    cfg->code_len = ((char *)code) - ((char *)cfg->native_code);
@@ -4843,10 +4795,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 	   MONO_INST_NEW (cfg, arg, OP_OUTARG);
 	   arg->inst_left = sig_arg;
 	   arg->type = STACK_PTR;
-	   
-	   /* prepend, so they get reversed */
-	   arg->next = call->out_args;
-	   call->out_args = arg;
+	   MONO_INST_LIST_ADD(&arg->node, &call->out_args);
 	 }
 		
        if (is_virtual && i == 0) {
@@ -4861,9 +4810,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 	 arg->cil_code = in->cil_code;
 	 arg->inst_left = in;
 	 arg->type = in->type;
-	 /* prepend, so they get reversed */
-	 arg->next = call->out_args;
-	 call->out_args = arg;
+	 MONO_INST_LIST_ADD(&arg->node, &call->out_args);
 
 	 CFG_DEBUG(3) g_print("ALPHA: Param[%d] - ", i);
 
@@ -4931,10 +4878,10 @@ mono_arch_call_opcode (MonoCompile *cfg,
 
 		     add_outarg_reg (cfg, call, set_reg, arg_storage,
 				     dest_reg, load);
-		     if (set_reg != call->out_args)
+		     if (&set_reg->node != call->out_args.next)
 		       {
-			 set_reg->next = call->out_args;
-			 call->out_args = set_reg;
+			 MONO_INST_LIST_ADD(&set_reg->node,
+					    &call->out_args);
 		     }
 		   }
 
@@ -4968,10 +4915,10 @@ mono_arch_call_opcode (MonoCompile *cfg,
 		     //outarg->inst_imm = 16 + ainfo->offset + (slot - 8) * 8;
 		     outarg->dreg = ainfo->offset + (slot - 22) * 8;
 
-		     if (outarg != call->out_args)
+		     if (&outarg->node != call->out_args.next)
 		       {
-			 outarg->next = call->out_args;
-			 call->out_args = outarg;
+			 MONO_INST_LIST_ADD(&outarg->node,
+					    &call->out_args);
 		       }
 		   }
 		
@@ -4982,10 +4929,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 		 arg->inst_left = vtaddr;
 		 arg->inst_right = in;
 		 arg->type = in->type;
-
-		 /* prepend, so they get reversed */
-		 arg->next = call->out_args;
-		 call->out_args = arg;
+		 MONO_INST_LIST_ADD(&arg->node, &call->out_args);
 	       }
 	     else
 	       {
@@ -5065,9 +5009,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 	 zero_inst->inst_p0 = 0;
 	 arg->inst_left = zero_inst;
 	 arg->type = STACK_PTR;
-	 /* prepend, so they get reversed */
-	 arg->next = call->out_args;
-	 call->out_args = arg;
+	 MONO_INST_LIST_ADD(&arg->node, &call->out_args);
        }
        else
 	 /* if the function returns a struct, the called method a
Index: mono/mini/mini-s390.c
===================================================================
--- mono/mini/mini-s390.c	(revision 89301)
+++ mono/mini/mini-s390.c	(working copy)
@@ -1867,9 +1867,7 @@ mono_arch_call_opcode (MonoCompile *cfg,
 			arg->ins.cil_code   = in->cil_code;
 			arg->ins.inst_left  = in;
 			arg->ins.type       = in->type;
-			/* prepend, we'll need to reverse them later */
-			arg->ins.next       = call->out_args;
-			call->out_args      = (MonoInst *) arg;
+			MONO_INST_LIST_ADD_TAIL(&arg->ins.node, &call->out_args);
 			arg->ins.inst_right = (MonoInst *) call;
 			if (ainfo->regtype == RegTypeGeneral) {
 				arg->ins.backend.reg3   = ainfo->reg;
@@ -1932,20 +1930,6 @@ mono_arch_call_opcode (MonoCompile *cfg,
 		emit_sig_cookie (cfg, call, cinfo, ainfo->size);
 	}
 
-	/*
-	 * Reverse the call->out_args list.
-	 */
-	{
-		MonoInst *prev = NULL, *list = call->out_args, *next;
-		while (list) {
-			next = list->next;
-			list->next = prev;
-			prev = list;
-			list = next;
-		}
-		call->out_args = prev;
-	}
-
 	g_free (cinfo);
 	return call;
 }
@@ -1993,8 +1977,7 @@ emit_sig_cookie (MonoCompile *cfg, MonoC
 	arg->ins.inst_right  = (MonoInst *) call;
 	arg->size            = argSize;
 	arg->offset          = cinfo->sigCookie.offset;
-	arg->ins.next        = call->out_args;
-	call->out_args       = (MonoInst *) arg;
+	MONO_INST_LIST_ADD_TAIL(&arg->ins.node, &call->out_args);
 }
 
 /*========================= End of Function ========================*/
@@ -2208,11 +2191,11 @@ handle_enum:
 static void
 peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins, *last_ins = NULL;
-	ins = bb->code;
-
-	while (ins) {
+	MonoInst *ins, *n;
 
+	MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(ins, n, &bb->ins_list, node) {
+		MonoInst *last_ins = mono_inst_list_prev(&ins->node,
+							 &bb->ins_list);
 		switch (ins->opcode) {
 		case OP_MUL_IMM: 
 			/* remove unnecessary multiplication with 1 */
@@ -2220,8 +2203,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 				if (ins->dreg != ins->sreg1) {
 					ins->opcode = OP_MOVE;
 				} else {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				}
 			}
@@ -2237,8 +2219,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			    ins->inst_basereg == last_ins->inst_destbasereg &&
 			    ins->inst_offset == last_ins->inst_offset) {
 				if (ins->dreg == last_ins->sreg1) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					ins->opcode = OP_MOVE;
@@ -2260,8 +2241,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			      ins->inst_offset == last_ins->inst_offset) {
 
 				if (ins->dreg == last_ins->dreg) {
-					last_ins->next = ins->next;				
-					ins = ins->next;				
+					MONO_DEL_INS(ins);
 					continue;
 				} else {
 					ins->opcode = OP_MOVE;
@@ -2314,9 +2294,7 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			 * OP_MOVE reg, reg 
 			 */
 			if (ins->dreg == ins->sreg1) {
-				if (last_ins)
-					last_ins->next = ins->next;				
-				ins = ins->next;
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			/* 
@@ -2326,16 +2304,12 @@ peephole_pass (MonoCompile *cfg, MonoBas
 			if (last_ins && last_ins->opcode == OP_MOVE &&
 			    ins->sreg1 == last_ins->dreg &&
 			    ins->dreg == last_ins->sreg1) {
-				last_ins->next = ins->next;				
-				ins = ins->next;				
+				MONO_DEL_INS(ins);
 				continue;
 			}
 			break;
 		}
-		last_ins = ins;
-		ins = ins->next;
 	}
-	bb->last_ins = last_ins;
 }
 
 /*========================= End of Function ========================*/
@@ -2431,11 +2405,10 @@ emit_float_to_int (MonoCompile *cfg, guc
 void
 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-	MonoInst *ins;
+	MonoInst *ins, *next;
 	MonoCallInst *call;
 	guint offset;
 	guint8 *code = cfg->native_code + cfg->code_len;
-	MonoInst *last_ins = NULL;
 	guint last_offset = 0;
 	int max_len, cpos, src2;
 
@@ -2460,8 +2433,7 @@ mono_arch_output_basic_block (MonoCompil
 		//x86_inc_mem (code, &cov->data [bb->dfn].count); 
 	}
 
-	ins = bb->code;
-	while (ins) {
+	MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node) {
 		offset = code - cfg->native_code;
 
 		max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
@@ -2697,28 +2669,32 @@ mono_arch_output_basic_block (MonoCompil
 		}
 			break;
 		case OP_COMPARE: {
-			if ((ins->next) && 
-			    (((ins->next->opcode >= CEE_BNE_UN) &&
-			      (ins->next->opcode <= CEE_BLT_UN)) || 
-			     ((ins->next->opcode >= OP_COND_EXC_NE_UN) &&
-			      (ins->next->opcode <= OP_COND_EXC_LT_UN)) ||
-			     ((ins->next->opcode == OP_CLT_UN) ||
-			      (ins->next->opcode == OP_CGT_UN))))
+			next = mono_inst_list_next(&ins->node,
+						   &bb->ins_list);
+			if ((next) && 
+			    (((next->opcode >= CEE_BNE_UN) &&
+			      (next->opcode <= CEE_BLT_UN)) || 
+			     ((next->opcode >= OP_COND_EXC_NE_UN) &&
+			      (next->opcode <= OP_COND_EXC_LT_UN)) ||
+			     ((next->opcode == OP_CLT_UN) ||
+			      (next->opcode == OP_CGT_UN))))
 				s390_clr  (code, ins->sreg1, ins->sreg2);
 			else
 				s390_cr   (code, ins->sreg1, ins->sreg2);
 		}
 			break;
 		case OP_COMPARE_IMM: {
+			next = mono_inst_list_next(&ins->node,
+						   &bb->ins_list);
 			if (s390_is_imm16 (ins->inst_imm)) {
 				s390_lhi  (code, s390_r0, ins->inst_imm);
-				if ((ins->next) && 
-				    (((ins->next->opcode >= CEE_BNE_UN) &&
-				      (ins->next->opcode <= CEE_BLT_UN)) || 
-				     ((ins->next->opcode >= OP_COND_EXC_NE_UN) &&
-				      (ins->next->opcode <= OP_COND_EXC_LT_UN)) ||
-				     ((ins->next->opcode == OP_CLT_UN) ||
-				      (ins->next->opcode == OP_CGT_UN))))
+				if ((next) && 
+				    (((next->opcode >= CEE_BNE_UN) &&
+				      (next->opcode <= CEE_BLT_UN)) || 
+				     ((next->opcode >= OP_COND_EXC_NE_UN) &&
+				      (next->opcode <= OP_COND_EXC_LT_UN)) ||
+				     ((next->opcode == OP_CLT_UN) ||
+				      (next->opcode == OP_CGT_UN))))
 					s390_clr  (code, ins->sreg1, s390_r0);
 				else
 					s390_cr   (code, ins->sreg1, s390_r0);
@@ -2727,13 +2703,13 @@ mono_arch_output_basic_block (MonoCompil
 				s390_basr (code, s390_r13, 0);
 				s390_j    (code, 4);
 				s390_word (code, ins->inst_imm);
-				if ((ins->next) && 
-				    (((ins->next->opcode >= CEE_BNE_UN) &&
-				      (ins->next->opcode <= CEE_BLT_UN)) || 
-				     ((ins->next->opcode >= OP_COND_EXC_NE_UN) &&
-				      (ins->next->opcode <= OP_COND_EXC_LT_UN)) ||
-				     ((ins->next->opcode == OP_CLT_UN) ||
-				      (ins->next->opcode == OP_CGT_UN))))
+				if ((next) && 
+				    (((next->opcode >= CEE_BNE_UN) &&
+				      (next->opcode <= CEE_BLT_UN)) || 
+				     ((next->opcode >= OP_COND_EXC_NE_UN) &&
+				      (next->opcode <= OP_COND_EXC_LT_UN)) ||
+				     ((next->opcode == OP_CLT_UN) ||
+				      (next->opcode == OP_CGT_UN))))
 					s390_cl   (code, ins->sreg1, 0, s390_r13, 4);
 				else
 					s390_c 	  (code, ins->sreg1, 0, s390_r13, 4);
@@ -2764,8 +2740,10 @@ mono_arch_output_basic_block (MonoCompil
 			if (ins->dreg != ins->sreg1) {
 				s390_lr	  (code, ins->dreg, ins->sreg1);
 			}
-			if ((ins->next) &&
-			    (ins->next->opcode == OP_ADC_IMM)) {
+			next = mono_inst_list_next(&ins->node,
+						   &bb->ins_list);
+			if ((next) &&
+			    (next->opcode == OP_ADC_IMM)) {
 				s390_basr (code, s390_r13, 0);
 				s390_j	  (code, 4);
 				s390_word (code, ins->inst_imm);
@@ -2783,8 +2761,10 @@ mono_arch_output_basic_block (MonoCompil
 		}
 			break;
 		case OP_ADDCC_IMM: {
-			if ((ins->next) &&
-			    (ins->next->opcode == OP_ADC_IMM)) {
+			next = mono_inst_list_next(&ins->node,
+						   &bb->ins_list);
+			if ((next) &&
+			    (next->opcode == OP_ADC_IMM)) {
 				s390_basr (code, s390_r13, 0);
 				s390_j	  (code, 4);
 				s390_word (code, ins->inst_imm);
@@ -3362,9 +3342,11 @@ mono_arch_output_basic_block (MonoCompil
 			break;
 		case OP_FCONV_TO_R4: {
 			NOT_IMPLEMENTED("OP_FCONV_TO_R4");
-			if ((ins->next) &&
-			     (ins->next->opcode != OP_FMOVE) &&
-			     (ins->next->opcode != OP_STORER4_MEMBASE_REG))
+			next = mono_inst_list_next(&ins->node,
+						   &bb->ins_list);
+			if ((next) &&
+			     (next->opcode != OP_FMOVE) &&
+			     (next->opcode != OP_STORER4_MEMBASE_REG))
 				s390_ledbr (code, ins->dreg, ins->sreg1);
 		}
 			break;
@@ -4052,10 +4034,7 @@ mono_arch_output_basic_block (MonoCompil
 	       
 		cpos += max_len;
 
-		last_ins = ins;
 		last_offset = offset;
-		
-		ins = ins->next;
 	}
 
 	cfg->code_len = code - cfg->native_code;
@@ -4332,16 +4311,14 @@ mono_arch_emit_prolog (MonoCompile *cfg)
 	 */
 	max_offset = 0;
 	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-		MonoInst *ins = bb->code;
+		MonoInst *ins;
 		bb->max_offset = max_offset;
 
 		if (cfg->prof_options & MONO_PROFILE_COVERAGE)
 			max_offset += 6; 
 
-		while (ins) {
+		MONO_INST_LIST_FOR_EACH_ENTRY(ins, &bb->ins_list, node)
 			max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
-			ins = ins->next;
-		}
 	}
 
 	/* load arguments allocated to register from the stack */



More information about the Mono-devel-list mailing list