mirror of
https://github.com/python/cpython.git
synced 2025-12-31 04:23:37 +00:00
gh-104909: Split some more insts into ops (#109943)
These are the most popular specializations of `LOAD_ATTR` and `STORE_ATTR` that weren't already viable uops: * Split LOAD_ATTR_METHOD_WITH_VALUES * Split LOAD_ATTR_METHOD_NO_DICT * Split LOAD_ATTR_SLOT * Split STORE_ATTR_SLOT * Split STORE_ATTR_INSTANCE_VALUE Also: * Add `-v` flag to code generator which prints a list of non-viable uops (easter-egg: it can print execution counts -- see source) * Double _Py_UOP_MAX_TRACE_LENGTH to 128 I had dropped one of the DEOPT_IF() calls! :-(
This commit is contained in:
parent
45cf5b0c69
commit
5bb6f0fcba
8 changed files with 519 additions and 115 deletions
|
|
@ -414,3 +414,61 @@ def check_macro_components(
|
|||
case _:
|
||||
assert_never(uop)
|
||||
return components
|
||||
|
||||
def report_non_viable_uops(self, jsonfile: str) -> None:
|
||||
print("The following ops are not viable uops:")
|
||||
skips = {
|
||||
"CACHE",
|
||||
"RESERVED",
|
||||
"INTERPRETER_EXIT",
|
||||
"JUMP_BACKWARD",
|
||||
"LOAD_FAST_LOAD_FAST",
|
||||
"LOAD_CONST_LOAD_FAST",
|
||||
"STORE_FAST_STORE_FAST",
|
||||
"_BINARY_OP_INPLACE_ADD_UNICODE",
|
||||
"POP_JUMP_IF_TRUE",
|
||||
"POP_JUMP_IF_FALSE",
|
||||
"_ITER_JUMP_LIST",
|
||||
"_ITER_JUMP_TUPLE",
|
||||
"_ITER_JUMP_RANGE",
|
||||
}
|
||||
try:
|
||||
# Secret feature: if bmraw.json exists, print and sort by execution count
|
||||
counts = load_execution_counts(jsonfile)
|
||||
except FileNotFoundError as err:
|
||||
counts = {}
|
||||
non_viable = [
|
||||
instr
|
||||
for instr in self.instrs.values()
|
||||
if instr.name not in skips
|
||||
and not instr.name.startswith("INSTRUMENTED_")
|
||||
and not instr.is_viable_uop()
|
||||
]
|
||||
non_viable.sort(key=lambda instr: (-counts.get(instr.name, 0), instr.name))
|
||||
for instr in non_viable:
|
||||
if instr.name in counts:
|
||||
scount = f"{counts[instr.name]:,}"
|
||||
else:
|
||||
scount = ""
|
||||
print(f" {scount:>15} {instr.name:<35}", end="")
|
||||
if instr.name in self.families:
|
||||
print(" (unspecialized)", end="")
|
||||
elif instr.family is not None:
|
||||
print(f" (specialization of {instr.family.name})", end="")
|
||||
print()
|
||||
|
||||
|
||||
def load_execution_counts(jsonfile: str) -> dict[str, int]:
|
||||
import json
|
||||
|
||||
with open(jsonfile) as f:
|
||||
jsondata = json.load(f)
|
||||
|
||||
# Look for keys like "opcode[LOAD_FAST].execution_count"
|
||||
prefix = "opcode["
|
||||
suffix = "].execution_count"
|
||||
res: dict[str, int] = {}
|
||||
for key, value in jsondata.items():
|
||||
if key.startswith(prefix) and key.endswith(suffix):
|
||||
res[key[len(prefix) : -len(suffix)]] = value
|
||||
return res
|
||||
|
|
|
|||
|
|
@ -92,6 +92,13 @@
|
|||
description="Generate the code for the interpreter switch.",
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
|
||||
arg_parser.add_argument(
|
||||
"-v",
|
||||
"--verbose",
|
||||
help="Print list of non-viable uops and exit",
|
||||
action="store_true",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT
|
||||
)
|
||||
|
|
@ -865,6 +872,10 @@ def main() -> None:
|
|||
a.analyze() # Prints messages and sets a.errors on failure
|
||||
if a.errors:
|
||||
sys.exit(f"Found {a.errors} errors")
|
||||
if args.verbose:
|
||||
# Load execution counts from bmraw.json, if it exists
|
||||
a.report_non_viable_uops("bmraw.json")
|
||||
return
|
||||
|
||||
# These raise OSError if output can't be written
|
||||
a.write_instructions(args.output, args.emit_line_directives)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue