[m-rev.] for review: improve debugging support for il grade.
Peter Ross
pro at missioncriticalit.com
Tue Nov 4 05:05:52 AEDT 2003
On Sat, Nov 01, 2003 at 12:50:49PM +0100, Peter Ross wrote:
> On Sat, Nov 01, 2003 at 09:05:49PM +1100, Fergus Henderson wrote:
> > On 31-Oct-2003, Peter Ross <pro at missioncriticalit.com> wrote:
> > > On Wed, Oct 29, 2003 at 10:01:17AM +1100, Fergus Henderson wrote:
> > > > On 28-Oct-2003, Peter Ross <pro at missioncriticalit.com> wrote:
> > > > > Improve the support for debugging in the il grade, by not optimizing
> > > > > the generated il code, unless needed for verifiability.
> > > > >
> > > > > Using
> > > > > mmc --make --grade il --target-debug -O0 diff
> > > > > now generates code which is relatively easier to debug in an IL
> > > > > debugger.
> > > >
> > > > This is a good idea, but whether or not the generated IL code is
> > > > peephole optimized should depend on the "-O" setting, not on whether
> > > > or not --target-debug is specified. Otherwise there's too much danger
> > > > of Heisenbugs (bugs which go away when you enabled debugging).
> > > >
> > > > Currently peephole optimization is enabled at "-O0".
> > > > I'd be happy to change that so that it was instead enabled at "-O1"
> > > > for the IL back-end if and only if this speeds up compilation at "-O0".
> > > >
> > > > Otherwise, I'd say use "--target-debug -O-1" or
> > > > "--target-debug -O0 --no-optimize-peep" if you want
> > > > the IL code to be maximally easy to debug.
> > > > If that is too complicated, we could consider introducing
> > > > a new option (perhaps "--opt-debug", by analogy with to "--opt-space"?),
> > > > which disabled optimizations that inhibit debugging.
> > >
> > > IMHO when compiling Mercury with debugging turned on at the default
> > > optimization level, one should have a reasonable debugging experience.
> >
> > For Mercury debugging, I agree. That's why we default to --no-trace-optimized,
> > and why --trace deep turns off all optimizations that would inhibit debugging
> > unless --trace-optimized is specified.
> >
> > But for --target-debug, the argument is much less strong. If you're
> > debugging things at the level of the target code, you're already
> > looking under the hood. That's why we default to --c-optimize, even if
> > --target-debug is specified.
> >
> > I guess for IL it may be a bit different, since we don't support mdb for the
> > IL back-end yet.
> >
> I understand what you mean.
>
> This is what I believe should change.
>
> --debug should be allowed on the il backend.
>
> When --debug is enabled it implies --trace-debug.
>
> --no-trace-optimized should turn off --il-peephole-optimize.
>
> The peephole optimization phase should look at --verifiable-code and
> --il-peephole-optimization when deciding what type of peephole
> optimization to do.
>
> This I believe would satisfy us all.
>
Hi,
===================================================================
Estimated hours taken: 4
Branches: main
Improve the support for debugging in the il grade, by not optimizing
the generated il code, unless needed for verifiability.
Using
mmc --make --grade il --debug diff
now generates code which is relatively easier to debug in an IL
debugger.
compiler/handle_options.m:
--debug imples --target-debug for the il backend.
if debugging and --no-trace-optimize and il backend then
--no-optimize-peep.
Allow --debug as valid option for the il backend.
compiler/mlds_to_ilasm.m:
Use --verifiable-code and --optimize-peep to decide what level
of peephole optimization is needed to be done.
compiler/il_peephole.m:
Change the peephole optimizer so that it can do all peephole
optimizations, or only those which are needed for
verifiability.
diff -u compiler/il_peephole.m compiler/il_peephole.m
--- compiler/il_peephole.m
+++ compiler/il_peephole.m
@@ -38,9 +38,9 @@
:- import_module bool, list.
- % Peephole optimize a list of instructions.
- % Taking into account whether or not we are generating debuggable
- % code.
+ % il_peephole__optimize(VerifyOnly, IL0, IL)
+ % Peephole optimize a list of instructions, possibly only doing
+ % those optimizations which are necessary for verifiable code.
:- pred il_peephole__optimize(bool::in,
list(ilasm__decl)::in, list(ilasm__decl)::out) is det.
@@ -59,25 +59,25 @@
% when we find a sequence we can't optimize, we back up and try
% to optimize the sequence starting with the previous instruction.
-optimize(TargetDebug, Decls0, Decls) :-
- list__map_foldl(optimize_decl(TargetDebug), Decls0, Decls, no, _Mod).
+optimize(VerifyOnly, Decls0, Decls) :-
+ list__map_foldl(optimize_decl(VerifyOnly), Decls0, Decls, no, _Mod).
% Mod is a bool that says whether the code was modified as a
% result of the optimization (that is, whether Decl \= Decl0).
% This can be used to decide whether to keep repeat the
% optimizations.
:- pred optimize_decl(bool::in, decl::in, decl::out, bool::in, bool::out) is det.
-optimize_decl(TargetDebug, Decl0, Decl, Mod0, Mod) :-
+optimize_decl(VerifyOnly, Decl0, Decl, Mod0, Mod) :-
( Decl0 = class(A, B, C, D, ClassMembers0) ->
- list__map_foldl(optimize_class_member(TargetDebug),
+ list__map_foldl(optimize_class_member(VerifyOnly),
ClassMembers0, ClassMembers, Mod0, Mod),
Decl = class(A, B, C, D, ClassMembers)
; Decl0 = method(A, MethodDecls0) ->
- list__map_foldl(optimize_method_decl(TargetDebug), MethodDecls0,
+ list__map_foldl(optimize_method_decl(VerifyOnly), MethodDecls0,
MethodDecls, Mod0, Mod),
Decl = method(A, MethodDecls)
; Decl0 = namespace(A, NamespaceDecls0) ->
- list__map_foldl(optimize_decl(TargetDebug), NamespaceDecls0,
+ list__map_foldl(optimize_decl(VerifyOnly), NamespaceDecls0,
NamespaceDecls, Mod0, Mod),
Decl = namespace(A, NamespaceDecls)
;
@@ -87,9 +87,9 @@
:- pred optimize_class_member(bool::in, class_member::in, class_member::out,
bool::in, bool::out) is det.
-optimize_class_member(TargetDebug, Decl0, Decl, Mod0, Mod) :-
+optimize_class_member(VerifyOnly, Decl0, Decl, Mod0, Mod) :-
( Decl0 = method(A, MethodDecls0) ->
- list__map_foldl(optimize_method_decl(TargetDebug), MethodDecls0,
+ list__map_foldl(optimize_method_decl(VerifyOnly), MethodDecls0,
MethodDecls1, Mod0, Mod),
( Mod = yes ->
% find the new maxstack
@@ -119,9 +119,9 @@
:- pred optimize_method_decl(bool::in,
method_body_decl::in, method_body_decl::out,
bool::in, bool::out) is det.
-optimize_method_decl(TargetDebug, Decl0, Decl, Mod0, Mod) :-
+optimize_method_decl(VerifyOnly, Decl0, Decl, Mod0, Mod) :-
( Decl0 = instrs(Instrs0) ->
- optimize_instrs(TargetDebug, Instrs0, Instrs, Mod1),
+ optimize_instrs(VerifyOnly, Instrs0, Instrs, Mod1),
bool__or(Mod0, Mod1, Mod),
Decl = instrs(Instrs)
;
@@ -131,15 +131,15 @@
:- pred optimize_instrs(bool::in, instrs::in, instrs::out, bool::out) is det.
-optimize_instrs(TargetDebug, Instrs0, Instrs, Mod) :-
- optimize_2(TargetDebug, Instrs0, Instrs, Mod).
+optimize_instrs(VerifyOnly, Instrs0, Instrs, Mod) :-
+ optimize_2(VerifyOnly, Instrs0, Instrs, Mod).
:- pred optimize_2(bool, instrs, instrs, bool).
:- mode optimize_2(in, in, out, out) is det.
optimize_2(_, [], [], no).
-optimize_2(TargetDebug, [Instr0 | Instrs0], Instrs, Mod) :-
- optimize_2(TargetDebug, Instrs0, Instrs1, Mod0),
- opt_instr(TargetDebug, Instr0, Instrs1, Instrs, Mod1),
+optimize_2(VerifyOnly, [Instr0 | Instrs0], Instrs, Mod) :-
+ optimize_2(VerifyOnly, Instrs0, Instrs1, Mod0),
+ opt_instr(VerifyOnly, Instr0, Instrs1, Instrs, Mod1),
bool__or(Mod0, Mod1, Mod).
% Try to optimize the beginning of the given instruction sequence.
@@ -148,12 +148,12 @@
:- pred opt_instr(bool, instr, instrs, instrs, bool).
:- mode opt_instr(in, in, in, out, out) is det.
-opt_instr(TargetDebug, Instr0, Instrs0, Instrs, Mod) :-
+opt_instr(VerifyOnly, Instr0, Instrs0, Instrs, Mod) :-
(
- match(Instr0, TargetDebug, Instrs0, Instrs2)
+ match(Instr0, VerifyOnly, Instrs0, Instrs2)
->
( Instrs2 = [Instr2 | Instrs3] ->
- opt_instr(TargetDebug, Instr2, Instrs3, Instrs, _)
+ opt_instr(VerifyOnly, Instr2, Instrs3, Instrs, _)
;
Instrs = Instrs2
),
diff -u compiler/mlds_to_ilasm.m compiler/mlds_to_ilasm.m
--- compiler/mlds_to_ilasm.m
+++ compiler/mlds_to_ilasm.m
@@ -123,14 +123,23 @@
generate_il(MLDS, ILAsm0, ForeignLangs),
- % Perform peephole optimization if requested.
+ % Perform peephole optimization if requested. If peephole
+ % optimization was not requested, we may still need to invoke
+ % the peephole optimization pass, because some of the peephole
+ % optimizations are actually needed for verifiability of the
+ % generated IL.
globals__io_lookup_bool_option(optimize_peep, Peephole),
+ globals__io_lookup_bool_option(verifiable_code, Verifiable),
( { Peephole = yes } ->
- globals__io_lookup_bool_option(target_debug, TargetDebug),
- { il_peephole__optimize(TargetDebug, ILAsm0, ILAsm) }
+ { VerifyOnly = no },
+ { il_peephole__optimize(VerifyOnly, ILAsm0, ILAsm) }
+ ; { Verifiable = yes } ->
+ { VerifyOnly = yes },
+ { il_peephole__optimize(VerifyOnly, ILAsm0, ILAsm) }
;
{ ILAsm0 = ILAsm }
),
+
% Output the assembly.
ilasm__output(ILAsm),
only in patch2:
--- compiler/handle_options.m 26 Oct 2003 18:08:23 -0000 1.189
+++ compiler/handle_options.m 3 Nov 2003 17:57:45 -0000
@@ -386,6 +386,15 @@
globals__io_set_option(optimize_dead_procs, bool(yes))
;
[]
+ ),
+
+
+ % On the .NET backend we will be using a language independent
+ % debugger not mdb. Thus --debug has to imply --target-debug.
+ ( { given_trace_level_is_none(TraceLevel) = no } ->
+ globals__io_set_option(target_debug, bool(yes))
+ ;
+ []
)
;
[]
@@ -747,7 +756,17 @@
bool(no)),
globals__io_set_option(optimize_saved_vars_cell,
bool(no)),
- globals__io_set_option(loop_invariants, bool(no))
+ globals__io_set_option(loop_invariants, bool(no)),
+
+ % For the IL backend we turn off optimize_peep
+ % so that we don't optimize away references to the
+ % local variables of a procedure.
+ ( { Target = il } ->
+ globals__io_set_option(optimize_peep,
+ bool(no))
+ ;
+ []
+ )
;
[]
),
@@ -852,6 +871,7 @@
(
{ given_trace_level_is_none(TraceLevel) = yes
; HighLevel = no, Target = c
+ ; Target = il
}
->
[]
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.189
diff -u -r1.189 handle_options.m
--- compiler/handle_options.m 26 Oct 2003 18:08:23 -0000 1.189
+++ compiler/handle_options.m 3 Nov 2003 17:57:45 -0000
@@ -386,6 +386,15 @@
globals__io_set_option(optimize_dead_procs, bool(yes))
;
[]
+ ),
+
+
+ % On the .NET backend we will be using a language independent
+ % debugger not mdb. Thus --debug has to imply --target-debug.
+ ( { given_trace_level_is_none(TraceLevel) = no } ->
+ globals__io_set_option(target_debug, bool(yes))
+ ;
+ []
)
;
[]
@@ -747,7 +756,17 @@
bool(no)),
globals__io_set_option(optimize_saved_vars_cell,
bool(no)),
- globals__io_set_option(loop_invariants, bool(no))
+ globals__io_set_option(loop_invariants, bool(no)),
+
+ % For the IL backend we turn off optimize_peep
+ % so that we don't optimize away references to the
+ % local variables of a procedure.
+ ( { Target = il } ->
+ globals__io_set_option(optimize_peep,
+ bool(no))
+ ;
+ []
+ )
;
[]
),
@@ -852,6 +871,7 @@
(
{ given_trace_level_is_none(TraceLevel) = yes
; HighLevel = no, Target = c
+ ; Target = il
}
->
[]
Index: compiler/il_peephole.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/il_peephole.m,v
retrieving revision 1.8
diff -u -r1.8 il_peephole.m
--- compiler/il_peephole.m 15 Mar 2003 03:08:52 -0000 1.8
+++ compiler/il_peephole.m 3 Nov 2003 17:57:45 -0000
@@ -36,12 +36,14 @@
:- import_module ml_backend__ilasm.
-:- import_module list.
+:- import_module bool, list.
- % Peephole optimize a list of instructions.
+ % il_peephole__optimize(VerifyOnly, IL0, IL)
+ % Peephole optimize a list of instructions, possibly only doing
+ % those optimizations which are necessary for verifiable code.
-:- pred il_peephole__optimize(list(ilasm__decl)::in, list(ilasm__decl)::out)
- is det.
+:- pred il_peephole__optimize(bool::in,
+ list(ilasm__decl)::in, list(ilasm__decl)::out) is det.
:- implementation.
@@ -57,25 +59,25 @@
% when we find a sequence we can't optimize, we back up and try
% to optimize the sequence starting with the previous instruction.
-optimize(Decls0, Decls) :-
- list__map_foldl(optimize_decl, Decls0, Decls, no, _Mod).
+optimize(VerifyOnly, Decls0, Decls) :-
+ list__map_foldl(optimize_decl(VerifyOnly), Decls0, Decls, no, _Mod).
% Mod is a bool that says whether the code was modified as a
% result of the optimization (that is, whether Decl \= Decl0).
% This can be used to decide whether to keep repeat the
% optimizations.
-:- pred optimize_decl(decl::in, decl::out, bool::in, bool::out) is det.
-optimize_decl(Decl0, Decl, Mod0, Mod) :-
+:- pred optimize_decl(bool::in, decl::in, decl::out, bool::in, bool::out) is det.
+optimize_decl(VerifyOnly, Decl0, Decl, Mod0, Mod) :-
( Decl0 = class(A, B, C, D, ClassMembers0) ->
- list__map_foldl(optimize_class_member, ClassMembers0,
- ClassMembers, Mod0, Mod),
+ list__map_foldl(optimize_class_member(VerifyOnly),
+ ClassMembers0, ClassMembers, Mod0, Mod),
Decl = class(A, B, C, D, ClassMembers)
; Decl0 = method(A, MethodDecls0) ->
- list__map_foldl(optimize_method_decl, MethodDecls0,
+ list__map_foldl(optimize_method_decl(VerifyOnly), MethodDecls0,
MethodDecls, Mod0, Mod),
Decl = method(A, MethodDecls)
; Decl0 = namespace(A, NamespaceDecls0) ->
- list__map_foldl(optimize_decl, NamespaceDecls0,
+ list__map_foldl(optimize_decl(VerifyOnly), NamespaceDecls0,
NamespaceDecls, Mod0, Mod),
Decl = namespace(A, NamespaceDecls)
;
@@ -83,11 +85,11 @@
Decl0 = Decl
).
-:- pred optimize_class_member(class_member::in, class_member::out,
+:- pred optimize_class_member(bool::in, class_member::in, class_member::out,
bool::in, bool::out) is det.
-optimize_class_member(Decl0, Decl, Mod0, Mod) :-
+optimize_class_member(VerifyOnly, Decl0, Decl, Mod0, Mod) :-
( Decl0 = method(A, MethodDecls0) ->
- list__map_foldl(optimize_method_decl, MethodDecls0,
+ list__map_foldl(optimize_method_decl(VerifyOnly), MethodDecls0,
MethodDecls1, Mod0, Mod),
( Mod = yes ->
% find the new maxstack
@@ -114,11 +116,12 @@
Decl0 = Decl
).
-:- pred optimize_method_decl(method_body_decl::in, method_body_decl::out,
+:- pred optimize_method_decl(bool::in,
+ method_body_decl::in, method_body_decl::out,
bool::in, bool::out) is det.
-optimize_method_decl(Decl0, Decl, Mod0, Mod) :-
+optimize_method_decl(VerifyOnly, Decl0, Decl, Mod0, Mod) :-
( Decl0 = instrs(Instrs0) ->
- optimize_instrs(Instrs0, Instrs, Mod1),
+ optimize_instrs(VerifyOnly, Instrs0, Instrs, Mod1),
bool__or(Mod0, Mod1, Mod),
Decl = instrs(Instrs)
;
@@ -126,31 +129,31 @@
Decl0 = Decl
).
-:- pred optimize_instrs(instrs::in, instrs::out, bool::out) is det.
+:- pred optimize_instrs(bool::in, instrs::in, instrs::out, bool::out) is det.
-optimize_instrs(Instrs0, Instrs, Mod) :-
- optimize_2(Instrs0, Instrs, Mod).
+optimize_instrs(VerifyOnly, Instrs0, Instrs, Mod) :-
+ optimize_2(VerifyOnly, Instrs0, Instrs, Mod).
-:- pred optimize_2(instrs, instrs, bool).
-:- mode optimize_2(in, out, out) is det.
-optimize_2([], [], no).
-optimize_2([Instr0 | Instrs0], Instrs, Mod) :-
- optimize_2(Instrs0, Instrs1, Mod0),
- opt_instr(Instr0, Instrs1, Instrs, Mod1),
+:- pred optimize_2(bool, instrs, instrs, bool).
+:- mode optimize_2(in, in, out, out) is det.
+optimize_2(_, [], [], no).
+optimize_2(VerifyOnly, [Instr0 | Instrs0], Instrs, Mod) :-
+ optimize_2(VerifyOnly, Instrs0, Instrs1, Mod0),
+ opt_instr(VerifyOnly, Instr0, Instrs1, Instrs, Mod1),
bool__or(Mod0, Mod1, Mod).
% Try to optimize the beginning of the given instruction sequence.
% If successful, try it again.
-:- pred opt_instr(instr, instrs, instrs, bool).
-:- mode opt_instr(in, in, out, out) is det.
+:- pred opt_instr(bool, instr, instrs, instrs, bool).
+:- mode opt_instr(in, in, in, out, out) is det.
-opt_instr(Instr0, Instrs0, Instrs, Mod) :-
+opt_instr(VerifyOnly, Instr0, Instrs0, Instrs, Mod) :-
(
- match(Instr0, Instrs0, Instrs2)
+ match(Instr0, VerifyOnly, Instrs0, Instrs2)
->
( Instrs2 = [Instr2 | Instrs3] ->
- opt_instr(Instr2, Instrs3, Instrs, _)
+ opt_instr(VerifyOnly, Instr2, Instrs3, Instrs, _)
;
Instrs = Instrs2
),
@@ -163,9 +166,11 @@
%-----------------------------------------------------------------------------%
% Look for code patterns that can be optimized, and optimize them.
+ % The second argument says whether or not to only do the optimizations
+ % which are needed for verifiability.
-:- pred match(instr, instrs, instrs).
-:- mode match(in, in, out) is semidet.
+:- pred match(instr, bool, instrs, instrs).
+:- mode match(in, in, in, out) is semidet.
% If a ret is followed by anything other than a label,
% then we can delete the instruction that follows,
@@ -177,7 +182,7 @@
% Push ret past nops so we can find instructions on the other
% side of them (but don't eliminate them because they may be
% useful).
-match(ret, Instrs0, Replacement) :-
+match(ret, _, Instrs0, Replacement) :-
list__takewhile((pred(X::in) is semidet :-
X \= label(_)
), Instrs0, PreLabel, NextInstrs0),
@@ -194,7 +199,8 @@
% to just the return.
% NOTE: We only look for forwards branches.
-match(br(label_target(Label)), Instrs0, Instrs) :-
+match(br(label_target(Label)), VerifyOnly, Instrs0, Instrs) :-
+ VerifyOnly = no,
list__takewhile((pred(X::in) is semidet :-
X \= label(Label)
), Instrs0, _, [label(Label) | NextInstrs0]),
@@ -214,7 +220,8 @@
% This might be slightly denser, and is easier to detect and
% remove if it turns out the local is not used.
-match(stloc(Var), Instrs0, Instrs) :-
+match(stloc(Var), VerifyOnly, Instrs0, Instrs) :-
+ VerifyOnly = no,
% The pattern
skip_nops(Instrs0, Instrs1, Nops),
Instrs1 = [ldloc(Var) | Rest],
@@ -235,7 +242,8 @@
% dup
% stloc(X)
-match(ldc(Type, Const), [stloc(Var)| Instrs0], Instrs) :-
+match(ldc(Type, Const), VerifyOnly, [stloc(Var)| Instrs0], Instrs) :-
+ VerifyOnly = no,
% The pattern
list__takewhile((pred(X::in) is semidet :-
X \= ldloc(Var),
@@ -254,7 +262,8 @@
Instrs = list__append(Replacement, Rest).
% Two patterns begin with start_scope.
-match(start_block(scope(Locals), Id)) -->
+match(start_block(scope(Locals), Id), VerifyOnly) -->
+ { VerifyOnly = no },
(
match_start_scope_1(start_block(scope(Locals), Id))
->
Index: compiler/mlds_to_ilasm.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_ilasm.m,v
retrieving revision 1.21
diff -u -r1.21 mlds_to_ilasm.m
--- compiler/mlds_to_ilasm.m 15 Mar 2003 03:09:01 -0000 1.21
+++ compiler/mlds_to_ilasm.m 3 Nov 2003 17:57:51 -0000
@@ -123,13 +123,23 @@
generate_il(MLDS, ILAsm0, ForeignLangs),
- % Perform peephole optimization if requested.
+ % Perform peephole optimization if requested. If peephole
+ % optimization was not requested, we may still need to invoke
+ % the peephole optimization pass, because some of the peephole
+ % optimizations are actually needed for verifiability of the
+ % generated IL.
globals__io_lookup_bool_option(optimize_peep, Peephole),
- { Peephole = yes ->
- il_peephole__optimize(ILAsm0, ILAsm)
+ globals__io_lookup_bool_option(verifiable_code, Verifiable),
+ ( { Peephole = yes } ->
+ { VerifyOnly = no },
+ { il_peephole__optimize(VerifyOnly, ILAsm0, ILAsm) }
+ ; { Verifiable = yes } ->
+ { VerifyOnly = yes },
+ { il_peephole__optimize(VerifyOnly, ILAsm0, ILAsm) }
;
- ILAsm0 = ILAsm
- },
+ { ILAsm0 = ILAsm }
+ ),
+
% Output the assembly.
ilasm__output(ILAsm),
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list