[m-dev.] for review: --use-local-vars

Zoltan Somogyi zs at cs.mu.OZ.AU
Thu Mar 8 17:58:47 AEDT 2001


For review by anyone. The new optimization is not yet enabled at any
optimization level, because finding the right level to enable it at requires
more performance testing, but I can say that --no-lazy-code --use-local-vars
gets identical performance to --lazy-code --optimize-value-number on eight of
the ten benchmarks in the tests directory.

Zoltan.

Add a new optimization, --use-local-vars, to the LLDS backend. This
optimization is intended to replace references to fake registers and stack
slots with references to temporary variables in C code, since accessing these
should be cheaper.

With this optimization and one for delaying construction unifications,
the eager code generator should generate code at least good as that produced by
the old value numbering pass. This should make it possible to get rid of value
numbering, which is much harder to maintain.

compiler/use_local_vars.m:
	New file containing the optimization.

compiler/exprn_aux.m:
	Add new utility predicates for use by use_local_vars.

	If --debug-opt is specified, do not dump instruction sequences to
	standard output. Instead, put them in separate files, where they can be
	compared more easily.

compiler/options.m:
	Add the --use-local-vars option to control whether the use_local_vars
	pass gets run.

compiler/llds.m:
	Add liveness information to the c_code and pragma_foreign_code LLDS 
	instructions, in order to allow use_local_vars to work in the presence
	of automatically-generated C code (e.g. by debugging).

compiler/livemap.m:
	Use the new liveness information to generate useful livemap information
	even in the presence of automatically generated C code.

compiler/code_gen.m:
compiler/code_info.m:
compiler/dupelim.m:
compiler/frameopt.m:
compiler/llds_common.m:
compiler/llds_out.m:
compiler/middle_rec.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/pragma_c_gen.m:
compiler/trace.m:
compiler/vn_block.m:
compiler/vn_cost.m:
compiler/vn_filter.m:
compiler/vn_verify.m:
	Provide and/or ignore this additional liveness information.

compiler/wrap_block.m:
	The post_value_number pass wraps LLDS instruction sequences
	using temporaries in a block instruction which actually declares
	those temporaries. It used to be used only by value numbering;
	it is now also used by use_local_vars. It has therefore been renamed
	and put in its own file.

compiler/optimize.m:
	Invoke use_local_vars if required, and call wrap_blocks instead of
	post_value_number.

compiler/value_number.m:
	Since the value numbering pass still cannot handle automatically
	generated C code, check for it explicitly now that livemap carries out
	only a weaker check.

compiler/basic_block.m:
	Add a module qualification.

library/set.m:
library/set_bbbtree.m:
library/set_ordlist.m:
library/set_unordlist.m:
	Add a new predicate, union_list, to each implementation of sets,
	for use by some of the new code above.

tests/general/array_test.m:
	Print out the result of each operation as soon as it is done, so that
	if you get a seg fault, you know which operations have completed and
	which haven't.

cvs diff: Diffing .
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/basic_block.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/basic_block.m,v
retrieving revision 1.11
diff -u -b -r1.11 basic_block.m
--- compiler/basic_block.m	2000/10/31 02:15:41	1.11
+++ compiler/basic_block.m	2001/02/28 15:09:55
@@ -91,7 +91,7 @@
 			BlockMap0, BlockMap1, ProcLabel, C1, C),
 		( list__last(BlockInstrs, LastInstr) ->
 			LastInstr = LastUinstr - _,
-			possible_targets(LastUinstr, SideLabels),
+			opt_util__possible_targets(LastUinstr, SideLabels),
 			opt_util__can_instr_fall_through(LastUinstr,
 				CanFallThrough),
 			( CanFallThrough = yes ->
Index: compiler/code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_gen.m,v
retrieving revision 1.94
diff -u -b -r1.94 code_gen.m
--- compiler/code_gen.m	2001/02/19 02:05:57	1.94
+++ compiler/code_gen.m	2001/02/28 15:17:25
@@ -745,14 +745,16 @@
 				Fields, FieldsContext) },
 			{ string__format("#define\tMR_ORDINARY_SLOTS\t%d\n",
 				[i(TotalSlots)], DefineStr) },
-			{ DefineComponents = [pragma_c_raw_code(DefineStr)] },
+			{ DefineComponents = [pragma_c_raw_code(DefineStr,
+				live_lvals_info(set__init))] },
 			{ NondetFrameInfo = ordinary_frame(PushMsg, TotalSlots,
 				yes(Struct)) },
 			{ AllocCode = node([
 				mkframe(NondetFrameInfo, OutsideResumeAddress)
 					- "Allocate stack frame",
 				pragma_c([], DefineComponents,
-					will_not_call_mercury, no, no, no, no)
+					will_not_call_mercury, no, no, no, no,
+					no)
 					- ""
 			]) },
 			{ NondetPragma = yes }
@@ -836,10 +838,11 @@
 	{ FrameInfo = frame(TotalSlots, MaybeSuccipSlot, NondetPragma) },
 	( { NondetPragma = yes } ->
 		{ UndefStr = "#undef\tMR_ORDINARY_SLOTS\n" },
-		{ UndefComponents = [pragma_c_raw_code(UndefStr)] },
+		{ UndefComponents = [pragma_c_raw_code(UndefStr,
+			live_lvals_info(set__init))] },
 		{ UndefCode = node([
 			pragma_c([], UndefComponents,
-				will_not_call_mercury, no, no, no, no)
+				will_not_call_mercury, no, no, no, no, no)
 				- ""
 		]) },
 		{ RestoreDeallocCode = empty },	% always empty for nondet code
@@ -1284,12 +1287,12 @@
 		pragma_c(
 		[],
 		[
-		pragma_c_raw_code("\t{\n"),
-		pragma_c_raw_code(CallStruct),
-		pragma_c_raw_code(BytecodeCall),
-		pragma_c_raw_code("\t}\n")
+		pragma_c_raw_code("\t{\n", live_lvals_info(set__init)),
+		pragma_c_raw_code(CallStruct, live_lvals_info(set__init)),
+		pragma_c_raw_code(BytecodeCall, no_live_lvals_info),
+		pragma_c_raw_code("\t}\n", live_lvals_info(set__init))
 		],
-		may_call_mercury, no, no, no, no
+		may_call_mercury, no, no, no, no, no
 		) - "Entry stub"
 	].
 
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.263
diff -u -b -r1.263 code_info.m
--- compiler/code_info.m	2001/03/06 05:51:21	1.263
+++ compiler/code_info.m	2001/03/06 06:08:40
@@ -1830,15 +1830,18 @@
 			% inside MR_commit_{mark,cut}.
 			Components = [
 				pragma_c_raw_code(
-					"\tMR_save_transient_registers();\n"),
+					"\tMR_save_transient_registers();\n",
+					live_lvals_info(set__init)),
 				pragma_c_raw_code(
-					"\tMR_commit_mark();\n"),
+					"\tMR_commit_mark();\n",
+					live_lvals_info(set__init)),
 				pragma_c_raw_code(
-					"\tMR_restore_transient_registers();\n")
+					"\tMR_restore_transient_registers();\n",
+					live_lvals_info(set__init))
 			],
 			MarkCode = node([
 				pragma_c([], Components, will_not_call_mercury,
-					no, no, no, no) - ""
+					no, no, no, no, no) - ""
 			])
 		;
 			UseMinimalModel = no,
@@ -1912,11 +1915,12 @@
 			UseMinimalModel = yes,
 			% See the comment in prepare_for_semi_commit above.
 			Components = [
-				pragma_c_raw_code("\tMR_commit_cut();\n")
+				pragma_c_raw_code("\tMR_commit_cut();\n",
+					live_lvals_info(set__init))
 			],
 			CutCode = node([
 				pragma_c([], Components, will_not_call_mercury,
-					no, no, no, no)
+					no, no, no, no, no)
 					- "commit for temp frame hijack"
 			])
 		;
Index: compiler/dupelim.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dupelim.m,v
retrieving revision 1.49
diff -u -b -r1.49 dupelim.m
--- compiler/dupelim.m	2000/10/13 04:04:24	1.49
+++ compiler/dupelim.m	2001/02/28 15:18:44
@@ -119,7 +119,8 @@
 		[Instr::in, FoldFixed0::in, FoldFixed::out] is det, (
 		(
 			Instr = pragma_c(_, _, _,
-				MaybeFixedLabel, MaybeLayoutLabel, _, _) - _
+				MaybeFixedLabel, MaybeLayoutLabel,
+				MaybeOnlyLayoutLabel, _, _) - _
 		->
 			( MaybeFixedLabel = yes(FixedLabel) ->
 				set__insert(FoldFixed0, FixedLabel, FoldFixed1)
@@ -127,9 +128,16 @@
 				FoldFixed1 = FoldFixed0
 			),
 			( MaybeLayoutLabel = yes(LayoutLabel) ->
-				set__insert(FoldFixed1, LayoutLabel, FoldFixed)
+				set__insert(FoldFixed1, LayoutLabel,
+					FoldFixed2)
 			;
-				FoldFixed = FoldFixed1
+				FoldFixed2 = FoldFixed1
+			),
+			( MaybeOnlyLayoutLabel = yes(OnlyLayoutLabel) ->
+				set__insert(FoldFixed2, OnlyLayoutLabel,
+					FoldFixed)
+			;
+				FoldFixed = FoldFixed2
 			)
 		;
 			FoldFixed = FoldFixed0
@@ -321,7 +329,7 @@
 		Instr1 = computed_goto(_, _),
 		Instr = Instr1
 	;
-		Instr1 = c_code(_),
+		Instr1 = c_code(_, _),
 		Instr = Instr1
 	;
 		Instr1 = if_val(Rval1, CodeAddr),
@@ -388,7 +396,7 @@
 		standardize_lval(Lval1, Lval),
 		Instr = join_and_continue(Lval, N)
 	;
-		Instr1 = pragma_c(_, _, _, _, _, _, _),
+		Instr1 = pragma_c(_, _, _, _, _, _, _, _),
 		Instr = Instr1
 	).
 
@@ -600,7 +608,7 @@
 		Instr2 = Instr1,
 		Instr = Instr1
 	;
-		Instr1 = c_code(_),
+		Instr1 = c_code(_, _),
 		Instr2 = Instr1,
 		Instr = Instr1
 	;
@@ -666,7 +674,7 @@
 		Instr2 = Instr1,
 		Instr = Instr1
 	;
-		Instr1 = pragma_c(_, _, _, _, _, _, _),
+		Instr1 = pragma_c(_, _, _, _, _, _, _, _),
 		Instr2 = Instr1,
 		Instr = Instr1
 	).
Index: compiler/exprn_aux.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/exprn_aux.m,v
retrieving revision 1.40
diff -u -b -r1.40 exprn_aux.m
--- compiler/exprn_aux.m	2000/09/04 22:33:35	1.40
+++ compiler/exprn_aux.m	2001/03/06 14:33:26
@@ -1,5 +1,5 @@
 %-----------------------------------------------------------------------------%
-% Copyright (C) 1995-2000 The University of Melbourne.
+% Copyright (C) 1995-2001 The University of Melbourne.
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
 %------------------------------------------------------------------------------%
@@ -19,23 +19,20 @@
 			bool	% --unboxed-float
 		).
 
-:- pred exprn_aux__init_exprn_opts(option_table, exprn_opts).
-:- mode exprn_aux__init_exprn_opts(in, out) is det.
+:- pred exprn_aux__init_exprn_opts(option_table::in, exprn_opts::out) is det.
 
 	% Determine whether an rval_const can be used as the initializer
 	% of a C static constant.
-:- pred exprn_aux__const_is_constant(rval_const, exprn_opts, bool).
-:- mode exprn_aux__const_is_constant(in, in, out) is det.
+:- pred exprn_aux__const_is_constant(rval_const::in, exprn_opts::in, bool::out)
+	is det.
 
 	% exprn_aux__imported_is_constant(NonLocalGotos, AsmLabels, IsConst)
 	% figures out whether an imported label address is a constant.
 	% This depends on how we treat labels.
 
-:- pred exprn_aux__imported_is_constant(bool, bool, bool).
-:- mode exprn_aux__imported_is_constant(in, in, out) is det.
+:- pred exprn_aux__imported_is_constant(bool::in, bool::in, bool::out) is det.
 
-:- pred exprn_aux__rval_contains_lval(rval, lval).
-:- mode exprn_aux__rval_contains_lval(in, in) is semidet.
+:- pred exprn_aux__rval_contains_lval(rval::in, lval::in) is semidet.
 
 :- pred exprn_aux__rval_contains_rval(rval, rval).
 :- mode exprn_aux__rval_contains_rval(in, in) is semidet.
@@ -45,52 +42,48 @@
 :- mode exprn_aux__args_contain_rval(in, in) is semidet.
 :- mode exprn_aux__args_contain_rval(in, out) is nondet.
 
-:- pred exprn_aux__substitute_lval_in_lval(lval, lval, lval, lval).
-:- mode exprn_aux__substitute_lval_in_lval(in, in, in, out) is det.
+:- pred exprn_aux__substitute_lval_in_instr(lval::in, lval::in,
+	instruction::in, instruction::out, int::in, int::out) is det.
 
-:- pred exprn_aux__substitute_lval_in_rval(lval, lval, rval, rval).
-:- mode exprn_aux__substitute_lval_in_rval(in, in, in, out) is det.
+:- pred exprn_aux__substitute_lval_in_lval(lval::in, lval::in,
+	lval::in, lval::out) is det.
 
-:- pred exprn_aux__substitute_rval_in_rval(rval, rval, rval, rval).
-:- mode exprn_aux__substitute_rval_in_rval(in, in, in, out) is det.
+:- pred exprn_aux__substitute_lval_in_rval(lval::in, lval::in,
+	rval::in, rval::out) is det.
 
-:- pred exprn_aux__substitute_vars_in_rval(assoc_list(prog_var, rval),
-		rval, rval).
-:- mode exprn_aux__substitute_vars_in_rval(in, in, out) is det.
+:- pred exprn_aux__substitute_rval_in_rval(rval::in, rval::in,
+	rval::in, rval::out) is det.
 
-:- pred exprn_aux__substitute_rvals_in_rval(assoc_list(rval, rval), rval, rval).
-:- mode exprn_aux__substitute_rvals_in_rval(in, in, out) is det.
+:- pred exprn_aux__substitute_vars_in_rval(assoc_list(prog_var, rval)::in,
+	rval::in, rval::out) is det.
 
-:- pred exprn_aux__vars_in_lval(lval, list(prog_var)).
-:- mode exprn_aux__vars_in_lval(in, out) is det.
+:- pred exprn_aux__substitute_rvals_in_rval(assoc_list(rval, rval)::in,
+	rval::in, rval::out) is det.
 
-:- pred exprn_aux__vars_in_rval(rval, list(prog_var)).
-:- mode exprn_aux__vars_in_rval(in, out) is det.
+:- pred exprn_aux__vars_in_lval(lval::in, list(prog_var)::out) is det.
 
-:- pred exprn_aux__simplify_rval(rval, rval).
-:- mode exprn_aux__simplify_rval(in, out) is det.
+:- pred exprn_aux__vars_in_rval(rval::in, list(prog_var)::out) is det.
 
+:- pred exprn_aux__simplify_rval(rval::in, rval::out) is det.
+
 	% the following predicates take an lval/rval (list)
 	% and return a list of the code and data addresses that it references.
+
+:- pred exprn_aux__rval_list_addrs(list(rval)::in,
+	list(code_addr)::out, list(data_addr)::out) is det.
+
+:- pred exprn_aux__lval_list_addrs(list(lval)::in,
+	list(code_addr)::out, list(data_addr)::out) is det.
+
+:- pred exprn_aux__rval_addrs(rval::in,
+	list(code_addr)::out, list(data_addr)::out) is det.
 
-:- pred exprn_aux__rval_list_addrs(list(rval),
-	list(code_addr), list(data_addr)).
-:- mode exprn_aux__rval_list_addrs(in, out, out) is det.
-
-:- pred exprn_aux__lval_list_addrs(list(lval),
-	list(code_addr), list(data_addr)).
-:- mode exprn_aux__lval_list_addrs(in, out, out) is det.
-
-:- pred exprn_aux__rval_addrs(rval, list(code_addr), list(data_addr)).
-:- mode exprn_aux__rval_addrs(in, out, out) is det.
-
-:- pred exprn_aux__lval_addrs(lval, list(code_addr), list(data_addr)).
-:- mode exprn_aux__lval_addrs(in, out, out) is det.
-
-:- pred exprn_aux__maybe_rval_list_addrs(list(maybe(rval)),
-	list(code_addr), list(data_addr)).
-:- mode exprn_aux__maybe_rval_list_addrs(in, out, out) is det.
+:- pred exprn_aux__lval_addrs(lval::in,
+	list(code_addr)::out, list(data_addr)::out) is det.
 
+:- pred exprn_aux__maybe_rval_list_addrs(list(maybe(rval))::in,
+	list(code_addr)::out, list(data_addr)::out) is det.
+
 :- func exprn_aux__var_lval_to_rval(prog_var, lval) = rval.
 
 :- func exprn_aux__lval_to_rval(lval) = rval.
@@ -99,7 +92,9 @@
 %------------------------------------------------------------------------------%
 
 :- implementation.
-:- import_module int, require, getopt, options.
+
+:- import_module options.
+:- import_module int, set, require, getopt.
 
 exprn_aux__init_exprn_opts(Options, ExprnOpts) :-
 	getopt__lookup_bool_option(Options, gcc_non_local_gotos, NLG),
@@ -143,8 +138,8 @@
 exprn_aux__const_is_constant(label_entry(Label), ExprnOpts, IsConst) :-
 	exprn_aux__addr_is_constant(label(Label), ExprnOpts, IsConst).
 
-:- pred exprn_aux__addr_is_constant(code_addr, exprn_opts, bool).
-:- mode exprn_aux__addr_is_constant(in, in, out) is det.
+:- pred exprn_aux__addr_is_constant(code_addr::in, exprn_opts::in, bool::out)
+	is det.
 
 exprn_aux__addr_is_constant(label(Label), ExprnOpts, IsConst) :-
 	ExprnOpts = nlg_asm_sgt_ubf(NonLocalGotos, AsmLabels, _SGT, _UBF),
@@ -170,8 +165,8 @@
 exprn_aux__addr_is_constant(do_aditi_bulk_modify, _, no).
 exprn_aux__addr_is_constant(do_not_reached, _, no).
 
-:- pred exprn_aux__label_is_constant(label, bool, bool, bool).
-:- mode exprn_aux__label_is_constant(in, in, in, out) is det.
+:- pred exprn_aux__label_is_constant(label::in, bool::in, bool::in, bool::out)
+	is det.
 
 exprn_aux__label_is_constant(exported(_), NonLocalGotos, AsmLabels, IsConst) :-
 	exprn_aux__imported_is_constant(NonLocalGotos, AsmLabels, IsConst).
@@ -218,8 +213,7 @@
 		exprn_aux__rval_contains_lval(Rval1, Lval)
 	).
 
-:- pred exprn_aux__lval_contains_lval(lval, lval).
-:- mode exprn_aux__lval_contains_lval(in, in) is semidet.
+:- pred exprn_aux__lval_contains_lval(lval::in, lval::in) is semidet.
 
 exprn_aux__lval_contains_lval(Lval0, Lval) :-
 	(
@@ -242,8 +236,8 @@
 		fail
 	).
 
