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