Skip to content

Commit 422b28e

Browse files
jasonpaulosalgoidurovic
authored andcommitted
Revert "Revert "Optimization for constant assembly (algorand#128)""
This reverts commit cc405a5.
1 parent edfae0d commit 422b28e

File tree

2 files changed

+84
-3
lines changed

2 files changed

+84
-3
lines changed

pyteal/compiler/constants.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,14 @@ def createConstantBlocks(ops: List[TealComponent]) -> List[TealComponent]:
132132
sortedInts = sorted(intFreqs, key=lambda x: intFreqs[x], reverse=True)
133133
sortedBytes = sorted(byteFreqs, key=lambda x: byteFreqs[x], reverse=True)
134134

135-
intBlock = [i for i in sortedInts if intFreqs[i] > 1]
135+
# Use Op.pushint if the constant does not occur in the top 4 most frequent and is smaller than
136+
# 2 ** 7 to improve performance and save block space.
137+
intBlock = [
138+
val
139+
for i, val in enumerate(sortedInts)
140+
if intFreqs[val] > 1 and (i < 4 or isinstance(val, str) or val >= 2 ** 7)
141+
]
142+
136143
byteBlock = [
137144
("0x" + b.hex()) if type(b) is bytes else cast(str, b)
138145
for b in sortedBytes
@@ -151,13 +158,13 @@ def createConstantBlocks(ops: List[TealComponent]) -> List[TealComponent]:
151158

152159
if basicOp == Op.int:
153160
intValue = extractIntValue(op)
154-
if intFreqs[intValue] == 1:
161+
if intValue not in intBlock:
155162
assembled.append(
156163
TealOp(op.expr, Op.pushint, intValue, "//", *op.args)
157164
)
158165
continue
159166

160-
index = sortedInts.index(intValue)
167+
index = intBlock.index(intValue)
161168
if index == 0:
162169
assembled.append(TealOp(op.expr, Op.intc_0, "//", *op.args))
163170
elif index == 1:

pyteal/compiler/constants_test.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,3 +545,77 @@ def test_createConstantBlocks_tmpl_all():
545545

546546
actual = createConstantBlocks(ops)
547547
assert actual == expected
548+
549+
550+
def test_createConstantBlocks_intc():
551+
"""Test scenario where there are more than 4 constants in the intcblock.
552+
If the 4th constant can't fit in one varuint byte (more than 2**7) it
553+
should be referenced with the Op.intc 4 command.
554+
"""
555+
556+
ops = [
557+
TealOp(None, Op.int, 0),
558+
TealOp(None, Op.int, 0),
559+
TealOp(None, Op.int, 1),
560+
TealOp(None, Op.int, 1),
561+
TealOp(None, Op.int, 2),
562+
TealOp(None, Op.int, 2),
563+
TealOp(None, Op.int, 3),
564+
TealOp(None, Op.int, 3),
565+
TealOp(None, Op.int, 2 ** 7),
566+
TealOp(None, Op.int, 2 ** 7),
567+
]
568+
569+
expected = [
570+
TealOp(None, Op.intcblock, 0, 1, 2, 3, 2 ** 7),
571+
TealOp(None, Op.intc_0, "//", 0),
572+
TealOp(None, Op.intc_0, "//", 0),
573+
TealOp(None, Op.intc_1, "//", 1),
574+
TealOp(None, Op.intc_1, "//", 1),
575+
TealOp(None, Op.intc_2, "//", 2),
576+
TealOp(None, Op.intc_2, "//", 2),
577+
TealOp(None, Op.intc_3, "//", 3),
578+
TealOp(None, Op.intc_3, "//", 3),
579+
TealOp(None, Op.intc, 4, "//", 2 ** 7),
580+
TealOp(None, Op.intc, 4, "//", 2 ** 7),
581+
]
582+
583+
actual = createConstantBlocks(ops)
584+
assert actual == expected
585+
586+
587+
def test_createConstantBlocks_small_constant():
588+
"""If a constant cannot be referenced using the intc_[0..3] commands
589+
and it can be stored in one varuint it byte then Op.pushint is used.
590+
"""
591+
592+
for cur in range(4, 2 ** 7):
593+
ops = [
594+
TealOp(None, Op.int, 0),
595+
TealOp(None, Op.int, 0),
596+
TealOp(None, Op.int, 1),
597+
TealOp(None, Op.int, 1),
598+
TealOp(None, Op.int, 2),
599+
TealOp(None, Op.int, 2),
600+
TealOp(None, Op.int, 3),
601+
TealOp(None, Op.int, 3),
602+
TealOp(None, Op.int, cur),
603+
TealOp(None, Op.int, cur),
604+
]
605+
606+
expected = [
607+
TealOp(None, Op.intcblock, 0, 1, 2, 3),
608+
TealOp(None, Op.intc_0, "//", 0),
609+
TealOp(None, Op.intc_0, "//", 0),
610+
TealOp(None, Op.intc_1, "//", 1),
611+
TealOp(None, Op.intc_1, "//", 1),
612+
TealOp(None, Op.intc_2, "//", 2),
613+
TealOp(None, Op.intc_2, "//", 2),
614+
TealOp(None, Op.intc_3, "//", 3),
615+
TealOp(None, Op.intc_3, "//", 3),
616+
TealOp(None, Op.pushint, cur, "//", cur),
617+
TealOp(None, Op.pushint, cur, "//", cur),
618+
]
619+
620+
actual = createConstantBlocks(ops)
621+
assert actual == expected

0 commit comments

Comments
 (0)