Please use peepz80 instead
peepz80 is the next generation successor to this project and is actively supported.
A language-agnostic optimization library for 8080 and Z80 compilers.
upeep80 provides high-quality optimization passes for compilers targeting the Intel 8080 and Zilog Z80 processors. The library is designed to be reusable across different source languages.
- Constant Folding: Evaluate compile-time constant expressions
- Constant Propagation: Replace variables with their constant values
- Algebraic Simplification: x+0=x, x1=x, x0=0, etc.
- Strength Reduction: Replace expensive operations with cheaper equivalents
- Multiply/divide by power-of-2 → shifts
- Modulo by power-of-2 → bitwise AND
- Dead Code Elimination: Remove unreachable code
- Common Subexpression Elimination (CSE): Eliminate redundant calculations
- Copy Propagation: Track variable aliases
- Dead Store Elimination: Remove unused assignments
- Loop Optimizations:
- Loop-invariant code motion
- Loop unrolling (configurable)
- Boolean Simplification: x=x→true, x<>x→false
- Procedure Inlining: Inline small procedures
- Pattern-based optimization on Z80 assembly
- Redundant load/store elimination
- Jump optimization (including relative jumps for Z80)
- Stack operation combining
- Register allocation cleanup
- 8080 to Z80 mnemonic translation
- Level 0: No optimization
- Level 1: Basic (constant folding, algebraic simplification)
- Level 2: Standard (+ strength reduction, dead code elimination)
- Level 3: Aggressive (+ CSE, loop optimizations, inlining)
- Speed: Optimize for execution speed
- Size: Optimize for code size
- Balanced: Balance between speed and size
pip install upeep80Or for development:
git clone https://github.com/yourusername/upeep80.git
cd upeep80
pip install -e ".[dev]"from upeep80 import ASTOptimizer, OptimizeFor
# Create optimizer
optimizer = ASTOptimizer(
opt_level=2,
optimize_for=OptimizeFor.BALANCED
)
# Optimize your AST
optimized_ast = optimizer.optimize(ast_tree)
# Check statistics
print(f"Constants folded: {optimizer.stats.constants_folded}")
print(f"Dead code eliminated: {optimizer.stats.dead_code_eliminated}")from upeep80 import PeepholeOptimizer, Target
# Create optimizer
optimizer = PeepholeOptimizer(
target=Target.Z80,
opt_level=2
)
# Optimize assembly code
optimized_asm = optimizer.optimize(assembly_lines)
# Check statistics
print(f"Patterns applied: {optimizer.stats.patterns_applied}")
print(f"Instructions eliminated: {optimizer.stats.instructions_eliminated}")upeep80 is designed to be language-agnostic:
- Works on generic expression trees
- Requires minimal AST node interface:
- Binary/unary expressions
- Literals (integer, real)
- Identifiers
- Statements (assignment, if, loop, etc.)
- Can be adapted to any language's AST
- Works directly on assembly text
- No knowledge of source language required
- Pattern-based transformation engine
- Configurable for 8080 or Z80 targets
See the examples/ directory for complete examples:
optimize_ast.py- AST optimization exampleoptimize_asm.py- Assembly peephole optimization examplecustom_patterns.py- Custom peephole pattern definition
Full documentation is available at docs/:
pytestmypy upeep80black upeep80
ruff check upeep80Benchmarks on typical compiler workloads:
- AST optimization: ~10,000 nodes/second
- Peephole optimization: ~50,000 instructions/second
- Memory usage: ~100MB for typical compilation unit
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
This project is licensed under the GNU General Public License v2.0 - see LICENSE for details.
upeep80 was extracted from the uplm80 project to provide a reusable optimization library for multiple retro compiler projects targeting the 8080/Z80 architecture.
- Optimization techniques based on classic compiler optimization literature
- Pattern-based peephole optimization inspired by Davidson & Fraser's work
- Z80 instruction set reference from z80.info
- uplm80 - PL/M-80 compiler
- uada80 - Ada compiler for Z80
- Z80 CPU User Manual