diff: fix the value numbering bug reported by Simon

Zoltan Somogyi zs at cs.mu.OZ.AU
Fri Nov 6 17:16:49 AEDT 1998


Fix the problem that was causing tests/hard_coded/nondet_ctrl_vn to fail
sporadically when compiled with value numbering.

compiler/value_number.m:
	Put a fence around instructions of the form 

		if_val(Cond, do_redo|do_fail)

	to prevent value numbering from moving instructions (e.g. assignments
	to stack slots) across such instructions.

	The bug with nondet_ctrl_vn was moving an assigment to MR_stackvar(1)
	from before to after the if_val, causing MR_stackvar(1) to become
	undefined at the destination label. (The failure was only sporadic
	because the garbage in MR_stackvar(1) had a 50/50 chance of passing
	the simple comparison which was its only use. Whether the executable
	was compiled with dynamic linking or not affected the value of
	this garbage.)

	The default way of handling goto and computed_goto instructions
	effectively puts a fence around those instructions, so we don't need
	to handle them specially when the label(s) involved include do_redo
	and/or do_fail.

	Assignments to nondet stack control slots already have a similar
	fencing-in treatment.

Zoltan.

Index: value_number.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/value_number.m,v
retrieving revision 1.95
diff -u -u -c -r1.95 value_number.m
/usr/local/bin/diff: conflicting specifications of output style
*** value_number.m	1998/07/29 08:53:46	1.95
--- value_number.m	1998/11/06 06:14:30
***************
*** 106,115 ****
  	% Our caller will break the code sequence at these labels.
  	%
  	% Mkframe operations also change curfr, and therefore get the
! 	% same treatment. We also apply this treatment to assignments
! 	% to the control slots in nondet stack frames, since otherwise
! 	% a bug in the rest of value numbering may cause them to be
! 	% improperly deleted.
  
  :- pred value_number__prepare_for_vn(list(instruction), proc_label,
  	bool, set(label), set(label), int, int, list(instruction)).
--- 106,117 ----
  	% Our caller will break the code sequence at these labels.
  	%
  	% Mkframe operations also change curfr, and therefore get the
! 	% same treatment. We also apply this treatment to (1) assignments to
! 	% the control slots in nondet stack frames, since otherwise a bug
! 	% in the rest of value numbering may cause them to be improperly
! 	% deleted, and (b) uses of those control slots in the form of
! 	% branches to do_redo and do_fail, since otherwise assignments
! 	% to stack variables may be moved across them.
  
  :- pred value_number__prepare_for_vn(list(instruction), proc_label,
  	bool, set(label), set(label), int, int, list(instruction)).
***************
*** 122,145 ****
  		SeenAlloc, AllocSet, BreakSet, N0, N, Instrs) :-
  	Instr0 = Uinstr0 - _Comment,
  	( Uinstr0 = if_val(Test, TrueAddr) ->
! 		( Instrs0 = [label(FalseLabelPrime) - _ | _] ->
! 			FalseLabel = FalseLabelPrime,
! 			FalseAddr = label(FalseLabel),
  			N1 = N0
  		;
! 			FalseLabel = local(ProcLabel, N0),
! 			FalseAddr = label(FalseLabel),
! 			N1 is N0 + 1
  		),
  		value_number__breakup_complex_if(Test, TrueAddr, FalseAddr,
! 			FalseAddr, ProcLabel, N1, N2, IfInstrs),
  		value_number__prepare_for_vn(Instrs0, ProcLabel,
! 			SeenAlloc, AllocSet, BreakSet, N2, N, Instrs1),
! 		( N1 = N0 ->
! 			list__append(IfInstrs, Instrs1, Instrs)
  		;
! 			LabelInstr = label(FalseLabel) - "vn false label",
! 			list__append(IfInstrs, [LabelInstr | Instrs1], Instrs)
  		)
  	; Uinstr0 = incr_hp(_, _, _, _) ->
  		( SeenAlloc = yes ->
--- 124,164 ----
  		SeenAlloc, AllocSet, BreakSet, N0, N, Instrs) :-
  	Instr0 = Uinstr0 - _Comment,
  	( Uinstr0 = if_val(Test, TrueAddr) ->
! 		( ( TrueAddr = do_redo ; TrueAddr = do_fail ) ->
! 			MaybeBeforeLabel = yes(local(ProcLabel, N0)),
! 			N1 is N0 + 1
! 		;
! 			MaybeBeforeLabel = no,
  			N1 = N0
+ 		),
+ 		( Instrs0 = [label(OldFalseLabel) - _ | _] ->
+ 			FalseLabel = OldFalseLabel,
+ 			MaybeNewFalseLabel = no,
+ 			N2 = N1
  		;
! 			FalseLabel = local(ProcLabel, N1),
! 			MaybeNewFalseLabel = yes(FalseLabel),
! 			N2 is N1 + 1
  		),
+ 		FalseAddr = label(FalseLabel),
  		value_number__breakup_complex_if(Test, TrueAddr, FalseAddr,
! 			FalseAddr, ProcLabel, N2, N3, IfInstrs),
  		value_number__prepare_for_vn(Instrs0, ProcLabel,
! 			SeenAlloc, AllocSet, BreakSet0, N3, N, Instrs1),
! 		( MaybeNewFalseLabel = yes(NewFalseLabel) ->
! 			FalseInstr = label(NewFalseLabel) - "vn false label",
! 			list__append(IfInstrs, [FalseInstr | Instrs1], Instrs2)
! 		;
! 			list__append(IfInstrs, Instrs1, Instrs2)
! 		),
! 		( MaybeBeforeLabel = yes(BeforeLabel) ->
! 			set__insert(BreakSet0, BeforeLabel, BreakSet1),
! 			set__insert(BreakSet1, FalseLabel, BreakSet),
! 			BeforeInstr = label(BeforeLabel) - "vn before label",
! 			Instrs = [BeforeInstr | Instrs2]
  		;
! 			BreakSet = BreakSet0,
! 			Instrs = Instrs2
  		)
  	; Uinstr0 = incr_hp(_, _, _, _) ->
  		( SeenAlloc = yes ->



More information about the developers mailing list