Skip to content

Commit 8552182

Browse files
Use REPLACE_OPCODE_IF_EVALUTES_PURE
1 parent c4aae6c commit 8552182

File tree

5 files changed

+46
-47
lines changed

5 files changed

+46
-47
lines changed

Python/optimizer_bytecodes.c

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -222,58 +222,37 @@ dummy_func(void) {
222222
}
223223

224224
op(_BINARY_OP_ADD_INT, (left, right -- res)) {
225-
// We need to tell the cases generator that it's being used by the constant generator.
226-
// We should fix this in the cases generator.
227-
(void)(left);
228-
(void)(right);
225+
REPLACE_OPCODE_IF_EVALUTES_PURE(left, right);
229226
res = sym_new_type(ctx, &PyLong_Type);
230227
}
231228

232229
op(_BINARY_OP_SUBTRACT_INT, (left, right -- res)) {
233-
// We need to tell the cases generator that it's being used by the constant generator.
234-
// We should fix this in the cases generator.
235-
(void)(left);
236-
(void)(right);
230+
REPLACE_OPCODE_IF_EVALUTES_PURE(left, right);
237231
res = sym_new_type(ctx, &PyLong_Type);
238232
}
239233

240234
op(_BINARY_OP_MULTIPLY_INT, (left, right -- res)) {
241-
// We need to tell the cases generator that it's being used by the constant generator.
242-
// We should fix this in the cases generator.
243-
(void)(left);
244-
(void)(right);
235+
REPLACE_OPCODE_IF_EVALUTES_PURE(left, right);
245236
res = sym_new_type(ctx, &PyLong_Type);
246237
}
247238

248239
op(_BINARY_OP_ADD_FLOAT, (left, right -- res)) {
249-
// We need to tell the cases generator that it's being used by the constant generator.
250-
// We should fix this in the cases generator.
251-
(void)(left);
252-
(void)(right);
240+
REPLACE_OPCODE_IF_EVALUTES_PURE(left, right);
253241
res = sym_new_type(ctx, &PyFloat_Type);
254242
}
255243

256244
op(_BINARY_OP_SUBTRACT_FLOAT, (left, right -- res)) {
257-
// We need to tell the cases generator that it's being used by the constant generator.
258-
// We should fix this in the cases generator.
259-
(void)(left);
260-
(void)(right);
245+
REPLACE_OPCODE_IF_EVALUTES_PURE(left, right);
261246
res = sym_new_type(ctx, &PyFloat_Type);
262247
}
263248

264249
op(_BINARY_OP_MULTIPLY_FLOAT, (left, right -- res)) {
265-
// We need to tell the cases generator that it's being used by the constant generator.
266-
// We should fix this in the cases generator.
267-
(void)(left);
268-
(void)(right);
250+
REPLACE_OPCODE_IF_EVALUTES_PURE(left, right);
269251
res = sym_new_type(ctx, &PyFloat_Type);
270252
}
271253

272254
op(_BINARY_OP_ADD_UNICODE, (left, right -- res)) {
273-
// We need to tell the cases generator that it's being used here.
274-
// We should fix this in the cases generator.
275-
(void)(left);
276-
(void)(right);
255+
REPLACE_OPCODE_IF_EVALUTES_PURE(left, right);
277256
res = sym_new_type(ctx, &PyUnicode_Type);
278257
}
279258

@@ -386,6 +365,7 @@ dummy_func(void) {
386365
}
387366

388367
op(_UNARY_NOT, (value -- res)) {
368+
REPLACE_OPCODE_IF_EVALUTES_PURE(value);
389369
sym_set_type(value, &PyBool_Type);
390370
res = sym_new_truthiness(ctx, value, false);
391371
}

Python/optimizer_cases.c.h

Lines changed: 0 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tools/cases_generator/analyzer.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,12 @@ def variable_used(node: parser.CodeDef, name: str) -> bool:
520520
)
521521

522522