-:- pred exprn_aux__args_contain_lval(list(maybe(rval)), lval).
-:- mode exprn_aux__args_contain_lval(in, in) is semidet.
+:- pred exprn_aux__args_contain_lval(list(maybe(rval))::in, lval::in)
+	is semidet.
 
 exprn_aux__args_contain_lval([M | Ms], Lval) :-
 	(
@@ -348,16 +342,15 @@
 	exprn_aux__vars_in_rval(Rval, Vars).
 exprn_aux__vars_in_lval(lvar(Var), [Var]).
 
-:- pred exprn_aux__vars_in_mem_ref(mem_ref, list(prog_var)).
-:- mode exprn_aux__vars_in_mem_ref(in, out) is det.
+:- pred exprn_aux__vars_in_mem_ref(mem_ref::in, list(prog_var)::out) is det.
 
 exprn_aux__vars_in_mem_ref(stackvar_ref(_), []).
 exprn_aux__vars_in_mem_ref(framevar_ref(_), []).
 exprn_aux__vars_in_mem_ref(heap_ref(Rval, _, _), Vars) :-
 	exprn_aux__vars_in_rval(Rval, Vars).
 
-:- pred exprn_aux__vars_in_args(list(maybe(rval)), list(prog_var)).
-:- mode exprn_aux__vars_in_args(in, out) is det.
+:- pred exprn_aux__vars_in_args(list(maybe(rval))::in, list(prog_var)::out)
+	is det.
 
 exprn_aux__vars_in_args([], []).
 exprn_aux__vars_in_args([M | Ms], Vars) :-
@@ -373,172 +366,428 @@
 
 %------------------------------------------------------------------------------%
 
+:- pred exprn_aux__substitute_lval_in_lval(lval::in, lval::in,
+	lval::in, lval::out, int::in, int::out) is det.
+
+exprn_aux__substitute_lval_in_lval(OldLval, NewLval, Lval0, Lval) :-
+	exprn_aux__substitute_lval_in_lval(OldLval, NewLval, Lval0, Lval,
+		0, _).
+
+:- pred exprn_aux__substitute_lval_in_rval(lval::in, lval::in,
+	rval::in, rval::out, int::in, int::out) is det.
+
 exprn_aux__substitute_lval_in_rval(OldLval, NewLval, Rval0, Rval) :-
+	exprn_aux__substitute_lval_in_rval(OldLval, NewLval, Rval0, Rval,
+		0, _).
+
+exprn_aux__substitute_lval_in_instr(OldLval, NewLval, Instr0, Instr, N0, N) :-
+	Instr0 = Uinstr0 - Comment,
+	exprn_aux__substitute_lval_in_uinstr(OldLval, NewLval,
+		Uinstr0, Uinstr, N0, N),
+	Instr = Uinstr - Comment.
+
+:- pred exprn_aux__substitute_lval_in_uinstr(lval::in, lval::in,
+	instr::in, instr::out, int::in, int::out) is det.
+
+exprn_aux__substitute_lval_in_uinstr(OldLval, NewLval, Uinstr0, Uinstr, N0, N)
+		:-
+	(
+		Uinstr0 = comment(_),
+		Uinstr = Uinstr0,
+		N = N0
+	;
+		Uinstr0 = livevals(LvalSet0),
+		set__to_sorted_list(LvalSet0, Lvals0),
+		list__map_foldl(
+			exprn_aux__substitute_lval_in_lval(OldLval, NewLval),
+			Lvals0, Lvals, N0, N),
+		set__list_to_set(Lvals, LvalSet),
+		Uinstr = livevals(LvalSet)
+	;
+		Uinstr0 = block(TempR, TempF, Instrs0),
+		list__map_foldl(
+			exprn_aux__substitute_lval_in_instr(OldLval, NewLval),
+			Instrs0, Instrs, N0, N),
+		Uinstr = block(TempR, TempF, Instrs)
+	;
+		Uinstr0 = assign(Lval0, Rval0),
+		exprn_aux__substitute_lval_in_lval(OldLval, NewLval,
+			Lval0, Lval, N0, N1),
+		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
+			Rval0, Rval, N1, N),
+		Uinstr = assign(Lval, Rval)
+	;
+		Uinstr0 = call(_, _, _, _, _, _),
+		Uinstr = Uinstr0,
+		N = N0
+	;
+		Uinstr0 = mkframe(_, _),
+		Uinstr = Uinstr0,
+		N = N0
+	;
+		Uinstr0 = label(_),
+		Uinstr = Uinstr0,
+		N = N0
+	;
+		Uinstr0 = goto(_),
+		Uinstr = Uinstr0,
+		N = N0
+	;
+		Uinstr0 = computed_goto(Rval0, Labels),
+		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
+			Rval0, Rval, N0, N),
+		Uinstr = computed_goto(Rval, Labels)
+	;
+		Uinstr0 = c_code(Code, LiveLvals0),
+		exprn_aux__substitute_lval_in_live_lval_info(OldLval, NewLval,
+			LiveLvals0, LiveLvals, N0, N),
+		Uinstr = c_code(Code, LiveLvals)
+	;
+		Uinstr0 = if_val(Rval0, CodeAddr),
+		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
+			Rval0, Rval, N0, N),
+		Uinstr = if_val(Rval, CodeAddr)
+	;
+		Uinstr0 = incr_hp(Lval0, MaybeTag, Rval0, TypeCtor),
+		exprn_aux__substitute_lval_in_lval(OldLval, NewLval,
+			Lval0, Lval, N0, N1),
+		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
+			Rval0, Rval, N1, N),
+		Uinstr = incr_hp(Lval, MaybeTag, Rval, TypeCtor)
+	;
+		Uinstr0 = mark_hp(Lval0),
+		exprn_aux__substitute_lval_in_lval(OldLval, NewLval,
+			Lval0, Lval, N0, N),
+		Uinstr = mark_hp(Lval)
+	;
+		Uinstr0 = restore_hp(Rval0),
+		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
+			Rval0, Rval, N0, N),
+		Uinstr = restore_hp(Rval)
+	;
+		Uinstr0 = free_heap(Rval0),
+		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
+			Rval0, Rval, N0, N),
+		Uinstr = free_heap(Rval)
+	;
+		Uinstr0 = store_ticket(Lval0),
+		exprn_aux__substitute_lval_in_lval(OldLval, NewLval,
+			Lval0, Lval, N0, N),
+		Uinstr = store_ticket(Lval)
+	;
+		Uinstr0 = reset_ticket(Rval0, Reason),
+		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
+			Rval0, Rval, N0, N),
+		Uinstr = reset_ticket(Rval, Reason)
+	;
+		Uinstr0 = prune_ticket,
+		Uinstr = Uinstr0,
+		N = N0
+	;
+		Uinstr0 = discard_ticket,
+		Uinstr = Uinstr0,
+		N = N0
+	;
+		Uinstr0 = mark_ticket_stack(Lval0),
+		exprn_aux__substitute_lval_in_lval(OldLval, NewLval,
+			Lval0, Lval, N0, N),
+		Uinstr = mark_ticket_stack(Lval)
+	;
+		Uinstr0 = prune_tickets_to(Rval0),
+		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
+			Rval0, Rval, N0, N),
+		Uinstr = prune_tickets_to(Rval)
+%	;
+%		% discard_tickets_to(_) is used only in hand-written code
+%		Uinstr0 = discard_tickets_to(Rval0),
+%		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
+%			Rval0, Rval, N0, N),
+%		Uinstr = discard_tickets_to(Rval)
+	;
+		Uinstr0 = incr_sp(_, _),
+		Uinstr = Uinstr0,
+		N = N0
+	;
+		Uinstr0 = decr_sp(_),
+		Uinstr = Uinstr0,
+		N = N0
+	;
+		Uinstr0 = pragma_c(Decls, Components0, MayCallMercury,
+			MaybeLabel1, MaybeLabel2, MaybeLabel3, MaybeLabel4,
+			ReferStackSlot),
+		list__map_foldl(exprn_aux__substitute_lval_in_component(
+			OldLval, NewLval), Components0, Components, N0, N),
+		Uinstr = pragma_c(Decls, Components, MayCallMercury,
+			MaybeLabel1, MaybeLabel2, MaybeLabel3, MaybeLabel4,
+			ReferStackSlot)
+	;
+		Uinstr0 = init_sync_term(Lval0, BranchCount),
+		exprn_aux__substitute_lval_in_lval(OldLval, NewLval,
+			Lval0, Lval, N0, N),
+		Uinstr = init_sync_term(Lval, BranchCount)
+	;
+		Uinstr0 = fork(_, _, _),
+		Uinstr = Uinstr0,
+		N = N0
+	;
+		Uinstr0 = join_and_terminate(Lval0),
+		exprn_aux__substitute_lval_in_lval(OldLval, NewLval,
+			Lval0, Lval, N0, N),
+		Uinstr = join_and_terminate(Lval)
+	;
+		Uinstr0 = join_and_continue(Lval0, Label),
+		exprn_aux__substitute_lval_in_lval(OldLval, NewLval,
+			Lval0, Lval, N0, N),
+		Uinstr = join_and_continue(Lval, Label)
+	).
+
+:- pred exprn_aux__substitute_lval_in_component(lval::in, lval::in,
+	pragma_c_component::in, pragma_c_component::out, int::in, int::out)
+	is det.
+
+exprn_aux__substitute_lval_in_component(OldLval, NewLval,
+		Component0, Component, N0, N) :-
+	(
+		Component0 = pragma_c_inputs(Inputs0),
+		list__map_foldl(exprn_aux__substitute_lval_in_pragma_c_input(
+			OldLval, NewLval), Inputs0, Inputs, N0, N),
+		Component = pragma_c_inputs(Inputs)
+	;
+		Component0 = pragma_c_outputs(Outputs0),
+		list__map_foldl(exprn_aux__substitute_lval_in_pragma_c_output(
+			OldLval, NewLval), Outputs0, Outputs, N0, N),
+		Component = pragma_c_outputs(Outputs)
+	;
+		Component0 = pragma_c_user_code(_, _),
+		Component = Component0,
+		N = N0
+	;
+		Component0 = pragma_c_raw_code(Code, LvalSet0),
+		exprn_aux__substitute_lval_in_live_lval_info(OldLval, NewLval,
+			LvalSet0, LvalSet, N0, N),
+		Component = pragma_c_raw_code(Code, LvalSet)
+	;
+		Component0 = pragma_c_fail_to(_),
+		Component = Component0,
+		N = N0
+	;
+		Component0 = pragma_c_noop,
+		Component = Component0,
+		N = N0
+	).
+
+:- pred exprn_aux__substitute_lval_in_live_lval_info(lval::in, lval::in,
+	c_code_live_lvals::in, c_code_live_lvals::out, int::in, int::out)
+	is det.
+
+exprn_aux__substitute_lval_in_live_lval_info(_, _,
+		no_live_lvals_info, no_live_lvals_info, N, N).
+exprn_aux__substitute_lval_in_live_lval_info(OldLval, NewLval,
+		live_lvals_info(LvalSet0), live_lvals_info(LvalSet), N0, N) :-
+	Lvals0 = set__to_sorted_list(LvalSet0),
+	list__map_foldl(exprn_aux__substitute_lval_in_lval(OldLval, NewLval),
+		Lvals0, Lvals, N0, N),
+	set__list_to_set(Lvals, LvalSet).
+
+:- pred exprn_aux__substitute_lval_in_pragma_c_input(lval::in, lval::in,
+	pragma_c_input::in, pragma_c_input::out, int::in, int::out) is det.
+
+exprn_aux__substitute_lval_in_pragma_c_input(OldLval, NewLval, Out0, Out,
+		N0, N) :-
+	Out0 = pragma_c_input(Name, Type, Rval0),
+	exprn_aux__substitute_lval_in_rval(OldLval, NewLval, Rval0, Rval,
+		N0, N),
+	Out = pragma_c_input(Name, Type, Rval).
+
+:- pred exprn_aux__substitute_lval_in_pragma_c_output(lval::in, lval::in,
+	pragma_c_output::in, pragma_c_output::out, int::in, int::out) is det.
+
+exprn_aux__substitute_lval_in_pragma_c_output(OldLval, NewLval, Out0, Out,
+		N0, N) :-
+	Out0 = pragma_c_output(Lval0, Type, Name),
+	exprn_aux__substitute_lval_in_lval(OldLval, NewLval, Lval0, Lval,
+		N0, N),
+	Out = pragma_c_output(Lval, Type, Name).
+
+exprn_aux__substitute_lval_in_rval(OldLval, NewLval, Rval0, Rval, N0, N) :-
 	(
 		Rval0 = lval(Lval0),
 		exprn_aux__substitute_lval_in_lval(OldLval, NewLval,
-			Lval0, Lval),
+			Lval0, Lval, N0, N),
 		Rval = lval(Lval)
 	;
 		Rval0 = var(_Var),
-		Rval = Rval0
+		Rval = Rval0,
+		N = N0
 	;
 		Rval0 = create(Tag, Rvals0, ArgTypes, StatDyn,
 				Num, Msg, Reuse0),
 		exprn_aux__substitute_lval_in_args(OldLval, NewLval,
-			Rvals0, Rvals),
+			Rvals0, Rvals, N0, N1),
 		exprn_aux__substitute_lval_in_arg(OldLval, NewLval,
-			Reuse0, Reuse),
+			Reuse0, Reuse, N1, N),
 		Rval = create(Tag, Rvals, ArgTypes, StatDyn, Num, Msg, Reuse)
 	;
 		Rval0 = mkword(Tag, Rval1),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval1, Rval2),
+			Rval1, Rval2, N0, N),
 		Rval = mkword(Tag, Rval2)
 	;
 		Rval0 = const(_Const),
-		Rval = Rval0
+		Rval = Rval0,
+		N = N0
 	;
 		Rval0 = unop(Unop, Rval1),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval1, Rval2),
+			Rval1, Rval2, N0, N),
 		Rval = unop(Unop, Rval2)
 	;
 		Rval0 = binop(Binop, Rval1, Rval2),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval1, Rval3),
+			Rval1, Rval3, N0, N1),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval2, Rval4),
+			Rval2, Rval4, N1, N),
 		Rval = binop(Binop, Rval3, Rval4)
 	;
 		Rval0 = mem_addr(MemRef0),
 		exprn_aux__substitute_lval_in_mem_ref(OldLval, NewLval,
-			MemRef0, MemRef),
+			MemRef0, MemRef, N0, N),
 		Rval = mem_addr(MemRef)
 	).
 
-:- pred exprn_aux__substitute_lval_in_mem_ref(lval, lval, mem_ref, mem_ref).
-:- mode exprn_aux__substitute_lval_in_mem_ref(in, in, in, out) is det.
+:- pred exprn_aux__substitute_lval_in_mem_ref(lval::in, lval::in,
+	mem_ref::in, mem_ref::out, int::in, int::out) is det.
 
-exprn_aux__substitute_lval_in_mem_ref(OldLval, NewLval, MemRef0, MemRef) :-
+exprn_aux__substitute_lval_in_mem_ref(OldLval, NewLval, MemRef0, MemRef,
+		N0, N) :-
 	(
-		MemRef0 = stackvar_ref(N),
-		MemRef = stackvar_ref(N)
+		MemRef0 = stackvar_ref(_),
+		MemRef = MemRef0,
+		N = N0
 	;
-		MemRef0 = framevar_ref(N),
-		MemRef = framevar_ref(N)
+		MemRef0 = framevar_ref(_),
+		MemRef = MemRef0,
+		N = N0
 	;
-		MemRef0 = heap_ref(Rval0, Tag, N),
+		MemRef0 = heap_ref(Rval0, Tag, Slot),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval0, Rval),
-		MemRef = heap_ref(Rval, Tag, N)
+			Rval0, Rval, N0, N),
+		MemRef = heap_ref(Rval, Tag, Slot)
 	).
 
-exprn_aux__substitute_lval_in_lval(OldLval, NewLval, Lval0, Lval) :-
-	(
-		Lval0 = OldLval
-	->
-		Lval = NewLval
+exprn_aux__substitute_lval_in_lval(OldLval, NewLval, Lval0, Lval, N0, N) :-
+	( Lval0 = OldLval ->
+		Lval = NewLval,
+		N = N0 + 1
 	;
 		exprn_aux__substitute_lval_in_lval_2(OldLval, NewLval,
-			Lval0, Lval)
+			Lval0, Lval, N0, N)
 	).
 
-:- pred exprn_aux__substitute_lval_in_lval_2(lval, lval, lval, lval).
-:- mode exprn_aux__substitute_lval_in_lval_2(in, in, in, out) is det.
+:- pred exprn_aux__substitute_lval_in_lval_2(lval::in, lval::in,
+	lval::in, lval::out, int::in, int::out) is det.
 
-exprn_aux__substitute_lval_in_lval_2(OldLval, NewLval, Lval0, Lval) :-
+exprn_aux__substitute_lval_in_lval_2(OldLval, NewLval, Lval0, Lval, N0, N) :-
 	(
-		Lval0 = reg(T, N),
-		Lval = reg(T, N)
+		Lval0 = reg(_, _),
+		Lval = Lval0,
+		N = N0
 	;
 		Lval0 = succip,
-		Lval = succip
+		Lval = succip,
+		N = N0
 	;
 		Lval0 = maxfr,
-		Lval = maxfr
+		Lval = maxfr,
+		N = N0
 	;
 		Lval0 = curfr,
-		Lval = curfr
+		Lval = curfr,
+		N = N0
 	;
 		Lval0 = hp,
-		Lval = hp
+		Lval = hp,
+		N = N0
 	;
 		Lval0 = sp,
-		Lval = sp
+		Lval = sp,
+		N = N0
 	;
-		Lval0 = temp(T, N),
-		Lval = temp(T, N)
-	;
-		Lval0 = stackvar(N),
-		Lval = stackvar(N)
-	;
-		Lval0 = framevar(N),
-		Lval = framevar(N)
+		Lval0 = temp(_, _),
+		Lval = Lval0,
+		N = N0
+	;
+		Lval0 = stackvar(_),
+		Lval = Lval0,
+		N = N0
+	;
+		Lval0 = framevar(_),
+		Lval = Lval0,
+		N = N0
 	;
 		Lval0 = succip(Rval0),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval0, Rval),
+			Rval0, Rval, N0, N),
 		Lval = succip(Rval)
 	;
 		Lval0 = redoip(Rval0),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval0, Rval),
+			Rval0, Rval, N0, N),
 		Lval = redoip(Rval)
 	;
 		Lval0 = redofr(Rval0),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval0, Rval),
+			Rval0, Rval, N0, N),
 		Lval = redofr(Rval)
 	;
 		Lval0 = succfr(Rval0),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval0, Rval),
+			Rval0, Rval, N0, N),
 		Lval = succfr(Rval)
 	;
 		Lval0 = prevfr(Rval0),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval0, Rval),
+			Rval0, Rval, N0, N),
 		Lval = prevfr(Rval)
 	;
 		Lval0 = field(Tag, Rval1, Rval2),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval1, Rval3),
+			Rval1, Rval3, N0, N1),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval2, Rval4),
+			Rval2, Rval4, N1, N),
 		Lval = field(Tag, Rval3, Rval4)
 	;
 		Lval0 = mem_ref(Rval0),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval0, Rval),
+			Rval0, Rval, N0, N),
 		Lval = mem_ref(Rval)
 	;
-		Lval0 = lvar(N),
-		Lval = lvar(N)
-	).
+		Lval0 = lvar(_),
+		Lval = Lval0,
+		N = N0
+	).
+
+:- pred exprn_aux__substitute_lval_in_args(lval::in, lval::in,
+	list(maybe(rval))::in, list(maybe(rval))::out, int::in, int::out)
+	is det.
+
+exprn_aux__substitute_lval_in_args(_OldLval, _NewLval, [], [], N, N).
+exprn_aux__substitute_lval_in_args(OldLval, NewLval, [M0 | Ms0], [M | Ms],
+		N0, N) :-
+	exprn_aux__substitute_lval_in_arg(OldLval, NewLval, M0, M, N0, N1),
+	exprn_aux__substitute_lval_in_args(OldLval, NewLval, Ms0, Ms, N1, N).
 
-:- pred exprn_aux__substitute_lval_in_args(lval, lval,
-				list(maybe(rval)), list(maybe(rval))).
-:- mode exprn_aux__substitute_lval_in_args(in, in, in, out) is det.
-
-exprn_aux__substitute_lval_in_args(_OldLval, _NewLval, [], []).
-exprn_aux__substitute_lval_in_args(OldLval, NewLval, [M0 | Ms0], [M | Ms]) :-
-	exprn_aux__substitute_lval_in_arg(OldLval, NewLval, M0, M),
-	exprn_aux__substitute_lval_in_args(OldLval, NewLval, Ms0, Ms).
-
-:- pred exprn_aux__substitute_lval_in_arg(lval, lval,
-				maybe(rval), maybe(rval)).
-:- mode exprn_aux__substitute_lval_in_arg(in, in, in, out) is det.
+:- pred exprn_aux__substitute_lval_in_arg(lval::in, lval::in,
+	maybe(rval)::in, maybe(rval)::out, int::in, int::out) is det.
 
-exprn_aux__substitute_lval_in_arg(OldLval, NewLval, M0, M) :-
-	(
-		M0 = yes(Rval0)
-	->
+exprn_aux__substitute_lval_in_arg(OldLval, NewLval, M0, M, N0, N) :-
+	( M0 = yes(Rval0) ->
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
-			Rval0, Rval),
+			Rval0, Rval, N0, N),
 		M = yes(Rval)
 	;
-		M = M0
+		M = M0,
+		N = N0
 	).
 
 exprn_aux__substitute_rval_in_rval(OldRval, NewRval, Rval0, Rval) :-
@@ -592,8 +841,8 @@
 		)
 	).
 
-:- pred exprn_aux__substitute_rval_in_mem_ref(rval, rval, mem_ref, mem_ref).
-:- mode exprn_aux__substitute_rval_in_mem_ref(in, in, in, out) is det.
+:- pred exprn_aux__substitute_rval_in_mem_ref(rval::in, rval::in,
+	mem_ref::in, mem_ref::out) is det.
 
 exprn_aux__substitute_rval_in_mem_ref(OldRval, NewRval, MemRef0, MemRef) :-
 	(
@@ -609,8 +858,8 @@
 		MemRef = heap_ref(Rval, Tag, N)
 	).
 
-:- pred exprn_aux__substitute_rval_in_lval(rval, rval, lval, lval).
-:- mode exprn_aux__substitute_rval_in_lval(in, in, in, out) is det.
+:- pred exprn_aux__substitute_rval_in_lval(rval::in, rval::in,
+	lval::in, lval::out) is det.
 
 exprn_aux__substitute_rval_in_lval(OldRval, NewRval, Lval0, Lval) :-
 	(
@@ -682,18 +931,16 @@
 		Lval = lvar(N)
 	).
 
-:- pred exprn_aux__substitute_rval_in_args(rval, rval,
-				list(maybe(rval)), list(maybe(rval))).
-:- mode exprn_aux__substitute_rval_in_args(in, in, in, out) is det.
+:- pred exprn_aux__substitute_rval_in_args(rval::in, rval::in,
+	list(maybe(rval))::in, list(maybe(rval))::out) is det.
 
 exprn_aux__substitute_rval_in_args(_OldRval, _NewRval, [], []).
 exprn_aux__substitute_rval_in_args(OldRval, NewRval, [M0 | Ms0], [M | Ms]) :-
 	exprn_aux__substitute_rval_in_arg(OldRval, NewRval, M0, M),
 	exprn_aux__substitute_rval_in_args(OldRval, NewRval, Ms0, Ms).
 
-:- pred exprn_aux__substitute_rval_in_arg(rval, rval,
-				maybe(rval), maybe(rval)).
-:- mode exprn_aux__substitute_rval_in_arg(in, in, in, out) is det.
+:- pred exprn_aux__substitute_rval_in_arg(rval::in, rval::in,
+	maybe(rval)::in, maybe(rval)::out) is det.
 
 exprn_aux__substitute_rval_in_arg(OldRval, NewRval, M0, M) :-
 	(
@@ -713,7 +960,7 @@
 	exprn_aux__substitute_rval_in_rval(var(Var), Sub, Rval0, Rval1),
 	exprn_aux__substitute_vars_in_rval(Rest, Rval1, Rval).
 
-% When we substitute a one set of rvals for another, we face the problem
+% When we substitute one set of rvals for another, we face the problem
 % that the substitution may not be idempotent. We finesse this problem by
 % substituting unique new rvals for the original rvals, and then substituting
 % the replacement rvals for these unique rvals. We guarantee the uniqueness
@@ -725,9 +972,9 @@
 	exprn_aux__substitute_rvals_in_rval_2(RvalUniqPairs, Rval0, Rval1),
 	exprn_aux__substitute_rvals_in_rval_2(UniqRvalPairs, Rval1, Rval).
 
-:- pred exprn_aux__substitute_rvals_in_rval_1(assoc_list(rval, rval), int,
-	assoc_list(rval, rval), assoc_list(rval, rval)).
-:- mode exprn_aux__substitute_rvals_in_rval_1(in, in, out, out) is det.
+:- pred exprn_aux__substitute_rvals_in_rval_1(assoc_list(rval, rval)::in,
+	int::in, assoc_list(rval, rval)::out, assoc_list(rval, rval)::out)
+	is det.
 
 exprn_aux__substitute_rvals_in_rval_1([], _, [], []).
 exprn_aux__substitute_rvals_in_rval_1([Rval1 - Rval2 | RvalPairList], N0,
@@ -737,9 +984,8 @@
 	exprn_aux__substitute_rvals_in_rval_1(RvalPairList, N1,
 		RvalUniqList, UniqRvalList).
 
-:- pred exprn_aux__substitute_rvals_in_rval_2(assoc_list(rval, rval),
-	rval, rval).
-:- mode exprn_aux__substitute_rvals_in_rval_2(in, in, out) is det.
+:- pred exprn_aux__substitute_rvals_in_rval_2(assoc_list(rval, rval)::in,
+	rval::in, rval::out) is det.
 
 exprn_aux__substitute_rvals_in_rval_2([], Rval, Rval).
 exprn_aux__substitute_rvals_in_rval_2([Left - Right | Rest], Rval0, Rval2) :-
@@ -757,8 +1003,7 @@
 		Rval = Rval0
 	).
 
-:- pred exprn_aux__simplify_rval_2(rval, rval).
-:- mode exprn_aux__simplify_rval_2(in, out) is semidet.
+:- pred exprn_aux__simplify_rval_2(rval::in, rval::out) is semidet.
 
 exprn_aux__simplify_rval_2(Rval0, Rval) :-
 	(
@@ -806,16 +1051,15 @@
 		fail
 	).
 
-:- pred exprn_aux__simplify_args(list(maybe(rval)), list(maybe(rval))).
-:- mode exprn_aux__simplify_args(in, out) is det.
+:- pred exprn_aux__simplify_args(list(maybe(rval))::in, list(maybe(rval))::out)
+	is det.
 
 exprn_aux__simplify_args([], []).
 exprn_aux__simplify_args([MR0 | Ms0], [MR | Ms]) :-
 	exprn_aux__simplify_args(Ms0, Ms),
 	exprn_aux__simplify_arg(MR0, MR).
 
-:- pred exprn_aux__simplify_arg(maybe(rval), maybe(rval)).
-:- mode exprn_aux__simplify_arg(in, out) is det.
+:- pred exprn_aux__simplify_arg(maybe(rval)::in, maybe(rval)::out) is det.
 
 exprn_aux__simplify_arg(MR0, MR) :-
 	(
@@ -913,8 +1157,8 @@
 	list__append(CodeAddrs0, CodeAddrs1, CodeAddrs),
 	list__append(DataAddrs0, DataAddrs1, DataAddrs).
 
-:- pred exprn_aux__mem_ref_addrs(mem_ref, list(code_addr), list(data_addr)).
-:- mode exprn_aux__mem_ref_addrs(in, out, out) is det.
+:- pred exprn_aux__mem_ref_addrs(mem_ref::in,
+	list(code_addr)::out, list(data_addr)::out) is det.
 
 exprn_aux__mem_ref_addrs(stackvar_ref(_), [], []).
 exprn_aux__mem_ref_addrs(framevar_ref(_), [], []).
Index: compiler/frameopt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/frameopt.m,v
retrieving revision 1.78
diff -u -b -r1.78 frameopt.m
--- compiler/frameopt.m	2000/10/31 02:15:42	1.78
+++ compiler/frameopt.m	2001/02/28 15:19:40
@@ -538,15 +538,18 @@
 			;
 				Uinstr = mkframe(_, _)
 			;
-				Uinstr = c_code(_)
+				Uinstr = c_code(_, _)
 			;
 				Uinstr = pragma_c(_, _, MayCallMercury,
-					_, MaybeLayout, _, NeedStack),
+					_, MaybeLayout, MaybeOnlyLayout, _,
+					NeedStack),
 				(
 					MayCallMercury = may_call_mercury
 				;
 					MaybeLayout = yes(_)
 				;
+					MaybeOnlyLayout = yes(_)
+				;
 					NeedStack = yes
 				)
 			)
@@ -670,7 +673,8 @@
 			Uinstr = call(_, _, _, _, _, _)
 		;
 			% Only may_call_mercury pragma_c's can clobber succip.
-			Uinstr = pragma_c(_, _, may_call_mercury, _, _, _, _)
+			Uinstr = pragma_c(_, _, may_call_mercury,
+				_, _, _, _, _)
 		)
 	->
 		CanClobberSuccip = yes
Index: compiler/livemap.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/livemap.m,v
retrieving revision 1.50
diff -u -b -r1.50 livemap.m
--- compiler/livemap.m	2000/10/13 04:04:49	1.50
+++ compiler/livemap.m	2001/02/28 15:20:00
@@ -1,5 +1,5 @@
 %-----------------------------------------------------------------------------%
-% Copyright (C) 1995-2000 The University of Melbourne.
+% Copyright (C) 1995-2001 The University of Melbourne.
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
 %-----------------------------------------------------------------------------%
@@ -27,8 +27,7 @@
 	%
 	% We can compute this set only if the procedure contains no C code.
 
-:- pred livemap__build(list(instruction), maybe(livemap)).
-:- mode livemap__build(in, out) is det.
+:- pred livemap__build(list(instruction)::in, maybe(livemap)::out) is det.
 
 :- implementation.
 
@@ -55,14 +54,14 @@
 	list__reverse(Instrs, BackInstrs),
 	livemap__build_2(BackInstrs, Livemap0, MaybeLivemap).
 
-:- pred livemap__build_2(list(instruction), livemap, maybe(livemap)).
-:- mode livemap__build_2(in, in, out) is det.
+:- pred livemap__build_2(list(instruction)::in, livemap::in,
+	maybe(livemap)::out) is det.
 
 livemap__build_2(Backinstrs, Livemap0, MaybeLivemap) :-
 	set__init(Livevals0),
-	livemap__build_livemap(Backinstrs, Livevals0, no, DontValueNumber1,
+	livemap__build_livemap(Backinstrs, Livevals0, no, DontValueNumber,
 		Livemap0, Livemap1),
-	( DontValueNumber1 = yes ->
+	( DontValueNumber = yes ->
 		MaybeLivemap = no
 	; livemap__equal_livemaps(Livemap0, Livemap1) ->
 		MaybeLivemap = yes(Livemap1)
@@ -77,16 +76,15 @@
 	% The domain of Livemap2 should always be every label in the procedure.
 	% as should the domain of Livemap1 in every call after the first.
 
-:- pred livemap__equal_livemaps(livemap, livemap).
-:- mode livemap__equal_livemaps(in, in) is semidet.
+:- pred livemap__equal_livemaps(livemap::in, livemap::in) is semidet.
 
 livemap__equal_livemaps(Livemap1, Livemap2) :-
 	map__keys(Livemap1, Labels),
 	map__keys(Livemap2, Labels),
 	livemap__equal_livemaps_keys(Labels, Livemap1, Livemap2).
 
-:- pred livemap__equal_livemaps_keys(list(label), livemap, livemap).
-:- mode livemap__equal_livemaps_keys(in, in, in) is semidet.
+:- pred livemap__equal_livemaps_keys(list(label)::in, livemap::in, livemap::in)
+	is semidet.
 
 livemap__equal_livemaps_keys([], _Livemap1, _Livemap2).
 livemap__equal_livemaps_keys([Label | Labels], Livemap1, Livemap2) :-
@@ -101,9 +99,8 @@
 	% Build up a map of what lvals are live at each label.
 	% The input instruction sequence is reversed.
 
-:- pred livemap__build_livemap(list(instruction), lvalset, bool, bool,
-	livemap, livemap).
-:- mode livemap__build_livemap(in, in, in, out, in, out) is det.
+:- pred livemap__build_livemap(list(instruction)::in, lvalset::in,
+	bool::in, bool::out, livemap::in, livemap::out) is det.
 
 livemap__build_livemap([], _, DontValueNumber, DontValueNumber,
 		Livemap, Livemap).
@@ -115,10 +112,9 @@
 	livemap__build_livemap(Instrs1, Livevals1,
 		DontValueNumber1, DontValueNumber, Livemap1, Livemap).
 
-:- pred livemap__build_livemap_instr(instruction, list(instruction),
-	list(instruction), lvalset, lvalset, bool, bool, livemap, livemap).
-:- mode livemap__build_livemap_instr(in, in, out, in, out, in, out, in, out)
-	is det.
+:- pred livemap__build_livemap_instr(instruction::in, list(instruction)::in,
+	list(instruction)::out, lvalset::in, lvalset::out,
+	bool::in, bool::out, livemap::in, livemap::out) is det.
 
 livemap__build_livemap_instr(Instr0, Instrs0, Instrs,
 		Livevals0, Livevals, DontValueNumber0, DontValueNumber,
@@ -210,12 +206,6 @@
 		Instrs = Instrs0,
 		DontValueNumber = DontValueNumber0
 	;
-		Uinstr0 = c_code(_),
-		Livemap = Livemap0,
-		Livevals = Livevals0,
-		Instrs = Instrs0,
-		DontValueNumber = yes
-	;
 		Uinstr0 = if_val(Rval, CodeAddr),
 		livemap__look_for_livevals(Instrs0, Instrs,
 			Livevals0, Livevals1, "if_val", no, Found),
@@ -367,18 +357,85 @@
 		Instrs = Instrs0,
 		DontValueNumber = yes
 	;
-		% XXX we shouldn't just give up here
-		Uinstr0 = pragma_c(_, _, _, _, _, _, _),
+		Uinstr0 = c_code(_, LiveLvalInfo),
+		livemap__build_live_lval_info(LiveLvalInfo,
+			Livevals0, Livevals,
+			DontValueNumber0, DontValueNumber),
+		Livemap = Livemap0,
+		Instrs = Instrs0
+	;
+		Uinstr0 = pragma_c(_, Components, _, _, _, _, _, _),
+		livemap__build_livemap_pragma_components(Components,
+			Livevals0, Livevals,
+			DontValueNumber0, DontValueNumber),
 		Livemap = Livemap0,
-		Livevals = Livevals0,
-		Instrs = Instrs0,
-		DontValueNumber = yes
+		Instrs = Instrs0
 	).
 
-:- pred livemap__look_for_livevals(list(instruction), list(instruction),
-	lvalset, lvalset, string, bool, bool).
-:- mode livemap__look_for_livevals(in, out, in, out, in, in, out) is det.
+:- pred livemap__build_livemap_pragma_components(list(pragma_c_component)::in,
+	lvalset::in, lvalset::out, bool::in, bool::out) is det.
 
+livemap__build_livemap_pragma_components([], Livevals, Livevals,
+		DontValueNumber, DontValueNumber).
+livemap__build_livemap_pragma_components([Component | Components],
+		Livevals0, Livevals, DontValueNumber0, DontValueNumber) :-
+	(
+		Component = pragma_c_inputs(Inputs),
+		livemap__build_livemap_pragma_inputs(Inputs,
+			Livevals0, Livevals1),
+		DontValueNumber1 = DontValueNumber0
+	;
+		Component = pragma_c_outputs(_),
+		Livevals1 = Livevals0,
+		DontValueNumber1 = DontValueNumber0
+	;
+		Component = pragma_c_user_code(_, _),
+		Livevals1 = Livevals0,
+		DontValueNumber1 = yes
+	;
+		Component = pragma_c_raw_code(_, LiveLvalInfo),
+		livemap__build_live_lval_info(LiveLvalInfo,
+			Livevals0, Livevals1,
+			DontValueNumber0, DontValueNumber1)
+	;
+		Component = pragma_c_fail_to(_),
+		Livevals1 = Livevals0,
+		DontValueNumber1 = DontValueNumber0
+	;
+		Component = pragma_c_noop,
+		Livevals1 = Livevals0,
+		DontValueNumber1 = DontValueNumber0
+	),
+	livemap__build_livemap_pragma_components(Components,
+		Livevals1, Livevals, DontValueNumber1, DontValueNumber).
+
+:- pred livemap__build_live_lval_info(c_code_live_lvals::in,
+	lvalset::in, lvalset::out, bool::in, bool::out) is det.
+
+livemap__build_live_lval_info(no_live_lvals_info,
+		Livevals, Livevals, _, yes).
+livemap__build_live_lval_info(live_lvals_info(LiveLvalSet),
+		Livevals0, Livevals, DontValueNumber, DontValueNumber) :-
+	set__to_sorted_list(LiveLvalSet, LiveLvals),
+	livemap__insert_proper_livevals(LiveLvals, Livevals0, Livevals).
+
+:- pred livemap__build_livemap_pragma_inputs(list(pragma_c_input)::in,
+	lvalset::in, lvalset::out) is det.
+
+livemap__build_livemap_pragma_inputs([], Livevals, Livevals).
+livemap__build_livemap_pragma_inputs([Input | Inputs], Livevals0, Livevals) :-
+	Input = pragma_c_input(_, _, Rval),
+	( Rval = lval(Lval) ->
+		livemap__insert_proper_liveval(Lval, Livevals0, Livevals1)
+	;
+		Livevals1 = Livevals0
+	),
+	livemap__build_livemap_pragma_inputs(Inputs, Livevals1, Livevals).
+
+:- pred livemap__look_for_livevals(list(instruction)::in,
+	list(instruction)::out, lvalset::in, lvalset::out, string::in,
+	bool::in, bool::out) is det.
+
 livemap__look_for_livevals(Instrs0, Instrs, Livevals0, Livevals,
 		Site, Compulsory, Found) :-
 	opt_util__skip_comments(Instrs0, Instrs1),
@@ -397,8 +454,7 @@
 
 	% What lval (if any) is consulted when we branch to a code address?
 
-:- pred livemap__special_code_addr(code_addr, maybe(lval)).
-:- mode livemap__special_code_addr(in, out) is det.
+:- pred livemap__special_code_addr(code_addr::in, maybe(lval)::out) is det.
 
 livemap__special_code_addr(label(_), no).
 livemap__special_code_addr(imported(_), no).
@@ -423,8 +479,8 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
-:- pred livemap__make_live_in_rvals(list(rval), lvalset, lvalset).
-:- mode livemap__make_live_in_rvals(in, in, out) is det.
+:- pred livemap__make_live_in_rvals(list(rval)::in, lvalset::in, lvalset::out)
+	is det.
 
 livemap__make_live_in_rvals([], Live, Live).
 livemap__make_live_in_rvals([Rval | Rvals], Live0, Live) :-
@@ -435,8 +491,7 @@
 	% fields, since they are treated specially (the later stages consider
 	% them to be live even if they are not explicitly in the live set).
 
-:- pred livemap__make_live_in_rval(rval, lvalset, lvalset).
-:- mode livemap__make_live_in_rval(in, in, out) is det.
+:- pred livemap__make_live_in_rval(rval::in, lvalset::in, lvalset::out) is det.
 
 livemap__make_live_in_rval(lval(Lval), Live0, Live) :-
 	% XXX maybe we should treat mem_refs the same way as field refs
@@ -462,8 +517,8 @@
 livemap__make_live_in_rval(mem_addr(MemRef), Live0, Live) :-
 	livemap__make_live_in_mem_ref(MemRef, Live0, Live).
 
-:- pred livemap__make_live_in_mem_ref(mem_ref, lvalset, lvalset).
-:- mode livemap__make_live_in_mem_ref(in, in, out) is det.
+:- pred livemap__make_live_in_mem_ref(mem_ref::in, lvalset::in, lvalset::out)
+	is det.
 
 livemap__make_live_in_mem_ref(stackvar_ref(_), Live, Live).
 livemap__make_live_in_mem_ref(framevar_ref(_), Live, Live).
@@ -473,16 +528,15 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
-:- pred livemap__filter_livevals(lvalset, lvalset).
-:- mode livemap__filter_livevals(in, out) is det.
+:- pred livemap__filter_livevals(lvalset::in, lvalset::out) is det.
 
 livemap__filter_livevals(Livevals0, Livevals) :-
 	set__to_sorted_list(Livevals0, Livelist),
 	set__init(Livevals1),
 	livemap__insert_proper_livevals(Livelist, Livevals1, Livevals).
 
-:- pred livemap__insert_label_livevals(list(label), livemap, lvalset, lvalset).
-:- mode livemap__insert_label_livevals(in, in, in, out) is det.
+:- pred livemap__insert_label_livevals(list(label)::in, livemap::in,
+	lvalset::in, lvalset::out) is det.
 
 livemap__insert_label_livevals([], _, Livevals, Livevals).
 livemap__insert_label_livevals([Label | Labels], Livemap, Livevals0, Livevals)
@@ -495,8 +549,8 @@
 	),
 	livemap__insert_label_livevals(Labels, Livemap, Livevals1, Livevals).
 
-:- pred livemap__insert_proper_livevals(list(lval), lvalset, lvalset).
-:- mode livemap__insert_proper_livevals(in, in, out) is det.
+:- pred livemap__insert_proper_livevals(list(lval)::in, lvalset::in,
+	lvalset::out) is det.
 
 livemap__insert_proper_livevals([], Livevals, Livevals).
 livemap__insert_proper_livevals([Live | Livelist], Livevals0, Livevals) :-
@@ -505,8 +559,8 @@
 
 	% Don't insert references to locations on the heap.
 
-:- pred livemap__insert_proper_liveval(lval, lvalset, lvalset).
-:- mode livemap__insert_proper_liveval(in, in, out) is det.
+:- pred livemap__insert_proper_liveval(lval::in, lvalset::in, lvalset::out)
+	is det.
 
 livemap__insert_proper_liveval(Live, Livevals0, Livevals) :-
 	( Live = field(_, _, _) ->
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.273
diff -u -b -r1.273 llds.m
--- compiler/llds.m	2001/01/20 15:42:42	1.273
+++ compiler/llds.m	2001/02/28 15:13:53
@@ -295,7 +295,7 @@
 			% e.g. computed_goto(2, [A, B, C, D])
 			% will branch to label C.
 
-	;	c_code(string)
+	;	c_code(string, c_code_live_lvals)
 			% Do whatever is specified by the string,
 			% which can be any piece of C code that
 			% does not have any non-local flow of control.
@@ -415,7 +415,7 @@
 
 	;	pragma_c(list(pragma_c_decl), list(pragma_c_component),
 				may_call_mercury, maybe(label), maybe(label),
-				maybe(label), bool)
+				maybe(label), maybe(label), bool)
 			% The first argument says what local variable
 			% declarations are required for the following
 			% components, which in turn can specify how
@@ -440,16 +440,20 @@
 			% the fourth, fifth or sixth arg. The fourth argument
 			% may give the name of a label whose name is fixed
 			% because it embedded in raw C code, and which does
-			% not have a layout structure. The fifth argument
-			% may give the name of a label whose name is fixed
-			% because it does have an associated label layout
-			% structure (it may appear in C code as well).
-			% The sixth argument may give the name of a label
-			% that can be changed (because it is not mentioned
-			% in C code and has no associated layout structure,
-			% being mentioned only in pragma_c_fail_to components).
+			% not have a layout structure. The fifth and sixth
+			% arguments may give the names of labels whose names
+			% are fixed because they do have an associated label
+			% layout structure. The label in the fifth argument
+			% may appear in C code; the label in the sixth argument
+			% may not (such a label may therefore may be deleted
+			% from the LLDS code if it is not referred to from
+			% anywhere else). The seventh argument may give the
+			% name of a label that can be changed (because it is
+			% not mentioned in C code and has no associated layout
+			% structure, being mentioned only in pragma_c_fail_to
+			% components).
 			%
-			% The seventh argument says whether the contents
+			% The last argument says whether the contents
 			% of the pragma C code can refer to stack slots.
 			% User-written shouldn't refer to stack slots,
 			% the question is whether the compiler-generated
@@ -503,6 +507,17 @@
 						% pragma C code).
 		).
 
+:- type c_code_live_lvals
+	--->	no_live_lvals_info	% There is no information available
+					% about the live lvals used in
+					% the c_code.
+
+	;	live_lvals_info(	
+			set(lval)	% The set of lvals defined before the
+					% c_code that are live inside the
+					% c_code.
+		).
+
 	% Temporary frames on the nondet stack exist only to provide a failure
 	% environment, i.e. a place to store a redoip and a redofr. Accurate
 	% garbage collection and execution tracing need to know how to
@@ -560,7 +575,7 @@
 	--->	pragma_c_inputs(list(pragma_c_input))
 	;	pragma_c_outputs(list(pragma_c_output))
 	;	pragma_c_user_code(maybe(prog_context), string)
-	;	pragma_c_raw_code(string)
+	;	pragma_c_raw_code(string, c_code_live_lvals)
 	;	pragma_c_fail_to(label)
 	;	pragma_c_noop.
 
