machine-dialect 0.1.0a1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- machine_dialect/__main__.py +667 -0
- machine_dialect/agent/__init__.py +5 -0
- machine_dialect/agent/agent.py +360 -0
- machine_dialect/ast/__init__.py +95 -0
- machine_dialect/ast/ast_node.py +35 -0
- machine_dialect/ast/call_expression.py +82 -0
- machine_dialect/ast/dict_extraction.py +60 -0
- machine_dialect/ast/expressions.py +439 -0
- machine_dialect/ast/literals.py +309 -0
- machine_dialect/ast/program.py +35 -0
- machine_dialect/ast/statements.py +1433 -0
- machine_dialect/ast/tests/test_ast_string_representation.py +62 -0
- machine_dialect/ast/tests/test_boolean_literal.py +29 -0
- machine_dialect/ast/tests/test_collection_hir.py +138 -0
- machine_dialect/ast/tests/test_define_statement.py +142 -0
- machine_dialect/ast/tests/test_desugar.py +541 -0
- machine_dialect/ast/tests/test_foreach_desugar.py +245 -0
- machine_dialect/cfg/__init__.py +6 -0
- machine_dialect/cfg/config.py +156 -0
- machine_dialect/cfg/examples.py +221 -0
- machine_dialect/cfg/generate_with_ai.py +187 -0
- machine_dialect/cfg/openai_generation.py +200 -0
- machine_dialect/cfg/parser.py +94 -0
- machine_dialect/cfg/tests/__init__.py +1 -0
- machine_dialect/cfg/tests/test_cfg_parser.py +252 -0
- machine_dialect/cfg/tests/test_config.py +188 -0
- machine_dialect/cfg/tests/test_examples.py +391 -0
- machine_dialect/cfg/tests/test_generate_with_ai.py +354 -0
- machine_dialect/cfg/tests/test_openai_generation.py +256 -0
- machine_dialect/codegen/__init__.py +5 -0
- machine_dialect/codegen/bytecode_module.py +89 -0
- machine_dialect/codegen/bytecode_serializer.py +300 -0
- machine_dialect/codegen/opcodes.py +101 -0
- machine_dialect/codegen/register_codegen.py +1996 -0
- machine_dialect/codegen/symtab.py +208 -0
- machine_dialect/codegen/tests/__init__.py +1 -0
- machine_dialect/codegen/tests/test_array_operations_codegen.py +295 -0
- machine_dialect/codegen/tests/test_bytecode_serializer.py +185 -0
- machine_dialect/codegen/tests/test_register_codegen_ssa.py +324 -0
- machine_dialect/codegen/tests/test_symtab.py +418 -0
- machine_dialect/codegen/vm_serializer.py +621 -0
- machine_dialect/compiler/__init__.py +18 -0
- machine_dialect/compiler/compiler.py +197 -0
- machine_dialect/compiler/config.py +149 -0
- machine_dialect/compiler/context.py +149 -0
- machine_dialect/compiler/phases/__init__.py +19 -0
- machine_dialect/compiler/phases/bytecode_optimization.py +90 -0
- machine_dialect/compiler/phases/codegen.py +40 -0
- machine_dialect/compiler/phases/hir_generation.py +39 -0
- machine_dialect/compiler/phases/mir_generation.py +86 -0
- machine_dialect/compiler/phases/optimization.py +110 -0
- machine_dialect/compiler/phases/parsing.py +39 -0
- machine_dialect/compiler/pipeline.py +143 -0
- machine_dialect/compiler/tests/__init__.py +1 -0
- machine_dialect/compiler/tests/test_compiler.py +568 -0
- machine_dialect/compiler/vm_runner.py +173 -0
- machine_dialect/errors/__init__.py +32 -0
- machine_dialect/errors/exceptions.py +369 -0
- machine_dialect/errors/messages.py +82 -0
- machine_dialect/errors/tests/__init__.py +0 -0
- machine_dialect/errors/tests/test_expected_token_errors.py +188 -0
- machine_dialect/errors/tests/test_name_errors.py +118 -0
- machine_dialect/helpers/__init__.py +0 -0
- machine_dialect/helpers/stopwords.py +225 -0
- machine_dialect/helpers/validators.py +30 -0
- machine_dialect/lexer/__init__.py +9 -0
- machine_dialect/lexer/constants.py +23 -0
- machine_dialect/lexer/lexer.py +907 -0
- machine_dialect/lexer/tests/__init__.py +0 -0
- machine_dialect/lexer/tests/helpers.py +86 -0
- machine_dialect/lexer/tests/test_apostrophe_identifiers.py +122 -0
- machine_dialect/lexer/tests/test_backtick_identifiers.py +140 -0
- machine_dialect/lexer/tests/test_boolean_literals.py +108 -0
- machine_dialect/lexer/tests/test_case_insensitive_keywords.py +188 -0
- machine_dialect/lexer/tests/test_comments.py +200 -0
- machine_dialect/lexer/tests/test_double_asterisk_keywords.py +127 -0
- machine_dialect/lexer/tests/test_lexer_position.py +113 -0
- machine_dialect/lexer/tests/test_list_tokens.py +282 -0
- machine_dialect/lexer/tests/test_stopwords.py +80 -0
- machine_dialect/lexer/tests/test_strict_equality.py +129 -0
- machine_dialect/lexer/tests/test_token.py +41 -0
- machine_dialect/lexer/tests/test_tokenization.py +294 -0
- machine_dialect/lexer/tests/test_underscore_literals.py +343 -0
- machine_dialect/lexer/tests/test_url_literals.py +169 -0
- machine_dialect/lexer/tokens.py +487 -0
- machine_dialect/linter/__init__.py +10 -0
- machine_dialect/linter/__main__.py +144 -0
- machine_dialect/linter/linter.py +154 -0
- machine_dialect/linter/rules/__init__.py +8 -0
- machine_dialect/linter/rules/base.py +112 -0
- machine_dialect/linter/rules/statement_termination.py +99 -0
- machine_dialect/linter/tests/__init__.py +1 -0
- machine_dialect/linter/tests/mdrules/__init__.py +0 -0
- machine_dialect/linter/tests/mdrules/test_md101_statement_termination.py +181 -0
- machine_dialect/linter/tests/test_linter.py +81 -0
- machine_dialect/linter/tests/test_rules.py +110 -0
- machine_dialect/linter/tests/test_violations.py +71 -0
- machine_dialect/linter/violations.py +51 -0
- machine_dialect/mir/__init__.py +69 -0
- machine_dialect/mir/analyses/__init__.py +20 -0
- machine_dialect/mir/analyses/alias_analysis.py +315 -0
- machine_dialect/mir/analyses/dominance_analysis.py +49 -0
- machine_dialect/mir/analyses/escape_analysis.py +286 -0
- machine_dialect/mir/analyses/loop_analysis.py +272 -0
- machine_dialect/mir/analyses/tests/test_type_analysis.py +736 -0
- machine_dialect/mir/analyses/type_analysis.py +448 -0
- machine_dialect/mir/analyses/use_def_chains.py +232 -0
- machine_dialect/mir/basic_block.py +385 -0
- machine_dialect/mir/dataflow.py +445 -0
- machine_dialect/mir/debug_info.py +208 -0
- machine_dialect/mir/hir_to_mir.py +1738 -0
- machine_dialect/mir/mir_dumper.py +366 -0
- machine_dialect/mir/mir_function.py +167 -0
- machine_dialect/mir/mir_instructions.py +1877 -0
- machine_dialect/mir/mir_interpreter.py +556 -0
- machine_dialect/mir/mir_module.py +225 -0
- machine_dialect/mir/mir_printer.py +480 -0
- machine_dialect/mir/mir_transformer.py +410 -0
- machine_dialect/mir/mir_types.py +367 -0
- machine_dialect/mir/mir_validation.py +455 -0
- machine_dialect/mir/mir_values.py +268 -0
- machine_dialect/mir/optimization_config.py +233 -0
- machine_dialect/mir/optimization_pass.py +251 -0
- machine_dialect/mir/optimization_pipeline.py +355 -0
- machine_dialect/mir/optimizations/__init__.py +84 -0
- machine_dialect/mir/optimizations/algebraic_simplification.py +733 -0
- machine_dialect/mir/optimizations/branch_prediction.py +372 -0
- machine_dialect/mir/optimizations/constant_propagation.py +634 -0
- machine_dialect/mir/optimizations/cse.py +398 -0
- machine_dialect/mir/optimizations/dce.py +288 -0
- machine_dialect/mir/optimizations/inlining.py +551 -0
- machine_dialect/mir/optimizations/jump_threading.py +487 -0
- machine_dialect/mir/optimizations/licm.py +405 -0
- machine_dialect/mir/optimizations/loop_unrolling.py +366 -0
- machine_dialect/mir/optimizations/strength_reduction.py +422 -0
- machine_dialect/mir/optimizations/tail_call.py +207 -0
- machine_dialect/mir/optimizations/tests/test_loop_unrolling.py +483 -0
- machine_dialect/mir/optimizations/type_narrowing.py +397 -0
- machine_dialect/mir/optimizations/type_specialization.py +447 -0
- machine_dialect/mir/optimizations/type_specific.py +906 -0
- machine_dialect/mir/optimize_mir.py +89 -0
- machine_dialect/mir/pass_manager.py +391 -0
- machine_dialect/mir/profiling/__init__.py +26 -0
- machine_dialect/mir/profiling/profile_collector.py +318 -0
- machine_dialect/mir/profiling/profile_data.py +372 -0
- machine_dialect/mir/profiling/profile_reader.py +272 -0
- machine_dialect/mir/profiling/profile_writer.py +226 -0
- machine_dialect/mir/register_allocation.py +302 -0
- machine_dialect/mir/reporting/__init__.py +17 -0
- machine_dialect/mir/reporting/optimization_reporter.py +314 -0
- machine_dialect/mir/reporting/report_formatter.py +289 -0
- machine_dialect/mir/ssa_construction.py +342 -0
- machine_dialect/mir/tests/__init__.py +1 -0
- machine_dialect/mir/tests/test_algebraic_associativity.py +204 -0
- machine_dialect/mir/tests/test_algebraic_complex_patterns.py +221 -0
- machine_dialect/mir/tests/test_algebraic_division.py +126 -0
- machine_dialect/mir/tests/test_algebraic_simplification.py +863 -0
- machine_dialect/mir/tests/test_basic_block.py +425 -0
- machine_dialect/mir/tests/test_branch_prediction.py +459 -0
- machine_dialect/mir/tests/test_call_lowering.py +168 -0
- machine_dialect/mir/tests/test_collection_lowering.py +604 -0
- machine_dialect/mir/tests/test_cross_block_constant_propagation.py +255 -0
- machine_dialect/mir/tests/test_custom_passes.py +166 -0
- machine_dialect/mir/tests/test_debug_info.py +285 -0
- machine_dialect/mir/tests/test_dict_extraction_lowering.py +192 -0
- machine_dialect/mir/tests/test_dictionary_lowering.py +299 -0
- machine_dialect/mir/tests/test_double_negation.py +231 -0
- machine_dialect/mir/tests/test_escape_analysis.py +233 -0
- machine_dialect/mir/tests/test_hir_to_mir.py +465 -0
- machine_dialect/mir/tests/test_hir_to_mir_complete.py +389 -0
- machine_dialect/mir/tests/test_hir_to_mir_simple.py +130 -0
- machine_dialect/mir/tests/test_inlining.py +435 -0
- machine_dialect/mir/tests/test_licm.py +472 -0
- machine_dialect/mir/tests/test_mir_dumper.py +313 -0
- machine_dialect/mir/tests/test_mir_instructions.py +445 -0
- machine_dialect/mir/tests/test_mir_module.py +860 -0
- machine_dialect/mir/tests/test_mir_printer.py +387 -0
- machine_dialect/mir/tests/test_mir_types.py +123 -0
- machine_dialect/mir/tests/test_mir_types_enhanced.py +132 -0
- machine_dialect/mir/tests/test_mir_validation.py +378 -0
- machine_dialect/mir/tests/test_mir_values.py +168 -0
- machine_dialect/mir/tests/test_one_based_indexing.py +202 -0
- machine_dialect/mir/tests/test_optimization_helpers.py +60 -0
- machine_dialect/mir/tests/test_optimization_pipeline.py +554 -0
- machine_dialect/mir/tests/test_optimization_reporter.py +318 -0
- machine_dialect/mir/tests/test_pass_manager.py +294 -0
- machine_dialect/mir/tests/test_pass_registration.py +64 -0
- machine_dialect/mir/tests/test_profiling.py +356 -0
- machine_dialect/mir/tests/test_register_allocation.py +307 -0
- machine_dialect/mir/tests/test_report_formatters.py +372 -0
- machine_dialect/mir/tests/test_ssa_construction.py +433 -0
- machine_dialect/mir/tests/test_tail_call.py +236 -0
- machine_dialect/mir/tests/test_type_annotated_instructions.py +192 -0
- machine_dialect/mir/tests/test_type_narrowing.py +277 -0
- machine_dialect/mir/tests/test_type_specialization.py +421 -0
- machine_dialect/mir/tests/test_type_specific_optimization.py +545 -0
- machine_dialect/mir/tests/test_type_specific_optimization_advanced.py +382 -0
- machine_dialect/mir/type_inference.py +368 -0
- machine_dialect/parser/__init__.py +12 -0
- machine_dialect/parser/enums.py +45 -0
- machine_dialect/parser/parser.py +3655 -0
- machine_dialect/parser/protocols.py +11 -0
- machine_dialect/parser/symbol_table.py +169 -0
- machine_dialect/parser/tests/__init__.py +0 -0
- machine_dialect/parser/tests/helper_functions.py +193 -0
- machine_dialect/parser/tests/test_action_statements.py +334 -0
- machine_dialect/parser/tests/test_boolean_literal_expressions.py +152 -0
- machine_dialect/parser/tests/test_call_statements.py +154 -0
- machine_dialect/parser/tests/test_call_statements_errors.py +187 -0
- machine_dialect/parser/tests/test_collection_mutations.py +264 -0
- machine_dialect/parser/tests/test_conditional_expressions.py +343 -0
- machine_dialect/parser/tests/test_define_integration.py +468 -0
- machine_dialect/parser/tests/test_define_statements.py +311 -0
- machine_dialect/parser/tests/test_dict_extraction.py +115 -0
- machine_dialect/parser/tests/test_empty_literal.py +155 -0
- machine_dialect/parser/tests/test_float_literal_expressions.py +163 -0
- machine_dialect/parser/tests/test_identifier_expressions.py +57 -0
- machine_dialect/parser/tests/test_if_empty_block.py +61 -0
- machine_dialect/parser/tests/test_if_statements.py +299 -0
- machine_dialect/parser/tests/test_illegal_tokens.py +86 -0
- machine_dialect/parser/tests/test_infix_expressions.py +680 -0
- machine_dialect/parser/tests/test_integer_literal_expressions.py +137 -0
- machine_dialect/parser/tests/test_interaction_statements.py +269 -0
- machine_dialect/parser/tests/test_list_literals.py +277 -0
- machine_dialect/parser/tests/test_no_none_in_ast.py +94 -0
- machine_dialect/parser/tests/test_panic_mode_recovery.py +171 -0
- machine_dialect/parser/tests/test_parse_errors.py +114 -0
- machine_dialect/parser/tests/test_possessive_syntax.py +182 -0
- machine_dialect/parser/tests/test_prefix_expressions.py +415 -0
- machine_dialect/parser/tests/test_program.py +13 -0
- machine_dialect/parser/tests/test_return_statements.py +89 -0
- machine_dialect/parser/tests/test_set_statements.py +152 -0
- machine_dialect/parser/tests/test_strict_equality.py +258 -0
- machine_dialect/parser/tests/test_symbol_table.py +217 -0
- machine_dialect/parser/tests/test_url_literal_expressions.py +209 -0
- machine_dialect/parser/tests/test_utility_statements.py +423 -0
- machine_dialect/parser/token_buffer.py +159 -0
- machine_dialect/repl/__init__.py +3 -0
- machine_dialect/repl/repl.py +426 -0
- machine_dialect/repl/tests/__init__.py +0 -0
- machine_dialect/repl/tests/test_repl.py +606 -0
- machine_dialect/semantic/__init__.py +12 -0
- machine_dialect/semantic/analyzer.py +906 -0
- machine_dialect/semantic/error_messages.py +189 -0
- machine_dialect/semantic/tests/__init__.py +1 -0
- machine_dialect/semantic/tests/test_analyzer.py +364 -0
- machine_dialect/semantic/tests/test_error_messages.py +104 -0
- machine_dialect/tests/edge_cases/__init__.py +10 -0
- machine_dialect/tests/edge_cases/test_boundary_access.py +256 -0
- machine_dialect/tests/edge_cases/test_empty_collections.py +166 -0
- machine_dialect/tests/edge_cases/test_invalid_operations.py +243 -0
- machine_dialect/tests/edge_cases/test_named_list_edge_cases.py +295 -0
- machine_dialect/tests/edge_cases/test_nested_structures.py +313 -0
- machine_dialect/tests/edge_cases/test_type_mixing.py +277 -0
- machine_dialect/tests/integration/test_array_operations_emulation.py +248 -0
- machine_dialect/tests/integration/test_list_compilation.py +395 -0
- machine_dialect/tests/integration/test_lists_and_dictionaries.py +322 -0
- machine_dialect/type_checking/__init__.py +21 -0
- machine_dialect/type_checking/tests/__init__.py +1 -0
- machine_dialect/type_checking/tests/test_type_system.py +230 -0
- machine_dialect/type_checking/type_system.py +270 -0
- machine_dialect-0.1.0a1.dist-info/METADATA +128 -0
- machine_dialect-0.1.0a1.dist-info/RECORD +268 -0
- machine_dialect-0.1.0a1.dist-info/WHEEL +5 -0
- machine_dialect-0.1.0a1.dist-info/entry_points.txt +3 -0
- machine_dialect-0.1.0a1.dist-info/licenses/LICENSE +201 -0
- machine_dialect-0.1.0a1.dist-info/top_level.txt +2 -0
- machine_dialect_vm/__init__.pyi +15 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
"""MIR optimization pipeline integration.
|
2
|
+
|
3
|
+
This module provides the main entry point for optimizing MIR modules
|
4
|
+
using the pass management infrastructure.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from machine_dialect.mir.mir_module import MIRModule
|
8
|
+
from machine_dialect.mir.optimization_config import (
|
9
|
+
OptimizationConfig,
|
10
|
+
OptimizationPipeline,
|
11
|
+
)
|
12
|
+
from machine_dialect.mir.optimizations import register_all_passes
|
13
|
+
from machine_dialect.mir.pass_manager import PassManager
|
14
|
+
|
15
|
+
|
16
|
+
def optimize_mir(
|
17
|
+
module: MIRModule,
|
18
|
+
optimization_level: int = 1,
|
19
|
+
config: OptimizationConfig | None = None,
|
20
|
+
debug: bool = False,
|
21
|
+
custom_passes: list[str] | None = None,
|
22
|
+
) -> tuple[MIRModule, dict[str, dict[str, int]]]:
|
23
|
+
"""Optimize a MIR module using the optimization framework.
|
24
|
+
|
25
|
+
Args:
|
26
|
+
module: The MIR module to optimize.
|
27
|
+
optimization_level: Optimization level (0-3).
|
28
|
+
config: Optional custom optimization configuration.
|
29
|
+
debug: Enable debug output.
|
30
|
+
custom_passes: Optional list of custom passes to run instead of default pipeline.
|
31
|
+
|
32
|
+
Returns:
|
33
|
+
Tuple of (optimized module, pass statistics).
|
34
|
+
"""
|
35
|
+
# Use provided config or create from level
|
36
|
+
if config is None:
|
37
|
+
config = OptimizationConfig.from_level(optimization_level)
|
38
|
+
|
39
|
+
# Create pass manager
|
40
|
+
pass_manager = PassManager()
|
41
|
+
pass_manager.debug_mode = debug or config.debug_passes
|
42
|
+
|
43
|
+
# Register all available passes
|
44
|
+
register_all_passes(pass_manager)
|
45
|
+
|
46
|
+
# Get optimization pipeline
|
47
|
+
if custom_passes is not None:
|
48
|
+
# Use custom passes if provided
|
49
|
+
passes = custom_passes
|
50
|
+
else:
|
51
|
+
# Use default pipeline based on config
|
52
|
+
passes = OptimizationPipeline.get_passes(config)
|
53
|
+
|
54
|
+
if debug:
|
55
|
+
print(f"Running optimization level {optimization_level}")
|
56
|
+
print(f"Passes: {passes}")
|
57
|
+
|
58
|
+
# Run optimization passes
|
59
|
+
modified = pass_manager.run_passes(module, passes, optimization_level)
|
60
|
+
|
61
|
+
if debug:
|
62
|
+
print(f"Module modified: {modified}")
|
63
|
+
|
64
|
+
# Get statistics
|
65
|
+
stats = pass_manager.get_statistics()
|
66
|
+
|
67
|
+
if debug and config.pass_statistics:
|
68
|
+
print("\nOptimization Statistics:")
|
69
|
+
for pass_name, pass_stats in stats.items():
|
70
|
+
if pass_stats:
|
71
|
+
print(f" {pass_name}:")
|
72
|
+
for stat_name, value in pass_stats.items():
|
73
|
+
print(f" {stat_name}: {value}")
|
74
|
+
|
75
|
+
return module, stats
|
76
|
+
|
77
|
+
|
78
|
+
def optimize_mir_simple(module: MIRModule, level: int = 1) -> MIRModule:
|
79
|
+
"""Simple interface for MIR optimization.
|
80
|
+
|
81
|
+
Args:
|
82
|
+
module: The MIR module to optimize.
|
83
|
+
level: Optimization level (0-3).
|
84
|
+
|
85
|
+
Returns:
|
86
|
+
The optimized module.
|
87
|
+
"""
|
88
|
+
optimized, _ = optimize_mir(module, level)
|
89
|
+
return optimized
|
@@ -0,0 +1,391 @@
|
|
1
|
+
"""Pass manager for orchestrating optimization and analysis passes.
|
2
|
+
|
3
|
+
This module implements the pass management infrastructure for scheduling,
|
4
|
+
executing, and managing dependencies between passes.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from collections import defaultdict
|
8
|
+
from typing import Any
|
9
|
+
|
10
|
+
from machine_dialect.mir.mir_function import MIRFunction
|
11
|
+
from machine_dialect.mir.mir_module import MIRModule
|
12
|
+
from machine_dialect.mir.optimization_pass import (
|
13
|
+
AnalysisPass,
|
14
|
+
FunctionAnalysisPass,
|
15
|
+
FunctionPass,
|
16
|
+
ModuleAnalysisPass,
|
17
|
+
ModulePass,
|
18
|
+
OptimizationPass,
|
19
|
+
Pass,
|
20
|
+
PassInfo,
|
21
|
+
PassType,
|
22
|
+
PreservationLevel,
|
23
|
+
)
|
24
|
+
|
25
|
+
|
26
|
+
class PassRegistry:
|
27
|
+
"""Registry for available passes."""
|
28
|
+
|
29
|
+
def __init__(self) -> None:
|
30
|
+
"""Initialize the pass registry."""
|
31
|
+
self._passes: dict[str, type[Pass]] = {}
|
32
|
+
self._pass_info: dict[str, PassInfo] = {}
|
33
|
+
|
34
|
+
def register(self, pass_class: type[Pass]) -> None:
|
35
|
+
"""Register a pass.
|
36
|
+
|
37
|
+
Args:
|
38
|
+
pass_class: The pass class to register.
|
39
|
+
"""
|
40
|
+
instance = pass_class()
|
41
|
+
info = instance.get_info()
|
42
|
+
self._passes[info.name] = pass_class
|
43
|
+
self._pass_info[info.name] = info
|
44
|
+
|
45
|
+
def get_pass(self, name: str) -> Pass | None:
|
46
|
+
"""Get a pass instance by name.
|
47
|
+
|
48
|
+
Args:
|
49
|
+
name: Pass name.
|
50
|
+
|
51
|
+
Returns:
|
52
|
+
Pass instance or None.
|
53
|
+
"""
|
54
|
+
pass_class = self._passes.get(name)
|
55
|
+
if pass_class:
|
56
|
+
return pass_class()
|
57
|
+
return None
|
58
|
+
|
59
|
+
def get_info(self, name: str) -> PassInfo | None:
|
60
|
+
"""Get pass information by name.
|
61
|
+
|
62
|
+
Args:
|
63
|
+
name: Pass name.
|
64
|
+
|
65
|
+
Returns:
|
66
|
+
Pass information or None.
|
67
|
+
"""
|
68
|
+
return self._pass_info.get(name)
|
69
|
+
|
70
|
+
def list_passes(self, pass_type: PassType | None = None) -> list[str]:
|
71
|
+
"""List available passes.
|
72
|
+
|
73
|
+
Args:
|
74
|
+
pass_type: Optional filter by pass type.
|
75
|
+
|
76
|
+
Returns:
|
77
|
+
List of pass names.
|
78
|
+
"""
|
79
|
+
if pass_type is None:
|
80
|
+
return list(self._passes.keys())
|
81
|
+
|
82
|
+
result = []
|
83
|
+
for name, info in self._pass_info.items():
|
84
|
+
# Handle both single PassType and list of PassTypes
|
85
|
+
if isinstance(info.pass_type, list):
|
86
|
+
if pass_type in info.pass_type:
|
87
|
+
result.append(name)
|
88
|
+
elif info.pass_type == pass_type:
|
89
|
+
result.append(name)
|
90
|
+
return result
|
91
|
+
|
92
|
+
|
93
|
+
class AnalysisManager:
|
94
|
+
"""Manager for analysis passes and their results."""
|
95
|
+
|
96
|
+
def __init__(self) -> None:
|
97
|
+
"""Initialize the analysis manager."""
|
98
|
+
self._analyses: dict[str, AnalysisPass] = {}
|
99
|
+
self._dependencies: dict[str, set[str]] = defaultdict(set)
|
100
|
+
|
101
|
+
def register_analysis(self, name: str, analysis: AnalysisPass) -> None:
|
102
|
+
"""Register an analysis pass.
|
103
|
+
|
104
|
+
Args:
|
105
|
+
name: Analysis name.
|
106
|
+
analysis: Analysis pass instance.
|
107
|
+
"""
|
108
|
+
self._analyses[name] = analysis
|
109
|
+
|
110
|
+
def get_analysis(
|
111
|
+
self,
|
112
|
+
name: str,
|
113
|
+
target: MIRModule | MIRFunction,
|
114
|
+
) -> Any:
|
115
|
+
"""Get analysis results.
|
116
|
+
|
117
|
+
Args:
|
118
|
+
name: Analysis name.
|
119
|
+
target: Module or function to analyze.
|
120
|
+
|
121
|
+
Returns:
|
122
|
+
Analysis results.
|
123
|
+
|
124
|
+
Raises:
|
125
|
+
KeyError: If analysis not found.
|
126
|
+
"""
|
127
|
+
if name not in self._analyses:
|
128
|
+
raise KeyError(f"Analysis '{name}' not found")
|
129
|
+
|
130
|
+
analysis = self._analyses[name]
|
131
|
+
|
132
|
+
if isinstance(analysis, ModuleAnalysisPass) and isinstance(target, MIRModule):
|
133
|
+
return analysis.get_analysis(target)
|
134
|
+
elif isinstance(analysis, FunctionAnalysisPass) and isinstance(
|
135
|
+
target,
|
136
|
+
MIRFunction,
|
137
|
+
):
|
138
|
+
return analysis.get_analysis(target)
|
139
|
+
else:
|
140
|
+
raise TypeError("Incompatible analysis and target types")
|
141
|
+
|
142
|
+
def invalidate(self, names: list[str] | None = None) -> None:
|
143
|
+
"""Invalidate analyses.
|
144
|
+
|
145
|
+
Args:
|
146
|
+
names: Specific analyses to invalidate, or None for all.
|
147
|
+
"""
|
148
|
+
if names is None:
|
149
|
+
for analysis in self._analyses.values():
|
150
|
+
analysis.invalidate()
|
151
|
+
else:
|
152
|
+
for name in names:
|
153
|
+
if name in self._analyses:
|
154
|
+
self._analyses[name].invalidate()
|
155
|
+
# Invalidate dependent analyses
|
156
|
+
for dep_name, deps in self._dependencies.items():
|
157
|
+
if name in deps and dep_name in self._analyses:
|
158
|
+
self._analyses[dep_name].invalidate()
|
159
|
+
|
160
|
+
def preserve_analyses(self, level: PreservationLevel) -> None:
|
161
|
+
"""Preserve analyses based on preservation level.
|
162
|
+
|
163
|
+
Args:
|
164
|
+
level: Preservation level.
|
165
|
+
"""
|
166
|
+
if level == PreservationLevel.NONE:
|
167
|
+
self.invalidate()
|
168
|
+
elif level == PreservationLevel.CFG:
|
169
|
+
# Invalidate analyses that depend on CFG changes
|
170
|
+
to_invalidate = []
|
171
|
+
for name, analysis in self._analyses.items():
|
172
|
+
info = analysis.get_info()
|
173
|
+
if "cfg" not in info.requires:
|
174
|
+
to_invalidate.append(name)
|
175
|
+
self.invalidate(to_invalidate)
|
176
|
+
elif level == PreservationLevel.DOMINANCE:
|
177
|
+
# Invalidate analyses that depend on dominance
|
178
|
+
to_invalidate = []
|
179
|
+
for name, analysis in self._analyses.items():
|
180
|
+
info = analysis.get_info()
|
181
|
+
if "dominance" not in info.requires:
|
182
|
+
to_invalidate.append(name)
|
183
|
+
self.invalidate(to_invalidate)
|
184
|
+
# PreservationLevel.ALL preserves everything
|
185
|
+
|
186
|
+
|
187
|
+
class PassScheduler:
|
188
|
+
"""Schedules passes based on dependencies and optimization level."""
|
189
|
+
|
190
|
+
def __init__(self, registry: PassRegistry) -> None:
|
191
|
+
"""Initialize the pass scheduler.
|
192
|
+
|
193
|
+
Args:
|
194
|
+
registry: Pass registry.
|
195
|
+
"""
|
196
|
+
self.registry = registry
|
197
|
+
|
198
|
+
def schedule_passes(
|
199
|
+
self,
|
200
|
+
pass_names: list[str],
|
201
|
+
optimization_level: int = 1,
|
202
|
+
) -> list[str]:
|
203
|
+
"""Schedule passes in optimal order.
|
204
|
+
|
205
|
+
Args:
|
206
|
+
pass_names: Requested passes.
|
207
|
+
optimization_level: Optimization level (0-3).
|
208
|
+
|
209
|
+
Returns:
|
210
|
+
Ordered list of passes to run.
|
211
|
+
"""
|
212
|
+
# Build dependency graph
|
213
|
+
dependencies: dict[str, set[str]] = {}
|
214
|
+
for name in pass_names:
|
215
|
+
info = self.registry.get_info(name)
|
216
|
+
if info:
|
217
|
+
dependencies[name] = set(info.requires)
|
218
|
+
|
219
|
+
# Topological sort with cycle detection
|
220
|
+
scheduled = []
|
221
|
+
visited = set()
|
222
|
+
visiting = set()
|
223
|
+
|
224
|
+
def visit(name: str) -> None:
|
225
|
+
if name in visited:
|
226
|
+
return
|
227
|
+
if name in visiting:
|
228
|
+
raise ValueError(f"Circular dependency detected involving {name}")
|
229
|
+
|
230
|
+
visiting.add(name)
|
231
|
+
|
232
|
+
# Visit dependencies first
|
233
|
+
for dep in dependencies.get(name, set()):
|
234
|
+
if dep not in pass_names:
|
235
|
+
# Add required dependency
|
236
|
+
pass_names.append(dep)
|
237
|
+
dep_info = self.registry.get_info(dep)
|
238
|
+
if dep_info:
|
239
|
+
dependencies[dep] = set(dep_info.requires)
|
240
|
+
visit(dep)
|
241
|
+
|
242
|
+
visiting.remove(name)
|
243
|
+
visited.add(name)
|
244
|
+
scheduled.append(name)
|
245
|
+
|
246
|
+
for name in pass_names:
|
247
|
+
visit(name)
|
248
|
+
|
249
|
+
# Apply optimization level heuristics
|
250
|
+
if optimization_level == 0:
|
251
|
+
# No optimizations
|
252
|
+
scheduled = [
|
253
|
+
n for n in scheduled if (info := self.registry.get_info(n)) and info.pass_type != PassType.OPTIMIZATION
|
254
|
+
]
|
255
|
+
elif optimization_level >= 2:
|
256
|
+
# Add aggressive optimizations
|
257
|
+
# Could add more passes based on level
|
258
|
+
pass
|
259
|
+
|
260
|
+
return scheduled
|
261
|
+
|
262
|
+
|
263
|
+
class PassManager:
|
264
|
+
"""Main pass manager for running optimization pipelines."""
|
265
|
+
|
266
|
+
def __init__(self) -> None:
|
267
|
+
"""Initialize the pass manager."""
|
268
|
+
self.registry = PassRegistry()
|
269
|
+
self.analysis_manager = AnalysisManager()
|
270
|
+
self.scheduler = PassScheduler(self.registry)
|
271
|
+
self.stats: dict[str, dict[str, int]] = {}
|
272
|
+
self.debug_mode = False
|
273
|
+
|
274
|
+
def register_pass(self, pass_class: type[Pass]) -> None:
|
275
|
+
"""Register a pass with the manager.
|
276
|
+
|
277
|
+
Args:
|
278
|
+
pass_class: Pass class to register.
|
279
|
+
"""
|
280
|
+
self.registry.register(pass_class)
|
281
|
+
|
282
|
+
def run_passes(
|
283
|
+
self,
|
284
|
+
module: MIRModule,
|
285
|
+
pass_names: list[str],
|
286
|
+
optimization_level: int = 1,
|
287
|
+
) -> bool:
|
288
|
+
"""Run a sequence of passes on a module.
|
289
|
+
|
290
|
+
Args:
|
291
|
+
module: Module to optimize.
|
292
|
+
pass_names: List of pass names to run.
|
293
|
+
optimization_level: Optimization level (0-3).
|
294
|
+
|
295
|
+
Returns:
|
296
|
+
True if the module was modified.
|
297
|
+
"""
|
298
|
+
# Schedule passes
|
299
|
+
scheduled = self.scheduler.schedule_passes(pass_names, optimization_level)
|
300
|
+
|
301
|
+
if self.debug_mode:
|
302
|
+
print(f"Scheduled passes: {scheduled}")
|
303
|
+
|
304
|
+
modified = False
|
305
|
+
for pass_name in scheduled:
|
306
|
+
pass_instance = self.registry.get_pass(pass_name)
|
307
|
+
if not pass_instance:
|
308
|
+
print(f"Warning: Pass '{pass_name}' not found")
|
309
|
+
continue
|
310
|
+
|
311
|
+
# Set up analysis manager for optimization passes
|
312
|
+
if isinstance(pass_instance, OptimizationPass):
|
313
|
+
pass_instance.analysis_manager = self.analysis_manager
|
314
|
+
|
315
|
+
# Initialize pass
|
316
|
+
pass_instance.initialize()
|
317
|
+
pass_instance.debug_mode = self.debug_mode
|
318
|
+
|
319
|
+
# Run pass
|
320
|
+
pass_info = pass_instance.get_info()
|
321
|
+
if pass_info.pass_type == PassType.ANALYSIS:
|
322
|
+
# Register analysis
|
323
|
+
if isinstance(pass_instance, AnalysisPass):
|
324
|
+
self.analysis_manager.register_analysis(
|
325
|
+
pass_name,
|
326
|
+
pass_instance,
|
327
|
+
)
|
328
|
+
# Run analysis to populate cache
|
329
|
+
if isinstance(pass_instance, ModuleAnalysisPass):
|
330
|
+
pass_instance.run_on_module(module)
|
331
|
+
elif isinstance(pass_instance, FunctionAnalysisPass):
|
332
|
+
for function in module.functions.values():
|
333
|
+
pass_instance.run_on_function(function)
|
334
|
+
else:
|
335
|
+
# Run optimization/utility pass
|
336
|
+
if isinstance(pass_instance, ModulePass):
|
337
|
+
if pass_instance.run_on_module(module):
|
338
|
+
modified = True
|
339
|
+
elif isinstance(pass_instance, FunctionPass):
|
340
|
+
if pass_instance.run_on_module(module):
|
341
|
+
modified = True
|
342
|
+
|
343
|
+
# Handle analysis preservation
|
344
|
+
self.analysis_manager.preserve_analyses(pass_info.preserves)
|
345
|
+
|
346
|
+
# Finalize pass
|
347
|
+
pass_instance.finalize()
|
348
|
+
|
349
|
+
# Collect statistics
|
350
|
+
self.stats[pass_name] = pass_instance.get_stats()
|
351
|
+
|
352
|
+
if self.debug_mode and self.stats[pass_name]:
|
353
|
+
print(f" {pass_name}: {self.stats[pass_name]}")
|
354
|
+
|
355
|
+
return modified
|
356
|
+
|
357
|
+
def run_function_pass(
|
358
|
+
self,
|
359
|
+
function: MIRFunction,
|
360
|
+
pass_name: str,
|
361
|
+
) -> bool:
|
362
|
+
"""Run a single function pass.
|
363
|
+
|
364
|
+
Args:
|
365
|
+
function: Function to optimize.
|
366
|
+
pass_name: Pass name.
|
367
|
+
|
368
|
+
Returns:
|
369
|
+
True if the function was modified.
|
370
|
+
"""
|
371
|
+
pass_instance = self.registry.get_pass(pass_name)
|
372
|
+
if not pass_instance or not isinstance(pass_instance, FunctionPass):
|
373
|
+
return False
|
374
|
+
|
375
|
+
pass_instance.initialize()
|
376
|
+
modified = pass_instance.run_on_function(function)
|
377
|
+
pass_instance.finalize()
|
378
|
+
|
379
|
+
return modified
|
380
|
+
|
381
|
+
def get_statistics(self) -> dict[str, dict[str, int]]:
|
382
|
+
"""Get statistics from all passes.
|
383
|
+
|
384
|
+
Returns:
|
385
|
+
Dictionary of pass statistics.
|
386
|
+
"""
|
387
|
+
return self.stats.copy()
|
388
|
+
|
389
|
+
def reset_statistics(self) -> None:
|
390
|
+
"""Reset all statistics."""
|
391
|
+
self.stats.clear()
|
@@ -0,0 +1,26 @@
|
|
1
|
+
"""Profiling infrastructure for MIR optimization.
|
2
|
+
|
3
|
+
This module provides profile-guided optimization (PGO) support for the MIR
|
4
|
+
optimization framework, enabling data-driven optimization decisions based on
|
5
|
+
runtime behavior.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from machine_dialect.mir.profiling.profile_collector import ProfileCollector
|
9
|
+
from machine_dialect.mir.profiling.profile_data import (
|
10
|
+
BranchProfile,
|
11
|
+
FunctionProfile,
|
12
|
+
LoopProfile,
|
13
|
+
ProfileData,
|
14
|
+
)
|
15
|
+
from machine_dialect.mir.profiling.profile_reader import ProfileReader
|
16
|
+
from machine_dialect.mir.profiling.profile_writer import ProfileWriter
|
17
|
+
|
18
|
+
__all__ = [
|
19
|
+
"BranchProfile",
|
20
|
+
"FunctionProfile",
|
21
|
+
"LoopProfile",
|
22
|
+
"ProfileCollector",
|
23
|
+
"ProfileData",
|
24
|
+
"ProfileReader",
|
25
|
+
"ProfileWriter",
|
26
|
+
]
|