mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-13 12:53:53 +00:00
Estimated hours taken: weeks Branches: main Implement a mechanism to generate the information required to determine the algorithmic complexity of selected procedures. The basis of the mechanism is a program transformation that wraps up the body of each selected procedure in code that detects top-level (non-recursive) calls, and for each top-level call, records the sizes of the input arguments and information about the cost of the call. For now, the cost information consists only of the number of cells and words allocated during the call, but there is provision for later adding information from a real-time clock. compiler/complexity.m: A new module containing the new transformation. compiler/transform_hlds.m: Add complexity.m to the list of submodules. compiler/mercury_compile.m: Invoke the new module. compiler/notes/compiler_design.html: Mention the new module. compiler/options.m: Add an option, --experimental-complexity. Its argument is a filename that specifies the list of procedures to transform. Add an option, --no-allow-inlining, to disallow all inlining. This is simpler to use than specifying several options to turn off each potential reason to inline procedures. doc/user_guide.texi: Document the new options. The documentation present now is only a shell; it will be expanded later. compiler/table_gen.m: compiler/goal_util.m: Move the predicate for creating renamings from table_gen.m to goal_util.m, since complexity.m also needs it now. In the process, make it more general by allowing outputs to have more complex modes than simply `out'. compiler/goal_util.m: Fix a bug exposed by the new transformation: when renaming goals (e.g. for quantification), rename the variables holding information about term sizes. compiler/handle_options.m: Disable inlining if experimental complexity analysis is enabled. compiler/compile_target_code.m: Pass the --experimental-complexity option on to the linker. library/term_size_prof_builtin.m: Add the Mercury predicates that serve as interfaces to the primitives needed by the experimental complexity transformation. runtime/mercury_term_size.[ch]: Add the implementations of the primitives needed by the experimental complexity transformation. runtime/mercury_wrapper.[ch]: Add global variables holding counters of the numbers of words and cells allocated so far. runtime/mercury_heap.h: Update these global variables when allocating memory. runtime/mercury_complexity.h: New file that contains the definition of the data structures holding the data collected by the experimental complexity transformation. This is separate from mercury_term_size.h, because it needs to be #included in mercury_init.h, the header file of the mkinit-generated <program>_init.c files. runtime/mercury_init.h: runtime/mercury_imp.h: #include mercury_complexity.h. util/mkinit.c: Define and initialize the data structures holding complexity information when given the -X option (mkinit doesn't have long options). Fix some deviations from our coding style. scripts/parse_ml_options.sh-subr.in: Accept the --experiment-complexity option. scripts/c2init.in: Pass the --experiment-complexity option on to mkinit.c. tools/bootcheck: Preserve the files containing the results of complexity analysis, if they exist. tools/makebatch: Allow the specification of EXTRA_MLFLAGS in the generated Mmake.stage.params files.
115 lines
4.0 KiB
C
115 lines
4.0 KiB
C
/*
|
|
** vim:ts=4 sw=4 expandtab
|
|
*/
|
|
/*
|
|
** Copyright (C) 2003 The University of Melbourne.
|
|
** This file may only be copied under the terms of the GNU Library General
|
|
** Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
*/
|
|
|
|
/*
|
|
** mercury_complexity.h
|
|
**
|
|
** This module defines the structures returning the sizes of terms.
|
|
*/
|
|
|
|
#ifndef MR_MERCURY_COMPLEXITY_H
|
|
#define MR_MERCURY_COMPLEXITY_H
|
|
|
|
#define MR_COMPLEXITY_SLOTS_PER_CHUNK 1024
|
|
|
|
/*
|
|
** This type should correspond to the representation of the
|
|
** complexity_is_active type in library/term_size_prof_builtin.m.
|
|
*/
|
|
|
|
typedef struct MR_ComplexityProc_Struct MR_ComplexityProc;
|
|
|
|
typedef enum {
|
|
MR_COMPLEXITY_INPUT_VAR_SIZE,
|
|
MR_COMPLEXITY_INPUT_FIX_SIZE,
|
|
MR_COMPLEXITY_OUTPUT
|
|
} MR_ComplexityArgKind;
|
|
|
|
typedef struct {
|
|
const char *MR_clpai_maybe_name;
|
|
MR_ComplexityArgKind MR_clpai_kind;
|
|
} MR_ComplexityArgInfo;
|
|
|
|
typedef enum {
|
|
MR_COMPLEXITY_IS_INACTIVE,
|
|
MR_COMPLEXITY_IS_ACTIVE
|
|
} MR_ComplexityIsActive;
|
|
|
|
typedef int MR_ComplexityCounter;
|
|
|
|
typedef struct {
|
|
MR_ComplexityCounter MR_clpm_num_words;
|
|
MR_ComplexityCounter MR_clpm_num_cells;
|
|
MR_ComplexityCounter MR_clpm_num_ticks;
|
|
} MR_ComplexityMetrics;
|
|
|
|
typedef struct MR_ComplexityPastSlots_Struct MR_ComplexityPastSlots;
|
|
|
|
struct MR_ComplexityPastSlots_Struct {
|
|
MR_ComplexityMetrics *MR_clpps_metrics;
|
|
int *MR_clpps_sizes;
|
|
MR_ComplexityPastSlots *MR_clpps_previous;
|
|
};
|
|
|
|
/*
|
|
** The MR_ComplexityProc structure contains all the information we have
|
|
** about a procedure whose complexity we are trying to determine
|
|
** experimentally.
|
|
**
|
|
** The MR_clp_full_proc_name field contains the name of the procedure. The
|
|
** format of the name is name/arity-modenum, where name is the a fully module
|
|
** qualified predicate or function name, arity is the user arity (not including
|
|
** the return value for functions), and modenum is the mode number. This field
|
|
** is initialized in the program's mkinit-generated _init.c file and never
|
|
** modified later, but is sanity-checked on every invocation of
|
|
** MR_complexity_is_active.
|
|
**
|
|
** The MR_clp_num_profiled_args field contains the number of profiled input
|
|
** arguments of the procedure.
|
|
** XXX
|
|
** It is initialized and re-initialized on every invocation of
|
|
** MR_complexity_is_active.
|
|
**
|
|
** The MR_clp_is_active field specifies whether the procedure is currently
|
|
** being executed. It is initialized in the program's _init.c file, and updated
|
|
** as necessary by the macros we invoke at the call, exit, fail and redo ports.
|
|
**
|
|
** The MR_clp_metrics field points to an array of MR_COMPLEXITY_SLOTS_PER_CHUNK
|
|
** elements, while the MR_clp_sizes field point to an array of
|
|
** MR_COMPLEXITY_SLOTS_PER_CHUNK times MR_clp_num_profiled_args elements.
|
|
**
|
|
** Each top-level invocation of the procedure allocates a "slot" for its
|
|
** measurement. The slot consists of one element of the MR_clp_metrics array
|
|
** and MR_clp_num_profiled_args consecutive elements of the MR_clp_sizes array.
|
|
** The MR_clp_next_slot_num identifies the next available slot.
|
|
**
|
|
** When we have used up all the slots in the MR_clp_metrics and MR_clp_sizes
|
|
** arrays, we allocate a MR_ComplexityPastSlots structure, move those arrays to
|
|
** the new structure, and allocate a fresh pair of arrays.
|
|
**
|
|
** The full set of measurements for a procedure is thus the initial
|
|
** MR_clp_next_slot_num elements of the MR_clp_metrics and MR_clp_sizes arrays,
|
|
** and the MR_COMPLEXITY_SLOTS_PER_CHUNK elements of each structure linked
|
|
** via MR_clp_past_slots.
|
|
*/
|
|
|
|
struct MR_ComplexityProc_Struct {
|
|
const char *MR_clp_full_proc_name;
|
|
int MR_clp_num_profiled_args;
|
|
int MR_clp_num_args;
|
|
MR_ComplexityArgInfo *MR_clp_arg_infos;
|
|
MR_ComplexityIsActive MR_clp_is_active;
|
|
MR_ComplexityPastSlots *MR_clp_past_slots;
|
|
int MR_clp_next_slot_num;
|
|
MR_ComplexityMetrics *MR_clp_metrics;
|
|
int *MR_clp_sizes;
|
|
};
|
|
|
|
#endif /* MR_MERCURY_COMPLEXITY_H */
|