Index: compiler/llds_common.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_common.m,v
retrieving revision 1.36
diff -u -b -r1.36 llds_common.m
--- compiler/llds_common.m	2001/01/18 01:18:45	1.36
+++ compiler/llds_common.m	2001/02/28 15:20:04
@@ -273,7 +273,7 @@
 		llds_common__process_rval(Rval0, Rval, Info0, Info),
 		Instr = computed_goto(Rval, Labels)
 	;
-		Instr0 = c_code(_),
+		Instr0 = c_code(_, _),
 		Instr = Instr0,
 		Info = Info0
 	;
@@ -349,7 +349,7 @@
 		Instr = Instr0,
 		Info = Info0
 	;
-		Instr0 = pragma_c(_, _, _, _, _, _, _),
+		Instr0 = pragma_c(_, _, _, _, _, _, _, _),
 		Instr = Instr0,
 		Info = Info0
 	).
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.174
diff -u -b -r1.174 llds_out.m
--- compiler/llds_out.m	2001/02/20 14:08:34	1.174
+++ compiler/llds_out.m	2001/02/28 15:21:17
@@ -1355,7 +1355,7 @@
 		DeclSet0, DeclSet) -->
 	output_code_addr_decls(Target, "", "", 0, _, DeclSet0, DeclSet1),
 	output_code_addr_decls(ContLabel, "", "", 0, _, DeclSet1, DeclSet).
-output_instruction_decls(c_code(_), _, DeclSet, DeclSet) --> [].
+output_instruction_decls(c_code(_, _), _, DeclSet, DeclSet) --> [].
 output_instruction_decls(mkframe(FrameInfo, FailureContinuation), _,
 		DeclSet0, DeclSet) -->
 	(
@@ -1422,7 +1422,8 @@
 	output_rval_decls(Rval, "", "", 0, _, DeclSet0, DeclSet).
 output_instruction_decls(incr_sp(_, _), _, DeclSet, DeclSet) --> [].
 output_instruction_decls(decr_sp(_), _, DeclSet, DeclSet) --> [].
-output_instruction_decls(pragma_c(_, Comps, _, _, MaybeLayoutLabel, _, _),
+output_instruction_decls(pragma_c(_, Comps, _, _,
+		MaybeLayoutLabel, MaybeOnlyLayoutLabel, _, _),
 		StackLayoutLabels, DeclSet0, DeclSet) -->
 	( { MaybeLayoutLabel = yes(Label) } ->
 		{ map__lookup(StackLayoutLabels, Label, DataAddr) },
@@ -1430,7 +1431,13 @@
 	;
 		{ DeclSet1 = DeclSet0 }
 	),
-	output_pragma_c_component_list_decls(Comps, DeclSet1, DeclSet).
+	( { MaybeOnlyLayoutLabel = yes(OnlyLabel) } ->
+		{ map__lookup(StackLayoutLabels, OnlyLabel, OnlyDataAddr) },
+		output_stack_layout_decl(OnlyDataAddr, DeclSet1, DeclSet2)
+	;
+		{ DeclSet2 = DeclSet1 }
+	),
+	output_pragma_c_component_list_decls(Comps, DeclSet2, DeclSet).
 output_instruction_decls(init_sync_term(Lval, _), _, DeclSet0, DeclSet) -->
 	output_lval_decls(Lval, "", "", 0, _, DeclSet0, DeclSet).
 output_instruction_decls(fork(Child, Parent, _), _, DeclSet0, DeclSet) -->
@@ -1462,7 +1469,8 @@
 output_pragma_c_component_decls(pragma_c_outputs(Outputs), DeclSet0, DeclSet)
 		-->
 	output_pragma_output_lval_decls(Outputs, DeclSet0, DeclSet).
-output_pragma_c_component_decls(pragma_c_raw_code(_), DeclSet, DeclSet) --> [].
+output_pragma_c_component_decls(pragma_c_raw_code(_, _), DeclSet, DeclSet)
+		--> [].
 output_pragma_c_component_decls(pragma_c_user_code(_, _), DeclSet, DeclSet)
 		--> [].
 output_pragma_c_component_decls(pragma_c_fail_to(_), DeclSet, DeclSet) --> [].
@@ -1623,7 +1631,7 @@
 	output_call(Target, ContLabel, CallerLabel),
 	output_gc_livevals(LiveVals).
 
-output_instruction(c_code(C_Code_String), _) -->
+output_instruction(c_code(C_Code_String, _), _) -->
 	io__write_string("\t"),
 	io__write_string(C_Code_String).
 
@@ -1764,7 +1772,7 @@
 	io__write_int(N),
 	io__write_string(");\n").
 
-output_instruction(pragma_c(Decls, Components, _, _, _, _, _), _) -->
+output_instruction(pragma_c(Decls, Components, _, _, _, _, _, _), _) -->
 	io__write_string("\t{\n"),
 	output_pragma_decls(Decls),
 	output_pragma_c_components(Components),
@@ -1832,7 +1840,7 @@
 			io__write_string(";}\n")
 		)
 	).
-output_pragma_c_component(pragma_c_raw_code(C_Code)) -->
+output_pragma_c_component(pragma_c_raw_code(C_Code, _)) -->
 	io__write_string(C_Code).
 output_pragma_c_component(pragma_c_fail_to(Label)) -->
 	io__write_string("if (!MR_r1) MR_GOTO_LABEL("),
Index: compiler/middle_rec.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/middle_rec.m,v
retrieving revision 1.86
diff -u -b -r1.86 middle_rec.m
--- compiler/middle_rec.m	2000/11/23 04:32:42	1.86
+++ compiler/middle_rec.m	2001/02/28 15:21:38
@@ -402,7 +402,7 @@
 middle_rec__find_used_registers_instr(goto(_), Used, Used).
 middle_rec__find_used_registers_instr(computed_goto(Rval, _), Used0, Used) :-
 	middle_rec__find_used_registers_rval(Rval, Used0, Used).
-middle_rec__find_used_registers_instr(c_code(_), Used, Used).
+middle_rec__find_used_registers_instr(c_code(_, _), Used, Used).
 middle_rec__find_used_registers_instr(if_val(Rval, _), Used0, Used) :-
 	middle_rec__find_used_registers_rval(Rval, Used0, Used).
 middle_rec__find_used_registers_instr(incr_hp(Lval, _, Rval, _), Used0, Used) :-
@@ -426,8 +426,8 @@
 	middle_rec__find_used_registers_rval(Rval, Used0, Used).
 middle_rec__find_used_registers_instr(incr_sp(_, _), Used, Used).
 middle_rec__find_used_registers_instr(decr_sp(_), Used, Used).
-middle_rec__find_used_registers_instr(pragma_c(_, Components, _, _, _, _, _),
-		Used0, Used) :-
+middle_rec__find_used_registers_instr(pragma_c(_, Components,
+		_, _, _, _, _, _), Used0, Used) :-
 	middle_rec__find_used_registers_components(Components, Used0, Used).
 middle_rec__find_used_registers_instr(init_sync_term(Lval, _), Used0, Used) :-
 	middle_rec__find_used_registers_lval(Lval, Used0, Used).
@@ -455,7 +455,7 @@
 middle_rec__find_used_registers_component(pragma_c_outputs(Out), Used0, Used) :-
 	insert_pragma_c_output_registers(Out, Used0, Used).
 middle_rec__find_used_registers_component(pragma_c_user_code(_, _), Used, Used).
-middle_rec__find_used_registers_component(pragma_c_raw_code(_), Used, Used).
+middle_rec__find_used_registers_component(pragma_c_raw_code(_, _), Used, Used).
 middle_rec__find_used_registers_component(pragma_c_fail_to(_), Used, Used).
 middle_rec__find_used_registers_component(pragma_c_noop, Used, Used).
 
Index: compiler/opt_debug.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_debug.m,v
retrieving revision 1.112
diff -u -b -r1.112 opt_debug.m
--- compiler/opt_debug.m	2001/01/20 15:42:47	1.112
+++ compiler/opt_debug.m	2001/02/28 15:22:08
@@ -1028,7 +1028,7 @@
 	opt_debug__dump_rval(Rval, R_str),
 	opt_debug__dump_labels(Labels, L_str),
 	string__append_list(["computed_goto(", R_str, ", ", L_str, ")"], Str).
-opt_debug__dump_instr(c_code(Code), Str) :-
+opt_debug__dump_instr(c_code(Code, _), Str) :-
 	string__append_list(["c_code(", Code, ")"], Str).
 opt_debug__dump_instr(if_val(Rval, CodeAddr), Str) :-
 	opt_debug__dump_rval(Rval, R_str),
@@ -1093,7 +1093,7 @@
 	opt_debug__dump_label(Label, LabelStr),
 	string__append_list(["join(", LvalStr, ", ", LabelStr, ")"], Str).
 % XXX  should probably give more info than this
-opt_debug__dump_instr(pragma_c(_, Comps, _, _, _, _, _), Str) :-
+opt_debug__dump_instr(pragma_c(_, Comps, _, _, _, _, _, _), Str) :-
 	opt_debug__dump_components(Comps, C_str),
 	string__append_list(["pragma_c(", C_str, ")"], Str).
 
@@ -1112,7 +1112,7 @@
 opt_debug__dump_component(pragma_c_inputs(_), "").
 opt_debug__dump_component(pragma_c_outputs(_), "").
 opt_debug__dump_component(pragma_c_user_code(_, Code), Code).
-opt_debug__dump_component(pragma_c_raw_code(Code), Code).
+opt_debug__dump_component(pragma_c_raw_code(Code, _), Code).
 opt_debug__dump_component(pragma_c_fail_to(Label), Code) :-
 	opt_debug__dump_label(Label, LabelStr),
 	string__append_list(["fail to ", LabelStr], Code).
Index: compiler/opt_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_util.m,v
retrieving revision 1.111
diff -u -b -r1.111 opt_util.m
--- compiler/opt_util.m	2000/10/31 02:15:46	1.111
+++ compiler/opt_util.m	2001/02/28 15:23:47
@@ -800,7 +800,7 @@
 			Need = no
 		)
 	;
-		Uinstr0 = c_code(_),
+		Uinstr0 = c_code(_, _),
 		Need = no
 	;
 		Uinstr0 = if_val(Rval, _),
@@ -891,7 +891,7 @@
 		Uinstr0 = decr_sp(_),
 		Need = no
 	;
-		Uinstr0 = pragma_c(_, _, _, _, _, _, _),
+		Uinstr0 = pragma_c(_, _, _, _, _, _, _, _),
 		Need = no
 	;
 		Uinstr0 = init_sync_term(Lval, _),
@@ -988,7 +988,7 @@
 opt_util__can_instr_branch_away(label(_), no).
 opt_util__can_instr_branch_away(goto(_), yes).
 opt_util__can_instr_branch_away(computed_goto(_, _), yes).
-opt_util__can_instr_branch_away(c_code(_), no).
+opt_util__can_instr_branch_away(c_code(_, _), no).
 opt_util__can_instr_branch_away(if_val(_, _), yes).
 opt_util__can_instr_branch_away(incr_hp(_, _, _, _), no).
 opt_util__can_instr_branch_away(mark_hp(_), no).
@@ -1006,8 +1006,8 @@
 opt_util__can_instr_branch_away(fork(_, _, _), yes).
 opt_util__can_instr_branch_away(join_and_terminate(_), no).
 opt_util__can_instr_branch_away(join_and_continue(_, _), yes).
-opt_util__can_instr_branch_away(pragma_c(_, Comps, _, _, _, _, _), BranchAway)
-		:-
+opt_util__can_instr_branch_away(pragma_c(_, Comps, _, _, _, _, _, _),
+		BranchAway) :-
 	opt_util__can_components_branch_away(Comps, BranchAway).
 
 :- pred opt_util__can_components_branch_away(list(pragma_c_component), bool).
@@ -1039,7 +1039,8 @@
 
 opt_util__can_component_branch_away(pragma_c_inputs(_), no).
 opt_util__can_component_branch_away(pragma_c_outputs(_), no).
-opt_util__can_component_branch_away(pragma_c_raw_code(Code), CanBranchAway) :-
+opt_util__can_component_branch_away(pragma_c_raw_code(Code, _),
+		CanBranchAway) :-
 	( Code = "" -> CanBranchAway = no ; CanBranchAway = yes ).
 opt_util__can_component_branch_away(pragma_c_user_code(_, _), no).
 opt_util__can_component_branch_away(pragma_c_fail_to(_), yes).
@@ -1055,7 +1056,7 @@
 opt_util__can_instr_fall_through(label(_), yes).
 opt_util__can_instr_fall_through(goto(_), no).
 opt_util__can_instr_fall_through(computed_goto(_, _), no).
-opt_util__can_instr_fall_through(c_code(_), yes).
+opt_util__can_instr_fall_through(c_code(_, _), yes).
 opt_util__can_instr_fall_through(if_val(_, _), yes).
 opt_util__can_instr_fall_through(incr_hp(_, _, _, _), yes).
 opt_util__can_instr_fall_through(mark_hp(_), yes).
@@ -1073,7 +1074,7 @@
 opt_util__can_instr_fall_through(fork(_, _, _), no).
 opt_util__can_instr_fall_through(join_and_terminate(_), no).
 opt_util__can_instr_fall_through(join_and_continue(_, _), no).
-opt_util__can_instr_fall_through(pragma_c(_, _, _, _, _, _, _), yes).
+opt_util__can_instr_fall_through(pragma_c(_, _, _, _, _, _, _, _), yes).
 
 	% Check whether an instruction sequence can possibly fall through
 	% to the next instruction without using its label.
@@ -1101,7 +1102,7 @@
 opt_util__can_use_livevals(label(_), no).
 opt_util__can_use_livevals(goto(_), yes).
 opt_util__can_use_livevals(computed_goto(_, _), no).
-opt_util__can_use_livevals(c_code(_), no).
+opt_util__can_use_livevals(c_code(_, _), no).
 opt_util__can_use_livevals(if_val(_, _), yes).
 opt_util__can_use_livevals(incr_hp(_, _, _, _), no).
 opt_util__can_use_livevals(mark_hp(_), no).
@@ -1119,7 +1120,7 @@
 opt_util__can_use_livevals(fork(_, _, _), no).
 opt_util__can_use_livevals(join_and_terminate(_), no).
 opt_util__can_use_livevals(join_and_continue(_, _), no).
-opt_util__can_use_livevals(pragma_c(_, _, _, _, _, _, _), no).
+opt_util__can_use_livevals(pragma_c(_, _, _, _, _, _, _, _), no).
 
 % determine all the labels and code_addresses that are referenced by Instr
 
@@ -1164,7 +1165,7 @@
 opt_util__instr_labels_2(label(_), [], []).
 opt_util__instr_labels_2(goto(Addr), [], [Addr]).
 opt_util__instr_labels_2(computed_goto(_, Labels), Labels, []).
-opt_util__instr_labels_2(c_code(_), [], []).
+opt_util__instr_labels_2(c_code(_, _), [], []).
 opt_util__instr_labels_2(if_val(_, Addr), [], [Addr]).
 opt_util__instr_labels_2(incr_hp(_, _, _, _), [], []).
 opt_util__instr_labels_2(mark_hp(_), [], []).
@@ -1183,9 +1184,9 @@
 opt_util__instr_labels_2(join_and_terminate(_), [], []).
 opt_util__instr_labels_2(join_and_continue(_, Label), [Label], []).
 opt_util__instr_labels_2(pragma_c(_, _, _, MaybeFixLabel, MaybeLayoutLabel,
-		MaybeSubLabel, _), Labels, []) :-
+		MaybeOnlyLayoutLabel, MaybeSubLabel, _), Labels, []) :-
 	opt_util__pragma_c_labels(MaybeFixLabel, MaybeLayoutLabel,
-		MaybeSubLabel, Labels).
+		MaybeOnlyLayoutLabel, MaybeSubLabel, Labels).
 
 opt_util__possible_targets(comment(_), []).
 opt_util__possible_targets(livevals(_), []).
@@ -1207,7 +1208,7 @@
 		Targets = []
 	).
 opt_util__possible_targets(computed_goto(_, Targets), Targets).
-opt_util__possible_targets(c_code(_), []).
+opt_util__possible_targets(c_code(_, _), []).
 opt_util__possible_targets(if_val(_, CodeAddr), Targets) :-
 	( CodeAddr = label(Label) ->
 		Targets = [Label]
@@ -1231,16 +1232,16 @@
 opt_util__possible_targets(join_and_terminate(_), []).
 opt_util__possible_targets(join_and_continue(_, L), [L]).
 opt_util__possible_targets(pragma_c(_, _, _, MaybeFixedLabel, MaybeLayoutLabel,
-		MaybeSubLabel, _), Labels) :-
+		_, MaybeSubLabel, _), Labels) :-
 	opt_util__pragma_c_labels(MaybeFixedLabel, MaybeLayoutLabel,
-		MaybeSubLabel, Labels).
+		no, MaybeSubLabel, Labels).
 
 :- pred opt_util__pragma_c_labels(maybe(label), maybe(label), maybe(label),
-	list(label)).
-:- mode opt_util__pragma_c_labels(in, in, in, out) is det.
+	maybe(label), list(label)).
+:- mode opt_util__pragma_c_labels(in, in, in, in, out) is det.
 
-opt_util__pragma_c_labels(MaybeFixedLabel, MaybeLayoutLabel, MaybeSubLabel,
-		Labels) :-
+opt_util__pragma_c_labels(MaybeFixedLabel, MaybeLayoutLabel,
+		MaybeOnlyLayoutLabel, MaybeSubLabel, Labels) :-
 	( MaybeFixedLabel = yes(FixedLabel) ->
 		Labels0 = [FixedLabel]
 	;
@@ -1251,10 +1252,15 @@
 	;
 		Labels1 = Labels0
 	),
+	( MaybeOnlyLayoutLabel = yes(OnlyLayoutLabel) ->
+		Labels2 = [OnlyLayoutLabel | Labels1]
+	;
+		Labels2 = Labels1
+	),
 	( MaybeSubLabel = yes(SubLabel) ->
-		Labels = [SubLabel | Labels1]
+		Labels = [SubLabel | Labels2]
 	;
-		Labels = Labels1
+		Labels = Labels2
 	).
 
 :- pred opt_util__instr_rvals_and_lvals(instr, list(rval), list(lval)).
@@ -1272,7 +1278,7 @@
 opt_util__instr_rvals_and_lvals(label(_), [], []).
 opt_util__instr_rvals_and_lvals(goto(_), [], []).
 opt_util__instr_rvals_and_lvals(computed_goto(Rval, _), [Rval], []).
-opt_util__instr_rvals_and_lvals(c_code(_), [], []).
+opt_util__instr_rvals_and_lvals(c_code(_, _), [], []).
 opt_util__instr_rvals_and_lvals(if_val(Rval, _), [Rval], []).
 opt_util__instr_rvals_and_lvals(incr_hp(Lval, _, Rval, _), [Rval], [Lval]).
 opt_util__instr_rvals_and_lvals(mark_hp(Lval), [], [Lval]).
@@ -1290,8 +1296,8 @@
 opt_util__instr_rvals_and_lvals(fork(_, _, _), [], []).
 opt_util__instr_rvals_and_lvals(join_and_terminate(Lval), [], [Lval]).
 opt_util__instr_rvals_and_lvals(join_and_continue(Lval, _), [], [Lval]).
-opt_util__instr_rvals_and_lvals(pragma_c(_, Cs, _, _, _, _, _), Rvals, Lvals)
-		:-
+opt_util__instr_rvals_and_lvals(pragma_c(_, Cs, _, _, _, _, _, _),
+		Rvals, Lvals) :-
 	pragma_c_components_get_rvals_and_lvals(Cs, Rvals, Lvals).
 
 	% extract the rvals and lvals from the pragma_c_components
@@ -1321,7 +1327,7 @@
 	list__append(Lvals1, Lvals0, Lvals).
 pragma_c_component_get_rvals_and_lvals(pragma_c_user_code(_, _),
 		Rvals, Rvals, Lvals, Lvals).
-pragma_c_component_get_rvals_and_lvals(pragma_c_raw_code(_),
+pragma_c_component_get_rvals_and_lvals(pragma_c_raw_code(_, _),
 		Rvals, Rvals, Lvals, Lvals).
 pragma_c_component_get_rvals_and_lvals(pragma_c_fail_to(_),
 		Rvals, Rvals, Lvals, Lvals).
@@ -1410,7 +1416,7 @@
 	opt_util__count_temps_rval(Rval, R0, R, F0, F).
 opt_util__count_temps_instr(if_val(Rval, _), R0, R, F0, F) :-
 	opt_util__count_temps_rval(Rval, R0, R, F0, F).
-opt_util__count_temps_instr(c_code(_), R, R, F, F).
+opt_util__count_temps_instr(c_code(_, _), R, R, F, F).
 opt_util__count_temps_instr(incr_hp(Lval, _, Rval, _), R0, R, F0, F) :-
 	opt_util__count_temps_lval(Lval, R0, R1, F0, F1),
 	opt_util__count_temps_rval(Rval, R1, R, F1, F).
@@ -1439,7 +1445,7 @@
 	opt_util__count_temps_lval(Lval, R0, R, F0, F).
 opt_util__count_temps_instr(join_and_continue(Lval, _), R0, R, F0, F) :-
 	opt_util__count_temps_lval(Lval, R0, R, F0, F).
-opt_util__count_temps_instr(pragma_c(_, _, _, _, _, _, _), R, R, F, F).
+opt_util__count_temps_instr(pragma_c(_, _, _, _, _, _, _, _), R, R, F, F).
 
 :- pred opt_util__count_temps_lval(lval, int, int, int, int).
 :- mode opt_util__count_temps_lval(in, in, out, in, out) is det.
@@ -1546,7 +1552,7 @@
 		opt_util__touches_nondet_ctrl_lval(Lval, Touch)
 	; Uinstr = restore_hp(Rval) ->
 		opt_util__touches_nondet_ctrl_rval(Rval, Touch)
-	; Uinstr = pragma_c(_, Components, _, _, _, _, _) ->
+	; Uinstr = pragma_c(_, Components, _, _, _, _, _, _) ->
 		opt_util__touches_nondet_ctrl_components(Components, Touch)
 	;
 		Touch = yes
@@ -1626,7 +1632,7 @@
 
 opt_util__touches_nondet_ctrl_component(pragma_c_inputs(_), no).
 opt_util__touches_nondet_ctrl_component(pragma_c_outputs(_), no).
-opt_util__touches_nondet_ctrl_component(pragma_c_raw_code(_), no).
+opt_util__touches_nondet_ctrl_component(pragma_c_raw_code(_, _), no).
 opt_util__touches_nondet_ctrl_component(pragma_c_user_code(_, _), yes).
 opt_util__touches_nondet_ctrl_component(pragma_c_fail_to(_), no).
 opt_util__touches_nondet_ctrl_component(pragma_c_noop, no).
@@ -1790,7 +1796,7 @@
 		Rval = Rval0
 	),
 	opt_util__replace_labels_label_list(Labels0, ReplMap, Labels).