523+
def uop_variable_used(uop: Uop, text: str) -> bool:
524+
return any(
525+
token.kind == "IDENTIFIER" and token.text == text for token in uop.body.tokens()
526+
)
527+
528+
523529
def oparg_used(node: parser.CodeDef) -> bool:
524530
"""Determine whether `oparg` is used in a node."""
525531
return any(

Tools/cases_generator/generators_common.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ def emit_to(out: CWriter, tkn_iter: TokenIterator, end: str) -> Token:
8787
out.emit(tkn)
8888
raise analysis_error(f"Expecting {end}. Reached end of file", tkn)
8989

90+
def skip_to(tkn_iter: TokenIterator, end: str) -> Token:
91+
parens = 0
92+
for tkn in tkn_iter:
93+
if tkn.kind == end and parens == 0:
94+
return tkn
95+
if tkn.kind == "LPAREN":
96+
parens += 1
97+
if tkn.kind == "RPAREN":
98+
parens -= 1
99+
raise analysis_error(f"Expecting {end}. Reached end of file", tkn)
90100

91101
ReplacementFunctionType = Callable[
92102
[Token, TokenIterator, CodeSection, Storage, Instruction | None], bool

Tools/cases_generator/optimizer_generator.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@
1515
analysis_error,
1616
CodeSection,
1717
Label,
18+
uop_variable_used,
1819
)
1920
from generators_common import (
2021
DEFAULT_INPUT,
2122
ROOT,
2223
write_header,
2324
Emitter,
2425
TokenIterator,
26+
skip_to,
2527
)
2628
from cwriter import CWriter
2729
from typing import TextIO
@@ -146,6 +148,10 @@ def emit_default(out: CWriter, uop: Uop, stack: Stack) -> None:
146148

147149
class OptimizerEmitter(Emitter):
148150

151+
def __init__(self, out: CWriter, labels: dict[str, Label]):
152+
super().__init__(out, labels)
153+
self._replacers["REPLACE_OPCODE_IF_EVALUTES_PURE"] = self.replace_opcode_if_evaluates_pure
154+
149155
def emit_save(self, storage: Storage) -> None:
150156
storage.flush(self.out)
151157

@@ -156,6 +162,16 @@ def goto_label(self, goto: Token, label: Token, storage: Storage) -> None:
156162
self.out.emit(goto)
157163
self.out.emit(label)
158164

165+
def replace_opcode_if_evaluates_pure(
166+
self,
167+
tkn: Token,
168+
tkn_iter: TokenIterator,
169+
uop: CodeSection,
170+
storage: Storage,
171+
inst: Instruction | None,
172+
) -> bool:
173+
skip_to(tkn_iter, "SEMI")
174+
return True
159175

160176
class OptimizerConstantEmitter(OptimizerEmitter):
161177
def __init__(self, out: CWriter, labels: dict[str, Label], uop: Uop):
@@ -240,7 +256,7 @@ def write_uop(
240256
stack = Stack(extract_bits=False, cast_type="JitOptSymbol *")
241257
try:
242258
out.start_line()
243-
if override or uop.properties.pure:
259+
if override:
244260
storage = Storage.for_uop(stack, prototype, out, check_liveness=False)
245261
if debug:
246262
args = []
@@ -257,11 +273,12 @@ def write_uop(
257273
type = f"uint{cache.size*16}_t "
258274
cast = f"uint{cache.size*16}_t"
259275
out.emit(f"{type}{cache.name} = ({cast})this_instr->operand0;\n")
260-
if override or uop.properties.pure:
276+
if override:
261277
# No reference management of inputs needed.
262278
for var in storage.inputs: # type: ignore[possibly-undefined]
263279
var.in_local = False
264-
if uop.properties.pure:
280+
replace_opcode_if_evaluates_pure = uop_variable_used(override, "REPLACE_OPCODE_IF_EVALUTES_PURE")
281+
if replace_opcode_if_evaluates_pure:
265282
write_uop_pure_evaluation_region_header(uop, out, stack)
266283
out.start_line()
267284
if override:
@@ -272,7 +289,7 @@ def write_uop(
272289
else:
273290
emit_default(out, uop, stack)
274291
out.start_line()
275-
if uop.properties.pure:
292+
if replace_opcode_if_evaluates_pure:
276293
write_uop_pure_evaluation_region_footer(out)
277294
else:
278295
emit_default(out, uop, stack)
@@ -319,7 +336,7 @@ def generate_abstract_interpreter(
319336
if override:
320337
declare_variables(override, out, skip_inputs=False)
321338
else:
322-
declare_variables(uop, out, skip_inputs=not uop.properties.pure)
339+
declare_variables(uop, out, skip_inputs=True)
323340
write_uop(override, uop, out, debug)
324341
out.start_line()
325342
out.emit("break;\n")

0 commit comments

Comments
 (0)