-
Notifications
You must be signed in to change notification settings - Fork 132
Tools : PyTeal optimization utility #247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
75 commits
Select commit
Hold shift + click to select a range
94a482b
Optimization added for repeated int constants under 2**7 w/ tests
algoidurovic e0795fc
fixed type problem and formatted
algoidurovic bb1eb20
Expanded test and added comment for clarification
algoidurovic 6fde8ec
implement optimization utility with simple slot store/load canceling
algoidurovic a9ba3ef
minor refactor
algoidurovic 73ad2a9
reformat code
algoidurovic b41f727
Update pyteal/compiler/optimizer/optimizer.py
algoidurovic 0925456
Update pyteal/compiler/optimizer/optimizer.py
algoidurovic edbbfd2
Adding exponentiation to arithmatic ops docs (#134)
barnjamin 4fdb032
updating to use new syntax for seq (#135)
barnjamin 9ad3288
Make pylance recognize wildcard imports (#133)
barnjamin ac14058
Include pyi files in build (#137)
jasonpaulos 4f97035
Revert "Optimization for constant assembly (#128)"
jasonpaulos 22b7eb3
Revert "String optimization and addition of Suffix() (#126)"
jasonpaulos 46e2a42
Update to v0.9.1 (#138)
jasonpaulos edfae0d
Revert "Revert "String optimization and addition of Suffix() (#126)""
jasonpaulos 422b28e
Revert "Revert "Optimization for constant assembly (#128)""
jasonpaulos 7c92bc7
Update examples.rst (#140)
edwardgaudio 1999f01
Fix type for App.globalGetEx in docs (#142)
jasonpaulos 39710b5
up max teal version (#146)
barnjamin 2f62030
Formatting subroutines with name and newline (#148)
barnjamin 0a445ed
Call type_of() in require_type() for better exception messages (#151)
joe-p 1d71c44
`method` pseudo-op support for ABI methods (#153)
ahangsu 7d0453c
Print diff of `__init__.pyi` (#166)
jasonpaulos 49fbf04
C2C Feature Support (#149)
ahangsu 3227438
Add BytesSqrt (#163)
StylishTriangles 85cffeb
adding new globals from teal6 (#168)
barnjamin b6b2439
Acct params get (#165)
barnjamin 8ccc2fa
Change Subroutine Wrapped Callable to a class with call method (#171)
ahangsu aae4548
Subroutine Type Annotations (#182)
tzaffi c3e5659
fix docs referencing what apps should eval to (#191)
barnjamin c139e93
Move from Travis to Github Actions (#190)
algojack 2d3769b
MultiValue expression implemented to support opcodes that return mult…
algoidurovic 2a82718
Support TEAL 6 txn fields LastLog, StateProofPK and opcodes divw, itx…
barnjamin a979363
Fixed typo (#202)
gconnect 3fdb4a8
Add Github action to generate docset (#201)
aldur a30ff01
Update docs to group transaction field tables like go-algorand (#204)
michaeldiamant 727f3d3
Update accessing_transaction_field.rst to fix typo (#207)
michaeldiamant 23dbbc6
Add docs README to explain docs/ testing procedure (#205)
michaeldiamant d4ec5de
v0.10.0 (#206)
jasonpaulos bc403cc
fixing github actions to run on tags (#208)
algojack 91e5118
Fix typos in docstrings and error messages (#211)
michaeldiamant b336506
Test on Python 3.10 (#212)
jasonpaulos df08d3f
Update versions.rst (#210)
PabloLION e1c4bfa
Pass-by-Ref / Dynamic Scratch Variables via the `loads` and `stores` …
tzaffi 0cf27fb
Fix build script invocation (#223)
jasonpaulos 76af624
Bring #225 to master (#227)
michaeldiamant 002a480
Ignore tests generating TEAL file outputs used for expected compariso…
michaeldiamant bbbf5d9
Fix typo in CONTRIBUTING.md (#229)
michaeldiamant d3080d0
Fix subroutine mutual recursion with different argument counts bug (#…
jasonpaulos ff8dd95
Revert "Pass-by-Ref / Dynamic Scratch Variables via the `loads` and `…
jasonpaulos 221e6fd
v0.10.1 (#237)
jasonpaulos edbae57
Revert "Revert "Pass-by-Ref / Dynamic Scratch Variables via the `load…
jasonpaulos c2331f9
Update user guide docs to reflect addition of DynamicScratchVar (#226)
michaeldiamant 49f4a5c
Update CONTRIBUTING.md on PEP 8 naming conventions policy (#241)
michaeldiamant 155f69a
implement optimization utility with simple slot store/load canceling
algoidurovic a521b33
minor refactor
algoidurovic 19b9f30
reformat code
algoidurovic 5b2fa88
correct import format to match convention
algoidurovic 7cee3f2
resolve merge conflicts
algoidurovic 1b04cbb
slot optimization awareness of reserved ids added
algoidurovic 9d4b173
fix typo
algoidurovic 3cb76ec
remove dataclass usage
algoidurovic 4a32b3f
slight reorg of compiler process in order to perform optimization on cfg
algoidurovic 53f6231
clean up imports
algoidurovic 3d3208e
Merge branch 'master' of https://github.com/algorand/pyteal into opti…
algoidurovic b0704e6
Merge branch 'master' of https://github.com/algorand/pyteal into opti…
algoidurovic 4b3ccf2
updated documentation and reformatted with new version of black
algoidurovic f353330
remove unused imports and comments
algoidurovic fd1f71f
reformatting
algoidurovic 17543ed
add additional optimizer unit tests
algoidurovic 33256a7
improve testing and slight refactoring
algoidurovic 6795234
more renaming
algoidurovic 89f4100
documentation and import changes
algoidurovic 808768f
fixed typos in docs
algoidurovic File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
.. _compiler_optimization: | ||
|
||
Compiler Optimization | ||
======================== | ||
**The optimizer is at an early stage and is disabled by default. Backwards compatability cannot be | ||
guaranteed at this point.** | ||
|
||
The optimizer is a tool for improving performance and reducing resource consumption. In this context, | ||
the terms *performance* and *resource* can apply across multiple dimensions, including but not limited | ||
to: compiled code size, scratch slot usage, opcode cost, etc. | ||
|
||
Optimizer Usage | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
The compiler determines which optimizations to apply based on the provided :any:`OptimizeOptions` object as | ||
shown in the code block below. The :any:`OptimizeOptions` constructor receives a set of keyword arguments | ||
representing flags corresponding to particular optimizations. If arguments are not provided to the | ||
constructor or no :any:`OptimizeOptions` object is passed to :any:`compileTeal` then the default behavior is | ||
that no optimizations are applied. | ||
|
||
============================== ================================================================================ =========================== | ||
Optimization Flag Description Default | ||
============================== ================================================================================ =========================== | ||
:code:`scratch_slots` A boolean describing whether or not scratch slot optimization should be applied. :code:`False` | ||
============================== ================================================================================ =========================== | ||
|
||
.. code-block:: python | ||
|
||
optimize_options = OptimizeOptions(scratch_slots=True) | ||
compileTeal(approval_program(), mode=Mode.Application, version=4, optimize=optimize_options) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .optimizer import OptimizeOptions, apply_global_optimizations |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
from typing import Set | ||
from ...ast import ScratchSlot | ||
from ...ir import TealBlock, TealOp, Op | ||
from ...errors import TealInternalError | ||
|
||
|
||
class OptimizeOptions: | ||
"""An object which specifies the optimizations to be performed and relevant context. | ||
|
||
_skip_slots: the slots that should be skipped during optimization. At the moment this includes: | ||
1. reserved slots because they may have dependencies outside | ||
the current application. For example, the 'gloads' opcode can | ||
access the slots of other applications in the tx group. | ||
2. global slots because they're outside the scope of global | ||
optimizations, which only apply to the control flow graph of | ||
a single subroutine. | ||
3. slots used with dynamic scratch vars. These slots use | ||
indirection by means of the 'stores' opcode and dependencies | ||
can only be determined at runtime. | ||
|
||
Args: | ||
|
||
scratch_slots (optional): cancel contiguous store/load operations | ||
that have no load dependencies elsewhere. | ||
""" | ||
|
||
def __init__(self, *, scratch_slots: bool = False): | ||
self.scratch_slots = scratch_slots | ||
self._skip_slots: Set[ScratchSlot] = set() | ||
|
||
|
||
def _remove_extraneous_slot_access(start: TealBlock, remove: Set[ScratchSlot]): | ||
def keep_op(op: TealOp) -> bool: | ||
if type(op) != TealOp or (op.op != Op.store and op.op != Op.load): | ||
return True | ||
|
||
return not set(op.getSlots()).issubset(remove) | ||
|
||
for block in TealBlock.Iterate(start): | ||
block.ops = list(filter(keep_op, block.ops)) | ||
|
||
|
||
# Very dumb, overly eager dependency checking. A "dependency" is considered | ||
# any time the slot is loaded from in the entire control flow graph. This | ||
# can definitely be improved in the future. | ||
def _has_load_dependencies( | ||
cur_block: TealBlock, start: TealBlock, slot: ScratchSlot, pos: int | ||
) -> bool: | ||
for block in TealBlock.Iterate(start): | ||
for i, op in enumerate(block.ops): | ||
if block == cur_block and i == pos: | ||
continue | ||
|
||
if type(op) == TealOp and op.op == Op.load and slot in set(op.getSlots()): | ||
return True | ||
algoidurovic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return False | ||
|
||
|
||
def _apply_slot_to_stack( | ||
cur_block: TealBlock, start: TealBlock, skip_slots: Set[ScratchSlot] | ||
): | ||
slots_to_remove = set() | ||
# surprisingly, this slicing is totally safe - even if the list is empty. | ||
for i, op in enumerate(cur_block.ops[:-1]): | ||
jasonpaulos marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if type(op) != TealOp or op.op != Op.store: | ||
continue | ||
|
||
if set(op.getSlots()).issubset(skip_slots): | ||
continue | ||
|
||
next_op = cur_block.ops[i + 1] | ||
algoidurovic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if type(next_op) != TealOp or next_op.op != Op.load: | ||
continue | ||
|
||
cur_slots, next_slots = op.getSlots(), next_op.getSlots() | ||
if len(cur_slots) != 1 or len(next_slots) != 1: | ||
raise TealInternalError( | ||
"load/store op does not have exactly one slot argument" | ||
) | ||
if cur_slots[0] != next_slots[0]: | ||
continue | ||
|
||
if not _has_load_dependencies(cur_block, start, cur_slots[0], i + 1): | ||
slots_to_remove.add(cur_slots[0]) | ||
|
||
_remove_extraneous_slot_access(start, slots_to_remove) | ||
|
||
|
||
def apply_global_optimizations(start: TealBlock, options: OptimizeOptions) -> TealBlock: | ||
# limit number of iterations to length of teal program to avoid potential | ||
# infinite loops. | ||
for block in TealBlock.Iterate(start): | ||
for _ in range(len(block.ops)): | ||
prev_ops = block.ops.copy() | ||
if options.scratch_slots: | ||
_apply_slot_to_stack(block, start, options._skip_slots) | ||
|
||
if prev_ops == block.ops: | ||
jasonpaulos marked this conversation as resolved.
Show resolved
Hide resolved
|
||
break | ||
|
||
return start |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.