-opt_util__replace_labels_instr(c_code(Code), _, _, c_code(Code)).
+opt_util__replace_labels_instr(c_code(Code, Lvals), _, _, c_code(Code, Lvals)).
 opt_util__replace_labels_instr(if_val(Rval0, Target0), ReplMap, ReplData,
 		if_val(Rval, Target)) :-
 	(
@@ -1893,8 +1899,9 @@
 	opt_util__replace_labels_label(Label0, Replmap, Label),
 	opt_util__replace_labels_lval(Lval0, Replmap, Lval).
 opt_util__replace_labels_instr(pragma_c(A, Comps0, C, MaybeFix, MaybeLayout,
-		MaybeSub0, F), ReplMap, _,
-		pragma_c(A, Comps, C, MaybeFix, MaybeLayout, MaybeSub, F)) :-
+		MaybeOnlyLayout, MaybeSub0, F), ReplMap, _,
+		pragma_c(A, Comps, C, MaybeFix, MaybeLayout, MaybeOnlyLayout,
+			MaybeSub, F)) :-
 	(
 		MaybeFix = no
 	;
@@ -1917,6 +1924,17 @@
 			"trying to replace Mercury label with layout")
 	),
 	(
+		MaybeOnlyLayout = no
+	;
+		MaybeOnlyLayout = yes(OnlyLayoutLabel0),
+		opt_util__replace_labels_label(OnlyLayoutLabel0, ReplMap,
+			OnlyLayoutLabel),
+			% We cannot replace the label that has a layout
+			% structure.
+		require(unify(OnlyLayoutLabel0, OnlyLayoutLabel),
+			"trying to replace Mercury label with layout")
+	),
+	(
 		MaybeSub0 = no,
 		MaybeSub = no,
 		Comps = Comps0
@@ -1944,7 +1962,8 @@
 opt_util__replace_labels_comp(pragma_c_outputs(A), _, pragma_c_outputs(A)).
 opt_util__replace_labels_comp(pragma_c_user_code(A, B), _,
 		pragma_c_user_code(A, B)).
-opt_util__replace_labels_comp(pragma_c_raw_code(A), _, pragma_c_raw_code(A)).
+opt_util__replace_labels_comp(pragma_c_raw_code(A, B), _,
+		pragma_c_raw_code(A, B)).
 opt_util__replace_labels_comp(pragma_c_fail_to(Label0), ReplMap,
 		pragma_c_fail_to(Label)) :-
 	opt_util__replace_labels_label(Label0, ReplMap, Label).
Index: compiler/optimize.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/optimize.m,v
retrieving revision 1.25
diff -u -b -r1.25 optimize.m
--- compiler/optimize.m	2000/08/21 09:42:01	1.25
+++ compiler/optimize.m	2001/03/06 15:25:33
@@ -1,5 +1,5 @@
 %-----------------------------------------------------------------------------%
-% Copyright (C) 1996-2000 The University of Melbourne.
+% Copyright (C) 1996-2001 The University of Melbourne.
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
 %-----------------------------------------------------------------------------%
@@ -28,11 +28,12 @@
 :- implementation.
 
 :- import_module jumpopt, labelopt, dupelim, peephole.
-:- import_module frameopt, delay_slot, value_number, options.
+:- import_module frameopt, delay_slot, value_number, use_local_vars, options.
 :- import_module globals, passes_aux, opt_util, opt_debug, vn_debug.
-:- import_module continuation_info.
+:- import_module wrap_blocks, hlds_pred, llds_out, continuation_info.
 
-:- import_module bool, int, map, bimap, set, std_util, counter.
+:- import_module bool, int, string.
+:- import_module map, bimap, set, std_util, require, counter.
 
 optimize_main([], _, []) --> [].
 optimize_main([Proc0 | Procs0], GlobalData, [Proc | Procs]) -->
@@ -42,10 +43,8 @@
 optimize__proc(CProc0, GlobalData, CProc) -->
 	{ CProc0 = c_procedure(Name, Arity, PredProcId, Instrs0,
 		ProcLabel, C0, ContainsReconstruction) },
-	globals__io_lookup_bool_option(debug_opt, DebugOpt),
-	{ counter__allocate(N0, C0, _) },
-	opt_debug__msg(DebugOpt, N0, "before optimization"),
-	opt_debug__dump_instrs(DebugOpt, Instrs0),
+	optimize__init_opt_debug_info(Name, Arity, PredProcId, Instrs0, C0,
+		OptDebugInfo0),
 	globals__io_lookup_int_option(optimize_repeat, AllRepeat),
 	globals__io_lookup_int_option(optimize_vnrepeat, VnRepeat),
 	globals__io_lookup_bool_option(optimize_value_number, ValueNumber),
@@ -62,34 +61,119 @@
 	( { ValueNumber = yes } ->
 		{ NovnRepeat is AllRepeat - VnRepeat },
 		optimize__repeat(NovnRepeat, no, ContainsReconstruction,
-			LayoutLabelSet, Instrs0, ProcLabel, C0, C1, Instrs1),
-		optimize__middle(Instrs1, no, LayoutLabelSet,
-			ProcLabel, C1, C2, Instrs2),
+			LayoutLabelSet, Instrs0, ProcLabel, C0, C1,
+			OptDebugInfo0, OptDebugInfo1, Instrs1),
+		optimize__middle(Instrs1, no, LayoutLabelSet, ProcLabel,
+			C1, C2, OptDebugInfo1, OptDebugInfo2, Instrs2),
 		optimize__repeat(VnRepeat, yes, ContainsReconstruction,
-			LayoutLabelSet, Instrs2, ProcLabel, C2, C, Instrs3)
+			LayoutLabelSet, Instrs2, ProcLabel, C2, C,
+			OptDebugInfo2, OptDebugInfo, Instrs3)
 	;
 		optimize__repeat(AllRepeat, no, ContainsReconstruction,
-			LayoutLabelSet, Instrs0, ProcLabel, C0, C1, Instrs1),
-		optimize__middle(Instrs1, yes, LayoutLabelSet,
-			ProcLabel, C1, C, Instrs3)
+			LayoutLabelSet, Instrs0, ProcLabel, C0, C1,
+			OptDebugInfo0, OptDebugInfo1, Instrs1),
+		optimize__middle(Instrs1, yes, LayoutLabelSet, ProcLabel,
+			C1, C, OptDebugInfo1, OptDebugInfo, Instrs3)
 	),
-	optimize__last(Instrs3, LayoutLabelSet, Instrs),
+	optimize__last(Instrs3, LayoutLabelSet, C, OptDebugInfo, Instrs),
 	{ CProc = c_procedure(Name, Arity, PredProcId, Instrs,
 		ProcLabel, C, ContainsReconstruction) }.
 
 %-----------------------------------------------------------------------------%
 
+:- type opt_debug_info
+	--->	opt_debug_info(
+			string,			% base file name
+			int			% last file number written
+		)
+	;	no_opt_debug_info.
+
+:- pred optimize__init_opt_debug_info(string::in, int::in, pred_proc_id::in,
+	list(instruction)::in, counter::in, opt_debug_info::out,
+	io__state::di, io__state::uo) is det.
+
+optimize__init_opt_debug_info(Name, Arity, PredProcId, Instrs0, Counter,
+		OptDebugInfo) -->
+	globals__io_lookup_bool_option(debug_opt, DebugOpt),
+	(
+		{ DebugOpt = yes },
+		{ llds_out__name_mangle(Name, MangledName) },
+		{ PredProcId = proc(PredId, ProcId) },
+		{ pred_id_to_int(PredId, PredIdInt) },
+		{ proc_id_to_int(ProcId, ProcIdInt) },
+		{ string__int_to_string(Arity, ArityStr) },
+		{ string__int_to_string(PredIdInt, PredIdStr) },
+		{ string__int_to_string(ProcIdInt, ProcIdStr) },
+		{ string__append_list([MangledName, "_", ArityStr,
+			".pred", PredIdStr, ".proc", ProcIdStr], BaseName) },
+		{ OptDebugInfo = opt_debug_info(BaseName, 0) },
+
+		{ string__append_list([BaseName, ".opt0"], FileName) },
+		io__tell(FileName, Res),
+		( { Res = ok } ->
+			{ counter__allocate(NextLabel, Counter, _) },
+			opt_debug__msg(yes, NextLabel, "before optimization"),
+			opt_debug__dump_instrs(yes, Instrs0),
+			io__told
+		;
+			{ string__append("cannot open ", FileName, ErrorMsg) },
+			{ error(ErrorMsg) }
+		)
+	;
+		{ DebugOpt = no },
+		{ OptDebugInfo = no_opt_debug_info }
+	).
+
+:- pred optimize__maybe_opt_debug(list(instruction)::in, counter::in,
+	string::in, opt_debug_info::in, opt_debug_info::out,
+	io__state::di, io__state::uo) is det.
+
+optimize__maybe_opt_debug(Instrs, Counter, Msg,
+		OptDebugInfo0, OptDebugInfo) -->
+	(
+		{ OptDebugInfo0 = opt_debug_info(BaseName, OptNum0) },
+		{ OptNum = OptNum0 + 1 },
+		{ string__int_to_string(OptNum0, OptNum0Str) },
+		{ string__int_to_string(OptNum, OptNumStr) },
+		{ string__append_list([BaseName, ".opt", OptNum0Str],
+			OptFileName0) },
+		{ string__append_list([BaseName, ".opt", OptNumStr],
+			OptFileName) },
+		{ string__append_list([BaseName, ".diff", OptNumStr],
+			DiffFileName) },
+		io__tell(OptFileName, Res),
+		( { Res = ok } ->
+			{ counter__allocate(NextLabel, Counter, _) },
+			opt_debug__msg(yes, NextLabel, Msg),
+			opt_debug__dump_instrs(yes, Instrs),
+			io__told
+		;
+			{ string__append("cannot open ", OptFileName,
+				ErrorMsg) },
+			{ error(ErrorMsg) }
+		),
+		{ string__append_list(["diff -u ",
+			OptFileName0, " ", OptFileName,
+			" > ", DiffFileName], DiffCommand) },
+		io__call_system(DiffCommand, _),
+		{ OptDebugInfo = opt_debug_info(BaseName, OptNum) }
+	;
+		{ OptDebugInfo0 = no_opt_debug_info },
+		{ OptDebugInfo = no_opt_debug_info }
+	).
+
+%-----------------------------------------------------------------------------%
+
 :- pred optimize__repeat(int::in, bool::in, contains_reconstruction::in,
-	set(label)::in, list(instruction)::in,
-	proc_label::in, counter::in, counter::out, list(instruction)::out,
+	set(label)::in, list(instruction)::in, proc_label::in,
+	counter::in, counter::out, opt_debug_info::in, opt_debug_info::out,
+	list(instruction)::out,
 	io__state::di, io__state::uo) is det.
 
 optimize__repeat(Iter0, DoVn, ContainsReconstruction, LayoutLabelSet, Instrs0,
-		ProcLabel, C0, C, Instrs) -->
-	(
-		{ Iter0 > 0 }
-	->
-		{ Iter1 is Iter0 - 1 },
+		ProcLabel, C0, C, OptDebugInfo0, OptDebugInfo, Instrs) -->
+	( { Iter0 > 0 } ->
+		{ Iter1 = Iter0 - 1 },
 		( { Iter1 = 0 } ->
 			{ Final = yes }
 		;
@@ -97,18 +181,20 @@
 		),
 		optimize__repeated(Instrs0, DoVn, ContainsReconstruction,
 			Final, LayoutLabelSet, ProcLabel, C0, C1,
-			Instrs1, Mod),
+			OptDebugInfo0, OptDebugInfo1, Instrs1, Mod),
 		( { Mod = yes } ->
 			optimize__repeat(Iter1, DoVn, ContainsReconstruction,
 				LayoutLabelSet, Instrs1, ProcLabel, C1, C,
-				Instrs)
+				OptDebugInfo1, OptDebugInfo, Instrs)
 		;
 			{ Instrs = Instrs1 },
-			{ C = C1 }
+			{ C = C1 },
+			{ OptDebugInfo = OptDebugInfo0 }
 		)
 	;
 		{ Instrs = Instrs0 },
-		{ C = C0 }
+		{ C = C0 },
+		{ OptDebugInfo = OptDebugInfo0 }
 	).
 
 	% We short-circuit jump sequences before normal peepholing
@@ -116,13 +202,14 @@
 
 :- pred optimize__repeated(list(instruction)::in, bool::in,
 	contains_reconstruction::in, bool::in, set(label)::in,
-	proc_label::in, counter::in, counter::out, list(instruction)::out,
+	proc_label::in, counter::in, counter::out,
+	opt_debug_info::in, opt_debug_info::out, list(instruction)::out,
 	bool::out, io__state::di, io__state::uo) is det.
 
 optimize__repeated(Instrs0, DoVn, ContainsReconstruction, Final,
-		LayoutLabelSet, ProcLabel, C0, C, Instrs, Mod) -->
+		LayoutLabelSet, ProcLabel, C0, C, OptDebugInfo0, OptDebugInfo,
+		Instrs, Mod) -->
 	globals__io_lookup_bool_option(very_verbose, VeryVerbose),
-	globals__io_lookup_bool_option(debug_opt, DebugOpt),
 	{ opt_util__find_first_label(Instrs0, Label) },
 	{ opt_util__format_label(Label, LabelStr) },
 
@@ -137,16 +224,12 @@
 		),
 		value_number_main(Instrs0, ContainsReconstruction,
 			LayoutLabelSet, ProcLabel, C0, C1, Instrs1),
-		( { Instrs1 = Instrs0 } ->
-			[]
-		;
-			{ counter__allocate(N1, C1, _) },
-			opt_debug__msg(DebugOpt, N1, "after value numbering"),
-			opt_debug__dump_instrs(DebugOpt, Instrs1)
-		)
+		optimize__maybe_opt_debug(Instrs1, C1, "after value numbering",
+			OptDebugInfo0, OptDebugInfo1)
 	;
 		{ Instrs1 = Instrs0 },
-		{ C1 = C0 }
+		{ C1 = C0 },
+		{ OptDebugInfo1 = OptDebugInfo0 }
 	),
 	globals__io_lookup_bool_option(optimize_jumps, Jumpopt),
 	globals__io_lookup_bool_option(optimize_fulljumps, FullJumpopt),
@@ -164,17 +247,12 @@
 		{ jumpopt_main(Instrs1, LayoutLabelSet, TraceLevel, ProcLabel,
 			C1, C2, FullJumpopt, Final, CheckedNondetTailCalls,
 			Instrs2, Mod1) },
-		( { Mod1 = yes } ->
-			{ counter__allocate(N2A, C2, _) },
-			opt_debug__msg(DebugOpt, N2A,
-				"after jump optimization"),
-			opt_debug__dump_instrs(DebugOpt, Instrs2)
+		optimize__maybe_opt_debug(Instrs2, C2, "after jump opt",
+			OptDebugInfo1, OptDebugInfo2)
 		;
-			[]
-		)
-	;
 		{ Instrs2 = Instrs1 },
 		{ C2 = C1 },
+		{ OptDebugInfo2 = OptDebugInfo1 },
 		{ Mod1 = no }
 	),
 	globals__io_lookup_bool_option(optimize_peep, Peephole),
@@ -188,15 +266,11 @@
 		),
 		globals__io_get_gc_method(GC_Method),
 		{ peephole__optimize(GC_Method, Instrs2, Instrs3, Mod2) },
-		( { Mod2 = yes } ->
-			{ counter__allocate(N2B, C2, _) },
-			opt_debug__msg(DebugOpt, N2B, "after peepholing"),
-			opt_debug__dump_instrs(DebugOpt, Instrs3)
+		optimize__maybe_opt_debug(Instrs3, C2, "after peephole",
+			OptDebugInfo2, OptDebugInfo3)
 		;
-			[]
-		)
-	;
 		{ Instrs3 = Instrs2 },
+		{ OptDebugInfo3 = OptDebugInfo2 },
 		{ Mod2 = no }
 	),
 	globals__io_lookup_bool_option(optimize_labels, LabelElim),
@@ -210,16 +284,11 @@
 		),
 		{ labelopt_main(Instrs3, Final, LayoutLabelSet,
 			Instrs4, Mod3) },
-		( { Mod3 = yes } ->
-			{ counter__allocate(N2C, C2, _) },
-			opt_debug__msg(DebugOpt, N2C,
-				"after label optimization"),
-			opt_debug__dump_instrs(DebugOpt, Instrs4)
-		;
-			[]
-		)
+		optimize__maybe_opt_debug(Instrs4, C2, "after label opt",
+			OptDebugInfo3, OptDebugInfo4)
 	;
 		{ Instrs4 = Instrs3 },
+		{ OptDebugInfo4 = OptDebugInfo3 },
 		{ Mod3 = no }
 	),
 	globals__io_lookup_bool_option(optimize_dups, DupElim),
@@ -232,16 +301,11 @@
 			[]
 		),
 		{ dupelim_main(Instrs4, ProcLabel, C2, C, Instrs) },
-		( { Instrs = Instrs4 } ->
-			[]
-		;
-			{ counter__allocate(N, C, _) },
-			opt_debug__msg(DebugOpt, N,
-				"after duplicate elimination"),
-			opt_debug__dump_instrs(DebugOpt, Instrs)
-		)
+		optimize__maybe_opt_debug(Instrs, C, "after duplicates",
+			OptDebugInfo4, OptDebugInfo)
 	;
 		{ Instrs = Instrs4 },
+		{ OptDebugInfo = OptDebugInfo4 },
 		{ C = C2 }
 	),
 	{ Mod1 = no, Mod2 = no, Mod3 = no, Instrs = Instrs0 ->
@@ -253,12 +317,13 @@
 	maybe_report_stats(Statistics).
 
 :- pred optimize__middle(list(instruction)::in, bool::in, set(label)::in,
-	proc_label::in, counter::in, counter::out, list(instruction)::out,
+	proc_label::in, counter::in, counter::out,
+	opt_debug_info::in, opt_debug_info::out, list(instruction)::out,
 	io__state::di, io__state::uo) is det.
 
-optimize__middle(Instrs0, Final, LayoutLabelSet, ProcLabel, C0, C, Instrs) -->
+optimize__middle(Instrs0, Final, LayoutLabelSet, ProcLabel, C0, C,
+		OptDebugInfo0, OptDebugInfo, Instrs) -->
 	globals__io_lookup_bool_option(very_verbose, VeryVerbose),
-	globals__io_lookup_bool_option(debug_opt, DebugOpt),
 	{ opt_util__find_first_label(Instrs0, Label) },
 	{ opt_util__format_label(Label, LabelStr) },
 
@@ -273,14 +338,8 @@
 		),
 		{ frameopt_main(Instrs0, ProcLabel, C0, C1, Instrs1,
 			Mod1, Jumps) },
-		( { Mod1 = yes } ->
-			{ counter__allocate(N1, C1, _) },
-			opt_debug__msg(DebugOpt, N1,
-				"after frame optimization"),
-			opt_debug__dump_instrs(DebugOpt, Instrs1)
-		;
-			[]
-		),
+		optimize__maybe_opt_debug(Instrs1, C1, "after frame opt",
+			OptDebugInfo0, OptDebugInfo1),
 		globals__io_lookup_bool_option(optimize_fulljumps, FullJumpopt),
 		globals__io_lookup_bool_option(checked_nondet_tailcalls,
 			CheckedNondetTailCalls),
@@ -294,19 +353,14 @@
 				[]
 			),
 			{ jumpopt_main(Instrs1, LayoutLabelSet, TraceLevel,
-				ProcLabel, C1, C, FullJumpopt, Final,
-				CheckedNondetTailCalls, Instrs2, Mod2) },
-			( { Mod2 = yes } ->
-				{ counter__allocate(NA, C, _) },
-				opt_debug__msg(DebugOpt, NA,
-					"after jump optimization"),
-				opt_debug__dump_instrs(DebugOpt, Instrs2)
-			;
-				[]
-			)
+				ProcLabel, C1, C2, FullJumpopt, Final,
+				CheckedNondetTailCalls, Instrs2, _Mod2) },
+			optimize__maybe_opt_debug(Instrs2, C2, "after jumps",
+				OptDebugInfo1, OptDebugInfo2)
 		;
 			{ Instrs2 = Instrs1 },
