Files
mercury/compiler/ml_backend.m
Zoltan Somogyi 7ca1a07296 Allow the MLDS backend to generate indexing switches (switches implemented
Estimated hours taken: 16
Branches: main

Allow the MLDS backend to generate indexing switches (switches implemented
more efficiently than just a if-then-else chain) for strings even if the target
language does not support gotos.

Previously, we use always used gotos to break out of search loops
after we found a match:

    do {
        if (we have a match) {
            ... handle the match ...
            goto end
        } else {
            ... handle nonmatches ...
        }
    } while (loop should continue);
    maybe some code to handle the failure of the search
end:

Now, if the "maybe some code" is empty, we prefer to use break statements
if the target language supports this:

    do {
        if (we have a match) {
            ... handle the match ...
            break;
        } else {
            ... handle nonmatches ...
        }
    } while (loop should continue)

If we cannot use either gotos or break statements, we instead use
a boolean variable named "stop_loop":

    stop_loop = 0;
    do {
        if (we have a match) {
            ... handle the match ...
            stop_loop = 1;
        } else {
            ... handle nonmatches ...
        }
    } while (stop_loop == 0 && loop should continue)
    if (stop_loop == 0) {
    	maybe some code to handle the failure of the search
    }

We omit the final if statement if the then-part would be empty.

The break method generates the smallest code, followed by the goto code.
I don't have information on speed, since we don't have a benchmark that
runs long enough, and the compiler itself does not spend any significant
amount of time on string switches. Probably the break method is also the
fastest, simply because it leaves the code looking most like normal C code.
(Some optimizations are harder to apply to code containing gotos, and some
optimizer writers do not bother.)

For C, we now normally prefer to generate code using the second method
(breaks), if we can, though normally "maybe some code" is not empty,
in which case we use the first method (goto).

However, if the value of the --experiment option is set to "use_stop_loop",
we always use the third method, and if it is set to "use_end_label", we always
use the first, even when we could use the second. This allow us to test all
three approaches using the C back end.

With backends that support neither gotos nor break, we always use the third
method (stop_loop).

With backends that don't support gotos but do support breaks, we also always
use the third method. This is because trying to use the second method would
require us to commit to not creating the stop_loop variable BEFORE we know
that the "maybe some code to handle the failure of the search" is empty,
and if it isn't empty, then we don't have the goto method to fall back on.

compiler/ml_string_switch.m:
	Make the change described above. Where possible, make the required
	change not to the original code, but to a version in which common
	parts have been factored out. (Previously, the duplicated code was
	small; now, it would be big.)

compiler/ml_target_util.m:
	A new module containing existing functions that test various properties
	of the target language. Keeping some of those functions in their
	original modules would have introduced a circular dependency.

compiler/ml_switch_gen.m:
	Enable the new functionality by removing the tests that previously
	prevented the compiler from using indexing switches on strings
	if the target language did not support gotos.

	Remove the code moved to ml_target_util.m.

compiler/ml_optimize.m:
compiler/ml_unify_gen.m:
	Remove the code moved to ml_target_util.m.

compiler/ml_backend.m:
compiler/notes/compiler_design.m:
	Add the new module.

compiler/ml_proc_gen.m:
	Delete a predicate that hasn't been used for a long time.

tools/makebatch:
	Fix an old pair of typos.
2011-08-15 06:23:20 +00:00

102 lines
3.2 KiB
Mathematica

%-----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%-----------------------------------------------------------------------------%
% Copyright (C) 2002-2006, 2009-2011 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.
%-----------------------------------------------------------------------------%
%
% The MLDS back-end.
%
% This package includes
% - the MLDS data structure, which is an abstract
% representation of a generic imperative language;
% - the MLDS code generator, which converts HLDS to MLDS;
% - the high-level C back-end, the Java back-end, the .NET back-end,
% and a wrapper for the assembler back-end,
% each of which convert MLDS to their respective target language.
%
% The main part of the assembler back-end, which converts MLDS to GCC's
% internal abstract syntax trees and then invokes the GCC back-end to convert
% this to assembler, is in a package of its own, so that this package doesn't
% depend on the GCC back-end.
%
:- module ml_backend.
:- interface.
:- import_module hlds.
:- import_module parse_tree.
%-----------------------------------------------------------------------------%
:- include_module mlds.
:- include_module ml_target_util.
:- include_module ml_util.
% Phase 4-ml: MLDS-specific HLDS to HLDS transformations and annotations.
:- include_module add_heap_ops. % transformation
:- include_module add_trail_ops. % transformation
% Phase 5-ml: compile HLDS to MLDS
:- include_module ml_proc_gen.
:- include_module ml_code_gen.
:- include_module ml_call_gen.
:- include_module ml_foreign_proc_gen.
:- include_module ml_closure_gen.
:- include_module ml_commit_gen.
:- include_module ml_disj_gen.
:- include_module ml_switch_gen.
:- include_module ml_simplify_switch.
:- include_module ml_string_switch.
:- include_module ml_tag_switch.
:- include_module ml_lookup_switch.
:- include_module ml_type_gen.
:- include_module ml_unify_gen.
:- include_module ml_gen_info.
:- include_module ml_code_util.
:- include_module ml_accurate_gc.
:- include_module ml_global_data.
:- include_module rtti_to_mlds.
% Phase 6-ml: MLDS -> MLDS transformations
:- include_module ml_elim_nested.
:- include_module ml_optimize.
:- include_module ml_tailcall.
% Phase 7-ml: compile MLDS to target code
% MLDS->C back-end
:- include_module mlds_to_c.
% MLDS->Assembler back-end
:- include_module maybe_mlds_to_gcc.
% :- include_module mlds_to_gcc
% :- include_module gcc.
% MLDS->Java back-end
:- include_module mlds_to_java.
:- include_module java_util.
% MLDS->C# back-end.
:- include_module mlds_to_cs.
% MLDS->.NET CLR back-end
:- include_module il_peephole.
:- include_module ilasm.
:- include_module ilds.
:- include_module mlds_to_il.
:- include_module mlds_to_ilasm.
:- include_module mlds_to_managed.
:- implementation.
:- import_module backend_libs.
:- import_module libs.
:- import_module check_hlds. % needed for type_util, mode_util,
% and polymorphism.
:- import_module mdbcomp.
:- end_module ml_backend.
%-----------------------------------------------------------------------------%