-			{ C = C1 }
+			{ OptDebugInfo2 = OptDebugInfo1 },
+			{ C2 = C1 }
 		),
 		( { Mod1 = yes } ->
 			( { VeryVerbose = yes } ->
@@ -317,37 +371,55 @@
 				[]
 			),
 			{ labelopt_main(Instrs2, Final, LayoutLabelSet,
-				Instrs, Mod3) },
-			( { Mod3 = yes } ->
-				{ counter__allocate(NB, C, _) },
-				opt_debug__msg(DebugOpt, NB,
-					"after label optimization"),
-				opt_debug__dump_instrs(DebugOpt, Instrs)
+				Instrs3, _Mod3) },
+			optimize__maybe_opt_debug(Instrs3, C2, "after labels",
+				OptDebugInfo2, OptDebugInfo3)
 			;
-				[]
+			{ OptDebugInfo3 = OptDebugInfo2 },
+			{ Instrs3 = Instrs2 }
 			)
 		;
-			{ Instrs = Instrs2 }
-		)
+		{ Instrs3 = Instrs0 },
+		{ OptDebugInfo3 = OptDebugInfo0 },
+		{ C2 = C0 }
+	),
+	globals__io_lookup_bool_option(use_local_vars, UseLocalVars),
+	(
+		{ UseLocalVars = yes },
+		( { VeryVerbose = yes } ->
+			io__write_string("% Optimizing local vars for "),
+			io__write_string(LabelStr),
+			io__write_string("\n")
 	;
-		{ Instrs = Instrs0 },
-		{ C = C0 }
+			[]
+		),
+		globals__io_lookup_int_option(num_real_r_regs, NumRealRRegs),
+		{ use_local_vars__main(Instrs3, Instrs,
+			ProcLabel, NumRealRRegs, C2, C) },
+		optimize__maybe_opt_debug(Instrs, C, "after use_local_vars",
+			OptDebugInfo3, OptDebugInfo)
+	;
+		{ UseLocalVars = no },
+		{ Instrs = Instrs3 },
+		{ OptDebugInfo = OptDebugInfo3 },
+		{ C = C2 }
 	).
 
 :- pred optimize__last(list(instruction)::in, set(label)::in,
-	list(instruction)::out, io__state::di, io__state::uo) is det.
+	counter::in, opt_debug_info::in, list(instruction)::out,
+	io__state::di, io__state::uo) is det.
 
-optimize__last(Instrs0, LayoutLabelSet, Instrs) -->
+optimize__last(Instrs0, LayoutLabelSet, C, OptDebugInfo0, Instrs) -->
 	globals__io_lookup_bool_option(very_verbose, VeryVerbose),
-	globals__io_lookup_bool_option(debug_opt, DebugOpt),
 	{ opt_util__find_first_label(Instrs0, Label) },
 	{ opt_util__format_label(Label, LabelStr) },
 
 	globals__io_lookup_bool_option(optimize_delay_slot, DelaySlot),
 	globals__io_lookup_bool_option(optimize_value_number, ValueNumber),
-	( { DelaySlot = yes ; ValueNumber = yes } ->
+	globals__io_lookup_bool_option(use_local_vars, UseLocalVars),
+	( { DelaySlot = yes ; ValueNumber = yes ; UseLocalVars = yes } ->
 		% We must get rid of any extra labels added by other passes,
-		% since they can confuse both post_value_number and delay_slot.
+		% since they can confuse both wrap_blocks and delay_slot.
 		( { VeryVerbose = yes } ->
 			io__write_string("% Optimizing labels for "),
 			io__write_string(LabelStr),
@@ -355,15 +427,11 @@
 		;
 			[]
 		),
-		{ labelopt_main(Instrs0, no, LayoutLabelSet, Instrs1, Mod1) },
-		( { Mod1 = yes } ->
-			opt_debug__msg(DebugOpt, -1,
-				"after label optimization"),
-			opt_debug__dump_instrs(DebugOpt, Instrs1)
-		;
-			[]
-		)
+		{ labelopt_main(Instrs0, no, LayoutLabelSet, Instrs1, _Mod1) },
+		optimize__maybe_opt_debug(Instrs1, C, "after label opt",
+			OptDebugInfo0, OptDebugInfo1)
 	;
+		{ OptDebugInfo1 = OptDebugInfo0 },
 		{ Instrs1 = Instrs0 }
 	),
 	( { DelaySlot = yes } ->
@@ -375,17 +443,13 @@
 			[]
 		),
 		{ fill_branch_delay_slot(Instrs1, Instrs2) },
-		( { Instrs1 = Instrs0 } ->
-			opt_debug__msg(DebugOpt, -1,
-				"after delay slot filling"),
-			opt_debug__dump_instrs(DebugOpt, Instrs2)
-		;
-			[]
-		)
+		optimize__maybe_opt_debug(Instrs2, C, "after delay slots",
+			OptDebugInfo1, OptDebugInfo2)
 	;
+		{ OptDebugInfo2 = OptDebugInfo1 },
 		{ Instrs2 = Instrs1 }
 	),
-	( { ValueNumber = yes } ->
+	( { ValueNumber = yes ; UseLocalVars = yes } ->
 		( { VeryVerbose = yes } ->
 			io__write_string("% Optimizing post value number for "),
 			io__write_string(LabelStr),
@@ -393,14 +457,9 @@
 		;
 			[]
 		),
-		{ value_number__post_main(Instrs2, Instrs) },
-		( { Instrs = Instrs2 } ->
-			[]
-		;
-			opt_debug__msg(DebugOpt, -1,
-				"after post value number"),
-			opt_debug__dump_instrs(DebugOpt, Instrs)
-		)
+		{ wrap_blocks(Instrs2, Instrs) },
+		optimize__maybe_opt_debug(Instrs, C, "after wrap blocks",
+			OptDebugInfo2, _OptDebugInfo)
 	;
 		{ Instrs = Instrs1 }
 	).
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.315
diff -u -b -r1.315 options.m
--- compiler/options.m	2001/03/05 03:35:26	1.315
+++ compiler/options.m	2001/03/08 06:45:50
@@ -380,6 +380,7 @@
 		;	optimize_jumps
 		;	optimize_fulljumps
 		;	checked_nondet_tailcalls
+		;	use_local_vars
 		;	optimize_labels
 		;	optimize_dups
 %%% unused:	;	optimize_copyprop
@@ -772,6 +773,7 @@
 	optimize_jumps		-	bool(no),
 	optimize_fulljumps	-	bool(no),
 	checked_nondet_tailcalls	-	bool(no),
+	use_local_vars		-	bool(yes),
 	optimize_labels		-	bool(no),
 	optimize_dups		-	bool(no),
 %%%	optimize_copyprop	-	bool(no),
@@ -1209,6 +1211,7 @@
 long_option("optimize-fulljumps",	optimize_fulljumps).
 long_option("optimise-fulljumps",	optimize_fulljumps).
 long_option("checked-nondet-tailcalls", checked_nondet_tailcalls).
+long_option("use-local-vars",		use_local_vars).
 long_option("optimize-labels",		optimize_labels).
 long_option("optimise-labels",		optimize_labels).
 long_option("optimize-dups",		optimize_dups).
@@ -2555,6 +2558,8 @@
 		"\tConvert nondet calls into tail calls whenever possible, even",
 		"\twhen this requires a runtime check. This option tries to",
 		"\tminimize stack consumption, possibly at the expense of speed.",
+		"--no-use-local-vars",
+		"\tDisable the use of local variables in C code blocks.",
 		"--no-optimize-labels",
 		"\tDisable elimination of dead labels and code.",
 		"--optimize-dups",
Index: compiler/pragma_c_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/pragma_c_gen.m,v
retrieving revision 1.43
diff -u -b -r1.43 pragma_c_gen.m
--- compiler/pragma_c_gen.m	2001/03/06 05:51:24	1.43
+++ compiler/pragma_c_gen.m	2001/03/06 06:08:41
@@ -444,29 +444,32 @@
 	% MR_save_registers(); /* see notes (1) and (2) above */
 	%
 	{ MayCallMercury = will_not_call_mercury ->
-		SaveRegsComp = pragma_c_raw_code("")
+		SaveRegsComp = pragma_c_raw_code("",
+			live_lvals_info(set__init))
 	;
 		SaveRegsComp = pragma_c_raw_code(
-			"\tMR_save_registers();\n"
-		)
+			"\tMR_save_registers();\n",
+			live_lvals_info(set__init))
 	},
 
 	%
 	% Code fragments to obtain and release the global lock
 	%
 	{ ThreadSafe = thread_safe ->
-		ObtainLock = pragma_c_raw_code(""),
-		ReleaseLock = pragma_c_raw_code("")
+		ObtainLock = pragma_c_raw_code("", live_lvals_info(set__init)),
+		ReleaseLock = pragma_c_raw_code("", live_lvals_info(set__init))
 	;
 		module_info_pred_info(ModuleInfo, PredId, PredInfo),
 		pred_info_name(PredInfo, Name),
 		llds_out__quote_c_string(Name, MangledName),
 		string__append_list(["\tMR_OBTAIN_GLOBAL_LOCK(""",
 			MangledName, """);\n"], ObtainLockStr),
-		ObtainLock = pragma_c_raw_code(ObtainLockStr),
+		ObtainLock = pragma_c_raw_code(ObtainLockStr,
+			live_lvals_info(set__init)),
 		string__append_list(["\tMR_RELEASE_GLOBAL_LOCK(""",
 			MangledName, """);\n"], ReleaseLockStr),
-		ReleaseLock = pragma_c_raw_code(ReleaseLockStr)
+		ReleaseLock = pragma_c_raw_code(ReleaseLockStr,
+			live_lvals_info(set__init))
 	},
 
 	%
@@ -495,7 +498,8 @@
 		RestoreRegsComp = pragma_c_noop
 	;
 		RestoreRegsComp = pragma_c_raw_code(
-		"#ifndef CONSERVATIVE_GC\n\tMR_restore_registers();\n#endif\n"
+		"#ifndef CONSERVATIVE_GC\n\tMR_restore_registers();\n#endif\n",
+		live_lvals_info(set__init)
 		)
 	},
 
@@ -525,7 +529,7 @@
 			CheckR1_Comp, RestoreRegsComp,
 			OutputComp, ProcLabelHashUndef] },
 	{ PragmaCCode = node([
-		pragma_c(Decls, Components, MayCallMercury, no, no,
+		pragma_c(Decls, Components, MayCallMercury, no, no, no,
 			MaybeFailLabel, no)
 			- "Pragma C inclusion"
 	]) },
@@ -576,8 +580,10 @@
 		ProcLabelHashDef, ProcLabelHashUndef) :-
 	ProcLabelHashDef = pragma_c_raw_code(string__append_list([
 		"#define\tMR_PROC_LABEL\t",
-		make_proc_label_string(ModuleInfo, PredId, ProcId), "\n"])),
-	ProcLabelHashUndef = pragma_c_raw_code("#undef\tMR_PROC_LABEL\n").
+		make_proc_label_string(ModuleInfo, PredId, ProcId), "\n"]),
+		live_lvals_info(set__init)),
+	ProcLabelHashUndef = pragma_c_raw_code("#undef\tMR_PROC_LABEL\n",
+		live_lvals_info(set__init)).
 
 :- func make_proc_label_string(module_info, pred_id, proc_id) = string.
 
@@ -789,59 +795,62 @@
 		CallDecls = [SaveStructDecl | Decls],
 		CallComponents = [
 			pragma_c_inputs(InputDescs),
-			pragma_c_raw_code(InitSaveStruct),
-			pragma_c_raw_code(SaveRegs),
+			pragma_c_raw_code(InitSaveStruct, no_live_lvals_info),
+			pragma_c_raw_code(SaveRegs, no_live_lvals_info),
 			ProcLabelDefine,
-			pragma_c_raw_code(CallDef1),
-			pragma_c_raw_code(CallDef2),
-			pragma_c_raw_code(CallDef3),
+			pragma_c_raw_code(CallDef1, no_live_lvals_info),
+			pragma_c_raw_code(CallDef2, no_live_lvals_info),
+			pragma_c_raw_code(CallDef3, no_live_lvals_info),
 			pragma_c_user_code(FirstContext, First),
 			pragma_c_user_code(SharedContext, Shared),
-			pragma_c_raw_code(CallSuccessLabel),
-			pragma_c_raw_code(RestoreRegs),
+			pragma_c_raw_code(CallSuccessLabel, no_live_lvals_info),
+			pragma_c_raw_code(RestoreRegs, no_live_lvals_info),
 			pragma_c_outputs(OutputDescs),
-			pragma_c_raw_code(Succeed),
-			pragma_c_raw_code(CallLastSuccessLabel),
-			pragma_c_raw_code(RestoreRegs),
+			pragma_c_raw_code(Succeed, no_live_lvals_info),
+			pragma_c_raw_code(CallLastSuccessLabel,
+				no_live_lvals_info),
+			pragma_c_raw_code(RestoreRegs, no_live_lvals_info),
 			pragma_c_outputs(OutputDescs),
-			pragma_c_raw_code(SucceedDiscard),
-			pragma_c_raw_code(Undef1),
-			pragma_c_raw_code(Undef2),
-			pragma_c_raw_code(Undef3),
+			pragma_c_raw_code(SucceedDiscard, no_live_lvals_info),
+			pragma_c_raw_code(Undef1, no_live_lvals_info),
+			pragma_c_raw_code(Undef2, no_live_lvals_info),
+			pragma_c_raw_code(Undef3, no_live_lvals_info),
 			ProcLabelUndef
 		],
 		CallBlockCode = node([
 			pragma_c(CallDecls, CallComponents,
-				MayCallMercury, no, no, no, yes)
+				MayCallMercury, no, no, no, no, yes)
 				- "Call and shared pragma C inclusion"
 		]),
 
 		RetryDecls = [SaveStructDecl | OutDecls],
 		RetryComponents = [
-			pragma_c_raw_code(InitSaveStruct),
-			pragma_c_raw_code(SaveRegs),
+			pragma_c_raw_code(InitSaveStruct, no_live_lvals_info),
+			pragma_c_raw_code(SaveRegs, no_live_lvals_info),
 			ProcLabelDefine,
-			pragma_c_raw_code(RetryDef1),
-			pragma_c_raw_code(RetryDef2),
-			pragma_c_raw_code(RetryDef3),
+			pragma_c_raw_code(RetryDef1, no_live_lvals_info),
+			pragma_c_raw_code(RetryDef2, no_live_lvals_info),
+			pragma_c_raw_code(RetryDef3, no_live_lvals_info),
 			pragma_c_user_code(LaterContext, Later),
 			pragma_c_user_code(SharedContext, Shared),
-			pragma_c_raw_code(RetrySuccessLabel),
-			pragma_c_raw_code(RestoreRegs),
+			pragma_c_raw_code(RetrySuccessLabel,
+				no_live_lvals_info),
+			pragma_c_raw_code(RestoreRegs, no_live_lvals_info),
 			pragma_c_outputs(OutputDescs),
-			pragma_c_raw_code(Succeed),
-			pragma_c_raw_code(RetryLastSuccessLabel),
-			pragma_c_raw_code(RestoreRegs),
+			pragma_c_raw_code(Succeed, no_live_lvals_info),
+			pragma_c_raw_code(RetryLastSuccessLabel,
+				no_live_lvals_info),
+			pragma_c_raw_code(RestoreRegs, no_live_lvals_info),
 			pragma_c_outputs(OutputDescs),
-			pragma_c_raw_code(SucceedDiscard),
-			pragma_c_raw_code(Undef1),
-			pragma_c_raw_code(Undef2),
-			pragma_c_raw_code(Undef3),
+			pragma_c_raw_code(SucceedDiscard, no_live_lvals_info),
+			pragma_c_raw_code(Undef1, no_live_lvals_info),
+			pragma_c_raw_code(Undef2, no_live_lvals_info),
+			pragma_c_raw_code(Undef3, no_live_lvals_info),
 			ProcLabelUndef
 		],
 		RetryBlockCode = node([
 			pragma_c(RetryDecls, RetryComponents,
-				MayCallMercury, no, no, no, yes)
+				MayCallMercury, no, no, no, no, yes)
 				- "Retry and shared pragma C inclusion"
 		]),
 
@@ -879,87 +888,93 @@
 		CallDecls = [SaveStructDecl | Decls],
 		CallComponents = [
 			pragma_c_inputs(InputDescs),
-			pragma_c_raw_code(InitSaveStruct),
-			pragma_c_raw_code(SaveRegs),
+			pragma_c_raw_code(InitSaveStruct, no_live_lvals_info),
+			pragma_c_raw_code(SaveRegs, no_live_lvals_info),
 			ProcLabelDefine,
-			pragma_c_raw_code(CallDef1),
-			pragma_c_raw_code(CallDef2),
-			pragma_c_raw_code(CallDef3),
+			pragma_c_raw_code(CallDef1, no_live_lvals_info),
+			pragma_c_raw_code(CallDef2, no_live_lvals_info),
+			pragma_c_raw_code(CallDef3, no_live_lvals_info),
 			pragma_c_user_code(FirstContext, First),
-			pragma_c_raw_code(GotoSharedLabel),
-			pragma_c_raw_code(CallSuccessLabel),
-			pragma_c_raw_code(RestoreRegs),
+			pragma_c_raw_code(GotoSharedLabel, no_live_lvals_info),
+			pragma_c_raw_code(CallSuccessLabel,
+				no_live_lvals_info),
+			pragma_c_raw_code(RestoreRegs, no_live_lvals_info),
 			pragma_c_outputs(OutputDescs),
-			pragma_c_raw_code(Succeed),
-			pragma_c_raw_code(CallLastSuccessLabel),
-			pragma_c_raw_code(RestoreRegs),
+			pragma_c_raw_code(Succeed, no_live_lvals_info),
+			pragma_c_raw_code(CallLastSuccessLabel,
+				no_live_lvals_info),
+			pragma_c_raw_code(RestoreRegs, no_live_lvals_info),
 			pragma_c_outputs(OutputDescs),
-			pragma_c_raw_code(SucceedDiscard),
-			pragma_c_raw_code(Undef1),
-			pragma_c_raw_code(Undef2),
-			pragma_c_raw_code(Undef3),
+			pragma_c_raw_code(SucceedDiscard, no_live_lvals_info),
+			pragma_c_raw_code(Undef1, no_live_lvals_info),
+			pragma_c_raw_code(Undef2, no_live_lvals_info),
+			pragma_c_raw_code(Undef3, no_live_lvals_info),
 			ProcLabelUndef
 		],
 		CallBlockCode = node([
-			pragma_c(CallDecls, CallComponents,
-				MayCallMercury, yes(SharedLabel), no, no, yes)
+			pragma_c(CallDecls, CallComponents, MayCallMercury,
+				yes(SharedLabel), no, no, no, yes)
 				- "Call pragma C inclusion"
 		]),
 
 		RetryDecls = [SaveStructDecl | OutDecls],
 		RetryComponents = [
-			pragma_c_raw_code(InitSaveStruct),
-			pragma_c_raw_code(SaveRegs),
+			pragma_c_raw_code(InitSaveStruct, no_live_lvals_info),
+			pragma_c_raw_code(SaveRegs, no_live_lvals_info),
 			ProcLabelDefine,
-			pragma_c_raw_code(RetryDef1),
-			pragma_c_raw_code(RetryDef2),
-			pragma_c_raw_code(RetryDef3),
+			pragma_c_raw_code(RetryDef1, no_live_lvals_info),
+			pragma_c_raw_code(RetryDef2, no_live_lvals_info),
+			pragma_c_raw_code(RetryDef3, no_live_lvals_info),
 			pragma_c_user_code(LaterContext, Later),
-			pragma_c_raw_code(GotoSharedLabel),
-			pragma_c_raw_code(RetrySuccessLabel),
-			pragma_c_raw_code(RestoreRegs),
+			pragma_c_raw_code(GotoSharedLabel, no_live_lvals_info),
+			pragma_c_raw_code(RetrySuccessLabel,
+				no_live_lvals_info),
+			pragma_c_raw_code(RestoreRegs, no_live_lvals_info),
 			pragma_c_outputs(OutputDescs),
-			pragma_c_raw_code(Succeed),
-			pragma_c_raw_code(RetryLastSuccessLabel),
-			pragma_c_raw_code(RestoreRegs),
+			pragma_c_raw_code(Succeed, no_live_lvals_info),
+			pragma_c_raw_code(RetryLastSuccessLabel,
+				no_live_lvals_info),
+			pragma_c_raw_code(RestoreRegs, no_live_lvals_info),
 			pragma_c_outputs(OutputDescs),
-			pragma_c_raw_code(SucceedDiscard),
-			pragma_c_raw_code(Undef1),
-			pragma_c_raw_code(Undef2),
-			pragma_c_raw_code(Undef3),
+			pragma_c_raw_code(SucceedDiscard, no_live_lvals_info),
+			pragma_c_raw_code(Undef1, no_live_lvals_info),
+			pragma_c_raw_code(Undef2, no_live_lvals_info),
+			pragma_c_raw_code(Undef3, no_live_lvals_info),
 			ProcLabelUndef
 		],
 		RetryBlockCode = node([
-			pragma_c(RetryDecls, RetryComponents,
-				MayCallMercury, yes(SharedLabel), no, no, yes)
+			pragma_c(RetryDecls, RetryComponents, MayCallMercury,
+				yes(SharedLabel), no, no, no, yes)
 				- "Retry pragma C inclusion"
 		]),
 
 		SharedDecls = [SaveStructDecl | OutDecls],
 		SharedComponents = [
-			pragma_c_raw_code(InitSaveStruct),
-			pragma_c_raw_code(SaveRegs),
+			pragma_c_raw_code(InitSaveStruct, no_live_lvals_info),
+			pragma_c_raw_code(SaveRegs, no_live_lvals_info),
 			ProcLabelDefine,
-			pragma_c_raw_code(SharedDef1),
-			pragma_c_raw_code(SharedDef2),
-			pragma_c_raw_code(SharedDef3),
+			pragma_c_raw_code(SharedDef1, no_live_lvals_info),
+			pragma_c_raw_code(SharedDef2, no_live_lvals_info),
+			pragma_c_raw_code(SharedDef3, no_live_lvals_info),
 			pragma_c_user_code(SharedContext, Shared),
-			pragma_c_raw_code(SharedSuccessLabel),
-			pragma_c_raw_code(RestoreRegs),
+			pragma_c_raw_code(SharedSuccessLabel,
+				no_live_lvals_info),
+			pragma_c_raw_code(RestoreRegs, no_live_lvals_info),
 			pragma_c_outputs(OutputDescs),
-			pragma_c_raw_code(Succeed),
-			pragma_c_raw_code(SharedLastSuccessLabel),
-			pragma_c_raw_code(RestoreRegs),
+			pragma_c_raw_code(Succeed, no_live_lvals_info),
+			pragma_c_raw_code(SharedLastSuccessLabel,
+				no_live_lvals_info),
+			pragma_c_raw_code(RestoreRegs, no_live_lvals_info),
 			pragma_c_outputs(OutputDescs),
-			pragma_c_raw_code(SucceedDiscard),
-			pragma_c_raw_code(Undef1),
-			pragma_c_raw_code(Undef2),
-			pragma_c_raw_code(Undef3),
+			pragma_c_raw_code(SucceedDiscard, no_live_lvals_info),
+			pragma_c_raw_code(Undef1, no_live_lvals_info),
+			pragma_c_raw_code(Undef2, no_live_lvals_info),
+			pragma_c_raw_code(Undef3, no_live_lvals_info),
 			ProcLabelUndef
 		],
 		SharedBlockCode = node([
 			pragma_c(SharedDecls, SharedComponents,
-				MayCallMercury, no, no, no, yes)
+				MayCallMercury, no, no, no, no, yes)
 				- "Shared pragma C inclusion"
 		]),
 
Index: compiler/trace.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/trace.m,v
retrieving revision 1.45
diff -u -b -r1.45 trace.m
--- compiler/trace.m	2001/01/18 01:18:57	1.45
+++ compiler/trace.m	2001/02/28 15:14:34
@@ -591,8 +591,9 @@
 		TraceStmt1 = FillSlotsUptoTrail
 	),
 	TraceCode1 = node([
-		pragma_c([], [pragma_c_raw_code(TraceStmt1)],
-			will_not_call_mercury, no, MaybeLayoutLabel, no, yes)
+		pragma_c([], [pragma_c_raw_code(TraceStmt1,
+			live_lvals_info(set__init))], will_not_call_mercury,
+			no, no, MaybeLayoutLabel, no, yes)
 			- ""
 	]),
 	(
@@ -611,8 +612,10 @@
 			"\t\t", CallTableLvalStr, " = 0;"
 		], TraceStmt3),
 		TraceCode3 = node([
-			pragma_c([], [pragma_c_raw_code(TraceStmt3)],
-				will_not_call_mercury, no, no, no, yes) - ""
+			pragma_c([], [pragma_c_raw_code(TraceStmt3,
+				live_lvals_info(set__init))],
+				will_not_call_mercury, no, no, no, no, yes)
+				- ""
 		])
 	;
 		MaybeCallTableLval = no,
@@ -641,8 +644,10 @@
 			ResetFromFullStmt = "MR_trace_from_full = TRUE;\n"
 		),
 		TraceCode = node([
-			c_code(ResetFromFullStmt) - "",
-			c_code(ResetDepthStmt) - ""
+			c_code(ResetFromFullStmt, live_lvals_info(set__init))
+				- "",
+			c_code(ResetDepthStmt, live_lvals_info(set__init))
+				- ""
 		])
 	;
 		TraceCode = empty
@@ -800,6 +805,15 @@
 	set__to_sorted_list(TvarSet, TvarList),
 	continuation_info__find_typeinfos_for_tvars(TvarList,
 		VarLocs, ProcInfo, TvarDataMap),
+
+	VarLvals = list__map(find_lval_in_var_info, VarInfoList),
+	map__values(TvarDataMap, TvarLocnSets),
+	TvarLocnSet = set__union_list(TvarLocnSets),
+	set__to_sorted_list(TvarLocnSet, TvarLocns),
+	TvarLvals = list__map(find_lval_in_layout_locn, TvarLocns),
+	list__append(VarLvals, TvarLvals, LiveLvals),
+	LiveLvalSet = set__list_to_set(LiveLvals),
+
 	set__list_to_set(VarInfoList, VarInfoSet),
 	LayoutLabelInfo = layout_label_info(VarInfoSet, TvarDataMap),
 	LabelStr = layout_out__make_label_layout_name(Label),
@@ -848,12 +862,23 @@
 				% because sometimes this pair is preceded
 				% by another label, and this way we can
 				% eliminate this other label.
-			pragma_c([], [pragma_c_raw_code(TraceStmt)],
-				may_call_mercury, no, yes(Label), no, yes)
+			pragma_c([], [pragma_c_raw_code(TraceStmt,
+				live_lvals_info(LiveLvalSet))],
+				may_call_mercury, no, no, yes(Label), no, yes)
 				- ""
 		]),
 	Code = tree(ProduceCode, TraceCode)
 	}.
+
+:- func find_lval_in_var_info(var_info) = lval.
+
+find_lval_in_var_info(var_info(LayoutLocn, _)) =
+	find_lval_in_layout_locn(LayoutLocn).
+
+:- func find_lval_in_layout_locn(layout_locn) = lval.
+
+find_lval_in_layout_locn(direct(Lval)) = Lval.
+find_lval_in_layout_locn(indirect(Lval, _)) = Lval.
 
 trace__maybe_setup_redo_event(TraceInfo, Code) :-
 	TraceRedoLabel = TraceInfo ^ redo_label,
Index: compiler/use_local_vars.m
===================================================================
RCS file: use_local_vars.m
diff -N use_local_vars.m
--- /dev/null	Fri Dec  1 02:25:58 2000
+++ use_local_vars.m	Wed Mar  7 13:45:54 2001
@@ -0,0 +1,435 @@
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2001 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% File: use_local_vars.m
+%
+% Author: zs.
+%
+% This module transforms the sequence of instructions in a procedure body.
+% It looks for two patterns. The first is
+%
+%	<instruction that defines a fake register>
+%	<instructions that use and possibly define the fake register>
+%	<end of basic block, at which the fake register is not live>
+%
+% When it finds an occurrence of that pattern, it replaces all references to
+% the fake register with a temporary, which the C compiler can then put into a
+% real machine register.
+%
+% If the basic block jumps to a code address which is not a label (e.g.
+% do_redo, do_fail), we consider all registers to be live at the end of the
+% basic block. This is because livemap.m, which computes liveness information
+% for us, does not know about liveness requirements introduced by backtracking.
+% This is a conservative approximation. The union of the livenesses of all the
+% labels that represent resume points is a better approximation, but it would
+% be tedious to compute and is unlikely to yield significantly better code.
+%
+% The second pattern we look for is simply an instruction that defines a fake
+% register or stack slot, followed by some uses of that register or stack slot
+% before code that redefines the register or stack slot. When we find this
+% pattern, we again replace all references to the fake register or stack slot
+% with a temporary, but since this time we cannot be sure that the original
+% lval will not be referred to, we assign the temporary to the lval as well.
+% This is a win because the cost of the assignment is less than the savings
+% from replacing the fake register or stack slot references with temporary
+% variable references.
+
+%-----------------------------------------------------------------------------%
+
+:- module use_local_vars.
+
+:- interface.
+
+:- import_module llds.
+:- import_module list, counter.
+
+:- pred use_local_vars__main(list(instruction)::in, list(instruction)::out,
+	proc_label::in, int::in, counter::in, counter::out) is det.
+
+:- implementation.
+
+:- import_module basic_block, livemap, exprn_aux, opt_util.
+:- import_module int, set, map, counter, std_util, require.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+use_local_vars__main(Instrs0, Instrs, ProcLabel, NumRealRRegs, C0, C) :-
+	create_basic_blocks(Instrs0, Comments, ProcLabel, C0, C1,
+		LabelSeq, BlockMap0),
+	flatten_basic_blocks(LabelSeq, BlockMap0, TentativeInstrs),
+	livemap__build(TentativeInstrs, MaybeLiveMap),
+	(
+		% Instrs0 must have contained C code which cannot be analyzed
+		MaybeLiveMap = no,
+		Instrs = Instrs0,
+		C = C0
+	;
+		MaybeLiveMap = yes(LiveMap),
+		list__foldl(use_local_vars_block(LiveMap, NumRealRRegs),
+			LabelSeq, BlockMap0, BlockMap),
+		flatten_basic_blocks(LabelSeq, BlockMap, Instrs1),
+		list__append(Comments, Instrs1, Instrs),
+		C = C1
+	).
+
+:- pred use_local_vars_block(livemap::in, int::in, label::in, block_map::in,
+	block_map::out) is det.
+
+use_local_vars_block(LiveMap, NumRealRRegs, Label, BlockMap0, BlockMap) :-
+	map__lookup(BlockMap0, Label, BlockInfo0),
+	BlockInfo0 = block_info(BlockLabel, LabelInstr, RestInstrs0,
+		JumpLabels, MaybeFallThrough),
+	( can_branch_to_unknown_label(RestInstrs0) ->
+		MaybeEndLiveLvals = no
+	;
+		(
+			MaybeFallThrough = yes(FallThrough),
+			EndLabels = [FallThrough | JumpLabels]
+		;
+			MaybeFallThrough = no,
+			EndLabels = JumpLabels
+		),
+		list__foldl(find_live_lvals_at_end_labels(LiveMap), EndLabels,
+			set__init, EndLiveLvals0),
+		list__foldl(find_live_lvals_in_annotations, RestInstrs0,
+			EndLiveLvals0, EndLiveLvals),
+		MaybeEndLiveLvals = yes(EndLiveLvals)
+	),
+	counter__init(1, TempCounter0),
+	use_local_vars_instrs(RestInstrs0, RestInstrs,
+		TempCounter0, TempCounter, NumRealRRegs, MaybeEndLiveLvals),
+	( TempCounter = TempCounter0 ->
+		BlockMap = BlockMap0
+	;
+		BlockInfo = block_info(BlockLabel, LabelInstr,
+			RestInstrs, JumpLabels, MaybeFallThrough),
+		map__det_update(BlockMap0, Label, BlockInfo, BlockMap)
+	).
+
+:- pred can_branch_to_unknown_label(list(instruction)::in) is semidet.
+
+can_branch_to_unknown_label([Uinstr - _ | Instrs]) :-
+	(
+		opt_util__instr_labels(Uinstr, _, CodeAddrs),
+		some_code_addr_is_not_label(CodeAddrs)
+	;
+		can_branch_to_unknown_label(Instrs)
+	).
+
+:- pred some_code_addr_is_not_label(list(code_addr)::in) is semidet.
+
+some_code_addr_is_not_label([CodeAddr | CodeAddrs]) :-
+	(
+		\+ CodeAddr = label(_Label)
+	;
+		some_code_addr_is_not_label(CodeAddrs)
+	).
+
+:- pred find_live_lvals_at_end_labels(livemap::in, label::in,
+	lvalset::in, lvalset::out) is det.
+
+find_live_lvals_at_end_labels(LiveMap, Label, LiveLvals0, LiveLvals) :-
+	( map__search(LiveMap, Label, LabelLiveLvals) ->
+		set__union(LiveLvals0, LabelLiveLvals, LiveLvals)
+	; Label = local(_, _) ->
+		error("find_live_lvals_at_end_labels: local label not found")
+	;
+		% Non-local labels can be found only through call instructions,
+		% which must be preceded by livevals instructions. The
+		% variables live at the label will be included when we process
+		% the livevals instruction.
+		LiveLvals = LiveLvals0
+	).
+
+:- pred find_live_lvals_in_annotations(instruction::in,
+	lvalset::in, lvalset::out) is det.
+
+find_live_lvals_in_annotations(Uinstr - _, LiveLvals0, LiveLvals) :-
+	( Uinstr = livevals(InstrLiveLvals) ->
+		set__union(LiveLvals0, InstrLiveLvals, LiveLvals)
+	;
+		LiveLvals = LiveLvals0
+	).
+
+:- pred use_local_vars_instrs(list(instruction)::in, list(instruction)::out,
+	counter::in, counter::out, int::in, maybe(lvalset)::in) is det.
+
+use_local_vars_instrs([], [], TempCounter, TempCounter, _, _).
+use_local_vars_instrs([Instr0 | TailInstrs0], Instrs,
+		TempCounter0, TempCounter, NumRealRRegs, MaybeEndLiveLvals) :-
+	Instr0 = Uinstr0 - _Comment0,
+	(
+		( Uinstr0 = assign(ToLval, _FromRval)
+		; Uinstr0 = incr_hp(ToLval, _MaybeTag, _SizeRval, _Type)
+		),
+		(
+			ToLval = reg(r, RegNum),
+			RegNum > NumRealRRegs
+		;
+			ToLval = stackvar(_)
+		;
+			ToLval = framevar(_)
+		)
+	->
+		counter__allocate(TempNum, TempCounter0, TempCounter1),
+		NewLval = temp(r, TempNum),
+		(
+			ToLval = reg(_, _),
+			MaybeEndLiveLvals = yes(EndLiveLvals),
+			not set__member(ToLval, EndLiveLvals)
+		->
+			substitute_lval_in_defn(ToLval, NewLval,
+				Instr0, Instr),
+			list__map_foldl(exprn_aux__substitute_lval_in_instr(
+				ToLval, NewLval),
+				TailInstrs0, TailInstrs1, 0, _),
+			use_local_vars_instrs(TailInstrs1, TailInstrs,
+				TempCounter1, TempCounter,
+				NumRealRRegs, MaybeEndLiveLvals),
+			Instrs = [Instr | TailInstrs]
+		;
+			substitute_lval_in_instr_until_defn(ToLval, NewLval,
+				TailInstrs0, TailInstrs1, 0, NumSubst),
+			NumSubst > 1
+		->
+			substitute_lval_in_defn(ToLval, NewLval,
+				Instr0, Instr),
+			CopyInstr = assign(ToLval, lval(NewLval)) - "",
+			use_local_vars_instrs(TailInstrs1, TailInstrs,
+				TempCounter1, TempCounter,
+				NumRealRRegs, MaybeEndLiveLvals),
+			Instrs = [Instr, CopyInstr | TailInstrs]
+		;
+			use_local_vars_instrs(TailInstrs0, TailInstrs,
+				TempCounter0, TempCounter,
+				NumRealRRegs, MaybeEndLiveLvals),
+			Instrs = [Instr0 | TailInstrs]
+		)
+	;
+		use_local_vars_instrs(TailInstrs0, TailInstrs,
+			TempCounter0, TempCounter,
+			NumRealRRegs, MaybeEndLiveLvals),
+		Instrs = [Instr0 | TailInstrs]
+	).
+
+	% When processing substituting e.g. tempr1 for e.g. r2
+	% in the instruction that defines r2, we must be careful
+	% to leave intact the value being assigned. Given the instruction
+	%
+	%	r2 = field(0, r2, 5)
+	%
+	% we must generate
+	%
+	%	tempr1 = field(0, r2, 5)
+	%
+	% Generating
+	%
+	%	tempr1 = field(0, tempr1, 5)
+	%
+	% would introduce a bug, since the right hand side now refers to
+	% an as yet undefined variable.
+
+:- pred substitute_lval_in_defn(lval::in, lval::in,
+	instruction::in, instruction::out) is det.
+
+substitute_lval_in_defn(OldLval, NewLval, Instr0, Instr) :-
+	Instr0 = Uinstr0 - Comment,
+	( Uinstr0 = assign(ToLval, FromRval) ->
+		require(unify(ToLval, OldLval),
+			"substitute_lval_in_defn: mismatch in assign"),
+		Uinstr = assign(NewLval, FromRval)
+	; Uinstr0 = incr_hp(ToLval, MaybeTag, SizeRval, Type) ->
+		require(unify(ToLval, OldLval),
+			"substitute_lval_in_defn: mismatch in incr_hp"),
+		Uinstr = incr_hp(NewLval, MaybeTag, SizeRval, Type)
+	;
+		error("substitute_lval_in_defn: unexpected instruction")
+	),
+	Instr = Uinstr - Comment.
+
+	% Substitute NewLval for OldLval in an instruction sequence
+	% until we come an instruction that may define OldLval.
+	% We don't worry about instructions that define a variable that
+	% occurs in the access path to OldLval (and which therefore indirectly
+	% modifies the value that OldLval refers to), because our caller will
+	% call us only with OldLvals (and NewLvals for that matter) that have
+	% no lvals in their access path.
+	%
+	% This predicate takes a conservative view of what may define OldLval.
+	% For some instruction types, we simply give up. Since these
+	% instruction types are relatively rare, the effect on the performance
+	% of the generated code should be negligible.
+
+:- pred substitute_lval_in_instr_until_defn(lval::in, lval::in,
+	list(instruction)::in, list(instruction)::out, int::in, int::out)
+	is det.
+
+substitute_lval_in_instr_until_defn(_, _, [], [], N, N).
+substitute_lval_in_instr_until_defn(OldLval, NewLval,
+		[Instr0 | Instrs0], [Instr | Instrs], N0, N) :-
+	Instr0 = Uinstr0 - _,
+	(
+		Uinstr0 = comment(_),
+		Instr = Instr0,
+		substitute_lval_in_instr_until_defn(OldLval, NewLval,
+			Instrs0, Instrs, N0, N)
+	;
+		Uinstr0 = livevals(_),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = block(_, _, _),
+		error("substitute_lval_in_instr_until_defn: found block")
+	;
+		Uinstr0 = assign(Lval, _),
+		( Lval = OldLval ->
+				% If we alter any lval that occurs in OldLval,
+				% we must stop the substitutions. At the
+				% moment, the only lval OldLval contains is
+				% itself.
+			Instr = Instr0,
+			Instrs = Instrs0,
+			N = N0
+		;
+			exprn_aux__substitute_lval_in_instr(OldLval, NewLval,
+				Instr0, Instr, N0, N1),
+			substitute_lval_in_instr_until_defn(OldLval, NewLval,
+				Instrs0, Instrs, N1, N)
+		)
+	;
+		Uinstr0 = call(_, _, _, _, _, _),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = mkframe(_, _),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = label(_),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = goto(_),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = computed_goto(_, _),
+		exprn_aux__substitute_lval_in_instr(OldLval, NewLval,
+			Instr0, Instr, N0, N),
+		Instrs = Instrs0
+	;
+		Uinstr0 = if_val(_, _),
+		exprn_aux__substitute_lval_in_instr(OldLval, NewLval,
+			Instr0, Instr, N0, N),
+		Instrs = Instrs0
+	;
+		Uinstr0 = incr_hp(Lval, _, _, _),
+		( Lval = OldLval ->
+				% If we alter any lval that occurs in OldLval,
+				% we must stop the substitutions. At the
+				% moment, the only lval OldLval contains is
+				% itself.
+			Instr = Instr0,
+			Instrs = Instrs0,
+			N = N0
+		;
+			exprn_aux__substitute_lval_in_instr(OldLval, NewLval,
+				Instr0, Instr, N0, N1),
+			substitute_lval_in_instr_until_defn(OldLval, NewLval,
+				Instrs0, Instrs, N1, N)
+		)
+	;
+		Uinstr0 = mark_hp(_),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = restore_hp(_),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = free_heap(_),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = store_ticket(_),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = reset_ticket(_, _),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = discard_ticket,
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = prune_ticket,
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = mark_ticket_stack(_),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = prune_tickets_to(_),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = incr_sp(_, _),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = decr_sp(_),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = init_sync_term(_, _),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = fork(_, _, _),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = join_and_terminate(_),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = join_and_continue(_, _),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = c_code(_, _),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	;
+		Uinstr0 = pragma_c(_, _, _, _, _, _, _, _),
+		Instr = Instr0,
+		Instrs = Instrs0,
+		N = N0
+	).
Index: compiler/value_number.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/value_number.m,v
retrieving revision 1.107
diff -u -b -r1.107 value_number.m
--- compiler/value_number.m	2000/10/31 02:15:48	1.107
+++ compiler/value_number.m	2001/03/06 09:52:07
@@ -24,16 +24,6 @@
 	set(label)::in, proc_label::in, counter::in, counter::out,
 	list(instruction)::out, io__state::di, io__state::uo) is det.
 
-	% The main value numbering pass introduces references to temporary
-	% variables whose values need be preserved only within an extended
-	% basic block. The post_main pass looks for references to temporaries
-	% and introduces block instructions whenever it sees them. These
-	% block instructions go from the first reference to a temporary
-	% to the end of its extended basic block.
-
-:- pred value_number__post_main(list(instruction), list(instruction)).
-:- mode value_number__post_main(in, out) is det.
-
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -61,6 +51,14 @@
 	{ livemap__build(Instrs2, MaybeLiveMap) },
 	(
 		{ MaybeLiveMap = yes(LiveMap) },
+		{ \+ (
+			list__member(Instr, Instrs2),
+			Instr = Uinstr - _,
+			( Uinstr = c_code(_, _)
+			; Uinstr = pragma_c(_, _, _, _, _, _, _, _)
+			)
+		) }
+	->
 		vn_debug__livemap_msg(LiveMap),
 		value_number__procedure(Instrs2, LiveMap, UseSet,
 			AllocSet, BreakSet, C1, C, Instrs3),
@@ -68,7 +66,6 @@
 	;
 		% Can't find live lvals and thus can't perform value numbering
 		% if there is a c_code or a pragma_c in the instructions.
-		{ MaybeLiveMap = no },
 		{ C = C1 },
 		{ Instrs = Instrs0 }
 	).
@@ -1123,7 +1120,7 @@
 value_number__boundary_instr(label(_), yes).
 value_number__boundary_instr(goto(_), yes).
 value_number__boundary_instr(computed_goto(_, _), yes).
-value_number__boundary_instr(c_code(_), yes).
+value_number__boundary_instr(c_code(_, _), yes).
 value_number__boundary_instr(if_val(_, _), yes).
 value_number__boundary_instr(incr_hp(_, _, _, _), no).
 value_number__boundary_instr(mark_hp(_), no).
@@ -1141,7 +1138,7 @@
 value_number__boundary_instr(fork(_, _, _), yes).
 value_number__boundary_instr(join_and_terminate(_), yes).
 value_number__boundary_instr(join_and_continue(_, _), yes).
-value_number__boundary_instr(pragma_c(_, _, _, _, _, _, _), yes).
+value_number__boundary_instr(pragma_c(_, _, _, _, _, _, _, _), yes).
 
 %-----------------------------------------------------------------------------%
 
@@ -1175,53 +1172,6 @@
 value_number__no_old_labels([Label | Labels], SoFar) :-
 	\+ set__member(Label, SoFar),
 	value_number__no_old_labels(Labels, SoFar).
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
-value_number__post_main(Instrs0, Instrs) :-
-	value_number__post_main_2(Instrs0, 0, 0, [], Instrs).
-
-	% R is the number of the highest numbered tempr variable seen so far;
-	% R = 0 means we haven't seen any temp variables. Similarly, F is the
-	% highest numbered tempf variable seen so far. RevSofar is a
-	% reversed list of instructions starting with the first instruction
-	% in this block that accesses a temp variable. Invariant: RevSofar
-	% is always empty if R = 0 and F = 0.
-
-:- pred value_number__post_main_2(list(instruction), int, int,
-	list(instruction), list(instruction)).
-:- mode value_number__post_main_2(in, in, in, in, out) is det.
-
-value_number__post_main_2([], R, F, RevSofar, []) :-
-	( RevSofar = [_|_] ->
-		error("procedure ends with fallthrough")
-	; ( R > 0 ; F > 0 ) ->
-		error("procedure ends without closing block")
-	;
-		true
-	).
-value_number__post_main_2([Instr0 | Instrs0], R0, F0, RevSofar, Instrs) :-
-	Instr0 = Uinstr0 - _Comment0,
-	opt_util__count_temps_instr(Uinstr0, R0, R1, F0, F1),
-	( ( R1 > 0 ; F1 > 0) ->
-		( opt_util__can_instr_fall_through(Uinstr0, no) ->
-			list__reverse([Instr0 | RevSofar], BlockInstrs),
-			value_number__post_main_2(Instrs0, 0, 0, [], Instrs1),
-			Instrs = [block(R1, F1, BlockInstrs) - "" | Instrs1]
-		; Uinstr0 = label(_) ->
-			list__reverse(RevSofar, BlockInstrs),
-			value_number__post_main_2(Instrs0, 0, 0, [], Instrs1),
-			Instrs = [block(R1, F1, BlockInstrs) - "", Instr0
-				| Instrs1]
-		;
-			value_number__post_main_2(Instrs0, R1, F1,
-				[Instr0 | RevSofar], Instrs)
-		)
-	;
-		value_number__post_main_2(Instrs0, 0, 0, [], Instrs1),
-		Instrs = [Instr0 | Instrs1]
-	).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
Index: compiler/vn_block.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_block.m,v
retrieving revision 1.67
diff -u -b -r1.67 vn_block.m
--- compiler/vn_block.m	2000/10/31 02:15:48	1.67
+++ compiler/vn_block.m	2001/02/28 15:25:25
@@ -270,7 +270,7 @@
 	vn_block__new_ctrl_node(vn_computed_goto(Vn, Labels), Livemap,
 		Params, VnTables1, VnTables,
 		Liveset0, Liveset, Tuple0, Tuple).
-vn_block__handle_instr(c_code(_),
+vn_block__handle_instr(c_code(_, _),
 		_Livemap, _Params, VnTables, VnTables, Liveset, Liveset,
 		SeenIncr, SeenIncr, Tuple, Tuple) :-
 	error("c_code should not be found in handle_instr").
@@ -373,7 +373,7 @@
 	vn_block__new_ctrl_node(vn_decr_sp(N), Livemap,
 		Params, VnTables0, VnTables,
 		Liveset0, Liveset, Tuple0, Tuple).
-vn_block__handle_instr(pragma_c(_, _, _, _, _, _, _),
+vn_block__handle_instr(pragma_c(_, _, _, _, _, _, _, _),
 		_Livemap, _Params, VnTables, VnTables, Liveset, Liveset,
 		SeenIncr, SeenIncr, Tuple, Tuple) :-
 	error("value numbering not supported for pragma_c").
@@ -929,7 +929,7 @@
 vn_block__is_ctrl_instr(label(_), yes).
 vn_block__is_ctrl_instr(goto(_), yes).
 vn_block__is_ctrl_instr(computed_goto(_, _), yes).
-vn_block__is_ctrl_instr(c_code(_), no).
+vn_block__is_ctrl_instr(c_code(_, _), no).
 vn_block__is_ctrl_instr(if_val(_, _), yes).
 vn_block__is_ctrl_instr(incr_hp(_, _, _, _), no).
 vn_block__is_ctrl_instr(mark_hp(_), yes).
@@ -947,7 +947,7 @@
 vn_block__is_ctrl_instr(fork(_, _, _), yes).
 vn_block__is_ctrl_instr(join_and_terminate(_), yes).
 vn_block__is_ctrl_instr(join_and_continue(_, _), yes).
-vn_block__is_ctrl_instr(pragma_c(_, _, _, _, _, _, _), no).
+vn_block__is_ctrl_instr(pragma_c(_, _, _, _, _, _, _, _), no).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
Index: compiler/vn_cost.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_cost.m,v
retrieving revision 1.45
diff -u -b -r1.45 vn_cost.m
--- compiler/vn_cost.m	2001/01/20 15:42:47	1.45
+++ compiler/vn_cost.m	2001/02/28 15:25:29
@@ -124,7 +124,7 @@
 		vn_cost__rval_cost(Rval, Params, RvalCost),
 		Cost = RvalCost
 	;
-		Uinstr = c_code(_),
+		Uinstr = c_code(_, _),
 		error("c_code found in vn_block_cost")
 	;
 		Uinstr = if_val(Rval, _),
@@ -185,7 +185,7 @@
 		Uinstr = decr_sp(_),
 		Cost = 0
 	;
-		Uinstr = pragma_c(_, _, _, _, _, _, _),
+		Uinstr = pragma_c(_, _, _, _, _, _, _, _),
 		error("pragma_c found in vn_block_cost")
 	;
 		Uinstr = init_sync_term(_, _),
Index: compiler/vn_filter.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_filter.m,v
retrieving revision 1.27
diff -u -b -r1.27 vn_filter.m
--- compiler/vn_filter.m	2000/10/13 04:05:26	1.27
+++ compiler/vn_filter.m	2001/02/28 15:25:51
@@ -141,7 +141,7 @@
 vn_filter__user_instr(goto(_), no).
 vn_filter__user_instr(computed_goto(Rval, _), yes(Rval)).
 vn_filter__user_instr(if_val(Rval, _), yes(Rval)).
-vn_filter__user_instr(c_code(_), _):-
+vn_filter__user_instr(c_code(_, _), _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__user_instr(incr_hp(_, _, Rval, _), yes(Rval)).
 vn_filter__user_instr(mark_hp(_), no).
@@ -155,7 +155,7 @@
 vn_filter__user_instr(prune_tickets_to(Rval), yes(Rval)).
 vn_filter__user_instr(incr_sp(_, _), no).
 vn_filter__user_instr(decr_sp(_), no).
-vn_filter__user_instr(pragma_c(_, _, _, _, _, _, _), _):-
+vn_filter__user_instr(pragma_c(_, _, _, _, _, _, _, _), _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__user_instr(init_sync_term(_, _), _):-
 	error("init_sync_term instruction in vn__filter").
@@ -197,7 +197,7 @@
 vn_filter__replace_in_user_instr(if_val(Rval0, Label), Temp, Defn,
 		if_val(Rval, Label)) :-
 	vn_filter__replace_in_rval(Rval0, Temp, Defn, Rval).
-vn_filter__replace_in_user_instr(c_code(_), _, _, _):-
+vn_filter__replace_in_user_instr(c_code(_, _), _, _, _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__replace_in_user_instr(incr_hp(Lval, Tag, Rval0, Msg), Temp, Defn,
 		incr_hp(Lval, Tag, Rval, Msg)) :-
@@ -228,7 +228,7 @@
 	error("non-user instruction in vn_filter__replace_in_user_instr").
 vn_filter__replace_in_user_instr(decr_sp(_), _, _, _) :-
 	error("non-user instruction in vn_filter__replace_in_user_instr").
-vn_filter__replace_in_user_instr(pragma_c(_, _, _, _, _, _, _), _, _, _):-
+vn_filter__replace_in_user_instr(pragma_c(_, _, _, _, _, _, _, _), _, _, _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__replace_in_user_instr(init_sync_term(_, _), _, _, _):-
 	error("init_sync_term instruction in vn__filter").
@@ -255,7 +255,7 @@
 vn_filter__defining_instr(goto(_), no).
 vn_filter__defining_instr(computed_goto(_, _), no).
 vn_filter__defining_instr(if_val(_, _), no).
-vn_filter__defining_instr(c_code(_), _):-
+vn_filter__defining_instr(c_code(_, _), _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__defining_instr(incr_hp(Lval, _, _, _), yes(Lval)).
 vn_filter__defining_instr(mark_hp(Lval), yes(Lval)).
@@ -269,7 +269,7 @@
 vn_filter__defining_instr(prune_tickets_to(_), no).
 vn_filter__defining_instr(incr_sp(_, _), no).
 vn_filter__defining_instr(decr_sp(_), no).
-vn_filter__defining_instr(pragma_c(_, _, _, _, _, _, _), _):-
+vn_filter__defining_instr(pragma_c(_, _, _, _, _, _, _, _), _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__defining_instr(init_sync_term(_, _), _):-
 	error("init_sync_term instruction in vn__filter").
@@ -309,7 +309,7 @@
 	error("non-def instruction in vn_filter__replace_in_defining_instr").
 vn_filter__replace_in_defining_instr(if_val(_, _), _, _, _) :-
 	error("non-def instruction in vn_filter__replace_in_defining_instr").
-vn_filter__replace_in_defining_instr(c_code(_), _, _, _):-
+vn_filter__replace_in_defining_instr(c_code(_, _), _, _, _):-
 	error("inappropriate instruction in vn__filter").
 vn_filter__replace_in_defining_instr(incr_hp(Lval0, Tag, Rval, Msg), Temp, Defn,
 		incr_hp(Lval, Tag, Rval, Msg)) :-
@@ -347,7 +347,8 @@
 	error("join_and_terminate instruction in vn_filter__replace_in_defining_instr").
 vn_filter__replace_in_defining_instr(join_and_continue(_, _), _, _, _):-
 	error("join_and_continue instruction in vn_filter__replace_in_defining_instr").
-vn_filter__replace_in_defining_instr(pragma_c(_, _, _, _, _, _, _), _, _, _) :-
+vn_filter__replace_in_defining_instr(pragma_c(_, _, _, _, _, _, _, _),
+		_, _, _) :-
 	error("inappropriate instruction in vn__filter").
 
 	% vn_filter__replace_in_lval(Lval0, Old, New, Lval):
Index: compiler/vn_verify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_verify.m,v
retrieving revision 1.28
diff -u -b -r1.28 vn_verify.m
--- compiler/vn_verify.m	2001/02/08 11:37:49	1.28
+++ compiler/vn_verify.m	2001/02/28 15:26:02
@@ -317,7 +317,7 @@
 		NoDeref = NoDeref0,
 		Tested = Tested0
 	;
-		Instr = c_code(_),
+		Instr = c_code(_, _),
 		error("found c_code in vn_verify__tags_instr")
 	;
 		Instr = if_val(Rval, _),
@@ -381,7 +381,7 @@
 		NoDeref = NoDeref0,
 		Tested = Tested0
 	;
-		Instr = pragma_c(_, _, _, _, _, _, _),
+		Instr = pragma_c(_, _, _, _, _, _, _, _),
 		error("found c_code in vn_verify__tags_instr")
 	).
 
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/aditi
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/stream
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing java
cvs diff: Diffing library
Index: library/set.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/set.m,v
retrieving revision 1.56
diff -u -b -r1.56 set.m
--- library/set.m	2001/01/05 03:28:41	1.56
+++ library/set.m	2001/02/28 11:53:47
@@ -186,6 +186,10 @@
 
 :- func set__union(set(T), set(T)) = set(T).
 
+	% `set__union_list(A, B)' is true iff `B' is the union of
+	% all the sets in `A'
+:- func set__union_list(list(set(T))) = set(T).
+
 	% `set__power_union(A, B)' is true iff `B' is the union of
 	% all the sets in `A'
 
@@ -354,6 +358,8 @@
 
 set__union(SetA, SetB, Set) :-
 	set_ordlist__union(SetA, SetB, Set).
+
+set__union_list(Sets) = set_ordlist__union_list(Sets).
 
 set__power_union(Sets, Set) :-
 	set_ordlist__power_union(Sets, Set).
Index: library/set_bbbtree.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/set_bbbtree.m,v
retrieving revision 1.16
diff -u -b -r1.16 set_bbbtree.m
--- library/set_bbbtree.m	2000/11/12 08:51:36	1.16
+++ library/set_bbbtree.m	2001/02/28 09:36:44
@@ -228,6 +228,11 @@
 :- func set_bbbtree__union(set_bbbtree(T), set_bbbtree(T)) = set_bbbtree(T).
 
 
+	% `set_bbbtree__union_list(Sets) = Set' is true iff `Set' is the union
+	% of all the sets in `Sets'
+
+:- func set_bbbtree__union_list(list(set_bbbtree(T))) = set_bbbtree(T).
+
 	% `set_bbbtree__power_union(Sets, Set)' is true iff `Set' is the union
 	% of all the sets in `Sets'
 
@@ -776,6 +781,11 @@
 	set_bbbtree__union_r(LL, NewRL, LSet, Ratio),
 	set_bbbtree__union_r(LR, NewRR, RSet, Ratio),
 	set_bbbtree__concat4(LSet, RSet, V, Set, Ratio).
+
+%------------------------------------------------------------------------------%
+
+set_bbbtree__union_list(ListofSets) = 
+	list__foldl(set_bbbtree__union, ListofSets, set_bbbtree__init).
 
 %------------------------------------------------------------------------------%
 
Index: library/set_ordlist.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/set_ordlist.m,v
retrieving revision 1.13
diff -u -b -r1.13 set_ordlist.m
--- library/set_ordlist.m	2001/01/05 03:28:41	1.13
+++ library/set_ordlist.m	2001/02/28 11:53:11
@@ -170,6 +170,11 @@
 
 :- func set_ordlist__union(set_ordlist(T), set_ordlist(T)) = set_ordlist(T).
 
+	% `set_ordlist__union_list(A, B)' is true iff `B' is the union of
+	% all the sets in `A'
+
+:- func set_ordlist__union_list(list(set_ordlist(T))) = set_ordlist(T).
+
 	% `set_ordlist__power_union(A, B)' is true iff `B' is the union of
 	% all the sets in `A'
 
@@ -369,6 +374,10 @@
 
 set_ordlist__union(Set0, Set1, Set) :-
 	list__merge_and_remove_dups(Set0, Set1, Set).
+
+set_ordlist__union_list(ListofSets) = Set :-
+	set_ordlist__init(Set0),
+	set_ordlist__power_union_2(ListofSets, Set0, Set).
 
 set_ordlist__power_union(SetofSets, Set) :-
 	set_ordlist__init(Set0),
Index: library/set_unordlist.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/set_unordlist.m,v
retrieving revision 1.18
diff -u -b -r1.18 set_unordlist.m
--- library/set_unordlist.m	2001/01/05 03:28:41	1.18
+++ library/set_unordlist.m	2001/02/28 09:36:31
@@ -175,6 +175,12 @@
 :- func set_unordlist__union(set_unordlist(T), set_unordlist(T))
 		= set_unordlist(T).
 
+	% `set_unordlist__union_list(A) = B' is true iff `B' is the union of
+	% all the sets in `A'
+
+:- func set_unordlist__union_list(list(set_unordlist(T)))
+		= set_unordlist(T).
+
 	% `set_unordlist__power_union(A, B)' is true iff `B' is the union of
 	% all the sets in `A'
 
@@ -307,6 +313,9 @@
 
 set_unordlist__union(Set0, Set1, Set) :-
 	list__append(Set1, Set0, Set).
+
+set_unordlist__union_list(LS) = S :-
+	set_unordlist__power_union(LS, S).
 
 set_unordlist__power_union(PS, S) :-
 	set_unordlist__init(S0),
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
Index: tests/general/array_test.m
===================================================================
RCS file: /home/mercury1/repository/tests/general/array_test.m,v
retrieving revision 1.3
diff -u -b -r1.3 array_test.m
--- tests/general/array_test.m	2001/02/20 10:42:17	1.3
+++ tests/general/array_test.m	2001/03/07 01:53:35
@@ -20,64 +20,63 @@
 	{
 		Cmp = lambda([X :: in, Y :: in, Res :: out] is det,
 			compare(Res, X, Y)),
-		array__from_list(Xs, A0),
-		array__to_list(A0, As0),
-		array__max(A0, AMax0),
-		array__min(A0, AMin0),
-		array__size(A0, ASize),
-		array__bounds(A0, AMin1, AMax1),
-		array__bsearch(A0, 4, Cmp, ABsearch),
-		array__set(A0, 8, 100, A1),
-		array__to_list(A1, As1),
-		array__resize(A1, 15, 1000, A2),
-		array__to_list(A2, As2),
-		array__shrink(A2, 10, A3),
-		array__to_list(A3, As3),
-		A4 = array__sort(array(1 `..` 10)),
-		array__to_list(A4, As4),
-		A5 = array__sort(array(list__reverse(1 `..` 10))),
-		array__to_list(A5, As5)
+		array__from_list(Xs, A0)
 	},
+	{ array__to_list(A0, As0) },
 	write_message_int_list("A0: ", As0),
+	{ array__max(A0, AMax0) },
 	write_message_int("AMax0: ", AMax0),
+	{ array__min(A0, AMin0) },
 	write_message_int("AMin0: ", AMin0),
+	{ array__size(A0, ASize) },
 	write_message_int("ASize: ", ASize),
+	{ array__bounds(A0, AMin1, AMax1) },
 	write_message_int("AMin1: ", AMin1),
 	write_message_int("AMax1: ", AMax1),
+	{ array__bsearch(A0, 4, Cmp, ABsearch) },
 	write_message_maybe_int("ABsearch: ", ABsearch),
+	{ array__set(A0, 8, 100, A1) },
+	{ array__to_list(A1, As1) },
 	write_message_int_list("A1: ", As1),
+	{ array__resize(A1, 15, 1000, A2) },
+	{ array__to_list(A2, As2) },
 	write_message_int_list("A2: ", As2),
+	{ array__shrink(A2, 10, A3) },
+	{ array__to_list(A3, As3) },
 	write_message_int_list("A3: ", As3),
+	{ A4 = array__sort(array(1 `..` 10)) },
+	{ array__to_list(A4, As4) },
 	write_message_int_list("A4: ", As4),
+	{ A5 = array__sort(array(list__reverse(1 `..` 10))) },
+	{ array__to_list(A5, As5) },
 	write_message_int_list("A5: ", As5),
-	{
-		bt_array__from_list(0, Xs, B0),
-		bt_array__to_list(B0, Bs0),
-		bt_array__max(B0, BMax0),
-		bt_array__min(B0, BMin0),
-		bt_array__size(B0, BSize),
-		bt_array__bounds(B0, BMin1, BMax1),
-		( bt_array__bsearch(B0, 4, Cmp, BBsearch0) ->
-			BBsearch = yes(BBsearch0)
-		;
-			BBsearch = no
-		),
-		bt_array__set(B0, 8, 100, B1),
-		bt_array__to_list(B1, Bs1),
-		bt_array__resize(B1, 0, 14, 1000, B2),
-		bt_array__to_list(B2, Bs2),
-		bt_array__shrink(B2, 0, 9, B3),
-		bt_array__to_list(B3, Bs3)
-	},
+
+	{ bt_array__from_list(0, Xs, B0) },
+	{ bt_array__to_list(B0, Bs0) },
 	write_message_int_list("B0: ", Bs0),
+	{ bt_array__max(B0, BMax0) },
 	write_message_int("BMax0: ", BMax0),
+	{ bt_array__min(B0, BMin0) },
 	write_message_int("BMin0: ", BMin0),
+	{ bt_array__size(B0, BSize) },
 	write_message_int("BSize: ", BSize),
+	{ bt_array__bounds(B0, BMin1, BMax1) },
 	write_message_int("BMin1: ", BMin1),
 	write_message_int("BMax1: ", BMax1),
+	{ ( bt_array__bsearch(B0, 4, Cmp, BBsearch0) ->
+		BBsearch = yes(BBsearch0)
+	;
+		BBsearch = no
+	) },
 	write_message_maybe_int("BBsearch: ", BBsearch),
+	{ bt_array__set(B0, 8, 100, B1) },
+	{ bt_array__to_list(B1, Bs1) },
 	write_message_int_list("B1: ", Bs1),
+	{ bt_array__resize(B1, 0, 14, 1000, B2) },
+	{ bt_array__to_list(B2, Bs2) },
 	write_message_int_list("B2: ", Bs2),
+	{ bt_array__shrink(B2, 0, 9, B3) },
+	{ bt_array__to_list(B3, Bs3) },
 	write_message_int_list("B3: ", Bs3),
 
 	% Finally, just in case, compare the two implementations.
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list